Merge pull request #11345 from kirbyfan64/tmpfiles-c-empty

tmpfiles: Make C still copy if the destination directory is empty
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2019-01-15 16:54:19 +01:00
committed by GitHub
7 changed files with 77 additions and 23 deletions
+21 -7
View File
@@ -24,6 +24,7 @@
#include "macro.h"
#include "missing.h"
#include "mountpoint-util.h"
#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
#include "time-util.h"
@@ -501,7 +502,7 @@ static int fd_copy_directory(
_cleanup_close_ int fdf = -1, fdt = -1;
_cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
bool created;
bool exists, created;
int r;
assert(st);
@@ -522,13 +523,26 @@ static int fd_copy_directory(
return -errno;
fdf = -1;
r = mkdirat(dt, to, st->st_mode & 07777);
if (r >= 0)
created = true;
else if (errno == EEXIST && (copy_flags & COPY_MERGE))
exists = false;
if (copy_flags & COPY_MERGE_EMPTY) {
r = dir_is_empty_at(dt, to);
if (r < 0 && r != -ENOENT)
return r;
else if (r == 1)
exists = true;
}
if (exists)
created = false;
else
return -errno;
else {
r = mkdirat(dt, to, st->st_mode & 07777);
if (r >= 0)
created = true;
else if (errno == EEXIST && (copy_flags & COPY_MERGE))
created = false;
else
return -errno;
}
fdt = openat(dt, to, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
if (fdt < 0)
+5 -4
View File
@@ -9,10 +9,11 @@
#include <sys/types.h>
typedef enum CopyFlags {
COPY_REFLINK = 1 << 0, /* Try to reflink */
COPY_MERGE = 1 << 1, /* Merge existing trees with our new one to copy */
COPY_REPLACE = 1 << 2, /* Replace an existing file if there's one */
COPY_SAME_MOUNT = 1 << 3, /* Don't descend recursively into other file systems, across mount point boundaries */
COPY_REFLINK = 1 << 0, /* Try to reflink */
COPY_MERGE = 1 << 1, /* Merge existing trees with our new one to copy */
COPY_REPLACE = 1 << 2, /* Replace an existing file if there's one */
COPY_SAME_MOUNT = 1 << 3, /* Don't descend recursively into other file systems, across mount point boundaries */
COPY_MERGE_EMPTY = 1 << 4, /* Merge an existing, empty directory with our new tree to copy */
} CopyFlags;
typedef int (*copy_progress_bytes_t)(uint64_t n_bytes, void *userdata);
+12 -3
View File
@@ -67,13 +67,22 @@ int is_device_node(const char *path) {
return !!(S_ISBLK(info.st_mode) || S_ISCHR(info.st_mode));
}
int dir_is_empty(const char *path) {
_cleanup_closedir_ DIR *d;
int dir_is_empty_at(int dir_fd, const char *path) {
_cleanup_close_ int fd = -1;
_cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
d = opendir(path);
if (path)
fd = openat(dir_fd, path, O_RDONLY|O_DIRECTORY|O_CLOEXEC);
else
fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
if (fd < 0)
return -errno;
d = fdopendir(fd);
if (!d)
return -errno;
fd = -1;
FOREACH_DIRENT(de, d, return -errno)
return 0;
+4 -1
View File
@@ -15,7 +15,10 @@ int is_dir(const char *path, bool follow);
int is_dir_fd(int fd);
int is_device_node(const char *path);
int dir_is_empty(const char *path);
int dir_is_empty_at(int dir_fd, const char *path);
static inline int dir_is_empty(const char *path) {
return dir_is_empty_at(AT_FDCWD, path);
}
static inline int dir_is_populated(const char *path) {
int r;