check_mandatory_lock.c

 avatar
unknown
c_cpp
3 years ago
1.8 kB
7
Indexable
#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.

    }
}