logo

bootstrap-initrd

Linux initrd to bootstrap from a small binary seed git clone https://hacktivis.me/git/make-initrd.git
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:

Mcp-stub.c83++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
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);