xref: /freebsd/contrib/netbsd-tests/lib/libc/sys/t_msgget.c (revision acfbf5901384e07ff4b54ef1d6a8480eed6e223e)
1*57718be8SEnji Cooper /* $NetBSD: t_msgget.c,v 1.2 2014/02/27 00:59:50 joerg Exp $ */
2*57718be8SEnji Cooper 
3*57718be8SEnji Cooper /*-
4*57718be8SEnji Cooper  * Copyright (c) 2011 The NetBSD Foundation, Inc.
5*57718be8SEnji Cooper  * All rights reserved.
6*57718be8SEnji Cooper  *
7*57718be8SEnji Cooper  * This code is derived from software contributed to The NetBSD Foundation
8*57718be8SEnji Cooper  * by Jukka Ruohonen.
9*57718be8SEnji Cooper  *
10*57718be8SEnji Cooper  * Redistribution and use in source and binary forms, with or without
11*57718be8SEnji Cooper  * modification, are permitted provided that the following conditions
12*57718be8SEnji Cooper  * are met:
13*57718be8SEnji Cooper  * 1. Redistributions of source code must retain the above copyright
14*57718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer.
15*57718be8SEnji Cooper  * 2. Redistributions in binary form must reproduce the above copyright
16*57718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer in the
17*57718be8SEnji Cooper  *    documentation and/or other materials provided with the distribution.
18*57718be8SEnji Cooper  *
19*57718be8SEnji Cooper  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20*57718be8SEnji Cooper  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21*57718be8SEnji Cooper  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22*57718be8SEnji Cooper  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23*57718be8SEnji Cooper  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*57718be8SEnji Cooper  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*57718be8SEnji Cooper  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*57718be8SEnji Cooper  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*57718be8SEnji Cooper  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*57718be8SEnji Cooper  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*57718be8SEnji Cooper  * POSSIBILITY OF SUCH DAMAGE.
30*57718be8SEnji Cooper  */
31*57718be8SEnji Cooper #include <sys/cdefs.h>
32*57718be8SEnji Cooper __RCSID("$NetBSD: t_msgget.c,v 1.2 2014/02/27 00:59:50 joerg Exp $");
33*57718be8SEnji Cooper 
34*57718be8SEnji Cooper #include <sys/msg.h>
35*57718be8SEnji Cooper #include <sys/stat.h>
36*57718be8SEnji Cooper #include <sys/sysctl.h>
37*57718be8SEnji Cooper #include <sys/wait.h>
38*57718be8SEnji Cooper 
39*57718be8SEnji Cooper #include <atf-c.h>
40*57718be8SEnji Cooper #include <errno.h>
41*57718be8SEnji Cooper #include <pwd.h>
42*57718be8SEnji Cooper #include <stdio.h>
43*57718be8SEnji Cooper #include <stdlib.h>
44*57718be8SEnji Cooper #include <string.h>
45*57718be8SEnji Cooper #include <sysexits.h>
46*57718be8SEnji Cooper #include <time.h>
47*57718be8SEnji Cooper #include <unistd.h>
48*57718be8SEnji Cooper 
49*57718be8SEnji Cooper #define MSG_KEY		12345689
50*57718be8SEnji Cooper 
51*57718be8SEnji Cooper static void		clean(void);
52*57718be8SEnji Cooper 
53*57718be8SEnji Cooper static void
clean(void)54*57718be8SEnji Cooper clean(void)
55*57718be8SEnji Cooper {
56*57718be8SEnji Cooper 	int id;
57*57718be8SEnji Cooper 
58*57718be8SEnji Cooper 	if ((id = msgget(MSG_KEY, 0)) != -1)
59*57718be8SEnji Cooper 		(void)msgctl(id, IPC_RMID, 0);
60*57718be8SEnji Cooper }
61*57718be8SEnji Cooper 
62*57718be8SEnji Cooper ATF_TC_WITH_CLEANUP(msgget_excl);
ATF_TC_HEAD(msgget_excl,tc)63*57718be8SEnji Cooper ATF_TC_HEAD(msgget_excl, tc)
64*57718be8SEnji Cooper {
65*57718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test msgget(2) with IPC_EXCL");
66*57718be8SEnji Cooper }
67*57718be8SEnji Cooper 
ATF_TC_BODY(msgget_excl,tc)68*57718be8SEnji Cooper ATF_TC_BODY(msgget_excl, tc)
69*57718be8SEnji Cooper {
70*57718be8SEnji Cooper 	int id;
71*57718be8SEnji Cooper 
72*57718be8SEnji Cooper 	/*
73*57718be8SEnji Cooper 	 * Create a message queue and re-open it with
74*57718be8SEnji Cooper 	 * O_CREAT and IPC_EXCL set. This should fail.
75*57718be8SEnji Cooper 	 */
76*57718be8SEnji Cooper 	id = msgget(MSG_KEY, IPC_CREAT | 0600);
77*57718be8SEnji Cooper 
78*57718be8SEnji Cooper 	if (id < 0)
79*57718be8SEnji Cooper 		atf_tc_fail("failed to create message queue");
80*57718be8SEnji Cooper 
81*57718be8SEnji Cooper 	errno = 0;
82*57718be8SEnji Cooper 
83*57718be8SEnji Cooper 	if (msgget(MSG_KEY, IPC_CREAT | IPC_EXCL | 0600) != -1)
84*57718be8SEnji Cooper 		atf_tc_fail("msgget(2) failed for IPC_EXCL");
85*57718be8SEnji Cooper 
86*57718be8SEnji Cooper 	ATF_REQUIRE(errno == EEXIST);
87*57718be8SEnji Cooper 
88*57718be8SEnji Cooper 	/*
89*57718be8SEnji Cooper 	 * However, the same call should succeed
90*57718be8SEnji Cooper 	 * when IPC_EXCL is not set in the flags.
91*57718be8SEnji Cooper 	 */
92*57718be8SEnji Cooper 	id = msgget(MSG_KEY, IPC_CREAT | 0600);
93*57718be8SEnji Cooper 
94*57718be8SEnji Cooper 	if (id < 0)
95*57718be8SEnji Cooper 		atf_tc_fail("msgget(2) failed to re-open");
96*57718be8SEnji Cooper 
97*57718be8SEnji Cooper 	ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
98*57718be8SEnji Cooper }
99*57718be8SEnji Cooper 
ATF_TC_CLEANUP(msgget_excl,tc)100*57718be8SEnji Cooper ATF_TC_CLEANUP(msgget_excl, tc)
101*57718be8SEnji Cooper {
102*57718be8SEnji Cooper 	clean();
103*57718be8SEnji Cooper }
104*57718be8SEnji Cooper 
105*57718be8SEnji Cooper ATF_TC_WITH_CLEANUP(msgget_exit);
ATF_TC_HEAD(msgget_exit,tc)106*57718be8SEnji Cooper ATF_TC_HEAD(msgget_exit, tc)
107*57718be8SEnji Cooper {
108*57718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
109*57718be8SEnji Cooper 	    "Test that XSI message queues are "
110*57718be8SEnji Cooper 	    "not removed when the process exits");
111*57718be8SEnji Cooper }
112*57718be8SEnji Cooper 
ATF_TC_BODY(msgget_exit,tc)113*57718be8SEnji Cooper ATF_TC_BODY(msgget_exit, tc)
114*57718be8SEnji Cooper {
115*57718be8SEnji Cooper 	int id, sta;
116*57718be8SEnji Cooper 	pid_t pid;
117*57718be8SEnji Cooper 
118*57718be8SEnji Cooper 	pid = fork();
119*57718be8SEnji Cooper 	ATF_REQUIRE(pid >= 0);
120*57718be8SEnji Cooper 
121*57718be8SEnji Cooper 	if (pid == 0) {
122*57718be8SEnji Cooper 
123*57718be8SEnji Cooper 		if (msgget(MSG_KEY, IPC_CREAT | IPC_EXCL | 0600) == -1)
124*57718be8SEnji Cooper 			_exit(EXIT_FAILURE);
125*57718be8SEnji Cooper 
126*57718be8SEnji Cooper 		_exit(EXIT_SUCCESS);
127*57718be8SEnji Cooper 	}
128*57718be8SEnji Cooper 
129*57718be8SEnji Cooper 	(void)wait(&sta);
130*57718be8SEnji Cooper 
131*57718be8SEnji Cooper 	if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
132*57718be8SEnji Cooper 		atf_tc_fail("failed to create message queue");
133*57718be8SEnji Cooper 
134*57718be8SEnji Cooper 	id = msgget(MSG_KEY, 0);
135*57718be8SEnji Cooper 
136*57718be8SEnji Cooper 	if (id == -1)
137*57718be8SEnji Cooper 		atf_tc_fail("message queue was removed on process exit");
138*57718be8SEnji Cooper 
139*57718be8SEnji Cooper 	ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
140*57718be8SEnji Cooper }
141*57718be8SEnji Cooper 
ATF_TC_CLEANUP(msgget_exit,tc)142*57718be8SEnji Cooper ATF_TC_CLEANUP(msgget_exit, tc)
143*57718be8SEnji Cooper {
144*57718be8SEnji Cooper 	clean();
145*57718be8SEnji Cooper }
146*57718be8SEnji Cooper 
147*57718be8SEnji Cooper ATF_TC_WITH_CLEANUP(msgget_init);
ATF_TC_HEAD(msgget_init,tc)148*57718be8SEnji Cooper ATF_TC_HEAD(msgget_init, tc)
149*57718be8SEnji Cooper {
150*57718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
151*57718be8SEnji Cooper 	    "Test that msgget(2) initializes data structures properly");
152*57718be8SEnji Cooper }
153*57718be8SEnji Cooper 
ATF_TC_BODY(msgget_init,tc)154*57718be8SEnji Cooper ATF_TC_BODY(msgget_init, tc)
155*57718be8SEnji Cooper {
156*57718be8SEnji Cooper 	const uid_t uid = geteuid();
157*57718be8SEnji Cooper 	const gid_t gid = getegid();
158*57718be8SEnji Cooper 	struct msqid_ds msgds;
159*57718be8SEnji Cooper 	time_t t;
160*57718be8SEnji Cooper 	int id;
161*57718be8SEnji Cooper 
162*57718be8SEnji Cooper 	(void)memset(&msgds, 0x9, sizeof(struct msqid_ds));
163*57718be8SEnji Cooper 
164*57718be8SEnji Cooper 	t = time(NULL);
165*57718be8SEnji Cooper 	id = msgget(MSG_KEY, IPC_CREAT | 0600);
166*57718be8SEnji Cooper 
167*57718be8SEnji Cooper 	ATF_REQUIRE(id !=-1);
168*57718be8SEnji Cooper 	ATF_REQUIRE(msgctl(id, IPC_STAT, &msgds) == 0);
169*57718be8SEnji Cooper 
170*57718be8SEnji Cooper 	ATF_CHECK(msgds.msg_qnum == 0);
171*57718be8SEnji Cooper 	ATF_CHECK(msgds.msg_lspid == 0);
172*57718be8SEnji Cooper 	ATF_CHECK(msgds.msg_lrpid == 0);
173*57718be8SEnji Cooper 	ATF_CHECK(msgds.msg_rtime == 0);
174*57718be8SEnji Cooper 	ATF_CHECK(msgds.msg_stime == 0);
175*57718be8SEnji Cooper 	ATF_CHECK(msgds.msg_perm.uid == uid);
176*57718be8SEnji Cooper 	ATF_CHECK(msgds.msg_perm.gid == gid);
177*57718be8SEnji Cooper 	ATF_CHECK(msgds.msg_perm.cuid == uid);
178*57718be8SEnji Cooper 	ATF_CHECK(msgds.msg_perm.cgid == gid);
179*57718be8SEnji Cooper 	ATF_CHECK(msgds.msg_perm.mode == 0600);
180*57718be8SEnji Cooper 
181*57718be8SEnji Cooper 	if (llabs(t - msgds.msg_ctime) > 5)
182*57718be8SEnji Cooper 		atf_tc_fail("msgget(2) initialized current time incorrectly");
183*57718be8SEnji Cooper 
184*57718be8SEnji Cooper 	ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
185*57718be8SEnji Cooper }
186*57718be8SEnji Cooper 
ATF_TC_CLEANUP(msgget_init,tc)187*57718be8SEnji Cooper ATF_TC_CLEANUP(msgget_init, tc)
188*57718be8SEnji Cooper {
189*57718be8SEnji Cooper 	clean();
190*57718be8SEnji Cooper }
191*57718be8SEnji Cooper 
192*57718be8SEnji Cooper ATF_TC(msgget_limit);
ATF_TC_HEAD(msgget_limit,tc)193*57718be8SEnji Cooper ATF_TC_HEAD(msgget_limit, tc)
194*57718be8SEnji Cooper {
195*57718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test msgget(2) against system limits");
196*57718be8SEnji Cooper }
197*57718be8SEnji Cooper 
ATF_TC_BODY(msgget_limit,tc)198*57718be8SEnji Cooper ATF_TC_BODY(msgget_limit, tc)
199*57718be8SEnji Cooper {
200*57718be8SEnji Cooper 	size_t len = sizeof(int);
201*57718be8SEnji Cooper 	bool fail = false;
202*57718be8SEnji Cooper 	int i, lim = 0;
203*57718be8SEnji Cooper 	int *buf;
204*57718be8SEnji Cooper 
205*57718be8SEnji Cooper 	if (sysctlbyname("kern.ipc.msgmni", &lim, &len, NULL, 0) != 0)
206*57718be8SEnji Cooper 		atf_tc_skip("failed to read kern.ipc.msgmni sysctl");
207*57718be8SEnji Cooper 
208*57718be8SEnji Cooper 	buf = calloc(lim + 1, sizeof(*buf));
209*57718be8SEnji Cooper 	ATF_REQUIRE(buf != NULL);
210*57718be8SEnji Cooper 
211*57718be8SEnji Cooper 	for (i = 0; i < lim; i++) {
212*57718be8SEnji Cooper 
213*57718be8SEnji Cooper 		buf[i] = msgget(MSG_KEY + i, IPC_CREAT | IPC_EXCL | 0600);
214*57718be8SEnji Cooper 
215*57718be8SEnji Cooper 		(void)fprintf(stderr, "key[%d] = %d\n", i, buf[i]);
216*57718be8SEnji Cooper 
217*57718be8SEnji Cooper 		/*
218*57718be8SEnji Cooper 		 * This test only works when there are zero existing
219*57718be8SEnji Cooper 		 * message queues. Thus, bypass the unit test when
220*57718be8SEnji Cooper 		 * this precondition is not met, for reason or another.
221*57718be8SEnji Cooper 		 */
222*57718be8SEnji Cooper 		if (buf[i] == -1)
223*57718be8SEnji Cooper 			goto out;
224*57718be8SEnji Cooper 	}
225*57718be8SEnji Cooper 
226*57718be8SEnji Cooper 	errno = 0;
227*57718be8SEnji Cooper 
228*57718be8SEnji Cooper 	buf[i] = msgget(MSG_KEY + i, IPC_CREAT | IPC_EXCL | 0600);
229*57718be8SEnji Cooper 
230*57718be8SEnji Cooper 	if (buf[i] != -1 || errno != ENOSPC)
231*57718be8SEnji Cooper 		fail = true;
232*57718be8SEnji Cooper 
233*57718be8SEnji Cooper out:	/* Remember to clean-up. */
234*57718be8SEnji Cooper 	for (i = 0; i < lim; i++)
235*57718be8SEnji Cooper 		(void)msgctl(buf[i], IPC_RMID, 0);
236*57718be8SEnji Cooper 
237*57718be8SEnji Cooper 	free(buf);
238*57718be8SEnji Cooper 
239*57718be8SEnji Cooper 	if (fail != false)
240*57718be8SEnji Cooper 		atf_tc_fail("msgget(2) opened more than %d queues", lim);
241*57718be8SEnji Cooper }
242*57718be8SEnji Cooper 
243*57718be8SEnji Cooper ATF_TC_WITH_CLEANUP(msgget_mode);
ATF_TC_HEAD(msgget_mode,tc)244*57718be8SEnji Cooper ATF_TC_HEAD(msgget_mode, tc)
245*57718be8SEnji Cooper {
246*57718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test different modes with msgget(2)");
247*57718be8SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
248*57718be8SEnji Cooper }
249*57718be8SEnji Cooper 
ATF_TC_BODY(msgget_mode,tc)250*57718be8SEnji Cooper ATF_TC_BODY(msgget_mode, tc)
251*57718be8SEnji Cooper {
252*57718be8SEnji Cooper 	static const mode_t mode[] = {
253*57718be8SEnji Cooper 		S_IRWXU, S_IRUSR, S_IWUSR, S_IXUSR, S_IRWXG, S_IRGRP,
254*57718be8SEnji Cooper 		S_IWGRP, S_IXGRP, S_IRWXO, S_IROTH, S_IWOTH, S_IXOTH
255*57718be8SEnji Cooper 	};
256*57718be8SEnji Cooper 
257*57718be8SEnji Cooper 	struct msqid_ds msgds;
258*57718be8SEnji Cooper 	size_t i;
259*57718be8SEnji Cooper 	int id;
260*57718be8SEnji Cooper 
261*57718be8SEnji Cooper 	for (i = 0; i < __arraycount(mode); i++) {
262*57718be8SEnji Cooper 
263*57718be8SEnji Cooper 		(void)fprintf(stderr, "testing mode %d\n", mode[i]);
264*57718be8SEnji Cooper 		(void)memset(&msgds, 0, sizeof(struct msqid_ds));
265*57718be8SEnji Cooper 
266*57718be8SEnji Cooper 		id = msgget(MSG_KEY, IPC_CREAT | IPC_EXCL | (int)mode[i]);
267*57718be8SEnji Cooper 
268*57718be8SEnji Cooper 		ATF_REQUIRE(id != -1);
269*57718be8SEnji Cooper 		ATF_REQUIRE(msgctl(id, IPC_STAT, &msgds) == 0);
270*57718be8SEnji Cooper 		ATF_REQUIRE(msgds.msg_perm.mode == mode[i]);
271*57718be8SEnji Cooper 		ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
272*57718be8SEnji Cooper 	}
273*57718be8SEnji Cooper }
274*57718be8SEnji Cooper 
ATF_TC_CLEANUP(msgget_mode,tc)275*57718be8SEnji Cooper ATF_TC_CLEANUP(msgget_mode, tc)
276*57718be8SEnji Cooper {
277*57718be8SEnji Cooper 	clean();
278*57718be8SEnji Cooper }
279*57718be8SEnji Cooper 
280*57718be8SEnji Cooper 
ATF_TP_ADD_TCS(tp)281*57718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
282*57718be8SEnji Cooper {
283*57718be8SEnji Cooper 
284*57718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, msgget_excl);
285*57718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, msgget_exit);
286*57718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, msgget_init);
287*57718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, msgget_limit);
288*57718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, msgget_mode);
289*57718be8SEnji Cooper 
290*57718be8SEnji Cooper 	return atf_no_error();
291*57718be8SEnji Cooper }
292