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