[PATCH v2] sysv: linux: Add 64-bit time_t variant for msgctl

Alistair Francis alistair23@gmail.com
Wed Jul 8 17:56:12 GMT 2020


On Wed, Jul 8, 2020 at 8:33 AM Adhemerval Zanella via Libc-alpha
<libc-alpha@sourceware.org> wrote:
>
> This is a small updated version that basically does:
>
>   git mv include/sys/msg.h sysdeps/unix/sysv/linux/include/sys/msg.h
>
> It moves the sysvipc to be Linux specific, since the generic version
> does implement _libc_msgsnd or __libc_msgrcv; and avoid a build failure
> on Hurd (since it does not provide struct_msqid64_ds.h).
>
> ---
>
> To provide a y2038 safe interface a new symbol __msgctl64 is added
> and __msgctl is change to call it instead (it adds some extra buffer
> coping for the 32 bit time_t implementation).
>
> Two new structures are added:
>
>   1. kernel_msqid64_ds: used internally only on 32-bit architectures
>      to issue the syscall.  A handful of architectures (hppa, i386, mips,
>      powerpc32, and sparc32) require specific implementations due to
>      their kernel ABI.
>
>   2. msqid_ds64: this is only for __TIMESIZE != 64 to use along with
>      the 64-bit semctl.  It is different than the kernel struct because
>      the exported 64-bit time_t might require different alignment
>      depending on the architecture ABI.
>
> So the resulting implementation does:
>
>   1. For 64-bit architectures it assumes msqid_ds already contains
>      64-bit time_t fields and will result in just the __msgctl symbol
>      using the __msgctl64 code.  The msgid_ds argument is passed as-is
>      to the syscall.
>
>   2. For 32-bit architectures with default 64-bit time_t (newer ABIs
>      such riscv32 or arc), it will also result in only one exported
>      symbol but with the required high/low time handling.
>
>   3. Finally for 32-bit architecture with both 32-bit and 64-bit time_t
>      support we follow the already set way to provide one symbol with
>      64-bit time_t support and implement the 32-bit time_t support using
>      the 64-bit time_t.
>
>      The default 32-bit symbol will allocate and copy the msqid_ds
>      over multiple buffers, but this should be deprecated in favor
>      of the __msgctl64 anyway.
>
> Checked on i686-linux-gnu and x86_64-linux-gnu.  I also did some sniff
> tests on powerpc, powerpc64, mips, mips64, armhf, sparcv9, and
> sparc64.
>
> Tested-by: Carlos O'Donell <carlos@redhat.com>
> Reviewed-by: Carlos O'Donell <carlos@redhat.com>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  .../sysv/linux/bits/types/struct_msqid64_ds.h |  38 ++++
>  .../sysv/linux/bits/types/struct_msqid_ds.h   |   6 +-
>  .../linux/hppa/bits/types/struct_msqid_ds.h   |   6 +-
>  .../linux/hppa/struct_kernel_msqid64_ds.h     |  18 ++
>  .../linux/i386/struct_kernel_msqid64_ds.h     |  18 ++
>  .../unix/sysv/linux/include}/sys/msg.h        |  10 +
>  .../linux/mips/bits/types/struct_msqid_ds.h   |  12 +-
>  .../linux/mips/struct_kernel_msqid64_ds.h     |  33 ++++
>  sysdeps/unix/sysv/linux/msgctl.c              | 179 ++++++++++++++----
>  .../powerpc/bits/types/struct_msqid_ds.h      |   6 +-
>  .../powerpc32/struct_kernel_msqid64_ds.h      |  18 ++
>  sysdeps/unix/sysv/linux/semctl.c              |  27 +--
>  .../linux/sparc/bits/types/struct_msqid_ds.h  |   6 +-
>  .../sparc/sparc32/struct_kernel_msqid64_ds.h  |  18 ++
>  .../sysv/linux/struct_kernel_msqid64_ds.h     |  19 ++
>  15 files changed, 350 insertions(+), 64 deletions(-)
>  create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h
>  rename {include => sysdeps/unix/sysv/linux/include}/sys/msg.h (55%)
>  create mode 100644 sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h
>  create mode 100644 sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h
>
> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h
> new file mode 100644
> index 0000000000..3536c8ea62
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_msqid64_ds.h
> @@ -0,0 +1,38 @@
> +/* Generic implementation of the SysV message struct msqid64_ds.
> +   Copyright (C) 2020 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 Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 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
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef _SYS_MSG_H
> +# error "Never use <bits/msq.h> directly; include <sys/msg.h> instead."
> +#endif
> +
> +#if __TIMESIZE == 64
> +# define __msqid64_ds msqid_ds
> +#else
> +struct __msqid64_ds
> +{
> +  struct ipc_perm msg_perm;    /* structure describing operation permission */
> +  __time64_t msg_stime;                /* time of last msgsnd command */
> +  __time64_t msg_rtime;                /* time of last msgsnd command */
> +  __time64_t msg_ctime;                /* time of last change */
> +  __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */
> +  msgqnum_t msg_qnum;          /* number of messages currently on queue */
> +  msglen_t msg_qbytes;         /* max number of bytes allowed on queue */
> +  __pid_t msg_lspid;           /* pid of last msgsnd() */
> +  __pid_t msg_lrpid;           /* pid of last msgrcv() */
> +};
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
> index 32173a7b60..43b38175ad 100644
> --- a/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
> +++ b/sysdeps/unix/sysv/linux/bits/types/struct_msqid_ds.h
> @@ -27,11 +27,11 @@ struct msqid_ds
>    struct ipc_perm msg_perm;    /* structure describing operation permission */
>  #if __TIMESIZE == 32
>    __time_t msg_stime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_rtime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_ctime;          /* time of last change */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;
>  #else
>    __time_t msg_stime;          /* time of last msgsnd command */
>    __time_t msg_rtime;          /* time of last msgsnd command */
> diff --git a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
> index 3cf70e36c4..16eac46941 100644
> --- a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
> +++ b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_msqid_ds.h
> @@ -26,11 +26,11 @@ struct msqid_ds
>  {
>    struct ipc_perm msg_perm;    /* structure describing operation permission */
>  #if __TIMESIZE == 32
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_stime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_rtime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;
>    __time_t msg_ctime;          /* time of last change */
>  #else
>    __time_t msg_stime;          /* time of last msgsnd command */
> diff --git a/sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..69a63ee27a
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/hppa/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,18 @@
> +/* Analogous to kernel struct msqid64_ds used on msgctl.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +  unsigned long msg_stime_high;
> +  unsigned long msg_stime;
> +  unsigned long msg_rtime_high;
> +  unsigned long msg_rtime;
> +  unsigned long msg_ctime_high;
> +  unsigned long msg_ctime;
> +  unsigned long msg_cbytes;
> +  unsigned long msg_qnum;
> +  unsigned long msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long __unused1;
> +  unsigned long __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..65b940567b
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/i386/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,18 @@
> +/* Analogous to kernel struct compat_msqid64_ds used on msgctl.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +  unsigned long msg_stime;
> +  unsigned long msg_stime_high;
> +  unsigned long msg_rtime;
> +  unsigned long msg_rtime_high;
> +  unsigned long msg_ctime;
> +  unsigned long msg_ctime_high;
> +  unsigned long msg_cbytes;
> +  unsigned long msg_qnum;
> +  unsigned long msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long __unused1;
> +  unsigned long __unused2;
> +};
> diff --git a/include/sys/msg.h b/sysdeps/unix/sysv/linux/include/sys/msg.h
> similarity index 55%
> rename from include/sys/msg.h
> rename to sysdeps/unix/sysv/linux/include/sys/msg.h
> index 43ec5b9472..522903f818 100644
> --- a/include/sys/msg.h
> +++ b/sysdeps/unix/sysv/linux/include/sys/msg.h
> @@ -6,6 +6,16 @@ extern ssize_t __libc_msgrcv (int msqid, void *msgp, size_t msgsz,
>                               long int msgtyp, int msgflg);
>  extern int __libc_msgsnd (int msqid, const void *msgp, size_t msgsz,
>                           int msgflg);
> +
> +# include <bits/types/struct_msqid64_ds.h>
> +
> +# if __TIMESIZE == 64
> +#  define __msgctl64 __msgctl
> +# else
> +extern int __msgctl64 (int msqid, int cmd, struct __msqid64_ds *buf);
> +libc_hidden_proto (__msgctl64);
> +# endif
> +
>  #endif
>
>  #endif
> diff --git a/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
> index 85fdeef274..9ff010c763 100644
> --- a/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
> +++ b/sysdeps/unix/sysv/linux/mips/bits/types/struct_msqid_ds.h
> @@ -28,17 +28,17 @@ struct msqid_ds
>  #if __TIMESIZE == 32
>  # ifdef __MIPSEL__
>    __time_t msg_stime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_rtime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_ctime;          /* time of last change */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;
>  # else
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_stime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_rtime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;
>    __time_t msg_ctime;          /* time of last change */
>  # endif
>  #else
> diff --git a/sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..9cfd5a0dfe
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,33 @@
> +/* Analogous to kernel struct msqid64_ds used on msgctl.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +#if __TIMESIZE == 32
> +# ifdef __MIPSEL__
> +  unsigned long int msg_stime;
> +  unsigned long int msg_stime_high;
> +  unsigned long int msg_rtime;
> +  unsigned long int msg_rtime_high;
> +  unsigned long int msg_ctime;
> +  unsigned long int msg_ctime_high;
> +# else
> +  unsigned long int msg_stime_high;
> +  unsigned long int msg_stime;
> +  unsigned long int msg_rtime_high;
> +  unsigned long int msg_rtime;
> +  unsigned long int msg_ctime_high;
> +  unsigned long int msg_ctime;
> +# endif
> +#else
> +  unsigned long int msg_stime;
> +  unsigned long int msg_rtime;
> +  unsigned long int msg_ctime;
> +#endif
> +  unsigned long int msg_cbytes;
> +  unsigned long int msg_qnum;
> +  unsigned long int msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long int __unused1;
> +  unsigned long int __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/msgctl.c b/sysdeps/unix/sysv/linux/msgctl.c
> index fd46aec1a0..a7f7651280 100644
> --- a/sysdeps/unix/sysv/linux/msgctl.c
> +++ b/sysdeps/unix/sysv/linux/msgctl.c
> @@ -23,16 +23,55 @@
>  #include <errno.h>
>  #include <linux/posix_types.h>  /* For __kernel_mode_t.  */
>
> -#ifndef DEFAULT_VERSION
> -# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -#  define DEFAULT_VERSION GLIBC_2_2
> -# else
> -#  define DEFAULT_VERSION GLIBC_2_31
> -# endif
> +/* POSIX states ipc_perm mode should have type of mode_t.  */
> +_Static_assert (sizeof ((struct msqid_ds){0}.msg_perm.mode)
> +               == sizeof (mode_t),
> +               "sizeof (msqid_ds.msg_perm.mode) != sizeof (mode_t)");
> +
> +#if __IPC_TIME64 == 0
> +typedef struct msqid_ds msgctl_arg_t;
> +#else
> +# include <struct_kernel_msqid64_ds.h>
> +
> +static void
> +msqid64_to_kmsqid64 (const struct __msqid64_ds *msqid64,
> +                    struct kernel_msqid64_ds *kmsqid)
> +{
> +  kmsqid->msg_perm       = msqid64->msg_perm;
> +  kmsqid->msg_stime      = msqid64->msg_stime;
> +  kmsqid->msg_stime_high = msqid64->msg_stime >> 32;
> +  kmsqid->msg_rtime      = msqid64->msg_rtime;
> +  kmsqid->msg_rtime_high = msqid64->msg_rtime >> 32;
> +  kmsqid->msg_ctime      = msqid64->msg_ctime;
> +  kmsqid->msg_ctime_high = msqid64->msg_ctime >> 32;
> +  kmsqid->msg_qnum       = msqid64->msg_qnum;
> +  kmsqid->msg_qbytes     = msqid64->msg_qbytes;
> +  kmsqid->msg_lspid      = msqid64->msg_lspid;
> +  kmsqid->msg_lrpid      = msqid64->msg_lrpid;
> +}
> +
> +static void
> +kmsqid64_to_msqid64 (const struct kernel_msqid64_ds *kmsqid,
> +                    struct __msqid64_ds *msqid64)
> +{
> +  msqid64->msg_perm   = kmsqid->msg_perm;
> +  msqid64->msg_stime  = kmsqid->msg_stime
> +                       | ((__time64_t) kmsqid->msg_stime_high << 32);
> +  msqid64->msg_rtime  = kmsqid->msg_rtime
> +                       | ((__time64_t) kmsqid->msg_rtime_high << 32);
> +  msqid64->msg_ctime  = kmsqid->msg_ctime
> +                       | ((__time64_t) kmsqid->msg_ctime_high << 32);
> +  msqid64->msg_qnum   = kmsqid->msg_qnum;
> +  msqid64->msg_qbytes = kmsqid->msg_qbytes;
> +  msqid64->msg_lspid  = kmsqid->msg_lspid;
> +  msqid64->msg_lrpid  = kmsqid->msg_lrpid;
> +}
> +
> +typedef struct kernel_msqid64_ds msgctl_arg_t;
>  #endif
>
>  static int
> -msgctl_syscall (int msqid, int cmd, struct msqid_ds *buf)
> +msgctl_syscall (int msqid, int cmd, msgctl_arg_t *buf)
>  {
>  #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
>    return INLINE_SYSCALL_CALL (msgctl, msqid, cmd | __IPC_64, buf);
> @@ -43,46 +82,118 @@ msgctl_syscall (int msqid, int cmd, struct msqid_ds *buf)
>  }
>
>  int
> -__new_msgctl (int msqid, int cmd, struct msqid_ds *buf)
> +__msgctl64 (int msqid, int cmd, struct __msqid64_ds *buf)
>  {
> -  /* POSIX states ipc_perm mode should have type of mode_t.  */
> -  _Static_assert (sizeof ((struct msqid_ds){0}.msg_perm.mode)
> -                 == sizeof (mode_t),
> -                 "sizeof (msqid_ds.msg_perm.mode) != sizeof (mode_t)");
> -
> -#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -  struct msqid_ds tmpds;
> -  if (cmd == IPC_SET)
> +#if __IPC_TIME64
> +  struct kernel_msqid64_ds ksemid, *arg = NULL;
> +  if (buf != NULL)
>      {
> -      tmpds = *buf;
> -      tmpds.msg_perm.mode *= 0x10000U;
> -      buf = &tmpds;
> +      msqid64_to_kmsqid64 (buf, &ksemid);
> +      arg = &ksemid;
>      }
> +# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> +  if (cmd == IPC_SET)
> +    arg->msg_perm.mode *= 0x10000U;
> +# endif
> +#else
> +  msgctl_arg_t *arg = buf;
>  #endif
>
> -  int ret = msgctl_syscall (msqid, cmd, buf);
> +  int ret = msgctl_syscall (msqid, cmd, arg);
> +  if (ret < 0)
> +    return ret;
>
> -  if (ret >= 0)
> +  switch (cmd)
>      {
> -      switch (cmd)
> -       {
> -       case IPC_STAT:
> -       case MSG_STAT:
> -       case MSG_STAT_ANY:
> +    case IPC_STAT:
> +    case MSG_STAT:
> +    case MSG_STAT_ANY:
>  #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
> -         buf->msg_perm.mode >>= 16;
> +      arg->msg_perm.mode >>= 16;
>  #else
> -         /* Old Linux kernel versions might not clear the mode padding.  */
> -         if (sizeof ((struct msqid_ds){0}.msg_perm.mode)
> -             != sizeof (__kernel_mode_t))
> -           buf->msg_perm.mode &= 0xFFFF;
> +      /* Old Linux kernel versions might not clear the mode padding.  */
> +      if (sizeof ((struct msqid_ds){0}.msg_perm.mode)
> +          != sizeof (__kernel_mode_t))
> +       arg->msg_perm.mode &= 0xFFFF;
> +#endif
> +
> +#if __IPC_TIME64
> +      kmsqid64_to_msqid64 (arg, buf);
>  #endif
> -       }
>      }
>
>    return ret;
>  }
> -versioned_symbol (libc, __new_msgctl, msgctl, DEFAULT_VERSION);
> +#if __TIMESIZE != 64
> +libc_hidden_def (__msgctl64)
> +
> +static void
> +msqid_to_msqid64 (struct __msqid64_ds *mq64, const struct msqid_ds *mq)
> +{
> +  mq64->msg_perm   = mq->msg_perm;
> +  mq64->msg_stime  = mq->msg_stime
> +                    | ((__time64_t) mq->__msg_stime_high << 32);
> +  mq64->msg_rtime  = mq->msg_rtime
> +                    | ((__time64_t) mq->__msg_rtime_high << 32);
> +  mq64->msg_ctime  = mq->msg_ctime
> +                    | ((__time64_t) mq->__msg_ctime_high << 32);
> +  mq64->msg_qnum   = mq->msg_qnum;
> +  mq64->msg_qbytes = mq->msg_qbytes;
> +  mq64->msg_lspid  = mq->msg_lspid;
> +  mq64->msg_lrpid  = mq->msg_lrpid;
> +}
> +
> +static void
> +msqid64_to_msqid (struct msqid_ds *mq, const struct __msqid64_ds *mq64)
> +{
> +  mq->msg_perm         = mq64->msg_perm;
> +  mq->msg_stime        = mq64->msg_stime;
> +  mq->__msg_stime_high = 0;
> +  mq->msg_rtime        = mq64->msg_rtime;
> +  mq->__msg_rtime_high = 0;
> +  mq->msg_ctime        = mq64->msg_ctime;
> +  mq->__msg_ctime_high = 0;
> +  mq->msg_qnum         = mq64->msg_qnum;
> +  mq->msg_qbytes       = mq64->msg_qbytes;
> +  mq->msg_lspid        = mq64->msg_lspid;
> +  mq->msg_lrpid        = mq64->msg_lrpid;
> +}
> +
> +int
> +__msgctl (int msqid, int cmd, struct msqid_ds *buf)
> +{
> +  struct __msqid64_ds msqid64, *buf64 = NULL;
> +  if (buf != NULL)
> +    {
> +      msqid_to_msqid64 (&msqid64, buf);
> +      buf64 = &msqid64;
> +    }
> +
> +  int ret = __msgctl64 (msqid, cmd, buf64);
> +  if (ret < 0)
> +    return ret;
> +
> +  switch (cmd)
> +    {
> +    case IPC_STAT:
> +    case MSG_STAT:
> +    case MSG_STAT_ANY:
> +      if (buf64 != NULL)
> +        msqid64_to_msqid (buf, buf64);
> +    }
> +
> +  return ret;
> +}
> +#endif
> +
> +#ifndef DEFAULT_VERSION
> +# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
> +#  define DEFAULT_VERSION GLIBC_2_2
> +# else
> +#  define DEFAULT_VERSION GLIBC_2_31
> +# endif
> +#endif
> +versioned_symbol (libc, __msgctl, msgctl, DEFAULT_VERSION);
>
>  #if defined __ASSUME_SYSVIPC_BROKEN_MODE_T \
>      && SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_31)
> @@ -90,7 +201,7 @@ int
>  attribute_compat_text_section
>  __msgctl_mode16 (int msqid, int cmd, struct msqid_ds *buf)
>  {
> -  return msgctl_syscall (msqid, cmd, buf);
> +  return msgctl_syscall (msqid, cmd, (msgctl_arg_t *) buf);
>  }
>  compat_symbol (libc, __msgctl_mode16, msgctl, GLIBC_2_2);
>  #endif
> diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
> index 4ae2fbcbdc..35cc51f733 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
> +++ b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_msqid_ds.h
> @@ -26,11 +26,11 @@ struct msqid_ds
>  {
>    struct ipc_perm msg_perm;    /* structure describing operation permission */
>  #if __TIMESIZE == 32
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_stime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_rtime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;
>    __time_t msg_ctime;          /* time of last change */
>  #else
>    __time_t msg_stime;          /* time of last msgsnd command */
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..69a63ee27a
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,18 @@
> +/* Analogous to kernel struct msqid64_ds used on msgctl.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +  unsigned long msg_stime_high;
> +  unsigned long msg_stime;
> +  unsigned long msg_rtime_high;
> +  unsigned long msg_rtime;
> +  unsigned long msg_ctime_high;
> +  unsigned long msg_ctime;
> +  unsigned long msg_cbytes;
> +  unsigned long msg_qnum;
> +  unsigned long msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long __unused1;
> +  unsigned long __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c
> index 90460e6310..005c00ea75 100644
> --- a/sysdeps/unix/sysv/linux/semctl.c
> +++ b/sysdeps/unix/sysv/linux/semctl.c
> @@ -196,19 +196,11 @@ libc_hidden_def (__semctl64)
>
>  /* The 64-bit time_t semid_ds version might have a different layout and
>     internal field alignment.  */
> -static void
> -semid64_ds_to_semid_ds (struct semid_ds *ds, const struct __semid64_ds *ds64)
> -{
> -  ds->sem_perm = ds64->sem_perm;
> -  ds->sem_otime = ds64->sem_otime;
> -  ds->sem_ctime = ds64->sem_ctime;
> -  ds->sem_nsems = ds64->sem_nsems;
> -}
>
>  static void
> -semid_ds_to_semid64_ds (struct __semid64_ds *ds64, const struct semid_ds *ds)
> +semid_to_semid64 (struct __semid64_ds *ds64, const struct semid_ds *ds)
>  {
> -  ds64->sem_perm = ds->sem_perm;
> +  ds64->sem_perm  = ds->sem_perm;
>    ds64->sem_otime = ds->sem_otime
>                     | ((__time64_t) ds->__sem_otime_high << 32);
>    ds64->sem_ctime = ds->sem_ctime
> @@ -216,6 +208,17 @@ semid_ds_to_semid64_ds (struct __semid64_ds *ds64, const struct semid_ds *ds)
>    ds64->sem_nsems = ds->sem_nsems;
>  }
>
> +static void
> +semid64_to_semid (struct semid_ds *ds, const struct __semid64_ds *ds64)
> +{
> +  ds->sem_perm         = ds64->sem_perm;
> +  ds->sem_otime        = ds64->sem_otime;
> +  ds->__sem_otime_high = 0;
> +  ds->sem_ctime        = ds64->sem_ctime;
> +  ds->__sem_ctime_high = 0;
> +  ds->sem_nsems        = ds64->sem_nsems;
> +}
> +
>  static union semun64
>  semun_to_semun64 (int cmd, union semun semun, struct __semid64_ds *semid64)
>  {
> @@ -232,7 +235,7 @@ semun_to_semun64 (int cmd, union semun semun, struct __semid64_ds *semid64)
>      case IPC_STAT:
>      case IPC_SET:
>        r.buf = semid64;
> -      semid_ds_to_semid64_ds (r.buf, semun.buf);
> +      semid_to_semid64 (r.buf, semun.buf);
>  # ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
>        if (cmd == IPC_SET)
>         r.buf->sem_perm.mode *= 0x10000U;
> @@ -282,7 +285,7 @@ __semctl (int semid, int semnum, int cmd, ...)
>      case IPC_STAT:
>      case SEM_STAT:
>      case SEM_STAT_ANY:
> -      semid64_ds_to_semid_ds (arg.buf, arg64.buf);
> +      semid64_to_semid (arg.buf, arg64.buf);
>      }
>
>    return ret;
> diff --git a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
> index 71980839c7..502c23d91e 100644
> --- a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
> +++ b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_msqid_ds.h
> @@ -26,11 +26,11 @@ struct msqid_ds
>  {
>    struct ipc_perm msg_perm;    /* structure describing operation permission */
>  #if __TIMESIZE == 32
> -  unsigned long int __glibc_reserved1;
> +  unsigned long int __msg_stime_high;
>    __time_t msg_stime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved2;
> +  unsigned long int __msg_rtime_high;
>    __time_t msg_rtime;          /* time of last msgsnd command */
> -  unsigned long int __glibc_reserved3;
> +  unsigned long int __msg_ctime_high;
>    __time_t msg_ctime;          /* time of last change */
>  #else
>    __time_t msg_stime;          /* time of last msgsnd command */
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..69a63ee27a
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,18 @@
> +/* Analogous to kernel struct msqid64_ds used on msgctl.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +  unsigned long msg_stime_high;
> +  unsigned long msg_stime;
> +  unsigned long msg_rtime_high;
> +  unsigned long msg_rtime;
> +  unsigned long msg_ctime_high;
> +  unsigned long msg_ctime;
> +  unsigned long msg_cbytes;
> +  unsigned long msg_qnum;
> +  unsigned long msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long __unused1;
> +  unsigned long __unused2;
> +};
> diff --git a/sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h b/sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h
> new file mode 100644
> index 0000000000..b88d910adc
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/struct_kernel_msqid64_ds.h
> @@ -0,0 +1,19 @@
> +/* Analogous to kernel struct msqid64_ds used on msgctl.  It is only used
> +   for 32-bit architectures on 64-bit time_t msgctl64 implementation.  */
> +struct kernel_msqid64_ds
> +{
> +  struct ipc_perm msg_perm;
> +  unsigned long int msg_stime;
> +  unsigned long int msg_stime_high;
> +  unsigned long int msg_rtime;
> +  unsigned long int msg_rtime_high;
> +  unsigned long int msg_ctime;
> +  unsigned long int msg_ctime_high;
> +  unsigned long int msg_cbytes;
> +  unsigned long int msg_qnum;
> +  unsigned long int msg_qbytes;
> +  __pid_t msg_lspid;
> +  __pid_t msg_lrpid;
> +  unsigned long int __unused4;
> +  unsigned long int __unused5;
> +};
> --
> 2.25.1
>


More information about the Libc-alpha mailing list