fcntl()--Perform File Control Command



Syntax

#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>

int fcntl(int file_descriptor, int cmd, . . .);

Threadsafe: Conditional; see Usage Notes.


The fcntl() function performs various actions on open descriptors.

Parameters

file_descriptor
(Input) The descriptor on which the control command is to be performed.

cmd
(Input) The command to be performed.

arg
(Input)) This third argument is interpreted based on the value of cmd.

The cmd argument can be one of the following symbols:

F_DUPFD
Duplicates the descriptor. A third int argument must be specified. fcntl() returns the lowest descriptor greater than or equal to this third argument that is not already associated with an open file. This descriptor refers to the same file as file_descriptor and shares any locks. If the original file descriptor was opened in text mode, data conversion is also done on the duplicated file descriptor. The FD_CLOEXEC flag that is associated with the new file descriptor is cleared.
F_GETFD
Obtains the file descriptor flags for file_descriptor. fcntl() returns these flags as its result. For a list of supported file descriptor flags, see Flags. File descriptor flags are associated with a single file descriptor and do not affect other file descriptors that refer to the same file.
F_SETFD
Sets the file descriptor flags for fildes. You must specify a third int argument, which gives the new file descriptor flag settings (see Flags). If any other bits in the third argument are set, fcntl() fails with the [EINVAL] error. fcntl() returns 0 if it successfully sets the flags.
F_GETFL
Obtains the file status flags and file access mode flags for file_descriptor. fcntl() returns these flags as its result. For a list of supported file status and file access mode flags, see Flags.
F_SETFL
Sets the file status flags for file_descriptor. You must specify a third int argument, giving the new file status flag settings (see Flags). fcntl() does not change the file access mode, and file access bits in the third argument are ignored. All other oflag values that are valid on the open() API are also ignored. If any other bits in the third argument are set, fcntl() fails with the [EINVAL] error. fcntl() returns 0 if it successfully sets the flags.
F_GETLK
Obtains locking information for a file. You must specify a third argument of type struct flock *. See File Locking for details. fcntl() returns 0 if it successfully obtains the locking information. When you develop in C-based languages and the function is compiled with the _LARGE_FILES macro defined, F_GETLK is mapped to the F_GETLK64 symbol.
F_SETLK
Sets or clears a file segment lock. You must specify a third argument of type struct flock *. See File Locking for details. fcntl() returns 0 if it successfully clears the lock. When you develop in C-based languages and the function is compiled with the _LARGE_FILES macro defined, F_SETLK is mapped to the F_SETLK64 symbol.
F_SETLKW
Sets or clears a file segment lock; however, if a shared or exclusive lock is blocked by other locks, fcntl() waits until the request can be satisfied. You must specify a third argument of type struct flock *. See File Locking for details. When you develop in C-based languages and the function is compiled with the _LARGE_FILES macro defined, F_SETLKW is mapped to the F_SETLKW64 symbol.
F_GETLK64
Obtains locking information for a large file. You must specify a third argument of type struct flock64 *. See File Locking for details. fcntl() returns 0 if it successfully obtains the locking information. When you develop in C-based languages, it is necessary to compile the function with the _LARGE_FILE_API macro defined to use this symbol.
F_SETLK64
Sets or clears a file segment lock for a large file. You must specify a third argument of type struct flock64 *. See File Locking for details. fcntl() returns 0 if it successfully clears the lock. When you develop in C-based languages, it is necessary to compile the function with the _LARGE_FILE_API macro defined to use this symbol.
F_SETLKW64
Sets or clears a file segment lock on a large file; however, if a shared or exclusive lock is blocked by other locks, fcntl() waits until the request can be satisfied. See File Locking for details. You must specify a third argument of type struct flock64 *. When you develop in C-based languages, it is necessary to compile the function with the _LARGE_FILE_API macro defined to use this symbol.

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 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.

The file status flags O_NONBLOCK, O_NDELAY, FNDELAY, and FASYNC apply only to socket descriptors. For more details, see the Sockets Programming book, SC41-5422.

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.

A mask can be used to extract flags:

O_ACCMODE
Extracts file access mode flags.

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

FD_CLOEXEC
Controls file descriptor inheritance during spawn() and spawnp() when simple inheritance is being used, as follows:

