1 /*
2 * Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7 #include <fcntl.h>
8 #include <errno.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13
14
15 extern const char *__progname;
16
17 const char* kTemporaryFile = "/tmp/axels-lock-test";
18
19
20 const char*
type_name(int type)21 type_name(int type)
22 {
23 return type == F_RDLCK ? "shared" : type == F_WRLCK
24 ? "exclusive" : "remove";
25 }
26
27
28 int
do_lock(int fd,int type,off_t start,off_t length)29 do_lock(int fd, int type, off_t start, off_t length)
30 {
31 printf("%s lock %lld:%lld\n", type_name(type), start, length);
32
33 struct flock flock;
34 flock.l_type = type;
35 flock.l_whence = SEEK_SET;
36 flock.l_start = start;
37 flock.l_len = length;
38 if (fcntl(fd, F_SETLK, &flock) != 0) {
39 fprintf(stderr, "ERROR: %s lock %lld:%lld failed: %s\n", type_name(type),
40 start, length, strerror(errno));
41 return -1;
42 }
43
44 return 0;
45 }
46
47
48 int
shared_lock(int fd,off_t start,off_t length)49 shared_lock(int fd, off_t start, off_t length)
50 {
51 return do_lock(fd, F_RDLCK, start, length);
52 }
53
54
55 int
exclusive_lock(int fd,off_t start,off_t length)56 exclusive_lock(int fd, off_t start, off_t length)
57 {
58 return do_lock(fd, F_WRLCK, start, length);
59 }
60
61
62 int
remove_lock(int fd,off_t start,off_t length)63 remove_lock(int fd, off_t start, off_t length)
64 {
65 return do_lock(fd, F_UNLCK, start, length);
66 }
67
68
69 void
wait_for_enter()70 wait_for_enter()
71 {
72 puts("wait for <enter>...");
73 char buffer[64];
74 fgets(buffer, sizeof(buffer), stdin);
75 }
76
77
78 void
usage()79 usage()
80 {
81 fprintf(stderr, "usage: %s [shared|exclusive|unlock <start> <length>] "
82 "[wait] [...]\n", __progname);
83 exit(1);
84 }
85
86
87 bool
is_command(const char * op,const char * command1,const char * command2)88 is_command(const char* op, const char* command1, const char* command2)
89 {
90 int length = strlen(op);
91 if (length == 0)
92 return false;
93
94 return command1 != NULL && !strncmp(op, command1, length)
95 || command2 != NULL && !strncmp(op, command2, length);
96 }
97
98
99 int
main(int argc,char ** argv)100 main(int argc, char** argv)
101 {
102 int fd = open(kTemporaryFile, O_CREAT | O_RDWR, 0644);
103 if (fd < 0) {
104 fprintf(stderr, "Could not create lock file: %s\n", strerror(errno));
105 return 1;
106 }
107
108 while (argc > 1) {
109 const char* op = argv[1];
110 if (is_command(op, "wait", NULL)) {
111 wait_for_enter();
112 argv++;
113 argc--;
114 continue;
115 }
116 if (argc < 3)
117 usage();
118
119 off_t start = strtoll(argv[2], NULL, 0);
120 off_t length = strtoll(argv[3], NULL, 0);
121 int type = 0;
122 if (is_command(op, "read", "shared"))
123 type = F_RDLCK;
124 else if (is_command(op, "write", "exclusive"))
125 type = F_WRLCK;
126 else if (is_command(op, "unlock", "remove"))
127 type = F_UNLCK;
128 else
129 usage();
130
131 do_lock(fd, type, start, length);
132 argc -= 3;
133 argv += 3;
134 }
135
136 close(fd);
137 return 0;
138 }
139
140