Back to index

glibc  2.9
Classes | Defines | Typedefs | Functions
fts.h File Reference
#include <features.h>
#include <sys/types.h>
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  FTS
struct  _ftsent

Defines

#define FTS_COMFOLLOW   0x0001 /* follow command line symlinks */
#define FTS_LOGICAL   0x0002 /* logical walk */
#define FTS_NOCHDIR   0x0004 /* don't change directories */
#define FTS_NOSTAT   0x0008 /* don't get stat info */
#define FTS_PHYSICAL   0x0010 /* physical walk */
#define FTS_SEEDOT   0x0020 /* return dot and dot-dot */
#define FTS_XDEV   0x0040 /* don't cross devices */
#define FTS_WHITEOUT   0x0080 /* return whiteout information */
#define FTS_OPTIONMASK   0x00ff /* valid user option mask */
#define FTS_NAMEONLY   0x0100 /* (private) child names only */
#define FTS_STOP   0x0200 /* (private) unrecoverable error */
#define FTS_ROOTPARENTLEVEL   -1
#define FTS_ROOTLEVEL   0
#define FTS_D   1 /* preorder directory */
#define FTS_DC   2 /* directory that causes cycles */
#define FTS_DEFAULT   3 /* none of the above */
#define FTS_DNR   4 /* unreadable directory */
#define FTS_DOT   5 /* dot or dot-dot */
#define FTS_DP   6 /* postorder directory */
#define FTS_ERR   7 /* error; errno is set */
#define FTS_F   8 /* regular file */
#define FTS_INIT   9 /* initialized only */
#define FTS_NS   10 /* stat(2) failed */
#define FTS_NSOK   11 /* no stat(2) requested */
#define FTS_SL   12 /* symbolic link */
#define FTS_SLNONE   13 /* symbolic link without target */
#define FTS_W   14 /* whiteout object */
#define FTS_DONTCHDIR   0x01 /* don't chdir .. to the parent */
#define FTS_SYMFOLLOW   0x02 /* followed a symlink to get here */
#define FTS_AGAIN   1 /* read node again */
#define FTS_FOLLOW   2 /* follow symbolic link */
#define FTS_NOINSTR   3 /* no instructions */
#define FTS_SKIP   4 /* discard node */

Typedefs

typedef struct _ftsent FTSENT

Functions

__BEGIN_DECLS FTSENTfts_children (FTS *, int)
int fts_close (FTS *)
FTSfts_open (char *const *, int, int(*)(const FTSENT **, const FTSENT **))
FTSENTfts_read (FTS *)
int fts_set (FTS *, FTSENT *, int) __THROW

Class Documentation

struct _ftsent

Definition at line 71 of file fts.h.

Collaboration diagram for _ftsent:
Class Members
char * fts_accpath
struct _ftsent * fts_cycle
dev_t fts_dev
int fts_errno
u_short fts_flags
u_short fts_info
ino_t fts_ino
u_short fts_instr
short fts_level
struct _ftsent * fts_link
char fts_name
u_short fts_namelen
nlink_t fts_nlink
long fts_number
struct _ftsent * fts_parent
char * fts_path
u_short fts_pathlen
void * fts_pointer
struct stat * fts_statp
int fts_symfd

Define Documentation

#define FTS_AGAIN   1 /* read node again */

Definition at line 112 of file fts.h.

#define FTS_COMFOLLOW   0x0001 /* follow command line symlinks */

Definition at line 56 of file fts.h.

#define FTS_D   1 /* preorder directory */

Definition at line 92 of file fts.h.

#define FTS_DC   2 /* directory that causes cycles */

Definition at line 93 of file fts.h.

#define FTS_DEFAULT   3 /* none of the above */

Definition at line 94 of file fts.h.

#define FTS_DNR   4 /* unreadable directory */

Definition at line 95 of file fts.h.

#define FTS_DONTCHDIR   0x01 /* don't chdir .. to the parent */

Definition at line 108 of file fts.h.

#define FTS_DOT   5 /* dot or dot-dot */

Definition at line 96 of file fts.h.

