summaryrefslogtreecommitdiff
path: root/src/partition
diff options
context:
space:
mode:
authorDaan De Meyer <daan.j.demeyer@gmail.com>2023-02-20 20:30:44 +0100
committerDaan De Meyer <daan.j.demeyer@gmail.com>2023-02-22 12:44:36 +0100
commitb63bd125d4fb8ad1905d6c7dc4d87033ecf8148c (patch)
treeb49e4ae1f36c310a56a33579742294ab38bb5882 /src/partition
parent5ab863be51ba8a700c30f9d7b4f42ca82836263a (diff)
downloadsystemd-b63bd125d4fb8ad1905d6c7dc4d87033ecf8148c.tar.gz
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.
Diffstat (limited to 'src/partition')
-rw-r--r--src/partition/repart.c27
1 files changed, 15 insertions, 12 deletions
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;