cfdopen

File Locking compatible with fgets and fprintf


I am reading http://beej.us/guide/bgipc/html/multi/flocking.html for file locking, now I try to figure how to work with both file description and file pointers (I need fprintf and fgets), this code actually works but I'm not sure if flags assigned to fdopen are correct, is this a good way to proceed?

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>

#define LINE_MAX 100

#define FILE_READING 1
#define FILE_WRITING 2

int main(int argc, char *argv[])
{
    struct flock fl = {F_WRLCK, SEEK_SET, 0, 0, 0};
    char s[LINE_MAX];
    int fd, fstatus;
    FILE *fp;

    fl.l_pid = getpid();
    if (argc == 1) {
        fl.l_type = F_RDLCK;
        fstatus = FILE_READING;
    } else {
        fstatus = FILE_WRITING;
    }
    if ((fd = open("demo.txt", fstatus == FILE_READING ? O_RDONLY | O_CREAT : O_WRONLY | O_APPEND | O_CREAT, 0600)) == -1) {
        perror("open");
        exit(1);
    }
    printf("Press <RETURN> to try to get lock: ");
    getchar();
    printf("Trying to get lock...\n");
    if (fcntl(fd, F_SETLKW, &fl) == -1) {
        perror("fcntl");
        exit(1);
    }
    if (fstatus == FILE_WRITING) {
        fp = fdopen(fd, "a");
        fprintf(fp, "%s\n", argv[1]);
    } else {
        fp = fdopen(fd, "r");
        while (fgets(s, LINE_MAX, fp)) {
            printf("%s", s);
        }
    }
    printf("got lock\n");
    printf("Press <RETURN> to release lock: ");
    getchar();
    fl.l_type = F_UNLCK;
    if (fcntl(fd, F_SETLK, &fl) == -1) {
        perror("fcntl");
        exit(1);
    }
    printf("Unlocked.\n");
    fclose(fp);
    close(fd);
    return 0;
}

Solution

  • According to the documentation, fdopen() uses the same mode arguments as fopen(), so as far as I can tell you, you have used them properly.