Next | Prev | Up | Top | Contents | Index

Setting a File Lock

Several ways exist to set a lock on a file. These methods depend upon how the lock interacts with the rest of the program. Issues of portability and performance need to be considered. Two methods for setting a lock are given here: using the fcntl() system call and using the /usr/group standards-compatible lockf() library function call.

Locking an entire file is just a special case of record locking--one record is locked, which has the size of the entire file. The file is locked starting at a byte offset of zero and size of the maximum file size. This size is beyond any real end-of-file so that no other lock can be placed on the file.

Since a whole-file lock is a common operation, the fcntl() function treats a lock size of 0 as meaning "size of file." Example 4-2 contains a function that attempts a specified number of times to obtain a whole-file lock using fcntl(). When the lock is placed, it returns 1; if the lock cannot be placed, it returns 0..

Example 4-2 : Setting a Whole-File Lock With fcntl()

#include <fcntl.h>
#define MAX_TRY 10
int
lockWholeFile(int fd, int tries)
{
    int limit = (tries)?tries:MAX_TRY;
    int try = 0;
    struct flock lck;
    /* set up the record locking structure for whole file */
    lck.l_type = F_WRLCK; /* setting a write lock */
    lck.l_whence = 0; /* offset l_start from beginning of file */
    lck.l_start = 0L;
    lck.l_len = 0L; /* until the end of the file address space */
    /* Attempt locking MAX_TRY times before giving up. */
    while (0 > fcntl(fd, F_SETLK, &lck))
    {
        if ((++try < limit) && (errno == EAGAIN || errno == EACCES))
        {
            (void) sginap(1);
            continue;
        }
        else
        { /* not EAGAIN|EACCES, or too many failures */
            perror("fcntl");
            return 0;
        }
    }
    return 1;
}
Example 4-3 shows a version of the same function that performs the same task using the lockf() function.

Example 4-3 : Setting a Whole-File Lock With lockf()

#include <unistd.h>
#define MAX_TRY 10
int
lockWholeFile(int fd, int tries)
{
    int limit = (tries)?tries:MAX_TRY;
    int try = 0;
    /* make sure the file ptr is at the beginning of file. */
    lseek(fd, 0L, 0);
    /* Attempt locking MAX_TRY times before giving up. */
    while (0 > lockf(fd, F_TLOCK, 0L))
    {
        if ((++try < limit) && (errno == EAGAIN || errno == EACCES))
        {
            (void) sginap(1);
            continue;
        }
        else
        { /* not EAGAIN|EACCES, or too many failures */
            perror("lockf");
            return 0;
        }
    }
    return 1;
}
The following differences between Example 4-2 and Example 4-3 that should be noted:


Next | Prev | Up | Top | Contents | Index