~ubuntu-branches/ubuntu/utopic/coreutils/utopic-proposed

« back to all changes in this revision

Viewing changes to lib/fts.c

  • Committer: Package Import Robot
  • Author(s): Colin Watson
  • Date: 2012-11-28 03:03:42 UTC
  • mfrom: (8.3.4 sid)
  • Revision ID: package-import@ubuntu.com-20121128030342-21zanj8354gas5gr
Tags: 8.20-3ubuntu1
* Resynchronise with Debian.  Remaining changes:
  - Make 'uname -i -p' return the real processor/hardware, instead of
    unknown.
  - Build-depend on gettext:any instead of on gettext, so that apt-get can
    properly resolve build-dependencies on the tool when cross-building.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Traverse a file hierarchy.
2
2
 
3
 
   Copyright (C) 2004-2011 Free Software Foundation, Inc.
 
3
   Copyright (C) 2004-2012 Free Software Foundation, Inc.
4
4
 
5
5
   This program is free software: you can redistribute it and/or modify
6
6
   it under the terms of the GNU General Public License as published by
31
31
 *    may be used to endorse or promote products derived from this software
32
32
 *    without specific prior written permission.
33
33
 *
34
 
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 
34
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
35
35
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36
36
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37
37
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
229
229
#define ISSET(opt)      (sp->fts_options & (opt))
230
230
#define SET(opt)        (sp->fts_options |= (opt))
231
231
 
232
 
/* FIXME: make this a function */
233
 
#define RESTORE_INITIAL_CWD(sp)                 \
234
 
  (fd_ring_clear (&((sp)->fts_fd_ring)),        \
235
 
   FCHDIR ((sp), (ISSET (FTS_CWDFD) ? AT_FDCWD : (sp)->fts_rfd)))
236
 
 
237
232
/* FIXME: FTS_NOCHDIR is now misnamed.
238
233
   Call it FTS_USE_FULL_RELATIVE_FILE_NAMES instead. */
239
234
#define FCHDIR(sp, fd)                                  \
349
344
  sp->fts_cwd_fd = fd;
350
345
}
351
346
 
 
347
/* Restore the initial, pre-traversal, "working directory".
 
348
   In FTS_CWDFD mode, we merely call cwd_advance_fd, otherwise,
 
349
   we may actually change the working directory.
 
350
   Return 0 upon success. Upon failure, set errno and return nonzero.  */
 
351
static int
 
352
restore_initial_cwd (FTS *sp)
 
353
{
 
354
  int fail = FCHDIR (sp, ISSET (FTS_CWDFD) ? AT_FDCWD : sp->fts_rfd);
 
355
  fd_ring_clear (&(sp->fts_fd_ring));
 
356
  return fail;
 
357
}
 
358
 
352
359
/* Open the directory DIR if possible, and return a file
353
360
   descriptor.  Return -1 and set errno on failure.  It doesn't matter
354
361
   whether the file descriptor has read or write access.  */
420
427
                           O_SEARCH | (ISSET (FTS_NOATIME) ? O_NOATIME : 0));
421
428
            if (fd < 0)
