Merge pull request #22649 from keszybz/symlink-enablement-yet-again-punish-me-harder

Fixups to the unit enablement logic
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2022-03-29 21:10:03 +02:00
committed by GitHub
78 changed files with 2503 additions and 1372 deletions
+2 -1
View File
@@ -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;
}
+8 -4
View File
@@ -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);
}
+5 -1
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+27 -20
View File
@@ -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
View File
@@ -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;
+5 -5
View File
@@ -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 }, \
+19
View File
@@ -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;
+2
View File
@@ -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 */