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 * fcntl06.c 23 * 24 * DESCRIPTION 25 * Error checking conditions for remote locking of regions of a file. 26 * 27 * CALLS 28 * open(2), write(2), fcntl(2) 29 * 30 * ALGORITHM 31 * Test unlocking sections around a write lock using remote Lock/Unlock 32 * call which should all fail. 33 * 34 * USAGE 35 * fcntl06 36 * 37 * HISTORY 38 * 07/2001 Ported by Wayne Boyer 39 * 40 * RESTRICTIONS 41 * Currently Linux kernel doesn't implement R_GETLK/R_SETLK facility, 42 * but this facility seems to be present in other standard flavours of 43 * Unix. Currently this program has all the testing done under 44 * "#ifdef LINUX_FILE_REGION_LOCK", when Linux implements the regions 45 * locking then, this testcase should be recompiled accordingly with the 46 * "ifdef" removed. 47 */ 48 49 #include <fcntl.h> 50 #include <errno.h> 51 #include <signal.h> 52 #include <sys/types.h> 53 #include <sys/stat.h> 54 #include "test.h" 55 56 #define F_RGETLK 10 /* kludge code */ 57 #define F_RSETLK 11 /* kludge code */ 58 59 char *TCID = "fcntl06"; 60 int TST_TOTAL = 1; 61 62 void setup(); 63 void cleanup(); 64 65 #define STRINGSIZE 27 66 #define STRING "abcdefghijklmnopqrstuvwxyz\n" 67 68 int fd; 69 void unlock_file(); 70 int do_lock(int, short, short, int, int); 71 72 int main(int ac, char **av) 73 { 74 int fail = 0; 75 76 tst_parse_opts(ac, av, NULL, NULL); 77 78 setup(); /* global setup */ 79 80 fail = 0; 81 82 #ifdef LINUX_FILE_REGION_LOCK 83 if (fcntl(fd, F_RGETLK, &tl) == -1) { 84 if (errno == EINVAL) 85 tst_brkm(TCONF, cleanup, 86 "fcntl remote locking feature not implemented in " 87 "the kernel"); 88 else { 89 /* 90 * FIXME (garrcoop): having it always pass on 91 * non-EINVAL is a bad test. 92 */ 93 tst_resm(TPASS, "fcntl on file failed"); 94 } 95 } 96 97 /* 98 * Add a write lock to the middle of the file and unlock a section 99 * just before the lock 100 */ 101 if (do_lock(F_RSETLK, F_WRLCK, 0, 10, 5) == -1) 102 tst_resm(TFAIL, "F_RSETLK WRLCK failed"); 103 104 if (do_lock(F_RSETLK, F_UNLCK, 0, 5, 5) == -1) 105 tst_resm(TFAIL | TERRNO, "F_RSETLK UNLOCK failed"); 106 107 unlock_file(); 108 #else 109 tst_resm(TCONF, "system doesn't have LINUX_LOCK_FILE_REGION support"); 110 #endif 111 112 cleanup(); 113 tst_exit(); 114 } 115 116 void setup(void) 117 { 118 char *buf = STRING; 119 char template[PATH_MAX]; 120 121 tst_sig(FORK, DEF_HANDLER, cleanup); 122 123 umask(0); 124 125 TEST_PAUSE; 126 127 tst_tmpdir(); 128 129 snprintf(template, PATH_MAX, "fcntl06XXXXXX"); 130 131 if ((fd = mkstemp(template)) == -1) 132 tst_resm(TBROK | TERRNO, "mkstemp failed"); 133 134 if (write(fd, buf, STRINGSIZE) == -1) 135 tst_resm(TBROK | TERRNO, "write failed"); 136 } 137 138 int do_lock(int cmd, short type, short whence, int start, int len) 139 { 140 struct flock fl; 141 142 fl.l_type = type; 143 fl.l_whence = whence; 144 fl.l_start = start; 145 fl.l_len = len; 146 return (fcntl(fd, cmd, &fl)); 147 } 148 149 void unlock_file(void) 150 { 151 if (do_lock(F_RSETLK, (short)F_UNLCK, (short)0, 0, 0) == -1) { 152 /* Same as FIXME comment above. */ 153 tst_resm(TPASS | TERRNO, "fcntl on file failed"); 154 } 155 } 156 157 void cleanup(void) 158 { 159 160 if (close(fd) == -1) 161 tst_resm(TWARN | TERRNO, "close failed"); 162 163 tst_rmdir(); 164 165 } 166