libroot: Replace ftw/nftw implemenations with their musl counterparts.

Rewrite ftw.h to be a Haiku header instead of a BSD one while at it.
This commit is contained in:
Augustin Cavalier 2022-06-09 16:24:11 -04:00
parent 22b1d791b2
commit 9b2434d26f
7 changed files with 181 additions and 249 deletions

View File

@ -1,63 +1,44 @@
/* $OpenBSD: ftw.h,v 1.1 2003/07/21 21:13:18 millert Exp $ */
/* /*
* Copyright (c) 2003 Todd C. Miller <Todd.Miller@courtesan.com> * Copyright 2022, Haiku, Inc. All rights reserved.
* * Distributed under the terms of the MIT License.
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Sponsored in part by the Defense Advanced Research Projects
* Agency (DARPA) and Air Force Research Laboratory, Air Force
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
*
* $FreeBSD$
*/ */
#ifndef _FTW_H_
#define _FTW_H_
#ifndef _FTW_H
#define _FTW_H
#include <sys/cdefs.h> #include <features.h>
#include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
/*
* Valid flags for the 3rd argument to the function that is passed as the
* second argument to ftw(3) and nftw(3). Say it three times fast!
*/
#define FTW_F 0 /* File. */
#define FTW_D 1 /* Directory. */
#define FTW_DNR 2 /* Directory without read permission. */
#define FTW_DP 3 /* Directory with subdirectories visited. */
#define FTW_NS 4 /* Unknown type; stat() failed. */
#define FTW_SL 5 /* Symbolic link. */
#define FTW_SLN 6 /* Sym link that names a nonexistent file. */
/* #define FTW_F 0
* Flags for use as the 4th argument to nftw(3). These may be ORed together. #define FTW_D 1
*/ #define FTW_DNR 2
#define FTW_PHYS 0x01 /* Physical walk, don't follow sym links. */ #define FTW_DP 3
#define FTW_MOUNT 0x02 /* The walk does not cross a mount point. */ #define FTW_NS 4
#define FTW_DEPTH 0x04 /* Subdirs visited before the dir itself. */ #define FTW_SL 5
#define FTW_CHDIR 0x08 /* Change to a directory before reading it. */ #define FTW_SLN 6
#define FTW_PHYS 0x01
#define FTW_MOUNT 0x02
#define FTW_DEPTH 0x04
#define FTW_CHDIR 0x08
struct FTW { struct FTW {
int base; int base;
int level; int level;
}; };
__BEGIN_DECLS
#ifdef __cplusplus
extern "C" {
#endif
int ftw(const char *, int (*)(const char *, const struct stat *, int), int); int ftw(const char *, int (*)(const char *, const struct stat *, int), int);
int nftw(const char *, int (*)(const char *, const struct stat *, int, int nftw(const char *, int (*)(const char *, const struct stat *, int,
struct FTW *), int, int); struct FTW *), int, int);
__END_DECLS
#endif /* !_FTW_H */ #ifdef __cplusplus
}
#endif
#endif /* _FTW_H_ */

View File

