From 47a8842e78e790912ec0493a594b0eb1e972ab25 Mon Sep 17 00:00:00 2001 From: makepost Date: Mon, 10 Jun 2019 16:29:10 +0000 Subject: 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. --- tests/cp.test | 8 ++++---- toys/posix/cp.c | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/cp.test b/tests/cp.test index c7d445c0..9ee6cd0e 100755 --- a/tests/cp.test +++ b/tests/cp.test @@ -90,12 +90,12 @@ testing "-r dir1/* dir2" \ rm -rf one dir dir2 mkdir one; touch one/two; cp one/two one/three -cp -r one/ one_ # Succeeds twice in a row -testing "-r dir/." "cp -r one/. one_ && echo yes" "yes\n" "" "" +cp -pr one/ one_ # Succeeds twice in a row +testing "-pr dir/." "cp -pr one/. one_ && echo yes" "yes\n" "" "" rm -rf one one_ mkdir one; touch one/two; ln -s two one/three -cp -r one/ one_ # First time ok, but second will fail with "File exists" -testing "-r dir/. symlink child" "cp -r one/. one_ && echo yes" "yes\n" "" "" +cp -pr one/ one_ # First time ok, second mustn't fail with "File exists" +testing "-pr dir/. symlink child" "cp -pr one/. one_ && echo yes" "yes\n" "" "" rm -rf one one_ touch walrus 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; -- cgit v1.2.3