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