This is the mail archive of the libc-hacker@sourceware.cygnus.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[PATCH] Re: 32bit uids on Alpha, MIPS, PPC and Sparc64


On Tue, Feb 01, 2000 at 02:34:53PM +0100, Andreas Jaeger wrote:
> 
> AFAIK the Linux ports for Alpha, MIPS, PPC and Sparc64 always had
> 32bit uids and therefore don't need any compatibility stuff.
> 
> The following five files in sysdeps/unix/sysv/linux use __ASSUME_32BITUIDS:
> 
> getresgid.c, getresuid.c, msgctl.c, semctl.c, shmctl.c
> 
> Looking at the code from e.g. getresuid.c, I don't think this will
> work with Alpha etc.  Jakub, does it work for you on Ultrasparc with
> headers from 2.3.39+ kernels and --enable-kernel=2.3.40?  I would be
> surprised ;-)

It does work on sparc64:
[jj@tucnak src]# grep getres[ug]id /usr/src/libc/sysdeps/unix/sysv/linux/sparc/sparc64/syscalls.list
getresuid       -       getresuid       3       getresuid
getresgid       -       getresgid       3       getresgid
[jj@tucnak src]# ls -l /usr/src/libc/sysdeps/unix/sysv/linux/sparc/sparc64/*ctl.c
-rw-r--r--    1 jj       root         1324 Jan 25 15:36 /usr/src/libc/sysdeps/unix/sysv/linux/sparc/sparc64/msgctl.c
-rw-r--r--    1 jj       root         1725 Jan 25 15:36 /usr/src/libc/sysdeps/unix/sysv/linux/sparc/sparc64/semctl.c
-rw-r--r--    1 jj       root         1305 Jan 25 15:36 /usr/src/libc/sysdeps/unix/sysv/linux/sparc/sparc64/shmctl.c

