aboutsummaryrefslogtreecommitdiff
path: root/gnu/libexec/uucp/libunix/ftw.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/libexec/uucp/libunix/ftw.c')
-rw-r--r--gnu/libexec/uucp/libunix/ftw.c250
1 files changed, 250 insertions, 0 deletions
diff --git a/gnu/libexec/uucp/libunix/ftw.c b/gnu/libexec/uucp/libunix/ftw.c
new file mode 100644
index 000000000000..c3372b53ca48
--- /dev/null
+++ b/gnu/libexec/uucp/libunix/ftw.c
@@ -0,0 +1,250 @@
+/* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+Contributed by Ian Lance Taylor (ian@airs.com).
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+Modified by Ian Lanc Taylor for Taylor UUCP, June 1992. */
+
+#include "uucp.h"
+
+#include "sysdep.h"
+
+#include <errno.h>
+
+#if HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#if HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#if HAVE_OPENDIR
+#if HAVE_DIRENT_H
+#include <dirent.h>
+#else /* ! HAVE_DIRENT_H */
+#include <sys/dir.h>
+#define dirent direct
+#endif /* ! HAVE_DIRENT_H */
+#endif /* HAVE_OPENDIR */
+
+#if HAVE_FTW_H
+#include <ftw.h>
+#endif
+
+#ifndef PATH_MAX
+#ifdef MAXPATHLEN
+#define PATH_MAX MAXPATHLEN
+#else
+#define PATH_MAX 1024
+#endif
+#endif
+
+/* Traverse one level of a directory tree. */
+
+static int
+ftw_dir (dirs, level, descriptors, dir, len, func)
+ DIR **dirs;
+ int level;
+ int descriptors;
+ char *dir;
+ size_t len;
+ int (*func) P((const char *file, const struct stat *status, int flag));
+{
+ int got;
+ struct dirent *entry;
+
+ got = 0;
+
+ errno = 0;
+
+ while ((entry = readdir (dirs[level])) != NULL)
+ {
+ size_t namlen;
+ struct stat s;
+ int flag, ret, newlev;
+
+ ++got;
+
+ namlen = strlen (entry->d_name);
+ if (entry->d_name[0] == '.'
+ && (namlen == 1 ||
+ (namlen == 2 && entry->d_name[1] == '.')))
+ {
+ errno = 0;
+ continue;
+ }
+
+ if (namlen + len + 1 > PATH_MAX)
+ {
+#ifdef ENAMETOOLONG
+ errno = ENAMETOOLONG;
+#else
+ errno = ENOMEM;
+#endif
+ return -1;
+ }
+
+ dir[len] = '/';
+ memcpy ((dir + len + 1), entry->d_name, namlen + 1);
+
+ if (stat (dir, &s) < 0)
+ {
+ if (errno != EACCES)
+ return -1;
+ flag = FTW_NS;
+ }
+ else if (S_ISDIR (s.st_mode))
+ {
+ newlev = (level + 1) % descriptors;
+
+ if (dirs[newlev] != NULL)
+ closedir (dirs[newlev]);
+
+ dirs[newlev] = opendir (dir);
+ if (dirs[newlev] != NULL)
+ flag = FTW_D;
+ else
+ {
+ if (errno != EACCES)
+ return -1;
+ flag = FTW_DNR;
+ }
+ }
+ else
+ flag = FTW_F;
+
+ ret = (*func) (dir, &s, flag);
+
+ if (flag == FTW_D)
+ {
+ if (ret == 0)
+ ret = ftw_dir (dirs, newlev, descriptors, dir,
+ namlen + len + 1, func);
+ if (dirs[newlev] != NULL)
+ {
+ int save;
+
+ save = errno;
+ closedir (dirs[newlev]);
+ errno = save;
+ dirs[newlev] = NULL;
+ }
+ }
+
+ if (ret != 0)
+ return ret;
+
+ if (dirs[level] == NULL)
+ {
+ int skip;
+
+ dir[len] = '\0';
+ dirs[level] = opendir (dir);
+ if (dirs[level] == NULL)
+ return -1;
+ skip = got;
+ while (skip-- != 0)
+ {
+ errno = 0;
+ if (readdir (dirs[level]) == NULL)
+ return errno == 0 ? 0 : -1;
+ }
+ }
+
+ errno = 0;
+ }
+
+ return errno == 0 ? 0 : -1;
+}
+
+/* Call a function on every element in a directory tree. */
+
+int
+ftw (dir, func, descriptors)
+ const char *dir;
+ int (*func) P((const char *file, const struct stat *status, int flag));
+ int descriptors;
+{
+ DIR **dirs;
+ int c;
+ DIR **p;
+ size_t len;
+ char buf[PATH_MAX + 1];
+ struct stat s;
+ int flag, ret;
+
+ if (descriptors <= 0)
+ descriptors = 1;
+
+ dirs = (DIR **) malloc (descriptors * sizeof (DIR *));
+ if (dirs == NULL)
+ return -1;
+ c = descriptors;
+ p = dirs;
+ while (c-- != 0)
+ *p++ = NULL;
+
+ len = strlen (dir);
+ memcpy (buf, dir, len + 1);
+
+ if (stat (dir, &s) < 0)
+ {
+ if (errno != EACCES)
+ {
+ free ((pointer) dirs);
+ return -1;
+ }
+ flag = FTW_NS;
+ }
+ else if (S_ISDIR (s.st_mode))
+ {
+ dirs[0] = opendir (dir);
+ if (dirs[0] != NULL)
+ flag = FTW_D;
+ else
+ {
+ if (errno != EACCES)
+ {
+ free ((pointer) dirs);
+ return -1;
+ }
+ flag = FTW_DNR;
+ }
+ }
+ else
+ flag = FTW_F;
+
+ ret = (*func) (buf, &s, flag);
+
+ if (flag == FTW_D)
+ {
+ if (ret == 0)
+ ret = ftw_dir (dirs, 0, descriptors, buf, len, func);
+ if (dirs[0] != NULL)
+ {
+ int save;
+
+ save = errno;
+ closedir (dirs[0]);
+ errno = save;
+ }
+ }
+
+ free ((pointer) dirs);
+ return ret;
+}