a4b143
From cb869b77802b536aab1716714cdd5478d891d3f4 Mon Sep 17 00:00:00 2001
a4b143
From: Lennart Poettering <lennart@poettering.net>
a4b143
Date: Tue, 17 Sep 2013 16:33:30 -0500
a4b143
Subject: [PATCH] tmpfiles: add a new "m" line type that adjusts
a4b143
 user/group/mode of a file if it exists
a4b143
a4b143
---
a4b143
 man/systemd-tmpfiles.xml |  2 +-
a4b143
 man/tmpfiles.d.xml       | 11 +++++++++++
a4b143
 src/tmpfiles/tmpfiles.c  | 39 +++++++++++++++++++++++++++++++--------
a4b143
 3 files changed, 43 insertions(+), 9 deletions(-)
a4b143
a4b143
diff --git a/man/systemd-tmpfiles.xml b/man/systemd-tmpfiles.xml
a4b143
index 281ab3c..ba727e1 100644
a4b143
--- a/man/systemd-tmpfiles.xml
a4b143
+++ b/man/systemd-tmpfiles.xml
a4b143
@@ -165,7 +165,7 @@
a4b143
                 <title>See Also</title>
a4b143
                 <para>
a4b143
                         <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
a4b143
-                        <citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
a4b143
+                        <citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>
a4b143
                 </para>
a4b143
         </refsect1>
a4b143
 
a4b143
diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml
a4b143
index cdc87c9..98e3690 100644
a4b143
--- a/man/tmpfiles.d.xml
a4b143
+++ b/man/tmpfiles.d.xml
a4b143
@@ -152,6 +152,17 @@ L    /tmp/foobar -    -    -    -   /dev/null</programlisting>
a4b143
                                 </varlistentry>
a4b143
 
a4b143
                                 <varlistentry>
a4b143
+                                        <term><varname>m</varname></term>
a4b143
+                                        <listitem><para>If the
a4b143
+                                        specified file path exists
a4b143
+                                        adjust its access mode, group
a4b143
+                                        and user to the specified
a4b143
+                                        values and reset the SELinux
a4b143
+                                        label. If it doesn't exist do
a4b143
+                                        nothing.</para></listitem>
a4b143
+                                </varlistentry>
a4b143
+
a4b143
+                                <varlistentry>
a4b143
                                         <term><varname>x</varname></term>
a4b143
                                         <listitem><para>Ignore a path
a4b143
                                         during cleaning. Use this type
a4b143
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
a4b143
index ea99920..49e6529 100644
a4b143
--- a/src/tmpfiles/tmpfiles.c
a4b143
+++ b/src/tmpfiles/tmpfiles.c
a4b143
@@ -68,6 +68,7 @@ typedef enum ItemType {
a4b143
         CREATE_SYMLINK = 'L',
a4b143
         CREATE_CHAR_DEVICE = 'c',
a4b143
         CREATE_BLOCK_DEVICE = 'b',
a4b143
+        ADJUST_MODE = 'm',
a4b143
 
a4b143
         /* These ones take globs */
a4b143
         IGNORE_PATH = 'x',
a4b143
@@ -256,8 +257,8 @@ static int dir_cleanup(
a4b143
                 dev_t rootdev,
a4b143
                 bool mountpoint,
a4b143
                 int maxdepth,
a4b143
-                bool keep_this_level)
a4b143
-{
a4b143
+                bool keep_this_level) {
a4b143
+
a4b143
         struct dirent *dent;
a4b143
         struct timespec times[2];
a4b143
         bool deleted = false;
a4b143
@@ -431,12 +432,16 @@ finish:
a4b143
         return r;
a4b143
 }
a4b143
 
a4b143
-static int item_set_perms(Item *i, const char *path) {
a4b143
+static int item_set_perms_full(Item *i, const char *path, bool ignore_enoent) {
a4b143
+        int r;
a4b143
+
a4b143
         /* not using i->path directly because it may be a glob */
a4b143
         if (i->mode_set)
a4b143
                 if (chmod(path, i->mode) < 0) {
a4b143
-                        log_error("chmod(%s) failed: %m", path);
a4b143
-                        return -errno;
a4b143
+                        if (errno != ENOENT || !ignore_enoent) {
a4b143
+                                log_error("chmod(%s) failed: %m", path);
a4b143
+                                return -errno;
a4b143
+                        }
a4b143
                 }
a4b143
 
a4b143
         if (i->uid_set || i->gid_set)
a4b143
@@ -444,11 +449,18 @@ static int item_set_perms(Item *i, const char *path) {
a4b143
                           i->uid_set ? i->uid : (uid_t) -1,
a4b143
                           i->gid_set ? i->gid : (gid_t) -1) < 0) {
a4b143
 
a4b143
-                        log_error("chown(%s) failed: %m", path);
a4b143
-                        return -errno;
a4b143
+                        if (errno != ENOENT || !ignore_enoent) {
a4b143
+                                log_error("chown(%s) failed: %m", path);
a4b143
+                                return -errno;
a4b143
+                        }
a4b143
                 }
a4b143
 
a4b143
-        return label_fix(path, false, false);
a4b143
+        r = label_fix(path, false, false);
a4b143
+        return r == -ENOENT && ignore_enoent ? 0 : r;
a4b143
+}
a4b143
+
a4b143
+static int item_set_perms(Item *i, const char *path) {
a4b143
+        return item_set_perms_full(i, path, false);
a4b143
 }
a4b143
 
a4b143
 static int write_one_file(Item *i, const char *path) {
a4b143
@@ -644,6 +656,7 @@ static int create_item(Item *i) {
a4b143
                 if (r < 0)
a4b143
                         return r;
a4b143
                 break;
a4b143
+
a4b143
         case WRITE_FILE:
a4b143
                 r = glob_item(i, write_one_file);
a4b143
                 if (r < 0)
a4b143
@@ -651,6 +664,13 @@ static int create_item(Item *i) {
a4b143
 
a4b143
                 break;
a4b143
 
a4b143
+        case ADJUST_MODE:
a4b143
+                r = item_set_perms_full(i, i->path, true);
a4b143
+                if (r < 0)
a4b143
+                        return r;
a4b143
+
a4b143
+                break;
a4b143
+
a4b143
         case TRUNCATE_DIRECTORY:
a4b143
         case CREATE_DIRECTORY:
a4b143
 
a4b143
@@ -821,6 +841,7 @@ static int remove_item_instance(Item *i, const char *instance) {
a4b143
         case RELABEL_PATH:
a4b143
         case RECURSIVE_RELABEL_PATH:
a4b143
         case WRITE_FILE:
a4b143
+        case ADJUST_MODE:
a4b143
                 break;
a4b143
 
a4b143
         case REMOVE_PATH:
a4b143
@@ -866,6 +887,7 @@ static int remove_item(Item *i) {
a4b143
         case RELABEL_PATH:
a4b143
         case RECURSIVE_RELABEL_PATH:
a4b143
         case WRITE_FILE:
a4b143
+        case ADJUST_MODE:
a4b143
                 break;
a4b143
 
a4b143
         case REMOVE_PATH:
a4b143
@@ -1093,6 +1115,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
a4b143
         case RECURSIVE_REMOVE_PATH:
a4b143
         case RELABEL_PATH:
a4b143
         case RECURSIVE_RELABEL_PATH:
a4b143
+        case ADJUST_MODE:
a4b143
                 break;
a4b143
 
a4b143
         case CREATE_SYMLINK: