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 * NAME 22 * fcntl18.c 23 * 24 * DESCRIPTION 25 * Test to check the error conditions in fcntl system call 26 * 27 * USAGE 28 * fcntl18 29 * 30 * HISTORY 31 * 07/2001 Ported by Wayne Boyer 32 * 33 * RESTRICTIONS 34 * NONE 35 */ 36 37#include <signal.h> 38#include <errno.h> 39#include <pwd.h> 40#include <sys/types.h> 41#include <sys/wait.h> 42#include <sys/stat.h> 43#include <sys/param.h> 44#include <fcntl.h> 45#include <unistd.h> 46#include "test.h" 47 48#define INVAL_FLAG -1 49#define INVAL_MIN (-2147483647L-1L) 50 51int fd; 52char string[40] = ""; 53 54char *TCID = "fcntl18"; 55int TST_TOTAL = 1; 56struct passwd *pass; 57 58void setup(void); 59void cleanup(void); 60int fail; 61 62int main(int ac, char **av) 63{ 64 int retval; 65 struct flock fl; 66 int pid, status; 67 68 tst_parse_opts(ac, av, NULL, NULL); 69 70 setup(); /* global setup */ 71 72/* //block1: */ 73#ifndef UCLINUX 74 /* Skip since uClinux does not implement memory protection */ 75 tst_resm(TINFO, "Enter block 1"); 76 fail = 0; 77 if ((fd = open("temp.dat", O_CREAT | O_RDWR, 0777)) < 0) { //mode must be specified when O_CREATE is in the flag 78 tst_resm(TFAIL, "file opening error"); 79 fail = 1; 80 } 81 82 /* Error condition if address is bad */ 83 retval = fcntl(fd, F_GETLK, (struct flock *)INVAL_FLAG); 84 if (errno == EFAULT) { 85 tst_resm(TPASS, "Test F_GETLK: for errno EFAULT PASSED"); 86 } else { 87 tst_resm(TFAIL, "Test F_GETLK: for errno EFAULT FAILED"); 88 fail = 1; 89 } 90 if (fail) { 91 tst_resm(TINFO, "Block 1 FAILED"); 92 } else { 93 tst_resm(TINFO, "Block 1 PASSED"); 94 } 95 tst_resm(TINFO, "Exit block 1"); 96#else 97 tst_resm(TINFO, "Skip block 1 on uClinux"); 98#endif 99 100/* //block2: */ 101#ifndef UCLINUX 102 /* Skip since uClinux does not implement memory protection */ 103 tst_resm(TINFO, "Enter block 2"); 104 fail = 0; 105 /* Error condition if address is bad */ 106 retval = fcntl(fd, F_GETLK64, (struct flock *)INVAL_FLAG); 107 if (errno == EFAULT) { 108 tst_resm(TPASS, "Test F_GETLK64: for errno EFAULT PASSED"); 109 } else { 110 tst_resm(TFAIL, "Test F_GETLK64: for errno EFAULT FAILED"); 111 fail = 1; 112 } 113 if (fail) { 114 tst_resm(TINFO, "Block 2 FAILED"); 115 } else { 116 tst_resm(TINFO, "Block 2 PASSED"); 117 } 118 tst_resm(TINFO, "Exit block 2"); 119#else 120 tst_resm(TINFO, "Skip block 2 on uClinux"); 121#endif 122 123/* //block3: */ 124 tst_resm(TINFO, "Enter block 3"); 125 fail = 0; 126 if ((pid = FORK_OR_VFORK()) == 0) { /* child */ 127 fail = 0; 128 pass = getpwnam("nobody"); 129 retval = setreuid(-1, pass->pw_uid); 130 if (retval < 0) { 131 tst_resm(TFAIL, "setreuid to user nobody failed, " 132 "errno: %d", errno); 133 fail = 1; 134 } 135 136 /* Error condition: invalid cmd */ 137 retval = fcntl(fd, INVAL_FLAG, &fl); 138 if (errno == EINVAL) { 139 tst_resm(TPASS, "Test for errno EINVAL PASSED"); 140 } else { 141 tst_resm(TFAIL, "Test for errno EINVAL FAILED, " 142 "got: %d", errno); 143 fail = 1; 144 } 145 exit(fail); 146 } else { /* parent */ 147 waitpid(pid, &status, 0); 148 if (WEXITSTATUS(status) != 0) { 149 tst_resm(TFAIL, "child returned bad exit status"); 150 fail = 1; 151 } 152 if (fail) { 153 tst_resm(TINFO, "Block 3 FAILED"); 154 } else { 155 tst_resm(TINFO, "Block 3 PASSED"); 156 } 157 } 158 tst_resm(TINFO, "Exit block 3"); 159 160 cleanup(); 161 tst_exit(); 162 163} 164 165/* 166 * setup() 167 * performs all ONE TIME setup for this test 168 */ 169void setup(void) 170{ 171 172 tst_sig(FORK, DEF_HANDLER, cleanup); 173 174 tst_require_root(); 175 176 umask(0); 177 178 TEST_PAUSE; 179 180 tst_tmpdir(); 181 182 sprintf(string, "./fcntl18.%d.1", getpid()); 183 unlink(string); 184} 185 186/* 187 * cleanup() 188 * performs all the ONE TIME cleanup for this test at completion or 189 * or premature exit. 190 */ 191void cleanup(void) 192{ 193 /* 194 * print timing status if that option was specified. 195 * print errno log if that option was specified 196 */ 197 close(fd); 198 199 tst_rmdir(); 200 201 unlink("temp.dat"); 202 203} 204