422
429
              {
423
 
                /* Even if `.' is unreadable, don't revert to FTS_NOCHDIR mode
 
430
                /* Even if "." is unreadable, don't revert to FTS_NOCHDIR mode
424
431
                   on systems like Linux+PROC_FS, where our openat emulation
425
432
                   is good enough.  Note: on a system that emulates
426
433
                   openat via /proc, this technique can still fail, but
480
487
        for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) {
481
488
                /* *Do* allow zero-length file names. */
482
489
                size_t len = strlen(*argv);
 
490
 
 
491
                /* If there are two or more trailing slashes, trim all but one,
 
492
                   but don't change "//" to "/", and do map "///" to "/".  */
 
493
                char const *v = *argv;
 
494
                if (2 < len && v[len - 1] == '/')
 
495
                  while (1 < len && v[len - 2] == '/')
 
496
                    --len;
 
497
 
483
498
                if ((p = fts_alloc(sp, *argv, len)) == NULL)
484
499
                        goto mem3;
485
500
                p->fts_level = FTS_ROOTLEVEL;
697
712
 
698
713
  switch (fs_buf.f_type)
699
714
    {
700
 
      /* List here the file system types that lack useable dirent.d_type
 
715
      /* List here the file system types that lack usable dirent.d_type
701
716
         info, yet for which the optimization does apply.  */
702
717
    case S_MAGIC_REISERFS:
703
718
      return true;
948
963
                 * root.
949
964
                 */
950
965
                if (p->fts_level == FTS_ROOTLEVEL) {
951
 
                        if (RESTORE_INITIAL_CWD(sp)) {
 
966
                        if (restore_initial_cwd(sp)) {
952
967
                                SET(FTS_STOP);
953
968
                                return (NULL);
954
969
                        }
1055
1070
         * one level, via "..".
1056
1071
         */
1057
1072
        if (p->fts_level == FTS_ROOTLEVEL) {
1058
 
                if (RESTORE_INITIAL_CWD(sp)) {
 
1073
                if (restore_initial_cwd(sp)) {
1059
1074
                        p->fts_errno = errno;
1060
1075
                        SET(FTS_STOP);
1061
1076
                }
1422
1437
 
1423
1438
        level = cur->fts_level + 1;
1424
1439
 
1425
 
        /* Read the directory, attaching each entry to the `link' pointer. */
 
1440
        /* Read the directory, attaching each entry to the "link" pointer. */
1426
1441
        doadjust = false;
1427
1442
        head = NULL;
1428
1443
        tail = NULL;
1579
1594
         */
1580
1595
        if (!continue_readdir && descend && (type == BCHILD || !nitems) &&
1581
1596
            (cur->fts_level == FTS_ROOTLEVEL
1582
 
             ? RESTORE_INITIAL_CWD(sp)
 
1597
             ? restore_initial_cwd(sp)
1583
1598
             : fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
1584
1599
                cur->fts_info = FTS_ERR;
1585
1600
                SET(FTS_STOP);
1887
1902
                return (NULL);
1888
1903
 
1889
1904
        /* Copy the name and guarantee NUL termination. */
1890
 
        memmove(p->fts_name, name, namelen);
 
1905
        memcpy(p->fts_name, name, namelen);
1891
1906
        p->fts_name[namelen] = '\0';
1892
1907
 
1893
1908
        p->fts_namelen = namelen;
1981
1996
}
1982
1997
 
1983
1998
static size_t
1984
 
internal_function
 
1999
internal_function _GL_ATTRIBUTE_PURE
1985
2000
fts_maxarglen (char * const *argv)
1986
2001
{
1987
2002
        size_t len, max;
1997
2012
 * tricked by someone changing the world out from underneath us.
1998
2013
 * Assumes p->fts_statp->st_dev and p->fts_statp->st_ino are filled in.
1999
2014
 * If FD is non-negative, expect it to be used after this function returns,
2000
 
 * and to be closed eventually.  So don't pass e.g., `dirfd(dirp)' and then
 
2015
 * and to be closed eventually.  So don't pass e.g., 'dirfd(dirp)' and then
2001
2016
 * do closedir(dirp), because that would invalidate the saved FD.
2002
2017
 * Upon failure, close FD immediately and return nonzero.
2003
2018
 */
2046
2061
          return -1;
2047
2062
 
2048
2063
        /* The following dev/inode check is necessary if we're doing a
2049
 
           `logical' traversal (through symlinks, a la chown -L), if the
 
2064
           "logical" traversal (through symlinks, a la chown -L), if the
2050
2065
           system lacks O_NOFOLLOW support, or if we're changing to ".."
2051
2066
           (but not via a popped file descriptor).  When changing to the
2052
2067
           name "..", O_NOFOLLOW can't help.  In general, when the target is