Some file systems (at least, reiserfs) return DT_UNKNOWN for
every directory entry in readdir(). So far in several places
systemd filtered on DT_REG/DT_LNK and so skipped any file on
such filesystems. It affected systemd-update-utmp, systemd-modules-load
and systemd-tty-ask-password-agent.

This patch adds additional stat() check for file type for DT_UNKNOWN
case. Additionally, it adds check that DT_LNK really points to
regular file.

The patch fixes misterious runlevel entry in utmp discussed in
http://lists.freedesktop.org/archives/systemd-devel/2011-March/001433.html

Reported-By: tolzm...@molgen.mpg.de
Signed-off-by: Andrey Borzenkov <arvidj...@gmail.com>

---
 src/modules-load.c           |  137 +++++++++++++++++++++++-------------------
 src/tmpfiles.c               |   22 ++++---
 src/tty-ask-password-agent.c |    8 ++-
 3 files changed, 94 insertions(+), 73 deletions(-)

diff --git a/src/modules-load.c b/src/modules-load.c
index 3e3ccb0..7d733d1 100644
--- a/src/modules-load.c
+++ b/src/modules-load.c
@@ -43,12 +43,76 @@ static int scandir_filter(const struct dirent *d) {
                 return 0;
 
         if (d->d_type != DT_REG &&
-            d->d_type != DT_LNK)
+            d->d_type != DT_LNK &&
+           d->d_type != DT_UNKNOWN)
                 return 0;
 
         return endswith(d->d_name, ".conf");
 }
 
