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:
M | cmd/mv.c | 67 | ++++++++++++++++++++++++++++++++++++++++++++++--------------------- |
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)
{