diff --git a/include/walk_tree.h b/include/walk_tree.h index 9f1ec34..344c7ef 100644 --- a/include/walk_tree.h +++ b/include/walk_tree.h @@ -25,15 +25,17 @@ #define WALK_TREE_LOGICAL 0x04 #define WALK_TREE_DEREFERENCE 0x08 #define WALK_TREE_DEREFERENCE_TOPLEVEL 0x10 +#define WALK_TREE_ONEFILESYSTEM 0x20 #define WALK_TREE_TOPLEVEL 0x100 #define WALK_TREE_SYMLINK 0x200 #define WALK_TREE_FAILED 0x400 +#define WALK_TREE_STOP 0x800 struct stat; extern int walk_tree(const char *path, int walk_flags, unsigned int num, int (*func)(const char *, const struct stat *, int, - void *), void *arg); + void *), void *arg, dev_t fs_id); #endif diff --git a/libmisc/walk_tree.c b/libmisc/walk_tree.c index d4a7dcd..8e85287 100644 --- a/libmisc/walk_tree.c +++ b/libmisc/walk_tree.c @@ -58,7 +58,7 @@ static int walk_tree_visited(dev_t dev, ino_t ino) static int walk_tree_rec(const char *path, int walk_flags, int (*func)(const char *, const struct stat *, int, - void *), void *arg, int depth) + void *), void *arg, int depth, dev_t fs_id) { int follow_symlinks = (walk_flags & WALK_TREE_LOGICAL) || ((walk_flags & WALK_TREE_DEREFERENCE) && @@ -78,6 +78,12 @@ static int walk_tree_rec(const char *path, int walk_flags, if (lstat(path, &st) != 0) return func(path, NULL, flags | WALK_TREE_FAILED, arg); + + /* if file is on another filesystem, stop */ + if((flags & WALK_TREE_ONEFILESYSTEM) && (st.st_dev != fs_id )) { + return func(path, NULL, flags | WALK_TREE_STOP, arg); + } + if (S_ISLNK(st.st_mode)) { flags |= WALK_TREE_SYMLINK; if ((flags & WALK_TREE_DEREFERENCE) || @@ -181,7 +187,7 @@ close_another_dir: *path_end++ = '/'; strcpy(path_end, entry->d_name); err += walk_tree_rec(path, walk_flags, func, arg, - depth + 1); + depth + 1, fs_id); *--path_end = 0; if (!dir.stream) { /* Reopen the directory handle. */ @@ -210,7 +216,7 @@ close_another_dir: int walk_tree(const char *path, int walk_flags, unsigned int num, int (*func)(const char *, const struct stat *, int, void *), - void *arg) + void *arg, dev_t fs_id) { char path_copy[FILENAME_MAX]; @@ -228,5 +234,5 @@ int walk_tree(const char *path, int walk_flags, unsigned int num, return func(path, NULL, WALK_TREE_FAILED, arg); } strcpy(path_copy, path); - return walk_tree_rec(path_copy, walk_flags, func, arg, 0); + return walk_tree_rec(path_copy, walk_flags, func, arg, 0, fs_id); } diff --git a/tools/getfacl.c b/tools/getfacl.c index e3df09c..bf6931b 100644 --- a/tools/getfacl.c +++ b/tools/getfacl.c @@ -42,7 +42,7 @@ #define POSIXLY_CORRECT_STR "POSIXLY_CORRECT" #if !POSIXLY_CORRECT -# define CMD_LINE_OPTIONS "aceEsRLPtpndvh" +# define CMD_LINE_OPTIONS "aceEsRXLPtpndvh" #endif #define POSIXLY_CMD_LINE_OPTIONS "d" @@ -59,6 +59,7 @@ struct option long_options[] = { { "tabular", 0, 0, 't' }, { "absolute-names", 0, 0, 'p' }, { "numeric", 0, 0, 'n' }, + { "one-file-system", 0, 0, 'X'}, #endif { "default", 0, 0, 'd' }, { "version", 0, 0, 'v' }, @@ -85,6 +86,8 @@ int had_errors; int absolute_warning; /* Absolute path warning was issued */ int print_options = TEXT_SOME_EFFECTIVE; int opt_numeric; /* don't convert id's to symbolic names */ +int opt_onefilesystem; /* get ACL only on current filesystem */ +struct stat st_onefilesystem; /* stat of file (command line argument) */ static const char *xquote(const char *str, const char *quote_chars) @@ -455,6 +458,10 @@ int do_print(const char *path_p, const struct stat *st, int walk_flags, void *un return 1; } + if (walk_flags & WALK_TREE_STOP ) { + return 0; + } + /* * Symlinks can never have ACLs, so when doing a physical walk, we * skip symlinks altogether, and when doing a half-logical walk, we @@ -588,6 +595,7 @@ void help(void) " -P, --physical physical walk, do not follow symbolic links\n" " -t, --tabular use tabular output format\n" " -n, --numeric print numeric user/group identifiers\n" +" -X, --one-file-system skip files on different filesystems\n" " -p, --absolute-names don't strip leading '/' in pathnames\n")); } #endif @@ -699,6 +707,11 @@ int main(int argc, char *argv[]) print_options |= TEXT_NUMERIC_IDS; break; + case 'X': /* one filesystem */ + opt_onefilesystem = 1; + walk_flags |= WALK_TREE_ONEFILESYSTEM; + break; + case 'v': /* print version */ printf("%s " VERSION "\n", progname); return 0; @@ -731,7 +744,7 @@ int main(int argc, char *argv[]) continue; had_errors += walk_tree(line, walk_flags, 0, - do_print, NULL); + do_print, NULL, 0); } if (!feof(stdin)) { fprintf(stderr, _("%s: Standard input: %s\n"), @@ -739,9 +752,15 @@ int main(int argc, char *argv[]) had_errors++; } } else + if (opt_onefilesystem) { + if( stat(argv[optind], &st_onefilesystem) != 0 ) { + opt_onefilesystem = 0; + } + } + had_errors += walk_tree(argv[optind], walk_flags, 0, - do_print, NULL); - optind++; + do_print, NULL, st_onefilesystem.st_dev); + optind++; } while (optind < argc); return had_errors ? 1 : 0; diff --git a/tools/setfacl.c b/tools/setfacl.c index 0844ca2..74b9923 100644 --- a/tools/setfacl.c +++ b/tools/setfacl.c @@ -311,14 +311,14 @@ int next_file(const char *arg, seq_t seq) if (strcmp(arg, "-") == 0) { while ((line = __acl_next_line(stdin))) - errors = walk_tree(line, walk_flags, 0, do_set, &args); + errors = walk_tree(line, walk_flags, 0, do_set, &args, 0); if (!feof(stdin)) { fprintf(stderr, _("%s: Standard input: %s\n"), progname, strerror(errno)); errors = 1; } } else { - errors = walk_tree(arg, walk_flags, 0, do_set, &args); + errors = walk_tree(arg, walk_flags, 0, do_set, &args, 0); } return errors ? 1 : 0; }