commit: 5d0060926e2f20e59fc1687f7417669fec0f4c8f
parent 5c1aa6699bd3d8767f0880e303bb69bafc6d5091
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Fri, 3 May 2024 14:30:42 +0200
cp-stub.c: Handle symlinks
Diffstat:
M | cp-stub.c | 83 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------- |
1 file changed, 70 insertions(+), 13 deletions(-)
diff --git a/cp-stub.c b/cp-stub.c
@@ -42,17 +42,6 @@ do_copy(char *src, char *dest, bool multi_src)
return -1;
}
- int src_open_flags = O_RDONLY;
-
- if(!follow_src_symlinks) src_open_flags |= O_NOFOLLOW;
-
- int src_fd = open(src, src_open_flags);
- if(src_fd < 0)
- {
- fprintf(stderr, "%s: Failed opening file '%s' for reading: %s\n", argv0, src, strerror(errno));
- return -1;
- }
-
struct stat dest_stat;
if(stat(dest, &dest_stat) < 0)
{
@@ -72,10 +61,9 @@ do_copy(char *src, char *dest, bool multi_src)
}
char *dest_path = dest;
-
+ char target[PATH_MAX] = "";
if(multi_src || S_ISDIR(dest_stat.st_mode))
{
- char target[PATH_MAX] = "";
char *src_basename = static_basename(src);
if(snprintf(target, PATH_MAX, "%s/%s", dest, src_basename) < 0)
@@ -105,12 +93,81 @@ do_copy(char *src, char *dest, bool multi_src)
return -1;
}
+ if(preserve_metadata)
+ {
+ struct timespec src_times[2] = {src_stat.st_atim, src_stat.st_mtim};
+ if(utimensat(AT_FDCWD, dest_path, src_times, 0) != 0)
+ {
+ fprintf(stderr,
+ "%s: Error while setting access/modification times on '%s': %s\n",
+ argv0,
+ dest_path,
+ strerror(errno));
+ return -1;
+ }
+
+ if(chown(dest, src_stat.st_uid, src_stat.st_gid) < 0)
+ {
+ fprintf(stderr,
+ "%s: Error: Failed setting ownership on file '%s': %s\n",
+ argv0,
+ dest_path,
+ strerror(errno));
+ return -1;
+ }
+ }
+
fprintf(stderr, "%s: FIXME: Copy the files inside '%s/'\n", argv0, dest);
return -1;
}
+ else if(S_ISLNK(src_stat.st_mode))
+ {
+ char link[PATH_MAX] = "";
+ if(readlink(src, link, sizeof(link)) <0)
+ {
+ fprintf(stderr, "%s: Failed reading symlink of '%s': %s\n", argv0, src, strerror(errno));
+ return -1;
+ }
+
+ if(symlink(link, dest_path) != 0)
+ {
+ fprintf(stderr, "%s: Failed copying symlink '%s' to '%s': %s\n", argv0, src, dest_path, strerror(errno));
+ return -1;
+ }
+
+ if(preserve_metadata)
+ {
+ struct timespec src_times[2] = {src_stat.st_atim, src_stat.st_mtim};
+ if(utimensat(AT_FDCWD, dest_path, src_times, AT_SYMLINK_NOFOLLOW) != 0)
+ {
+ fprintf(stderr,
+ "%s: Error while setting access/modification times on '%s': %s\n",
+ argv0,
+ dest_path,
+ strerror(errno));
+ return -1;
+ }
+
+ if(chown(dest, src_stat.st_uid, src_stat.st_gid) < 0)
+ {
+ fprintf(stderr,
+ "%s: Error: Failed setting ownership on file '%s': %s\n",
+ argv0,
+ dest_path,
+ strerror(errno));
+ return -1;
+ }
+ }
+ }
else if(S_ISREG(src_stat.st_mode))
{
// FIXME: Handle writing into block devices
+ int src_fd = open(src, O_RDONLY|O_NOFOLLOW);
+ if(src_fd < 0)
+ {
+ fprintf(stderr, "%s: Failed opening file '%s' for reading: %s\n", argv0, src, strerror(errno));
+ return -1;
+ }
// FIXME: Handle -i (consent)
int dest_fd = open(dest_path, O_CREAT | O_WRONLY | O_TRUNC, mode);