about summary refs log tree commit diff
path: root/io/fts.c
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2015-11-06 11:22:38 +0100
committerMark Wielaard <mjw@redhat.com>2015-11-06 11:24:16 +0100
commit8b7b7f75d91f7bac323dd6a370aeb3e9c5c4a7d5 (patch)
tree1d746e27fde388945a60b17e4855a0463d7892a9 /io/fts.c
parent5a28590adfc5ed898a335f7a3359a9243534eded (diff)
downloadglibc-8b7b7f75d91f7bac323dd6a370aeb3e9c5c4a7d5.tar.gz
glibc-8b7b7f75d91f7bac323dd6a370aeb3e9c5c4a7d5.tar.xz
glibc-8b7b7f75d91f7bac323dd6a370aeb3e9c5c4a7d5.zip
Add LFS support for fts functions (bug 11460)
fts didn't have large-file support yet and fts.h had an #error preventing
usage when _FILE_OFFSET_BITS was set. This required nasty workarounds for
programs using fts with LFS. This patch implements LFS support for fts by
adding FTS64 and FTENT64 variants plus fts64 functions. Which are simple
aliases for 64bit off_t arches.

Also includes a simple testcase for some of the fts functions with or
without LFS enabled.

	[BZ #11460]
	* io/Makefile (routines): Add fts64.
	(tests): Add tst-fts and tst-fts-lfs.
	(CFLAGS-fts64.c): New.
	* io/Versions (GLIBC_2.23): New.
	* io/fts.c: Replace FTS with FTSOBJ, FTSENT with FTSENTRY. Use
	function defines FTS_OPEN, FTS_CLOSE, FTS_READ, FTS_SET and
	FTS_CHILDREN. Define FTSOBJ, FTSENTRY, FTS_OPEN, FTS_CLOSE,
	FTS_READ, FTS_SET, FTS_CHILDREN, INO_T, STAT and LSTAT if necessary.
	* io/fts.h (FTS64): New if _USE_LARGEFILE64.
	(FTSENT64): Likewise.
	(fts64_children): Likewise.
	(fts64_close): Likewise.
	(fts64_open): Likewise.
	(fts64_read): Likewise.
	(fts64_set): Likewise.
	* io/fts64.c: New file.
	* io/tst-fts.c: New test.
	* io/tst-fts-lfs.c: Likewise.
	* sysdeps/unix/sysv/linux/aarch64/libc.abilist (GLIBC_2.23): Add
	GLIBC_2.23, fts64_children, fts64_close, fts64_open, fts64_read and
	fts64_set.
	* sysdeps/unix/sysv/linux/alpha/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/arm/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/hppa/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/i386/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/ia64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/microblaze/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/nios2/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sh/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist: Likewise.
	* sysdeps/wordsize-64/fts.c: New file.
	* sysdeps/wordsize-64/fts64.c: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n64/fts.c: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n64/fts64.c: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/x32/fts.c: likewise.
	* sysdeps/unix/sysv/linux/x86_64/x32/fts64.c: likewise.
Diffstat (limited to 'io/fts.c')
-rw-r--r--io/fts.c148
1 files changed, 90 insertions, 58 deletions
diff --git a/io/fts.c b/io/fts.c
index f83267611f..e8d32a2327 100644
--- a/io/fts.c
+++ b/io/fts.c
@@ -1,3 +1,21 @@
+/* File tree traversal functions.
+   Copyright (C) 1994-2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
 /*-
  * Copyright (c) 1990, 1993, 1994
  *	The Regents of the University of California.  All rights reserved.
@@ -53,16 +71,30 @@ static char sccsid[] = "@(#)fts.c	8.6 (Berkeley) 8/14/94";
 #endif
 
 
-static FTSENT	*fts_alloc (FTS *, const char *, size_t) internal_function;
-static FTSENT	*fts_build (FTS *, int) internal_function;
-static void	 fts_lfree (FTSENT *) internal_function;
-static void	 fts_load (FTS *, FTSENT *) internal_function;
+/* Support for the LFS API version.  */
+#ifndef FTS_OPEN
+#define FTS_OPEN fts_open
+#define FTS_CLOSE fts_close
+#define FTS_READ fts_read
+#define FTS_SET fts_set
+#define FTS_CHILDREN fts_children
+# define FTSOBJ FTS
+# define FTSENTRY FTSENT
+# define INO_T ino_t
+# define STAT stat
+# define LSTAT lstat
+#endif
+
+static FTSENTRY	*fts_alloc (FTSOBJ *, const char *, size_t) internal_function;
+static FTSENTRY	*fts_build (FTSOBJ *, int) internal_function;
+static void	 fts_lfree (FTSENTRY *) internal_function;
+static void	 fts_load (FTSOBJ *, FTSENTRY *) internal_function;
 static size_t	 fts_maxarglen (char * const *) internal_function;
-static void	 fts_padjust (FTS *, FTSENT *) internal_function;
-static int	 fts_palloc (FTS *, size_t) internal_function;
-static FTSENT	*fts_sort (FTS *, FTSENT *, int) internal_function;
-static u_short	 fts_stat (FTS *, FTSENT *, int) internal_function;
-static int      fts_safe_changedir (FTS *, FTSENT *, int, const char *)
+static void	 fts_padjust (FTSOBJ *, FTSENTRY *) internal_function;
+static int	 fts_palloc (FTSOBJ *, size_t) internal_function;
+static FTSENTRY	*fts_sort (FTSOBJ *, FTSENTRY *, int) internal_function;
+static u_short	 fts_stat (FTSOBJ *, FTSENTRY *, int) internal_function;
+static int      fts_safe_changedir (FTSOBJ *, FTSENTRY *, int, const char *)
      internal_function;
 
 #ifndef MAX
@@ -84,15 +116,15 @@ static int      fts_safe_changedir (FTS *, FTSENT *, int, const char *)
 #define	BNAMES		2		/* fts_children, names only */
 #define	BREAD		3		/* fts_read */
 
-FTS *
-fts_open (char * const *argv, int options,
-	  int (*compar) (const FTSENT **, const FTSENT **))
+FTSOBJ *
+FTS_OPEN (char * const *argv, int options,
+	  int (*compar) (const FTSENTRY **, const FTSENTRY **))
 {
-	FTS *sp;
-	FTSENT *p, *root;
+	FTSOBJ *sp;
+	FTSENTRY *p, *root;
 	int nitems;
-	FTSENT *parent = NULL;
-	FTSENT *tmp;
+	FTSENTRY *parent = NULL;
+	FTSENTRY *tmp;
 
 	/* Options check. */
 	if (options & ~FTS_OPTIONMASK) {
@@ -101,9 +133,9 @@ fts_open (char * const *argv, int options,
 	}
 
 	/* Allocate/initialize the stream */
-	if ((sp = malloc((u_int)sizeof(FTS))) == NULL)
+	if ((sp = malloc((u_int)sizeof(FTSOBJ))) == NULL)
 		return (NULL);
-	memset(sp, 0, sizeof(FTS));
+	memset(sp, 0, sizeof(FTSOBJ));
 	sp->fts_compar = (int (*) (const void *, const void *)) compar;
 	sp->fts_options = options;
 
@@ -200,7 +232,7 @@ mem1:	free(sp);
 
 static void
 internal_function
-fts_load (FTS *sp, FTSENT *p)
+fts_load (FTSOBJ *sp, FTSENTRY *p)
 {
 	int len;
 	char *cp;
@@ -224,9 +256,9 @@ fts_load (FTS *sp, FTSENT *p)
 }
 
 int
-fts_close (FTS *sp)
+FTS_CLOSE (FTSOBJ *sp)
 {
-	FTSENT *freep, *p;
+	FTSENTRY *freep, *p;
 	int saved_errno;
 
 	/*
@@ -276,10 +308,10 @@ fts_close (FTS *sp)
 	(p->fts_path[p->fts_pathlen - 1] == '/'				\
 	    ? p->fts_pathlen - 1 : p->fts_pathlen)
 
-FTSENT *
-fts_read (FTS *sp)
+FTSENTRY *
+FTS_READ (FTSOBJ *sp)
 {
-	FTSENT *p, *tmp;
+	FTSENTRY *p, *tmp;
 	int instr;
 	char *t;
 	int saved_errno;
@@ -473,7 +505,7 @@ name:		t = sp->fts_path + NAPPEND(p->fts_parent);
  */
 /* ARGSUSED */
 int
-fts_set (FTS *sp, FTSENT *p, int instr)
+FTS_SET (FTSOBJ *sp, FTSENTRY *p, int instr)
 {
 	if (instr != 0 && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
 	    instr != FTS_NOINSTR && instr != FTS_SKIP) {
@@ -484,10 +516,10 @@ fts_set (FTS *sp, FTSENT *p, int instr)
 	return (0);
 }
 
-FTSENT *
-fts_children (FTS *sp, int instr)
+FTSENTRY *
+FTS_CHILDREN(FTSOBJ *sp, int instr)
 {
-	FTSENT *p;
+	FTSENTRY *p;
 	int fd;
 
 	if (instr != 0 && instr != FTS_NAMEONLY) {
@@ -574,14 +606,14 @@ dirent_not_directory(const struct dirent *dp)
  * directories and for any files after the subdirectories in the directory have
  * been found, cutting the stat calls by about 2/3.
  */
-static FTSENT *
+static FTSENTRY *
 internal_function
-fts_build (FTS *sp, int type)
+fts_build (FTSOBJ *sp, int type)
 {
 	struct dirent *dp;
-	FTSENT *p, *head;
+	FTSENTRY *p, *head;
 	int nitems;
-	FTSENT *cur, *tail;
+	FTSENTRY *cur, *tail;
 	DIR *dirp;
 	void *oldaddr;
 	int cderrno, descend, len, level, nlinks, saved_errno,
@@ -839,12 +871,12 @@ mem1:				saved_errno = errno;
 
 static u_short
 internal_function
-fts_stat (FTS *sp, FTSENT *p, int follow)
+fts_stat (FTSOBJ *sp, FTSENTRY *p, int follow)
 {
-	FTSENT *t;
+	FTSENTRY *t;
 	dev_t dev;
-	ino_t ino;
-	struct stat *sbp, sb;
+	INO_T ino;
+	struct STAT *sbp, sb;
 	int saved_errno;
 
 	/* If user needs stat info, stat buffer already allocated. */
@@ -867,18 +899,18 @@ fts_stat (FTS *sp, FTSENT *p, int follow)
 	 * fail, set the errno from the stat call.
 	 */
 	if (ISSET(FTS_LOGICAL) || follow) {
-		if (stat(p->fts_accpath, sbp)) {
+		if (STAT(p->fts_accpath, sbp)) {
 			saved_errno = errno;
-			if (!lstat(p->fts_accpath, sbp)) {
+			if (!LSTAT(p->fts_accpath, sbp)) {
 				__set_errno (0);
 				return (FTS_SLNONE);
 			}
 			p->fts_errno = saved_errno;
 			goto err;
 		}
-	} else if (lstat(p->fts_accpath, sbp)) {
+	} else if (LSTAT(p->fts_accpath, sbp)) {
 		p->fts_errno = errno;
-err:		memset(sbp, 0, sizeof(struct stat));
+err:		memset(sbp, 0, sizeof(struct STAT));
 		return (FTS_NS);
 	}
 
@@ -918,11 +950,11 @@ err:		memset(sbp, 0, sizeof(struct stat));
 	return (FTS_DEFAULT);
 }
 
-static FTSENT *
+static FTSENTRY *
 internal_function
-fts_sort (FTS *sp, FTSENT *head, int nitems)
+fts_sort (FTSOBJ *sp, FTSENTRY *head, int nitems)
 {
-	FTSENT **ap, *p;
+	FTSENTRY **ap, *p;
 
 	/*
 	 * Construct an array of pointers to the structures and call qsort(3).
@@ -932,11 +964,11 @@ fts_sort (FTS *sp, FTSENT *head, int nitems)
 	 * 40 so don't realloc one entry at a time.
 	 */
 	if (nitems > sp->fts_nitems) {
-		struct _ftsent **a;
+		FTSENTRY **a;
 
 		sp->fts_nitems = nitems + 40;
 		if ((a = realloc(sp->fts_array,
- 		    (size_t)(sp->fts_nitems * sizeof(FTSENT *)))) == NULL) {
+		    (size_t)(sp->fts_nitems * sizeof(FTSENTRY *)))) == NULL) {
 			free(sp->fts_array);
 			sp->fts_array = NULL;
 			sp->fts_nitems = 0;
@@ -946,18 +978,18 @@ fts_sort (FTS *sp, FTSENT *head, int nitems)
 	}
 	for (ap = sp->fts_array, p = head; p; p = p->fts_link)
 		*ap++ = p;
-	qsort((void *)sp->fts_array, nitems, sizeof(FTSENT *), sp->fts_compar);
+	qsort((void *)sp->fts_array, nitems, sizeof(FTSENTRY *), sp->fts_compar);
 	for (head = *(ap = sp->fts_array); --nitems; ++ap)
 		ap[0]->fts_link = ap[1];
 	ap[0]->fts_link = NULL;
 	return (head);
 }
 
-static FTSENT *
+static FTSENTRY *
 internal_function
-fts_alloc (FTS *sp, const char *name, size_t namelen)
+fts_alloc (FTSOBJ *sp, const char *name, size_t namelen)
 {
-	FTSENT *p;
+	FTSENTRY *p;
 	size_t len;
 
 	/*
@@ -968,9 +1000,9 @@ fts_alloc (FTS *sp, const char *name, size_t namelen)
 	 * 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(FTSENTRY) + namelen;
 	if (!ISSET(FTS_NOSTAT))
-		len += sizeof(struct stat) + ALIGNBYTES;
+		len += sizeof(struct STAT) + ALIGNBYTES;
 	if ((p = malloc(len)) == NULL)
 		return (NULL);
 
@@ -979,7 +1011,7 @@ fts_alloc (FTS *sp, const char *name, size_t namelen)
 	p->fts_name[namelen] = '\0';
 
 	if (!ISSET(FTS_NOSTAT))
-		p->fts_statp = (struct stat *)ALIGN(p->fts_name + namelen + 2);
+		p->fts_statp = (struct STAT *)ALIGN(p->fts_name + namelen + 2);
 	p->fts_namelen = namelen;
 	p->fts_path = sp->fts_path;
 	p->fts_errno = 0;
@@ -992,9 +1024,9 @@ fts_alloc (FTS *sp, const char *name, size_t namelen)
 
 static void
 internal_function
-fts_lfree (FTSENT *head)
+fts_lfree (FTSENTRY *head)
 {
-	FTSENT *p;
+	FTSENTRY *p;
 
 	/* Free a linked list of structures. */
 	while ((p = head)) {
@@ -1011,7 +1043,7 @@ fts_lfree (FTSENT *head)
  */
 static int
 internal_function
-fts_palloc (FTS *sp, size_t more)
+fts_palloc (FTSOBJ *sp, size_t more)
 {
 	char *p;
 
@@ -1043,9 +1075,9 @@ fts_palloc (FTS *sp, size_t more)
  */
 static void
 internal_function
-fts_padjust (FTS *sp, FTSENT *head)
+fts_padjust (FTSOBJ *sp, FTSENTRY *head)
 {
-	FTSENT *p;
+	FTSENTRY *p;
 	char *addr = sp->fts_path;
 
 #define	ADJUST(p) do {							\
@@ -1085,7 +1117,7 @@ fts_maxarglen (char * const *argv)
  */
 static int
 internal_function
-fts_safe_changedir (FTS *sp, FTSENT *p, int fd, const char *path)
+fts_safe_changedir (FTSOBJ *sp, FTSENTRY *p, int fd, const char *path)
 {
 	int ret, oerrno, newfd;
 	struct stat64 sb;