Changeset View
Changeset View
Standalone View
Standalone View
head/lib/libc/gen/fts-compat.c
Show All 34 Lines | |||||
#endif /* LIBC_SCCS and not lint */ | #endif /* LIBC_SCCS and not lint */ | ||||
#endif | #endif | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include "namespace.h" | #include "namespace.h" | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#define _WANT_FREEBSD11_STATFS | |||||
#include <sys/mount.h> | #include <sys/mount.h> | ||||
#define _WANT_FREEBSD11_STAT | |||||
#include <sys/stat.h> | #include <sys/stat.h> | ||||
#define _WANT_FREEBSD11_DIRENT | |||||
#include <dirent.h> | #include <dirent.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#include "gen-compat.h" | |||||
#include "fts-compat.h" | #include "fts-compat.h" | ||||
#include "un-namespace.h" | #include "un-namespace.h" | ||||
#include "gen-private.h" | #include "gen-private.h" | ||||
FTSENT *__fts_children_44bsd(FTS *, int); | FTSENT *__fts_children_44bsd(FTS *, int); | ||||
int __fts_close_44bsd(FTS *); | int __fts_close_44bsd(FTS *); | ||||
void *__fts_get_clientptr_44bsd(FTS *); | void *__fts_get_clientptr_44bsd(FTS *); | ||||
Show All 31 Lines | |||||
/* | /* | ||||
* Internal representation of an FTS, including extra implementation | * Internal representation of an FTS, including extra implementation | ||||
* details. The FTS returned from fts_open points to this structure's | * details. The FTS returned from fts_open points to this structure's | ||||
* ftsp_fts member (and can be cast to an _fts_private as required) | * ftsp_fts member (and can be cast to an _fts_private as required) | ||||
*/ | */ | ||||
struct _fts_private { | struct _fts_private { | ||||
FTS ftsp_fts; | FTS ftsp_fts; | ||||
struct statfs ftsp_statfs; | struct freebsd11_statfs ftsp_statfs; | ||||
dev_t ftsp_dev; | uint32_t ftsp_dev; | ||||
int ftsp_linksreliable; | int ftsp_linksreliable; | ||||
}; | }; | ||||
/* | /* | ||||
* The "FTS_NOSTAT" option can avoid a lot of calls to stat(2) if it | * The "FTS_NOSTAT" option can avoid a lot of calls to stat(2) if it | ||||
* knows that a directory could not possibly have subdirectories. This | * knows that a directory could not possibly have subdirectories. This | ||||
* is decided by looking at the link count: a subdirectory would | * is decided by looking at the link count: a subdirectory would | ||||
* increment its parent's link count by virtue of its own ".." entry. | * increment its parent's link count by virtue of its own ".." entry. | ||||
▲ Show 20 Lines • Show All 512 Lines • ▼ Show 20 Lines | |||||
* of subdirectories in a node is equal to the number of links to the parent. | * of subdirectories in a node is equal to the number of links to the parent. | ||||
* The former skips all stat calls. The latter skips stat calls in any leaf | * The former skips all stat calls. The latter skips stat calls in any leaf | ||||
* directories and for any files after the subdirectories in the directory have | * directories and for any files after the subdirectories in the directory have | ||||
* been found, cutting the stat calls by about 2/3. | * been found, cutting the stat calls by about 2/3. | ||||
*/ | */ | ||||
static FTSENT * | static FTSENT * | ||||
fts_build(FTS *sp, int type) | fts_build(FTS *sp, int type) | ||||
{ | { | ||||
struct dirent *dp; | struct freebsd11_dirent *dp; | ||||
FTSENT *p, *head; | FTSENT *p, *head; | ||||
int nitems; | int nitems; | ||||
FTSENT *cur, *tail; | FTSENT *cur, *tail; | ||||
DIR *dirp; | DIR *dirp; | ||||
void *oldaddr; | void *oldaddr; | ||||
size_t dnamlen; | size_t dnamlen; | ||||
int cderrno, descend, len, level, maxlen, nlinks, oflag, saved_errno, | int cderrno, descend, len, level, maxlen, nlinks, oflag, saved_errno, | ||||
nostat, doadjust; | nostat, doadjust; | ||||
▲ Show 20 Lines • Show All 95 Lines • ▼ Show 20 Lines | #endif | ||||
} | } | ||||
len++; | len++; | ||||
maxlen = sp->fts_pathlen - len; | maxlen = sp->fts_pathlen - len; | ||||
level = cur->fts_level + 1; | 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 = 0; | doadjust = 0; | ||||
for (head = tail = NULL, nitems = 0; dirp && (dp = readdir(dirp));) { | for (head = tail = NULL, nitems = 0; | ||||
dirp && (dp = freebsd11_readdir(dirp));) { | |||||
dnamlen = dp->d_namlen; | dnamlen = dp->d_namlen; | ||||
if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name)) | if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name)) | ||||
continue; | continue; | ||||
if ((p = fts_alloc(sp, dp->d_name, (int)dnamlen)) == NULL) | if ((p = fts_alloc(sp, dp->d_name, (int)dnamlen)) == NULL) | ||||
goto mem1; | goto mem1; | ||||
if (dnamlen >= maxlen) { /* include space for NUL */ | if (dnamlen >= maxlen) { /* include space for NUL */ | ||||
oldaddr = sp->fts_path; | oldaddr = sp->fts_path; | ||||
▲ Show 20 Lines • Show All 136 Lines • ▼ Show 20 Lines | if (sp->fts_compar && nitems > 1) | ||||
head = fts_sort(sp, head, nitems); | head = fts_sort(sp, head, nitems); | ||||
return (head); | return (head); | ||||
} | } | ||||
static u_short | static u_short | ||||
fts_stat(FTS *sp, FTSENT *p, int follow) | fts_stat(FTS *sp, FTSENT *p, int follow) | ||||
{ | { | ||||
FTSENT *t; | FTSENT *t; | ||||
dev_t dev; | uint32_t dev; | ||||
ino_t ino; | uint32_t ino; | ||||
struct stat *sbp, sb; | struct freebsd11_stat *sbp, sb; | ||||
int saved_errno; | int saved_errno; | ||||
/* If user needs stat info, stat buffer already allocated. */ | /* If user needs stat info, stat buffer already allocated. */ | ||||
sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp; | sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp; | ||||
#ifdef FTS_WHITEOUT | #ifdef FTS_WHITEOUT | ||||
/* Check for whiteout. */ | /* Check for whiteout. */ | ||||
if (p->fts_flags & FTS_ISW) { | if (p->fts_flags & FTS_ISW) { | ||||
if (sbp != &sb) { | if (sbp != &sb) { | ||||
memset(sbp, '\0', sizeof(*sbp)); | memset(sbp, '\0', sizeof(*sbp)); | ||||
sbp->st_mode = S_IFWHT; | sbp->st_mode = S_IFWHT; | ||||
} | } | ||||
return (FTS_W); | return (FTS_W); | ||||
} | } | ||||
#endif | #endif | ||||
/* | /* | ||||
* If doing a logical walk, or application requested FTS_FOLLOW, do | * If doing a logical walk, or application requested FTS_FOLLOW, do | ||||
* a stat(2). If that fails, check for a non-existent symlink. If | * a stat(2). If that fails, check for a non-existent symlink. If | ||||
* fail, set the errno from the stat call. | * fail, set the errno from the stat call. | ||||
*/ | */ | ||||
if (ISSET(FTS_LOGICAL) || follow) { | if (ISSET(FTS_LOGICAL) || follow) { | ||||
if (stat(p->fts_accpath, sbp)) { | if (freebsd11_stat(p->fts_accpath, sbp)) { | ||||
saved_errno = errno; | saved_errno = errno; | ||||
if (!lstat(p->fts_accpath, sbp)) { | if (!freebsd11_lstat(p->fts_accpath, sbp)) { | ||||
errno = 0; | errno = 0; | ||||
return (FTS_SLNONE); | return (FTS_SLNONE); | ||||
} | } | ||||
p->fts_errno = saved_errno; | p->fts_errno = saved_errno; | ||||
goto err; | goto err; | ||||
} | } | ||||
} else if (lstat(p->fts_accpath, sbp)) { | } else if (freebsd11_lstat(p->fts_accpath, sbp)) { | ||||
p->fts_errno = errno; | p->fts_errno = errno; | ||||
err: memset(sbp, 0, sizeof(struct stat)); | err: memset(sbp, 0, sizeof(struct stat)); | ||||
return (FTS_NS); | return (FTS_NS); | ||||
} | } | ||||
if (S_ISDIR(sbp->st_mode)) { | if (S_ISDIR(sbp->st_mode)) { | ||||
/* | /* | ||||
* Set the device/inode. Used to find cycles and check for | * Set the device/inode. Used to find cycles and check for | ||||
▲ Show 20 Lines • Show All 77 Lines • ▼ Show 20 Lines | |||||
static FTSENT * | static FTSENT * | ||||
fts_alloc(FTS *sp, char *name, int namelen) | fts_alloc(FTS *sp, char *name, int namelen) | ||||
{ | { | ||||
FTSENT *p; | FTSENT *p; | ||||
size_t len; | size_t len; | ||||
struct ftsent_withstat { | struct ftsent_withstat { | ||||
FTSENT ent; | FTSENT ent; | ||||
struct stat statbuf; | struct freebsd11_stat statbuf; | ||||
}; | }; | ||||
/* | /* | ||||
* The file name is a variable length array and no stat structure is | * 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 | * necessary if the user has set the nostat bit. Allocate the FTSENT | ||||
* structure, the file name and the stat structure in one chunk, but | * structure, the file name and the stat structure in one chunk, but | ||||
* be careful that the stat structure is reasonably aligned. | * be careful that the stat structure is reasonably aligned. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 109 Lines • ▼ Show 20 Lines | |||||
* Change to dir specified by fd or p->fts_accpath without getting | * Change to dir specified by fd or p->fts_accpath without getting | ||||
* tricked by someone changing the world out from underneath us. | * tricked by someone changing the world out from underneath us. | ||||
* Assumes p->fts_dev and p->fts_ino are filled in. | * Assumes p->fts_dev and p->fts_ino are filled in. | ||||
*/ | */ | ||||
static int | static int | ||||
fts_safe_changedir(FTS *sp, FTSENT *p, int fd, char *path) | fts_safe_changedir(FTS *sp, FTSENT *p, int fd, char *path) | ||||
{ | { | ||||
int ret, oerrno, newfd; | int ret, oerrno, newfd; | ||||
struct stat sb; | struct freebsd11_stat sb; | ||||
newfd = fd; | newfd = fd; | ||||
if (ISSET(FTS_NOCHDIR)) | if (ISSET(FTS_NOCHDIR)) | ||||
return (0); | return (0); | ||||
if (fd < 0 && (newfd = _open(path, O_RDONLY | O_CLOEXEC, 0)) < 0) | if (fd < 0 && (newfd = _open(path, O_RDONLY | O_CLOEXEC, 0)) < 0) | ||||
return (-1); | return (-1); | ||||
if (_fstat(newfd, &sb)) { | if (freebsd11_fstat(newfd, &sb)) { | ||||
ret = -1; | ret = -1; | ||||
goto bail; | goto bail; | ||||
} | } | ||||
if (p->fts_dev != sb.st_dev || p->fts_ino != sb.st_ino) { | if (p->fts_dev != sb.st_dev || p->fts_ino != sb.st_ino) { | ||||
errno = ENOENT; /* disinformation */ | errno = ENOENT; /* disinformation */ | ||||
ret = -1; | ret = -1; | ||||
goto bail; | goto bail; | ||||
} | } | ||||
Show All 18 Lines | fts_ufslinks(FTS *sp, const FTSENT *ent) | ||||
priv = (struct _fts_private *)sp; | priv = (struct _fts_private *)sp; | ||||
/* | /* | ||||
* If this node's device is different from the previous, grab | * If this node's device is different from the previous, grab | ||||
* the filesystem information, and decide on the reliability | * the filesystem information, and decide on the reliability | ||||
* of the link information from this filesystem for stat(2) | * of the link information from this filesystem for stat(2) | ||||
* avoidance. | * avoidance. | ||||
*/ | */ | ||||
if (priv->ftsp_dev != ent->fts_dev) { | if (priv->ftsp_dev != ent->fts_dev) { | ||||
if (statfs(ent->fts_path, &priv->ftsp_statfs) != -1) { | if (freebsd11_statfs(ent->fts_path, &priv->ftsp_statfs) != -1) { | ||||
priv->ftsp_dev = ent->fts_dev; | priv->ftsp_dev = ent->fts_dev; | ||||
priv->ftsp_linksreliable = 0; | priv->ftsp_linksreliable = 0; | ||||
for (cpp = ufslike_filesystems; *cpp; cpp++) { | for (cpp = ufslike_filesystems; *cpp; cpp++) { | ||||
if (strcmp(priv->ftsp_statfs.f_fstypename, | if (strcmp(priv->ftsp_statfs.f_fstypename, | ||||
*cpp) == 0) { | *cpp) == 0) { | ||||
priv->ftsp_linksreliable = 1; | priv->ftsp_linksreliable = 1; | ||||
break; | break; | ||||
} | } | ||||
Show All 16 Lines |