One use of fcntl() is to retrieve or modify the access mode and open file status flags of an open file. (These are the values set by the flags argument specified in the call to open().) To retrieve these settings, we specify cmd as F_GETFL
:
int flags, accessMode; flags = fcntl(fd, F_GETFL); /* Third argument is not required */ if (flags == -1) errExit("fcntl");
After the above piece of code, we could test if the file was opened for synchronized writes as follows:
if (flags & O_SYNC) printf("writes are synchronized\n");
SUSv3 requires that only status flags that were specified during an open() or a later fcntl() F_SETFL
should be set on an open file. However, Linux deviates from this in one respect: if an application was compiled using one of the techniques described in I/O on Large Files for opening large files, then O_LARGEFILE
will always be set in the flags retrieved by F_GETFL
.
Checking the access mode of the file is slightly more complex, since the O_RDONLY
(0), O_WRONLY
(1), and O_RDWR
(2) constants don’t correspond to single bits in the open file status flags. Therefore, to make this check, we mask the flags value with the constant O_ACCMODE
, and then test for equality with one of the constants:
accessMode = flags & O_ACCMODE; if (accessMode == O_WRONLY || accessMode == O_RDWR) printf("file is writable\n");
We can use the fcntl() F_SETFL
command to modify some of the open file status flags. The flags that can be modified are O_APPEND
, O_NONBLOCK
, O_NOATIME
, O_ASYNC
, and O_DIRECT
. Attempts to modify other flags are ignored. (Some other UNIX implementations allow fcntl() to modify other flags, such as O_SYNC
.)
Using fcntl() to modify open file status flags is particularly useful in the following cases:
The file was not opened by the calling program, so that it had no control over the flags used in the open() call (e.g., the file may be one of the three standard descriptors that are opened before the program is started).
The file descriptor was obtained from a system call other than open(). Examples of such system calls are pipe(), which creates a pipe and returns two file descriptors referring to either end of the pipe, and socket(), which creates a socket and returns a file descriptor referring to the socket.
To modify the open file status flags, we use fcntl() to retrieve a copy of the existing flags, then modify the bits we wish to change, and finally make a further call to fcntl() to update the flags. Thus, to enable the O_APPEND
flag, we would write the following:
int flags; flags = fcntl(fd, F_GETFL); if (flags == -1) errExit("fcntl"); flags |= O_APPEND; if (fcntl(fd, F_SETFL, flags) == -1) errExit("fcntl");