Steve Grubb d5ab53
--- acl-2.2.39/getfacl/getfacl.c.walk	2006-06-20 08:51:25.000000000 +0200
Thomas Woerner 71326a
+++ acl-2.2.39/getfacl/getfacl.c	2007-03-21 10:52:07.000000000 +0100
Steve Grubb d5ab53
@@ -34,7 +34,6 @@
Steve Grubb d5ab53
 #include <dirent.h>
Steve Grubb d5ab53
 #include <libgen.h>
Steve Grubb d5ab53
 #include <getopt.h>
Steve Grubb d5ab53
-#include <ftw.h>
Steve Grubb d5ab53
 #include <locale.h>
Steve Grubb d5ab53
 #include "config.h"
Steve Grubb d5ab53
 #include "user_group.h"
Steve Grubb d5ab53
@@ -70,9 +69,9 @@
Steve Grubb d5ab53
 const char *progname;
Steve Grubb d5ab53
 const char *cmd_line_options;
Steve Grubb d5ab53
 
Steve Grubb d5ab53
-int opt_recursive;  /* recurse into sub-directories? */
Steve Grubb d5ab53
-int opt_walk_logical;  /* always follow symbolic links */
Steve Grubb d5ab53
-int opt_walk_physical;  /* never follow symbolic links */
Steve Grubb d5ab53
+int opt_recursive = 0;  /* recurse into sub-directories? */
Steve Grubb d5ab53
+int opt_walk_logical = 0;  /* always follow symbolic links */
Steve Grubb d5ab53
+int opt_walk_physical = 0;  /* never follow symbolic links */
Steve Grubb d5ab53
 int opt_print_acl = 0;
Steve Grubb d5ab53
 int opt_print_default_acl = 0;
Steve Grubb d5ab53
 int opt_strip_leading_slash = 1;
Thomas Woerner 71326a
@@ -562,71 +561,140 @@
Steve Grubb d5ab53
 
Steve Grubb d5ab53
 
Steve Grubb d5ab53
 static int __errors;