#define FTS_DP   6 /* postorder directory */

Definition at line 97 of file fts.h.

#define FTS_ERR   7 /* error; errno is set */

Definition at line 98 of file fts.h.

#define FTS_F   8 /* regular file */

Definition at line 99 of file fts.h.

#define FTS_FOLLOW   2 /* follow symbolic link */

Definition at line 113 of file fts.h.

#define FTS_INIT   9 /* initialized only */

Definition at line 100 of file fts.h.

#define FTS_LOGICAL   0x0002 /* logical walk */

Definition at line 57 of file fts.h.

#define FTS_NAMEONLY   0x0100 /* (private) child names only */

Definition at line 66 of file fts.h.

#define FTS_NOCHDIR   0x0004 /* don't change directories */

Definition at line 58 of file fts.h.

#define FTS_NOINSTR   3 /* no instructions */

Definition at line 114 of file fts.h.

#define FTS_NOSTAT   0x0008 /* don't get stat info */

Definition at line 59 of file fts.h.

#define FTS_NS   10 /* stat(2) failed */

Definition at line 101 of file fts.h.

#define FTS_NSOK   11 /* no stat(2) requested */

Definition at line 102 of file fts.h.

#define FTS_OPTIONMASK   0x00ff /* valid user option mask */

Definition at line 64 of file fts.h.

#define FTS_PHYSICAL   0x0010 /* physical walk */

Definition at line 60 of file fts.h.

#define FTS_ROOTLEVEL   0

Definition at line 89 of file fts.h.

#define FTS_ROOTPARENTLEVEL   -1

Definition at line 88 of file fts.h.

#define FTS_SEEDOT   0x0020 /* return dot and dot-dot */

Definition at line 61 of file fts.h.

#define FTS_SKIP   4 /* discard node */

Definition at line 115 of file fts.h.

#define FTS_SL   12 /* symbolic link */

Definition at line 103 of file fts.h.

#define FTS_SLNONE   13 /* symbolic link without target */

Definition at line 104 of file fts.h.

#define FTS_STOP   0x0200 /* (private) unrecoverable error */

Definition at line 67 of file fts.h.

#define FTS_SYMFOLLOW   0x02 /* followed a symlink to get here */

Definition at line 109 of file fts.h.

#define FTS_W   14 /* whiteout object */

Definition at line 105 of file fts.h.

#define FTS_WHITEOUT   0x0080 /* return whiteout information */

Definition at line 63 of file fts.h.

#define FTS_XDEV   0x0040 /* don't cross devices */

Definition at line 62 of file fts.h.


Typedef Documentation

typedef struct _ftsent FTSENT

Function Documentation

Definition at line 497 of file fts.c.

{
       register FTSENT *p;
       int fd;

       if (instr != 0 && instr != FTS_NAMEONLY) {
              __set_errno (EINVAL);
              return (NULL);
       }

       /* Set current node pointer. */
       p = sp->fts_cur;

       /*
        * Errno set to 0 so user can distinguish empty directory from
        * an error.
        */
       __set_errno (0);

       /* Fatal errors stop here. */
       if (ISSET(FTS_STOP))
              return (NULL);

       /* Return logical hierarchy of user's arguments. */
       if (p->fts_info == FTS_INIT)
              return (p->fts_link);

       /*
        * If not a directory being visited in pre-order, stop here.  Could
        * allow FTS_DNR, assuming the user has fixed the problem, but the
        * same effect is available with FTS_AGAIN.
        */
       if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */)
              return (NULL);

       /* Free up any previous child list. */
       if (sp->fts_child != NULL)
              fts_lfree(sp->fts_child);

       if (instr == FTS_NAMEONLY) {
              SET(FTS_NAMEONLY);
              instr = BNAMES;
       } else
              instr = BCHILD;

       /*
        * If using chdir on a relative path and called BEFORE fts_read does
        * its chdir to the root of a traversal, we can lose -- we need to
        * chdir into the subdirectory, and we don't know where the current
        * directory is, so we can't get back so that the upcoming chdir by
        * fts_read will work.
        */
       if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' ||
           ISSET(FTS_NOCHDIR))
              return (sp->fts_child = fts_build(sp, instr));

       if ((fd = __open(".", O_RDONLY, 0)) < 0)
              return (NULL);
       sp->fts_child = fts_build(sp, instr);
       if (__fchdir(fd))
              return (NULL);
       (void)__close(fd);
       return (sp->fts_child);
}

