return 1; /* received reply */
}
-static int search_rules_file_in_conf_dirs(const char *s, const char *root, char ***files) {
- _cleanup_free_ char *filename = NULL;
+static int search_rules_file_in_conf_dirs(const char *s, const char *root, ConfFile ***files, size_t *n_files) {
+ _cleanup_free_ char *with_suffix = NULL;
int r;
assert(s);
+ assert(files);
+ assert(n_files);
- if (!endswith(s, ".rules"))
- filename = strjoin(s, ".rules");
- else
- filename = strdup(s);
- if (!filename)
- return log_oom();
+ if (isempty(s) || is_path(s))
+ return 0;
+
+ if (!endswith(s, ".rules")) {
+ with_suffix = strjoin(s, ".rules");
+ if (!with_suffix)
+ return log_oom();
+
+ s = with_suffix;
+ }
- if (!filename_is_valid(filename))
+ if (!filename_is_valid(s))
return 0;
STRV_FOREACH(p, CONF_PATHS_STRV("udev/rules.d")) {
- _cleanup_free_ char *path = NULL, *resolved = NULL;
- path = path_join(*p, filename);
+ _cleanup_free_ char *path = path_join(*p, s);
if (!path)
return log_oom();
- r = chase(path, root, CHASE_PREFIX_ROOT | CHASE_MUST_BE_REGULAR, &resolved, /* ret_fd = */ NULL);
+ _cleanup_(conf_file_freep) ConfFile *c = NULL;
+ r = conf_file_new(path, root, CHASE_MUST_BE_REGULAR, &c);
if (r == -ENOENT)
continue;
if (r < 0)
return log_error_errno(r, "Failed to chase \"%s\": %m", path);
- r = strv_consume(files, TAKE_PTR(resolved));
- if (r < 0)
+ if (!GREEDY_REALLOC_APPEND(*files, *n_files, &c, 1))
return log_oom();
+ TAKE_PTR(c);
return 1; /* found */
}
return 0;
}
-static int search_rules_file(const char *s, const char *root, char ***files) {
+static int search_rules_file(const char *s, const char *root, ConfFile ***files, size_t *n_files) {
int r;
assert(s);
assert(files);
+ assert(n_files);
/* If the input is a file name (e.g. 99-systemd.rules), then try to find it in udev/rules.d directories. */
- r = search_rules_file_in_conf_dirs(s, root, files);
+ r = search_rules_file_in_conf_dirs(s, root, files, n_files);
if (r != 0)
return r;
/* If not found, or if it is a path, then chase it. */
- struct stat st;
- _cleanup_free_ char *resolved = NULL;
- r = chase_and_stat(s, root, CHASE_PREFIX_ROOT, &resolved, &st);
- if (r < 0)
- return log_error_errno(r, "Failed to chase \"%s\": %m", s);
-
- r = stat_verify_regular(&st);
- if (r == -EISDIR) {
- _cleanup_strv_free_ char **files_in_dir = NULL;
-
- r = conf_files_list_strv(&files_in_dir, ".rules", root, 0, (const char* const*) STRV_MAKE_CONST(s));
- if (r < 0)
- return log_error_errno(r, "Failed to enumerate rules files in '%s': %m", resolved);
-
- r = strv_extend_strv_consume(files, TAKE_PTR(files_in_dir), /* filter_duplicates = */ false);
- if (r < 0)
+ _cleanup_(conf_file_freep) ConfFile *c = NULL;
+ r = conf_file_new(s, root, CHASE_MUST_BE_REGULAR, &c);
+ if (r >= 0) {
+ if (!GREEDY_REALLOC_APPEND(*files, *n_files, &c, 1))
return log_oom();
+ TAKE_PTR(c);
return 0;
}
- if (r < 0)
- return log_error_errno(r, "'%s' is neither a regular file nor a directory: %m", resolved);
- r = strv_consume(files, TAKE_PTR(resolved));
+ if (r != -EISDIR)
+ return log_error_errno(r, "Failed to chase \"%s\": %m", s);
+
+ /* If a directory is specified, then find all rules file in the directory. */
+ ConfFile **f = NULL;
+ size_t n = 0;
+
+ CLEANUP_ARRAY(f, n, conf_file_free_many);
+
+ r = conf_files_list_strv_full(".rules", root, CONF_FILES_REGULAR, (const char* const*) STRV_MAKE_CONST(s), &f, &n);
if (r < 0)
+ return log_error_errno(r, "Failed to enumerate rules files in '%s': %m", s);
+
+ if (!GREEDY_REALLOC_APPEND(*files, *n_files, f, n))
return log_oom();
+ TAKE_PTR(f);
+ n = 0;
return 0;
}
-int search_rules_files(char * const *a, const char *root, char ***ret) {
- _cleanup_strv_free_ char **files = NULL;
+int search_rules_files(char * const *a, const char *root, ConfFile ***ret_files, size_t *ret_n_files) {
+ ConfFile **files = NULL;
+ size_t n_files = 0;
int r;
- assert(ret);
+ CLEANUP_ARRAY(files, n_files, conf_file_free_many);
+
+ assert(ret_files);
+ assert(ret_n_files);
if (strv_isempty(a)) {
- r = conf_files_list_strv(&files, ".rules", root, 0, (const char* const*) CONF_PATHS_STRV("udev/rules.d"));
+ r = conf_files_list_strv_full(".rules", root, CONF_FILES_REGULAR | CONF_FILES_FILTER_MASKED,
+ (const char* const*) CONF_PATHS_STRV("udev/rules.d"), &files, &n_files);
if (r < 0)
return log_error_errno(r, "Failed to enumerate rules files: %m");
- if (root && strv_isempty(files))
- return log_error_errno(SYNTHETIC_ERRNO(ENOENT), "No rules files found in %s.", root);
+ if (root && n_files == 0)
+ return log_error_errno(SYNTHETIC_ERRNO(ENOENT), "No rules files found in '%s'.", root);
} else
STRV_FOREACH(s, a) {
- r = search_rules_file(*s, root, &files);
+ r = search_rules_file(*s, root, &files, &n_files);
if (r < 0)
return r;
}
- *ret = TAKE_PTR(files);
+ *ret_files = TAKE_PTR(files);
+ *ret_n_files = n_files;
return 0;
}
#include <stdio.h>
#include "alloc-util.h"
+#include "conf-files.h"
#include "errno-util.h"
#include "log.h"
#include "parse-argument.h"
return 1;
}
-static int verify_rules_file(UdevRules *rules, const char *fname) {
+static int verify_rules_file(UdevRules *rules, const ConfFile *c) {
UdevRuleFile *file;
int r;
- r = udev_rules_parse_file(rules, fname, /* extra_checks = */ true, &file);
+ assert(rules);
+ assert(c);
+
+ r = udev_rules_parse_file(rules, c->resolved_path, /* extra_checks = */ true, &file);
if (r < 0)
- return log_error_errno(r, "Failed to parse rules file %s: %m", fname);
+ return log_error_errno(r, "Failed to parse rules file %s: %m", c->original_path);
if (r == 0) /* empty file. */
return 0;
unsigned mask = (1U << LOG_ERR) | (1U << LOG_WARNING);
if (issues & mask)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "%s: udev rules check failed.", fname);
+ "%s: udev rules check failed.", c->original_path);
if (arg_style && (issues & (1U << LOG_NOTICE)))
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
- "%s: udev rules have style issues.", fname);
+ "%s: udev rules have style issues.", c->original_path);
return 0;
}
-static int verify_rules(UdevRules *rules, char **files) {
+static int verify_rules(UdevRules *rules, ConfFile * const *files, size_t n_files) {
size_t fail_count = 0, success_count = 0;
int r, ret = 0;
assert(rules);
+ assert(files || n_files == 0);
- STRV_FOREACH(fp, files) {
- r = verify_rules_file(rules, *fp);
+ FOREACH_ARRAY(i, files, n_files) {
+ r = verify_rules_file(rules, *i);
if (r < 0)
++fail_count;
else
if (!rules)
return -ENOMEM;
- _cleanup_strv_free_ char **files = NULL;
- r = search_rules_files(strv_skip(argv, optind), arg_root, &files);
+ ConfFile **files = NULL;
+ size_t n_files = 0;
+
+ CLEANUP_ARRAY(files, n_files, conf_file_free_many);
+
+ r = search_rules_files(strv_skip(argv, optind), arg_root, &files, &n_files);
if (r < 0)
return r;
- return verify_rules(rules, files);
+ return verify_rules(rules, files, n_files);
}