about summary refs log tree commit diff
path: root/sysdeps/unix/sysv/linux
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix/sysv/linux')
-rw-r--r--sysdeps/unix/sysv/linux/i386/profil-counter.h5
-rw-r--r--sysdeps/unix/sysv/linux/ldd-rewrite.sed2
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/chown.c131
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/clone.S78
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/lchown.S35
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/profil-counter.h36
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/sigcontextinfo.h24
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/syscalls.list4
-rw-r--r--sysdeps/unix/sysv/linux/sys/mount.h6
9 files changed, 243 insertions, 78 deletions
diff --git a/sysdeps/unix/sysv/linux/i386/profil-counter.h b/sysdeps/unix/sysv/linux/i386/profil-counter.h
index a24ea19654..50186932be 100644
--- a/sysdeps/unix/sysv/linux/i386/profil-counter.h
+++ b/sysdeps/unix/sysv/linux/i386/profil-counter.h
@@ -18,9 +18,10 @@
    Boston, MA 02111-1307, USA.  */
 
 #include <signal.h>
+#include <sigcontextinfo.h>
 
 static void
-profil_counter (int signo, struct sigcontext sc)
+profil_counter (int signo, SIGCONTEXT scp)
 {
-  profil_count ((void *) sc.eip);
+  profil_count ((void *) GET_PC (scp));
 }
diff --git a/sysdeps/unix/sysv/linux/ldd-rewrite.sed b/sysdeps/unix/sysv/linux/ldd-rewrite.sed
index 0ad5bc4f93..7b8b6bdee0 100644
--- a/sysdeps/unix/sysv/linux/ldd-rewrite.sed
+++ b/sysdeps/unix/sysv/linux/ldd-rewrite.sed
@@ -1,7 +1,7 @@
 /Maybe extra code for non-ELF binaries/a\
   file=$1\
   # Run the ldd stub.\
-  lddlibc4 $file\
+  lddlibc4 "$file"\
   # Test the result.\
   if test $? -lt 3; then\
     return 0;\
diff --git a/sysdeps/unix/sysv/linux/powerpc/chown.c b/sysdeps/unix/sysv/linux/powerpc/chown.c
new file mode 100644
index 0000000000..5f6c3d29ce
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/chown.c
@@ -0,0 +1,131 @@
+/* chown() compatibility.
+   Copyright (C) 1998 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
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/syscall.h>
+#include <stdlib.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
+  new lchown do not follow symlinks.
+  This file emulates chown() under the old kernels.
+*/
+
+extern int __syscall_chown (const char *__file,
+			    uid_t __owner, gid_t __group);
+
+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;
+   int filelen;
+   static int libc_old_chown = 0 /* -1=old linux, 1=new linux, 0=unknown */;
+   
+   if (libc_old_chown == 1)
+     return __syscall_chown (file, owner, group);
+
+   old_errno = errno;
+
+#ifdef __NR_lchown
+   if (libc_old_chown == 0)
+     {
+       err = __syscall_chown (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++)
+   {
+     int linklen;
+     
+     if (err >= PATH_MAX+1)
+       {
+	 errno = ENAMETOOLONG;
+	 return -1;
+       }
+
+      link[err] = 0;  /* Null-terminate string, just-in-case.  */
+
+      linklen = strlen (link) + 1;
+      
+      if (link[0] == '/')
+	memcpy (path, link, linklen);
+      else
+	{
+	  filelen = strlen (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);
+	}
+
+      err = __readlink(path, link, PATH_MAX+1);
+      
+      if (err == -1)
+      {  
+	errno = old_errno;
+	return __lchown(path, owner, group);
+      }
+   }
+   errno = ELOOP;
+   return -1;
+}
+
+#if defined PIC && defined DO_VERSIONING
+default_symbol_version (__chown, chown, GLIBC_2.1);
+#else
+weak_alias (__chown, chown)
+#endif
diff --git a/sysdeps/unix/sysv/linux/powerpc/clone.S b/sysdeps/unix/sysv/linux/powerpc/clone.S
index 6209922b6b..69d2c5f586 100644
--- a/sysdeps/unix/sysv/linux/powerpc/clone.S
+++ b/sysdeps/unix/sysv/linux/powerpc/clone.S
@@ -1,5 +1,5 @@
 /* Wrapper around clone system call.
-   Copyright (C) 1997 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998 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
@@ -28,56 +28,60 @@
 /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */
 
 ENTRY(__clone)