Here is the call graph for this function:

int fts_close ( FTS )

Definition at line 231 of file fts.c.

{
       register FTSENT *freep, *p;
       int saved_errno;

       /*
        * This still works if we haven't read anything -- the dummy structure
        * points to the root list, so we step through to the end of the root
        * list which has a valid parent pointer.
        */
       if (sp->fts_cur) {
              for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
                     freep = p;
                     p = p->fts_link != NULL ? p->fts_link : p->fts_parent;
                     free(freep);
              }
              free(p);
       }

       /* Free up child linked list, sort array, path buffer. */
       if (sp->fts_child)
              fts_lfree(sp->fts_child);
       free(sp->fts_array);
       free(sp->fts_path);

       /* Return to original directory, save errno if necessary. */
       if (!ISSET(FTS_NOCHDIR)) {
              saved_errno = __fchdir(sp->fts_rfd) ? errno : 0;
              (void)__close(sp->fts_rfd);

              /* Set errno and return. */
              if (saved_errno != 0) {
                     /* Free up the stream pointer. */
                     free(sp);
                     __set_errno (saved_errno);
                     return (-1);
              }
       }

       /* Free up the stream pointer. */
       free(sp);
       return (0);
}

Here is the call graph for this function:

FTS* fts_open ( char *const ,
int  ,
int(*)(const FTSENT **, const FTSENT **)   
)
FTSENT* fts_read ( FTS )

Definition at line 285 of file fts.c.

{
       register FTSENT *p, *tmp;
       register int instr;
       register char *t;
       int saved_errno;

       /* If finished or unrecoverable error, return NULL. */
       if (sp->fts_cur == NULL || ISSET(FTS_STOP))
              return (NULL);

       /* Set current node pointer. */
       p = sp->fts_cur;

       /* Save and zero out user instructions. */
       instr = p->fts_instr;
       p->fts_instr = FTS_NOINSTR;

       /* Any type of file may be re-visited; re-stat and re-turn. */
       if (instr == FTS_AGAIN) {
              p->fts_info = fts_stat(sp, p, 0);
              return (p);
       }

       /*
        * Following a symlink -- SLNONE test allows application to see
        * SLNONE and recover.  If indirecting through a symlink, have
        * keep a pointer to current location.  If unable to get that
        * pointer, follow fails.
        */
       if (instr == FTS_FOLLOW &&
           (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
              p->fts_info = fts_stat(sp, p, 1);
              if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
                     if ((p->fts_symfd = __open(".", O_RDONLY, 0)) < 0) {
                            p->fts_errno = errno;
                            p->fts_info = FTS_ERR;
                     } else
                            p->fts_flags |= FTS_SYMFOLLOW;
              }
              return (p);
       }

       /* Directory in pre-order. */
       if (p->fts_info == FTS_D) {
              /* If skipped or crossed mount point, do post-order visit. */
              if (instr == FTS_SKIP ||
                  (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) {
                     if (p->fts_flags & FTS_SYMFOLLOW)
                            (void)__close(p->fts_symfd);
                     if (sp->fts_child) {
                            fts_lfree(sp->fts_child);
                            sp->fts_child = NULL;
                     }
                     p->fts_info = FTS_DP;
                     return (p);
              }

              /* Rebuild if only read the names and now traversing. */
              if (sp->fts_child != NULL && ISSET(FTS_NAMEONLY)) {
                     CLR(FTS_NAMEONLY);
                     fts_lfree(sp->fts_child);
                     sp->fts_child = NULL;
              }

              /*
               * Cd to the subdirectory.
               *
               * If have already read and now fail to chdir, whack the list
               * to make the names come out right, and set the parent errno
               * so the application will eventually get an error condition.
               * Set the FTS_DONTCHDIR flag so that when we logically change
               * directories back to the parent we don't do a chdir.
               *
               * If haven't read do so.  If the read fails, fts_build sets
               * FTS_STOP or the fts_info field of the node.
               */
              if (sp->fts_child != NULL) {
                     if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) {
                            p->fts_errno = errno;
                            p->fts_flags |= FTS_DONTCHDIR;
                            for (p = sp->fts_child; p != NULL;
                                 p = p->fts_link)
                                   p->fts_accpath =
                                       p->fts_parent->fts_accpath;
                     }
              } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) {
                     if (ISSET(FTS_STOP))
                            return (NULL);
                     return (p);
              }
              p = sp->fts_child;
              sp->fts_child = NULL;
              sp->fts_cur = p;
              goto name;
       }

       /* Move to the next node on this level. */