Steve Grubb d5ab53
-int __do_print(const char *file, const struct stat *stat,
Steve Grubb d5ab53
-               int flag, struct FTW *ftw)
Steve Grubb d5ab53
+
Steve Grubb d5ab53
+int walk_tree(const char *file)
Steve Grubb d5ab53
 {
Steve Grubb d5ab53
-	int saved_errno = errno;
Steve Grubb d5ab53
+	static int level = 0;
Steve Grubb d5ab53
+	static int link_count = 0;
Steve Grubb d5ab53
+	DIR *dir;
Steve Grubb d5ab53
+	struct dirent *entry;
Steve Grubb d5ab53
+	struct stat buf;
Thomas Woerner 71326a
+	char path[FILENAME_MAX];
Thomas Woerner 71326a
+	char path2[FILENAME_MAX];
Thomas Woerner 71326a
+	char path3[FILENAME_MAX];
Thomas Woerner 71326a
+	char *dir_name;
Thomas Woerner 71326a
+	size_t len;
Thomas Woerner 71326a
+	ssize_t slen;
Thomas Woerner 71326a
+	int res;
Steve Grubb d5ab53
 
Steve Grubb d5ab53
 	/* Process the target of a symbolic link, and traverse the link,
Steve Grubb d5ab53
            only if doing a logical walk, or if the symbolic link was
Steve Grubb d5ab53
            specified on the command line. Always skip symbolic links if
Steve Grubb d5ab53
            doing a physical walk. */
Steve Grubb d5ab53
 
Steve Grubb d5ab53
-	if (S_ISLNK(stat->st_mode) &&
Steve Grubb d5ab53
-	    (opt_walk_physical || (ftw->level > 0 && !opt_walk_logical)))
Thomas Woerner 71326a
+	len = strlen(file);
Thomas Woerner 71326a
+	/* check for FILENAME_MAX */
Thomas Woerner 71326a
+	if (len >= FILENAME_MAX) {
Thomas Woerner 71326a
+		fprintf(stderr, "%s: %s: %s\n", progname, xquote(file),
Thomas Woerner 71326a
+			strerror(ENAMETOOLONG));
Thomas Woerner 71326a
+		__errors++;
Steve Grubb d5ab53
 		return 0;
Thomas Woerner 71326a
+	}
Thomas Woerner 71326a
+	/* string ends with '/', remove it and restart */
Thomas Woerner 71326a
+	if (len > 1 && file[len-1] == '/') {
Thomas Woerner 71326a
+		strncpy(path, file, len);
Thomas Woerner 71326a
+		path[len-1] = '\0'; /* overwrite slash */
Thomas Woerner 71326a
+		return walk_tree(path);
Thomas Woerner 71326a
+	}
Steve Grubb d5ab53
 
Steve Grubb d5ab53
-	if (do_print(file, stat))
Thomas Woerner 71326a
-		__errors++;
Thomas Woerner 71326a
+	if (level > 0 && !opt_recursive)
Thomas Woerner 71326a
+		return 0;
Thomas Woerner 71326a
 
Steve Grubb d5ab53
-	if (flag == FTW_DNR && opt_recursive) {
Steve Grubb d5ab53
-		/* Item is a directory which can't be read. */
Steve Grubb d5ab53
-		fprintf(stderr, "%s: %s: %s\n",
Steve Grubb d5ab53
-			progname, file, strerror(saved_errno));
Thomas Woerner 71326a
+	if (lstat(file, &buf) != 0) {
Thomas Woerner 71326a
+		fprintf(stderr, "%s: %s: %s\n", progname, xquote(file),
Thomas Woerner 71326a
+			strerror(errno));
Thomas Woerner 71326a
+		__errors++;
Steve Grubb d5ab53
 		return 0;
Steve Grubb d5ab53
 	}
Steve Grubb d5ab53
 
Steve Grubb d5ab53
-	/* We also get here in non-recursive mode. In that case,
Steve Grubb d5ab53
-	   return something != 0 to abort nftw. */
Thomas Woerner 71326a
+	if (S_ISLNK(buf.st_mode)) {
Thomas Woerner 71326a
+		/* physical means: no links at all */
Thomas Woerner 71326a
+		if (opt_walk_physical)
Thomas Woerner 71326a
+			return 1;
Thomas Woerner 71326a
+
Thomas Woerner 71326a
+		/* logical: show information or walk if points to directory
Thomas Woerner 71326a
+		 * also for symbolic link arguments on level 0 */
Thomas Woerner 71326a
+		if (opt_walk_logical || level == 0) {
Thomas Woerner 71326a
+			/* copy and append terminating '\0' */
Thomas Woerner 71326a
+			strncpy(path2, file, len+1);
Thomas Woerner 71326a
+
Thomas Woerner 71326a
+			/* get directory name */
Thomas Woerner 71326a
+			dir_name = dirname(path2);
Thomas Woerner 71326a
+
Thomas Woerner 71326a
+			/* get link target */
Thomas Woerner 71326a
+			slen = readlink(file, path, FILENAME_MAX-1);
Thomas Woerner 71326a
+			if (slen < 0) {
Thomas Woerner 71326a
+				fprintf(stderr, "%s: %s: %s\n", progname,
Thomas Woerner 71326a
+					xquote(file), strerror(errno));
Thomas Woerner 71326a
+				__errors++;
Thomas Woerner 71326a
+				return 0;
Thomas Woerner 71326a
+			}
Thomas Woerner 71326a
+			path[slen] = '\0';
Thomas Woerner 71326a
 
Steve Grubb d5ab53
-	if (!opt_recursive)
Thomas Woerner 71326a
-		return 1;
Thomas Woerner 71326a
+			if (slen == 0 || path[0] == '/') {
Thomas Woerner 71326a
+				/* absolute:
Thomas Woerner 71326a
+				 * copy and append terminating '\0' */
Thomas Woerner 71326a
+				strncpy(path3, path, slen+1);
Thomas Woerner 71326a
+			} else
Thomas Woerner 71326a
+				/* relative */
Thomas Woerner 71326a
+				snprintf(path3, FILENAME_MAX, "%s/%s",
Thomas Woerner 71326a
+					 dir_name, path);
Thomas Woerner 71326a
+			
Thomas Woerner 71326a
+			if (lstat(path3, &buf) != 0) {
Thomas Woerner 71326a
+				fprintf(stderr, "%s: %s: %s\n", progname,
Thomas Woerner 71326a
+					xquote(path), strerror(errno));
Thomas Woerner 71326a
+				__errors++;
Thomas Woerner 71326a
+				return 0;
Thomas Woerner 71326a
+			}
Steve Grubb d5ab53
 
Steve Grubb d5ab53
-	return 0;
Steve Grubb d5ab53
-}
Thomas Woerner 71326a
+			if ((S_ISDIR(buf.st_mode) && opt_recursive && 
Thomas Woerner 71326a
+			     link_count < 1) || S_ISLNK(buf.st_mode)) {
Thomas Woerner 71326a
+				/* walk directory or follow symlink on level
Thomas Woerner 71326a
+				 * 0 */
Thomas Woerner 71326a
+				link_count++;
Thomas Woerner 71326a
+				res = walk_tree(path3);
Thomas Woerner 71326a
+				link_count--;
Thomas Woerner 71326a
+				if (res != 1)
Thomas Woerner 71326a
+					return 0;
Thomas Woerner 71326a
+			} else
Thomas Woerner 71326a
+				if (do_print(path3, &buf))
Thomas Woerner 71326a
+					__errors++;
Thomas Woerner 71326a
 
Steve Grubb d5ab53
-char *resolve_symlinks(const char *file)
Steve Grubb d5ab53
-{
Steve Grubb d5ab53
-	static char buffer[4096];
Steve Grubb d5ab53
-	char *path = NULL;
Steve Grubb d5ab53
-	ssize_t len;
Steve Grubb d5ab53
-
Steve Grubb d5ab53
-	len = readlink(file, buffer, sizeof(buffer)-1);
Steve Grubb d5ab53
-	if (len < 0) {
Steve Grubb d5ab53
-		if (errno == EINVAL)	/* not a symlink, use given path */
Steve Grubb d5ab53
-			path = (char *)file;
Steve Grubb d5ab53
-	} else {
Steve Grubb d5ab53
-		buffer[len+1] = '\0';
Steve Grubb d5ab53
-		path = buffer;
Steve Grubb d5ab53
+			return 1;
Steve Grubb d5ab53
+		}
Steve Grubb d5ab53
 	}
Steve Grubb d5ab53
-	return path;
Steve Grubb d5ab53
-}
Steve Grubb d5ab53
-
Steve Grubb d5ab53
-int walk_tree(const char *file)
Steve Grubb d5ab53
-{
Steve Grubb d5ab53
-	const char *p;
Steve Grubb d5ab53
 
Steve Grubb d5ab53
-	__errors = 0;
Steve Grubb d5ab53
-	if ((p = resolve_symlinks(file)) == NULL) {
Steve Grubb d5ab53
-		fprintf(stderr, "%s: %s: %s\n", progname,
Steve Grubb d5ab53
-			xquote(file), strerror(errno));
Steve Grubb d5ab53
-		__errors++;
Steve Grubb d5ab53
-	} else if (nftw(p, __do_print, 0, opt_walk_logical? 0 : FTW_PHYS) < 0) {
Steve Grubb d5ab53
-		fprintf(stderr, "%s: %s: %s\n", progname, xquote(file),
Steve Grubb d5ab53
-			strerror(errno));
Steve Grubb d5ab53
+	if (do_print(file, &buf))
Steve Grubb d5ab53
 		__errors++;
Steve Grubb d5ab53
+
Thomas Woerner 71326a
+	/* it is a directory, walk */
Steve Grubb d5ab53
+	if (S_ISDIR(buf.st_mode)) {
Steve Grubb d5ab53
+		dir = opendir(file);
Steve Grubb d5ab53
+		if (!dir) {
Steve Grubb d5ab53
+			fprintf(stderr, "%s: %s: %s\n", progname,
Steve Grubb d5ab53
+				xquote(file), strerror(errno));
Steve Grubb d5ab53
+			__errors++;
Steve Grubb d5ab53
+			return 0;
Steve Grubb d5ab53
+		}
Steve Grubb d5ab53
+
Thomas Woerner 71326a
+		level++;
Steve Grubb d5ab53
+		while ((entry = readdir(dir)) != NULL) {
Steve Grubb d5ab53
+			if (! strcmp(entry->d_name, ".") || 
Steve Grubb d5ab53
+			    ! strcmp(entry->d_name, ".."))
Steve Grubb d5ab53
+				continue;
Steve Grubb d5ab53
+
Thomas Woerner 71326a
+			snprintf(path, FILENAME_MAX, "%s/%s", file,
Thomas Woerner 71326a
+				 entry->d_name);
Steve Grubb d5ab53
+
Thomas Woerner 71326a
+			/* ignore result, walk every entry */
Thomas Woerner 71326a
+			res = walk_tree(path);
Steve Grubb d5ab53
+		}
Steve Grubb d5ab53
+		level--;
Thomas Woerner 71326a
+
Thomas Woerner 71326a
+		closedir(dir);
Steve Grubb d5ab53
 	}
Steve Grubb d5ab53
-	return __errors;
Steve Grubb d5ab53
+
Steve Grubb d5ab53
+	return 1;
Steve Grubb d5ab53
 }
Steve Grubb d5ab53
 
Steve Grubb d5ab53
 int main(int argc, char *argv[])
Thomas Woerner 71326a
@@ -762,15 +830,22 @@
Thomas Woerner 71326a
 				if (*line == '\0')
Thomas Woerner 71326a
 					continue;
Thomas Woerner 71326a
 
Thomas Woerner 71326a
-				had_errors += walk_tree(line);
Thomas Woerner 71326a
+				/* ignore result of walk_tree, use __errors */
Thomas Woerner 71326a
+				__errors = 0;
Thomas Woerner 71326a
+				walk_tree(line);
Thomas Woerner 71326a
+				had_errors += __errors;
Thomas Woerner 71326a
 			}
Thomas Woerner 71326a
 			if (!feof(stdin)) {
Thomas Woerner 71326a
 				fprintf(stderr, _("%s: Standard input: %s\n"),
Thomas Woerner 71326a
 				        progname, strerror(errno));
Thomas Woerner 71326a
 				had_errors++;
Thomas Woerner 71326a
 			}
Thomas Woerner 71326a
-		} else
Thomas Woerner 71326a
-			had_errors += walk_tree(argv[optind]);
Thomas Woerner 71326a
+		} else {
Thomas Woerner 71326a
+			/* ignore result of walk_tree, use __errors */
Thomas Woerner 71326a
+			__errors = 0;
Thomas Woerner 71326a
+			walk_tree(argv[optind]);
Thomas Woerner 71326a
+			had_errors += __errors;
Thomas Woerner 71326a
+		}
Thomas Woerner 71326a
 		optind++;
Thomas Woerner 71326a
 	} while (optind < argc);
Thomas Woerner 71326a