File locking with fcntl() fails on shared volumes!?

Discussion in 'Mac Programming' started by idelovski, Nov 10, 2008.

  1. idelovski macrumors regular

    Joined:
    Sep 11, 2008
    #1
    I'm using fcntl() to perform locking of regions on files. It works well on local volume, but fails on shared volumes.

    This line produces error 45, ENOTSUP on shared volumes:
    Code:
    fcntl(fp, F_SETLKW, &lk)
    Here is an example I wrote to test it. If I give it ~ as a param all works well. If I use some folder on shared volume (on either Mac or Windows) it fails:
    Code:
    #include <stdlib.h>
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/time.h>
    #include <sys/resource.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <string.h>
    #include <errno.h>
    
    int main (int argc, const char * argv[])
    {
       int           fp, bytesGone, len;
       char          tmpStr[256], buff[256];
       struct flock  lk;
       
       if (argc != 2)
          exit (1);
       
       if (argv[1][strlen(argv[1])-1] == '/')
          sprintf (tmpStr, "%s%s", argv[1], "MyFile");
       else
          sprintf (tmpStr, "%s/%s", argv[1], "MyFile");
       
       if ((fp = open (tmpStr, O_RDWR)) < 0)  {
          if ((fp = open (tmpStr, O_RDWR | O_CREAT, 0666)) < 0)  {
             printf ("Open file error!\n");
             exit (1);
          }
       }
    
       lseek (fp, 0L, SEEK_SET);
       if (write(fp, tmpStr, len = strlen(tmpStr)+1) != len)
          exit (1);
    
       lseek (fp, 0L, SEEK_SET);
       if (read (fp, tmpStr, len) != len)
          exit (1);
       
       lseek (fp, 0L, SEEK_SET);
    
       lk.l_start  = 0;
       lk.l_len    = 8;
       lk.l_pid    = 0; // getpid ();
       lk.l_type   = F_WRLCK;
       lk.l_whence = SEEK_CUR;
       if (fcntl(fp, F_SETLKW, &lk))  {  // or F_SETLK, both give ENOTSUP
          printf ("Lock error: %d\n", errno);
          exit (1);
       }
    
       printf ("All is well! Len = %d\n", len);
       return (0);
    }
    
    There's even some Tech note by Apple that shows how to use Gestalt() to test if a volume supports file locking and all the volumes I checked passed that test.

    Any idea how to solve this or find a workaround.
     
  2. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #2
    I haven't looked very far, but the fcntl man pages recommend that you use flock instead, with comments like "this interface follows the completely stupid semantics of System V and POSIX.1"
     
  3. idelovski thread starter macrumors regular

    Joined:
    Sep 11, 2008
    #3
    Thanks for the reply. I've seen the S Word in man and that made me stop crying and start laughing (at least for a moment).

    Anyway, "flock applies or removes an advisory lock on the file associated with the file descriptor fd".

    It doesn't help with ranges locking within the file.
     
  4. ChrisA macrumors G4

    Joined:
    Jan 5, 2006
    Location:
    Redondo Beach, California
    #4
    At least you are getting the correct error returned.

    Locking a network share is a hard problem. Not all fie servers support locks. To be completely general you need to Handel locking yourself.

    A lot of people just give up and decide to keep the central data in an SQL Database rather then a file. This solves the problem completely
     
  5. Ti_Poussin macrumors regular

    Ti_Poussin

    Joined:
    May 6, 2005
    #5
    You want to make a daemon server on the remote machine if that's possible, the daemon may act as a proxy for you're file and only passing by him you can see the file. The daemon lock by himself the file. If that's not an option, I second the Database idea.

    Else, you may change the permission temporary on the file to lock it completely, work on a duplicate, overwrite and give permission back. This won't assure 100% the work, but if you're not having a lot of request to the same file at high speed, it shouldn't be a problem.

    flock can lock a part of a file, but it's base on the good will of other software, it mean that if other don't check for flock nothing prevent them to use the same file at the same time. To use flock, every apps that use the file must check for it, I used it for a software and it work well for what it is.
     

Share This Page