-	/* Set up stack frame, save registers.  */
-	stwu  %r1,-32(%r1)
 	/* Check for child_stack == NULL || fn == NULL.  */
-	cmpwi %cr0,%r4,0
-	stw   %r31,16(%r1)
-	cmpwi %cr1,%r3,0
-	stw   %r30,20(%r1)
-	beq-  %cr0,badargs
-	beq-  %cr1,badargs
+	cmpwi	%cr0,%r4,0
+	cmpwi	%cr1,%r3,0
+	cror	cr0*4+eq,cr1*4+eq,cr0*4+eq
+	beq-	%cr0,L(badargs)
 
+	/* Set up stack frame for parent.  */
+	stwu	%r1,-32(%r1)
+	stmw	%r29,16(%r1)
+	
 	/* Set up stack frame for child.  */
-	addi  %r4,%r4,-16
-	clrrwi %r4,%r4,4
-	li    %r0,0
-	stw   %r0,0(%r4)
+	clrrwi	%r4,%r4,4
+	li	%r0,0
+	stwu	%r0,-16(%r4)
 
-	/* Save fn, args across syscall.  */
-	mr    %r30,%r3		/* Function in r30.  */
-	mr    %r31,%r6		/* Arguments in r31.  */
+	/* Save fn, args, stack across syscall.  */
+	mr	%r29,%r3		/* Function in r29.  */
+	mr	%r30,%r4		/* Stack pointer in r30.  */
+	mr	%r31,%r6		/* Argument in r31.  */
 
 	/* 'flags' argument is first parameter to clone syscall. (The other
 	   argument is the stack pointer, already in r4.)  */
-	mr    %r3,%r5
+	mr	%r3,%r5
 
 	/* Do the call.  */
 	DO_CALL(SYS_ify(clone))
-	bso-  error
-	beq   child
 
-	/* Parent.  Restore registers & return.  */
-	lwz   %r31,16(%r1)
-	lwz   %r30,20(%r1)
-	addi  %r1,%r1,32
-	blr
+	/* Check for child process.  */
+	cmpwi	%cr1,%r3,0
+	crandc	cr1*4+eq,cr1*4+eq,cr0*4+so
+	bne-	%cr1,L(parent)		/* The '-' is to minimise the race.  */
 
-child:
+	/* On at least mklinux DR3a5, clone() doesn't actually change
+	   the stack pointer.  I'm pretty sure this is a bug, because
+	   it adds a race condition if a signal is sent to a thread
+	   just after it is created (in the previous three instructions).  */
+	mr	%r1,%r30
 	/* Call procedure.  */
-	mtlr  %r30
-	mr    %r3,%r31
-	blrl
+	mtctr	%r29
+	mr	%r3,%r31
+	bctrl
 	/* Call _exit with result from procedure.  */
-	b JUMPTARGET(_exit)
-
-badargs:
-	li    %r3,EINVAL
-error:
-	lwz   %r31,16(%r1)
-	lwz   %r30,20(%r1)
-	addi  %r1,%r1,32
-	b JUMPTARGET(__syscall_error)
+	b	JUMPTARGET(_exit)
+
+L(parent):
+	/* Parent.  Restore registers & return.  */
+	lmw	%r29,16(%r1)
+	addi	%r1,%r1,32
+	bnslr+
+	b	JUMPTARGET(__syscall_error)
+
+L(badargs):
+	li	%r3,EINVAL
+	b	JUMPTARGET(__syscall_error)
 END (__clone)
 
 weak_alias (__clone, clone)
