Index: acl-2.2.45/doc/CHANGES =================================================================== --- acl-2.2.45.orig/doc/CHANGES +++ acl-2.2.45/doc/CHANGES @@ -2,6 +2,12 @@ * Update acl.5 man page to clarify the relationship between the file permissions and the *OBJ ACL entries thanks to Andreas Gruenbacher. +* In some cases, gcc does not link in functions from libmisc.a + unless libmisc is specifief before the dynamic libraries on + the command line. +* Rip out nftw tree walking, it is broken and hopeless to fix. + The replacement walk_tree() function does exactly what we + want, and is much simpler to use. 2.2.45 (11 September 2007) * Fix symlink handling with getfacl and setfacl, thanks to Utako Usaka. Index: acl-2.2.45/getfacl/Makefile =================================================================== --- acl-2.2.45.orig/getfacl/Makefile +++ acl-2.2.45/getfacl/Makefile @@ -9,8 +9,8 @@ LTCOMMAND = getfacl CFILES = getfacl.c user_group.c HFILES = user_group.h -LLDLIBS = $(LIBACL) $(LIBATTR) $(LIBMISC) -LTDEPENDENCIES = $(LIBACL) $(LIBMISC) +LLDLIBS = $(LIBMISC) $(LIBACL) $(LIBATTR) +LTDEPENDENCIES = $(LIBMISC) $(LIBACL) default: $(LTCOMMAND) Index: acl-2.2.45/getfacl/getfacl.c =================================================================== --- acl-2.2.45.orig/getfacl/getfacl.c +++ acl-2.2.45/getfacl/getfacl.c @@ -34,10 +34,10 @@ #include #include #include -#include #include #include "config.h" #include "user_group.h" +#include "walk_tree.h" #include "misc.h" #define POSIXLY_CORRECT_STR "POSIXLY_CORRECT" @@ -70,24 +70,22 @@ struct option long_options[] = { 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_print_acl = 0; -int opt_print_default_acl = 0; +int walk_flags = WALK_TREE_DEREFERENCE; +int opt_print_acl; +int opt_print_default_acl; int opt_strip_leading_slash = 1; int opt_comments = 1; /* include comments */ -int opt_skip_base = 0; /* skip files that only have the base entries */ -int opt_tabular = 0; /* tabular output format (alias `showacl') */ +int opt_skip_base; /* skip files that only have the base entries */ +int opt_tabular; /* tabular output format (alias `showacl') */ #if POSIXLY_CORRECT const int posixly_correct = 1; /* Posix compatible behavior! */ #else -int posixly_correct = 0; /* Posix compatible behavior? */ +int posixly_correct; /* Posix compatible behavior? */ #endif -int had_errors = 0; -int absolute_warning = 0; /* Absolute path warning was issued */ +int had_errors; +int absolute_warning; /* Absolute path warning was issued */ int print_options = TEXT_SOME_EFFECTIVE; -int opt_numeric = 0; /* don't convert id's to symbolic names */ +int opt_numeric; /* don't convert id's to symbolic names */ static const char *xquote(const char *str) @@ -425,12 +423,18 @@ acl_get_file_mode(const char *path_p) return acl_from_mode(st.st_mode); } -int do_print(const char *path_p, const struct stat *st) +int do_print(const char *path_p, const struct stat *st, int walk_flags, void *unused) { const char *default_prefix = NULL; acl_t acl = NULL, default_acl = NULL; int error = 0; + if (walk_flags & WALK_TREE_FAILED) { + fprintf(stderr, "%s: %s: %s\n", progname, xquote(path_p), + strerror(errno)); + return 1; + } + if (opt_print_acl) { acl = acl_get_file(path_p, ACL_TYPE_ACCESS); if (acl == NULL && (errno == ENOSYS || errno == ENOTSUP)) @@ -549,7 +553,7 @@ void help(void) " --skip-base skip files that only have the base entries\n" " -R, --recursive recurse into subdirectories\n" " -L, --logical logical walk, follow symbolic links\n" -" -P --physical physical walk, do not follow symbolic links\n" +" -P, --physical physical walk, do not follow symbolic links\n" " --tabular use tabular output format\n" " --numeric print numeric user/group identifiers\n" " --absolute-names don't strip leading '/' in pathnames\n")); @@ -560,75 +564,6 @@ void help(void) " --help this help text\n")); } - -static int __errors; -int __do_print(const char *file, const struct stat *stat, - int flag, struct FTW *ftw) -{ - int saved_errno = errno; - - /* 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))) - return 0; - - if (do_print(file, stat)) - __errors++; - - 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)); - return 0; - } - - /* We also get here in non-recursive mode. In that case, - return something != 0 to abort nftw. */ - - if (!opt_recursive) - return 1; - - return 0; -} - -char *resolve_symlinks(const char *file) -{ - static char buffer[4096]; - struct stat stat; - char *path = NULL; - - if (lstat(file, &stat) == -1) - return path; - - if (S_ISLNK(stat.st_mode) && !opt_walk_physical) - path = realpath(file, buffer); - else - path = (char *)file; /* not a symlink, use given path */ - - 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)); - __errors++; - } - return __errors; -} - int main(int argc, char *argv[]) { int opt; @@ -691,21 +626,21 @@ int main(int argc, char *argv[]) case 'R': /* recursive */ if (posixly_correct) goto synopsis; - opt_recursive = 1; + walk_flags |= WALK_TREE_RECURSIVE; break; case 'L': /* follow all symlinks */ if (posixly_correct) goto synopsis; - opt_walk_logical = 1; - opt_walk_physical = 0; + walk_flags |= WALK_TREE_LOGICAL; + walk_flags &= ~WALK_TREE_PHYSICAL; break; case 'P': /* skip all symlinks */ if (posixly_correct) goto synopsis; - opt_walk_logical = 0; - opt_walk_physical = 1; + walk_flags |= WALK_TREE_PHYSICAL; + walk_flags &= ~WALK_TREE_LOGICAL; break; case 's': /* skip files with only base entries */ @@ -762,7 +697,7 @@ int main(int argc, char *argv[]) if (*line == '\0') continue; - had_errors += walk_tree(line); + had_errors += walk_tree(line, walk_flags, do_print, NULL); } if (!feof(stdin)) { fprintf(stderr, _("%s: Standard input: %s\n"), @@ -770,7 +705,7 @@ int main(int argc, char *argv[]) had_errors++; } } else - had_errors += walk_tree(argv[optind]); + had_errors += walk_tree(argv[optind], walk_flags, do_print, NULL); optind++; } while (optind < argc); Index: acl-2.2.45/libmisc/Makefile =================================================================== --- acl-2.2.45.orig/libmisc/Makefile +++ acl-2.2.45/libmisc/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/include/builddefs LTLIBRARY = libmisc.la LTLDFLAGS = -CFILES = quote.c unquote.c high_water_alloc.c next_line.c +CFILES = quote.c unquote.c high_water_alloc.c next_line.c walk_tree.c default: $(LTLIBRARY) install install-dev install-lib: Index: acl-2.2.45/setfacl/Makefile =================================================================== --- acl-2.2.45.orig/setfacl/Makefile +++ acl-2.2.45/setfacl/Makefile @@ -9,8 +9,8 @@ LTCOMMAND = setfacl CFILES = setfacl.c do_set.c sequence.c parse.c HFILES = sequence.h parse.h -LLDLIBS = $(LIBACL) $(LIBATTR) $(LIBMISC) -LTDEPENDENCIES = $(LIBACL) $(LIBMISC) +LLDLIBS = $(LIBMISC) $(LIBACL) $(LIBATTR) +LTDEPENDENCIES = $(LIBMISC) $(LIBACL) default: $(LTCOMMAND) Index: acl-2.2.45/setfacl/do_set.c =================================================================== --- acl-2.2.45.orig/setfacl/do_set.c +++ acl-2.2.45/setfacl/do_set.c @@ -36,10 +36,10 @@ #include "sequence.h" #include "parse.h" #include "config.h" +#include "walk_tree.h" extern const char *progname; -extern int opt_recursive; extern int opt_recalculate; extern int opt_test; extern int print_options; @@ -259,8 +259,10 @@ int do_set( const char *path_p, const struct stat *st, - const seq_t seq) + int walk_flags, + void *arg) { + const seq_t seq = (const seq_t)arg; acl_t old_acl = NULL, old_default_acl = NULL; acl_t acl = NULL, default_acl = NULL; acl_t *xacl, *old_xacl; @@ -272,6 +274,11 @@ do_set( int acl_modified = 0, default_acl_modified = 0; int acl_mask_provided = 0, default_acl_mask_provided = 0; + if (walk_flags & WALK_TREE_FAILED) { + fprintf(stderr, "%s: %s: %s\n", progname, path_p, strerror(errno)); + return 1; + } + /* Execute the commands in seq (read ACLs on demand) */ error = seq_get_cmd(seq, SEQ_FIRST_CMD, &cmd); if (error == 0) @@ -426,7 +433,7 @@ do_set( } /* Only directores can have default ACLs */ - if (default_acl && !S_ISDIR(st->st_mode) && opt_recursive) { + if (default_acl && !S_ISDIR(st->st_mode) && (walk_flags & WALK_TREE_RECURSIVE)) { /* In recursive mode, ignore default ACLs for files */ acl_free(default_acl); default_acl = NULL; Index: acl-2.2.45/setfacl/setfacl.c =================================================================== --- acl-2.2.45.orig/setfacl/setfacl.c +++ acl-2.2.45/setfacl/setfacl.c @@ -28,20 +28,15 @@ #include #include #include -#include #include #include #include "config.h" #include "sequence.h" #include "parse.h" +#include "walk_tree.h" #include "misc.h" -extern int -do_set( - const char *path_p, - const struct stat *stat_p, - const seq_t seq); - +extern int do_set(const char *path_p, const struct stat *stat_p, int flags, void *arg); #define POSIXLY_CORRECT_STR "POSIXLY_CORRECT" @@ -82,9 +77,7 @@ struct option long_options[] = { const char *progname; const char *cmd_line_options, *cmd_line_spec; -int opt_recursive; /* recurse into sub-directories? */ -int opt_walk_logical; /* always follow symbolic links */ -int opt_walk_physical; /* never follow symbolic links */ +int walk_flags = WALK_TREE_DEREFERENCE; int opt_recalculate; /* recalculate mask entry (0=default, 1=yes, -1=no) */ int opt_promote; /* promote access ACL to default ACL */ int opt_test; /* do not write to the file system. @@ -188,7 +181,7 @@ restore( stat.st_uid = uid; stat.st_gid = gid; - error = do_set(path_p, &stat, seq); + error = do_set(path_p, &stat, 0, seq); if (error != 0) { status = 1; goto resume; @@ -275,77 +268,6 @@ void help(void) } -static int __errors; -static seq_t __seq; - -int __do_set(const char *file, const struct stat *stat, - int flag, struct FTW *ftw) -{ - int saved_errno = errno; - - /* 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))) - return 0; - - if (do_set(file, stat, __seq)) - __errors++; - - 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)); - return 0; - } - - /* We also get here in non-recursive mode. In that case, - return something != 0 to abort nftw. */ - - if (!opt_recursive) - return 1; - - return 0; -} - -char *resolve_symlinks(const char *file) -{ - static char buffer[4096]; - struct stat stat; - char *path = NULL; - - if (lstat(file, &stat) == -1) - return path; - - if (S_ISLNK(stat.st_mode) && !opt_walk_physical) - path = realpath(file, buffer); - else - path = (char *)file; /* not a symlink, use given path */ - - return path; -} - -int walk_tree(const char *file, seq_t seq) -{ - const char *p; - - __errors = 0; - __seq = seq; - if ((p = resolve_symlinks(file)) == NULL) { - fprintf(stderr, "%s: %s: %s\n", progname, - xquote(file), strerror(errno)); - __errors++; - } else if (nftw(p, __do_set, 0, opt_walk_logical ? 0 : FTW_PHYS) < 0) { - fprintf(stderr, "%s: %s: %s\n", progname, - xquote(file), strerror(errno)); - __errors++; - } - return __errors; -} - int next_file(const char *arg, seq_t seq) { char *line; @@ -353,14 +275,14 @@ int next_file(const char *arg, seq_t seq if (strcmp(arg, "-") == 0) { while ((line = next_line(stdin))) - errors = walk_tree(line, seq); + errors = walk_tree(line, walk_flags, do_set, seq); if (!feof(stdin)) { fprintf(stderr, _("%s: Standard input: %s\n"), progname, strerror(errno)); errors = 1; } } else { - errors = walk_tree(arg, seq); + errors = walk_tree(arg, walk_flags, do_set, seq); } return errors ? 1 : 0; } @@ -627,17 +549,17 @@ int main(int argc, char *argv[]) break; case 'R': /* recursive */ - opt_recursive = 1; + walk_flags |= WALK_TREE_RECURSIVE; break; case 'L': /* follow symlinks */ - opt_walk_logical = 1; - opt_walk_physical = 0; + walk_flags |= WALK_TREE_LOGICAL; + walk_flags &= ~WALK_TREE_PHYSICAL; break; case 'P': /* do not follow symlinks */ - opt_walk_logical = 0; - opt_walk_physical = 1; + walk_flags |= WALK_TREE_PHYSICAL; + walk_flags &= ~WALK_TREE_LOGICAL; break; case 't': /* test mode */ Index: acl-2.2.45/include/walk_tree.h =================================================================== --- /dev/null +++ acl-2.2.45/include/walk_tree.h @@ -0,0 +1,18 @@ +#ifndef __WALK_TREE_H +#define __WALK_TREE_H + +#define WALK_TREE_RECURSIVE 0x1 +#define WALK_TREE_PHYSICAL 0x2 +#define WALK_TREE_LOGICAL 0x4 +#define WALK_TREE_DEREFERENCE 0x8 + +#define WALK_TREE_SYMLINK 0x10 +#define WALK_TREE_FAILED 0x20 + +struct stat; + +extern int walk_tree(const char *path, int walk_flags, + int (*func)(const char *, const struct stat *, int, void *), + void *arg); + +#endif Index: acl-2.2.45/libmisc/walk_tree.c =================================================================== --- /dev/null +++ acl-2.2.45/libmisc/walk_tree.c @@ -0,0 +1,100 @@ +/* + File: walk_tree.c + + Copyright (C) 2007 Andreas Gruenbacher + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "walk_tree.h" + +static int walk_tree_rec(const char *path, int walk_flags, + int (*func)(const char *, const struct stat *, int, void *), + void *arg, int depth) +{ + int (*xstat)(const char *, struct stat *) = lstat; + struct stat st; + int local_walk_flags = walk_flags, err; + + /* Default to traversing symlinks on the command line, traverse all symlinks + * with -L, and do not traverse symlinks with -P. (This is similar to chown.) + */ + +follow_symlink: + if (xstat(path, &st) != 0) + return func(path, NULL, local_walk_flags | WALK_TREE_FAILED, arg); + if (S_ISLNK(st.st_mode)) { + if ((local_walk_flags & WALK_TREE_PHYSICAL) || + (!(local_walk_flags & WALK_TREE_LOGICAL) && depth > 1)) + return 0; + local_walk_flags |= WALK_TREE_SYMLINK; + xstat = stat; + if (local_walk_flags & WALK_TREE_DEREFERENCE) + goto follow_symlink; + } + err = func(path, &st, local_walk_flags, arg); + if ((local_walk_flags & WALK_TREE_RECURSIVE) && + (S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode))) { + char path2[FILENAME_MAX]; + DIR *dir; + struct dirent *entry; + int err2; + + dir = opendir(path); + if (!dir) { + /* PATH may be a symlink to a regular file or a dead symlink + * which we didn't follow above. + */ + if (errno != ENOTDIR && errno != ENOENT) + err += func(path, &st, + local_walk_flags | WALK_TREE_FAILED, arg); + return err; + } + while ((entry = readdir(dir)) != NULL) { + if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) + continue; + err2 = snprintf(path2, sizeof(path2), "%s/%s", path, + entry->d_name); + if (err2 < 0 || err2 > FILENAME_MAX) { + errno = ENAMETOOLONG; + err += func(path, NULL, + local_walk_flags | WALK_TREE_FAILED, arg); + continue; + } + err += walk_tree_rec(path2, walk_flags, func, arg, depth + 1); + } + if (closedir(dir) != 0) + err += func(path, &st, local_walk_flags | WALK_TREE_FAILED, arg); + } + return err; +} + +int walk_tree(const char *path, int walk_flags, + int (*func)(const char *, const struct stat *, int, void *), void *arg) +{ + if (strlen(path) >= FILENAME_MAX) { + errno = ENAMETOOLONG; + return func(path, NULL, WALK_TREE_FAILED, arg); + } + return walk_tree_rec(path, walk_flags, func, arg, 1); +}