It should work on Alpha as well, as far as I can see Alpha has getres[ug]id in syscalls.list the same way
and the sysv/linux/*ctl.c are ok for it.

> 
> What's the best way to handle this?

Patch attached.
getresuid/getresgid should IMHO be really moved to i386 subdir (as done in
the patch) because they use __libc_missing_32bit_uids symbol which is
defined in i386 subdir only anyway. And they are used by
i386/arm/m68k only.
This patch also creates i386 versions of msgctl, semctl and shmctl, because
on platforms which do have getuid32 syscall it is fairly easy how to find
out whether it is safe to use new IPC or whether old IPC should be used.
So, I use __libc_missing_32bit_uids as a 3 state variable now, -1 means
untested, 0 means use 32bit uids, 1 means they are not available.
But as msgctl/semctl/shmctl are IMHO not as common as the majority of other
32bit uid syscalls, I have not put setting __libc_missing_32bit_uids = 0
after every successful 32bit uid syscall so that it does not create unneeded
overhead. Instead, only msgctl/shmctl/semctl, if they find
__libc_missing_32bit_uids == -1, then they call getuid32 first and check for
ENOSYS and set __libc_missing_32bit_uids to either 1 (if ENOSYS) or 0.

2000-02-01  Jakub Jelinek  <jakub@redhat.com>

	* sysdeps/unix/sysv/linux/getresgid.c: Move...
	* sysdeps/unix/sysv/linux/i386/getresgid.c: ...here.
	(getresgid): Use getresgid32 if __libc_missing_32bit_uids
	is -1 or 0.
	* sysdeps/unix/sysv/linux/getresuid.c: Move...
	* sysdeps/unix/sysv/linux/i386/getresuid.c: ...here.
	(getresuid): Use getresuid32 if __libc_missing_32bit_uids
	is -1 or 0.
	* sysdeps/unix/sysv/linux/i386/getuid.c: Document new tristate
	__libc_missing_32bit_uids.
	(__getuid): Use 32bit uid syscall if __libc_missing_32bit_uids is
	-1 or 0.
	* sysdeps/unix/sysv/linux/i386/chown.c (__real_chown): Likewise.
	* sysdeps/unix/sysv/linux/i386/fchown.c (__fchown): Likewise.
	* sysdeps/unix/sysv/linux/i386/getegid.c (__getegid): Likewise.
	* sysdeps/unix/sysv/linux/i386/geteuid.c (__geteuid): Likewise.
	* sysdeps/unix/sysv/linux/i386/getgroups.c (__getgroups): Likewise.
	* sysdeps/unix/sysv/linux/i386/getgid.c (__getgid): Likewise.
	* sysdeps/unix/sysv/linux/i386/lchown.c (__lchown): Likewise.
	* sysdeps/unix/sysv/linux/i386/setfsgid.c (setfsgid): Likewise.
	* sysdeps/unix/sysv/linux/i386/setfsuid.c (setfsuid): Likewise.
	* sysdeps/unix/sysv/linux/i386/setgid.c (__setgid): Likewise.
	* sysdeps/unix/sysv/linux/i386/setgroups.c (setgroups): Likewise.
	* sysdeps/unix/sysv/linux/i386/setregid.c (__setregid): Likewise.
	* sysdeps/unix/sysv/linux/i386/setresgid.c (setresgid): Likewise.
	* sysdeps/unix/sysv/linux/i386/setresuid.c (__setresuid): Likewise.
	* sysdeps/unix/sysv/linux/i386/setreuid.c (__setreuid): Likewise.
	* sysdeps/unix/sysv/linux/i386/setuid.c (__setuid): Likewise.
	* sysdeps/unix/sysv/linux/m68k/chown.c (__chown): Likewise.
	* sysdeps/unix/sysv/linux/arm/getresuid.c: New file.
	* sysdeps/unix/sysv/linux/arm/getresgid.c: New file.
	* sysdeps/unix/sysv/linux/arm/msgctl.c: New file.
	* sysdeps/unix/sysv/linux/arm/semctl.c: New file.
	* sysdeps/unix/sysv/linux/arm/shmctl.c: New file.
	* sysdeps/unix/sysv/linux/i386/msgctl.c: New file.
	* sysdeps/unix/sysv/linux/i386/semctl.c: New file.
	* sysdeps/unix/sysv/linux/i386/shmctl.c: New file.
	* sysdeps/unix/sysv/linux/m68k/getresgid.c: New file.
	* sysdeps/unix/sysv/linux/m68k/getresuid.c: New file.
	* sysdeps/unix/sysv/linux/m68k/msgctl.c: New file.
	* sysdeps/unix/sysv/linux/m68k/semctl.c: New file.
	* sysdeps/unix/sysv/linux/m68k/shmctl.c: New file.
	* sysdeps/unix/sysv/linux/sparc/sparc32/msgctl.c: New file.
	* sysdeps/unix/sysv/linux/sparc/sparc32/semctl.c: New file.
	* sysdeps/unix/sysv/linux/sparc/sparc32/shmctl.c: New file.
	* sysdeps/unix/sysv/linux/mips/syscalls.list (getresuid):
	Make syscall directly, no stubs needed.
	(getresgid): Likewise.
	* sysdeps/unix/sysv/linux/powerpc/syscalls.list (getresuid):
	Likewise.
	(getresgid): Likewise.

--- libc/sysdeps/unix/sysv/linux/getresgid.c.jj	Mon Jan 17 07:58:54 2000
+++ libc/sysdeps/unix/sysv/linux/getresgid.c	Tue Feb  1 16:00:41 2000
@@ -1,83 +0,0 @@
-/* Copyright (C) 1998, 2000 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 <unistd.h>
-#include <sys/types.h>
-
-#include <linux/posix_types.h>
-
-#include <sysdep.h>
-#include <sys/syscall.h>
-#include "kernel-features.h"
-
-#ifdef __NR_getresgid
-
-extern int __syscall_getresgid (__kernel_gid_t *rgid, __kernel_gid_t *egid,
-				__kernel_gid_t *sgid);
-
-# ifdef __NR_getresgid32
-extern int __syscall_getresgid32 (__kernel_gid32_t *rgid, __kernel_gid32_t *egid,
-				  __kernel_gid32_t *sgid);
-
-#  if __ASSUME_32BITUIDS == 0
-/* This variable is shared with all files that need to check for 32bit
-   uids.  */
-extern int __libc_missing_32bit_uids;
-#  endif
-# endif /* __NR_getresgid32 */
-
-
-int
-getresgid (gid_t *rgid, gid_t *egid, gid_t *sgid)
-{
-# if __ASSUME_32BITUIDS > 0
-  return INLINE_SYSCALL (getresgid32, 3, rgid, egid, sgid);
-# else  
-  __kernel_gid_t k_rgid, k_egid, k_sgid;
-  int result;
-#  ifdef __NR_getresgid32
-  if (!__libc_missing_32bit_uids)
-    {
-      int r;
-      int saved_errno = errno;
-
-      r = INLINE_SYSCALL (getresgid32, 3, rgid, egid, sgid);
-      if (r == 0 || errno != ENOSYS)
-	return r;
-
-      __set_errno (saved_errno);
-      __libc_missing_32bit_uids = 1;
-    }
-#  endif /* __NR_getresgid32 */
-
-  result = INLINE_SYSCALL (getresgid, 3, &k_rgid, &k_egid, &k_sgid);
-
-  if (result == 0)
-    {
-      *rgid = (gid_t) k_rgid;
-      *egid = (gid_t) k_egid;
-      *sgid = (gid_t) k_sgid;
-    }
-
-  return result;
-# endif
-}
-#else
-# include <sysdeps/generic/getresgid.c>
-#endif
--- libc/sysdeps/unix/sysv/linux/getresuid.c.jj	Mon Jan 17 07:58:54 2000
+++ libc/sysdeps/unix/sysv/linux/getresuid.c	Tue Feb  1 16:00:44 2000
@@ -1,82 +0,0 @@
-/* Copyright (C) 1998, 2000 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 <unistd.h>
-#include <sys/types.h>
-
-#include <linux/posix_types.h>
-
-#include <sysdep.h>
-#include <sys/syscall.h>
-
-#include "kernel-features.h"
-
-#ifdef __NR_getresuid
-
-extern int __syscall_getresuid (__kernel_uid_t *ruid, __kernel_uid_t *euid,
-				__kernel_uid_t *suid);
-
-# ifdef __NR_getresuid32
-extern int __syscall_getresuid32 (__kernel_uid32_t *ruid, __kernel_uid32_t *euid,
-				  __kernel_uid32_t *suid);
-#  if __ASSUME_32BITUIDS == 0
-/* This variable is shared with all files that need to check for 32bit
-   uids.  */
-extern int __libc_missing_32bit_uids;
-#  endif
-# endif /* __NR_getresuid32 */
-
-int
-getresuid (uid_t *ruid, uid_t *euid, uid_t *suid)
-{
-# if __ASSUME_32BITUIDS > 0
-  return INLINE_SYSCALL (getresuid32, 3, ruid, euid, suid);
-# else
-  __kernel_uid_t k_ruid, k_euid, k_suid;
-  int result;
-#  ifdef __NR_getresuid32
-  if (!__libc_missing_32bit_uids)
-    {
-      int r;
-      int saved_errno = errno;
-
-      r = INLINE_SYSCALL (getresuid32, 3, ruid, euid, suid);
-      if (r == 0 || errno != ENOSYS)
-	return r;
-
-      __set_errno (saved_errno);
-      __libc_missing_32bit_uids = 1;
-    }
-#  endif /* __NR_getresuid32 */
-
-  result = INLINE_SYSCALL (getresuid, 3, &k_ruid, &k_euid, &k_suid);
-
-  if (result == 0)
-    {
-      *ruid = (uid_t) k_ruid;
-      *euid = (uid_t) k_euid;
-      *suid = (uid_t) k_suid;
-    }
-
-  return result;
-# endif
-}
-#else
-# include <sysdeps/generic/getresuid.c>
-#endif
--- libc/sysdeps/unix/sysv/linux/arm/getresuid.c.jj	Tue Feb  1 16:01:43 2000
+++ libc/sysdeps/unix/sysv/linux/arm/getresuid.c	Tue Feb  1 16:01:40 2000
@@ -0,0 +1 @@
+#include <sysdeps/unix/sysv/linux/i386/getresuid.c>
--- libc/sysdeps/unix/sysv/linux/arm/getresgid.c.jj	Tue Feb  1 16:01:43 2000
+++ libc/sysdeps/unix/sysv/linux/arm/getresgid.c	Tue Feb  1 16:01:59 2000
@@ -0,0 +1 @@
+#include <sysdeps/unix/sysv/linux/i386/getresgid.c>
--- libc/sysdeps/unix/sysv/linux/arm/msgctl.c.jj	Tue Feb  1 16:01:43 2000
+++ libc/sysdeps/unix/sysv/linux/arm/msgctl.c	Tue Feb  1 16:49:04 2000
@@ -0,0 +1 @@
+#include <sysdeps/unix/sysv/linux/i386/msgctl.c>
--- libc/sysdeps/unix/sysv/linux/arm/semctl.c.jj	Tue Feb  1 16:01:43 2000
+++ libc/sysdeps/unix/sysv/linux/arm/semctl.c	Tue Feb  1 16:49:14 2000
@@ -0,0 +1 @@
+#include <sysdeps/unix/sysv/linux/i386/semctl.c>
--- libc/sysdeps/unix/sysv/linux/arm/shmctl.c.jj	Tue Feb  1 16:01:43 2000
+++ libc/sysdeps/unix/sysv/linux/arm/shmctl.c	Tue Feb  1 16:49:27 2000
@@ -0,0 +1 @@
+#include <sysdeps/unix/sysv/linux/i386/shmctl.c>
--- libc/sysdeps/unix/sysv/linux/i386/getresgid.c.jj	Tue Feb  1 16:01:03 2000
+++ libc/sysdeps/unix/sysv/linux/i386/getresgid.c	Tue Feb  1 16:19:56 2000
@@ -0,0 +1,83 @@
+/* Copyright (C) 1998, 2000 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 <unistd.h>
+#include <sys/types.h>
+
+#include <linux/posix_types.h>
+
+#include <sysdep.h>
+#include <sys/syscall.h>
+#include "kernel-features.h"
+
+#ifdef __NR_getresgid
+
+extern int __syscall_getresgid (__kernel_gid_t *rgid, __kernel_gid_t *egid,
+				__kernel_gid_t *sgid);
+
+# ifdef __NR_getresgid32
+extern int __syscall_getresgid32 (__kernel_gid32_t *rgid, __kernel_gid32_t *egid,
+				  __kernel_gid32_t *sgid);
+
+#  if __ASSUME_32BITUIDS == 0
+/* This variable is shared with all files that need to check for 32bit
+   uids.  */
+extern int __libc_missing_32bit_uids;
+#  endif
+# endif /* __NR_getresgid32 */
+
+
+int
+getresgid (gid_t *rgid, gid_t *egid, gid_t *sgid)
+{
+# if __ASSUME_32BITUIDS > 0
+  return INLINE_SYSCALL (getresgid32, 3, rgid, egid, sgid);
+# else  
+  __kernel_gid_t k_rgid, k_egid, k_sgid;
+  int result;
+#  ifdef __NR_getresgid32
+  if (__libc_missing_32bit_uids <= 0)
+    {
+      int r;
+      int saved_errno = errno;
+
+      r = INLINE_SYSCALL (getresgid32, 3, rgid, egid, sgid);
+      if (r == 0 || errno != ENOSYS)
+	return r;
+
+      __set_errno (saved_errno);
+      __libc_missing_32bit_uids = 1;
+    }
+#  endif /* __NR_getresgid32 */
+
+  result = INLINE_SYSCALL (getresgid, 3, &k_rgid, &k_egid, &k_sgid);
+
+  if (result == 0)
+    {
+      *rgid = (gid_t) k_rgid;
+      *egid = (gid_t) k_egid;
+      *sgid = (gid_t) k_sgid;
+    }
+
+  return result;
+# endif
+}
+#else
+# include <sysdeps/generic/getresgid.c>
+#endif
--- libc/sysdeps/unix/sysv/linux/i386/getresuid.c.jj	Tue Feb  1 16:01:06 2000
+++ libc/sysdeps/unix/sysv/linux/i386/getresuid.c	Tue Feb  1 16:20:05 2000
@@ -0,0 +1,82 @@
+/* Copyright (C) 1998, 2000 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 <unistd.h>
+#include <sys/types.h>
+
+#include <linux/posix_types.h>
+
+#include <sysdep.h>
+#include <sys/syscall.h>
+
+#include "kernel-features.h"
+
+#ifdef __NR_getresuid
+
+extern int __syscall_getresuid (__kernel_uid_t *ruid, __kernel_uid_t *euid,
+				__kernel_uid_t *suid);
+
+# ifdef __NR_getresuid32
+extern int __syscall_getresuid32 (__kernel_uid32_t *ruid, __kernel_uid32_t *euid,
+				  __kernel_uid32_t *suid);
+#  if __ASSUME_32BITUIDS == 0
+/* This variable is shared with all files that need to check for 32bit
+   uids.  */
+extern int __libc_missing_32bit_uids;
+#  endif
+# endif /* __NR_getresuid32 */
+
+int
+getresuid (uid_t *ruid, uid_t *euid, uid_t *suid)
+{
+# if __ASSUME_32BITUIDS > 0
+  return INLINE_SYSCALL (getresuid32, 3, ruid, euid, suid);
+# else
+  __kernel_uid_t k_ruid, k_euid, k_suid;
+  int result;
+#  ifdef __NR_getresuid32
+  if (__libc_missing_32bit_uids <= 0)
+    {
+      int r;
+      int saved_errno = errno;
+
+      r = INLINE_SYSCALL (getresuid32, 3, ruid, euid, suid);
+      if (r == 0 || errno != ENOSYS)
+	return r;
+
+      __set_errno (saved_errno);
+      __libc_missing_32bit_uids = 1;
+    }
+#  endif /* __NR_getresuid32 */
+
+  result = INLINE_SYSCALL (getresuid, 3, &k_ruid, &k_euid, &k_suid);
+
+  if (result == 0)
+    {
+      *ruid = (uid_t) k_ruid;
+      *euid = (uid_t) k_euid;
+      *suid = (uid_t) k_suid;
+    }
+
+  return result;
+# endif
+}
+#else
+# include <sysdeps/generic/getresuid.c>
+#endif
--- libc/sysdeps/unix/sysv/linux/i386/msgctl.c.jj	Tue Feb  1 16:05:16 2000
+++ libc/sysdeps/unix/sysv/linux/i386/msgctl.c	Tue Feb  1 16:38:59 2000
@@ -0,0 +1,151 @@
+/* Copyright (C) 1995, 1997, 1998, 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, August 1995.
+
+   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 <sys/msg.h>
+#include <ipc_priv.h>
+
+#include <sysdep.h>
+#include <string.h>
+#include <sys/syscall.h>
+
+#include "kernel-features.h"
+
+struct __old_msqid_ds
+{
+  struct __old_ipc_perm msg_perm;	/* structure describing operation permission */
+  struct msg *__msg_first;		/* pointer to first message on queue */
+  struct msg *__msg_last;		/* pointer to last message on queue */
+  __time_t msg_stime;			/* time of last msgsnd command */
+  __time_t msg_rtime;			/* time of last msgrcv command */
+  __time_t msg_ctime;			/* time of last change */
+  struct wait_queue *__wwait;		/* ??? */
+  struct wait_queue *__rwait;		/* ??? */
+  unsigned short int __msg_cbytes;	/* current number of bytes on queue */
+  unsigned short int msg_qnum;		/* number of messages currently on queue */
+  unsigned short int msg_qbytes;	/* max number of bytes allowed on queue */
+  __ipc_pid_t msg_lspid;		/* pid of last msgsnd() */
+  __ipc_pid_t msg_lrpid;		/* pid of last msgrcv() */
+};
+
+/* Allows to control internal state and destruction of message queue
+   objects.  */
+int __old_msgctl (int, int, struct __old_msqid_ds *);
+int __new_msgctl (int, int, struct msqid_ds *);
+
+#ifdef __NR_getuid32
+# if __ASSUME_32BITUIDS == 0
+/* This variable is shared with all files that need to check for 32bit
+   uids.  */
+extern int __libc_missing_32bit_uids;
+# endif
+#endif
+
+int
+__old_msgctl (int msqid, int cmd, struct __old_msqid_ds *buf)
+{
+  return INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, msqid, cmd, 0, buf);
+}
+
+int
+__new_msgctl (int msqid, int cmd, struct msqid_ds *buf)
+{
+#if __ASSUME_32BITUIDS > 0
+  return INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, msqid, cmd | __IPC_64, 0, buf);
+#else
+  switch (cmd) {
+    case MSG_STAT:
+    case IPC_STAT:
+    case IPC_SET:
+      break;
+    default:
+      return INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, msqid, cmd, 0, buf);
+  }
+
+  {
+    int save_errno, result;
+    struct __old_msqid_ds old;
+
+#ifdef __NR_getuid32
+    if (__libc_missing_32bit_uids <= 0)
+      {
+	if (__libc_missing_32bit_uids < 0)
+	  {
+	    save_errno = errno;
+
+	    /* Test presence of new IPC by testing for getuid32 syscall.  */
+	    result = INLINE_SYSCALL (getuid32, 0);
+	    if (result == -1 && errno == ENOSYS)
+	      __libc_missing_32bit_uids = 1;
+	    else
+	      __libc_missing_32bit_uids = 0;
+	    __set_errno(save_errno);
+	  }
+	if (__libc_missing_32bit_uids <= 0)
+	  {
+	    result = INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, msqid, cmd | __IPC_64, 0, buf);
+	    return result;
+	  }
+      }
+#endif
+    if (cmd == IPC_SET)
+      {
+	old.msg_perm.uid = buf->msg_perm.uid;
+	old.msg_perm.gid = buf->msg_perm.gid;
+	old.msg_perm.mode = buf->msg_perm.mode;
+	old.msg_qbytes = buf->msg_qbytes;
+	if (old.msg_perm.uid != buf->msg_perm.uid ||
+	    old.msg_perm.gid != buf->msg_perm.gid ||
+	    old.msg_qbytes != buf->msg_qbytes)
+	  {
+	    __set_errno (EINVAL);
+	    return -1;
+	  }
+      }
+    result = INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, msqid, cmd, 0, &old);
+    if (result != -1 && cmd != IPC_SET)
+      {
+	memset(buf, 0, sizeof(*buf));
+	buf->msg_perm.__key = old.msg_perm.__key;
+	buf->msg_perm.uid = old.msg_perm.uid;
+	buf->msg_perm.gid = old.msg_perm.gid;
+	buf->msg_perm.cuid = old.msg_perm.cuid;
+	buf->msg_perm.cgid = old.msg_perm.cgid;
+	buf->msg_perm.mode = old.msg_perm.mode;
+	buf->msg_perm.__seq = old.msg_perm.__seq;
+	buf->msg_stime = old.msg_stime;
+	buf->msg_rtime = old.msg_rtime;
+	buf->msg_ctime = old.msg_ctime;
+	buf->__msg_cbytes = old.__msg_cbytes;
+	buf->msg_qnum = old.msg_qnum;
+	buf->msg_qbytes = old.msg_qbytes;
+	buf->msg_lspid = old.msg_lspid;
+	buf->msg_lrpid = old.msg_lrpid;
+      }
+    return result;
+  }
+#endif
+}
+
+#if defined PIC && DO_VERSIONING
+default_symbol_version (__new_msgctl, msgctl, GLIBC_2.2);
+symbol_version (__old_msgctl, msgctl, GLIBC_2.0);
+#else
+weak_alias (__new_msgctl, msgctl);
+#endif
--- libc/sysdeps/unix/sysv/linux/i386/chown.c.jj	Wed Jan 19 21:36:10 2000
+++ libc/sysdeps/unix/sysv/linux/i386/chown.c	Tue Feb  1 16:17:59 2000
@@ -63,7 +63,7 @@ __real_chown (const char *file, uid_t ow
     {
       int saved_errno = errno;
 #  ifdef __NR_chown32
-      if (!__libc_missing_32bit_uids)
+      if (__libc_missing_32bit_uids <= 0)
 	{
 	  int result;
 	  int saved_errno = errno;
@@ -99,7 +99,7 @@ __real_chown (const char *file, uid_t ow
 # else
   /* !__ASSUME_32BITUIDS && ASSUME_LCHOWN_SYSCALL  */
 #  ifdef __NR_chown32
-  if (!__libc_missing_32bit_uids)
+  if (__libc_missing_32bit_uids <= 0)
     {
       int result;
       int saved_errno = errno;
--- libc/sysdeps/unix/sysv/linux/i386/fchown.c.jj	Wed Jan 19 21:36:10 2000
+++ libc/sysdeps/unix/sysv/linux/i386/fchown.c	Tue Feb  1 16:18:29 2000
@@ -45,7 +45,7 @@ __fchown (int fd, uid_t owner, gid_t gro
   return INLINE_SYSCALL (fchown32, 3, fd, owner, group);
 #else
 # ifdef __NR_fchown32
-  if (!__libc_missing_32bit_uids)
+  if (__libc_missing_32bit_uids <= 0)
     {
       int result;
       int saved_errno = errno;
--- libc/sysdeps/unix/sysv/linux/i386/getegid.c.jj	Mon Jan 17 06:19:04 2000
+++ libc/sysdeps/unix/sysv/linux/i386/getegid.c	Tue Feb  1 16:18:41 2000
@@ -41,7 +41,7 @@ __getegid (void)
   return INLINE_SYSCALL (getegid32, 0);
 #else
 # ifdef __NR_getegid32
-  if (!__libc_missing_32bit_uids)
+  if (__libc_missing_32bit_uids <= 0)
     {
       int result;
       int saved_errno = errno;
--- libc/sysdeps/unix/sysv/linux/i386/geteuid.c.jj	Mon Jan 17 06:19:11 2000
+++ libc/sysdeps/unix/sysv/linux/i386/geteuid.c	Tue Feb  1 16:18:50 2000
@@ -41,7 +41,7 @@ __geteuid (void)
   return INLINE_SYSCALL (geteuid32, 0);
 #else
 # ifdef __NR_geteuid32
-  if (!__libc_missing_32bit_uids)
+  if (__libc_missing_32bit_uids <= 0)
     {
       int result;
       int saved_errno = errno;
--- libc/sysdeps/unix/sysv/linux/i386/getgroups.c.jj	Mon Jan 17 07:58:55 2000
+++ libc/sysdeps/unix/sysv/linux/i386/getgroups.c	Tue Feb  1 16:19:04 2000
@@ -56,7 +56,7 @@ __getgroups (int n, gid_t *groups)
       int i, ngids;
       __kernel_gid_t kernel_groups[n = MIN (n, __sysconf (_SC_NGROUPS_MAX))];
 # ifdef __NR_getgroups32
-      if (!__libc_missing_32bit_uids)
+      if (__libc_missing_32bit_uids <= 0)
 	{
 	  int result;
 	  int saved_errno = errno;
--- libc/sysdeps/unix/sysv/linux/i386/getuid.c.jj	Mon Jan 17 06:19:18 2000
+++ libc/sysdeps/unix/sysv/linux/i386/getuid.c	Tue Feb  1 16:17:37 2000
@@ -30,8 +30,11 @@ extern int __syscall_getuid (void);
 extern int __syscall_getuid32 (void);
 # if __ASSUME_32BITUIDS == 0
 /* This variable is shared with all files that need to check for 32bit
-   uids.  This is the definition */
-int __libc_missing_32bit_uids;
+   uids.  This is the definition.
+   -1 if libc does not know yet whether kernel has 32bit uids or not.
+   0 if it does have them.
+   1 if it does not have them.  */
+int __libc_missing_32bit_uids = -1;
 # endif
 #endif /* __NR_getuid32 */
 
@@ -42,7 +45,7 @@ __getuid (void)
   return INLINE_SYSCALL (getuid32, 0);
 #else
 # ifdef __NR_getuid32
-  if (!__libc_missing_32bit_uids)
+  if (__libc_missing_32bit_uids <= 0)
     {
       int result;
       int saved_errno = errno;
--- libc/sysdeps/unix/sysv/linux/i386/getgid.c.jj	Mon Jan 17 06:19:26 2000
+++ libc/sysdeps/unix/sysv/linux/i386/getgid.c	Tue Feb  1 16:19:42 2000
@@ -42,7 +42,7 @@ __getgid (void)
   return INLINE_SYSCALL (getgid32, 0);
 #else
 # ifdef __NR_getgid32
-  if (!__libc_missing_32bit_uids)
+  if (__libc_missing_32bit_uids <= 0)
     {
       int result;
       int saved_errno = errno;
--- libc/sysdeps/unix/sysv/linux/i386/lchown.c.jj	Wed Jan 19 21:36:10 2000
+++ libc/sysdeps/unix/sysv/linux/i386/lchown.c	Tue Feb  1 16:20:27 2000
@@ -46,7 +46,7 @@ __lchown (const char *file, uid_t owner,
   return INLINE_SYSCALL (lchown32, 3, file, owner, group);
 # else
 #  ifdef __NR_lchown32
-  if (!__libc_missing_32bit_uids)
+  if (__libc_missing_32bit_uids <= 0)
     {
       int result;
       int saved_errno = errno;
--- libc/sysdeps/unix/sysv/linux/i386/setfsgid.c.jj	Mon Jan 17 07:58:55 2000
+++ libc/sysdeps/unix/sysv/linux/i386/setfsgid.c	Tue Feb  1 16:21:44 2000
@@ -46,7 +46,7 @@ setfsgid (gid_t gid)
   return INLINE_SYSCALL (setfsgid32, 1, gid);
 # else
 #  ifdef __NR_setfsgid32
-  if (!__libc_missing_32bit_uids)
+  if (__libc_missing_32bit_uids <= 0)
     {
       int result;
       int saved_errno = errno;
--- libc/sysdeps/unix/sysv/linux/i386/setfsuid.c.jj	Mon Jan 17 07:58:55 2000
+++ libc/sysdeps/unix/sysv/linux/i386/setfsuid.c	Tue Feb  1 16:22:05 2000
@@ -46,7 +46,7 @@ setfsuid (uid_t uid)
   return INLINE_SYSCALL (setfsuid32, 1, uid);
 # else  
 #  ifdef __NR_setfsuid32
-  if (!__libc_missing_32bit_uids)
+  if (__libc_missing_32bit_uids <= 0)
     {
       int result;
       int saved_errno = errno;
--- libc/sysdeps/unix/sysv/linux/i386/setgid.c.jj	Mon Jan 17 07:58:55 2000
+++ libc/sysdeps/unix/sysv/linux/i386/setgid.c	Tue Feb  1 16:22:29 2000
@@ -45,7 +45,7 @@ __setgid (gid_t gid)
   return INLINE_SYSCALL (setgid32, 1, gid);
 #else
 # ifdef __NR_setgid32
-  if (!__libc_missing_32bit_uids)
+  if (__libc_missing_32bit_uids <= 0)
     {
       int result;
       int saved_errno = errno;
--- libc/sysdeps/unix/sysv/linux/i386/setgroups.c.jj	Mon Jan 17 07:58:55 2000
+++ libc/sysdeps/unix/sysv/linux/i386/setgroups.c	Tue Feb  1 16:22:55 2000
@@ -57,7 +57,7 @@ setgroups (size_t n, const gid_t *groups
       size_t i;
       __kernel_gid_t kernel_groups[n];
 # ifdef __NR_setgroups32
-      if (!__libc_missing_32bit_uids)
+      if (__libc_missing_32bit_uids <= 0)
 	{
 	  int result;
 	  int saved_errno = errno;
--- libc/sysdeps/unix/sysv/linux/i386/setregid.c.jj	Wed Jan 19 21:36:10 2000
+++ libc/sysdeps/unix/sysv/linux/i386/setregid.c	Tue Feb  1 16:23:10 2000
@@ -45,7 +45,7 @@ __setregid (gid_t rgid, gid_t egid)
   return INLINE_SYSCALL (setregid32, 2, rgid, egid);
 #else
 # ifdef __NR_setregid32
-  if (!__libc_missing_32bit_uids)
+  if (__libc_missing_32bit_uids <= 0)
     {
       int result;
       int saved_errno = errno;
--- libc/sysdeps/unix/sysv/linux/i386/setresgid.c.jj	Wed Jan 19 21:36:10 2000
+++ libc/sysdeps/unix/sysv/linux/i386/setresgid.c	Tue Feb  1 16:23:25 2000
@@ -48,7 +48,7 @@ setresgid (gid_t rgid, gid_t egid, gid_t
   return INLINE_SYSCALL (setresgid32, 3, rgid, egid, sgid);
 # else
 #  ifdef __NR_setresgid32
-  if (!__libc_missing_32bit_uids)
+  if (__libc_missing_32bit_uids <= 0)
     {
       int result;
       int saved_errno = errno;
--- libc/sysdeps/unix/sysv/linux/i386/setresuid.c.jj	Wed Jan 19 21:36:10 2000
+++ libc/sysdeps/unix/sysv/linux/i386/setresuid.c	Tue Feb  1 16:23:48 2000
@@ -48,7 +48,7 @@ __setresuid (uid_t ruid, uid_t euid, uid
   return INLINE_SYSCALL (setresuid32, 3, ruid, euid, suid);
 # else
 #  ifdef __NR_setresuid32
-  if (!__libc_missing_32bit_uids)
+  if (__libc_missing_32bit_uids <= 0)
     {
       int result;
       int saved_errno = errno;
--- libc/sysdeps/unix/sysv/linux/i386/setreuid.c.jj	Wed Jan 19 21:36:10 2000
+++ libc/sysdeps/unix/sysv/linux/i386/setreuid.c	Tue Feb  1 16:24:02 2000
@@ -45,7 +45,7 @@ __setreuid (uid_t ruid, uid_t euid)
   return INLINE_SYSCALL (setreuid32, 2, ruid, euid);
 #else
 # ifdef __NR_setreuid32
-  if (!__libc_missing_32bit_uids)
+  if (__libc_missing_32bit_uids <= 0)
     {
       int result;
       int saved_errno = errno;
--- libc/sysdeps/unix/sysv/linux/i386/setuid.c.jj	Mon Jan 17 07:58:55 2000
+++ libc/sysdeps/unix/sysv/linux/i386/setuid.c	Tue Feb  1 16:24:20 2000
@@ -44,7 +44,7 @@ __setuid (uid_t uid)
   return INLINE_SYSCALL (setuid32, 1, uid);
 #else
 # ifdef __NR_setuid32
-  if (!__libc_missing_32bit_uids)
+  if (__libc_missing_32bit_uids <= 0)
     {
       int result;
       int saved_errno = errno;
--- libc/sysdeps/unix/sysv/linux/i386/semctl.c.jj	Tue Feb  1 16:25:15 2000
+++ libc/sysdeps/unix/sysv/linux/i386/semctl.c	Tue Feb  1 16:41:20 2000
@@ -0,0 +1,173 @@
+/* Copyright (C) 1995, 1997, 1998, 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, August 1995.
+
+   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 <stdarg.h>
+#include <sys/sem.h>
+#include <ipc_priv.h>
+
+#include <sysdep.h>
+#include <string.h>
+#include <sys/syscall.h>
+
+#include "kernel-features.h"
+
+struct __old_semid_ds
+{
+  struct __old_ipc_perm sem_perm;	/* operation permission struct */
+  __time_t sem_otime;			/* last semop() time */
+  __time_t sem_ctime;			/* last time changed by semctl() */
+  struct sem *__sembase;		/* ptr to first semaphore in array */
+  struct sem_queue *__sem_pending;	/* pending operations */
+  struct sem_queue *__sem_pending_last; /* last pending operation */
+  struct sem_undo *__undo;		/* ondo requests on this array */
+  unsigned short int sem_nsems;		/* number of semaphores in set */
+};
+
+/* Define a `union semun' suitable for Linux here.  */
+union semun
+{
+  int val;			/* value for SETVAL */
+  struct semid_ds *buf;		/* buffer for IPC_STAT & IPC_SET */
+  unsigned short int *array;	/* array for GETALL & SETALL */
+  struct seminfo *__buf;	/* buffer for IPC_INFO */
+};
+
+#ifdef __NR_getuid32
+# if __ASSUME_32BITUIDS == 0
+/* This variable is shared with all files that need to check for 32bit
+   uids.  */
+extern int __libc_missing_32bit_uids;
+# endif
+#endif
+
+/* Return identifier for array of NSEMS semaphores associated with
+   KEY.  */
+int __old_semctl (int semid, int semnum, int cmd, ...);
+int __new_semctl (int semid, int semnum, int cmd, ...);
+
+int
+__old_semctl (int semid, int semnum, int cmd, ...)
+{
+  union semun arg;
+  va_list ap;
+
+  va_start (ap, cmd);
+
+  /* Get the argument.  */
+  arg = va_arg (ap, union semun);
+
+  va_end (ap);
+
+  return INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd, &arg);
+}
+
+int
+__new_semctl (int semid, int semnum, int cmd, ...)
+{
+  union semun arg;
+  va_list ap;
+
+  va_start (ap, cmd);
+
+  /* Get the argument.  */
+  arg = va_arg (ap, union semun);
+
+  va_end (ap);
+
+#if __ASSUME_32BITUIDS > 0
+  return INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd | __IPC_64, &arg);
+#else
+  switch (cmd) {
+    case SEM_STAT:
+    case IPC_STAT:
+    case IPC_SET:
+      break;
+    default:
+      return INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd, &arg);
+  }
+
+  {
+    int save_errno, result;
+    struct __old_semid_ds old;
+    struct semid_ds *buf;
+
+#ifdef __NR_getuid32
+    if (__libc_missing_32bit_uids <= 0)
+      {
+	if (__libc_missing_32bit_uids < 0)
+	  {
+	    save_errno = errno;
+
+	    /* Test presence of new IPC by testing for getuid32 syscall.  */
+	    result = INLINE_SYSCALL (getuid32, 0);
+	    if (result == -1 && errno == ENOSYS)
+	      __libc_missing_32bit_uids = 1;
+	    else
+	      __libc_missing_32bit_uids = 0;
+	    __set_errno(save_errno);
+	  }
+	if (__libc_missing_32bit_uids <= 0)
+	  {
+	    result = INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd | __IPC_64, &arg);
+	    return result;
+	  }
+      }
+#endif
+
+    buf = arg.buf;
+    arg.buf = (struct semid_ds *)&old;
+    if (cmd == IPC_SET)
+      {
+	old.sem_perm.uid = buf->sem_perm.uid;
+	old.sem_perm.gid = buf->sem_perm.gid;
+	old.sem_perm.mode = buf->sem_perm.mode;
+	if (old.sem_perm.uid != buf->sem_perm.uid ||
+	    old.sem_perm.gid != buf->sem_perm.gid)
+	  {
+	    __set_errno (EINVAL);
+	    return -1;
+	  }
+      }
+    result = INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd, &arg);
+    if (result != -1 && cmd != IPC_SET)
+      {
+	memset(buf, 0, sizeof(*buf));
+	buf->sem_perm.__key = old.sem_perm.__key;
+	buf->sem_perm.uid = old.sem_perm.uid;
+	buf->sem_perm.gid = old.sem_perm.gid;
+	buf->sem_perm.cuid = old.sem_perm.cuid;
+	buf->sem_perm.cgid = old.sem_perm.cgid;
+	buf->sem_perm.mode = old.sem_perm.mode;
+	buf->sem_perm.__seq = old.sem_perm.__seq;
+	buf->sem_otime = old.sem_otime;
+	buf->sem_ctime = old.sem_ctime;
+	buf->sem_nsems = old.sem_nsems;
+      }
+    return result;
+  }
+#endif
+}
+
+#if defined PIC && DO_VERSIONING
+default_symbol_version (__new_semctl, semctl, GLIBC_2.2);
+symbol_version (__old_semctl, semctl, GLIBC_2.0);
+#else
+weak_alias (__new_semctl, semctl);
+#endif
--- libc/sysdeps/unix/sysv/linux/i386/shmctl.c.jj	Tue Feb  1 16:47:11 2000
+++ libc/sysdeps/unix/sysv/linux/i386/shmctl.c	Tue Feb  1 16:45:56 2000
@@ -0,0 +1,173 @@
+/* Copyright (C) 1995, 1997, 1998, 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, August 1995.
+
+   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 <sys/shm.h>
+#include <ipc_priv.h>
+
+#include <sysdep.h>
+#include <string.h>
+#include <sys/syscall.h>
+#include <bits/wordsize.h>
+
+#include "kernel-features.h"
+
+struct __old_shmid_ds
+{
+  struct __old_ipc_perm shm_perm;	/* operation permission struct */
+  int shm_segsz;			/* size of segment in bytes */
+  __time_t shm_atime;			/* time of last shmat() */
+  __time_t shm_dtime;			/* time of last shmdt() */
+  __time_t shm_ctime;			/* time of last change by shmctl() */
+  __ipc_pid_t shm_cpid;			/* pid of creator */
+  __ipc_pid_t shm_lpid;			/* pid of last shmop */
+  unsigned short int shm_nattch;	/* number of current attaches */
+  unsigned short int __shm_npages;	/* size of segment (pages) */
+  unsigned long int *__shm_pages;	/* array of ptrs to frames -> SHMMAX */
+  struct vm_area_struct *__attaches;	/* descriptors for attaches */
+};
+
+struct __old_shminfo
+{
+  int shmmax;
+  int shmmin;
+  int shmmni;
+  int shmseg;
+  int shmall;
+};
+
+#ifdef __NR_getuid32
+# if __ASSUME_32BITUIDS == 0
+/* This variable is shared with all files that need to check for 32bit
+   uids.  */
+extern int __libc_missing_32bit_uids;
+# endif
+#endif
+
+/* Provide operations to control over shared memory segments.  */
+int __old_shmctl (int, int, struct __old_shmid_ds *);
+int __new_shmctl (int, int, struct shmid_ds *);
+
+int
+__old_shmctl (int shmid, int cmd, struct __old_shmid_ds *buf)
+{
+  return INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd, 0, buf);
+}
+
+int
+__new_shmctl (int shmid, int cmd, struct shmid_ds *buf)
+{
+#if __ASSUME_32BITUIDS > 0
+  return INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd | __IPC_64, 0, buf);
+#else
+  switch (cmd) {
+    case SHM_STAT:
+    case IPC_STAT:
+    case IPC_SET:
+#if __WORDSIZE != 32
+    case IPC_INFO:
+#endif
+      break;
+    default:
+      return INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd, 0, buf);
+  }
+
+  {
+    int save_errno = result;
+    struct __old_shmid_ds old;
+
+#ifdef __NR_getuid32
+    if (__libc_missing_32bit_uids <= 0)
+      {
+	if (__libc_missing_32bit_uids < 0)
+	  {
+	    save_errno = errno;
+
+	    /* Test presence of new IPC by testing for getuid32 syscall.  */
+	    result = INLINE_SYSCALL (getuid32, 0);
+	    if (result == -1 && errno == ENOSYS)
+	      __libc_missing_32bit_uids = 1;
+	    else
+	      __libc_missing_32bit_uids = 0;
+	    __set_errno(save_errno);
+	  }
+	if (__libc_missing_32bit_uids <= 0)
+	  {
+	    result = INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd | __IPC_64, 0, buf);
+	    return result;
+	  }
+      }
+#endif
+
+    if (cmd == IPC_SET)
+      {
+	old.shm_perm.uid = buf->shm_perm.uid;
+	old.shm_perm.gid = buf->shm_perm.gid;
+	old.shm_perm.mode = buf->shm_perm.mode;
+	if (old.shm_perm.uid != buf->shm_perm.uid ||
+	    old.shm_perm.gid != buf->shm_perm.gid)
+	  {
+	    __set_errno (EINVAL);
+	    return -1;
+	  }
+      }
+    result = INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd, 0, &old);
+    if (result != -1 && (cmd == SHM_STAT || cmd == IPC_STAT))
+      {
+	memset(buf, 0, sizeof(*buf));
+	buf->shm_perm.__key = old.shm_perm.__key;
+	buf->shm_perm.uid = old.shm_perm.uid;
+	buf->shm_perm.gid = old.shm_perm.gid;
+	buf->shm_perm.cuid = old.shm_perm.cuid;
+	buf->shm_perm.cgid = old.shm_perm.cgid;
+	buf->shm_perm.mode = old.shm_perm.mode;
+	buf->shm_perm.__seq = old.shm_perm.__seq;
+	buf->shm_atime = old.shm_atime;
+	buf->shm_dtime = old.shm_dtime;
+	buf->shm_ctime = old.shm_ctime;
+	buf->shm_segsz = old.shm_segsz;
+	buf->shm_nattch = old.shm_nattch;
+	buf->shm_cpid = old.shm_cpid;
+	buf->shm_lpid = old.shm_lpid;
+      }
+#if __WORDSIZE != 32
+    else if (result != -1 && cmd == IPC_INFO)
+      {
+	struct __old_shminfo *oldi = (struct __old_shminfo *)&old;
+	struct shminfo *i = (struct shminfo *)buf;
+
+	memset(i, 0, sizeof(*i));
+	i->shmmax = oldi->shmmax;
+	i->shmmin = oldi->shmmin;
+	i->shmmni = oldi->shmmni;
+	i->shmseg = oldi->shmseg;
+	i->shmall = oldi->shmall;
+      }
+#endif
+    return result;
+  }
+#endif
+}
+
+#if defined PIC && DO_VERSIONING
+default_symbol_version (__new_shmctl, shmctl, GLIBC_2.2);
+symbol_version (__old_shmctl, shmctl, GLIBC_2.0);
+#else
+weak_alias (__new_shmctl, shmctl);
+#endif
--- libc/sysdeps/unix/sysv/linux/m68k/getresgid.c.jj	Tue Feb  1 16:01:43 2000
+++ libc/sysdeps/unix/sysv/linux/m68k/getresgid.c	Tue Feb  1 16:01:59 2000
@@ -0,0 +1 @@
+#include <sysdeps/unix/sysv/linux/i386/getresgid.c>
--- libc/sysdeps/unix/sysv/linux/m68k/getresuid.c.jj	Tue Feb  1 16:01:43 2000
+++ libc/sysdeps/unix/sysv/linux/m68k/getresuid.c	Tue Feb  1 16:01:40 2000
@@ -0,0 +1 @@
+#include <sysdeps/unix/sysv/linux/i386/getresuid.c>
--- libc/sysdeps/unix/sysv/linux/m68k/chown.c.jj	Wed Jan 19 21:36:11 2000
+++ libc/sysdeps/unix/sysv/linux/m68k/chown.c	Tue Feb  1 16:24:44 2000
@@ -45,7 +45,7 @@ __chown (const char *file, uid_t owner, 
   return INLINE_SYSCALL (chown32, 3, file, owner, group);
 #else
 # ifdef __NR_chown32
-  if (!__libc_missing_32bit_uids)
+  if (__libc_missing_32bit_uids <= 0)
     {
       int result;
       int saved_errno = errno;
--- libc/sysdeps/unix/sysv/linux/m68k/msgctl.c.jj	Tue Feb  1 16:01:43 2000
+++ libc/sysdeps/unix/sysv/linux/m68k/msgctl.c	Tue Feb  1 16:49:04 2000
@@ -0,0 +1 @@
+#include <sysdeps/unix/sysv/linux/i386/msgctl.c>
--- libc/sysdeps/unix/sysv/linux/m68k/semctl.c.jj	Tue Feb  1 16:01:43 2000
+++ libc/sysdeps/unix/sysv/linux/m68k/semctl.c	Tue Feb  1 16:49:14 2000
@@ -0,0 +1 @@
+#include <sysdeps/unix/sysv/linux/i386/semctl.c>
--- libc/sysdeps/unix/sysv/linux/m68k/shmctl.c.jj	Tue Feb  1 16:01:43 2000
+++ libc/sysdeps/unix/sysv/linux/m68k/shmctl.c	Tue Feb  1 16:49:27 2000
@@ -0,0 +1 @@
+#include <sysdeps/unix/sysv/linux/i386/shmctl.c>
--- libc/sysdeps/unix/sysv/linux/mips/syscalls.list.jj	Wed Dec  8 17:00:09 1999
+++ libc/sysdeps/unix/sysv/linux/mips/syscalls.list	Tue Feb  1 16:03:39 2000
@@ -56,8 +56,8 @@ s_execve	execve	execve		3	__syscall_exec
 s_getcwd	getcwd	getcwd		2	__syscall_getcwd
 s_getdents	getdents getdents	3	__syscall_getdents
 s_getpriority	getpriority getpriority	2	__syscall_getpriority
-s_getresgid	getresgid getresgid	3	__syscall_getresgid
-s_getresuid	getresuid getresuid	3	__syscall_getresuid
+getresgid	-	getresgid	3	getresgid
+getresuid	-	getresuid	3	getresuid
 s_ipc		msgget	ipc		5	__syscall_ipc
 s_poll		poll	poll		3	__syscall_poll
 s_pread64	pread64	pread		6	__syscall_pread
--- libc/sysdeps/unix/sysv/linux/powerpc/syscalls.list.jj	Fri Jan 28 14:54:12 2000
+++ libc/sysdeps/unix/sysv/linux/powerpc/syscalls.list	Tue Feb  1 16:04:01 2000
@@ -18,8 +18,8 @@ s_getcwd	getcwd	getcwd		2	__syscall_getc
 s_getdents	getdents getdents	3	__syscall_getdents
 s_getpmsg	getpmsg	getpmsg		5	__syscall_getpmsg
 s_getpriority	getpriority getpriority	2	__syscall_getpriority
-s_getresgid	getresgid getresgid	3	__syscall_getresgid
-s_getresuid	getresuid getresuid	3	__syscall_getresuid
+getresgid	-	getresgid	3	getresgid
+getresuid	-	getresuid	3	getresuid
 s_getrlimit	getrlimit getrlimit	2	__syscall_getrlimit
 s_lstat64	lxstat64 lstat64	2	__syscall_lstat64
 s_mmap2		mmap64	mmap2		6	__syscall_mmap2
--- libc/sysdeps/unix/sysv/linux/sparc/sparc32/msgctl.c.jj	Tue Feb  1 16:01:43 2000
+++ libc/sysdeps/unix/sysv/linux/sparc/sparc32/msgctl.c	Tue Feb  1 16:49:04 2000
@@ -0,0 +1 @@
+#include <sysdeps/unix/sysv/linux/i386/msgctl.c>
--- libc/sysdeps/unix/sysv/linux/sparc/sparc32/semctl.c.jj	Tue Feb  1 16:01:43 2000
+++ libc/sysdeps/unix/sysv/linux/sparc/sparc32/semctl.c	Tue Feb  1 16:49:14 2000
@@ -0,0 +1 @@
+#include <sysdeps/unix/sysv/linux/i386/semctl.c>
--- libc/sysdeps/unix/sysv/linux/sparc/sparc32/shmctl.c.jj	Tue Feb  1 16:01:43 2000
+++ libc/sysdeps/unix/sysv/linux/sparc/sparc32/shmctl.c	Tue Feb  1 16:49:27 2000
@@ -0,0 +1 @@
+#include <sysdeps/unix/sysv/linux/i386/shmctl.c>


Cheers,
    Jakub
___________________________________________________________________
Jakub Jelinek | jakub@redhat.com | http://sunsite.mff.cuni.cz/~jj
Linux version 2.3.41 on a sparc64 machine (1343.49 BogoMips)
___________________________________________________________________

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]