(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[glibc.git] / sysdeps / unix / sysv / linux / powerpc / chown.c
blob4b283e720cefa38af5c3f8650cb50d8fca7aa7f7
1 /* chown() compatibility.
2 Copyright (C) 1998, 2000, 2002, 2003 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
20 #include <errno.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <limits.h>
24 #include <sysdep.h>
25 #include <stdlib.h>
28 In Linux 2.1.x the chown functions have been changed. A new function lchown
29 was introduced. The new chown now follows symlinks - the old chown and the
30 new lchown do not follow symlinks.
31 This file emulates chown() under the old kernels.
34 int
35 __chown (const char *file, uid_t owner, gid_t group)
37 int err;
38 int old_errno;
39 char link[PATH_MAX+2];
40 char path[2*PATH_MAX+4];
41 int loopct;
42 size_t filelen;
43 static int libc_old_chown = 0 /* -1=old linux, 1=new linux, 0=unknown */;
45 if (libc_old_chown == 1)
46 return INLINE_SYSCALL (chown, 3, __ptrvalue (file), owner, group);
48 old_errno = errno;
50 #ifdef __NR_lchown
51 if (libc_old_chown == 0)
53 err = INLINE_SYSCALL (chown, 3, __ptrvalue (file), owner, group);
54 if (err != -1 || errno != ENOSYS)
56 libc_old_chown = 1;
57 return err;
59 libc_old_chown = -1;
61 #endif
63 err = __readlink (file, link, PATH_MAX+1);
64 if (err == -1)
66 errno = old_errno;
67 return __lchown(file, owner, group);
70 filelen = strlen (file) + 1;
71 if (filelen > sizeof(path))
73 errno = ENAMETOOLONG;
74 return -1;
76 memcpy (path, file, filelen);
78 /* 'The system has an arbitrary limit...' In practise, we'll hit
79 ENAMETOOLONG before this, usually. */
80 for (loopct = 0; loopct < 128; loopct++)
82 size_t linklen;
84 if (err >= PATH_MAX+1)
86 errno = ENAMETOOLONG;
87 return -1;
90 link[err] = 0; /* Null-terminate string, just-in-case. */
92 linklen = strlen (link) + 1;
94 if (link[0] == '/')
95 memcpy (path, link, linklen);
96 else
98 filelen = strlen (path);
100 while (filelen > 1 && path[filelen-1] == '/')
101 filelen--;
102 while (filelen > 0 && path[filelen-1] != '/')
103 filelen--;
104 if (filelen + linklen > sizeof(path))
106 errno = ENAMETOOLONG;
107 return -1;
109 memcpy (path+filelen, link, linklen);
112 err = __readlink(path, link, PATH_MAX+1);
114 if (err == -1)
116 errno = old_errno;
117 return __lchown(path, owner, group);
120 errno = ELOOP;
121 return -1;
123 libc_hidden_def (__chown)
125 #include <shlib-compat.h>
126 versioned_symbol (libc, __chown, chown, GLIBC_2_1);