1 /* Basic tests for Linux SYSV message queue extensions.
2 Copyright (C) 2020-2023 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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/>. */
26 #include <support/check.h>
27 #include <support/temp_file.h>
29 #define MSGQ_MODE 0644
31 /* These are for the temporary file we generate. */
38 /* Enforce message queue removal in case of early test failure.
39 Ignore error since the msg may already have being removed. */
40 msgctl (msqid
, IPC_RMID
, NULL
);
44 do_prepare (int argc
, char *argv
[])
46 TEST_VERIFY_EXIT (create_temp_file ("tst-sysvmsg.", &name
) != -1);
49 #define PREPARE do_prepare
58 /* It tries to obtain some system-wide SysV message queue information from
59 /proc to check against IPC_INFO/MSG_INFO. The /proc only returns the
60 tunables value of MSGMAX, MSGMNB, and MSGMNI.
62 The kernel also returns constant value for MSGSSZ, MSGSEG and also MSGMAP,
63 MSGPOOL, and MSGTQL (for IPC_INFO). The issue to check them is they might
64 change over kernel releases. */
67 read_proc_file (const char *file
)
69 FILE *f
= fopen (file
, "r");
71 FAIL_UNSUPPORTED ("/proc is not mounted or %s is not available", file
);
74 int r
= fscanf (f
, "%d", & v
);
75 TEST_VERIFY_EXIT (r
== 1);
82 /* Check if the message queue with IDX (index into the kernel's internal
83 array) matches the one with KEY. The CMD is either MSG_STAT or
87 check_msginfo (int idx
, key_t key
, int cmd
)
89 struct msqid_ds msginfo
;
90 int mid
= msgctl (idx
, cmd
, &msginfo
);
91 /* Ignore unused array slot returned by the kernel or information from
92 unknown message queue. */
93 if ((mid
== -1 && errno
== EINVAL
) || mid
!= msqid
)
97 FAIL_EXIT1 ("msgctl with %s failed: %m",
98 cmd
== MSG_STAT
? "MSG_STAT" : "MSG_STAT_ANY");
100 TEST_COMPARE (msginfo
.msg_perm
.__key
, key
);
101 TEST_COMPARE (msginfo
.msg_perm
.mode
, MSGQ_MODE
);
102 TEST_COMPARE (msginfo
.msg_qnum
, 0);
112 key_t key
= ftok (name
, 'G');
114 FAIL_EXIT1 ("ftok failed: %m");
116 msqid
= msgget (key
, MSGQ_MODE
| IPC_CREAT
);
118 FAIL_EXIT1 ("msgget failed: %m");
120 struct test_msginfo tipcinfo
;
121 tipcinfo
.msgmax
= read_proc_file ("/proc/sys/kernel/msgmax");
122 tipcinfo
.msgmnb
= read_proc_file ("/proc/sys/kernel/msgmnb");
123 tipcinfo
.msgmni
= read_proc_file ("/proc/sys/kernel/msgmni");
128 struct msginfo ipcinfo
;
129 msqidx
= msgctl (msqid
, IPC_INFO
, (struct msqid_ds
*) &ipcinfo
);
131 FAIL_EXIT1 ("msgctl with IPC_INFO failed: %m");
133 TEST_COMPARE (ipcinfo
.msgmax
, tipcinfo
.msgmax
);
134 TEST_COMPARE (ipcinfo
.msgmnb
, tipcinfo
.msgmnb
);
135 TEST_COMPARE (ipcinfo
.msgmni
, tipcinfo
.msgmni
);
138 /* Same as before but with MSG_INFO. */
140 struct msginfo ipcinfo
;
141 msqidx
= msgctl (msqid
, MSG_INFO
, (struct msqid_ds
*) &ipcinfo
);
143 FAIL_EXIT1 ("msgctl with IPC_INFO failed: %m");
145 TEST_COMPARE (ipcinfo
.msgmax
, tipcinfo
.msgmax
);
146 TEST_COMPARE (ipcinfo
.msgmnb
, tipcinfo
.msgmnb
);
147 TEST_COMPARE (ipcinfo
.msgmni
, tipcinfo
.msgmni
);
150 /* We check if the created message queue shows in global list. */
152 for (int i
= 0; i
<= msqidx
; i
++)
154 /* We can't tell apart if MSG_STAT_ANY is not supported (kernel older
155 than 4.17) or if the index used is invalid. So it just check if the
156 value returned from a valid call matches the created message
158 check_msginfo (i
, key
, MSG_STAT_ANY
);
160 if (check_msginfo (i
, key
, MSG_STAT
))
168 FAIL_EXIT1 ("msgctl with MSG_STAT/MSG_STAT_ANY could not find the "
169 "created message queue");
171 if (msgctl (msqid
, IPC_RMID
, NULL
) == -1)
172 FAIL_EXIT1 ("msgctl failed");
177 #include <support/test-driver.c>