||
Lynx (etc) text mode tables arranged to 110 chars/line - where if properly adjusted the tables appear most "readable"... |
[intro] [a:index] [s:index] [#:index] [sys_fcntl] [man fcntl]
Preliminary, from "glibc" <llio.html>, yet not thoroughly revised and, probably still providing much "GNU"/"C"-ish nonsense... i.e it is not clear what was meant w. "GNU extension" in the source documents because sometimes them refer to "Linux" which is occasionally stated a "GNU system" by those people, sometimes the (after 19 years of development:) still un-released "HURD" was more or less implicitely referred. I.e. any such references are entirely un-reliable and, thus not included in this text.
Linux source, fcntl flags and data array definitions re asm/fcntl.h (Linux) & fcntl.h (libc).
File Control
- eax := int fcntl (ebx: int fd, ecx: int command, edx: optional arg)
fcntl controls file properties by the rsp file descriptor which aren't covered by a specific system call e.g, inquiring or setting file status flags, manipulating record locks &c. Many of the flags to fcntl are arguments to open, as well.
fcntl
commands:fcntl is a cancellation point in multi-threaded programs where a conflict might occur if the thread allocates some resources (memory, file descriptors, semaphores &c), coincidentally, which, after the rsp thread's termination remain allocated until the program ends unless the system call was protected by a respective cancellation handler.
F_DUPFD
Duplicate fd,
i.e. return another file descriptor pointing to the same open file.F_GETFD
Get fd flags.F_SETFD
Set fd flags.F_GETFL
Get status flags.F_SETFL
Set status flags.F_GETLK
Get a file lock.F_SETLK
Set or clear a file lock.F_SETLKW
F_SETLK
, waiting for completion.F_GETOWN
Get PID or GID receiveingSIGIO
signals.F_SETOWN
Set PID or GID receiveingSIGIO
signals.
[hp: Pse, NOTE that this might be libc specific! I'd yet not test any fcntl calls wrt that issue.]
Duplicating Descriptors
The command
F_DUPFD
duplicates a file descriptor, or allocates another file descriptor which refers to the same, open file as the original. Duplicate descriptors have a distinct set of file descriptor flags but, share file position and the file status flags.The major use of duplicating a file descriptor is to redirecting input or output, i.e. changeing the file or pipe which a particular file descriptor corresponds to.
The
F_DUPFD
command can be substituted, executing atomically, with thedup
anddup2
system calls, refcntl.h
for the flags tofcntl
.
int F_DUPFD Macro
This macro is used as the command argument to fcntl
, to copy the file descriptor given as the first argument.The form of the call in this case is:
fcntl (old, F_DUPFD, next-filedes)The next-filedes argument is of type
int
and specifies that the file descriptor returned should be the next available one greater than or equal to this value.The return value from
fcntl
with this command is normally the value of the new file descriptor. A return value of -1 indicates an error. The followingerrno
error conditions are defined for this command:
EBADF
- The old argument is invalid.
EINVAL
- The next-filedes argument is invalid.
EMFILE
- There are no more file descriptors available - your program is already using the maximum. In BSD and GNU, the maximum is controlled by a resource limit that can be changed; re Limits on Resources, for more information about the
RLIMIT_NOFILE
limit.
ENFILE
is not a possible error code fordup2
becausedup2
does not create a new opening of a file; duplicate descriptors do not count toward the limit whichENFILE
indicates.EMFILE
is possible because it refers to the limit on distinct descriptor numbers in use in one process.Here is an example showing how to use
dup2
to do redirection. Typically, redirection of the standard streams (likestdin
) is done by a shell or shell-like program before calling one of theexec
functions (re Executing a File) to execute a new program in a child process. When the new program is executed, it creates and initializes the standard streams to point to the corresponding file descriptors, before itsmain
function is invoked.So, to redirect standard input to a file, the shell could do something like:
pid = fork (); if (pid == 0) { char *filename; char *program; int file; ... file = TEMP_FAILURE_RETRY (open (filename, O_RDONLY)); dup2 (file, STDIN_FILENO); TEMP_FAILURE_RETRY (close (file)); execv (program, NULL); }There is also a more detailed example showing how to implement redirection in the context of a pipeline of processes in Launching Jobs.
File Descriptor Flags
File descriptor flags are miscellaneous attributes of a file descriptor. These flags are associated with particular file descriptors, so that if you have created duplicate file descriptors from a single opening of a file, each descriptor has its own set of flags.
Currently there is just one file descriptor flag:
FD_CLOEXEC
, which causes the descriptor to be closed if you use any of theexec...
functions (re Executing a File).
int F_GETFD
command, to returning the file descriptor flags associated with the fd. The normal return value from
fcntl
with this command is a nonnegative number which can be interpreted as the bitwise OR of the individual flags (except that currently there is only one flag to use).In case of an error,
fcntl
returns -1. The followingerrno
error conditions are defined for this command:
EBADF
- fd not valid.
int F_SETFD Macro
command argument to fcntl
, specifying that it should set the file descriptor flags associated with the filedes argument. This requires a thirdint
argument to specify the new flags:fcntl (filedes, F_SETFD, new-flags)The normal return value from
fcntl
with this command is an unspecified value other than -1, which indicates an error. The flags and error conditions are the same as for theF_GETFD
command.The following macro is defined for use as a file descriptor flag with the
fcntl
function. The value is an integer constant usable as a bit mask value.
int FD_CLOEXEC Macro
This flag specifies that the file descriptor should be closed when an exec
function is invoked; see Executing a File. When a file descriptor is allocated (as withopen
ordup
), this bit is initially cleared on the new file descriptor, meaning that descriptor will survive into the new program afterexec
.If you want to modify the file descriptor flags, you should get the current flags with
F_GETFD
and modify the value. Don't assume that the flags listed here are the only ones that are implemented; your program may be run years from now and more flags may exist then. For example, here is a function to set or clear the flagFD_CLOEXEC
without altering any other flags:/* Set theFD_CLOEXEC
flag of desc if value is nonzero, or clear the flag if value is 0. Return 0 on success, or -1 on error witherrno
set. */ int set_cloexec_flag (int desc, int value) { int oldflags = fcntl (desc, F_GETFD, 0); /* If reading the flags failed, return error indication now. if (oldflags < 0) return oldflags; /* Set just the flag we want to set. */ if (value != 0) oldflags |= FD_CLOEXEC; else oldflags &= ~FD_CLOEXEC; /* Store modified flag word in the descriptor. */ return fcntl (desc, F_SETFD, oldflags); }
[File Locks] : [Descriptor Flags] :File Status Flags
File status flags are used to specify attributes of the opening of a file. Unlike the file descriptor flags discussed in Descriptor Flags, the file status flags are shared by duplicated file descriptors resulting from a single opening of the file. The file status flags are specified with the flags argument to
open
; re Opening and Closing Files.File status flags fall into three categories, which are described in the following sections.
- Access Modes specify what type of access is allowed to the file: reading, writing, or both. They are set by
open
and are returned byfcntl
, but cannot be changed.- Opening Flags control details of what
open
will do. These flags are not preserved after theopen
call.- Operating Modes affect how operations such as
read
andwrite
are done. They are set byopen
, and can be fetched or changed withfcntl
.
- Access Modes: Whether the descriptor can read or write.
- Opening Flags: Details of
open
.- Operating Modes: Special modes to control I/O operations.
- Getting File Status Flags: Fetching and changing these flags.
File Access Modes
The file access modes allow a file descriptor to be used for reading, writing, or both (GNU/Linux can also allow none of these, and allow execution of the file as a program). The access modes are chosen when the file is opened, and never change.
O_RDONLY Open the file for read access. O_WRONLY Open the file for write access. O_RDWR Open the file for reading and writing. The portable way to extract the file access mode bits is with
O_ACCMODE
:
O_ACCMODE a mask that can be bitwise-ANDed with the file status flag value to produce a value representing the file access mode. The mode will be O_RDONLY
,O_WRONLY
or,O_RDWR
.
Opening Flags
The opening flags specify options affecting how
open
will behave. These options are not preserved once the file is open, with the exception ofO_NONBLOCK
, which is also an I/O operating mode. re Opening and Closing Files, for how to callopen
.There are two sorts of options specified by opening flags.
- File name translation flags affect how
open
looks up the file name and, whether the file can be created.- Opening flags specify extra operations that
open
will perform on the file once open.File name translation flags:
O_CREAT If set, the file will be created if it doesn't already exist. O_EXCL If both O_CREAT
andO_EXCL
are set, thenopen
fails if the specified file already exists.This is guaranteed to never clobber an existing file. O_NONBLOCK prevents open
from blocking for a "long time" to open the file, usually for devicessuch as serial ports; harmless and ignored where not applicable. Note that the O_NONBLOCK
flag conicides with both. an I/O operating mode and a file nametranslation flag. I.e. specifying O_NONBLOCK
inopen
also sets nonblocking I/O mode;re Operating Modes. To open the file without blocking but for normal I/O that blocks, call open
O_NONBLOCK
and turn the rsp. bit off byfcntl
, afterwards.O_NOCTTY If the named file is a terminal device, don't make it the controlling terminal for the process. re Job Control, for information about what "the controlling terminal" is. The opening flags tell
open
to do additional operations which are not really related to opening the file. The reason to do them as part ofopen
instead of in separate calls is thatopen
can do them atomically:
O_TRUNC Truncate the file to zero length. - POSIX.1 requires write access. BSD specific extensions:
O_SHLOCK Acquire a shared lock on the file, as with flock
, re File Locks.Atomically locking if O_CREAT
specified, no other process will
get the lock on the new file first. O_EXLOCK Atomically acquire an exclusive lock on the file. re File Locks.
[Getting File Status Flags] : [Opening Flags] :I/O Operating Modes
The operating modes affect how input and output operations using a file descriptor work. These flags are set by
open
and can be fetched and changed withfcntl
.
O_APPEND
Enables append mode. If set, all write
operations write the data to the end of the file, extending it, regardless of the current file position. This is the only reliable way to append to a file. In append mode, written data are guaranteed to always being stored to the current end of the file, regardless of other processes writing to the file.
O_NONBLOCK
Enables nonblocking mode. If set, read
requests on the file can return immediately with a failure status if there is no input immediately available, instead of blocking. Likewise,write
requests can also return immediately with a failure status if the output can't be written immediately.
O_NDELAY
Another name for O_NONBLOCK
, provided for compatibility with BSD, not defined by POSIX.1.The remaining operating modes are BSD and "GNU" extensions which exist only on some systems.
O_ASYNC
enables asynchronous input mode; SIGIO
signals will be generated when input is available. re Interrupt Input.Asynchronous input mode is a BSD feature.
O_FSYNC
The bit that enables synchronous writing for the file. If set, each write
call will make sure the data is reliably stored on disk before returning. Synchronous writing is a BSD feature.
O_SYNC
same as O_FSYNC
.
O_NOATIME
If set, read
will not update the access time of the file. re File Times. This is used by programs that do backups, so that backing up a file does not count as 'reading'. Only the owner of the file or the superuser may use this bit."GNU"-specific.
Getting and Setting File Status Flags
fcntl
can fetch or change file status flags.
F_GETFL
This macro is used as the command argument to fcntl
, to read the file status flags for the open file with descriptor filedes.The normal return value from
fcntl
with this command is a nonnegative number which can be interpreted as the bitwise OR of the individual flags. Since the file access modes are not single-bit values, you can mask off other bits in the returned flags withO_ACCMODE
to compare them.In case of an error,
fcntl
returns -1. The followingerrno
error conditions are defined for this command:
EBADF
- The filedes argument is invalid.
F_SETFL
This macro is used as the command argument to fcntl
, to set the file status flags for the open file corresponding to the filedes argument. This command requires a thirdint
argument to specify the new flags, so the call looks like this:fcntl (filedes, F_SETFL, new-flags)You can't change the access mode for the file in this way; that is, whether the file descriptor was opened for reading or writing.
The normal return value from
fcntl
with this command is an unspecified value other than -1, which indicates an error. The error conditions are the same as for theF_GETFL
command.If you want to modify the file status flags, you should get the current flags with
F_GETFL
and modify the value. Don't assume that the flags listed here are the only ones that are implemented; your program may be run years from now and more flags may exist then. For example, here is a function to set or clear the flagO_NONBLOCK
without altering any other flags:/* Set theO_NONBLOCK
flag of desc if value is nonzero, or clear the flag if value is 0. Return 0 on success, or -1 on error witherrno
set. */ int set_nonblock_flag (int desc, int value) { int oldflags = fcntl (desc, F_GETFL, 0); /* If reading the flags failed, return error indication now. */ if (oldflags == -1) return -1; /* Set just the flag we want to set. */ if (value != 0) oldflags |= O_NONBLOCK; else oldflags &= ~O_NONBLOCK; /* Store modified flag word in the descriptor. */ return fcntl (desc, F_SETFL, oldflags); }
File Locks
The remaining
fcntl
commands are used to support record locking, which permits multiple cooperating programs to prevent each other from simultaneously accessing parts of a file in error-prone ways.An exclusive or write lock gives a process exclusive access for writing to the specified part of the file. While a write lock is in place, no other process can lock that part of the file.
A shared or read lock prohibits any other process from requesting a write lock on the specified part of the file. However, other processes can request read locks.
The
read
andwrite
functions do not actually check to see whether there are any locks in place. If you want to implement a locking protocol for a file shared by multiple processes, your application must do explicitfcntl
calls to request and clear locks at the appropriate points.Locks are associated with processes. A process can only have one kind of lock set for each byte of a given file. When any locked file descriptor is closed by the process, all locks on that file are released which that process holds, regardless of the rsp. file descriptors' state. Likewise, locks are released when a process exits, and not inherited by child processes created by the
fork
syscall.When making a lock, use a
struct flock
to specify what kind of lock and where. refcntl.h
.
struct flock describes a file lock
short int l_type
- either one of
F_RDLCK
,F_WRLCK
, orF_UNLCK
lock type.short int l_whence
- the whence argument to
fseek
orlseek
, specifying the relation of "offset", either one ofSEEK_SET
,SEEK_CUR
,SEEK_END
.off_t l_start
- offset in bytes of the region to lock, wrt current file pointer as specified w.
l_whence
.off_t l_len
- length of the region to lock.
0
to extending the region till eof.pid_t l_pid
- process ID of the process holding the lock. Filled in w.
F_GETLK
, ignored while locking.
F_GETLK
command to requesting information about a lock; requires a third argument of type struct flock *
tofcntl
, so that the form of the call is:fcntl (filedes, F_GETLK, lockp)If there is a lock already in place that would block the lock described by the lockp argument, information about that lock overwrites
*lockp
. Existing locks are not reported if they are compatible with making a new lock as specified. The lock type ofF_WRLCK
should be specified to finding 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. Thel_whence
member of the lockp structure is set toSEEK_SET
and thel_start
andl_len
fields set to identify the locked region.If no lock applies, the only change to the lockp structure is to update the
l_type
to a value ofF_UNLCK
.The normal return value from
fcntl
with this command is an unspecified value other than -1, which is reserved to indicate an error. The followingerrno
error conditions are defined for this command:
EBADF
- The filedes argument is invalid.
EINVAL
- Either the lockp argument doesn't specify valid lock information, or the file associated with filedes doesn't support locks.
F_SETLK
command, specifying that the fcntl
should set or clear a lock; requires a third argument of typestruct flock *
:fcntl (filedes, F_SETLK, lockp)If the process 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 function does not block waiting for other processes to release locks. Iffcntl
succeeds, it return a value other than -1.The following
errno
error conditions are defined for this function:
EAGAIN
EACCES
- The lock cannot be set because it is blocked by an existing lock on the file. Some systems use
EAGAIN
in this case, and other systems useEACCES
; your program should treat them alike, afterF_SETLK
("GNU" always useingEAGAIN
).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, 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.
F_SETLKW
command to setting or clearing a lock. It is just like the F_SETLK
command, but causes the process to block (or wait) until the request can be specified.This command requires a third argument of type
struct flock *
, as for theF_SETLK
command.The
fcntl
return values and errors are the same as for theF_SETLK
command, but these additionalerrno
error conditions are defined for this command:
EINTR
- The function was interrupted by a signal while it was waiting. re Interrupted Primitives.
EDEADLK
- The specified region is being locked by another process. But that process is waiting to lock a region which the current process has locked, so waiting for the lock would result in deadlock. The system does not guarantee that it will detect all such conditions, but it lets you know if it notices one.
The following macros are defined for use as values for the
l_type
member of theflock
structure. The values are integer constants.
F_RDLCK
- used to specify a read (or shared) lock.
F_WRLCK
- used to specify a write (or exclusive) lock.
F_UNLCK
- used to specify that the region is unlocked.
As an example of a situation where file locking is useful, consider a program that can be run simultaneously by several different users, that logs status information to a common file. One example of such a program might be a game that uses a file to keep track of high scores. Another example might be a program that records usage or accounting information for billing purposes.
Having multiple copies of the program simultaneously writing to the file could cause the contents of the file to become mixed up. But you can prevent this kind of problem by setting a write lock on the file before actually writing to the file.
If the program also needs to read the file and wants to make sure that the contents of the file are in a consistent state, then it can also use a read lock. While the read lock is set, no other process can lock that part of the file for writing.
Remember that file locks are only a voluntary protocol for controlling access to a file. There is still potential for access to the file by programs that don't use the lock protocol.
Interrupt-Driven Input
If you set the
O_ASYNC
status flag on a file descriptor (re File Status Flags), aSIGIO
signal is sent whenever input or output becomes possible on that file descriptor. The process or process group to receive the signal can be selected by using theF_SETOWN
command to thefcntl
function. If the file descriptor is a socket, this also selects the recipient ofSIGURG
signals that are delivered when out-of-band data arrives on that socket; see Out-of-Band Data. -SIGURG
is sent in any situation whereselect
would report the socket as having an "exceptional condition". re Waiting for I/O.If the file descriptor corresponds to a terminal device, then
SIGIO
signals are sent to the foreground process group of the terminal. re Job Control.
F_GETOWN
This macro is used as the command argument to fcntl
, to specify that it should get information about the process or process group to whichSIGIO
signals are sent.The return value is interpreted as a process ID; if negative, its absolute value is the process group ID.
The following
errno
error condition is defined for this command:
EBADF
- The filedes argument is invalid.
F_SETOWN
This macro is used as the command argument to fcntl
, to specify that it should set the process or process group to whichSIGIO
signals are sent. This command requires a third argument of typepid_t
to be passed tofcntl
, so that the form of the call is:fcntl (filedes, F_SETOWN, pid)The pid argument should be a process ID. You can also pass a negative number whose absolute value is a process group ID.
The return value from
fcntl
with this command is -1 in case of error and some other value if successful. The followingerrno
error conditions are defined for this command:
EBADF
- The filedes argument is invalid.
ESRCH
- There is no process or process group corresponding to pid.