From: Jonathan Rajotte Date: Thu, 17 Mar 2016 18:56:02 +0000 (-0400) Subject: Fix: d_type validity is not guaranteed on all nfs versions X-Git-Tag: v2.7.3~10 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=d8e2a9cd25350875282a9a8d1df3c28ccfd87368;p=lttng-tools.git Fix: d_type validity is not guaranteed on all nfs versions 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 Signed-off-by: Jérémie Galarneau --- diff --git a/src/bin/lttng-crash/lttng-crash.c b/src/bin/lttng-crash/lttng-crash.c index 95dad26cb..0c1f45ae6 100644 --- a/src/bin/lttng-crash/lttng-crash.c +++ b/src/bin/lttng-crash/lttng-crash.c @@ -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; }