1/* 2 * 3 * Copyright (c) International Business Machines Corp., 2001 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13 * the GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20/* 21 * Test Name: llseek02 22 * Note that glibc exports the llseek syscall as lseek64. 23 * 24 * Test Description: 25 * Verify that, 26 * 1. llseek() returns -1 and sets errno to EINVAL, if the 'Whence' argument 27 * is not a proper value. 28 * 2. llseek() returns -1 and sets errno to EBADF, if the file handle of 29 * the specified file is not valid. 30 * 31 * Expected Result: 32 * llseek() should fail with return value -1 and set expected errno. 33 * 34 * Algorithm: 35 * Setup: 36 * Setup signal handling. 37 * Create temporary directory. 38 * Pause for SIGUSR1 if option specified. 39 * 40 * Test: 41 * Loop if the proper options are given. 42 * Execute system call 43 * Check return code, if system call failed (return=-1) 44 * if errno set == expected errno 45 * Issue sys call fails with expected return value and errno. 46 * Otherwise, 47 * Issue sys call fails with unexpected errno. 48 * Otherwise, 49 * Issue sys call returns unexpected value. 50 * 51 * Cleanup: 52 * Print errno log and/or timing stats if options given 53 * Delete the temporary directory(s)/file(s) created. 54 * 55 * Usage: <for command-line> 56 * llseek02 [-c n] [-e] [-i n] [-I x] [-P x] [-t] 57 * where, -c n : Run n copies concurrently. 58 * -i n : Execute test n times. 59 * -I x : Execute test for x seconds. 60 * -P x : Pause for x seconds between iterations. 61 * -t : Turn on syscall timing. 62 * 63 * HISTORY 64 * 07/2001 Ported by Wayne Boyer 65 * 66 * RESTRICTIONS: 67 * None. 68 */ 69 70#ifndef _GNU_SOURCE 71#define _GNU_SOURCE 72#endif 73 74#include <stdio.h> 75#include <unistd.h> 76#include <sys/types.h> 77#include <errno.h> 78#include <fcntl.h> 79#include <utime.h> 80#include <string.h> 81#include <sys/stat.h> 82#include <signal.h> 83 84#include "test.h" 85 86#define TEMP_FILE1 "tmp_file1" 87#define TEMP_FILE2 "tmp_file2" 88#define FILE_MODE S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH 89#define SEEK_TOP 10 90 91char *TCID = "llseek02"; 92int TST_TOTAL = 2; 93 94int no_setup(); 95int setup1(); /* setup function to test llseek() for EINVAL */ 96int setup2(); /* setup function to test llseek() for EBADF */ 97 98int fd1; /* file handle for testfile1 */ 99int fd2; /* file handle for testfile2 */ 100 101struct test_case_t { /* test case struct. to hold ref. test cond's */ 102 int fd; 103 int Whence; 104 char *desc; 105 int exp_errno; 106 int (*setupfunc) (); 107} Test_cases[] = { 108 { 109 1, SEEK_TOP, "'whence' argument is not valid", EINVAL, setup1}, { 110 2, SEEK_SET, "'fd' is not an open file descriptor", EBADF, setup2}, 111 { 112 0, 0, NULL, 0, no_setup} 113}; 114 115void setup(); /* Main setup function of test */ 116void cleanup(); /* cleanup function for the test */ 117 118int main(int ac, char **av) 119{ 120 int lc; 121 int fildes; /* file handle for testfile */ 122 int whence; /* position of file handle in the file */ 123 char *test_desc; /* test specific error message */ 124 int ind; /* counter to test different test conditions */ 125 126 tst_parse_opts(ac, av, NULL, NULL); 127 128 setup(); 129 130 for (lc = 0; TEST_LOOPING(lc); lc++) { 131 132 tst_count = 0; 133 134 for (ind = 0; Test_cases[ind].desc != NULL; ind++) { 135 fildes = Test_cases[ind].fd; 136 test_desc = Test_cases[ind].desc; 137 whence = Test_cases[ind].Whence; 138 139 /* Assign the 'fd' values appropriatly */ 140 if (fildes == 1) { 141 fildes = fd1; 142 } else { 143 fildes = fd2; 144 } 145 146 /* 147 * Invoke llseek(2) to test different test conditions. 148 * Verify that it fails with -1 return value and 149 * sets appropriate errno. 150 */ 151 TEST(lseek64(fildes, (loff_t) 0, whence)); 152 153 if (TEST_RETURN != (loff_t) - 1) { 154 tst_resm(TFAIL, 155 "llseek() returned %ld, expected" 156 " -1, errno:%d", TEST_RETURN, 157 Test_cases[ind].exp_errno); 158 continue; 159 } 160 if (TEST_ERRNO == Test_cases[ind].exp_errno) { 161 tst_resm(TPASS, "llseek() fails, %s, errno:%d", 162 test_desc, TEST_ERRNO); 163 } else { 164 tst_resm(TFAIL, "llseek() fails, %s, errno:%d, " 165 "expected errno:%d", test_desc, 166 TEST_ERRNO, Test_cases[ind].exp_errno); 167 } 168 } 169 } 170 171 cleanup(); 172 173 tst_exit(); 174} 175 176/* 177 * setup() - performs all ONE TIME setup for this test. 178 * Create a temporary directory and change directory to it. 179 * Invoke individual test setup functions according to the order 180 * set in test struct. definition. 181 */ 182void setup(void) 183{ 184 int ind; 185 186 tst_sig(NOFORK, DEF_HANDLER, cleanup); 187 188 TEST_PAUSE; 189 190 tst_tmpdir(); 191 192 /* call individual setup functions */ 193 for (ind = 0; Test_cases[ind].desc != NULL; ind++) { 194 Test_cases[ind].setupfunc(); 195 } 196} 197 198/* 199 * no_setup() - This is a dummy function which simply returns 0. 200 */ 201int no_setup(void) 202{ 203 return 0; 204} 205 206/* 207 * setup1() - setup function for a test condition for which llseek(2) 208 * returns -1 and sets errno to EINVAL. 209 * Creat a temporary file for reading/writing and write some data 210 * into it. 211 * This function returns 0 on success. 212 */ 213int setup1(void) 214{ 215 char write_buff[BUFSIZ]; /* buffer to hold data */ 216 217 /* Get the data to be written to temporary file */ 218 strcpy(write_buff, "abcdefg"); 219 220 /* Creat/open a temporary file under above directory */ 221 if ((fd1 = open(TEMP_FILE1, O_RDWR | O_CREAT, FILE_MODE)) == -1) { 222 tst_brkm(TBROK, cleanup, 223 "open(%s, O_RDWR|O_CREAT, %#o) Failed, errno=%d :%s", 224 TEMP_FILE1, FILE_MODE, errno, strerror(errno)); 225 } 226 227 /* Write data into temporary file */ 228 if (write(fd1, write_buff, sizeof(write_buff)) <= 0) { 229 tst_brkm(TBROK, cleanup, "write(2) on %s Failed, errno=%d : %s", 230 TEMP_FILE1, errno, strerror(errno)); 231 } 232 233 return 0; 234} 235 236/* 237 * setup2() - setup function for a test condition for which llseek(2) 238 * returns -1 and sets errno to EBADF. 239 * Creat a temporary file for reading/writing and close it. 240 * This function returns 0 on success. 241 */ 242int setup2(void) 243{ 244 /* Creat/open a temporary file under above directory */ 245 if ((fd2 = open(TEMP_FILE2, O_RDWR | O_CREAT, FILE_MODE)) == -1) { 246 tst_brkm(TBROK, cleanup, 247 "open(%s, O_RDWR|O_CREAT, %#o) Failed, errno=%d :%s", 248 TEMP_FILE2, FILE_MODE, errno, strerror(errno)); 249 } 250 251 /* Close the temporary file created above */ 252 if (close(fd2) < 0) { 253 tst_brkm(TBROK, cleanup, "close(%s) Failed, errno=%d : %s:", 254 TEMP_FILE2, errno, strerror(errno)); 255 } 256 257 return 0; 258} 259 260/* 261 * cleanup() - performs all ONE TIME cleanup for this test at 262 * completion or premature exit. 263 * Close the temporary file. 264 * Remove the test directory and testfile created in the setup. 265 */ 266void cleanup(void) 267{ 268 269 /* Close the temporary file(s) created in setup1/setup2 */ 270 if (close(fd1) < 0) { 271 tst_brkm(TFAIL, NULL, "close(%s) Failed, errno=%d : %s:", 272 TEMP_FILE1, errno, strerror(errno)); 273 } 274 275 tst_rmdir(); 276 277} 278