Blame lib/fts_.h

Packit 709fb3
/* Traverse a file hierarchy.
Packit 709fb3
Packit 709fb3
   Copyright (C) 2004-2017 Free Software Foundation, Inc.
Packit 709fb3
Packit 709fb3
   This program is free software: you can redistribute it and/or modify
Packit 709fb3
   it under the terms of the GNU General Public License as published by
Packit 709fb3
   the Free Software Foundation; either version 3 of the License, or
Packit 709fb3
   (at your option) any later version.
Packit 709fb3
Packit 709fb3
   This program is distributed in the hope that it will be useful,
Packit 709fb3
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 709fb3
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 709fb3
   GNU General Public License for more details.
Packit 709fb3
Packit 709fb3
   You should have received a copy of the GNU General Public License
Packit 709fb3
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit 709fb3
Packit 709fb3
/*
Packit 709fb3
 * Copyright (c) 1989, 1993
Packit 709fb3
 *      The Regents of the University of California.  All rights reserved.
Packit 709fb3
 *
Packit 709fb3
 * Redistribution and use in source and binary forms, with or without
Packit 709fb3
 * modification, are permitted provided that the following conditions
Packit 709fb3
 * are met:
Packit 709fb3
 * 1. Redistributions of source code must retain the above copyright
Packit 709fb3
 *    notice, this list of conditions and the following disclaimer.
Packit 709fb3
 * 2. Redistributions in binary form must reproduce the above copyright
Packit 709fb3
 *    notice, this list of conditions and the following disclaimer in the
Packit 709fb3
 *    documentation and/or other materials provided with the distribution.
Packit 709fb3
 * 4. Neither the name of the University nor the names of its contributors
Packit 709fb3
 *    may be used to endorse or promote products derived from this software
Packit 709fb3
 *    without specific prior written permission.
Packit 709fb3
 *
Packit 709fb3
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
Packit 709fb3
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit 709fb3
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit 709fb3
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
Packit 709fb3
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit 709fb3
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
Packit 709fb3
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
Packit 709fb3
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
Packit 709fb3
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
Packit 709fb3
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
Packit 709fb3
 * SUCH DAMAGE.
Packit 709fb3
 *
Packit 709fb3
 *      @(#)fts.h       8.3 (Berkeley) 8/14/94
Packit 709fb3
 */
