Compare commits
7 Commits
a43f8ef333
...
443f938d01
Author | SHA1 | Date |
---|---|---|
Michael Ferrari | 443f938d01 | |
Antonio Alvarez Feijoo | fb4c82b643 | |
Daan De Meyer | 4d9ccdc9ae | |
Antonio Alvarez Feijoo | bf39626d61 | |
Marius Hoch | ff831e7c50 | |
Michael Ferrari | 17393505b1 | |
Michael Ferrari | 17c53ebf20 |
|
@ -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
|
||||
|
||||
#########################################
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue