FCNTL(2V)

NAME
fcntl - file control

SYNOPSIS
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>

int fcntl(fd, cmd, arg)
int fd, cmd, arg;

DESCRIPTION

fcntl() performs a variety of functions on open descriptors. The argument fd is an open descriptor used by cmd as follows:

F_DUPFD
    Returns a new descriptor, which has the smallest value greater than or equal to arg. It refers to the same object as the original descriptor, and has the same access mode (read, write or read/write). The new descriptor shares descriptor status flags with fd, and if the object was a file, the same file pointer. It is also associated with a FD_CLOEXEC (close-on-exec) flag set to remain open across execve(2V) system calls.

F_GETFD
    Get the FD_CLOEXEC (close-on-exec) flag associated with fd. If the low-order bit is 0, the file remains open after executing execve(), otherwise it is closed.

F_SETFD
    Set the FD_CLOEXEC (close-on-exec) flag associated with fd to the low order bit of arg (0 or 1 as above).

    Note: this is a per-process and per-descriptor flag. Setting or clearing it for a particular descriptor does not affect the flag on descriptors copied from it by dup(2V) or F_DUPFD, nor does it affect the flag on other processes of that descriptor.

F_GETFL
    Get descriptor status flags (see fcntl(5) for definitions).

F_SETFL
    Set descriptor status flags (see fcntl(5) for definitions). The following flags are the only ones whose values may change: O_APPEND, O_SYNC, and O_NDELAY, and the FASYNC, FNDELAY, and FNBIO flags defined in <fcntl.h>.

    O_NDELAY and FNDELAY are identical.

    Descriptor status flag values set by F_SETFL affects descriptors copied using dup(2V), F_DUPFD or other processes.

    Setting or clearing the FNDELAY flag on a descriptor causes an FIONBIO ioctl(2) request to be performed on the object referred to by that descriptor. Setting or clearing non-blocking mode, and setting or clearing the FASYNC flag on a descriptor causes an FIOASYNC ioctl(2) request to be performed on the object referred to by that descriptor, setting or clearing asynchronous mode. Thus, all descriptors referring to the object are affected.

F_GETLK
    Get a description of the first lock which would block the lock specified by the flock structure pointed to by arg (see the definition of struct flock below). If a lock exists, The flock structure is overwritten with that lock's description. Otherwise, the structure is passed back with the lock type set to F_UNLOCK and is otherwise unchanged.

F_SETLK
    Set or clear a file segment lock according to the flock structure pointed to by arg. F_SETLK is used to set shared (F_RDLCK) or exclusive (F_WRLCK) locks, or to remove those locks (F_UNLCK). If the specified lock cannot be applied, fcntl() fails and returns immediately.

F_SETLKW
    This cmd is the same as F_SETLK except that if a shared or exclusive lock is blocked by other locks, the process waits until the requested lock can be applied. If a signal that is set to be caught (see signal(3V)) is received while fcntl() is waiting for a region, the call to fcntl() is interrupted. Upon return from the process's signal handler, fcntl() fails and returns, and the requested lock is not applied.

F_GETOWN
    Get the process ID or process group currently receiving SIGIO and SIGURG signals; process groups are returned as negative values.

F_SETOWN
    Set the process or process group to receive SIGIO and SIGURG signals. Process groups are specified by supplying arg as negative, otherwise arg is interpreted as a process ID.

F_RSETLK
F_RSETLKW
F_RGETLK
    Are used by the network lock daemon, lockd(8C), to communicate with the NFS server kernel to handle locks on the NFS files.

Record locking is done with either shared (F_RDLCK), or exclusive (F_WRLCK) locks. More than one process may hold a shared lock on a particular file segment, but if one process holds an exclusive lock on the segment, no other process may hold any lock on the segment until the exclusive lock is removed.

In order to claim a shared lock, a descriptor must be opened with read access. Descriptors for exclusive locks must be opened with write access.

A shared lock may be changed to an exclusive lock, and vice versa, simply by specifying the appropriate lock type with a F_SETLK or F_SETLKW cmd. Before the previous lock is released and the new lock applied, any other processes already in line must gain and release their locks.

If cmd is F_SETLKW and the requested lock cannot be claimed immediately (for instance, when another process holds an exclusive lock that overlaps the current request) the calling process is blocked until the lock may be acquired. These blocks may be interrupted by signals. Care should be taken to avoid deadlocks caused by multiple processes all blocking the same records.

A shared or exclusive lock is either advisory or mandatory depending on the mode bits of the file containing the locked segment. The lock is mandatory if the set-GID bit (S_ISGID) is set and the group execute bit (S_IXGRP) is clear (see stat(2V) for information about mode bits). Otherwise, the lock is advisory.

If a process holds a mandatory shared lock on a segment of a file, other processes may read from the segment, but write operations block until all locks are removed. If a process holds a mandatory exclusive lock on a segment of a file, both read and write operations block until the lock is removed (see WARNINGS).

An advisory lock does not affect read and write access to the locked segment. Advisory locks may be used by cooperating processes checking for locks using F_GETLCK and voluntarily observing the indicated read and write restrictions.

The record to be locked or unlocked is described by the flock structure defined in <fcntl.h> as follows:

    struct flock {
        short	l_type;	/* F_RDLCK, F_WRLCK, or F_UNLCK */
        short	l_whence;	/* flag to choose starting offset */
        long	l_start;	/* relative offset, in bytes */
        long	l_len;	/* length, in bytes;  0 means lock to EOF */
        pid_t	l_pid;	/* returned with F_GETLK */
    };

The flock structure describes the type (l_type), starting offset (l_whence), relative offset (l_start), and size (l_len) of the file segment to be affected. l_whence is set to SEEK_SET, SEEK_CUR, or SEEK_END (see lseek(2V)) to indicate that the relative offset is to be measured from the start of the file, current position, or EOF, respectively. The process id field (l_pid) is only used with the F_GETLK cmd to return the description of a lock held by another process. Note: do not confuse struct flock with the function flock(2). They are unrelated.

Locks may start or extend beyond the current EOF, but may not be negative relative to the beginning of the file. Setting l_len to zero (0) extends the lock to EOF. If l_whence is set to SEEK_SET and l_start and l_len are set to zero (0), the entire file is locked. Changing or unlocking the subset of a locked segment leaves the smaller segments at either end locked. Locking a segment already locked by the calling process causes the old lock type to be removed and the new lock type to take affect. All locks associated with a file for a given process are removed when the file is closed or the process terminates. Locks are not inherited by the child process in a fork(2V) system call.

fcntl() record locks are implemented in the kernel for local locks, and throughout the network by the network lock daemon (lockd(8C)) for remote locks on NFS files. If the file server crashes and has to be rebooted, the lock daemon attempts to recover all locks that were associated with that server. If a lock cannot be reclaimed, the process that held the lock is issued a SIGLOST signal.

In order to maintain consistency in the network case, data must not be cached on client machines. For this reason, file buffering for an NFS file is turned off when the first lock is attempted on the file. Buffering remains off as long as the file is open. Programs that do I/O buffering in the user address space, however, may have inconsistent results. The standard I/O package, for instance, is a common source of unexpected buffering.

SYSTEM V DESCRIPTION
O_NDELAY and FNBIO are identical.

RETURN VALUES

On success, the value returned by fcntl() depends on cmd as follows:

    F_DUPFD
        A new descriptor.

    F_GETFD
        Value of flag (only the low-order bit is defined).

    F_GETFL
        Value of flags.

    F_GETOWN
        Value of descriptor owner.

    other
        Value other than -1.

On failure, fcntl() returns -1 and sets errno to indicate the error.

ERRORS

EACCES
    cmd is F_SETLK, the lock type (l_type) is F_RDLCK (shared lock), and the file segment to be locked is already under an exclusive lock held by another process. This error is also returned if the lock type is F_WRLCK (exclusive lock) and the file segment is already locked with a shared or exclusive lock.

    Note: In future, fcntl() may generate EAGAIN under these conditions, so applications testing for EACCES should also test for EAGAIN.

EBADF
    fd is not a valid open descriptor.

    cmd is F_SETLK or F_SETLKW and the process does not have the appropriate read or write permissions on the file.

EDEADLK
    cmd is F_SETLKW, the lock is blocked by one from another process, and putting the calling-process to sleep would cause a deadlock.

EFAULT
    cmd is F_GETLK, F_SETLK, or F_SETLKW and arg points to an invalid address.

EINTR
    cmd is F_SETLKW and a signal interrupted the process while it was waiting for the lock to be granted.

EINVAL
    cmd is F_DUPFD and arg is negative or greater than the maximum allowable number (see getdtablesize(2)).

    cmd is F_GETLK, F_SETLK, or F_SETLKW and arg points to invalid data.

EMFILE
    cmd is F_DUPFD and the maximum number of open descriptors has been reached.

ENOLCK
    cmd is F_SETLK or F_SETLKW and there are no more file lock entries available.

SEE ALSO
close(2V), execve(2V), flock(2), fork(2V), getdtablesize(2), ioctl(2), open(2V), sigvec(2), lockf(3), fcntl(5), lockd(8C)

WARNINGS
Mandatory record locks are dangerous. If a runaway or otherwise out-of-control process should hold a mandatory lock on a file critical to the system and fail to release that lock, the entire system could hang or crash. For this reason, mandatory record locks may be removed in a future SunOS release. Use advisory record locking whenever possible.

NOTES

Advisory locks allow cooperating processes to perform consistent operations on files, but do not guarantee exclusive access. Files can be accessed without advisory files, but inconsistencies may result.

read(2V) and write(2V) system calls on files are affected by mandatory file and record locks (see chmod(2V)).

BUGS

File locks obtained by fcntl() do not interact with flock() locks. They do, however, work correctly with the exclusive locks claimed by lockf(3).

F_GETLK returns F_UNLCK if the requesting process holds the specified lock. Thus, there is no way for a process to determine if it is still holding a specific lock after catching a SIGLOST signal.

In a network environment, the value of l_pid returned by F_GETLK is next to useless.