]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
tmpfiles: introduce an explicit line flag $ for enabling purge logic for a line
authorLennart Poettering <lennart@poettering.net>
Thu, 12 Sep 2024 16:23:06 +0000 (18:23 +0200)
committerLennart Poettering <lennart@poettering.net>
Sun, 15 Sep 2024 17:43:09 +0000 (19:43 +0200)
Let's make the risk of accidental misuse, and mark lines that shall be
covered by --purge with an explicit new flag "$".

See: #33349

NEWS
man/systemd-tmpfiles.xml
man/tmpfiles.d.xml
src/tmpfiles/tmpfiles.c
test/units/TEST-22-TMPFILES.18.sh

diff --git a/NEWS b/NEWS
index 81b6380cedf9f3998128be88f43994f50335c6fa..915d61abe30de3a158d3fc11a349590e414f1b32 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,15 @@ systemd System and Service Manager
 
 CHANGES WITH 257 in spe:
 
+        Incompatible changes:
+
+        * The --purge switch of systemd-tmpfiles (which was added in v256) has
+          been reworked: it will now only apply to tmpfiles.d/ lines marked
+          with the new "$" flag. This is an incompatible change, and means any
+          tmpfiles.d/ files which shall be used together with --purge need to
+          be updated accordingly. This change has been made to make it harder
+          to accidentally delete too many files when using --purge incorrectly.
+
         Announcements of Future Feature Removals and Incompatible Changes:
 
         * Support for automatic flushing of the nscd user/group database caches
index f3108b53d9cb96c6a1588994fa8cb7ee97f4bc3a..b7b4d0dca68ec1a54603566e77d7e4ea8c0128d6 100644 (file)
       <varlistentry>
         <term><option>--purge</option></term>
 
-        <listitem><para>If this option is passed, all files and directories marked for
-        <emphasis>creation</emphasis> by the <filename>tmpfiles.d/</filename> files specified on the command
-        line will be <emphasis>deleted</emphasis>. Specifically, this acts on all files and directories
-        marked with <varname>f</varname>, <varname>F</varname>, <varname>d</varname>, <varname>D</varname>,
+        <listitem><para>If this option is passed, all files and directories declared for
+        <emphasis>creation</emphasis> and marked with the <literal>$</literal> character by the
+        <filename>tmpfiles.d/</filename> files specified on the command line will be
+        <emphasis>deleted</emphasis>. Specifically, this acts on all files and directories marked with
+        <varname>f</varname>, <varname>F</varname>, <varname>d</varname>, <varname>D</varname>,
         <varname>v</varname>, <varname>q</varname>, <varname>Q</varname>, <varname>p</varname>,
         <varname>L</varname>, <varname>c</varname>, <varname>b</varname>, <varname>C</varname>,
         <varname>w</varname>, <varname>e</varname>. If this switch is used at least one
index 15027def60526e7734f3f6df7b61187a27f729bb..a721c1e66d4efee14d789d8021fde678d85efffb 100644 (file)
@@ -539,6 +539,10 @@ w- /proc/sys/vm/swappiness - - - - 10</programlisting></para>
       service, the line is silently skipped. If <literal>^</literal> and <literal>~</literal> are combined
       Base64 decoding is applied to the credential contents.</para>
 
+      <para>If the dollar sign (<literal>$</literal>) is used, the file becomes subject to removal when
+      <command>systemd-tmpfiles</command> is invoked with the <option>--purge</option> switch. Lines without
+      this character are unaffected by that switch.</para>
+
       <para>Note that for all line types that result in creation of any kind of file node
       (i.e. <varname>f</varname>,
       <varname>d</varname>/<varname>D</varname>/<varname>v</varname>/<varname>q</varname>/<varname>Q</varname>,
index 59b48492ab74dafe7f795373fe2f3c1cfdf8ae7f..16f831bc2624550ab920716c82d29ef7173a2f33 100644 (file)
@@ -170,6 +170,8 @@ typedef struct Item {
 
         bool try_replace:1;
 
+        bool purge:1;
+
         OperationMask done;
 } Item;
 
@@ -3046,6 +3048,9 @@ static int purge_item(Context *c, Item *i) {
         if (!needs_purge(i->type))
                 return 0;
 
+        if (!i->purge)
+                return 0;
+
         log_debug("Running purge action for entry %c %s", (char) i->type, i->path);
 
         if (needs_glob(i->type))
@@ -3602,7 +3607,7 @@ static int parse_line(
         ItemArray *existing;
         OrderedHashmap *h;
         bool append_or_force = false, boot = false, allow_failure = false, try_replace = false,
-                unbase64 = false, from_cred = false, missing_user_or_group = false;
+                unbase64 = false, from_cred = false, missing_user_or_group = false, purge = false;
         int r;
 
         assert(fname);
@@ -3668,6 +3673,8 @@ static int parse_line(
                         unbase64 = true;
                 else if (action[pos] == '^' && !from_cred)
                         from_cred = true;
+                else if (action[pos] == '$' && !purge)
+                        purge = true;
                 else {
                         *invalid_config = true;
                         return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EBADMSG),
@@ -3684,6 +3691,7 @@ static int parse_line(
         i.append_or_force = append_or_force;
         i.allow_failure = allow_failure;
         i.try_replace = try_replace;
+        i.purge = purge;
 
         r = specifier_printf(path, PATH_MAX-1, specifier_table, arg_root, NULL, &i.path);
         if (ERRNO_IS_NOINFO(r))
@@ -3838,6 +3846,12 @@ static int parse_line(
                                   "Unknown command type '%c'.", (char) i.type);
         }
 
+        if (i.purge && !needs_purge(i.type)) {
+                *invalid_config = true;
+                return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EBADMSG),
+                                  "Purge flag '$' combined with line type '%c' which does not support purging.", (char) i.type);
+        }
+
         if (!should_include_path(i.path))
                 return 0;
 
index 5d24197c8137b32a5e8596a1e43092f1bca98e99..c81f6bd0ef5a7571b4d1fa18df5a5d102a4f4334 100755 (executable)
@@ -9,26 +9,39 @@ set -o pipefail
 export SYSTEMD_LOG_LEVEL=debug
 
 c='
-d /tmp/somedir
-f /tmp/somedir/somefile - - - - baz
+d$ /tmp/somedir
+f$ /tmp/somedir/somefile - - - - baz
+f /tmp/someotherfile - - - - qux
 '
 
 systemd-tmpfiles --create - <<<"$c"
 test -f /tmp/somedir/somefile
 grep -q baz /tmp/somedir/somefile
+grep -q qux /tmp/someotherfile
 
 systemd-tmpfiles --purge --dry-run - <<<"$c"
 test -f /tmp/somedir/somefile
 grep -q baz /tmp/somedir/somefile
+grep -q qux /tmp/someotherfile
 
 systemd-tmpfiles --purge - <<<"$c"
 test ! -f /tmp/somedir/somefile
 test ! -d /tmp/somedir/
+grep -q qux /tmp/someotherfile
 
 systemd-tmpfiles --create --purge --dry-run - <<<"$c"
 test ! -f /tmp/somedir/somefile
 test ! -d /tmp/somedir/
+grep -q qux /tmp/someotherfile
 
 systemd-tmpfiles --create --purge - <<<"$c"
 test -f /tmp/somedir/somefile
 grep -q baz /tmp/somedir/somefile
+grep -q qux /tmp/someotherfile
+
+systemd-tmpfiles --purge - <<<"$c"
+test ! -f /tmp/somedir/somefile
+test ! -d /tmp/somedir/
+grep -q qux /tmp/someotherfile
+
+rm /tmp/someotherfile