Compare commits

...

7 Commits

Author SHA1 Message Date
Michael Ferrari 443f938d01
Merge 17393505b1 into fb4c82b643 2024-09-18 17:01:19 +01:00
Antonio Alvarez Feijoo fb4c82b643 nsresourced: fix build without libbpf
```
In file included from ../src/nsresourced/nsresourced-manager.c:9:
../src/shared/bpf-link.h:5:10: fatal error: bpf/libbpf.h: No such file or directory
    5 | #include <bpf/libbpf.h>
      |          ^~~~~~~~~~~~~~
```

Follow-up for 46718d344f
2024-09-18 16:44:12 +02:00
Daan De Meyer 4d9ccdc9ae repart: Drop unprivileged subvolumes logic for btrfs
The functionality was explicitly not included in 6.11 for some
unknown reason so drop the logic from systemd-repart as well so
we don't release v257 with it included.
2024-09-18 16:41:42 +02:00
Antonio Alvarez Feijoo bf39626d61 man/repart: use <varname> instead of <variable>
Otherwise, `<variable>$BOOT</variable>` is rendered:

```
[2548/2992] Generating man/repart.d.5 with a custom command
Element variable in namespace '' encountered in para, but no template matches.
Element variable in namespace '' encountered in para, but no template matches.
```
2024-09-18 16:03:56 +02:00
Marius Hoch ff831e7c50 hwdb: Add accel orientation quirk for the IdeaPad Duet 3 10IGL5-LTE
Signed-off-by: Marius Hoch <mail@mariushoch.de>
2024-09-18 20:30:11 +09:00
Michael Ferrari 17393505b1
firstboot: add similar input suggestion
This uses the same logic as similar verb suggestion for command line
utilities. Try to be helpful when the user entered something invalid
instead of just showing the prompt again.
2024-09-14 02:01:52 +02:00
Michael Ferrari 17c53ebf20
firstboot: use default value when empty
This results in the "default" pathway having sane options set instead
of skipping the question, as it was explicitly requested to prompt the
user. Entering `-` allows skipping a prompt without writing any value.
2024-09-14 01:35:41 +02:00
7 changed files with 92 additions and 79 deletions

View File

@ -760,8 +760,9 @@ sensor:modalias:i2c:bmc150_accel:dmi:*:svnLENOVO:*:pvrLenovoYoga300-11IBR:*
sensor:modalias:acpi:ACCL0001*:dmi:*:svnLENOVO:pn60072:pvr851*:*
ACCEL_MOUNT_MATRIX=0, 1, 0; -1, 0, 0; 0, 0, 1
# IdeaPad Duet 3 10IGL5 (82AT)
# IdeaPad Duet 3 10IGL5 (82AT) and 10IGL5-LTE (82HK)
sensor:modalias:acpi:SMO8B30*:dmi:*:svnLENOVO*:pn82AT:*
sensor:modalias:acpi:SMO8B30*:dmi:*:svnLENOVO*:pn82HK:*
ACCEL_MOUNT_MATRIX=0, 1, 0; -1, 0, 0; 0, 0, 1
#########################################

View File

@ -922,9 +922,9 @@
target for some other supplement definition. A target cannot have more than one supplement partition
associated with it.</para>
<para>For example, distributions can use this to implement <variable>$BOOT</variable> as defined in
<para>For example, distributions can use this to implement <varname>$BOOT</varname> as defined in
the <ulink url="https://uapi-group.org/specifications/specs/boot_loader_specification/">Boot Loader
Specification</ulink>. Distributions may prefer to use the ESP as <variable>$BOOT</variable> whenever
Specification</ulink>. Distributions may prefer to use the ESP as <varname>$BOOT</varname> whenever
possible, but to adhere to the spec XBOOTLDR must sometimes be used instead. So, they should create
two definitions: the first defining an ESP big enough to hold just the bootloader, and a second for
the XBOOTLDR that's sufficiently large to hold kernels and configured as a supplement for the ESP.

View File

