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_ulink01.c						  */
25/*									    */
26/* Description: This tests the mq_ulink() syscall			     */
27/*									      */
28/* 									      */
29/*									      */
30/*									      */
31/*									      */
32/*									    */
33/* Usage:  <for command-line>						 */
34/* mq_ulink01 [-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_ulink01					     */
45/* History:     Porting from Crackerjack to LTP is done by		    */
46/*	      Manas Kumar Nayak maknayak@in.ibm.com>			*/
47/******************************************************************************/
48
49#include <sys/syscall.h>
50#include <sys/types.h>
51#include <sys/stat.h>
52#include <sys/uio.h>
53#include <getopt.h>
54#include <stdlib.h>
55#include <errno.h>
56#include <stdio.h>
57#include <unistd.h>
58#include <string.h>
59#include <mqueue.h>
60#include <limits.h>
61
62#include "../utils/include_j_h.h"
63#include "../utils/common_j_h.c"
64
65#include "test.h"
66#include "linux_syscall_numbers.h"
67
68char *TCID = "mq_ulink01";
69int testno;
70int TST_TOTAL = 1;
71
72/* Extern Global Functions */
73/******************************************************************************/
74/*									    */
75/* Function:    cleanup						       */
76/*									    */
77/* Description: Performs all one time clean up for this test on successful    */
78/*	      completion,  premature exit or  failure. Closes all temporary */
79/*	      files, removes all temporary directories exits the test with  */
80/*	      appropriate return code by calling tst_exit() function.       */
81/*									    */
82/* Input:       None.							 */
83/*									    */
84/* Output:      None.							 */
85/*									    */
86/* Return:      On failure - Exits calling tst_exit(). Non '0' return code.   */
87/*	      On success - Exits calling tst_exit(). With '0' return code.  */
88/*									    */
89/******************************************************************************/
90void cleanup(void)
91{
92
93	tst_rmdir();
94}
95
96/* Local  Functions */
97/******************************************************************************/
98/*									    */
99/* Function:    setup							 */
100/*									    */
101/* Description: Performs all one time setup for this test. This function is   */
102/*	      typically used to capture signals, create temporary dirs      */
103/*	      and temporary files that may be used in the course of this    */
104/*	      test.							 */
105/*									    */
106/* Input:       None.							 */
107/*									    */
108/* Output:      None.							 */
109/*									    */
110/* Return:      On failure - Exits by calling cleanup().		      */
111/*	      On success - returns 0.				       */
112/*									    */
113/******************************************************************************/
114void setup(void)
115{
116	tst_require_root();
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_ulink"
127
128enum test_type {
129	NORMAL,
130};
131
132/*
133 * Data Structure
134 */
135struct test_case {
136	char *user;
137	char *qname;
138	int ttype;
139	int ret;
140	int err;
141};
142
143/* Test cases
144*
145*   test status of errors on man page
146*
147*   EACCES	     v (permission is denied)
148*   ENAMETOOLONG       v (too long name length)
149*   ENOENT	     v (named message queue does not exist)
150*/
151
152static struct test_case tcase[] = {
153	{			// case00
154	 .ttype = NORMAL,
155	 .qname = QUEUE_NAME,
156	 .ret = 0,
157	 .err = 0,
158	 },
159	{			// case01
160	 .ttype = NORMAL,
161	 .user = "nobody",
162	 .qname = QUEUE_NAME,
163	 .ret = -1,
164	 .err = EACCES,
165	 },
166	{			// case02
167	 .ttype = NORMAL,
168	 //  0    1       2       3
169	 //  0123456789012345678901234567890123456789
170	 .qname = "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
171	 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
172	 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
173	 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
174	 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
175	 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaa",
176	 .ret = -1,
177	 .err = ENOENT,
178	 },
179	{			// case03
180	 .ttype = NORMAL,
181	 //  0    1       2       3
182	 //  0123456789012345678901234567890123456789
183	 .qname = "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
184	 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
185	 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
186	 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
187	 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
188	 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaa",
189	 .ret = -1,
190	 .err = ENAMETOOLONG,
191	 },
192};
193
194/*
195 * do_test()
196 *
197 *   Input  : TestCase Data
198 *   Return : RESULT_OK(0), RESULT_NG(1)
199 *
200 */
201
202static int do_test(struct test_case *tc)
203{
204	int sys_ret;
205	int sys_errno;
206	int result = RESULT_OK;
207	int rc, fd1 = -1, fd2 = -1;
208	uid_t old_uid = -1;
209
210	/*
211	 * When test ended with SIGTERM etc, mq discriptor is left remains.
212	 * So we delete it first.
213	 */
214	TEST(mq_unlink(QUEUE_NAME));
215
216	/*
217	 * Open message queue
218	 */
219	rc = mq_open(QUEUE_NAME, O_CREAT | O_EXCL | O_RDWR, S_IRWXU, NULL);
220	if (rc == -1) {
221		tst_resm(TFAIL | TTERRNO, "mq_open failed");
222		result = 1;
223		goto EXIT;
224	}
225	fd1 = rc;
226
227	/*
228	 * Change effective user id
229	 */
230	if (tc->user != NULL) {
231		TEST(rc = setup_euid(tc->user, &old_uid));
232		if (TEST_RETURN < 0) {
233			result = 1;
234			goto EXIT;
235		}
236	}
237
238	/*
239	 * Execute system call
240	 */
241	errno = 0;
242	TEST(sys_ret = mq_unlink(tc->qname));
243	sys_errno = errno;
244	if (sys_ret >= 0)
245		fd2 = sys_ret;
246
247	/*
248	 * Check results
249	 */
250	result |= (sys_errno != tc->err);
251	PRINT_RESULT(sys_ret >= 0, tc->ret, tc->err, sys_ret, sys_errno);
252
253EXIT:
254	if (tc->user != NULL && old_uid != -1)
255		cleanup_euid(old_uid);
256
257	if (fd1 >= 0)
258		close(fd1);
259	if (fd2 >= 0)
260		close(fd2);
261	mq_unlink(QUEUE_NAME);
262	return 0;
263}
264
265int main(int ac, char **av)
266{
267	int i;
268	int lc;
269
270	tst_parse_opts(ac, av, NULL, NULL);
271
272	setup();
273
274	for (lc = 0; TEST_LOOPING(lc); ++lc) {
275		tst_count = 0;
276		for (testno = 0; testno < TST_TOTAL; ++testno) {
277
278			int ret;
279
280			ret = 0;
281
282			for (i = 0; ret == 0 &&
283			     i < (int)ARRAY_SIZE(tcase); i++) {
284				ret = do_test(&tcase[i]);
285			}
286
287		}
288	}
289	cleanup();
290	tst_exit();
291}
292