repart: add 'fsverity' flag for CopyFiles= lines

We currently pass the CopyFlags that we use to populate the temporary
directory in the form of a constant at each of the copy_tree_at() call
sites.  De-duplicate that and move it into the `CopyFilesLine` struct,
initializing it from the parser.

Add our first non-constant flag: `fsverity=`.  This can be set to `off`
(the default) or `copy`, in which case we copy the fs-verity state from
the source files.

This arrangement is amenable to the introduction of more flags to
`CopyFiles=` lines, if we want to add them in the future.

Update the `repart.d(5)` manpage.

Closes #35352

Signed-off-by: Allison Karlitskaya <allison.karlitskaya@redhat.com>
This commit is contained in:
Allison Karlitskaya
2025-05-27 09:26:02 +02:00
parent 80f00d67ad
commit eef63efcc3
2 changed files with 74 additions and 15 deletions
+40 -3
View File
@@ -280,6 +280,7 @@ static PartitionEncryptedVolume* partition_encrypted_volume_free(PartitionEncryp
typedef struct CopyFiles {
char *source;
char *target;
CopyFlags flags;
} CopyFiles;
static void copy_files_free_many(CopyFiles *f, size_t n) {
@@ -1769,7 +1770,7 @@ static int config_parse_copy_files(
void *data,
void *userdata) {
_cleanup_free_ char *source = NULL, *buffer = NULL, *resolved_source = NULL, *resolved_target = NULL;
_cleanup_free_ char *source = NULL, *buffer = NULL, *resolved_source = NULL, *resolved_target = NULL, *options = NULL;
Partition *partition = ASSERT_PTR(data);
const char *p = rvalue, *target;
int r;
@@ -1792,9 +1793,38 @@ static int config_parse_copy_files(
else
target = buffer;
r = extract_first_word(&p, &options, ":", EXTRACT_CUNESCAPE|EXTRACT_DONT_COALESCE_SEPARATORS);
if (r < 0)
return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract options: %s", rvalue);
if (!isempty(p))
return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), "Too many arguments: %s", rvalue);
CopyFlags flags = COPY_REFLINK|COPY_HOLES|COPY_MERGE|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS|COPY_ALL_XATTRS|COPY_GRACEFUL_WARN|COPY_TRUNCATE|COPY_RESTORE_DIRECTORY_TIMESTAMPS;
for (const char *opts = options;;) {
_cleanup_free_ char *word = NULL;
const char *val;
r = extract_first_word(&opts, &word, ",", EXTRACT_DONT_COALESCE_SEPARATORS | EXTRACT_UNESCAPE_SEPARATORS);
if (r < 0)
return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CopyFile options: %s", options);
if (r == 0)
break;
if (isempty(word))
continue;
if ((val = startswith(word, "fsverity="))) {
if (streq(val, "copy"))
flags |= COPY_PRESERVE_FS_VERITY;
else if (streq(val, "off"))
flags &= ~COPY_PRESERVE_FS_VERITY;
else
log_syntax(unit, LOG_WARNING, filename, line, 0, "fsverity= expects either 'off' or 'copy'.");
} else
log_syntax(unit, LOG_WARNING, filename, line, 0, "Encountered unknown option '%s', ignoring.", word);
}
r = specifier_printf(source, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, NULL, &resolved_source);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
@@ -1823,6 +1853,7 @@ static int config_parse_copy_files(
partition->copy_files[partition->n_copy_files++] = (CopyFiles) {
.source = TAKE_PTR(resolved_source),
.target = TAKE_PTR(resolved_target),
.flags = flags,
};
return 0;
@@ -2398,6 +2429,12 @@ static MakeFileSystemFlags partition_mkfs_flags(const Partition *p) {
if (streq(p->format, "erofs") && !DEBUG_LOGGING)
flags |= MKFS_QUIET;
FOREACH_ARRAY(cf, p->copy_files, p->n_copy_files)
if (cf->flags & COPY_PRESERVE_FS_VERITY) {
flags |= MKFS_FS_VERITY;
break;
}
return flags;
}
@@ -5783,14 +5820,14 @@ static int do_copy_files(Context *context, Partition *p, const char *root) {
sfd, ".",
pfd, fn,
UID_INVALID, GID_INVALID,
COPY_REFLINK|COPY_HOLES|COPY_MERGE|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS|COPY_ALL_XATTRS|COPY_GRACEFUL_WARN|COPY_TRUNCATE|COPY_RESTORE_DIRECTORY_TIMESTAMPS,
line->flags,
denylist, subvolumes_by_source_inode);
} else
r = copy_tree_at(
sfd, ".",
tfd, ".",
UID_INVALID, GID_INVALID,
COPY_REFLINK|COPY_HOLES|COPY_MERGE|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS|COPY_ALL_XATTRS|COPY_GRACEFUL_WARN|COPY_TRUNCATE|COPY_RESTORE_DIRECTORY_TIMESTAMPS,
line->flags,
denylist, subvolumes_by_source_inode);
if (r < 0)
return log_error_errno(r, "Failed to copy '%s%s' to '%s%s': %m",