steps:
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
- - uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93
- with:
- node-version: '16'
-
- name: Parse issue form
uses: stefanbuck/github-issue-parser@fc06b2a0adc5ccb7702ab6b641fd8a742a5e9cc0
id: issue-parser
steps:
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
- - uses: systemd/mkosi@f37c19e7217a41c52d9a9a8769e98496255e2e2d
+ - uses: systemd/mkosi@d93967b94225ca63b3f5c18045db815439897b5c
- name: Install
run: sudo apt-get update && sudo apt-get install --no-install-recommends python3-pexpect python3-jinja2
KernelCommandLine=${{ env.KERNEL_CMDLINE }}
EOF
- echo systemd-stable/ >> .gitignore
-
- name: Build ${{ matrix.distro }}
- run: ./.github/workflows/run_mkosi.sh build
+ run: sudo python3 -m mkosi build
- name: Show ${{ matrix.distro }} image summary
- run: ./.github/workflows/run_mkosi.sh summary
+ run: sudo python3 -m mkosi summary
- name: Boot ${{ matrix.distro }} systemd-nspawn
- run: ./.github/workflows/run_mkosi.sh boot ${{ env.KERNEL_CMDLINE }}
+ run: sudo python3 -m mkosi boot ${{ env.KERNEL_CMDLINE }}
- name: Check ${{ matrix.distro }} systemd-nspawn
- run: ./.github/workflows/run_mkosi.sh shell bash -c "[[ -e /testok ]] || { cat /failed-services; exit 1; }"
+ run: sudo python3 -m mkosi shell bash -c "[[ -e /testok ]] || { cat /failed-services; exit 1; }"
- name: Boot ${{ matrix.distro }} QEMU
- run: ./.github/workflows/run_mkosi.sh qemu
+ run: sudo timeout -k 30 10m python3 -m mkosi qemu
- name: Check ${{ matrix.distro }} QEMU
- run: ./.github/workflows/run_mkosi.sh shell bash -c "[[ -e /testok ]] || { cat /failed-services; exit 1; }"
+ run: sudo python3 -m mkosi shell bash -c "[[ -e /testok ]] || { cat /failed-services; exit 1; }"
+++ /dev/null
-#!/usr/bin/env bash
-# SPDX-License-Identifier: LGPL-2.1-or-later
-# shellcheck disable=SC2064
-
-set -eu
-set -o pipefail
-
-EC=0
-TEMPFILE="$(mktemp)"
-TEMP_EXTRA_TREE="$(mktemp --directory)"
-trap "rm -rf '$TEMPFILE' '$TEMP_EXTRA_TREE'" EXIT
-
-# We need isc-dhcp-server to be installed for the networkd unit tests, but we don't want to
-# run it by default. mktemp creates the directory as 700, so change it, otherwise it will
-# affect the image's root folder permissions.
-chmod 755 "$TEMP_EXTRA_TREE"
-mkdir -p "$TEMP_EXTRA_TREE/etc/systemd/system/"
-ln -s /dev/null "$TEMP_EXTRA_TREE/etc/systemd/system/isc-dhcp-server.service"
-ln -s /dev/null "$TEMP_EXTRA_TREE/etc/systemd/system/isc-dhcp-server6.service"
-
-for ((i = 0; i < 5; i++)); do
- EC=0
- (sudo timeout -k 30 10m python3 -m mkosi --extra-tree="$TEMP_EXTRA_TREE" "$@") |& tee "$TEMPFILE" || EC=$?
- if [[ $EC -eq 0 ]]; then
- # The command passed — let's return immediately
- break
- fi
-
- if ! grep -E "Failed to dissect image .+: Connection timed out" "$TEMPFILE"; then
- # The command failed for other reason than the dissect-related timeout -
- # let's exit with the same EC
- exit $EC
- fi
-
- # The command failed due to the dissect-related timeout — let's try again
- sleep 1
-done
-
-exit $EC
units.
systemd-oomd is now considered fully supported (the usual
- backwards-compatiblity promises apply). Swap is not required for
+ backwards-compatibility promises apply). Swap is not required for
operation, but it is still recommended.
* systemd-timesyncd gained a new ConnectionRetrySec= setting which
KEYBOARD_KEY_17=prog1
KEYBOARD_KEY_1a=f20 # Microphone mute button; should be micmute
KEYBOARD_KEY_45=bookmarks
+ KEYBOARD_KEY_46=prog2
# ThinkPad Keyboard with TrackPoint
evdev:input:b0003v17EFp6009*
<para>The <varname>DNSSECStatistics</varname> property contains information about the DNSSEC
validations executed so far. It contains four 64-bit counters: the number of secure, insecure, bogus,
and indeterminate DNSSEC validations so far. The counters are increased for each validated RRset, and
- each non-existance proof. The secure counter is increased for each operation that successfully verified
+ each non-existence proof. The secure counter is increased for each operation that successfully verified
a signed reply, the insecure counter is increased for each operation that successfully verified that an
unsigned reply is rightfully unsigned. The bogus counter is increased for each operation where the
validation did not check out and the data is likely to have been tempered with. Finally the
optional. Each option may be used at most once.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--current</option></term>
+ <listitem><para>When used with the <command>calculate</command> verb, takes the PCR 11 values
+ currently in effect for the system (which should typically reflect the hashes of the currently booted
+ kernel). This can be used in place of <option>--linux=</option> and the other switches listed
+ above.</para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><option>--bank=DIGEST</option></term>
<cmdsynopsis>
<command>systemd-sysext</command>
<arg choice="opt" rep="repeat">OPTIONS</arg>
+ <arg choice="plain">COMMAND</arg>
</cmdsynopsis>
<para><literallayout><filename>systemd-sysext.service</filename></literallayout></para>
install : true,
install_dir : rootbindir)
public_programs += exe
-
- if want_tests != 'false'
- test('test-repart',
- test_repart_sh,
- args : [exe.full_path(), udevadm.full_path()])
- endif
endif
executable(
--- /dev/null
+# systemd-sysext(8) completion -*- shell-script -*-
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# systemd is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with systemd; If not, see <https://www.gnu.org/licenses/>.
+
+__contains_word() {
+ local w word=$1; shift
+ for w in "$@"; do
+ [[ $w = "$word" ]] && return
+ done
+}
+
+_systemd-sysext() {
+ local i verb comps
+ local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword
+ local -A OPTS=(
+ [STANDALONE]='-h --help --version
+ --no-pager
+ --no-legend
+ --force'
+ [ARG]='--root
+ --json'
+ )
+
+ local -A VERBS=(
+ [STANDALONE]='status
+ merge
+ unmerge
+ refresh
+ list'
+ )
+
+ _init_completion || return
+
+ if __contains_word "$prev" ${OPTS[ARG]}; then
+ case $prev in
+ --root)
+ comps=$(compgen -A directory -- "$cur" )
+ compopt -o dirnames
+ ;;
+ --json)
+ comps='pretty short off'
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
+ return 0
+ fi
+
+ if [[ "$cur" = -* ]]; then
+ COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") )
+ return 0
+ fi
+
+ for ((i=0; i < COMP_CWORD; i++)); do
+ if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} &&
+ ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then
+ verb=${COMP_WORDS[i]}
+ break
+ fi
+ done
+
+ if [[ -z ${verb-} ]]; then
+ comps=${VERBS[*]}
+ elif __contains_word "$verb" ${VERBS[STANDALONE]}; then
+ comps=''
+ fi
+
+ COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
+ return 0
+}
+
+complete -F _systemd-sysext systemd-sysext
_cleanup_free_ char *p = NULL;
int r;
- if (chase_flags & CHASE_NONEXISTENT)
+ if (chase_flags & (CHASE_NONEXISTENT|CHASE_STEP))
return -EINVAL;
if (empty_or_root(root) && !ret_path && (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE)) == 0) {
/* Shortcut this call if none of the special features of this call are requested */
- r = open(path, open_flags);
+ r = open(path, open_flags | (FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? O_NOFOLLOW : 0));
if (r < 0)
return -errno;
if (!ret_dir)
return -EINVAL;
- if (chase_flags & CHASE_NONEXISTENT)
+ if (chase_flags & (CHASE_NONEXISTENT|CHASE_STEP))
return -EINVAL;
if (empty_or_root(root) && !ret_path && (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE)) == 0) {
assert(path);
assert(ret_stat);
- if (chase_flags & CHASE_NONEXISTENT)
+ if (chase_flags & (CHASE_NONEXISTENT|CHASE_STEP))
return -EINVAL;
- if (empty_or_root(root) && !ret_path && (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE)) == 0) {
+ if (empty_or_root(root) && !ret_path && (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE)) == 0 && !ret_fd) {
/* Shortcut this call if none of the special features of this call are requested */
- if (stat(path, ret_stat) < 0)
+
+ if (fstatat(AT_FDCWD, path, ret_stat, FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0) < 0)
return -errno;
return 1;
return 1;
}
+int chase_symlinks_and_access(
+ const char *path,
+ const char *root,
+ ChaseSymlinksFlags chase_flags,
+ int access_mode,
+ char **ret_path,
+ int *ret_fd) {
+
+ _cleanup_close_ int path_fd = -1;
+ _cleanup_free_ char *p = NULL;
+ int r;
+
+ assert(path);
+
+ if (chase_flags & (CHASE_NONEXISTENT|CHASE_STEP))
+ return -EINVAL;
+
+ if (empty_or_root(root) && !ret_path && (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE)) == 0 && !ret_fd) {
+ /* Shortcut this call if none of the special features of this call are requested */
+
+ if (faccessat(AT_FDCWD, path, access_mode, FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0) < 0)
+ return -errno;
+
+ return 1;
+ }
+
+ r = chase_symlinks(path, root, chase_flags, ret_path ? &p : NULL, &path_fd);
+ if (r < 0)
+ return r;
+ assert(path_fd >= 0);
+
+ r = access_fd(path_fd, access_mode);
+ if (r < 0)
+ return r;
+
+ if (ret_path)
+ *ret_path = TAKE_PTR(p);
+ if (ret_fd)
+ *ret_fd = TAKE_FD(path_fd);
+
+ return 1;
+}
+
int chase_symlinks_and_fopen_unlocked(
const char *path,
const char *root,
int chase_symlinks_and_open(const char *path, const char *root, ChaseSymlinksFlags chase_flags, int open_flags, char **ret_path);
int chase_symlinks_and_opendir(const char *path, const char *root, ChaseSymlinksFlags chase_flags, char **ret_path, DIR **ret_dir);
int chase_symlinks_and_stat(const char *path, const char *root, ChaseSymlinksFlags chase_flags, char **ret_path, struct stat *ret_stat, int *ret_fd);
-
+int chase_symlinks_and_access(const char *path, const char *root, ChaseSymlinksFlags chase_flags, int access_mode, char **ret_path, int *ret_fd);
int chase_symlinks_and_fopen_unlocked(const char *path, const char *root, ChaseSymlinksFlags chase_flags, const char *open_flags, char **ret_path, FILE **ret_file);
#include <stdio.h>
#include <stdlib.h>
+#include "chase-symlinks.h"
#include "conf-files.h"
#include "def.h"
#include "dirent-util.h"
unsigned flags,
const char *path) {
+ _cleanup_free_ char *dirpath = NULL;
_cleanup_closedir_ DIR *dir = NULL;
- const char *dirpath;
int r;
assert(h);
assert((flags & CONF_FILES_FILTER_MASKED) == 0 || masked);
assert(path);
- dirpath = prefix_roota(root, path);
-
- dir = opendir(dirpath);
- if (!dir) {
- if (errno == ENOENT)
- return 0;
-
- return log_debug_errno(errno, "Failed to open directory '%s': %m", dirpath);
- }
+ r = chase_symlinks_and_opendir(path, root, CHASE_PREFIX_ROOT, &dirpath, &dir);
+ if (r == -ENOENT)
+ return 0;
+ if (r < 0)
+ return log_debug_errno(r, "Failed to open directory '%s/%s': %m", empty_or_root(root) ? "" : root, dirpath);
FOREACH_DIRENT(de, dir, return -errno) {
struct stat st;
bool *is_first) {
_cleanup_closedir_ DIR *d = NULL;
- const char *p;
+ _cleanup_free_ char *p = NULL;
int c = 0, r;
assert(esp_path);
assert(previous);
assert(is_first);
- p = prefix_roota(esp_path, path);
- d = opendir(p);
- if (!d) {
- if (errno == ENOENT)
- return 0;
-
- return log_error_errno(errno, "Failed to read \"%s\": %m", p);
- }
+ r = chase_symlinks_and_opendir(path, esp_path, CHASE_PREFIX_ROOT, &p, &d);
+ if (r == -ENOENT)
+ return 0;
+ if (r < 0)
+ return log_error_errno(r, "Failed to read \"%s/%s\": %m", esp_path, path);
FOREACH_DIRENT(de, d, break) {
_cleanup_free_ char *v = NULL;
return 0;
}
-static int install_variables(const char *esp_path,
- uint32_t part, uint64_t pstart, uint64_t psize,
- sd_id128_t uuid, const char *path,
- bool first) {
- const char *p;
+static int install_variables(
+ const char *esp_path,
+ uint32_t part,
+ uint64_t pstart,
+ uint64_t psize,
+ sd_id128_t uuid,
+ const char *path,
+ bool first) {
+
uint16_t slot;
int r;
return 0;
}
- p = prefix_roota(esp_path, path);
- if (access(p, F_OK) < 0) {
- if (errno == ENOENT)
- return 0;
-
- return log_error_errno(errno, "Cannot access \"%s\": %m", p);
- }
+ r = chase_symlinks_and_access(path, esp_path, CHASE_PREFIX_ROOT, F_OK, NULL, NULL);
+ if (r == -ENOENT)
+ return 0;
+ if (r < 0)
+ return log_error_errno(r, "Cannot access \"%s/%s\": %m", esp_path, path);
r = find_slot(uuid, path, &slot);
if (r < 0)
static int remove_boot_efi(const char *esp_path) {
_cleanup_closedir_ DIR *d = NULL;
- const char *p;
+ _cleanup_free_ char *p = NULL;
int r, c = 0;
- p = prefix_roota(esp_path, "/EFI/BOOT");
- d = opendir(p);
- if (!d) {
- if (errno == ENOENT)
- return 0;
-
- return log_error_errno(errno, "Failed to open directory \"%s\": %m", p);
- }
+ r = chase_symlinks_and_opendir("/EFI/BOOT", esp_path, CHASE_PREFIX_ROOT, &p, &d);
+ if (r == -ENOENT)
+ return 0;
+ if (r < 0)
+ return log_error_errno(r, "Failed to open directory \"%s/EFI/BOOT\": %m", esp_path);
FOREACH_DIRENT(de, d, break) {
_cleanup_close_ int fd = -1;
static char **arg_banks = NULL;
static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
static PagerFlags arg_pager_flags = 0;
+static bool arg_current = false;
STATIC_DESTRUCTOR_REGISTER(arg_banks, strv_freep);
" --initrd=PATH Path to initrd image\n"
" --splash=PATH Path to splash bitmap\n"
" --dtb=PATH Path to Devicetree file\n"
+ " -c --current Use current PCR values\n"
" --bank=DIGEST Select TPM bank (SHA1, SHA256)\n"
" --json=MODE Output as JSON\n"
" -j Same as --json=pretty on tty, --json=short otherwise\n"
{ "initrd", required_argument, NULL, ARG_INITRD },
{ "splash", required_argument, NULL, ARG_SPLASH },
{ "dtb", required_argument, NULL, ARG_DTB },
+ { "current", no_argument, NULL, 'c' },
{ "bank", required_argument, NULL, ARG_BANK },
{ "json", required_argument, NULL, ARG_JSON },
{}
/* Make sure the arguments list and the section list, stays in sync */
assert_cc(_ARG_SECTION_FIRST + _UNIFIED_SECTION_MAX == _ARG_SECTION_LAST + 1);
- while ((c = getopt_long(argc, argv, "hj", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "hjc", options, NULL)) >= 0)
switch (c) {
case 'h':
break;
}
+ case 'c':
+ arg_current = true;
+ break;
+
case ARG_BANK: {
const EVP_MD *implementation;
strv_sort(arg_banks);
strv_uniq(arg_banks);
+ if (arg_current)
+ for (UnifiedSection us = 0; us < _UNIFIED_SECTION_MAX; us++)
+ if (arg_sections[us])
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "The --current switch cannot be used in combination with --linux= and related switches.");
+
return 1;
}
if (!buffer)
return log_oom();
+ if (arg_current) {
+ /* Shortcut things, if we should just use the current PCR value */
+
+ for (size_t i = 0; i < n; i++) {
+ _cleanup_free_ char *p = NULL, *s = NULL;
+
+ if (asprintf(&p, "/sys/class/tpm/tpm0/pcr-%s/%" PRIu32, pcr_states[i].bank, TPM_PCR_INDEX_KERNEL_IMAGE) < 0)
+ return log_oom();
+
+ r = read_virtual_file(p, 4096, &s, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to read '%s': %m", p);
+
+ r = unhexmem(strstrip(s), SIZE_MAX, &pcr_states[i].value, &pcr_states[i].value_size);
+ if (r < 0)
+ return log_error_errno(r, "Failed to decode PCR value '%s': %m", s);
+ }
+
+ return 0;
+ }
+
for (UnifiedSection c = 0; c < _UNIFIED_SECTION_MAX; c++) {
_cleanup_(evp_md_ctx_free_all) EVP_MD_CTX **mdctx = NULL;
_cleanup_close_ int fd = -1;
size_t n = 0;
int r;
- if (!arg_sections[UNIFIED_SECTION_LINUX])
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--linux= switch must be specified, refusing.");
+ if (!arg_sections[UNIFIED_SECTION_LINUX] && !arg_current)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Either --linux= or --current must be specified, refusing.");
pcr_states = new0(PcrState, strv_length(arg_banks) + 1);
if (!pcr_states)
}
int unit_attach_pids_to_cgroup(Unit *u, Set *pids, const char *suffix_path) {
+ _cleanup_free_ char *joined = NULL;
CGroupMask delegated_mask;
const char *p;
void *pidp;
if (isempty(suffix_path))
p = u->cgroup_path;
- else
- p = prefix_roota(u->cgroup_path, suffix_path);
+ else {
+ joined = path_join(u->cgroup_path, suffix_path);
+ if (!joined)
+ return -ENOMEM;
+
+ p = joined;
+ }
delegated_mask = unit_get_delegate_mask(u);
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Random seed passed from boot loader has zero size? Ignoring.");
/* Before we use the seed, let's mark it as used, so that we never credit it twice. Also, it's a nice
- * way to let users known that we successfully acquired entropy from the boot laoder. */
+ * way to let users known that we successfully acquired entropy from the boot loader. */
r = touch("/run/systemd/efi-random-seed-taken");
if (r < 0)
return log_warning_errno(r, "Unable to mark EFI random seed as used, not using it: %m");
static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
+static void mount_enter_dead(Mount *m, MountResult f);
+static void mount_enter_mounted(Mount *m, MountResult f);
+static void mount_cycle_clear(Mount *m);
static int mount_process_proc_self_mountinfo(Manager *m);
static bool MOUNT_STATE_WITH_PROCESS(MountState state) {
static int mount_coldplug(Unit *u) {
Mount *m = MOUNT(u);
- MountState new_state = MOUNT_DEAD;
int r;
assert(m);
assert(m->state == MOUNT_DEAD);
- if (m->deserialized_state != m->state)
- new_state = m->deserialized_state;
- else if (m->from_proc_self_mountinfo)
- new_state = MOUNT_MOUNTED;
-
- if (new_state == m->state)
+ if (m->deserialized_state == m->state)
return 0;
if (m->control_pid > 0 &&
pid_is_unwaited(m->control_pid) &&
- MOUNT_STATE_WITH_PROCESS(new_state)) {
+ MOUNT_STATE_WITH_PROCESS(m->deserialized_state)) {
r = unit_watch_pid(UNIT(m), m->control_pid, false);
if (r < 0)
return r;
}
- if (!IN_SET(new_state, MOUNT_DEAD, MOUNT_FAILED)) {
+ if (!IN_SET(m->deserialized_state, MOUNT_DEAD, MOUNT_FAILED)) {
(void) unit_setup_dynamic_creds(u);
(void) unit_setup_exec_runtime(u);
}
- mount_set_state(m, new_state);
+ mount_set_state(m, m->deserialized_state);
return 0;
}
+static void mount_catchup(Unit *u) {
+ Mount *m = MOUNT(ASSERT_PTR(u));
+
+ assert(m);
+
+ /* Adjust the deserialized state. See comments in mount_process_proc_self_mountinfo(). */
+ if (m->from_proc_self_mountinfo)
+ switch (m->state) {
+ case MOUNT_DEAD:
+ case MOUNT_FAILED:
+ assert(m->control_pid == 0);
+ unit_acquire_invocation_id(u);
+ mount_cycle_clear(m);
+ mount_enter_mounted(m, MOUNT_SUCCESS);
+ break;
+ case MOUNT_MOUNTING:
+ assert(m->control_pid > 0);
+ mount_set_state(m, MOUNT_MOUNTING_DONE);
+ break;
+ default:
+ break;
+ }
+ else
+ switch (m->state) {
+ case MOUNT_MOUNTING_DONE:
+ assert(m->control_pid > 0);
+ mount_set_state(m, MOUNT_MOUNTING);
+ break;
+ case MOUNT_MOUNTED:
+ assert(m->control_pid == 0);
+ mount_enter_dead(m, MOUNT_SUCCESS);
+ break;
+ default:
+ break;
+ }
+}
+
static void mount_dump(Unit *u, FILE *f, const char *prefix) {
Mount *m = MOUNT(u);
MountParameters *p;
.done = mount_done,
.coldplug = mount_coldplug,
+ .catchup = mount_catchup,
.dump = mount_dump,
static int should_skip_path(const char *prefix, const char *suffix) {
#if HAVE_SPLIT_USR
- _cleanup_free_ char *target = NULL;
- const char *dirname, *p;
+ _cleanup_free_ char *target = NULL, *dirname = NULL;
+ const char *p;
- dirname = prefix_roota(prefix, suffix);
+ dirname = path_join(prefix, suffix);
+ if (!dirname)
+ return -ENOMEM;
if (chase_symlinks(dirname, NULL, 0, &target, NULL) < 0)
return false;
const char *description,
usec_t timeout) {
- _cleanup_free_ char *unit = NULL;
+ _cleanup_free_ char *unit = NULL, *p = NULL;
_cleanup_fclose_ FILE *f = NULL;
- const char *opt = "noauto", *p;
+ const char *opt = "noauto";
int r;
assert(id);
if (r < 0)
return log_error_errno(r, "Failed to generate unit name: %m");
- p = prefix_roota(arg_dest, unit);
+ p = path_join(arg_dest, unit);
+ if (!p)
+ return log_oom();
+
f = fopen(p, "wxe");
if (!f)
return log_error_errno(errno, "Failed to create unit file %s: %m", unit);
if (!isempty(c->data[PROP_CHASSIS]))
return strdup(c->data[PROP_CHASSIS]);
- if (get_dmi_data("ID_CHASSIS", NULL, &dmi) >= 0)
+ if (get_dmi_data("ID_CHASSIS", NULL, &dmi) > 0)
return dmi;
fallback = fallback_chassis();
/* We cache all sysattr lookups. If an attribute does not exist, it is stored
* with a NULL value in the cache, otherwise the returned string is stored */
_public_ int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **ret_value) {
- _cleanup_free_ char *value = NULL;
- const char *path, *syspath;
+ _cleanup_free_ char *value = NULL, *path = NULL;
+ const char *syspath;
struct stat statbuf;
int r;
if (r < 0)
return r;
- path = prefix_roota(syspath, sysattr);
+ path = path_join(syspath, sysattr);
+ if (!path)
+ return -ENOMEM;
+
if (lstat(path, &statbuf) < 0) {
int k;
}
_public_ int sd_device_set_sysattr_value(sd_device *device, const char *sysattr, const char *_value) {
- _cleanup_free_ char *value = NULL;
- const char *syspath, *path;
+ _cleanup_free_ char *value = NULL, *path = NULL;
+ const char *syspath;
size_t len;
int r;
if (r < 0)
return r;
- path = prefix_roota(syspath, sysattr);
+ path = path_join(syspath, sysattr);
+ if (!path)
+ return -ENOMEM;
len = strlen(_value);
const char *prefix,
const char *filename) {
- const char *path;
+ _cleanup_free_ char *path = NULL;
assert(j);
assert(prefix);
if (!file_type_wanted(j->flags, filename))
return 0;
- path = prefix_roota(prefix, filename);
+ path = path_join(prefix, filename);
+ if (!path)
+ return -ENOMEM;
+
return add_any_file(j, -1, path);
}
-static void remove_file_by_name(
+static int remove_file_by_name(
sd_journal *j,
const char *prefix,
const char *filename) {
- const char *path;
+ _cleanup_free_ char *path = NULL;
JournalFile *f;
assert(j);
assert(prefix);
assert(filename);
- path = prefix_roota(prefix, filename);
+ path = path_join(prefix, filename);
+ if (!path)
+ return -ENOMEM;
+
f = ordered_hashmap_get(j->files, path);
if (!f)
- return;
+ return 0;
remove_file_real(j, f);
+ return 1;
}
static void remove_file_real(sd_journal *j, JournalFile *f) {
if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB))
(void) add_file_by_name(j, d->path, e->name);
else if (e->mask & (IN_DELETE|IN_MOVED_FROM|IN_UNMOUNT))
- remove_file_by_name(j, d->path, e->name);
+ (void) remove_file_by_name(j, d->path, e->name);
} else if (!d->is_root && e->len == 0) {
# SPDX-License-Identifier: LGPL-2.1-or-later
systemd_repart_sources = files('repart.c')
-
-test_repart_sh = find_program('test-repart.sh')
offset *= secsz;
n_partitions = fdisk_table_get_nents(t);
- for (size_t i = 0; i < n_partitions; i++) {
+ for (size_t i = 0; i < n_partitions; i++) {
struct fdisk_partition *q;
uint64_t start;
return log_error_errno(r, "Failed to acquire partition table: %m");
n_partitions = fdisk_table_get_nents(t);
- for (size_t i = 0; i < n_partitions; i++) {
+ for (size_t i = 0; i < n_partitions; i++) {
_cleanup_free_ char *label_copy = NULL;
Partition *last = NULL;
struct fdisk_partition *p;
return log_error_errno(errno, "Failed to lock LUKS device: %m");
target_fd = encrypted_dev_fd;
- } else {
+ } else {
if (lseek(whole_fd, p->offset, SEEK_SET) == (off_t) -1)
return log_error_errno(errno, "Failed to seek to partition offset: %m");
struct {
sd_id128_t type_uuid;
uint64_t counter;
- } _packed_ plaintext = {};
+ } _packed_ plaintext = {};
union {
uint8_t md[SHA256_DIGEST_SIZE];
sd_id128_t id;
+++ /dev/null
-#!/usr/bin/env bash
-# SPDX-License-Identifier: LGPL-2.1-or-later
-set -eux
-set -o pipefail
-
-[[ -e /dev/loop-control ]] || exit 77
-
-repart="${1:?}"
-udevadm="${2:?}"
-test -x "$repart"
-test -x "$udevadm"
-
-PATH=$PATH:/sbin:/usr/sbin
-
-D="$(mktemp --tmpdir --directory "test-repart.XXXXXXXXXX")"
-
-# shellcheck disable=SC2064
-trap "rm -rf '$D'" EXIT INT QUIT PIPE
-mkdir -p "$D/definitions"
-
-SEED=e2a40bf9-73f1-4278-9160-49c031e7aef8
-
-echo "### Testing systemd-repart --empty=create ###"
-
-"$repart" "$D/zzz" --empty=create --size=1G --seed="$SEED" --no-pager
-
-sfdisk -d "$D/zzz" | grep -v -e 'sector-size' -e '^$' >"$D/empty"
-
-cmp "$D/empty" - <<EOF
-label: gpt
-label-id: EF7F7EE2-47B3-4251-B1A1-09EA8BF12D5D
-device: $D/zzz
-unit: sectors
-first-lba: 2048
-last-lba: 2097118
-EOF
-
-echo "### Testing with root, root2, home, & swap ###"
-
-cat >"$D/definitions/root.conf" <<EOF
-[Partition]
-Type=root-x86-64
-EOF
-
-ln -s root.conf "$D/definitions/root2.conf"
-
-cat >"$D/definitions/home.conf" <<EOF
-[Partition]
-Type=home
-Label=home-first
-Label=home-always-too-long-xxxxxxxxxxxxxx-%v
-EOF
-
-cat >"$D/definitions/swap.conf" <<EOF
-[Partition]
-Type=swap
-SizeMaxBytes=64M
-PaddingMinBytes=92M
-EOF
-
-"$repart" "$D/zzz" --dry-run=no --seed="$SEED" --definitions="$D/definitions" --no-pager
-
-sfdisk -d "$D/zzz" | grep -v -e 'sector-size' -e '^$' >"$D/populated"
-
-cmp "$D/populated" - <<EOF
-label: gpt
-label-id: EF7F7EE2-47B3-4251-B1A1-09EA8BF12D5D
-device: $D/zzz
-unit: sectors
-first-lba: 2048
-last-lba: 2097118
-$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first", attrs="GUID:59"
-$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64", attrs="GUID:59"
-$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2", attrs="GUID:59"
-$D/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=2AA78CDB-59C7-4173-AF11-C7453737A5D1, name="swap"
-EOF
-
-echo "### Testing with root, root2, home, swap, & another partition ###"
-
-cat >"$D/definitions/swap.conf" <<EOF
-[Partition]
-Type=swap
-SizeMaxBytes=64M
-EOF
-
-cat >"$D/definitions/extra.conf" <<EOF
-[Partition]
-Type=linux-generic
-Label=custom_label
-UUID=a0a1a2a3a4a5a6a7a8a9aaabacadaeaf
-EOF
-
-echo "Label=ignored_label" >>"$D/definitions/home.conf"
-echo "UUID=b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" >>"$D/definitions/home.conf"
-
-"$repart" "$D/zzz" --dry-run=no --seed="$SEED" --definitions="$D/definitions" --no-pager
-
-sfdisk -d "$D/zzz" | grep -v -e 'sector-size' -e '^$' >"$D/populated2"
-
-cmp "$D/populated2" - <<EOF
-label: gpt
-label-id: EF7F7EE2-47B3-4251-B1A1-09EA8BF12D5D
-device: $D/zzz
-unit: sectors
-first-lba: 2048
-last-lba: 2097118
-$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first", attrs="GUID:59"
-$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64", attrs="GUID:59"
-$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2", attrs="GUID:59"
-$D/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=2AA78CDB-59C7-4173-AF11-C7453737A5D1, name="swap"
-$D/zzz5 : start= 1908696, size= 188416, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name="custom_label"
-EOF
-
-echo "### Resizing to 2G ###"
-
-"$repart" "$D/zzz" --size=2G --dry-run=no --seed="$SEED" --definitions="$D/definitions" --no-pager
-
-sfdisk -d "$D/zzz" | grep -v -e 'sector-size' -e '^$' >"$D/populated3"
-
-cmp "$D/populated3" - <<EOF
-label: gpt
-label-id: EF7F7EE2-47B3-4251-B1A1-09EA8BF12D5D
-device: $D/zzz
-unit: sectors
-first-lba: 2048
-last-lba: 4194270
-$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first", attrs="GUID:59"
-$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64", attrs="GUID:59"
-$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2", attrs="GUID:59"
-$D/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=2AA78CDB-59C7-4173-AF11-C7453737A5D1, name="swap"
-$D/zzz5 : start= 1908696, size= 2285568, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name="custom_label"
-EOF
-
-dd if=/dev/urandom of="$D/block-copy" bs=4096 count=10240
-
-echo "### Testing with root, root2, home, swap, another partition, & partition copy ###"
-
-cat >"$D/definitions/extra2.conf" <<EOF
-[Partition]
-Type=linux-generic
-Label=block-copy
-UUID=2a1d97e1d0a346cca26eadc643926617
-CopyBlocks=$D/block-copy
-EOF
-
-"$repart" "$D/zzz" --size=3G --dry-run=no --seed="$SEED" --definitions="$D/definitions" --no-pager
-
-sfdisk -d "$D/zzz" | grep -v -e 'sector-size' -e '^$' >"$D/populated4"
-
-cmp "$D/populated4" - <<EOF
-label: gpt
-label-id: EF7F7EE2-47B3-4251-B1A1-09EA8BF12D5D
-device: $D/zzz
-unit: sectors
-first-lba: 2048
-last-lba: 6291422
-$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first", attrs="GUID:59"
-$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64", attrs="GUID:59"
-$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2", attrs="GUID:59"
-$D/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=2AA78CDB-59C7-4173-AF11-C7453737A5D1, name="swap"
-$D/zzz5 : start= 1908696, size= 2285568, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name="custom_label"
-$D/zzz6 : start= 4194264, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=2A1D97E1-D0A3-46CC-A26E-ADC643926617, name="block-copy"
-EOF
-
-cmp --bytes=41943040 --ignore-initial=0:$((512*4194264)) "$D/block-copy" "$D/zzz"
-
-if [ "$(id -u)" -eq 0 ] && type -P cryptsetup diff losetup >/dev/null ; then
- echo "### Testing Format=/Encrypt=/CopyFiles="
-
- # These tests require privileges unfortunately
-
- cat >"$D/definitions/extra3.conf" <<EOF
-[Partition]
-Type=linux-generic
-Label=luks-format-copy
-UUID=7b93d1f2-595d-4ce3-b0b9-837fbd9e63b0
-Format=ext4
-Encrypt=yes
-CopyFiles=$D/definitions:/def
-SizeMinBytes=48M
-EOF
-
- "$repart" "$D/zzz" --size=auto --dry-run=no --seed="$SEED" --definitions="$D/definitions" --no-pager
-
- sfdisk -d "$D/zzz" | grep -v -e 'sector-size' -e '^$' >"$D/populated5"
-
- cmp "$D/populated5" - <<EOF
-label: gpt
-label-id: EF7F7EE2-47B3-4251-B1A1-09EA8BF12D5D
-device: $D/zzz
-unit: sectors
-first-lba: 2048
-last-lba: 6389726
-$D/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=A6005774-F558-4330-A8E5-D6D2C01C01D6, name="home-first", attrs="GUID:59"
-$D/zzz2 : start= 593904, size= 591856, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=CE9C76EB-A8F1-40FF-813C-11DCA6C0A55B, name="root-x86-64", attrs="GUID:59"
-$D/zzz3 : start= 1185760, size= 591864, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, uuid=AC60A837-550C-43BD-B5C4-9CB73B884E79, name="root-x86-64-2", attrs="GUID:59"
-$D/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=2AA78CDB-59C7-4173-AF11-C7453737A5D1, name="swap"
-$D/zzz5 : start= 1908696, size= 2285568, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name="custom_label"
-$D/zzz6 : start= 4194264, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=2A1D97E1-D0A3-46CC-A26E-ADC643926617, name="block-copy"
-$D/zzz7 : start= 6291416, size= 98304, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=7B93D1F2-595D-4CE3-B0B9-837FBD9E63B0, name="luks-format-copy"
-EOF
-
- LOOP="$(losetup -P --show --find "$D/zzz")"
- "${udevadm:?}" wait --timeout 60 --settle "${LOOP:?}"
-
- VOLUME="test-repart-$RANDOM"
-
- touch "$D/empty-password"
- cryptsetup open --type=luks2 --key-file="$D/empty-password" "${LOOP}p7" "$VOLUME"
- mkdir "$D/mount"
- mount -t ext4 "/dev/mapper/$VOLUME" "$D/mount"
- # Use deferred closing on the mapper and autoclear on the loop, so they are cleaned up on umount
- cryptsetup close --deferred "$VOLUME"
- losetup -d "$LOOP"
- diff -r "$D/mount/def" "$D/definitions" >/dev/null
- umount "$D/mount"
-else
- echo "### Skipping Format=/Encrypt=/CopyFiles= test, lacking privileges or missing cryptsetup/diff/losetup"
-fi
-
-echo "### Testing json output ###"
-"$repart" "$D/zzz" --size=3G --dry-run=no --seed="$SEED" --definitions="$D/definitions" --no-pager --json=help
-"$repart" "$D/zzz" --size=3G --dry-run=no --seed="$SEED" --definitions="$D/definitions" --no-pager --json=pretty
-"$repart" "$D/zzz" --size=3G --dry-run=no --seed="$SEED" --definitions="$D/definitions" --no-pager --json=short
-
-echo "### Testing drop-in overrides ###"
-
-mkdir -p "$D/definitions-overrides"
-
-cat >"$D/definitions-overrides/root.conf" <<EOF
-[Partition]
-Type=swap
-SizeMaxBytes=64M
-UUID=837c3d67-21b3-478e-be82-7e7f83bf96d3
-EOF
-
-mkdir -p "$D/definitions-overrides/root.conf.d"
-
-cat >"$D/definitions-overrides/root.conf.d/override1.conf" <<EOF
-[Partition]
-Label=label1
-SizeMaxBytes=32M
-EOF
-
-cat >"$D/definitions-overrides/root.conf.d/override2.conf" <<EOF
-[Partition]
-Label=label2
-EOF
-
-rm -f test-drop-in-image
-
-JSON_OUTPUT=$("$repart" --definitions="$D/definitions-overrides" --dry-run=yes --empty=create --size=100M --json=pretty test-drop-in-image)
-
-diff <(echo "$JSON_OUTPUT") - <<EOF
-[
- {
- "type" : "swap",
- "label" : "label2",
- "uuid" : "837c3d67-21b3-478e-be82-7e7f83bf96d3",
- "file" : "root.conf",
- "node" : "test-drop-in-image1",
- "offset" : 1048576,
- "old_size" : 0,
- "raw_size" : 33554432,
- "old_padding" : 0,
- "raw_padding" : 0,
- "activity" : "create",
- "drop-in_files" : [
- "$D/definitions-overrides/root.conf.d/override1.conf",
- "$D/definitions-overrides/root.conf.d/override2.conf"
- ]
- }
-]
-EOF
-
-echo "### Testing list of definitions directories ###"
-
-mkdir -p "$D/definitions1"
-
-cat >"$D/definitions1/root1.conf" <<EOF
-[Partition]
-Type=swap
-SizeMaxBytes=32M
-UUID=7b93d1f2-595d-4ce3-b0b9-837fbd9e63b0
-Label=label1
-EOF
-
-mkdir -p "$D/definitions2"
-
-cat >"$D/definitions2/root2.conf" <<EOF
-[Partition]
-Type=swap
-SizeMaxBytes=32M
-UUID=837c3d67-21b3-478e-be82-7e7f83bf96d3
-Label=label2
-EOF
-
-rm -f test-definitions
-
-JSON_OUTPUT=$("$repart" --definitions="$D/definitions1" --definitions="$D/definitions2" --dry-run=yes --empty=create --size=100M --json=pretty test-definitions)
-
-diff <(echo "$JSON_OUTPUT") - <<EOF
-[
- {
- "type" : "swap",
- "label" : "label1",
- "uuid" : "7b93d1f2-595d-4ce3-b0b9-837fbd9e63b0",
- "file" : "root1.conf",
- "node" : "test-definitions1",
- "offset" : 1048576,
- "old_size" : 0,
- "raw_size" : 33554432,
- "old_padding" : 0,
- "raw_padding" : 0,
- "activity" : "create"
- },
- {
- "type" : "swap",
- "label" : "label2",
- "uuid" : "837c3d67-21b3-478e-be82-7e7f83bf96d3",
- "file" : "root2.conf",
- "node" : "test-definitions2",
- "offset" : 34603008,
- "old_size" : 0,
- "raw_size" : 33554432,
- "old_padding" : 0,
- "raw_padding" : 0,
- "activity" : "create"
- }
-]
-EOF
const char *path,
const char *source) {
+ _cleanup_free_ char *path_buf = NULL, *source_buf = NULL;
+
assert(path);
assert(!changes == !n_changes);
return 0;
if (prefix) {
- path = prefix_roota(prefix, path);
+ path_buf = path_join(prefix, path);
+ if (!path_buf)
+ return -ENOMEM;
+
+ path = path_buf;
+
+ if (source) {
+ source_buf = path_join(prefix, source);
+ if (!source_buf)
+ return -ENOMEM;
- if (source)
- source = prefix_roota(prefix, source);
+ source = source_buf;
+ }
}
return portable_changes_add(changes, n_changes, type_or_errno, path, source);
_cleanup_(unlink_and_freep) char *chroot_dropin = NULL, *profile_dropin = NULL;
_cleanup_(rmdir_and_freep) char *dropin_dir = NULL;
- const char *where, *path;
+ _cleanup_free_ char *path = NULL;
+ const char *where;
int r;
assert(paths);
} else
(void) portable_changes_add(changes, n_changes, PORTABLE_MKDIR, where, NULL);
- path = prefix_roota(where, m->name);
+ path = path_join(where, m->name);
+ if (!path)
+ return -ENOMEM;
+
dropin_dir = strjoin(path, ".d");
if (!dropin_dir)
return -ENOMEM;
/* Returns true if this is a cache item created as result of an explicit lookup, or created as "side-effect"
* of another request. "Primary" entries will carry the full answer data (with NSEC, …) that can aso prove
- * wildcard expansion, non-existance and such, while entries that were created as "side-effect" just contain
+ * wildcard expansion, non-existence and such, while entries that were created as "side-effect" just contain
* immediate RR data for the specified RR key, but nothing else. */
#define DNS_CACHE_ITEM_IS_PRIMARY(item) (!!(item)->answer)
/* Returns the size of the string in bytes without the terminating two zero bytes */
- if (buf_len_bytes % sizeof(uint16_t) != 0)
- return -EINVAL;
-
while (l < buf_len_bytes / sizeof(uint16_t)) {
if (s[l] == 0)
return (l + 1) * sizeof(uint16_t);
const char *name,
FILE **file) {
- const char *unit;
+ _cleanup_free_ char *unit = NULL;
FILE *f;
int r;
- unit = prefix_roota(dest, name);
+ unit = path_join(dest, name);
+ if (!unit)
+ return log_oom();
r = fopen_unlocked(unit, "wxe", &f);
if (r < 0) {
const char *what) {
_cleanup_free_ char *node = NULL, *unit = NULL, *escaped = NULL, *where_unit = NULL;
+ _cleanup_free_ char *unit_file = NULL;
_cleanup_fclose_ FILE *f = NULL;
- const char *unit_file;
int r;
node = fstab_node_to_udev_node(what);
return log_error_errno(r, "Failed to make unit instance name from path \"%s\": %m",
node);
- unit_file = prefix_roota(dir, unit);
+ unit_file = path_join(dir, unit);
+ if (!unit_file)
+ return log_oom();
+
log_debug("Creating %s", unit_file);
escaped = cescape(node);
const char *where,
const char *type) {
- _cleanup_free_ char *node = NULL, *unit = NULL, *escaped = NULL, *where_unit = NULL;
+ _cleanup_free_ char *node = NULL, *unit = NULL, *unit_file = NULL, *escaped = NULL, *where_unit = NULL;
_cleanup_fclose_ FILE *f = NULL;
- const char *unit_file;
int r;
node = fstab_node_to_udev_node(what);
return log_error_errno(r, "Failed to make unit instance name from path \"%s\": %m",
node);
- unit_file = prefix_roota(dir, unit);
+ unit_file = path_join(dir, unit);
+ if (!unit_file)
+ return log_oom();
+
log_debug("Creating %s", unit_file);
escaped = cescape(node);
const char *where,
const char *target) {
- _cleanup_free_ char *unit = NULL, *escaped = NULL, *where_unit = NULL;
+ _cleanup_free_ char *unit = NULL, *escaped = NULL, *where_unit = NULL, *unit_file = NULL;
_cleanup_fclose_ FILE *f = NULL;
- const char *unit_file;
int r;
assert(dir);
return log_error_errno(r, "Failed to make unit name from path \"%s\": %m",
where);
- unit_file = prefix_roota(dir, unit);
+ unit_file = path_join(dir, unit);
+ if (!unit_file)
+ return log_oom();
+
log_debug("Creating %s", unit_file);
f = fopen(unit_file, "wxe");
_GPT_ARCH_SEXTET(PARISC, "parisc"),
_GPT_ARCH_SEXTET(PPC, "ppc"),
_GPT_ARCH_SEXTET(PPC64, "ppc64"),
- _GPT_ARCH_SEXTET(PPC64_LE, "ppc64-le"),
+ _GPT_ARCH_SEXTET(PPC64_LE, "ppc64-le"),
_GPT_ARCH_SEXTET(RISCV32, "riscv32"),
_GPT_ARCH_SEXTET(RISCV64, "riscv64"),
_GPT_ARCH_SEXTET(S390, "s390"),
#define GPT_ROOT_PPC64_LE SD_ID128_MAKE(c3,1c,45,e6,3f,39,41,2e,80,fb,48,09,c4,98,05,99)
#define GPT_ROOT_RISCV32 SD_ID128_MAKE(60,d5,a7,fe,8e,7d,43,5c,b7,14,3d,d8,16,21,44,e1)
#define GPT_ROOT_RISCV64 SD_ID128_MAKE(72,ec,70,a6,cf,74,40,e6,bd,49,4b,da,08,e8,f2,24)
-#define GPT_ROOT_S390 SD_ID128_MAKE(08,a7,ac,ea,62,4c,4a,20,91,e8,6e,0f,a6,7d,23,f9)
#define GPT_ROOT_S390X SD_ID128_MAKE(5e,ea,d9,a9,fe,09,4a,1e,a1,d7,52,0d,00,53,13,06)
+#define GPT_ROOT_S390 SD_ID128_MAKE(08,a7,ac,ea,62,4c,4a,20,91,e8,6e,0f,a6,7d,23,f9)
#define GPT_ROOT_TILEGX SD_ID128_MAKE(c5,0c,dd,70,38,62,4c,c3,90,e1,80,9a,8c,93,ee,2c)
#define GPT_ROOT_X86 SD_ID128_MAKE(44,47,95,40,f2,97,41,b2,9a,f7,d1,31,d5,f0,45,8a)
#define GPT_ROOT_X86_64 SD_ID128_MAKE(4f,68,bc,e3,e8,cd,4d,b1,96,e7,fb,ca,f9,84,b7,09)
#define GPT_USR_PPC64_LE SD_ID128_MAKE(15,bb,03,af,77,e7,4d,4a,b1,2b,c0,d0,84,f7,49,1c)
#define GPT_USR_RISCV32 SD_ID128_MAKE(b9,33,fb,22,5c,3f,4f,91,af,90,e2,bb,0f,a5,07,02)
#define GPT_USR_RISCV64 SD_ID128_MAKE(be,ae,c3,4b,84,42,43,9b,a4,0b,98,43,81,ed,09,7d)
-#define GPT_USR_S390 SD_ID128_MAKE(cd,0f,86,9b,d0,fb,4c,a0,b1,41,9e,a8,7c,c7,8d,66)
#define GPT_USR_S390X SD_ID128_MAKE(8a,4f,57,70,50,aa,4e,d3,87,4a,99,b7,10,db,6f,ea)
+#define GPT_USR_S390 SD_ID128_MAKE(cd,0f,86,9b,d0,fb,4c,a0,b1,41,9e,a8,7c,c7,8d,66)
#define GPT_USR_TILEGX SD_ID128_MAKE(55,49,70,29,c7,c1,44,cc,aa,39,81,5e,d1,55,86,30)
#define GPT_USR_X86 SD_ID128_MAKE(75,25,0d,76,8c,c6,45,8e,bd,66,bd,47,cc,81,a8,12)
#define GPT_USR_X86_64 SD_ID128_MAKE(84,84,68,0c,95,21,48,c6,9c,11,b0,72,06,56,f6,9e)
# define GPT_USR_NATIVE_VERITY GPT_USR_RISCV64_VERITY
# define GPT_USR_NATIVE_VERITY_SIG GPT_USR_RISCV64_VERITY_SIG
-#elif defined(__s390__)
-# define GPT_ROOT_NATIVE GPT_ROOT_S390
-# define GPT_ROOT_NATIVE_VERITY GPT_ROOT_S390_VERITY
-# define GPT_ROOT_NATIVE_VERITY_SIG GPT_ROOT_S390_VERITY_SIG
-# define GPT_USR_NATIVE GPT_USR_S390
-# define GPT_USR_NATIVE_VERITY GPT_USR_S390_VERITY
-# define GPT_USR_NATIVE_VERITY_SIG GPT_USR_S390_VERITY_SIG
-
#elif defined(__s390x__)
# define GPT_ROOT_NATIVE GPT_ROOT_S390X
# define GPT_ROOT_NATIVE_VERITY GPT_ROOT_S390X_VERITY
# define GPT_USR_NATIVE_VERITY GPT_USR_S390X_VERITY
# define GPT_USR_NATIVE_VERITY_SIG GPT_USR_S390X_VERITY_SIG
+#elif defined(__s390__)
+# define GPT_ROOT_NATIVE GPT_ROOT_S390
+# define GPT_ROOT_NATIVE_VERITY GPT_ROOT_S390_VERITY
+# define GPT_ROOT_NATIVE_VERITY_SIG GPT_ROOT_S390_VERITY_SIG
+# define GPT_USR_NATIVE GPT_USR_S390
+# define GPT_USR_NATIVE_VERITY GPT_USR_S390_VERITY
+# define GPT_USR_NATIVE_VERITY_SIG GPT_USR_S390_VERITY_SIG
+
#elif defined(__tilegx__)
# define GPT_ROOT_NATIVE GPT_ROOT_TILEGX
# define GPT_ROOT_NATIVE_VERITY GPT_ROOT_TILEGX_VERITY
if (r < 0)
return log_oom();
- printf("%1$s [OPTIONS...] [DEVICE]\n"
+ printf("%1$s [OPTIONS...] COMMAND\n"
"\n%5$sMerge extension images into /usr/ and /opt/ hierarchies.%6$s\n"
"\n%3$sCommands:%4$s\n"
" status Show current merge status (default)\n"
}
static int add_alias(const char *service, const char *alias) {
- const char *link;
- int r;
+ _cleanup_free_ char *link = NULL;
assert(service);
assert(alias);
- link = prefix_roota(arg_dest, alias);
+ link = path_join(arg_dest, alias);
+ if (!link)
+ return -ENOMEM;
- r = symlink(service, link);
- if (r < 0) {
+ if (symlink(service, link) < 0) {
if (errno == EEXIST)
return 0;
}
static int generate_unit_file(SysvStub *s) {
- _cleanup_free_ char *path_escaped = NULL;
+ _cleanup_free_ char *path_escaped = NULL, *unit = NULL;
_cleanup_fclose_ FILE *f = NULL;
- const char *unit;
int r;
assert(s);
if (!path_escaped)
return log_oom();
- unit = prefix_roota(arg_dest, s->name);
+ unit = path_join(arg_dest, s->name);
+ if (!unit)
+ return log_oom();
/* We might already have a symlink with the same name from a Provides:,
* or from backup files like /etc/init.d/foo.bak. Real scripts always win,
}
/*
- * Type-independant Stuff
+ * Type-independent Stuff
*/
static const char *dmi_string(const struct dmi_header *dm, uint8_t s) {
if (r < 0)
return r;
- if (event->retry_again_next_usec <= now_usec)
+ if (event->retry_again_next_usec > now_usec)
return true;
}
set -e
TEST_DESCRIPTION="test systemd-repart"
-TEST_NO_NSPAWN=1
# shellcheck source=test/test-functions
. "$TEST_BASE_DIR/test-functions"
+test_append_files() {
+ if ! get_bool "${TEST_NO_QEMU:=}"; then
+ install_dmevent
+ generate_module_dependencies
+ fi
+}
+
do_test "$@"
image_install /lib/tmpfiles.d/knot.conf
image_install "${ROOTLIBDIR:?}/system/knot.service"
image_install -o /etc/dbus-1/system.d/cz.nic.knotd.conf
+ image_install -o /etc/default/knot
# Copy over our configuration
mkdir -p "${workspace:?}/var/lib/knot/zones/" "${workspace:?}/etc/knot/"
# shellcheck disable=SC2064
trap "rm -rf '$D'" EXIT INT QUIT PIPE
mkdir -p "$D/etc/udev"
-ln -s "$ROOTDIR/hwdb.d" "$D/etc/udev/hwdb.d"
+cp -a "$ROOTDIR/hwdb.d" "$D/etc/udev/hwdb.d"
# Test "good" properties" — no warnings or errors allowed
err=$("$SYSTEMD_HWDB" update --root "$D" 2>&1 >/dev/null) && rc= || rc=$?
fi
# Test "bad" properties" — warnings required, errors not allowed
-rm -f "$D/etc/udev/hwdb.bin" "$D/etc/udev/hwdb.d"
+rm -rf "$D/etc/udev/hwdb.bin" "$D/etc/udev/hwdb.d"
-ln -s "$ROOTDIR/test/hwdb.d" "$D/etc/udev/hwdb.d"
+cp -a "$ROOTDIR/test/hwdb.d" "$D/etc/udev/hwdb.d"
err=$("$SYSTEMD_HWDB" update --root "$D" 2>&1 >/dev/null) && rc= || rc=$?
if [ -n "$rc" ]; then
echo "$SYSTEMD_HWDB returned $rc"
exit 0
fi
+# shellcheck source=test/units/assert.sh
+. "$(dirname "$0")"/assert.sh
+
export SYSTEMD_LOG_LEVEL=debug
export PAGER=cat
+seed=750b6cd5c4ae4012a15e7be3c29e6a47
+
+if ! systemd-detect-virt --quiet --container; then
+ mkdir -p /run/systemd/system/systemd-udevd.service.d
+ cat >/run/systemd/system/systemd-udevd.service.d/debug.conf <<EOF
+[Service]
+Environment=SYSTEMD_LOG_LEVEL=debug
+EOF
+
+ systemctl daemon-reload
+ udevadm settle
+ systemctl restart systemd-udevd.service
+ udevadm control --ping
+fi
+
machine="$(uname -m)"
if [ "${machine}" = "x86_64" ]; then
- root_guid=4f68bce3-e8cd-4db1-96e7-fbcaf984b709
+ root_guid=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709
root_uuid=60F33797-1D71-4DCB-AA6F-20564F036CD0
- usr_guid=8484680c-9521-48c6-9c11-b0720656f69e
+ root_uuid2=73A4CCD2-EAF5-44DA-A366-F99188210FDC
+ usr_guid=8484680C-9521-48C6-9C11-B0720656F69E
usr_uuid=7E3369DD-D653-4513-ADF5-B993A9F20C16
architecture="x86-64"
elif [ "${machine}" = "i386" ] || [ "${machine}" = "i686" ] || [ "${machine}" = "x86" ]; then
- root_guid=44479540-f297-41b2-9af7-d131d5f0458a
- root_uuid=02b4253f-29a4-404e-8972-1669d3b03c87
- usr_guid=75250d76-8cc6-458e-bd66-bd47cc81a812
- usr_uuid=7b42ffb0-b0e1-4395-b20b-c78f4a571648
+ root_guid=44479540-F297-41B2-9AF7-D131D5F0458A
+ root_uuid=02B4253F-29A4-404E-8972-1669D3B03C87
+ root_uuid2=268E0FD3-B468-4806-A823-E533FE9BB9CC
+ usr_guid=75250D76-8CC6-458E-BD66-BD47CC81A812
+ usr_uuid=7B42FFB0-B0E1-4395-B20B-C78F4A571648
architecture="x86"
elif [ "${machine}" = "aarch64" ] || [ "${machine}" = "aarch64_be" ] || [ "${machine}" = "armv8b" ] || [ "${machine}" = "armv8l" ]; then
- root_guid=b921b045-1df0-41c3-af44-4c6f280d3fae
- root_uuid=055d0227-53a6-4033-85c3-9a5973eff483
- usr_guid=b0e01050-ee5f-4390-949a-9101b17104e9
- usr_uuid=fce3c75e-d6a4-44c0-87f0-4c105183fb1f
+ root_guid=B921B045-1DF0-41C3-AF44-4C6F280D3FAE
+ root_uuid=055D0227-53A6-4033-85C3-9A5973EFF483
+ root_uuid2=F7DBBE48-8FD0-4833-8411-AA34E7C8E60A
+ usr_guid=B0E01050-EE5F-4390-949A-9101B17104E9
+ usr_uuid=FCE3C75E-D6A4-44C0-87F0-4C105183FB1F
architecture="arm64"
elif [ "${machine}" = "arm" ]; then
- root_guid=69dad710-2ce4-4e3c-b16c-21a1d49abed3
- root_uuid=567da89e-8de2-4499-8d10-18f212dff034
- usr_guid=7d0359a3-02b3-4f0a-865c-654403e70625
- usr_uuid=71e93dc2-5073-42cb-8a84-a354e64d8966
+ root_guid=69DAD710-2CE4-4E3C-B16C-21A1D49ABED3
+ root_uuid=567DA89E-8DE2-4499-8D10-18F212DFF034
+ root_uuid2=813ECFE5-4C89-4193-8A52-437493F2F96E
+ usr_guid=7D0359A3-02B3-4F0A-865C-654403E70625
+ usr_uuid=71E93DC2-5073-42CB-8A84-A354E64D8966
architecture="arm"
elif [ "${machine}" = "loongarch64" ]; then
- root_guid=77055800-792c-4f94-b39a-98c91b762bb6
- root_uuid=d8efc2d2-0133-41e4-bdcb-3b9f4cfddde8
- usr_guid=e611c702-575c-4cbe-9a46-434fa0bf7e3f
- usr_uuid=031ffa75-00bb-49b6-a70d-911d2d82a5b7
+ root_guid=77055800-792C-4F94-B39A-98C91B762BB6
+ root_uuid=D8EFC2D2-0133-41E4-BDCB-3B9F4CFDDDE8
+ root_uuid2=36499F9E-0688-40C1-A746-EA8FD9543C56
+ usr_guid=E611C702-575C-4CBE-9A46-434FA0BF7E3F
+ usr_uuid=031FFA75-00BB-49B6-A70D-911D2D82A5B7
architecture="loongarch64"
elif [ "${machine}" = "ia64" ]; then
- root_guid=993d8d3d-f80e-4225-855a-9daf8ed7ea97
- root_uuid=dcf33449-0896-4ea9-bc24-7d58aeef522d
- usr_guid=4301d2a6-4e3b-4b2a-bb94-9e0b2c4225ea
- usr_uuid=bc2bcce7-80d6-449a-85cc-637424ce5241
+ root_guid=993D8D3D-F80E-4225-855A-9DAF8ED7EA97
+ root_uuid=DCF33449-0896-4EA9-BC24-7D58AEEF522D
+ root_uuid2=C2A6CAB7-ABEA-4FBA-8C48-CB4C52E6CA38
+ usr_guid=4301D2A6-4E3B-4B2A-BB94-9E0B2C4225EA
+ usr_uuid=BC2BCCE7-80D6-449A-85CC-637424CE5241
architecture="ia64"
elif [ "${machine}" = "s390x" ]; then
- root_guid=5eead9a9-fe09-4a1e-a1d7-520d00531306
- root_uuid=7ebe0c85-e27e-48ec-b164-f4807606232e
- usr_guid=8a4f5770-50aa-4ed3-874a-99b710db6fea
- usr_uuid=51171d30-35cf-4a49-b8b5-9478b9b796a5
+ root_guid=5EEAD9A9-FE09-4A1E-A1D7-520D00531306
+ root_uuid=7EBE0C85-E27E-48EC-B164-F4807606232E
+ root_uuid2=2A074E1C-2A19-4094-A0C2-24B1A5D52FCB
+ usr_guid=8A4F5770-50AA-4ED3-874A-99B710DB6FEA
+ usr_uuid=51171D30-35CF-4A49-B8B5-9478B9B796A5
architecture="s390x"
elif [ "${machine}" = "ppc64le" ]; then
- root_guid=c31c45e6-3f39-412e-80fb-4809c4980599
- root_uuid=061e67a1-092f-482f-8150-b525d50d6654
- usr_guid=15bb03af-77e7-4d4a-b12b-c0d084f7491c
- usr_uuid=c0d0823b-8040-4c7c-a629-026248e297fb
+ root_guid=C31C45E6-3F39-412E-80FB-4809C4980599
+ root_uuid=061E67A1-092F-482F-8150-B525D50D6654
+ root_uuid2=A6687CEF-4E4F-44E7-90B3-CDA52EA81739
+ usr_guid=15BB03AF-77E7-4D4A-B12B-C0D084F7491C
+ usr_uuid=C0D0823B-8040-4C7C-A629-026248E297FB
architecture="ppc64-le"
else
echo "Unexpected uname -m: ${machine} in testsuite-58.sh, please fix me"
exit 1
fi
-rm -f /var/tmp/testsuite-58.img /var/tmp/testsuite-58.2.img /tmp/testsuite-58.dump
-mkdir -p /tmp/testsuite-58-defs/
+test_basic() {
+ local defs imgs output
+ local loop volume
+
+ defs="$(mktemp --directory "/tmp/test-repart.XXXXXXXXXX")"
+ imgs="$(mktemp --directory "/var/tmp/test-repart.XXXXXXXXXX")"
+ # shellcheck disable=SC2064
+ trap "rm -rf '$defs' '$imgs'" RETURN
+
+ # 1. create an empty image
+
+ systemd-repart --empty=create \
+ --size=1G \
+ --seed="$seed" \
+ "$imgs/zzz"
+
+ output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$')
+
+ assert_eq "$output" "label: gpt
+label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD
+device: $imgs/zzz
+unit: sectors
+first-lba: 2048
+last-lba: 2097118"
+
+ # 2. Testing with root, root2, home, and swap
+
+ cat >"$defs/root.conf" <<EOF
+[Partition]
+Type=root
+EOF
+
+ ln -s root.conf "$defs/root2.conf"
+
+ cat >"$defs/home.conf" <<EOF
+[Partition]
+Type=home
+Label=home-first
+Label=home-always-too-long-xxxxxxxxxxxxxx-%v
+EOF
+
+ cat >"$defs/swap.conf" <<EOF
+[Partition]
+Type=swap
+SizeMaxBytes=64M
+PaddingMinBytes=92M
+EOF
+
+ systemd-repart --definitions="$defs" \
+ --dry-run=no \
+ --seed="$seed" \
+ "$imgs/zzz"
+
+ output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$')
+
+ assert_eq "$output" "label: gpt
+label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD
+device: $imgs/zzz
+unit: sectors
+first-lba: 2048
+last-lba: 2097118
+$imgs/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\"
+$imgs/zzz2 : start= 593904, size= 591856, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\"
+$imgs/zzz3 : start= 1185760, size= 591864, type=${root_guid}, uuid=${root_uuid2}, name=\"root-${architecture}-2\", attrs=\"GUID:59\"
+$imgs/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\""
+
+ # 3. Testing with root, root2, home, swap, and another partition
+
+ cat >"$defs/swap.conf" <<EOF
+[Partition]
+Type=swap
+SizeMaxBytes=64M
+EOF
+
+ cat >"$defs/extra.conf" <<EOF
+[Partition]
+Type=linux-generic
+Label=custom_label
+UUID=a0a1a2a3a4a5a6a7a8a9aaabacadaeaf
+EOF
+
+ echo "Label=ignored_label" >>"$defs/home.conf"
+ echo "UUID=b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" >>"$defs/home.conf"
+
+ systemd-repart --definitions="$defs" \
+ --dry-run=no \
+ --seed="$seed" \
+ "$imgs/zzz"
+
+ output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$')
+
+ assert_eq "$output" "label: gpt
+label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD
+device: $imgs/zzz
+unit: sectors
+first-lba: 2048
+last-lba: 2097118
+$imgs/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\"
+$imgs/zzz2 : start= 593904, size= 591856, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\"
+$imgs/zzz3 : start= 1185760, size= 591864, type=${root_guid}, uuid=${root_uuid2}, name=\"root-${architecture}-2\", attrs=\"GUID:59\"
+$imgs/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\"
+$imgs/zzz5 : start= 1908696, size= 188416, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name=\"custom_label\""
+
+ # 4. Resizing to 2G
+
+ systemd-repart --definitions="$defs" \
+ --size=2G \
+ --dry-run=no \
+ --seed="$seed" \
+ "$imgs/zzz"
+
+ output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$')
+
+ assert_eq "$output" "label: gpt
+label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD
+device: $imgs/zzz
+unit: sectors
+first-lba: 2048
+last-lba: 4194270
+$imgs/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\"
+$imgs/zzz2 : start= 593904, size= 591856, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\"
+$imgs/zzz3 : start= 1185760, size= 591864, type=${root_guid}, uuid=${root_uuid2}, name=\"root-${architecture}-2\", attrs=\"GUID:59\"
+$imgs/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\"
+$imgs/zzz5 : start= 1908696, size= 2285568, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name=\"custom_label\""
+
+ # 5. Testing with root, root2, home, swap, another partition, and partition copy
+
+ dd if=/dev/urandom of="$imgs/block-copy" bs=4096 count=10240
+
+ cat >"$defs/extra2.conf" <<EOF
+[Partition]
+Type=linux-generic
+Label=block-copy
+UUID=2a1d97e1d0a346cca26eadc643926617
+CopyBlocks=$imgs/block-copy
+EOF
+
+ systemd-repart --definitions="$defs" \
+ --size=3G \
+ --dry-run=no \
+ --seed="$seed" \
+ "$imgs/zzz"
+
+ output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$')
+
+ assert_eq "$output" "label: gpt
+label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD
+device: $imgs/zzz
+unit: sectors
+first-lba: 2048
+last-lba: 6291422
+$imgs/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\"
+$imgs/zzz2 : start= 593904, size= 591856, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\"
+$imgs/zzz3 : start= 1185760, size= 591864, type=${root_guid}, uuid=${root_uuid2}, name=\"root-${architecture}-2\", attrs=\"GUID:59\"
+$imgs/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\"
+$imgs/zzz5 : start= 1908696, size= 2285568, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name=\"custom_label\"
+$imgs/zzz6 : start= 4194264, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=2A1D97E1-D0A3-46CC-A26E-ADC643926617, name=\"block-copy\""
+
+ cmp --bytes=$((4096*10240)) --ignore-initial=0:$((512*4194264)) "$imgs/block-copy" "$imgs/zzz"
+
+ if systemd-detect-virt --quiet --container; then
+ echo "Skipping encrypt tests in container."
+ return
+ fi
+
+ # 6. Testing Format=/Encrypt=/CopyFiles=
+
+ cat >"$defs/extra3.conf" <<EOF
+[Partition]
+Type=linux-generic
+Label=luks-format-copy
+UUID=7b93d1f2-595d-4ce3-b0b9-837fbd9e63b0
+Format=ext4
+Encrypt=yes
+CopyFiles=$defs:/def
+SizeMinBytes=48M
+EOF
+
+ systemd-repart --definitions="$defs" \
+ --size=auto \
+ --dry-run=no \
+ --seed="$seed" \
+ "$imgs/zzz"
+
+ output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$')
+
+ assert_eq "$output" "label: gpt
+label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD
+device: $imgs/zzz
+unit: sectors
+first-lba: 2048
+last-lba: 6389726
+$imgs/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\"
+$imgs/zzz2 : start= 593904, size= 591856, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\"
+$imgs/zzz3 : start= 1185760, size= 591864, type=${root_guid}, uuid=${root_uuid2}, name=\"root-${architecture}-2\", attrs=\"GUID:59\"
+$imgs/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\"
+$imgs/zzz5 : start= 1908696, size= 2285568, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name=\"custom_label\"
+$imgs/zzz6 : start= 4194264, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=2A1D97E1-D0A3-46CC-A26E-ADC643926617, name=\"block-copy\"
+$imgs/zzz7 : start= 6291416, size= 98304, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=7B93D1F2-595D-4CE3-B0B9-837FBD9E63B0, name=\"luks-format-copy\""
+
+ loop="$(losetup -P --show --find "$imgs/zzz")"
+ udevadm wait --timeout 60 --settle "${loop:?}"
+
+ volume="test-repart-$RANDOM"
+
+ touch "$imgs/empty-password"
+ cryptsetup open --type=luks2 --key-file="$imgs/empty-password" "${loop}p7" "$volume"
+ mkdir -p "$imgs/mount"
+ mount -t ext4 "/dev/mapper/$volume" "$imgs/mount"
+ # Use deferred closing on the mapper and autoclear on the loop, so they are cleaned up on umount
+ cryptsetup close --deferred "$volume"
+ losetup -d "$loop"
+ diff -r "$imgs/mount/def" "$defs" >/dev/null
+ umount "$imgs/mount"
+}
+
+test_dropin() {
+ local defs imgs output
-# First part: create a disk image and verify its in order
+ defs="$(mktemp --directory "/tmp/test-repart.XXXXXXXXXX")"
+ imgs="$(mktemp --directory "/var/tmp/test-repart.XXXXXXXXXX")"
+ # shellcheck disable=SC2064
+ trap "rm -rf '$defs' '$imgs'" RETURN
-cat >/tmp/testsuite-58-defs/esp.conf <<EOF
+ cat >"$defs/root.conf" <<EOF
+[Partition]
+Type=swap
+SizeMaxBytes=64M
+UUID=837c3d67-21b3-478e-be82-7e7f83bf96d3
+EOF
+
+ mkdir -p "$defs/root.conf.d"
+ cat >"$defs/root.conf.d/override1.conf" <<EOF
+[Partition]
+Label=label1
+SizeMaxBytes=32M
+EOF
+
+ cat >"$defs/root.conf.d/override2.conf" <<EOF
+[Partition]
+Label=label2
+EOF
+
+ output=$(systemd-repart --definitions="$defs" --empty=create --size=100M --json=pretty "$imgs/zzz")
+
+ diff <(echo "$output") - <<EOF
+[
+ {
+ "type" : "swap",
+ "label" : "label2",
+ "uuid" : "837c3d67-21b3-478e-be82-7e7f83bf96d3",
+ "file" : "root.conf",
+ "node" : "$imgs/zzz1",
+ "offset" : 1048576,
+ "old_size" : 0,
+ "raw_size" : 33554432,
+ "size" : "→ 32.0M",
+ "old_padding" : 0,
+ "raw_padding" : 0,
+ "padding" : "→ 0B",
+ "activity" : "create",
+ "drop-in_files" : [
+ "$defs/root.conf.d/override1.conf",
+ "$defs/root.conf.d/override2.conf"
+ ]
+ }
+]
+EOF
+}
+
+test_multiple_definitions() {
+ local defs imgs output
+
+ defs="$(mktemp --directory "/tmp/test-repart.XXXXXXXXXX")"
+ imgs="$(mktemp --directory "/var/tmp/test-repart.XXXXXXXXXX")"
+ # shellcheck disable=SC2064
+ trap "rm -rf '$defs' '$imgs'" RETURN
+
+ mkdir -p "$defs/1"
+
+ cat >"$defs/1/root1.conf" <<EOF
+[Partition]
+Type=swap
+SizeMaxBytes=32M
+UUID=7b93d1f2-595d-4ce3-b0b9-837fbd9e63b0
+Label=label1
+EOF
+
+ mkdir -p "$defs/2"
+
+ cat >"$defs/2/root2.conf" <<EOF
+[Partition]
+Type=swap
+SizeMaxBytes=32M
+UUID=837c3d67-21b3-478e-be82-7e7f83bf96d3
+Label=label2
+EOF
+
+ output=$(systemd-repart --definitions="$defs/1" --definitions="$defs/2" --empty=create --size=100M --json=pretty "$imgs/zzz")
+
+ diff <(echo "$output") - <<EOF
+[
+ {
+ "type" : "swap",
+ "label" : "label1",
+ "uuid" : "7b93d1f2-595d-4ce3-b0b9-837fbd9e63b0",
+ "file" : "root1.conf",
+ "node" : "$imgs/zzz1",
+ "offset" : 1048576,
+ "old_size" : 0,
+ "raw_size" : 33554432,
+ "size" : "→ 32.0M",
+ "old_padding" : 0,
+ "raw_padding" : 0,
+ "padding" : "→ 0B",
+ "activity" : "create"
+ },
+ {
+ "type" : "swap",
+ "label" : "label2",
+ "uuid" : "837c3d67-21b3-478e-be82-7e7f83bf96d3",
+ "file" : "root2.conf",
+ "node" : "$imgs/zzz2",
+ "offset" : 34603008,
+ "old_size" : 0,
+ "raw_size" : 33554432,
+ "size" : "→ 32.0M",
+ "old_padding" : 0,
+ "raw_padding" : 0,
+ "padding" : "→ 0B",
+ "activity" : "create"
+ }
+]
+EOF
+}
+
+test_copy_blocks() {
+ local defs imgs output
+
+ if systemd-detect-virt --quiet --container; then
+ echo "Skipping copy blocks tests in container."
+ return
+ fi
+
+ defs="$(mktemp --directory "/tmp/test-repart.XXXXXXXXXX")"
+ imgs="$(mktemp --directory "/var/tmp/test-repart.XXXXXXXXXX")"
+ # shellcheck disable=SC2064
+ trap "rm -rf '$defs' '$imgs'" RETURN
+
+ # First, create a disk image and verify its in order
+
+ cat >"$defs/esp.conf" <<EOF
[Partition]
Type=esp
SizeMinBytes=10M
Format=vfat
EOF
-cat >/tmp/testsuite-58-defs/usr.conf <<EOF
+ cat >"$defs/usr.conf" <<EOF
[Partition]
Type=usr-${architecture}
SizeMinBytes=10M
ReadOnly=yes
EOF
-cat >/tmp/testsuite-58-defs/root.conf <<EOF
+ cat >"$defs/root.conf" <<EOF
[Partition]
Type=root-${architecture}
SizeMinBytes=10M
MakeDirectories=/usr /efi
EOF
-systemd-repart --definitions=/tmp/testsuite-58-defs/ \
- --empty=create \
- --size=auto \
- --seed=750b6cd5c4ae4012a15e7be3c29e6a47 \
- /var/tmp/testsuite-58.img
+ systemd-repart --definitions="$defs" \
+ --empty=create \
+ --size=auto \
+ --seed="$seed" \
+ "$imgs/zzz"
-sfdisk --dump /var/tmp/testsuite-58.img | tee /tmp/testsuite-58.dump
+ output=$(sfdisk --dump "$imgs/zzz")
-grep -qixF "/var/tmp/testsuite-58.img1 : start= 2048, size= 20480, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=39107B09-615D-48FB-BA37-C663885FCE67, name=\"esp\"" /tmp/testsuite-58.dump
-grep -qixF "/var/tmp/testsuite-58.img2 : start= 22528, size= 20480, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\"" /tmp/testsuite-58.dump
-grep -qixF "/var/tmp/testsuite-58.img3 : start= 43008, size= 20480, type=${usr_guid}, uuid=${usr_uuid}, name=\"usr-${architecture}\", attrs=\"GUID:60\"" /tmp/testsuite-58.dump
+ assert_in "$imgs/zzz1 : start= 2048, size= 20480, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=39107B09-615D-48FB-BA37-C663885FCE67, name=\"esp\"" "$output"
+ assert_in "$imgs/zzz2 : start= 22528, size= 20480, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\"" "$output"
+ assert_in "$imgs/zzz3 : start= 43008, size= 20480, type=${usr_guid}, uuid=${usr_uuid}, name=\"usr-${architecture}\", attrs=\"GUID:60\"" "$output"
-# Second part, duplicate it with CopyBlocks=auto
+ # Then, create another image with CopyBlocks=auto
-cat >/tmp/testsuite-58-defs/esp.conf <<EOF
+ cat >"$defs/esp.conf" <<EOF
[Partition]
Type=esp
CopyBlocks=auto
EOF
-cat >/tmp/testsuite-58-defs/usr.conf <<EOF
+ cat >"$defs/usr.conf" <<EOF
[Partition]
Type=usr-${architecture}
ReadOnly=yes
CopyBlocks=auto
EOF
-cat >/tmp/testsuite-58-defs/root.conf <<EOF
+ cat >"$defs/root.conf" <<EOF
[Partition]
Type=root-${architecture}
CopyBlocks=auto
EOF
-systemd-repart --definitions=/tmp/testsuite-58-defs/ \
- --empty=create \
- --size=auto \
- --seed=750b6cd5c4ae4012a15e7be3c29e6a47 \
- --image=/var/tmp/testsuite-58.img \
- /var/tmp/testsuite-58.2.img
+ systemd-repart --definitions="$defs" \
+ --empty=create \
+ --size=auto \
+ --seed="$seed" \
+ --image="$imgs/zzz" \
+ "$imgs/yyy"
-cmp /var/tmp/testsuite-58.img /var/tmp/testsuite-58.2.img
+ cmp "$imgs/zzz" "$imgs/yyy"
+}
-rm /var/tmp/testsuite-58.img /var/tmp/testsuite-58.2.img /tmp/testsuite-58.dump
-rm -r /tmp/testsuite-58-defs/
+test_unaligned_partition() {
+ local defs imgs output
-# Third part: operate on an an image with unaligned partition, to see if that works.
+ defs="$(mktemp --directory "/tmp/test-repart.XXXXXXXXXX")"
+ imgs="$(mktemp --directory "/var/tmp/test-repart.XXXXXXXXXX")"
+ # shellcheck disable=SC2064
+ trap "rm -rf '$defs' '$imgs'" RETURN
-rm -f /var/tmp/testsuite-58.3.img /tmp/testsuite-58-3.dump
-mkdir -p /tmp/testsuite-58.3-defs/
+ # Operate on an image with unaligned partition.
-cat >/tmp/testsuite-58.3-defs/root.conf <<EOF
+ cat >"$defs/root.conf" <<EOF
[Partition]
Type=root-${architecture}
EOF
-truncate -s 10g /var/tmp/testsuite-58.3.img
-sfdisk /var/tmp/testsuite-58.3.img <<EOF
+ truncate -s 10g "$imgs/unaligned"
+ sfdisk "$imgs/unaligned" <<EOF
label: gpt
start=2048, size=69044
start=71092, size=3591848
EOF
-systemd-repart --definitions=/tmp/testsuite-58.3-defs/ \
- --seed=750b6cd5c4ae4012a15e7be3c29e6a47 \
- --dry-run=no \
- /var/tmp/testsuite-58.3.img
+ systemd-repart --definitions="$defs" \
+ --seed="$seed" \
+ --dry-run=no \
+ "$imgs/unaligned"
+
+ output=$(sfdisk --dump "$imgs/unaligned")
+
+ assert_in "$imgs/unaligned1 : start= 2048, size= 69044," "$output"
+ assert_in "$imgs/unaligned2 : start= 71092, size= 3591848," "$output"
+ assert_in "$imgs/unaligned3 : start= 3662944, size= 17308536, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\"" "$output"
+}
-sfdisk --dump /var/tmp/testsuite-58.3.img | tee /tmp/testsuite-58.3.dump
+test_issue_21817() {
+ local defs imgs output
-grep -qF '/var/tmp/testsuite-58.3.img1 : start= 2048, size= 69044,' /tmp/testsuite-58.3.dump
-grep -qF '/var/tmp/testsuite-58.3.img2 : start= 71092, size= 3591848,' /tmp/testsuite-58.3.dump
-grep -qixF "/var/tmp/testsuite-58.3.img3 : start= 3662944, size= 17308536, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\"" /tmp/testsuite-58.3.dump
+ # testcase for #21817
-rm /var/tmp/testsuite-58.3.img /tmp/testsuite-58.3.dump
-rm -r /tmp/testsuite-58.3-defs/
+ defs="$(mktemp --directory "/tmp/test-repart.XXXXXXXXXX")"
+ imgs="$(mktemp --directory "/var/tmp/test-repart.XXXXXXXXXX")"
+ # shellcheck disable=SC2064
+ trap "rm -rf '$defs' '$imgs'" RETURN
-# testcase for #21817
-mkdir -p /tmp/testsuite-58-issue-21817-defs/
-truncate -s 100m /var/tmp/testsuite-58-issue-21817.img
-sfdisk /var/tmp/testsuite-58-issue-21817.img <<EOF
+ cat >"$defs/test.conf" <<EOF
+[Partition]
+Type=root
+EOF
+
+ truncate -s 100m "$imgs/21817.img"
+ sfdisk "$imgs/21817.img" <<EOF
label: gpt
size=50M, type=${root_guid}
,
EOF
-cat >/tmp/testsuite-58-issue-21817-defs/test.conf <<EOF
-[Partition]
-Type=root
-EOF
-systemd-repart --pretty=yes --definitions /tmp/testsuite-58-issue-21817-defs/ --dry-run=no /var/tmp/testsuite-58-issue-21817.img
-sfdisk --dump /var/tmp/testsuite-58-issue-21817.img | tee /tmp/testsuite-58-issue-21817.dump
-grep -qiF "/var/tmp/testsuite-58-issue-21817.img1 : start= 2048, size= 102400, type=${root_guid}," /tmp/testsuite-58-issue-21817.dump
-# Accept both unpadded (pre-v2.38 util-linux) and padded (v2.38+ util-linux) sizes
-grep -qE "/var/tmp/testsuite-58-issue-21817.img2 : start= 104448, size= (100319| 98304)," /tmp/testsuite-58-issue-21817.dump
+ systemd-repart --pretty=yes \
+ --definitions "$imgs" \
+ --seed="$seed" \
+ --dry-run=no \
+ "$imgs/21817.img"
-rm /var/tmp/testsuite-58-issue-21817.img /tmp/testsuite-58-issue-21817.dump
-rm -r /tmp/testsuite-58-issue-21817-defs/
+ output=$(sfdisk --dump "$imgs/21817.img")
-testsector()
-{
- echo "Running sector test with sector size $1..."
+ assert_in "$imgs/21817.img1 : start= 2048, size= 102400, type=${root_guid}," "$output"
+ # Accept both unpadded (pre-v2.38 util-linux) and padded (v2.38+ util-linux) sizes
+ assert_in "$imgs/21817.img2 : start= 104448, size= (100319| 98304)," "$output"
+}
- mkdir -p /tmp/testsuite-58-sector
- cat > /tmp/testsuite-58-sector/a.conf <<EOF
+test_sector() {
+ local defs imgs output loop
+ local start size ratio
+ local sector="${1?}"
+
+ if systemd-detect-virt --quiet --container; then
+ echo "Skipping sector size tests in container."
+ return
+ fi
+
+ defs="$(mktemp --directory "/tmp/test-repart.XXXXXXXXXX")"
+ imgs="$(mktemp --directory "/var/tmp/test-repart.XXXXXXXXXX")"
+ # shellcheck disable=SC2064
+ trap "rm -rf '$defs' '$imgs'" RETURN
+
+ cat > "$defs/a.conf" <<EOF
[Partition]
Type=root
SizeMaxBytes=15M
SizeMinBytes=15M
EOF
- cat > /tmp/testsuite-58-sector/b.conf <<EOF
+ cat > "$defs/b.conf" <<EOF
[Partition]
Type=linux-generic
Weight=250
EOF
- cat > /tmp/testsuite-58-sector/c.conf <<EOF
+ cat > "$defs/c.conf" <<EOF
[Partition]
Type=linux-generic
Weight=750
EOF
- truncate -s 100m "/tmp/testsuite-58-sector-$1.img"
- LOOP=$(losetup -b "$1" -P --show -f "/tmp/testsuite-58-sector-$1.img" )
- udevadm wait --timeout 60 --settle "${LOOP:?}"
- systemd-repart --pretty=yes --definitions=/tmp/testsuite-58-sector/ --seed=750b6cd5c4ae4012a15e7be3c29e6a47 --empty=require --dry-run=no "$LOOP"
- rm -rf /tmp/testsuite-58-sector
- sfdisk --verify "$LOOP"
- sfdisk --dump "$LOOP"
- losetup -d "$LOOP"
-
- rm "/tmp/testsuite-58-sector-$1.img"
+ truncate -s 100m "$imgs/$sector.img"
+ loop=$(losetup -b "$sector" -P --show -f "$imgs/$sector.img" )
+ udevadm wait --timeout 60 --settle "${loop:?}"
+ systemd-repart --pretty=yes \
+ --definitions="$defs" \
+ --seed="$seed" \
+ --empty=require \
+ --dry-run=no \
+ "$loop"
+
+ sfdisk --verify "$loop"
+ output=$(sfdisk --dump "$loop")
+ losetup -d "$loop"
+
+ ratio=$(( sector / 512 ))
+ start=$(( 2048 / ratio ))
+ size=$(( 30720 / ratio ))
+ assert_in "${loop}p1 : start= *${start}, size= *${size}, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\"" "$output"
+ start=$(( start + size ))
+ size=$(( 42992 / ratio ))
+ assert_in "${loop}p2 : start= *${start}, size= *${size}, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=DF71F5E3-080A-4D16-824B-18591B881380, name=\"linux-generic\"" "$output"
+ start=$(( start + size ))
+ size=$(( 129000 / ratio ))
+ assert_in "${loop}p3 : start= *${start}, size= *${size}, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=DB081670-07AE-48CA-9F5E-813D5E40B976, name=\"linux-generic-2\"" "$output"
}
+test_basic
+test_dropin
+test_multiple_definitions
+test_copy_blocks
+test_unaligned_partition
+test_issue_21817
+
# Valid block sizes on the Linux block layer are >= 512 and <= PAGE_SIZE, and
# must be powers of 2. Which leaves exactly four different ones to test on
# typical hardware
-testsector 512
-testsector 1024
-testsector 2048
-testsector 4096
+test_sector 512
+test_sector 1024
+test_sector 2048
+test_sector 4096
echo OK >/testok
}
}
+test_issue_23796() {
+ local mount_path mount_mytmpfs
+
+ mount_path="$(command -v mount 2>/dev/null)"
+ mount_mytmpfs="${mount_path/\/bin/\/sbin}.mytmpfs"
+ cat >"$mount_mytmpfs" <<EOF
+#!/bin/bash
+sleep ".\$RANDOM"
+exec -- $mount_path -t tmpfs tmpfs "\$2"
+EOF
+ chmod +x "$mount_mytmpfs"
+
+ mkdir -p /run/systemd/system
+ cat >/run/systemd/system/tmp-hoge.mount <<EOF
+[Mount]
+What=mytmpfs
+Where=/tmp/hoge
+Type=mytmpfs
+EOF
+
+ # shellcheck disable=SC2064
+ trap "rm -f /run/systemd/system/tmp-hoge.mount '$mount_mytmpfs'" RETURN
+
+ for ((i = 0; i < 10; i++)); do
+ systemctl --no-block start tmp-hoge.mount
+ sleep ".$RANDOM"
+ systemctl daemon-reexec
+
+ sleep 1
+
+ if [[ "$(systemctl is-failed tmp-hoge.mount)" == "failed" ]] || \
+ journalctl -u tmp-hoge.mount -q --grep "but there is no mount"; then
+ exit 1
+ fi
+
+ systemctl stop tmp-hoge.mount
+ done
+}
+
: >/failed
systemd-analyze log-level debug
# test that handling of mount start jobs is delayed when /proc/self/mouninfo monitor is rate limited
test_issue_20329
+# test for reexecuting with background mount job
+test_issue_23796
+
systemd-analyze log-level info
touch /testok
# SPDX-License-Identifier: LGPL-2.1-or-later
[Unit]
-Description=TEST-62-RESTRICT-IFACES-empty-assigment
+Description=TEST-62-RESTRICT-IFACES-empty-assignment
[Service]
ExecStart=/bin/sh -c 'ping -c 1 -W 0.2 192.168.113.1'
ExecStart=/bin/sh -c 'ping -c 1 -W 0.2 192.168.113.5'
# SPDX-License-Identifier: LGPL-2.1-or-later
[Unit]
-Description=TEST-62-RESTRICT-IFACES-invert-assigment
+Description=TEST-62-RESTRICT-IFACES-invert-assignment
[Service]
ExecStart=/bin/sh -c '! ping -c 1 -W 0.2 192.168.113.1'
ExecStart=/bin/sh -c 'ping -c 1 -W 0.2 192.168.113.5'
fi
}
+restore_machine_info() {
+ if [[ -e /tmp/machine-info.bak ]]; then
+ mv /tmp/machine-info.bak /etc/machine-info
+ else
+ rm -f /etc/machine-info
+ fi
+}
+
+get_chassis() (
+ # shellcheck source=/dev/null
+ . /etc/machine-info
+
+ echo "$CHASSIS"
+)
+
+test_chassis() {
+ local i
+
+ if [[ -f /etc/machine-info ]]; then
+ cp /etc/machine-info /tmp/machine-info.bak
+ fi
+
+ trap restore_machine_info RETURN
+
+ # Invalid chassis type is refused
+ assert_rc 1 hostnamectl chassis hoge
+
+ # Valid chassis types
+ for i in vm container desktop laptop convertible server tablet handset watch embedded; do
+ hostnamectl chassis "$i"
+ assert_eq "$(hostnamectl chassis)" "$i"
+ assert_eq "$(get_chassis)" "$i"
+ done
+
+ systemctl stop systemd-hostnamed.service
+ rm -f /etc/machine-info
+
+ # fallback chassis type
+ if systemd-detect-virt --quiet --container; then
+ assert_eq "$(hostnamectl chassis)" container
+ elif systemd-detect-virt --quiet --vm; then
+ assert_eq "$(hostnamectl chassis)" vm
+ fi
+}
+
: >/failed
test_hostname
+test_chassis
touch /testok
rm /failed