9
#define LOG_ERR(func, err) \
11
fprintf(stderr, "%s : returned error (%s)\n", func, strerror(err)); \
17
char *buf = "ten bytes!";
18
char *fname = "/mnt/glusterfs/0/mand.lock";
19
int open_flags, child, err, status, blocked = 0;
24
/* Initialize file open flags */
25
if (strcmp(argv[2], "BLOCK") == 0)
27
else if (strcmp(argv[2], "TRUNC") == 0)
28
open_flags = O_RDWR | O_TRUNC | O_NONBLOCK;
29
else if (strcmp(argv[2], "NONE") == 0)
30
open_flags = O_RDWR | O_NONBLOCK;
32
LOG_ERR("Invalid option:", EINVAL);
35
fd = open(fname, open_flags);
37
LOG_ERR("Child open", errno);
39
/* Perform the file operation*/
40
if (strcmp(argv[3], "READ") == 0) {
42
err = read(fd, buf, 10);
44
LOG_ERR("Child read", errno);
45
} else if (strcmp(argv[3], "WRITE") == 0) {
46
err = write(fd, buf, 10);
48
LOG_ERR("Child write", errno);
49
} else if (strcmp(argv[3], "FTRUNCATE") == 0) {
50
err = ftruncate(fd, 5);
52
LOG_ERR("Child ftruncate", errno);
54
LOG_ERR("Invalid operation:", EINVAL);
59
LOG_ERR("Child close", errno);
66
main(int argc, char *argv[])
70
"Wrong usage: Use as ./mandatory-lock "
71
"<RD_LCK/WR_LCK> <BLOCK/TRUNC/NONE> "
72
"<READ/WRITE/FTRUNCATE\n");
75
/* Create an empty lock file */
76
fd = open(fname, O_CREAT | O_RDWR, 0755);
78
LOG_ERR("Parent create", errno);
80
/* Determine the type of lock */
81
if (strcmp(argv[1], "RD_LCK") == 0)
82
lock.l_type = F_RDLCK;
83
else if (strcmp(argv[1], "WR_LCK") == 0)
84
lock.l_type = F_WRLCK;
86
LOG_ERR("Parent lock type", EINVAL);
88
lock.l_whence = SEEK_SET;
92
/* Let parent acquire the initial lock */
93
err = fcntl(fd, F_SETLK, &lock);
95
LOG_ERR("Parent lock", errno);
97
/* Now fork a child */
100
/* Perform the child operations */
103
/* If blocking mode, then sleep for 2 seconds
104
* and wait for the child */
105
if (strcmp(argv[2], "NONE") != 0) {
107
if (waitpid(child, &status, WNOHANG) == 0)
109
/* Release the parent lock so that the
110
* child can terminate */
111
lock.l_type = F_UNLCK;
112
err = fcntl(fd, F_SETLK, &lock);
114
LOG_ERR("Parent unlock", errno);
117
/* Wait for child to finish */
118
waitpid(child, &status, 0);
120
/* Close the parent fd */
123
LOG_ERR("Parent close", errno);
125
/* Remove the lock file*/
128
LOG_ERR("Parent unlink", errno);
130
/* If not blocked, exit with child exit status*/
131
errno = WEXITSTATUS(status);
133
/* If blocked, exit with corresponding
139
printf("%s\n", strerror(errno));