stat: fix determination of max name length on BSD systems

We only use one of statfs or statvfs for `stat -f`
and on the BSDs we use statfs which doesn't have the
f_namelen member.  However on OpenBSD and later FreeBSD
systems statfs does provide f_namemax, so use that.

* NEWS: Mention the improvement for OpenBSD and FreeBSD.
* m4/stat-prog.m4: Check for f_namemax in the statfs struct.
* src/stat.c: Return '?' rather than '*' when we can't
determine the max length of the file system.
* tests/ln/sf-1.sh: This test was failing on all BSDs
due to '*' being returned for the max length which
caused the test to attempt to create 1Mi+1 names.
The test now uses a short name when we can't determine
the max name length to use.

Reported by Assaf Gordon on various BSD based systems.
This commit is contained in:
Pádraig Brady 2017-08-29 23:42:54 -07:00
parent 3ebdc3e1af
commit f169345506
4 changed files with 14 additions and 9 deletions

3
NEWS
View File

@ -104,6 +104,9 @@ GNU coreutils NEWS -*- outline -*-
mv --verbose now distinguishes rename and copy operations.
stat -f -c %l, used to output the max file name length on a file system,
is now supported on FreeBSD and OpenBSD.
tail -f now exits immediately if the output is piped
and the reader of the pipe terminates.

View File

@ -72,8 +72,9 @@ AC_INCLUDES_DEFAULT
[AC_DEFINE([STRUCT_STATVFS_F_FSID_IS_INTEGER], [1],
[Define to 1 if the f_fsid member of struct statvfs is an integer.])])
else
AC_CHECK_MEMBERS([struct statfs.f_namelen, struct statfs.f_type,
struct statfs.f_frsize],,, [$statfs_includes])
AC_CHECK_MEMBERS([struct statfs.f_namelen, struct statfs.f_namemax,
struct statfs.f_type, struct statfs.f_frsize],,,
[$statfs_includes])
if test $ac_cv_header_OS_h != yes; then
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(

View File

@ -92,6 +92,8 @@
# define HAVE_STRUCT_STATXFS_F_TYPE HAVE_STRUCT_STATFS_F_TYPE
# if HAVE_STRUCT_STATFS_F_NAMELEN
# define SB_F_NAMEMAX(S) ((S)->f_namelen)
# elif HAVE_STRUCT_STATFS_F_NAMEMAX
# define SB_F_NAMEMAX(S) ((S)->f_namemax)
# endif
# define STATFS statfs
# if HAVE_OS_H /* BeOS */
@ -139,8 +141,9 @@ statfs (char const *filename, struct fs_info *buf)
#ifdef SB_F_NAMEMAX
# define OUT_NAMEMAX out_uint
#else
/* NetBSD 1.5.2 has neither f_namemax nor f_namelen. */
# define SB_F_NAMEMAX(S) "*"
/* Depending on whether statvfs or statfs is used,
neither f_namemax or f_namelen may be available. */
# define SB_F_NAMEMAX(S) "?"
# define OUT_NAMEMAX out_string
#endif

View File

@ -33,12 +33,10 @@ esac
# Ensure we replace symlinks that don't or can't link to an existing target.
# coreutils-8.22 would fail to replace {ENOTDIR,ELOOP,ENAMETOOLONG}_link below.
name_max=$(stat -f -c %l .) || skip_ 'Error determining NAME_MAX'
# Apply a limit since AIX returns 2^32-1 which would trigger resource issues.
name_limit=$((1024*1024))
test "$name_max" -lt "$name_limit" || name_max="$name_limit"
# We apply a limit since AIX returns 2^32-1 which would trigger resource issues.
name_max=$(stat -f -c %l .) && test "$name_max" -lt $((1024*1024)) ||
name_max=1 # skip this portion of the test
name_max_plus1=$(expr $name_max + 1)
test $name_max_plus1 -gt 1 || skip_ 'Error determining NAME_MAX'
long_name=$(printf '%0*d' $name_max_plus1 0)
for f in '' f; do