Back to index

glibc  2.9
chown.c
Go to the documentation of this file.
00001 /* Copyright (C) 2000,2001,2002,2003,2004,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 #include <errno.h>
00020 #include <unistd.h>
00021 
00022 #include <sysdep.h>
00023 #include <sys/syscall.h>
00024 #include <shlib-compat.h>
00025 #include <bp-checks.h>
00026 
00027 #include <linux/posix_types.h>
00028 #include <kernel-features.h>
00029 
00030 /*
00031   In Linux 2.1.x the chown functions have been changed.  A new function lchown
00032   was introduced.  The new chown now follows symlinks - the old chown and the
00033   new lchown do not follow symlinks.
00034   The new lchown function has the same number as the old chown had and the
00035   new chown has a new number.  When compiling with headers from Linux > 2.1.8x
00036   it's impossible to run this libc with older kernels.  In these cases libc
00037   has therefore to route calls to chown to the old chown function.
00038 */
00039 
00040 /* Running under Linux > 2.1.80.  */
00041 
00042 #ifdef __NR_chown32
00043 # if __ASSUME_32BITUIDS == 0
00044 /* This variable is shared with all files that need to check for 32bit
00045    uids.  */
00046 extern int __libc_missing_32bit_uids;
00047 # endif
00048 #endif /* __NR_chown32 */
00049 
00050 int
00051 __real_chown (const char *file, uid_t owner, gid_t group)
00052 {
00053 #if __ASSUME_32BITUIDS > 0
00054   return INLINE_SYSCALL (chown32, 3, CHECK_STRING (file), owner, group);
00055 #else
00056   static int __libc_old_chown;
00057   int result;
00058 
00059   if (!__libc_old_chown)
00060     {
00061       int saved_errno = errno;
00062 # ifdef __NR_chown32
00063       if (__libc_missing_32bit_uids <= 0)
00064        {
00065          int result;
00066          int saved_errno = errno;
00067 
00068          result = INLINE_SYSCALL (chown32, 3, CHECK_STRING (file), owner, group);
00069          if (result == 0 || errno != ENOSYS)
00070            return result;
00071 
00072          __set_errno (saved_errno);
00073          __libc_missing_32bit_uids = 1;
00074        }
00075 # endif /* __NR_chown32 */
00076       if (((owner + 1) > (uid_t) ((__kernel_uid_t) -1U))
00077          || ((group + 1) > (gid_t) ((__kernel_gid_t) -1U)))
00078        {
00079          __set_errno (EINVAL);
00080          return -1;
00081        }
00082 
00083       result = INLINE_SYSCALL (chown, 3, CHECK_STRING (file), owner, group);
00084 
00085       if (result >= 0 || errno != ENOSYS)
00086        return result;
00087 
00088       __set_errno (saved_errno);
00089       __libc_old_chown = 1;
00090     }
00091 
00092   return __lchown (file, owner, group);
00093 #endif
00094 }
00095 
00096 
00097 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
00098 /* Compiling for compatibiity.  */
00099 int
00100 attribute_compat_text_section
00101 __chown_is_lchown (const char *file, uid_t owner, gid_t group)
00102 {
00103   return __lchown (file, owner, group);
00104 }
00105 #endif
00106 
00107 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
00108 strong_alias (__chown_is_lchown, _chown_is_lchown)
00109 compat_symbol (libc, __chown_is_lchown, __chown, GLIBC_2_0);
00110 compat_symbol (libc, _chown_is_lchown, chown, GLIBC_2_0);
00111 
00112 strong_alias (__real_chown, _real_chown)
00113 versioned_symbol (libc, __real_chown, __chown, GLIBC_2_1);
00114 versioned_symbol (libc, _real_chown, chown, GLIBC_2_1);
00115 libc_hidden_ver (__real_chown, __chown)
00116 #else
00117 strong_alias (__real_chown, __chown)
00118 libc_hidden_def (__chown)
00119 weak_alias (__real_chown, chown)
00120 #endif