/* Traverse a file hierarchy.
- Copyright (C) 2004-2011 Free Software Foundation, Inc.
+ Copyright (C) 2004-2013 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
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
/* file-descriptor-relative opendir. */
/* FIXME: if others need this function, move it into lib/openat.c */
-static inline DIR *
+static DIR *
internal_function
opendirat (int fd, char const *dir, int extra_flags, int *pdir_fd)
{
descriptor. Return -1 and set errno on failure. It doesn't matter
whether the file descriptor has read or write access. */
-static inline int
+static int
internal_function
diropen (FTS const *sp, char const *dir)
{
O_SEARCH | (ISSET (FTS_NOATIME) ? O_NOATIME : 0));
if (fd < 0)
{
- /* Even if `.' is unreadable, don't revert to FTS_NOCHDIR mode
+ /* Even if "." is unreadable, don't revert to FTS_NOCHDIR mode
on systems like Linux+PROC_FS, where our openat emulation
is good enough. Note: on a system that emulates
openat via /proc, this technique can still fail, but
for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) {
/* *Do* allow zero-length file names. */
size_t len = strlen(*argv);
+
+ if ( ! (options & FTS_VERBATIM))
+ {
+ /* If there are two or more trailing slashes, trim all but one,
+ but don't change "//" to "/", and do map "///" to "/". */
+ char const *v = *argv;
+ if (2 < len && v[len - 1] == '/')
+ while (1 < len && v[len - 2] == '/')
+ --len;
+ }
+
if ((p = fts_alloc(sp, *argv, len)) == NULL)
goto mem3;
p->fts_level = FTS_ROOTLEVEL;
switch (fs_buf.f_type)
{
- /* List here the file system types that lack useable dirent.d_type
+ /* List here the file system types that lack usable dirent.d_type
info, yet for which the optimization does apply. */
case S_MAGIC_REISERFS:
return true;
level = cur->fts_level + 1;
- /* Read the directory, attaching each entry to the `link' pointer. */
+ /* Read the directory, attaching each entry to the "link" pointer. */
doadjust = false;
head = NULL;
tail = NULL;
return (NULL);
/* Copy the name and guarantee NUL termination. */
- memmove(p->fts_name, name, namelen);
+ memcpy(p->fts_name, name, namelen);
p->fts_name[namelen] = '\0';
p->fts_namelen = namelen;
* tricked by someone changing the world out from underneath us.
* Assumes p->fts_statp->st_dev and p->fts_statp->st_ino are filled in.
* If FD is non-negative, expect it to be used after this function returns,
- * and to be closed eventually. So don't pass e.g., `dirfd(dirp)' and then
+ * and to be closed eventually. So don't pass e.g., 'dirfd(dirp)' and then
* do closedir(dirp), because that would invalidate the saved FD.
* Upon failure, close FD immediately and return nonzero.
*/
return -1;
/* The following dev/inode check is necessary if we're doing a
- `logical' traversal (through symlinks, a la chown -L), if the
+ "logical" traversal (through symlinks, a la chown -L), if the
system lacks O_NOFOLLOW support, or if we're changing to ".."
(but not via a popped file descriptor). When changing to the
name "..", O_NOFOLLOW can't help. In general, when the target is