2002-10-16 22:09:42 +00:00
|
|
|
/* Get file-specific information about a file. Linux version.
|
2021-01-02 19:32:25 +00:00
|
|
|
Copyright (C) 1991-2021 Free Software Foundation, Inc.
|
1998-10-23 13:44:50 +00:00
|
|
|
This file is part of the GNU C Library.
|
|
|
|
|
|
|
|
The GNU C Library is free software; you can redistribute it and/or
|
2001-07-06 04:58:11 +00:00
|
|
|
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.
|
1998-10-23 13:44:50 +00:00
|
|
|
|
|
|
|
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
|
2001-07-06 04:58:11 +00:00
|
|
|
Lesser General Public License for more details.
|
1998-10-23 13:44:50 +00:00
|
|
|
|
2001-07-06 04:58:11 +00:00
|
|
|
You should have received a copy of the GNU Lesser General Public
|
2012-02-09 23:18:22 +00:00
|
|
|
License along with the GNU C Library; if not, see
|
Prefer https to http for gnu.org and fsf.org URLs
Also, change sources.redhat.com to sourceware.org.
This patch was automatically generated by running the following shell
script, which uses GNU sed, and which avoids modifying files imported
from upstream:
sed -ri '
s,(http|ftp)(://(.*\.)?(gnu|fsf|sourceware)\.org($|[^.]|\.[^a-z])),https\2,g
s,(http|ftp)(://(.*\.)?)sources\.redhat\.com($|[^.]|\.[^a-z]),https\2sourceware.org\4,g
' \
$(find $(git ls-files) -prune -type f \
! -name '*.po' \
! -name 'ChangeLog*' \
! -path COPYING ! -path COPYING.LIB \
! -path manual/fdl-1.3.texi ! -path manual/lgpl-2.1.texi \
! -path manual/texinfo.tex ! -path scripts/config.guess \
! -path scripts/config.sub ! -path scripts/install-sh \
! -path scripts/mkinstalldirs ! -path scripts/move-if-change \
! -path INSTALL ! -path locale/programs/charmap-kw.h \
! -path po/libc.pot ! -path sysdeps/gnu/errlist.c \
! '(' -name configure \
-execdir test -f configure.ac -o -f configure.in ';' ')' \
! '(' -name preconfigure \
-execdir test -f preconfigure.ac ';' ')' \
-print)
and then by running 'make dist-prepare' to regenerate files built
from the altered files, and then executing the following to cleanup:
chmod a+x sysdeps/unix/sysv/linux/riscv/configure
# Omit irrelevant whitespace and comment-only changes,
# perhaps from a slightly-different Autoconf version.
git checkout -f \
sysdeps/csky/configure \
sysdeps/hppa/configure \
sysdeps/riscv/configure \
sysdeps/unix/sysv/linux/csky/configure
# Omit changes that caused a pre-commit check to fail like this:
# remote: *** error: sysdeps/powerpc/powerpc64/ppc-mcount.S: trailing lines
git checkout -f \
sysdeps/powerpc/powerpc64/ppc-mcount.S \
sysdeps/unix/sysv/linux/s390/s390-64/syscall.S
# Omit change that caused a pre-commit check to fail like this:
# remote: *** error: sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S: last line does not end in newline
git checkout -f sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S
2019-09-07 05:40:42 +00:00
|
|
|
<https://www.gnu.org/licenses/>. */
|
1998-10-23 13:44:50 +00:00
|
|
|
|
2003-06-11 23:22:36 +00:00
|
|
|
#include <errno.h>
|
2011-07-07 14:53:16 +00:00
|
|
|
#include <mntent.h>
|
|
|
|
#include <stdio_ext.h>
|
2011-07-20 18:12:57 +00:00
|
|
|
#include <string.h>
|
2011-07-07 14:53:16 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/sysmacros.h>
|
2008-03-08 01:57:18 +00:00
|
|
|
|
2002-10-16 22:09:42 +00:00
|
|
|
#include "pathconf.h"
|
2003-06-11 23:22:36 +00:00
|
|
|
#include "linux_fsinfo.h"
|
2008-03-08 01:57:18 +00:00
|
|
|
#include <not-cancel.h>
|
1998-10-23 13:44:50 +00:00
|
|
|
|
2002-10-16 22:09:42 +00:00
|
|
|
static long int posix_pathconf (const char *file, int name);
|
1998-10-23 13:44:50 +00:00
|
|
|
|
2002-10-16 22:09:42 +00:00
|
|
|
/* Define this first, so it can be inlined. */
|
|
|
|
#define __pathconf static posix_pathconf
|
|
|
|
#include <sysdeps/posix/pathconf.c>
|
1998-10-23 13:44:50 +00:00
|
|
|
|
|
|
|
|
2002-10-16 22:09:42 +00:00
|
|
|
/* Get file-specific information about FILE. */
|
1998-10-23 13:44:50 +00:00
|
|
|
long int
|
2002-10-16 22:09:42 +00:00
|
|
|
__pathconf (const char *file, int name)
|
1998-10-23 13:44:50 +00:00
|
|
|
{
|
2002-10-18 19:03:55 +00:00
|
|
|
struct statfs fsbuf;
|
|
|
|
|
|
|
|
switch (name)
|
1998-10-23 13:44:50 +00:00
|
|
|
{
|
2002-10-18 19:03:55 +00:00
|
|
|
case _PC_LINK_MAX:
|
2011-07-07 14:53:16 +00:00
|
|
|
return __statfs_link_max (__statfs (file, &fsbuf), &fsbuf, file, -1);
|
2003-03-14 06:28:45 +00:00
|
|
|
|
2002-10-18 19:03:55 +00:00
|
|
|
case _PC_FILESIZEBITS:
|
2003-06-11 23:22:36 +00:00
|
|
|
return __statfs_filesize_max (__statfs (file, &fsbuf), &fsbuf);
|
2003-03-14 06:28:45 +00:00
|
|
|
|
|
|
|
case _PC_2_SYMLINKS:
|
2003-06-11 23:22:36 +00:00
|
|
|
return __statfs_symlinks (__statfs (file, &fsbuf), &fsbuf);
|
2003-03-14 06:28:45 +00:00
|
|
|
|
2008-03-08 01:57:18 +00:00
|
|
|
case _PC_CHOWN_RESTRICTED:
|
|
|
|
return __statfs_chown_restricted (__statfs (file, &fsbuf), &fsbuf);
|
|
|
|
|
2002-10-18 19:03:55 +00:00
|
|
|
default:
|
|
|
|
return posix_pathconf (file, name);
|
1998-10-23 13:44:50 +00:00
|
|
|
}
|
|
|
|
}
|
2003-06-11 23:22:36 +00:00
|
|
|
|
|
|
|
|
2011-07-07 14:53:16 +00:00
|
|
|
static long int
|
|
|
|
distinguish_extX (const struct statfs *fsbuf, const char *file, int fd)
|
|
|
|
{
|
|
|
|
char buf[64];
|
|
|
|
char path[PATH_MAX];
|
2021-03-02 20:06:02 +00:00
|
|
|
struct __stat64_t64 st;
|
2011-07-07 14:53:16 +00:00
|
|
|
|
2021-03-02 20:06:02 +00:00
|
|
|
if ((file == NULL ? __fstat64_time64 (fd, &st)
|
|
|
|
: __stat64_time64 (file, &st)) != 0)
|
2011-07-07 14:53:16 +00:00
|
|
|
/* Strange. The statfd call worked, but stat fails. Default to
|
|
|
|
the more pessimistic value. */
|
|
|
|
return EXT2_LINK_MAX;
|
|
|
|
|
|
|
|
__snprintf (buf, sizeof (buf), "/sys/dev/block/%u:%u",
|
Fix -Os gnu_dev_* linknamespace, localplt issues (bug 15105, bug 19463).
Building with -Os produces linknamespace and localplt failures for,
among other functions, gnu_dev_major, gnu_dev_minor and
gnu_dev_makedev.
The issue is that those functions are not inlined when building with
-Os. While one could force them to be inlined in that case, it seems
more natural to fix this issue similarly to other namespace issues.
Thus, this patch makes gnu_dev_* into weak aliases for hidden symbols
__gnu_dev_*; __gnu_dev_* are then defined as inlines in the internal
include/sys/sysmacros.h, and uses of gnu_dev_* (often via the macros
major, minor and makedev) for which there are namespace issues are
changed to use __gnu_dev_*; where there are no namespace issues, use
of libc_hidden_proto serves to avoid unnecessary local PLT entry use.
Tested for x86_64, (a) without -Os, to verify the testsuite continues
to pass without problems and that the functions called under their new
names continue to be inlined as expected in that case; (b) with -Os,
to verify that the linknamespace and localplt failures in question go
away (but because of other such failures present, neither of the
relevant bugs can yet be closed).
[BZ #15105]
[BZ #19463]
* include/sys/sysmacros.h [!_ISOMAC]
(__SYSMACROS_NEED_IMPLEMENTATION): Define macro.
[!_SYS_SYSMACROS_H_WRAPPER && !_ISOMAC]
(_SYS_SYSMACROS_H_WRAPPER): Likewise.
[!_SYS_SYSMACROS_H_WRAPPER && !_ISOMAC] (gnu_dev_major): Use
libc_hidden_proto.
[!_SYS_SYSMACROS_H_WRAPPER && !_ISOMAC] (gnu_dev_minor): Likewise.
[!_SYS_SYSMACROS_H_WRAPPER && !_ISOMAC] (gnu_dev_makedev):
Likewise.
[!_SYS_SYSMACROS_H_WRAPPER && !_ISOMAC] (__SYSMACROS_DECL_TEMPL):
Undefine and redefine to add use __gnu_dev_ prefix.
[!_SYS_SYSMACROS_H_WRAPPER && !_ISOMAC] (__SYSMACROS_IMPL_TEMPL):
Likewise.
[!_SYS_SYSMACROS_H_WRAPPER && !_ISOMAC] (__gnu_dev_major): Declare
and define as hidden inline function.
[!_SYS_SYSMACROS_H_WRAPPER && !_ISOMAC] (__gnu_dev_minor):
Likewise.
[!_SYS_SYSMACROS_H_WRAPPER && !_ISOMAC] (__gnu_dev_makedev):
Likewise.
* misc/makedev.c (OUT_OF_LINE_IMPL_TEMPL): Use __gnu_dev_ prefix.
(gnu_dev_major): Use weak_alias and libc_hidden_weak.
(gnu_dev_minor): Likewise.
(gnu_dev_makedev): Likewise.
* csu/check_fds.c (check_one_fd): Use __gnu_dev_makedev instead of
makedev.
* posix/wordexp.c (exec_comm_child): Likewise.
* sysdeps/mach/hurd/xmknodat.c (__xmknodat): Use __gnu_dev_minor
instead of minor and __gnu_dev_major instead of major.
* sysdeps/unix/sysv/linux/device-nrs.h (DEV_TTY_P): Use
__gnu_dev_major instead of major.
* sysdeps/unix/sysv/linux/pathconf.c (distinguish_extX): Use
__gnu_dev_major instead of gnu_dev_major and __gnu_dev_minor
instead of gnu_dev_minor.
* sysdeps/unix/sysv/linux/ptsname.c (MASTER_P): Likewise.
(SLAVE_P): Likewise.
(__ptsname_internal): Use __gnu_dev_minor instead of minor.
* sysdeps/unix/sysv/linux/ttyname.h (is_pty): Use __gnu_dev_major
instead of major.
2018-02-07 14:57:31 +00:00
|
|
|
__gnu_dev_major (st.st_dev), __gnu_dev_minor (st.st_dev));
|
2011-07-07 14:53:16 +00:00
|
|
|
|
|
|
|
ssize_t n = __readlink (buf, path, sizeof (path));
|
|
|
|
if (n != -1 && n < sizeof (path))
|
|
|
|
{
|
|
|
|
path[n] = '\0';
|
2015-05-22 17:09:36 +00:00
|
|
|
char *base = strdupa (__basename (path));
|
2011-07-07 14:53:16 +00:00
|
|
|
__snprintf (path, sizeof (path), "/sys/fs/ext4/%s", base);
|
|
|
|
|
|
|
|
return __access (path, F_OK) == 0 ? EXT4_LINK_MAX : EXT2_LINK_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX Is there a better way to distinguish ext2/3 from ext4 than
|
|
|
|
iterating over the mounted filesystems and compare the device
|
|
|
|
numbers? */
|
|
|
|
FILE *mtab = __setmntent ("/proc/mounts", "r");
|
|
|
|
if (mtab == NULL)
|
|
|
|
mtab = __setmntent (_PATH_MOUNTED, "r");
|
|
|
|
|
|
|
|
/* By default be conservative. */
|
|
|
|
long int result = EXT2_LINK_MAX;
|
|
|
|
if (mtab != NULL)
|
|
|
|
{
|
|
|
|
struct mntent mntbuf;
|
|
|
|
char tmpbuf[1024];
|
|
|
|
|
|
|
|
/* No locking needed. */
|
|
|
|
(void) __fsetlocking (mtab, FSETLOCKING_BYCALLER);
|
|
|
|
|
|
|
|
while (__getmntent_r (mtab, &mntbuf, tmpbuf, sizeof (tmpbuf)))
|
|
|
|
{
|
|
|
|
if (strcmp (mntbuf.mnt_type, "ext2") != 0
|
|
|
|
&& strcmp (mntbuf.mnt_type, "ext3") != 0
|
|
|
|
&& strcmp (mntbuf.mnt_type, "ext4") != 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
struct stat64 fsst;
|
2020-07-15 19:35:58 +00:00
|
|
|
if (__stat64 (mntbuf.mnt_dir, &fsst) >= 0
|
2011-07-07 14:53:16 +00:00
|
|
|
&& st.st_dev == fsst.st_dev)
|
|
|
|
{
|
|
|
|
if (strcmp (mntbuf.mnt_type, "ext4") == 0)
|
|
|
|
result = EXT4_LINK_MAX;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Close the file. */
|
|
|
|
__endmntent (mtab);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-06-11 23:22:36 +00:00
|
|
|
/* Used like: return statfs_link_max (__statfs (name, &buf), &buf); */
|
|
|
|
long int
|
2011-07-07 14:53:16 +00:00
|
|
|
__statfs_link_max (int result, const struct statfs *fsbuf, const char *file,
|
|
|
|
int fd)
|
2003-06-11 23:22:36 +00:00
|
|
|
{
|
|
|
|
if (result < 0)
|
|
|
|
{
|
|
|
|
if (errno == ENOSYS)
|
|
|
|
/* Not possible, return the default value. */
|
|
|
|
return LINUX_LINK_MAX;
|
|
|
|
|
|
|
|
/* Some error occured. */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (fsbuf->f_type)
|
|
|
|
{
|
|
|
|
case EXT2_SUPER_MAGIC:
|
2011-07-07 14:53:16 +00:00
|
|
|
/* Unfortunately the kernel does not return a different magic number
|
|
|
|
for ext4. This would be necessary to easily detect etx4 since it
|
|
|
|
has a different LINK_MAX value. Therefore we have to find it out
|
|
|
|
the hard way. */
|
|
|
|
return distinguish_extX (fsbuf, file, fd);
|
2003-06-11 23:22:36 +00:00
|
|
|
|
2013-03-06 15:35:19 +00:00
|
|
|
case F2FS_SUPER_MAGIC:
|
|
|
|
return F2FS_LINK_MAX;
|
|
|
|
|
2003-06-11 23:22:36 +00:00
|
|
|
case MINIX_SUPER_MAGIC:
|
|
|
|
case MINIX_SUPER_MAGIC2:
|
|
|
|
return MINIX_LINK_MAX;
|
|
|
|
|
|
|
|
case MINIX2_SUPER_MAGIC:
|
|
|
|
case MINIX2_SUPER_MAGIC2:
|
|
|
|
return MINIX2_LINK_MAX;
|
|
|
|
|
|
|
|
case XENIX_SUPER_MAGIC:
|
|
|
|
return XENIX_LINK_MAX;
|
|
|
|
|
|
|
|
case SYSV4_SUPER_MAGIC:
|
|
|
|
case SYSV2_SUPER_MAGIC:
|
|
|
|
return SYSV_LINK_MAX;
|
|
|
|
|
|
|
|
case COH_SUPER_MAGIC:
|
|
|
|
return COH_LINK_MAX;
|
|
|
|
|
|
|
|
case UFS_MAGIC:
|
|
|
|
case UFS_CIGAM:
|
|
|
|
return UFS_LINK_MAX;
|
|
|
|
|
|
|
|
case REISERFS_SUPER_MAGIC:
|
|
|
|
return REISERFS_LINK_MAX;
|
|
|
|
|
|
|
|
case XFS_SUPER_MAGIC:
|
|
|
|
return XFS_LINK_MAX;
|
|
|
|
|
2011-07-07 04:20:32 +00:00
|
|
|
case LUSTRE_SUPER_MAGIC:
|
|
|
|
return LUSTRE_LINK_MAX;
|
|
|
|
|
2003-06-11 23:22:36 +00:00
|
|
|
default:
|
|
|
|
return LINUX_LINK_MAX;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Used like: return statfs_filesize_max (__statfs (name, &buf), &buf); */
|
|
|
|
long int
|
|
|
|
__statfs_filesize_max (int result, const struct statfs *fsbuf)
|
|
|
|
{
|
|
|
|
if (result < 0)
|
|
|
|
{
|
|
|
|
if (errno == ENOSYS)
|
|
|
|
/* Not possible, return the default value. */
|
|
|
|
return 32;
|
|
|
|
|
|
|
|
/* Some error occured. */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (fsbuf->f_type)
|
|
|
|
{
|
2013-03-06 15:35:19 +00:00
|
|
|
case F2FS_SUPER_MAGIC:
|
|
|
|
return 256;
|
|
|
|
|
2010-10-01 14:49:47 +00:00
|
|
|
case BTRFS_SUPER_MAGIC:
|
|
|
|
return 255;
|
|
|
|
|
2003-06-11 23:22:36 +00:00
|
|
|
case EXT2_SUPER_MAGIC:
|
|
|
|
case UFS_MAGIC:
|
|
|
|
case UFS_CIGAM:
|
|
|
|
case REISERFS_SUPER_MAGIC:
|
|
|
|
case XFS_SUPER_MAGIC:
|
|
|
|
case SMB_SUPER_MAGIC:
|
|
|
|
case NTFS_SUPER_MAGIC:
|
|
|
|
case UDF_SUPER_MAGIC:
|
|
|
|
case JFS_SUPER_MAGIC:
|
2003-09-04 14:42:25 +00:00
|
|
|
case VXFS_SUPER_MAGIC:
|
2010-10-01 14:49:47 +00:00
|
|
|
case CGROUP_SUPER_MAGIC:
|
2011-07-07 04:20:32 +00:00
|
|
|
case LUSTRE_SUPER_MAGIC:
|
2003-06-11 23:22:36 +00:00
|
|
|
return 64;
|
|
|
|
|
|
|
|
case MSDOS_SUPER_MAGIC:
|
|
|
|
case JFFS_SUPER_MAGIC:
|
|
|
|
case JFFS2_SUPER_MAGIC:
|
|
|
|
case NCP_SUPER_MAGIC:
|
|
|
|
case ROMFS_SUPER_MAGIC:
|
|
|
|
return 32;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return 32;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Used like: return statfs_link_max (__statfs (name, &buf), &buf); */
|
|
|
|
long int
|
|
|
|
__statfs_symlinks (int result, const struct statfs *fsbuf)
|
|
|
|
{
|
|
|
|
if (result < 0)
|
|
|
|
{
|
|
|
|
if (errno == ENOSYS)
|
|
|
|
/* Not possible, return the default value. */
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
/* Some error occured. */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (fsbuf->f_type)
|
|
|
|
{
|
|
|
|
case ADFS_SUPER_MAGIC:
|
|
|
|
case BFS_MAGIC:
|
|
|
|
case CRAMFS_MAGIC:
|
|
|
|
case DEVPTS_SUPER_MAGIC:
|
|
|
|
case EFS_SUPER_MAGIC:
|
|
|
|
case EFS_MAGIC:
|
|
|
|
case MSDOS_SUPER_MAGIC:
|
|
|
|
case NTFS_SUPER_MAGIC:
|
|
|
|
case QNX4_SUPER_MAGIC:
|
|
|
|
case ROMFS_SUPER_MAGIC:
|
|
|
|
/* No symlink support. */
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
2008-03-08 01:57:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* Used like: return __statfs_chown_restricted (__statfs (name, &buf), &buf);*/
|
|
|
|
long int
|
|
|
|
__statfs_chown_restricted (int result, const struct statfs *fsbuf)
|
|
|
|
{
|
|
|
|
if (result < 0)
|
|
|
|
{
|
|
|
|
if (errno == ENOSYS)
|
|
|
|
/* Not possible, return the default value. */
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
/* Some error occured. */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-04-03 05:26:45 +00:00
|
|
|
return 1;
|
2008-03-08 01:57:18 +00:00
|
|
|
}
|