#if ! _LIBC
# include "fcntl--.h"
-# include "openat.h"
+# include "dirent--.h"
# include "unistd--.h"
# include "same-inode.h"
#endif
# define SIZE_MAX ((size_t) -1)
#endif
-#ifndef O_DIRECTORY
-# define O_DIRECTORY 0
-#endif
-
#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
#define STREQ(a, b) (strcmp ((a), (b)) == 0)
internal_function
opendirat (int fd, char const *dir)
{
- int new_fd = openat (fd, dir, O_RDONLY);
+ int new_fd = openat (fd, dir,
+ O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK);
DIR *dirp;
if (new_fd < 0)
if (ISSET(FTS_CWDFD))
{
if (0 <= sp->fts_cwd_fd)
- close (sp->fts_cwd_fd);
+ if (close (sp->fts_cwd_fd))
+ saved_errno = errno;
}
else if (!ISSET(FTS_NOCHDIR))
{
/* Return to original directory, save errno if necessary. */
if (fchdir(sp->fts_rfd))
saved_errno = errno;
- close(sp->fts_rfd);
+
+ /* If close fails, record errno only if saved_errno is zero,
+ so that we report the probably-more-meaningful fchdir errno. */
+ if (close (sp->fts_rfd))
+ if (saved_errno == 0)
+ saved_errno = errno;
}
fd_ring_clear (&sp->fts_fd_ring);
+#if GNULIB_FTS
if (sp->fts_leaf_optimization_works_ht)
hash_free (sp->fts_leaf_optimization_works_ht);
+#endif
free_dir (sp);
static bool leaf_optimization_applies (int dir_fd) { return false; }
#endif
+#if GNULIB_FTS
/* link-count-optimization entry:
map an stat.st_dev number to a boolean: leaf_optimization_works */
struct LCO_ent
return opt_ok;
}
+#endif
/*
* Special case of "/" at the end of the file name so that slashes aren't
SET(FTS_STOP);
return (NULL);
}
+ free_dir(sp);
fts_load(sp, p);
+ setup_dir(sp);
goto check_for_dir;
}
if (p->fts_statp->st_size == FTS_STAT_REQUIRED)
{
FTSENT *parent = p->fts_parent;
- if (parent->fts_n_dirs_remaining == 0
+ if (FTS_ROOTLEVEL < p->fts_level
+ /* ->fts_n_dirs_remaining is not valid
+ for command-line-specified names. */
+ && parent->fts_n_dirs_remaining == 0
&& ISSET(FTS_NOSTAT)
&& ISSET(FTS_PHYSICAL)
&& link_count_optimize_ok (parent))
else
{
p->fts_info = fts_stat(sp, p, false);
- if (S_ISDIR(p->fts_statp->st_mode))
- {
- if (parent->fts_n_dirs_remaining)
+ if (S_ISDIR(p->fts_statp->st_mode)
+ && p->fts_level != FTS_ROOTLEVEL
+ && parent->fts_n_dirs_remaining)
parent->fts_n_dirs_remaining--;
- }
}
}
else