From e156347e0480d3eee4877463297149ae96e34f8c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 19 Jun 2014 19:36:08 +0200 Subject: tmpfiles: make sure "C" doesn't copy anything if the destination already exists Previously it would recursively copy the entire tree in, and descend into subdirectories even if the destination already exists. Let's do what the documentation says and not do that. If files down the tree shall be copied too, they should get their own "C" lines. --- src/tmpfiles/tmpfiles.c | 49 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 14 deletions(-) (limited to 'src/tmpfiles') diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index c6c8ce8fe..cbad78aea 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -667,10 +667,29 @@ static int create_item(Item *i) { break; case COPY_FILES: - r = copy_tree(i->argument, i->path); + r = copy_tree(i->argument, i->path, false); if (r < 0) { - log_error("Failed to copy files to %s: %s", i->path, strerror(-r)); - return r; + struct stat a, b; + + if (r != -EEXIST) { + log_error("Failed to copy files to %s: %s", i->path, strerror(-r)); + return -r; + } + + if (stat(i->argument, &a) < 0) { + log_error("stat(%s) failed: %m", i->argument); + return -errno; + } + + if (stat(i->path, &b) < 0) { + log_error("stat(%s) failed: %m", i->path); + return -errno; + } + + if ((a.st_mode ^ b.st_mode) & S_IFMT) { + log_debug("Can't copy to %s, file exists already and is of different type", i->path); + return 0; + } } r = item_set_perms(i, i->path); @@ -694,19 +713,21 @@ static int create_item(Item *i) { r = mkdir_label(i->path, i->mode); } - if (r < 0 && r != -EEXIST) { - log_error("Failed to create directory %s: %s", i->path, strerror(-r)); - return r; - } + if (r < 0) { + if (r != -EEXIST) { + log_error("Failed to create directory %s: %s", i->path, strerror(-r)); + return r; + } - if (stat(i->path, &st) < 0) { - log_error("stat(%s) failed: %m", i->path); - return -errno; - } + if (stat(i->path, &st) < 0) { + log_error("stat(%s) failed: %m", i->path); + return -errno; + } - if (!S_ISDIR(st.st_mode)) { - log_error("%s is not a directory.", i->path); - return -EEXIST; + if (!S_ISDIR(st.st_mode)) { + log_debug("%s already exists and is not a directory.", i->path); + return 0; + } } r = item_set_perms(i, i->path); -- cgit v1.2.3