3232#include "macro.h"
3333#include "missing.h"
3434#include "path-util.h"
35+ #include "stat-util.h"
3536#include "string-util.h"
3637#include "strv.h"
3738#include "util.h"
3839
39- static int files_add(Hashmap *h, const char *root , const char *path, const char *suffix ) {
40+ static int files_add(Hashmap *h, const char *suffix , const char *root, unsigned flags, const char *path ) {
4041 _cleanup_closedir_ DIR *dir = NULL;
4142 const char *dirpath;
4243 struct dirent *de;
@@ -59,6 +60,31 @@ static int files_add(Hashmap *h, const char *root, const char *path, const char
5960 if (!dirent_is_file_with_suffix(de, suffix))
6061 continue;
6162
63+ if (flags & CONF_FILES_EXECUTABLE) {
64+ struct stat st;
65+
66+ /* As requested: check if the file is marked exectuable. Note that we don't check access(X_OK)
67+ * here, as we care about whether the file is marked executable at all, and not whether it is
68+ * executable for us, because if such errors are stuff we should log about. */
69+
70+ if (fstatat(dirfd(dir), de->d_name, &st, 0) < 0) {
71+ log_debug_errno(errno, "Failed to stat %s/%s, ignoring: %m", dirpath, de->d_name);
72+ continue;
73+ }
74+
75+ /* We only want executable regular files (or symlinks to them), or symlinks to /dev/null */
76+ if (S_ISREG(st.st_mode)) {
77+ if ((st.st_mode & 0111) == 0) { /* not executable */
78+ log_debug("Ignoring %s/%s, as it is not marked executable.", dirpath, de->d_name);
79+ continue;
80+ }
81+
82+ } else if (!null_or_empty(&st)) { /* /dev/null? */
83+ log_debug("Ignoring %s/%s, as it is not a regular file (or symlink to /dev/null).", dirpath, de->d_name);
84+ continue;
85+ }
86+ }
87+
6288 p = strjoin(dirpath, "/", de->d_name);
6389 if (!p)
6490 return -ENOMEM;
@@ -87,7 +113,7 @@ static int base_cmp(const void *a, const void *b) {
87113 return strcmp(basename(s1), basename(s2));
88114}
89115
90- static int conf_files_list_strv_internal(char ***strv, const char *suffix, const char *root, char **dirs) {
116+ static int conf_files_list_strv_internal(char ***strv, const char *suffix, const char *root, unsigned flags, char **dirs) {
91117 _cleanup_hashmap_free_ Hashmap *fh = NULL;
92118 char **files, **p;
93119 int r;
@@ -103,7 +129,7 @@ static int conf_files_list_strv_internal(char ***strv, const char *suffix, const
103129 return -ENOMEM;
104130
105131 STRV_FOREACH(p, dirs) {
106- r = files_add(fh, root, *p, suffix );
132+ r = files_add(fh, suffix, root, flags, *p );
107133 if (r == -ENOMEM)
108134 return r;
109135 if (r < 0)
@@ -120,7 +146,7 @@ static int conf_files_list_strv_internal(char ***strv, const char *suffix, const
120146 return 0;
121147}
122148
123- int conf_files_list_strv(char ***strv, const char *suffix, const char *root, const char* const* dirs) {
149+ int conf_files_list_strv(char ***strv, const char *suffix, const char *root, unsigned flags, const char* const* dirs) {
124150 _cleanup_strv_free_ char **copy = NULL;
125151
126152 assert(strv);
@@ -129,10 +155,10 @@ int conf_files_list_strv(char ***strv, const char *suffix, const char *root, con
129155 if (!copy)
130156 return -ENOMEM;
131157
132- return conf_files_list_strv_internal(strv, suffix, root, copy);
158+ return conf_files_list_strv_internal(strv, suffix, root, flags, copy);
133159}
134160
135- int conf_files_list(char ***strv, const char *suffix, const char *root, const char *dir, ...) {
161+ int conf_files_list(char ***strv, const char *suffix, const char *root, unsigned flags, const char *dir, ...) {
136162 _cleanup_strv_free_ char **dirs = NULL;
137163 va_list ap;
138164
@@ -145,10 +171,10 @@ int conf_files_list(char ***strv, const char *suffix, const char *root, const ch
145171 if (!dirs)
146172 return -ENOMEM;
147173
148- return conf_files_list_strv_internal(strv, suffix, root, dirs);
174+ return conf_files_list_strv_internal(strv, suffix, root, flags, dirs);
149175}
150176
151- int conf_files_list_nulstr(char ***strv, const char *suffix, const char *root, const char *d) {
177+ int conf_files_list_nulstr(char ***strv, const char *suffix, const char *root, unsigned flags, const char *d) {
152178 _cleanup_strv_free_ char **dirs = NULL;
153179
154180 assert(strv);
@@ -157,5 +183,5 @@ int conf_files_list_nulstr(char ***strv, const char *suffix, const char *root, c
157183 if (!dirs)
158184 return -ENOMEM;
159185
160- return conf_files_list_strv_internal(strv, suffix, root, dirs);
186+ return conf_files_list_strv_internal(strv, suffix, root, flags, dirs);
161187}
0 commit comments