X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Ffts_.h;h=0fb0f99ca2a82b0a14eaac30465c5e640142bf1f;hb=4cd8485e904c1a98470eb548fe6ac0f04e343c4e;hp=4bf903bd3f267f95e00eb00ffe6dacadbe2613b0;hpb=359c0a71713e606f440d40f55a43c77349df2aaa;p=gnulib.git diff --git a/lib/fts_.h b/lib/fts_.h index 4bf903bd3..0fb0f99ca 100644 --- a/lib/fts_.h +++ b/lib/fts_.h @@ -1,11 +1,11 @@ /* Traverse a file hierarchy. - Copyright (C) 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2004-2008 Free Software Foundation, Inc. - This program is free software; you can redistribute it and/or modify + 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 - the Free Software Foundation; either version 2, or (at your option) - any later version. + the Free Software Foundation; either version 3 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 @@ -13,8 +13,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + along with this program. If not, see . */ /* * Copyright (c) 1989, 1993 @@ -52,7 +51,6 @@ # ifdef _LIBC # include -# define _LGPL_PACKAGE 1 # else # undef __THROW # define __THROW @@ -65,6 +63,7 @@ # include # include # include +# include "i-ring.h" typedef struct { struct _ftsent *fts_cur; /* current node */ @@ -73,8 +72,10 @@ typedef struct { dev_t fts_dev; /* starting device # */ 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 +89,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,16 +98,49 @@ 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 is 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 */ -# if !_LGPL_PACKAGE +# if GNULIB_FTS union { /* This data structure is used if FTS_TIGHT_CYCLE_CHECK is specified. It records the directories between a starting @@ -121,12 +156,18 @@ typedef struct { 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. */ + /* 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 {