Home | History | Annotate | Download | only in fcntl
      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 
     51 int fd;
     52 char string[40] = "";
     53 
     54 char *TCID = "fcntl18";
     55 int TST_TOTAL = 1;
     56 struct passwd *pass;
     57 
     58 void setup(void);
     59 void cleanup(void);
     60 int fail;
     61 
     62 int 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  */
    169 void 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  */
    191 void 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