chiark / gitweb /
Introduce udev object cleanup functions
[elogind.git] / src / tmpfiles / tmpfiles.c
index 5eca82ad26c423c3ca7320eb20eecb9e98c83de6..42cc34d6c41576ece05a1a9242cd7a22daaa67c2 100644 (file)
@@ -51,6 +51,7 @@
 #include "set.h"
 #include "conf-files.h"
 #include "capability.h"
+#include "specifier.h"
 
 /* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates
  * them in the file system. This is intended to be used to create
@@ -68,6 +69,7 @@ typedef enum ItemType {
         CREATE_SYMLINK = 'L',
         CREATE_CHAR_DEVICE = 'c',
         CREATE_BLOCK_DEVICE = 'b',
+        ADJUST_MODE = 'm',
 
         /* These ones take globs */
         IGNORE_PATH = 'x',
@@ -256,8 +258,8 @@ static int dir_cleanup(
                 dev_t rootdev,
                 bool mountpoint,
                 int maxdepth,
-                bool keep_this_level)
-{
+                bool keep_this_level) {
+
         struct dirent *dent;
         struct timespec times[2];
         bool deleted = false;
@@ -428,12 +430,16 @@ finish:
         return r;
 }
 
-static int item_set_perms(Item *i, const char *path) {
+static int item_set_perms_full(Item *i, const char *path, bool ignore_enoent) {
+        int r;
+
         /* not using i->path directly because it may be a glob */
         if (i->mode_set)
                 if (chmod(path, i->mode) < 0) {
-                        log_error("chmod(%s) failed: %m", path);
-                        return -errno;
+                        if (errno != ENOENT || !ignore_enoent) {
+                                log_error("chmod(%s) failed: %m", path);
+                                return -errno;
+                        }
                 }
 
         if (i->uid_set || i->gid_set)
@@ -441,11 +447,18 @@ static int item_set_perms(Item *i, const char *path) {
                           i->uid_set ? i->uid : (uid_t) -1,
                           i->gid_set ? i->gid : (gid_t) -1) < 0) {
 
-                        log_error("chown(%s) failed: %m", path);
-                        return -errno;
+                        if (errno != ENOENT || !ignore_enoent) {
+                                log_error("chown(%s) failed: %m", path);
+                                return -errno;
+                        }
                 }
 
-        return label_fix(path, false, false);
+        r = label_fix(path, false, false);
+        return r == -ENOENT && ignore_enoent ? 0 : r;
+}
+
+static int item_set_perms(Item *i, const char *path) {
+        return item_set_perms_full(i, path, false);
 }
 
 static int write_one_file(Item *i, const char *path) {
@@ -641,6 +654,7 @@ static int create_item(Item *i) {
                 if (r < 0)
                         return r;
                 break;
+
         case WRITE_FILE:
                 r = glob_item(i, write_one_file);
                 if (r < 0)
@@ -648,6 +662,13 @@ static int create_item(Item *i) {
 
                 break;
 
+        case ADJUST_MODE:
+                r = item_set_perms_full(i, i->path, true);
+                if (r < 0)
+                        return r;
+
+                break;
+
         case TRUNCATE_DIRECTORY:
         case CREATE_DIRECTORY:
 
@@ -818,6 +839,7 @@ static int remove_item_instance(Item *i, const char *instance) {
         case RELABEL_PATH:
         case RECURSIVE_RELABEL_PATH:
         case WRITE_FILE:
+        case ADJUST_MODE:
                 break;
 
         case REMOVE_PATH:
@@ -863,6 +885,7 @@ static int remove_item(Item *i) {
         case RELABEL_PATH:
         case RECURSIVE_RELABEL_PATH:
         case WRITE_FILE:
+        case ADJUST_MODE:
                 break;
 
         case REMOVE_PATH:
@@ -972,10 +995,7 @@ static void item_free(Item *i) {
         free(i);
 }
 
-static inline void item_freep(Item **i) {
-        if (*i)
-                item_free(*i);
-}
+define_trivial_cleanup_func(Item*, item_free)
 #define _cleanup_item_free_ _cleanup_(item_freep)
 
 static bool item_equal(Item *a, Item *b) {
@@ -1038,10 +1058,19 @@ static bool should_include_path(const char *path) {
 }
 
 static int parse_line(const char *fname, unsigned line, const char *buffer) {
+
+        static const Specifier specifier_table[] = {
+                { 'm', specifier_machine_id, NULL },
+                { 'b', specifier_boot_id, NULL },
+                { 'H', specifier_host_name, NULL },
+                { 'v', specifier_kernel_release, NULL },
+                {}
+        };
+
         _cleanup_item_free_ Item *i = NULL;
         Item *existing;
         _cleanup_free_ char
-                *mode = NULL, *user = NULL, *group = NULL, *age = NULL;
+                *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
         char type;
         Hashmap *h;
         int r, n = -1;
@@ -1050,14 +1079,10 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
         assert(line >= 1);
         assert(buffer);
 
-        i = new0(Item, 1);
-        if (!i)
-                return log_oom();
-
         r = sscanf(buffer,
                    "%c %ms %ms %ms %ms %ms %n",
                    &type,
-                   &i->path,
+                   &path,
                    &mode,
                    &user,
                    &group,
@@ -1068,6 +1093,16 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
                 return -EIO;
         }
 
+        i = new0(Item, 1);
+        if (!i)
+                return log_oom();
+
+        r = specifier_printf(path, specifier_table, NULL, &i->path);
+        if (r < 0) {
+                log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
+                return r;
+        }
+
         if (n >= 0)  {
                 n += strspn(buffer+n, WHITESPACE);
                 if (buffer[n] != 0 && (buffer[n] != '-' || buffer[n+1] != 0)) {
@@ -1090,6 +1125,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
         case RECURSIVE_REMOVE_PATH:
         case RELABEL_PATH:
         case RECURSIVE_RELABEL_PATH:
+        case ADJUST_MODE:
                 break;
 
         case CREATE_SYMLINK:
@@ -1307,11 +1343,12 @@ static int parse_argv(int argc, char *argv[]) {
 }
 
 static int read_config_file(const char *fn, bool ignore_enoent) {
-        FILE *f;
-        unsigned v = 0;
-        int r;
+        _cleanup_fclose_ FILE *f = NULL;
+        char line[LINE_MAX];
         Iterator iterator;
+        unsigned v = 0;
         Item *i;
+        int r;
 
         assert(fn);
 
@@ -1324,23 +1361,19 @@ static int read_config_file(const char *fn, bool ignore_enoent) {
                 return r;
         }
 
-        log_debug("apply: %s\n", fn);
-        for (;;) {
-                char line[LINE_MAX], *l;
+        FOREACH_LINE(line, f, break) {
+                char *l;
                 int k;
 
-                if (!(fgets(line, sizeof(line), f)))
-                        break;
-
                 v++;
 
                 l = strstrip(line);
                 if (*l == '#' || *l == 0)
                         continue;
 
-                if ((k = parse_line(fn, v, l)) < 0)
-                        if (r == 0)
-                                r = k;
+                k = parse_line(fn, v, l);
+                if (k < 0 && r == 0)
+                        r = k;
         }
 
         /* we have to determine age parameter for each entry of type X */
@@ -1377,8 +1410,6 @@ static int read_config_file(const char *fn, bool ignore_enoent) {
                         r = -EIO;
         }
 
-        fclose(f);
-
         return r;
 }