/* Traverse a file hierarchy.
- Copyright (C) 2004-2010 Free Software Foundation, Inc.
+ Copyright (C) 2004-2011 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
diropen (FTS const *sp, char const *dir)
{
int open_flags = (O_SEARCH | O_DIRECTORY | O_NOCTTY | O_NONBLOCK
- | (ISSET (FTS_PHYSICAL) ? O_NOFOLLOW : 0));
+ | (ISSET (FTS_PHYSICAL) ? O_NOFOLLOW : 0)
+ | (ISSET (FTS_NOATIME) ? O_NOATIME : 0));
int fd = (ISSET (FTS_CWDFD)
? openat (sp->fts_cwd_fd, dir, open_flags)
early, doing it here saves us the trouble of ensuring
later (where it'd be messier) that "." can in fact
be opened. If not, revert to FTS_NOCHDIR mode. */
- int fd = open (".", O_SEARCH);
+ int fd = open (".",
+ O_SEARCH | (ISSET (FTS_NOATIME) ? O_NOATIME : 0));
if (fd < 0)
{
/* Even if `.' is unreadable, don't revert to FTS_NOCHDIR mode
#if defined __linux__ \
&& HAVE_SYS_VFS_H && HAVE_FSTATFS && HAVE_STRUCT_STATFS_F_TYPE
-#include <sys/vfs.h>
+# include <sys/vfs.h>
/* Linux-specific constants from coreutils' src/fs.h */
# define S_MAGIC_TMPFS 0x1021994
#endif
/* link-count-optimization entry:
- map an stat.st_dev number to a boolean: leaf_optimization_works */
+ map a stat.st_dev number to a boolean: leaf_optimization_works */
struct LCO_ent
{
dev_t st_dev;
st->st_mode = type;
}
+# define __opendir2(file) \
+ opendirat((! ISSET(FTS_NOCHDIR) && ISSET(FTS_CWDFD) \
+ ? sp->fts_cwd_fd : AT_FDCWD), \
+ file, \
+ (((ISSET(FTS_PHYSICAL) \
+ && ! (ISSET(FTS_COMFOLLOW) \
+ && cur->fts_level == FTS_ROOTLEVEL)) \
+ ? O_NOFOLLOW : 0) \
+ | (ISSET (FTS_NOATIME) ? O_NOATIME : 0)), \
+ &dir_fd)
+
/*
* This is the tricky part -- do not casually change *anything* in here. The
* idea is to build the linked list of entries that are used by fts_children
/* Set current node pointer. */
cur = sp->fts_cur;
- /*
- * Open the directory for reading. If this fails, we're done.
- * If being called from fts_read, set the fts_info field.
- */
-#if defined FTS_WHITEOUT && 0
- if (ISSET(FTS_WHITEOUT))
- oflag = DTF_NODUP|DTF_REWIND;
- else
- oflag = DTF_HIDEW|DTF_NODUP|DTF_REWIND;
-#else
-# define __opendir2(file, flag) \
- opendirat((! ISSET(FTS_NOCHDIR) && ISSET(FTS_CWDFD) \
- ? sp->fts_cwd_fd : AT_FDCWD), \
- file, \
- ((ISSET(FTS_PHYSICAL) \
- && ! (ISSET(FTS_COMFOLLOW) \
- && cur->fts_level == FTS_ROOTLEVEL)) \
- ? O_NOFOLLOW : 0), \
- &dir_fd)
-#endif
- if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) {
+ /* Open the directory for reading. If this fails, we're done.
+ If being called from fts_read, set the fts_info field. */
+ if ((dirp = __opendir2(cur->fts_accpath)) == NULL) {
if (type == BREAD) {
cur->fts_info = FTS_DNR;
cur->fts_errno = errno;
}
return (NULL);
}
- /* Rather than calling fts_stat for each and every entry encountered
- in the readdir loop (below), stat each directory only right after
- opening it. */
- if (cur->fts_info == FTS_NSOK)
- cur->fts_info = fts_stat(sp, cur, false);
- else if (sp->fts_options & FTS_TIGHT_CYCLE_CHECK) {
- /* Now read the stat info again after opening a directory to
- * reveal eventual changes caused by a submount triggered by
- * the traversal. But do it only for utilities which use
- * FTS_TIGHT_CYCLE_CHECK. Therefore, only find and du
- * benefit/suffer from this feature for now.
- */
- LEAVE_DIR (sp, cur, "4");
- fts_stat (sp, cur, false);
- if (! enter_dir (sp, cur)) {
- __set_errno (ENOMEM);
- return NULL;
- }
- }
+ /* Rather than calling fts_stat for each and every entry encountered
+ in the readdir loop (below), stat each directory only right after
+ opening it. */
+ if (cur->fts_info == FTS_NSOK)
+ cur->fts_info = fts_stat(sp, cur, false);
+ else if (sp->fts_options & FTS_TIGHT_CYCLE_CHECK)
+ {
+ /* Now read the stat info again after opening a directory to
+ reveal eventual changes caused by a submount triggered by
+ the traversal. But do it only for utilities which use
+ FTS_TIGHT_CYCLE_CHECK. Therefore, only find and du
+ benefit/suffer from this feature for now. */
+ LEAVE_DIR (sp, cur, "4");
+ fts_stat (sp, cur, false);
+ if (! enter_dir (sp, cur))
+ {
+ __set_errno (ENOMEM);
+ return NULL;
+ }
+ }
- /*
- * Nlinks is the number of possible entries of type directory in the
- * directory if we're cheating on stat calls, 0 if we're not doing
- * any stat calls at all, (nlink_t) -1 if we're statting everything.
- */
+ /* Nlinks is the number of possible entries of type directory in the
+ directory if we're cheating on stat calls, 0 if we're not doing
+ any stat calls at all, (nlink_t) -1 if we're statting everything. */
if (type == BNAMES) {
nlinks = 0;
/* Be quiet about nostat, GCC. */
p->fts_parent = sp->fts_cur;
p->fts_pathlen = new_len;
-#if defined FTS_WHITEOUT && 0
- if (dp->d_type == DT_WHT)
- p->fts_flags |= FTS_ISW;
-#endif
/* Store dirent.d_ino, in case we need to sort
entries before processing them. */
p->fts_statp->st_ino = D_INO (dp);
int fd = i_ring_pop (&fd_w);
if (0 <= fd)
{
- int parent_fd = openat (cwd_fd, "..", O_SEARCH);
+ int parent_fd = openat (cwd_fd, "..", O_SEARCH | O_NOATIME);
if (parent_fd < 0)
{
// Warn?
if (p->fts_level == FTS_ROOTLEVEL && ISSET(FTS_COMFOLLOW))
follow = true;
-#if defined FTS_WHITEOUT && 0
- /* check for whiteout */
- if (p->fts_flags & FTS_ISW) {
- memset(sbp, '\0', sizeof (*sbp));
- sbp->st_mode = S_IFWHT;
- return (FTS_W);
- }
-#endif
-
/*
* If doing a logical walk, or application requested FTS_FOLLOW, do
* a stat(2). If that fails, check for a non-existent symlink. If