@node ftw, file system @findex ftw @subheading Syntax @example #include int ftw(const char *dir, int (*func)(const char *path, struct stat *stbuf, int flag), int depth); @end example @subheading Description This function recursively descends the directory hierarchy which starts with @var{dir}. For each file in the hierarchy, @code{ftw} calls the user-defined function @var{func} which is passed a pointer to a @code{NULL}-terminated character array in @var{path} holding the full pathname of the file, a pointer to a @code{stat} structure (@pxref{stat}) @var{stbuf} with a filesystem information about that file, and an integer @var{flag}. Possible values of @var{flag} are: @table @code @item FTW_F This is a regular file. @item FTW_D This is a directory. @item FTW_VL This is a volume label. @item FTW_DNR This is a directory which cannot be read with @code{readdir()}. (This will never happen in DJGPP.) @item FTW_NS This file exists, but @code{stat} fails for it. @end table If @var{flag} is @code{FTW_DNR}, the descendants of that directory won't be processed. If @var{flag} is @code{FTW_NS}, then @var{stbuf} will be garbled. This function always visits a directory before any of its siblings. The argument @var{dir} must be a directory, or @code{ftw} will fail and set @code{errno} to @code{ENOTDIR}. The function @var{func} is called with @var{dir} as its argument before the recursive descent begins. The @var{depth} argument has no meaning in the DJGPP implementation and is always ignored. The tree traversal continues until one of the following events: (1) The tree is exhausted (i.e., all descendants of @var{dir} are processed). In this case, @code{ftw} returns 0, meaning a success. (2) An invocation of @var{func} returns a non-zero value. In this case, @code{ftw} stops the tree traversal and returns whatever @var{func} returned. (3) An error is detected within @code{ftw}. In that case, @code{ftw} returns -1 and sets @code{errno} (@pxref{errno}) to a suitable value. @subheading Return Value Zero in case the entire tree was successfully traversed, -1 if @code{ftw} detected some error during its operation, or any other non-zero value which was returned by the user-defined function @var{func}. @subheading Implementation Notes This function uses @code{malloc} (@pxref{malloc}) for dynamic memory allocation during its operation. If @var{func} disrupts the normal flow of code execution by e.g. calling @code{longjump} or if an interrupt handler which never returns is executed, this memory will remain permanently allocated. This function calls @code{opendir()} and @code{readdir()} functions to read the directory entries. Therefore, you can control what files will your @var{func} get by setting the appropriate bits in the external variable @var{__opendir_flags}. @xref{opendir}, for description of these bits. This function also calls @code{stat} for every directory entry it passes to @var{func}. If your application only needs some part of the information returned in the @code{stat} structure, you can make your application significantly faster by setting bits in the external variable @var{_djstat_flags} (@pxref{_djstat_flags} for details). The most expensive @code{stat} features are @code{_STAT_EXEC_MAGIC} and @code{_STAT_DIRSIZE}. @subheading Portability @portability !ansi, !posix @subheading Example @example #include int file_walker(const char *path, struct stat *sb, int flag) @{ char *base; printf("%s:\t%u\t", path, sb->st_size); if (S_ISLABEL(sb->st_mode)) printf("V"); if (S_ISDIR(sb->st_mode)) printf("D"); if (S_ISCHR(sb->st_mode)) printf("C"); if (sb->st_mode & S_IRUSR) printf("r"); if (sb->st_mode & S_IWUSR) printf("w"); if (sb->st_mode & S_IXUSR) printf("x"); if (flag == FTW_NS) printf(" !!no_stat!!"); printf("\n"); base = strrchr(path, '/'); if (base == 0) base = strrchr(path, '\\'); if (base == 0) base = strrchr(path, ':'); if (strcmp(base == 0 ? path : base + 1, "xxxxx") == 0) return 42; return 0; @} int main(int argc, char *argv[]) @{ if (argc > 1) @{ char msg[80]; sprintf(msg, "file_tree_walk: %d", ftw(argv[1], file_walker, 0)); if (errno) perror(msg); else puts(msg); @} else printf("Usage: %s dir\n", argv[0]); return 0; @} @end example