### 13.17 Open File Description Locks ¶

In contrast to process-associated record locks (see File Locks), open file description record locks are associated with an open file description rather than a process.

Using `fcntl` to apply an open file description lock on a region that already has an existing open file description lock that was created via the same file descriptor will never cause a lock conflict.

Open file description locks are also inherited by child processes across `fork`, or `clone` with `CLONE_FILES` set (see Creating a Process), along with the file descriptor.

It is important to distinguish between the open file description (an instance of an open file, usually created by a call to `open`) and an open file descriptor, which is a numeric value that refers to the open file description. The locks described here are associated with the open file description and not the open file descriptor.

Using `dup` (see Duplicating Descriptors) to copy a file descriptor does not give you a new open file description, but rather copies a reference to an existing open file description and assigns it to a new file descriptor. Thus, open file description locks set on a file descriptor cloned by `dup` will never conflict with open file description locks set on the original descriptor since they refer to the same open file description. Depending on the range and type of lock involved, the original lock may be modified by a `F_OFD_SETLK` or `F_OFD_SETLKW` command in this situation however.

Open file description locks always conflict with process-associated locks, even if acquired by the same process or on the same open file descriptor.

Open file description locks use the same `struct flock` as process-associated locks as an argument (see File Locks) and the macros for the `command` values are also declared in the header file `fcntl.h`. To use them, the macro `_GNU_SOURCE` must be defined prior to including any header file.

In contrast to process-associated locks, any `struct flock` used as an argument to open file description lock commands must have the `l_pid` value set to 0. Also, when returning information about an open file description lock in a `F_GETLK` or `F_OFD_GETLK` request, the `l_pid` field in `struct flock` will be set to -1 to indicate that the lock is not associated with a process.

When the same `struct flock` is reused as an argument to a `F_OFD_SETLK` or `F_OFD_SETLKW` request after being used for an `F_OFD_GETLK` request, it is necessary to inspect and reset the `l_pid` field to 0.

Macro: `int` F_OFD_GETLK ¶

  This macro is used as the command argument to `fcntl`, to specify that it should get information about a lock. This command requires a third argument of type `struct flock *` to be passed to `fcntl`, so that the form of the call is:

      fcntl (filedes, F_OFD_GETLK, lockp)

  If there is a lock already in place that would block the lock described by the lockp argument, information about that lock is written to `*lockp`. Existing locks are not reported if they are compatible with making a new lock as specified. Thus, you should specify a lock type of `F_WRLCK` if you want to find out about both read and write locks, or `F_RDLCK` if you want to find out about write locks only.

  There might be more than one lock affecting the region specified by the lockp argument, but `fcntl` only returns information about one of them. Which lock is returned in this situation is undefined.

  The `l_whence` member of the lockp structure are set to `SEEK_SET` and the `l_start` and `l_len` fields are set to identify the locked region.

  If no conflicting lock exists, the only change to the lockp structure is to update the `l_type` field to the value `F_UNLCK`.

  The normal return value from `fcntl` with this command is either 0 on success or -1, which indicates an error. The following `errno` error conditions are defined for this command:

  `EBADF`

    The filedes argument is invalid.

  `EINVAL`

    Either the lockp argument doesn’t specify valid lock information, the operating system kernel doesn’t support open file description locks, or the file associated with filedes doesn’t support locks.

Macro: `int` F_OFD_SETLK ¶

  This macro is used as the command argument to `fcntl`, to specify that it should set or clear a lock. This command requires a third argument of type `struct flock *` to be passed to `fcntl`, so that the form of the call is:

      fcntl (filedes, F_OFD_SETLK, lockp)

  If the open file already has a lock on any part of the region, the old lock on that part is replaced with the new lock. You can remove a lock by specifying a lock type of `F_UNLCK`.

  If the lock cannot be set, `fcntl` returns immediately with a value of -1. This command does not wait for other tasks to release locks. If `fcntl` succeeds, it returns 0.

  The following `errno` error conditions are defined for this command:

  `EAGAIN`

    The lock cannot be set because it is blocked by an existing lock on the file.

  `EBADF`

    Either: the filedes argument is invalid; you requested a read lock but the filedes is not open for read access; or, you requested a write lock but the filedes is not open for write access.

  `EINVAL`

    Either the lockp argument doesn’t specify valid lock information, the operating system kernel doesn’t support open file description locks, or the file associated with filedes doesn’t support locks.

  `ENOLCK`

    The system has run out of file lock resources; there are already too many file locks in place.

    Well-designed file systems never report this error, because they have no limitation on the number of locks. However, you must still take account of the possibility of this error, as it could result from network access to a file system on another machine.

Macro: `int` F_OFD_SETLKW ¶

  This macro is used as the command argument to `fcntl`, to specify that it should set or clear a lock. It is just like the `F_OFD_SETLK` command, but causes the process to wait until the request can be completed.

  This command requires a third argument of type `struct flock *`, as for the `F_OFD_SETLK` command.

  The `fcntl` return values and errors are the same as for the `F_OFD_SETLK` command, but these additional `errno` error conditions are defined for this command:

  `EINTR`

    The function was interrupted by a signal while it was waiting. See Primitives Interrupted by Signals.

Open file description locks are useful in the same sorts of situations as process-associated locks. They can also be used to synchronize file access between threads within the same process by having each thread perform its own `open` of the file, to obtain its own open file description.

Because open file description locks are automatically freed only upon closing the last file descriptor that refers to the open file description, this locking mechanism avoids the possibility that locks are inadvertently released due to a library routine opening and closing a file without the application being aware.

As with process-associated locks, open file description locks are advisory.