Merge pull request #22649 from keszybz/symlink-enablement-yet-again-punish-me-harder
Fixups to the unit enablement logic
This commit is contained in:
@@ -785,7 +785,8 @@ static int condition_test_needs_update(Condition *c, char **env) {
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to parse timestamp file '%s', using mtime: %m", p);
|
||||
return true;
|
||||
} else if (r == 0) {
|
||||
}
|
||||
if (isempty(timestamp_str)) {
|
||||
log_debug("No data in timestamp file '%s', using mtime.", p);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -97,7 +97,11 @@ static int specifier_last_component(char specifier, const void *data, const char
|
||||
return 0;
|
||||
}
|
||||
|
||||
int install_name_printf(const UnitFileInstallInfo *i, const char *format, const char *root, char **ret) {
|
||||
int install_name_printf(
|
||||
LookupScope scope,
|
||||
const UnitFileInstallInfo *info,
|
||||
const char *format,
|
||||
char **ret) {
|
||||
/* This is similar to unit_name_printf() */
|
||||
|
||||
const Specifier table[] = {
|
||||
@@ -109,13 +113,13 @@ int install_name_printf(const UnitFileInstallInfo *i, const char *format, const
|
||||
|
||||
COMMON_SYSTEM_SPECIFIERS,
|
||||
|
||||
COMMON_CREDS_SPECIFIERS,
|
||||
COMMON_CREDS_SPECIFIERS(scope),
|
||||
{}
|
||||
};
|
||||
|
||||
assert(i);
|
||||
assert(info);
|
||||
assert(format);
|
||||
assert(ret);
|
||||
|
||||
return specifier_printf(format, UNIT_NAME_MAX, table, root, i, ret);
|
||||
return specifier_printf(format, UNIT_NAME_MAX, table, info->root, info, ret);
|
||||
}
|
||||
|
||||
@@ -4,4 +4,8 @@
|
||||
#include "install.h"
|
||||
#include "unit-name.h"
|
||||
|
||||
int install_name_printf(const UnitFileInstallInfo *i, const char *format, const char *root, char **ret);
|
||||
int install_name_printf(
|
||||
LookupScope scope,
|
||||
const UnitFileInstallInfo *info,
|
||||
const char *format,
|
||||
char **ret);
|
||||
|
||||
+638
-468
File diff suppressed because it is too large
Load Diff
+27
-20
@@ -15,6 +15,7 @@ typedef struct UnitFileInstallInfo UnitFileInstallInfo;
|
||||
#include "macro.h"
|
||||
#include "path-lookup.h"
|
||||
#include "strv.h"
|
||||
#include "unit-file.h"
|
||||
#include "unit-name.h"
|
||||
|
||||
enum UnitFilePresetMode {
|
||||
@@ -70,7 +71,8 @@ struct UnitFileList {
|
||||
|
||||
enum UnitFileType {
|
||||
UNIT_FILE_TYPE_REGULAR,
|
||||
UNIT_FILE_TYPE_SYMLINK,
|
||||
UNIT_FILE_TYPE_LINKED,
|
||||
UNIT_FILE_TYPE_ALIAS,
|
||||
UNIT_FILE_TYPE_MASKED,
|
||||
_UNIT_FILE_TYPE_MAX,
|
||||
_UNIT_FILE_TYPE_INVALID = -EINVAL,
|
||||
@@ -94,28 +96,28 @@ struct UnitFileInstallInfo {
|
||||
};
|
||||
|
||||
int unit_file_enable(
|
||||
UnitFileScope scope,
|
||||
LookupScope scope,
|
||||
UnitFileFlags flags,
|
||||
const char *root_dir,
|
||||
char **files,
|
||||
UnitFileChange **changes,
|
||||
size_t *n_changes);
|
||||
int unit_file_disable(
|
||||
UnitFileScope scope,
|
||||
LookupScope scope,
|
||||
UnitFileFlags flags,
|
||||
const char *root_dir,
|
||||
char **files,
|
||||
UnitFileChange **changes,
|
||||
size_t *n_changes);
|
||||
int unit_file_reenable(
|
||||
UnitFileScope scope,
|
||||
LookupScope scope,
|
||||
UnitFileFlags flags,
|
||||
const char *root_dir,
|
||||
char **files,
|
||||
char **names_or_paths,
|
||||
UnitFileChange **changes,
|
||||
size_t *n_changes);
|
||||
int unit_file_preset(
|
||||
UnitFileScope scope,
|
||||
LookupScope scope,
|
||||
UnitFileFlags flags,
|
||||
const char *root_dir,
|
||||
char **files,
|
||||
@@ -123,52 +125,52 @@ int unit_file_preset(
|
||||
UnitFileChange **changes,
|
||||
size_t *n_changes);
|
||||
int unit_file_preset_all(
|
||||
UnitFileScope scope,
|
||||
LookupScope scope,
|
||||
UnitFileFlags flags,
|
||||
const char *root_dir,
|
||||
UnitFilePresetMode mode,
|
||||
UnitFileChange **changes,
|
||||
size_t *n_changes);
|
||||
int unit_file_mask(
|
||||
UnitFileScope scope,
|
||||
LookupScope scope,
|
||||
UnitFileFlags flags,
|
||||
const char *root_dir,
|
||||
char **files,
|
||||
UnitFileChange **changes,
|
||||
size_t *n_changes);
|
||||
int unit_file_unmask(
|
||||
UnitFileScope scope,
|
||||
LookupScope scope,
|
||||
UnitFileFlags flags,
|
||||
const char *root_dir,
|
||||
char **files,
|
||||
UnitFileChange **changes,
|
||||
size_t *n_changes);
|
||||
int unit_file_link(
|
||||
UnitFileScope scope,
|
||||
LookupScope scope,
|
||||
UnitFileFlags flags,
|
||||
const char *root_dir,
|
||||
char **files,
|
||||
UnitFileChange **changes,
|
||||
size_t *n_changes);
|
||||
int unit_file_revert(
|
||||
UnitFileScope scope,
|
||||
LookupScope scope,
|
||||
const char *root_dir,
|
||||
char **files,
|
||||
UnitFileChange **changes,
|
||||
size_t *n_changes);
|
||||
int unit_file_set_default(
|
||||
UnitFileScope scope,
|
||||
LookupScope scope,
|
||||
UnitFileFlags flags,
|
||||
const char *root_dir,
|
||||
const char *file,
|
||||
UnitFileChange **changes,
|
||||
size_t *n_changes);
|
||||
int unit_file_get_default(
|
||||
UnitFileScope scope,
|
||||
LookupScope scope,
|
||||
const char *root_dir,
|
||||
char **name);
|
||||
int unit_file_add_dependency(
|
||||
UnitFileScope scope,
|
||||
LookupScope scope,
|
||||
UnitFileFlags flags,
|
||||
const char *root_dir,
|
||||
char **files,
|
||||
@@ -178,22 +180,27 @@ int unit_file_add_dependency(
|
||||
size_t *n_changes);
|
||||
|
||||
int unit_file_lookup_state(
|
||||
UnitFileScope scope,
|
||||
LookupScope scope,
|
||||
const LookupPaths *paths,
|
||||
const char *name,
|
||||
UnitFileState *ret);
|
||||
|
||||
int unit_file_get_state(UnitFileScope scope, const char *root_dir, const char *filename, UnitFileState *ret);
|
||||
int unit_file_exists(UnitFileScope scope, const LookupPaths *paths, const char *name);
|
||||
int unit_file_get_state(LookupScope scope, const char *root_dir, const char *filename, UnitFileState *ret);
|
||||
int unit_file_exists(LookupScope scope, const LookupPaths *paths, const char *name);
|
||||
|
||||
int unit_file_get_list(UnitFileScope scope, const char *root_dir, Hashmap *h, char **states, char **patterns);
|
||||
int unit_file_get_list(LookupScope scope, const char *root_dir, Hashmap *h, char **states, char **patterns);
|
||||
Hashmap* unit_file_list_free(Hashmap *h);
|
||||
|
||||
int unit_file_changes_add(UnitFileChange **changes, size_t *n_changes, int type, const char *path, const char *source);
|
||||
void unit_file_changes_free(UnitFileChange *changes, size_t n_changes);
|
||||
void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *changes, size_t n_changes, bool quiet);
|
||||
|
||||
int unit_file_verify_alias(const UnitFileInstallInfo *i, const char *dst, char **ret_dst);
|
||||
int unit_file_verify_alias(
|
||||
const UnitFileInstallInfo *info,
|
||||
const char *dst,
|
||||
char **ret_dst,
|
||||
UnitFileChange **changes,
|
||||
size_t *n_changes);
|
||||
|
||||
typedef struct UnitFilePresetRule UnitFilePresetRule;
|
||||
|
||||
@@ -204,7 +211,7 @@ typedef struct {
|
||||
} UnitFilePresets;
|
||||
|
||||
void unit_file_presets_freep(UnitFilePresets *p);
|
||||
int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name, UnitFilePresets *cached);
|
||||
int unit_file_query_preset(LookupScope scope, const char *root_dir, const char *name, UnitFilePresets *cached);
|
||||
|
||||
const char *unit_file_state_to_string(UnitFileState s) _const_;
|
||||
UnitFileState unit_file_state_from_string(const char *s) _pure_;
|
||||
|
||||
+57
-22
@@ -18,6 +18,7 @@
|
||||
#include "id128-util.h"
|
||||
#include "macro.h"
|
||||
#include "os-util.h"
|
||||
#include "path-lookup.h"
|
||||
#include "path-util.h"
|
||||
#include "specifier.h"
|
||||
#include "string-util.h"
|
||||
@@ -162,7 +163,8 @@ int specifier_machine_id(char specifier, const void *data, const char *root, con
|
||||
|
||||
fd = chase_symlinks_and_open("/etc/machine-id", root, CHASE_PREFIX_ROOT, O_RDONLY|O_CLOEXEC|O_NOCTTY, NULL);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
/* Translate error for missing os-release file to EUNATCH. */
|
||||
return fd == -ENOENT ? -EUNATCH : fd;
|
||||
|
||||
r = id128_read_fd(fd, ID128_PLAIN, &id);
|
||||
} else
|
||||
@@ -269,44 +271,54 @@ int specifier_architecture(char specifier, const void *data, const char *root, c
|
||||
}
|
||||
|
||||
/* Note: fields in /etc/os-release might quite possibly be missing, even if everything is entirely valid
|
||||
* otherwise. We'll return an empty value or NULL in that case from the functions below. */
|
||||
* otherwise. We'll return an empty value or NULL in that case from the functions below. But if the
|
||||
* os-release file is missing, we'll return -EUNATCH. This means that something is seriously wrong with the
|
||||
* installation. */
|
||||
|
||||
static int parse_os_release_specifier(const char *root, const char *id, char **ret) {
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
/* Translate error for missing os-release file to EUNATCH. */
|
||||
r = parse_os_release(root, id, ret);
|
||||
return r == -ENOENT ? -EUNATCH : r;
|
||||
}
|
||||
|
||||
int specifier_os_id(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
|
||||
assert(ret);
|
||||
return parse_os_release(root, "ID", ret);
|
||||
return parse_os_release_specifier(root, "ID", ret);
|
||||
}
|
||||
|
||||
int specifier_os_version_id(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
|
||||
assert(ret);
|
||||
return parse_os_release(root, "VERSION_ID", ret);
|
||||
return parse_os_release_specifier(root, "VERSION_ID", ret);
|
||||
}
|
||||
|
||||
int specifier_os_build_id(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
|
||||
assert(ret);
|
||||
return parse_os_release(root, "BUILD_ID", ret);
|
||||
return parse_os_release_specifier(root, "BUILD_ID", ret);
|
||||
}
|
||||
|
||||
int specifier_os_variant_id(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
|
||||
assert(ret);
|
||||
return parse_os_release(root, "VARIANT_ID", ret);
|
||||
return parse_os_release_specifier(root, "VARIANT_ID", ret);
|
||||
}
|
||||
|
||||
int specifier_os_image_id(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
|
||||
assert(ret);
|
||||
return parse_os_release(root, "IMAGE_ID", ret);
|
||||
return parse_os_release_specifier(root, "IMAGE_ID", ret);
|
||||
}
|
||||
|
||||
int specifier_os_image_version(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
|
||||
assert(ret);
|
||||
return parse_os_release(root, "IMAGE_VERSION", ret);
|
||||
return parse_os_release_specifier(root, "IMAGE_VERSION", ret);
|
||||
}
|
||||
|
||||
int specifier_group_name(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
|
||||
LookupScope scope = PTR_TO_INT(data);
|
||||
char *t;
|
||||
|
||||
assert(ret);
|
||||
|
||||
t = gid_to_name(getgid());
|
||||
if (scope == LOOKUP_SCOPE_GLOBAL)
|
||||
return -EINVAL;
|
||||
|
||||
t = gid_to_name(scope == LOOKUP_SCOPE_USER ? getgid() : 0);
|
||||
if (!t)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -315,27 +327,42 @@ int specifier_group_name(char specifier, const void *data, const char *root, con
|
||||
}
|
||||
|
||||
int specifier_group_id(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
|
||||
LookupScope scope = PTR_TO_INT(data);
|
||||
gid_t gid;
|
||||
|
||||
assert(ret);
|
||||
|
||||
if (asprintf(ret, UID_FMT, getgid()) < 0)
|
||||
if (scope == LOOKUP_SCOPE_GLOBAL)
|
||||
return -EINVAL;
|
||||
|
||||
gid = scope == LOOKUP_SCOPE_USER ? getgid() : 0;
|
||||
|
||||
if (asprintf(ret, UID_FMT, gid) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int specifier_user_name(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
|
||||
LookupScope scope = PTR_TO_INT(data);
|
||||
uid_t uid;
|
||||
char *t;
|
||||
|
||||
assert(ret);
|
||||
|
||||
/* If we are UID 0 (root), this will not result in NSS, otherwise it might. This is good, as we want to be able
|
||||
* to run this in PID 1, where our user ID is 0, but where NSS lookups are not allowed.
|
||||
if (scope == LOOKUP_SCOPE_GLOBAL)
|
||||
return -EINVAL;
|
||||
|
||||
* We don't use getusername_malloc() here, because we don't want to look at $USER, to remain consistent with
|
||||
* specifer_user_id() below.
|
||||
uid = scope == LOOKUP_SCOPE_USER ? getuid() : 0;
|
||||
|
||||
/* If we are UID 0 (root), this will not result in NSS, otherwise it might. This is good, as we want
|
||||
* to be able to run this in PID 1, where our user ID is 0, but where NSS lookups are not allowed.
|
||||
|
||||
* We don't use getusername_malloc() here, because we don't want to look at $USER, to remain
|
||||
* consistent with specifer_user_id() below.
|
||||
*/
|
||||
|
||||
t = uid_to_name(getuid());
|
||||
t = uid_to_name(uid);
|
||||
if (!t)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -344,9 +371,17 @@ int specifier_user_name(char specifier, const void *data, const char *root, cons
|
||||
}
|
||||
|
||||
int specifier_user_id(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
|
||||
LookupScope scope = PTR_TO_INT(data);
|
||||
uid_t uid;
|
||||
|
||||
assert(ret);
|
||||
|
||||
if (asprintf(ret, UID_FMT, getuid()) < 0)
|
||||
if (scope == LOOKUP_SCOPE_GLOBAL)
|
||||
return -EINVAL;
|
||||
|
||||
uid = scope == LOOKUP_SCOPE_USER ? getuid() : 0;
|
||||
|
||||
if (asprintf(ret, UID_FMT, uid) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -84,11 +84,11 @@ int specifier_var_tmp_dir(char specifier, const void *data, const char *root, co
|
||||
{ 'w', specifier_os_version_id, NULL }, \
|
||||
{ 'W', specifier_os_variant_id, NULL }
|
||||
|
||||
#define COMMON_CREDS_SPECIFIERS \
|
||||
{ 'g', specifier_group_name, NULL }, \
|
||||
{ 'G', specifier_group_id, NULL }, \
|
||||
{ 'u', specifier_user_name, NULL }, \
|
||||
{ 'U', specifier_user_id, NULL }
|
||||
#define COMMON_CREDS_SPECIFIERS(scope) \
|
||||
{ 'g', specifier_group_name, INT_TO_PTR(scope) }, \
|
||||
{ 'G', specifier_group_id, INT_TO_PTR(scope) }, \
|
||||
{ 'u', specifier_user_name, INT_TO_PTR(scope) }, \
|
||||
{ 'U', specifier_user_id, INT_TO_PTR(scope) }
|
||||
|
||||
#define COMMON_TMP_SPECIFIERS \
|
||||
{ 'T', specifier_tmp_dir, NULL }, \
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "cgroup-util.h"
|
||||
#include "env-file.h"
|
||||
#include "env-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "log.h"
|
||||
#include "namespace-util.h"
|
||||
@@ -33,6 +34,7 @@
|
||||
#include "random-util.h"
|
||||
#include "strv.h"
|
||||
#include "tests.h"
|
||||
#include "tmpfile-util.h"
|
||||
|
||||
char* setup_fake_runtime_dir(void) {
|
||||
char t[] = "/tmp/fake-xdg-runtime-XXXXXX", *p;
|
||||
@@ -132,6 +134,23 @@ int log_tests_skipped_errno(int r, const char *message) {
|
||||
return EXIT_TEST_SKIP;
|
||||
}
|
||||
|
||||
int write_tmpfile(char *pattern, const char *contents) {
|
||||
_cleanup_close_ int fd = -1;
|
||||
|
||||
assert(pattern);
|
||||
assert(contents);
|
||||
|
||||
fd = mkostemp_safe(pattern);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
ssize_t l = strlen(contents);
|
||||
errno = 0;
|
||||
if (write(fd, contents, l) != l)
|
||||
return errno_or_else(EIO);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool have_namespaces(void) {
|
||||
siginfo_t si = {};
|
||||
pid_t pid;
|
||||
|
||||
@@ -30,6 +30,8 @@ void test_setup_logging(int level);
|
||||
int log_tests_skipped(const char *message);
|
||||
int log_tests_skipped_errno(int r, const char *message);
|
||||
|
||||
int write_tmpfile(char *pattern, const char *contents);
|
||||
|
||||
bool have_namespaces(void);
|
||||
|
||||
/* We use the small but non-trivial limit here */
|
||||
|
||||
Reference in New Issue
Block a user