469 lines
15 KiB
Diff
469 lines
15 KiB
Diff
From 46f5da05629638d9ea67782d4afc0b0f5154e7b9 Mon Sep 17 00:00:00 2001
|
|
From: Gleb Fotengauer-Malinovskiy <glebfm@altlinux.org>
|
|
Date: Wed, 16 Aug 2017 19:20:03 +0300
|
|
Subject: [PATCH] Add support of LFS-compatible fts functions
|
|
|
|
Since glibc 2.23, fts has LFS support.
|
|
---
|
|
configure.ac | 15 ++++--
|
|
src/Makefile.am | 1 +
|
|
src/fts.c | 147 +++++++++++++++++++++++++++++++++-----------------------
|
|
src/fts64.c | 33 +++++++++++++
|
|
4 files changed, 132 insertions(+), 64 deletions(-)
|
|
create mode 100644 src/fts64.c
|
|
|
|
diff --git a/configure.ac b/configure.ac
|
|
index 30557a4..e87ce94 100644
|
|
--- a/configure.ac
|
|
+++ b/configure.ac
|
|
@@ -190,6 +190,7 @@ AC_CHECK_FUNCS(m4_normalize([
|
|
fts_children
|
|
fts_open
|
|
fts_read
|
|
+ fts64_open
|
|
ftw
|
|
ftw64
|
|
futimesat
|
|
@@ -315,11 +316,19 @@ m4_foreach_w([function], [getpeername getsockname],
|
|
|
|
ACX_CHECK_FUNC_ARGTYPES([fts_open],
|
|
[], [sys/types.h sys/stat.h fts.h],
|
|
- [[FTS *], [char * const *_], [int], [int (*_)(const FTSENT **, const FTSENT **)]],
|
|
- [[FTS *]],
|
|
+ [[FTSOBJ *], [char * const *_], [int], [int (*_)(const FTSENTRY **, const FTSENTRY **)]],
|
|
+ [[FTSOBJ *]],
|
|
[[char * const *_]],
|
|
[[int _]],
|
|
- [[int (*_)(const FTSENT * const *, const FTSENT * const *)], [int (*_)(const FTSENT **, const FTSENT **)]])
|
|
+ [[int (*_)(const FTSENTRY * const *, const FTSENTRY * const *)], [int (*_)(const FTSENTRY **, const FTSENTRY **)]])
|
|
+
|
|
+ACX_CHECK_FUNC_ARGTYPES([fts64_open],
|
|
+ [], [sys/types.h sys/stat.h fts.h],
|
|
+ [[FTSOBJ *], [char * const *_], [int], [int (*_)(const FTSENTRY **, const FTSENTRY **)]],
|
|
+ [[FTSOBJ *]],
|
|
+ [[char * const *_]],
|
|
+ [[int _]],
|
|
+ [[int (*_)(const FTSENTRY * const *, const FTSENTRY * const *)], [int (*_)(const FTSENTRY **, const FTSENTRY **)]])
|
|
|
|
ACX_CHECK_FUNC_ARGTYPES([readlink],
|
|
[
|
|
diff --git a/src/Makefile.am b/src/Makefile.am
|
|
index 01fc652..8af41eb 100644
|
|
--- a/src/Makefile.am
|
|
+++ b/src/Makefile.am
|
|
@@ -62,6 +62,7 @@ libfakechroot_la_SOURCES = \
|
|
freopen.c \
|
|
freopen64.c \
|
|
fts.c \
|
|
+ fts64.c \
|
|
ftw.c \
|
|
ftw64.c \
|
|
futimesat.c \
|
|
diff --git a/src/fts.c b/src/fts.c
|
|
index 61ac032..e69e1b7 100644
|
|
--- a/src/fts.c
|
|
+++ b/src/fts.c
|
|
@@ -32,10 +32,13 @@
|
|
|
|
#include <config.h>
|
|
|
|
+#if !defined FTS64_C__ || (defined FTS64_C__ && HAVE_FTS64_OPEN)
|
|
+
|
|
#define _ATFILE_SOURCE
|
|
#define _BSD_SOURCE
|
|
#define _XOPEN_SOURCE 500
|
|
#define _DEFAULT_SOURCE
|
|
+#define _LARGEFILE64_SOURCE
|
|
#include <sys/param.h>
|
|
#include <sys/stat.h>
|
|
|
|
@@ -80,16 +83,34 @@
|
|
# endif
|
|
#endif
|
|
|
|
-static FTSENT *fts_alloc(FTS *, char *, size_t);
|
|
-static FTSENT *fts_build(FTS *, int);
|
|
-static void fts_lfree(FTSENT *);
|
|
-static void fts_load(FTS *, FTSENT *);
|
|
+/* Support for the LFS API version. */
|
|
+#ifndef FTS_OPEN
|
|
+/* functions */
|
|
+# 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
|
|
+/* types */
|
|
+# define FTSOBJ FTS
|
|
+# define _FTSENT _ftsent
|
|
+# define FTSENTRY FTSENT
|
|
+# define INO_T ino_t
|
|
+# define STAT stat
|
|
+# define FSTAT fstat
|
|
+# define LSTAT lstat
|
|
+#endif
|
|
+
|
|
+static FTSENTRY *fts_alloc(FTSOBJ *, char *, size_t);
|
|
+static FTSENTRY *fts_build(FTSOBJ *, int);
|
|
+static void fts_lfree(FTSENTRY *);
|
|
+static void fts_load(FTSOBJ *, FTSENTRY *);
|
|
static size_t fts_maxarglen(char * const *);
|
|
-static void fts_padjust(FTS *, FTSENT *);
|
|
-static int fts_palloc(FTS *, size_t);
|
|
-static FTSENT *fts_sort(FTS *, FTSENT *, int);
|
|
-static u_short fts_stat(FTS *, FTSENT *, int);
|
|
-static int fts_safe_changedir(FTS *, FTSENT *, int, char *);
|
|
+static void fts_padjust(FTSOBJ *, FTSENTRY *);
|
|
+static int fts_palloc(FTSOBJ *, size_t);
|
|
+static FTSENTRY *fts_sort(FTSOBJ *, FTSENTRY *, int);
|
|
+static u_short fts_stat(FTSOBJ *, FTSENTRY *, int);
|
|
+static int fts_safe_changedir(FTSOBJ *, FTSENTRY *, int, char *);
|
|
|
|
#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
|
|
|
|
@@ -104,14 +125,14 @@ static int fts_safe_changedir(FTS *, FTSENT *, int, char *);
|
|
#define BNAMES 2 /* fts_children, names only */
|
|
#define BREAD 3 /* fts_read */
|
|
|
|
-FTS *
|
|
-fts_open(char * const *argv, int options,
|
|
+FTSOBJ *
|
|
+FTS_OPEN(char * const *argv, int options,
|
|
FTS_OPEN_TYPE_ARG3(compar))
|
|
{
|
|
- FTS *sp;
|
|
- FTSENT *p, *root;
|
|
+ FTSOBJ *sp;
|
|
+ FTSENTRY *p, *root;
|
|
int nitems;
|
|
- FTSENT *parent, *tmp = NULL;
|
|
+ FTSENTRY *parent, *tmp = NULL;
|
|
size_t len;
|
|
|
|
debug("fts_open({\"%s\", ...}, %d, &compar)", **argv, options);
|
|
@@ -123,7 +144,7 @@ fts_open(char * const *argv, int options,
|
|
}
|
|
|
|
/* Allocate/initialize the stream */
|
|
- if ((sp = calloc(1, sizeof(FTS))) == NULL)
|
|
+ if ((sp = calloc(1, sizeof(FTSOBJ))) == NULL)
|
|
return (NULL);
|
|
sp->fts_compar = (void *)compar;
|
|
sp->fts_options = options;
|
|
@@ -216,7 +237,7 @@ mem1: free(sp);
|
|
}
|
|
|
|
static void
|
|
-fts_load(FTS *sp, FTSENT *p)
|
|
+fts_load(FTSOBJ *sp, FTSENTRY *p)
|
|
{
|
|
size_t len;
|
|
char *cp;
|
|
@@ -240,9 +261,9 @@ fts_load(FTS *sp, FTSENT *p)
|
|
}
|
|
|
|
int
|
|
-fts_close(FTS *sp)
|
|
+FTS_CLOSE(FTSOBJ *sp)
|
|
{
|
|
- FTSENT *freep, *p;
|
|
+ FTSENTRY *freep, *p;
|
|
int rfd, error = 0;
|
|
|
|
debug("fts_close(&sp)");
|
|
@@ -292,10 +313,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;
|
|
@@ -490,7 +511,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)
|
|
{
|
|
debug("fts_set(&sp, &p, %d)", instr);
|
|
if (instr && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
|
|
@@ -502,10 +523,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;
|
|
|
|
debug("fts_children(&sp, %d)", instr);
|
|
@@ -586,12 +607,12 @@ fts_children(FTS *sp, int instr)
|
|
* directories and for any files after the subdirectories in the directory have
|
|
* been found, cutting the stat calls by about 2/3.
|
|
*/
|
|
-static FTSENT *
|
|
-fts_build(FTS *sp, int type)
|
|
+static FTSENTRY *
|
|
+fts_build(FTSOBJ *sp, int type)
|
|
{
|
|
struct dirent *dp;
|
|
- FTSENT *p, *head;
|
|
- FTSENT *cur, *tail;
|
|
+ FTSENTRY *p, *head;
|
|
+ FTSENTRY *cur, *tail;
|
|
DIR *dirp;
|
|
void *oldaddr;
|
|
size_t len, maxlen;
|
|
@@ -834,12 +855,12 @@ mem1: saved_errno = errno;
|
|
}
|
|
|
|
static u_short
|
|
-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. */
|
|
@@ -851,18 +872,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)) {
|
|
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);
|
|
}
|
|
|
|
@@ -902,10 +923,10 @@ err: memset(sbp, 0, sizeof(struct stat));
|
|
return (FTS_DEFAULT);
|
|
}
|
|
|
|
-static FTSENT *
|
|
-fts_sort(FTS *sp, FTSENT *head, int nitems)
|
|
+static FTSENTRY *
|
|
+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).
|
|
@@ -915,11 +936,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;
|
|
+ struct _FTSENT **a;
|
|
|
|
sp->fts_nitems = nitems + 40;
|
|
if ((a = realloc(sp->fts_array,
|
|
- sp->fts_nitems * sizeof(FTSENT *))) == NULL) {
|
|
+ sp->fts_nitems * sizeof(FTSENTRY *))) == NULL) {
|
|
if (sp->fts_array)
|
|
free(sp->fts_array);
|
|
sp->fts_array = NULL;
|
|
@@ -930,33 +951,33 @@ 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 *), (void *)sp->fts_compar);
|
|
+ qsort((void *)sp->fts_array, nitems, sizeof(FTSENTRY *), (void *)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 *
|
|
-fts_alloc(FTS *sp, char *name, size_t namelen)
|
|
+static FTSENTRY *
|
|
+fts_alloc(FTSOBJ *sp, char *name, size_t namelen)
|
|
{
|
|
- FTSENT *p;
|
|
+ FTSENTRY *p;
|
|
size_t len;
|
|
|
|
#ifdef HAVE_STRUCT__FTSENT_FTS_NAME_TYPE_CHAR_P
|
|
struct ftsent_withstat {
|
|
- FTSENT ent;
|
|
+ FTSENTRY ent;
|
|
struct stat statbuf;
|
|
};
|
|
|
|
/*
|
|
* 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 FTSENTRY
|
|
* structure, the file name and the stat structure in one chunk, but
|
|
* be careful that the stat structure is reasonably aligned.
|
|
*/
|
|
if (ISSET(FTS_NOSTAT))
|
|
- len = sizeof(FTSENT) + namelen + 1;
|
|
+ len = sizeof(FTSENTRY) + namelen + 1;
|
|
else
|
|
len = sizeof(struct ftsent_withstat) + namelen + 1;
|
|
|
|
@@ -985,15 +1006,15 @@ fts_alloc(FTS *sp, char *name, size_t namelen)
|
|
#else
|
|
/*
|
|
* 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 FTSENTRY
|
|
* structure, the file name and the stat structure in one chunk, but
|
|
* be careful that the stat structure is reasonably aligned. Since the
|
|
* 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);
|
|
|
|
@@ -1002,7 +1023,7 @@ fts_alloc(FTS *sp, char *name, size_t namelen)
|
|
p->fts_namelen = namelen;
|
|
p->fts_instr = FTS_NOINSTR;
|
|
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);
|
|
memcpy(p->fts_name, name, namelen);
|
|
#endif
|
|
|
|
@@ -1010,9 +1031,9 @@ fts_alloc(FTS *sp, char *name, size_t namelen)
|
|
}
|
|
|
|
static void
|
|
-fts_lfree(FTSENT *head)
|
|
+fts_lfree(FTSENTRY *head)
|
|
{
|
|
- FTSENT *p;
|
|
+ FTSENTRY *p;
|
|
|
|
/* Free a linked list of structures. */
|
|
while ((p = head)) {
|
|
@@ -1028,7 +1049,7 @@ fts_lfree(FTSENT *head)
|
|
* plus 256 bytes so don't realloc the path 2 bytes at a time.
|
|
*/
|
|
static int
|
|
-fts_palloc(FTS *sp, size_t more)
|
|
+fts_palloc(FTSOBJ *sp, size_t more)
|
|
{
|
|
char *p;
|
|
|
|
@@ -1060,9 +1081,9 @@ fts_palloc(FTS *sp, size_t more)
|
|
* already returned.
|
|
*/
|
|
static void
|
|
-fts_padjust(FTS *sp, FTSENT *head)
|
|
+fts_padjust(FTSOBJ *sp, FTSENTRY *head)
|
|
{
|
|
- FTSENT *p;
|
|
+ FTSENTRY *p;
|
|
char *addr = sp->fts_path;
|
|
|
|
#define ADJUST(p) { \
|
|
@@ -1100,17 +1121,17 @@ fts_maxarglen(char * const *argv)
|
|
* Assumes p->fts_dev and p->fts_ino are filled in.
|
|
*/
|
|
static int
|
|
-fts_safe_changedir(FTS *sp, FTSENT *p, int fd, char *path)
|
|
+fts_safe_changedir(FTSOBJ *sp, FTSENTRY *p, int fd, char *path)
|
|
{
|
|
int ret, oerrno, newfd;
|
|
- struct stat sb;
|
|
+ struct STAT sb;
|
|
|
|
newfd = fd;
|
|
if (ISSET(FTS_NOCHDIR))
|
|
return (0);
|
|
if (fd < 0 && (newfd = open(path, O_RDONLY, 0)) < 0)
|
|
return (-1);
|
|
- if (fstat(newfd, &sb)) {
|
|
+ if (FSTAT(newfd, &sb)) {
|
|
ret = -1;
|
|
goto bail;
|
|
}
|
|
@@ -1127,3 +1148,7 @@ bail:
|
|
errno = oerrno;
|
|
return (ret);
|
|
}
|
|
+
|
|
+#else
|
|
+typedef int empty_translation_unit;
|
|
+#endif
|
|
diff --git a/src/fts64.c b/src/fts64.c
|
|
new file mode 100644
|
|
index 0000000..ba98805
|
|
--- /dev/null
|
|
+++ b/src/fts64.c
|
|
@@ -0,0 +1,33 @@
|
|
+/* File tree traversal functions LFS version.
|
|
+ Copyright (C) 2015-2017 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/>. */
|
|
+
|
|
+#define FTS64_C__
|
|
+#define FTS_OPEN fts64_open
|
|
+#define FTS_CLOSE fts64_close
|
|
+#define FTS_READ fts64_read
|
|
+#define FTS_SET fts64_set
|
|
+#define FTS_CHILDREN fts64_children
|
|
+#define FTSOBJ FTS64
|
|
+#define FTSENTRY FTSENT64
|
|
+#define _FTSENT _ftsent64
|
|
+#define INO_T ino64_t
|
|
+#define STAT stat64
|
|
+#define FSTAT fstat64
|
|
+#define LSTAT lstat64
|
|
+
|
|
+#include "fts.c"
|
|
--
|
|
2.14.1
|
|
|