• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************/
2 /* Copyright (c) Crackerjack Project., 2007-2008 ,Hitachi, Ltd		*/
3 /*	  Author(s): Takahiro Yasui <takahiro.yasui.mp@hitachi.com>,	      */
4 /*		       Yumiko Sugita <yumiko.sugita.yf@hitachi.com>, 	      */
5 /*		       Satoshi Fujiwara <sa-fuji@sdl.hitachi.co.jp>	      */
6 /*								  	      */
7 /* This program is free software;  you can redistribute it and/or modify      */
8 /* it under the terms of the GNU General Public License as published by       */
9 /* the Free Software Foundation; either version 2 of the License, or	  */
10 /* (at your option) any later version.					*/
11 /*									    */
12 /* This program is distributed in the hope that it will be useful,	    */
13 /* but WITHOUT ANY WARRANTY;  without even the implied warranty of	    */
14 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See		  */
15 /* the GNU General Public License for more details.			   */
16 /*									    */
17 /* You should have received a copy of the GNU General Public License	  */
18 /* along with this program;  if not, write to the Free Software	       */
19 /* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA    */
20 /*									    */
21 /******************************************************************************/
22 /******************************************************************************/
23 /*									    */
24 /* File:	mq_open01.c						   */
25 /*									    */
26 /* Description: This tests the mq_open() syscall			      */
27 /*									      */
28 /* 									      */
29 /*									      */
30 /*									      */
31 /*									      */
32 /*									    */
33 /* Usage:  <for command-line>						 */
34 /* mq_open01 [-c n] [-e][-i n] [-I x] [-p x] [-t]			     */
35 /*      where,  -c n : Run n copies concurrently.			     */
36 /*	      -e   : Turn on errno logging.				 */
37 /*	      -i n : Execute test n times.				  */
38 /*	      -I x : Execute test for x seconds.			    */
39 /*	      -P x : Pause for x seconds between iterations.		*/
40 /*	      -t   : Turn on syscall timing.				*/
41 /*									    */
42 /* Total Tests: 1							     */
43 /*									    */
44 /* Test Name:   mq_open01						     */
45 /* History:     Porting from Crackerjack to LTP is done by		    */
46 /*	      Manas Kumar Nayak maknayak@in.ibm.com>			*/
47 /******************************************************************************/
48 #include <sys/syscall.h>
49 #include <sys/types.h>
50 #include <sys/stat.h>
51 #include <sys/uio.h>
52 #include <getopt.h>
53 #include <stdlib.h>
54 #include <errno.h>
55 #include <stdio.h>
56 #include <unistd.h>
57 #include <string.h>
58 #include <mqueue.h>
59 #include <limits.h>
60 
61 #include "../utils/include_j_h.h"
62 #include "../utils/common_j_h.c"
63 
64 #include "test.h"
65 #include "linux_syscall_numbers.h"
66 
67 char *TCID = "mq_open01";
68 int testno;
69 int TST_TOTAL = 1;
70 
71 /* Extern Global Functions */
72 /******************************************************************************/
73 /*									    */
74 /* Function:    cleanup						       */
75 /*									    */
76 /* Description: Performs all one time clean up for this test on successful    */
77 /*	      completion,  premature exit or  failure. Closes all temporary */
78 /*	      files, removes all temporary directories exits the test with  */
79 /*	      appropriate return code by calling tst_exit() function.       */
80 /*									    */
81 /* Input:       None.							 */
82 /*									    */
83 /* Output:      None.							 */
84 /*									    */
85 /* Return:      On failure - Exits calling tst_exit(). Non '0' return code.   */
86 /*	      On success - Exits calling tst_exit(). With '0' return code.  */
87 /*									    */
88 /******************************************************************************/
cleanup(void)89 void cleanup(void)
90 {
91 
92 	tst_rmdir();
93 }
94 
95 /* Local  Functions */
96 /******************************************************************************/
97 /*									    */
98 /* Function:    setup							 */
99 /*									    */
100 /* Description: Performs all one time setup for this test. This function is   */
101 /*	      typically used to capture signals, create temporary dirs      */
102 /*	      and temporary files that may be used in the course of this    */
103 /*	      test.							 */
104 /*									    */
105 /* Input:       None.							 */
106 /*									    */
107 /* Output:      None.							 */
108 /*									    */
109 /* Return:      On failure - Exits by calling cleanup().		      */
110 /*	      On success - returns 0.				       */
111 /*									    */
112 /******************************************************************************/
setup(void)113 void setup(void)
114 {
115 	tst_require_root();
116 
117 	/* Capture signals if any */
118 	/* Create temporary directories */
119 	TEST_PAUSE;
120 	tst_tmpdir();
121 }
122 
123 /*
124  * Macros
125  */
126 #define SYSCALL_NAME    "mq_open"
127 
128 enum test_type {
129 	NORMAL,
130 	NO_FILE,
131 	NO_SPACE,
132 };
133 
134 /*
135  * Data Structure
136  */
137 struct test_case {
138 	int ttype;
139 	char *user;
140 	char *qname;
141 	int oflag;
142 	long mq_maxmsg;		// Maximum numebr of messages.
143 	long mq_msgsize;	// Maximum message size.
144 	int ret;
145 	int err;
146 };
147 
148 #define ULIMIT_FNUM     0
149 #define PROC_MAX_QUEUES "/proc/sys/fs/mqueue/queues_max"
150 
151 /* Test cases
152  *
153  *   test status of errors on man page
154  *
155  *   EACCES	     v (permission is denied)
156  *   EEXIST	     v (named message queue already exists)
157  *   EINTR	      --- (interrupted by a signal)
158  *   EINVAL	     v (not supported for the given name, or invalid
159  *			 arguments)
160  *   EMFILE	     v (process file table overflow)
161  *   ENAMETOOLONG       v (too long name length)
162  *   ENFILE	     can't check because it's difficult to create no-fd
163  *   ENOENT	     v (O_CREAT is not set and the named message queue
164  *			 does not exist)
165  *   ENOSPC	     v (no space for the new message queue)
166  */
167 
168 static struct test_case tcase[] = {
169 #if 1
170 	{			// case00
171 	 .ttype = NORMAL,
172 	 .qname = QUEUE_NAME,
173 	 .oflag = O_CREAT,
174 	 .mq_maxmsg = 20,
175 	 .mq_msgsize = 16384,
176 	 .ret = 0,
177 	 .err = 0,
178 	 },
179 #else
180 	{			// case00
181 	 .ttype = NORMAL,
182 	 .qname = QUEUE_NAME,
183 	 .oflag = O_CREAT,
184 	 .ret = 0,
185 	 .err = 0,
186 	 },
187 	{			// case01
188 	 .ttype = NORMAL,
189 	 //  0    1       2       3
190 	 //  0123456789012345678901234567890123456789
191 	 "aaaaaaaaaaaaaaa",
192 	 .oflag = O_CREAT,
193 	 .ret = 0,
194 	 .err = 0,
195 	 },
196 	{			// case02
197 	 .ttype = NORMAL,
198 	 //  0    1       2       3
199 	 //  0123456789012345678901234567890123456789
200 	 "aaaaaaaaaaaaaaaa",
201 	 .oflag = O_CREAT,
202 	 .ret = -1,
203 	 .err = ENAMETOOLONG,
204 	 },
205 
206 	{			// case03
207 	 .ttype = NORMAL,
208 	 .qname = "",
209 	 .oflag = O_CREAT,
210 	 .ret = -1,
211 	 .err = EINVAL,
212 	 },
213 	{			// case04
214 	 .ttype = NORMAL,
215 	 .user = "nobody",
216 	 .qname = QUEUE_NAME,
217 	 .ret = -1,
218 	 .err = EACCES,
219 	 },
220 	{			// case05
221 	 .ttype = NORMAL,
222 	 .qname = QUEUE_NAME,
223 	 .oflag = O_CREAT | O_EXCL,
224 	 .ret = -1,
225 	 .err = EEXIST,
226 	 },
227 	{			// case06
228 	 .ttype = NO_FILE,
229 	 .qname = QUEUE_NAME,
230 	 .oflag = O_CREAT,
231 	 .ret = -1,
232 	 .err = EMFILE,
233 	 },
234 	{			// case07
235 	 .ttype = NORMAL,
236 	 .qname = "/notexist",
237 	 .oflag = 0,
238 	 .ret = -1,
239 	 .err = ENOENT,
240 	 },
241 
242 	{			// case08
243 	 .ttype = NO_SPACE,
244 	 .user = "nobody",
245 	 .qname = QUEUE_NAME,
246 	 .oflag = O_CREAT,
247 	 .ret = -1,
248 	 .err = ENOSPC,
249 	 },
250 #endif
251 };
252 
253 /*
254  * do_test()
255  *
256  *   Input  : TestCase Data
257  *   Return : RESULT_OK(0), RESULT_NG(1)
258  *
259  */
260 
do_test(struct test_case * tc)261 static int do_test(struct test_case *tc)
262 {
263 	int sys_ret;
264 	int sys_errno;
265 	int result = RESULT_OK;
266 	int rc, fd1 = -1, fd2 = -1, cmp_ok = 1;
267 	uid_t old_uid = -1;
268 	rlim_t oldlim = -1;
269 	int oldval = -1;
270 	struct mq_attr new, old, *p_attr;
271 
272 	/*
273 	 * When test ended with SIGTERM etc, mq discriptor is left remains.
274 	 * So we delete it first.
275 	 */
276 	TEST(mq_unlink(QUEUE_NAME));
277 
278 	/*
279 	 * Execute system call
280 	 */
281 
282 	if (tc->ttype != NO_SPACE && !(tc->oflag & O_CREAT)) {
283 		errno = 0;
284 		TEST(sys_ret =
285 		     mq_open(QUEUE_NAME, O_CREAT | O_EXCL | O_RDWR, S_IRWXU,
286 			     NULL));
287 		sys_errno = errno;
288 		if (sys_ret < 0)
289 			goto TEST_END;
290 		fd1 = sys_ret;
291 	}
292 	if (tc->ttype == NO_FILE) {
293 		TEST(rc = setup_ulimit_fnum(ULIMIT_FNUM, &oldlim));
294 		if (rc < 0) {
295 			result = 1;
296 			goto EXIT;
297 		}
298 	}
299 
300 	/*
301 	 * Change /proc/sys/fs/mqueue/queues_max
302 	 */
303 	if (tc->ttype == NO_SPACE) {
304 		TEST(rc = setup_proc_fs(PROC_MAX_QUEUES, 0, &oldval));
305 		if (rc < 0) {
306 			result = 1;
307 			goto EXIT;
308 		}
309 	}
310 
311 	/*
312 	 * Change effective user id
313 	 */
314 	if (tc->user != NULL) {
315 		TEST(rc = setup_euid(tc->user, &old_uid));
316 		if (rc < 0) {
317 			result = 1;
318 			goto EXIT;
319 		}
320 	}
321 
322 	/*
323 	 * Execute system call
324 	 */
325 	//tst_resm(TINFO,"PATH_MAX: %d\n", PATH_MAX);
326 	//tst_resm(TINFO,"NAME_MAX: %d", NAME_MAX);
327 	p_attr = NULL;
328 	if (tc->mq_maxmsg || tc->mq_msgsize) {
329 		new.mq_maxmsg = tc->mq_maxmsg;
330 		new.mq_msgsize = tc->mq_msgsize;
331 		p_attr = &new;
332 	}
333 	errno = 0;
334 	if (tc->oflag & O_CREAT)
335 		TEST(sys_ret = mq_open(tc->qname, tc->oflag, S_IRWXU, p_attr));
336 	else
337 		TEST(sys_ret = mq_open(tc->qname, tc->oflag));
338 	sys_errno = errno;
339 	if (sys_ret < 0)
340 		goto TEST_END;
341 	fd2 = sys_ret;
342 
343 	if (p_attr) {
344 		TEST(rc = ltp_syscall(__NR_mq_getsetattr, fd2, NULL, &old));
345 		if (TEST_RETURN < 0) {
346 			tst_resm(TFAIL,
347 				 "mq_getsetattr failed - errno = %d : %s",
348 				 TEST_ERRNO, strerror(TEST_ERRNO));
349 			result = 1;
350 			goto EXIT;
351 		}
352 		tst_resm(TINFO, "mq_maxmsg E:%ld,\tR:%ld", new.mq_maxmsg,
353 			 old.mq_maxmsg);
354 		tst_resm(TINFO, "mq_msgsize E:%ld,\tR:%ld", new.mq_msgsize,
355 			 old.mq_msgsize);
356 		cmp_ok = old.mq_maxmsg == new.mq_maxmsg
357 		    && old.mq_msgsize == new.mq_msgsize;
358 	}
359 
360 TEST_END:
361 	/*
362 	 * Check results
363 	 */
364 	result |= (sys_errno != tc->err) || !cmp_ok;
365 	PRINT_RESULT_CMP(sys_ret >= 0, tc->ret, tc->err, sys_ret, sys_errno,
366 			 cmp_ok);
367 
368 EXIT:
369 	if (tc->user != NULL && old_uid != -1)
370 		TEST(cleanup_euid(old_uid));
371 
372 	if (tc->ttype == NO_SPACE && oldval != -1)
373 		TEST(cleanup_proc_fs(PROC_MAX_QUEUES, oldval));
374 
375 	if (tc->ttype == NO_FILE && oldlim != -1)
376 		TEST(cleanup_ulimit_fnum(oldlim));
377 	if (fd1 >= 0)
378 		TEST(close(fd1));
379 	if (fd2 >= 0)
380 		TEST(close(fd2));
381 	if (fd1 >= 0)
382 		TEST(mq_unlink(QUEUE_NAME));
383 	if (fd2 >= 0 && strcmp(tc->qname, QUEUE_NAME) != 0)
384 		TEST(mq_unlink(tc->qname));
385 
386 	return result;
387 }
388 
389 /*
390  * main()
391  */
392 
main(int ac,char ** av)393 int main(int ac, char **av)
394 {
395 	int result = RESULT_OK;
396 	int i;
397 	int lc;
398 
399 	tst_parse_opts(ac, av, NULL, NULL);
400 
401 	setup();
402 
403 	for (lc = 0; TEST_LOOPING(lc); ++lc) {
404 		tst_count = 0;
405 		for (testno = 0; testno < TST_TOTAL; ++testno) {
406 
407 			/*
408 			 * Execute test
409 			 */
410 			for (i = 0; i < (int)ARRAY_SIZE(tcase); i++) {
411 				int ret;
412 				tst_resm(TINFO, "(case%02d) START", i);
413 				ret = do_test(&tcase[i]);
414 				tst_resm(TINFO, "(case%02d) END => %s", i,
415 					 (ret == 0) ? "OK" : "NG");
416 				result |= ret;
417 			}
418 
419 			/*
420 			 * Check results
421 			 */
422 			switch (result) {
423 			case RESULT_OK:
424 				tst_resm(TPASS, "mq_open call succeeded ");
425 				break;
426 
427 			default:
428 				tst_brkm(TFAIL | TTERRNO, cleanup,
429 					 "mq_open failed");
430 				break;
431 			}
432 
433 		}
434 	}
435 	cleanup();
436 	tst_exit();
437 }
438