Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

idelovski

macrumors regular
Original poster
Sep 11, 2008
235
0
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.
 

gnasher729

Suspended
Nov 25, 2005
17,980
5,566
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"
 

idelovski

macrumors regular
Original poster
Sep 11, 2008
235
0
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.
 

ChrisA

macrumors G5
Jan 5, 2006
12,919
2,173
Redondo Beach, California
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:

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
 

Ti_Poussin

macrumors regular
May 6, 2005
210
0
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.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.