summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Gruenbacher <agruenba@redhat.com>2020-10-31 02:25:37 +0100
committerAndreas Gruenbacher <agruenba@redhat.com>2021-03-11 19:11:35 +0100
commit15c44cee610a3003b820ab102e495bbf1e903990 (patch)
tree5c4119ee1d3b0c18bbc3dfcaee054cbd25ace7e9
parent74da517cc655a82ded715dea7245ce88ebc91b98 (diff)
downloadattr-15c44cee610a3003b820ab102e495bbf1e903990.tar.gz
Move walk_tree_rec arguments into a separate struct
-rw-r--r--libmisc/walk_tree.c81
1 files changed, 49 insertions, 32 deletions
diff --git a/libmisc/walk_tree.c b/libmisc/walk_tree.c
index 00cea7b..26a9b6e 100644
--- a/libmisc/walk_tree.c
+++ b/libmisc/walk_tree.c
@@ -39,6 +39,14 @@ struct entry_handle {
long pos;
};
+struct walk_tree_args {
+ char path[FILENAME_MAX];
+ int walk_flags;
+ int (*func)(const char *, const struct stat *, int, void *);
+ void *arg;
+ int depth;
+};
+
static struct entry_handle head = {
.next = &head,
.prev = &head,
@@ -57,15 +65,13 @@ static int walk_tree_visited(dev_t dev, ino_t ino)
return 0;
}
-static int walk_tree_rec(const char *path, int walk_flags,
- int (*func)(const char *, const struct stat *, int,
- void *), void *arg, int depth)
+static int walk_tree_rec(struct walk_tree_args *args)
{
- int follow_symlinks = (walk_flags & WALK_TREE_LOGICAL) ||
- ((walk_flags & WALK_TREE_DEREFERENCE) &&
- !(walk_flags & WALK_TREE_PHYSICAL) &&
- depth == 0);
- int have_dir_stat = 0, flags = walk_flags, err;
+ int follow_symlinks = (args->walk_flags & WALK_TREE_LOGICAL) ||
+ ((args->walk_flags & WALK_TREE_DEREFERENCE) &&
+ !(args->walk_flags & WALK_TREE_PHYSICAL) &&
+ args->depth == 0);
+ int have_dir_stat = 0, flags = args->walk_flags, err;
struct entry_handle dir;
struct stat st;
@@ -74,19 +80,21 @@ static int walk_tree_rec(const char *path, int walk_flags,
* If (walk_flags & WALK_TREE_LOGICAL), traverse all symlinks.
* Otherwise, traverse only top-level symlinks.
*/
- if (depth == 0)
+ if (args->depth == 0)
flags |= WALK_TREE_TOPLEVEL;
- if (lstat(path, &st) != 0)
- return func(path, NULL, flags | WALK_TREE_FAILED, arg);
+ if (lstat(args->path, &st) != 0)
+ return args->func(args->path, NULL, flags | WALK_TREE_FAILED,
+ args->arg);
if (S_ISLNK(st.st_mode)) {
flags |= WALK_TREE_SYMLINK;
if ((flags & WALK_TREE_DEREFERENCE) ||
((flags & WALK_TREE_TOPLEVEL) &&
(flags & WALK_TREE_DEREFERENCE_TOPLEVEL))) {
- if (stat(path, &st) != 0)
- return func(path, NULL,
- flags | WALK_TREE_FAILED, arg);
+ if (stat(args->path, &st) != 0)
+ return args->func(args->path, NULL,
+ flags | WALK_TREE_FAILED,
+ args->arg);
dir.dev = st.st_dev;
dir.ino = st.st_ino;
have_dir_stat = 1;
@@ -96,7 +104,7 @@ static int walk_tree_rec(const char *path, int walk_flags,
dir.ino = st.st_ino;
have_dir_stat = 1;
}
- err = func(path, &st, flags, arg);
+ err = args->func(args->path, &st, flags, args->arg);
/*
* Recurse if WALK_TREE_RECURSIVE and the path is:
@@ -130,7 +138,7 @@ close_another_dir:
num_dir_handles++;
}
- dir.stream = opendir(path);
+ dir.stream = opendir(args->path);
if (!dir.stream) {
if (errno == ENFILE && closed->prev != &head) {
/* Ran out of file descriptors. */
@@ -143,14 +151,14 @@ close_another_dir:
* symlink which we didn't follow above.
*/
if (errno != ENOTDIR && errno != ENOENT)
- err += func(path, NULL, flags |
- WALK_TREE_FAILED, arg);
+ err += args->func(args->path, NULL, flags |
+ WALK_TREE_FAILED, args->arg);
return err;
}
/* See walk_tree_visited() comment above... */
if (!have_dir_stat) {
- if (stat(path, &st) != 0)
+ if (stat(args->path, &st) != 0)
goto skip_dir;
dir.dev = st.st_dev;
dir.ino = st.st_ino;
@@ -171,25 +179,29 @@ close_another_dir:
if (!strcmp(entry->d_name, ".") ||
!strcmp(entry->d_name, ".."))
continue;
- path_end = strchr(path, 0);
- if ((path_end - path) + strlen(entry->d_name) + 1 >=
+ path_end = strchr(args->path, 0);
+ if ((path_end - args->path) + strlen(entry->d_name) + 1 >=
FILENAME_MAX) {
errno = ENAMETOOLONG;
- err += func(path, NULL,
- flags | WALK_TREE_FAILED, arg);
+ err += args->func(args->path, NULL,
+ flags | WALK_TREE_FAILED,
+ args->arg);
continue;
}
*path_end++ = '/';
strcpy(path_end, entry->d_name);
- err += walk_tree_rec(path, walk_flags, func, arg,
- depth + 1);
+ args->depth++;
+ err += walk_tree_rec(args);
+ args->depth--;
*--path_end = 0;
if (!dir.stream) {
/* Reopen the directory handle. */
- dir.stream = opendir(path);
+ dir.stream = opendir(args->path);
if (!dir.stream)
- return err + func(path, NULL, flags |
- WALK_TREE_FAILED, arg);
+ return err + args->func(args->path,
+ NULL,
+ flags | WALK_TREE_FAILED,
+ args->arg);
seekdir(dir.stream, dir.pos);
closed = closed->next;
@@ -204,7 +216,8 @@ close_another_dir:
skip_dir:
if (closedir(dir.stream) != 0)
- err += func(path, NULL, flags | WALK_TREE_FAILED, arg);
+ err += args->func(args->path, NULL,
+ flags | WALK_TREE_FAILED, args->arg);
}
return err;
}
@@ -213,7 +226,7 @@ int walk_tree(const char *path, int walk_flags, unsigned int num,
int (*func)(const char *, const struct stat *, int, void *),
void *arg)
{
- char path_copy[FILENAME_MAX];
+ struct walk_tree_args args;
num_dir_handles = num;
if (num_dir_handles < 1) {
@@ -228,6 +241,10 @@ int walk_tree(const char *path, int walk_flags, unsigned int num,
errno = ENAMETOOLONG;
return func(path, NULL, WALK_TREE_FAILED, arg);
}
- strcpy(path_copy, path);
- return walk_tree_rec(path_copy, walk_flags, func, arg, 0);
+ strcpy(args.path, path);
+ args.walk_flags = walk_flags;
+ args.func = func;
+ args.arg = arg;
+ args.depth = 0;
+ return walk_tree_rec(&args);
}