diff options
Diffstat (limited to 'sysdeps/unix')
14 files changed, 330 insertions, 49 deletions
diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h new file mode 100644 index 0000000000..f71e0d28ff --- /dev/null +++ b/sysdeps/unix/sysv/linux/bits/types/struct_shmid64_ds.h @@ -0,0 +1,37 @@ +/* Generic implementation of the shared memory struct shmid_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_SHM_H +# error "Never include <bits/types/struct_shmid_ds.h> directly; use <sys/shm.h> instead." +#endif + +#if __TIMESIZE == 64 +# define __shmid64_ds shmid_ds +#else +struct __shmid64_ds +{ + struct ipc_perm shm_perm; /* operation permission struct */ + size_t shm_segsz; /* size of segment in bytes */ + __time64_t shm_atime; /* time of last shmat() */ + __time64_t shm_dtime; /* time of last shmdt() */ + __time64_t shm_ctime; /* time of last change by shmctl() */ + __pid_t shm_cpid; /* pid of creator */ + __pid_t shm_lpid; /* pid of last shmop */ + shmatt_t shm_nattch; /* number of current attaches */ +}; +#endif diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h index 61ed4a08c3..836a7d50e9 100644 --- a/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h +++ b/sysdeps/unix/sysv/linux/bits/types/struct_shmid_ds.h @@ -27,11 +27,11 @@ struct shmid_ds size_t shm_segsz; /* size of segment in bytes */ #if __TIMESIZE == 32 __time_t shm_atime; /* time of last shmat() */ - unsigned long int __glibc_reserved1; + unsigned long int __shm_atime_high; __time_t shm_dtime; /* time of last shmdt() */ - unsigned long int __glibc_reserved2; + unsigned long int __shm_dtime_high; __time_t shm_ctime; /* time of last change by shmctl() */ - unsigned long int __glibc_reserved3; + unsigned long int __shm_ctime_high; #else __time_t shm_atime; /* time of last shmat() */ __time_t shm_dtime; /* time of last shmdt() */ diff --git a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h index 1ebf222eac..1abed1e149 100644 --- a/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h +++ b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_shmid_ds.h @@ -25,11 +25,11 @@ struct shmid_ds { struct ipc_perm shm_perm; /* operation permission struct */ #if __TIMESIZE == 32 - unsigned long int __glibc_reserved1; + unsigned long int __shm_atime_high; __time_t shm_atime; /* time of last shmat() */ - unsigned long int __glibc_reserved2; + unsigned long int __shm_dtime_high; __time_t shm_dtime; /* time of last shmdt() */ - unsigned long int __glibc_reserved3; + unsigned long int __shm_ctime_high; __time_t shm_ctime; /* time of last change by shmctl() */ unsigned long int __glibc_reserved4; #else diff --git a/sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h new file mode 100644 index 0000000000..4d09fc7f62 --- /dev/null +++ b/sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h @@ -0,0 +1,18 @@ +/* Analogous to kernel struct shmid64_ds used on shmctl. */ +struct kernel_shmid64_ds +{ + struct ipc_perm shm_perm; /* operation permission struct */ + unsigned long int shm_atime_high; + unsigned long int shm_atime; /* time of last shmat() */ + unsigned long int shm_dtime_high; + unsigned long int shm_dtime; /* time of last shmdt() */ + unsigned long int shm_ctime_high; + unsigned long int shm_ctime; /* time of last change by shmctl() */ + unsigned long int __pad; + size_t shm_segsz; /* size of segment in bytes */ + __pid_t shm_cpid; /* pid of creator */ + __pid_t shm_lpid; /* pid of last shmop */ + shmatt_t shm_nattch; /* number of current attaches */ + unsigned long int __unused1; + unsigned long int __unused2; +}; diff --git a/sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h new file mode 100644 index 0000000000..6a0a0d9c71 --- /dev/null +++ b/sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h @@ -0,0 +1,17 @@ +/* Analogous to kernel struct compat_shmid64_ds used on shmctl. */ +struct kernel_shmid64_ds +{ + struct ipc_perm shm_perm; + size_t shm_segsz; + unsigned long int shm_atime; + unsigned long int shm_atime_high; + unsigned long int shm_dtime; + unsigned long int shm_dtime_high; + unsigned long int shm_ctime; + unsigned long int shm_ctime_high; + __pid_t shm_cpid; + __pid_t shm_lpid; + unsigned long int shm_nattch; + unsigned long int __unused4; + unsigned long int __unused5; +}; diff --git a/sysdeps/unix/sysv/linux/include/sys/shm.h b/sysdeps/unix/sysv/linux/include/sys/shm.h new file mode 100644 index 0000000000..530a1cdfc9 --- /dev/null +++ b/sysdeps/unix/sysv/linux/include/sys/shm.h @@ -0,0 +1,17 @@ +#ifndef _SYS_SHM_H +#include <sysvipc/sys/shm.h> + +#ifndef _ISOMAC + +# include <bits/types/struct_shmid64_ds.h> + +# if __TIMESIZE == 64 +# define __shmctl64 __shmctl +# else +extern int __shmctl64 (int shmid, int cmd, struct __shmid64_ds *buf); +libc_hidden_proto (__shmctl64); +# endif + +#endif /* _ISOMAC */ + +#endif /* _SYS_SHM_H */ diff --git a/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h index 8e13928980..58090e2fcb 100644 --- a/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h +++ b/sysdeps/unix/sysv/linux/mips/bits/types/struct_shmid_ds.h @@ -38,9 +38,9 @@ struct shmid_ds __pid_t shm_lpid; /* pid of last shmop */ shmatt_t shm_nattch; /* number of current attaches */ #if __TIMESIZE == 32 - unsigned short int __glibc_reserved1; - unsigned short int __glibc_reserved2; - unsigned short int __glibc_reserved3; + unsigned short int __shm_atime_high; + unsigned short int __shm_dtime_high; + unsigned short int __shm_ctime_high; unsigned short int __glibc_reserved4; #else __syscall_ulong_t __glibc_reserved5; diff --git a/sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h new file mode 100644 index 0000000000..a4baa5614f --- /dev/null +++ b/sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h @@ -0,0 +1,27 @@ +/* Analogous to kernel struct shmid64_ds used on shmctl. */ +struct kernel_shmid64_ds +{ + struct ipc_perm shm_perm; + size_t shm_segsz; +#if __TIMESIZE == 64 + long int shm_atime; + long int shm_dtime; + long int shm_ctime; +#else + unsigned long int shm_atime; + unsigned long int shm_dtime; + unsigned long int shm_ctime; +#endif + __pid_t shm_cpid; + __pid_t shm_lpid; + unsigned long int shm_nattch; +#if __TIMESIZE == 64 + unsigned long int __unused1; + unsigned long int __unused2; +#else + unsigned short int shm_atime_high; + unsigned short int shm_dtime_high; + unsigned short int shm_ctime_high; + unsigned short int __ununsed1; +#endif +}; diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h index b0816fb16a..39b3e5fd3e 100644 --- a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h +++ b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_shmid_ds.h @@ -25,11 +25,11 @@ struct shmid_ds { struct ipc_perm shm_perm; /* operation permission struct */ #if __TIMESIZE == 32 - unsigned long int __glibc_reserved1; + unsigned long int __shm_atime_high; __time_t shm_atime; /* time of last shmat() */ - unsigned long int __glibc_reserved2; + unsigned long int __shm_dtime_high; __time_t shm_dtime; /* time of last shmdt() */ - unsigned long int __glibc_reserved3; + unsigned long int __shm_ctime_high; __time_t shm_ctime; /* time of last change by shmctl() */ unsigned long int __glibc_reserved4; #else diff --git a/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h new file mode 100644 index 0000000000..ae3f3987ac --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h @@ -0,0 +1,18 @@ +/* Analogous to kernel struct shmid64_ds used on shmctl. */ +struct kernel_shmid64_ds +{ + struct ipc_perm shm_perm; + unsigned long int shm_atime_high; + unsigned long int shm_atime; + unsigned long int shm_dtime_high; + unsigned long int shm_dtime; + unsigned long int shm_ctime_high; + unsigned long int shm_ctime; + unsigned long int __ununsed1; + size_t shm_segsz; + __pid_t shm_cpid; + __pid_t shm_lpid; + unsigned long int shm_nattch; + unsigned long int __unused2; + unsigned long int __unused3; +}; diff --git a/sysdeps/unix/sysv/linux/shmctl.c b/sysdeps/unix/sysv/linux/shmctl.c index f41b359b8b..76d88441f1 100644 --- a/sysdeps/unix/sysv/linux/shmctl.c +++ b/sysdeps/unix/sysv/linux/shmctl.c @@ -24,16 +24,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 shmid_ds){0}.shm_perm.mode) + == sizeof (mode_t), + "sizeof (shmid_ds.shm_perm.mode) != sizeof (mode_t)"); + +#if __IPC_TIME64 == 0 +typedef struct shmid_ds shmctl_arg_t; +#else +# include <struct_kernel_shmid64_ds.h> + +static void +shmid64_to_kshmid64 (const struct __shmid64_ds *shmid64, + struct kernel_shmid64_ds *kshmid) +{ + kshmid->shm_perm = shmid64->shm_perm; + kshmid->shm_segsz = shmid64->shm_segsz; + kshmid->shm_atime = shmid64->shm_atime; + kshmid->shm_atime_high = shmid64->shm_atime >> 32; + kshmid->shm_dtime = shmid64->shm_dtime; + kshmid->shm_dtime_high = shmid64->shm_dtime >> 32; + kshmid->shm_ctime = shmid64->shm_ctime; + kshmid->shm_ctime_high = shmid64->shm_ctime >> 32; + kshmid->shm_cpid = shmid64->shm_cpid; + kshmid->shm_lpid = shmid64->shm_lpid; + kshmid->shm_nattch = shmid64->shm_nattch; +} + +static void +kshmid64_to_shmid64 (const struct kernel_shmid64_ds *kshmid, + struct __shmid64_ds *shmid64) +{ + shmid64->shm_perm = kshmid->shm_perm; + shmid64->shm_segsz = kshmid->shm_segsz; + shmid64->shm_atime = kshmid->shm_atime + | ((__time64_t) kshmid->shm_atime_high << 32); + shmid64->shm_dtime = kshmid->shm_dtime + | ((__time64_t) kshmid->shm_dtime_high << 32); + shmid64->shm_ctime = kshmid->shm_ctime + | ((__time64_t) kshmid->shm_ctime_high << 32); + shmid64->shm_cpid = kshmid->shm_cpid; + shmid64->shm_lpid = kshmid->shm_lpid; + shmid64->shm_nattch = kshmid->shm_nattch; +} + +typedef struct kernel_shmid64_ds shmctl_arg_t; #endif static int -shmctl_syscall (int shmid, int cmd, struct shmid_ds *buf) +shmctl_syscall (int shmid, int cmd, shmctl_arg_t *buf) { #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS return INLINE_SYSCALL_CALL (shmctl, shmid, cmd | __IPC_64, buf); @@ -45,46 +84,120 @@ shmctl_syscall (int shmid, int cmd, struct shmid_ds *buf) /* Provide operations to control over shared memory segments. */ int -__new_shmctl (int shmid, int cmd, struct shmid_ds *buf) +__shmctl64 (int shmid, int cmd, struct __shmid64_ds *buf) { - /* POSIX states ipc_perm mode should have type of mode_t. */ - _Static_assert (sizeof ((struct shmid_ds){0}.shm_perm.mode) - == sizeof (mode_t), - "sizeof (msqid_ds.msg_perm.mode) != sizeof (mode_t)"); - -#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T - struct shmid_ds tmpds; - if (cmd == IPC_SET) +#if __IPC_TIME64 + struct kernel_shmid64_ds kshmid, *arg = NULL; + if (buf != NULL) { - tmpds = *buf; - tmpds.shm_perm.mode *= 0x10000U; - buf = &tmpds; + shmid64_to_kshmid64 (buf, &kshmid); + arg = &kshmid; } +# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T + if (cmd == IPC_SET) + arg->shm_perm.mode *= 0x10000U; +# endif +#else + shmctl_arg_t *arg = buf; #endif - int ret = shmctl_syscall (shmid, cmd, buf); + int ret = shmctl_syscall (shmid, cmd, arg); + if (ret < 0) + return ret; - if (ret >= 0) + switch (cmd) { - switch (cmd) - { - case IPC_STAT: - case SHM_STAT: - case SHM_STAT_ANY: + case IPC_INFO: + case IPC_STAT: + case SHM_STAT: + case SHM_STAT_ANY: #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T - buf->shm_perm.mode >>= 16; + arg->shm_perm.mode >>= 16; #else - /* Old Linux kernel versions might not clear the mode padding. */ - if (sizeof ((struct shmid_ds){0}.shm_perm.mode) - != sizeof (__kernel_mode_t)) - buf->shm_perm.mode &= 0xFFFF; + /* Old Linux kernel versions might not clear the mode padding. */ + if (sizeof ((struct shmid_ds){0}.shm_perm.mode) + != sizeof (__kernel_mode_t)) + arg->shm_perm.mode &= 0xFFFF; +#endif + +#if __IPC_TIME64 + kshmid64_to_shmid64 (arg, buf); #endif - } } return ret; } -versioned_symbol (libc, __new_shmctl, shmctl, DEFAULT_VERSION); +#if __TIMESIZE != 64 +libc_hidden_def (__shmctl64) + +static void +shmid_to_shmid64 (struct __shmid64_ds *shm64, const struct shmid_ds *shm) +{ + shm64->shm_perm = shm->shm_perm; + shm64->shm_segsz = shm->shm_segsz; + shm64->shm_atime = shm->shm_atime + | ((__time64_t) shm->__shm_atime_high << 32); + shm64->shm_dtime = shm->shm_dtime + | ((__time64_t) shm->__shm_dtime_high << 32); + shm64->shm_ctime = shm->shm_ctime + | ((__time64_t) shm->__shm_ctime_high << 32); + shm64->shm_cpid = shm->shm_cpid; + shm64->shm_lpid = shm->shm_lpid; + shm64->shm_nattch = shm->shm_nattch; +} + +static void +shmid64_to_shmid (struct shmid_ds *shm, const struct __shmid64_ds *shm64) +{ + shm->shm_perm = shm64->shm_perm; + shm->shm_segsz = shm64->shm_segsz; + shm->shm_atime = shm64->shm_atime; + shm->__shm_atime_high = 0; + shm->shm_dtime = shm64->shm_dtime; + shm->__shm_dtime_high = 0; + shm->shm_ctime = shm64->shm_ctime; + shm->__shm_ctime_high = 0; + shm->shm_cpid = shm64->shm_cpid; + shm->shm_lpid = shm64->shm_lpid; + shm->shm_nattch = shm64->shm_nattch; +} + +int +__shmctl (int shmid, int cmd, struct shmid_ds *buf) +{ + struct __shmid64_ds shmid64, *buf64 = NULL; + if (buf != NULL) + { + shmid_to_shmid64 (&shmid64, buf); + buf64 = &shmid64; + } + + int ret = __shmctl64 (shmid, cmd, buf64); + if (ret < 0) + return ret; + + switch (cmd) + { + case IPC_INFO: + case IPC_STAT: + case SHM_STAT: + case SHM_STAT_ANY: + shmid64_to_shmid (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, __shmctl, shmctl, DEFAULT_VERSION); #if defined __ASSUME_SYSVIPC_BROKEN_MODE_T \ && SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_31) @@ -92,7 +205,7 @@ int attribute_compat_text_section __shmctl_mode16 (int shmid, int cmd, struct shmid_ds *buf) { - return shmctl_syscall (shmid, cmd, buf); + return shmctl_syscall (shmid, cmd, (shmctl_arg_t *) buf); } compat_symbol (libc, __shmctl_mode16, shmctl, GLIBC_2_2); #endif diff --git a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h index d5fb61d374..cab3a2686f 100644 --- a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h +++ b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_shmid_ds.h @@ -25,11 +25,11 @@ struct shmid_ds { struct ipc_perm shm_perm; /* operation permission struct */ #if __TIMESIZE == 32 - unsigned long int __glibc_reserved1; + unsigned long int __shm_atime_high; __time_t shm_atime; /* time of last shmat() */ - unsigned long int __glibc_reserved2; + unsigned long int __shm_dtime_high; __time_t shm_dtime; /* time of last shmdt() */ - unsigned long int __glibc_reserved3; + unsigned long int __shm_ctime_high; __time_t shm_ctime; /* time of last change by shmctl() */ #else __time_t shm_atime; /* time of last shmat() */ diff --git a/sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h new file mode 100644 index 0000000000..333a410641 --- /dev/null +++ b/sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h @@ -0,0 +1,17 @@ +/* Analogous to kernel struct shmid64_ds used on shmctl. */ +struct kernel_shmid64_ds +{ + struct ipc_perm shm_perm; + unsigned long int shm_atime_high; + unsigned long int shm_atime; + unsigned long int shm_dtime_high; + unsigned long int shm_dtime; + unsigned long int shm_ctime_high; + unsigned long int shm_ctime; + size_t shm_segsz; + __pid_t shm_cpid; + __pid_t shm_lpid; + unsigned long int shm_nattch; + unsigned long int __unused1; + unsigned long int __unused2; +}; diff --git a/sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h new file mode 100644 index 0000000000..6fe67afccb --- /dev/null +++ b/sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h @@ -0,0 +1,17 @@ +/* Analogous to kernel struct shmid64_ds used on shmctl. */ +struct kernel_shmid64_ds +{ + struct ipc_perm shm_perm; + size_t shm_segsz; + unsigned long int shm_atime; + unsigned long int shm_atime_high; + unsigned long int shm_dtime; + unsigned long int shm_dtime_high; + unsigned long int shm_ctime; + unsigned long int shm_ctime_high; + __pid_t shm_cpid; + __pid_t shm_lpid; + unsigned long int shm_nattch; + unsigned long int __unused1; + unsigned long int __unused2; +}; |