commit: b170e6a9eb7564dbead8a94660c9808131d827a2
parent d99da98d804678e12b7bce2e21c56d03dad6a5e9
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Wed, 28 Aug 2024 18:53:16 +0200
cmd/mv: follow source file symlink only when found
Diffstat:
2 files changed, 42 insertions(+), 19 deletions(-)
diff --git a/cmd/mv.c b/cmd/mv.c
@@ -133,7 +133,7 @@ do_renameat(struct named_fd srcdir,
}
struct stat src_status;
- if(fstatat(srcdir.fd, src, &src_status, 0) < 0)
+ if(fstatat(srcdir.fd, src, &src_status, AT_SYMLINK_NOFOLLOW) < 0)
{
fprintf(stderr,
"mv: Failed getting status for source file '%s/%s': %s\n",
@@ -142,6 +142,14 @@ do_renameat(struct named_fd srcdir,
strerror(errno));
return -1;
}
+ if(S_ISLNK(src_status.st_mode))
+ {
+ struct stat src_link_status;
+ if(fstatat(srcdir.fd, src, &src_link_status, 0) == 0)
+ {
+ src_status = src_link_status;
+ }
+ }
errno = 0;
diff --git a/test-cmd/mv.t b/test-cmd/mv.t
@@ -55,25 +55,32 @@ POSIX mv(1) step 1b, no -f option, -i passed
$ rm -fr 1a_no-f_write
POSIX mv(1) step 2, same file
- $ touch same
- $ mv same same
- mv: Error, passed to both source and destination: 'same'
+ $ touch same-name
+ $ mv same-name same-name
+ mv: Error, passed to both source and destination: 'same-name'
[1]
- $ test -e same
- $ ln same Same
- $ mv same Same
- $ test -e same
- $ test -e Same
- $ ln -s same same-s
- $ mv same same-s
- $ test -e same
- $ test -e Same
- $ test -e same-s
- $ mv Same same-s
- $ test -e same
- $ test -e Same
- $ test -e same-s
- $ rm same Same same-s
+ $ test -e same-name
+ $ rm same-name
+
+POSIX mv(1) step 2, same file, hardlink
+ $ touch same-src-h
+ $ ln same-src-h same-dest-h
+ $ mv same-src-h same-src-h
+ mv: Error, passed to both source and destination: 'same-src-h'
+ [1]
+ $ test -e same-src-h
+ $ test -e same-dest-h
+ $ rm same-src-h same-dest-h
+
+POSIX mv(1) step 2, same file, symlink
+ $ touch same-src-s
+ $ ln -s same-src-s same-dest-s
+ $ mv same-src-s same-src-s
+ mv: Error, passed to both source and destination: 'same-src-s'
+ [1]
+ $ test -e same-src-s
+ $ test -e same-dest-s
+ $ rm same-src-s same-dest-s
Where destination is an existing directory
$ mkdir destdir
@@ -135,6 +142,14 @@ Last component used for destination filename
$ test -f dest_last/file
$ rm -r src_last dest_last
+Works with non-resolving source symlinks
+ $ ln -s /var/empty/e/no/ent symlink_enoent
+ $ test -L symlink_enoent
+ $ mv symlink_enoent symlink_enoent.done
+ $ test ! -L symlink_enoent
+ $ test -L symlink_enoent.done
+ $ rm symlink_enoent.done
+
No files should be left
$ find .
.