File Locking (Range Locking)
Reference: More details are in Chapter 12.3, Advanced Programming in the UNIX Environment, by W. Richard Stevens.

The purpose of file locking is to lock a section, sometimes called records but byte ranges are meant, of a file that the current process will shortly read (respectively write) to prevent other processes from writing (respectively reading or writing) it. File locking is necessary in database programs and, for example, for mailers accessing a mailbox. It can also be used to prevent multiple instances of daemons from running. An alternative but not completely foolproof or desirable method, is to use a second file - if the file exists then do not access the main file because it is in use.

File locking comes in two flavours: advisory versus mandatory. Advisory locking is locking which is not enforced by the operating system. Processes that access the file must be written so as to respect the conventions - request a lock before modifying the file. Mandatory locking is locking which is enforced by the operating system. Mandatory locking is requested by removing the execute permission for group and setting the setgid bit on the file. The shell commands are:

chmod g-x file
chmod g+l file     ## g+s on some systems
ls -l file     ## permissions shown as: -rw-r-l--- or -rw-r-S---
Unfortunately a process that has write permission in the directory could defeat locking by deleting the file and creating a new file with the same name.

File locking must not be used together with stdio functions as the buffering in stdio defeats the purpose of file locking, as the locking would only apply when the buffer is read or written.

A lock is released if any file descriptor for that file is closed!

File locking is done with fcntl( ). SVR4 provides lockf( ) which has a simpler interface. BSD provides flock( ) which should not be used (in Solaris). The file must be open( )ed before if can be locked.

lockf - section locking on files, an interface to fcntl

lockf(int fd, int operation, off_t size);
where operation is one of F_ULOCK (unlock previously locked section), F_LOCK (lock section for exclusive use, sleeping until available), F_TLOCK (lock section for exclusive use, return if unavailable), F_TEST (test section for locks). size is the number of contiguous bytes to be locked or unlocked, starting at the current offset in the file and extending forward for a positive size and backward for a negative size (the preceding bytes up to but not including the current offset). If size is zero, the section from the current offset through the largest file offset is locked (that is, from the current offset through the present or any future EOF); this has the effect of locking all appends to the file.

fcntl - file control as used for locking

fcntl(int fd, int cmd, struct flock *pflock);
where cmd is one of F_GETLK, F_SETLK or F_SETLKW. F_GETLK is used to test to see if there are any locks that would block a lock given by pflock, returning info about the first such lock, if any, through pflock. F_SETLK and F_SETLKW set or clear locks. F_SETLK returns immediately whereas F_SETLKW waits until it succeeds.
The behaviour is further specified by:
     struct flock {           /* May vary - may have more members */
          short   l_type;     /* operation type */
          short   l_whence;   /* base indicator */
          off_t   l_start;    /* starting offset from base */
          off_t   l_len;      /* length; l_len == 0 means until EOF */
          pid_t   l_pid;      /* process ID of process holding lock */
     }
where

Last update: 2001 April 9