summaryrefslogtreecommitdiff
path: root/getfattr/walk_tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'getfattr/walk_tree.c')
-rw-r--r--getfattr/walk_tree.c94
1 files changed, 94 insertions, 0 deletions
diff --git a/getfattr/walk_tree.c b/getfattr/walk_tree.c
new file mode 100644
index 0000000..468fef4
--- /dev/null
+++ b/getfattr/walk_tree.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org>
+ *
+ * TODO: should this be replaced by using nftw(3)?
+ */
+#include <sys/stat.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "walk_tree.h"
+
+int walk_recurse = 0;
+int walk_postorder = 0;
+int walk_symlinks = WALK_HALF_LOGICAL;
+
+int walk_tree(const char *path_p, int (*call)(const char *, struct stat *,
+ void *), void *arg)
+{
+ static struct stat st;
+ static int level = 0;
+ int follow;
+ int errors = 0;
+
+ level++;
+ if (lstat(path_p, &st) != 0)
+ goto fail;
+
+ if (S_ISLNK(st.st_mode)) {
+ if (walk_symlinks == WALK_PHYSICAL)
+ follow = 0;
+ else {
+ if (stat(path_p, &st) != 0)
+ goto fail;
+ follow = ((walk_symlinks == WALK_HALF_LOGICAL &&
+ level == 1) ||
+ walk_symlinks == WALK_FULL_LOGICAL);
+ }
+ } else
+ follow = 1;
+
+ if (!follow)
+ goto cleanup;
+
+ if (!walk_postorder)
+ errors += call(path_p, &st, arg);
+
+ if (walk_recurse && S_ISDIR(st.st_mode)) {
+ struct dirent *dirent;
+ DIR *dir;
+
+ char *ipath_p = (char *)path_p;
+ int ipath_length = strlen(ipath_p);
+ if (ipath_p[ipath_length-1] != '/') {
+ ipath_p = (char*)alloca(ipath_length +
+ _POSIX_PATH_MAX + 2);
+ if (ipath_p == NULL)
+ goto fail;
+ strcpy(ipath_p, path_p);
+ strcpy(ipath_p + ipath_length, "/");
+ ipath_length++;
+ }
+
+ dir = opendir(path_p);
+ if (dir == NULL)
+ goto fail;
+ while ((dirent = readdir(dir)) != NULL) {
+ if (!strcmp(dirent->d_name, ".") ||
+ !strcmp(dirent->d_name, ".."))
+ continue;
+ strncpy(ipath_p + ipath_length,
+ dirent->d_name, _POSIX_PATH_MAX);
+ ipath_p[ipath_length + _POSIX_PATH_MAX] = '\0';
+ walk_tree(ipath_p, call, arg); /* recurse */
+ }
+ ipath_p[ipath_length] = '\0';
+ closedir(dir);
+ }
+
+ if (walk_postorder)
+ errors += call(path_p, &st, arg);
+
+cleanup:
+ level--;
+ return errors;
+
+fail:
+ fprintf(stderr, "%s: %s: %s\n", progname, path_p, strerror(errno));
+ errors++;
+ goto cleanup;
+}
+