summaryrefslogtreecommitdiff
path: root/src/shared/copy.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared/copy.c')
-rw-r--r--src/shared/copy.c37
1 files changed, 12 insertions, 25 deletions
diff --git a/src/shared/copy.c b/src/shared/copy.c
index 073b7279b..867e49bf8 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))