summaryrefslogtreecommitdiffstats
path: root/lib/libc/gen/fts-compat.c
diff options
context:
space:
mode:
authoryar <yar@FreeBSD.org>2008-01-26 17:09:40 +0000
committeryar <yar@FreeBSD.org>2008-01-26 17:09:40 +0000
commitac1e4103b99e1e9f8d65dd75a868092bf0bf5fe0 (patch)
tree2a5d945168363a5dc91eeeca07c233b9f6a775a2 /lib/libc/gen/fts-compat.c
parentbbd4f2a2116be9844c33e49113b99b9fcfe493be (diff)
downloadFreeBSD-src-ac1e4103b99e1e9f8d65dd75a868092bf0bf5fe0.zip
FreeBSD-src-ac1e4103b99e1e9f8d65dd75a868092bf0bf5fe0.tar.gz
Our fts(3) API, as inherited from 4.4BSD, suffers from integer
fields in FTS and FTSENT structs being too narrow. In addition, the narrow types creep from there into fts.c. As a result, fts(3) consumers, e.g., find(1) or rm(1), can't handle file trees an ordinary user can create, which can have security implications. To fix the historic implementation of fts(3), OpenBSD and NetBSD have already changed <fts.h> in somewhat incompatible ways, so we are free to do so, too. This change is a superset of changes from the other BSDs with a few more improvements. It doesn't touch fts(3) functionality; it just extends integer types used by it to match modern reality and the C standard. Here are its points: o For C object sizes, use size_t unless it's 100% certain that the object will be really small. (Note that fts(3) can construct pathnames _much_ longer than PATH_MAX for its consumers.) o Avoid the short types because on modern platforms using them results in larger and slower code. Change shorts to ints as follows: - For variables than count simple, limited things like states, use plain vanilla `int' as it's the type of choice in C. - For a limited number of bit flags use `unsigned' because signed bit-wise operations are implementation-defined, i.e., unportable, in C. o For things that should be at least 64 bits wide, use long long and not int64_t, as the latter is an optional type. See FTSENT.fts_number aka FTS.fts_bignum. Extending fts_number `to satisfy future needs' is pointless because there is fts_pointer, which can be used to link to arbitrary data from an FTSENT. However, there already are fts(3) consumers that require fts_number, or fts_bignum, have at least 64 bits in it, so we must allow for them. o For the tree depth, use `long'. This is a trade-off between making this field too wide and allowing for 64-bit inode numbers and/or chain-mounted filesystems. On the one hand, `long' is almost enough for 32-bit filesystems on a 32-bit platform (our ino_t is uint32_t now). On the other hand, platforms with a 64-bit (or wider) `long' will be ready for 64-bit inode numbers, as well as for several 32-bit filesystems mounted one under another. Note that fts_level has to be signed because -1 is a magic value for it, FTS_ROOTPARENTLEVEL. o For the `nlinks' local var in fts_build(), use `long'. The logic in fts_build() requires that `nlinks' be signed, but our nlink_t currently is uint16_t. Therefore let's make the signed var wide enough to be able to represent 2^16-1 in pure C99, and even 2^32-1 on a 64-bit platform. Perhaps the logic should be changed just to use nlink_t, but it can be done later w/o breaking fts(3) ABI any more because `nlinks' is just a local var. This commit also inludes supporting stuff for the fts change: o Preserve the old versions of fts(3) functions through libc symbol versioning because the old versions appeared in all our former releases. o Bump __FreeBSD_version just in case. There is a small chance that some ill-written 3-rd party apps may fail to build or work correctly if compiled after this change. o Update the fts(3) manpage accordingly. In particular, remove references to fts_bignum, which was a FreeBSD-specific hack to work around the too narrow types of FTSENT members. Now fts_number is at least 64 bits wide (long long) and fts_bignum is an undocumented alias for fts_number kept around for compatibility reasons. According to Google Code Search, the only big consumers of fts_bignum are in our own source tree, so they can be fixed easily to use fts_number. o Mention the change in src/UPDATING. PR: bin/104458 Approved by: re (quite a while ago) Discussed with: deischen (the symbol versioning part) Reviewed by: -arch (mostly silence); das (generally OK, but we didn't agree on some types used; assuming that no objections on -arch let me to stick to my opinion)
Diffstat (limited to 'lib/libc/gen/fts-compat.c')
-rw-r--r--lib/libc/gen/fts-compat.c37
1 files changed, 28 insertions, 9 deletions
diff --git a/lib/libc/gen/fts-compat.c b/lib/libc/gen/fts-compat.c
index 83f9c67..3afb87d 100644
--- a/lib/libc/gen/fts-compat.c
+++ b/lib/libc/gen/fts-compat.c
@@ -46,12 +46,22 @@ __FBSDID("$FreeBSD$");
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
-#include <fts.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include "fts-compat.h"
#include "un-namespace.h"
+FTSENT *__fts_children_44bsd(FTS *, int);
+int __fts_close_44bsd(FTS *);
+void *__fts_get_clientptr_44bsd(FTS *);
+FTS *__fts_get_stream_44bsd(FTSENT *);
+FTS *__fts_open_44bsd(char * const *, int,
+ int (*)(const FTSENT * const *, const FTSENT * const *));
+FTSENT *__fts_read_44bsd(FTS *);
+int __fts_set_44bsd(FTS *, FTSENT *, int);
+void __fts_set_clientptr_44bsd(FTS *, void *);
+
static FTSENT *fts_alloc(FTS *, char *, int);
static FTSENT *fts_build(FTS *, int);
static void fts_lfree(FTSENT *);
@@ -107,7 +117,7 @@ static const char *ufslike_filesystems[] = {
};
FTS *
-fts_open(argv, options, compar)
+__fts_open_44bsd(argv, options, compar)
char * const *argv;
int options;
int (*compar)(const FTSENT * const *, const FTSENT * const *);
@@ -246,7 +256,7 @@ fts_load(sp, p)
}
int
-fts_close(sp)
+__fts_close_44bsd(sp)
FTS *sp;
{
FTSENT *freep, *p;
@@ -301,7 +311,7 @@ fts_close(sp)
? p->fts_pathlen - 1 : p->fts_pathlen)
FTSENT *
-fts_read(sp)
+__fts_read_44bsd(sp)
FTS *sp;
{
FTSENT *p, *tmp;
@@ -495,7 +505,7 @@ name: t = sp->fts_path + NAPPEND(p->fts_parent);
*/
/* ARGSUSED */
int
-fts_set(sp, p, instr)
+__fts_set_44bsd(sp, p, instr)
FTS *sp;
FTSENT *p;
int instr;
@@ -510,7 +520,7 @@ fts_set(sp, p, instr)
}
FTSENT *
-fts_children(sp, instr)
+__fts_children_44bsd(sp, instr)
FTS *sp;
int instr;
{
@@ -582,7 +592,7 @@ fts_children(sp, instr)
#endif
void *
-(fts_get_clientptr)(FTS *sp)
+(__fts_get_clientptr_44bsd)(FTS *sp)
{
return (fts_get_clientptr(sp));
@@ -593,13 +603,13 @@ void *
#endif
FTS *
-(fts_get_stream)(FTSENT *p)
+(__fts_get_stream_44bsd)(FTSENT *p)
{
return (fts_get_stream(p));
}
void
-fts_set_clientptr(FTS *sp, void *clientptr)
+__fts_set_clientptr_44bsd(FTS *sp, void *clientptr)
{
sp->fts_clientptr = clientptr;
@@ -1220,3 +1230,12 @@ fts_ufslinks(FTS *sp, const FTSENT *ent)
}
return (priv->ftsp_linksreliable);
}
+
+__sym_compat(fts_open, __fts_open_44bsd, FBSD_1.0);
+__sym_compat(fts_close, __fts_close_44bsd, FBSD_1.0);
+__sym_compat(fts_read, __fts_read_44bsd, FBSD_1.0);
+__sym_compat(fts_set, __fts_set_44bsd, FBSD_1.0);
+__sym_compat(fts_children, __fts_children_44bsd, FBSD_1.0);
+__sym_compat(fts_get_clientptr, __fts_get_clientptr_44bsd, FBSD_1.0);
+__sym_compat(fts_get_stream, __fts_get_stream_44bsd, FBSD_1.0);
+__sym_compat(fts_set_clientptr, __fts_set_clientptr_44bsd, FBSD_1.0);
OpenPOWER on IntegriCloud