From b63bd125d4fb8ad1905d6c7dc4d87033ecf8148c Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Mon, 20 Feb 2023 20:30:44 +0100 Subject: copy: Support both inode exclusion and contents exclusion In some cases, we want to exclude a directory's contents but not the directory itself. In other cases, we want to exclude a directory and its contents. Let's extend the denylist logic in copy.h to support both by changing the denylist from a set to hashmap so we can store the deny type as the value. We also modify the repart ExcludeFiles= option to make use of this. If a directory to exclude ends with a "/", we'll only exclude its contents. Otherwise, we'll exclude the full directory. --- src/partition/repart.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'src/partition') diff --git a/src/partition/repart.c b/src/partition/repart.c index 9d5c60977f..786f7d8da5 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -3787,7 +3787,7 @@ static int context_copy_blocks(Context *context) { return 0; } -static int do_copy_files(Partition *p, const char *root, const Set *denylist) { +static int do_copy_files(Partition *p, const char *root, Hashmap *denylist) { int r; assert(p); @@ -3932,7 +3932,7 @@ static bool partition_needs_populate(Partition *p) { return !strv_isempty(p->copy_files) || !strv_isempty(p->make_directories); } -static int partition_populate_directory(Partition *p, const Set *denylist, char **ret) { +static int partition_populate_directory(Partition *p, Hashmap *denylist, char **ret) { _cleanup_(rm_rf_physical_and_freep) char *root = NULL; const char *vt; int r; @@ -3963,7 +3963,7 @@ static int partition_populate_directory(Partition *p, const Set *denylist, char return 0; } -static int partition_populate_filesystem(Partition *p, const char *node, const Set *denylist) { +static int partition_populate_filesystem(Partition *p, const char *node, Hashmap *denylist) { int r; assert(p); @@ -4010,7 +4010,7 @@ static int partition_populate_filesystem(Partition *p, const char *node, const S return 0; } -static int add_exclude_path(const char *path, Set **denylist) { +static int add_exclude_path(const char *path, Hashmap **denylist, DenyType type) { _cleanup_free_ struct stat *st = NULL; int r; @@ -4028,10 +4028,10 @@ static int add_exclude_path(const char *path, Set **denylist) { return log_error_errno(r, "Failed to stat source file '%s%s': %m", strempty(arg_root), path); - if (set_contains(*denylist, st)) + if (hashmap_contains(*denylist, st)) return 0; - if (set_ensure_put(denylist, &inode_hash_ops, st) < 0) + if (hashmap_ensure_put(denylist, &inode_hash_ops, st, INT_TO_PTR(type)) < 0) return log_oom(); TAKE_PTR(st); @@ -4039,8 +4039,8 @@ static int add_exclude_path(const char *path, Set **denylist) { return 0; } -static int make_copy_files_denylist(Context *context, const Partition *p, Set **ret) { - _cleanup_set_free_ Set *denylist = NULL; +static int make_copy_files_denylist(Context *context, const Partition *p, Hashmap **ret) { + _cleanup_hashmap_free_ Hashmap *denylist = NULL; int r; assert(context); @@ -4048,6 +4048,9 @@ static int make_copy_files_denylist(Context *context, const Partition *p, Set ** assert(ret); LIST_FOREACH(partitions, q, context->partitions) { + if (p == q) + continue; + const char *sources = gpt_partition_type_mountpoint_nulstr(q->type); if (!sources) continue; @@ -4056,14 +4059,14 @@ static int make_copy_files_denylist(Context *context, const Partition *p, Set ** /* Exclude the children of partition mount points so that the nested partition mount * point itself still ends up in the upper partition. */ - r = add_exclude_path(s, &denylist); + r = add_exclude_path(s, &denylist, DENY_CONTENTS); if (r < 0) return r; } } STRV_FOREACH(e, p->exclude_files) { - r = add_exclude_path(*e, &denylist); + r = add_exclude_path(*e, &denylist, endswith(*e, "/") ? DENY_CONTENTS : DENY_INODE); if (r < 0) return r; } @@ -4080,7 +4083,7 @@ static int context_mkfs(Context *context) { /* Make a file system */ LIST_FOREACH(partitions, p, context->partitions) { - _cleanup_set_free_ Set *denylist = NULL; + _cleanup_hashmap_free_ Hashmap *denylist = NULL; _cleanup_(rm_rf_physical_and_freep) char *root = NULL; _cleanup_(partition_target_freep) PartitionTarget *t = NULL; @@ -5400,7 +5403,7 @@ static int context_minimize(Context *context) { return log_error_errno(r, "Could not determine temporary directory: %m"); LIST_FOREACH(partitions, p, context->partitions) { - _cleanup_set_free_ Set *denylist = NULL; + _cleanup_hashmap_free_ Hashmap *denylist = NULL; _cleanup_(rm_rf_physical_and_freep) char *root = NULL; _cleanup_(unlink_and_freep) char *temp = NULL; _cleanup_(loop_device_unrefp) LoopDevice *d = NULL; -- cgit v1.2.1