/* Traverse a file hierarchy.
- Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include <string.h>
#include <unistd.h>
+#if ! _LIBC
+# include "lstat.h"
+#endif
+
#if defined _LIBC
# include <dirent.h>
# define NAMLEN(dirent) _D_EXACT_NAMLEN (dirent)
# define internal_function /* empty */
#endif
-/* Arrange to make lstat calls go through the wrapper function
- on systems with an lstat function that does not dereference symlinks
- that are specified with a trailing slash. */
-#if ! _LIBC && ! LSTAT_FOLLOWS_SLASHED_SYMLINK
-int rpl_lstat (const char *, struct stat *);
-# undef lstat
-# define lstat(Name, Stat_buf) rpl_lstat(Name, Stat_buf)
-#endif
-
#ifndef __set_errno
# define __set_errno(Val) errno = (Val)
#endif
static void leave_dir (FTS *fts, FTSENT *ent) {}
static bool setup_dir (FTS *fts) { return true; }
static void free_dir (FTS *fts) {}
-static int fd_safer (int fd) { return fd; }
#else
+# include "fcntl--.h"
# include "fts-cycle.c"
-# include "unistd-safer.h"
#endif
#ifndef MAX
internal_function
diropen (char const *dir)
{
- int fd = open (dir, O_RDONLY | O_DIRECTORY);
- if (fd < 0)
- fd = open (dir, O_WRONLY | O_DIRECTORY);
- return fd;
+ return open (dir, O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK);
}
FTS *
#ifndef MAXPATHLEN
# define MAXPATHLEN 1024
#endif
- if (! fts_palloc(sp, MAX(fts_maxarglen(argv), MAXPATHLEN)))
- goto mem1;
+ {
+ size_t maxarglen = fts_maxarglen(argv);
+ if (! fts_palloc(sp, MAX(maxarglen, MAXPATHLEN)))
+ goto mem1;
+ }
/* Allocate/initialize root's parent. */
if ((parent = fts_alloc(sp, "", 0)) == NULL)
if (p->fts_level == FTS_ROOTLEVEL) {
if (FCHDIR(sp, sp->fts_rfd)) {
SET(FTS_STOP);
+ sp->fts_cur = p;
return (NULL);
}
fts_load(sp, p);
return (sp->fts_child = NULL);
sp->fts_child = fts_build(sp, instr);
if (fchdir(fd)) {
+ int saved_errno = errno;
(void)close(fd);
+ __set_errno (saved_errno);
return (NULL);
}
(void)close(fd);
struct Active_dir ad;
ad.ino = t->fts_statp->st_ino;
ad.dev = t->fts_statp->st_dev;
- if ( ! hash_lookup (sp->active_dir_ht, &ad))
+ if ( ! hash_lookup (sp->fts_cycle.ht, &ad))
printf ("ERROR: active dir, %s, not in tree\n", t->fts_path);
}
|| ent->fts_info == FTS_D))
{
struct Active_dir *ad;
- for (ad = hash_get_first (sp->active_dir_ht); ad != NULL;
- ad = hash_get_next (sp->active_dir_ht, ad))
+ for (ad = hash_get_first (sp->fts_cycle.ht); ad != NULL;
+ ad = hash_get_next (sp->fts_cycle.ht, ad))
{
find_matching_ancestor (ent, ad);
}
if (ISSET(FTS_LOGICAL) || follow) {
if (stat(p->fts_accpath, sbp)) {
saved_errno = errno;
- if (!lstat(p->fts_accpath, sbp)) {
+ if (errno == ENOENT
+ && lstat(p->fts_accpath, sbp) == 0) {
__set_errno (0);
return (FTS_SLNONE);
}
newfd = fd;
if (ISSET(FTS_NOCHDIR))
return (0);
- if (fd < 0 && (newfd = fd_safer (diropen (dir))) < 0)
+ if (fd < 0 && (newfd = diropen (dir)) < 0)
return (-1);
if (fstat(newfd, &sb)) {
ret = -1;