chiark / gitweb /
tmpfiles: Fix handling of duplicate lines
[elogind.git] / src / tmpfiles / tmpfiles.c
index 473c51166b49daf368975270f9559f5a707f1357..652fe5f229ca653993f95cf89aa504dca0b947bf 100644 (file)
@@ -26,8 +26,6 @@
 #include <string.h>
 #include <limits.h>
 #include <dirent.h>
-#include <grp.h>
-#include <pwd.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stddef.h>
@@ -37,8 +35,6 @@
 #include <glob.h>
 #include <fnmatch.h>
 #include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/param.h>
 #include <sys/xattr.h>
 
 #include "log.h"
@@ -465,18 +461,12 @@ static int dir_cleanup(
                                 continue;
                         }
 
-                        if (i->type == IGNORE_DIRECTORY_PATH && streq(dent->d_name, p))
-                                log_debug("Ignoring directory \"%s\"", sub_path);
-                        else {
-                                log_debug("Removing directory \"%s\".", sub_path);
-
-                                if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0) {
-                                        if (errno != ENOENT && errno != ENOTEMPTY) {
-                                                log_error_errno(errno, "rmdir(%s): %m", sub_path);
-                                                r = -errno;
-                                        }
+                        log_debug("Removing directory \"%s\".", sub_path);
+                        if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0)
+                                if (errno != ENOENT && errno != ENOTEMPTY) {
+                                        log_error_errno(errno, "rmdir(%s): %m", sub_path);
+                                        r = -errno;
                                 }
-                        }
 
                 } else {
                         /* Skip files for which the sticky bit is
@@ -688,7 +678,6 @@ static int path_set_xattrs(Item *i, const char *path) {
 static int get_acls_from_arg(Item *item) {
 #ifdef HAVE_ACL
         int r;
-        _cleanup_(acl_freep) acl_t a = NULL, d = NULL;
 
         assert(item);
 
@@ -696,7 +685,7 @@ static int get_acls_from_arg(Item *item) {
          * afterwards, so the mask can be added now if necessary. */
         r = parse_acl(item->argument, &item->acl_access, &item->acl_default, !item->force);
         if (r < 0)
-                log_warning_errno(errno, "Failed to parse ACL \"%s\": %m. Ignoring",
+                log_warning_errno(r, "Failed to parse ACL \"%s\": %m. Ignoring",
                                   item->argument);
 #else
         log_warning_errno(ENOSYS, "ACLs are not supported. Ignoring");
@@ -705,11 +694,15 @@ static int get_acls_from_arg(Item *item) {
         return 0;
 }
 
+#ifdef HAVE_ACL
 static int path_set_acl(const char *path, acl_type_t type, acl_t acl, bool modify) {
         _cleanup_(acl_freep) acl_t dup = NULL;
         int r;
         _cleanup_(acl_free_charpp) char *t = NULL;
 
+        /* Returns 0 for success, positive error if already warned,
+         * negative error otherwise. */
+
         if (modify) {
                 r = acls_for_file(path, type, acl, &dup);
                 if (r < 0)
@@ -737,34 +730,36 @@ static int path_set_acl(const char *path, acl_type_t type, acl_t acl, bool modif
 
         r = acl_set_file(path, type, dup);
         if (r < 0)
-                return log_error_errno(-errno,
-                                       "Setting %s ACL \"%s\" on %s failed: %m",
-                                       type == ACL_TYPE_ACCESS ? "access" : "default",
-                                       strna(t), path);
+                return -log_error_errno(errno,
+                                        "Setting %s ACL \"%s\" on %s failed: %m",
+                                        type == ACL_TYPE_ACCESS ? "access" : "default",
+                                        strna(t), path);
+
         return 0;
 }
+#endif
 
 static int path_set_acls(Item *item, const char *path) {
+        int r = 0;
 #ifdef HAVE_ACL
-        int r;
-
         assert(item);
         assert(path);
 
-        if (item->acl_access) {
+        if (item->acl_access)
                 r = path_set_acl(path, ACL_TYPE_ACCESS, item->acl_access, item->force);
-                if (r < 0)
-                        return r;
-        }
 
-        if (item->acl_default) {
+        if (r == 0 && item->acl_default)
                 r = path_set_acl(path, ACL_TYPE_DEFAULT, item->acl_default, item->force);
-                if (r < 0)
-                        return r;
-        }
-#endif
 
-        return 0;
+        if (r > 0)
+                return -r; /* already warned */
+        else if (r == -ENOTSUP) {
+                log_debug_errno(r, "ACLs not supported by file system at %s", path);
+                return 0;
+        } else if (r < 0)
+                log_error_errno(r, "ACL operation on \"%s\" failed: %m", path);
+#endif
+        return r;
 }
 
 static int write_one_file(Item *i, const char *path) {
@@ -909,9 +904,26 @@ static int glob_item(Item *i, action_t action, bool recursive) {
         return r;
 }
 
+typedef enum {
+        CREATION_NORMAL,
+        CREATION_EXISTING,
+        CREATION_FORCE,
+        _CREATION_MODE_MAX,
+        _CREATION_MODE_INVALID = -1
+} CreationMode;
+
+static const char *creation_mode_verb_table[_CREATION_MODE_MAX] = {
+        [CREATION_NORMAL] = "Created",
+        [CREATION_EXISTING] = "Found existing",
+        [CREATION_FORCE] = "Created replacement",
+};
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(creation_mode_verb, CreationMode);
+
 static int create_item(Item *i) {
         struct stat st;
         int r = 0;
+        CreationMode creation;
 
         assert(i);
 
@@ -996,8 +1008,11 @@ static int create_item(Item *i) {
                                 log_debug("\"%s\" already exists and is not a directory.", i->path);
                                 return 0;
                         }
-                }
-                log_debug("Created directory \"%s\".", i->path);
+
+                        creation = CREATION_EXISTING;
+                } else
+                        creation = CREATION_NORMAL;
+                log_debug("%s directory \"%s\".", creation_mode_verb_to_string(creation), i->path);
 
                 r = path_set_perms(i, i->path);
                 if (r < 0)
@@ -1032,13 +1047,16 @@ static int create_item(Item *i) {
 
                                         if (r < 0)
                                                 return log_error_errno(r, "Failed to create fifo %s: %m", i->path);
+                                        creation = CREATION_FORCE;
                                 } else {
                                         log_debug("%s is not a fifo.", i->path);
                                         return 0;
                                 }
-                        }
-                }
-                log_debug("Created fifo \"%s\".", i->path);
+                        } else
+                                creation = CREATION_EXISTING;
+                } else
+                        creation = CREATION_NORMAL;
+                log_debug("%s fifo \"%s\".", creation_mode_verb_to_string(creation), i->path);
 
                 r = path_set_perms(i, i->path);
                 if (r < 0)
