SCCS-vsn: lib/libc/gen/fts.c 5.2
*/
#if defined(LIBC_SCCS) && !defined(lint)
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)fts.c 5.1 (Berkeley) %G%";
+static char sccsid[] = "@(#)fts.c 5.2 (Berkeley) %G%";
#endif /* LIBC_SCCS and not lint */
#include <sys/param.h>
#endif /* LIBC_SCCS and not lint */
#include <sys/param.h>
p->path[0] == '/' ? 0 : p->pathlen)
#define CHDIR(sp, path) (!(sp->options & FTS_NOCHDIR) && chdir(path))
p->path[0] == '/' ? 0 : p->pathlen)
#define CHDIR(sp, path) (!(sp->options & FTS_NOCHDIR) && chdir(path))
+#define FCHDIR(sp, fd) (!(sp->options & FTS_NOCHDIR) && fchdir(fd))
#define ROOTLEVEL 0
#define ROOTPARENTLEVEL -1
#define ROOTLEVEL 0
#define ROOTPARENTLEVEL -1
sp->child = NULL;
}
} else {
sp->child = NULL;
}
} else {
- if (sp->child) {
- /* cd into child directory */
- if (CHDIR(sp, p->accpath)) {
- sp->options |= FTS__STOP;
- p->info = FTS_ERR;
- return(p);
- }
- } else if (!(sp->child = fts_build(sp, 1)))
+ if (!sp->child && (!(sp->child = fts_build(sp, 1))))
return(p);
p = sp->child;
sp->child = NULL;
return(p);
p = sp->child;
sp->child = NULL;
- cp = sp->path + NAPPEND(p->parent);
- *cp++ = '/';
- bcopy(p->name, cp, p->namelen + 1);
return(sp->cur = p);
}
else if (p->info == FTS_SL && instr == FTS_FOLLOW) {
return(sp->cur = p);
}
else if (p->info == FTS_SL && instr == FTS_FOLLOW) {
return(NULL);
if (sp->child)
fts_lfree(sp->child);
return(NULL);
if (sp->child)
fts_lfree(sp->child);
- if (sp->child = fts_build(sp, 0)) {
- /*
- * have to cd up so that the fields of the current node
- * as returned from readfts will be correct.
- */
- if (CHDIR(sp, "..")) {
- sp->options |= FTS__STOP;
- return(NULL);
- }
- }
- return(sp->child);
+ return(sp->child = fts_build(sp, 0));
}
#define ISDOT(a) (a[0] == '.' && (!a[1] || a[1] == '.' && !a[2]))
static FTSENT *
}
#define ISDOT(a) (a[0] == '.' && (!a[1] || a[1] == '.' && !a[2]))
static FTSENT *
-fts_build(sp, set_node_errors)
{
register struct dirent *dp;
register FTSENT *p, *head;
register int nitems;
DIR *dirp;
{
register struct dirent *dp;
register FTSENT *p, *head;
register int nitems;
DIR *dirp;
- int len, level, maxlen, nlinks, saved_errno;
+ int descend, len, level, maxlen, nlinks, saved_errno;
char *cp;
p = sp->cur;
if (!(dirp = opendir(p->accpath))) {
char *cp;
p = sp->cur;
if (!(dirp = opendir(p->accpath))) {
errno = 0;
p->info = FTS_DNR;
}
return(NULL);
}
errno = 0;
p->info = FTS_DNR;
}
return(NULL);
}
- if (CHDIR(sp, p->accpath)) {
- if (set_node_errors) {
- errno = 0;
- p->info = FTS_DNX;
- }
- return(NULL);
- }
/*
* the real slowdown in walking the tree is the stat calls. If
/*
* the real slowdown in walking the tree is the stat calls. If
+ if (nlinks || set_node) {
+ if (FCHDIR(sp, dirfd(dirp))) {
+ if (set_node) {
+ errno = 0;
+ p->info = FTS_DNX;
+ }
+ return(NULL);
+ }
+ descend = 1;
+ } else
+ descend = 0;
+
/* read the directory, attching each new entry to the `link' pointer */
for (head = NULL, nitems = 0; dp = readdir(dirp);) {
if (ISDOT(dp->d_name) && !(sp->options & FTS_SEEDOT))
/* read the directory, attching each new entry to the `link' pointer */
for (head = NULL, nitems = 0; dp = readdir(dirp);) {
if (ISDOT(dp->d_name) && !(sp->options & FTS_SEEDOT))
saved_errno = errno;
(void)free((char *)p);
mem1: fts_lfree(head);
saved_errno = errno;
(void)free((char *)p);
mem1: fts_lfree(head);
+ if (descend && CHDIR(sp, "..")) {
saved_errno = errno;
sp->options |= FTS__STOP;
}
saved_errno = errno;
sp->options |= FTS__STOP;
}
+ if (descend && (!nitems || !set_node) && CHDIR(sp, "..")) {
+ sp->options |= FTS__STOP;
+ p->info = FTS_ERR;
+ *--cp = '\0';
+ return(NULL);
+ }
+
- if (CHDIR(sp, "..")) {
- sp->options |= FTS__STOP;
- p->info = FTS_ERR;
- } else if (set_node_errors)
p->info = FTS_DP;
*--cp = '\0';
return(NULL);
p->info = FTS_DP;
*--cp = '\0';
return(NULL);
if (sp->compar && nitems > 1)
head = fts_sort(head, nitems);
if (sp->compar && nitems > 1)
head = fts_sort(head, nitems);
bcopy(head->name, cp, head->namelen + 1);
else
*--cp = '\0';
bcopy(head->name, cp, head->namelen + 1);
else
*--cp = '\0';