diff options
Diffstat (limited to 'src/shared/copy.c')
-rw-r--r-- | src/shared/copy.c | 37 |
1 files changed, 12 insertions, 25 deletions
diff --git a/src/shared/copy.c b/src/shared/copy.c index 073b7279b4..867e49bf89 100644 --- a/src/shared/copy.c +++ b/src/shared/copy.c @@ -59,12 +59,8 @@ static int fd_copy_symlink(int df, const char *from, const struct stat *st, int if (r < 0) return r; - if (symlinkat(target, dt, to) < 0) { - if (errno == EEXIST) - return 0; - + if (symlinkat(target, dt, to) < 0) return -errno; - } if (fchownat(dt, to, st->st_uid, st->st_gid, AT_SYMLINK_NOFOLLOW) < 0) return -errno; @@ -85,12 +81,8 @@ static int fd_copy_regular(int df, const char *from, const struct stat *st, int return -errno; fdt = openat(dt, to, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, st->st_mode & 07777); - if (fdt < 0) { - if (errno == EEXIST) - return 0; - + if (fdt < 0) return -errno; - } r = copy_bytes(fdf, fdt); if (r < 0) { @@ -123,12 +115,8 @@ static int fd_copy_fifo(int df, const char *from, const struct stat *st, int dt, assert(to); r = mkfifoat(dt, to, st->st_mode & 07777); - if (r < 0) { - if (errno == EEXIST) - return 0; - + if (r < 0) return -errno; - } if (fchownat(dt, to, st->st_uid, st->st_gid, AT_SYMLINK_NOFOLLOW) < 0) r = -errno; @@ -147,12 +135,8 @@ static int fd_copy_node(int df, const char *from, const struct stat *st, int dt, assert(to); r = mknodat(dt, to, st->st_mode, st->st_rdev); - if (r < 0) { - if (errno == EEXIST) - return 0; - + if (r < 0) return -errno; - } if (fchownat(dt, to, st->st_uid, st->st_gid, AT_SYMLINK_NOFOLLOW) < 0) r = -errno; @@ -163,7 +147,7 @@ static int fd_copy_node(int df, const char *from, const struct stat *st, int dt, return r; } -static int fd_copy_directory(int df, const char *from, const struct stat *st, int dt, const char *to, dev_t original_device) { +static int fd_copy_directory(int df, const char *from, const struct stat *st, int dt, const char *to, dev_t original_device, bool merge) { _cleanup_close_ int fdf = -1, fdt = -1; _cleanup_closedir_ DIR *d = NULL; struct dirent *de; @@ -186,7 +170,7 @@ static int fd_copy_directory(int df, const char *from, const struct stat *st, in r = mkdirat(dt, to, st->st_mode & 07777); if (r >= 0) created = true; - else if (errno == EEXIST) + else if (errno == EEXIST && merge) created = false; else return -errno; @@ -219,7 +203,7 @@ static int fd_copy_directory(int df, const char *from, const struct stat *st, in if (S_ISREG(buf.st_mode)) q = fd_copy_regular(dirfd(d), de->d_name, &buf, fdt, de->d_name); else if (S_ISDIR(buf.st_mode)) - q = fd_copy_directory(dirfd(d), de->d_name, &buf, fdt, de->d_name, original_device); + q = fd_copy_directory(dirfd(d), de->d_name, &buf, fdt, de->d_name, original_device, merge); else if (S_ISLNK(buf.st_mode)) q = fd_copy_symlink(dirfd(d), de->d_name, &buf, fdt, de->d_name); else if (S_ISFIFO(buf.st_mode)) @@ -229,6 +213,9 @@ static int fd_copy_directory(int df, const char *from, const struct stat *st, in else q = -ENOTSUP; + if (q == -EEXIST && merge) + q = 0; + if (q < 0) r = q; } @@ -236,7 +223,7 @@ static int fd_copy_directory(int df, const char *from, const struct stat *st, in return r; } -int copy_tree(const char *from, const char *to) { +int copy_tree(const char *from, const char *to, bool merge) { struct stat st; assert(from); @@ -248,7 +235,7 @@ int copy_tree(const char *from, const char *to) { if (S_ISREG(st.st_mode)) return fd_copy_regular(AT_FDCWD, from, &st, AT_FDCWD, to); else if (S_ISDIR(st.st_mode)) - return fd_copy_directory(AT_FDCWD, from, &st, AT_FDCWD, to, st.st_dev); + return fd_copy_directory(AT_FDCWD, from, &st, AT_FDCWD, to, st.st_dev, merge); else if (S_ISLNK(st.st_mode)) return fd_copy_symlink(AT_FDCWD, from, &st, AT_FDCWD, to); else if (S_ISFIFO(st.st_mode)) |