]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: support upgrading from DynamicUser=0 to DynamicUser=1 for unit directories...
authorLennart Poettering <lennart@poettering.net>
Thu, 30 Nov 2017 10:52:39 +0000 (11:52 +0100)
committerGitHub <noreply@github.com>
Thu, 30 Nov 2017 10:52:39 +0000 (11:52 +0100)
This makes sure we migrate /var/lib/<foo> if it exists to
/var/lib/private/<foo> if DynamicUser=1 is set. This is useful to allow
turning on DynamicUser= on services that previously didn't use it, and
we can deal with this, and migrate the relevant directories as
necessary.

Note that "downgrading" from DynamicUser=1 backto DynamicUser=0 works
too. However in that case we simply continue to use
/var/lib/private/<foo>, which works because /var/lib/<foo> is a symlink
there after all.

src/core/execute.c

index 2b936bcf4af3102d401e5b496e89d75281fda780..59a8d60fe3e38df7e52d2e5fad162bf871610df5 100644 (file)
@@ -98,6 +98,7 @@
 #include "signal-util.h"
 #include "smack-util.h"
 #include "special.h"
+#include "stat-util.h"
 #include "string-table.h"
 #include "string-util.h"
 #include "strv.h"
@@ -2077,10 +2078,24 @@ static int setup_exec_directory(
                         if (r < 0)
                                 goto fail;
 
-                        /* Finally, create the actual directory for the service */
-                        r = mkdir_label(pp, context->directories[type].mode);
-                        if (r < 0 && r != -EEXIST)
-                                goto fail;
+                        if (is_dir(p, false) > 0 &&
+                            (laccess(pp, F_OK) < 0 && errno == ENOENT)) {
+
+                                /* Hmm, the private directory doesn't exist yet, but the normal one exists? If so, move
+                                 * it over. Most likely the service has been upgraded from one that didn't use
+                                 * DynamicUser=1, to one that does. */
+
+                                if (rename(p, pp) < 0) {
+                                        r = -errno;
+                                        goto fail;
+                                }
+                        } else {
+                                /* Otherwise, create the actual directory for the service */
+
+                                r = mkdir_label(pp, context->directories[type].mode);
+                                if (r < 0 && r != -EEXIST)
+                                        goto fail;
+                        }
 
                         parent = dirname_malloc(p);
                         if (!parent) {