summaryrefslogtreecommitdiff
path: root/sysdeps/unix/sysv/linux/powerpc/chown.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix/sysv/linux/powerpc/chown.c')
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/chown.c140
1 files changed, 73 insertions, 67 deletions
diff --git a/sysdeps/unix/sysv/linux/powerpc/chown.c b/sysdeps/unix/sysv/linux/powerpc/chown.c
index 4b283e720c..fdcbd3683a 100644
--- a/sysdeps/unix/sysv/linux/powerpc/chown.c
+++ b/sysdeps/unix/sysv/linux/powerpc/chown.c
@@ -1,5 +1,5 @@
/* chown() compatibility.
- Copyright (C) 1998, 2000, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2000, 2002, 2003, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -24,6 +24,8 @@
#include <sysdep.h>
#include <stdlib.h>
+#include <kernel-features.h>
+
/*
In Linux 2.1.x the chown functions have been changed. A new function lchown
was introduced. The new chown now follows symlinks - the old chown and the
@@ -34,58 +36,61 @@
int
__chown (const char *file, uid_t owner, gid_t group)
{
- int err;
- int old_errno;
- char link[PATH_MAX+2];
- char path[2*PATH_MAX+4];
- int loopct;
- size_t filelen;
- static int libc_old_chown = 0 /* -1=old linux, 1=new linux, 0=unknown */;
-
- if (libc_old_chown == 1)
- return INLINE_SYSCALL (chown, 3, __ptrvalue (file), owner, group);
-
- old_errno = errno;
-
-#ifdef __NR_lchown
- if (libc_old_chown == 0)
- {
- err = INLINE_SYSCALL (chown, 3, __ptrvalue (file), owner, group);
- if (err != -1 || errno != ENOSYS)
- {
- libc_old_chown = 1;
- return err;
- }
- libc_old_chown = -1;
- }
-#endif
-
- err = __readlink (file, link, PATH_MAX+1);
- if (err == -1)
- {
- errno = old_errno;
- return __lchown(file, owner, group);
- }
-
- filelen = strlen (file) + 1;
- if (filelen > sizeof(path))
- {
- errno = ENAMETOOLONG;
- return -1;
- }
- memcpy (path, file, filelen);
-
- /* 'The system has an arbitrary limit...' In practise, we'll hit
- ENAMETOOLONG before this, usually. */
- for (loopct = 0; loopct < 128; loopct++)
- {
- size_t linklen;
-
- if (err >= PATH_MAX+1)
- {
- errno = ENAMETOOLONG;
- return -1;
- }
+#if __ASSUME_LCHOWN_SYSCALL
+ return INLINE_SYSCALL (chown, 3, file, owner, group);
+#else
+ int err;
+ int old_errno;
+ char link[PATH_MAX + 2];
+ char path[2 * PATH_MAX + 4];
+ int loopct;
+ size_t filelen;
+ static int libc_old_chown = 0 /* -1=old linux, 1=new linux, 0=unknown */;
+
+ if (libc_old_chown == 1)
+ return INLINE_SYSCALL (chown, 3, __ptrvalue (file), owner, group);
+
+ old_errno = errno;
+
+# ifdef __NR_lchown
+ if (libc_old_chown == 0)
+ {
+ err = INLINE_SYSCALL (chown, 3, __ptrvalue (file), owner, group);
+ if (err != -1 || errno != ENOSYS)
+ {
+ libc_old_chown = 1;
+ return err;
+ }
+ libc_old_chown = -1;
+ }
+# endif
+
+ err = __readlink (file, link, PATH_MAX + 1);
+ if (err == -1)
+ {
+ __set_errno (old_errno);
+ return __lchown (file, owner, group);
+ }
+
+ filelen = strlen (file) + 1;
+ if (filelen > sizeof (path))
+ {
+ __set_errno (ENAMETOOLONG);
+ return -1;
+ }
+ memcpy (path, file, filelen);
+
+ /* 'The system has an arbitrary limit...' In practise, we'll hit
+ ENAMETOOLONG before this, usually. */
+ for (loopct = 0; loopct < 128; ++loopct)
+ {
+ size_t linklen;
+
+ if (err >= PATH_MAX + 1)
+ {
+ __set_errno (ENAMETOOLONG);
+ return -1;
+ }
link[err] = 0; /* Null-terminate string, just-in-case. */
@@ -97,28 +102,29 @@ __chown (const char *file, uid_t owner, gid_t group)
{
filelen = strlen (path);
- while (filelen > 1 && path[filelen-1] == '/')
- filelen--;
- while (filelen > 0 && path[filelen-1] != '/')
- filelen--;
- if (filelen + linklen > sizeof(path))
+ while (filelen > 1 && path[filelen - 1] == '/')
+ --filelen;
+ while (filelen > 0 && path[filelen - 1] != '/')
+ --filelen;
+ if (filelen + linklen > sizeof (path))
{
errno = ENAMETOOLONG;
return -1;
}
- memcpy (path+filelen, link, linklen);
+ memcpy (path + filelen, link, linklen);
}
- err = __readlink(path, link, PATH_MAX+1);
+ err = __readlink (path, link, PATH_MAX + 1);
if (err == -1)
- {
- errno = old_errno;
- return __lchown(path, owner, group);
- }
- }
- errno = ELOOP;
- return -1;
+ {
+ __set_errno (old_errno);
+ return __lchown (path, owner, group);
+ }
+ }
+ __set_errno (ELOOP);
+ return -1;
+#endif
}
libc_hidden_def (__chown)