1 /* 2 * Copyright (c) International Business Machines Corp., 2002 3 * Copyright (c) 2012 Cyril Hrubis <chrubis (at) suse.cz> 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 * This test verifies that flock cannot unlock a file locked 22 * by another task 23 * 24 * Test Steps: 25 * 26 * Fork a child processes The parent flocks a file with LOCK_EX Child waits 27 * for that to happen, then checks to make sure it is locked. Child then 28 * tries to unlock the file. If the unlock succeeds, the child attempts to 29 * lock the file with LOCK_EX. The test passes if the child is able to lock 30 * the file. 31 */ 32 33 #include <stdio.h> 34 #include <errno.h> 35 #include <fcntl.h> 36 #include <sys/types.h> 37 #include <sys/stat.h> 38 #include <sys/file.h> 39 #include <sys/wait.h> 40 #include "test.h" 41 42 #define FILE_NAME "flock03" 43 44 static void setup(void); 45 static void cleanup(void); 46 static void childfunc(int); 47 48 #ifdef UCLINUX 49 static int fd_uc; 50 static void childfunc_uc(void) 51 { 52 childfunc(fd_uc); 53 } 54 #endif 55 56 char *TCID = "flock03"; 57 int TST_TOTAL = 3; 58 59 int main(int argc, char **argv) 60 { 61 int lc; 62 pid_t pid; 63 int status; 64 int fd; 65 66 tst_parse_opts(argc, argv, NULL, NULL); 67 68 #ifdef UCLINUX 69 maybe_run_child(&childfunc_uc, "ds", &fd_uc, FILE_NAME); 70 #endif 71 72 setup(); 73 74 for (lc = 0; TEST_LOOPING(lc); lc++) { 75 tst_count = 0; 76 77 fd = open(FILE_NAME, O_RDWR); 78 79 if (fd == -1) 80 tst_brkm(TFAIL | TERRNO, cleanup, 81 "parent failed to open the file"); 82 83 pid = FORK_OR_VFORK(); 84 85 if (pid == -1) 86 tst_brkm(TFAIL | TERRNO, cleanup, "fork() failed"); 87 if (pid == 0) { 88 #ifdef UCLINUX 89 if (self_exec(argv[0], "ds", fd, FILE_NAME) < 0) 90 tst_brkm(TFAIL | TERRNO, cleanup, 91 "self_exec failed"); 92 #else 93 childfunc(fd); 94 #endif 95 } 96 97 TEST(flock(fd, LOCK_EX | LOCK_NB)); 98 99 if (TEST_RETURN != 0) 100 tst_resm(TFAIL | TTERRNO, 101 "Parent: Initial attempt to flock() failed"); 102 else 103 tst_resm(TPASS, 104 "Parent: Initial attempt to flock() passed"); 105 106 TST_SAFE_CHECKPOINT_WAKE(cleanup, 0); 107 108 if ((waitpid(pid, &status, 0)) < 0) { 109 tst_resm(TFAIL, "wait() failed"); 110 continue; 111 } 112 if ((WIFEXITED(status)) && (WEXITSTATUS(status) == 0)) 113 tst_resm(TPASS, "flock03 Passed"); 114 else 115 tst_resm(TFAIL, "flock03 Failed"); 116 117 close(fd); 118 119 } 120 121 cleanup(); 122 tst_exit(); 123 } 124 125 static void childfunc(int fd) 126 { 127 int fd2; 128 129 TST_SAFE_CHECKPOINT_WAIT(NULL, 0); 130 131 fd2 = open(FILE_NAME, O_RDWR); 132 133 if (fd2 == -1) { 134 fprintf(stderr, "CHILD: failed to open the file: %s\n", 135 strerror(errno)); 136 exit(1); 137 } 138 139 if (flock(fd2, LOCK_EX | LOCK_NB) != -1) { 140 fprintf(stderr, "CHILD: The file was not already locked\n"); 141 exit(1); 142 } 143 144 TEST(flock(fd, LOCK_UN)); 145 /* XXX: LOCK_UN does not return an error if there was nothing to 146 * unlock. 147 */ 148 if (TEST_RETURN == -1) { 149 fprintf(stderr, "CHILD: Unable to unlock file locked by " 150 "parent: %s\n", strerror(TEST_ERRNO)); 151 exit(1); 152 } else { 153 fprintf(stderr, "CHILD: File locked by parent unlocked\n"); 154 } 155 156 TEST(flock(fd2, LOCK_EX | LOCK_NB)); 157 158 if (TEST_RETURN == -1) { 159 fprintf(stderr, "CHILD: Unable to lock file after " 160 "unlocking: %s\n", strerror(TEST_ERRNO)); 161 exit(1); 162 } else { 163 fprintf(stderr, "CHILD: Locking after unlock passed\n"); 164 } 165 166 close(fd); 167 close(fd2); 168 169 exit(0); 170 } 171 172 static void setup(void) 173 { 174 int fd; 175 176 tst_sig(FORK, DEF_HANDLER, cleanup); 177 178 TEST_PAUSE; 179 180 tst_tmpdir(); 181 182 TST_CHECKPOINT_INIT(tst_rmdir); 183 184 fd = creat(FILE_NAME, 0666); 185 if (fd < 0) { 186 tst_resm(TBROK, "creating a new file failed"); 187 cleanup(); 188 } 189 close(fd); 190 } 191 192 static void cleanup(void) 193 { 194 tst_rmdir(); 195 } 196