Packit 709fb3
Packit 709fb3
#ifndef _FTS_H
Packit 709fb3
# define _FTS_H 1
Packit 709fb3
Packit 709fb3
# ifdef _LIBC
Packit 709fb3
#  include <features.h>
Packit 709fb3
#  if __STDC_VERSION__ < 199901L
Packit 709fb3
#   define __FLEXIBLE_ARRAY_MEMBER 1
Packit 709fb3
#  else
Packit 709fb3
#   define __FLEXIBLE_ARRAY_MEMBER
Packit 709fb3
#  endif
Packit 709fb3
# else
Packit 709fb3
#  define __FLEXIBLE_ARRAY_MEMBER FLEXIBLE_ARRAY_MEMBER
Packit 709fb3
#  undef __THROW
Packit 709fb3
#  define __THROW
Packit 709fb3
#  undef __BEGIN_DECLS
Packit 709fb3
#  undef __END_DECLS
Packit 709fb3
#  ifdef __cplusplus
Packit 709fb3
#   define __BEGIN_DECLS extern "C" {
Packit 709fb3
#   define __END_DECLS }
Packit 709fb3
#  else
Packit 709fb3
#   define __BEGIN_DECLS
Packit 709fb3
#   define __END_DECLS
Packit 709fb3
#  endif
Packit 709fb3
# endif
Packit 709fb3
Packit 709fb3
# include <stddef.h>
Packit 709fb3
# include <sys/types.h>
Packit 709fb3
# include <dirent.h>
Packit 709fb3
# include <sys/stat.h>
Packit 709fb3
# include "i-ring.h"
Packit 709fb3
Packit 709fb3
typedef struct {
Packit 709fb3
        struct _ftsent *fts_cur;        /* current node */
Packit 709fb3
        struct _ftsent *fts_child;      /* linked list of children */
Packit 709fb3
        struct _ftsent **fts_array;     /* sort array */
Packit 709fb3
        dev_t fts_dev;                  /* starting device # */
Packit 709fb3
        char *fts_path;                 /* file name for this descent */
Packit 709fb3
        int fts_rfd;                    /* fd for root */
Packit 709fb3
        int fts_cwd_fd;                 /* the file descriptor on which the
Packit 709fb3
                                           virtual cwd is open, or AT_FDCWD */
Packit 709fb3
        size_t fts_pathlen;             /* sizeof(path) */
Packit 709fb3
        size_t fts_nitems;              /* elements in the sort array */
Packit 709fb3
        int (*fts_compar) (struct _ftsent const **, struct _ftsent const **);
Packit 709fb3
                                        /* compare fn */
Packit 709fb3
Packit 709fb3
# define FTS_COMFOLLOW  0x0001          /* follow command line symlinks */
Packit 709fb3
# define FTS_LOGICAL    0x0002          /* logical walk */
Packit 709fb3
# define FTS_NOCHDIR    0x0004          /* don't change directories */
Packit 709fb3
# define FTS_NOSTAT     0x0008          /* don't get stat info */
Packit 709fb3
# define FTS_PHYSICAL   0x0010          /* physical walk */
Packit 709fb3
# define FTS_SEEDOT     0x0020          /* return dot and dot-dot */
Packit 709fb3
# define FTS_XDEV       0x0040          /* don't cross devices */
Packit 709fb3
# define FTS_WHITEOUT   0x0080          /* return whiteout information */
Packit 709fb3
Packit 709fb3
  /* There are two ways to detect cycles.
Packit 709fb3
     The lazy way (which works only with FTS_PHYSICAL),
Packit 709fb3
     with which one may process a directory that is a
Packit 709fb3
     part of the cycle several times before detecting the cycle.
Packit 709fb3
     The "tight" way, whereby fts uses more memory (proportional
Packit 709fb3
     to number of "active" directories, aka distance from root
Packit 709fb3
     of current tree to current directory -- see active_dir_ht)
Packit 709fb3
     to detect any cycle right away.  For example, du must use
Packit 709fb3
     this option to avoid counting disk space in a cycle multiple
Packit 709fb3
     times, but chown -R need not.
Packit 709fb3
     The default is to use the constant-memory lazy way, when possible
Packit 709fb3
     (see below).
Packit 709fb3
Packit 709fb3
     However, with FTS_LOGICAL (when following symlinks, e.g., chown -L)
Packit 709fb3
     using lazy cycle detection is inadequate.  For example, traversing
Packit 709fb3
     a directory containing a symbolic link to a peer directory, it is
Packit 709fb3
     possible to encounter the same directory twice even though there
Packit 709fb3
     is no cycle:
Packit 709fb3
     dir
Packit 709fb3
     ...
Packit 709fb3
     slink -> dir
Packit 709fb3
     So, when FTS_LOGICAL is selected, we have to use a different
Packit 709fb3
     mode of cycle detection: FTS_TIGHT_CYCLE_CHECK.  */
Packit 709fb3
# define FTS_TIGHT_CYCLE_CHECK  0x0100
Packit 709fb3
Packit 709fb3
  /* Use this flag to enable semantics with which the parent
Packit 709fb3
     application may be made both more efficient and more robust.
Packit 709fb3
     Whereas the default is to visit each directory in a recursive
Packit 709fb3
     traversal (via chdir), using this flag makes it so the initial
Packit 709fb3
     working directory is never changed.  Instead, these functions
Packit 709fb3
     perform the traversal via a virtual working directory, maintained
Packit 709fb3
     through the file descriptor member, fts_cwd_fd.  */
Packit 709fb3
# define FTS_CWDFD              0x0200
Packit 709fb3
Packit 709fb3
  /* Historically, for each directory that fts initially encounters, it would
Packit 709fb3
     open it, read all entries, and stat each entry, storing the results, and
Packit 709fb3
     then it would process the first entry.  But that behavior is bad for
Packit 709fb3
     locality of reference, and also causes trouble with inode-simulating
Packit 709fb3
     file systems like FAT, CIFS, FUSE-based ones, etc., when entries from
Packit 709fb3
     their name/inode cache are flushed too early.
Packit 709fb3
     Use this flag to make fts_open and fts_read defer the stat/lstat/fststat
Packit 709fb3
     of each entry until it is actually processed.  However, note that if you
Packit 709fb3
     use this option and also specify a comparison function, that function may
Packit 709fb3
     not examine any data via fts_statp.  However, when fts_statp->st_mode is
Packit 709fb3
     nonzero, the S_IFMT type bits are valid, with mapped dirent.d_type data.
Packit 709fb3
     Of course, that happens only on file systems that provide useful
Packit 709fb3
     dirent.d_type data.  */
Packit 709fb3
# define FTS_DEFER_STAT         0x0400
Packit 709fb3
Packit 709fb3
# define FTS_NOATIME    0x0800          /* use O_NOATIME during traversal */
Packit 709fb3
Packit 709fb3
  /* Use this flag to disable stripping of trailing slashes
Packit 709fb3
     from input path names during fts_open initialization.  */
Packit 709fb3
# define FTS_VERBATIM   0x1000
Packit 709fb3
Packit 709fb3
# define FTS_OPTIONMASK 0x1fff          /* valid user option mask */
Packit 709fb3
Packit 709fb3
# define FTS_NAMEONLY   0x2000          /* (private) child names only */
Packit 709fb3
# define FTS_STOP       0x4000          /* (private) unrecoverable error */
Packit 709fb3
        int fts_options;                /* fts_open options, global flags */
Packit 709fb3
Packit 709fb3
        /* Map a directory's device number to a boolean.  The boolean is
Packit 709fb3
           true if for that file system (type determined by a single fstatfs
Packit 709fb3
           call per FS) st_nlink can be used to calculate the number of
Packit 709fb3
           sub-directory entries in a directory.
Packit 709fb3
           Using this table is an optimization that permits us to look up
Packit 709fb3
           file system type on a per-inode basis at the minimal cost of
Packit 709fb3
           calling fstatfs only once per traversed device.  */
Packit 709fb3
        struct hash_table *fts_leaf_optimization_works_ht;
Packit 709fb3
Packit 709fb3
        union {
Packit 709fb3
                /* This data structure is used if FTS_TIGHT_CYCLE_CHECK is
Packit 709fb3
                   specified.  It records the directories between a starting
Packit 709fb3
                   point and the current directory.  I.e., a directory is
Packit 709fb3
                   recorded here IFF we have visited it once, but we have not
Packit 709fb3
                   yet completed processing of all its entries.  Every time we
Packit 709fb3
                   visit a new directory, we add that directory to this set.
Packit 709fb3
                   When we finish with a directory (usually by visiting it a
Packit 709fb3
                   second time), we remove it from this set.  Each entry in
Packit 709fb3
                   this data structure is a device/inode pair.  This data
Packit 709fb3
                   structure is used to detect directory cycles efficiently and
Packit 709fb3
                   promptly even when the depth of a hierarchy is in the tens
Packit 709fb3
                   of thousands.  */
Packit 709fb3
                struct hash_table *ht;
Packit 709fb3
Packit 709fb3
                /* FIXME: rename these two members to have the fts_ prefix */
Packit 709fb3
                /* This data structure uses a lazy cycle-detection algorithm,
Packit 709fb3
                   as done by rm via cycle-check.c.  It's the default,
Packit 709fb3
                   but it's not appropriate for programs like du.  */
Packit 709fb3
                struct cycle_check_state *state;
Packit 709fb3
        } fts_cycle;
Packit 709fb3
Packit 709fb3
        /* A stack of the file descriptors corresponding to the
Packit 709fb3
           most-recently traversed parent directories.
Packit 709fb3
           Currently used only in FTS_CWDFD mode.  */
Packit 709fb3
        I_ring fts_fd_ring;
Packit 709fb3
} FTS;
Packit 709fb3
Packit 709fb3
typedef struct _ftsent {
Packit 709fb3
        struct _ftsent *fts_cycle;      /* cycle node */
Packit 709fb3
        struct _ftsent *fts_parent;     /* parent directory */
Packit 709fb3
        struct _ftsent *fts_link;       /* next file in directory */
Packit 709fb3
        DIR *fts_dirp;                  /* Dir pointer for any directory
Packit 709fb3
                                           containing more entries than we
Packit 709fb3
                                           read at one time.  */
Packit 709fb3
        long fts_number;                /* local numeric value */
Packit 709fb3
        void *fts_pointer;              /* local address value */
Packit 709fb3
        char *fts_accpath;              /* access file name */
Packit 709fb3
        char *fts_path;                 /* root name; == fts_fts->fts_path */
Packit 709fb3
        int fts_errno;                  /* errno for this node */
Packit 709fb3
        int fts_symfd;                  /* fd for symlink */
Packit 709fb3
        size_t fts_pathlen;             /* strlen(fts_path) */
Packit 709fb3
Packit 709fb3
        FTS *fts_fts;                   /* the file hierarchy itself */
Packit 709fb3
Packit 709fb3
# define FTS_ROOTPARENTLEVEL    (-1)
Packit 709fb3
# define FTS_ROOTLEVEL           0
Packit 709fb3
        ptrdiff_t fts_level;            /* depth (-1 to N) */
Packit 709fb3
Packit 709fb3
        size_t fts_namelen;             /* strlen(fts_name) */
Packit 709fb3
        nlink_t fts_n_dirs_remaining;   /* count down from st_nlink */
Packit 709fb3
Packit 709fb3
# define FTS_D           1              /* preorder directory */
Packit 709fb3
# define FTS_DC          2              /* directory that causes cycles */
Packit 709fb3
# define FTS_DEFAULT     3              /* none of the above */
Packit 709fb3
# define FTS_DNR         4              /* unreadable directory */
Packit 709fb3
# define FTS_DOT         5              /* dot or dot-dot */
Packit 709fb3
# define FTS_DP          6              /* postorder directory */
Packit 709fb3
# define FTS_ERR         7              /* error; errno is set */
Packit 709fb3
# define FTS_F           8              /* regular file */
Packit 709fb3
# define FTS_INIT        9              /* initialized only */
Packit 709fb3
# define FTS_NS         10              /* stat(2) failed */
Packit 709fb3
# define FTS_NSOK       11              /* no stat(2) requested */
Packit 709fb3
# define FTS_SL         12              /* symbolic link */
Packit 709fb3
# define FTS_SLNONE     13              /* symbolic link without target */
Packit 709fb3
# define FTS_W          14              /* whiteout object */
Packit 709fb3
        unsigned short int fts_info;    /* user flags for FTSENT structure */
Packit 709fb3
Packit 709fb3
# define FTS_DONTCHDIR   0x01           /* don't chdir .. to the parent */
Packit 709fb3
# define FTS_SYMFOLLOW   0x02           /* followed a symlink to get here */
Packit 709fb3
        unsigned short int fts_flags;   /* private flags for FTSENT structure */
Packit 709fb3
Packit 709fb3
# define FTS_AGAIN       1              /* read node again */
Packit 709fb3
# define FTS_FOLLOW      2              /* follow symbolic link */
Packit 709fb3
# define FTS_NOINSTR     3              /* no instructions */
Packit 709fb3
# define FTS_SKIP        4              /* discard node */
Packit 709fb3
        unsigned short int fts_instr;   /* fts_set() instructions */
Packit 709fb3
Packit 709fb3
        struct stat fts_statp[1];       /* stat(2) information */
Packit 709fb3
        char fts_name[__FLEXIBLE_ARRAY_MEMBER]; /* file name */
Packit 709fb3
} FTSENT;
Packit 709fb3
Packit 709fb3
#ifndef __GNUC_PREREQ
Packit 709fb3
# if defined __GNUC__ && defined __GNUC_MINOR__
Packit 709fb3
#  define __GNUC_PREREQ(maj, min) \
Packit 709fb3
         ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
