version 1.5, 2014/12/11 09:05:01 |
version 1.8, 2015/02/07 07:53:01 |
|
|
* SUCH DAMAGE. |
* SUCH DAMAGE. |
*/ |
*/ |
|
|
#include <sys/param.h> |
|
#include <sys/stat.h> |
#include <sys/stat.h> |
#include <sys/types.h> |
#include <sys/types.h> |
|
|
|
|
#include <unistd.h> |
#include <unistd.h> |
#include "compat_fts.h" |
#include "compat_fts.h" |
|
|
|
#define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b)) |
|
|
static FTSENT *fts_alloc(FTS *, const char *, size_t); |
static FTSENT *fts_alloc(FTS *, const char *, size_t); |
static FTSENT *fts_build(FTS *); |
static FTSENT *fts_build(FTS *); |
static void fts_lfree(FTSENT *); |
static void fts_lfree(FTSENT *); |
Line 62 static unsigned short fts_stat(FTS *, FTSENT *); |
|
Line 63 static unsigned short fts_stat(FTS *, FTSENT *); |
|
static int fts_safe_changedir(FTS *, FTSENT *, int, const char *); |
static int fts_safe_changedir(FTS *, FTSENT *, int, const char *); |
|
|
#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2]))) |
#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2]))) |
|
#ifndef O_DIRECTORY |
|
#define O_DIRECTORY 0 |
|
#endif |
|
#ifndef O_CLOEXEC |
|
#define O_CLOEXEC 0 |
|
#endif |
|
|
#define CLR(opt) (sp->fts_options &= ~(opt)) |
#define CLR(opt) (sp->fts_options &= ~(opt)) |
#define ISSET(opt) (sp->fts_options & (opt)) |
#define ISSET(opt) (sp->fts_options & (opt)) |
Line 93 fts_open(char * const *argv, int options, void *dummy) |
|
Line 100 fts_open(char * const *argv, int options, void *dummy) |
|
* Start out with 1K of path space, and enough, in any case, |
* Start out with 1K of path space, and enough, in any case, |
* to hold the user's paths. |
* to hold the user's paths. |
*/ |
*/ |
if (fts_palloc(sp, MAX(fts_maxarglen(argv), PATH_MAX))) |
if (fts_palloc(sp, MAXIMUM(fts_maxarglen(argv), PATH_MAX))) |
goto mem1; |
goto mem1; |
|
|
/* Allocate/initialize root's parent. */ |
/* Allocate/initialize root's parent. */ |
Line 407 fts_build(FTS *sp) |
|
Line 414 fts_build(FTS *sp) |
|
DIR *dirp; |
DIR *dirp; |
void *oldaddr; |
void *oldaddr; |
size_t dlen, len, maxlen; |
size_t dlen, len, maxlen; |
int nitems, cderrno, descend, level, nlinks, nostat, doadjust; |
int nitems, cderrno, descend, level, doadjust; |
int saved_errno; |
int saved_errno; |
char *cp; |
char *cp; |
|
|
Line 425 fts_build(FTS *sp) |
|
Line 432 fts_build(FTS *sp) |
|
} |
} |
|
|
/* |
/* |
* 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, -1 if we're doing stats on everything. |
|
*/ |
|
nlinks = -1; |
|
nostat = 0; |
|
|
|
/* |
|
* If we're going to need to stat anything or we want to descend |
* If we're going to need to stat anything or we want to descend |
* and stay in the directory, chdir. If this fails we keep going, |
* and stay in the directory, chdir. If this fails we keep going, |
* but set a flag so we don't chdir after the post-order visit. |
* but set a flag so we don't chdir after the post-order visit. |
Line 449 fts_build(FTS *sp) |
|
Line 448 fts_build(FTS *sp) |
|
*/ |
*/ |
cderrno = 0; |
cderrno = 0; |
if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) { |
if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) { |
if (nlinks) |
cur->fts_errno = errno; |
cur->fts_errno = errno; |
|
cur->fts_flags |= FTS_DONTCHDIR; |
cur->fts_flags |= FTS_DONTCHDIR; |
descend = 0; |
descend = 0; |
cderrno = errno; |
cderrno = errno; |
Line 545 mem1: saved_errno = errno; |
|
Line 543 mem1: saved_errno = errno; |
|
} |
} |
|
|
if (cderrno) { |
if (cderrno) { |
if (nlinks) { |
p->fts_info = FTS_NS; |
p->fts_info = FTS_NS; |
p->fts_errno = cderrno; |
p->fts_errno = cderrno; |
|
} else |
|
p->fts_info = FTS_NSOK; |
|
p->fts_accpath = cur->fts_accpath; |
p->fts_accpath = cur->fts_accpath; |
} else if (nlinks == 0 |
|
#ifdef DT_DIR |
|
|| (nostat && |
|
dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN) |
|
#endif |
|
) { |
|
p->fts_accpath = |
|
ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name; |
|
p->fts_info = FTS_NSOK; |
|
} else { |
} else { |
/* Build a file name for fts_stat to stat. */ |
/* Build a file name for fts_stat to stat. */ |
if (ISSET(FTS_NOCHDIR)) { |
if (ISSET(FTS_NOCHDIR)) { |
Line 569 mem1: saved_errno = errno; |
|
Line 555 mem1: saved_errno = errno; |
|
p->fts_accpath = p->fts_name; |
p->fts_accpath = p->fts_name; |
/* Stat it. */ |
/* Stat it. */ |
p->fts_info = fts_stat(sp, p); |
p->fts_info = fts_stat(sp, p); |
|
|
/* Decrement link count if applicable. */ |
|
if (nlinks > 0 && (p->fts_info == FTS_D || |
|
p->fts_info == FTS_DC || p->fts_info == FTS_DOT)) |
|
--nlinks; |
|
} |
} |
|
|
/* We walk in directory order so "ls -f" doesn't get upset. */ |
/* We walk in directory order so "ls -f" doesn't get upset. */ |