Patchwork [v5] Add LFS support for fts functions [BZ #11460]

login
register
mail settings
Submitter Mark Wielaard
Date Oct. 22, 2015, 11:34 a.m.
Message ID <1445513672-21431-1-git-send-email-mjw@redhat.com>
Download mbox | patch
Permalink /patch/9310/
State New
Headers show

Comments

Mark Wielaard - Oct. 22, 2015, 11:34 a.m.
I believe I dealt with all the review comments. This last version
is just to deal with the changes caused by rebasing to current master.
OK to commit?

changes:
- Rebased. Deal with prototype-style functions everywhere.

V4 changes:
- Add NEWS entry.

V3 changes:
- Remove redundant initialization in test.
- Use %m instead of %s with strerror(errno) in test.
- Use 0600/0700 modes for open/mkdir in test.
- Replace error with printf/exit(1) in test.
- Use asprintf instead of malloc+snprintf in test.

V2 changes:
- Change fts functions to prototypes.
- Update sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
- Add sysdeps/unix/sysv/linux/mips/mips64/n64/fts{64,}.c
- Add sysdeps/unix/sysv/linux/x86_64/x32/fts{64,}.c

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.

2015-10-22  Mark Wielaard  <mjw@redhat.com>

	* 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.

---
Mark Wielaard - Oct. 28, 2015, 7:56 p.m.
On Thu, 2015-10-22 at 13:34 +0200, Mark Wielaard wrote:
> I believe I dealt with all the review comments. This last version
> is just to deal with the changes caused by rebasing to current master.
> OK to commit?

Ping. I rebased and retested again. This time luckily the only conflicts
were in the NEWS file, so I won't post a new version. I still would like
to commit it though. OK?

> changes:
> - Rebased. Deal with prototype-style functions everywhere.
> 
> V4 changes:
> - Add NEWS entry.
> 
> V3 changes:
> - Remove redundant initialization in test.
> - Use %m instead of %s with strerror(errno) in test.
> - Use 0600/0700 modes for open/mkdir in test.
> - Replace error with printf/exit(1) in test.
> - Use asprintf instead of malloc+snprintf in test.
> 
> V2 changes:
> - Change fts functions to prototypes.
> - Update sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
> - Add sysdeps/unix/sysv/linux/mips/mips64/n64/fts{64,}.c
> - Add sysdeps/unix/sysv/linux/x86_64/x32/fts{64,}.c
> 
> 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.
> 
> 2015-10-22  Mark Wielaard  <mjw@redhat.com>
> 
> 	* 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.
Mark Wielaard - Nov. 2, 2015, 9:50 a.m.
On Wed, 2015-10-28 at 20:56 +0100, Mark Wielaard wrote:
> On Thu, 2015-10-22 at 13:34 +0200, Mark Wielaard wrote:
> > I believe I dealt with all the review comments. This last version
> > is just to deal with the changes caused by rebasing to current master.
> > OK to commit?
> 
> Ping. I rebased and retested again. This time luckily the only conflicts
> were in the NEWS file, so I won't post a new version. I still would like
> to commit it though. OK?

I cannot tell whether not getting any more replies to this patch means
we have consensus that this is a good patch and I can commit it now. Or
that it simply means nobody has time to go over it one last time. Please
let me know which one it is.

Thanks,

Mark
Florian Weimer - Nov. 2, 2015, 3:31 p.m.
On 11/02/2015 10:50 AM, Mark Wielaard wrote:
> On Wed, 2015-10-28 at 20:56 +0100, Mark Wielaard wrote:
>> On Thu, 2015-10-22 at 13:34 +0200, Mark Wielaard wrote:
>>> I believe I dealt with all the review comments. This last version
>>> is just to deal with the changes caused by rebasing to current master.
>>> OK to commit?
>>
>> Ping. I rebased and retested again. This time luckily the only conflicts
>> were in the NEWS file, so I won't post a new version. I still would like
>> to commit it though. OK?
> 
> I cannot tell whether not getting any more replies to this patch means
> we have consensus that this is a good patch and I can commit it now. Or
> that it simply means nobody has time to go over it one last time. Please
> let me know which one it is.

I suppose it's ready to commit.  I was confused by this bit:

+#define fts64_open __rename_fts64_open
+#define fts64_close __rename_fts64_close
+#define fts64_read __rename_fts64_read
+#define fts64_set __rename_fts64_set
+#define fts64_children __rename_fts64_children

But I think it's standard practice to avoid impact from the headers in
such cases (other such uses are uncommented as well).

Florian
Carlos O'Donell - Nov. 3, 2015, 12:02 a.m.
On 10/22/2015 07:34 AM, Mark Wielaard wrote:
> I believe I dealt with all the review comments. This last version
> is just to deal with the changes caused by rebasing to current master.
> OK to commit?

This looks good to me.

Please fix the various nits and wait until the end of the week before
checking in. That should be enough time for others to review if they
think something should need a change.

I can't see why anyone would object to this at the high level, it would
be nice to have fts work with _FILE_OFFSET_BITS=64, and you add more
tests for it.

The details of your patch are pretty straight forward, meeting coding
style guidelines and look good.

> changes:
> - Rebased. Deal with prototype-style functions everywhere.
> 
> V4 changes:
> - Add NEWS entry.
> 
> V3 changes:
> - Remove redundant initialization in test.
> - Use %m instead of %s with strerror(errno) in test.
> - Use 0600/0700 modes for open/mkdir in test.
> - Replace error with printf/exit(1) in test.
> - Use asprintf instead of malloc+snprintf in test.
> 
> V2 changes:
> - Change fts functions to prototypes.
> - Update sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
> - Add sysdeps/unix/sysv/linux/mips/mips64/n64/fts{64,}.c
> - Add sysdeps/unix/sysv/linux/x86_64/x32/fts{64,}.c
> 
> 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.
> 
> 2015-10-22  Mark Wielaard  <mjw@redhat.com>
> 
> 	* 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.
> 
> ---
> 
> diff --git a/NEWS b/NEWS
> index de3a233..0b72ff9 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -9,18 +9,23 @@ Version 2.23
>  
>  * The following bugs are resolved with this release:
>  
> -  887, 2542, 2543, 2558, 2898, 4404, 6803, 10432, 14341, 14912, 15367,
> -  15384, 15470, 15786, 15918, 16141, 16296, 16347, 16399, 16415, 16422,
> -  16517, 16519, 16520, 16521, 16620, 16734, 16973, 16985, 17118, 17243,
> -  17244, 17250, 17441, 17787, 17886, 17887, 17905, 18084, 18086, 18240,
> -  18265, 18370, 18421, 18480, 18525, 18595, 18589, 18610, 18618, 18647,
> -  18661, 18674, 18675, 18681, 18724, 18743, 18757, 18778, 18781, 18787,
> -  18789, 18790, 18795, 18796, 18803, 18820, 18823, 18824, 18825, 18857,
> -  18863, 18870, 18872, 18873, 18875, 18887, 18918, 18921, 18928, 18951,
> -  18952, 18953, 18956, 18961, 18966, 18967, 18969, 18970, 18977, 18980,
> -  18981, 18982, 18985, 19003, 19007, 19012, 19016, 19018, 19032, 19046,
> -  19049, 19050, 19059, 19071, 19074, 19076, 19077, 19078, 19079, 19085,
> -  19086, 19088, 19094, 19095, 19124, 19125, 19129, 19134, 19137, 19156.
> +  887, 2542, 2543, 2558, 2898, 4404, 6803, 10432, 11460, 14341, 14912,
> +  15367, 15384, 15470, 15786, 15918, 16141, 16296, 16347, 16399, 16415,
> +  16422, 16517, 16519, 16520, 16521, 16620, 16734, 16973, 16985, 17118,
> +  17243, 17244, 17250, 17441, 17787, 17886, 17887, 17905, 18084, 18086,
> +  18240, 18265, 18370, 18421, 18480, 18525, 18595, 18589, 18610, 18618,
> +  18647, 18661, 18674, 18675, 18681, 18724, 18743, 18757, 18778, 18781,
> +  18787, 18789, 18790, 18795, 18796, 18803, 18820, 18823, 18824, 18825,
> +  18857, 18863, 18870, 18872, 18873, 18875, 18887, 18918, 18921, 18928,
> +  18951, 18952, 18953, 18956, 18961, 18966, 18967, 18969, 18970, 18977,
> +  18980, 18981, 18982, 18985, 19003, 19007, 19012, 19016, 19018, 19032,
> +  19046, 19049, 19050, 19059, 19071, 19074, 19076, 19077, 19078, 19079,
> +  19085, 19086, 19088, 19094, 19095, 19124, 19125, 19129, 19134, 19137,
> +  19156.

OK.

> +
> +* fts.h can now be used with -D_FILE_OFFSET_BITS=64.  With LFS the following
> +  new symbols are used: fts64_children, fts64_close, fts64_open, fts64_read
> +  and fts64_set.

Suggest:

* The fts.h header can now be used with ...

OK with or without that change.
  
>  * There is now a --disable-timezone-tools configure option for disabling the
>    building and installing of the timezone related utilities (zic, zdump, and
> diff --git a/io/Makefile b/io/Makefile
> index 613dce0..a9ad919 100644
> --- a/io/Makefile
> +++ b/io/Makefile
> @@ -49,7 +49,7 @@ routines :=								\
>  	ttyname ttyname_r isatty					\
>  	link linkat symlink symlinkat readlink readlinkat		\
>  	unlink unlinkat rmdir						\
> -	ftw ftw64 fts poll ppoll					\
> +	ftw ftw64 fts fts64 poll ppoll					\

OK.

>  	posix_fadvise posix_fadvise64					\
>  	posix_fallocate posix_fallocate64				\
>  	sendfile sendfile64 \
> @@ -71,7 +71,7 @@ tests		:= test-utime test-stat test-stat2 test-lfs tst-getcwd \
>  		   tst-renameat tst-fchownat tst-fchmodat tst-faccessat \
>  		   tst-symlinkat tst-linkat tst-readlinkat tst-mkdirat \
>  		   tst-mknodat tst-mkfifoat tst-ttyname_r bug-ftw5 \
> -		   tst-posix_fallocate
> +		   tst-posix_fallocate tst-fts tst-fts-lfs

OK.

>  
>  ifeq ($(run-built-tests),yes)
>  tests-special += $(objpfx)ftwtest.out
> @@ -90,6 +90,7 @@ CFLAGS-fstatfs.c = -fexceptions
>  CFLAGS-statvfs.c = -fexceptions
>  CFLAGS-fstatvfs.c = -fexceptions
>  CFLAGS-fts.c = -Wno-uninitialized $(uses-callbacks) -fexceptions
> +CFLAGS-fts64.c = -Wno-uninitialized $(uses-callbacks) -fexceptions

OK.

>  CFLAGS-ftw.c = $(uses-callbacks) -fexceptions
>  CFLAGS-ftw64.c = $(uses-callbacks) -fexceptions
>  CFLAGS-lockf.c = -fexceptions
> diff --git a/io/Versions b/io/Versions
> index 6c0a23b..64316cd 100644
> --- a/io/Versions
> +++ b/io/Versions
> @@ -122,4 +122,7 @@ libc {
>    GLIBC_2.9 {
>      dup3; pipe2;
>    }
> +  GLIBC_2.23 {
> +    fts64_children; fts64_close; fts64_open; fts64_read; fts64_set;

OK.

> +  }
>  }
> diff --git a/io/fts.c b/io/fts.c
> index f832676..32f60a6 100644
> --- a/io/fts.c
> +++ b/io/fts.c
> @@ -1,3 +1,20 @@

Should have a one line description.

> +/* Copyright (C) 1992-2015 Free Software Foundation, Inc.

How did you determine 1992?

The oldest ChangeLog reference to file modifications which would
require the new FSF header is 1994 (ChangeLog.4).

i.e.
~~~
Tue Nov 15 01:39:36 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
...
        * io/fts.c (MAXPATHLEN): Define if not defined.
...
        * io/fts.c, io/fts.h: New files, from 4.4 BSD code by Keith Bostic.
...
~~~

Therefore I think this should be 1994-2015.

> +   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 +70,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

OK.

> +
> +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 *)

OK.

>       internal_function;
>  
>  #ifndef MAX
> @@ -84,15 +115,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 **))

OK.

>  {
> -	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 +132,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 +231,7 @@ mem1:	free(sp);
>  
>  static void
>  internal_function
> -fts_load (FTS *sp, FTSENT *p)
> +fts_load (FTSOBJ *sp, FTSENTRY *p)

OK.

>  {
>  	int len;
>  	char *cp;
> @@ -224,9 +255,9 @@ fts_load (FTS *sp, FTSENT *p)
>  }
>  
>  int
> -fts_close (FTS *sp)
> +FTS_CLOSE (FTSOBJ *sp)

OK.

>  {
> -	FTSENT *freep, *p;
> +	FTSENTRY *freep, *p;
>  	int saved_errno;
>  
>  	/*
> @@ -276,10 +307,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)

OK.

>  {
> -	FTSENT *p, *tmp;
> +	FTSENTRY *p, *tmp;
>  	int instr;
>  	char *t;
>  	int saved_errno;
> @@ -473,7 +504,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)

OK.

>  {
>  	if (instr != 0 && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
>  	    instr != FTS_NOINSTR && instr != FTS_SKIP) {
> @@ -484,10 +515,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)

OK.

>  {
> -	FTSENT *p;
> +	FTSENTRY *p;
>  	int fd;
>  
>  	if (instr != 0 && instr != FTS_NAMEONLY) {
> @@ -574,14 +605,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)

OK.

>  {
>  	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 +870,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)

OK.

>  {
> -	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 +898,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 +949,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)

OK.

>  {
> -	FTSENT **ap, *p;
> +	FTSENTRY **ap, *p;
>  
>  	/*
>  	 * Construct an array of pointers to the structures and call qsort(3).
> @@ -932,11 +963,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) {

OK.

>  			free(sp->fts_array);
>  			sp->fts_array = NULL;
>  			sp->fts_nitems = 0;
> @@ -946,18 +977,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);

OK.

>  	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)

OK.

>  {
> -	FTSENT *p;
> +	FTSENTRY *p;
>  	size_t len;
>  
>  	/*
> @@ -968,9 +999,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 +1010,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 +1023,9 @@ fts_alloc (FTS *sp, const char *name, size_t namelen)
>  
>  static void
>  internal_function
> -fts_lfree (FTSENT *head)
> +fts_lfree (FTSENTRY *head)

OK.

>  {
> -	FTSENT *p;
> +	FTSENTRY *p;
>  
>  	/* Free a linked list of structures. */
>  	while ((p = head)) {
> @@ -1011,7 +1042,7 @@ fts_lfree (FTSENT *head)
>   */
>  static int
>  internal_function
> -fts_palloc (FTS *sp, size_t more)
> +fts_palloc (FTSOBJ *sp, size_t more)

OK.

>  {
>  	char *p;
>  
> @@ -1043,9 +1074,9 @@ fts_palloc (FTS *sp, size_t more)
>   */
>  static void
>  internal_function
> -fts_padjust (FTS *sp, FTSENT *head)
> +fts_padjust (FTSOBJ *sp, FTSENTRY *head)

OK.

>  {
> -	FTSENT *p;
> +	FTSENTRY *p;
>  	char *addr = sp->fts_path;
>  
>  #define	ADJUST(p) do {							\
> @@ -1085,7 +1116,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)

OK.

>  {
>  	int ret, oerrno, newfd;
>  	struct stat64 sb;
> diff --git a/io/fts.h b/io/fts.h
> index 0a070ba..eca1aeb 100644
> --- a/io/fts.h
> +++ b/io/fts.h
> @@ -1,3 +1,20 @@

Needs one line header.

> +/* Copyright (C) 1992-2015 Free Software Foundation, Inc.

Likeise, should IMO be 1994-2015.

> +   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) 1989, 1993
>   *	The Regents of the University of California.  All rights reserved.
> @@ -35,12 +52,6 @@
>  #include <features.h>
>  #include <sys/types.h>
>  
> -/* The fts interface is incompatible with the LFS interface which
> -   transparently uses the 64-bit file access functions.  */
> -#ifdef __USE_FILE_OFFSET64
> -# error "<fts.h> cannot be used with -D_FILE_OFFSET_BITS==64"
> -#endif

OK.

> -
>  
>  typedef struct {
>  	struct _ftsent *fts_cur;	/* current node */
> @@ -68,6 +79,21 @@ typedef struct {
>  	int fts_options;		/* fts_open options, global flags */
>  } FTS;
>  
> +#ifdef __USE_LARGEFILE64
> +typedef struct {
> +	struct _ftsent64 *fts_cur;	/* current node */
> +	struct _ftsent64 *fts_child;	/* linked list of children */
> +	struct _ftsent64 **fts_array;	/* sort array */
> +	dev_t fts_dev;			/* starting device # */
> +	char *fts_path;			/* path for this descent */
> +	int fts_rfd;			/* fd for root */
> +	int fts_pathlen;		/* sizeof(path) */
> +	int fts_nitems;			/* elements in the sort array */
> +	int (*fts_compar) (const void *, const void *); /* compare fn */
> +	int fts_options;		/* fts_open options, global flags */
> +} FTS64;

OK.

> +#endif
> +
>  typedef struct _ftsent {
>  	struct _ftsent *fts_cycle;	/* cycle node */
>  	struct _ftsent *fts_parent;	/* parent directory */
> @@ -119,13 +145,70 @@ typedef struct _ftsent {
>  	char fts_name[1];		/* file name */
>  } FTSENT;
>  
> +#ifdef __USE_LARGEFILE64
> +typedef struct _ftsent64 {
> +	struct _ftsent64 *fts_cycle;	/* cycle node */
> +	struct _ftsent64 *fts_parent;	/* parent directory */
> +	struct _ftsent64 *fts_link;	/* next file in directory */
> +	long fts_number;	        /* local numeric value */
> +	void *fts_pointer;	        /* local address value */
> +	char *fts_accpath;		/* access path */
> +	char *fts_path;			/* root path */
> +	int fts_errno;			/* errno for this node */
> +	int fts_symfd;			/* fd for symlink */
> +	u_short fts_pathlen;		/* strlen(fts_path) */
> +	u_short fts_namelen;		/* strlen(fts_name) */
> +
> +	ino64_t fts_ino;		/* inode */
> +	dev_t fts_dev;			/* device */
> +	nlink_t fts_nlink;		/* link count */
> +
> +	short fts_level;		/* depth (-1 to N) */
> +
> +	u_short fts_info;		/* user flags for FTSENT structure */
> +
> +	u_short fts_flags;		/* private flags for FTSENT structure */
> +
> +	u_short fts_instr;		/* fts_set() instructions */
> +
> +	struct stat64 *fts_statp;	/* stat(2) information */
> +	char fts_name[1];		/* file name */
> +} FTSENT64;
> +#endif

OK.

> +
>  __BEGIN_DECLS
> +#ifndef __USE_FILE_OFFSET64
>  FTSENT	*fts_children (FTS *, int);
>  int	 fts_close (FTS *);
>  FTS	*fts_open (char * const *, int,
>  		   int (*)(const FTSENT **, const FTSENT **));
>  FTSENT	*fts_read (FTS *);
>  int	 fts_set (FTS *, FTSENT *, int) __THROW;
> +#else
> +# ifdef __REDIRECT
> +FTSENT	*__REDIRECT (fts_children, (FTS *, int), fts64_children);
> +int	 __REDIRECT (fts_close, (FTS *), fts64_close);
> +FTS	*__REDIRECT (fts_open, (char * const *, int,
> +				int (*)(const FTSENT **, const FTSENT **)),
> +		     fts64_open);
> +FTSENT	*__REDIRECT (fts_read, (FTS *), fts64_read);
> +int	 __REDIRECT (fts_set, (FTS *, FTSENT *, int), fts64_set) __THROW;
> +# else
> +#  define fts_children fts64_children
> +#  define fts_close fts64_close
> +#  define fts_open fts64_open
> +#  define fts_read fts64_read
> +#  define fts_set fts64_set
> +# endif
> +#endif
> +#ifdef __USE_LARGEFILE64
> +FTSENT64 *fts64_children (FTS64 *, int);
> +int	  fts64_close (FTS64 *);
> +FTS64	 *fts64_open (char * const *, int,
> +		      int (*)(const FTSENT64 **, const FTSENT64 **));
> +FTSENT64 *fts64_read (FTS64 *);
> +int	 fts64_set (FTS64 *, FTSENT64 *, int) __THROW;
> +#endif

OK.

>  __END_DECLS
>  
>  #endif /* fts.h */
> diff --git a/io/fts64.c b/io/fts64.c
> new file mode 100644
> index 0000000..a45947e
> --- /dev/null
> +++ b/io/fts64.c
> @@ -0,0 +1,29 @@

Line describing thefile.

> +/* Copyright (C) 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/>.  */
> +
> +#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 INO_T ino64_t
> +#define STAT stat64
> +#define LSTAT lstat64
> +
> +#include "fts.c"
> diff --git a/io/tst-fts-lfs.c b/io/tst-fts-lfs.c
> new file mode 100644
> index 0000000..bc16934
> --- /dev/null
> +++ b/io/tst-fts-lfs.c
> @@ -0,0 +1,2 @@
> +#define _FILE_OFFSET_BITS 64
> +#include "tst-fts.c"
> diff --git a/io/tst-fts.c b/io/tst-fts.c
> new file mode 100644
> index 0000000..17401e7
> --- /dev/null
> +++ b/io/tst-fts.c
> @@ -0,0 +1,230 @@
> +/* Simple test for some fts functions.
> +   Copyright (C) 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/>.  */
> +
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <fts.h>
> +
> +#include <errno.h>
> +#include <error.h>
> +#include <string.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <unistd.h>
> +
> +static void prepare (void);
> +static int do_test (void);
> +#define PREPARE(argc, argv)     prepare ()

OK.

> +#define TEST_FUNCTION           do_test ()

OK.

> +#include "../test-skeleton.c"
> +
> +static char *fts_test_dir;
> +
> +static void
> +make_dir (const char *dirname)
> +{
> +  char *name;
> +  if (asprintf (&name, "%s/%s", fts_test_dir, dirname) < 0)
> +    {
> +      puts ("out of memory");
> +      exit (1);
> +    }
> +
> +  if (mkdir (name, 0700) < 0)
> +    {
> +      printf ("cannot create dir \"%s\": %m\n", name);
> +      exit (1);
> +    }
> +
> +  add_temp_file (name);
> +}
> +
> +static void
> +make_file (const char *filename)
> +{
> +  char *name;
> +  if (asprintf (&name, "%s/%s", fts_test_dir, filename) < 0)
> +    {
> +      puts ("out of memory");
> +      exit (1);
> +    }
> +
> +  int fd = open (name, O_WRONLY | O_CREAT | O_EXCL, 0600);
> +  if (fd < 0)
> +    {
> +      printf ("cannot create file \"%s\": %m\n", name);
> +      exit (1);
> +    }
> +  close (fd);
> +
> +  add_temp_file (name);
> +}
> +
> +static void
> +prepare (void)
> +{
> +  char *dirbuf;
> +  char dir_name[] = "/tst-fts.XXXXXX";
> +
> +  if (asprintf (&dirbuf, "%s%s", test_dir, dir_name) < 0)
> +    {
> +      puts ("out of memory");
> +      exit (1);
> +    }
> +
> +  if (mkdtemp (dirbuf) == NULL)
> +    {
> +      puts ("cannot create temporary directory");
> +      exit (1);
> +    }
> +
> +  add_temp_file (dirbuf);
> +  fts_test_dir = dirbuf;
> +
> +  make_file ("12");
> +  make_file ("345");
> +  make_file ("6789");
> +
> +  make_dir ("aaa");
> +  make_file ("aaa/1234");
> +  make_file ("aaa/5678");
> +
> +  make_dir ("bbb");
> +  make_file ("bbb/1234");
> +  make_file ("bbb/5678");
> +  make_file ("bbb/90ab");
> +}
> +
> +/* Largest name wins, otherwise strcmp.  */
> +static int
> +compare_ents (const FTSENT **ent1, const FTSENT **ent2)
> +{
> +  short len1 = (*ent1)->fts_namelen;
> +  short len2 = (*ent2)->fts_namelen;
> +  if (len1 != len2)
> +    return len1 - len2;
> +  else
> +    {
> +      const char *name1 = (*ent1)->fts_name;
> +      const char *name2 = (*ent2)->fts_name;
> +      return strcmp (name1, name2);
> +    }
> +}
> +
> +/* Count the number of files seen as children.  */
> +static int files = 0;
> +
> +static void
> +children (FTS *fts)
> +{
> +  FTSENT *child = fts_children (fts, 0);
> +  if (child == NULL && errno != 0)
> +    {
> +      printf ("fts_children: %m\n");
> +      exit (1);
> +    }
> +
> +  while (child != NULL)
> +    {
> +      short level = child->fts_level;
> +      const char *name = child->fts_name;
> +      if (child->fts_info == FTS_F || child->fts_info == FTS_NSOK)
> +	{
> +	  files++;
> +	  printf ("%*s%s\n", 2 * level, "", name);
> +	}
> +      child = child->fts_link;
> +    }
> +}
> +
> +/* Count the number of dirs seen in the test.  */
> +static int dirs = 0;
> +
> +static int
> +do_test (void)
> +{
> +  char *paths[2] = { fts_test_dir, NULL };
> +  FTS *fts;
> +  fts = fts_open (paths, FTS_LOGICAL, &compare_ents);
> +  if (fts == NULL)
> +    {
> +      printf ("fts_open: %m\n");

Please prefix "FAIL:" so it's clear it's a failure.

> +      exit (1);
> +    }
> +
> +  FTSENT *ent;
> +  while ((ent = fts_read (fts)) != NULL)
> +    {
> +      const char *name = ent->fts_name;
> +      short level = ent->fts_level;
> +      switch (ent->fts_info)
> +	{
> +	case FTS_F:
> +	  /* Don't show anything, children will have on parent dir.  */
> +	  break;
> +
> +	case FTS_D:
> +	  printf ("%*s%s =>\n", 2 * level, "", name);
> +	  children (fts);
> +	  break;
> +
> +	case FTS_DP:
> +	  dirs++;
> +	  printf ("%*s<= %s\n", 2 * level, "", name);
> +	  break;
> +
> +	case FTS_NS:
> +	case FTS_ERR:
> +	  printf ("fts_read ent: %s\n", strerror (ent->fts_errno));

Please prefix "FAIL:" so it's clear it's a failure.

> +	  exit (1);
> +	  break;
> +
> +	default:
> +	  printf ("unexpected fts_read ent %s\n", name);

Please prefix "FAIL:" so it's clear it's a failure.

> +	  exit (1);
> +	  break;
> +	}
> +    }
> +  /* fts_read returns NULL when done (and clears errno)
> +     or when an error occured (with errno set).  */
> +  if (errno != 0)
> +    {
> +      printf ("fts_read: %m\n");

Please prefix "FAIL:" so it's clear it's a failure.

> +      exit (1);
> +    }
> +
> +  if (fts_close (fts) != 0)
> +    {
> +      printf ("fts_close: %m\n");

Please prefix "FAIL:" so it's clear it's a failure.

> +      exit (1);
> +    }
> +
> +  if (files != 8)
> +    {
> +      printf ("Unexpected number of files: %d\n", files);

Please prefix "FAIL:" so it's clear it's a failure.

> +      return 1;
> +    }
> +
> +  if (dirs != 3)
> +    {
> +      printf ("Unexpected number of dirs: %d\n", dirs);

Please prefix "FAIL:" so it's clear it's a failure.

> +      return 1;
> +    }
> +

Optionally print "PASS:" entries for passing a given sub-test or the
whole test, such that it's clear from *.test-results that we actually
did some useful work.

> +  return 0;
> +}

OK.

> diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> index 3e0f329..7b6d68b 100644
> --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> @@ -2084,3 +2084,10 @@ GLIBC_2.18
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F
> diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
> index 58c8b32..4acd11f 100644
> --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
> @@ -1825,6 +1825,13 @@ GLIBC_2.18
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F
>  GLIBC_2.2
>   GLIBC_2.2 A
>   _IO_adjust_wcolumn F
> diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
> index f2b20ad..7fd3ed7 100644
> --- a/sysdeps/unix/sysv/linux/arm/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
> @@ -92,6 +92,13 @@ GLIBC_2.18
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F
>  GLIBC_2.4
>   GLIBC_2.4 A
>   _Exit F
> diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
> index cf0ad90..a48110e 100644
> --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
> @@ -98,6 +98,13 @@ GLIBC_2.19
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F
>  GLIBC_2.2
>   GLIBC_2.2 A
>   _Exit F
> diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
> index fcf1b72..1ad650e 100644
> --- a/sysdeps/unix/sysv/linux/i386/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
> @@ -2026,6 +2026,13 @@ GLIBC_2.2.6
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F
>  GLIBC_2.3
>   GLIBC_2.3 A
>   __ctype_b_loc F
> diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
> index 16c2e3d..9dea013 100644
> --- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
> @@ -1884,6 +1884,13 @@ GLIBC_2.2.6
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F
>  GLIBC_2.3
>   GLIBC_2.3 A
>   __ctype_b_loc F
> diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> index 902b0c3..85aae0f 100644
> --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> @@ -93,6 +93,13 @@ GLIBC_2.18
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F
>  GLIBC_2.4
>   GLIBC_2.4 A
>   _Exit F
> diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> index 4db00b0..e6eda6d 100644
> --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> @@ -1982,6 +1982,13 @@ GLIBC_2.2.6
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F
>  GLIBC_2.3
>   GLIBC_2.3 A
>   __ctype_b_loc F
> diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
> index f1f76a1..78aedb6 100644
> --- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
> @@ -2083,3 +2083,10 @@ GLIBC_2.18
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> index 2d51989..0e91e60 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> @@ -1954,6 +1954,13 @@ GLIBC_2.2.6
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F
>  GLIBC_2.3
>   GLIBC_2.3 A
>   __ctype_b_loc F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> index b012bdf..46958d2 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> @@ -1952,6 +1952,13 @@ GLIBC_2.2.6
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F
>  GLIBC_2.3
>   GLIBC_2.3 A
>   __ctype_b_loc F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> index 9db0e8b..7308b7a 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> @@ -1950,6 +1950,13 @@ GLIBC_2.2.6
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F
>  GLIBC_2.3
>   GLIBC_2.3 A
>   __ctype_b_loc F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fts.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/fts.c
> new file mode 100644
> index 0000000..d0c62e6
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fts.c
> @@ -0,0 +1 @@
> +#include <io/fts.c>
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fts64.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/fts64.c
> new file mode 100644
> index 0000000..2472f8b
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fts64.c
> @@ -0,0 +1 @@
> +#include <io/fts64.c>
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> index eecfcfe..9933093 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> @@ -1944,6 +1944,13 @@ GLIBC_2.2.6
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F
>  GLIBC_2.3
>   GLIBC_2.3 A
>   __ctype_b_loc F
> diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
> index b10bf62..b961502 100644
> --- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
> @@ -2124,3 +2124,10 @@ GLIBC_2.21
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> index 0f15463..787a810 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> @@ -1986,6 +1986,13 @@ GLIBC_2.2.6
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F
>  GLIBC_2.3
>   GLIBC_2.3 A
>   __ctype_b_loc F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
> index 7bcaa07..5cfeecf 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
> @@ -1992,6 +1992,13 @@ GLIBC_2.2.6
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F
>  GLIBC_2.3
>   GLIBC_2.3 A
>   __ctype_b_loc F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
> index c0b3985..67668b0 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
> @@ -2172,3 +2172,10 @@ GLIBC_2.18
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
> index e58a00d..cfabf78 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
> @@ -93,6 +93,13 @@ GLIBC_2.18
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F
>  GLIBC_2.3
>   GLIBC_2.3 A
>   _Exit F
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> index 0ce7824..639cde6 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> @@ -1987,6 +1987,13 @@ GLIBC_2.2.6
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F
>  GLIBC_2.3
>   GLIBC_2.3 A
>   __ctype_b_loc F
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> index dc79912..8c835b0 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> @@ -1883,6 +1883,13 @@ GLIBC_2.2.6
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F
>  GLIBC_2.3
>   GLIBC_2.3 A
>   __ctype_b_loc F
> diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
> index 9ed1b45..f424e7c 100644
> --- a/sysdeps/unix/sysv/linux/sh/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
> @@ -1867,6 +1867,13 @@ GLIBC_2.2.6
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F
>  GLIBC_2.3
>   GLIBC_2.3 A
>   __ctype_b_loc F
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> index 5a40ff3..cd647ca 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> @@ -1978,6 +1978,13 @@ GLIBC_2.2.6
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F
>  GLIBC_2.3
>   GLIBC_2.3 A
>   __ctype_b_loc F
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> index fa70645..1d77587 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> @@ -1911,6 +1911,13 @@ GLIBC_2.2.6
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F
>  GLIBC_2.3
>   GLIBC_2.3 A
>   __ctype_b_loc F
> diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
> index dd215d7..16cafa3 100644
> --- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
> @@ -2094,3 +2094,10 @@ GLIBC_2.18
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F
> diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
> index ef4747a..0032abd 100644
> --- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
> @@ -2094,3 +2094,10 @@ GLIBC_2.18
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F
> diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
> index dd215d7..16cafa3 100644
> --- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
> @@ -2094,3 +2094,10 @@ GLIBC_2.18
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F
> diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> index b377b04..e386ba7 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> @@ -1857,6 +1857,13 @@ GLIBC_2.2.6
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F

OK.

>  GLIBC_2.3
>   GLIBC_2.3 A
>   __ctype_b_loc F
> diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/fts.c b/sysdeps/unix/sysv/linux/x86_64/x32/fts.c
> new file mode 100644
> index 0000000..980573e
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/x86_64/x32/fts.c
> @@ -0,0 +1 @@
> +#include <sysdeps/wordsize-64/fts.c>

OK.

> diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/fts64.c b/sysdeps/unix/sysv/linux/x86_64/x32/fts64.c
> new file mode 100644
> index 0000000..221d1b5
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/x86_64/x32/fts64.c
> @@ -0,0 +1 @@
> +#include <sysdeps/wordsize-64/fts64.c>

OK.

> diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> index 5f70329..91e485b 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> @@ -2092,3 +2092,10 @@ GLIBC_2.18
>  GLIBC_2.22
>   GLIBC_2.22 A
>   fmemopen F
> +GLIBC_2.23
> + GLIBC_2.23 A
> + fts64_children F
> + fts64_close F
> + fts64_open F
> + fts64_read F
> + fts64_set F
> diff --git a/sysdeps/wordsize-64/fts.c b/sysdeps/wordsize-64/fts.c
> new file mode 100644
> index 0000000..159dc1f
> --- /dev/null
> +++ b/sysdeps/wordsize-64/fts.c
> @@ -0,0 +1,19 @@
> +#define fts64_open __rename_fts64_open
> +#define fts64_close __rename_fts64_close
> +#define fts64_read __rename_fts64_read
> +#define fts64_set __rename_fts64_set
> +#define fts64_children __rename_fts64_children
> +
> +#include "../../io/fts.c"
> +
> +#undef fts64_open
> +#undef fts64_close
> +#undef fts64_read
> +#undef fts64_set
> +#undef fts64_children
> +
> +weak_alias (fts_open, fts64_open)
> +weak_alias (fts_close, fts64_close)
> +weak_alias (fts_read, fts64_read)
> +weak_alias (fts_set, fts64_set)
> +weak_alias (fts_children, fts64_children)

OK.

> diff --git a/sysdeps/wordsize-64/fts64.c b/sysdeps/wordsize-64/fts64.c
> new file mode 100644
> index 0000000..f2848fc
> --- /dev/null
> +++ b/sysdeps/wordsize-64/fts64.c
> @@ -0,0 +1 @@
> +/* Defined in fts.c.  */

OK.

> 

Cheers,
Carlos.
Mark Wielaard - Nov. 3, 2015, 10:07 a.m.
On Mon, 2015-11-02 at 19:02 -0500, Carlos O'Donell wrote:
> On 10/22/2015 07:34 AM, Mark Wielaard wrote:
>
> Please fix the various nits and wait until the end of the week before
> checking in. That should be enough time for others to review if they
> think something should need a change.

OK.

> > +* fts.h can now be used with -D_FILE_OFFSET_BITS=64.  With LFS the following
> > +  new symbols are used: fts64_children, fts64_close, fts64_open, fts64_read
> > +  and fts64_set.
> 
> Suggest:
> 
> * The fts.h header can now be used with ...

Changed.

> > diff --git a/io/fts.c b/io/fts.c
> > index f832676..32f60a6 100644
> > --- a/io/fts.c
> > +++ b/io/fts.c
> > @@ -1,3 +1,20 @@
> 
> Should have a one line description.

Added "File tree traversal functions."

> > +/* Copyright (C) 1992-2015 Free Software Foundation, Inc.
> 
> How did you determine 1992?

I assumed they got introduced with the other files when the io
subdirectory got added. But your detective work says otherwise:

> The oldest ChangeLog reference to file modifications which would
> require the new FSF header is 1994 (ChangeLog.4).
> 
> i.e.
> ~~~
> Tue Nov 15 01:39:36 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
> ...
>         * io/fts.c (MAXPATHLEN): Define if not defined.
> ...
>         * io/fts.c, io/fts.h: New files, from 4.4 BSD code by Keith Bostic.
> ...
> ~~~
> 
> Therefore I think this should be 1994-2015.

Agreed, changed.

> > --- a/io/fts.h
> > +++ b/io/fts.h
> > @@ -1,3 +1,20 @@
> 
> Needs one line header.

Added "File tree traversal function declarations."

> > +/* Copyright (C) 1992-2015 Free Software Foundation, Inc.
> 
> Likeise, should IMO be 1994-2015.

Changed.

> > --- /dev/null
> > +++ b/io/fts64.c
> > @@ -0,0 +1,29 @@
> 
> Line describing thefile.

Added "File tree traversal functions LFS version."

> > +static int
> > +do_test (void)
> > +{
> > +  char *paths[2] = { fts_test_dir, NULL };
> > +  FTS *fts;
> > +  fts = fts_open (paths, FTS_LOGICAL, &compare_ents);
> > +  if (fts == NULL)
> > +    {
> > +      printf ("fts_open: %m\n");
> 
> Please prefix "FAIL:" so it's clear it's a failure.

Added. And for the other failing outputs too.

> Optionally print "PASS:" entries for passing a given sub-test or the
> whole test, such that it's clear from *.test-results that we actually
> did some useful work.

I added a single puts ("PASS") before the final return 0.

Thanks,

Mark

Patch

diff --git a/NEWS b/NEWS
index de3a233..0b72ff9 100644
--- a/NEWS
+++ b/NEWS
@@ -9,18 +9,23 @@  Version 2.23
 
 * The following bugs are resolved with this release:
 
-  887, 2542, 2543, 2558, 2898, 4404, 6803, 10432, 14341, 14912, 15367,
-  15384, 15470, 15786, 15918, 16141, 16296, 16347, 16399, 16415, 16422,
-  16517, 16519, 16520, 16521, 16620, 16734, 16973, 16985, 17118, 17243,
-  17244, 17250, 17441, 17787, 17886, 17887, 17905, 18084, 18086, 18240,
-  18265, 18370, 18421, 18480, 18525, 18595, 18589, 18610, 18618, 18647,
-  18661, 18674, 18675, 18681, 18724, 18743, 18757, 18778, 18781, 18787,
-  18789, 18790, 18795, 18796, 18803, 18820, 18823, 18824, 18825, 18857,
-  18863, 18870, 18872, 18873, 18875, 18887, 18918, 18921, 18928, 18951,
-  18952, 18953, 18956, 18961, 18966, 18967, 18969, 18970, 18977, 18980,
-  18981, 18982, 18985, 19003, 19007, 19012, 19016, 19018, 19032, 19046,
-  19049, 19050, 19059, 19071, 19074, 19076, 19077, 19078, 19079, 19085,
-  19086, 19088, 19094, 19095, 19124, 19125, 19129, 19134, 19137, 19156.
+  887, 2542, 2543, 2558, 2898, 4404, 6803, 10432, 11460, 14341, 14912,
+  15367, 15384, 15470, 15786, 15918, 16141, 16296, 16347, 16399, 16415,
+  16422, 16517, 16519, 16520, 16521, 16620, 16734, 16973, 16985, 17118,
+  17243, 17244, 17250, 17441, 17787, 17886, 17887, 17905, 18084, 18086,
+  18240, 18265, 18370, 18421, 18480, 18525, 18595, 18589, 18610, 18618,
+  18647, 18661, 18674, 18675, 18681, 18724, 18743, 18757, 18778, 18781,
+  18787, 18789, 18790, 18795, 18796, 18803, 18820, 18823, 18824, 18825,
+  18857, 18863, 18870, 18872, 18873, 18875, 18887, 18918, 18921, 18928,
+  18951, 18952, 18953, 18956, 18961, 18966, 18967, 18969, 18970, 18977,
+  18980, 18981, 18982, 18985, 19003, 19007, 19012, 19016, 19018, 19032,
+  19046, 19049, 19050, 19059, 19071, 19074, 19076, 19077, 19078, 19079,
+  19085, 19086, 19088, 19094, 19095, 19124, 19125, 19129, 19134, 19137,
+  19156.
+
+* fts.h can now be used with -D_FILE_OFFSET_BITS=64.  With LFS the following
+  new symbols are used: fts64_children, fts64_close, fts64_open, fts64_read
+  and fts64_set.
 
 * There is now a --disable-timezone-tools configure option for disabling the
   building and installing of the timezone related utilities (zic, zdump, and
diff --git a/io/Makefile b/io/Makefile
index 613dce0..a9ad919 100644
--- a/io/Makefile
+++ b/io/Makefile
@@ -49,7 +49,7 @@  routines :=								\
 	ttyname ttyname_r isatty					\
 	link linkat symlink symlinkat readlink readlinkat		\
 	unlink unlinkat rmdir						\
-	ftw ftw64 fts poll ppoll					\
+	ftw ftw64 fts fts64 poll ppoll					\
 	posix_fadvise posix_fadvise64					\
 	posix_fallocate posix_fallocate64				\
 	sendfile sendfile64 \
@@ -71,7 +71,7 @@  tests		:= test-utime test-stat test-stat2 test-lfs tst-getcwd \
 		   tst-renameat tst-fchownat tst-fchmodat tst-faccessat \
 		   tst-symlinkat tst-linkat tst-readlinkat tst-mkdirat \
 		   tst-mknodat tst-mkfifoat tst-ttyname_r bug-ftw5 \
-		   tst-posix_fallocate
+		   tst-posix_fallocate tst-fts tst-fts-lfs
 
 ifeq ($(run-built-tests),yes)
 tests-special += $(objpfx)ftwtest.out
@@ -90,6 +90,7 @@  CFLAGS-fstatfs.c = -fexceptions
 CFLAGS-statvfs.c = -fexceptions
 CFLAGS-fstatvfs.c = -fexceptions
 CFLAGS-fts.c = -Wno-uninitialized $(uses-callbacks) -fexceptions
+CFLAGS-fts64.c = -Wno-uninitialized $(uses-callbacks) -fexceptions
 CFLAGS-ftw.c = $(uses-callbacks) -fexceptions
 CFLAGS-ftw64.c = $(uses-callbacks) -fexceptions
 CFLAGS-lockf.c = -fexceptions
diff --git a/io/Versions b/io/Versions
index 6c0a23b..64316cd 100644
--- a/io/Versions
+++ b/io/Versions
@@ -122,4 +122,7 @@  libc {
   GLIBC_2.9 {
     dup3; pipe2;
   }
+  GLIBC_2.23 {
+    fts64_children; fts64_close; fts64_open; fts64_read; fts64_set;
+  }
 }
diff --git a/io/fts.c b/io/fts.c
index f832676..32f60a6 100644
--- a/io/fts.c
+++ b/io/fts.c
@@ -1,3 +1,20 @@ 
+/* Copyright (C) 1992-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 +70,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 +115,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 +132,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 +231,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 +255,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 +307,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 +504,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 +515,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 +605,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 +870,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 +898,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 +949,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 +963,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 +977,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 +999,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 +1010,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 +1023,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 +1042,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 +1074,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 +1116,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;
diff --git a/io/fts.h b/io/fts.h
index 0a070ba..eca1aeb 100644
--- a/io/fts.h
+++ b/io/fts.h
@@ -1,3 +1,20 @@ 
+/* Copyright (C) 1992-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) 1989, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -35,12 +52,6 @@ 
 #include <features.h>
 #include <sys/types.h>
 
-/* The fts interface is incompatible with the LFS interface which
-   transparently uses the 64-bit file access functions.  */
-#ifdef __USE_FILE_OFFSET64
-# error "<fts.h> cannot be used with -D_FILE_OFFSET_BITS==64"
-#endif
-
 
 typedef struct {
 	struct _ftsent *fts_cur;	/* current node */
@@ -68,6 +79,21 @@  typedef struct {
 	int fts_options;		/* fts_open options, global flags */
 } FTS;
 
+#ifdef __USE_LARGEFILE64
+typedef struct {
+	struct _ftsent64 *fts_cur;	/* current node */
+	struct _ftsent64 *fts_child;	/* linked list of children */
+	struct _ftsent64 **fts_array;	/* sort array */
+	dev_t fts_dev;			/* starting device # */
+	char *fts_path;			/* path for this descent */
+	int fts_rfd;			/* fd for root */
+	int fts_pathlen;		/* sizeof(path) */
+	int fts_nitems;			/* elements in the sort array */
+	int (*fts_compar) (const void *, const void *); /* compare fn */
+	int fts_options;		/* fts_open options, global flags */
+} FTS64;
+#endif
+
 typedef struct _ftsent {
 	struct _ftsent *fts_cycle;	/* cycle node */
 	struct _ftsent *fts_parent;	/* parent directory */
@@ -119,13 +145,70 @@  typedef struct _ftsent {
 	char fts_name[1];		/* file name */
 } FTSENT;
 
+#ifdef __USE_LARGEFILE64
+typedef struct _ftsent64 {
+	struct _ftsent64 *fts_cycle;	/* cycle node */
+	struct _ftsent64 *fts_parent;	/* parent directory */
+	struct _ftsent64 *fts_link;	/* next file in directory */
+	long fts_number;	        /* local numeric value */
+	void *fts_pointer;	        /* local address value */
+	char *fts_accpath;		/* access path */
+	char *fts_path;			/* root path */
+	int fts_errno;			/* errno for this node */
+	int fts_symfd;			/* fd for symlink */
+	u_short fts_pathlen;		/* strlen(fts_path) */
+	u_short fts_namelen;		/* strlen(fts_name) */
+
+	ino64_t fts_ino;		/* inode */
+	dev_t fts_dev;			/* device */
+	nlink_t fts_nlink;		/* link count */
+
+	short fts_level;		/* depth (-1 to N) */
+
+	u_short fts_info;		/* user flags for FTSENT structure */
+
+	u_short fts_flags;		/* private flags for FTSENT structure */
+
+	u_short fts_instr;		/* fts_set() instructions */
+
+	struct stat64 *fts_statp;	/* stat(2) information */
+	char fts_name[1];		/* file name */
+} FTSENT64;
+#endif
+
 __BEGIN_DECLS
+#ifndef __USE_FILE_OFFSET64
 FTSENT	*fts_children (FTS *, int);
 int	 fts_close (FTS *);
 FTS	*fts_open (char * const *, int,
 		   int (*)(const FTSENT **, const FTSENT **));
 FTSENT	*fts_read (FTS *);
 int	 fts_set (FTS *, FTSENT *, int) __THROW;
+#else
+# ifdef __REDIRECT
+FTSENT	*__REDIRECT (fts_children, (FTS *, int), fts64_children);
+int	 __REDIRECT (fts_close, (FTS *), fts64_close);
+FTS	*__REDIRECT (fts_open, (char * const *, int,
+				int (*)(const FTSENT **, const FTSENT **)),
+		     fts64_open);
+FTSENT	*__REDIRECT (fts_read, (FTS *), fts64_read);
+int	 __REDIRECT (fts_set, (FTS *, FTSENT *, int), fts64_set) __THROW;
+# else
+#  define fts_children fts64_children
+#  define fts_close fts64_close
+#  define fts_open fts64_open
+#  define fts_read fts64_read
+#  define fts_set fts64_set
+# endif
+#endif
+#ifdef __USE_LARGEFILE64
+FTSENT64 *fts64_children (FTS64 *, int);
+int	  fts64_close (FTS64 *);
+FTS64	 *fts64_open (char * const *, int,
+		      int (*)(const FTSENT64 **, const FTSENT64 **));
+FTSENT64 *fts64_read (FTS64 *);
+int	 fts64_set (FTS64 *, FTSENT64 *, int) __THROW;
+#endif
 __END_DECLS
 
 #endif /* fts.h */
diff --git a/io/fts64.c b/io/fts64.c
new file mode 100644
index 0000000..a45947e
--- /dev/null
+++ b/io/fts64.c
@@ -0,0 +1,29 @@ 
+/* Copyright (C) 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/>.  */
+
+#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 INO_T ino64_t
+#define STAT stat64
+#define LSTAT lstat64
+
+#include "fts.c"
diff --git a/io/tst-fts-lfs.c b/io/tst-fts-lfs.c
new file mode 100644
index 0000000..bc16934
--- /dev/null
+++ b/io/tst-fts-lfs.c
@@ -0,0 +1,2 @@ 
+#define _FILE_OFFSET_BITS 64
+#include "tst-fts.c"
diff --git a/io/tst-fts.c b/io/tst-fts.c
new file mode 100644
index 0000000..17401e7
--- /dev/null
+++ b/io/tst-fts.c
@@ -0,0 +1,230 @@ 
+/* Simple test for some fts functions.
+   Copyright (C) 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/>.  */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fts.h>
+
+#include <errno.h>
+#include <error.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static void prepare (void);
+static int do_test (void);
+#define PREPARE(argc, argv)     prepare ()
+#define TEST_FUNCTION           do_test ()
+#include "../test-skeleton.c"
+
+static char *fts_test_dir;
+
+static void
+make_dir (const char *dirname)
+{
+  char *name;
+  if (asprintf (&name, "%s/%s", fts_test_dir, dirname) < 0)
+    {
+      puts ("out of memory");
+      exit (1);
+    }
+
+  if (mkdir (name, 0700) < 0)
+    {
+      printf ("cannot create dir \"%s\": %m\n", name);
+      exit (1);
+    }
+
+  add_temp_file (name);
+}
+
+static void
+make_file (const char *filename)
+{
+  char *name;
+  if (asprintf (&name, "%s/%s", fts_test_dir, filename) < 0)
+    {
+      puts ("out of memory");
+      exit (1);
+    }
+
+  int fd = open (name, O_WRONLY | O_CREAT | O_EXCL, 0600);
+  if (fd < 0)
+    {
+      printf ("cannot create file \"%s\": %m\n", name);
+      exit (1);
+    }
+  close (fd);
+
+  add_temp_file (name);
+}
+
+static void
+prepare (void)
+{
+  char *dirbuf;
+  char dir_name[] = "/tst-fts.XXXXXX";
+
+  if (asprintf (&dirbuf, "%s%s", test_dir, dir_name) < 0)
+    {
+      puts ("out of memory");
+      exit (1);
+    }
+
+  if (mkdtemp (dirbuf) == NULL)
+    {
+      puts ("cannot create temporary directory");
+      exit (1);
+    }
+
+  add_temp_file (dirbuf);
+  fts_test_dir = dirbuf;
+
+  make_file ("12");
+  make_file ("345");
+  make_file ("6789");
+
+  make_dir ("aaa");
+  make_file ("aaa/1234");
+  make_file ("aaa/5678");
+
+  make_dir ("bbb");
+  make_file ("bbb/1234");
+  make_file ("bbb/5678");
+  make_file ("bbb/90ab");
+}
+
+/* Largest name wins, otherwise strcmp.  */
+static int
+compare_ents (const FTSENT **ent1, const FTSENT **ent2)
+{
+  short len1 = (*ent1)->fts_namelen;
+  short len2 = (*ent2)->fts_namelen;
+  if (len1 != len2)
+    return len1 - len2;
+  else
+    {
+      const char *name1 = (*ent1)->fts_name;
+      const char *name2 = (*ent2)->fts_name;
+      return strcmp (name1, name2);
+    }
+}
+
+/* Count the number of files seen as children.  */
+static int files = 0;
+
+static void
+children (FTS *fts)
+{
+  FTSENT *child = fts_children (fts, 0);
+  if (child == NULL && errno != 0)
+    {
+      printf ("fts_children: %m\n");
+      exit (1);
+    }
+
+  while (child != NULL)
+    {
+      short level = child->fts_level;
+      const char *name = child->fts_name;
+      if (child->fts_info == FTS_F || child->fts_info == FTS_NSOK)
+	{
+	  files++;
+	  printf ("%*s%s\n", 2 * level, "", name);
+	}
+      child = child->fts_link;
+    }
+}
+
+/* Count the number of dirs seen in the test.  */
+static int dirs = 0;
+
+static int
+do_test (void)
+{
+  char *paths[2] = { fts_test_dir, NULL };
+  FTS *fts;
+  fts = fts_open (paths, FTS_LOGICAL, &compare_ents);
+  if (fts == NULL)
+    {
+      printf ("fts_open: %m\n");
+      exit (1);
+    }
+
+  FTSENT *ent;
+  while ((ent = fts_read (fts)) != NULL)
+    {
+      const char *name = ent->fts_name;
+      short level = ent->fts_level;
+      switch (ent->fts_info)
+	{
+	case FTS_F:
+	  /* Don't show anything, children will have on parent dir.  */
+	  break;
+
+	case FTS_D:
+	  printf ("%*s%s =>\n", 2 * level, "", name);
+	  children (fts);
+	  break;
+
+	case FTS_DP:
+	  dirs++;
+	  printf ("%*s<= %s\n", 2 * level, "", name);
+	  break;
+
+	case FTS_NS:
+	case FTS_ERR:
+	  printf ("fts_read ent: %s\n", strerror (ent->fts_errno));
+	  exit (1);
+	  break;
+
+	default:
+	  printf ("unexpected fts_read ent %s\n", name);
+	  exit (1);
+	  break;
+	}
+    }
+  /* fts_read returns NULL when done (and clears errno)
+     or when an error occured (with errno set).  */
+  if (errno != 0)
+    {
+      printf ("fts_read: %m\n");
+      exit (1);
+    }
+
+  if (fts_close (fts) != 0)
+    {
+      printf ("fts_close: %m\n");
+      exit (1);
+    }
+
+  if (files != 8)
+    {
+      printf ("Unexpected number of files: %d\n", files);
+      return 1;
+    }
+
+  if (dirs != 3)
+    {
+      printf ("Unexpected number of dirs: %d\n", dirs);
+      return 1;
+    }
+
+  return 0;
+}
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 3e0f329..7b6d68b 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2084,3 +2084,10 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 58c8b32..4acd11f 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -1825,6 +1825,13 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
 GLIBC_2.2
  GLIBC_2.2 A
  _IO_adjust_wcolumn F
diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index f2b20ad..7fd3ed7 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -92,6 +92,13 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
 GLIBC_2.4
  GLIBC_2.4 A
  _Exit F
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index cf0ad90..a48110e 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -98,6 +98,13 @@  GLIBC_2.19
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
 GLIBC_2.2
  GLIBC_2.2 A
  _Exit F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index fcf1b72..1ad650e 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2026,6 +2026,13 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index 16c2e3d..9dea013 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -1884,6 +1884,13 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 902b0c3..85aae0f 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -93,6 +93,13 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
 GLIBC_2.4
  GLIBC_2.4 A
  _Exit F
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 4db00b0..e6eda6d 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -1982,6 +1982,13 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
index f1f76a1..78aedb6 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -2083,3 +2083,10 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index 2d51989..0e91e60 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -1954,6 +1954,13 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index b012bdf..46958d2 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -1952,6 +1952,13 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index 9db0e8b..7308b7a 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -1950,6 +1950,13 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fts.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/fts.c
new file mode 100644
index 0000000..d0c62e6
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fts.c
@@ -0,0 +1 @@ 
+#include <io/fts.c>
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fts64.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/fts64.c
new file mode 100644
index 0000000..2472f8b
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fts64.c
@@ -0,0 +1 @@ 
+#include <io/fts64.c>
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index eecfcfe..9933093 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -1944,6 +1944,13 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index b10bf62..b961502 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2124,3 +2124,10 @@  GLIBC_2.21
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index 0f15463..787a810 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -1986,6 +1986,13 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index 7bcaa07..5cfeecf 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -1992,6 +1992,13 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
index c0b3985..67668b0 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
@@ -2172,3 +2172,10 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
index e58a00d..cfabf78 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
@@ -93,6 +93,13 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
 GLIBC_2.3
  GLIBC_2.3 A
  _Exit F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index 0ce7824..639cde6 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -1987,6 +1987,13 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index dc79912..8c835b0 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -1883,6 +1883,13 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
index 9ed1b45..f424e7c 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -1867,6 +1867,13 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 5a40ff3..cd647ca 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -1978,6 +1978,13 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index fa70645..1d77587 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -1911,6 +1911,13 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
index dd215d7..16cafa3 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
@@ -2094,3 +2094,10 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
index ef4747a..0032abd 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
@@ -2094,3 +2094,10 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
index dd215d7..16cafa3 100644
--- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
@@ -2094,3 +2094,10 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index b377b04..e386ba7 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -1857,6 +1857,13 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/fts.c b/sysdeps/unix/sysv/linux/x86_64/x32/fts.c
new file mode 100644
index 0000000..980573e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/fts.c
@@ -0,0 +1 @@ 
+#include <sysdeps/wordsize-64/fts.c>
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/fts64.c b/sysdeps/unix/sysv/linux/x86_64/x32/fts64.c
new file mode 100644
index 0000000..221d1b5
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/fts64.c
@@ -0,0 +1 @@ 
+#include <sysdeps/wordsize-64/fts64.c>
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 5f70329..91e485b 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2092,3 +2092,10 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ fts64_children F
+ fts64_close F
+ fts64_open F
+ fts64_read F
+ fts64_set F
diff --git a/sysdeps/wordsize-64/fts.c b/sysdeps/wordsize-64/fts.c
new file mode 100644
index 0000000..159dc1f
--- /dev/null
+++ b/sysdeps/wordsize-64/fts.c
@@ -0,0 +1,19 @@ 
+#define fts64_open __rename_fts64_open
+#define fts64_close __rename_fts64_close
+#define fts64_read __rename_fts64_read
+#define fts64_set __rename_fts64_set
+#define fts64_children __rename_fts64_children
+
+#include "../../io/fts.c"
+
+#undef fts64_open
+#undef fts64_close
+#undef fts64_read
+#undef fts64_set
+#undef fts64_children
+
+weak_alias (fts_open, fts64_open)
+weak_alias (fts_close, fts64_close)
+weak_alias (fts_read, fts64_read)
+weak_alias (fts_set, fts64_set)
+weak_alias (fts_children, fts64_children)
diff --git a/sysdeps/wordsize-64/fts64.c b/sysdeps/wordsize-64/fts64.c
new file mode 100644
index 0000000..f2848fc
--- /dev/null
+++ b/sysdeps/wordsize-64/fts64.c
@@ -0,0 +1 @@ 
+/* Defined in fts.c.  */