gtpc2m26C/C++ Language Support User's Guide

fcntl-Control Open File Descriptors

This function controls the open file descriptors.

Format

#include <fcntl.h>
int fcntl(int fildes, int action, ...);

fildes
A file descriptor for the file you want to change.

action
A symbol indicating the action you want to perform. These symbols are defined in the fcntl.h header file.

The action argument can be one of the following symbols:

F_DUPFD
Duplicates the file descriptor. A third int argument must be specified. The fcntl function returns the lowest file descriptor greater than or equal to this third argument that is not already associated with an open file. This file descriptor refers to the same file as fildes and shares any locks. The FD_CLOEXEC flag is turned off in the new file descriptor so that the file descriptor is inherited by a process activated by the system function.

F_GETFD
Obtains the file descriptor flags for fildes. The fcntl function returns these flags as its result.

F_SETFD
Sets the file descriptor flags for fildes. You must specify a third int argument, giving the new file descriptor flag settings. The fcntl function returns 0 if it successfully sets the flags.

F_GETFL
Obtains the file status flags, file access mode flags, and the O_TPF_NODDCLOSE for fildes. fcntl returns these flags as its result.

F_SETFL
Sets the file status flags for fildes. You must specify a third int argument, giving the new file descriptor flag settings. fcntl does not change the file access mode, and file access bits in the third argument are ignored. fcntl returns 0 if it successfully sets the flags.

F_SETLKW
Sets or clears a file segment lock, but if a lock is blocked by other locks, fcntl waits until the request can be satisfied.
TPF deviation from POSIX

The TPF system does not support the F_GETLK and F_SETLK action parameter values.

...
Indicates a third argument. The type of the third argument depends on action, and some actions do not need an additional argument.

Performs various actions on open file descriptors.

File Flags

There are several types of flags associated with each open file. Flags for a file are represented by symbols defined in the fcntl.h header file.

The following file descriptor flag can be associated with a file:

FD_CLOEXEC
If this flag is 1, the file descriptor is closed in any child processes created by system function calls. If the flag is 0, a child process created by a system function call inherits a copy of the open file descriptor.

The following file status flags can be associated with a file:

O_APPEND
Append mode. If this flag is 1, every write operation on the file begins at the end of the file.

O_NONBLOCK
No blocking. If this flag is 1, read and write operations on the file return with an error status if they cannot perform their I/O immediately. If this flag is 0, read and write operations on the file wait (or block) until the file is ready for I/O. For more information, see read-Read from a File and write-Write Data to a File Descriptor.

The following file access mode flags can be associated with a file:

O_RDONLY
The file is opened for reading only.

O_RDWR
The file is opened for reading and writing.

O_WRONLY
The file is opened for writing only.

Two masks can be used to extract flags:

O_ACCMODE
Extracts file access mode flags.

O_GETFL
Extracts file status flags and file access mode flags.

The following TPF-specific control flag can be associated with a file:

O_TPF_NODDCLOSE
This flag is set to on when the application needs to take control of the underlying system resources that are referenced by an open file description. It prevents the device driver TPF_FSDD_CLOSE-type function from being called when the last file descriptor referencing the open file description is closed.

File Locking

TPF deviation from POSIX

The only file locking supported by the TPF system is a blocking exclusive lock over an entire file. The fcntl function options to lock a range of bytes in a file (other than the entire file), to attempt to lock without blocking, to get a shared lock, and to query locks are not supported.

A process can use the fcntl function to lock out other processes from a file so that the process can read or write to that part of the file without interference from other files. File locking can ensure data integrity when several processes have a file accessed concurrently. File locking can be performed only on file descriptors that refer to regular files. Locking is not permitted on file descriptors that refer to directories, character special files, or any other type of files.

A structure that has the type struct flock (defined in the fcntl.h header file) controls locking operations. This structure has the following members:

short l_type
Indicates the type of lock by using one of the following symbols (defined in the fcntl.h header file):

