1ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart/** Test program for POSIX advisory record locking. See also #164669 2ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart * (http://bugs.kde.org/show_bug.cgi?id=164669). 3ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart * See also http://www.opengroup.org/onlinepubs/007908799/xsh/fcntl.html. 4ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart */ 5ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart 6ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart 7e55883df39c57a7aad64e85a770492509d2e4c2bbart#include <assert.h> 8e55883df39c57a7aad64e85a770492509d2e4c2bbart#include <errno.h> 9ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart#include <fcntl.h> 10ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart#include <stdio.h> 11ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart#include <stdlib.h> 1283b62cbbab29bde83eba40231f307c2a311e73c8njn#include "tests/sys_mman.h" 13e55883df39c57a7aad64e85a770492509d2e4c2bbart#include <sys/stat.h> 14e55883df39c57a7aad64e85a770492509d2e4c2bbart#include <sys/types.h> 15e55883df39c57a7aad64e85a770492509d2e4c2bbart#include <sys/wait.h> 16e55883df39c57a7aad64e85a770492509d2e4c2bbart#include <unistd.h> 17ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart#include <unistd.h> 18ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart 19ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart 20ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart/** Lock an entire file exclusively. 21ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart * 22ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart * @return 1 upon success, 0 upon failure. 23ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart */ 24ad60eeb3336aea0f14de01fd74d219c664e6d7d0bartstatic int lock_file(const int fd) 25ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart{ 26ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart struct flock fl; 27ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart 28ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart fl.l_type = F_WRLCK; /* exclusive lock */ 29ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart fl.l_whence = SEEK_SET; 30ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart fl.l_start = 0; 31ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart fl.l_len = 0; /* lock entire file */ 32ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart fl.l_pid = 0; 33ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart return fcntl(fd, F_SETLK, &fl) >= 0; 34ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart} 35ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart 36e55883df39c57a7aad64e85a770492509d2e4c2bbartstatic int open_lock_and_map(const char* const process_name, 37e55883df39c57a7aad64e85a770492509d2e4c2bbart const char* const filename) 38e55883df39c57a7aad64e85a770492509d2e4c2bbart{ 39e55883df39c57a7aad64e85a770492509d2e4c2bbart int fd; 40e55883df39c57a7aad64e85a770492509d2e4c2bbart int flags; 41e55883df39c57a7aad64e85a770492509d2e4c2bbart 42e55883df39c57a7aad64e85a770492509d2e4c2bbart fd = open(filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); 43e55883df39c57a7aad64e85a770492509d2e4c2bbart if (fd < 0) 44e55883df39c57a7aad64e85a770492509d2e4c2bbart { 45e55883df39c57a7aad64e85a770492509d2e4c2bbart perror("open"); 46e55883df39c57a7aad64e85a770492509d2e4c2bbart goto err1; 47e55883df39c57a7aad64e85a770492509d2e4c2bbart } 48e55883df39c57a7aad64e85a770492509d2e4c2bbart 49e55883df39c57a7aad64e85a770492509d2e4c2bbart flags = fcntl(fd, F_GETFD); 50e55883df39c57a7aad64e85a770492509d2e4c2bbart assert(flags >= 0); 51e55883df39c57a7aad64e85a770492509d2e4c2bbart if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) 52e55883df39c57a7aad64e85a770492509d2e4c2bbart assert(0); 53e55883df39c57a7aad64e85a770492509d2e4c2bbart 54e55883df39c57a7aad64e85a770492509d2e4c2bbart fprintf(stderr, "%s: about to lock file for writing.\n", process_name); 55e55883df39c57a7aad64e85a770492509d2e4c2bbart if (! lock_file(fd)) 56e55883df39c57a7aad64e85a770492509d2e4c2bbart { 57e55883df39c57a7aad64e85a770492509d2e4c2bbart perror("fcntl"); 58e55883df39c57a7aad64e85a770492509d2e4c2bbart goto err2; 59e55883df39c57a7aad64e85a770492509d2e4c2bbart } 60e55883df39c57a7aad64e85a770492509d2e4c2bbart 61e55883df39c57a7aad64e85a770492509d2e4c2bbart fprintf(stderr, "%s: file locking attempt succeeded.\n", process_name); 62e55883df39c57a7aad64e85a770492509d2e4c2bbart if (mmap(NULL, 1, PROT_WRITE, MAP_SHARED, fd, 0) == 0) 63e55883df39c57a7aad64e85a770492509d2e4c2bbart { 64e55883df39c57a7aad64e85a770492509d2e4c2bbart perror("mmap"); 65e55883df39c57a7aad64e85a770492509d2e4c2bbart goto err2; 66e55883df39c57a7aad64e85a770492509d2e4c2bbart } 67e55883df39c57a7aad64e85a770492509d2e4c2bbart 68e55883df39c57a7aad64e85a770492509d2e4c2bbart goto out; 69e55883df39c57a7aad64e85a770492509d2e4c2bbart 70e55883df39c57a7aad64e85a770492509d2e4c2bbarterr2: 71e55883df39c57a7aad64e85a770492509d2e4c2bbart close(fd); 72e55883df39c57a7aad64e85a770492509d2e4c2bbarterr1: 73e55883df39c57a7aad64e85a770492509d2e4c2bbartout: 74e55883df39c57a7aad64e85a770492509d2e4c2bbart return fd; 75e55883df39c57a7aad64e85a770492509d2e4c2bbart} 76ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart 77ad60eeb3336aea0f14de01fd74d219c664e6d7d0bartint main(int argc, char *argv[]) 78ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart{ 79ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart int fd1; 80ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart int fd2; 81ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart int exitcode = 1; 82ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart char filename[256]; 83ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart 848eb8bab992e3998c33770b0cdb16059a8b918a06sewardj snprintf(filename, sizeof(filename), "/tmp/valgrind-file-locking-test.%ld", 858eb8bab992e3998c33770b0cdb16059a8b918a06sewardj (long) getpid()); 86ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart 87ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart unlink(filename); 88ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart 89e55883df39c57a7aad64e85a770492509d2e4c2bbart if ((fd1 = open_lock_and_map("parent", filename)) >= 0) 90ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart { 91e55883df39c57a7aad64e85a770492509d2e4c2bbart pid_t fork_result; 92e55883df39c57a7aad64e85a770492509d2e4c2bbart 93e55883df39c57a7aad64e85a770492509d2e4c2bbart fork_result = fork(); 94e55883df39c57a7aad64e85a770492509d2e4c2bbart switch (fork_result) 95ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart { 96e55883df39c57a7aad64e85a770492509d2e4c2bbart case -1: 97e55883df39c57a7aad64e85a770492509d2e4c2bbart perror("fork"); 98e55883df39c57a7aad64e85a770492509d2e4c2bbart break; 99e55883df39c57a7aad64e85a770492509d2e4c2bbart 100e55883df39c57a7aad64e85a770492509d2e4c2bbart case 0: 101e55883df39c57a7aad64e85a770492509d2e4c2bbart /* child */ 102e55883df39c57a7aad64e85a770492509d2e4c2bbart fd2 = open_lock_and_map("child", filename); 103e55883df39c57a7aad64e85a770492509d2e4c2bbart if (fd2 >= 0) 104ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart { 105ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart close(fd2); 106ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart } 107e55883df39c57a7aad64e85a770492509d2e4c2bbart exit(0); 108e55883df39c57a7aad64e85a770492509d2e4c2bbart break; 109e55883df39c57a7aad64e85a770492509d2e4c2bbart 110e55883df39c57a7aad64e85a770492509d2e4c2bbart default: 111e55883df39c57a7aad64e85a770492509d2e4c2bbart /* parent */ 112ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart { 113e55883df39c57a7aad64e85a770492509d2e4c2bbart int child_status; 114e55883df39c57a7aad64e85a770492509d2e4c2bbart int wait_result; 115e55883df39c57a7aad64e85a770492509d2e4c2bbart 116e55883df39c57a7aad64e85a770492509d2e4c2bbart wait_result = wait4(fork_result, &child_status, 0, 0); 117e55883df39c57a7aad64e85a770492509d2e4c2bbart assert(wait_result >= 0); 118ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart } 119ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart } 120ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart } 121ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart 122e55883df39c57a7aad64e85a770492509d2e4c2bbart close(fd1); 123e55883df39c57a7aad64e85a770492509d2e4c2bbart 124ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart unlink(filename); 125ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart 126e55883df39c57a7aad64e85a770492509d2e4c2bbart fprintf(stderr, "Test finished.\n"); 127ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart 128ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart return exitcode; 129ad60eeb3336aea0f14de01fd74d219c664e6d7d0bart} 130