Fix: d_type validity is not guaranteed on all nfs versions
authorJonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Thu, 17 Mar 2016 18:56:02 +0000 (14:56 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Fri, 20 May 2016 20:21:38 +0000 (16:21 -0400)
When using lttng-crash on files mounted on a nfs mount the d_type from
the dirent struct is not necessarily set and results in a DT_UNKNOWN
d_type.

stat() provides the valid information on an nfs mount.

Signed-off-by: Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
src/bin/lttng-crash/lttng-crash.c

index 95dad26cbc6a39c218a2f9d179d9413fdff0ad20..0c1f45ae61e79e914ebf0d1966cb66dff3bf01bb 100644 (file)
@@ -977,6 +977,7 @@ int extract_trace_recursive(const char *output_path,
        DIR *dir;
        int dir_fd, ret = 0, closeret;
        struct dirent *entry;
+       size_t path_len;
        int has_warning = 0;
 
        /* Open directory */
@@ -985,6 +986,9 @@ int extract_trace_recursive(const char *output_path,
                PERROR("Cannot open '%s' path", input_path);
                return -1;
        }
+
+       path_len = strlen(input_path);
+
        dir_fd = dirfd(dir);
        if (dir_fd < 0) {
                PERROR("dirfd");
@@ -992,13 +996,34 @@ int extract_trace_recursive(const char *output_path,
        }
 
        while ((entry = readdir(dir))) {
+               struct stat st;
+               size_t name_len;
+               char filename[PATH_MAX];
+
                if (!strcmp(entry->d_name, ".")
                                || !strcmp(entry->d_name, "..")) {
                        continue;
                }
-               switch (entry->d_type) {
-               case DT_DIR:
-               {
+
+               name_len = strlen(entry->d_name);
+               if (path_len + name_len + 2 > sizeof(filename)) {
+                       ERR("Failed to remove file: path name too long (%s/%s)",
+                               input_path, entry->d_name);
+                       continue;
+               }
+
+               if (snprintf(filename, sizeof(filename), "%s/%s",
+                               input_path, entry->d_name) < 0) {
+                       ERR("Failed to format path.");
+                       continue;
+               }
+
+               if (stat(filename, &st)) {
+                       PERROR("stat");
+                       continue;
+               }
+
+               if (S_ISDIR(st.st_mode)) {
                        char output_subpath[PATH_MAX];
                        char input_subpath[PATH_MAX];
 
@@ -1030,10 +1055,7 @@ int extract_trace_recursive(const char *output_path,
                        if (ret) {
                                has_warning = 1;
                        }
-                       break;
-               }
-               case DT_REG:
-               case DT_LNK:
+               } else if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
                        if (!strcmp(entry->d_name, "metadata")) {
                                ret = extract_one_trace(output_path,
                                        input_path);
@@ -1043,9 +1065,7 @@ int extract_trace_recursive(const char *output_path,
                                        has_warning = 1;
                                }
                        }
-                       /* Ignore other files */
-                       break;
-               default:
+               } else {
                        has_warning = 1;
                        goto end;
                }
@@ -1063,6 +1083,7 @@ int delete_dir_recursive(const char *path)
 {
        DIR *dir;
        int dir_fd, ret = 0, closeret;
+       size_t path_len;
        struct dirent *entry;
 
        /* Open trace directory */
@@ -1072,6 +1093,9 @@ int delete_dir_recursive(const char *path)
                ret = -errno;
                goto end;
        }
+
+       path_len = strlen(path);
+
        dir_fd = dirfd(dir);
        if (dir_fd < 0) {
                PERROR("dirfd");
@@ -1080,13 +1104,34 @@ int delete_dir_recursive(const char *path)
        }
 
        while ((entry = readdir(dir))) {
+               struct stat st;
+               size_t name_len;
+               char filename[PATH_MAX];
+
                if (!strcmp(entry->d_name, ".")
                                || !strcmp(entry->d_name, "..")) {
                        continue;
                }
-               switch (entry->d_type) {
-               case DT_DIR:
-               {
+
+               name_len = strlen(entry->d_name);
+               if (path_len + name_len + 2 > sizeof(filename)) {
+                       ERR("Failed to remove file: path name too long (%s/%s)",
+                               path, entry->d_name);
+                       continue;
+               }
+
+               if (snprintf(filename, sizeof(filename), "%s/%s",
+                               path, entry->d_name) < 0) {
+                       ERR("Failed to format path.");
+                       continue;
+               }
+
+               if (stat(filename, &st)) {
+                       PERROR("stat");
+                       continue;
+               }
+
+               if (S_ISDIR(st.st_mode)) {
                        char *subpath = zmalloc(PATH_MAX);
 
                        if (!subpath) {
@@ -1107,16 +1152,13 @@ int delete_dir_recursive(const char *path)
                                /* Error occured, abort traversal. */
                                goto end;
                        }
-                       break;
-               }
-               case DT_REG:
+               } else if (S_ISREG(st.st_mode)) {
                        ret = unlinkat(dir_fd, entry->d_name, 0);
                        if (ret) {
                                PERROR("Unlinking '%s'", entry->d_name);
                                goto end;
                        }
-                       break;
-               default:
+               } else {
                        ret = -EINVAL;
                        goto end;
                }
This page took 0.027703 seconds and 4 git commands to generate.