diff --git a/sysdeps/unix/sysv/linux/powerpc/lchown.S b/sysdeps/unix/sysv/linux/powerpc/lchown.S
new file mode 100644
index 0000000000..9195eab516
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/lchown.S
@@ -0,0 +1,35 @@
+/* lchown system call.
+   Copyright (C) 1998 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
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* Some old kernel headers call lchown() 'chown'.  The number is
+   the same.  */
+	
+#include <sysdep.h>
+
+#ifdef __NR_lchown
+	PSEUDO (__lchown, lchown, 3)
+#else
+	PSEUDO (__lchown, chown, 3)
+#endif
+	ret
+	PSEUDO_END(__lchown)
+	weak_alias (__lchown, lchown)
+#if defined PIC && defined DO_VERSIONING
+	symbol_version (__lchown, chown, GLIBC_2.0);
+#endif
diff --git a/sysdeps/unix/sysv/linux/powerpc/profil-counter.h b/sysdeps/unix/sysv/linux/powerpc/profil-counter.h
index 4be6f11270..8a6a0bcf3d 100644
--- a/sysdeps/unix/sysv/linux/powerpc/profil-counter.h
+++ b/sysdeps/unix/sysv/linux/powerpc/profil-counter.h
@@ -1,34 +1,2 @@
-/* Low-level statistical profiling support function.  Linux/PowerPC version.
-   Copyright (C) 1996, 1997 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
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Library General Public License for more details.
-
-   You should have received a copy of the GNU Library General Public
-   License along with the GNU C Library; see the file COPYING.LIB.  If not,
-   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
-
-#include <sys/ptrace.h>
-
-/* You can also do this by using
-   void
-   profil_counter (int signo, struct pt_regs *pt)
-   {
-     profil_count ((void *) pt->nip);
-   }
-   */
-
-void
-profil_counter (int signo, void **regs)
-{
-  profil_count (regs[PT_NIP]);
-}
+/* We can use the ix86 version.  */
+#include <sysdeps/unix/sysv/linux/i386/profil-counter.h>
diff --git a/sysdeps/unix/sysv/linux/powerpc/sigcontextinfo.h b/sysdeps/unix/sysv/linux/powerpc/sigcontextinfo.h
new file mode 100644
index 0000000000..2a7a2fe5c8
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/sigcontextinfo.h
@@ -0,0 +1,24 @@
+/* Copyright (C) 1998 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
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <sys/ptrace.h>
+
+#define SIGCONTEXT void **
+#define GET_PC(ctx)	((ctx)[PT_NIP])
+#define GET_FRAME(ctx)	(*(void **)(ctx)[PT_R1])
+#define GET_STACK(ctx)	((ctx)[PT_R1])
diff --git a/sysdeps/unix/sysv/linux/powerpc/syscalls.list b/sysdeps/unix/sysv/linux/powerpc/syscalls.list
index 605762a2a4..3af0c5b6f8 100644
--- a/sysdeps/unix/sysv/linux/powerpc/syscalls.list
+++ b/sysdeps/unix/sysv/linux/powerpc/syscalls.list
@@ -1,6 +1,4 @@
 # File name	Caller	Syscall name	# args	Strong name	Weak names
 
 s_llseek	llseek	_llseek		5	__sys_llseek
-
-getresuid	-	getresuid	3	getresuid
-getresgid	-	getresgid	3	getresgid
+s_chown		chown	chown		3	__syscall_chown
diff --git a/sysdeps/unix/sysv/linux/sys/mount.h b/sysdeps/unix/sysv/linux/sys/mount.h
index f29d158fb5..862c1f0407 100644
--- a/sysdeps/unix/sysv/linux/sys/mount.h
+++ b/sysdeps/unix/sysv/linux/sys/mount.h
@@ -83,7 +83,11 @@ enum
 
 
 /* Possible value for FLAGS parameter of `umount2'.  */
-#define MNT_FORCE		/* Force unmounting.  */
+enum
+{
+  MNT_FORCE = 1			/* Force unmounting.  */
+#define MNT_FORCE MNT_FORCE
+};
 
 
 __BEGIN_DECLS