1/*-
2 * Copyright (c) 2003-2007 Tim Kientzle
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 * $FreeBSD$
26 */
27
28/*-
29 * A set of routines for traversing directory trees.
30 * Similar in concept to the fts library, but with a few
31 * important differences:
32 *    * Uses less memory.  In particular, fts stores an entire directory
33 *      in memory at a time.  This package only keeps enough subdirectory
34 *      information in memory to track the traversal.  Information
35 *      about non-directories is discarded as soon as possible.
36 *    * Supports very deep logical traversals.  The fts package
37 *      uses "non-chdir" approach for logical traversals.  This
38 *      package does use a chdir approach for logical traversals
39 *      and can therefore handle pathnames much longer than
40 *      PATH_MAX.
41 *    * Supports deep physical traversals "out of the box."
42 *      Due to the memory optimizations above, there's no need to
43 *      limit dir names to 32k.
44 */
45
46#include <sys/stat.h>
47#include <stdio.h>
48
49struct tree;
50
51/* Initiate/terminate a tree traversal. */
52struct tree *tree_open(const char * /* pathname */);
53void tree_close(struct tree *);
54
55/*
56 * tree_next() returns Zero if there is no next entry, non-zero if there is.
57 * Note that directories are potentially visited three times.  The first
58 * time as "regular" file.  If tree_descend() is invoked at that time,
59 * the directory is added to a work list and will be visited two more
60 * times:  once just after descending into the directory and again
61 * just after ascending back to the parent.
62 *
63 * TREE_ERROR is returned if the descent failed (because the
64 * directory couldn't be opened, for instance).  This is returned
65 * instead of TREE_PREVISIT/TREE_POSTVISIT.
66 */
67#define	TREE_REGULAR	1
68#define	TREE_POSTDESCENT	2
69#define	TREE_POSTASCENT	3
70#define	TREE_ERROR_DIR	-1
71int tree_next(struct tree *);
72
73int tree_errno(struct tree *);
74
75/*
76 * Request that current entry be visited.  If you invoke it on every
77 * directory, you'll get a physical traversal.  This is ignored if the
78 * current entry isn't a directory or a link to a directory.  So, if
79 * you invoke this on every returned path, you'll get a full logical
80 * traversal.
81 */
82void tree_descend(struct tree *);
83
84/*
85 * Return information about the current entry.
86 */
87
88int tree_current_depth(struct tree *);
89/*
90 * The current full pathname, length of the full pathname,
91 * and a name that can be used to access the file.
92 * Because tree does use chdir extensively, the access path is
93 * almost never the same as the full current path.
94 */
95const char *tree_current_path(struct tree *);
96size_t tree_current_pathlen(struct tree *);
97const char *tree_current_access_path(struct tree *);
98/*
99 * Request the lstat() or stat() data for the current path.  Since the
100 * tree package needs to do some of this anyway, and caches the
101 * results, you should take advantage of it here if you need it rather
102 * than make a redundant stat() or lstat() call of your own.
103 */
104const struct stat *tree_current_stat(struct tree *);
105const struct stat *tree_current_lstat(struct tree *);
106/* The following tests may use mechanisms much faster than stat()/lstat(). */
107/* "is_physical_dir" is equivalent to S_ISDIR(tree_current_lstat()->st_mode) */
108int tree_current_is_physical_dir(struct tree *);
109/* "is_physical_link" is equivalent to S_ISLNK(tree_current_lstat()->st_mode) */
110int tree_current_is_physical_link(struct tree *);
111/* "is_dir" is equivalent to S_ISDIR(tree_current_stat()->st_mode) */
112int tree_current_is_dir(struct tree *);
113
114/* For testing/debugging: Dump the internal status to the given filehandle. */
115void tree_dump(struct tree *, FILE *);
116