The ellipsis in the SYNOPSIS is the syntax specified by the ISO C
standard for a variable number of arguments. It is used because
System V uses pointers for the implementation of file locking
functions.
This volume of POSIX.1‐2017 permits concurrent read and write
access to file data using the fcntl() function; this is a change
from the 1984 /usr/group standard and early proposals. Without
concurrency controls, this feature may not be fully utilized
without occasional loss of data.
Data losses occur in several ways. One case occurs when several
processes try to update the same record, without sequencing
controls; several updates may occur in parallel and the last
writer ``wins''. Another case is a bit-tree or other internal
list-based database that is undergoing reorganization. Without
exclusive use to the tree segment by the updating process, other
reading processes chance getting lost in the database when the
index blocks are split, condensed, inserted, or deleted. While
fcntl() is useful for many applications, it is not intended to be
overly general and does not handle the bit-tree example well.
This facility is only required for regular files because it is
not appropriate for many devices such as terminals and network
connections.
Since fcntl() works with ``any file descriptor associated with
that file, however it is obtained'', the file descriptor may have
been inherited through a fork() or exec operation and thus may
affect a file that another process also has open.
The use of the open file description to identify what to lock
requires extra calls and presents problems if several processes
are sharing an open file description, but there are too many
implementations of the existing mechanism for this volume of
POSIX.1‐2017 to use different specifications.
Another consequence of this model is that closing any file
descriptor for a given file (whether or not it is the same open
file description that created the lock) causes the locks on that
file to be relinquished for that process. Equivalently, any close
for any file/process pair relinquishes the locks owned on that
file for that process. But note that while an open file
description may be shared through fork(), locks are not inherited
through fork(). Yet locks may be inherited through one of the
exec functions.
The identification of a machine in a network environment is
outside the scope of this volume of POSIX.1‐2017. Thus, an
l_sysid member, such as found in System V, is not included in the
locking structure.
Changing of lock types can result in a previously locked region
being split into smaller regions.
Mandatory locking was a major feature of the 1984 /usr/group
standard.
For advisory file record locking to be effective, all processes
that have access to a file must cooperate and use the advisory
mechanism before doing I/O on the file. Enforcement-mode record
locking is important when it cannot be assumed that all processes
are cooperating. For example, if one user uses an editor to
update a file at the same time that a second user executes
another process that updates the same file and if only one of the
two processes is using advisory locking, the processes are not
cooperating. Enforcement-mode record locking would protect
against accidental collisions.
Secondly, advisory record locking requires a process using
locking to bracket each I/O operation with lock (or test) and
unlock operations. With enforcement-mode file and record
locking, a process can lock the file once and unlock when all I/O
operations have been completed. Enforcement-mode record locking
provides a base that can be enhanced; for example, with sharable
locks. That is, the mechanism could be enhanced to allow a
process to lock a file so other processes could read it, but none
of them could write it.
Mandatory locks were omitted for several reasons:
1. Mandatory lock setting was done by multiplexing the set-
group-ID bit in most implementations; this was confusing, at
best.
2. The relationship to file truncation as supported in 4.2 BSD
was not well specified.
3. Any publicly readable file could be locked by anyone. Many
historical implementations keep the password database in a
publicly readable file. A malicious user could thus prohibit
logins. Another possibility would be to hold open a long-
distance telephone line.
4. Some demand-paged historical implementations offer memory
mapped files, and enforcement cannot be done on that type of
file.
Since sleeping on a region is interrupted with any signal,
alarm() may be used to provide a timeout facility in applications
requiring it. This is useful in deadlock detection. Since
implementation of full deadlock detection is not always feasible,
the [EDEADLK]
error was made optional.