Refer to and for additional information about FD_CLOEXEC.

File Locking

A local or remote job can use fcntl() to lock out other local or remote jobs from a part of a file. By locking out other jobs, the job can read or write to that part of the file without interference from others. File locking can ensure data integrity when several jobs have a file accessed concurrently. For more information about remote locking, see information about the network lock manager and the network status monitor in the OS/400 Network File System Support book, SC41-5714.

Two different structures are used to control locking operations: struct flock and struct flock64 (both defined in the <fcntl.h> header file). You can use struct flock64 with the F_GETLK64, F_SETLK64, and F_SETLKW64 commands to control locks on large files (files greater than 2GB minus 1 byte). The struct flock structure has the following members:
short l_type Indicates the type of lock, as indicated by one of the following symbols (defined in the <fcntl.h> header file):
F_RDLCK
Indicates a read lock; also called a shared lock. When a job has a read lock, no other job can obtain write locks for that part of the file. More than one job can have a read lock on the same part of a file simultaneously.

To establish a read lock, a job must have the file accessed for reading.

F_WRLCK
Indicates a write lock; also called an exclusive lock. When a job has a write lock, no other job can obtain a read lock or write lock on the same part or an overlapping part of that file. A job cannot put a write lock on part of a file if another job already has a read lock on an overlapping part of the file. To establish a write lock, a job must have accessed the file for writing.
F_UNLCK
Unlocks a lock that was set previously.
short l_whence One of three symbols used in determining the part of the file that is affected by this lock. These symbols are defined in the <unistd.h> header file and are the same as symbols used by lseek():
SEEK_CUR
The current file offset in the file.
SEEK_END
The end of the file.
SEEK_SET
The start of the file.
off_t l_start Gives a byte offset used to identify the part of the file that is affected by this lock. If l_start is negative, it is handled as an unsigned value. The part of the file affected by the lock begins at this offset from the location given by l_whence. For example, if l_whence is SEEK_SET and l_start is 10, the locked part of the file begins at an offset of 10 bytes from the beginning of the file.
off_t l_len Gives the size of the locked part of the file, in bytes. If the size is negative, it is treated as an unsigned value. If l_len is zero, the locked part of the file begins at the position specified by l_whence and l_start, and extends to the end of the file. Together, l_whence, l_start, and l_len are used to describe the part of the file that is affected by this lock.
pid_t l_pid Specifies the job ID of the job that holds the lock. This is an output field used only with F_GETLK actions.
void *l_reserved0 Reserved. Must be set to NULL.
void *l_reserved1 Reserved. Must be set to NULL.

When you develop in C-based languages and this function is compiled with _LARGE_FILES defined, the struct flock data type will be mapped to a struct flock64 data type. To use the struct flock64 data type explicitly, it is necessary to compile the function with _LARGE_FILE_API defined.

The struct flock64 structure has the following members:
short l_type Indicates the type of lock, as indicated by one of the following symbols (defined in the <fcntl.h> header file):
F_RDLCK
Indicates a read lock; also called a shared lock. When a job has a read lock, no other job can obtain write locks for that part of the file. More than one job can have a read lock on the same part of a file simultaneously.

To establish a read lock, a job must have the file accessed for reading.

F_WRLCK
Indicates a write lock; also called an exclusive lock. When a job has a write lock, no other job can obtain a read lock or write lock on the same part or an overlapping part of that file. A job cannot put a write lock on part of a file if another job already has a read lock on an overlapping part of the file. To establish a write lock, a job must have accessed the file for writing.
F_UNLCK
Unlocks a lock that was set previously.
short l_whence One of three symbols used in determining the part of the file that is affected by this lock. These symbols are defined in the <unistd.h> header file and are the same as symbols used by lseek():
SEEK_CUR
The current file offset in the file.
SEEK_END
The end of the file.
SEEK_SET
The start of the file.
char l_reserved2[4] Reserved field
off64_t l_start Gives a byte offset used to identify the part of the file that is affected by this lock. Start of change l_start is handled as a signed value. End of change The part of the file affected by the lock begins at this offset from the location given by l_whence. For example, if l_whence is SEEK_SET and l_start is 10, the locked part of the file begins at an offset of 10 bytes from the beginning of the file.
off64_t l_len Gives the size of the locked part of the file, in bytes. If the size is negative, it is treated as an unsigned value. If l_len is zero, the locked part of the file begins at the position specified by l_whence and l_start, and extends to the end of the file. Together, l_whence, l_start, and l_len are used to describe the part of the file that is affected by this lock.
pid_t l_pid Specifies the job ID of the job that holds the lock. This is an output field used only with F_GETLK actions.
char reserved3[4] Reserved field.
void *l_reserved0 Reserved. Must be set to NULL.
void *l_reserved1 Reserved. Must be set to NULL.

