summaryrefslogtreecommitdiff
path: root/sysdeps/unix/sysv/linux/msgctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix/sysv/linux/msgctl.c')
-rw-r--r--sysdeps/unix/sysv/linux/msgctl.c56
1 files changed, 53 insertions, 3 deletions
diff --git a/sysdeps/unix/sysv/linux/msgctl.c b/sysdeps/unix/sysv/linux/msgctl.c
index a52b5477ce..19d5ded19f 100644
--- a/sysdeps/unix/sysv/linux/msgctl.c
+++ b/sysdeps/unix/sysv/linux/msgctl.c
@@ -23,11 +23,15 @@
#include <errno.h>
#ifndef DEFAULT_VERSION
-# define DEFAULT_VERSION GLIBC_2_2
+# ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
+# define DEFAULT_VERSION GLIBC_2_2
+# else
+# define DEFAULT_VERSION GLIBC_2_31
+# endif
#endif
-int
-__new_msgctl (int msqid, int cmd, struct msqid_ds *buf)
+static int
+msgctl_syscall (int msqid, int cmd, struct msqid_ds *buf)
{
#ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
return INLINE_SYSCALL_CALL (msgctl, msqid, cmd | __IPC_64, buf);
@@ -36,8 +40,54 @@ __new_msgctl (int msqid, int cmd, struct msqid_ds *buf)
buf);
#endif
}
+
+int
+__new_msgctl (int msqid, int cmd, struct msqid_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)
+ {
+ tmpds = *buf;
+ tmpds.msg_perm.mode *= 0x10000U;
+ buf = &tmpds;
+ }
+#endif
+
+ int ret = msgctl_syscall (msqid, cmd, buf);
+
+#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
+ if (ret >= 0)
+ {
+ switch (cmd)
+ {
+ case IPC_STAT:
+ case MSG_STAT:
+ case MSG_STAT_ANY:
+ buf->msg_perm.mode >>= 16;
+ }
+ }
+#endif
+
+ return ret;
+}
versioned_symbol (libc, __new_msgctl, msgctl, DEFAULT_VERSION);
+#if defined __ASSUME_SYSVIPC_BROKEN_MODE_T \
+ && SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_31)
+int
+attribute_compat_text_section
+__msgctl_mode16 (int msqid, int cmd, struct msqid_ds *buf)
+{
+ return msgctl_syscall (msqid, cmd, buf);
+}
+compat_symbol (libc, __msgctl_mode16, msgctl, GLIBC_2_2);
+#endif
#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2)
struct __old_msqid_ds