Open File Status Flags

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");

Note

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:

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");