From: Alberto Planas Date: Thu, 24 Apr 2025 13:02:27 +0000 (+0200) Subject: repart: add --append-fstab parameter X-Git-Tag: v258-rc1~567^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fc0cc3065c94a1e7d532195841b9423749e7f030;p=thirdparty%2Fsystemd.git repart: add --append-fstab parameter If --generate-fstab=PATH is used, there is the possibility that the fstab file already exists, making systemd-repart fail. This commit will add a new --append-fstab= parameter, that will read the file and merge it with the new generated content. Using the comments, the command can separate the automatic-generated section from the user-provided section, allowing for the next append the replacement only of the automatic-generated section, keeping the user one. Signed-off-by: Alberto Planas --- diff --git a/man/systemd-repart.xml b/man/systemd-repart.xml index 0c41ef38ab0..2f20a6fe43a 100644 --- a/man/systemd-repart.xml +++ b/man/systemd-repart.xml @@ -619,6 +619,30 @@ + + + + Takes one of no, auto or + replace. Controls how the generated + fstab5 + file by will behave in case that there is a previously + existing file. + + If no systemd-repart will complain and abort in + case that there is a file. This is the default behaviour. If replace + the file will be silently replaced with the new generated one. + + If auto systemd-repart will search in the pre-existing file + the section that belong to the automatically generated content and will replace it with the newer + generated content, and keep the user provided section if there is one. The generated section is + identified looking for the automatic content surrounded by + # Start section ↓ of automatically generated fstab by systemd-repart and + # End section ↑ of automatically generated fstab by systemd-repart. The content + that is before and after those comments are considered user provided, and kept in the new file. + + + + diff --git a/src/repart/repart.c b/src/repart/repart.c index be4d66101ac..c8cb286cb7a 100644 --- a/src/repart/repart.c +++ b/src/repart/repart.c @@ -111,6 +111,9 @@ #define APIVFS_TMP_DIRS_NULSTR "proc\0sys\0dev\0tmp\0run\0var/tmp\0" +#define AUTOMATIC_FSTAB_HEADER_START "# Start section ↓ of automatically generated fstab by systemd-repart" +#define AUTOMATIC_FSTAB_HEADER_END "# End section ↑ of automatically generated fstab by systemd-repart" + /* Note: When growing and placing new partitions we always align to 4K sector size. It's how newer hard disks * are designed, and if everything is aligned to that performance is best. And for older hard disks with 512B * sector size devices were generally assumed to have an even number of sectors, hence at the worst we'll @@ -135,6 +138,14 @@ typedef enum FilterPartitionType { _FILTER_PARTITIONS_INVALID = -EINVAL, } FilterPartitionsType; +typedef enum AppendMode { + APPEND_NO, + APPEND_AUTO, + APPEND_REPLACE, + _APPEND_MODE_MAX, + _APPEND_MODE_INVALID = -EINVAL, +} AppendMode; + static EmptyMode arg_empty = EMPTY_UNSET; static bool arg_dry_run = true; static char *arg_node = NULL; @@ -181,6 +192,7 @@ static int arg_offline = -1; static char **arg_copy_from = NULL; static char *arg_copy_source = NULL; static char *arg_make_ddi = NULL; +static AppendMode arg_append_fstab = APPEND_NO; static char *arg_generate_fstab = NULL; static char *arg_generate_crypttab = NULL; static Set *arg_verity_settings = NULL; @@ -455,6 +467,12 @@ static const char *empty_mode_table[_EMPTY_MODE_MAX] = { [EMPTY_CREATE] = "create", }; +static const char *append_mode_table[_APPEND_MODE_MAX] = { + [APPEND_NO] = "no", + [APPEND_AUTO] = "auto", + [APPEND_REPLACE] = "replace", +}; + static const char *encrypt_mode_table[_ENCRYPT_MODE_MAX] = { [ENCRYPT_OFF] = "off", [ENCRYPT_KEY_FILE] = "key-file", @@ -476,6 +494,7 @@ static const char *minimize_mode_table[_MINIMIZE_MODE_MAX] = { }; DEFINE_PRIVATE_STRING_TABLE_LOOKUP(empty_mode, EmptyMode); +DEFINE_PRIVATE_STRING_TABLE_LOOKUP(append_mode, AppendMode); DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(encrypt_mode, EncryptMode, ENCRYPT_KEY_FILE); DEFINE_PRIVATE_STRING_TABLE_LOOKUP(verity_mode, VerityMode); DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(minimize_mode, MinimizeMode, MINIMIZE_BEST); @@ -7495,7 +7514,7 @@ static bool need_fstab(const Context *context) { static int context_fstab(Context *context) { _cleanup_(unlink_and_freep) char *t = NULL; _cleanup_fclose_ FILE *f = NULL; - _cleanup_free_ char *path = NULL; + _cleanup_free_ char *path = NULL, *c = NULL; int r; assert(context); @@ -7517,7 +7536,7 @@ static int context_fstab(Context *context) { if (r < 0) return log_error_errno(r, "Failed to open temporary file for %s: %m", path); - fprintf(f, "# Automatically generated by systemd-repart\n\n"); + fputs(AUTOMATIC_FSTAB_HEADER_START "\n", f); LIST_FOREACH(partitions, p, context->partitions) { _cleanup_free_ char *what = NULL, *options = NULL; @@ -7552,7 +7571,38 @@ static int context_fstab(Context *context) { } } - r = flink_tmpfile(f, t, path, 0); + fputs(AUTOMATIC_FSTAB_HEADER_END "\n", f); + + switch (arg_append_fstab) { + case APPEND_AUTO: { + r = read_full_file(path, &c, NULL); + if (r < 0) { + if (r == -ENOENT) { + log_debug("File fstab not found in %s", path); + break; + } + return log_error_errno(r, "Failed to open %s: %m", path); + } + + const char *acs, *ace; + acs = find_line(c, AUTOMATIC_FSTAB_HEADER_START); + if (acs) { + fwrite(c, 1, acs - c, f); + ace = find_line_after(acs, AUTOMATIC_FSTAB_HEADER_END); + if (ace) + fputs(ace, f); + } else + fputs(c, f); + break; + } + case APPEND_NO: + case APPEND_REPLACE: + break; + default: + assert_not_reached(); + } + + r = flink_tmpfile(f, t, path, IN_SET(arg_append_fstab, APPEND_AUTO, APPEND_REPLACE) ? LINK_TMPFILE_REPLACE : 0); if (r < 0) return log_error_errno(r, "Failed to link temporary file to %s: %m", path); @@ -8174,6 +8224,8 @@ static int help(void) { " -C --make-ddi=confext Make a configuration extension DDI\n" " -P --make-ddi=portable Make a portable service DDI\n" "\n%3$sAuxiliary Resource Generation:%4$s\n" + " --append-fstab=MODE One of no, auto, replace; controls how to join the\n" + " content of a pre-existing fstab with the generated one\n" " --generate-fstab=PATH\n" " Write fstab configuration to the given path\n" " --generate-crypttab=PATH\n" @@ -8229,6 +8281,7 @@ static int parse_argv(int argc, char *argv[], X509 **ret_certificate, EVP_PKEY * ARG_OFFLINE, ARG_COPY_FROM, ARG_MAKE_DDI, + ARG_APPEND_FSTAB, ARG_GENERATE_FSTAB, ARG_GENERATE_CRYPTTAB, ARG_LIST_DEVICES, @@ -8275,6 +8328,7 @@ static int parse_argv(int argc, char *argv[], X509 **ret_certificate, EVP_PKEY * { "copy-from", required_argument, NULL, ARG_COPY_FROM }, { "copy-source", required_argument, NULL, 's' }, { "make-ddi", required_argument, NULL, ARG_MAKE_DDI }, + { "append-fstab", required_argument, NULL, ARG_APPEND_FSTAB }, { "generate-fstab", required_argument, NULL, ARG_GENERATE_FSTAB }, { "generate-crypttab", required_argument, NULL, ARG_GENERATE_CRYPTTAB }, { "list-devices", no_argument, NULL, ARG_LIST_DEVICES }, @@ -8658,6 +8712,17 @@ static int parse_argv(int argc, char *argv[], X509 **ret_certificate, EVP_PKEY * return r; break; + case ARG_APPEND_FSTAB: + if (isempty(optarg)) { + arg_append_fstab = APPEND_AUTO; + break; + } + + arg_append_fstab = append_mode_from_string(optarg); + if (arg_append_fstab < 0) + return log_error_errno(arg_append_fstab, "Failed to parse --append-fstab= parameter: %s", optarg); + break; + case ARG_GENERATE_FSTAB: r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_generate_fstab); if (r < 0) @@ -8850,6 +8915,9 @@ static int parse_argv(int argc, char *argv[], X509 **ret_certificate, EVP_PKEY * return log_error_errno(r, "Failed to load private key from %s: %m", arg_private_key); } + if (arg_append_fstab && !arg_generate_fstab) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No --generate-fstab= specified for --append-fstab=%s.", append_mode_to_string(arg_append_fstab)); + *ret_certificate = TAKE_PTR(certificate); *ret_private_key = TAKE_PTR(private_key); *ret_ui = TAKE_PTR(ui);