mirror of
git://sourceware.org/git/glibc.git
synced 2024-12-21 04:31:04 +08:00
cf06a4e357
pathconf (sysdeps/unix/sysv/linux/pathconf.c) uses basename. But pathconf is in POSIX back to 1990 while basename is only reserved with external linkage in those standards including XPG functions. This patch fixes this namespace issue in the usual way, renaming basename to __basename and making it into a weak alias. Tested for x86_64 and x86 (testsuite, and that disassembly of installed shared libraries is unchanged by the patch). [BZ #18444] * string/basename.c (basename): Rename to __basename and define as weak alias of __basename. Use libc_hidden_weak. * include/string.h (__basename): Declare. Use libc_hidden_proto. * sysdeps/unix/sysv/linux/pathconf.c (distinguish_extX): Call __basename instead of basename. * conform/Makefile (test-xfail-POSIX2008/unistd.h/linknamespace): Remove variable. (test-xfail-XOPEN2K8/unistd.h/linknamespace): Likewise.
294 lines
6.9 KiB
C
294 lines
6.9 KiB
C
/* Get file-specific information about a file. Linux version.
|
|
Copyright (C) 1991-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 <errno.h>
|
|
#include <mntent.h>
|
|
#include <stdio_ext.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <sys/sysmacros.h>
|
|
|
|
#include "pathconf.h"
|
|
#include "linux_fsinfo.h"
|
|
#include <not-cancel.h>
|
|
|
|
static long int posix_pathconf (const char *file, int name);
|
|
|
|
/* Define this first, so it can be inlined. */
|
|
#define __pathconf static posix_pathconf
|
|
#include <sysdeps/posix/pathconf.c>
|
|
|
|
|
|
/* Get file-specific information about FILE. */
|
|
long int
|
|
__pathconf (const char *file, int name)
|
|
{
|
|
struct statfs fsbuf;
|
|
|
|
switch (name)
|
|
{
|
|
case _PC_LINK_MAX:
|
|
return __statfs_link_max (__statfs (file, &fsbuf), &fsbuf, file, -1);
|
|
|
|
case _PC_FILESIZEBITS:
|
|
return __statfs_filesize_max (__statfs (file, &fsbuf), &fsbuf);
|
|
|
|
case _PC_2_SYMLINKS:
|
|
return __statfs_symlinks (__statfs (file, &fsbuf), &fsbuf);
|
|
|
|
case _PC_CHOWN_RESTRICTED:
|
|
return __statfs_chown_restricted (__statfs (file, &fsbuf), &fsbuf);
|
|
|
|
default:
|
|
return posix_pathconf (file, name);
|
|
}
|
|
}
|
|
|
|
|
|
static long int
|
|
distinguish_extX (const struct statfs *fsbuf, const char *file, int fd)
|
|
{
|
|
char buf[64];
|
|
char path[PATH_MAX];
|
|
struct stat64 st;
|
|
|
|
if ((file == NULL ? fstat64 (fd, &st) : stat64 (file, &st)) != 0)
|
|
/* 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",
|
|
gnu_dev_major (st.st_dev), gnu_dev_minor (st.st_dev));
|
|
|
|
ssize_t n = __readlink (buf, path, sizeof (path));
|
|
if (n != -1 && n < sizeof (path))
|
|
{
|
|
path[n] = '\0';
|
|
char *base = strdupa (__basename (path));
|
|
__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;
|
|
if (stat64 (mntbuf.mnt_dir, &fsst) >= 0
|
|
&& 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;
|
|
}
|
|
|
|
|
|
/* Used like: return statfs_link_max (__statfs (name, &buf), &buf); */
|
|
long int
|
|
__statfs_link_max (int result, const struct statfs *fsbuf, const char *file,
|
|
int fd)
|
|
{
|
|
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:
|
|
/* 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);
|
|
|
|
case F2FS_SUPER_MAGIC:
|
|
return F2FS_LINK_MAX;
|
|
|
|
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;
|
|
|
|
case LUSTRE_SUPER_MAGIC:
|
|
return LUSTRE_LINK_MAX;
|
|
|
|
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)
|
|
{
|
|
case F2FS_SUPER_MAGIC:
|
|
return 256;
|
|
|
|
case BTRFS_SUPER_MAGIC:
|
|
return 255;
|
|
|
|
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:
|
|
case VXFS_SUPER_MAGIC:
|
|
case CGROUP_SUPER_MAGIC:
|
|
case LUSTRE_SUPER_MAGIC:
|
|
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;
|
|
}
|
|
}
|
|
|
|
|
|
/* 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;
|
|
}
|
|
|
|
return 1;
|
|
}
|