@ -33,11 +33,9 @@ for architectureObject in [ MultiArchSubDirSetup ] {
errno.c errno.c
fcntl.cpp fcntl.cpp
fts.c fts.c
ftw.c
glob.c glob.c
inttypes.c inttypes.c
libgen.cpp libgen.cpp
nftw.c
poll.cpp poll.cpp
$(PWD_BACKEND) $(PWD_BACKEND)
scheduler.cpp scheduler.cpp

View File

@ -1,91 +0,0 @@
/* $OpenBSD: ftw.c,v 1.5 2005/08/08 08:05:34 espie Exp $ */
/*
* Copyright (c) 2003, 2004 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Sponsored in part by the Defense Advanced Research Projects
* Agency (DARPA) and Air Force Research Laboratory, Air Force
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
*/
#include <sys/cdefs.h>
// __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fts.h>
#include <ftw.h>
int
ftw(const char *path, int (*fn)(const char *, const struct stat *, int),
int nfds)
{
char * const paths[2] = { (char *)path, NULL };
FTSENT *cur;
FTS *ftsp;
int error = 0, fnflag, sverrno;
/* XXX - nfds is currently unused */
if (nfds < 1) {
errno = EINVAL;
return (-1);
}
ftsp = fts_open(paths, FTS_LOGICAL | FTS_COMFOLLOW | FTS_NOCHDIR, NULL);
if (ftsp == NULL)
return (-1);
while ((cur = fts_read(ftsp)) != NULL) {
switch (cur->fts_info) {
case FTS_D:
fnflag = FTW_D;
break;
case FTS_DNR:
fnflag = FTW_DNR;
break;
case FTS_DP:
/* we only visit in preorder */
continue;
case FTS_F:
case FTS_DEFAULT:
fnflag = FTW_F;
break;
case FTS_NS:
case FTS_NSOK:
case FTS_SLNONE:
fnflag = FTW_NS;
break;
case FTS_SL:
fnflag = FTW_SL;
break;
case FTS_DC:
errno = ELOOP;
/* FALLTHROUGH */
default:
error = -1;
goto done;
}
error = fn(cur->fts_path, cur->fts_statp, fnflag);
if (error != 0)
break;
}
done:
sverrno = errno;
if (fts_close(ftsp) != 0 && error == 0)
error = -1;
else
errno = sverrno;
return (error);
}

View File

@ -12,7 +12,9 @@ for architectureObject in [ MultiArchSubDirSetup ] {
MergeObject <$(architecture)>posix_musl_misc.o : MergeObject <$(architecture)>posix_musl_misc.o :
a64l.c a64l.c
ffs.c ffs.c
ftw.c
getsubopt.c getsubopt.c
nftw.c
; ;
} }
} }

View File

@ -0,0 +1,9 @@
#include <ftw.h>
int ftw(const char *path, int (*fn)(const char *, const struct stat *, int), int fd_limit)
{
/* The following cast assumes that calling a function with one
* argument more than it needs behaves as expected. This is
* actually undefined, but works on all real-world machines. */
return nftw(path, (int (*)())fn, fd_limit, FTW_PHYS);
}

View File

@ -0,0 +1,142 @@
#include <ftw.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>
#include <pthread.h>
struct history
{
struct history *chain;
dev_t dev;
ino_t ino;
int level;
int base;
};
#undef dirfd
#define dirfd(d) (*(int *)d)
static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int, struct FTW *), int fd_limit, int flags, struct history *h)
{
size_t l = strlen(path), j = l && path[l-1]=='/' ? l-1 : l;
struct stat st;
struct history new;
int type;
int r;
int dfd;
int err;
struct FTW lev;
if ((flags & FTW_PHYS) ? lstat(path, &st) : stat(path, &st) < 0) {
if (!(flags & FTW_PHYS) && errno==ENOENT && !lstat(path, &st))
type = FTW_SLN;
else if (errno != EACCES) return -1;
else type = FTW_NS;
} else if (S_ISDIR(st.st_mode)) {
if (flags & FTW_DEPTH) type = FTW_DP;
else type = FTW_D;
} else if (S_ISLNK(st.st_mode)) {
if (flags & FTW_PHYS) type = FTW_SL;
else type = FTW_SLN;
} else {
type = FTW_F;
}
if ((flags & FTW_MOUNT) && h && st.st_dev != h->dev)
return 0;
new.chain = h;
new.dev = st.st_dev;
new.ino = st.st_ino;
new.level = h ? h->level+1 : 0;
new.base = j+1;
lev.level = new.level;
if (h) {
lev.base = h->base;
} else {
size_t k;
for (k=j; k && path[k]=='/'; k--);
for (; k && path[k-1]!='/'; k--);
lev.base = k;
}
if (type == FTW_D || type == FTW_DP) {
dfd = open(path, O_RDONLY);
err = errno;
if (dfd < 0 && err == EACCES) type = FTW_DNR;
if (!fd_limit) close(dfd);
}
if (!(flags & FTW_DEPTH) && (r=fn(path, &st, type, &lev)))
return r;
for (; h; h = h->chain)
if (h->dev == st.st_dev && h->ino == st.st_ino)
return 0;
if ((type == FTW_D || type == FTW_DP) && fd_limit) {
if (dfd < 0) {
errno = err;
return -1;
}
{
DIR *d = fdopendir(dfd);
if (d) {
struct dirent *de;
while ((de = readdir(d))) {
if (de->d_name[0] == '.'
&& (!de->d_name[1]
|| (de->d_name[1]=='.'
&& !de->d_name[2]))) continue;
if (strlen(de->d_name) >= PATH_MAX-l) {
errno = ENAMETOOLONG;
closedir(d);
return -1;
}
path[j]='/';
strcpy(path+j+1, de->d_name);
if ((r=do_nftw(path, fn, fd_limit-1, flags, &new))) {
closedir(d);
return r;
}
}
closedir(d);
} else {
close(dfd);
return -1;
}
}
}
path[l] = 0;
if ((flags & FTW_DEPTH) && (r=fn(path, &st, type, &lev)))
return r;
return 0;
}
int nftw(const char *path, int (*fn)(const char *, const struct stat *, int, struct FTW *), int fd_limit, int flags)
{
int r, cs;
size_t l;
char pathbuf[PATH_MAX+1];
if (fd_limit <= 0) return 0;
l = strlen(path);
if (l > PATH_MAX) {
errno = ENAMETOOLONG;
return -1;
}
memcpy(pathbuf, path, l+1);
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
r = do_nftw(pathbuf, fn, fd_limit, flags, NULL);
pthread_setcancelstate(cs, 0);
return r;
}

