=================================================================== RCS file: /cvs/mandoc/compat_fts.c,v retrieving revision 1.1 retrieving revision 1.7 diff -u -p -r1.1 -r1.7 --- mandoc/compat_fts.c 2014/08/11 01:39:00 1.1 +++ mandoc/compat_fts.c 2015/02/07 07:42:56 1.7 @@ -1,12 +1,13 @@ #include "config.h" -#ifdef HAVE_FTS +#if HAVE_FTS int dummy; #else -/* $OpenBSD: compat_fts.c,v 1.1 2014/08/11 01:39:00 schwarze Exp $ */ +/* $Id: compat_fts.c,v 1.7 2015/02/07 07:42:56 schwarze Exp $ */ +/* $OpenBSD: compat_fts.c,v 1.7 2015/02/07 07:42:56 schwarze Exp $ */ /*- * Copyright (c) 1990, 1993, 1994 @@ -37,7 +38,6 @@ int dummy; * SUCH DAMAGE. */ -#include #include #include @@ -50,6 +50,8 @@ int dummy; #include #include "compat_fts.h" +#define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b)) + static FTSENT *fts_alloc(FTS *, const char *, size_t); static FTSENT *fts_build(FTS *); static void fts_lfree(FTSENT *); @@ -61,6 +63,9 @@ static unsigned short fts_stat(FTS *, FTSENT *); static int fts_safe_changedir(FTS *, FTSENT *, int, const char *); #define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2]))) +#ifndef O_DIRECTORY +#define O_DIRECTORY 0 +#endif #define CLR(opt) (sp->fts_options &= ~(opt)) #define ISSET(opt) (sp->fts_options & (opt)) @@ -92,7 +97,7 @@ fts_open(char * const *argv, int options, void *dummy) * Start out with 1K of path space, and enough, in any case, * 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; /* Allocate/initialize root's parent. */ @@ -145,7 +150,8 @@ fts_open(char * const *argv, int options, void *dummy) * and ".." are all fairly nasty problems. Note, if we can't get the * descriptor we run anyway, just more slowly. */ - if (!ISSET(FTS_NOCHDIR) && (sp->fts_rfd = open(".", O_RDONLY, 0)) < 0) + if (!ISSET(FTS_NOCHDIR) && + (sp->fts_rfd = open(".", O_RDONLY | O_CLOEXEC)) < 0) SET(FTS_NOCHDIR); if (nitems == 0) @@ -404,8 +410,8 @@ fts_build(FTS *sp) FTSENT *cur, *tail; DIR *dirp; void *oldaddr; - size_t len, maxlen; - int nitems, cderrno, descend, level, nlinks, nostat, doadjust; + size_t dlen, len, maxlen; + int nitems, cderrno, descend, level, doadjust; int saved_errno; char *cp; @@ -423,14 +429,6 @@ 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 * 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. @@ -447,8 +445,7 @@ fts_build(FTS *sp) */ cderrno = 0; if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) { - if (nlinks) - cur->fts_errno = errno; + cur->fts_errno = errno; cur->fts_flags |= FTS_DONTCHDIR; descend = 0; cderrno = errno; @@ -489,11 +486,17 @@ fts_build(FTS *sp) if (ISDOT(dp->d_name)) continue; - if (!(p = fts_alloc(sp, dp->d_name, (size_t)dp->d_namlen))) +#if HAVE_DIRENT_NAMLEN + dlen = dp->d_namlen; +#else + dlen = strlen(dp->d_name); +#endif + + if (!(p = fts_alloc(sp, dp->d_name, dlen))) goto mem1; - if (dp->d_namlen >= maxlen) { /* include space for NUL */ + if (dlen >= maxlen) { /* include space for NUL */ oldaddr = sp->fts_path; - if (fts_palloc(sp, dp->d_namlen +len + 1)) { + if (fts_palloc(sp, dlen + len + 1)) { /* * No more memory for path or structures. Save * errno, free up the current structure and the @@ -520,7 +523,7 @@ mem1: saved_errno = errno; p->fts_level = level; p->fts_parent = sp->fts_cur; - p->fts_pathlen = len + dp->d_namlen; + p->fts_pathlen = len + dlen; if (p->fts_pathlen < len) { /* * If we wrap, free up the current structure and @@ -537,21 +540,9 @@ mem1: saved_errno = errno; } if (cderrno) { - if (nlinks) { - p->fts_info = FTS_NS; - p->fts_errno = cderrno; - } else - p->fts_info = FTS_NSOK; + p->fts_info = FTS_NS; + p->fts_errno = cderrno; 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 { /* Build a file name for fts_stat to stat. */ if (ISSET(FTS_NOCHDIR)) { @@ -561,11 +552,6 @@ mem1: saved_errno = errno; p->fts_accpath = p->fts_name; /* Stat it. */ 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. */ @@ -680,23 +666,18 @@ fts_alloc(FTS *sp, const char *name, size_t namelen) FTSENT *p; size_t len; - /* - * The file name is a variable length array and no stat structure is - * necessary if the user has set the nostat bit. Allocate the FTSENT - * structure, the file name and the stat structure in one chunk, but - * be careful that the stat structure is reasonably aligned. Since the - * fts_name field is declared to be of size 1, the fts_name pointer is - * namelen + 2 before the first possible address of the stat structure. - */ len = sizeof(FTSENT) + namelen; - len += sizeof(struct stat) + ALIGNBYTES; if ((p = calloc(1, len)) == NULL) return (NULL); p->fts_path = sp->fts_path; p->fts_namelen = namelen; p->fts_instr = FTS_NOINSTR; - p->fts_statp = (struct stat *)ALIGN(p->fts_name + namelen + 2); + p->fts_statp = malloc(sizeof(struct stat)); + if (p->fts_statp == NULL) { + free(p); + return (NULL); + } memcpy(p->fts_name, name, namelen); return (p); @@ -801,7 +782,7 @@ fts_safe_changedir(FTS *sp, FTSENT *p, int fd, const c newfd = fd; if (ISSET(FTS_NOCHDIR)) return (0); - if (fd < 0 && (newfd = open(path, O_RDONLY, 0)) < 0) + if (fd < 0 && (newfd = open(path, O_RDONLY|O_DIRECTORY|O_CLOEXEC)) < 0) return (-1); if (fstat(newfd, &sb)) { ret = -1;