You can set locks by specifying F_SETLK or F_SETLK64 as the cmd argument for fcntl(). Such a function call requires a third argument pointing to a struct flock structure (or struct flock64 in the case of F_SETLK64), as in this example:

   struct flock lock_it;
   lock_it.l_type = F_RDLCK;
   lock_it.l_whence = SEEK_SET;
   lock_it.l_start = 0;
   lock_it.l_len = 100;
   fcntl(file_descriptor,F_SETLK,&lock_it);

This example sets up a flock structure describing a read lock on the first 100 bytes of a file, and then calls fcntl() to establish the lock. You can unlock this lock by setting l_type to F_UNLCK and making the same call. If an F_SETLK operation cannot set a lock, it returns immediately with an error saying that the lock cannot be set.

The F_SETLKW and F_SETLKW64 operations are similar to F_SETLK and F_SETLK64, except that they wait until the lock can be set. For example, if you want to establish an exclusive lock and some other job already has a lock established on an overlapping part of the file, fcntl() waits until the other process has removed its lock.

F_SETLKW and F_SETLKW64 operations can encounter deadlocks when job A is waiting for job B to unlock a region and job B is waiting for job A to unlock a different region. If the system detects that an F_SETLKW or F_SETLKW64 might cause a deadlock, fcntl() fails with errno set to [EDEADLK].

With the F_SETLK64, F_SETLKW64, and F_GETLK64 operations, the maximum offset that can be specified is the largest value that can be held in an 8-byte, signed integer.

A job can determine locking information about a file by using F_GETLK and F_GETLK64 as the cmd argument for fcntl(). In this case, the call to fcntl() should specify a third argument pointing to a flock structure. The structure should describe the lock operation you want. When fcntl() returns, the structure indicated by the flock pointer is changed to show the first lock that would prevent the proposed lock operation from taking place. The returned structure shows the type of lock that is set, the part of the file that is locked, and the job ID of the job that holds the lock. In the returned structure:

If there are no locks that prevent the proposed lock operation, the returned structure has F_UNLCK in l_type and is otherwise unchanged.

If fcntl() attempts to operate on a large file (one larger than 2GB minus 1 byte) with the F_SETLK, F_GETLK, or FSETLKW commands, the API fails with [EOVERFLOW]. To work with large files, compile with the _LARGE_FILE_API macro defined (when you develop in C-based languages) and use the F_SETLK64, F_GETLK64, or FSETLKW64 commands. When you develop in C-based languages, it is also possible to work with large files by compiling the source with the _LARGE_FILES macro label defined. Note that the file must have been opened for large file access (either the open64() API was used or the open() API was used with the O_LARGEFILE flag defined in the oflag parameter).

An application that uses the F_SETLK or F_SETLKW commands may try to lock or unlock a file that has been extended beyond 2GB minus 1 byte by another application. If the value of l_len is set to 0 on the lock or unlock request, the byte range held or released will go to the end of the file rather than ending at offset 2GB minus 2.

An application that uses the F_SETLK or F_SETLKW commands also may try to lock or unlock a file that has been extended beyond offset 2GB minus 2 with l_len NOT set to 0. If this application attempts to lock or unlock the byte range up to offset 2GB minus 2 and l_len is not 0, the unlock request will unlock the file only up to offset 2GB minus 2 rather than to the end of the file.

A job can have several locks on a file at the same time, but only one type of lock can be set on a given byte. Therefore, if a job puts a new lock on a part of a file that it had locked previously, the job has only one lock on that part of the file. The type of the lock is the one specified in the most recent locking operation.

