Move to u16-mbtouc-unsafe.
[gnulib.git] / lib / fts_.h
index b932cf7..a8a52d2 100644 (file)
@@ -1,6 +1,6 @@
 /* Traverse a file hierarchy.
 
-   Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
 # include <stddef.h>
 # include <sys/types.h>
-# include "hash.h"
-# include "cycle-check.h"
+# include <sys/stat.h>
+# include "i-ring.h"
 
 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 */
+       int fts_cwd_fd;                 /* the file descriptor on which the
+                                          virtual cwd is open, or AT_FDCWD */
        size_t fts_pathlen;             /* sizeof(path) */
-       size_t fts_nitems;                      /* elements in the sort array */
+       size_t fts_nitems;              /* elements in the sort array */
        int (*fts_compar) (struct _ftsent const **, struct _ftsent const **);
                                        /* compare fn */
 
@@ -88,7 +90,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,28 +99,76 @@ 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 */
+  /* Use this flag to enable semantics with which the parent
+     application may be made both more efficient and more robust.
+     Whereas the default is to visit each directory in a recursive
+     traversal (via chdir), using this flag makes it so the initial
+     working directory is never changed.  Instead, these functions
+     perform the traversal via a virtual working directory, maintained
+     through the file descriptor member, fts_cwd_fd.  */
+# define FTS_CWDFD             0x0200
+
+  /* Historically, for each directory that fts initially encounters, it would
+     open it, read all entries, and stat each entry, storing the results, and
+     then it would process the first entry.  But that behavior is bad for
+     locality of reference, and also causes trouble with inode-simulating
+     file systems like FAT, CIFS, FUSE-based ones, etc., when entries from
+     their name/inode cache are flushed too early.
+     Use this flag to make fts_open and fts_read defer the stat/lstat/fststat
+     of each entry until it actually processed.  However, note that if you use
+     this option and also specify a comparison function, that function may not
+     examine any data via fts_statp.  */
+# define FTS_DEFER_STAT                0x0400
+
+# define FTS_OPTIONMASK        0x07ff          /* valid user option mask */
 
 # define FTS_NAMEONLY  0x1000          /* (private) child names only */
 # 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 GNULIB_FTS
+       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;
+
+               /* FIXME: rename these two members to have the fts_ prefix */
+               /* This data structure uses a lazy cycle-detection algorithm,
+                  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
+       /* A stack of the file descriptors corresponding to the
+          most-recently traversed parent directories.
+          Currently used only in FTS_CWDFD mode.  */
+       I_ring fts_fd_ring;
 } FTS;
 
 typedef struct _ftsent {
@@ -126,8 +177,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) */