Packit 709fb3
# else
Packit 709fb3
#  define __GNUC_PREREQ(maj, min) 0
Packit 709fb3
# endif
Packit 709fb3
#endif
Packit 709fb3
Packit 709fb3
#if __GNUC_PREREQ (3,4)
Packit 709fb3
# undef __attribute_warn_unused_result__
Packit 709fb3
# define __attribute_warn_unused_result__ \
Packit 709fb3
   __attribute__ ((__warn_unused_result__))
Packit 709fb3
#else
Packit 709fb3
# define __attribute_warn_unused_result__ /* empty */
Packit 709fb3
#endif
Packit 709fb3
Packit 709fb3
__BEGIN_DECLS
Packit 709fb3
FTSENT  *fts_children (FTS *, int) __THROW __attribute_warn_unused_result__;
Packit 709fb3
int      fts_close (FTS *) __THROW __attribute_warn_unused_result__;
Packit 709fb3
FTS     *fts_open (char * const *, int,
Packit 709fb3
                   int (*)(const FTSENT **, const FTSENT **))
Packit 709fb3
  __THROW __attribute_warn_unused_result__;
Packit 709fb3
FTSENT  *fts_read (FTS *) __THROW __attribute_warn_unused_result__;
Packit 709fb3
int      fts_set (FTS *, FTSENT *, int) __THROW;
Packit 709fb3
__END_DECLS
Packit 709fb3
Packit 709fb3
#endif /* fts.h */