[lttng-dev] [PATCH lttng-tools 1/2] Fix: d_type validity is not guaranteed on all nfs versions
Jonathan Rajotte
jonathan.rajotte-julien at efficios.com
Fri Mar 18 17:20:48 UTC 2016
When using lttng-crash on files mounted on a nfs mount the d_type from the dirent
struct is not necessarily set and result in DT_UNKNOWN d_type.
stat() provide the valid information on an nfs mount.
Signed-off-by: Jonathan Rajotte <jonathan.rajotte-julien at efficios.com>
---
src/bin/lttng-crash/lttng-crash.c | 80 +++++++++++++++++++++++++++++----------
1 file changed, 61 insertions(+), 19 deletions(-)
diff --git a/src/bin/lttng-crash/lttng-crash.c b/src/bin/lttng-crash/lttng-crash.c
index 653e4d0..8eddbd9 100644
--- a/src/bin/lttng-crash/lttng-crash.c
+++ b/src/bin/lttng-crash/lttng-crash.c
@@ -976,6 +976,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 */
@@ -984,6 +985,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");
@@ -991,13 +995,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];
@@ -1029,22 +1054,17 @@ 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);
if (ret) {
WARN("Error extracting trace '%s', continuing anyway.",
input_path);
- has_warning = 1;
+ has_warning = 2;
}
}
- /* Ignore other files */
- break;
- default:
+ } else {
has_warning = 1;
goto end;
}
@@ -1062,6 +1082,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 */
@@ -1071,6 +1092,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");
@@ -1079,13 +1103,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) {
@@ -1106,16 +1151,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;
}
--
2.7.0
More information about the lttng-dev
mailing list