1 /* Copyright (C) 1995-2024 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
21 #include <shlib-compat.h>
23 #include <linux/posix_types.h> /* For __kernel_mode_t. */
25 /* POSIX states ipc_perm mode should have type of mode_t. */
26 _Static_assert (sizeof ((struct msqid_ds
){0}.msg_perm
.mode
)
28 "sizeof (msqid_ds.msg_perm.mode) != sizeof (mode_t)");
31 typedef struct msqid_ds msgctl_arg_t
;
33 # include <struct_kernel_msqid64_ds.h>
36 msqid64_to_kmsqid64 (const struct __msqid64_ds
*msqid64
,
37 struct kernel_msqid64_ds
*kmsqid
)
39 kmsqid
->msg_perm
= msqid64
->msg_perm
;
40 kmsqid
->msg_stime
= msqid64
->msg_stime
;
41 kmsqid
->msg_stime_high
= msqid64
->msg_stime
>> 32;
42 kmsqid
->msg_rtime
= msqid64
->msg_rtime
;
43 kmsqid
->msg_rtime_high
= msqid64
->msg_rtime
>> 32;
44 kmsqid
->msg_ctime
= msqid64
->msg_ctime
;
45 kmsqid
->msg_ctime_high
= msqid64
->msg_ctime
>> 32;
46 kmsqid
->msg_cbytes
= msqid64
->msg_cbytes
;
47 kmsqid
->msg_qnum
= msqid64
->msg_qnum
;
48 kmsqid
->msg_qbytes
= msqid64
->msg_qbytes
;
49 kmsqid
->msg_lspid
= msqid64
->msg_lspid
;
50 kmsqid
->msg_lrpid
= msqid64
->msg_lrpid
;
54 kmsqid64_to_msqid64 (const struct kernel_msqid64_ds
*kmsqid
,
55 struct __msqid64_ds
*msqid64
)
57 msqid64
->msg_perm
= kmsqid
->msg_perm
;
58 msqid64
->msg_stime
= kmsqid
->msg_stime
59 | ((__time64_t
) kmsqid
->msg_stime_high
<< 32);
60 msqid64
->msg_rtime
= kmsqid
->msg_rtime
61 | ((__time64_t
) kmsqid
->msg_rtime_high
<< 32);
62 msqid64
->msg_ctime
= kmsqid
->msg_ctime
63 | ((__time64_t
) kmsqid
->msg_ctime_high
<< 32);
64 msqid64
->msg_cbytes
= kmsqid
->msg_cbytes
;
65 msqid64
->msg_qnum
= kmsqid
->msg_qnum
;
66 msqid64
->msg_qbytes
= kmsqid
->msg_qbytes
;
67 msqid64
->msg_lspid
= kmsqid
->msg_lspid
;
68 msqid64
->msg_lrpid
= kmsqid
->msg_lrpid
;
71 typedef struct kernel_msqid64_ds msgctl_arg_t
;
75 msgctl_syscall (int msqid
, int cmd
, msgctl_arg_t
*buf
)
77 #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
78 return INLINE_SYSCALL_CALL (msgctl
, msqid
, cmd
| __IPC_64
, buf
);
80 return INLINE_SYSCALL_CALL (ipc
, IPCOP_msgctl
, msqid
, cmd
| __IPC_64
, 0,
86 __msgctl64 (int msqid
, int cmd
, struct __msqid64_ds
*buf
)
88 #if IPC_CTL_NEED_TRANSLATION
90 struct kernel_msqid64_ds ksemid
, *arg
= NULL
;
95 /* Some applications pass the __IPC_64 flag in cmd, to invoke
96 previously unsupported commands back when there was no EINVAL
97 error checking in glibc. Mask the flag for the switch statements
98 below. msgctl_syscall adds back the __IPC_64 flag for the actual
115 msqid64_to_kmsqid64 (buf
, &ksemid
);
118 # ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
120 arg
->msg_perm
.mode
*= 0x10000U
;
129 /* This is a Linux extension where kernel returns a 'struct msginfo'
131 arg
= (__typeof__ (arg
)) buf
;
135 __set_errno (EINVAL
);
139 int ret
= msgctl_syscall (msqid
, cmd
, arg
);
148 # ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
149 arg
->msg_perm
.mode
>>= 16;
151 /* Old Linux kernel versions might not clear the mode padding. */
152 if (sizeof ((struct msqid_ds
){0}.msg_perm
.mode
)
153 != sizeof (__kernel_mode_t
))
154 arg
->msg_perm
.mode
&= 0xFFFF;
158 kmsqid64_to_msqid64 (arg
, buf
);
164 #else /* !IPC_CTL_NEED_TRANSLATION */
165 return msgctl_syscall (msqid
, cmd
, buf
);
169 libc_hidden_def (__msgctl64
)
172 msqid_to_msqid64 (struct __msqid64_ds
*mq64
, const struct msqid_ds
*mq
)
174 mq64
->msg_perm
= mq
->msg_perm
;
175 mq64
->msg_stime
= mq
->msg_stime
176 | ((__time64_t
) mq
->__msg_stime_high
<< 32);
177 mq64
->msg_rtime
= mq
->msg_rtime
178 | ((__time64_t
) mq
->__msg_rtime_high
<< 32);
179 mq64
->msg_ctime
= mq
->msg_ctime
180 | ((__time64_t
) mq
->__msg_ctime_high
<< 32);
181 mq64
->msg_cbytes
= mq
->msg_cbytes
;
182 mq64
->msg_qnum
= mq
->msg_qnum
;
183 mq64
->msg_qbytes
= mq
->msg_qbytes
;
184 mq64
->msg_lspid
= mq
->msg_lspid
;
185 mq64
->msg_lrpid
= mq
->msg_lrpid
;
189 msqid64_to_msqid (struct msqid_ds
*mq
, const struct __msqid64_ds
*mq64
)
191 mq
->msg_perm
= mq64
->msg_perm
;
192 mq
->msg_stime
= mq64
->msg_stime
;
193 mq
->__msg_stime_high
= 0;
194 mq
->msg_rtime
= mq64
->msg_rtime
;
195 mq
->__msg_rtime_high
= 0;
196 mq
->msg_ctime
= mq64
->msg_ctime
;
197 mq
->__msg_ctime_high
= 0;
198 mq
->msg_cbytes
= mq64
->msg_cbytes
;
199 mq
->msg_qnum
= mq64
->msg_qnum
;
200 mq
->msg_qbytes
= mq64
->msg_qbytes
;
201 mq
->msg_lspid
= mq64
->msg_lspid
;
202 mq
->msg_lrpid
= mq64
->msg_lrpid
;
206 __msgctl (int msqid
, int cmd
, struct msqid_ds
*buf
)
208 struct __msqid64_ds msqid64
, *buf64
= NULL
;
211 /* This is a Linux extension where kernel returns a 'struct msginfo'
213 if (cmd
== IPC_INFO
|| cmd
== MSG_INFO
)
214 buf64
= (struct __msqid64_ds
*) buf
;
217 msqid_to_msqid64 (&msqid64
, buf
);
222 int ret
= __msgctl64 (msqid
, cmd
, buf64
);
231 msqid64_to_msqid (buf
, buf64
);
238 #ifndef DEFAULT_VERSION
239 # ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
240 # define DEFAULT_VERSION GLIBC_2_2
242 # define DEFAULT_VERSION GLIBC_2_31
245 versioned_symbol (libc
, __msgctl
, msgctl
, DEFAULT_VERSION
);
247 #if defined __ASSUME_SYSVIPC_BROKEN_MODE_T \
248 && SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_31)
250 attribute_compat_text_section
251 __msgctl_mode16 (int msqid
, int cmd
, struct msqid_ds
*buf
)
253 return msgctl_syscall (msqid
, cmd
, (msgctl_arg_t
*) buf
);
255 compat_symbol (libc
, __msgctl_mode16
, msgctl
, GLIBC_2_2
);
258 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2)
259 struct __old_msqid_ds
261 struct __old_ipc_perm msg_perm
; /* structure describing operation permission */
262 struct msg
*__msg_first
; /* pointer to first message on queue */
263 struct msg
*__msg_last
; /* pointer to last message on queue */
264 __time_t msg_stime
; /* time of last msgsnd command */
265 __time_t msg_rtime
; /* time of last msgrcv command */
266 __time_t msg_ctime
; /* time of last change */
267 struct wait_queue
*__wwait
; /* ??? */
268 struct wait_queue
*__rwait
; /* ??? */
269 unsigned short int __msg_cbytes
; /* current number of bytes on queue */
270 unsigned short int msg_qnum
; /* number of messages currently on queue */
271 unsigned short int msg_qbytes
; /* max number of bytes allowed on queue */
272 __ipc_pid_t msg_lspid
; /* pid of last msgsnd() */
273 __ipc_pid_t msg_lrpid
; /* pid of last msgrcv() */
277 attribute_compat_text_section
278 __old_msgctl (int msqid
, int cmd
, struct __old_msqid_ds
*buf
)
280 #if defined __ASSUME_DIRECT_SYSVIPC_SYSCALLS \
281 && !defined __ASSUME_SYSVIPC_DEFAULT_IPC_64
282 /* For architecture that have wire-up msgctl but also have __IPC_64 to a
283 value different than default (0x0) it means the compat symbol used the
285 return INLINE_SYSCALL_CALL (msgctl
, msqid
, cmd
, buf
);
287 return INLINE_SYSCALL_CALL (ipc
, IPCOP_msgctl
, msqid
, cmd
, 0, buf
);
290 compat_symbol (libc
, __old_msgctl
, msgctl
, GLIBC_2_0
);