@@ -1068,13 +1086,16 @@ static int create_item(Item *i) {
 
                                         if (r < 0)
                                                 return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path);
+                                        creation = CREATION_FORCE;
                                 } else {
                                         log_debug("\"%s\" is not a symlink or does not point to the correct path.", i->path);
                                         return 0;
                                 }
-                        }
-                }
-                log_debug("Created symlink \"%s\".", i->path);
+                        } else
+                                creation = CREATION_EXISTING;
+                } else
+                        creation = CREATION_NORMAL;
+                log_debug("%s symlink \"%s\".", creation_mode_verb_to_string(creation), i->path);
 
                 break;
 
@@ -1124,14 +1145,18 @@ static int create_item(Item *i) {
                                         }
 
                                         if (r < 0)
-                                                return log_error_errno(r, "Failed to create device node %s: %m", i->path);
+                                                return log_error_errno(r, "Failed to create device node \"%s\": %m", i->path);
+                                        creation = CREATION_FORCE;
                                 } else {
                                         log_debug("%s is not a device node.", i->path);
                                         return 0;
                                 }
-                        }
-                }
-                log_debug("Created %s device node \"%s\" %u:%u.",
+                        } else
+                                creation = CREATION_EXISTING;
+                } else
+                        creation = CREATION_NORMAL;
+                log_debug("%s %s device node \"%s\" %u:%u.",
+                          creation_mode_verb_to_string(creation),
                           i->type == CREATE_BLOCK_DEVICE ? "block" : "char",
                           i->path, major(i->mode), minor(i->mode));
 
@@ -1721,9 +1746,11 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
                 unsigned n;
 
                 for (n = 0; n < existing->count; n++) {
-                        if (!item_compatible(existing->items + n, &i))
+                        if (!item_compatible(existing->items + n, &i)) {
                                 log_warning("[%s:%u] Duplicate line for path \"%s\", ignoring.",
                                             fname, line, i.path);
+                                return 0;
+                        }
                 }
         } else {
                 existing = new0(ItemArray, 1);