2.9
[glibc/nacl-glibc.git] / sysdeps / unix / sysv / linux / s390 / s390-32 / chown.c
blob5909ba8a43403dab1ccd3a3ef1d464cadf5b626d
1 /* Copyright (C) 2000,2001,2002,2003,2004,2006 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 Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the 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 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307 USA. */
19 #include <errno.h>
20 #include <unistd.h>
22 #include <sysdep.h>
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 /* Running under Linux > 2.1.80. */
42 #ifdef __NR_chown32
43 # if __ASSUME_32BITUIDS == 0
44 /* This variable is shared with all files that need to check for 32bit
45 uids. */
46 extern int __libc_missing_32bit_uids;
47 # endif
48 #endif /* __NR_chown32 */
50 int
51 __real_chown (const char *file, uid_t owner, gid_t group)
53 #if __ASSUME_32BITUIDS > 0
54 return INLINE_SYSCALL (chown32, 3, CHECK_STRING (file), owner, group);
55 #else
56 static int __libc_old_chown;
57 int result;
59 if (!__libc_old_chown)
61 int saved_errno = errno;
62 # ifdef __NR_chown32
63 if (__libc_missing_32bit_uids <= 0)
65 int result;
66 int saved_errno = errno;
68 result = INLINE_SYSCALL (chown32, 3, CHECK_STRING (file), owner, group);
69 if (result == 0 || errno != ENOSYS)
70 return result;
72 __set_errno (saved_errno);
73 __libc_missing_32bit_uids = 1;
75 # endif /* __NR_chown32 */
76 if (((owner + 1) > (uid_t) ((__kernel_uid_t) -1U))
77 || ((group + 1) > (gid_t) ((__kernel_gid_t) -1U)))
79 __set_errno (EINVAL);
80 return -1;
83 result = INLINE_SYSCALL (chown, 3, CHECK_STRING (file), owner, group);
85 if (result >= 0 || errno != ENOSYS)
86 return result;
88 __set_errno (saved_errno);
89 __libc_old_chown = 1;
92 return __lchown (file, owner, group);
93 #endif
97 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
98 /* Compiling for compatibiity. */
99 int
100 attribute_compat_text_section
101 __chown_is_lchown (const char *file, uid_t owner, gid_t group)
103 return __lchown (file, owner, group);
105 #endif
107 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
108 strong_alias (__chown_is_lchown, _chown_is_lchown)
109 compat_symbol (libc, __chown_is_lchown, __chown, GLIBC_2_0);
110 compat_symbol (libc, _chown_is_lchown, chown, GLIBC_2_0);
112 strong_alias (__real_chown, _real_chown)
113 versioned_symbol (libc, __real_chown, __chown, GLIBC_2_1);
114 versioned_symbol (libc, _real_chown, chown, GLIBC_2_1);
115 libc_hidden_ver (__real_chown, __chown)
116 #else
117 strong_alias (__real_chown, __chown)
118 libc_hidden_def (__chown)
119 weak_alias (__real_chown, chown)
120 #endif