How do I lock files using fopen()?

前端 未结 7 1913
时光取名叫无心
时光取名叫无心 2020-12-01 06:41

I wonder if there is any way to lock and unlock a file in Linux when I open a file using fopen (not open)?

Based on Stack Overflow question

相关标签:
7条回答
  • 2020-12-01 07:10

    If you wish to implement your own lock simply, I suggest Rob's answer of using flock. If you wish to implement it in a complex manner, such as for high availability, you can try something like using a thread to touch a file at a regular interval. All other programs wanting to lock the file should also check the file to see if its update time has been updated in at another fixed, but larger interval (the larger part is important). This is probably overkill for most applications, but it handles things such as crashes, freezes, etc. much better than flock.

    0 讨论(0)
  • 2020-12-01 07:15

    I would strongly disagree with the claim that fopen is prefered over open. It's impossible to use fopen safely when writing a file in a directory that's writable by other users due to symlink vulnerabilities/race conditions, since there is no O_EXCL option. If you need to use stdio on POSIX systems, it's best to use open and fdopen rather than calling fopen directly.

    Now, as for locking it depends on what you want to do. POSIX does not have mandatory locking like Windows, but if you just want to ensure you're working with a new file and not clobbering an existing file or following a symlink, use the O_EXCL and O_NOFOLLOW options, as appropriate. If you want to do cooperative locking beyond the initial open, use fcntl locks.

    0 讨论(0)
  • 2020-12-01 07:16

    The below code is not letting me lock the file using lockf, flock works fine though

        #include <iostream>
        #include <unistd.h>
        #include<thread>
        #include <vector>
        #include <sys/file.h>
        #include <fcntl.h>
        #include <string.h>
    
    using namespace std;
    
    void append()
    {
        FILE *fp=fopen("a.txt","a");
        if(fp)
        {
            cout<<lockf(fileno(fp),F_LOCK,0)<<endl;
    
            //flock(fileno(fp), LOCK_EX);
    
            fprintf(fp,"abcdefghijklmnopqrstuvwxyz\n");fflush(fp);
            sleep(1);
            fprintf(fp,"^$^&%&*&^&*(*)_*)_()_*&***&(\n");fflush(fp);
    
            fclose(fp);
        }
        else {
            printf("null\n");
        }
    }
    
    
    int main()
    {
        fclose(fopen("a.txt","w"));
        //return 0;
        vector<thread*> v;
        //#pragma omp parallel for
        for(int i=0;i<1000;++i)
        {
            v.push_back(new thread(append));
    
            //append();
        }
    
        for(auto y:v)
        {
            y->join();
            delete y;
        }
    
        return 0;
    }
    
    0 讨论(0)
  • 2020-12-01 07:19

    In Linux, if you need a file descriptor (e.g., to pass to a file-locking primitive), you can use fileno(FILE*) to retrieve it. After retrieving the file descriptor, you can use it as if it had been returned by open.

    For example, instead of

    int fd = open("myfile.txt", flags);
    int result = flock(fd, LOCK_SH);
    

    you could equally well do this:

    FILE* f = fopen("myfile.txt", "r");
    int result = flock(fileno(f)), LOCK_SH);
    

    Note that fileno is defined in the POSIX standard, but not in C or C++ standards.

    As for your second question, the Linux open() man page has this to say:

    The solution for performing atomic file locking using a lockfile is to create a unique file on the same file system (e.g., incorporating hostname and pid), use link(2) to make a link to the lockfile. If link() returns 0, the lock is successful. Otherwise, use stat(2) on the unique file to check if its link count has increased to 2, in which case the lock is also successful.

    0 讨论(0)
  • 2020-12-01 07:20

    Files can be locked by using flock(). Its syntax is

     #include <sys/file.h>
     #define   LOCK_SH   1    /* shared lock */
     #define   LOCK_EX   2    /* exclusive lock */
     #define   LOCK_NB   4    /* don't block when locking */
     #define   LOCK_UN   8    /* unlock */
    
    int flock(int fd, int operation);
    

    First file is opened using fopen() or open(). Then this opened file is locked using flock() as given below

    int fd = open("test.txt","r");
    int lock = flock(fd, LOCK_SH);  // Lock the file . . .
    // . . . .
    // Locked file in use 
    // . . . .
    int release = flock(fd, LOCK_UN);  // Unlock the file . . .
    
    0 讨论(0)
  • 2020-12-01 07:22

    There is another way with open() function, but I'm not sure about this called locked file. I am using file permissions to open a file.

    The code is here:

    #include <stdio.h>
    #include <fcntl.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    
    #define FILE_NAME "hello.txt"
    
    int main()
    {
        int fd;
    
        fd = open(FILE_NAME, O_CREAT, S_IRWXU);
    
        // Error checking
        if(fd == -1){
            perror("[error]\n");
        }
        else{
            printf("[file is opened]\n");
        }
    
        return 0;
    }
    

    I used a flag for permissions (third argument). This flag gives read, write and execute permissions to the user.

    $ls -alh
    
    total 24K
    drwxrwxr-x  2 arien arien 4.0K Dec 28 20:56 .
    drwxrwxr-x 18 arien arien 4.0K Dec 27 22:20 ..
    -rwxrwxr-x  1 arien arien 8.5K Dec 28 20:56 fopen
    -rw-rw-r--  1 arien arien  290 Dec 28 20:56 fopen.c
    -rwx------  1 arien arien    0 Dec 28 20:55 hello.txt
    

    A little tip: If you are using Ubuntu or Debian, you can see the description of functions with man [function_name] man pages of open() function.

    0 讨论(0)
提交回复
热议问题