ftw.c
上传用户:sy_wanhua
上传日期:2013-07-25
资源大小:3048k
文件大小:7k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

C/C++

  1. /*
  2.  * Copyright (c) 1988 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17. #define HAVE_DIRENT 1
  18. #define HAVE_SYMLINK 1
  19. #ifdef HAVE_DIRENT
  20. #include <dirent.h>
  21. #else
  22. #include <sys/dir.h>
  23. #endif
  24. #include <errno.h>
  25. #include <sys/param.h>
  26. #include <sys/stat.h>
  27. #include <sys/stat.h>
  28. #include "ftw.h"
  29. #if !HAS_FTW
  30. #if defined(LIBC_SCCS) && !defined(lint)
  31. static char sccsid[] = "@(#)ftw.c 5.3 (Berkeley) 8/5/88";
  32. #endif /* LIBC_SCCS and not lint */
  33. /* #include "../src/config.h" */
  34. #define NODESC -1
  35. #ifdef HAVE_SYMLINK
  36. # define ISLINK(sb) ((sb.st_mode&S_IFMT) == S_IFLNK)
  37. #else
  38. # define lstat stat
  39. #endif
  40. #define ISDIR(sb) ((sb.st_mode&S_IFMT) == S_IFDIR)
  41. #define ISDOT(dp) 
  42. (dp->d_name[0] == '.' && (!dp->d_name[1] || 
  43.     (dp->d_name[1] == '.' && !dp->d_name[2])))
  44. extern int errno;
  45. static int g_fds,
  46.   (*g_fn) (),
  47.   g_opts;
  48. static char *bp;
  49. #ifdef __STDC__
  50. int treewalk(const char *path, int (*fn) (const char *file, const struct stat *sb, int flag), int maxfds, int opts);
  51. #else
  52. int treewalk();
  53. #endif
  54. /*
  55.  * cycle through the directories at the top of the tree, otherwise, once
  56.  * you run out of descriptors you have to keep reusing the same one and
  57.  * it gets *real* slow.
  58.  */
  59. typedef struct d_fd {
  60. struct d_fd *next;
  61. DIR *dirp;
  62. off_t off;
  63. } FD;
  64. static FD *freep,
  65.  *node;
  66. static int
  67. walk(register char *name)
  68. {
  69. #ifdef HAVE_DIRENT
  70. register struct dirent *dp;
  71. #else
  72. register struct direct *dp;
  73. #endif
  74. register int rval;
  75. struct stat sb;
  76. FD cur;
  77. char *save,
  78. #ifdef __STDC__
  79.  *strcpy(char *, const char *);
  80. #else
  81.  *strcpy();
  82. #endif
  83. if (!freep)
  84. freep = &cur;
  85. else
  86. node->next = &cur;
  87. node = &cur;
  88. cur.off = 0;
  89.   getfd:if (!g_fds) {
  90. freep->off = telldir(freep->dirp);
  91. closedir(freep->dirp);
  92. freep = freep->next;
  93. ++g_fds;
  94. }
  95. if ( !(cur.dirp = opendir(bp)) ) {
  96. if (errno == EMFILE) {
  97. g_fds = 0;
  98. goto getfd;
  99. }
  100. return (errno == EACCES ? (*g_fn) (bp, &sb, FTW_DNR) : -1);
  101. } else
  102. --g_fds;
  103. for (; *name; ++name) ;
  104. *name++ = '/';
  105. for (rval = 0, dp = readdir(cur.dirp); dp; dp = readdir(cur.dirp)) {
  106. if (ISDOT(dp))
  107. continue;
  108. (void) strcpy(name, dp->d_name);
  109. if (lstat(bp, &sb)) {
  110. rval = errno == EACCES ?
  111. (*g_fn) (bp, &sb, FTW_NS) : -1;
  112. if (rval)
  113. break;
  114. }
  115. #ifdef HAVE_SYMLINK
  116. if (ISLINK(sb) && g_opts & FTW_SYMLINK)
  117. if (stat(bp, &sb))
  118. continue;
  119. #endif
  120. if (!ISDIR(sb)) {
  121. rval = (*g_fn) (bp, &sb, FTW_F);
  122. if (rval)
  123. break;
  124. continue;
  125. }
  126. if (g_opts & FTW_DIRLAST)
  127. #ifdef HAVE_D_NAMLEN
  128. save = name + dp->d_namlen;
  129. #else
  130. save = name + strlen(dp->d_name);
  131. #endif
  132. rval = (*g_fn) (bp, &sb, FTW_D);
  133. if ( (rval && rval != NODESC) || (rval = walk(name)))
  134. break;
  135. if (g_opts & FTW_DIRLAST) {
  136. *save = '';
  137. rval = (*g_fn) (dp->d_name, &sb, FTW_D2);
  138. if (rval)
  139. if (rval == NODESC)
  140. rval = 0;
  141. else
  142. break;
  143. }
  144. if (cur.off) {
  145. *name = '';
  146. if ( (cur.dirp = opendir(bp)) ) {
  147. seekdir(cur.dirp, cur.off);
  148. /* tricky; if we have to reset the directory pointer we know
  149.  * it's the next one to reuse */
  150. freep = &cur;
  151. --g_fds;
  152. }
  153. /* directory moved from under us!!! */
  154. else {
  155. rval = -1;
  156. break;
  157. }
  158. }
  159. }
  160. closedir(cur.dirp);
  161. ++g_fds;
  162. return (rval);
  163. }
  164. static int
  165. chwalk(register const char *name)
  166. {
  167. #ifdef HAVE_DIRENT
  168. register struct dirent *dp;
  169. #else
  170. register struct direct *dp;
  171. #endif
  172. register int rval;
  173. struct stat sb;
  174. FD cur;
  175. char *pwd,
  176.  *getwd(char *),
  177. #ifndef NO_MALLOC_PROTO
  178.  *malloc(size_t),
  179. #endif
  180.  *strcpy(char *, const char *);
  181. if (!freep)
  182. freep = &cur;
  183. else
  184. node->next = &cur;
  185. node = &cur;
  186. cur.off = 0;
  187. if (chdir(name))
  188. return (errno == EACCES ? (*g_fn) (name, &sb, FTW_DNR) : -1);
  189.   getfd:if (!g_fds) {
  190. freep->off = telldir(freep->dirp);
  191. closedir(freep->dirp);
  192. freep = freep->next;
  193. ++g_fds;
  194. }
  195. if ( !(cur.dirp = opendir(".")) )  {
  196. if (errno == EMFILE) {
  197. g_fds = 0;
  198. goto getfd;
  199. }
  200. return (errno == EACCES ? (*g_fn) (".", &sb, FTW_DNR) : -1);
  201. } else
  202. --g_fds;
  203. for (rval = 0, dp = readdir(cur.dirp); dp; dp = readdir(cur.dirp)) {
  204. if (ISDOT(dp))
  205. continue;
  206. if (lstat(dp->d_name, &sb)) {
  207. rval = errno == EACCES ?
  208. (*g_fn) (dp->d_name, &sb, FTW_NS) : -1;
  209. if (rval)
  210. break;
  211. }
  212. pwd = NULL;
  213. #ifdef HAVE_SYMLINK
  214. if (ISLINK(sb) && g_opts & FTW_SYMLINK) {
  215. if (stat(dp->d_name, &sb))
  216. continue;
  217. if (ISDIR(sb)) {
  218. /* NOSTRICT */
  219. if (!(pwd = malloc((u_int) MAXPATHLEN))) {
  220. rval = -1;
  221. break;
  222. }
  223. if (!getwd(pwd)) {
  224. rval = -1;
  225. break;
  226. }
  227. }
  228. }
  229. #endif
  230. if (!ISDIR(sb)) {
  231. rval = (*g_fn) (dp->d_name, &sb, FTW_F);
  232. if (rval)
  233. break;
  234. continue;
  235. }
  236. rval = (*g_fn) (dp->d_name, &sb, FTW_D);
  237. if ((rval && rval != NODESC) || (rval = chwalk(dp->d_name)))
  238. break;
  239. if (g_opts & FTW_DIRLAST) {
  240. rval = (*g_fn) (dp->d_name, &sb, FTW_D2);
  241. if (rval)
  242. if (rval == NODESC)
  243. rval = 0;
  244. else
  245. break;
  246. }
  247. if (pwd && chdir(pwd)) {
  248. rval = -1;
  249. break;
  250. }
  251. if (cur.off) {
  252. if ( (cur.dirp = opendir(".")) ) {
  253. seekdir(cur.dirp, cur.off);
  254. /* tricky; if we have to reset the directory pointer we know
  255.  * it's the next one to reuse */
  256. freep = &cur;
  257. --g_fds;
  258. }
  259. /* directory moved from under us!!! */
  260. else {
  261. rval = -1;
  262. break;
  263. }
  264. }
  265. }
  266. closedir(cur.dirp);
  267. ++g_fds;
  268. if (chdir(".."))
  269. return (-1);
  270. return (rval);
  271. }
  272. /* S5 compatible ftw(BA_LIB) */
  273. int
  274. ftw(const char *path, int (*fn) (const char *file, const struct stat *sb, int flag), int maxfds)
  275. {
  276. return (treewalk(path, fn, maxfds, 0));
  277. }
  278. int
  279. treewalk(const char *path, int (*fn) (const char *file, const struct stat *sb, int flag), int maxfds, int opts)
  280. {
  281. struct stat sb;
  282. int rval;
  283. char *pwd,
  284.  *getwd(char *),
  285. #ifndef NO_MALLOC_PROTO
  286.  *malloc(size_t),
  287. #endif
  288.  *strcpy(char *, const char *);
  289. if (lstat(path, &sb))
  290. return (errno == EACCES ? (*fn) (path, &sb, FTW_NS) : -1);
  291. pwd = NULL;
  292. #ifdef HAVE_SYMLINK
  293. if (ISLINK(sb) && opts & FTW_SYMLINK) {
  294. if (stat(path, &sb))
  295. return (0);
  296. if (ISDIR(sb)) {
  297. /* NOSTRICT */
  298. if (!(pwd = malloc((u_int) MAXPATHLEN)))
  299. return (-1);
  300. if (!getwd(pwd))
  301. return (-1);
  302. }
  303. }
  304. #endif
  305. if (!ISDIR(sb))
  306. return ((*fn) (path, &sb, FTW_F));
  307. if (!maxfds)
  308. return (-1);
  309. g_fds = maxfds == -1 ? getdtablesize(): maxfds;
  310. g_fn = fn;
  311. g_opts = opts;
  312. if (!(opts & FTW_CHDIR) && !(bp = malloc((u_int) MAXPATHLEN))) {
  313. errno = ENOMEM;
  314. return (-1);
  315. }
  316. rval = (*fn) (path, &sb, FTW_D);
  317. if (rval == NODESC)
  318. rval = 0;
  319. else if (!rval) {
  320. if (opts & FTW_CHDIR)
  321. rval = chwalk(path);
  322. else
  323. rval = walk(strcpy(bp, path));
  324. if (!rval && opts & FTW_DIRLAST) {
  325. rval = (*fn) (path, &sb, FTW_D2);
  326. if (rval == NODESC)
  327. rval = 0;
  328. }
  329. }
  330. if (pwd && chdir(pwd))
  331. return (-1);
  332. return (rval);
  333. }
  334. #endif