diff --git a/bin/cp/cp.c b/bin/cp/cp.c --- a/bin/cp/cp.c +++ b/bin/cp/cp.c @@ -179,9 +179,9 @@ target = dot; } else if ((sep = strrchr(target, '/')) != NULL && sep[1] == '\0') { have_trailing_slash = true; - while (sep > target + 1 && *(sep - 1) == '/') + while (sep > target && *sep == '/') sep--; - *sep = '\0'; + sep[1] = '\0'; } /* * Copy target into to.base, leaving room for a possible separator @@ -293,9 +293,11 @@ /* * We have previously made sure there is room for this. */ - sep = strchr(to.base, '\0'); - sep[0] = '/'; - sep[1] = '\0'; + if (strcmp(to.base, "/") != 0) { + sep = strchr(to.base, '\0'); + sep[0] = '/'; + sep[1] = '\0'; + } } else { /* * We will create the destination directory imminently. diff --git a/bin/cp/tests/cp_test.sh b/bin/cp/tests/cp_test.sh --- a/bin/cp/tests/cp_test.sh +++ b/bin/cp/tests/cp_test.sh @@ -570,6 +570,27 @@ atf_check cmp dir/file dst/file } +atf_test_case to_root cleanup +to_root_head() +{ + atf_set "require.user" "root" +} +to_root_body() +{ + dst="$(atf_get ident).$$" + echo "$dst" >dst + echo "foo" >"$dst" + atf_check cp "$dst" / + atf_check cmp -s "$dst" "/$dst" + atf_check rm "/$dst" + atf_check cp "$dst" // + atf_check cmp -s "$dst" "/$dst" +} +to_root_cleanup() +{ + (dst=$(cat dst) && [ -n "/$dst" ] && [ -f "/$dst" ] && rm "/$dst") || true +} + atf_init_test_cases() { atf_add_test_case basic @@ -607,4 +628,5 @@ atf_add_test_case to_deaddirlink atf_add_test_case to_link_outside atf_add_test_case dstmode + atf_add_test_case to_root }