1 /* 2 * Copyright 2017 SUSE LLC 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of version 2 of the GNU General Public License as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it would be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 * 12 * You should have received a copy of the GNU General Public License along 13 * with this program; If not, see <http://www.gnu.org/licenses/>. 14 * 15 * Tests that file locks are not inherited by the child process after a fork. 16 */ 17 18 #include <stdio.h> 19 #include <stdlib.h> 20 #include <unistd.h> 21 #include <fcntl.h> 22 #include <sys/wait.h> 23 #include <errno.h> 24 #include <string.h> 25 26 #include "posixtest.h" 27 28 static int child(int fd) 29 { 30 struct flock fl = { 31 .l_type = F_WRLCK, 32 .l_whence = SEEK_SET, 33 .l_start = 1, 34 .l_len = 99 35 }; 36 37 if (fcntl(fd, F_GETLK, &fl) == -1) { 38 printf("Could not get lock: %s (%d)\n", 39 strerror(errno), errno); 40 return PTS_UNRESOLVED; 41 } 42 43 if (fl.l_type == F_UNLCK) { 44 printf("Child found lock is F_UNLCK, should be F_WRLCK\n"); 45 return PTS_FAIL; 46 } 47 48 if (fcntl(fd, F_SETLK, &fl) == -1) { 49 if (errno == EACCES || errno == EAGAIN) { 50 printf("PASSED: child did not inherit the lock\n"); 51 return PTS_PASS; 52 } 53 54 printf("Unexpected fcntl error: %s (%d)\n", 55 strerror(errno), errno); 56 return PTS_UNRESOLVED; 57 } 58 59 printf("Child locked file already locked by parent\n"); 60 return PTS_FAIL; 61 } 62 63 int main(void) 64 { 65 char path_template[] = "/tmp/fork-11-1-XXXXXX"; 66 int fd, child_stat, result = PTS_UNRESOLVED; 67 pid_t child_pid; 68 struct flock fl = { 69 .l_type = F_WRLCK, 70 .l_whence = SEEK_SET, 71 .l_start = 0, 72 .l_len = 100, 73 }; 74 75 fd = mkstemp(path_template); 76 if (fd == -1) { 77 printf("Could not open temporary file: %s (%d)\n", 78 strerror(errno), errno); 79 return result; 80 } 81 82 if (fcntl(fd, F_SETLK, &fl) == -1) { 83 printf("Could not set initial lock: %s (%d)\n", 84 strerror(errno), errno); 85 goto cleanup; 86 } 87 88 child_pid = fork(); 89 if (child_pid == -1) { 90 printf("Fork failed: %s (%d)\n", strerror(errno), errno); 91 goto cleanup; 92 } 93 94 if (child_pid == 0) 95 exit(child(fd)); 96 97 if (waitpid(child_pid, &child_stat, 0) == -1) { 98 printf("Wait failed: %s (%d)\n", strerror(errno), errno); 99 goto cleanup; 100 } 101 102 if (WIFEXITED(child_stat)) 103 result = WEXITSTATUS(child_stat); 104 else 105 printf("Child terminated abnormally!\n"); 106 107 cleanup: 108 close(fd); 109 return result; 110 } 111