diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2016-05-02 13:56:07 -0400 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2016-05-02 13:56:07 -0400 |
commit | 8ad54a01825f962458cfac9e5a62e7268ac2fa05 (patch) | |
tree | d291750e20dc93c40871f24815104f455dd71711 /src/basic/copy.c | |
parent | 33e40442c6c5d296dfaa733b8429bff1a24869cc (diff) | |
parent | d13febb1e0d17ce11cfa904085c91e98d336f476 (diff) |
Merge pull request #3153 from poettering/async-clone
machined: make "clone" asynchronous, and support copy-based fall-back
Diffstat (limited to 'src/basic/copy.c')
-rw-r--r-- | src/basic/copy.c | 50 |
1 files changed, 33 insertions, 17 deletions
diff --git a/src/basic/copy.c b/src/basic/copy.c index 3001234a01..c3586728d0 100644 --- a/src/basic/copy.c +++ b/src/basic/copy.c @@ -305,6 +305,8 @@ static int fd_copy_directory( fdf = openat(df, from, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); else fdf = fcntl(df, F_DUPFD_CLOEXEC, 3); + if (fdf < 0) + return -errno; d = fdopendir(fdf); if (!d) @@ -325,22 +327,6 @@ static int fd_copy_directory( r = 0; - if (created) { - struct timespec ut[2] = { - st->st_atim, - st->st_mtim - }; - - if (fchown(fdt, st->st_uid, st->st_gid) < 0) - r = -errno; - - if (fchmod(fdt, st->st_mode & 07777) < 0) - r = -errno; - - (void) futimens(fdt, ut); - (void) copy_xattr(dirfd(d), fdt); - } - FOREACH_DIRENT_ALL(de, d, return -errno) { struct stat buf; int q; @@ -376,6 +362,22 @@ static int fd_copy_directory( r = q; } + if (created) { + struct timespec ut[2] = { + st->st_atim, + st->st_mtim + }; + + if (fchown(fdt, st->st_uid, st->st_gid) < 0) + r = -errno; + + if (fchmod(fdt, st->st_mode & 07777) < 0) + r = -errno; + + (void) copy_xattr(dirfd(d), fdt); + (void) futimens(fdt, ut); + } + return r; } @@ -407,7 +409,6 @@ int copy_tree(const char *from, const char *to, bool merge) { } int copy_directory_fd(int dirfd, const char *to, bool merge) { - struct stat st; assert(dirfd >= 0); @@ -422,6 +423,21 @@ int copy_directory_fd(int dirfd, const char *to, bool merge) { return fd_copy_directory(dirfd, NULL, &st, AT_FDCWD, to, st.st_dev, merge); } +int copy_directory(const char *from, const char *to, bool merge) { + struct stat st; + + assert(from); + assert(to); + + if (lstat(from, &st) < 0) + return -errno; + + if (!S_ISDIR(st.st_mode)) + return -ENOTDIR; + + return fd_copy_directory(AT_FDCWD, from, &st, AT_FDCWD, to, st.st_dev, merge); +} + int copy_file_fd(const char *from, int fdt, bool try_reflink) { _cleanup_close_ int fdf = -1; int r; |