Back to index

glibc  2.9
fxstatat.c
Go to the documentation of this file.
00001 /* Copyright (C) 2005, 2006 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003 
00004    The GNU C Library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Lesser General Public
00006    License as published by the Free Software Foundation; either
00007    version 2.1 of the License, or (at your option) any later version.
00008 
00009    The GNU C Library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Lesser General Public License for more details.
00013 
00014    You should have received a copy of the GNU Lesser General Public
00015    License along with the GNU C Library; if not, write to the Free
00016    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00017    02111-1307 USA.  */
00018 
00019 /* Ho hum, if fxstatat == fxstatat64 we must get rid of the prototype or gcc
00020    will complain since they don't strictly match.  */
00021 #define __fxstatat64 __fxstatat64_disable
00022 
00023 #include <errno.h>
00024 #include <fcntl.h>
00025 #include <stddef.h>
00026 #include <stdio.h>
00027 #include <string.h>
00028 #include <sys/stat.h>
00029 #include <kernel_stat.h>
00030 
00031 #include <sysdep.h>
00032 #include <sys/syscall.h>
00033 #include <bp-checks.h>
00034 
00035 #include <kernel-features.h>
00036 
00037 #include <xstatconv.h>
00038 
00039 #ifdef __NR_stat64
00040 # if __ASSUME_STAT64_SYSCALL == 0
00041 /* The variable is shared between all wrappers around *stat64 calls.  */
00042 extern int __have_no_stat64;
00043 # endif
00044 #endif
00045 
00046 
00047 /* Get information about the file NAME relative to FD in ST.  */
00048 int
00049 __fxstatat (int vers, int fd, const char *file, struct stat *st, int flag)
00050 {
00051   int result;
00052   INTERNAL_SYSCALL_DECL (err);
00053   struct stat64 st64;
00054 
00055 #ifdef __NR_fstatat64
00056 # ifndef __ASSUME_ATFCTS
00057   if (__have_atfcts >= 0)
00058 # endif
00059     {
00060       result = INTERNAL_SYSCALL (fstatat64, err, 4, fd, file, &st64, flag);
00061 # ifndef __ASSUME_ATFCTS
00062       if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 1)
00063          && INTERNAL_SYSCALL_ERRNO (result, err) == ENOSYS)
00064        __have_atfcts = -1;
00065       else
00066 # endif
00067        if (!__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 1))
00068          return __xstat32_conv (vers, &st64, st);
00069        else
00070          {
00071            __set_errno (INTERNAL_SYSCALL_ERRNO (result, err));
00072            return -1;
00073          }
00074     }
00075 #endif
00076 
00077 #ifndef __ASSUME_ATFCTS
00078   if (__builtin_expect (flag & ~AT_SYMLINK_NOFOLLOW, 0))
00079     {
00080       __set_errno (EINVAL);
00081       return -1;
00082     }
00083 
00084   char *buf = NULL;
00085 
00086   if (fd != AT_FDCWD && file[0] != '/')
00087     {
00088       size_t filelen = strlen (file);
00089       static const char procfd[] = "/proc/self/fd/%d/%s";
00090       /* Buffer for the path name we are going to use.  It consists of
00091         - the string /proc/self/fd/
00092         - the file descriptor number
00093         - the file name provided.
00094         The final NUL is included in the sizeof.   A bit of overhead
00095         due to the format elements compensates for possible negative
00096         numbers.  */
00097       size_t buflen = sizeof (procfd) + sizeof (int) * 3 + filelen;
00098       buf = alloca (buflen);
00099 
00100       __snprintf (buf, buflen, procfd, fd, file);
00101       file = buf;
00102     }
00103 
00104 # if __ASSUME_STAT64_SYSCALL == 0
00105   struct kernel_stat kst;
00106 # endif
00107   if (vers == _STAT_VER_KERNEL)
00108     {
00109       if (flag & AT_SYMLINK_NOFOLLOW)
00110        result = INTERNAL_SYSCALL (lstat, err, 2, CHECK_STRING (file),
00111                                CHECK_1 ((struct kernel_stat *) st));
00112       else
00113        result = INTERNAL_SYSCALL (stat, err, 2, CHECK_STRING (file),
00114                                CHECK_1 ((struct kernel_stat *) st));
00115       goto out;
00116     }
00117 
00118 # if __ASSUME_STAT64_SYSCALL > 0
00119 
00120   if (flag & AT_SYMLINK_NOFOLLOW)
00121     result = INTERNAL_SYSCALL (lstat64, err, 2, CHECK_STRING (file),
00122                             __ptrvalue (&st64));
00123   else
00124     result = INTERNAL_SYSCALL (stat64, err, 2, CHECK_STRING (file),
00125                             __ptrvalue (&st64));
00126   if (__builtin_expect (!INTERNAL_SYSCALL_ERROR_P (result, err), 1))
00127     return __xstat32_conv (vers, &st64, st);
00128 # else
00129 #  if defined __NR_stat64
00130   /* To support 32 bit UIDs, we have to use stat64.  The normal stat
00131      call only returns 16 bit UIDs.  */
00132   if (! __have_no_stat64)
00133     {
00134       if (flag & AT_SYMLINK_NOFOLLOW)
00135        result = INTERNAL_SYSCALL (lstat64, err, 2, CHECK_STRING (file),
00136                                __ptrvalue (&st64));
00137       else
00138        result = INTERNAL_SYSCALL (stat64, err, 2, CHECK_STRING (file),
00139                                __ptrvalue (&st64));
00140 
00141       if (__builtin_expect (!INTERNAL_SYSCALL_ERROR_P (result, err), 1))
00142        result = __xstat32_conv (vers, &st64, st);
00143 
00144       if (__builtin_expect (!INTERNAL_SYSCALL_ERROR_P (result, err), 1)
00145          || INTERNAL_SYSCALL_ERRNO (result, err) != ENOSYS)
00146        goto out;
00147 
00148       __have_no_stat64 = 1;
00149     }
00150 #  endif
00151   if (flag & AT_SYMLINK_NOFOLLOW)
00152     result = INTERNAL_SYSCALL (lstat, err, 2, CHECK_STRING (file),
00153                             __ptrvalue (&kst));
00154   else
00155     result = INTERNAL_SYSCALL (stat, err, 2, CHECK_STRING (file),
00156                             __ptrvalue (&kst));
00157   if (__builtin_expect (!INTERNAL_SYSCALL_ERROR_P (result, err), 1))
00158     return __xstat_conv (vers, &kst, st);
00159 # endif  /* __ASSUME_STAT64_SYSCALL  */
00160 
00161  out:
00162   if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0))
00163     {
00164       __atfct_seterrno (INTERNAL_SYSCALL_ERRNO (result, err), fd, buf);
00165       result = -1;
00166     }
00167 
00168   return result;
00169 #endif
00170 }
00171 libc_hidden_def (__fxstatat)
00172 #ifdef XSTAT_IS_XSTAT64
00173 # undef __fxstatat64
00174 strong_alias (__fxstatat, __fxstatat64);
00175 libc_hidden_ver (__fxstatat, __fxstatat64)
00176 #endif