1 /* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
23 #include <sys/syscall.h>
24 #include <shlib-compat.h>
25 #include <bp-checks.h>
27 #include <linux/posix_types.h>
28 #include "kernel-features.h"
31 In Linux 2.1.x the chown functions have been changed. A new function lchown
32 was introduced. The new chown now follows symlinks - the old chown and the
33 new lchown do not follow symlinks.
34 The new lchown function has the same number as the old chown had and the
35 new chown has a new number. When compiling with headers from Linux > 2.1.8x
36 it's impossible to run this libc with older kernels. In these cases libc
37 has therefore to route calls to chown to the old chown function.
40 extern int __syscall_chown (const char *__file,
41 __kernel_uid_t __owner, __kernel_gid_t __group);
42 #if defined __NR_lchown || __ASSUME_LCHOWN_SYSCALL > 0
43 /* Running under Linux > 2.1.80. */
46 extern int __syscall_chown32 (const char *__file,
47 __kernel_uid32_t owner, __kernel_gid32_t group);
48 # if __ASSUME_32BITUIDS == 0
49 /* This variable is shared with all files that need to check for 32bit
51 extern int __libc_missing_32bit_uids;
53 # endif /* __NR_chown32 */
56 __real_chown (const char *file, uid_t owner, gid_t group)
58 # if __ASSUME_LCHOWN_SYSCALL == 0
59 static int __libc_old_chown;
62 if (!__libc_old_chown)
64 int saved_errno = errno;
66 if (__libc_missing_32bit_uids <= 0)
69 int saved_errno = errno;
71 result = INLINE_SYSCALL (chown32, 3, CHECK_STRING (file), owner, group);
72 if (result == 0 || errno != ENOSYS)
75 __set_errno (saved_errno);
76 __libc_missing_32bit_uids = 1;
78 # endif /* __NR_chown32 */
79 if (((owner + 1) > (uid_t) ((__kernel_uid_t) -1U))
80 || ((group + 1) > (gid_t) ((__kernel_gid_t) -1U)))
86 result = INLINE_SYSCALL (chown, 3, CHECK_STRING (file), owner, group);
88 if (result >= 0 || errno != ENOSYS)
91 __set_errno (saved_errno);
95 return __lchown (file, owner, group);
96 # elif __ASSUME_32BITUIDS
97 /* This implies __ASSUME_LCHOWN_SYSCALL. */
98 return INLINE_SYSCALL (chown32, 3, CHECK_STRING (file), owner, group);
100 /* !__ASSUME_32BITUIDS && ASSUME_LCHOWN_SYSCALL */
102 if (__libc_missing_32bit_uids <= 0)
105 int saved_errno = errno;
107 result = INLINE_SYSCALL (chown32, 3, CHECK_STRING (file), owner, group);
108 if (result == 0 || errno != ENOSYS)
111 __set_errno (saved_errno);
112 __libc_missing_32bit_uids = 1;
114 # endif /* __NR_chown32 */
115 if (((owner + 1) > (uid_t) ((__kernel_uid_t) -1U))
116 || ((group + 1) > (gid_t) ((__kernel_gid_t) -1U)))
118 __set_errno (EINVAL);
122 return INLINE_SYSCALL (chown, 3, CHECK_STRING (file), owner, group);
128 #if !defined __NR_lchown && __ASSUME_LCHOWN_SYSCALL == 0
129 /* Compiling under older kernels. */
131 __chown_is_lchown (const char *file, uid_t owner, gid_t group)
133 return INLINE_SYSCALL (chown, 3, CHECK_STRING (file), owner, group);
135 #elif SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
136 /* Compiling for compatibiity. */
138 __chown_is_lchown (const char *file, uid_t owner, gid_t group)
140 return __lchown (file, owner, group);
144 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
145 strong_alias (__chown_is_lchown, _chown_is_lchown)
146 compat_symbol (libc, __chown_is_lchown, __chown, GLIBC_2_0);
147 compat_symbol (libc, _chown_is_lchown, chown, GLIBC_2_0);
151 strong_alias (__real_chown, _real_chown)
152 versioned_symbol (libc, __real_chown, __chown, GLIBC_2_1);
153 versioned_symbol (libc, _real_chown, chown, GLIBC_2_1);
155 strong_alias (__chown_is_lchown, __chown_is_lchown21)
156 strong_alias (__chown_is_lchown, _chown_is_lchown21)
157 versioned_symbol (libc, __chown_is_lchown21, __chown, GLIBC_2_1);
158 versioned_symbol (libc, _chown_is_lchown21, chown, GLIBC_2_1);