mirror of
https://github.com/Dasharo/systemd.git
synced 2026-03-06 15:02:31 -08:00
core: introduce a "control" unit file directory
This patch adds a concept of a "control" unit file directory, which is supposed to be used as place for unit file drop-ins created by "systemctl set-property" (note that this directory is not actually hooked up to "systemctl set-property" yet, that's coming in a later patch). The rationale for this: previously changes made by the user and by "systemctl set-property" were done in the same directory, which made semantics very unclear: the changes made by "systemctl set-property" were applied instantly, and their drop-ins only written to not lose settings on a later "systemctl daemon-reload", while drop-ins made by the user would only be in effect after "systemctl daemon-reload". This is particular problematic as the changes made by "systemctl set-property" would really apply immediately without any respect for the unit search path. This meant that using "set-property" could have an effect that is lsot as soon as "daemon-reload" is issued, in case there was a "later" drop-in already in place. With this change the directories are seperated, and the "control" directory always takes the highest priority of all, to avoid any confusion.
This commit is contained in:
@@ -29,39 +29,12 @@
|
||||
#include "mkdir.h"
|
||||
#include "path-lookup.h"
|
||||
#include "path-util.h"
|
||||
#include "rm-rf.h"
|
||||
#include "stat-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "util.h"
|
||||
|
||||
static int user_config_home(char **ret) {
|
||||
const char *e;
|
||||
char *j;
|
||||
|
||||
assert(ret);
|
||||
|
||||
e = getenv("XDG_CONFIG_HOME");
|
||||
if (e) {
|
||||
j = strappend(e, "/systemd/user");
|
||||
if (!j)
|
||||
return -ENOMEM;
|
||||
|
||||
} else {
|
||||
const char *home;
|
||||
|
||||
home = getenv("HOME");
|
||||
if (!home)
|
||||
return -ENXIO;
|
||||
|
||||
j = strappend(home, "/.config/systemd/user");
|
||||
if (!j)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
*ret = j;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int user_runtime_dir(char **ret, const char *suffix) {
|
||||
const char *e;
|
||||
char *j;
|
||||
@@ -81,7 +54,33 @@ static int user_runtime_dir(char **ret, const char *suffix) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int user_data_home_dir(char **ret, const char *suffix) {
|
||||
static int user_config_dir(char **ret, const char *suffix) {
|
||||
const char *e;
|
||||
char *j;
|
||||
|
||||
assert(ret);
|
||||
|
||||
e = getenv("XDG_CONFIG_HOME");
|
||||
if (e)
|
||||
j = strappend(e, suffix);
|
||||
else {
|
||||
const char *home;
|
||||
|
||||
home = getenv("HOME");
|
||||
if (!home)
|
||||
return -ENXIO;
|
||||
|
||||
j = strjoin(home, "/.config", suffix, NULL);
|
||||
}
|
||||
|
||||
if (!j)
|
||||
return -ENOMEM;
|
||||
|
||||
*ret = j;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int user_data_dir(char **ret, const char *suffix) {
|
||||
const char *e;
|
||||
char *j;
|
||||
|
||||
@@ -118,7 +117,9 @@ static char** user_dirs(
|
||||
const char *generator,
|
||||
const char *generator_early,
|
||||
const char *generator_late,
|
||||
const char *transient) {
|
||||
const char *transient,
|
||||
const char *persistent_control,
|
||||
const char *runtime_control) {
|
||||
|
||||
const char * const config_unit_paths[] = {
|
||||
USER_CONFIG_UNIT_PATH,
|
||||
@@ -158,7 +159,7 @@ static char** user_dirs(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
r = user_data_home_dir(&data_home, "/systemd/user");
|
||||
r = user_data_dir(&data_home, "/systemd/user");
|
||||
if (r < 0 && r != -ENXIO)
|
||||
return NULL;
|
||||
|
||||
@@ -173,13 +174,17 @@ static char** user_dirs(
|
||||
return NULL;
|
||||
|
||||
/* Now merge everything we found. */
|
||||
if (transient)
|
||||
if (strv_extend(&res, transient) < 0)
|
||||
return NULL;
|
||||
if (strv_extend(&res, persistent_control) < 0)
|
||||
return NULL;
|
||||
|
||||
if (generator_early)
|
||||
if (strv_extend(&res, generator_early) < 0)
|
||||
return NULL;
|
||||
if (strv_extend(&res, runtime_control) < 0)
|
||||
return NULL;
|
||||
|
||||
if (strv_extend(&res, transient) < 0)
|
||||
return NULL;
|
||||
|
||||
if (strv_extend(&res, generator_early) < 0)
|
||||
return NULL;
|
||||
|
||||
if (!strv_isempty(config_dirs))
|
||||
if (strv_extend_strv_concat(&res, config_dirs, "/systemd/user") < 0)
|
||||
@@ -194,13 +199,11 @@ static char** user_dirs(
|
||||
if (strv_extend(&res, runtime_config) < 0)
|
||||
return NULL;
|
||||
|
||||
if (generator)
|
||||
if (strv_extend(&res, generator) < 0)
|
||||
return NULL;
|
||||
if (strv_extend(&res, generator) < 0)
|
||||
return NULL;
|
||||
|
||||
if (data_home)
|
||||
if (strv_extend(&res, data_home) < 0)
|
||||
return NULL;
|
||||
if (strv_extend(&res, data_home) < 0)
|
||||
return NULL;
|
||||
|
||||
if (!strv_isempty(data_dirs))
|
||||
if (strv_extend_strv_concat(&res, data_dirs, "/systemd/user") < 0)
|
||||
@@ -209,9 +212,8 @@ static char** user_dirs(
|
||||
if (strv_extend_strv(&res, (char**) data_unit_paths, false) < 0)
|
||||
return NULL;
|
||||
|
||||
if (generator_late)
|
||||
if (strv_extend(&res, generator_late) < 0)
|
||||
return NULL;
|
||||
if (strv_extend(&res, generator_late) < 0)
|
||||
return NULL;
|
||||
|
||||
if (path_strv_make_absolute_cwd(res) < 0)
|
||||
return NULL;
|
||||
@@ -327,7 +329,6 @@ static int acquire_transient_dir(UnitFileScope scope, char **ret) {
|
||||
default:
|
||||
assert_not_reached("Hmm, unexpected scope value.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int acquire_config_dirs(UnitFileScope scope, char **persistent, char **runtime) {
|
||||
@@ -350,7 +351,7 @@ static int acquire_config_dirs(UnitFileScope scope, char **persistent, char **ru
|
||||
break;
|
||||
|
||||
case UNIT_FILE_USER:
|
||||
r = user_config_home(&a);
|
||||
r = user_config_dir(&a, "/systemd/user");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -377,6 +378,56 @@ static int acquire_config_dirs(UnitFileScope scope, char **persistent, char **ru
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acquire_control_dirs(UnitFileScope scope, char **persistent, char **runtime) {
|
||||
_cleanup_free_ char *a = NULL;
|
||||
int r;
|
||||
|
||||
assert(persistent);
|
||||
assert(runtime);
|
||||
|
||||
switch (scope) {
|
||||
|
||||
case UNIT_FILE_SYSTEM: {
|
||||
_cleanup_free_ char *b = NULL;
|
||||
|
||||
a = strdup("/etc/systemd/system.control");
|
||||
if (!a)
|
||||
return -ENOMEM;
|
||||
|
||||
b = strdup("/run/systemd/system.control");
|
||||
if (!b)
|
||||
return -ENOMEM;
|
||||
|
||||
*runtime = b;
|
||||
b = NULL;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case UNIT_FILE_USER:
|
||||
r = user_config_dir(&a, "/systemd/system.control");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = user_runtime_dir(runtime, "/systemd/system.control");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
break;
|
||||
|
||||
case UNIT_FILE_GLOBAL:
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
default:
|
||||
assert_not_reached("Hmm, unexpected scope value.");
|
||||
}
|
||||
|
||||
*persistent = a;
|
||||
a = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int patch_root_prefix(char **p, const char *root_dir) {
|
||||
char *c;
|
||||
|
||||
@@ -420,7 +471,8 @@ int lookup_paths_init(
|
||||
*root = NULL,
|
||||
*persistent_config = NULL, *runtime_config = NULL,
|
||||
*generator = NULL, *generator_early = NULL, *generator_late = NULL,
|
||||
*transient = NULL;
|
||||
*transient = NULL,
|
||||
*persistent_control = NULL, *runtime_control = NULL;
|
||||
bool append = false; /* Add items from SYSTEMD_UNIT_PATH before normal directories */
|
||||
char **l = NULL;
|
||||
const char *e;
|
||||
@@ -457,6 +509,10 @@ int lookup_paths_init(
|
||||
if (r < 0 && r != -EOPNOTSUPP && r != -ENXIO)
|
||||
return r;
|
||||
|
||||
r = acquire_control_dirs(scope, &persistent_control, &runtime_control);
|
||||
if (r < 0 && r != -EOPNOTSUPP && r != -ENXIO)
|
||||
return r;
|
||||
|
||||
/* First priority is whatever has been passed to us via env vars */
|
||||
e = getenv("SYSTEMD_UNIT_PATH");
|
||||
if (e) {
|
||||
@@ -494,6 +550,8 @@ int lookup_paths_init(
|
||||
add = strv_new(
|
||||
/* If you modify this you also want to modify
|
||||
* systemdsystemunitpath= in systemd.pc.in! */
|
||||
STRV_IFNOTNULL(persistent_control),
|
||||
STRV_IFNOTNULL(runtime_control),
|
||||
STRV_IFNOTNULL(transient),
|
||||
STRV_IFNOTNULL(generator_early),
|
||||
persistent_config,
|
||||
@@ -517,6 +575,8 @@ int lookup_paths_init(
|
||||
/* If you modify this you also want to modify
|
||||
* systemduserunitpath= in systemd.pc.in, and
|
||||
* the arrays in user_dirs() above! */
|
||||
STRV_IFNOTNULL(persistent_control),
|
||||
STRV_IFNOTNULL(runtime_control),
|
||||
STRV_IFNOTNULL(transient),
|
||||
STRV_IFNOTNULL(generator_early),
|
||||
persistent_config,
|
||||
@@ -537,7 +597,8 @@ int lookup_paths_init(
|
||||
case UNIT_FILE_USER:
|
||||
add = user_dirs(persistent_config, runtime_config,
|
||||
generator, generator_early, generator_late,
|
||||
transient);
|
||||
transient,
|
||||
persistent_config, runtime_control);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -578,6 +639,14 @@ int lookup_paths_init(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = patch_root_prefix(&persistent_control, root);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = patch_root_prefix(&runtime_control, root);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = patch_root_prefix_strv(l, root);
|
||||
if (r < 0)
|
||||
return -ENOMEM;
|
||||
@@ -597,6 +666,10 @@ int lookup_paths_init(
|
||||
p->transient = transient;
|
||||
transient = NULL;
|
||||
|
||||
p->persistent_control = persistent_control;
|
||||
p->runtime_control = runtime_control;
|
||||
persistent_control = runtime_control = NULL;
|
||||
|
||||
p->root_dir = root;
|
||||
root = NULL;
|
||||
|
||||
@@ -618,6 +691,9 @@ void lookup_paths_free(LookupPaths *p) {
|
||||
|
||||
p->transient = mfree(p->transient);
|
||||
|
||||
p->persistent_control = mfree(p->persistent_control);
|
||||
p->runtime_control = mfree(p->runtime_control);
|
||||
|
||||
p->root_dir = mfree(p->root_dir);
|
||||
}
|
||||
|
||||
@@ -730,6 +806,8 @@ void lookup_paths_trim_generator(LookupPaths *p) {
|
||||
void lookup_paths_flush_generator(LookupPaths *p) {
|
||||
assert(p);
|
||||
|
||||
/* Flush the generated unit files in full */
|
||||
|
||||
if (p->generator)
|
||||
(void) rm_rf(p->generator, REMOVE_ROOT);
|
||||
if (p->generator_early)
|
||||
|
||||
@@ -27,20 +27,33 @@ typedef struct LookupPaths LookupPaths;
|
||||
#include "macro.h"
|
||||
|
||||
struct LookupPaths {
|
||||
/* Where we look for unit files. This includes the individual special paths below, but also any vendor
|
||||
* supplied, static unit file paths. */
|
||||
char **search_path;
|
||||
|
||||
/* Where we shall create or remove our installation symlinks, aka "configuration". */
|
||||
/* Where we shall create or remove our installation symlinks, aka "configuration", and where the user/admin
|
||||
* shall place his own unit files. */
|
||||
char *persistent_config;
|
||||
char *runtime_config;
|
||||
|
||||
/* Where to place generated unit files */
|
||||
/* Where to place generated unit files (i.e. those a "generator" tool generated). Note the special semantics of
|
||||
* this directory: the generators are flushed each time a "systemctl daemon-reload" is issued. The user should
|
||||
* not alter these directories directly. */
|
||||
char *generator;
|
||||
char *generator_early;
|
||||
char *generator_late;
|
||||
|
||||
/* Where to place transient unit files */
|
||||
/* Where to place transient unit files (i.e. those created dynamically via the bus API). Note the special
|
||||
* semantics of this directory: all units created transiently have their unit files removed as the transient
|
||||
* unit is unloaded. The user should not alter this directory directly. */
|
||||
char *transient;
|
||||
|
||||
/* Where the snippets created by "systemctl set-property" are placed. Note that for transient units, the
|
||||
* snippets are placed in the transient directory though (see above). The user should not alter this directory
|
||||
* directly. */
|
||||
char *persistent_control;
|
||||
char *runtime_control;
|
||||
|
||||
/* The root directory prepended to all items above, or NULL */
|
||||
char *root_dir;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user