diff options
-rwxr-xr-x | .github/workflows/build_test.sh | 1 | ||||
-rw-r--r-- | TODO | 2 | ||||
-rw-r--r-- | hwdb.d/60-sensor.hwdb | 12 | ||||
-rw-r--r-- | man/bootctl.xml | 13 | ||||
-rw-r--r-- | meson.build | 3 | ||||
-rw-r--r-- | rules.d/50-udev-default.rules.in | 2 | ||||
-rw-r--r-- | src/basic/selinux-util.c | 29 | ||||
-rw-r--r-- | src/basic/unit-file.c | 199 | ||||
-rw-r--r-- | src/boot/bootctl.c | 116 | ||||
-rw-r--r-- | src/core/manager.c | 3 | ||||
-rw-r--r-- | src/test/test-unit-file.c | 1 | ||||
-rw-r--r-- | test/test-functions | 17 | ||||
-rwxr-xr-x | test/units/testsuite-15.sh | 44 |
13 files changed, 321 insertions, 121 deletions
diff --git a/.github/workflows/build_test.sh b/.github/workflows/build_test.sh index 8ad7e76790..8471ea181e 100755 --- a/.github/workflows/build_test.sh +++ b/.github/workflows/build_test.sh @@ -13,6 +13,7 @@ ARGS=( "--optimization=3 -Db_lto=true" "--optimization=3 -Db_lto=false" "--optimization=3 -Ddns-over-tls=openssl" + "--optimization=3 -Dfexecve=true -Dstandalone-binaries=true -Dstatic-libsystemd=true -Dstatic-libudev=true" "-Db_ndebug=true" ) PACKAGES=( @@ -228,8 +228,6 @@ Features: * systemd-analyze netif that explains predictable interface (or networkctl) -* port selinux code from mallinfo() to mallinfo2() once added to glibc - * Add service setting to run a service within the specified VRF. i.e. do the equivalent of "ip vrf exec". diff --git a/hwdb.d/60-sensor.hwdb b/hwdb.d/60-sensor.hwdb index c76509e2af..1c061b3e90 100644 --- a/hwdb.d/60-sensor.hwdb +++ b/hwdb.d/60-sensor.hwdb @@ -345,6 +345,14 @@ sensor:modalias:acpi:KIOX010A*:dmi:*:svnGEO*:pnGeoFlex*:* ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, -1, 0; 0, 0, 1 ######################################### +# Glavey +######################################### + +# Glavey TM800A550L +sensor:modalias:acpi:KXCJ9000*:dmi:*:bvrZY-8-BI-PX4S70VTR400-X423B-005-D:*:rvnAMICorporation:rnAptioCRB:* + ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1 + +######################################### # Google Chromebooks ######################################### sensor:modalias:platform:cros-ec-accel:dmi:*:svnGOOGLE:* @@ -778,6 +786,10 @@ sensor:modalias:acpi:BMA250E*:dmi:bvnAmericanMegatrendsInc.:bvr5.6.5:bd04/15/201 # Toshiba ######################################### +# Toshiba Encore WT8-B tablet +sensor:modalias:acpi:INVN6500*:dmi:*:svnTOSHIBA:pnTOSHIBAENCORE2WT8-B:* + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 + # Toshiba Encore WT10A tablet sensor:modalias:acpi:INVN6500*:dmi:*:svnTOSHIBA:pnTOSHIBAWT10-A-103:* ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 diff --git a/man/bootctl.xml b/man/bootctl.xml index 878f24742e..5dfed110dd 100644 --- a/man/bootctl.xml +++ b/man/bootctl.xml @@ -237,6 +237,19 @@ cannot be written. Currently only applies to random seed operations.</para></listitem> </varlistentry> + <varlistentry> + <term><option>--make-machine-id-directory=yes|no|auto</option></term> + <listitem><para>Control creation and deletion of <literal>$ESP/$MACHINE_ID</literal> during + <option>install</option> and <option>remove</option>, respectively. + <literal>auto</literal> is equivalent to to <literal>yes</literal> if <literal>/etc/machine-id</literal> + resides on a filesystem other than tmpfs and <literal>no</literal> otherwise. + Defaults to <literal>auto</literal>.</para> + + <para>Overriding this may be desired to hide the machine ID from the (unencrypted) ESP, + configure a <citerefentry><refentrytitle>kernel-install</refentrytitle><manvolnum>8</manvolnum></citerefentry> script, or, + conversely, commit a machine-id that only appears transient.</para></listitem> + </varlistentry> + <xi:include href="standard-options.xml" xpointer="no-pager"/> <xi:include href="standard-options.xml" xpointer="help"/> <xi:include href="standard-options.xml" xpointer="version"/> diff --git a/meson.build b/meson.build index b13817f0d2..ee94d5c354 100644 --- a/meson.build +++ b/meson.build @@ -555,6 +555,7 @@ foreach ident : [ #include <signal.h> #include <sys/wait.h>'''], ['mallinfo', '''#include <malloc.h>'''], + ['mallinfo2', '''#include <malloc.h>'''], ['execveat', '''#include <unistd.h>'''], ['close_range', '''#include <unistd.h>'''], ['epoll_pwait2', '''#include <sys/epoll.h>'''], @@ -721,7 +722,7 @@ if time_epoch == -1 if time_epoch == '' and git.found() and run_command('test', '-e', '.git').returncode() == 0 # If we're in a git repository, use the creation time of the latest git tag. latest_tag = run_command('git', 'describe', '--abbrev=0', '--tags').stdout().strip() - time_epoch = run_command('git', 'log', '-1', '--format=%at', latest_tag).stdout() + time_epoch = run_command('git', 'log', '--no-show-signature', '-1', '--format=%at', latest_tag).stdout() endif if time_epoch == '' NEWS = files('NEWS') diff --git a/rules.d/50-udev-default.rules.in b/rules.d/50-udev-default.rules.in index 53d485dabf..3304e32bb6 100644 --- a/rules.d/50-udev-default.rules.in +++ b/rules.d/50-udev-default.rules.in @@ -91,6 +91,8 @@ KERNEL=="fuse", MODE="0666", OPTIONS+="static_node=fuse" # The static_node is required on s390x and ppc (they are using MODULE_ALIAS) KERNEL=="kvm", GROUP="kvm", MODE="@DEV_KVM_MODE@", OPTIONS+="static_node=kvm" +KERNEL=="vfio", MODE="0666", OPTIONS+="static_node=vfio/vfio" + KERNEL=="vsock", MODE="0666" KERNEL=="vhost-vsock", GROUP="kvm", MODE="@DEV_KVM_MODE@", OPTIONS+="static_node=vhost-vsock" diff --git a/src/basic/selinux-util.c b/src/basic/selinux-util.c index ee9e34ed47..8c5544d46b 100644 --- a/src/basic/selinux-util.c +++ b/src/basic/selinux-util.c @@ -84,15 +84,24 @@ void mac_selinux_retest(void) { } #if HAVE_SELINUX -# if HAVE_MALLINFO -static struct mallinfo mallinfo_nowarn(void) { - /* glibc has deprecated mallinfo(), but the replacement malloc_info() returns an XML blob ;=[ */ +# if HAVE_MALLINFO2 +# define HAVE_GENERIC_MALLINFO 1 +typedef struct mallinfo2 generic_mallinfo; +static generic_mallinfo generic_mallinfo_get(void) { + return mallinfo2(); +} +# elif HAVE_MALLINFO +# define HAVE_GENERIC_MALLINFO 1 +typedef struct mallinfo generic_mallinfo; +static generic_mallinfo generic_mallinfo_get(void) { + /* glibc has deprecated mallinfo(), let's suppress the deprecation warning if mallinfo2() doesn't + * exist yet. */ DISABLE_WARNING_DEPRECATED_DECLARATIONS return mallinfo(); REENABLE_WARNING } # else -# warning "mallinfo() is missing, add mallinfo2() supported instead." +# define HAVE_GENERIC_MALLINFO 0 # endif static int open_label_db(void) { @@ -100,8 +109,8 @@ static int open_label_db(void) { usec_t before_timestamp, after_timestamp; char timespan[FORMAT_TIMESPAN_MAX]; -# if HAVE_MALLINFO - struct mallinfo before_mallinfo = mallinfo_nowarn(); +# if HAVE_GENERIC_MALLINFO + generic_mallinfo before_mallinfo = generic_mallinfo_get(); # endif before_timestamp = now(CLOCK_MONOTONIC); @@ -110,10 +119,10 @@ static int open_label_db(void) { return log_enforcing_errno(errno, "Failed to initialize SELinux labeling handle: %m"); after_timestamp = now(CLOCK_MONOTONIC); -# if HAVE_MALLINFO - struct mallinfo after_mallinfo = mallinfo_nowarn(); - int l = after_mallinfo.uordblks > before_mallinfo.uordblks ? after_mallinfo.uordblks - before_mallinfo.uordblks : 0; - log_debug("Successfully loaded SELinux database in %s, size on heap is %iK.", +# if HAVE_GENERIC_MALLINFO + generic_mallinfo after_mallinfo = generic_mallinfo_get(); + size_t l = LESS_BY((size_t) after_mallinfo.uordblks, (size_t) before_mallinfo.uordblks); + log_debug("Successfully loaded SELinux database in %s, size on heap is %zuK.", format_timespan(timespan, sizeof(timespan), after_timestamp - before_timestamp, 0), DIV_ROUND_UP(l, 1024)); # else diff --git a/src/basic/unit-file.c b/src/basic/unit-file.c index 50e6eccbf7..ff8aa02d10 100644 --- a/src/basic/unit-file.c +++ b/src/basic/unit-file.c @@ -284,7 +284,7 @@ int unit_file_build_name_map( continue; } - FOREACH_DIRENT_ALL(de, d, log_warning_errno(errno, "Failed to read \"%s\", ignoring: %m", *dir)) { + FOREACH_DIRENT(de, d, log_warning_errno(errno, "Failed to read \"%s\", ignoring: %m", *dir)) { char *filename; _cleanup_free_ char *_filename_free = NULL, *simplified = NULL; const char *suffix, *dst = NULL; @@ -403,6 +403,7 @@ int unit_file_build_name_map( /* Let's also put the names in the reverse db. */ const char *dummy, *src; HASHMAP_FOREACH_KEY(dummy, src, ids) { + _cleanup_free_ char *inst = NULL, *dst_inst = NULL; const char *dst; r = unit_ids_map_get(ids, src, &dst); @@ -412,15 +413,31 @@ int unit_file_build_name_map( if (null_or_empty_path(dst) != 0) continue; - /* Do not treat instance symlinks that point to the template as aliases */ - if (unit_name_is_valid(basename(dst), UNIT_NAME_TEMPLATE) && - unit_name_is_valid(src, UNIT_NAME_INSTANCE)) - continue; + dst = basename(dst); + + /* If we have an symlink from an instance name to a template name, it is an alias just for + * this specific instance, foo@id.service ↔ template@id.service. */ + if (unit_name_is_valid(dst, UNIT_NAME_TEMPLATE)) { + UnitNameFlags t = unit_name_to_instance(src, &inst); + if (t < 0) + return log_error_errno(t, "Failed to extract instance part from %s: %m", src); + if (t == UNIT_NAME_INSTANCE) { + r = unit_name_replace_instance(dst, inst, &dst_inst); + if (r < 0) { + /* This might happen e.g. if the combined length is too large. + * Let's not make too much of a fuss. */ + log_debug_errno(r, "Failed to build alias name (%s + %s), ignoring: %m", + dst, inst); + continue; + } - r = string_strv_hashmap_put(&names, basename(dst), src); + dst = dst_inst; + } + } + + r = string_strv_hashmap_put(&names, dst, src); if (r < 0) - return log_warning_errno(r, "Failed to add entry to hashmap (%s→%s): %m", - basename(dst), src); + return log_warning_errno(r, "Failed to add entry to hashmap (%s→%s): %m", dst, src); } if (cache_timestamp_hash) @@ -434,6 +451,88 @@ int unit_file_build_name_map( return 1; } +static int add_name( + const char *unit_name, + Set **names, + const char *name) { + int r; + + assert(names); + assert(name); + + r = set_put_strdup(names, name); + if (r < 0) + return r; + if (r > 0 && !streq(unit_name, name)) + log_debug("Unit %s has alias %s.", unit_name, name); + return r; +} + +static int add_names( + Hashmap *unit_ids_map, + Hashmap *unit_name_map, + const char *unit_name, + const char *fragment_basename, /* Only set when adding additional names based on fragment path */ + UnitNameFlags name_type, + const char *instance, + Set **names, + const char *name) { + + char **aliases, **alias; + int r; + + assert(name_type == UNIT_NAME_PLAIN || instance); + + /* The unit has its own name if it's not a template. If we're looking at a fragment, the fragment + * name (possibly with instance inserted), is also always one of the unit names. */ + if (name_type != UNIT_NAME_TEMPLATE) { + r = add_name(unit_name, names, name); + if (r < 0) + return r; + } + + /* Add any aliases of the name to the set of names. + * + * We don't even need to know which fragment we will use. The unit_name_map should return the same + * set of names for any of the aliases. */ + aliases = hashmap_get(unit_name_map, name); + STRV_FOREACH(alias, aliases) { + if (name_type == UNIT_NAME_INSTANCE && unit_name_is_valid(*alias, UNIT_NAME_TEMPLATE)) { + _cleanup_free_ char *inst = NULL; + const char *inst_fragment = NULL; + + r = unit_name_replace_instance(*alias, instance, &inst); + if (r < 0) + return log_debug_errno(r, "Cannot build instance name %s + %s: %m", + *alias, instance); + + /* Exclude any aliases that point in some other direction. + * + * See https://github.com/systemd/systemd/pull/13119#discussion_r308145418. */ + r = unit_ids_map_get(unit_ids_map, inst, &inst_fragment); + if (r < 0 && !IN_SET(r, -ENOENT, -ENXIO)) + return log_debug_errno(r, "Cannot find instance fragment %s: %m", inst); + + if (inst_fragment && + !streq(basename(inst_fragment), fragment_basename)) { + log_debug("Instance %s has fragment %s and is not an alias of %s.", + inst, inst_fragment, unit_name); + continue; + } + + r = set_consume(*names, TAKE_PTR(inst)); + if (r > 0) + log_debug("Unit %s has alias %s.", unit_name, inst); + } else + r = add_name(unit_name, names, *alias); + + if (r < 0) + return r; + } + + return 0; +} + int unit_file_find_fragment( Hashmap *unit_ids_map, Hashmap *unit_name_map, @@ -443,9 +542,8 @@ int unit_file_find_fragment( const char *fragment = NULL; _cleanup_free_ char *template = NULL, *instance = NULL; - _cleanup_set_free_free_ Set *names = NULL; - char **t, **nnn; - int r, name_type; + _cleanup_set_free_ Set *names = NULL; + int r; /* Finds a fragment path, and returns the set of names: * if we have …/foo.service and …/foo-alias.service→foo.service, @@ -461,53 +559,19 @@ int unit_file_find_fragment( * foo-alias@inst.service → …/foo@inst.service, {foo@inst.service, foo-alias@inst.service}. */ - name_type = unit_name_to_instance(unit_name, &instance); + UnitNameFlags name_type = unit_name_to_instance(unit_name, &instance); if (name_type < 0) return name_type; - names = set_new(&string_hash_ops); - if (!names) - return -ENOMEM; - - /* The unit always has its own name if it's not a template. */ - if (IN_SET(name_type, UNIT_NAME_PLAIN, UNIT_NAME_INSTANCE)) { - r = set_put_strdup(&names, unit_name); - if (r < 0) - return r; - } + r = add_names(unit_ids_map, unit_name_map, unit_name, NULL, name_type, instance, &names, unit_name); + if (r < 0) + return r; /* First try to load fragment under the original name */ r = unit_ids_map_get(unit_ids_map, unit_name, &fragment); if (r < 0 && !IN_SET(r, -ENOENT, -ENXIO)) return log_debug_errno(r, "Cannot load unit %s: %m", unit_name); - if (fragment) { - /* Add any aliases of the original name to the set of names */ - nnn = hashmap_get(unit_name_map, basename(fragment)); - STRV_FOREACH(t, nnn) { - if (name_type == UNIT_NAME_INSTANCE && unit_name_is_valid(*t, UNIT_NAME_TEMPLATE)) { - char *inst; - - r = unit_name_replace_instance(*t, instance, &inst); - if (r < 0) - return log_debug_errno(r, "Cannot build instance name %s+%s: %m", *t, instance); - - if (!streq(unit_name, inst)) - log_debug("%s: %s has alias %s", __func__, unit_name, inst); - - log_info("%s: %s+%s → %s", __func__, *t, instance, inst); - r = set_consume(names, inst); - } else { - if (!streq(unit_name, *t)) - log_debug("%s: %s has alias %s", __func__, unit_name, *t); - - r = set_put_strdup(&names, *t); - } - if (r < 0) - return r; - } - } - if (!fragment && name_type == UNIT_NAME_INSTANCE) { /* Look for a fragment under the template name */ @@ -518,43 +582,22 @@ int unit_file_find_fragment( r = unit_ids_map_get(unit_ids_map, template, &fragment); if (r < 0 && !IN_SET(r, -ENOENT, -ENXIO)) return log_debug_errno(r, "Cannot load template %s: %m", template); + } - if (fragment) { - /* Add any aliases of the original name to the set of names */ - nnn = hashmap_get(unit_name_map, basename(fragment)); - STRV_FOREACH(t, nnn) { - _cleanup_free_ char *inst = NULL; - const char *inst_fragment = NULL; - - r = unit_name_replace_instance(*t, instance, &inst); - if (r < 0) - return log_debug_errno(r, "Cannot build instance name %s+%s: %m", template, instance); - - /* Exclude any aliases that point in some other direction. */ - r = unit_ids_map_get(unit_ids_map, inst, &inst_fragment); - if (r < 0 && !IN_SET(r, -ENOENT, -ENXIO)) - return log_debug_errno(r, "Cannot find instance fragment %s: %m", inst); - - if (inst_fragment && - !streq(basename(inst_fragment), basename(fragment))) { - log_debug("Instance %s has fragment %s and is not an alias of %s.", - inst, inst_fragment, unit_name); - continue; - } + if (fragment) { + const char *fragment_basename = basename(fragment); - if (!streq(unit_name, inst)) - log_debug("%s: %s has alias %s", __func__, unit_name, inst); - r = set_consume(names, TAKE_PTR(inst)); - if (r < 0) - return r; - } + if (!streq(fragment_basename, unit_name)) { + /* Add names based on the fragment name to the set of names */ + r = add_names(unit_ids_map, unit_name_map, unit_name, fragment_basename, name_type, instance, &names, fragment_basename); + if (r < 0) + return r; } } *ret_fragment_path = fragment; *ret_names = TAKE_PTR(names); - // FIXME: if instance, consider any unit names with different template name return 0; } diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index a684717bb0..34f0c14b44 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -29,6 +29,7 @@ #include "main-func.h" #include "mkdir.h" #include "pager.h" +#include "parse-argument.h" #include "parse-util.h" #include "pretty-print.h" #include "random-util.h" @@ -52,6 +53,7 @@ static bool arg_print_dollar_boot_path = false; static bool arg_touch_variables = true; static PagerFlags arg_pager_flags = 0; static bool arg_graceful = false; +static int arg_make_machine_id_directory = -1; STATIC_DESTRUCTOR_REGISTER(arg_esp_path, freep); STATIC_DESTRUCTOR_REGISTER(arg_xbootldr_path, freep); @@ -112,6 +114,19 @@ static int acquire_xbootldr(bool unprivileged_mode, sd_id128_t *ret_uuid) { return 1; } +static void settle_make_machine_id_directory(void) { + int r; + + if (arg_make_machine_id_directory >= 0) + return; + + r = path_is_temporary_fs("/etc/machine-id"); + if (r < 0) + log_debug_errno(r, "Couldn't determine whether /etc/machine-id is on a temporary file system, assuming so."); + + arg_make_machine_id_directory = r == 0; +} + /* search for "#### LoaderInfo: systemd-boot 218 ####" string inside the binary */ static int get_file_version(int fd, char **v) { struct stat st; @@ -888,6 +903,24 @@ static int remove_subdirs(const char *root, const char *const *subdirs) { return r < 0 ? r : q; } +static int remove_machine_id_directory(const char *root) { + sd_id128_t machine_id; + char buf[SD_ID128_STRING_MAX]; + int r; + + assert(root); + assert(arg_make_machine_id_directory >= 0); + + if (!arg_make_machine_id_directory) + return 0; + + r = sd_id128_get_machine(&machine_id); + if (r < 0) + return log_error_errno(r, "Failed to get machine id: %m"); + + return rmdir_one(root, sd_id128_to_string(machine_id, buf)); +} + static int remove_binaries(const char *esp_path) { const char *p; int r, q; @@ -974,9 +1007,13 @@ static int install_loader_config(const char *esp_path) { _cleanup_(unlink_and_freep) char *t = NULL; _cleanup_fclose_ FILE *f = NULL; _cleanup_close_ int fd = -1; + sd_id128_t machine_id; + char machine_string[SD_ID128_STRING_MAX]; const char *p; int r; + assert(arg_make_machine_id_directory >= 0); + p = prefix_roota(esp_path, "/loader/loader.conf"); if (access(p, F_OK) >= 0) /* Silently skip creation if the file already exists (early check) */ return 0; @@ -991,6 +1028,13 @@ static int install_loader_config(const char *esp_path) { fprintf(f, "#timeout 3\n" "#console-mode keep\n"); + if (arg_make_machine_id_directory) { + r = sd_id128_get_machine(&machine_id); + if (r < 0) + return log_error_errno(r, "Failed to get machine id: %m"); + + fprintf(f, "default %s-*\n", sd_id128_to_string(machine_id, machine_string)); + } r = fflush_sync_and_check(f); if (r < 0) @@ -1006,6 +1050,24 @@ static int install_loader_config(const char *esp_path) { return 1; } +static int install_machine_id_directory(const char *root) { + sd_id128_t machine_id; + char buf[SD_ID128_STRING_MAX]; + int r; + + assert(root); + assert(arg_make_machine_id_directory >= 0); + + if (!arg_make_machine_id_directory) + return 0; + + r = sd_id128_get_machine(&machine_id); + if (r < 0) + return log_error_errno(r, "Failed to get machine id: %m"); + + return mkdir_one(root, sd_id128_to_string(machine_id, buf)); +} + static int help(int argc, char *argv[], void *userdata) { _cleanup_free_ char *link = NULL; int r; @@ -1043,6 +1105,8 @@ static int help(int argc, char *argv[], void *userdata) { " --no-pager Do not pipe output into a pager\n" " --graceful Don't fail when the ESP cannot be found or EFI\n" " variables cannot be written\n" + " --make-machine-id-directory=yes|no|auto\n" + " Create $BOOT/$MACHINE_ID\n" "\nSee the %2$s for details.\n", program_invocation_short_name, link, @@ -1062,24 +1126,27 @@ static int parse_argv(int argc, char *argv[]) { ARG_NO_VARIABLES, ARG_NO_PAGER, ARG_GRACEFUL, + ARG_MAKE_MACHINE_ID_DIRECTORY, }; static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "esp-path", required_argument, NULL, ARG_ESP_PATH }, - { "path", required_argument, NULL, ARG_ESP_PATH }, /* Compatibility alias */ - { "boot-path", required_argument, NULL, ARG_BOOT_PATH }, - { "print-esp-path", no_argument, NULL, 'p' }, - { "print-path", no_argument, NULL, 'p' }, /* Compatibility alias */ - { "print-boot-path", no_argument, NULL, 'x' }, - { "no-variables", no_argument, NULL, ARG_NO_VARIABLES }, - { "no-pager", no_argument, NULL, ARG_NO_PAGER }, - { "graceful", no_argument, NULL, ARG_GRACEFUL }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "esp-path", required_argument, NULL, ARG_ESP_PATH }, + { "path", required_argument, NULL, ARG_ESP_PATH }, /* Compatibility alias */ + { "boot-path", required_argument, NULL, ARG_BOOT_PATH }, + { "print-esp-path", no_argument, NULL, 'p' }, + { "print-path", no_argument, NULL, 'p' }, /* Compatibility alias */ + { "print-boot-path", no_argument, NULL, 'x' }, + { "no-variables", no_argument, NULL, ARG_NO_VARIABLES }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "graceful", no_argument, NULL, ARG_GRACEFUL }, + { "make-machine-id-directory", required_argument, NULL, ARG_MAKE_MACHINE_ID_DIRECTORY }, {} }; int c, r; + bool b; assert(argc >= 0); assert(argv); @@ -1132,6 +1199,17 @@ static int parse_argv(int argc, char *argv[]) { arg_graceful = true; break; + case ARG_MAKE_MACHINE_ID_DIRECTORY: + if (streq(optarg, "auto")) + arg_make_machine_id_directory = -1; /* default */ + else { + r = parse_boolean_argument("--make-machine-id-directory=", optarg, &b); + if (r < 0) + return r; + arg_make_machine_id_directory = b; + } + break; + case '?': return -EINVAL; @@ -1530,6 +1608,8 @@ static int verb_install(int argc, char *argv[], void *userdata) { if (r < 0) return r; + settle_make_machine_id_directory(); + install = streq(argv[0], "install"); RUN_WITH_UMASK(0002) { @@ -1555,6 +1635,10 @@ static int verb_install(int argc, char *argv[], void *userdata) { if (r < 0) return r; + r = install_machine_id_directory(arg_dollar_boot_path()); + if (r < 0) + return r; + r = install_random_seed(arg_esp_path); if (r < 0) return r; @@ -1584,6 +1668,8 @@ static int verb_remove(int argc, char *argv[], void *userdata) { if (r < 0) return r; + settle_make_machine_id_directory(); + r = remove_binaries(arg_esp_path); q = remove_file(arg_esp_path, "/loader/loader.conf"); @@ -1602,11 +1688,19 @@ static int verb_remove(int argc, char *argv[], void *userdata) { if (q < 0 && r >= 0) r = q; + q = remove_machine_id_directory(arg_esp_path); + if (q < 0 && r >= 0) + r = 1; + if (arg_xbootldr_path) { /* Remove the latter two also in the XBOOTLDR partition if it exists */ q = remove_subdirs(arg_xbootldr_path, dollar_boot_subdirs); if (q < 0 && r >= 0) r = q; + + q = remove_machine_id_directory(arg_xbootldr_path); + if (q < 0 && r >= 0) + r = q; } (void) sync_everything(); diff --git a/src/core/manager.c b/src/core/manager.c index 4abe6606f6..30aadb0944 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -688,7 +688,8 @@ static int manager_setup_prefix(Manager *m) { for (ExecDirectoryType i = 0; i < _EXEC_DIRECTORY_TYPE_MAX; i++) { r = sd_path_lookup(p[i].type, p[i].suffix, &m->prefix[i]); if (r < 0) - return r; + return log_warning_errno(r, "Failed to lookup %s path: %m", + exec_directory_type_to_string(i)); } return 0; diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c index 8f9679051d..477ae03a02 100644 --- a/src/test/test-unit-file.c +++ b/src/test/test-unit-file.c @@ -92,6 +92,7 @@ static void test_runlevel_to_target(void) { } int main(int argc, char **argv) { + log_show_color(true); test_setup_logging(LOG_DEBUG); test_unit_validate_alias_symlink_and_warn(); diff --git a/test/test-functions b/test/test-functions index fdab3b9d41..65e3c96539 100644 --- a/test/test-functions +++ b/test/test-functions @@ -1134,8 +1134,7 @@ check_result_common() { local ret if [ -s "$workspace/failed" ]; then - # …/failed only counts if non-empty - ls -l "$workspace/failed" + # Non-empty …/failed has highest priority cp -a "$workspace/failed" "${TESTDIR:?}/" ret=1 elif [ -e "$workspace/testok" ]; then @@ -1147,24 +1146,28 @@ check_result_common() { cat "$workspace/skipped" ret=0 elif [ -n "$TIMED_OUT" ]; then - echo "${TESTNAME:?} timed out!" + echo "(timeout)" >"${TESTDIR:?}/failed" ret=2 else - echo "${TESTNAME:?} did not report a result!" + echo "(failed; see logs)" >"${TESTDIR:?}/failed" + ret=3 fi save_journal "$workspace/var/log/journal" - check_asan_reports "$workspace" || ret=3 + check_asan_reports "$workspace" || ret=4 if [ -d "${ARTIFACT_DIRECTORY}" ] && [ -f "$workspace/strace.out" ]; then cp "$workspace/strace.out" "${ARTIFACT_DIRECTORY}/" fi - [ -f "$TESTDIR/failed" ] && cat "$TESTDIR/failed" + if [ ${ret:?} != 0 ] && [ -f "$TESTDIR/failed" ]; then + echo -n "${TESTNAME:?}: " + cat "$TESTDIR/failed" + fi echo "${JOURNAL_LIST:-"No journals were saved"}" - return $ret + return ${ret:?} } check_result_nspawn() { diff --git a/test/units/testsuite-15.sh b/test/units/testsuite-15.sh index 23c2156501..c3784e299d 100755 --- a/test/units/testsuite-15.sh +++ b/test/units/testsuite-15.sh @@ -32,12 +32,9 @@ create_service () { Description=$SERVICE_NAME unit [Service] -ExecStart=/bin/sleep 100000 +ExecStart=sleep 100000 EOF - mkdir -p /{etc,run,usr/lib}/systemd/system/"$SERVICE_NAME".service.d - mkdir -p /etc/systemd/system/"$SERVICE_NAME".service.{wants,requires} - mkdir -p /run/systemd/system/"$SERVICE_NAME".service.{wants,requires} - mkdir -p /usr/lib/systemd/system/"$SERVICE_NAME".service.{wants,requires} + mkdir -p /{etc,run,usr/lib}/systemd/system/"$SERVICE_NAME".service.{d,wants,requires} } create_services () { @@ -47,12 +44,10 @@ create_services () { } check_ok () { - [ $# -eq 3 ] || return - - x="$(systemctl show --value -p "$2" "$1")" + x="$(systemctl show --value -p "${2:?}" "${1:?}")" case "$x" in - *$3*) return 0 ;; - *) return 1 ;; + *${3:?}*) return 0 ;; + *) return 1 ;; esac } @@ -123,7 +118,7 @@ EOF check_ok test15-b ExecCondition "/bin/echo test15-b" rm -rf /usr/lib/systemd/system/service.d - clear_services test15-a test15-b test15-c + clear_services test15-a test15-b test15-c test15-c1 } test_linked_units () { @@ -153,6 +148,32 @@ test_linked_units () { clear_services test15-a test15-b } +test_template_alias() { + echo "Testing instance alias..." + echo "*** forward" + + create_service test15-a@ + ln -s test15-a@inst.service /etc/systemd/system/test15-b@inst.service # alias + + check_ok test15-a@inst Names test15-a@inst.service + check_ok test15-a@inst Names test15-b@inst.service + + check_ok test15-a@other Names test15-a@other.service + check_ko test15-a@other Names test15-b@other.service + + echo "*** reverse" + + systemctl daemon-reload + + check_ok test15-b@inst Names test15-a@inst.service + check_ok test15-b@inst Names test15-b@inst.service + + check_ko test15-b@other Names test15-a@other.service + check_ok test15-b@other Names test15-b@other.service + + clear_services test15-a@ test15-b@ +} + test_hierarchical_dropins () { echo "Testing hierarchical dropins..." echo "*** test service.d/ top level drop-in" @@ -495,6 +516,7 @@ test_invalid_dropins () { test_basic_dropins test_linked_units +test_template_alias test_hierarchical_dropins test_template_dropins test_alias_dropins |