#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/wait.h>
int
write_lock(int fd, int offset, short offset_type, int len) {
struct flock fl;
fl.l_type = F_WRLCK;
fl.l_len = len;
fl.l_start = offset;
fl.l_whence = offset_type;
return fcntl(fd, F_SETLK, &fl);
}
int
main(int argc, char *argv[]) {
int fd;
pid_t pid;
char buf[6];
struct stat statbuf;
if (argc != 2) {
fprintf(stderr, "usage: %s filename\n", argv[0]);
exit(1);
}
if ((fd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC)) < 0)
perror("open error");
if (write(fd, "abcdef", 6) != 6)
perror("write error");
/* turn on set-group-ID and turn off group-execute */
if (fstat(fd, &statbuf) < 0)
perror("fstat error");
if (fchmod(fd, (statbuf.st_mode & ~S_IXGRP) | S_ISGID) < 0)
perror("fchmod error");
if ((pid = fork()) < 0) {
perror("fork error");
} else if (pid > 0) {
/* parent */
/* write lock entire file */
if (write_lock(fd, 0, SEEK_SET, 0) < 0)
perror("write_lock error");
if (waitpid(pid, NULL, 0) < 0)
perror("waitpid error");
} else {
/* child */
int flg;
fcntl(fd, F_GETFL, &flg);
fcntl(fd, F_SETFL, flg | O_NONBLOCK); // to show EAGAIN error
/* now try to read the mandatory locked file */
if (lseek(fd, 0, SEEK_SET) == -1)
perror("lseek error");
if (read(fd, buf, 6) < 0)
perror("read failed (mandatory locking works)");
else
printf("read OK (no mandatory locking), buf = %2.2s\n", buf);
sleep(5); // you can lslocks here.
}
}