* io/Makefile (routines): Add fstatat, fstatat64, fxstatat, fxstatat64,
fchownat, and unlinkat. (static-only-routines): Add fstatat and fstatat64. (tests): Add tst-unlinkat, tst-fstatat, tst-futimesat, tst-renameat, and tst-fchownat. * io/Versions [GLIBC_2.4]: Add fchownat, __fxstatat, __fxstatat64, and unlinkat. * io/fcntl.h: Define AT_FDCWD, AT_SYMLINK_NOFOLLOW, and AT_REMOVEDIR. * io/fstatat.c: New file. * io/fstatat64.c: New file. * io/sys/stat.h: Declare fstatat, fstatat64, __fxstatat, __fxstatat64 and define fstatat and fstatat64 inline functions. * libio/stdio.h: Declare renameat. * misc/Makefile (routines): Add futimesat. * misc/Versions [GLIBC_2.4]: Add futimesat. * posix/unistd.h: Declare fchownat and unlinkat. * stdio-common/Makefile (routines): Add renameat. * stdio-common/Versions [GLIBC_2.4]: Add renameat. * sysdeps/generic/fchownat.c: New file. * sysdeps/generic/futimesat.c: New file. * sysdeps/generic/fxstatat.c: New file. * sysdeps/generic/fxstatat64.c: New file. * sysdeps/generic/renameat.c: New file. * sysdeps/generic/unlinkat.c: New file. * sysdeps/unix/sysv/linux/fchownat.c: New file. * sysdeps/unix/sysv/linux/futimesat.c: New file. * sysdeps/unix/sysv/linux/fxstatat.c: New file. * sysdeps/unix/sysv/linux/fxstatat64.c: New file. * sysdeps/unix/sysv/linux/renameat.c: New file. * sysdeps/unix/sysv/linux/unlinkat.c: New file. * sysdeps/unix/sysv/linux/alpha/fxstatat.c: New file. * sysdeps/unix/sysv/linux/i386/fchownat.c: New file. * sysdeps/unix/sysv/linux/i386/fxstatat.c: New file. * sysdeps/unix/sysv/linux/m68k/fchownat.c: New file. * sysdeps/unix/sysv/linux/m68k/fxstatat.c: New file. * sysdeps/unix/sysv/linux/powerpc/fchownat.c: New file. * sysdeps/unix/sysv/linux/powerpc/powerpc32/fxstatat.c: New file. * sysdeps/unix/sysv/linux/s390/s390-32/fchownat.c: New file. * sysdeps/unix/sysv/linux/s390/s390-32/fxstatat.c: New file. * sysdeps/unix/sysv/linux/sh/fchownat.c: New file. * sysdeps/unix/sysv/linux/sh/fxstatat.c: New file. * sysdeps/unix/sysv/linux/sparc/sparc32/fchownat.c: New file. * sysdeps/unix/sysv/linux/sparc/sparc32/fxstatat.c: New file. * sysdeps/unix/sysv/linux/sparc/sparc64/fxstatat.c: New file. * sysdeps/unix/sysv/linux/wordsize-64/fxstatat.c: New file. * sysdeps/unix/sysv/linux/wordsize-64/fxstatat64.c: New file. * time/sys/time.h: Declare futimesat. * include/fcntl.h: Declare __atfct_seterrno. * sysdeps/unix/sysv/linux/openat.c (__atfct_seterrno): New function. Split out from openat code and called. (do_test): Allow openat to fail with ENOSYS. Handle AT_FDCWD. * sysdeps/generic/openat.c: Handle AT_FDCWD. * sysdeps/generic/openat64.c: Likewise. * io/tst-unlinkat.c: New file. * io/tst-fstatat.c: New file. * io/tst-futimesat.c: New file. * io/tst-renameat.c: New file. * io/tst-fchownat.c: New file. * io/tst-openat.c: Don't fail if openat is not implemented. * sysdeps/unix/sysv/linux/powerpc/chown.c: Don't provide backward compatibility code if new kernel is guaranteed. * time/sys/time.h: Add a few nonnull attributes.
This commit is contained in:
parent
4973cbe599
commit
26cec518ac
67
ChangeLog
67
ChangeLog
|
@ -1,3 +1,70 @@
|
||||||
|
2005-11-11 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
|
* io/Makefile (routines): Add fstatat, fstatat64, fxstatat, fxstatat64,
|
||||||
|
fchownat, and unlinkat.
|
||||||
|
(static-only-routines): Add fstatat and fstatat64.
|
||||||
|
(tests): Add tst-unlinkat, tst-fstatat, tst-futimesat, tst-renameat,
|
||||||
|
and tst-fchownat.
|
||||||
|
* io/Versions [GLIBC_2.4]: Add fchownat, __fxstatat, __fxstatat64,
|
||||||
|
and unlinkat.
|
||||||
|
* io/fcntl.h: Define AT_FDCWD, AT_SYMLINK_NOFOLLOW, and AT_REMOVEDIR.
|
||||||
|
* io/fstatat.c: New file.
|
||||||
|
* io/fstatat64.c: New file.
|
||||||
|
* io/sys/stat.h: Declare fstatat, fstatat64, __fxstatat, __fxstatat64
|
||||||
|
and define fstatat and fstatat64 inline functions.
|
||||||
|
* libio/stdio.h: Declare renameat.
|
||||||
|
* misc/Makefile (routines): Add futimesat.
|
||||||
|
* misc/Versions [GLIBC_2.4]: Add futimesat.
|
||||||
|
* posix/unistd.h: Declare fchownat and unlinkat.
|
||||||
|
* stdio-common/Makefile (routines): Add renameat.
|
||||||
|
* stdio-common/Versions [GLIBC_2.4]: Add renameat.
|
||||||
|
* sysdeps/generic/fchownat.c: New file.
|
||||||
|
* sysdeps/generic/futimesat.c: New file.
|
||||||
|
* sysdeps/generic/fxstatat.c: New file.
|
||||||
|
* sysdeps/generic/fxstatat64.c: New file.
|
||||||
|
* sysdeps/generic/renameat.c: New file.
|
||||||
|
* sysdeps/generic/unlinkat.c: New file.
|
||||||
|
* sysdeps/unix/sysv/linux/fchownat.c: New file.
|
||||||
|
* sysdeps/unix/sysv/linux/futimesat.c: New file.
|
||||||
|
* sysdeps/unix/sysv/linux/fxstatat.c: New file.
|
||||||
|
* sysdeps/unix/sysv/linux/fxstatat64.c: New file.
|
||||||
|
* sysdeps/unix/sysv/linux/renameat.c: New file.
|
||||||
|
* sysdeps/unix/sysv/linux/unlinkat.c: New file.
|
||||||
|
* sysdeps/unix/sysv/linux/alpha/fxstatat.c: New file.
|
||||||
|
* sysdeps/unix/sysv/linux/i386/fchownat.c: New file.
|
||||||
|
* sysdeps/unix/sysv/linux/i386/fxstatat.c: New file.
|
||||||
|
* sysdeps/unix/sysv/linux/m68k/fchownat.c: New file.
|
||||||
|
* sysdeps/unix/sysv/linux/m68k/fxstatat.c: New file.
|
||||||
|
* sysdeps/unix/sysv/linux/powerpc/fchownat.c: New file.
|
||||||
|
* sysdeps/unix/sysv/linux/powerpc/powerpc32/fxstatat.c: New file.
|
||||||
|
* sysdeps/unix/sysv/linux/s390/s390-32/fchownat.c: New file.
|
||||||
|
* sysdeps/unix/sysv/linux/s390/s390-32/fxstatat.c: New file.
|
||||||
|
* sysdeps/unix/sysv/linux/sh/fchownat.c: New file.
|
||||||
|
* sysdeps/unix/sysv/linux/sh/fxstatat.c: New file.
|
||||||
|
* sysdeps/unix/sysv/linux/sparc/sparc32/fchownat.c: New file.
|
||||||
|
* sysdeps/unix/sysv/linux/sparc/sparc32/fxstatat.c: New file.
|
||||||
|
* sysdeps/unix/sysv/linux/sparc/sparc64/fxstatat.c: New file.
|
||||||
|
* sysdeps/unix/sysv/linux/wordsize-64/fxstatat.c: New file.
|
||||||
|
* sysdeps/unix/sysv/linux/wordsize-64/fxstatat64.c: New file.
|
||||||
|
* time/sys/time.h: Declare futimesat.
|
||||||
|
* include/fcntl.h: Declare __atfct_seterrno.
|
||||||
|
* sysdeps/unix/sysv/linux/openat.c (__atfct_seterrno): New function.
|
||||||
|
Split out from openat code and called.
|
||||||
|
(do_test): Allow openat to fail with ENOSYS. Handle AT_FDCWD.
|
||||||
|
* sysdeps/generic/openat.c: Handle AT_FDCWD.
|
||||||
|
* sysdeps/generic/openat64.c: Likewise.
|
||||||
|
* io/tst-unlinkat.c: New file.
|
||||||
|
* io/tst-fstatat.c: New file.
|
||||||
|
* io/tst-futimesat.c: New file.
|
||||||
|
* io/tst-renameat.c: New file.
|
||||||
|
* io/tst-fchownat.c: New file.
|
||||||
|
* io/tst-openat.c: Don't fail if openat is not implemented.
|
||||||
|
|
||||||
|
* sysdeps/unix/sysv/linux/powerpc/chown.c: Don't provide backward
|
||||||
|
compatibility code if new kernel is guaranteed.
|
||||||
|
|
||||||
|
* time/sys/time.h: Add a few nonnull attributes.
|
||||||
|
|
||||||
2005-11-09 Ulrich Drepper <drepper@redhat.com>
|
2005-11-09 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
* io/fcntl.h: Declare openat and openat64.
|
* io/fcntl.h: Declare openat and openat64.
|
||||||
|
|
5
NEWS
5
NEWS
|
@ -1,4 +1,4 @@
|
||||||
GNU C Library NEWS -- history of user-visible changes. 2005-11-09
|
GNU C Library NEWS -- history of user-visible changes. 2005-11-11
|
||||||
Copyright (C) 1992-2002,2003,2004,2005 Free Software Foundation, Inc.
|
Copyright (C) 1992-2002,2003,2004,2005 Free Software Foundation, Inc.
|
||||||
See the end for copying conditions.
|
See the end for copying conditions.
|
||||||
|
|
||||||
|
@ -27,7 +27,8 @@ Version 2.4
|
||||||
For a libc and libpthread that works well on Linux 2.4 kernels, we
|
For a libc and libpthread that works well on Linux 2.4 kernels, we
|
||||||
recommend using the stable 2.3 branch.
|
recommend using the stable 2.3 branch.
|
||||||
|
|
||||||
* New interfaces: fdopendir, openat.
|
* New interfaces: fdopendir, openat, fstatat, fchownat, futimesat, renameat,
|
||||||
|
unlinkat.
|
||||||
|
|
||||||
Version 2.3.6
|
Version 2.3.6
|
||||||
|
|
||||||
|
|
|
@ -18,4 +18,8 @@ libc_hidden_proto (__open)
|
||||||
extern int __fcntl (int __fd, int __cmd, ...);
|
extern int __fcntl (int __fd, int __cmd, ...);
|
||||||
libc_hidden_proto (__fcntl)
|
libc_hidden_proto (__fcntl)
|
||||||
|
|
||||||
|
/* Helper functions for the various *at functions. For Linux. */
|
||||||
|
extern void __atfct_seterrno (int errval, int fd, const char *buf)
|
||||||
|
attribute_hidden;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
51
io/Makefile
51
io/Makefile
|
@ -26,40 +26,43 @@ headers := sys/stat.h bits/stat.h sys/statfs.h bits/statfs.h sys/vfs.h \
|
||||||
poll.h sys/poll.h bits/poll.h \
|
poll.h sys/poll.h bits/poll.h \
|
||||||
utime.h ftw.h fts.h sys/sendfile.h
|
utime.h ftw.h fts.h sys/sendfile.h
|
||||||
|
|
||||||
routines := \
|
routines := \
|
||||||
utime \
|
utime \
|
||||||
mkfifo \
|
mkfifo \
|
||||||
stat fstat lstat mknod stat64 fstat64 lstat64 \
|
stat fstat lstat mknod stat64 fstat64 lstat64 fstatat fstatat64 \
|
||||||
xstat fxstat lxstat xmknod xstat64 fxstat64 lxstat64 \
|
xstat fxstat lxstat xmknod xstat64 fxstat64 lxstat64 \
|
||||||
statfs fstatfs statfs64 fstatfs64 \
|
fxstatat fxstatat64 \
|
||||||
statvfs fstatvfs statvfs64 fstatvfs64 \
|
statfs fstatfs statfs64 fstatfs64 \
|
||||||
umask chmod fchmod lchmod mkdir \
|
statvfs fstatvfs statvfs64 fstatvfs64 \
|
||||||
open open64 openat openat64 close \
|
umask chmod fchmod lchmod mkdir \
|
||||||
read write lseek lseek64 access euidaccess \
|
open open64 openat openat64 close \
|
||||||
fcntl flock lockf lockf64 \
|
read write lseek lseek64 access euidaccess \
|
||||||
dup dup2 pipe \
|
fcntl flock lockf lockf64 \
|
||||||
creat creat64 \
|
dup dup2 pipe \
|
||||||
chdir fchdir \
|
creat creat64 \
|
||||||
getcwd getwd getdirname \
|
chdir fchdir \
|
||||||
chown fchown lchown \
|
getcwd getwd getdirname \
|
||||||
ttyname ttyname_r isatty \
|
chown fchown lchown fchownat \
|
||||||
link symlink readlink \
|
ttyname ttyname_r isatty \
|
||||||
unlink rmdir \
|
link symlink readlink \
|
||||||
ftw ftw64 fts poll \
|
unlink unlinkat rmdir \
|
||||||
posix_fadvise posix_fadvise64 \
|
ftw ftw64 fts poll \
|
||||||
posix_fallocate posix_fallocate64 \
|
posix_fadvise posix_fadvise64 \
|
||||||
|
posix_fallocate posix_fallocate64 \
|
||||||
sendfile sendfile64
|
sendfile sendfile64
|
||||||
|
|
||||||
# These routines will be omitted from the libc shared object.
|
# These routines will be omitted from the libc shared object.
|
||||||
# Instead the static object files will be included in a special archive
|
# Instead the static object files will be included in a special archive
|
||||||
# linked against when the shared library will be used.
|
# linked against when the shared library will be used.
|
||||||
static-only-routines = stat fstat lstat mknod stat64 fstat64 lstat64
|
static-only-routines = stat fstat lstat mknod stat64 fstat64 lstat64 \
|
||||||
|
fstatat fstatat64
|
||||||
|
|
||||||
others := pwd
|
others := pwd
|
||||||
test-srcs := ftwtest
|
test-srcs := ftwtest
|
||||||
tests := test-utime test-stat test-stat2 test-lfs tst-getcwd \
|
tests := test-utime test-stat test-stat2 test-lfs tst-getcwd \
|
||||||
tst-fcntl bug-ftw1 bug-ftw2 bug-ftw3 bug-ftw4 tst-statvfs \
|
tst-fcntl bug-ftw1 bug-ftw2 bug-ftw3 bug-ftw4 tst-statvfs \
|
||||||
tst-openat
|
tst-openat tst-unlinkat tst-fstatat tst-futimesat \
|
||||||
|
tst-renameat tst-fchownat
|
||||||
|
|
||||||
distribute := ftwtest-sh
|
distribute := ftwtest-sh
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,9 @@ libc {
|
||||||
nftw; nftw64;
|
nftw; nftw64;
|
||||||
}
|
}
|
||||||
GLIBC_2.4 {
|
GLIBC_2.4 {
|
||||||
|
fchownat;
|
||||||
|
__fxstatat; __fxstatat64;
|
||||||
openat; openat64;
|
openat; openat64;
|
||||||
|
unlinkat;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,15 @@ __BEGIN_DECLS
|
||||||
# define SEEK_END 2 /* Seek from end of file. */
|
# define SEEK_END 2 /* Seek from end of file. */
|
||||||
#endif /* XPG */
|
#endif /* XPG */
|
||||||
|
|
||||||
|
#ifdef __USE_GNU
|
||||||
|
# define AT_FDCWD -100 /* Special value used to indicate
|
||||||
|
openat should use the current
|
||||||
|
working directory. */
|
||||||
|
# define AT_SYMLINK_NOFOLLOW 0x100 /* Do not follow symbolic links. */
|
||||||
|
# define AT_REMOVEDIR 0x200 /* Remove directory instead of
|
||||||
|
unlinking file. */
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Do the file control operation described by CMD on FD.
|
/* Do the file control operation described by CMD on FD.
|
||||||
The remaining arguments are interpreted depending on CMD.
|
The remaining arguments are interpreted depending on CMD.
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
/* Copyright (C) 2005 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.
|
||||||
|
|
||||||
|
In addition to the permissions in the GNU Lesser General Public
|
||||||
|
License, the Free Software Foundation gives you unlimited
|
||||||
|
permission to link the compiled version of this file with other
|
||||||
|
programs, and to distribute those programs without any restriction
|
||||||
|
coming from the use of this file. (The GNU Lesser General Public
|
||||||
|
License restrictions do apply in other respects; for example, they
|
||||||
|
cover modification of the file, and distribution when not linked
|
||||||
|
into another program.)
|
||||||
|
|
||||||
|
Note that people who make modified versions of this file are not
|
||||||
|
obligated to grant this special exception for their modified
|
||||||
|
versions; it is their choice whether to do so. The GNU Lesser
|
||||||
|
General Public License gives permission to release a modified
|
||||||
|
version without this exception; this exception also makes it
|
||||||
|
possible to release a modified version which carries forward this
|
||||||
|
exception.
|
||||||
|
|
||||||
|
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, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
/* This definition is only used if inlining fails for this function; see
|
||||||
|
the last page of <sys/stat.h>. The real work is done by the `x'
|
||||||
|
function which is passed a version number argument. We arrange in the
|
||||||
|
makefile that when not inlined this function is always statically
|
||||||
|
linked; that way a dynamically-linked executable always encodes the
|
||||||
|
version number corresponding to the data structures it uses, so the `x'
|
||||||
|
functions in the shared library can adapt without needing to recompile
|
||||||
|
all callers. */
|
||||||
|
|
||||||
|
#undef fstatat
|
||||||
|
int
|
||||||
|
fstatat (int fd, const char *file, struct stat *buf, int flag)
|
||||||
|
{
|
||||||
|
return __fxstatat (_STAT_VER, fd, file, buf, flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide the symbol so that no definition but the one locally in the
|
||||||
|
executable or DSO is used. */
|
||||||
|
#ifdef HAVE_DOT_HIDDEN
|
||||||
|
asm (".hidden\tfstatat");
|
||||||
|
#endif
|
|
@ -0,0 +1,58 @@
|
||||||
|
/* Copyright (C) 2005 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.
|
||||||
|
|
||||||
|
In addition to the permissions in the GNU Lesser General Public
|
||||||
|
License, the Free Software Foundation gives you unlimited
|
||||||
|
permission to link the compiled version of this file with other
|
||||||
|
programs, and to distribute those programs without any restriction
|
||||||
|
coming from the use of this file. (The GNU Lesser General Public
|
||||||
|
License restrictions do apply in other respects; for example, they
|
||||||
|
cover modification of the file, and distribution when not linked
|
||||||
|
into another program.)
|
||||||
|
|
||||||
|
Note that people who make modified versions of this file are not
|
||||||
|
obligated to grant this special exception for their modified
|
||||||
|
versions; it is their choice whether to do so. The GNU Lesser
|
||||||
|
General Public License gives permission to release a modified
|
||||||
|
version without this exception; this exception also makes it
|
||||||
|
possible to release a modified version which carries forward this
|
||||||
|
exception.
|
||||||
|
|
||||||
|
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, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
/* This definition is only used if inlining fails for this function; see
|
||||||
|
the last page of <sys/stat.h>. The real work is done by the `x'
|
||||||
|
function which is passed a version number argument. We arrange in the
|
||||||
|
makefile that when not inlined this function is always statically
|
||||||
|
linked; that way a dynamically-linked executable always encodes the
|
||||||
|
version number corresponding to the data structures it uses, so the `x'
|
||||||
|
functions in the shared library can adapt without needing to recompile
|
||||||
|
all callers. */
|
||||||
|
|
||||||
|
#undef fstatat64
|
||||||
|
int
|
||||||
|
fstatat64 (int fd, const char *file, struct stat64 *buf, int flag)
|
||||||
|
{
|
||||||
|
return __fxstatat64 (_STAT_VER, fd, file, buf, flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide the symbol so that no definition but the one locally in the
|
||||||
|
executable or DSO is used. */
|
||||||
|
#ifdef HAVE_DOT_HIDDEN
|
||||||
|
asm (".hidden\tfstatat64");
|
||||||
|
#endif
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 1991,1992,1995-2002,2003,2004 Free Software Foundation, Inc.
|
/* Copyright (C) 1991,1992,1995-2004,2005 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
@ -228,6 +228,23 @@ extern int stat64 (__const char *__restrict __file,
|
||||||
extern int fstat64 (int __fd, struct stat64 *__buf) __THROW __nonnull ((2));
|
extern int fstat64 (int __fd, struct stat64 *__buf) __THROW __nonnull ((2));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __USE_GNU
|
||||||
|
/* Similar to stat, get the attributes for FILE and put them in BUF.
|
||||||
|
Relative path names are interpreted relative to FD unless FD is
|
||||||
|
AT_FDCWD. */
|
||||||
|
# ifndef __USE_FILE_OFFSET64
|
||||||
|
extern int fstatat (int __fd, const char *__file, struct stat *__buf,
|
||||||
|
int __flag) __THROW __nonnull ((2, 3));
|
||||||
|
# else
|
||||||
|
extern int __REDIRECT_NTH (fstatat, (int __fd, const char *__file,
|
||||||
|
struct stat *__buf, int __flag),
|
||||||
|
fstatat64) __THROW __nonnull ((2, 3));
|
||||||
|
# endif
|
||||||
|
|
||||||
|
extern int fstatat64 (int __fd, const char *__file, struct stat64 *__buf,
|
||||||
|
int __flag) __THROW __nonnull ((2, 3));
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED
|
#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED
|
||||||
# ifndef __USE_FILE_OFFSET64
|
# ifndef __USE_FILE_OFFSET64
|
||||||
/* Get file attributes about FILE and put them in BUF.
|
/* Get file attributes about FILE and put them in BUF.
|
||||||
|
@ -327,6 +344,9 @@ extern int __xstat (int __ver, __const char *__filename,
|
||||||
struct stat *__stat_buf) __THROW __nonnull ((2, 3));
|
struct stat *__stat_buf) __THROW __nonnull ((2, 3));
|
||||||
extern int __lxstat (int __ver, __const char *__filename,
|
extern int __lxstat (int __ver, __const char *__filename,
|
||||||
struct stat *__stat_buf) __THROW __nonnull ((2, 3));
|
struct stat *__stat_buf) __THROW __nonnull ((2, 3));
|
||||||
|
extern int __fxstatat (int __ver, int __fildes, __const char *__filename,
|
||||||
|
struct stat *__stat_buf, int __flag)
|
||||||
|
__THROW __nonnull ((3, 4));
|
||||||
#else
|
#else
|
||||||
# ifdef __REDIRECT_NTH
|
# ifdef __REDIRECT_NTH
|
||||||
extern int __REDIRECT_NTH (__fxstat, (int __ver, int __fildes,
|
extern int __REDIRECT_NTH (__fxstat, (int __ver, int __fildes,
|
||||||
|
@ -338,6 +358,10 @@ extern int __REDIRECT_NTH (__xstat, (int __ver, __const char *__filename,
|
||||||
extern int __REDIRECT_NTH (__lxstat, (int __ver, __const char *__filename,
|
extern int __REDIRECT_NTH (__lxstat, (int __ver, __const char *__filename,
|
||||||
struct stat *__stat_buf), __lxstat64)
|
struct stat *__stat_buf), __lxstat64)
|
||||||
__nonnull ((2, 3));
|
__nonnull ((2, 3));
|
||||||
|
extern int __REDIRECT_NTH (__fxstatat, (int __ver, int __fildes,
|
||||||
|
__const char *__filename,
|
||||||
|
struct stat *__stat_buf, int __flag),
|
||||||
|
__fxstatat64) __nonnull ((3, 4));
|
||||||
|
|
||||||
# else
|
# else
|
||||||
# define __fxstat __fxstat64
|
# define __fxstat __fxstat64
|
||||||
|
@ -353,6 +377,9 @@ extern int __xstat64 (int __ver, __const char *__filename,
|
||||||
struct stat64 *__stat_buf) __THROW __nonnull ((2, 3));
|
struct stat64 *__stat_buf) __THROW __nonnull ((2, 3));
|
||||||
extern int __lxstat64 (int __ver, __const char *__filename,
|
extern int __lxstat64 (int __ver, __const char *__filename,
|
||||||
struct stat64 *__stat_buf) __THROW __nonnull ((2, 3));
|
struct stat64 *__stat_buf) __THROW __nonnull ((2, 3));
|
||||||
|
extern int __fxstatat64 (int __ver, int __fildes, __const char *__filename,
|
||||||
|
struct stat64 *__stat_buf, int __flag)
|
||||||
|
__THROW __nonnull ((3, 4));
|
||||||
#endif
|
#endif
|
||||||
extern int __xmknod (int __ver, __const char *__path, __mode_t __mode,
|
extern int __xmknod (int __ver, __const char *__path, __mode_t __mode,
|
||||||
__dev_t *__dev) __THROW __nonnull ((2, 4));
|
__dev_t *__dev) __THROW __nonnull ((2, 4));
|
||||||
|
@ -380,6 +407,15 @@ __NTH (fstat (int __fd, struct stat *__statbuf))
|
||||||
return __fxstat (_STAT_VER, __fd, __statbuf);
|
return __fxstat (_STAT_VER, __fd, __statbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ifdef __USE_GNU
|
||||||
|
extern __inline__ int
|
||||||
|
__NTH (fstatat (int __fd, __const char *__filename, struct stat *__statbuf,
|
||||||
|
int __flag))
|
||||||
|
{
|
||||||
|
return __fxstatat (_STAT_VER, __fd, __filename, __statbuf, __flag);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
# if defined __USE_MISC || defined __USE_BSD
|
# if defined __USE_MISC || defined __USE_BSD
|
||||||
extern __inline__ int
|
extern __inline__ int
|
||||||
__NTH (mknod (__const char *__path, __mode_t __mode, __dev_t __dev))
|
__NTH (mknod (__const char *__path, __mode_t __mode, __dev_t __dev))
|
||||||
|
@ -412,6 +448,15 @@ __NTH (fstat64 (int __fd, struct stat64 *__statbuf))
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
# ifdef __USE_GNU
|
||||||
|
extern __inline__ int
|
||||||
|
__NTH (fstatat64 (int __fd, __const char *__filename, struct stat64 *__statbuf,
|
||||||
|
int __flag))
|
||||||
|
{
|
||||||
|
return __fxstatat64 (_STAT_VER, __fd, __filename, __statbuf, __flag);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
|
@ -0,0 +1,145 @@
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
static void prepare (void);
|
||||||
|
#define PREPARE(argc, argv) prepare ()
|
||||||
|
|
||||||
|
static int do_test (void);
|
||||||
|
#define TEST_FUNCTION do_test ()
|
||||||
|
|
||||||
|
#include "../test-skeleton.c"
|
||||||
|
|
||||||
|
static int dir_fd;
|
||||||
|
|
||||||
|
static void
|
||||||
|
prepare (void)
|
||||||
|
{
|
||||||
|
#if _POSIX_CHOWN_RESTRICTED > 0
|
||||||
|
uid_t uid = getuid ();
|
||||||
|
if (uid != 0)
|
||||||
|
{
|
||||||
|
puts ("need root privileges");
|
||||||
|
exit (0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
size_t test_dir_len = strlen (test_dir);
|
||||||
|
static const char dir_name[] = "/tst-fchownat.XXXXXX";
|
||||||
|
|
||||||
|
size_t dirbuflen = test_dir_len + sizeof (dir_name);
|
||||||
|
char *dirbuf = malloc (dirbuflen);
|
||||||
|
if (dirbuf == NULL)
|
||||||
|
{
|
||||||
|
puts ("out of memory");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf (dirbuf, dirbuflen, "%s%s", test_dir, dir_name);
|
||||||
|
if (mkdtemp (dirbuf) == NULL)
|
||||||
|
{
|
||||||
|
puts ("cannot create temporary directory");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
add_temp_file (dirbuf);
|
||||||
|
|
||||||
|
dir_fd = open (dirbuf, O_RDONLY | O_DIRECTORY);
|
||||||
|
if (dir_fd == -1)
|
||||||
|
{
|
||||||
|
puts ("cannot open directory");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_test (void)
|
||||||
|
{
|
||||||
|
/* fdopendir takes over the descriptor, make a copy. */
|
||||||
|
int dupfd = dup (dir_fd);
|
||||||
|
if (dupfd == -1)
|
||||||
|
{
|
||||||
|
puts ("dup failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (lseek (dupfd, 0, SEEK_SET) != 0)
|
||||||
|
{
|
||||||
|
puts ("1st lseek failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The directory should be empty safe the . and .. files. */
|
||||||
|
DIR *dir = fdopendir (dupfd);
|
||||||
|
if (dir == NULL)
|
||||||
|
{
|
||||||
|
puts ("fdopendir failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
struct dirent64 *d;
|
||||||
|
while ((d = readdir64 (dir)) != NULL)
|
||||||
|
if (strcmp (d->d_name, ".") != 0 && strcmp (d->d_name, "..") != 0)
|
||||||
|
{
|
||||||
|
printf ("temp directory contains file \"%s\"\n", d->d_name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
closedir (dir);
|
||||||
|
|
||||||
|
/* Try to create a file. */
|
||||||
|
int fd = openat (dir_fd, "some-file", O_CREAT|O_RDWR|O_EXCL, 0666);
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
if (errno == ENOSYS)
|
||||||
|
{
|
||||||
|
puts ("*at functions not supported");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
puts ("file creation failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
write (fd, "hello", 5);
|
||||||
|
puts ("file created");
|
||||||
|
|
||||||
|
struct stat64 st1;
|
||||||
|
if (fstat64 (fd, &st1) != 0)
|
||||||
|
{
|
||||||
|
puts ("fstat64 failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
close (fd);
|
||||||
|
|
||||||
|
if (fchownat (dir_fd, "some-file", st1.st_uid + 1, st1.st_gid + 1, 0) != 0)
|
||||||
|
{
|
||||||
|
puts ("fchownat failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct stat64 st2;
|
||||||
|
if (fstatat64 (dir_fd, "some-file", &st2, 0) != 0)
|
||||||
|
{
|
||||||
|
puts ("fstatat64 failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (st1.st_uid + 1 != st2.st_uid || st1.st_gid + 1 != st2.st_gid)
|
||||||
|
{
|
||||||
|
puts ("owner change failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlinkat (dir_fd, "some-file", 0) != 0)
|
||||||
|
{
|
||||||
|
puts ("unlinkat failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
close (dir_fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,143 @@
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
static void prepare (void);
|
||||||
|
#define PREPARE(argc, argv) prepare ()
|
||||||
|
|
||||||
|
static int do_test (void);
|
||||||
|
#define TEST_FUNCTION do_test ()
|
||||||
|
|
||||||
|
#include "../test-skeleton.c"
|
||||||
|
|
||||||
|
static int dir_fd;
|
||||||
|
|
||||||
|
static void
|
||||||
|
prepare (void)
|
||||||
|
{
|
||||||
|
size_t test_dir_len = strlen (test_dir);
|
||||||
|
static const char dir_name[] = "/tst-fstatat.XXXXXX";
|
||||||
|
|
||||||
|
size_t dirbuflen = test_dir_len + sizeof (dir_name);
|
||||||
|
char *dirbuf = malloc (dirbuflen);
|
||||||
|
if (dirbuf == NULL)
|
||||||
|
{
|
||||||
|
puts ("out of memory");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf (dirbuf, dirbuflen, "%s%s", test_dir, dir_name);
|
||||||
|
if (mkdtemp (dirbuf) == NULL)
|
||||||
|
{
|
||||||
|
puts ("cannot create temporary directory");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
add_temp_file (dirbuf);
|
||||||
|
|
||||||
|
dir_fd = open (dirbuf, O_RDONLY | O_DIRECTORY);
|
||||||
|
if (dir_fd == -1)
|
||||||
|
{
|
||||||
|
puts ("cannot open directory");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_test (void)
|
||||||
|
{
|
||||||
|
/* fdopendir takes over the descriptor, make a copy. */
|
||||||
|
int dupfd = dup (dir_fd);
|
||||||
|
if (dupfd == -1)
|
||||||
|
{
|
||||||
|
puts ("dup failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (lseek (dupfd, 0, SEEK_SET) != 0)
|
||||||
|
{
|
||||||
|
puts ("1st lseek failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The directory should be empty safe the . and .. files. */
|
||||||
|
DIR *dir = fdopendir (dupfd);
|
||||||
|
if (dir == NULL)
|
||||||
|
{
|
||||||
|
puts ("fdopendir failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
struct dirent64 *d;
|
||||||
|
while ((d = readdir64 (dir)) != NULL)
|
||||||
|
if (strcmp (d->d_name, ".") != 0 && strcmp (d->d_name, "..") != 0)
|
||||||
|
{
|
||||||
|
printf ("temp directory contains file \"%s\"\n", d->d_name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
closedir (dir);
|
||||||
|
|
||||||
|
/* Try to create a file. */
|
||||||
|
int fd = openat (dir_fd, "some-file", O_CREAT|O_RDWR|O_EXCL, 0666);
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
if (errno == ENOSYS)
|
||||||
|
{
|
||||||
|
puts ("*at functions not supported");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
puts ("file creation failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
write (fd, "hello", 5);
|
||||||
|
puts ("file created");
|
||||||
|
|
||||||
|
struct stat64 st1;
|
||||||
|
if (fstat64 (fd, &st1) != 0)
|
||||||
|
{
|
||||||
|
puts ("fstat64 failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
close (fd);
|
||||||
|
|
||||||
|
struct stat64 st2;
|
||||||
|
if (fstatat64 (dir_fd, "some-file", &st2, 0) != 0)
|
||||||
|
{
|
||||||
|
puts ("fstatat64 failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (st1.st_dev != st2.st_dev
|
||||||
|
|| st1.st_ino != st2.st_ino
|
||||||
|
|| st1.st_size != st2.st_size)
|
||||||
|
{
|
||||||
|
puts ("stat results do not match");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlinkat (dir_fd, "some-file", 0) != 0)
|
||||||
|
{
|
||||||
|
puts ("unlinkat failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fstatat64 (dir_fd, "some-file", &st2, 0) == 0)
|
||||||
|
{
|
||||||
|
puts ("second fstatat64 succeeded");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (errno != ENOENT)
|
||||||
|
{
|
||||||
|
puts ("second fstatat64 did not fail with ENOENT");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
close (dir_fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,147 @@
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
|
||||||
|
static void prepare (void);
|
||||||
|
#define PREPARE(argc, argv) prepare ()
|
||||||
|
|
||||||
|
static int do_test (void);
|
||||||
|
#define TEST_FUNCTION do_test ()
|
||||||
|
|
||||||
|
#include "../test-skeleton.c"
|
||||||
|
|
||||||
|
static int dir_fd;
|
||||||
|
|
||||||
|
static void
|
||||||
|
prepare (void)
|
||||||
|
{
|
||||||
|
size_t test_dir_len = strlen (test_dir);
|
||||||
|
static const char dir_name[] = "/tst-futimesat.XXXXXX";
|
||||||
|
|
||||||
|
size_t dirbuflen = test_dir_len + sizeof (dir_name);
|
||||||
|
char *dirbuf = malloc (dirbuflen);
|
||||||
|
if (dirbuf == NULL)
|
||||||
|
{
|
||||||
|
puts ("out of memory");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf (dirbuf, dirbuflen, "%s%s", test_dir, dir_name);
|
||||||
|
if (mkdtemp (dirbuf) == NULL)
|
||||||
|
{
|
||||||
|
puts ("cannot create temporary directory");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
add_temp_file (dirbuf);
|
||||||
|
|
||||||
|
dir_fd = open (dirbuf, O_RDONLY | O_DIRECTORY);
|
||||||
|
if (dir_fd == -1)
|
||||||
|
{
|
||||||
|
puts ("cannot open directory");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_test (void)
|
||||||
|
{
|
||||||
|
/* fdopendir takes over the descriptor, make a copy. */
|
||||||
|
int dupfd = dup (dir_fd);
|
||||||
|
if (dupfd == -1)
|
||||||
|
{
|
||||||
|
puts ("dup failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (lseek (dupfd, 0, SEEK_SET) != 0)
|
||||||
|
{
|
||||||
|
puts ("1st lseek failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The directory should be empty safe the . and .. files. */
|
||||||
|
DIR *dir = fdopendir (dupfd);
|
||||||
|
if (dir == NULL)
|
||||||
|
{
|
||||||
|
puts ("fdopendir failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
struct dirent64 *d;
|
||||||
|
while ((d = readdir64 (dir)) != NULL)
|
||||||
|
if (strcmp (d->d_name, ".") != 0 && strcmp (d->d_name, "..") != 0)
|
||||||
|
{
|
||||||
|
printf ("temp directory contains file \"%s\"\n", d->d_name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
closedir (dir);
|
||||||
|
|
||||||
|
/* Try to create a file. */
|
||||||
|
int fd = openat (dir_fd, "some-file", O_CREAT|O_RDWR|O_EXCL, 0666);
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
if (errno == ENOSYS)
|
||||||
|
{
|
||||||
|
puts ("*at functions not supported");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
puts ("file creation failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
write (fd, "hello", 5);
|
||||||
|
puts ("file created");
|
||||||
|
|
||||||
|
struct stat64 st1;
|
||||||
|
if (fstat64 (fd, &st1) != 0)
|
||||||
|
{
|
||||||
|
puts ("fstat64 failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
close (fd);
|
||||||
|
|
||||||
|
struct timeval tv[2];
|
||||||
|
tv[0].tv_sec = st1.st_atime + 1;
|
||||||
|
tv[0].tv_usec = 0;
|
||||||
|
tv[1].tv_sec = st1.st_mtime + 1;
|
||||||
|
tv[1].tv_usec = 0;
|
||||||
|
if (futimesat (dir_fd, "some-file", tv) != 0)
|
||||||
|
{
|
||||||
|
puts ("futimesat failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct stat64 st2;
|
||||||
|
if (fstatat64 (dir_fd, "some-file", &st2, 0) != 0)
|
||||||
|
{
|
||||||
|
puts ("fstatat64 failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (st2.st_mtime != tv[1].tv_sec
|
||||||
|
#ifdef _STATBUF_ST_NSEC
|
||||||
|
|| st2.st_mtim.tv_nsec != 0
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
puts ("stat shows different mtime");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (unlinkat (dir_fd, "some-file", 0) != 0)
|
||||||
|
{
|
||||||
|
puts ("unlinkat failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
close (dir_fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -84,6 +84,12 @@ do_test (void)
|
||||||
int fd = openat (dir_fd, "some-file", O_CREAT|O_RDWR|O_EXCL, 0666);
|
int fd = openat (dir_fd, "some-file", O_CREAT|O_RDWR|O_EXCL, 0666);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
{
|
{
|
||||||
|
if (errno == ENOSYS)
|
||||||
|
{
|
||||||
|
puts ("*at functions not supported");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
puts ("file creation failed");
|
puts ("file creation failed");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,149 @@
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
static void prepare (void);
|
||||||
|
#define PREPARE(argc, argv) prepare ()
|
||||||
|
|
||||||
|
static int do_test (void);
|
||||||
|
#define TEST_FUNCTION do_test ()
|
||||||
|
|
||||||
|
#include "../test-skeleton.c"
|
||||||
|
|
||||||
|
static int dir_fd;
|
||||||
|
|
||||||
|
static void
|
||||||
|
prepare (void)
|
||||||
|
{
|
||||||
|
size_t test_dir_len = strlen (test_dir);
|
||||||
|
static const char dir_name[] = "/tst-renameat.XXXXXX";
|
||||||
|
|
||||||
|
size_t dirbuflen = test_dir_len + sizeof (dir_name);
|
||||||
|
char *dirbuf = malloc (dirbuflen);
|
||||||
|
if (dirbuf == NULL)
|
||||||
|
{
|
||||||
|
puts ("out of memory");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf (dirbuf, dirbuflen, "%s%s", test_dir, dir_name);
|
||||||
|
if (mkdtemp (dirbuf) == NULL)
|
||||||
|
{
|
||||||
|
puts ("cannot create temporary directory");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
add_temp_file (dirbuf);
|
||||||
|
|
||||||
|
dir_fd = open (dirbuf, O_RDONLY | O_DIRECTORY);
|
||||||
|
if (dir_fd == -1)
|
||||||
|
{
|
||||||
|
puts ("cannot open directory");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_test (void)
|
||||||
|
{
|
||||||
|
/* fdopendir takes over the descriptor, make a copy. */
|
||||||
|
int dupfd = dup (dir_fd);
|
||||||
|
if (dupfd == -1)
|
||||||
|
{
|
||||||
|
puts ("dup failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (lseek (dupfd, 0, SEEK_SET) != 0)
|
||||||
|
{
|
||||||
|
puts ("1st lseek failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The directory should be empty safe the . and .. files. */
|
||||||
|
DIR *dir = fdopendir (dupfd);
|
||||||
|
if (dir == NULL)
|
||||||
|
{
|
||||||
|
puts ("fdopendir failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
struct dirent64 *d;
|
||||||
|
while ((d = readdir64 (dir)) != NULL)
|
||||||
|
if (strcmp (d->d_name, ".") != 0 && strcmp (d->d_name, "..") != 0)
|
||||||
|
{
|
||||||
|
printf ("temp directory contains file \"%s\"\n", d->d_name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
closedir (dir);
|
||||||
|
|
||||||
|
/* Try to create a file. */
|
||||||
|
int fd = openat (dir_fd, "some-file", O_CREAT|O_RDWR|O_EXCL, 0666);
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
if (errno == ENOSYS)
|
||||||
|
{
|
||||||
|
puts ("*at functions not supported");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
puts ("file creation failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
write (fd, "hello", 5);
|
||||||
|
puts ("file created");
|
||||||
|
|
||||||
|
struct stat64 st1;
|
||||||
|
if (fstat64 (fd, &st1) != 0)
|
||||||
|
{
|
||||||
|
puts ("fstat64 failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
close (fd);
|
||||||
|
|
||||||
|
if (renameat (dir_fd, "some-file", dir_fd, "another-file") != 0)
|
||||||
|
{
|
||||||
|
puts ("renameat failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct stat64 st2;
|
||||||
|
if (fstatat64 (dir_fd, "some-file", &st2, 0) == 0)
|
||||||
|
{
|
||||||
|
puts ("fstatat64 succeeded");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (errno != ENOENT)
|
||||||
|
{
|
||||||
|
puts ("fstatat64 did not fail with ENOENT");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fstatat64 (dir_fd, "another-file", &st2, 0) != 0)
|
||||||
|
{
|
||||||
|
puts ("2nd fstatat64 failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (st1.st_dev != st2.st_dev
|
||||||
|
|| st1.st_ino != st2.st_ino
|
||||||
|
|| st1.st_size != st2.st_size)
|
||||||
|
{
|
||||||
|
puts ("stat results do not match");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlinkat (dir_fd, "another-file", 0) != 0)
|
||||||
|
{
|
||||||
|
puts ("unlinkat failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
close (dir_fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,178 @@
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
static void prepare (void);
|
||||||
|
#define PREPARE(argc, argv) prepare ()
|
||||||
|
|
||||||
|
static int do_test (void);
|
||||||
|
#define TEST_FUNCTION do_test ()
|
||||||
|
|
||||||
|
#include "../test-skeleton.c"
|
||||||
|
|
||||||
|
static int dir_fd;
|
||||||
|
|
||||||
|
static void
|
||||||
|
prepare (void)
|
||||||
|
{
|
||||||
|
size_t test_dir_len = strlen (test_dir);
|
||||||
|
static const char dir_name[] = "/tst-unlinkat.XXXXXX";
|
||||||
|
|
||||||
|
size_t dirbuflen = test_dir_len + sizeof (dir_name);
|
||||||
|
char *dirbuf = malloc (dirbuflen);
|
||||||
|
if (dirbuf == NULL)
|
||||||
|
{
|
||||||
|
puts ("out of memory");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf (dirbuf, dirbuflen, "%s%s", test_dir, dir_name);
|
||||||
|
if (mkdtemp (dirbuf) == NULL)
|
||||||
|
{
|
||||||
|
puts ("cannot create temporary directory");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
add_temp_file (dirbuf);
|
||||||
|
|
||||||
|
dir_fd = open (dirbuf, O_RDONLY | O_DIRECTORY);
|
||||||
|
if (dir_fd == -1)
|
||||||
|
{
|
||||||
|
puts ("cannot open directory");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_test (void)
|
||||||
|
{
|
||||||
|
/* fdopendir takes over the descriptor, make a copy. */
|
||||||
|
int dupfd = dup (dir_fd);
|
||||||
|
if (dupfd == -1)
|
||||||
|
{
|
||||||
|
puts ("dup failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (lseek (dupfd, 0, SEEK_SET) != 0)
|
||||||
|
{
|
||||||
|
puts ("1st lseek failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The directory should be empty safe the . and .. files. */
|
||||||
|
DIR *dir = fdopendir (dupfd);
|
||||||
|
if (dir == NULL)
|
||||||
|
{
|
||||||
|
puts ("fdopendir failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
struct dirent64 *d;
|
||||||
|
while ((d = readdir64 (dir)) != NULL)
|
||||||
|
if (strcmp (d->d_name, ".") != 0 && strcmp (d->d_name, "..") != 0)
|
||||||
|
{
|
||||||
|
printf ("temp directory contains file \"%s\"\n", d->d_name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
closedir (dir);
|
||||||
|
|
||||||
|
/* Try to create a file. */
|
||||||
|
int fd = openat (dir_fd, "some-file", O_CREAT|O_RDWR|O_EXCL, 0666);
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
if (errno == ENOSYS)
|
||||||
|
{
|
||||||
|
puts ("*at functions not supported");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
puts ("file creation failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
write (fd, "hello", 5);
|
||||||
|
close (fd);
|
||||||
|
puts ("file created");
|
||||||
|
|
||||||
|
/* fdopendir takes over the descriptor, make a copy. */
|
||||||
|
dupfd = dup (dir_fd);
|
||||||
|
if (dupfd == -1)
|
||||||
|
{
|
||||||
|
puts ("2nd dup failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (lseek (dupfd, 0, SEEK_SET) != 0)
|
||||||
|
{
|
||||||
|
puts ("2nd lseek failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The directory should be empty safe the . and .. files. */
|
||||||
|
dir = fdopendir (dupfd);
|
||||||
|
if (dir == NULL)
|
||||||
|
{
|
||||||
|
puts ("2nd fdopendir failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
bool seen_file = false;
|
||||||
|
while ((d = readdir64 (dir)) != NULL)
|
||||||
|
if (strcmp (d->d_name, ".") != 0 && strcmp (d->d_name, "..") != 0)
|
||||||
|
{
|
||||||
|
if (strcmp (d->d_name, "some-file") != 0)
|
||||||
|
{
|
||||||
|
printf ("temp directory contains file \"%s\"\n", d->d_name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
seen_file = true;
|
||||||
|
}
|
||||||
|
closedir (dir);
|
||||||
|
|
||||||
|
if (!seen_file)
|
||||||
|
{
|
||||||
|
puts ("file not created in correct directory");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove the file now. */
|
||||||
|
if (unlinkat (dir_fd, "some-file", 0) != 0)
|
||||||
|
{
|
||||||
|
puts ("unlinkat failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We won't need dir_fd anymore after this, so use it. */
|
||||||
|
if (lseek (dir_fd, 0, SEEK_SET) != 0)
|
||||||
|
{
|
||||||
|
puts ("3rd lseek failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The directory should be empty safe the . and .. files. */
|
||||||
|
dir = fdopendir (dir_fd);
|
||||||
|
if (dir == NULL)
|
||||||
|
{
|
||||||
|
puts ("3rd fdopendir failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
while ((d = readdir64 (dir)) != NULL)
|
||||||
|
if (strcmp (d->d_name, ".") != 0 && strcmp (d->d_name, "..") != 0)
|
||||||
|
{
|
||||||
|
if (strcmp (d->d_name, "some-file") == 0)
|
||||||
|
{
|
||||||
|
puts ("some-file not removed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf ("temp directory contains file \"%s\"\n", d->d_name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir (dir);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -154,6 +154,11 @@ extern int remove (__const char *__filename) __THROW;
|
||||||
extern int rename (__const char *__old, __const char *__new) __THROW;
|
extern int rename (__const char *__old, __const char *__new) __THROW;
|
||||||
__END_NAMESPACE_STD
|
__END_NAMESPACE_STD
|
||||||
|
|
||||||
|
#ifdef __USE_GNU
|
||||||
|
/* Rename file OLD relative to OLDFD to NEW relative to NEWFD. */
|
||||||
|
extern int renameat (int __oldfd, __const char *__old, int __newfd,
|
||||||
|
__const char *__new) __THROW;
|
||||||
|
#endif
|
||||||
|
|
||||||
__BEGIN_NAMESPACE_STD
|
__BEGIN_NAMESPACE_STD
|
||||||
/* Create a temporary file and open it read/write.
|
/* Create a temporary file and open it read/write.
|
||||||
|
|
|
@ -47,7 +47,7 @@ routines := brk sbrk sstk ioctl \
|
||||||
gtty stty \
|
gtty stty \
|
||||||
ptrace \
|
ptrace \
|
||||||
fstab mntent mntent_r \
|
fstab mntent mntent_r \
|
||||||
utimes lutimes futimes \
|
utimes lutimes futimes futimesat \
|
||||||
truncate ftruncate truncate64 ftruncate64 \
|
truncate ftruncate truncate64 ftruncate64 \
|
||||||
chflags fchflags \
|
chflags fchflags \
|
||||||
insremque getttyent getusershell getpass ttyslot \
|
insremque getttyent getusershell getpass ttyslot \
|
||||||
|
|
|
@ -131,6 +131,7 @@ libc {
|
||||||
remap_file_pages;
|
remap_file_pages;
|
||||||
}
|
}
|
||||||
GLIBC_2.4 {
|
GLIBC_2.4 {
|
||||||
|
futimesat;
|
||||||
__syslog_chk; __vsyslog_chk;
|
__syslog_chk; __vsyslog_chk;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -431,6 +431,14 @@ extern int lchown (__const char *__file, __uid_t __owner, __gid_t __group)
|
||||||
|
|
||||||
#endif /* Use BSD || X/Open Unix. */
|
#endif /* Use BSD || X/Open Unix. */
|
||||||
|
|
||||||
|
#ifdef __USE_GNU
|
||||||
|
/* Change the owner and group of FILE relative to the directory FD is open
|
||||||
|
on. */
|
||||||
|
extern int fchownat (int __fd, __const char *__file, __uid_t __owner,
|
||||||
|
__gid_t __group, int __flag)
|
||||||
|
__THROW __nonnull ((2)) __wur;
|
||||||
|
#endif /* Use GNU. */
|
||||||
|
|
||||||
/* Change the process's working directory to PATH. */
|
/* Change the process's working directory to PATH. */
|
||||||
extern int chdir (__const char *__path) __THROW __nonnull ((1)) __wur;
|
extern int chdir (__const char *__path) __THROW __nonnull ((1)) __wur;
|
||||||
|
|
||||||
|
@ -749,6 +757,12 @@ extern int readlink (__const char *__restrict __path, char *__restrict __buf,
|
||||||
/* Remove the link NAME. */
|
/* Remove the link NAME. */
|
||||||
extern int unlink (__const char *__name) __THROW __nonnull ((1));
|
extern int unlink (__const char *__name) __THROW __nonnull ((1));
|
||||||
|
|
||||||
|
#ifdef __USE_GNU
|
||||||
|
/* Remove the link NAME relative to FD. */
|
||||||
|
extern int unlinkat (int __fd, __const char *__name, int __flag)
|
||||||
|
__THROW __nonnull ((2));
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Remove the directory PATH. */
|
/* Remove the directory PATH. */
|
||||||
extern int rmdir (__const char *__path) __THROW __nonnull ((1));
|
extern int rmdir (__const char *__path) __THROW __nonnull ((1));
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ routines := \
|
||||||
perror psignal \
|
perror psignal \
|
||||||
tmpfile tmpfile64 tmpnam tmpnam_r tempnam tempname \
|
tmpfile tmpfile64 tmpnam tmpnam_r tempnam tempname \
|
||||||
getline getw putw \
|
getline getw putw \
|
||||||
remove rename \
|
remove rename renameat \
|
||||||
flockfile ftrylockfile funlockfile
|
flockfile ftrylockfile funlockfile
|
||||||
|
|
||||||
install-others = $(inst_includedir)/bits/stdio_lim.h
|
install-others = $(inst_includedir)/bits/stdio_lim.h
|
||||||
|
|
|
@ -46,6 +46,9 @@ libc {
|
||||||
# t*
|
# t*
|
||||||
tmpfile; tmpfile64;
|
tmpfile; tmpfile64;
|
||||||
}
|
}
|
||||||
|
GLIBC_2.4 {
|
||||||
|
renameat;
|
||||||
|
}
|
||||||
GLIBC_PRIVATE {
|
GLIBC_PRIVATE {
|
||||||
# global variables
|
# global variables
|
||||||
_itoa_lower_digits;
|
_itoa_lower_digits;
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
/* Copyright (C) 2005 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, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
/* Change the owner and group of FILE. */
|
||||||
|
int
|
||||||
|
fchownat (fd, file, owner, group, flag)
|
||||||
|
int fd;
|
||||||
|
const char *file;
|
||||||
|
uid_t owner;
|
||||||
|
gid_t group;
|
||||||
|
int flag;
|
||||||
|
{
|
||||||
|
if (file == NULL || (flag & ~AT_SYMLINK_NOFOLLOW) != 0)
|
||||||
|
{
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fd < 0 && fd != AT_FDCWD)
|
||||||
|
{
|
||||||
|
__set_errno (EBADF);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
__set_errno (ENOSYS);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
stub_warning (fchownat)
|
||||||
|
|
||||||
|
#include <stub-tag.h>
|
|
@ -0,0 +1,52 @@
|
||||||
|
/* Copyright (C) 2005 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, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* Change the access time of FILE relative to FD to TVP[0] and
|
||||||
|
the modification time of FILE to TVP[1]. */
|
||||||
|
int
|
||||||
|
futimesat (fd, file, tvp)
|
||||||
|
int fd;
|
||||||
|
const char *file;
|
||||||
|
const struct timeval tvp[2];
|
||||||
|
{
|
||||||
|
if (fd < 0 && fd != AT_FDCWD)
|
||||||
|
{
|
||||||
|
__set_errno (EBADF);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file == NULL)
|
||||||
|
{
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
__set_errno (ENOSYS);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
weak_alias (__utimes, utimes)
|
||||||
|
|
||||||
|
stub_warning (utimes)
|
||||||
|
#include <stub-tag.h>
|
|
@ -0,0 +1,49 @@
|
||||||
|
/* Copyright (C) 2005 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, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
/* Get information about the file descriptor FD in BUF. */
|
||||||
|
int
|
||||||
|
__fxstatat (int vers, int fd, const char *filename, struct stat *buf, int flag)
|
||||||
|
{
|
||||||
|
if (vers != _STAT_VER)
|
||||||
|
{
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fd < 0 && fd != AT_FDCWD)
|
||||||
|
{
|
||||||
|
__set_errno (EBADF);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (buf == NULL || (flag & ~AT_SYMLINK_NOFOLLOW) != 0)
|
||||||
|
{
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
__set_errno (ENOSYS);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
stub_warning (fstatat)
|
||||||
|
#include <stub-tag.h>
|
|
@ -0,0 +1,50 @@
|
||||||
|
/* Copyright (C) 2005 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, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
/* Get information about the file descriptor FD in BUF. */
|
||||||
|
int
|
||||||
|
__fxstatat64 (int vers, int fd, const char *filename, struct stat64 *buf,
|
||||||
|
int flag)
|
||||||
|
{
|
||||||
|
if (vers != _STAT_VER)
|
||||||
|
{
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fd < 0 && fd != AT_FDCWD)
|
||||||
|
{
|
||||||
|
__set_errno (EBADF);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (buf == NULL || (flag & ~AT_SYMLINK_NOFOLLOW) != 0)
|
||||||
|
{
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
__set_errno (ENOSYS);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
stub_warning (fstatat64)
|
||||||
|
#include <stub-tag.h>
|
|
@ -39,7 +39,7 @@ openat (fd, file, oflag)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file[0] != '/')
|
if (fd != AT_FDCWD && file[0] != '/')
|
||||||
{
|
{
|
||||||
/* Check FD is associated with a directory. */
|
/* Check FD is associated with a directory. */
|
||||||
struct stat64 st;
|
struct stat64 st;
|
||||||
|
|
|
@ -39,7 +39,7 @@ openat64 (fd, file, oflag)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file[0] != '/')
|
if (fd != AT_FDCWD && file[0] != '/')
|
||||||
{
|
{
|
||||||
/* Check FD is associated with a directory. */
|
/* Check FD is associated with a directory. */
|
||||||
struct stat64 st;
|
struct stat64 st;
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
/* Copyright (C) 2005 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, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* Rename the file OLD relative to OLDFD to NEW relative to NEWFD. */
|
||||||
|
int
|
||||||
|
renameat (oldfd, old, newfd, new)
|
||||||
|
int oldfd;
|
||||||
|
const char *old;
|
||||||
|
int newfd;
|
||||||
|
const char *new;
|
||||||
|
{
|
||||||
|
if ((oldfd < 0 & oldfd !_ AT_FDCWD) || (newfd < 0 && newfd != AT_FDCWD))
|
||||||
|
{
|
||||||
|
__set_errno (EBADF);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (old == NULL || new == NULL)
|
||||||
|
{
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
__set_errno (ENOSYS);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
stub_warning (renameat)
|
||||||
|
#include <stub-tag.h>
|
|
@ -0,0 +1,49 @@
|
||||||
|
/* Copyright (C) 2005 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, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* Remove the link named NAME. */
|
||||||
|
int
|
||||||
|
unlinkat (fd, name, flag)
|
||||||
|
int fd;
|
||||||
|
const char *name;
|
||||||
|
int flag;
|
||||||
|
{
|
||||||
|
if (name == NULL || (flag & AT_REMOVEDIR) != 0)
|
||||||
|
{
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fd < 0 && fd != AT_FDCWD)
|
||||||
|
{
|
||||||
|
__set_errno (EBADF);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
__set_errno (ENOSYS);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
stub_warning (unlinkat)
|
||||||
|
|
||||||
|
#include <stub-tag.h>
|
|
@ -0,0 +1,100 @@
|
||||||
|
/* Copyright (C) 2005 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, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#define __fxstatat64 __fxstatat64_disable
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <kernel_stat.h>
|
||||||
|
#include <sysdep.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <xstatconv.h>
|
||||||
|
|
||||||
|
#undef __fxstatat64
|
||||||
|
|
||||||
|
|
||||||
|
/* Get information about the file NAME in BUF. */
|
||||||
|
int
|
||||||
|
__fxstatat (int vers, int fd, const char *file, struct stat *st, int flag)
|
||||||
|
{
|
||||||
|
if (flag & ~AT_SYMLINK_NOFOLLOW)
|
||||||
|
{
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *buf = NULL;
|
||||||
|
|
||||||
|
if (fd != AT_FDCWD && file[0] != '/')
|
||||||
|
{
|
||||||
|
size_t filelen = strlen (file);
|
||||||
|
static const char procfd[] = "/proc/self/fd/%d/%s";
|
||||||
|
/* Buffer for the path name we are going to use. It consists of
|
||||||
|
- the string /proc/self/fd/
|
||||||
|
- the file descriptor number
|
||||||
|
- the file name provided.
|
||||||
|
The final NUL is included in the sizeof. A bit of overhead
|
||||||
|
due to the format elements compensates for possible negative
|
||||||
|
numbers. */
|
||||||
|
size_t buflen = sizeof (procfd) + sizeof (int) * 3 + filelen;
|
||||||
|
buf = alloca (buflen);
|
||||||
|
|
||||||
|
__snprintf (buf, buflen, procfd, fd, file);
|
||||||
|
file = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
INTERNAL_SYSCALL_DECL (err);
|
||||||
|
int result, errno_out;
|
||||||
|
struct kernel_stat kst;
|
||||||
|
|
||||||
|
if (vers == _STAT_VER_KERNEL64 && !__libc_missing_axp_stat64)
|
||||||
|
{
|
||||||
|
if (flags & AT_SYMLINK_NOFOLLOW)
|
||||||
|
result = INTERNAL_SYSCALL (lstat64, err, 2, file, st);
|
||||||
|
else
|
||||||
|
result = INTERNAL_SYSCALL (stat64, err, 2, file, st);
|
||||||
|
|
||||||
|
if (__builtin_expect (!INTERNAL_SYSCALL_ERROR_P (result, err), 1))
|
||||||
|
return result;
|
||||||
|
errno_out = INTERNAL_SYSCALL_ERRNO (result, err);
|
||||||
|
if (errno_out != ENOSYS)
|
||||||
|
goto fail;
|
||||||
|
__libc_missing_axp_stat64 = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag & AT_SYMLINK_NOFOLLOW)
|
||||||
|
result = INTERNAL_SYSCALL (lstat, err, 2, file, &kst);
|
||||||
|
else
|
||||||
|
result = INTERNAL_SYSCALL (stat, err, 2, file, &kst);
|
||||||
|
|
||||||
|
if (__builtin_expect (!INTERNAL_SYSCALL_ERROR_P (result, err), 1))
|
||||||
|
return __xstat_conv (vers, &kst, st);
|
||||||
|
errno_out = INTERNAL_SYSCALL_ERRNO (result, err);
|
||||||
|
|
||||||
|
fail:
|
||||||
|
__atfct_seterrno (errno_out, fd, buf);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
hidden_def (__xstat)
|
||||||
|
weak_alias (__xstat, _xstat);
|
||||||
|
strong_alias (__xstat, __xstat64);
|
||||||
|
hidden_ver (__xstat, __xstat64)
|
|
@ -0,0 +1,73 @@
|
||||||
|
/* Copyright (C) 2005 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, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
/* Change the owner and group of FILE. */
|
||||||
|
int
|
||||||
|
fchownat (fd, file, owner, group, flag)
|
||||||
|
int fd;
|
||||||
|
const char *file;
|
||||||
|
uid_t owner;
|
||||||
|
gid_t group;
|
||||||
|
int flag;
|
||||||
|
{
|
||||||
|
if (flag & ~AT_SYMLINK_NOFOLLOW)
|
||||||
|
{
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *buf = NULL;
|
||||||
|
|
||||||
|
if (fd != AT_FDCWD && file[0] != '/')
|
||||||
|
{
|
||||||
|
size_t filelen = strlen (file);
|
||||||
|
static const char procfd[] = "/proc/self/fd/%d/%s";
|
||||||
|
/* Buffer for the path name we are going to use. It consists of
|
||||||
|
- the string /proc/self/fd/
|
||||||
|
- the file descriptor number
|
||||||
|
- the file name provided.
|
||||||
|
The final NUL is included in the sizeof. A bit of overhead
|
||||||
|
due to the format elements compensates for possible negative
|
||||||
|
numbers. */
|
||||||
|
size_t buflen = sizeof (procfd) + sizeof (int) * 3 + filelen;
|
||||||
|
buf = alloca (buflen);
|
||||||
|
|
||||||
|
__snprintf (buf, buflen, procfd, fd, file);
|
||||||
|
file = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result;
|
||||||
|
INTERNAL_SYSCALL_DECL (err);
|
||||||
|
|
||||||
|
if (flag & AT_SYMLINK_NOFOLLOW)
|
||||||
|
result = INTERNAL_SYSCALL (lchown, err, 3, file, owner, group);
|
||||||
|
else
|
||||||
|
result = INTERNAL_SYSCALL (chown, err, 3, file, owner, group);
|
||||||
|
|
||||||
|
if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0))
|
||||||
|
__atfct_seterrno (INTERNAL_SYSCALL_ERRNO (result, err), fd, buf);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
/* Copyright (C) 2005 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, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <utime.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sysdep.h>
|
||||||
|
#include "kernel-features.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Change the access time of FILE relative to FD to TVP[0] and
|
||||||
|
the modification time of FILE to TVP[1]. */
|
||||||
|
int
|
||||||
|
futimesat (fd, file, tvp)
|
||||||
|
int fd;
|
||||||
|
const char *file;
|
||||||
|
const struct timeval tvp[2];
|
||||||
|
{
|
||||||
|
char *buf = NULL;
|
||||||
|
|
||||||
|
if (fd != AT_FDCWD && file[0] != '/')
|
||||||
|
{
|
||||||
|
size_t filelen = strlen (file);
|
||||||
|
static const char procfd[] = "/proc/self/fd/%d/%s";
|
||||||
|
/* Buffer for the path name we are going to use. It consists of
|
||||||
|
- the string /proc/self/fd/
|
||||||
|
- the file descriptor number
|
||||||
|
- the file name provided.
|
||||||
|
The final NUL is included in the sizeof. A bit of overhead
|
||||||
|
due to the format elements compensates for possible negative
|
||||||
|
numbers. */
|
||||||
|
size_t buflen = sizeof (procfd) + sizeof (int) * 3 + filelen;
|
||||||
|
buf = alloca (buflen);
|
||||||
|
|
||||||
|
__snprintf (buf, buflen, procfd, fd, file);
|
||||||
|
file = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result;
|
||||||
|
INTERNAL_SYSCALL_DECL (err);
|
||||||
|
|
||||||
|
#ifdef __NR_utimes
|
||||||
|
result = INTERNAL_SYSCALL (utimes, err, 2, file, tvp);
|
||||||
|
if (__builtin_expect (!INTERNAL_SYSCALL_ERROR_P (result, err), 1))
|
||||||
|
return result;
|
||||||
|
|
||||||
|
# ifndef __ASSUME_UTIMES
|
||||||
|
if (INTERNAL_SYSCALL_ERRNO (result, err) != ENOSYS)
|
||||||
|
goto fail;
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The utimes() syscall does not exist or is not available in the
|
||||||
|
used kernel. Use utime(). For this we have to convert to the
|
||||||
|
data format utime() expects. */
|
||||||
|
#ifndef __ASSUME_UTIMES
|
||||||
|
struct utimbuf tmp;
|
||||||
|
struct utimbuf *times;
|
||||||
|
|
||||||
|
if (tvp != NULL)
|
||||||
|
{
|
||||||
|
times = &tmp;
|
||||||
|
tmp.actime = tvp[0].tv_sec + tvp[0].tv_usec / 1000000;
|
||||||
|
tmp.modtime = tvp[1].tv_sec + tvp[1].tv_usec / 1000000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
times = NULL;
|
||||||
|
|
||||||
|
result = INTERNAL_SYSCALL (utime, err, 2, file, times);
|
||||||
|
if (__builtin_expect (!INTERNAL_SYSCALL_ERROR_P (result, err), 1))
|
||||||
|
return result;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
__atfct_seterrno (INTERNAL_SYSCALL_ERRNO (result, err), fd, buf);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
/* Copyright (C) 2005 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, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
/* Ho hum, if fxstatat == fxstatat64 we must get rid of the prototype or gcc
|
||||||
|
will complain since they don't strictly match. */
|
||||||
|
#define __fxstatat64 __fxstatat64_disable
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <kernel_stat.h>
|
||||||
|
|
||||||
|
#include <sysdep.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <bp-checks.h>
|
||||||
|
|
||||||
|
#include <xstatconv.h>
|
||||||
|
|
||||||
|
/* Get information about the file NAME in BUF. */
|
||||||
|
int
|
||||||
|
__fxstatat (int vers, int fd, const char *file, struct stat *st, int flag)
|
||||||
|
{
|
||||||
|
if (flag & ~AT_SYMLINK_NOFOLLOW)
|
||||||
|
{
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *buf = NULL;
|
||||||
|
|
||||||
|
if (fd != AT_FDCWD && file[0] != '/')
|
||||||
|
{
|
||||||
|
size_t filelen = strlen (file);
|
||||||
|
static const char procfd[] = "/proc/self/fd/%d/%s";
|
||||||
|
/* Buffer for the path name we are going to use. It consists of
|
||||||
|
- the string /proc/self/fd/
|
||||||
|
- the file descriptor number
|
||||||
|
- the file name provided.
|
||||||
|
The final NUL is included in the sizeof. A bit of overhead
|
||||||
|
due to the format elements compensates for possible negative
|
||||||
|
numbers. */
|
||||||
|
size_t buflen = sizeof (procfd) + sizeof (int) * 3 + filelen;
|
||||||
|
buf = alloca (buflen);
|
||||||
|
|
||||||
|
__snprintf (buf, buflen, procfd, fd, file);
|
||||||
|
file = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result;
|
||||||
|
INTERNAL_SYSCALL_DECL (err);
|
||||||
|
|
||||||
|
if (vers == _STAT_VER_KERNEL)
|
||||||
|
{
|
||||||
|
if (flag & AT_SYMLINK_NOFOLLOW)
|
||||||
|
result = INTERNAL_SYSCALL (lstat, err, 2, CHECK_STRING (file),
|
||||||
|
CHECK_1 ((struct kernel_stat *) st));
|
||||||
|
else
|
||||||
|
result = INTERNAL_SYSCALL (stat, err, 2, CHECK_STRING (file),
|
||||||
|
CHECK_1 ((struct kernel_stat *) st));
|
||||||
|
|
||||||
|
if (__builtin_expect (!INTERNAL_SYSCALL_ERROR_P (result, err), 1))
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef STAT_IS_KERNEL_STAT
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
#else
|
||||||
|
struct kernel_stat kst;
|
||||||
|
|
||||||
|
if (flag & AT_SYMLINK_NOFOLLOW)
|
||||||
|
result = INTERNAL_SYSCALL (lstat, err, 2, CHECK_STRING (file),
|
||||||
|
__ptrvalue (&kst));
|
||||||
|
else
|
||||||
|
result = INTERNAL_SYSCALL (stat, err, 2, CHECK_STRING (file),
|
||||||
|
__ptrvalue (&kst));
|
||||||
|
|
||||||
|
if (__builtin_expect (!INTERNAL_SYSCALL_ERROR_P (result, err), 1))
|
||||||
|
return __xstat_conv (vers, &kst, st);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
__atfct_seterrno (INTERNAL_SYSCALL_ERRNO (result, err), fd, buf);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#ifdef XSTAT_IS_XSTAT64
|
||||||
|
# undef __fxstatat64
|
||||||
|
strong_alias (__fxstatat, __fxstatat64);
|
||||||
|
#endif
|
|
@ -0,0 +1,135 @@
|
||||||
|
/* Copyright (C) 2005 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, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <kernel_stat.h>
|
||||||
|
|
||||||
|
#include <sysdep.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <bp-checks.h>
|
||||||
|
|
||||||
|
#include "kernel-features.h"
|
||||||
|
|
||||||
|
#if __ASSUME_STAT64_SYSCALL == 0
|
||||||
|
# include <xstatconv.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __NR_stat64
|
||||||
|
# if __ASSUME_STAT64_SYSCALL == 0
|
||||||
|
/* The variable is shared between all wrappers around *stat64 calls.
|
||||||
|
This is the definition. */
|
||||||
|
extern int __have_no_stat64;
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Get information about the file NAME in BUF. */
|
||||||
|
|
||||||
|
int
|
||||||
|
__fxstatat64 (int vers, int fd, const char *file, struct stat64 *st, int flag)
|
||||||
|
{
|
||||||
|
if (flag & ~AT_SYMLINK_NOFOLLOW)
|
||||||
|
{
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *buf = NULL;
|
||||||
|
|
||||||
|
if (fd != AT_FDCWD && file[0] != '/')
|
||||||
|
{
|
||||||
|
size_t filelen = strlen (file);
|
||||||
|
static const char procfd[] = "/proc/self/fd/%d/%s";
|
||||||
|
/* Buffer for the path name we are going to use. It consists of
|
||||||
|
- the string /proc/self/fd/
|
||||||
|
- the file descriptor number
|
||||||
|
- the file name provided.
|
||||||
|
The final NUL is included in the sizeof. A bit of overhead
|
||||||
|
due to the format elements compensates for possible negative
|
||||||
|
numbers. */
|
||||||
|
size_t buflen = sizeof (procfd) + sizeof (int) * 3 + filelen;
|
||||||
|
buf = alloca (buflen);
|
||||||
|
|
||||||
|
__snprintf (buf, buflen, procfd, fd, file);
|
||||||
|
file = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result;
|
||||||
|
INTERNAL_SYSCALL_DECL (err);
|
||||||
|
|
||||||
|
#if __ASSUME_STAT64_SYSCALL > 0
|
||||||
|
if (flag & AT_SYMLINK_NOFOLLOW)
|
||||||
|
result = INTERNAL_SYSCALL (lstat64, err, 2, CHECK_STRING (file),
|
||||||
|
CHECK_1 (st));
|
||||||
|
else
|
||||||
|
result = INTERNAL_SYSCALL (stat64, err, 2, CHECK_STRING (file),
|
||||||
|
CHECK_1 (st));
|
||||||
|
if (__builtin_expect (!INTERNAL_SYSCALL_ERROR_P (result, err), 1))
|
||||||
|
{
|
||||||
|
# if defined _HAVE_STAT64___ST_INO && __ASSUME_ST_INO_64_BIT == 0
|
||||||
|
if (st->__st_ino != (__ino_t) st->st_ino)
|
||||||
|
st->st_ino = st->__st_ino;
|
||||||
|
# endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
struct kernel_stat kst;
|
||||||
|
# if defined __NR_stat64
|
||||||
|
if (! __have_no_stat64)
|
||||||
|
{
|
||||||
|
if (flag & AT_SYMLINK_NOFOLLOW)
|
||||||
|
result = INTERNAL_SYSCALL (lstat64, err, 2, CHECK_STRING (file),
|
||||||
|
CHECK_1 (st));
|
||||||
|
else
|
||||||
|
result = INTERNAL_SYSCALL (stat64, err, 2, CHECK_STRING (file),
|
||||||
|
CHECK_1 (st));
|
||||||
|
|
||||||
|
if (__builtin_expect (!INTERNAL_SYSCALL_ERROR_P (result, err), 1))
|
||||||
|
{
|
||||||
|
# if defined _HAVE_STAT64___ST_INO && __ASSUME_ST_INO_64_BIT == 0
|
||||||
|
if (st->__st_ino != (__ino_t) st->st_ino)
|
||||||
|
st->st_ino = st->__st_ino;
|
||||||
|
# endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (INTERNAL_SYSCALL_ERRNO (result, err) != ENOSYS)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
__have_no_stat64 = 1;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
if (flag & AT_SYMLINK_NOFOLLOW)
|
||||||
|
result = INTERNAL_SYSCALL (lstat, err, 2, CHECK_STRING (file),
|
||||||
|
__ptrvalue (&kst));
|
||||||
|
else
|
||||||
|
result = INTERNAL_SYSCALL (stat, err, 2, CHECK_STRING (file),
|
||||||
|
__ptrvalue (&kst));
|
||||||
|
|
||||||
|
if (__builtin_expect (!INTERNAL_SYSCALL_ERROR_P (result, err), 1))
|
||||||
|
return __xstat64_conv (vers, &kst, st);
|
||||||
|
|
||||||
|
fail:
|
||||||
|
__atfct_seterrno (INTERNAL_SYSCALL_ERRNO (result, err), fd, buf);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -0,0 +1,177 @@
|
||||||
|
/* Copyright (C) 2005 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, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <sysdep.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <shlib-compat.h>
|
||||||
|
#include <bp-checks.h>
|
||||||
|
|
||||||
|
#include <linux/posix_types.h>
|
||||||
|
#include "kernel-features.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
In Linux 2.1.x the chown functions have been changed. A new function lchown
|
||||||
|
was introduced. The new chown now follows symlinks - the old chown and the
|
||||||
|
new lchown do not follow symlinks.
|
||||||
|
The new lchown function has the same number as the old chown had and the
|
||||||
|
new chown has a new number. When compiling with headers from Linux > 2.1.8x
|
||||||
|
it's impossible to run this libc with older kernels. In these cases libc
|
||||||
|
has therefore to route calls to chown to the old chown function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int __chown_is_lchown (const char *__file, uid_t __owner,
|
||||||
|
gid_t __group);
|
||||||
|
extern int __real_chown (const char *__file, uid_t __owner, gid_t __group);
|
||||||
|
|
||||||
|
|
||||||
|
#if defined __NR_lchown || __ASSUME_LCHOWN_SYSCALL > 0
|
||||||
|
/* Running under Linux > 2.1.80. */
|
||||||
|
|
||||||
|
# ifdef __NR_chown32
|
||||||
|
# if __ASSUME_32BITUIDS == 0
|
||||||
|
/* This variable is shared with all files that need to check for 32bit
|
||||||
|
uids. */
|
||||||
|
extern int __libc_missing_32bit_uids;
|
||||||
|
# endif
|
||||||
|
# endif /* __NR_chown32 */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
|
||||||
|
{
|
||||||
|
if (flag & ~AT_SYMLINK_NOFOLLOW)
|
||||||
|
{
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *buf = NULL;
|
||||||
|
|
||||||
|
if (fd != AT_FDCWD && file[0] != '/')
|
||||||
|
{
|
||||||
|
size_t filelen = strlen (file);
|
||||||
|
static const char procfd[] = "/proc/self/fd/%d/%s";
|
||||||
|
/* Buffer for the path name we are going to use. It consists of
|
||||||
|
- the string /proc/self/fd/
|
||||||
|
- the file descriptor number
|
||||||
|
- the file name provided.
|
||||||
|
The final NUL is included in the sizeof. A bit of overhead
|
||||||
|
due to the format elements compensates for possible negative
|
||||||
|
numbers. */
|
||||||
|
size_t buflen = sizeof (procfd) + sizeof (int) * 3 + filelen;
|
||||||
|
buf = alloca (buflen);
|
||||||
|
|
||||||
|
__snprintf (buf, buflen, procfd, fd, file);
|
||||||
|
file = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result;
|
||||||
|
INTERNAL_SYSCALL_DECL (err);
|
||||||
|
|
||||||
|
#if defined __NR_lchown || __ASSUME_LCHOWN_SYSCALL > 0
|
||||||
|
# if __ASSUME_LCHOWN_SYSCALL == 0
|
||||||
|
static int __libc_old_chown;
|
||||||
|
|
||||||
|
# ifdef __NR_chown32
|
||||||
|
if (__libc_missing_32bit_uids <= 0)
|
||||||
|
{
|
||||||
|
if (flag & AT_SYMLINK_NOFOLLOW)
|
||||||
|
result = INTERNAL_SYSCALL (lchown32, err, 3, CHECK_STRING (file),
|
||||||
|
owner, group);
|
||||||
|
else
|
||||||
|
result = INTERNAL_SYSCALL (chown32, err, 3, CHECK_STRING (file),
|
||||||
|
owner, group);
|
||||||
|
|
||||||
|
if (!INTERNAL_SYSCALL_ERROR_P (result, err))
|
||||||
|
return result;
|
||||||
|
if (INTERNAL_SYSCALL_ERRNO (result, err) != ENOSYS)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
__libc_missing_32bit_uids = 1;
|
||||||
|
}
|
||||||
|
# endif /* __NR_chown32 */
|
||||||
|
|
||||||
|
if (((owner + 1) > (uid_t) ((__kernel_uid_t) -1U))
|
||||||
|
|| ((group + 1) > (gid_t) ((__kernel_gid_t) -1U)))
|
||||||
|
{
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!__libc_old_chown && (flag & AT_SYMLINK_NOFOLLOW) == 0)
|
||||||
|
{
|
||||||
|
result = INTERNAL_SYSCALL (chown, err, 3, CHECK_STRING (file), owner,
|
||||||
|
group);
|
||||||
|
|
||||||
|
if (!INTERNAL_SYSCALL_ERROR_P (result, err))
|
||||||
|
return result;
|
||||||
|
if (INTERNAL_SYSCALL_ERRNO (result, err) != ENOSYS)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
__libc_old_chown = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = INTERNAL_SYSCALL (lchown, err, 3, CHECK_STRING (file), owner,
|
||||||
|
group);
|
||||||
|
# elif __ASSUME_32BITUIDS
|
||||||
|
/* This implies __ASSUME_LCHOWN_SYSCALL. */
|
||||||
|
result = INTERNAL_SYSCALL (chown32, err, 3, CHECK_STRING (file), owner,
|
||||||
|
group);
|
||||||
|
# else
|
||||||
|
/* !__ASSUME_32BITUIDS && ASSUME_LCHOWN_SYSCALL */
|
||||||
|
# ifdef __NR_chown32
|
||||||
|
if (__libc_missing_32bit_uids <= 0)
|
||||||
|
{
|
||||||
|
result = INTERNAL_SYSCALL (chown32, err, 3, CHECK_STRING (file), owner,
|
||||||
|
group);
|
||||||
|
if (__builtin_expect (!INTERNAL_SYSCALL_ERROR_P (result, err), 1))
|
||||||
|
return result;
|
||||||
|
if (INTERNAL_SYSCALL_ERRNO (result, err) != ENOSYS)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
__libc_missing_32bit_uids = 1;
|
||||||
|
}
|
||||||
|
# endif /* __NR_chown32 */
|
||||||
|
if (((owner + 1) > (uid_t) ((__kernel_uid_t) -1U))
|
||||||
|
|| ((group + 1) > (gid_t) ((__kernel_gid_t) -1U)))
|
||||||
|
{
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = INTERNAL_SYSCALL (chown, err, 3, CHECK_STRING (file), owner, group);
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
result = INTERNAL_SYSCALL (chown, err, 3, CHECK_STRING (file), owner, group);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0))
|
||||||
|
{
|
||||||
|
fail:
|
||||||
|
__atfct_seterrno (INTERNAL_SYSCALL_ERRNO (result, err), fd, buf);
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,148 @@
|
||||||
|
/* Copyright (C) 2005 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, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
/* Ho hum, if fxstatat == fxstatat64 we must get rid of the prototype or gcc
|
||||||
|
will complain since they don't strictly match. */
|
||||||
|
#define __fxstatat64 __fxstatat64_disable
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <kernel_stat.h>
|
||||||
|
|
||||||
|
#include <sysdep.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <bp-checks.h>
|
||||||
|
|
||||||
|
#include "kernel-features.h"
|
||||||
|
|
||||||
|
#include <xstatconv.h>
|
||||||
|
|
||||||
|
#ifdef __NR_stat64
|
||||||
|
# if __ASSUME_STAT64_SYSCALL == 0
|
||||||
|
/* The variable is shared between all wrappers around *stat64 calls. */
|
||||||
|
extern int __have_no_stat64;
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Get information about the file NAME relative to FD in ST. */
|
||||||
|
int
|
||||||
|
__fxstatat (int vers, int fd, const char *file, struct stat *st, int flag)
|
||||||
|
{
|
||||||
|
if (flag & ~AT_SYMLINK_NOFOLLOW)
|
||||||
|
{
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *buf = NULL;
|
||||||
|
|
||||||
|
if (fd != AT_FDCWD && file[0] != '/')
|
||||||
|
{
|
||||||
|
size_t filelen = strlen (file);
|
||||||
|
static const char procfd[] = "/proc/self/fd/%d/%s";
|
||||||
|
/* Buffer for the path name we are going to use. It consists of
|
||||||
|
- the string /proc/self/fd/
|
||||||
|
- the file descriptor number
|
||||||
|
- the file name provided.
|
||||||
|
The final NUL is included in the sizeof. A bit of overhead
|
||||||
|
due to the format elements compensates for possible negative
|
||||||
|
numbers. */
|
||||||
|
size_t buflen = sizeof (procfd) + sizeof (int) * 3 + filelen;
|
||||||
|
buf = alloca (buflen);
|
||||||
|
|
||||||
|
__snprintf (buf, buflen, procfd, fd, file);
|
||||||
|
file = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if __ASSUME_STAT64_SYSCALL == 0
|
||||||
|
struct kernel_stat kst;
|
||||||
|
#endif
|
||||||
|
int result;
|
||||||
|
INTERNAL_SYSCALL_DECL (err);
|
||||||
|
|
||||||
|
if (vers == _STAT_VER_KERNEL)
|
||||||
|
{
|
||||||
|
if (flag & AT_SYMLINK_NOFOLLOW)
|
||||||
|
result = INTERNAL_SYSCALL (lstat, err, 2, CHECK_STRING (file),
|
||||||
|
CHECK_1 ((struct kernel_stat *) st));
|
||||||
|
else
|
||||||
|
result = INTERNAL_SYSCALL (stat, err, 2, CHECK_STRING (file),
|
||||||
|
CHECK_1 ((struct kernel_stat *) st));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if __ASSUME_STAT64_SYSCALL > 0
|
||||||
|
struct stat64 st64;
|
||||||
|
|
||||||
|
if (flag & AT_SYMLINK_NOFOLLOW)
|
||||||
|
result = INTERNAL_SYSCALL (lstat64, err, 2, CHECK_STRING (file),
|
||||||
|
__ptrvalue (&st64));
|
||||||
|
else
|
||||||
|
result = INTERNAL_SYSCALL (stat64, err, 2, CHECK_STRING (file),
|
||||||
|
__ptrvalue (&st64));
|
||||||
|
if (__builtin_expect (!INTERNAL_SYSCALL_ERROR_P (result, err), 1))
|
||||||
|
return __xstat32_conv (vers, &st64, st);
|
||||||
|
#else
|
||||||
|
# if defined __NR_stat64
|
||||||
|
/* To support 32 bit UIDs, we have to use stat64. The normal stat
|
||||||
|
call only returns 16 bit UIDs. */
|
||||||
|
if (! __have_no_stat64)
|
||||||
|
{
|
||||||
|
struct stat64 st64;
|
||||||
|
|
||||||
|
if (flag & AT_SYMLINK_NOFOLLOW)
|
||||||
|
result = INTERNAL_SYSCALL (lstat64, err, 2, CHECK_STRING (file),
|
||||||
|
__ptrvalue (&st64));
|
||||||
|
else
|
||||||
|
result = INTERNAL_SYSCALL (stat64, err, 2, CHECK_STRING (file),
|
||||||
|
__ptrvalue (&st64));
|
||||||
|
|
||||||
|
if (__builtin_expect (!INTERNAL_SYSCALL_ERROR_P (result, err), 1))
|
||||||
|
result = __xstat32_conv (vers, &st64, st);
|
||||||
|
|
||||||
|
if (__builtin_expect (!INTERNAL_SYSCALL_ERROR_P (result, err), 1)
|
||||||
|
|| INTERNAL_SYSCALL_ERRNO (result, err) != ENOSYS)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
__have_no_stat64 = 1;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
if (flag & AT_SYMLINK_NOFOLLOW)
|
||||||
|
result = INTERNAL_SYSCALL (lstat, err, 2, CHECK_STRING (file),
|
||||||
|
__ptrvalue (&kst));
|
||||||
|
else
|
||||||
|
result = INTERNAL_SYSCALL (stat, err, 2, CHECK_STRING (file),
|
||||||
|
__ptrvalue (&kst));
|
||||||
|
if (__builtin_expect (!INTERNAL_SYSCALL_ERROR_P (result, err), 1))
|
||||||
|
return __xstat_conv (vers, &kst, st);
|
||||||
|
#endif /* __ASSUME_STAT64_SYSCALL */
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0))
|
||||||
|
__atfct_seterrno (INTERNAL_SYSCALL_ERRNO (result, err), fd, buf);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#ifdef XSTAT_IS_XSTAT64
|
||||||
|
# undef __fxstatat64
|
||||||
|
strong_alias (__fxstatat, __fxstatat64);
|
||||||
|
#endif
|
|
@ -0,0 +1,121 @@
|
||||||
|
/* Copyright (C) 2005 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, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <sysdep.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <bp-checks.h>
|
||||||
|
|
||||||
|
#include <linux/posix_types.h>
|
||||||
|
#include "kernel-features.h"
|
||||||
|
|
||||||
|
#ifdef __NR_chown32
|
||||||
|
# if __ASSUME_32BITUIDS == 0
|
||||||
|
/* This variable is shared with all files that need to check for 32bit
|
||||||
|
uids. */
|
||||||
|
extern int __libc_missing_32bit_uids;
|
||||||
|
# endif
|
||||||
|
#endif /* __NR_chown32 */
|
||||||
|
|
||||||
|
int
|
||||||
|
fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
|
||||||
|
{
|
||||||
|
if (flag & ~AT_SYMLINK_NOFOLLOW)
|
||||||
|
{
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *buf = NULL;
|
||||||
|
|
||||||
|
if (fd != AT_FDCWD && file[0] != '/')
|
||||||
|
{
|
||||||
|
size_t filelen = strlen (file);
|
||||||
|
static const char procfd[] = "/proc/self/fd/%d/%s";
|
||||||
|
/* Buffer for the path name we are going to use. It consists of
|
||||||
|
- the string /proc/self/fd/
|
||||||
|
- the file descriptor number
|
||||||
|
- the file name provided.
|
||||||
|
The final NUL is included in the sizeof. A bit of overhead
|
||||||
|
due to the format elements compensates for possible negative
|
||||||
|
numbers. */
|
||||||
|
size_t buflen = sizeof (procfd) + sizeof (int) * 3 + filelen;
|
||||||
|
buf = alloca (buflen);
|
||||||
|
|
||||||
|
__snprintf (buf, buflen, procfd, fd, file);
|
||||||
|
file = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result;
|
||||||
|
INTERNAL_SYSCALL_DECL (err);
|
||||||
|
|
||||||
|
#if __ASSUME_32BITUIDS > 0
|
||||||
|
if (flag & AT_SYMLINK_NOFOLLOW)
|
||||||
|
result = INTERNAL_SYSCALL (lchown32, err, 3, CHECK_STRING (file), owner,
|
||||||
|
group);
|
||||||
|
else
|
||||||
|
result = INTERNAL_SYSCALL (chown32, err, 3, CHECK_STRING (file), owner,
|
||||||
|
group);
|
||||||
|
#else
|
||||||
|
# ifdef __NR_chown32
|
||||||
|
if (__libc_missing_32bit_uids <= 0)
|
||||||
|
{
|
||||||
|
if (flag & AT_SYMLINK_NOFOLLOW)
|
||||||
|
result = INTERNAL_SYSCALL (lchown32, err, 3, CHECK_STRING (file),
|
||||||
|
owner, group);
|
||||||
|
else
|
||||||
|
result = INTERNAL_SYSCALL (chown32, err, 3, CHECK_STRING (file), owner,
|
||||||
|
group);
|
||||||
|
|
||||||
|
if (__builtin_expect (!INTERNAL_SYSCALL_ERROR_P (result, err), 1))
|
||||||
|
return result;
|
||||||
|
if (INTERNAL_SYSCALL_ERRNO (result, err) != ENOSYS)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
__libc_missing_32bit_uids = 1;
|
||||||
|
}
|
||||||
|
# endif /* __NR_chown32 */
|
||||||
|
|
||||||
|
if (((owner + 1) > (gid_t) ((__kernel_uid_t) -1U))
|
||||||
|
|| ((group + 1) > (gid_t) ((__kernel_gid_t) -1U)))
|
||||||
|
{
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag & AT_SYMLINK_NOFOLLOW)
|
||||||
|
result = INTERNAL_SYSCALL (lchown, err, 3, CHECK_STRING (file), owner,
|
||||||
|
group);
|
||||||
|
else
|
||||||
|
result = INTERNAL_SYSCALL (chown, err, 3, CHECK_STRING (file), owner,
|
||||||
|
group);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0))
|
||||||
|
{
|
||||||
|
fail:
|
||||||
|
__atfct_seterrno (INTERNAL_SYSCALL_ERRNO (result, err), fd, buf);
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
#include <sysdeps/unix/sysv/linux/i386/fxstatat.c>
|
|
@ -29,6 +29,30 @@
|
||||||
#ifndef OPENAT
|
#ifndef OPENAT
|
||||||
# define OPENAT openat
|
# define OPENAT openat
|
||||||
# define MORE_OFLAGS 0
|
# define MORE_OFLAGS 0
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
attribute_hidden
|
||||||
|
__atfct_seterrno (int errval, int fd, const char *buf)
|
||||||
|
{
|
||||||
|
if (buf != NULL && errval == ENOTDIR)
|
||||||
|
{
|
||||||
|
/* This can mean either the file descriptor is invalid or
|
||||||
|
/proc is not mounted. */
|
||||||
|
struct stat64 st;
|
||||||
|
if (__fxstat64 (_STAT_VER, fd, &st) != 0)
|
||||||
|
/* errno is already set correctly. */
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* If /proc is not mounted there is nothing we can do. */
|
||||||
|
if (S_ISDIR (st.st_mode)
|
||||||
|
&& (__xstat64 (_STAT_VER, "/proc/self/fd", &st) != 0
|
||||||
|
|| !S_ISDIR (st.st_mode)))
|
||||||
|
errval = ENOSYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
__set_errno (errval);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Open FILE with access OFLAG. Interpret relative paths relative to
|
/* Open FILE with access OFLAG. Interpret relative paths relative to
|
||||||
|
@ -42,7 +66,7 @@ OPENAT (fd, file, oflag)
|
||||||
{
|
{
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
|
|
||||||
if (file[0] != '/')
|
if (fd != AT_FDCWD && file[0] != '/')
|
||||||
{
|
{
|
||||||
size_t filelen = strlen (file);
|
size_t filelen = strlen (file);
|
||||||
static const char procfd[] = "/proc/self/fd/%d/%s";
|
static const char procfd[] = "/proc/self/fd/%d/%s";
|
||||||
|
@ -85,26 +109,9 @@ OPENAT (fd, file, oflag)
|
||||||
|
|
||||||
if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0))
|
if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0))
|
||||||
{
|
{
|
||||||
int errval = INTERNAL_SYSCALL_ERRNO (res, err);
|
__atfct_seterrno (INTERNAL_SYSCALL_ERRNO (res, err), fd, buf);
|
||||||
if (buf != NULL && errval == ENOTDIR)
|
res = -1;
|
||||||
{
|
|
||||||
/* This can mean either the file desriptor is invalid or
|
|
||||||
/proc is not mounted. */
|
|
||||||
struct stat64 st;
|
|
||||||
if (__fxstat64 (_STAT_VER, fd, &st) != 0)
|
|
||||||
/* errno is already set correctly. */
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
/* If /proc is not mounted there is nothing we can do. */
|
|
||||||
if (S_ISDIR (st.st_mode)
|
|
||||||
&& (__xstat64 (_STAT_VER, "/proc/self/fd", &st) != 0
|
|
||||||
|| !S_ISDIR (st.st_mode)))
|
|
||||||
errval = ENOSYS;
|
|
||||||
}
|
|
||||||
|
|
||||||
__set_errno (errval);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* chown() compatibility.
|
/* chown() compatibility.
|
||||||
Copyright (C) 1998, 2000, 2002, 2003 Free Software Foundation, Inc.
|
Copyright (C) 1998, 2000, 2002, 2003, 2005 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
@ -24,6 +24,8 @@
|
||||||
#include <sysdep.h>
|
#include <sysdep.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <kernel-features.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
In Linux 2.1.x the chown functions have been changed. A new function lchown
|
In Linux 2.1.x the chown functions have been changed. A new function lchown
|
||||||
was introduced. The new chown now follows symlinks - the old chown and the
|
was introduced. The new chown now follows symlinks - the old chown and the
|
||||||
|
@ -34,58 +36,61 @@
|
||||||
int
|
int
|
||||||
__chown (const char *file, uid_t owner, gid_t group)
|
__chown (const char *file, uid_t owner, gid_t group)
|
||||||
{
|
{
|
||||||
int err;
|
#if __ASSUME_LCHOWN_SYSCALL
|
||||||
int old_errno;
|
return INLINE_SYSCALL (chown, 3, file, owner, group);
|
||||||
char link[PATH_MAX+2];
|
#else
|
||||||
char path[2*PATH_MAX+4];
|
int err;
|
||||||
int loopct;
|
int old_errno;
|
||||||
size_t filelen;
|
char link[PATH_MAX + 2];
|
||||||
static int libc_old_chown = 0 /* -1=old linux, 1=new linux, 0=unknown */;
|
char path[2 * PATH_MAX + 4];
|
||||||
|
int loopct;
|
||||||
|
size_t filelen;
|
||||||
|
static int libc_old_chown = 0 /* -1=old linux, 1=new linux, 0=unknown */;
|
||||||
|
|
||||||
if (libc_old_chown == 1)
|
if (libc_old_chown == 1)
|
||||||
return INLINE_SYSCALL (chown, 3, __ptrvalue (file), owner, group);
|
return INLINE_SYSCALL (chown, 3, __ptrvalue (file), owner, group);
|
||||||
|
|
||||||
old_errno = errno;
|
old_errno = errno;
|
||||||
|
|
||||||
#ifdef __NR_lchown
|
# ifdef __NR_lchown
|
||||||
if (libc_old_chown == 0)
|
if (libc_old_chown == 0)
|
||||||
{
|
{
|
||||||
err = INLINE_SYSCALL (chown, 3, __ptrvalue (file), owner, group);
|
err = INLINE_SYSCALL (chown, 3, __ptrvalue (file), owner, group);
|
||||||
if (err != -1 || errno != ENOSYS)
|
if (err != -1 || errno != ENOSYS)
|
||||||
{
|
{
|
||||||
libc_old_chown = 1;
|
libc_old_chown = 1;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
libc_old_chown = -1;
|
libc_old_chown = -1;
|
||||||
}
|
}
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
err = __readlink (file, link, PATH_MAX+1);
|
err = __readlink (file, link, PATH_MAX + 1);
|
||||||
if (err == -1)
|
if (err == -1)
|
||||||
{
|
{
|
||||||
errno = old_errno;
|
__set_errno (old_errno);
|
||||||
return __lchown(file, owner, group);
|
return __lchown (file, owner, group);
|
||||||
}
|
}
|
||||||
|
|
||||||
filelen = strlen (file) + 1;
|
filelen = strlen (file) + 1;
|
||||||
if (filelen > sizeof(path))
|
if (filelen > sizeof (path))
|
||||||
{
|
{
|
||||||
errno = ENAMETOOLONG;
|
__set_errno (ENAMETOOLONG);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy (path, file, filelen);
|
memcpy (path, file, filelen);
|
||||||
|
|
||||||
/* 'The system has an arbitrary limit...' In practise, we'll hit
|
/* 'The system has an arbitrary limit...' In practise, we'll hit
|
||||||
ENAMETOOLONG before this, usually. */
|
ENAMETOOLONG before this, usually. */
|
||||||
for (loopct = 0; loopct < 128; loopct++)
|
for (loopct = 0; loopct < 128; ++loopct)
|
||||||
{
|
{
|
||||||
size_t linklen;
|
size_t linklen;
|
||||||
|
|
||||||
if (err >= PATH_MAX+1)
|
if (err >= PATH_MAX + 1)
|
||||||
{
|
{
|
||||||
errno = ENAMETOOLONG;
|
__set_errno (ENAMETOOLONG);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
link[err] = 0; /* Null-terminate string, just-in-case. */
|
link[err] = 0; /* Null-terminate string, just-in-case. */
|
||||||
|
|
||||||
|
@ -97,28 +102,29 @@ __chown (const char *file, uid_t owner, gid_t group)
|
||||||
{
|
{
|
||||||
filelen = strlen (path);
|
filelen = strlen (path);
|
||||||
|
|
||||||
while (filelen > 1 && path[filelen-1] == '/')
|
while (filelen > 1 && path[filelen - 1] == '/')
|
||||||
filelen--;
|
--filelen;
|
||||||
while (filelen > 0 && path[filelen-1] != '/')
|
while (filelen > 0 && path[filelen - 1] != '/')
|
||||||
filelen--;
|
--filelen;
|
||||||
if (filelen + linklen > sizeof(path))
|
if (filelen + linklen > sizeof (path))
|
||||||
{
|
{
|
||||||
errno = ENAMETOOLONG;
|
errno = ENAMETOOLONG;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy (path+filelen, link, linklen);
|
memcpy (path + filelen, link, linklen);
|
||||||
}
|
}
|
||||||
|
|
||||||
err = __readlink(path, link, PATH_MAX+1);
|
err = __readlink (path, link, PATH_MAX + 1);
|
||||||
|
|
||||||
if (err == -1)
|
if (err == -1)
|
||||||
{
|
{
|
||||||
errno = old_errno;
|
__set_errno (old_errno);
|
||||||
return __lchown(path, owner, group);
|
return __lchown (path, owner, group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
errno = ELOOP;
|
__set_errno (ELOOP);
|
||||||
return -1;
|
return -1;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
libc_hidden_def (__chown)
|
libc_hidden_def (__chown)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,205 @@
|
||||||
|
/* Copyright (C) 2005 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, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <sysdep.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <kernel-features.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
In Linux 2.1.x the chown functions have been changed. A new function lchown
|
||||||
|
was introduced. The new chown now follows symlinks - the old chown and the
|
||||||
|
new lchown do not follow symlinks.
|
||||||
|
This file emulates chown() under the old kernels.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
|
||||||
|
{
|
||||||
|
if (flag & ~AT_SYMLINK_NOFOLLOW)
|
||||||
|
{
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *buf = NULL;
|
||||||
|
|
||||||
|
if (fd != AT_FDCWD && file[0] != '/')
|
||||||
|
{
|
||||||
|
size_t filelen = strlen (file);
|
||||||
|
static const char procfd[] = "/proc/self/fd/%d/%s";
|
||||||
|
/* Buffer for the path name we are going to use. It consists of
|
||||||
|
- the string /proc/self/fd/
|
||||||
|
- the file descriptor number
|
||||||
|
- the file name provided.
|
||||||
|
The final NUL is included in the sizeof. A bit of overhead
|
||||||
|
due to the format elements compensates for possible negative
|
||||||
|
numbers. */
|
||||||
|
size_t buflen = sizeof (procfd) + sizeof (int) * 3 + filelen;
|
||||||
|
buf = alloca (buflen);
|
||||||
|
|
||||||
|
__snprintf (buf, buflen, procfd, fd, file);
|
||||||
|
file = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result;
|
||||||
|
INTERNAL_SYSCALL_DECL (err);
|
||||||
|
|
||||||
|
#if __ASSUME_LCHOWN_SYSCALL
|
||||||
|
if (flag & AT_SYMLINK_NOFOLLOW)
|
||||||
|
result = INTERNAL_SYSCALL (lchown, err, 3, file, owner, group);
|
||||||
|
else
|
||||||
|
result = INTERNAL_SYSCALL (chown, err, 3, file, owner, group);
|
||||||
|
#else
|
||||||
|
char link[PATH_MAX + 2];
|
||||||
|
char path[2 * PATH_MAX + 4];
|
||||||
|
int loopct;
|
||||||
|
size_t filelen;
|
||||||
|
static int libc_old_chown = 0 /* -1=old linux, 1=new linux, 0=unknown */;
|
||||||
|
|
||||||
|
if (libc_old_chown == 1)
|
||||||
|
{
|
||||||
|
if (flag & AT_SYMLINK_NOFOLLOW)
|
||||||
|
result = INTERNAL_SYSCALL (lchown, err, 3, __ptrvalue (file), owner,
|
||||||
|
group);
|
||||||
|
else
|
||||||
|
result = INTERNAL_SYSCALL (chown, err, 3, __ptrvalue (file), owner,
|
||||||
|
group);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
# ifdef __NR_lchown
|
||||||
|
if (flag & AT_SYMLINK_NOFOLLOW)
|
||||||
|
{
|
||||||
|
result = INTERNAL_SYSCALL (lchown, err, 3, __ptrvalue (file), owner,
|
||||||
|
group);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (libc_old_chown == 0)
|
||||||
|
{
|
||||||
|
result = INTERNAL_SYSCALL (chown, err, 3, __ptrvalue (file), owner,
|
||||||
|
group);
|
||||||
|
if (__builtin_expect (!INTERNAL_SYSCALL_ERROR_P (result, err), 1))
|
||||||
|
return result;
|
||||||
|
if (INTERNAL_SYSCALL_ERRNO (result, err) != ENOSYS)
|
||||||
|
{
|
||||||
|
libc_old_chown = 1;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
libc_old_chown = -1;
|
||||||
|
}
|
||||||
|
# else
|
||||||
|
if (flag & AT_SYMLINK_NOFOLLOW)
|
||||||
|
{
|
||||||
|
result = INTERNAL_SYSCALL (chown, err, 3, __ptrvalue (file), owner,
|
||||||
|
group);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
result = __readlink (file, link, PATH_MAX + 1);
|
||||||
|
if (result == -1)
|
||||||
|
{
|
||||||
|
# ifdef __NR_lchown
|
||||||
|
result = INTERNAL_SYSCALL (lchown, err, 3, __ptrvalue (file), owner,
|
||||||
|
group);
|
||||||
|
# else
|
||||||
|
result = INTERNAL_SYSCALL (chown, err, 3, __ptrvalue (file), owner,
|
||||||
|
group);
|
||||||
|
# endif
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
filelen = strlen (file) + 1;
|
||||||
|
if (filelen > sizeof (path))
|
||||||
|
{
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy (path, file, filelen);
|
||||||
|
|
||||||
|
/* 'The system has an arbitrary limit...' In practise, we'll hit
|
||||||
|
ENAMETOOLONG before this, usually. */
|
||||||
|
for (loopct = 0; loopct < 128; ++loopct)
|
||||||
|
{
|
||||||
|
size_t linklen;
|
||||||
|
|
||||||
|
if (result >= PATH_MAX + 1)
|
||||||
|
{
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
link[result] = 0; /* Null-terminate string, just-in-case. */
|
||||||
|
|
||||||
|
linklen = strlen (link) + 1;
|
||||||
|
|
||||||
|
if (link[0] == '/')
|
||||||
|
memcpy (path, link, linklen);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
filelen = strlen (path);
|
||||||
|
|
||||||
|
while (filelen > 1 && path[filelen - 1] == '/')
|
||||||
|
--filelen;
|
||||||
|
while (filelen > 0 && path[filelen - 1] != '/')
|
||||||
|
--filelen;
|
||||||
|
if (filelen + linklen > sizeof (path))
|
||||||
|
{
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy (path + filelen, link, linklen);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = __readlink (path, link, PATH_MAX + 1);
|
||||||
|
|
||||||
|
if (result == -1)
|
||||||
|
{
|
||||||
|
# ifdef __NR_lchown
|
||||||
|
result = INTERNAL_SYSCALL (lchown, err, 3, path, owner, group);
|
||||||
|
# else
|
||||||
|
result = INTERNAL_SYSCALL (chown, err, 3, path, owner, group);
|
||||||
|
# endif
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
__set_errno (ELOOP);
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
out:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0))
|
||||||
|
{
|
||||||
|
#if !__ASSUME_LCHOWN_SYSCALL
|
||||||
|
fail:
|
||||||
|
#endif
|
||||||
|
__atfct_seterrno (INTERNAL_SYSCALL_ERRNO (result, err), fd, buf);
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
#include <sysdeps/unix/sysv/linux/i386/fxstatat.c>
|
|
@ -0,0 +1,121 @@
|
||||||
|
/* Copyright (C) 2005 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, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sysdep.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* Rename the file OLD relative to OLDFD to NEW relative to NEWFD. */
|
||||||
|
int
|
||||||
|
renameat (oldfd, old, newfd, new)
|
||||||
|
int oldfd;
|
||||||
|
const char *old;
|
||||||
|
int newfd;
|
||||||
|
const char *new;
|
||||||
|
{
|
||||||
|
static const char procfd[] = "/proc/self/fd/%d/%s";
|
||||||
|
char *bufold = NULL;
|
||||||
|
|
||||||
|
if (oldfd != AT_FDCWD && old[0] != '/')
|
||||||
|
{
|
||||||
|
size_t filelen = strlen (old);
|
||||||
|
/* Buffer for the path name we are going to use. It consists of
|
||||||
|
- the string /proc/self/fd/
|
||||||
|
- the file descriptor number
|
||||||
|
- the file name provided.
|
||||||
|
The final NUL is included in the sizeof. A bit of overhead
|
||||||
|
due to the format elements compensates for possible negative
|
||||||
|
numbers. */
|
||||||
|
size_t buflen = sizeof (procfd) + sizeof (int) * 3 + filelen;
|
||||||
|
bufold = alloca (buflen);
|
||||||
|
|
||||||
|
__snprintf (bufold, buflen, procfd, oldfd, old);
|
||||||
|
old = bufold;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *bufnew = NULL;
|
||||||
|
|
||||||
|
if (newfd != AT_FDCWD && new[0] != '/')
|
||||||
|
{
|
||||||
|
size_t filelen = strlen (new);
|
||||||
|
/* Buffer for the path name we are going to use. It consists of
|
||||||
|
- the string /proc/self/fd/
|
||||||
|
- the file descriptor number
|
||||||
|
- the file name provided.
|
||||||
|
The final NUL is included in the sizeof. A bit of overhead
|
||||||
|
due to the format elements compensates for possible negative
|
||||||
|
numbers. */
|
||||||
|
size_t buflen = sizeof (procfd) + sizeof (int) * 3 + filelen;
|
||||||
|
bufnew = alloca (buflen);
|
||||||
|
|
||||||
|
__snprintf (bufnew, buflen, procfd, newfd, new);
|
||||||
|
new = bufnew;
|
||||||
|
}
|
||||||
|
|
||||||
|
INTERNAL_SYSCALL_DECL (err);
|
||||||
|
|
||||||
|
int result = INTERNAL_SYSCALL (rename, err, 2, old, new);
|
||||||
|
|
||||||
|
if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0))
|
||||||
|
{
|
||||||
|
int errval = INTERNAL_SYSCALL_ERRNO (result, err);
|
||||||
|
if (errval == ENOTDIR && (bufnew != NULL || bufold != NULL))
|
||||||
|
{
|
||||||
|
/* This can mean either the file descriptor is invalid or
|
||||||
|
/proc is not mounted. */
|
||||||
|
struct stat64 st;
|
||||||
|
|
||||||
|
if (bufnew != NULL)
|
||||||
|
{
|
||||||
|
if (__fxstat64 (_STAT_VER, newfd, &st) != 0)
|
||||||
|
/* errno is already set correctly. */
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* If /proc is not mounted there is nothing we can do. */
|
||||||
|
if (S_ISDIR (st.st_mode)
|
||||||
|
&& (__xstat64 (_STAT_VER, "/proc/self/fd", &st) != 0
|
||||||
|
|| !S_ISDIR (st.st_mode)))
|
||||||
|
{
|
||||||
|
errval = ENOSYS;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bufold != NULL)
|
||||||
|
{
|
||||||
|
if (__fxstat64 (_STAT_VER, oldfd, &st) != 0)
|
||||||
|
/* errno is already set correctly. */
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* If /proc is not mounted there is nothing we can do. */
|
||||||
|
if (S_ISDIR (st.st_mode)
|
||||||
|
&& (__xstat64 (_STAT_VER, "/proc/self/fd", &st) != 0
|
||||||
|
|| !S_ISDIR (st.st_mode)))
|
||||||
|
errval = ENOSYS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
__set_errno (errval);
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,140 @@
|
||||||
|
/* Copyright (C) 2005 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, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <sysdep.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <shlib-compat.h>
|
||||||
|
#include <bp-checks.h>
|
||||||
|
|
||||||
|
#include <linux/posix_types.h>
|
||||||
|
#include "kernel-features.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
In Linux 2.1.x the chown functions have been changed. A new function lchown
|
||||||
|
was introduced. The new chown now follows symlinks - the old chown and the
|
||||||
|
new lchown do not follow symlinks.
|
||||||
|
The new lchown function has the same number as the old chown had and the
|
||||||
|
new chown has a new number. When compiling with headers from Linux > 2.1.8x
|
||||||
|
it's impossible to run this libc with older kernels. In these cases libc
|
||||||
|
has therefore to route calls to chown to the old chown function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Running under Linux > 2.1.80. */
|
||||||
|
|
||||||
|
#ifdef __NR_chown32
|
||||||
|
# if __ASSUME_32BITUIDS == 0
|
||||||
|
/* This variable is shared with all files that need to check for 32bit
|
||||||
|
uids. */
|
||||||
|
extern int __libc_missing_32bit_uids;
|
||||||
|
# endif
|
||||||
|
#endif /* __NR_chown32 */
|
||||||
|
|
||||||
|
int
|
||||||
|
fchownat (int fd, const char *file, uid_t owner, gid_t group, int flag)
|
||||||
|
{
|
||||||
|
if (flag & ~AT_SYMLINK_NOFOLLOW)
|
||||||
|
{
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *buf = NULL;
|
||||||
|
|
||||||
|
if (fd != AT_FDCWD && file[0] != '/')
|
||||||
|
{
|
||||||
|
size_t filelen = strlen (file);
|
||||||
|
static const char procfd[] = "/proc/self/fd/%d/%s";
|
||||||
|
/* Buffer for the path name we are going to use. It consists of
|
||||||
|
- the string /proc/self/fd/
|
||||||
|
- the file descriptor number
|
||||||
|
- the file name provided.
|
||||||
|
The final NUL is included in the sizeof. A bit of overhead
|
||||||
|
due to the format elements compensates for possible negative
|
||||||
|
numbers. */
|
||||||
|
size_t buflen = sizeof (procfd) + sizeof (int) * 3 + filelen;
|
||||||
|
buf = alloca (buflen);
|
||||||
|
|
||||||
|
__snprintf (buf, buflen, procfd, fd, file);
|
||||||
|
file = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result;
|
||||||
|
INTERNAL_SYSCALL_DECL (err);
|
||||||
|
|
||||||
|
#if __ASSUME_32BITUIDS > 0
|
||||||
|
result = INTERNAL_SYSCALL (chown32, err, 3, CHECK_STRING (file), owner,
|
||||||
|
group);
|
||||||
|
#else
|
||||||
|
static int __libc_old_chown;
|
||||||
|
|
||||||
|
# ifdef __NR_chown32
|
||||||
|
if (__libc_missing_32bit_uids <= 0)
|
||||||
|
{
|
||||||
|
if (flag & AT_SYMLINK_NOFOLLOW)
|
||||||
|
result = INTERNAL_SYSCALL (lchown32, err, 3, CHECK_STRING (file),
|
||||||
|
owner, group);
|
||||||
|
else
|
||||||
|
result = INTERNAL_SYSCALL (chown32, err, 3, CHECK_STRING (file),
|
||||||
|
owner, group);
|
||||||
|
|
||||||
|
if (__builtin_expect (!INTERNAL_SYSCALL_ERROR_P (result, err), 1))
|
||||||
|
return result;
|
||||||
|
if (INTERNAL_SYSCALL_ERRNO (result, err) != ENOSYS)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
__libc_missing_32bit_uids = 1;
|
||||||
|
}
|
||||||
|
# endif /* __NR_chown32 */
|
||||||
|
if (((owner + 1) > (uid_t) ((__kernel_uid_t) -1U))
|
||||||
|
|| ((group + 1) > (gid_t) ((__kernel_gid_t) -1U)))
|
||||||
|
{
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!__libc_old_chown && (flag & AT_SYMLINK_NOFOLLOW) == 0)
|
||||||
|
{
|
||||||
|
result = INTERNAL_SYSCALL (chown, err, 3, CHECK_STRING (file), owner,
|
||||||
|
group);
|
||||||
|
|
||||||
|
if (!INTERNAL_SYSCALL_ERROR_P (result, err))
|
||||||
|
return result;
|
||||||
|
if (INTERNAL_SYSCALL_ERRNO (result, err) != ENOSYS)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
__libc_old_chown = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = INTERNAL_SYSCALL (lchown, err, 3, CHECK_STRING (file), owner,
|
||||||
|
group);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0))
|
||||||
|
{
|
||||||
|
fail:
|
||||||
|
__atfct_seterrno (INTERNAL_SYSCALL_ERRNO (result, err), fd, buf);
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
#include <sysdeps/unix/sysv/linux/i386/fxstatat.c>
|
|
@ -0,0 +1 @@
|
||||||
|
#include <sysdeps/unix/sysv/linux/m68k/fchownat.c>
|
|
@ -0,0 +1 @@
|
||||||
|
#include <sysdeps/unix/sysv/linux/i386/fxstatat.c>
|
|
@ -0,0 +1 @@
|
||||||
|
#include <sysdeps/unix/sysv/linux/m68k/fchownat.c>
|
|
@ -0,0 +1 @@
|
||||||
|
#include <sysdeps/unix/sysv/linux/i386/fxstatat.c>
|
|
@ -0,0 +1 @@
|
||||||
|
#include "../../fxstatat.c"
|
|
@ -0,0 +1,74 @@
|
||||||
|
/* Copyright (C) 2005 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, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* Remove the link named NAME. */
|
||||||
|
int
|
||||||
|
unlinkat (fd, file, flag)
|
||||||
|
int fd;
|
||||||
|
const char *file;
|
||||||
|
int flag;
|
||||||
|
{
|
||||||
|
if (flag & ~AT_REMOVEDIR)
|
||||||
|
{
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *buf = NULL;
|
||||||
|
|
||||||
|
if (fd != AT_FDCWD && file[0] != '/')
|
||||||
|
{
|
||||||
|
size_t filelen = strlen (file);
|
||||||
|
static const char procfd[] = "/proc/self/fd/%d/%s";
|
||||||
|
/* Buffer for the path name we are going to use. It consists of
|
||||||
|
- the string /proc/self/fd/
|
||||||
|
- the file descriptor number
|
||||||
|
- the file name provided.
|
||||||
|
The final NUL is included in the sizeof. A bit of overhead
|
||||||
|
due to the format elements compensates for possible negative
|
||||||
|
numbers. */
|
||||||
|
size_t buflen = sizeof (procfd) + sizeof (int) * 3 + filelen;
|
||||||
|
buf = alloca (buflen);
|
||||||
|
|
||||||
|
__snprintf (buf, buflen, procfd, fd, file);
|
||||||
|
file = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result;
|
||||||
|
INTERNAL_SYSCALL_DECL (err);
|
||||||
|
|
||||||
|
if (flag & AT_REMOVEDIR)
|
||||||
|
result = INTERNAL_SYSCALL (rmdir, err, 1, file);
|
||||||
|
else
|
||||||
|
result = INTERNAL_SYSCALL (unlink, err, 1, file);
|
||||||
|
|
||||||
|
if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0))
|
||||||
|
{
|
||||||
|
__atfct_seterrno (INTERNAL_SYSCALL_ERRNO (result, err), fd, buf);
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
/* Copyright (C) 2005 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, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
/* Ho hum, since fxstatat == fxstatat64 we must get rid of the
|
||||||
|
prototype or gcc will complain since they don't strictly match. */
|
||||||
|
#define __fxstatat64 __fxstatat64_disable
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <sysdep.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <bp-checks.h>
|
||||||
|
|
||||||
|
/* Get information about the file NAME relative to FD in ST. */
|
||||||
|
int
|
||||||
|
__fxstatat (int vers, int fd, const char *file, struct stat *st, int flag)
|
||||||
|
{
|
||||||
|
if ((vers != _STAT_VER_KERNEL && vers != _STAT_VER_LINUX)
|
||||||
|
|| (flag & ~AT_SYMLINK_NOFOLLOW) != 0)
|
||||||
|
{
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *buf = NULL;
|
||||||
|
|
||||||
|
if (fd != AT_FDCWD && file[0] != '/')
|
||||||
|
{
|
||||||
|
size_t filelen = strlen (file);
|
||||||
|
static const char procfd[] = "/proc/self/fd/%d/%s";
|
||||||
|
/* Buffer for the path name we are going to use. It consists of
|
||||||
|
- the string /proc/self/fd/
|
||||||
|
- the file descriptor number
|
||||||
|
- the file name provided.
|
||||||
|
The final NUL is included in the sizeof. A bit of overhead
|
||||||
|
due to the format elements compensates for possible negative
|
||||||
|
numbers. */
|
||||||
|
size_t buflen = sizeof (procfd) + sizeof (int) * 3 + filelen;
|
||||||
|
buf = alloca (buflen);
|
||||||
|
|
||||||
|
__snprintf (buf, buflen, procfd, fd, file);
|
||||||
|
file = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
INTERNAL_SYSCALL_DECL (err);
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (flag & AT_SYMLINK_NOFOLLOW)
|
||||||
|
res = INTERNAL_SYSCALL (lstat, err, 2, file, CHECK_1 (st));
|
||||||
|
else
|
||||||
|
res = INTERNAL_SYSCALL (stat, err, 2, file, CHECK_1 (st));
|
||||||
|
|
||||||
|
if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0))
|
||||||
|
__atfct_seterrno (INTERNAL_SYSCALL_ERRNO (res, err), fd, buf);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#undef __fxstatat64
|
||||||
|
strong_alias (__fxstatat, __fxstatat64);
|
|
@ -0,0 +1 @@
|
||||||
|
/* fxstatat64 is in fxstatat.c */
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 1991-1994,1996-2002,2003 Free Software Foundation, Inc.
|
/* Copyright (C) 1991-1994,1996-2002,2003,2005 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
@ -70,13 +70,14 @@ typedef void *__restrict __timezone_ptr_t;
|
||||||
NOTE: This form of timezone information is obsolete.
|
NOTE: This form of timezone information is obsolete.
|
||||||
Use the functions and variables declared in <time.h> instead. */
|
Use the functions and variables declared in <time.h> instead. */
|
||||||
extern int gettimeofday (struct timeval *__restrict __tv,
|
extern int gettimeofday (struct timeval *__restrict __tv,
|
||||||
__timezone_ptr_t __tz) __THROW;
|
__timezone_ptr_t __tz) __THROW __nonnull ((1));
|
||||||
|
|
||||||
#ifdef __USE_BSD
|
#ifdef __USE_BSD
|
||||||
/* Set the current time of day and timezone information.
|
/* Set the current time of day and timezone information.
|
||||||
This call is restricted to the super-user. */
|
This call is restricted to the super-user. */
|
||||||
extern int settimeofday (__const struct timeval *__tv,
|
extern int settimeofday (__const struct timeval *__tv,
|
||||||
__const struct timezone *__tz) __THROW;
|
__const struct timezone *__tz)
|
||||||
|
__THROW __nonnull ((1));
|
||||||
|
|
||||||
/* Adjust the current time of day by the amount in DELTA.
|
/* Adjust the current time of day by the amount in DELTA.
|
||||||
If OLDDELTA is not NULL, it is filled in with the amount
|
If OLDDELTA is not NULL, it is filled in with the amount
|
||||||
|
@ -136,17 +137,25 @@ extern int setitimer (__itimer_which_t __which,
|
||||||
FILE to TVP[1]. If TVP is a null pointer, use the current time instead.
|
FILE to TVP[1]. If TVP is a null pointer, use the current time instead.
|
||||||
Returns 0 on success, -1 on errors. */
|
Returns 0 on success, -1 on errors. */
|
||||||
extern int utimes (__const char *__file, __const struct timeval __tvp[2])
|
extern int utimes (__const char *__file, __const struct timeval __tvp[2])
|
||||||
__THROW;
|
__THROW __nonnull ((1));
|
||||||
|
|
||||||
#ifdef __USE_BSD
|
#ifdef __USE_BSD
|
||||||
/* Same as `utimes', but does not follow symbolic links. */
|
/* Same as `utimes', but does not follow symbolic links. */
|
||||||
extern int lutimes (__const char *__file, __const struct timeval __tvp[2])
|
extern int lutimes (__const char *__file, __const struct timeval __tvp[2])
|
||||||
__THROW;
|
__THROW __nonnull ((1));
|
||||||
|
|
||||||
/* Same as `utimes', but takes an open file descriptor instead of a name. */
|
/* Same as `utimes', but takes an open file descriptor instead of a name. */
|
||||||
extern int futimes (int __fd, __const struct timeval __tvp[2]) __THROW;
|
extern int futimes (int __fd, __const struct timeval __tvp[2]) __THROW;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __USE_GNU
|
||||||
|
/* Change the access time of FILE relative to FD to TVP[0] and the
|
||||||
|
modification time of FILE to TVP[1]. If TVP is a null pointer, use
|
||||||
|
the current time instead. Returns 0 on success, -1 on errors. */
|
||||||
|
extern int futimesat (int __fd, __const char *__file,
|
||||||
|
__const struct timeval __tvp[2]) __THROW __nonnull ((2));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef __USE_BSD
|
#ifdef __USE_BSD
|
||||||
/* Convenience macros for operations on timevals.
|
/* Convenience macros for operations on timevals.
|
||||||
|
|
Loading…
Reference in New Issue