Locks can start and extend beyond the current end of a file, but cannot start or extend ahead of the beginning of a file.

All of the locks a job has on a file are removed when the job closes any descriptor that refers to the locked file.

All locks obtained using fcntl() are advisory only. Jobs can use advisory locks to inform each other that they want to protect parts of a file, but advisory locks do not prevent input and output on the locked parts. If a job has appropriate permissions on a file, it can perform whatever I/O it chooses, regardless of what advisory locks are set. Therefore, advisory locking is only a convention, and it works only when all jobs respect the convention.

Another type of lock, called a mandatory lock, can be set by a remote personal computer application. Mandatory locks restrict I/O on the locked parts. A read fails when reading a part that is locked with a mandatory write lock. A write fails when writing a part that is locked with a mandatory read or mandatory write lock.

Authorities

No authorization is required.

Return Value

value
fcntl() was successful. The value returned depends on the cmd that was specified.
-1
fcntl() was not successful. The errno global variable is set to indicate the error.

Error Conditions

If fcntl() is not successful, errno usually indicates one of the following errors. Under some conditions, errno could indicate an error other than those listed here.

[EACCES]
Permission denied.

An attempt was made to access an object in a way forbidden by its object access permissions.

The thread does not have access to the specified file, directory, component, or path.

If you are accessing a remote file through the Network File System, update operations to file permissions at the server are not reflected at the client until updates to data that is stored locally by the Network File System take place. (Several options on the Add Mounted File System (ADDMFS) command determine the time between refresh operations of local data.) Access to a remote file may also fail due to different mappings of user IDs (UID) or group IDs (GID) on the local and remote systems.

[EAGAIN]
Operation would have caused the process to be suspended.

The process tried to lock with F_SETLK, but the lock is in conflict with a previously established lock.

[EBADF]
Descriptor not valid.

A file descriptor argument was out of range, referred to a file that was not open, or a read or write request was made to a file that is not open for that operation.

A given file descriptor or directory pointer is not valid for this operation. The specified descriptor is incorrect, or does not refer to an open file.

[EBADFID]
A file ID could not be assigned when linking an object to a directory.

The file ID table is missing or damaged.

To recover from this error, run the Reclaim Storage (RCLSTG) command as soon as possible.

[EBUSY]
Resource busy.

An attempt was made to use a system resource that is not available at this time.

[EDAMAGE]
A damaged object was encountered.

A referenced object is damaged. The object cannot be used.

[EDEADLK]
Resource deadlock avoided.

An attempt was made to lock a system resource that would have resulted in a deadlock situation. The lock was not obtained.

The function attempted was failed to prevent a deadlock.

[EFAULT]
The address used for an argument is not correct.

In attempting to use an argument in a call, the system detected an address that is not valid.

While attempting to access a parameter passed to this function, the system detected an address that is not valid.

[EINVAL]
The value specified for the argument is not correct.

A function was passed incorrect argument values, or an operation was attempted on an object and the operation specified is not supported for that type of object.

An argument value is not valid, out of range, or NULL.

[EIO]
Input/output error.

A physical I/O error occurred.

A referenced object may be damaged.

[EMFILE]
Too many open files for this process.

An attempt was made to open more files than allowed by the value of OPEN_MAX. The value of OPEN_MAX can be retrieved using the sysconf() function.

The process has more than OPEN_MAX descriptors already open (see the sysconf() function).

[ENOLCK]
No locks available

A system-imposed limit on the number of simultaneous file and record locks was reached, and no more were available at that time.

[ENOMEM]
Storage allocation request failed.

A function needed to allocate storage, but no storage is available.

There is not enough memory to perform the requested function.

[ENOSYS]
Function not implemented.

An attempt was made to use a function that is not available in this implementation for any object or any arguments.

The path name given refers to an object that does not support this function.

[ENOTSAFE]
Function is not allowed in a job that is running with multiple threads.

[EOVERFLOW]
Object is too large to process.

The object's data size exceeds the limit allowed by this function.

One of the values to be returned cannot be represented correctly.

The cmd argument is F_GETLK, F_SETLK, or F_SETLKW and the offset of any byte in the requested segment cannot be represented correctly in a variable of type off_t (the offset is greater than 2GB minus 1 byte).

