summaryrefslogtreecommitdiff
path: root/src/regress/lib/libc/sys/t_msgget.c
diff options
context:
space:
mode:
authorbluhm <>2019-11-19 19:57:04 +0000
committerbluhm <>2019-11-19 19:57:04 +0000
commit9185f840eda265016178aeb0dcdba964f8f6f3e2 (patch)
treeda100b3712514c566fe948116f7926ad7f725401 /src/regress/lib/libc/sys/t_msgget.c
parent6a6fe688152b422f3d65c970dad56e7d9d28b1ee (diff)
downloadopenbsd-9185f840eda265016178aeb0dcdba964f8f6f3e2.tar.gz
openbsd-9185f840eda265016178aeb0dcdba964f8f6f3e2.tar.bz2
openbsd-9185f840eda265016178aeb0dcdba964f8f6f3e2.zip
Import NetBSD system call regression tests. They were written with
ATF (Automated Testing Framework), so we use a small wrapper to map it to our bsd.regress.mk framework. Only half of the 80 NetBSD tests have been taken, the others need more work to adapt. Of them 34 syscall tests pass. Moritz Buhl ported the tests to OpenBSD.
Diffstat (limited to 'src/regress/lib/libc/sys/t_msgget.c')
-rw-r--r--src/regress/lib/libc/sys/t_msgget.c339
1 files changed, 339 insertions, 0 deletions
diff --git a/src/regress/lib/libc/sys/t_msgget.c b/src/regress/lib/libc/sys/t_msgget.c
new file mode 100644
index 0000000000..2a9bb4cf3b
--- /dev/null
+++ b/src/regress/lib/libc/sys/t_msgget.c
@@ -0,0 +1,339 @@
1/* $OpenBSD: t_msgget.c,v 1.1.1.1 2019/11/19 19:57:04 bluhm Exp $ */
2/* $NetBSD: t_msgget.c,v 1.3 2017/10/08 08:31:05 kre Exp $ */
3
4/*-
5 * Copyright (c) 2011 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Jukka Ruohonen.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include "macros.h"
34
35#include <sys/cdefs.h>
36__RCSID("$NetBSD: t_msgget.c,v 1.3 2017/10/08 08:31:05 kre Exp $");
37
38#include <sys/msg.h>
39#include <sys/stat.h>
40#include <sys/sysctl.h>
41#include <sys/wait.h>
42
43#include "atf-c.h"
44#include <errno.h>
45#include <pwd.h>
46#include <stdio.h>
47#include <stdlib.h>
48#include <string.h>
49#include <sysexits.h>
50#include <time.h>
51#include <unistd.h>
52
53#define MSG_KEY 12345689
54
55static void clean(void);
56
57static void
58clean(void)
59{
60 int id;
61
62 if ((id = msgget(MSG_KEY, 0)) != -1)
63 (void)msgctl(id, IPC_RMID, 0);
64}
65
66ATF_TC_WITH_CLEANUP(msgget_excl);
67ATF_TC_HEAD(msgget_excl, tc)
68{
69 atf_tc_set_md_var(tc, "descr", "Test msgget(2) with IPC_EXCL");
70}
71
72ATF_TC_BODY(msgget_excl, tc)
73{
74 int id;
75
76 /*
77 * Create a message queue and re-open it with
78 * O_CREAT and IPC_EXCL set. This should fail.
79 */
80 id = msgget(MSG_KEY, IPC_CREAT | 0600);
81
82 if (id < 0)
83 atf_tc_fail("failed to create message queue");
84
85 errno = 0;
86
87 if (msgget(MSG_KEY, IPC_CREAT | IPC_EXCL | 0600) != -1)
88 atf_tc_fail("msgget(2) failed for IPC_EXCL");
89
90 ATF_REQUIRE(errno == EEXIST);
91
92 /*
93 * However, the same call should succeed
94 * when IPC_EXCL is not set in the flags.
95 */
96 id = msgget(MSG_KEY, IPC_CREAT | 0600);
97
98 if (id < 0)
99 atf_tc_fail("msgget(2) failed to re-open");
100
101 ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
102}
103
104ATF_TC_CLEANUP(msgget_excl, tc)
105{
106 clean();
107}
108
109ATF_TC_WITH_CLEANUP(msgget_exit);
110ATF_TC_HEAD(msgget_exit, tc)
111{
112 atf_tc_set_md_var(tc, "descr",
113 "Test that XSI message queues are "
114 "not removed when the process exits");
115}
116
117ATF_TC_BODY(msgget_exit, tc)
118{
119 int id, sta;
120 pid_t pid;
121
122 pid = fork();
123 ATF_REQUIRE(pid >= 0);
124
125 if (pid == 0) {
126
127 if (msgget(MSG_KEY, IPC_CREAT | IPC_EXCL | 0600) == -1)
128 _exit(EXIT_FAILURE);
129
130 _exit(EXIT_SUCCESS);
131 }
132
133 (void)wait(&sta);
134
135 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
136 atf_tc_fail("failed to create message queue");
137
138 id = msgget(MSG_KEY, 0);
139
140 if (id == -1)
141 atf_tc_fail("message queue was removed on process exit");
142
143 ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
144}
145
146ATF_TC_CLEANUP(msgget_exit, tc)
147{
148 clean();
149}
150
151ATF_TC_WITH_CLEANUP(msgget_init);
152ATF_TC_HEAD(msgget_init, tc)
153{
154 atf_tc_set_md_var(tc, "descr",
155 "Test that msgget(2) initializes data structures properly");
156}
157
158ATF_TC_BODY(msgget_init, tc)
159{
160 const uid_t uid = geteuid();
161 const gid_t gid = getegid();
162 struct msqid_ds msgds;
163 time_t t;
164 int id;
165
166 (void)memset(&msgds, 0x9, sizeof(struct msqid_ds));
167
168 t = time(NULL);
169 id = msgget(MSG_KEY, IPC_CREAT | 0600);
170
171 ATF_REQUIRE(id !=-1);
172 ATF_REQUIRE(msgctl(id, IPC_STAT, &msgds) == 0);
173
174 ATF_CHECK(msgds.msg_qnum == 0);
175 ATF_CHECK(msgds.msg_lspid == 0);
176 ATF_CHECK(msgds.msg_lrpid == 0);
177 ATF_CHECK(msgds.msg_rtime == 0);
178 ATF_CHECK(msgds.msg_stime == 0);
179 ATF_CHECK(msgds.msg_perm.uid == uid);
180 ATF_CHECK(msgds.msg_perm.gid == gid);
181 ATF_CHECK(msgds.msg_perm.cuid == uid);
182 ATF_CHECK(msgds.msg_perm.cgid == gid);
183 ATF_CHECK(msgds.msg_perm.mode == 0600);
184
185 if (llabs(t - msgds.msg_ctime) > 5)
186 atf_tc_fail("msgget(2) initialized current time incorrectly");
187
188 ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
189}
190
191ATF_TC_CLEANUP(msgget_init, tc)
192{
193 clean();
194}
195
196ATF_TC(msgget_limit);
197ATF_TC_HEAD(msgget_limit, tc)
198{
199 atf_tc_set_md_var(tc, "descr", "Test msgget(2) against system limits");
200}
201
202ATF_TC_BODY(msgget_limit, tc)
203{
204 size_t len = sizeof(int);
205 bool fail = false;
206 int i, lim = 0;
207 int *buf;
208
209 if (sysctlbyname("kern.ipc.msgmni", &lim, &len, NULL, 0) != 0)
210 atf_tc_skip("failed to read kern.ipc.msgmni sysctl");
211
212 buf = calloc(lim + 1, sizeof(*buf));
213 ATF_REQUIRE(buf != NULL);
214
215 for (i = 0; i < lim; i++) {
216
217 buf[i] = msgget(MSG_KEY + i, IPC_CREAT | IPC_EXCL | 0600);
218
219 (void)fprintf(stderr, "key[%d] = %d\n", i, buf[i]);
220
221 /*
222 * This test only works when there are zero existing
223 * message queues. Thus, bypass the unit test when
224 * this precondition is not met, for reason or another.
225 */
226 if (buf[i] == -1)
227 goto out;
228 }
229
230 i++;
231 errno = 0;
232
233 buf[i] = msgget(MSG_KEY + i, IPC_CREAT | IPC_EXCL | 0600);
234
235 if (buf[i] != -1 || errno != ENOSPC)
236 fail = true;
237
238out: /* Remember to clean-up. */
239 for (i = 0; i < lim; i++)
240 (void)msgctl(buf[i], IPC_RMID, 0);
241
242 free(buf);
243
244 if (fail != false)
245 atf_tc_fail("msgget(2) opened more than %d queues", lim);
246}
247
248ATF_TC_WITH_CLEANUP(msgget_mode);
249ATF_TC_HEAD(msgget_mode, tc)
250{
251 atf_tc_set_md_var(tc, "descr", "Test different modes with msgget(2)");
252 atf_tc_set_md_var(tc, "require.user", "root");
253}
254
255ATF_TC_BODY(msgget_mode, tc)
256{
257 static const mode_t mode[] = {
258 S_IRWXU, S_IRUSR, S_IWUSR, S_IXUSR, S_IRWXG, S_IRGRP,
259 S_IWGRP, S_IXGRP, S_IRWXO, S_IROTH, S_IWOTH, S_IXOTH
260 };
261
262 struct msqid_ds msgds;
263 size_t i;
264 int id;
265
266 for (i = 0; i < __arraycount(mode); i++) {
267
268 (void)fprintf(stderr, "testing mode %d\n", mode[i]);
269 (void)memset(&msgds, 0, sizeof(struct msqid_ds));
270
271 id = msgget(MSG_KEY, IPC_CREAT | IPC_EXCL | (int)mode[i]);
272
273 ATF_REQUIRE(id != -1);
274 ATF_REQUIRE(msgctl(id, IPC_STAT, &msgds) == 0);
275 ATF_REQUIRE(msgds.msg_perm.mode == mode[i]);
276 ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
277 }
278}
279
280ATF_TC_CLEANUP(msgget_mode, tc)
281{
282 clean();
283}
284
285static volatile int sig_caught;
286
287static void
288sigsys_handler(int signum)
289{
290
291 sig_caught = signum;
292}
293
294static int
295no_kernel_sysvmsg(void)
296{
297 int id;
298 void (*osig)(int);
299
300 sig_caught = 0;
301 osig = signal(SIGSYS, sigsys_handler);
302 id = msgget(MSG_KEY, IPC_CREAT | 0600);
303 if (sig_caught || id == -1)
304 return 1;
305
306 (void)msgctl(id, IPC_RMID, 0);
307 (void)signal(SIGSYS, osig);
308
309 return 0;
310}
311
312ATF_TC(msgget_query);
313ATF_TC_HEAD(msgget_query, tc)
314{
315 atf_tc_set_md_var(tc, "descr", "Skip msgget_* tests - no SYSVMSG");
316}
317ATF_TC_BODY(msgget_query, tc)
318{
319 atf_tc_skip("No SYSVMSG in kernel");
320}
321
322ATF_TP_ADD_TCS(tp)
323{
324
325 if (no_kernel_sysvmsg()) {
326 ATF_TP_ADD_TC(tp, msgget_query);
327 } else {
328 ATF_TP_ADD_TC(tp, msgget_excl);
329 ATF_TP_ADD_TC(tp, msgget_exit);
330 ATF_TP_ADD_TC(tp, msgget_init);
331 /*
332 * Adjusted for OpenBSD, not available
333 * ATF_TP_ADD_TC(tp, msgget_limit);
334 */
335 ATF_TP_ADD_TC(tp, msgget_mode);
336 }
337
338 return atf_no_error();
339}