1 /* Copyright (C) 1995-2020 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, August 1995.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
22 #include <shlib-compat.h>
24 #include <linux/posix_types.h> /* For __kernel_mode_t. */
26 /* POSIX states ipc_perm mode should have type of mode_t. */
27 _Static_assert (sizeof ((struct msqid_ds
){0}.msg_perm
.mode
)
29 "sizeof (msqid_ds.msg_perm.mode) != sizeof (mode_t)");
32 typedef struct msqid_ds msgctl_arg_t
;
34 # include <struct_kernel_msqid64_ds.h>
37 msqid64_to_kmsqid64 (const struct __msqid64_ds
*msqid64
,
38 struct kernel_msqid64_ds
*kmsqid
)
40 kmsqid
->msg_perm
= msqid64
->msg_perm
;
41 kmsqid
->msg_stime
= msqid64
->msg_stime
;
42 kmsqid
->msg_stime_high
= msqid64
->msg_stime
>> 32;
43 kmsqid
->msg_rtime
= msqid64
->msg_rtime
;
44 kmsqid
->msg_rtime_high
= msqid64
->msg_rtime
>> 32;
45 kmsqid
->msg_ctime
= msqid64
->msg_ctime
;
46 kmsqid
->msg_ctime_high
= msqid64
->msg_ctime
>> 32;
47 kmsqid
->msg_cbytes
= msqid64
->msg_cbytes
;
48 kmsqid
->msg_qnum
= msqid64
->msg_qnum
;
49 kmsqid
->msg_qbytes
= msqid64
->msg_qbytes
;
50 kmsqid
->msg_lspid
= msqid64
->msg_lspid
;
51 kmsqid
->msg_lrpid
= msqid64
->msg_lrpid
;
55 kmsqid64_to_msqid64 (const struct kernel_msqid64_ds
*kmsqid
,
56 struct __msqid64_ds
*msqid64
)
58 msqid64
->msg_perm
= kmsqid
->msg_perm
;
59 msqid64
->msg_stime
= kmsqid
->msg_stime
60 | ((__time64_t
) kmsqid
->msg_stime_high
<< 32);
61 msqid64
->msg_rtime
= kmsqid
->msg_rtime
62 | ((__time64_t
) kmsqid
->msg_rtime_high
<< 32);
63 msqid64
->msg_ctime
= kmsqid
->msg_ctime
64 | ((__time64_t
) kmsqid
->msg_ctime_high
<< 32);
65 msqid64
->msg_cbytes
= kmsqid
->msg_cbytes
;
66 msqid64
->msg_qnum
= kmsqid
->msg_qnum
;
67 msqid64
->msg_qbytes
= kmsqid
->msg_qbytes
;
68 msqid64
->msg_lspid
= kmsqid
->msg_lspid
;
69 msqid64
->msg_lrpid
= kmsqid
->msg_lrpid
;
72 typedef struct kernel_msqid64_ds msgctl_arg_t
;
76 msgctl_syscall (int msqid
, int cmd
, msgctl_arg_t
*buf
)
78 #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
79 return INLINE_SYSCALL_CALL (msgctl
, msqid
, cmd
| __IPC_64
, buf
);
81 return INLINE_SYSCALL_CALL (ipc
, IPCOP_msgctl
, msqid
, cmd
| __IPC_64
, 0,
87 __msgctl64 (int msqid
, int cmd
, struct __msqid64_ds
*buf
)
90 struct kernel_msqid64_ds ksemid
, *arg
= NULL
;
108 msqid64_to_kmsqid64 (buf
, &ksemid
);
111 # ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
113 arg
->msg_perm
.mode
*= 0x10000U
;
122 /* This is a Linux extension where kernel returns a 'struct msginfo'
124 arg
= (__typeof__ (arg
)) buf
;
128 __set_errno (EINVAL
);
132 int ret
= msgctl_syscall (msqid
, cmd
, arg
);
141 #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
142 arg
->msg_perm
.mode
>>= 16;
144 /* Old Linux kernel versions might not clear the mode padding. */
145 if (sizeof ((struct msqid_ds
){0}.msg_perm
.mode
)
146 != sizeof (__kernel_mode_t
))
147 arg
->msg_perm
.mode
&= 0xFFFF;
151 kmsqid64_to_msqid64 (arg
, buf
);
158 libc_hidden_def (__msgctl64
)
161 msqid_to_msqid64 (struct __msqid64_ds
*mq64
, const struct msqid_ds
*mq
)
163 mq64
->msg_perm
= mq
->msg_perm
;
164 mq64
->msg_stime
= mq
->msg_stime
165 | ((__time64_t
) mq
->__msg_stime_high
<< 32);
166 mq64
->msg_rtime
= mq
->msg_rtime
167 | ((__time64_t
) mq
->__msg_rtime_high
<< 32);
168 mq64
->msg_ctime
= mq
->msg_ctime
169 | ((__time64_t
) mq
->__msg_ctime_high
<< 32);
170 mq64
->msg_cbytes
= mq
->msg_cbytes
;
171 mq64
->msg_qnum
= mq
->msg_qnum
;
172 mq64
->msg_qbytes
= mq
->msg_qbytes
;
173 mq64
->msg_lspid
= mq
->msg_lspid
;
174 mq64
->msg_lrpid
= mq
->msg_lrpid
;
178 msqid64_to_msqid (struct msqid_ds
*mq
, const struct __msqid64_ds
*mq64
)
180 mq
->msg_perm
= mq64
->msg_perm
;
181 mq
->msg_stime
= mq64
->msg_stime
;
182 mq
->__msg_stime_high
= 0;
183 mq
->msg_rtime
= mq64
->msg_rtime
;
184 mq
->__msg_rtime_high
= 0;
185 mq
->msg_ctime
= mq64
->msg_ctime
;
186 mq
->__msg_ctime_high
= 0;
187 mq
->msg_cbytes
= mq64
->msg_cbytes
;
188 mq
->msg_qnum
= mq64
->msg_qnum
;
189 mq
->msg_qbytes
= mq64
->msg_qbytes
;
190 mq
->msg_lspid
= mq64
->msg_lspid
;
191 mq
->msg_lrpid
= mq64
->msg_lrpid
;
195 __msgctl (int msqid
, int cmd
, struct msqid_ds
*buf
)
197 struct __msqid64_ds msqid64
, *buf64
= NULL
;
200 /* This is a Linux extension where kernel returns a 'struct msginfo'
202 if (cmd
== IPC_INFO
|| cmd
== MSG_INFO
)
203 buf64
= (struct __msqid64_ds
*) buf
;
206 msqid_to_msqid64 (&msqid64
, buf
);
211 int ret
= __msgctl64 (msqid
, cmd
, buf64
);
220 msqid64_to_msqid (buf
, buf64
);
227 #ifndef DEFAULT_VERSION
228 # ifndef __ASSUME_SYSVIPC_BROKEN_MODE_T
229 # define DEFAULT_VERSION GLIBC_2_2
231 # define DEFAULT_VERSION GLIBC_2_31
234 versioned_symbol (libc
, __msgctl
, msgctl
, DEFAULT_VERSION
);
236 #if defined __ASSUME_SYSVIPC_BROKEN_MODE_T \
237 && SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_31)
239 attribute_compat_text_section
240 __msgctl_mode16 (int msqid
, int cmd
, struct msqid_ds
*buf
)
242 return msgctl_syscall (msqid
, cmd
, (msgctl_arg_t
*) buf
);
244 compat_symbol (libc
, __msgctl_mode16
, msgctl
, GLIBC_2_2
);
247 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2)
248 struct __old_msqid_ds
250 struct __old_ipc_perm msg_perm
; /* structure describing operation permission */
251 struct msg
*__msg_first
; /* pointer to first message on queue */
252 struct msg
*__msg_last
; /* pointer to last message on queue */
253 __time_t msg_stime
; /* time of last msgsnd command */
254 __time_t msg_rtime
; /* time of last msgrcv command */
255 __time_t msg_ctime
; /* time of last change */
256 struct wait_queue
*__wwait
; /* ??? */
257 struct wait_queue
*__rwait
; /* ??? */
258 unsigned short int __msg_cbytes
; /* current number of bytes on queue */
259 unsigned short int msg_qnum
; /* number of messages currently on queue */
260 unsigned short int msg_qbytes
; /* max number of bytes allowed on queue */
261 __ipc_pid_t msg_lspid
; /* pid of last msgsnd() */
262 __ipc_pid_t msg_lrpid
; /* pid of last msgrcv() */
266 attribute_compat_text_section
267 __old_msgctl (int msqid
, int cmd
, struct __old_msqid_ds
*buf
)
269 #if defined __ASSUME_DIRECT_SYSVIPC_SYSCALLS \
270 && !defined __ASSUME_SYSVIPC_DEFAULT_IPC_64
271 /* For architecture that have wire-up msgctl but also have __IPC_64 to a
272 value different than default (0x0) it means the compat symbol used the
274 return INLINE_SYSCALL_CALL (msgctl
, msqid
, cmd
, buf
);
276 return INLINE_SYSCALL_CALL (ipc
, IPCOP_msgctl
, msqid
, cmd
, 0, buf
);
279 compat_symbol (libc
, __old_msgctl
, msgctl
, GLIBC_2_0
);