acl and attr: Fix path walking code
Hello,
the tree walking code in acl and attr broke when resolve_symlinks() was introduced (by me, unfortunately). Following symlinks passed in on the command line is the intended behavior for the tools (unless in -P mode). The first version was buggy, and so someone "fixed" it by replacing readlink() with realpath() in resolve_symlinks().
The result is that the output of getfattr and getfacl will show pathnames that may point anywhere. When processing a directory tree it sometimes is helpful to treat symlinks as regular files, but resolving the pathnames is totally wrong.
After runnig into problem after problem with nftw and never ending up with even half-way clean code, I think it's time to ditch it altogether and replace it with sane code. So here are two patches, one for attr and one for acl, that does that.
Files include/walk_tree.h and libmisc/walk_tree.c are identical in both patches; that code is shared between the two packages.
Okay to apply?
Thanks,
Andreas
getfacl/getfacl.c +32 -90
@@ -34,10 +34,10 @@#include <dirent.h> #include <libgen.h> #include <getopt.h> -#include <ftw.h> #include <locale.h> #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,23 @@ 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 ((walk_flags &WALK_TREE_SYMLINK ) && + ((walk_flags &WALK_TREE_PHYSICAL ) || + !(walk_flags & (WALK_TREE_TOPLEVEL |WALK_TREE_LOGICAL )))) +return 0 ; +if (opt_print_acl) { acl =acl_get_file (path_p,ACL_TYPE_ACCESS );if (acl ==NULL && (errno ==ENOSYS || errno ==ENOTSUP ))
@@ -549,7 +558,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 +569,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 +631,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 +702,8 @@ int main(int argc, char *argv[])if (*line =='\0' )continue ; - had_errors +=walk_tree (line); + had_errors +=walk_tree (line, walk_flags,0 , + do_print,NULL ); }if (!feof (stdin)) { fprintf(stderr, _("%s: Standard input: %s\n"),
@@ -770,7 +711,8 @@ int main(int argc, char *argv[]) had_errors++; } }else - had_errors +=walk_tree (argv[optind]); + had_errors +=walk_tree (argv[optind], walk_flags,0 , + do_print,NULL ); optind++; }while (optind < argc);
libmisc/Makefile +1 -1
@@ -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:
setfacl/do_set.c +15 -3
@@ -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 @@ intdo_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,16 @@ 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 ; + } + +if ((walk_flags &WALK_TREE_SYMLINK ) && + ((walk_flags &WALK_TREE_PHYSICAL ) || + !(walk_flags & (WALK_TREE_TOPLEVEL |WALK_TREE_LOGICAL )))) +return 0 ; +/* Execute the commands in seq (read ACLs on demand) */ error =seq_get_cmd (seq,SEQ_FIRST_CMD , &cmd);if (error ==0 )
@@ -426,7 +438,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 ;
setfacl/setfacl.c +11 -89
155 lines not on this page · raw message
include/walk_tree.h new file +19 -0
@@ -0,0 +1,19 @@ +#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_TOPLEVEL 0x100 +#define WALK_TREE_SYMLINK 0x200 +#define WALK_TREE_FAILED 0x400 + +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); + +#endif
libmisc/walk_tree.c new file +188 -0
188 lines not on this page · raw message
getfattr/getfattr.c +23 -73
169 lines not on this page · raw message
libmisc/Makefile +1 -1
@@ -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:
test/attr.test +24 -29
110 lines not on this page · raw message
include/walk_tree.h new file +19 -0
@@ -0,0 +1,19 @@ +#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_TOPLEVEL 0x100 +#define WALK_TREE_SYMLINK 0x200 +#define WALK_TREE_FAILED 0x400 + +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); + +#endif
libmisc/walk_tree.c new file +188 -0
188 lines not on this page · raw message
test/getfattr.test new file +52 -0
52 lines not on this page · raw message
Hi Andreas,
Quoted 6 lines · Andreas Gruenbacher
Hello,
the tree walking code in acl and attr broke when
resolve_symlinks()was introduced (by me, unfortunately). Following symlinks passed in on the command line is the intended behavior for the tools (unless in -P mode). The first version was buggy, and so someone "fixed" it by replacingreadlink()withrealpath()inresolve_symlinks().The result is that the output of getfattr and getfacl will show pathnames that may point anywhere. When processing a directory tree it sometimes is helpful to treat symlinks as regular files, but resolving the pathnames is totally wrong.
Quoted 9 lines
After runnig into problem after problem with nftw and never ending up with even half-way clean code, I think it's time to ditch it altogether and replace it with sane code. So here are two patches, one for attr and one for acl, that does that.
Files
include/walk_tree.handlibmisc/walk_tree.care identical in both patches; that code is shared between the two packages.Okay to apply?
Thanks,
Andreas
I applied attr patch and tried it out on xfstests/062 (which I believe was based on one of your tests).
==========================================================
062.out.bad 2007-11-09 15:38:09.000000000 +1100 renamed from 062.out 2006-03-28 12:52:32.000000000 +1000 +8 -0
@@ -526,6 +526,10 @@ user.name=0xbabe user.name3=0xdeface +# file: SCRATCH_MNT/lnk +trusted.name=0xbabe +trusted.name3=0xdeface + # file: SCRATCH_MNT/dev/b trusted.name=0xbabe trusted.name3=0xdeface
@@ -562,6 +566,10 @@ user.1=0x3233 user.x=0x797a +# file: SCRATCH_MNT/descend/and/ascend +trusted.9=0x3837 +trusted.a=0x6263 + *** directory descent without following symlinks # file: SCRATCH_MNT/reg
==========================================================
So for the following of symlinks with getfattr -L i.e.
echo "*** directory descent with us following symlinks" getfattr -h -L -R -m '.' -e hex $SCRATCH_MNT
Looking at the 2nd difference...
It now picks up descend/and/ascend which contains the symlink of descend/and --> here/up.
So that makes sense, it is following a symlink which it didn't before and finding a dir, "up" in the linked dir. Good.
Looking at 1st difference...
It is now showing up "lnk" which is a symlink: lnk --> dir So why is it showing this up
and yet it is not showing descend/and (which is a link to here/up)? So yes we are following symlinks but are we supposed
to just do the symlinks themselves as well?
BTW, do we not allow user EAs on symlinks? (I've forgotten)
--Tim
Quoted 42 lines · On Friday 09 November 2007 06:41:21 Timothy Shimmin wrote:
I applied attr patch and tried it out on xfstests/062 (which I believe was based on one of your tests).
==========================================================
062.out.bad 2007-11-09 15:38:09.000000000 +1100 renamed from 062.out 2006-03-28 12:52:32.000000000 +1000 +8
-0@@ -526,6 +526,10 @@ user.name=0xbabe user.name3=0xdeface +# file: SCRATCH_MNT/lnk +trusted.name=0xbabe +trusted.name3=0xdeface + # file: SCRATCH_MNT/dev/b trusted.name=0xbabe trusted.name3=0xdeface@@ -562,6 +566,10 @@ user.1=0x3233 user.x=0x797a +# file: SCRATCH_MNT/descend/and/ascend +trusted.9=0x3837 +trusted.a=0x6263 + *** directory descent without following symlinks # file: SCRATCH_MNT/reg==========================================================
So for the following of symlinks with getfattr -L i.e.
echo "*** directory descent with us following symlinks" getfattr -h -L -R -m '.' -e hex $SCRATCH_MNTLooking at the 2nd difference...
It now picks up descend/and/ascend which contains the symlink of descend/and --> here/up.
So that makes sense, it is following a symlink which it didn't before and finding a dir, "up" in the linked dir. Good.
Quoted 6 lines
Looking at 1st difference...
It is now showing up "lnk" which is a symlink: lnk --> dir So why is it showing this up
and yet it is not showing descend/and (which is a link to here/up)? So yes we are following symlinks but are we supposed
to just do the symlinks themselves as well?
With -h, the utilities operate on the symlinks rather than the files that the symlinks point to. The test case sets attributes on SCRATCH_MNT/lnk, but not on descend/and.
The -h and -L options together don't make much sense actually.
Quoted 1 line
BTW, do we not allow user EAs on symlinks? (I've forgotten)
No we don't --- that's explained on attr(5).
Thanks for looking at this!
Andreas
Quoted 43 lines · Andreas Gruenbacher
Quoted 42 lines · On Friday 09 November 2007 06:41:21 Timothy Shimmin wrote:
I applied attr patch and tried it out on xfstests/062 (which I believe was based on one of your tests).
==========================================================
062.out.bad 2007-11-09 15:38:09.000000000 +1100 renamed from 062.out 2006-03-28 12:52:32.000000000 +1000 +8
-0@@ -526,6 +526,10 @@ user.name=0xbabe user.name3=0xdeface +# file: SCRATCH_MNT/lnk +trusted.name=0xbabe +trusted.name3=0xdeface + # file: SCRATCH_MNT/dev/b trusted.name=0xbabe trusted.name3=0xdeface@@ -562,6 +566,10 @@ user.1=0x3233 user.x=0x797a +# file: SCRATCH_MNT/descend/and/ascend +trusted.9=0x3837 +trusted.a=0x6263 + *** directory descent without following symlinks # file: SCRATCH_MNT/reg==========================================================
So for the following of symlinks with getfattr -L i.e.
echo "*** directory descent with us following symlinks" getfattr -h -L -R -m '.' -e hex $SCRATCH_MNTLooking at the 2nd difference...
It now picks up descend/and/ascend which contains the symlink of descend/and --> here/up.
So that makes sense, it is following a symlink which it didn't before and finding a dir, "up" in the linked dir. Good.
Quoted 10 lines
Quoted 6 lines
Looking at 1st difference...
It is now showing up "lnk" which is a symlink: lnk --> dir So why is it showing this up
and yet it is not showing descend/and (which is a link to here/up)? So yes we are following symlinks but are we supposed
to just do the symlinks themselves as well?With -h, the utilities operate on the symlinks rather than the files that the symlinks point to. The test case sets attributes on SCRATCH_MNT/lnk, but not on descend/and.
Oops, yep, there is no EA on descend/and.
Quoted 3 lines
The -h and -L options together don't make much sense actually.
No they don't :)
So will it not follow the argument but follow any descendents that it finds on the walk.
It kind of looked from the manpage that the -h is about just the argument and not about the walk.
<okay you clarified this below...>
Anyway, I took out the -h with the -L,
i.e. $ getfattr -L -R -m '.' -e hex $SCRATCH_MNT
And it is still reporting
Quoted 4 lines
062.out.bad 2007-11-09 15:38:09.000000000 +1100 line 532
Quoted 4 lines
062.out.bad 2007-11-09 15:38:09.000000000 +1100 renamed from 062.out 2006-03-28 12:52:32.000000000 +1000 +4
-0+# file: SCRATCH_MNT/lnk +trusted.name=0xbabe +trusted.name3=0xdeface +
So I presume following symlinks also mean operating on symlinks too (i.e. getting the EA)?
---
Quoted 11 lines · On Friday 09 November 2007 08:39:56 Timothy Shimmin wrote:
Quoted 4 lines
Quoted 4 lines
You mention -L/-P is like chown.
However, -P for getattr isn't about not walking symlinks to directories,
it's about skipping symlinks altogether, right?Hmm, -L and -P define which files and directories are visited, and -h defines whether we are looking at symlinks or the files they point to. The two concepts are orthogonal. -P is not about skipping symlinks, only about not recursing into them.
Oh okay.
There is the concept of following the symlink for traversal versus following the symlink to get the EA on.
So with -L should it just follow the symlink or look at the symlink first and then follow it?
And will -h modify this behavior?
I'm still confused about the 1st difference in 062 output.
I wonder if the man pages can be clarified in this area :)
--Tim
Quoted 19 lines
Quoted 9 lines · On Friday 09 November 2007 08:39:56 Timothy Shimmin wrote:
Quoted 4 lines
Quoted 4 lines
You mention -L/-P is like chown.
However, -P for getattr isn't about not walking symlinks to directories,
it's about skipping symlinks altogether, right?Hmm, -L and -P define which files and directories are visited, and -h
defines
Quoted 2 lines
whether we are looking at symlinks or the files they point to. The two concepts are orthogonal. -P is not about skipping symlinks, only
about not
Quoted 2 lines
recursing into them.
Oh okay.
There is the concept of following the symlink for traversal versus following the symlink to get the EA on.
Quoted 9 lines
So with -L should it just follow the symlink or look at the symlink first and then follow it?
And will -h modify this behavior?
I'm still confused about the 1st difference in 062 output.I wonder if the man pages can be clarified in this area :)
--Tim
Okay, looked at the code.
---
no -h => stat, getxattr, listxattr
-h => lstat, lgetxattr, llistxattr
-P => skip symlinks (as soon as see them, then return from place in walk)
-L => process symlink and then opendir on symlink (hence follow/traverse it)
default => -L for argument (depth==1) and -P for subdirs (depth>1)
----
This was different than my intuition.
I am happy with -h.
For -P, I was expecting it to process symlink but not follow/traverse it, I wouldn't think it should just skip them altogether (I realise the man page says that).
For -L, I wasn't sure if it should process it first and then traverse or simply just traverse.
So were these your intentions?
If so, the code seems to follow them but it would be nicer to have more explanation in the man page.
--Tim
Quoted 6 lines · On Tuesday 20 November 2007 06:11:12 Timothy Shimmin wrote:
Okay, looked at the code.
---
no -h => stat, getxattr, listxattr
-h => lstat, lgetxattr, llistxattr
Yes.
Quoted 1 line
-P => skip symlinks (as soon as see them, then return from place in walk)
No, -h never skips symlinks. (But depending on -L and -P, it may not follow symlinks to directories.) Here is an additional comment for do_print, and an equivalent version of the if in there. I hope that this will finally clarify the code.
Quoted 1 line
it would be nicer to have more explanation in the man page.
Agreed. How about the attached manpage patches?
Thanks,
Andreas
getfattr/getfattr.c +5 -4
@@ -355,14 +355,15 @@ int do_print(const char *path, const strreturn 1 ; } -/* -* When doing a physical walk or neither doing a logical walk nor processing a -* direct command like argument, do not dereference symlinks. +/* +* Only dereference symlinks when doing a logical walk, or when procesing +* a direct command-line argument while not doing a physical walk. */ if ((walk_flags &WALK_TREE_SYMLINK ) && (walk_flags &WALK_TREE_DEREFERENCE ) && + !(walk_flags &WALK_TREE_LOGICAL ) && ((walk_flags &WALK_TREE_PHYSICAL ) || - !(walk_flags & (WALK_TREE_TOPLEVEL |WALK_TREE_LOGICAL )))) + !(walk_flags & (WALK_TREE_TOPLEVEL ))))return 0 ;if (opt_name)
getfattr/getfattr.c +4 -0
@@ -355,6 +355,10 @@ int do_print(const char *path, const strreturn 1 ; } +/* +* When doing a physical walk or neither doing a logical walk nor processing a +* direct command like argument, do not dereference symlinks. +*/ if ((walk_flags & WALK_TREE_SYMLINK) && (walk_flags & WALK_TREE_DEREFERENCE) && ((walk_flags & WALK_TREE_PHYSICAL) ||
man/man1/getfacl.1 +6 -5
@@ -100,13 +100,14 @@ Skip files that only have the base ACL e List the ACLs of all files and directories recursively. .TP .I \-L, \-\-logical -Logical walk, follow symbolic links. The default behavior is to follow -symbolic link arguments, and to skip symbolic links encountered in -subdirectories. +Logical walk, follow symbolic links to directories. The default behavior is to follow +symbolic link arguments, and skip symbolic links encountered in subdirectories. +Only effective in combination with \-R. .TP .I \-P, \-\-physical -Physical walk, skip all symbolic links. This also skips symbolic link -arguments. +Physical walk, do not follow symbolic links to directories. This also skips symbolic +link arguments. +Only effective in combination with \-R. .TP .I \-\-tabular Use an alternative tabular output format. The ACL and the default ACL are displayed side by side. Permissions that are ineffective due to the ACL mask entry are displayed capitalized. The entry tag names for the ACL_USER_OBJ and ACL_GROUP_OBJ entries are also displayed in capital letters, which helps in spotting those entries.
man/man1/setfacl.1 +7 -3
@@ -104,11 +104,15 @@ Test mode. Instead of changing the ACLs Apply operations to all files and directories recursively. This option cannot be mixed with `\-\-restore'. .TP 4 .I \-L, \-\-logical -Logical walk, follow symbolic links. The default behavior is to follow symbolic link arguments, and to skip symbolic links encountered -in subdirectories. This option cannot be mixed with `\-\-restore'. +Logical walk, follow symbolic links to directories. The default behavior is to follow +symbolic link arguments, and skip symbolic links encountered in subdirectories. +Only effective in combination with \-R. +This option cannot be mixed with `\-\-restore'. .TP 4 .I \-P, \-\-physical -Physical walk, skip all symbolic links. This also skips symbolic link arguments. +Physical walk, do not follow symbolic links to directories. +This also skips symbolic link arguments. +Only effective in combination with \-R. This option cannot be mixed with `\-\-restore'. .TP 4 .I \-\-version
man/man1/getfattr.1 +6 -7
@@ -56,11 +56,8 @@ while strings encoded as hexidecimal and 0x and 0s, respectively. .TP .BR \-h ", " \-\-no-dereference -Do not follow symlinks. -If -.I pathname -is a symbolic link, the symbolic link itself is examined, -rather than the file the link refers to. +Do not dereference symlinks. Instead of the file a symlink refers to, the +symlink itself is examined. .TP .BR \-m " \f2pattern\f1, " \-\-match "=\f2pattern\f1" Only include attributes with names matching the regular expression
@@ -85,13 +82,15 @@ Dump out the extended attribute value(s) List the attributes of all files and directories recursively. .TP .BR \-L ", " \-\-logical -Logical walk, follow symbolic links. +Logical walk, follow symbolic links to directories. The default behaviour is to follow symbolic link arguments, and to skip symbolic links encountered in subdirectories. +Only effective in combination with \-R. .TP .BR \-P ", " \-\-physical -Physical walk, skip all symbolic links. +Physical walk, do not follow symbolic links to directories. This also skips symbolic link arguments. +Only effective in combination with \-R. .TP .B \-\-version Print the version of
Quoted 6 lines · Andreas Gruenbacher
Hello,
the tree walking code in acl and attr broke when
resolve_symlinks()was introduced (by me, unfortunately). Following symlinks passed in on the command line is the intended behavior for the tools (unless in -P mode). The first version was buggy, and so someone "fixed" it by replacingreadlink()withrealpath()inresolve_symlinks().The result is that the output of getfattr and getfacl will show pathnames that may point anywhere. When processing a directory tree it sometimes is helpful to treat symlinks as regular files, but resolving the pathnames is totally wrong.
Quoted 9 lines
After runnig into problem after problem with nftw and never ending up with even half-way clean code, I think it's time to ditch it altogether and replace it with sane code. So here are two patches, one for attr and one for acl, that does that.
Files
include/walk_tree.handlibmisc/walk_tree.care identical in both patches; that code is shared between the two packages.Okay to apply?
Thanks,
Andreas
You mention -L/-P is like chown.
However, -P for getattr isn't about not walking symlinks to directories,
it's about skipping symlinks altogether, right?
--Tim
Quoted 4 lines · On Friday 09 November 2007 08:39:56 Timothy Shimmin wrote:
You mention -L/-P is like chown.
However, -P for getattr isn't about not walking symlinks to directories,
it's about skipping symlinks altogether, right?
Hmm, -L and -P define which files and directories are visited, and -h defines whether we are looking at symlinks or the files they point to. The two concepts are orthogonal. -P is not about skipping symlinks, only about not recursing into them.
You can do this (as root), for example:
$ ln -s dead link $ setfattr -h -n trusted.name -v value link $ getfattr -h -m- -d -P link # file: link trusted.name="value"
With "getfattr -R -P -h" you get a physical dump of all attributes ("a real, complete dump"), while with "getfattr -R -L" you get a logical dump that treats all symlinks as the files they point to. I somewhat doubt that -L with -h has real value.
Thanks,
Andreas