X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Ffts_.h;h=42e06c9876fad60c375b5472f127798432a74fde;hb=595fe7f463f7fb72ad6acc58d885585590f8f285;hp=b932cf77bc1a8d725096fecc64c257ed09bda4c3;hpb=c0b6cbd43c59550c565712d0ba6a3fe827d63f4d;p=gnulib.git diff --git a/lib/fts_.h b/lib/fts_.h index b932cf77b..42e06c987 100644 --- a/lib/fts_.h +++ b/lib/fts_.h @@ -52,6 +52,7 @@ # ifdef _LIBC # include +# define _LGPL_PACKAGE 1 # else # undef __THROW # define __THROW @@ -63,15 +64,14 @@ # include # include -# include "hash.h" -# include "cycle-check.h" +# include typedef struct { struct _ftsent *fts_cur; /* current node */ struct _ftsent *fts_child; /* linked list of children */ struct _ftsent **fts_array; /* sort array */ dev_t fts_dev; /* starting device # */ - char *fts_path; /* path for this descent */ + char *fts_path; /* file name for this descent */ int fts_rfd; /* fd for root */ size_t fts_pathlen; /* sizeof(path) */ size_t fts_nitems; /* elements in the sort array */ @@ -88,7 +88,8 @@ typedef struct { # define FTS_WHITEOUT 0x0080 /* return whiteout information */ /* There are two ways to detect cycles. - The lazy way, with which one may process a directory that is a + The lazy way (which works only with FTS_PHYSICAL), + with which one may process a directory that is a part of the cycle several times before detecting the cycle. The `tight' way, whereby fts uses more memory (proportional to number of `active' directories, aka distance from root @@ -96,7 +97,19 @@ typedef struct { to detect any cycle right away. For example, du must use this option to avoid counting disk space in a cycle multiple times, but chown -R need not. - The default is to use the constant-memory lazy way. */ + The default is to use the constant-memory lazy way, when possible + (see below). + + However, with FTS_LOGICAL (when following symlinks, e.g., chown -L) + using lazy cycle detection is inadequate. For example, traversing + a directory containing a symbolic link to a peer directory, it is + possible to encounter the same directory twice even though there + is no cycle: + dir + ... + slink -> dir + So, when FTS_LOGICAL is selected, we have to use a different + mode of cycle detection: FTS_TIGHT_CYCLE_CHECK. */ # define FTS_TIGHT_CYCLE_CHECK 0x0100 # define FTS_OPTIONMASK 0x01ff /* valid user option mask */ @@ -105,19 +118,28 @@ typedef struct { # define FTS_STOP 0x2000 /* (private) unrecoverable error */ int fts_options; /* fts_open options, global flags */ - /* This data structure records the directories between a starting - point and the current directory. I.e., a directory is recorded - here IFF we have visited it once, but we have not yet completed - processing of all its entries. Every time we visit a new directory, - we add that directory to this set. When we finish with a directory - (usually by visiting it a second time), we remove it from this - set. Each entry in this data structure is a device/inode pair. - This data structure is used to detect directory cycles efficiently - and promptly even when the depth of a hierarchy is in the tens - of thousands. Lazy checking, as done by GNU rm via cycle-check.c, - wouldn't be appropriate for du. */ - Hash_table *active_dir_ht; - struct cycle_check_state *cycle_state; +# if !_LGPL_PACKAGE + union { + /* This data structure is used if FTS_TIGHT_CYCLE_CHECK is + specified. It records the directories between a starting + point and the current directory. I.e., a directory is + recorded here IFF we have visited it once, but we have not + yet completed processing of all its entries. Every time we + visit a new directory, we add that directory to this set. + When we finish with a directory (usually by visiting it a + second time), we remove it from this set. Each entry in + this data structure is a device/inode pair. This data + structure is used to detect directory cycles efficiently and + promptly even when the depth of a hierarchy is in the tens + of thousands. */ + struct hash_table *ht; + + /* This data structure uses lazy checking, as done by rm via + cycle-check.c. It's the default, but it's not appropriate + for programs like du. */ + struct cycle_check_state *state; + } fts_cycle; +# endif } FTS; typedef struct _ftsent { @@ -126,8 +148,8 @@ typedef struct _ftsent { struct _ftsent *fts_link; /* next file in directory */ long fts_number; /* local numeric value */ void *fts_pointer; /* local address value */ - char *fts_accpath; /* access path */ - char *fts_path; /* root path; == fts_fts->fts_path */ + char *fts_accpath; /* access file name */ + char *fts_path; /* root name; == fts_fts->fts_path */ int fts_errno; /* errno for this node */ int fts_symfd; /* fd for symlink */ size_t fts_pathlen; /* strlen(fts_path) */