View File

@ -1,109 +0,0 @@
/* $OpenBSD: nftw.c,v 1.7 2006/03/31 19:41:44 millert Exp $ */
/*
* Copyright (c) 2003, 2004 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Sponsored in part by the Defense Advanced Research Projects
* Agency (DARPA) and Air Force Research Laboratory, Air Force
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
*/
#include <sys/cdefs.h>
//__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fts.h>
#include <ftw.h>
int
nftw(const char *path, int (*fn)(const char *, const struct stat *, int,
struct FTW *), int nfds, int ftwflags)
{
char * const paths[2] = { (char *)path, NULL };
struct FTW ftw;
FTSENT *cur;
FTS *ftsp;
int error = 0, ftsflags, fnflag, postorder, sverrno;
/* XXX - nfds is currently unused */
if (nfds < 1) {
errno = EINVAL;
return (-1);
}
ftsflags = FTS_COMFOLLOW;
if (!(ftwflags & FTW_CHDIR))
ftsflags |= FTS_NOCHDIR;
if (ftwflags & FTW_MOUNT)
ftsflags |= FTS_XDEV;
if (ftwflags & FTW_PHYS)
ftsflags |= FTS_PHYSICAL;
else
ftsflags |= FTS_LOGICAL;
postorder = (ftwflags & FTW_DEPTH) != 0;
ftsp = fts_open(paths, ftsflags, NULL);
if (ftsp == NULL)
return (-1);
while ((cur = fts_read(ftsp)) != NULL) {
switch (cur->fts_info) {
case FTS_D:
if (postorder)
continue;
fnflag = FTW_D;
break;
case FTS_DC:
continue;
case FTS_DNR:
fnflag = FTW_DNR;
break;
case FTS_DP:
if (!postorder)
continue;
fnflag = FTW_DP;
break;
case FTS_F:
case FTS_DEFAULT:
fnflag = FTW_F;
break;
case FTS_NS:
case FTS_NSOK:
fnflag = FTW_NS;
break;
case FTS_SL:
fnflag = FTW_SL;
break;
case FTS_SLNONE:
fnflag = FTW_SLN;
break;
default:
error = -1;
goto done;
}
ftw.base = cur->fts_pathlen - cur->fts_namelen;
ftw.level = cur->fts_level;
error = fn(cur->fts_path, cur->fts_statp, fnflag, &ftw);
if (error != 0)
break;
}
done:
sverrno = errno;
if (fts_close(ftsp) != 0 && error == 0)
error = -1;
else
errno = sverrno;
return (error);
}