<xi:include href="version-info.xml" xpointer="v255"/></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--append-fstab=</option></term>
+
+ <listitem><para>Takes one of <literal>no</literal>, <literal>auto</literal> or
+ <literal>replace</literal>. Controls how the generated
+ <citerefentry project='man-pages'><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ file by <option>--generate-fstab=</option> will behave in case that there is a previously
+ existing file.</para>
+
+ <para>If <literal>no</literal> <command>systemd-repart</command> will complain and abort in
+ case that there is a file. This is the default behaviour. If <literal>replace</literal>
+ the file will be silently replaced with the new generated one.</para>
+
+ <para>If <literal>auto</literal> <command>systemd-repart</command> 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
+ <literal># Start section ↓ of automatically generated fstab by systemd-repart</literal> and
+ <literal># End section ↑ of automatically generated fstab by systemd-repart</literal>. The content
+ that is before and after those comments are considered user provided, and kept in the new file.</para>
+
+ <xi:include href="version-info.xml" xpointer="v258"/></listitem>
+ </varlistentry>
+
<varlistentry>
<term><option>--generate-fstab=<replaceable>PATH</replaceable></option></term>
#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
_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;
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;
[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",
};
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);
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);
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;
}
}
- 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);
" -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"
ARG_OFFLINE,
ARG_COPY_FROM,
ARG_MAKE_DDI,
+ ARG_APPEND_FSTAB,
ARG_GENERATE_FSTAB,
ARG_GENERATE_CRYPTTAB,
ARG_LIST_DEVICES,
{ "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 },
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)
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);