[PATCH] cp: fix `cp -aT` overwriting symlink to directories
From: Dominique Martinet busybox cp refuses to overwrites another symlink to a directory due to an incorrect stat() call that should be lstat(): ``` $ mkdir dir $ ln -s dir ln_src $ ln -s dir ln_dst $ busybox cp -aT ln_src ln_dst cp: 'ln_dst' is a directory ``` When using -T, we want to consider the target argument directly without resolving symlinks. (Note `cp -rLT` which would copy the source symlink as a directory after following the symlink still fails with `target ... is not a directory`) function old new delta cp_main 367 397 +30 cp_mv_stat10 - -10 -- (add/remove: 0/1 grow/shrink: 1/0 up/down: 30/-10) Total: 20 bytes text data bss dec hex filename 85493 16621424 88579 15a03 busybox_old 85513 16621424 88599 15a17 busybox_unstripped --- coreutils/cp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/coreutils/cp.c b/coreutils/cp.c index ee40af50b944..961de5b4271a 100644 --- a/coreutils/cp.c +++ b/coreutils/cp.c @@ -215,7 +215,8 @@ int cp_main(int argc, char **argv) (flags & FILEUTILS_DEREFERENCE) ? stat : lstat); if (s_flags < 0) /* error other than ENOENT */ return EXIT_FAILURE; - d_flags = cp_mv_stat(last, &dest_stat); + d_flags = cp_mv_stat2(last, &dest_stat, + (flags & FILEUTILS_NO_TARGET_DIR) ? lstat : stat); if (d_flags < 0) /* error other than ENOENT */ return EXIT_FAILURE; -- 2.47.3 ___ busybox mailing list [email protected] https://lists.busybox.net/mailman/listinfo/busybox
Re: [PATCH] cp: fix `cp -aT` overwriting symlink to directories
Dominique Martinet wrote on Tue, Sep 30, 2025 at 12:11:33PM +0900: > When using -T, we want to consider the target argument directly without > resolving symlinks. > (Note `cp -rLT` which would copy the source symlink as a directory after > following the symlink still fails with `target ... is not a directory`) Ah, I forgot to write that this only works with CONFIG_FEATURE_NON_POSIX_CP=y When that is unset it fails at the top of ask_and_unlink() with `cp: can't create 'ln_dst': File exists` without also setting `-f` (But I don't know posix and assume that's the expected behaviour even if coreutils with POSIXLY_CORRECT doesn't fail like that? ... And anyway, alpine sets the build config, so I didn't bother digging further at this point) Thanks, -- Dominique Martinet | Asmadeus ___ busybox mailing list [email protected] https://lists.busybox.net/mailman/listinfo/busybox
Re: [PATCH] cp: fix `cp -aT` overwriting symlink to directories
Applied, thank you. On Tue, Sep 30, 2025 at 6:29 AM Dominique Martinet wrote: > > Dominique Martinet wrote on Tue, Sep 30, 2025 at 12:11:33PM +0900: > > When using -T, we want to consider the target argument directly without > > resolving symlinks. > > (Note `cp -rLT` which would copy the source symlink as a directory after > > following the symlink still fails with `target ... is not a directory`) > > Ah, I forgot to write that this only works with > CONFIG_FEATURE_NON_POSIX_CP=y > > When that is unset it fails at the top of ask_and_unlink() with > `cp: can't create 'ln_dst': File exists` without also setting `-f` > > (But I don't know posix and assume that's the expected behaviour even if > coreutils with POSIXLY_CORRECT doesn't fail like that? > ... And anyway, alpine sets the build config, so I didn't bother digging > further at this point) > > Thanks, > -- > Dominique Martinet | Asmadeus ___ busybox mailing list [email protected] https://lists.busybox.net/mailman/listinfo/busybox