[ESTALE]
File or object handle rejected by server.

If you are accessing a remote file through the Network File System, the file may have been deleted at the server.

[EUNKNOWN]
Unknown system state.

The operation failed because of an unknown system state. See any messages in the job log and correct any errors that are indicated, then retry the operation.

If interaction with a file server is required to access the object, errno could indicate one of the following errors:

[EADDRNOTAVAIL]
Address not available.
[ECONNABORTED]
Connection ended abnormally.
[ECONNREFUSED]
The destination socket refused an attempted connect operation.
[ECONNRESET]
A connection with a remote socket was reset by that socket.
[EHOSTDOWN]
A remote host is not available.
[EHOSTUNREACH]
A route to the remote host is not available.
[ENETDOWN]
The network is not currently available.
[ENETRESET]
A socket is connected to a host that is no longer available.
[ENETUNREACH]
Cannot reach the destination network.
[ESTALE]
File or object handle rejected by server.

If you are accessing a remote file through the Network File System, the file may have been deleted at the server.

[ETIMEDOUT]
A remote host did not respond within the timeout period.
[EUNATCH]
The protocol required to support the specified address family is not available at this time.

Error Messages

The following messages may be sent from this function:

CPE3418 E
Possible APAR condition or hardware failure.
CPFA0D4 E
File system error occurred.
CPF3CF2 E
Error(s) occurred during running of &1 API.
CPF9872 E
Program or service program &1 in library &2 ended. Reason code &3.

Usage Notes

  1. This function will fail with error code [ENOTSAFE] when all the following conditions are true:

  2. QSYS.LIB File System Differences

    The following fcntl() commands are not supported:

    Using any of these commands results in an [ENOSYS] error.

  3. Network File System Differences

    Reading and writing to a file with the Network File System relies on byte-range locking to guarantee data integrity. To prevent data inconsistency, use the fcntl() API to get and release these locks. For more information about remote locking, see information about the network lock manager and the network status monitor in the OS/400 Network File System Support book.

  4. QNetWare File System Differences

    F_GETLK and F_SETLKW are not supported. F_RDLCK and F_WRLCK are ignored. All locks prevent reading and writing. Advisory locks are not supported. All locks are mandatory locks. Locking a file that is opened more than once in the same job with the same access mode is not supported, and its result is undefined.

  5. This function will fail with the [EOVERFLOW] error if the command is F_GETLK, F_SETLK, or F_SETLKW and the offset or the length exceeds offset 2 GB minus 2.

  6. When you develop in C-based languages and an application is compiled with the _LARGE_FILES macro defined, the struct flock data type will be mapped to a struct flock64 data type. To use the struct flock64 data type explicitly, it is necessary to compile the function with the _LARGE_FILE_API defined.

Related Information

Example

The following example uses fcntl():

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>

int main()
{
  int flags;
  int append_flag;
  int nonblock_flag;
  int access_mode;
  int file_descriptor; /* File Descriptor */
  char *text1 = "abcdefghij";
  char *text2 = "0123456789";
  char read_buffer[25];

  memset(read_buffer, '\0', 25);

  /* create a new file */
  file_descriptor = creat("testfile",S_IRWXU);
  write(file_descriptor, text1, 10);
  close(file_descriptor);

  /* open the file with read/write access */
  file_descriptor = open("testfile", O_RDWR);
  read(file_descriptor, read_buffer,24);
  printf("first read is \'%s\'\n",read_buffer);

  /* reset file pointer to the beginning of the file */
  lseek(file_descriptor, 0, SEEK_SET);
  /* set append flag to prevent overwriting existing text */
  fcntl(file_descriptor, F_SETFL, O_APPEND);
  write(file_descriptor, text2, 10);
  lseek(file_descriptor, 0, SEEK_SET);
  read(file_descriptor, read_buffer,24);
  printf("second read is \'%s\'\n",read_buffer);

  close(file_descriptor);
  unlink("testfile");

  return 0;
}

Output:

first read is 'abcdefghij'
second read is 'abcdefghij0123456789'


Top | Integrated File System APIs | APIs by category


[Information Center Home Page | Feedback ] [Legal | AS/400 Glossary]