From 949befd3f09e8c06a908ec99efd241666c21d944 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 30 Nov 2017 11:52:39 +0100 Subject: [PATCH] core: support upgrading from DynamicUser=0 to DynamicUser=1 for unit directories (#7507) This makes sure we migrate /var/lib/ if it exists to /var/lib/private/ 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/, which works because /var/lib/ is a symlink there after all. --- src/core/execute.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index 2b936bcf4af..59a8d60fe3e 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -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) { -- 2.39.2