aboutsummaryrefslogtreecommitdiff
path: root/toys
diff options
context:
space:
mode:
authormakepost <makepost@firemail.cc>2019-06-10 16:29:10 +0000
committerRob Landley <rob@landley.net>2019-06-21 01:52:55 -0500
commit47a8842e78e790912ec0493a594b0eb1e972ab25 (patch)
treeaf038711fb12b449f711a6ad80e439ae7590eb8f /toys
parent66050d1a023b4fde1ff0e30a31f2b09437605f3d (diff)
downloadtoybox-47a8842e78e790912ec0493a594b0eb1e972ab25.tar.gz
Fix cp -r dir/. symlink child.
Remove the existing link before trying to re-create, passing the test. Add -p to the -r test as a regression guard, portage calls cp with both.
Diffstat (limited to 'toys')
-rw-r--r--toys/posix/cp.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/toys/posix/cp.c b/toys/posix/cp.c
index e37b360d..681af025 100644
--- a/toys/posix/cp.c
+++ b/toys/posix/cp.c
@@ -252,7 +252,8 @@ static int cp_node(struct dirtree *try)
// make symlink, or make block/char/fifo/socket
if (S_ISLNK(try->st.st_mode)
? ((i = readlinkat0(tfd, try->name, toybuf, sizeof(toybuf))) &&
- !symlinkat(toybuf, cfd, catch))
+ ((!unlinkat(cfd, catch, 0) || ENOENT == errno) &&
+ !symlinkat(toybuf, cfd, catch)))
: !mknodat(cfd, catch, try->st.st_mode, try->st.st_rdev))
{
err = 0;