@ -66,6 +66,33 @@ char* strv_find_startswith(char * const *l, const char *name) {
return NULL;
}
char* strv_find_closest_by_levenshtein(char * const *l, const char *name) {
ssize_t best_distance = SSIZE_MAX;
char *best = NULL;
assert(name);
STRV_FOREACH(i, l) {
ssize_t distance;
distance = strlevenshtein(*i, name);
if (distance < 0) {
log_debug_errno(distance, "Failed to determine Levenshtein distance between %s and %s: %m", *i, name);
return NULL;
}
if (distance > 5) /* If the distance is just too far off, don't make a bad suggestion */
continue;
if (distance < best_distance) {
best_distance = distance;
best = *i;
}
}
return best;
}
char* strv_find_first_field(char * const *needles, char * const *haystack) {
STRV_FOREACH(k, needles) {
char *value = strv_env_pairs_get((char **)haystack, *k);

View File

@ -17,6 +17,7 @@ char* strv_find(char * const *l, const char *name) _pure_;
char* strv_find_case(char * const *l, const char *name) _pure_;
char* strv_find_prefix(char * const *l, const char *name) _pure_;
char* strv_find_startswith(char * const *l, const char *name) _pure_;
char* strv_find_closest_by_levenshtein(char * const *l, const char *name) _pure_;
/* Given two vectors, the first a list of keys and the second a list of key-value pairs, returns the value
* of the first key from the first vector that is found in the second vector. */
char* strv_find_first_field(char * const *needles, char * const *haystack) _pure_;

View File

@ -178,24 +178,31 @@ static int show_menu(char **x, unsigned n_columns, unsigned width, unsigned perc
return 0;
}
static int prompt_loop(const char *text, char **l, unsigned percentage, bool (*is_valid)(const char *name), char **ret) {
static int prompt_loop(const char *text, char **l, const char* fallback, unsigned percentage, bool (*is_valid)(const char *name), char **ret) {
int r;
assert(text);
assert(is_valid);
assert(is_valid(fallback));
assert(ret);
for (;;) {
_cleanup_free_ char *p = NULL;
char *best_match = NULL;
unsigned u;
r = ask_string(&p, "%s %s (empty to skip, \"list\" to list options): ",
special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET), text);
r = ask_string(&p, "%s %s (empty to default to \"%s\", \"-\" to skip, \"list\" to list options): ",
special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET), text, fallback);
if (r < 0)
return log_error_errno(r, "Failed to query user: %m");
if (isempty(p)) {
log_info("No data entered, skipping.");
log_info("No data entered, using default.");
return free_and_strdup_warn(ret, fallback);
}
if (streq(p, "-")) {
log_info("Skip requested, continuing.");
return 0;
}
@ -219,12 +226,20 @@ static int prompt_loop(const char *text, char **l, unsigned percentage, bool (*i
return free_and_strdup_warn(ret, l[u-1]);
}
if (!is_valid(p)) {
log_error("Entered data invalid.");
continue;
}
if (is_valid(p))
return free_and_replace(*ret, p);
return free_and_replace(*ret, p);
/* Be helperful to the user, and give a hint what the user might have wanted to
* type. We search with two mechanisms: a simple prefix match and if that didn't
* yield results , a Levenshtein word distance based match. */
best_match = strv_find_prefix(l, p);
if (!best_match)
best_match = strv_find_closest_by_levenshtein(l, p);
if (best_match)
log_error("Invalid data '%s', did you mean '%s'?", p, best_match);
else
log_error("Invalid data '%s'.", p);
}
}
@ -365,7 +380,7 @@ static int prompt_locale(int rfd) {
print_welcome(rfd);
r = prompt_loop("Please enter system locale name or number",
locales, 60, is_valid, &arg_locale);
locales, SYSTEMD_DEFAULT_LOCALE, 60, is_valid, &arg_locale);
if (r < 0)
return r;
@ -373,7 +388,7 @@ static int prompt_locale(int rfd) {
return 0;
r = prompt_loop("Please enter system message locale name or number",
locales, 60, is_valid, &arg_locale_messages);
locales, arg_locale, 60, is_valid, &arg_locale_messages);
if (r < 0)
return r;
@ -488,7 +503,7 @@ static int prompt_keymap(int rfd) {
print_welcome(rfd);
return prompt_loop("Please enter system keymap name or number",
kmaps, 60, determine_keymap_validity_func(rfd), &arg_keymap);
kmaps, SYSTEMD_DEFAULT_KEYMAP, 60, determine_keymap_validity_func(rfd), &arg_keymap);
}
static int process_keymap(int rfd) {
@ -578,7 +593,7 @@ static int prompt_timezone(int rfd) {
print_welcome(rfd);
r = prompt_loop("Please enter timezone name or number",
zones, 30, timezone_is_valid_log_debug, &arg_timezone);
zones, "UTC", 30, timezone_is_valid_log_debug, &arg_timezone);
if (r < 0)
return r;
@ -660,14 +675,24 @@ static int prompt_hostname(int rfd) {
putchar('\n');
for (;;) {
_cleanup_free_ char *h = NULL;
_cleanup_free_ char *h = NULL, *fallback = NULL;
r = ask_string(&h, "%s Please enter hostname for new system (empty to skip): ", special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET));
fallback = get_default_hostname();
if (!fallback)
return log_oom();
r = ask_string(&h, "%s Please enter hostname for new system (empty to default to \"%s\", \"-\" to skip): ",
special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET), fallback);
if (r < 0)
return log_error_errno(r, "Failed to query hostname: %m");
if (isempty(h)) {
log_info("No hostname entered, skipping.");
log_info("No hostname entered, using default.");
return free_and_strdup_warn(&arg_hostname, fallback);
}
if (streq(h, "-")) {
log_info("Skip requested, continuing.");
break;
}
@ -869,12 +894,18 @@ static int prompt_root_shell(int rfd) {
for (;;) {
_cleanup_free_ char *s = NULL;
r = ask_string(&s, "%s Please enter root shell for new system (empty to skip): ", special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET));
r = ask_string(&s, "%s Please enter root shell for new system (empty to default to \"%s\", \"-\" to skip): ",
special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET), DEFAULT_USER_SHELL);
if (r < 0)
return log_error_errno(r, "Failed to query root shell: %m");
if (isempty(s)) {
log_info("No shell entered, skipping.");
log_info("No shell entered, using default.");
return free_and_strdup_warn(&arg_root_shell, DEFAULT_USER_SHELL);
}
if (streq(s, "-")) {
log_info("Skip requested, continuing.");
break;
}

View File

@ -6,7 +6,9 @@
#include "sd-daemon.h"
#include "bpf-dlopen.h"
#if HAVE_VMLINUX_H
#include "bpf-link.h"
#endif
#include "build-path.h"
#include "common-signal.h"
#include "env-util.h"

View File

@ -304,19 +304,6 @@ static SubvolumeFlags subvolume_flags_from_string(const char *s) {
return flags;
}
static char* subvolume_flags_to_string(SubvolumeFlags flags) {
const char *l[CONST_LOG2U(_SUBVOLUME_FLAGS_MASK + 1) + 1]; /* one string per known flag at most */
size_t m = 0;
if (FLAGS_SET(flags, SUBVOLUME_RO))
l[m++] = "ro";
assert(m < ELEMENTSOF(l));
l[m] = NULL;
return strv_join((char**) l, ",");
}
typedef struct Subvolume {
char *path;
SubvolumeFlags flags;
@ -2438,6 +2425,14 @@ static int partition_read_definition(Partition *p, const char *path, const char
"SizeMinBytes=/SizeMaxBytes= cannot be used with Verity=%s.",
verity_mode_to_string(p->verity));
if (!ordered_hashmap_isempty(p->subvolumes) && arg_offline > 0)
return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EOPNOTSUPP),
"Subvolumes= cannot be used with --offline=yes.");
if (p->default_subvolume && arg_offline > 0)
return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EOPNOTSUPP),
"DefaultSubvolume= cannot be used with --offline=yes.");
if (p->default_subvolume && !ordered_hashmap_contains(p->subvolumes, p->default_subvolume))
return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
"DefaultSubvolume= must be one of the paths in Subvolumes=.");
@ -4286,7 +4281,7 @@ static int prepare_temporary_file(Context *context, PartitionTarget *t, uint64_t
static bool loop_device_error_is_fatal(const Partition *p, int r) {
assert(p);
return arg_offline == 0 || (r != -ENOENT && !ERRNO_IS_PRIVILEGE(r));
return arg_offline == 0 || (r != -ENOENT && !ERRNO_IS_PRIVILEGE(r)) || !ordered_hashmap_isempty(p->subvolumes) || p->default_subvolume;
}
static int partition_target_prepare(
@ -5793,38 +5788,6 @@ static int partition_populate_filesystem(Context *context, Partition *p, const c
return 0;
}
static int append_btrfs_subvols(char ***l, OrderedHashmap *subvolumes, const char *default_subvolume) {
Subvolume *subvolume;
int r;
assert(l);
ORDERED_HASHMAP_FOREACH(subvolume, subvolumes) {
_cleanup_free_ char *s = NULL, *f = NULL;
s = strdup(subvolume->path);
if (!s)
return log_oom();
f = subvolume_flags_to_string(subvolume->flags);
if (!f)
return log_oom();
if (streq_ptr(subvolume->path, default_subvolume) &&
!strextend_with_separator(&f, ",", "default"))
return log_oom();
if (!isempty(f) && !strextend_with_separator(&s, ":", f))
return log_oom();
r = strv_extend_many(l, "--subvol", s);
if (r < 0)
return log_oom();
}
return 0;
}
static int finalize_extra_mkfs_options(const Partition *p, const char *root, char ***ret) {
_cleanup_strv_free_ char **sv = NULL;
int r;
@ -5838,18 +5801,6 @@ static int finalize_extra_mkfs_options(const Partition *p, const char *root, cha
"Failed to determine mkfs command line options for '%s': %m",
p->format);
if (partition_needs_populate(p) && root && streq(p->format, "btrfs")) {
r = append_btrfs_subvols(&sv, p->subvolumes, p->default_subvolume);
if (r < 0)
return r;
if (p->suppressing) {
r = append_btrfs_subvols(&sv, p->suppressing->subvolumes, NULL);
if (r < 0)
return r;
}
}
*ret = TAKE_PTR(sv);
return 0;
}