next:  tmp = p;
       if ((p = p->fts_link) != NULL) {
              sp->fts_cur = p;
              free(tmp);

              /*
               * If reached the top, return to the original directory (or
               * the root of the tree), and load the paths for the next root.
               */
              if (p->fts_level == FTS_ROOTLEVEL) {
                     if (FCHDIR(sp, sp->fts_rfd)) {
                            SET(FTS_STOP);
                            return (NULL);
                     }
                     fts_load(sp, p);
                     return p;
              }

              /*
               * User may have called fts_set on the node.  If skipped,
               * ignore.  If followed, get a file descriptor so we can
               * get back if necessary.
               */
              if (p->fts_instr == FTS_SKIP)
                     goto next;
              if (p->fts_instr == FTS_FOLLOW) {
                     p->fts_info = fts_stat(sp, p, 1);
                     if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
                            if ((p->fts_symfd =
                                __open(".", O_RDONLY, 0)) < 0) {
                                   p->fts_errno = errno;
                                   p->fts_info = FTS_ERR;
                            } else
                                   p->fts_flags |= FTS_SYMFOLLOW;
                     }
                     p->fts_instr = FTS_NOINSTR;
              }

name:         t = sp->fts_path + NAPPEND(p->fts_parent);
              *t++ = '/';
              memmove(t, p->fts_name, p->fts_namelen + 1);
              return p;
       }

       /* Move up to the parent node. */
       p = tmp->fts_parent;
       sp->fts_cur = p;
       free(tmp);

       if (p->fts_level == FTS_ROOTPARENTLEVEL) {
              /*
               * Done; free everything up and set errno to 0 so the user
               * can distinguish between error and EOF.
               */
              free(p);
              __set_errno (0);
              return (sp->fts_cur = NULL);
       }

       /* NUL terminate the pathname. */
       sp->fts_path[p->fts_pathlen] = '\0';

       /*
        * Return to the parent directory.  If at a root node or came through
        * a symlink, go back through the file descriptor.  Otherwise, cd up
        * one directory.
        */
       if (p->fts_level == FTS_ROOTLEVEL) {
              if (FCHDIR(sp, sp->fts_rfd)) {
                     SET(FTS_STOP);
                     return (NULL);
              }
       } else if (p->fts_flags & FTS_SYMFOLLOW) {
              if (FCHDIR(sp, p->fts_symfd)) {
                     saved_errno = errno;
                     (void)__close(p->fts_symfd);
                     __set_errno (saved_errno);
                     SET(FTS_STOP);
                     return (NULL);
              }
              (void)__close(p->fts_symfd);
       } else if (!(p->fts_flags & FTS_DONTCHDIR) &&
                 fts_safe_changedir(sp, p->fts_parent, -1, "..")) {
              SET(FTS_STOP);
              return (NULL);
       }
       p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
       return p;
}

Here is the call graph for this function:

int fts_set ( FTS ,
FTSENT ,
int   
)

Definition at line 482 of file fts.c.

{
       if (instr != 0 && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
           instr != FTS_NOINSTR && instr != FTS_SKIP) {
              __set_errno (EINVAL);
              return (1);
       }
       p->fts_instr = instr;
       return (0);
}