From b2af30c5bed65edf0a59a85e8d8b759317aeaf2c Mon Sep 17 00:00:00 2001 From: Jiří Moskovčák Date: Nov 07 2007 09:49:31 +0000 Subject: New walk tree patch - better symlink handling --- diff --git a/acl-2.2.39-walk.patch b/acl-2.2.39-walk.patch index 01194f6..e8c2607 100644 --- a/acl-2.2.39-walk.patch +++ b/acl-2.2.39-walk.patch @@ -1,152 +1,13 @@ ---- acl-2.2.39/getfacl/getfacl.c.walk 2006-06-20 08:51:25.000000000 +0200 -+++ acl-2.2.39/getfacl/getfacl.c 2007-03-21 10:52:07.000000000 +0100 -@@ -34,7 +34,6 @@ - #include - #include - #include --#include - #include - #include "config.h" - #include "user_group.h" -@@ -70,9 +69,9 @@ - const char *progname; - const char *cmd_line_options; - --int opt_recursive; /* recurse into sub-directories? */ --int opt_walk_logical; /* always follow symbolic links */ --int opt_walk_physical; /* never follow symbolic links */ -+int opt_recursive = 0; /* recurse into sub-directories? */ -+int opt_walk_logical = 0; /* always follow symbolic links */ -+int opt_walk_physical = 0; /* never follow symbolic links */ - int opt_print_acl = 0; - int opt_print_default_acl = 0; - int opt_strip_leading_slash = 1; -@@ -562,71 +561,140 @@ - - - static int __errors; --int __do_print(const char *file, const struct stat *stat, -- int flag, struct FTW *ftw) -+ -+int walk_tree(const char *file) +--- acl-2.2.39/getfacl/getfacl.c 2007-11-07 09:49:56.000000000 +0100 ++++ ../devel/acl-2.2.45/getfacl/getfacl.c 2007-11-07 09:53:50.000000000 +0100 +@@ -598,17 +598,17 @@ int __do_print(const char *file, const s + char *resolve_symlinks(const char *file) { -- int saved_errno = errno; -+ static int level = 0; -+ static int link_count = 0; -+ DIR *dir; -+ struct dirent *entry; -+ struct stat buf; -+ char path[FILENAME_MAX]; -+ char path2[FILENAME_MAX]; -+ char path3[FILENAME_MAX]; -+ char *dir_name; -+ size_t len; -+ ssize_t slen; -+ int res; - - /* Process the target of a symbolic link, and traverse the link, - only if doing a logical walk, or if the symbolic link was - specified on the command line. Always skip symbolic links if - doing a physical walk. */ - -- if (S_ISLNK(stat->st_mode) && -- (opt_walk_physical || (ftw->level > 0 && !opt_walk_logical))) -+ len = strlen(file); -+ /* check for FILENAME_MAX */ -+ if (len >= FILENAME_MAX) { -+ fprintf(stderr, "%s: %s: %s\n", progname, xquote(file), -+ strerror(ENAMETOOLONG)); -+ __errors++; - return 0; -+ } -+ /* string ends with '/', remove it and restart */ -+ if (len > 1 && file[len-1] == '/') { -+ strncpy(path, file, len); -+ path[len-1] = '\0'; /* overwrite slash */ -+ return walk_tree(path); -+ } - -- if (do_print(file, stat)) -- __errors++; -+ if (level > 0 && !opt_recursive) -+ return 0; - -- if (flag == FTW_DNR && opt_recursive) { -- /* Item is a directory which can't be read. */ -- fprintf(stderr, "%s: %s: %s\n", -- progname, file, strerror(saved_errno)); -+ if (lstat(file, &buf) != 0) { -+ fprintf(stderr, "%s: %s: %s\n", progname, xquote(file), -+ strerror(errno)); -+ __errors++; - return 0; - } - -- /* We also get here in non-recursive mode. In that case, -- return something != 0 to abort nftw. */ -+ if (S_ISLNK(buf.st_mode)) { -+ /* physical means: no links at all */ -+ if (opt_walk_physical) -+ return 1; -+ -+ /* logical: show information or walk if points to directory -+ * also for symbolic link arguments on level 0 */ -+ if (opt_walk_logical || level == 0) { -+ /* copy and append terminating '\0' */ -+ strncpy(path2, file, len+1); -+ -+ /* get directory name */ -+ dir_name = dirname(path2); -+ -+ /* get link target */ -+ slen = readlink(file, path, FILENAME_MAX-1); -+ if (slen < 0) { -+ fprintf(stderr, "%s: %s: %s\n", progname, -+ xquote(file), strerror(errno)); -+ __errors++; -+ return 0; -+ } -+ path[slen] = '\0'; - -- if (!opt_recursive) -- return 1; -+ if (slen == 0 || path[0] == '/') { -+ /* absolute: -+ * copy and append terminating '\0' */ -+ strncpy(path3, path, slen+1); -+ } else -+ /* relative */ -+ snprintf(path3, FILENAME_MAX, "%s/%s", -+ dir_name, path); -+ -+ if (lstat(path3, &buf) != 0) { -+ fprintf(stderr, "%s: %s: %s\n", progname, -+ xquote(path), strerror(errno)); -+ __errors++; -+ return 0; -+ } - -- return 0; --} -+ if ((S_ISDIR(buf.st_mode) && opt_recursive && -+ link_count < 1) || S_ISLNK(buf.st_mode)) { -+ /* walk directory or follow symlink on level -+ * 0 */ -+ link_count++; -+ res = walk_tree(path3); -+ link_count--; -+ if (res != 1) -+ return 0; -+ } else -+ if (do_print(path3, &buf)) -+ __errors++; - --char *resolve_symlinks(const char *file) --{ -- static char buffer[4096]; -- char *path = NULL; + static char buffer[4096]; ++ struct stat stat; + char *path = NULL; - ssize_t len; -- + - len = readlink(file, buffer, sizeof(buffer)-1); - if (len < 0) { - if (errno == EINVAL) /* not a symlink, use given path */ @@ -154,82 +15,15 @@ - } else { - buffer[len+1] = '\0'; - path = buffer; -+ return 1; -+ } - } -- return path; --} -- --int walk_tree(const char *file) --{ -- const char *p; - -- __errors = 0; -- if ((p = resolve_symlinks(file)) == NULL) { -- fprintf(stderr, "%s: %s: %s\n", progname, -- xquote(file), strerror(errno)); -- __errors++; -- } else if (nftw(p, __do_print, 0, opt_walk_logical? 0 : FTW_PHYS) < 0) { -- fprintf(stderr, "%s: %s: %s\n", progname, xquote(file), -- strerror(errno)); -+ if (do_print(file, &buf)) - __errors++; -+ -+ /* it is a directory, walk */ -+ if (S_ISDIR(buf.st_mode)) { -+ dir = opendir(file); -+ if (!dir) { -+ fprintf(stderr, "%s: %s: %s\n", progname, -+ xquote(file), strerror(errno)); -+ __errors++; -+ return 0; -+ } +- } ++ if (lstat(file, &stat) == -1) ++ return path; + -+ level++; -+ while ((entry = readdir(dir)) != NULL) { -+ if (! strcmp(entry->d_name, ".") || -+ ! strcmp(entry->d_name, "..")) -+ continue; ++ if (S_ISLNK(stat.st_mode) && !opt_walk_physical) ++ path = realpath(file, buffer); ++ else ++ path = (char *)file; /* not a symlink, use given path */ + -+ snprintf(path, FILENAME_MAX, "%s/%s", file, -+ entry->d_name); -+ -+ /* ignore result, walk every entry */ -+ res = walk_tree(path); -+ } -+ level--; -+ -+ closedir(dir); - } -- return __errors; -+ -+ return 1; + return path; } - int main(int argc, char *argv[]) -@@ -762,15 +830,22 @@ - if (*line == '\0') - continue; - -- had_errors += walk_tree(line); -+ /* ignore result of walk_tree, use __errors */ -+ __errors = 0; -+ walk_tree(line); -+ had_errors += __errors; - } - if (!feof(stdin)) { - fprintf(stderr, _("%s: Standard input: %s\n"), - progname, strerror(errno)); - had_errors++; - } -- } else -- had_errors += walk_tree(argv[optind]); -+ } else { -+ /* ignore result of walk_tree, use __errors */ -+ __errors = 0; -+ walk_tree(argv[optind]); -+ had_errors += __errors; -+ } - optind++; - } while (optind < argc); - diff --git a/acl.spec b/acl.spec index 91d77e2..e783100 100644 --- a/acl.spec +++ b/acl.spec @@ -1,7 +1,7 @@ Summary: Access control list utilities Name: acl Version: 2.2.39 -Release: 4%{?dist} +Release: 5%{?dist} BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: libattr-devel >= 2.4.1 Source: ftp://oss.sgi.com/projects/xfs/cmd_tars/acl_%{version}-1.tar.gz @@ -102,6 +102,9 @@ rm -rf $RPM_BUILD_ROOT /%{_lib}/libacl.so.* %changelog +* Wed Nov 7 2007 Jiri Moskovcak 2.2.39-5 +- New walk patch backported from upstream - better symlink handling + * Thu Sep 20 2007 Jiri Moskovcak 2.2.39-4 - Rewriten path_max patch to support long UTF8 names - Resolves #287701, #183181