logo

utils-std

Collection of commonly available Unix tools git clone https://anongit.hacktivis.me/git/utils-std.git
commit: 6eff20f7c6043602f65be89ae05061da48756fa0
parent fcef9eaeca0535b8ad1e4663a1cdc6cb6d98dace
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Mon, 11 Nov 2024 07:28:49 +0100

cmd/mv: improve named_fd handling for AT_FDCWD case

Diffstat:

Mcmd/mv.c67++++++++++++++++++++++++++++++++++++++++++++++---------------------
1 file changed, 46 insertions(+), 21 deletions(-)

diff --git a/cmd/mv.c b/cmd/mv.c @@ -45,6 +45,7 @@ struct named_fd { int fd; const char *name; + const char *sep; }; static int do_renameat(struct named_fd srcdir, @@ -63,8 +64,9 @@ copy_file_unlink(struct named_fd srcdir, if(in < 0) { fprintf(stderr, - "mv: error: Failed opening source '%s/%s': %s\n", + "mv: error: Failed opening source '%s%s%s': %s\n", srcdir.name, + srcdir.sep, src, strerror(errno)); errno = 0; @@ -75,8 +77,9 @@ copy_file_unlink(struct named_fd srcdir, if(out < 0) { fprintf(stderr, - "mv: error: Failed opening destination '%s/%s': %s\n", + "mv: error: Failed opening destination '%s%s%s': %s\n", destdir.name, + destdir.sep, dest, strerror(errno)); errno = 0; @@ -87,8 +90,9 @@ copy_file_unlink(struct named_fd srcdir, if(futimens(out, times) != 0) { fprintf(stderr, - "mv: warning: Failed copying access & modification times to '%s/%s': %s\n", + "mv: warning: Failed copying access & modification times to '%s%s%s': %s\n", destdir.name, + destdir.sep, dest, strerror(errno)); errno = 0; @@ -97,8 +101,9 @@ copy_file_unlink(struct named_fd srcdir, if(fchown(out, src_status.st_uid, src_status.st_gid) != 0) { fprintf(stderr, - "mv: warning: Failed copying owner & group to '%s/%s': %s\n", + "mv: warning: Failed copying owner & group to '%s%s%s': %s\n", destdir.name, + destdir.sep, dest, strerror(errno)); errno = 0; @@ -117,7 +122,7 @@ rename_dir_entries(struct named_fd srcdir, struct named_fd destdir) { fprintf(stderr, "mv: error: Failed fd-opening source directory '%s': %s\n", - srcdir.name, + srcdir.name ? srcdir.name : ".", strerror(errno)); return -1; } @@ -133,7 +138,7 @@ rename_dir_entries(struct named_fd srcdir, struct named_fd destdir) fprintf(stderr, "mv: error: Failed reading source directory '%s': %s\n", - srcdir.name, + srcdir.name ? srcdir.name : ".", strerror(errno)); closedir(dirsrc); errno = 0; @@ -169,8 +174,9 @@ do_renameat(struct named_fd srcdir, if(fstatat(srcdir.fd, src, &src_status, AT_SYMLINK_NOFOLLOW) < 0) { fprintf(stderr, - "mv: error: Failed getting status for source file '%s/%s': %s\n", + "mv: error: Failed getting status for source file '%s%s%s': %s\n", srcdir.name, + srcdir.sep, src, strerror(errno)); return -1; @@ -191,8 +197,9 @@ do_renameat(struct named_fd srcdir, if(ret < 0 && errno != ENOENT) { fprintf(stderr, - "mv: error: Failed getting status for destination file '%s/%s': %s\n", + "mv: error: Failed getting status for destination file '%s%s%s': %s\n", destdir.name, + destdir.sep, dest, strerror(errno)); return -1; @@ -206,7 +213,11 @@ do_renameat(struct named_fd srcdir, if(no_clob) { - fprintf(stderr, "mv: error: Destination file '%s/%s' already exists\n", destdir.name, dest); + fprintf(stderr, + "mv: error: Destination file '%s%s%s' already exists\n", + destdir.name, + destdir.sep, + dest); return -1; } @@ -214,8 +225,10 @@ do_renameat(struct named_fd srcdir, { if(interact) { - if(!consentf( - "mv: Destination file '%s/%s' already exists, overwrite? [yN] ", destdir.name, dest)) + if(!consentf("mv: Destination file '%s%s%s' already exists, overwrite? [yN] ", + destdir.name, + destdir.sep, + dest)) return 0; } else if(stdin_tty) @@ -223,8 +236,9 @@ do_renameat(struct named_fd srcdir, if(faccessat(destdir.fd, dest, W_OK, 0) == 0) { if(!consentf( - "mv: error: No write permissions for destination file '%s/%s', overwrite? [yN] ", + "mv: error: No write permissions for destination file '%s%s%s', overwrite? [yN] ", destdir.name, + destdir.sep, dest)) return 0; } @@ -247,18 +261,20 @@ do_renameat(struct named_fd srcdir, if(S_ISDIR(src_status.st_mode)) { char child_srcdir_name[PATH_MAX] = ""; - snprintf(child_srcdir_name, PATH_MAX, "%s/%s", srcdir.name, src); + snprintf(child_srcdir_name, PATH_MAX, "%s%s%s", srcdir.name, srcdir.sep, src); struct named_fd child_srcdir = { .fd = openat(srcdir.fd, src, O_RDONLY | O_DIRECTORY | O_CLOEXEC), .name = child_srcdir_name, + .sep = "/", }; if(child_srcdir.fd < 0) { fprintf(stderr, - "mv: error: Failed opening source directory '%s/%s': %s\n", + "mv: error: Failed opening source directory '%s%s%s': %s\n", srcdir.name, + srcdir.sep, src, strerror(errno)); return -1; @@ -267,18 +283,20 @@ do_renameat(struct named_fd srcdir, if(mkdirat(destdir.fd, dest, src_status.st_mode) < 0) { fprintf(stderr, - "mv: error: Failed creating destination directory '%s/%s': %s\n", + "mv: error: Failed creating destination directory '%s%s%s': %s\n", destdir.name, + destdir.sep, dest, strerror(errno)); return -1; } char child_destdir_name[PATH_MAX] = ""; - snprintf(child_destdir_name, PATH_MAX, "%s/%s", destdir.name, dest); + snprintf(child_destdir_name, PATH_MAX, "%s%s%s", destdir.name, destdir.sep, dest); struct named_fd child_destdir = { .fd = openat(destdir.fd, dest, O_RDONLY | O_DIRECTORY | O_CLOEXEC), .name = child_destdir_name, + .sep = "/", }; if(rename_dir_entries(child_srcdir, child_destdir) < 0) return -1; @@ -289,8 +307,9 @@ do_renameat(struct named_fd srcdir, if(unlinkat(srcdir.fd, src, AT_REMOVEDIR) < 0) { fprintf(stderr, - "mv: error: Failed removing source directory '%s/%s': %s\n", + "mv: error: Failed removing source directory '%s%s%s': %s\n", srcdir.name, + srcdir.sep, src, strerror(errno)); return -1; @@ -338,16 +357,18 @@ do_renameat(struct named_fd srcdir, break; default: fprintf(stderr, - "mv: error: Failed moving '%s' to '%s/%s': %s\n", + "mv: error: Failed moving '%s' to '%s%s%s': %s\n", src, destdir.name, + destdir.sep, dest, strerror(errno)); return -1; } } - if(verbose) fprintf(stderr, "mv: renamed '%s' -> '%s/%s'\n", src, destdir.name, dest); + if(verbose) + fprintf(stderr, "mv: renamed '%s' -> '%s%s%s'\n", src, destdir.name, destdir.sep, dest); return 0; } @@ -365,11 +386,13 @@ main(int argc, char *argv[]) { struct named_fd destdir = { .fd = AT_FDCWD, - .name = ".", + .name = "", + .sep = "", }; struct named_fd srcdir = { .fd = AT_FDCWD, - .name = ".", + .name = "", + .sep = "", }; int c = -1; @@ -394,6 +417,7 @@ main(int argc, char *argv[]) break; case 't': destdir.name = optarg; + destdir.sep = "/"; destdir.fd = open(optarg, O_RDONLY | O_DIRECTORY | O_CLOEXEC); if(destdir.fd < 0) @@ -456,6 +480,7 @@ main(int argc, char *argv[]) argc--; destdir.name = argv[argc]; + destdir.sep = "/"; destdir.fd = open(destdir.name, O_RDONLY | O_DIRECTORY | O_CLOEXEC); if(destdir.fd < 0) {