mirror of
https://github.com/GnoConsortium/gno.git
synced 2024-09-29 09:56:26 +00:00
Put in some fixes that came out of FreeBSD-Current. Compilations not
yet verified on the IIgs. Also, dumped #ifdef's that avoided use of fdopen from before fdopen was available in libc.
This commit is contained in:
parent
d34f9db837
commit
7276456260
@ -30,7 +30,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)fts.h 8.1 (Berkeley) 6/2/93
|
||||
* @(#)fts.h 8.3 (Berkeley) 8/14/94
|
||||
*/
|
||||
|
||||
#ifndef _FTS_H_
|
||||
@ -55,10 +55,11 @@ typedef struct {
|
||||
#define FTS_PHYSICAL 0x010 /* physical walk */
|
||||
#define FTS_SEEDOT 0x020 /* return dot and dot-dot */
|
||||
#define FTS_XDEV 0x040 /* don't cross devices */
|
||||
#define FTS_OPTIONMASK 0x07f /* valid user option mask */
|
||||
#define FTS_WHITEOUT 0x080 /* return whiteout information */
|
||||
#define FTS_OPTIONMASK 0x0ff /* valid user option mask */
|
||||
|
||||
#define FTS_NAMEONLY 0x080 /* (private) child names only */
|
||||
#define FTS_STOP 0x100 /* (private) unrecoverable error */
|
||||
#define FTS_NAMEONLY 0x100 /* (private) child names only */
|
||||
#define FTS_STOP 0x200 /* (private) unrecoverable error */
|
||||
int fts_options; /* fts_open options, global flags */
|
||||
} FTS;
|
||||
|
||||
@ -96,10 +97,12 @@ typedef struct _ftsent {
|
||||
#define FTS_NSOK 11 /* no stat(2) requested */
|
||||
#define FTS_SL 12 /* symbolic link */
|
||||
#define FTS_SLNONE 13 /* symbolic link without target */
|
||||
#define FTS_W 14 /* whiteout object */
|
||||
u_short fts_info; /* user flags for FTSENT structure */
|
||||
|
||||
#define FTS_DONTCHDIR 0x01 /* don't chdir .. to the parent */
|
||||
#define FTS_SYMFOLLOW 0x02 /* followed a symlink to get here */
|
||||
#define FTS_ISW 0x04 /* this is a whiteout object */
|
||||
u_short fts_flags; /* private flags for FTSENT structure */
|
||||
|
||||
#define FTS_AGAIN 1 /* read node again */
|
||||
|
@ -36,7 +36,7 @@ segment "libc_gen_2";
|
||||
#endif
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)fts.c 8.4 (Berkeley) 4/16/94";
|
||||
static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -51,10 +51,6 @@ static char sccsid[] = "@(#)fts.c 8.4 (Berkeley) 4/16/94";
|
||||
#include <assert.h>
|
||||
#include <fts.h>
|
||||
|
||||
#if 0 /* def __GNO__ */
|
||||
#define FORCE_NOCHDIR 1 /* GNO v2.0.4 doesn't have fchdir */
|
||||
#endif
|
||||
|
||||
#ifdef MAX
|
||||
#undef MAX
|
||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||
@ -70,10 +66,13 @@ static int fts_palloc __P((FTS *, size_t));
|
||||
static FTSENT *fts_sort __P((FTS *, FTSENT *, int));
|
||||
static u_short fts_stat __P((FTS *, FTSENT *, int));
|
||||
|
||||
#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])) )
|
||||
static int fts_safe_changedir __P((FTS *, FTSENT *, int));
|
||||
|
||||
#define ISSET(opt) (sp->fts_options & opt)
|
||||
#define SET(opt) (sp->fts_options |= opt)
|
||||
#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
|
||||
|
||||
#define CLR(opt) (sp->fts_options &= ~(opt))
|
||||
#define ISSET(opt) (sp->fts_options & (opt))
|
||||
#define SET(opt) (sp->fts_options |= (opt))
|
||||
|
||||
#define CHDIR(sp, path) (!ISSET(FTS_NOCHDIR) && (assert(path!=NULL), 1) && chdir(path))
|
||||
#define FCHDIR(sp, fd) (!ISSET(FTS_NOCHDIR) && fchdir(fd))
|
||||
@ -107,12 +106,8 @@ fts_open(char * const *argv, register int options,
|
||||
sp->fts_options = options;
|
||||
|
||||
/* Logical walks turn on NOCHDIR; symbolic links are too hard. */
|
||||
#ifdef FORCE_NOCHDIR
|
||||
SET(FTS_NOCHDIR);
|
||||
#else
|
||||
if (ISSET(FTS_LOGICAL))
|
||||
SET(FTS_NOCHDIR);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Start out with 1K of path space, and enough, in any case,
|
||||
@ -181,10 +176,8 @@ fts_open(char * const *argv, register int options,
|
||||
* and ".." are all fairly nasty problems. Note, if we can't get the
|
||||
* descriptor we run anyway, just more slowly.
|
||||
*/
|
||||
#ifndef FORCE_NOCHDIR
|
||||
if (!ISSET(FTS_NOCHDIR) && (sp->fts_rfd = open(".", O_RDONLY, 0)) < 0)
|
||||
SET(FTS_NOCHDIR);
|
||||
#endif
|
||||
|
||||
return (sp);
|
||||
|
||||
@ -246,39 +239,30 @@ fts_close(FTS *sp)
|
||||
free(sp->fts_array);
|
||||
free(sp->fts_path);
|
||||
|
||||
#ifndef FORCE_NOCHDIR
|
||||
/* Return to original directory, save errno if necessary. */
|
||||
if (!ISSET(FTS_NOCHDIR)) {
|
||||
#ifdef HAS_FCHDIR
|
||||
saved_errno = fchdir(sp->fts_rfd) ? errno : 0;
|
||||
(void)close(sp->fts_rfd);
|
||||
#else
|
||||
assert(sp->fts_path != NULL);
|
||||
saved_errno = chdir(sp->fts_path) ? errno : 0;
|
||||
#endif
|
||||
}
|
||||
#endif /* ! FORCE_NOCHDIR */
|
||||
|
||||
/* Free up the stream pointer. */
|
||||
free(sp);
|
||||
|
||||
/* Set errno and return. */
|
||||
#ifndef FORCE_NOCHDIR
|
||||
if (!ISSET(FTS_NOCHDIR) && saved_errno) {
|
||||
errno = saved_errno;
|
||||
return (-1);
|
||||
}
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Special case a root of "/" so that slashes aren't appended which would
|
||||
* cause paths to be written as "//foo".
|
||||
* Special case of "/" at the end of the path so that slashes aren't
|
||||
* appended which would cause paths to be written as "....//foo".
|
||||
*/
|
||||
#define NAPPEND(p) \
|
||||
(p->fts_level == FTS_ROOTLEVEL && p->fts_pathlen == 1 && \
|
||||
p->fts_path[0] == '/' ? 0 : p->fts_pathlen)
|
||||
(p->fts_path[p->fts_pathlen - 1] == '/' \
|
||||
? p->fts_pathlen - 1 : p->fts_pathlen)
|
||||
|
||||
FTSENT *
|
||||
fts_read(register FTS *sp)
|
||||
@ -314,7 +298,6 @@ fts_read(register FTS *sp)
|
||||
if (instr == FTS_FOLLOW &&
|
||||
(p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
|
||||
p->fts_info = fts_stat(sp, p, 1);
|
||||
#ifndef FORCE_NOCHDIR
|
||||
if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
|
||||
if ((p->fts_symfd = open(".", O_RDONLY, 0)) < 0) {
|
||||
p->fts_errno = errno;
|
||||
@ -323,7 +306,6 @@ fts_read(register FTS *sp)
|
||||
p->fts_flags |= FTS_SYMFOLLOW;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return (p);
|
||||
}
|
||||
|
||||
@ -331,11 +313,9 @@ fts_read(register FTS *sp)
|
||||
if (p->fts_info == FTS_D) {
|
||||
/* If skipped or crossed mount point, do post-order visit. */
|
||||
if (instr == FTS_SKIP ||
|
||||
(ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev) ) {
|
||||
#ifndef FORCE_NOCHDIR
|
||||
(ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) {
|
||||
if (p->fts_flags & FTS_SYMFOLLOW)
|
||||
(void)close(p->fts_symfd);
|
||||
#endif
|
||||
if (sp->fts_child) {
|
||||
fts_lfree(sp->fts_child);
|
||||
sp->fts_child = NULL;
|
||||
@ -345,8 +325,8 @@ fts_read(register FTS *sp)
|
||||
}
|
||||
|
||||
/* Rebuild if only read the names and now traversing. */
|
||||
if (sp->fts_child && sp->fts_options & FTS_NAMEONLY) {
|
||||
sp->fts_options &= ~FTS_NAMEONLY;
|
||||
if (sp->fts_child && ISSET(FTS_NAMEONLY)) {
|
||||
CLR(FTS_NAMEONLY);
|
||||
fts_lfree(sp->fts_child);
|
||||
sp->fts_child = NULL;
|
||||
}
|
||||
@ -364,7 +344,7 @@ fts_read(register FTS *sp)
|
||||
* FTS_STOP or the fts_info field of the node.
|
||||
*/
|
||||
if (sp->fts_child) {
|
||||
if (CHDIR(sp, p->fts_accpath)) {
|
||||
if (fts_safe_changedir(sp, p, -1)) {
|
||||
p->fts_errno = errno;
|
||||
p->fts_flags |= FTS_DONTCHDIR;
|
||||
for (p = sp->fts_child; p; p = p->fts_link)
|
||||
@ -383,7 +363,7 @@ fts_read(register FTS *sp)
|
||||
|
||||
/* Move to the next node on this level. */
|
||||
next: tmp = p;
|
||||
if ( (p = p->fts_link) ) {
|
||||
if ((p = p->fts_link)) {
|
||||
free(tmp);
|
||||
|
||||
/*
|
||||
@ -391,16 +371,10 @@ next: tmp = p;
|
||||
* load the paths for the next root.
|
||||
*/
|
||||
if (p->fts_level == FTS_ROOTLEVEL) {
|
||||
#ifndef FORCE_NOCHDIR
|
||||
#ifdef HAS_FCHDIR
|
||||
if (!ISSET(FTS_NOCHDIR) && FCHDIR(sp, sp->fts_rfd)) {
|
||||
#else
|
||||
if (!ISSET(FTS_NOCHDIR) && CHDIR(sp, sp->fts_path)) {
|
||||
#endif
|
||||
if (FCHDIR(sp, sp->fts_rfd)) {
|
||||
SET(FTS_STOP);
|
||||
return (NULL);
|
||||
}
|
||||
#endif
|
||||
fts_load(sp, p);
|
||||
return (sp->fts_cur = p);
|
||||
}
|
||||
@ -414,7 +388,6 @@ next: tmp = p;
|
||||
goto next;
|
||||
if (p->fts_instr == FTS_FOLLOW) {
|
||||
p->fts_info = fts_stat(sp, p, 1);
|
||||
#ifndef FORCE_NOCHDIR
|
||||
if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
|
||||
if ((p->fts_symfd =
|
||||
open(".", O_RDONLY, 0)) < 0) {
|
||||
@ -424,7 +397,6 @@ next: tmp = p;
|
||||
p->fts_flags |= FTS_SYMFOLLOW;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
p->fts_instr = FTS_NOINSTR;
|
||||
}
|
||||
|
||||
@ -457,21 +429,12 @@ name: t = sp->fts_path + NAPPEND(p->fts_parent);
|
||||
* one directory.
|
||||
*/
|
||||
if (p->fts_level == FTS_ROOTLEVEL) {
|
||||
#ifndef FORCE_NOCHDIR
|
||||
#ifdef HAS_FCHDIR
|
||||
if (!ISSET(FTS_NOCHDIR) && FCHDIR(sp, sp->fts_rfd)) {
|
||||
#else
|
||||
if (!ISSET(FTS_NOCHDIR) && CHDIR(sp, sp->fts_path)) {
|
||||
#endif
|
||||
! if (FCHDIR(sp, sp->fts_rfd)) {
|
||||
SET(FTS_STOP);
|
||||
return (NULL);
|
||||
}
|
||||
} else if (p->fts_flags & FTS_SYMFOLLOW) {
|
||||
#ifdef HAS_FCHDIR
|
||||
if (FCHDIR(sp, p->fts_symfd)) {
|
||||
#else
|
||||
if (FCHDIR(sp, p->fts_symfd)) {
|
||||
#endif
|
||||
saved_errno = errno;
|
||||
(void)close(p->fts_symfd);
|
||||
errno = saved_errno;
|
||||
@ -479,7 +442,6 @@ name: t = sp->fts_path + NAPPEND(p->fts_parent);
|
||||
return (NULL);
|
||||
}
|
||||
(void)close(p->fts_symfd);
|
||||
#endif /* ! FORCE_NOCHDIR */
|
||||
} else if (!(p->fts_flags & FTS_DONTCHDIR)) {
|
||||
if (CHDIR(sp, "..")) {
|
||||
SET(FTS_STOP);
|
||||
@ -550,7 +512,7 @@ fts_children(register FTS *sp, int instr)
|
||||
fts_lfree(sp->fts_child);
|
||||
|
||||
if (instr == FTS_NAMEONLY) {
|
||||
sp->fts_options |= FTS_NAMEONLY;
|
||||
SET(FTS_NAMEONLY);
|
||||
instr = BNAMES;
|
||||
} else
|
||||
instr = BCHILD;
|
||||
@ -569,11 +531,7 @@ fts_children(register FTS *sp, int instr)
|
||||
if ((fd = open(".", O_RDONLY, 0)) < 0)
|
||||
return (NULL);
|
||||
sp->fts_child = fts_build(sp, instr);
|
||||
#ifdef HAS_FCHDIR
|
||||
if (fchdir(fd))
|
||||
#else
|
||||
if (chdir("."))
|
||||
#endif
|
||||
return (NULL);
|
||||
(void)close(fd);
|
||||
return (sp->fts_child);
|
||||
@ -602,7 +560,7 @@ fts_build(register FTS *sp, int type)
|
||||
FTSENT *cur, *tail;
|
||||
DIR *dirp;
|
||||
void *adjaddr;
|
||||
int cderrno, descend, len, level, maxlen, nlinks, saved_errno;
|
||||
int cderrno, descend, len, level, maxlen, nlinks, oflag, saved_errno;
|
||||
char *cp;
|
||||
|
||||
/* Set current node pointer. */
|
||||
@ -612,7 +570,15 @@ fts_build(register FTS *sp, int type)
|
||||
* Open the directory for reading. If this fails, we're done.
|
||||
* If being called from fts_read, set the fts_info field.
|
||||
*/
|
||||
if ((dirp = opendir(cur->fts_accpath)) == NULL) {
|
||||
#ifdef FTS_WHITEOUT
|
||||
if (ISSET(FTS_WHITEOUT))
|
||||
oflag = DTF_NODUP|DTF_REWIND;
|
||||
else
|
||||
oflag = DTF_HIDEW|DTF_NODUP|DTF_REWIND;
|
||||
#else
|
||||
#define __opendir2(path, flag) opendir(path)
|
||||
#endif
|
||||
if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) {
|
||||
if (type == BREAD) {
|
||||
cur->fts_info = FTS_DNR;
|
||||
cur->fts_errno = errno;
|
||||
@ -654,16 +620,14 @@ fts_build(register FTS *sp, int type)
|
||||
*/
|
||||
cderrno = 0;
|
||||
if (nlinks || type == BREAD)
|
||||
#ifdef HAS_FCHDIR
|
||||
if (FCHDIR(sp, dirfd(dirp))) {
|
||||
#else
|
||||
if (CHDIR(sp, cur->fts_accpath)) {
|
||||
#endif
|
||||
if (fts_safe_changedir(sp, cur, dirfd(dirp))) {
|
||||
if (nlinks && type == BREAD)
|
||||
cur->fts_errno = errno;
|
||||
cur->fts_flags |= FTS_DONTCHDIR;
|
||||
descend = 0;
|
||||
cderrno = errno;
|
||||
(void)closedir(dirp);
|
||||
dirp = NULL;
|
||||
} else
|
||||
descend = 1;
|
||||
else
|
||||
@ -690,7 +654,7 @@ fts_build(register FTS *sp, int type)
|
||||
|
||||
/* Read the directory, attaching each entry to the `link' pointer. */
|
||||
adjaddr = NULL;
|
||||
for (head = tail = NULL, nitems = 0; (dp = readdir(dirp)); ) {
|
||||
for (head = tail = NULL, nitems = 0; dirp && (dp = readdir(dirp));) {
|
||||
if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
|
||||
continue;
|
||||
|
||||
@ -721,6 +685,11 @@ mem1: saved_errno = errno;
|
||||
p->fts_parent = sp->fts_cur;
|
||||
p->fts_level = level;
|
||||
|
||||
#ifdef FTS_WHITEOUT
|
||||
if (dp->d_type == DT_WHT)
|
||||
p->fts_flags |= FTS_ISW;
|
||||
#endif
|
||||
|
||||
if (cderrno) {
|
||||
if (nlinks) {
|
||||
p->fts_info = FTS_NS;
|
||||
@ -763,6 +732,7 @@ mem1: saved_errno = errno;
|
||||
}
|
||||
++nitems;
|
||||
}
|
||||
if (dirp)
|
||||
(void)closedir(dirp);
|
||||
|
||||
/*
|
||||
@ -777,7 +747,7 @@ mem1: saved_errno = errno;
|
||||
* state.
|
||||
*/
|
||||
if (ISSET(FTS_NOCHDIR)) {
|
||||
if (cp - 1 > sp->fts_path)
|
||||
if (len == sp->fts_pathlen)
|
||||
--cp;
|
||||
*cp = '\0';
|
||||
}
|
||||
@ -791,11 +761,7 @@ mem1: saved_errno = errno;
|
||||
*/
|
||||
if (descend && (type == BCHILD || !nitems) &&
|
||||
(cur->fts_level == FTS_ROOTLEVEL ?
|
||||
#ifdef HAS_FCHDIR
|
||||
FCHDIR(sp, sp->fts_rfd) :
|
||||
#else
|
||||
CHDIR(sp, sp->fts_path) :
|
||||
#endif
|
||||
CHDIR(sp, ".."))) {
|
||||
cur->fts_info = FTS_ERR;
|
||||
SET(FTS_STOP);
|
||||
@ -827,6 +793,17 @@ fts_stat(FTS *sp, register FTSENT *p, int follow)
|
||||
/* If user needs stat info, stat buffer already allocated. */
|
||||
sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;
|
||||
|
||||
#ifdef FTS_WHITEOUT
|
||||
/* check for whiteout */
|
||||
if (p->fts_flags & FTS_ISW) {
|
||||
if (sbp != &sb) {
|
||||
memset(sbp, '\0', sizeof (*sbp));
|
||||
sbp->st_mode = S_IFWHT;
|
||||
}
|
||||
return (FTS_W);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If doing a logical walk, or application requested FTS_FOLLOW, do
|
||||
* a stat(2). If that fails, check for a non-existent symlink. If
|
||||
@ -960,7 +937,7 @@ fts_lfree(register FTSENT *head)
|
||||
register FTSENT *p;
|
||||
|
||||
/* Free a linked list of structures. */
|
||||
while ( (p = head) ) {
|
||||
while ((p = head)) {
|
||||
head = head->fts_link;
|
||||
free(p);
|
||||
}
|
||||
@ -968,6 +945,40 @@ fts_lfree(register FTSENT *head)
|
||||
|
||||
/*
|
||||
* Allow essentially unlimited paths; find, rm, ls should all work on any tree.
|
||||
}
|
||||
|
||||
/*
|
||||
* Change to dir specified by fd or p->fts_accpath without getting
|
||||
* tricked by someone changing the world out from underneath us.
|
||||
* Assumes p->fts_dev and p->fts_ino are filled in.
|
||||
*/
|
||||
static int
|
||||
fts_safe_changedir(FTS *sp, FTSENT *p, int fd)
|
||||
{
|
||||
int ret, oerrno, newfd;
|
||||
struct stat sb;
|
||||
|
||||
newfd = fd;
|
||||
if (ISSET(FTS_NOCHDIR))
|
||||
return (0);
|
||||
if (fd < 0 && (newfd = open(p->fts_accpath, O_RDONLY, 0)) < 0)
|
||||
return (-1);
|
||||
if (fstat(newfd, &sb)) {
|
||||
ret = -1;
|
||||
goto bail;
|
||||
}
|
||||
if (p->fts_dev != sb.st_dev || p->fts_ino != sb.st_ino) {
|
||||
errno = ENOENT; /* disinformation */
|
||||
ret = -1;
|
||||
goto bail;
|
||||
}
|
||||
ret = fchdir(newfd);
|
||||
bail:
|
||||
oerrno = errno;
|
||||
if (fd < 0)
|
||||
(void)close(newfd);
|
||||
errno = oerrno;
|
||||
return (ret);
|
||||
* Most systems will allow creation of paths much longer than MAXPATHLEN, even
|
||||
* though the kernel won't resolve them. Add the size (not just what's needed)
|
||||
* plus 256 bytes so don't realloc the path 2 bytes at a time.
|
||||
|
Loading…
Reference in New Issue
Block a user