+static int load_modules_from_file(char *fn, char ***arguments, int 
*n_arguments, int *n_allocated)
+{
+       FILE *f;
+       int r = 0;
+
+       f = fopen(fn, "re");
+
+       if (!f) {
+               if (errno == ENOENT)
+                       return 0;
+
+               log_error("Failed to open %s: %m", fn);
+               return -errno;
+       }
+
+       for (;;) {
+               char line[LINE_MAX], *l, *t;
+
+               if (!(fgets(line, sizeof(line), f)))
+                       break;
+
+               l = strstrip(line);
+               if (*l == '#' || *l == 0)
+                       continue;
+
+               if (!(t = strdup(l))) {
+                       log_error("Failed to allocate module name.");
+                       if (!r)
+                               r = -ENOMEM;
+                       continue;
+               }
+
+               if (*n_arguments >= *n_allocated) {
+                       char **a;
+                       unsigned m;
+
+                       m = MAX(16U, *n_arguments*2);
+
+                       if (!(a = realloc(*arguments, sizeof(char*) * (m+1)))) {
+                               log_error("Failed to increase module array 
size.");
+                               free(t);
+                               if (!r)
+                                       r = -ENOMEM;
+                               continue;
+                       }
+
+                       *arguments = a;
+                       *n_allocated = m;
+               }
+
+               *arguments[(*n_arguments)++] = t;
+       }
+
+       if (ferror(f)) {
+               r = -EIO;
+               log_error("Failed to read from file: %m");
+       }
+
+       fclose(f);
+
+       return r;
+}
+
 int main(int argc, char *argv[]) {
         struct dirent **de = NULL;
         int r = EXIT_FAILURE, n, i;
@@ -86,70 +150,21 @@ int main(int argc, char *argv[]) {
         for (i = 0; i < n; i++) {
                 int k;
                 char *fn;
-                FILE *f;
 
                 k = asprintf(&fn, "/etc/modules-load.d/%s", de[i]->d_name);
-                free(de[i]);
-
-                if (k < 0) {
+                if (k >= 0) {
+                       struct stat st;
+
+                       if (de[i]->d_type == DT_REG ||
+                           (stat(fn, &st) >= 0 && S_ISREG(st.st_mode)))
+                               if (load_modules_from_file(fn, &arguments, 
&n_arguments, &n_allocated) < 0)
+                                       r = EXIT_FAILURE;
+                       free(fn);
+               } else {
                         log_error("Failed to allocate file name.");
                         r = EXIT_FAILURE;
-                        continue;
-                }
-
-                f = fopen(fn, "re");
-                free(fn);
-
-                if (!f) {
-                        if (errno == ENOENT)
-                                continue;
-
-                        log_error("Failed to open %s: %m", fn);
-                        r = EXIT_FAILURE;
-                        continue;
-                }
-
-                for (;;) {
-                        char line[LINE_MAX], *l, *t;
-
-                        if (!(fgets(line, sizeof(line), f)))
-                                break;
-
-                        l = strstrip(line);
-                        if (*l == '#' || *l == 0)
-                                continue;
-
-                        if (!(t = strdup(l))) {
-                                log_error("Failed to allocate module name.");
-                                continue;
-                        }
-
-                        if (n_arguments >= n_allocated) {
-                                char **a;
-                                unsigned m;
-
-                                m = MAX(16U, n_arguments*2);
-
-                                if (!(a = realloc(arguments, sizeof(char*) * 
(m+1)))) {
-                                        log_error("Failed to increase module 
array size.");
-                                        free(t);
-                                        r = EXIT_FAILURE;
-                                        continue;
-                                }
-
-                                arguments = a;
-                                n_allocated = m;
-                        }
-
-                        arguments[n_arguments++] = t;
-                }
-
-                if (ferror(f)) {
-                        r = EXIT_FAILURE;
-                        log_error("Failed to read from file: %m");
-                }
-
-                fclose(f);
+               }
+               free(de[i]);
         }
 
         free(de);
diff --git a/src/tmpfiles.c b/src/tmpfiles.c
index 0c3b88d..2b9ad90 100644
--- a/src/tmpfiles.c
+++ b/src/tmpfiles.c
@@ -775,7 +775,8 @@ static int scandir_filter(const struct dirent *d) {
                 return 0;
 
         if (d->d_type != DT_REG &&
-            d->d_type != DT_LNK)
+            d->d_type != DT_LNK &&
+           d->d_type != DT_UNKNOWN)
                 return 0;
 
         return endswith(d->d_name, ".conf");
@@ -955,18 +956,19 @@ int main(int argc, char *argv[]) {
                         char *fn;
 
                         k = asprintf(&fn, "/etc/tmpfiles.d/%s", de[j]->d_name);
-                        free(de[j]);
-
-                        if (k < 0) {
+                       if (k >= 0) {
+                               struct stat st;
+
+                               if (de[j]->d_type == DT_REG ||
+                                   (stat(fn, &st) >= 0 && S_ISREG(st.st_mode)))
+                                       if (read_config_file(fn, true) < 0)
+                                               r = EXIT_FAILURE;
+                               free(fn);
+                       } else {
                                 log_error("Failed to allocate file name.");
                                 r = EXIT_FAILURE;
-                                continue;
                         }
-
-                        if (read_config_file(fn, true) < 0)
-                                r = EXIT_FAILURE;
-
-                        free(fn);
+                        free(de[j]);
                 }
 
                 free(de);
diff --git a/src/tty-ask-password-agent.c b/src/tty-ask-password-agent.c
index a9d06ac..3025102 100644
--- a/src/tty-ask-password-agent.c
+++ b/src/tty-ask-password-agent.c
@@ -507,8 +507,12 @@ static int show_passwords(void) {
                 int q;
                 char *wall;
 
-                if (de->d_type != DT_REG)
-                        continue;
+                if (de->d_type != DT_REG) {
+                       struct stat st;
+
+                       if (de->d_type != DT_UNKNOWN || fstatat(dirfd(d), 
de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0 || !S_ISREG(st.st_mode))
+                                       continue;
+               }
 
                 if (ignore_file(de->d_name))
                         continue;
-- 
tg: (fc7a744..) upstream/dt_unknown (depends on: origin/master)
_______________________________________________
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel

Reply via email to