sysupdate: Allow patterns to match path with directories
`MatchPattern` for regular-file and directory as target can now match subdirectories This is useful to install files for examples in `.extra.d` directories: ``` [Target] Type=regular-file Path=/EFI/Linux PathRelativeTo=boot MatchPattern=gnomeos_@v.efi.extra.d/apparmor.addon.efi ``` The if the directories in the path do not exist, they will be created. Whereas the part in `Path` is not created.
This commit is contained in:
@@ -69,30 +69,16 @@ static int resource_add_instance(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int resource_load_from_directory(
|
||||
static int resource_load_from_directory_recursive(
|
||||
Resource *rr,
|
||||
DIR* d,
|
||||
const char* relpath,
|
||||
mode_t m) {
|
||||
|
||||
_cleanup_closedir_ DIR *d = NULL;
|
||||
int r;
|
||||
|
||||
assert(rr);
|
||||
assert(IN_SET(rr->type, RESOURCE_TAR, RESOURCE_REGULAR_FILE, RESOURCE_DIRECTORY, RESOURCE_SUBVOLUME));
|
||||
assert(IN_SET(m, S_IFREG, S_IFDIR));
|
||||
|
||||
d = opendir(rr->path);
|
||||
if (!d) {
|
||||
if (errno == ENOENT) {
|
||||
log_debug("Directory %s does not exist, not loading any resources.", rr->path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return log_error_errno(errno, "Failed to open directory '%s': %m", rr->path);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
_cleanup_(instance_metadata_destroy) InstanceMetadata extracted_fields = INSTANCE_METADATA_NULL;
|
||||
_cleanup_free_ char *joined = NULL;
|
||||
_cleanup_free_ char *joined = NULL, *rel_joined = NULL;
|
||||
Instance *instance;
|
||||
struct dirent *de;
|
||||
struct stat st;
|
||||
@@ -111,7 +97,7 @@ static int resource_load_from_directory(
|
||||
break;
|
||||
|
||||
case DT_DIR:
|
||||
if (m != S_IFDIR)
|
||||
if (!IN_SET(m, S_IFDIR, S_IFREG))
|
||||
continue;
|
||||
|
||||
break;
|
||||
@@ -132,16 +118,36 @@ static int resource_load_from_directory(
|
||||
return log_error_errno(errno, "Failed to stat %s/%s: %m", rr->path, de->d_name);
|
||||
}
|
||||
|
||||
if ((st.st_mode & S_IFMT) != m)
|
||||
if (!(S_ISDIR(st.st_mode) && S_ISREG(m)) && ((st.st_mode & S_IFMT) != m))
|
||||
continue;
|
||||
|
||||
r = pattern_match_many(rr->patterns, de->d_name, &extracted_fields);
|
||||
if (r < 0)
|
||||
rel_joined = path_join(relpath, de->d_name);
|
||||
if (!rel_joined)
|
||||
return log_oom();
|
||||
|
||||
r = pattern_match_many(rr->patterns, rel_joined, &extracted_fields);
|
||||
if (r == PATTERN_MATCH_RETRY) {
|
||||
_cleanup_closedir_ DIR *subdir = NULL;
|
||||
|
||||
subdir = xopendirat(dirfd(d), rel_joined, 0);
|
||||
if (!subdir)
|
||||
continue;
|
||||
|
||||
r = resource_load_from_directory_recursive(rr, subdir, rel_joined, m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
continue;
|
||||
}
|
||||
else if (r < 0)
|
||||
return log_error_errno(r, "Failed to match pattern: %m");
|
||||
if (r == 0)
|
||||
else if (r == PATTERN_MATCH_NO)
|
||||
continue;
|
||||
|
||||
joined = path_join(rr->path, de->d_name);
|
||||
if (de->d_type == DT_DIR && m != S_IFDIR)
|
||||
continue;
|
||||
|
||||
joined = path_join(rr->path, rel_joined);
|
||||
if (!joined)
|
||||
return log_oom();
|
||||
|
||||
@@ -160,6 +166,28 @@ static int resource_load_from_directory(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int resource_load_from_directory(
|
||||
Resource *rr,
|
||||
mode_t m) {
|
||||
_cleanup_closedir_ DIR *d = NULL;
|
||||
|
||||
assert(rr);
|
||||
assert(IN_SET(rr->type, RESOURCE_TAR, RESOURCE_REGULAR_FILE, RESOURCE_DIRECTORY, RESOURCE_SUBVOLUME));
|
||||
assert(IN_SET(m, S_IFREG, S_IFDIR));
|
||||
|
||||
d = opendir(rr->path);
|
||||
if (!d) {
|
||||
if (errno == ENOENT) {
|
||||
log_debug_errno(errno, "Directory %s does not exist, not loading any resources: %m", rr->path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return log_error_errno(errno, "Failed to open directory '%s': %m", rr->path);
|
||||
}
|
||||
|
||||
return resource_load_from_directory_recursive(rr, d, NULL, m);
|
||||
}
|
||||
|
||||
static int resource_load_from_blockdev(Resource *rr) {
|
||||
_cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL;
|
||||
_cleanup_(fdisk_unref_tablep) struct fdisk_table *t = NULL;
|
||||
@@ -204,7 +232,7 @@ static int resource_load_from_blockdev(Resource *rr) {
|
||||
r = pattern_match_many(rr->patterns, pinfo.label, &extracted_fields);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to match pattern: %m");
|
||||
if (r == 0)
|
||||
if (IN_SET(r, PATTERN_MATCH_NO, PATTERN_MATCH_RETRY))
|
||||
continue;
|
||||
|
||||
r = resource_add_instance(rr, pinfo.device, &extracted_fields, &instance);
|
||||
@@ -402,7 +430,7 @@ static int resource_load_from_web(
|
||||
r = pattern_match_many(rr->patterns, fn, &extracted_fields);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to match pattern: %m");
|
||||
if (r > 0) {
|
||||
if (r == PATTERN_MATCH_YES) {
|
||||
_cleanup_free_ char *path = NULL;
|
||||
|
||||
r = import_url_append_component(rr->path, fn, &path);
|
||||
|
||||
Reference in New Issue
Block a user