F_WRLCK
Indicates a write lock (also called an exclusive lock). The process has exclusive access to the locked file and no other process can establish a write lock on that same file. If another process already has a write lock on the file, this process waits until the file is free.
TPF deviation from POSIX

To allow a reader to get exclusive access to a file, the requirement to have write access to the file when requesting a write lock is not enforced.

F_UNLCK
Unlocks a lock that was set previously.
TPF deviation from POSIX

The TPF system does not support read or shared locks. The fcntl function does not accept the F_RDLCK lock type.

short l_whence
The only accepted value is:

SEEK_SET
The start of the file.

This symbol is defined in the unistd.h header file and is the same as used by the lseek function.

TPF deviation from POSIX

The TPF system does not accept the SEEK_CUR and SEEK_END values for this field.

off_t l_start
The only value accepted by the TPF system is 0, indicating that the lock begins at the beginning of the file.

off_t l_len
The only value accepted by the TPF system is 0, indicating that the lock extends to the end of the file.
TPF deviation from POSIX

The TPF system does not support the pid_t l_pid field of the flock structure.

You can set a lock by specifying F_SETLKW as the action argument for the fcntl function. Such a function call requires a third argument pointing to a struct flock structure as in the following example:

   struct flock lock_it;
   lock_it.l_type = F_WRLCK;
   lock_it.l_whence = SEEK_SET;
   lock_it.l_start = 0;
   lock_it.l_len = 0;
   fcntl(fildes, F_SETLKW, &lock_it);

The previous example requests an exclusive lock for the entire file, which is the only type of lock that the TPF system supports. You can unlock this lock by setting l_type to F_UNLCK and making the same call. If an F_SETLKW operation cannot set a lock, it waits until the lock can be set. For example, if you want to establish a lock and some other process already has a lock established on the same file, fcntl waits until the other process has removed its lock.

Deadlocks can occur with F_SETLKW operations when process A is waiting for process B to unlock a file, and process B is waiting for process A to unlock a different file. Applications that lock more than one file at a time need to establish locking conventions that prevent more than one process from deadlocking.

A process lock on a file is removed when the process closes any file descriptor that refers to the locked file. Locks are not inherited by child processes created with system.

All locks are advisory only. Processes can use locks to inform each other that they want to protect a file, but locks do not prevent I/O on the locked files. If a process has appropriate permissions on a file, it can perform whatever I/O it chooses regardless of what locks are set. Therefore, file locking is only a convention, and it works only when all processes respect the convention.

Normal Return

If successful, the value returned will depend on the action that was specified.

Error Return

If unsuccessful, fcntl returns -1 and sets errno to one of the following:

EBADF
fildes is not a valid open file descriptor.

EINVAL
In an F_DUPFD operation, the third argument is negative or greater than or equal to OPEN_MAX, which is the highest file descriptor value allowed for the process.

In a locking operation, fildes refers to a file with a type that does not support locking, or the struct flock pointed to by the third argument has an incorrect form.

EMFILE
In an F_DUPFD operation, the process has already reached its maximum number of file descriptors or there are no available file descriptors greater than the specified third argument.

ENOLCK
In a F_SETLKW operation, the specified file is already locked by the requesting process.

Programming Considerations

None.

Examples

The following example opens a file and requests an exclusive lock for the entire file.

Note:
This is the only type of locking supported by the TPF system.
#include <fcntl.h>
#include <stdio.h>
 
int main(void)
{
    int fd = open("my.file", O_RDWR);
 
    if (fd < 0)
    {
        perror("open failure");
    }
    else
    {
        struct flock lock_it;
 
        lock_it.l_type = F_WRLCK;
        lock_it.l_whence = SEEK_SET;
        lock_it.l_start = 0;
        lock_it.l_len = 0;
        fcntl(fd, F_SETLKW, &lock_it);
        
·
·
·
close(fd) /* close releases the lock */ } }

Related Information

See Appendix E, Programming Support for the TPF File System for more information about TPF File System C Functions.