/* 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
# define fchdir __fchdir
# undef open
# define open __open
-# undef opendir
-# define opendir __opendir
# undef readdir
# define readdir __readdir
#else
/* FIXME: if others need this function, move it into lib/openat.c */
static inline DIR *
internal_function
-opendirat (int fd, char const *dir)
+opendirat (int fd, char const *dir, int extra_flags, int *pdir_fd)
{
int new_fd = openat (fd, dir,
- O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK);
+ (O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK
+ | extra_flags));
DIR *dirp;
if (new_fd < 0)
return NULL;
set_cloexec_flag (new_fd, true);
dirp = fdopendir (new_fd);
- if (dirp == NULL)
+ if (dirp)
+ *pdir_fd = new_fd;
+ else
{
int saved_errno = errno;
close (new_fd);
bool nostat;
size_t len, maxlen, new_len;
char *cp;
+ int dir_fd;
/* Set current node pointer. */
cur = sp->fts_cur;
oflag = DTF_HIDEW|DTF_NODUP|DTF_REWIND;
#else
# define __opendir2(file, flag) \
- ( ! ISSET(FTS_NOCHDIR) && ISSET(FTS_CWDFD) \
- ? opendirat(sp->fts_cwd_fd, file) \
- : opendir(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), \
+ &dir_fd)
#endif
if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) {
if (type == BREAD) {
* checking FTS_NS on the returned nodes.
*/
if (nlinks || type == BREAD) {
- int dir_fd = dirfd(dirp);
- if (ISSET(FTS_CWDFD) && 0 <= dir_fd)
+ if (ISSET(FTS_CWDFD))
{
dir_fd = dup (dir_fd);
- set_cloexec_flag (dir_fd, true);
+ if (0 <= dir_fd)
+ set_cloexec_flag (dir_fd, true);
}
if (dir_fd < 0 || fts_safe_changedir(sp, cur, dir_fd, NULL)) {
if (nlinks && type == BREAD)