|
|
1.1 root 1: /* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
2: This file is part of the GNU C Library.
3: Contributed by Ian Lance Taylor ([email protected]).
4:
5: The GNU C Library is free software; you can redistribute it and/or
6: modify it under the terms of the GNU Library General Public License as
7: published by the Free Software Foundation; either version 2 of the
8: License, or (at your option) any later version.
9:
10: The GNU C Library is distributed in the hope that it will be useful,
11: but WITHOUT ANY WARRANTY; without even the implied warranty of
12: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13: Library General Public License for more details.
14:
15: You should have received a copy of the GNU Library General Public
16: License along with the GNU C Library; see the file COPYING.LIB. If
17: not, write to the Free Software Foundation, Inc., 675 Mass Ave,
18: Cambridge, MA 02139, USA.
19:
20: Modified by Ian Lanc Taylor for Taylor UUCP, June 1992. */
21:
22: #include "uucp.h"
23:
24: #include "sysdep.h"
25:
26: #include <errno.h>
27:
28: #if HAVE_LIMITS_H
29: #include <limits.h>
30: #endif
31:
32: #if HAVE_SYS_PARAM_H
33: #include <sys/param.h>
34: #endif
35:
36: #if HAVE_OPENDIR
37: #if HAVE_DIRENT_H
38: #include <dirent.h>
39: #else /* ! HAVE_DIRENT_H */
40: #include <sys/dir.h>
41: #define dirent direct
42: #endif /* ! HAVE_DIRENT_H */
43: #endif /* HAVE_OPENDIR */
44:
45: #if HAVE_FTW_H
46: #include <ftw.h>
47: #endif
48:
49: #ifndef PATH_MAX
50: #ifdef MAXPATHLEN
51: #define PATH_MAX MAXPATHLEN
52: #else
53: #define PATH_MAX 1024
54: #endif
55: #endif
56:
57: /* Traverse one level of a directory tree. */
58:
59: static int
60: ftw_dir (dirs, level, descriptors, dir, len, func)
61: DIR **dirs;
62: int level;
63: int descriptors;
64: char *dir;
65: size_t len;
66: int (*func) P((const char *file, const struct stat *status, int flag));
67: {
68: int got;
69: struct dirent *entry;
70:
71: got = 0;
72:
73: errno = 0;
74:
75: while ((entry = readdir (dirs[level])) != NULL)
76: {
77: size_t namlen;
78: struct stat s;
79: int flag, ret, newlev;
80:
81: ++got;
82:
83: namlen = strlen (entry->d_name);
84: if (entry->d_name[0] == '.'
85: && (namlen == 1 ||
86: (namlen == 2 && entry->d_name[1] == '.')))
87: {
88: errno = 0;
89: continue;
90: }
91:
92: if (namlen + len + 1 > PATH_MAX)
93: {
94: #ifdef ENAMETOOLONG
95: errno = ENAMETOOLONG;
96: #else
97: errno = ENOMEM;
98: #endif
99: return -1;
100: }
101:
102: dir[len] = '/';
103: memcpy ((dir + len + 1), entry->d_name, namlen + 1);
104:
105: if (stat (dir, &s) < 0)
106: {
107: if (errno != EACCES)
108: return -1;
109: flag = FTW_NS;
110: }
111: else if (S_ISDIR (s.st_mode))
112: {
113: newlev = (level + 1) % descriptors;
114:
115: if (dirs[newlev] != NULL)
116: closedir (dirs[newlev]);
117:
118: dirs[newlev] = opendir (dir);
119: if (dirs[newlev] != NULL)
120: flag = FTW_D;
121: else
122: {
123: if (errno != EACCES)
124: return -1;
125: flag = FTW_DNR;
126: }
127: }
128: else
129: flag = FTW_F;
130:
131: ret = (*func) (dir, &s, flag);
132:
133: if (flag == FTW_D)
134: {
135: if (ret == 0)
136: ret = ftw_dir (dirs, newlev, descriptors, dir,
137: namlen + len + 1, func);
138: if (dirs[newlev] != NULL)
139: {
140: int save;
141:
142: save = errno;
143: closedir (dirs[newlev]);
144: errno = save;
145: dirs[newlev] = NULL;
146: }
147: }
148:
149: if (ret != 0)
150: return ret;
151:
152: if (dirs[level] == NULL)
153: {
154: int skip;
155:
156: dir[len] = '\0';
157: dirs[level] = opendir (dir);
158: if (dirs[level] == NULL)
159: return -1;
160: skip = got;
161: while (skip-- != 0)
162: {
163: errno = 0;
164: if (readdir (dirs[level]) == NULL)
165: return errno == 0 ? 0 : -1;
166: }
167: }
168:
169: errno = 0;
170: }
171:
172: return errno == 0 ? 0 : -1;
173: }
174:
175: /* Call a function on every element in a directory tree. */
176:
177: int
178: ftw (dir, func, descriptors)
179: const char *dir;
180: int (*func) P((const char *file, const struct stat *status, int flag));
181: int descriptors;
182: {
183: DIR **dirs;
184: int c;
185: DIR **p;
186: size_t len;
187: char buf[PATH_MAX + 1];
188: struct stat s;
189: int flag, ret;
190:
191: if (descriptors <= 0)
192: descriptors = 1;
193:
194: dirs = (DIR **) malloc (descriptors * sizeof (DIR *));
195: if (dirs == NULL)
196: return -1;
197: c = descriptors;
198: p = dirs;
199: while (c-- != 0)
200: *p++ = NULL;
201:
202: len = strlen (dir);
203: memcpy (buf, dir, len + 1);
204:
205: if (stat (dir, &s) < 0)
206: {
207: if (errno != EACCES)
208: {
209: free ((pointer) dirs);
210: return -1;
211: }
212: flag = FTW_NS;
213: }
214: else if (S_ISDIR (s.st_mode))
215: {
216: dirs[0] = opendir (dir);
217: if (dirs[0] != NULL)
218: flag = FTW_D;
219: else
220: {
221: if (errno != EACCES)
222: {
223: free ((pointer) dirs);
224: return -1;
225: }
226: flag = FTW_DNR;
227: }
228: }
229: else
230: flag = FTW_F;
231:
232: ret = (*func) (buf, &s, flag);
233:
234: if (flag == FTW_D)
235: {
236: if (ret == 0)
237: ret = ftw_dir (dirs, 0, descriptors, buf, len, func);
238: if (dirs[0] != NULL)
239: {
240: int save;
241:
242: save = errno;
243: closedir (dirs[0]);
244: errno = save;
245: }
246: }
247:
248: free ((pointer) dirs);
249: return ret;
250: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.