ftwalk - file tree walker


#include <ftwalk.h>

int ftwalk(char* path, int (*userf)(struct FTW* ftw), int options,

            int (*comparf)(struct FTW* ftw1, struct FTW* ftw2));
int ftwflags(void);


Ftwalk traverses a directory hierarchy using depth-first search. Upon visiting each file or directory in the hierarchy, it calls the user function userf to process that file or directory. On a directory object, userf may be called twice, once in preorder and once in postorder. On a terminal object such as a file or an unreadable directory, userf is called only once. Cycles due to hard links or symbolic links are detected to avoid infinite loops.

Path is the starting point of the search. It may be an absolute path name or a path name relative to the current directory. If path is a null pointer or points to an empty string, it is treated as if it points to the current (dot) directory.

Options consists of zero or more of the following bits:

FTW_CHILDREN: This implies preorder calls to userf on directory objects. On such a call to userf, the field ftw->link (below) points to a link list of the children of the respective directory. Upon returning from userf, if the field ftw->status of any child object is set to FTW_SKIP (below), that child is pruned from the search.
FTW_DELAY: When FTW_CHILDREN is turned on, the fields ftw->statb (struct stat) of children objects remain undefined until these objects are visited.
FTW_DOT: Do not use chdir(2) during the traversal. Normally chdir is used so that the base name of the object about to be processed can be used in accessing its data. This can enhance ftwalk efficiency but certain program effects such as core dumps may be generated in unexpected places or may not even be generated at all. Whenever chdir generates an error, if possible, the current directory is restored to the starting directory (see FTW_NAME and FTW_PATH).
FTW_MULTIPLE: The path argument is treated as a char** pointer to a null-terminated array of path names. All hierarchies rooted at these paths will be searched
FTW_POST: Calls to the user function are issued only in postorder. That is, userf is called on a directory only after its descendants have been processed. The absence of this bit indicates that calls to the user functions are issued in preorder. That is, userf is called on a directory before its descendants are processed.
FTW_PHYSICAL: Use lstat(2) instead of stat(2) to get file status and allow detection of symbolic links. In addition, if each component of the absolute path to the starting object has search permission, the absolute path is used for early detection of cycles.
FTW_META|FTW_PHYSICAL: Use stat(2) for top level file status and lstat(2) for all other files. Used to implement the POSIX -H option for commands like ls.
FTW_TWICE: Calls to the user function are issued in both preorder and postorder for directory objects.
FTW_USER: The first of 6 user defined option bits. These bits are ignored by ftwalk.

Userf is a user supplied function that is called upon different visits of an object. If the return value of userf is non-zero, ftwalk returns immediately with the same value. The userf prototype is:

     	int userf(struct FTW* ftw)

struct FTW contains at least the following elements:

         struct FTW*    link;    /* link list of children */
         struct FTW*    parent;  /* parent object on the search path */
         long           number;  /* local number */
         void*          pointer; /* local pointer */
         }              local;   /* user defined */
         struct stat    statb;   /* stat buffer of this object */
         char*          path;    /* full pathname */
         short          pathlen; /* strlen(path) */
         unsigned short info;    /* type of object */
         unsigned short status;  /* status of object */ 
         short          level;   /* depth of object on the search path */
         short          namelen; /* strlen(name) */
         char           name[];  /* file name of object */

The link field is normally NULL. If the option FTW_CHILDREN was turned on, it points to the start of the list of children of the directory being visited in preorder. Finally, if the directory being visited causes a cycle, link points to the object on the search path that is identical to this directory. Note that if FTW_PHYSICAL was turned on, this may point to a directory that is an ancestor of the starting object.

The parent field points to the parent object on the search path. For convenience, a parent object is also supplied for the starting object. In this case, except for the local field which is initialized to 0 and the level field which contains a negative number, the rest of the structure may be undefined.

The info field indicates the type of the object being visited and the type of the visit. The types are:

FTW_D: A directory being visited in preorder, i.e., none of its children has been visited by the search.
FTW_DNX: A directory being visited in preorder that does not have search permission.
FTW_DP: A directory being visited in postorder, i.e., all of its descendants have been completely processed.
FTW_DC: A directory that causes cycles. This is a terminal object.
FTW_DNR: A directory that cannot be opened for reading. This is a terminal object.
FTW_F: An ordinary file.
FTW_SL: A symbolic link. Unless FTW_FOLLOW (below) is issued by the user function, this object is terminal.
FTW_NS: Stat failed on this object. The stat buffer statb is undefined. This object is terminal.

The status field of struct FTW is used to communicate information between ftwalk and userf. On calls to userf, it has one of two values:

FTW_NAME: The name of the object as defined in ftw->name should be used for accessing its file information. This is because chdir(2) has been used to set the current directory to a suitable place (see FTW_CHDIR).
FTW_PATH: The argument path of userf should be used for accessing the file information of the object.

Upon returning, userf may set the status field to one of the following values:

FTW_AGAIN: If this is a directory object being visited in postorder, it will be processed again as if it had not been visited.
FTW_NOPOST: If this is a directory object being visited in preorder, the user function will not be called on its postorder visit.
FTW_SKIP: This object and its descendants are pruned from the search.
FTW_FOLLOW: If this object is a symbolic link, follow the link to its physical counterpart.

Comparf, if not NULL, is a pointer to a function used to define a search ordering for children of a directory. If FTW_CHILDREN is turned on, the ordering of the children of a directory is done before the preorder call to userf on that directory. Therefore, in that case, ftw->link will point to the smallest child.

The comparf prototype is:

     	int comparf(struct FTW* ftw1, struct FTW* ftw2)

Comparf should return a value <0, 0, or >0 to indicate whether ftw1 is considered smaller, equal, or larger than ftw2.

Ftwalk normally returns 0. On hard errors such as running out of memory, it returns -1. Ftwalk may also return other values as discussed with respect to userf.

Ftwflags returns a combination of 0, FTW_META, FTW_PHYSICAL according to the preferences specified by astconf("PATH_RESOLVE",0,0):






Ftwalk performs similar functions as that of the routine ftw provided in System V. However, it is more general than ftw and suitable for use as a base in implementing popular tools such as ls, find, tar, du, and rm. Ftwalk also handles symbolic links and hard links gracefully.


Phong Vo, Glenn Fowler, Dave Korn


find(1), rm(1), du(1), ls(1), tar(1), stat(2), symlink(2), astfeature(3), ftw(3), pathcd(3)

November 07, 2006