Thread: Mac - File locking with fcntl() fails on shared volumes!?

  1. #1
    Registered User
    Join Date
    Mar 2007
    Posts
    142

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

    This is a Mac specific question, but in essence it is a unix/bsd system level stuff. I suppose
    there are people here that can help me.

    I'm using fcntl() to perform locking regions of 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. When I try it in Terminal, 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 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. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I take it the suggested workarounds in your link is no good for some reason?

    Generally, as to why you can't do this on a shared volume is that to ensure that one and only one process holds the lock at any given time, the system must have atomic writes to some common memory of some sort. That is terribly hard to achieve (efficiently) when there are more than one machine involved.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Registered User
    Join Date
    Mar 2007
    Posts
    142
    I take it the suggested workarounds in your link is no good for some reason?
    Suggested workarounds?

    This one: "to create a "lockfile" in the same directory as the file being opened."

    They actually recommend fcntl() and say: "By using advisory locking, your application will be able to work in a cooperative manner with Carbon, Classic, and other applications in the future."

    I tried adding O_EXLOCK + O_NONBLOCK to open() but it didn't help.

    Anything else that I missed? Is this how it works only on BSD or can I expect problems on Linux? I see "Kernel hacker" beside your name...

    Ah, and I have this book by Arnold Robbins, Linux Programming by Example where he covers on pg 532 flock(), fcntl() and lockf().
    Maybe I should try my luck with flock() or lockf()?

    And even in Beginning Linux Programming, by Neil Matthew & Richard Stones they use fcntl() without any warnings about "shared volumes".
    Last edited by idelovski; 11-10-2008 at 04:19 PM. Reason: These Books by Robbins & others

  4. #4
    Registered User
    Join Date
    Mar 2007
    Posts
    142
    Coolest sentence on that document above:

    AppleShare servers and Personal File Sharing on Mac OS X do enforce exclusive file access
    and range locking for volumes accessed over the network. However, this functionality is only
    available when accessing files over a networked file sharing connection and is not available to
    applications running on the server itself.
    And it is in total opposition to what I'm experiencing here.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. opening empty file causes access violation
    By trevordunstan in forum C Programming
    Replies: 10
    Last Post: 10-21-2008, 11:19 PM
  2. Formatting a text file...
    By dagorsul in forum C Programming
    Replies: 12
    Last Post: 05-02-2008, 03:53 AM
  3. Formatting the contents of a text file
    By dagorsul in forum C++ Programming
    Replies: 2
    Last Post: 04-29-2008, 12:36 PM
  4. help with text input
    By Alphawaves in forum C Programming
    Replies: 8
    Last Post: 04-08-2007, 04:54 PM
  5. C++ std routines
    By siavoshkc in forum C++ Programming
    Replies: 33
    Last Post: 07-28-2006, 12:13 AM