blob: 4e60bea9e8a503bccbc2c7c7098ee2611beace67 [file] [log] [blame]
bartad60eeb2008-06-23 11:43:28 +00001/** Test program for POSIX advisory record locking. See also #164669
2 * (http://bugs.kde.org/show_bug.cgi?id=164669).
3 * See also http://www.opengroup.org/onlinepubs/007908799/xsh/fcntl.html.
4 */
5
6
barte55883d2008-06-24 09:54:05 +00007#include <assert.h>
8#include <errno.h>
bartad60eeb2008-06-23 11:43:28 +00009#include <fcntl.h>
10#include <stdio.h>
bartad60eeb2008-06-23 11:43:28 +000011#include <stdlib.h>
barte55883d2008-06-24 09:54:05 +000012#include <sys/mman.h>
13#include <sys/stat.h>
14#include <sys/types.h>
15#include <sys/wait.h>
16#include <unistd.h>
bartad60eeb2008-06-23 11:43:28 +000017#include <unistd.h>
18
19
20/** Lock an entire file exclusively.
21 *
22 * @return 1 upon success, 0 upon failure.
23 */
24static int lock_file(const int fd)
25{
26 struct flock fl;
27
28 fl.l_type = F_WRLCK; /* exclusive lock */
29 fl.l_whence = SEEK_SET;
30 fl.l_start = 0;
31 fl.l_len = 0; /* lock entire file */
32 fl.l_pid = 0;
33 return fcntl(fd, F_SETLK, &fl) >= 0;
34}
35
barte55883d2008-06-24 09:54:05 +000036static int open_lock_and_map(const char* const process_name,
37 const char* const filename)
38{
39 int fd;
40 int flags;
41
42 fd = open(filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
43 if (fd < 0)
44 {
45 perror("open");
46 goto err1;
47 }
48
49 flags = fcntl(fd, F_GETFD);
50 assert(flags >= 0);
51 if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
52 assert(0);
53
54 fprintf(stderr, "%s: about to lock file for writing.\n", process_name);
55 if (! lock_file(fd))
56 {
57 perror("fcntl");
58 goto err2;
59 }
60
61 fprintf(stderr, "%s: file locking attempt succeeded.\n", process_name);
62 if (mmap(NULL, 1, PROT_WRITE, MAP_SHARED, fd, 0) == 0)
63 {
64 perror("mmap");
65 goto err2;
66 }
67
68 goto out;
69
70err2:
71 close(fd);
72err1:
73out:
74 return fd;
75}
bartad60eeb2008-06-23 11:43:28 +000076
77int main(int argc, char *argv[])
78{
79 int fd1;
80 int fd2;
81 int exitcode = 1;
82 char filename[256];
83
84 snprintf(filename, sizeof(filename), "/tmp/valgrind-file-locking-test.%d",
85 getpid());
86
87 unlink(filename);
88
barte55883d2008-06-24 09:54:05 +000089 if ((fd1 = open_lock_and_map("parent", filename)) >= 0)
bartad60eeb2008-06-23 11:43:28 +000090 {
barte55883d2008-06-24 09:54:05 +000091 pid_t fork_result;
92
93 fork_result = fork();
94 switch (fork_result)
bartad60eeb2008-06-23 11:43:28 +000095 {
barte55883d2008-06-24 09:54:05 +000096 case -1:
97 perror("fork");
98 break;
99
100 case 0:
101 /* child */
102 fd2 = open_lock_and_map("child", filename);
103 if (fd2 >= 0)
bartad60eeb2008-06-23 11:43:28 +0000104 {
bartad60eeb2008-06-23 11:43:28 +0000105 close(fd2);
106 }
barte55883d2008-06-24 09:54:05 +0000107 exit(0);
108 break;
109
110 default:
111 /* parent */
bartad60eeb2008-06-23 11:43:28 +0000112 {
barte55883d2008-06-24 09:54:05 +0000113 int child_status;
114 int wait_result;
115
116 wait_result = wait4(fork_result, &child_status, 0, 0);
117 assert(wait_result >= 0);
bartad60eeb2008-06-23 11:43:28 +0000118 }
119 }
bartad60eeb2008-06-23 11:43:28 +0000120 }
barte55883d2008-06-24 09:54:05 +0000121
122 close(fd1);
bartad60eeb2008-06-23 11:43:28 +0000123
124 unlink(filename);
125
barte55883d2008-06-24 09:54:05 +0000126 fprintf(stderr, "Test finished.\n");
bartad60eeb2008-06-23 11:43:28 +0000127
128 return exitcode;
129}