   This file documents the GNU C library.

   This is Edition 0.08 DRAFT, last updated 11 Jan 1999, of `The GNU C
Library Reference Manual', for Version 2.1 Beta.

   Copyright (C) 1993, '94, '95, '96, '97, '98, '99 Free Software
Foundation, Inc.

   Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
preserved on all copies.

   Permission is granted to copy and distribute modified versions of
this manual under the conditions for verbatim copying, provided also
that the section entitled "GNU Library General Public License" is
included exactly as in the original, and provided that the entire
resulting derived work is distributed under the terms of a permission
notice identical to this one.

   Permission is granted to copy and distribute translations of this
manual into another language, under the above conditions for modified
versions, except that the text of the translation of the section
entitled "GNU Library General Public License" must be approved for
accuracy by the Foundation.

Synchronizing I/O operations
============================

   In most modern operation systems the normal I/O operations are not
executed synchronously.  I.e., even if a `write' system call returns
this does not mean the data is actually written to the media, e.g., the
disk.

   In situations where synchronization points are necessary the user can
use special functions which ensure that all operations finished before
they return.

 - Function: int sync (void)
     A call to this function will not return as long as there is data
     which that is not written to the device.  All dirty buffers in the
     kernel will be written and so an overall consistent system can be
     achieved (if no other process in parallel writes data).

     A prototype for `sync' can be found in `unistd.h'.

     The return value is zero to indicate no error.

   More often it is wanted that not all data in the system is committed.
Programs want to ensure that data written to a given file are all
committed and in this situation `sync' is overkill.

 - Function: int fsync (int FILDES)
     The `fsync' can be used to make sure all data associated with the
     open file FILDES is written to the device associated with the
     descriptor.  The function call does not return unless all actions
     have finished.

     A prototype for `fsync' can be found in `unistd.h'.

     This function is a cancelation point in multi-threaded programs.
     This is a problem if the thread allocates some resources (like
     memory, file descriptors, semaphores or whatever) at the time
     `fsync' is called.  If the thread gets canceled these resources
     stay allocated until the program ends.  To avoid this calls to
     `fsync' should be protected using cancelation handlers.

     The return value of the function is zero if no error occurred.
     Otherwise it is -1 and the global variable ERRNO is set to the
     following values:
    `EBADF'
          The descriptor FILDES is not valid.

    `EINVAL'
          No synchronization is possible since the system does not
          implement this.

   Sometimes it is not even necessary to write all data associated with
a file descriptor.  E.g., in database files which do not change in size
it is enough to write all the file content data to the device.
Meta-information like the modification time etc. are not that important
and leaving such information uncommitted does not prevent a successful
recovering of the file in case of a problem.

 - Function: int fdatasync (int FILDES)
     When a call to the `fdatasync' function returns it is made sure
     that all of the file data is written to the device.  For all
     pending I/O operations the parts guaranteeing data integrity
     finished.

     Not all systems implement the `fdatasync' operation.  On systems
     missing this functionality `fdatasync' is emulated by a call to
     `fsync' since the performed actions are a superset of those
     required by `fdatasyn'.

     The prototype for `fdatasync' is in `unistd.h'.

     The return value of the function is zero if no error occurred.
     Otherwise it is -1 and the global variable ERRNO is set to the
     following values:
    `EBADF'
          The descriptor FILDES is not valid.

    `EINVAL'
          No synchronization is possible since the system does not
          implement this.

Perform I/O Operations in Parallel
==================================

   The POSIX.1b standard defines a new set of I/O operations which can
reduce the time an application spends waiting at I/O significantly.  The
new functions allow a program to initiate one or more I/O operations and
then immediately resume the normal work while the I/O operations are
executed in parallel.  The functionality is available if the `unistd.h'
file defines the symbol `_POSIX_ASYNCHRONOUS_IO'.

   These functions are part of the library with realtime functions named
`librt'.  They are not actually part of the `libc' binary.  The
implementation of these functions can be done using support in the
kernel (if available) or using an implementation based on threads at
userlevel.  In the latter case it might be necessary to link
applications with the thread library `libpthread' in addition to
`librt'.

   All AIO operations operate on files which were opened previously.
There might be arbitrarily many operations for one file running.  The
asynchronous I/O operations are controlled using a data structure named
`struct aiocb' ("AIO control block").  It is defined in `aio.h' as
follows.

 - Data Type: struct aiocb
     The POSIX.1b standard mandates that the `struct aiocb' structure
     contains at least the members described in the following table.
     There might be more elements which are used by the implementation
     but depending on these elements is not portable and is highly
     deprecated.

    `int aio_fildes'
          This element specifies the file descriptor which is used for
          the operation.  It must be a legal descriptor since otherwise
          the operation fails for obvious reasons.

          The device on which the file is opened must allow the seek
          operation.  I.e., it is not possible to use any of the AIO
          operations on devices like terminals where an `lseek' call
          would lead to an error.

    `off_t aio_offset'
          This element specifies at which offset in the file the
          operation (input or output) is performed.  Since the
          operations are carried out in arbitrary order and more than
          one operation for one file descriptor can be started, one
          cannot expect a current read/write position of the file
          descriptor.

    `volatile void *aio_buf'
          This is a pointer to the buffer with the data to be written
          or the place where the read data is stored.

    `size_t aio_nbytes'
          This element specifies the length of the buffer pointed to by
          `aio_buf'.

    `int aio_reqprio'
          If the platform has defined `_POSIX_PRIORITIZED_IO' and
          `_POSIX_PRIORITY_SCHEDULING' the AIO requests are processed
          based on the current scheduling priority.  The `aio_reqprio'
          element can then be used to lower the priority of the AIO
          operation.

    `struct sigevent aio_sigevent'
          This element specifies how the calling process is notified
          once the operation terminates.  If the `sigev_notify' element
          is `SIGEV_NONE' no notification is send.  If it is
          `SIGEV_SIGNAL' the signal determined by `sigev_signo' is
          send.  Otherwise `sigev_notify' must be `SIGEV_THREAD'.  In
          this case a thread is created which starts executing the
          function pointed to by `sigev_notify_function'.

    `int aio_lio_opcode'
          This element is only used by the `lio_listio' and
          `lio_listio64' functions.  Since these functions allow to
          start an arbitrary number of operations at once and since
          each operation can be input or output (or nothing) the
          information must be stored in the control block.  The
          possible values are:

         `LIO_READ'
               Start a read operation.  Read from the file at position
               `aio_offset' and store the next `aio_nbytes' bytes in the
               buffer pointed to by `aio_buf'.

         `LIO_WRITE'
               Start a write operation.  Write `aio_nbytes' bytes
               starting at `aio_buf' into the file starting at position
               `aio_offset'.

         `LIO_NOP'
               Do nothing for this control block.  This value is useful
               sometimes when an array of `struct aiocb' values
               contains holes, i.e., some of the values must not be
               handled although the whole array is presented to the
               `lio_listio' function.

     When the sources are compiled using `_FILE_OFFSET_BITS == 64' on a
     32 bits machine this type is in fact `struct aiocb64' since the LFS
     interface transparently replaces the `struct aiocb' definition.

   For use with the AIO functions defined in the LFS there is a similar
type defined which replaces the types of the appropriate members with
larger types but otherwise is equivalent to `struct aiocb'.  Especially
all member names are the same.

 - Data Type: struct aiocb64
    `int aio_fildes'
          This element specifies the file descriptor which is used for
          the operation.  It must be a legal descriptor since otherwise
          the operation fails for obvious reasons.

          The device on which the file is opened must allow the seek
          operation.  I.e., it is not possible to use any of the AIO
          operations on devices like terminals where an `lseek' call
          would lead to an error.

    `off64_t aio_offset'
          This element specified at which offset in the file the
          operation (input or output) is performed.  Since the
          operation are carried in arbitrary order and more than one
          operation for one file descriptor can be started, one cannot
          expect a current read/write position of the file descriptor.

    `volatile void *aio_buf'
          This is a pointer to the buffer with the data to be written
          or the place where the ead data is stored.

    `size_t aio_nbytes'
          This element specifies the length of the buffer pointed to by
          `aio_buf'.

    `int aio_reqprio'
          If for the platform `_POSIX_PRIORITIZED_IO' and
          `_POSIX_PRIORITY_SCHEDULING' is defined the AIO requests are
          processed based on the current scheduling priority.  The
          `aio_reqprio' element can then be used to lower the priority
          of the AIO operation.

    `struct sigevent aio_sigevent'
          This element specifies how the calling process is notified
          once the operation terminates.  If the `sigev_notify' element
          is `SIGEV_NONE' no notification is send.  If it is
          `SIGEV_SIGNAL' the signal determined by `sigev_signo' is
          send.  Otherwise `sigev_notify' must be `SIGEV_THREAD' in
          which case a thread which starts executing the function
          pointed to by `sigev_notify_function'.

    `int aio_lio_opcode'
          This element is only used by the `lio_listio' and
          `[lio_listio64' functions.  Since these functions allow to
          start an arbitrary number of operations at once and since
          each operation can be input or output (or nothing) the
          information must be stored in the control block.  See the
          description of `struct aiocb' for a description of the
          possible values.

     When the sources are compiled using `_FILE_OFFSET_BITS == 64' on a
     32 bits machine this type is available under the name `struct
     aiocb64' since the LFS replaces transparently the old interface.

Asynchronous Read and Write Operations
--------------------------------------

 - Function: int aio_read (struct aiocb *AIOCBP)
     This function initiates an asynchronous read operation.  The
     function call immediately returns after the operation was enqueued
     or when an error was encountered.

     The first `aiocbp->aio_nbytes' bytes of the file for which
     `aiocbp->aio_fildes' is a descriptor are written to the buffer
     starting at `aiocbp->aio_buf'.  Reading starts at the absolute
     position `aiocbp->aio_offset' in the file.

     If prioritized I/O is supported by the platform the
     `aiocbp->aio_reqprio' value is used to adjust the priority before
     the request is actually enqueued.

     The calling process is notified about the termination of the read
     request according to the `aiocbp->aio_sigevent' value.

     When `aio_read' returns the return value is zero if no error
     occurred that can be found before the process is enqueued.  If
     such an early error is found the function returns -1 and sets
     `errno' to one of the following values.

    `EAGAIN'
          The request was not enqueued due to (temporarily) exceeded
          resource limitations.

    `ENOSYS'
          The `aio_read' function is not implemented.

    `EBADF'
          The `aiocbp->aio_fildes' descriptor is not valid.  This
          condition needs not be recognized before enqueueing the
          request and so this error might also be signaled
          asynchronously.

    `EINVAL'
          The `aiocbp->aio_offset' or `aiocbp->aio_reqpiro' value is
          invalid.  This condition need not be recognized before
          enqueueing the request and so this error might also be
          signaled asynchronously.

     In the case `aio_read' returns zero the current status of the
     request can be queried using `aio_error' and `aio_return'
     functions.  As long as the value returned by `aio_error' is
     `EINPROGRESS' the operation has not yet completed.  If `aio_error'
     returns zero the operation successfully terminated, otherwise the
     value is to be interpreted as an error code.  If the function
     terminated the result of the operation can be get using a call to
     `aio_return'.  The returned value is the same as an equivalent
     call to `read' would have returned.  Possible error codes returned
     by `aio_error' are:

    `EBADF'
          The `aiocbp->aio_fildes' descriptor is not valid.

    `ECANCELED'
          The operation was canceled before the operation was finished
          (see Cancel AIO Operations)

    `EINVAL'
          The `aiocbp->aio_offset' value is invalid.

     When the sources are compiled with `_FILE_OFFSET_BITS == 64' this
     function is in fact `aio_read64' since the LFS interface
     transparently replaces the normal implementation.

 - Function: int aio_read64 (struct aiocb *AIOCBP)
     This function is similar to the `aio_read' function.  The only
     difference is that on 32 bits machines the file descriptor should
     be opened in the large file mode.  Internally `aio_read64' uses
     functionality equivalent to `lseek64' (see File Position Primitive)
     to position the file descriptor correctly for the
     reading, as opposed to `lseek' functionality used in `aio_read'.

     When the sources are compiled with `_FILE_OFFSET_BITS == 64' this
     function is available under the name `aio_read' and so
     transparently replaces the interface for small files on 32 bits
     machines.

   To write data asynchronously to a file there exists an equivalent
pair of functions with a very similar interface.

 - Function: int aio_write (struct aiocb *AIOCBP)
     This function initiates an asynchronous write operation.  The
     function call immediately returns after the operation was enqueued
     or if before this happens an error was encountered.

     The first `aiocbp->aio_nbytes' bytes from the buffer starting at
     `aiocbp->aio_buf' are written to the file for which
     `aiocbp->aio_fildes' is an descriptor, starting at the absolute
     position `aiocbp->aio_offset' in the file.

     If prioritized I/O is supported by the platform the
     `aiocbp->aio_reqprio' value is used to adjust the priority before
     the request is actually enqueued.

     The calling process is notified about the termination of the read
     request according to the `aiocbp->aio_sigevent' value.

     When `aio_write' returns the return value is zero if no error
     occurred that can be found before the process is enqueued.  If
     such an early error is found the function returns -1 and sets
     `errno' to one of the following values.

    `EAGAIN'
          The request was not enqueued due to (temporarily) exceeded
          resource limitations.

    `ENOSYS'
          The `aio_write' function is not implemented.

    `EBADF'
          The `aiocbp->aio_fildes' descriptor is not valid.  This
          condition needs not be recognized before enqueueing the
          request and so this error might also be signaled
          asynchronously.

    `EINVAL'
          The `aiocbp->aio_offset' or `aiocbp->aio_reqpiro' value is
          invalid.  This condition needs not be recognized before
          enqueueing the request and so this error might also be
          signaled asynchronously.

     In the case `aio_write' returns zero the current status of the
     request can be queried using `aio_error' and `aio_return'
     functions.  As long as the value returned by `aio_error' is
     `EINPROGRESS' the operation has not yet completed.  If `aio_error'
     returns zero the operation successfully terminated, otherwise the
     value is to be interpreted as an error code.  If the function
     terminated the result of the operation can be get using a call to
     `aio_return'.  The returned value is the same as an equivalent
     call to `read' would have returned.  Possible error code returned
     by `aio_error' are:

    `EBADF'
          The `aiocbp->aio_fildes' descriptor is not valid.

    `ECANCELED'
          The operation was canceled before the operation was finished
          (see Cancel AIO Operations)

    `EINVAL'
          The `aiocbp->aio_offset' value is invalid.

     When the sources are compiled with `_FILE_OFFSET_BITS == 64' this
     function is in fact `aio_write64' since the LFS interface
     transparently replaces the normal implementation.

 - Function: int aio_write64 (struct aiocb *AIOCBP)
     This function is similar to the `aio_write' function.  The only
     difference is that on 32 bits machines the file descriptor should
     be opened in the large file mode.  Internally `aio_write64' uses
     functionality equivalent to `lseek64' (see File Position Primitive)
     to position the file descriptor correctly for the
     writing, as opposed to `lseek' functionality used in `aio_write'.

     When the sources are compiled with `_FILE_OFFSET_BITS == 64' this
     function is available under the name `aio_write' and so
     transparently replaces the interface for small files on 32 bits
     machines.

   Beside these functions with the more or less traditional interface
POSIX.1b also defines a function with can initiate more than one
operation at once and which can handled freely mixed read and write
operation.  It is therefore similar to a combination of `readv' and
`writev'.

 - Function: int lio_listio (int MODE, struct aiocb *const LIST[], int
          NENT, struct sigevent *SIG)
     The `lio_listio' function can be used to enqueue an arbitrary
     number of read and write requests at one time.  The requests can
     all be meant for the same file, all for different files or every
     solution in between.

     `lio_listio' gets the NENT requests from the array pointed to by
     LIST.  What operation has to be performed is determined by the
     `aio_lio_opcode' member in each element of LIST.  If this field is
     `LIO_READ' an read operation is queued, similar to a call of
     `aio_read' for this element of the array (except that the way the
     termination is signalled is different, as we will see below).  If
     the `aio_lio_opcode' member is `LIO_WRITE' an write operation is
     enqueued.  Otherwise the `aio_lio_opcode' must be `LIO_NOP' in
     which case this element of LIST is simply ignored.  This
     "operation" is useful in situations where one has a fixed array of
     `struct aiocb' elements from which only a few need to be handled at
     a time.  Another situation is where the `lio_listio' call was
     cancelled before all requests are processed (see Cancel AIO Operations)
     and the remaining requests have to be reissued.

     The other members of each element of the array pointed to by
     `list' must have values suitable for the operation as described in
     the documentation for `aio_read' and `aio_write' above.

     The MODE argument determines how `lio_listio' behaves after having
     enqueued all the requests.  If MODE is `LIO_WAIT' it waits until
     all requests terminated.  Otherwise MODE must be `LIO_NOWAIT' and
     in this case the function returns immediately after having
     enqueued all the requests.  In this case the caller gets a
     notification of the termination of all requests according to the
     SIG parameter.  If SIG is `NULL' no notification is send.
     Otherwise a signal is sent or a thread is started, just as
     described in the description for `aio_read' or `aio_write'.

     If MODE is `LIO_WAIT' the return value of `lio_listio' is 0 when
     all requests completed successfully.  Otherwise the function
     return -1 and `errno' is set accordingly.  To find out which
     request or requests failed one has to use the `aio_error' function
     on all the elements of the array LIST.

     In case MODE is `LIO_NOWAIT' the function return 0 if all requests
     were enqueued correctly.  The current state of the requests can be
     found using `aio_error' and `aio_return' as described above.  In
     case `lio_listio' returns -1 in this mode the global variable
     `errno' is set accordingly.  If a request did not yet terminate a
     call to `aio_error' returns `EINPROGRESS'.  If the value is
     different the request is finished and the error value (or 0) is
     returned and the result of the operation can be retrieved using
     `aio_return'.

     Possible values for `errno' are:

    `EAGAIN'
          The resources necessary to queue all the requests are not
          available in the moment.  The error status for each element
          of LIST must be checked which request failed.

          Another reason could be that the system wide limit of AIO
          requests is exceeded.  This cannot be the case for the
          implementation on GNU systems since no arbitrary limits exist.

    `EINVAL'
          The MODE parameter is invalid or NENT is larger than
          `AIO_LISTIO_MAX'.

    `EIO'
          One or more of the request's I/O operations failed.  The
          error status of each request should be checked for which one
          failed.

    `ENOSYS'
          The `lio_listio' function is not supported.

     If the MODE parameter is `LIO_NOWAIT' and the caller cancels an
     request the error status for this request returned by `aio_error'
     is `ECANCELED'.

     When the sources are compiled with `_FILE_OFFSET_BITS == 64' this
     function is in fact `lio_listio64' since the LFS interface
     transparently replaces the normal implementation.

 - Function: int lio_listio64 (int MODE, struct aiocb *const LIST, int
          NENT, struct sigevent *SIG)
     This function is similar to the `aio_listio' function.  The only
     difference is that only 32 bits machines the file descriptor should
     be opened in the large file mode.  Internally `lio_listio64' uses
     functionality equivalent to `lseek64' (see File Position Primitive)
     to position the file descriptor correctly for the
     reading or writing, as opposed to `lseek' functionality used in
     `lio_listio'.

     When the sources are compiled with `_FILE_OFFSET_BITS == 64' this
     function is available under the name `lio_listio' and so
     transparently replaces the interface for small files on 32 bits
     machines.

Getting the Status of AIO Operations
------------------------------------

   As already described in the documentation of the functions in the
last section it must be possible to get information about the status of
a I/O request.  When the operation is performed really asynchronous (as
with `aio_read' and `aio_write' and with `aio_listio' when the mode is
`LIO_NOWAIT') one sometimes needs to know whether a specific request
already terminated and if yes, what the result was..  The following two
function allow to get this kind of information.

 - Function: int aio_error (const struct aiocb *AIOCBP)
     This function determines the error state of the request described
     by the `struct aiocb' variable pointed to by AIOCBP.  If the
     request has not yet terminated the value returned is always
     `EINPROGRESS'.  Once the request has terminated the value
     `aio_error' returns is either 0 if the request completed
     successfully or it returns the value which would be stored in the
     `errno' variable if the request would have been done using `read',
     `write', or `fsync'.

     The function can return `ENOSYS' if it is not implemented.  It
     could also return `EINVAL' if the AIOCBP parameter does not refer
     to an asynchronous operation whose return status is not yet known.

     When the sources are compiled with `_FILE_OFFSET_BITS == 64' this
     function is in fact `aio_error64' since the LFS interface
     transparently replaces the normal implementation.

 - Function: int aio_error64 (const struct aiocb64 *AIOCBP)
     This function is similar to `aio_error' with the only difference
     that the argument is a reference to a variable of type `struct
     aiocb64'.

     When the sources are compiled with `_FILE_OFFSET_BITS == 64' this
     function is available under the name `aio_error' and so
     transparently replaces the interface for small files on 32 bits
     machines.

 - Function: ssize_t aio_return (const struct aiocb *AIOCBP)
     This function can be used to retrieve the return status of the
     operation carried out by the request described in the variable
     pointed to by AIOCBP.  As long as the error status of this request
     as returned by `aio_error' is `EINPROGRESS' the return of this
     function is undefined.

     Once the request is finished this function can be used exactly
     once to retrieve the return value.  Following calls might lead to
     undefined behaviour.  The return value itself is the value which
     would have been returned by the `read', `write', or `fsync' call.

     The function can return `ENOSYS' if it is not implemented.  It
     could also return `EINVAL' if the AIOCBP parameter does not refer
     to an asynchronous operation whose return status is not yet known.

     When the sources are compiled with `_FILE_OFFSET_BITS == 64' this
     function is in fact `aio_return64' since the LFS interface
     transparently replaces the normal implementation.

 - Function: int aio_return64 (const struct aiocb64 *AIOCBP)
     This function is similar to `aio_return' with the only difference
     that the argument is a reference to a variable of type `struct
     aiocb64'.

     When the sources are compiled with `_FILE_OFFSET_BITS == 64' this
     function is available under the name `aio_return' and so
     transparently replaces the interface for small files on 32 bits
     machines.

Getting into a Consistent State
-------------------------------

   When dealing with asynchronous operations it is sometimes necessary
to get into a consistent state.  This would mean for AIO that one wants
to know whether a certain request or a group of request were processed.
This could be done by waiting for the notification sent by the system
after the operation terminated but this sometimes would mean wasting
resources (mainly computation time).  Instead POSIX.1b defines two
functions which will help with most kinds of consistency.

   The `aio_fsync' and `aio_fsync64' functions are only available if in
`unistd.h' the symbol `_POSIX_SYNCHRONIZED_IO' is defined.

 - Function: int aio_fsync (int OP, struct aiocb *AIOCBP)
     Calling this function forces all I/O operations operating queued
     at the time of the function call operating on the file descriptor
     `aiocbp->aio_fildes' into the synchronized I/O completion state
     (see Synchronizing I/O).  The `aio_fsync' function return
     immediately but the notification through the method described in
     `aiocbp->aio_sigevent' will happen only after all requests for this
     file descriptor terminated and the file is synchronized.  This also
     means that requests for this very same file descriptor which are
     queued after the synchronization request are not effected.

     If OP is `O_DSYNC' the synchronization happens as with a call to
     `fdatasync'.  Otherwise OP should be `O_SYNC' and the
     synchronization happens as with `fsync'.

     As long as the synchronization has not happened a call to
     `aio_error' with the reference to the object pointed to by AIOCBP
     returns `EINPROGRESS'.  Once the synchronization is done
     `aio_error' return 0 if the synchronization was not successful.
     Otherwise the value returned is the value to which the `fsync' or
     `fdatasync' function would have set the `errno' variable.  In this
     case nothing can be assumed about the consistency for the data
     written to this file descriptor.

     The return value of this function is 0 if the request was
     successfully filed.  Otherwise the return value is -1 and `errno'
     is set to one of the following values:

    `EAGAIN'
          The request could not be enqueued due to temporary lack of
          resources.

    `EBADF'
          The file descriptor `aiocbp->aio_fildes' is not valid or not
          open for writing.

    `EINVAL'
          The implementation does not support I/O synchronization or
          the OP parameter is other than `O_DSYNC' and `O_SYNC'.

    `ENOSYS'
          This function is not implemented.

     When the sources are compiled with `_FILE_OFFSET_BITS == 64' this
     function is in fact `aio_return64' since the LFS interface
     transparently replaces the normal implementation.

 - Function: int aio_fsync64 (int OP, struct aiocb64 *AIOCBP)
     This function is similar to `aio_fsync' with the only difference
     that the argument is a reference to a variable of type `struct
     aiocb64'.

     When the sources are compiled with `_FILE_OFFSET_BITS == 64' this
     function is available under the name `aio_fsync' and so
     transparently replaces the interface for small files on 32 bits
     machines.

   Another method of synchronization is to wait until one or more
requests of a specific set terminated.  This could be achieved by the
`aio_*' functions to notify the initiating process about the
termination but in some situations this is not the ideal solution.  In
a program which constantly updates clients somehow connected to the
server it is not always the best solution to go round robin since some
connections might be slow.  On the other hand letting the `aio_*'
function notify the caller might also be not the best solution since
whenever the process works on preparing data for on client it makes no
sense to be interrupted by a notification since the new client will not
be handled before the current client is served.  For situations like
this `aio_suspend' should be used.

 - Function: int aio_suspend (const struct aiocb *const LIST[], int
          NENT, const struct timespec *TIMEOUT)
     When calling this function the calling thread is suspended until at
     least one of the requests pointed to by the NENT elements of the
     array LIST has completed.  If any of the requests already has
     completed at the time `aio_suspend' is called the function returns
     immediately.  Whether a request has terminated or not is done by
     comparing the error status of the request with `EINPROGRESS'.  If
     an element of LIST is `NULL' the entry is simply ignored.

     If no request has finished the calling process is suspended.  If
     TIMEOUT is `NULL' the process is not waked until a request
     finished.  If TIMEOUT is not `NULL' the process remains suspended
     at as long as specified in TIMEOUT.  In this case `aio_suspend'
     returns with an error.

     The return value of the function is 0 if one or more requests from
     the LIST have terminated.  Otherwise the function returns -1 and
     `errno' is set to one of the following values:

    `EAGAIN'
          None of the requests from the LIST completed in the time
          specified by TIMEOUT.

    `EINTR'
          A signal interrupted the `aio_suspend' function.  This signal
          might also be sent by the AIO implementation while signalling
          the termination of one of the requests.

    `ENOSYS'
          The `aio_suspend' function is not implemented.

     When the sources are compiled with `_FILE_OFFSET_BITS == 64' this
     function is in fact `aio_suspend64' since the LFS interface
     transparently replaces the normal implementation.

 - Function: int aio_suspend64 (const struct aiocb64 *const LIST[], int
          NENT, const struct timespec *TIMEOUT)
     This function is similar to `aio_suspend' with the only difference
     that the argument is a reference to a variable of type `struct
     aiocb64'.

     When the sources are compiled with `_FILE_OFFSET_BITS == 64' this
     function is available under the name `aio_suspend' and so
     transparently replaces the interface for small files on 32 bits
     machines.

Cancelation of AIO Operations
-----------------------------

   When one or more requests are asynchronously processed it might be
useful in some situations to cancel a selected operation, e.g., if it
becomes obvious that the written data is not anymore accurate and would
have to be overwritten soon.  As an example assume an application, which
writes data in files in a situation where new incoming data would have
to be written in a file which will be updated by an enqueued request.
The POSIX AIO implementation provides such a function but this function
is not capable to force the cancelation of the request.  It is up to the
implementation to decide whether it is possible to cancel the operation
or not.  Therefore using this function is merely a hint.

 - Function: int aio_cancel (int FILDES, struct aiocb *AIOCBP)
     The `aio_cancel' function can be used to cancel one or more
     outstanding requests.  If the AIOCBP parameter is `NULL' the
     function tries to cancel all outstanding requests which would
     process the file descriptor FILDES (i.e.,, whose `aio_fildes'
     member is FILDES).  If AIOCBP is not `NULL' the very specific
     request pointed to by AIOCBP is tried to be canceled.

     For requests which were successfully canceled the normal
     notification about the termination of the request should take
     place.  I.e., depending on the `struct sigevent' object which
     controls this, nothing happens, a signal is sent or a thread is
     started.  If the request cannot be canceled it terminates the
     usual way after performing the operation.

     After a request is successfully canceled a call to `aio_error' with
     a reference to this request as the parameter will return
     `ECANCELED' and a call to `aio_return' will return -1.  If the
     request wasn't canceled and is still running the error status is
     still `EINPROGRESS'.

     The return value of the function is `AIO_CANCELED' if there were
     requests which haven't terminated and which successfully were
     canceled.  If there is one or more request left which couldn't be
     canceled the return value is `AIO_NOTCANCELED'.  In this case
     `aio_error' must be used to find out which of the perhaps multiple
     requests (in AIOCBP is `NULL') wasn't successfully canceled.  If
     all requests already terminated at the time `aio_cancel' is called
     the return value is `AIO_ALLDONE'.

     If an error occurred during the execution of `aio_cancel' the
     function returns -1 and sets `errno' to one of the following
     values.

    `EBADF'
          The file descriptor FILDES is not valid.

    `ENOSYS'
          `aio_cancel' is not implemented.

     When the sources are compiled with `_FILE_OFFSET_BITS == 64' this
     function is in fact `aio_cancel64' since the LFS interface
     transparently replaces the normal implementation.

 - Function: int aio_cancel64 (int FILDES, struct aiocb *AIOCBP)
     This function is similar to `aio_cancel' with the only difference
     that the argument is a reference to a variable of type `struct
     aiocb64'.

     When the sources are compiled with `_FILE_OFFSET_BITS == 64' this
     function is available under the name `aio_cancel' and so
     transparently replaces the interface for small files on 32 bits
     machines.

How to optimize the AIO implementation
--------------------------------------

   The POSIX standard does not specify how the AIO functions are
implemented.  They could be system calls but it is also possible to
emulate them at userlevel.

   At least the available implementation at the point of this writing
is a userlevel implementation which uses threads for handling the
enqueued requests.  This implementation requires to make some decisions
about limitations but hard limitations are something which better
should be avoided the GNU C library implementation provides a mean to
tune the AIO implementation individually for each use.

 - Data Type: struct aioinit
     This data type is used to pass the configuration or tunable
     parameters to the implementation.  The program has to initialize
     the members of this struct and pass it to the implementation using
     the `aio_init' function.

    `int aio_threads'
          This member specifies the maximal number of threads which
          must be used at any one time.

    `int aio_num'
          This number provides an estimate on the maximal number of
          simultaneously enqueued requests.

    `int aio_locks'

    `int aio_usedba'

    `int aio_debug'

    `int aio_numusers'

    `int aio_reserved[2]'

 - Function: void aio_init (const struct aioinit *INIT)
     This function must be called before any other AIO function.
     Calling it is completely voluntarily since it only is meant to
     help the AIO implementation to perform better.

     Before calling the `aio_init' function the members of a variable of
     type `struct aioinit' must be initialized.  Then a reference to
     this variable is passed as the parameter to `aio_init' which itself
     may or may not pay attention to the hints.

     The function has no return value and no error cases are defined.
     It is a extension which follows a proposal from the SGI
     implementation in Irix 6.  It is not covered by POSIX.1b or Unix98.

Control Operations on Files
===========================

   This section describes how you can perform various other operations
on file descriptors, such as inquiring about or setting flags describing
the status of the file descriptor, manipulating record locks, and the
like.  All of these operations are performed by the function `fcntl'.

   The second argument to the `fcntl' function is a command that
specifies which operation to perform.  The function and macros that name
various flags that are used with it are declared in the header file
`fcntl.h'.  Many of these flags are also used by the `open' function;
see Opening and Closing Files.

 - Function: int fcntl (int FILEDES, int COMMAND, ...)
     The `fcntl' function performs the operation specified by COMMAND
     on the file descriptor FILEDES.  Some commands require additional
     arguments to be supplied.  These additional arguments and the
     return value and error conditions are given in the detailed
     descriptions of the individual commands.

     Briefly, here is a list of what the various commands are.

    `F_DUPFD'
          Duplicate the file descriptor (return another file descriptor
          pointing to the same open file).  See Duplicating Descriptors.

    `F_GETFD'
          Get flags associated with the file descriptor.  See
          Descriptor Flags.

    `F_SETFD'
          Set flags associated with the file descriptor.  See
          Descriptor Flags.

    `F_GETFL'
          Get flags associated with the open file.  See File Status Flags.

    `F_SETFL'
          Set flags associated with the open file.  See File Status Flags.

    `F_GETLK'
          Get a file lock.  See File Locks.

    `F_SETLK'
          Set or clear a file lock.  See File Locks.

    `F_SETLKW'
          Like `F_SETLK', but wait for completion.  See File Locks.

    `F_GETOWN'
          Get process or process group ID to receive `SIGIO' signals.
          See Interrupt Input.

    `F_SETOWN'
          Set process or process group ID to receive `SIGIO' signals.
          See Interrupt Input.

     This function is a cancelation point in multi-threaded programs.
     This is a problem if the thread allocates some resources (like
     memory, file descriptors, semaphores or whatever) at the time
     `fcntl' is called.  If the thread gets canceled these resources
     stay allocated until the program ends.  To avoid this calls to
     `fcntl' should be protected using cancelation handlers.

Duplicating Descriptors
=======================

   You can "duplicate" a file descriptor, or allocate another file
descriptor that refers to the same open file as the original.  Duplicate
descriptors share one file position and one set of file status flags
(see File Status Flags), but each has its own set of file descriptor
flags (see Descriptor Flags).

   The major use of duplicating a file descriptor is to implement
"redirection" of input or output:  that is, to change the file or pipe
that a particular file descriptor corresponds to.

   You can perform this operation using the `fcntl' function with the
`F_DUPFD' command, but there are also convenient functions `dup' and
`dup2' for duplicating descriptors.

   The `fcntl' function and flags are declared in `fcntl.h', while
prototypes for `dup' and `dup2' are in the header file `unistd.h'.

 - Function: int dup (int OLD)
     This function copies descriptor OLD to the first available
     descriptor number (the first number not currently open).  It is
     equivalent to `fcntl (OLD, F_DUPFD, 0)'.

 - Function: int dup2 (int OLD, int NEW)
     This function copies the descriptor OLD to descriptor number NEW.

     If OLD is an invalid descriptor, then `dup2' does nothing; it does
     not close NEW.  Otherwise, the new duplicate of OLD replaces any
     previous meaning of descriptor NEW, as if NEW were closed first.

     If OLD and NEW are different numbers, and OLD is a valid
     descriptor number, then `dup2' is equivalent to:

          close (NEW);
          fcntl (OLD, F_DUPFD, NEW)

     However, `dup2' does this atomically; there is no instant in the
     middle of calling `dup2' at which NEW is closed and not yet a
     duplicate of OLD.

 - Macro: int F_DUPFD
     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 following `errno' 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; see
          Limits on Resources, for more information about the
          `RLIMIT_NOFILE' limit.

     `ENFILE' is not a possible error code for `dup2' because `dup2'
     does not create a new opening of a file; duplicate descriptors do
     not count toward the limit which `ENFILE' 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 (like `stdin') is done
by a shell or shell-like program before calling one of the `exec'
functions (see 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 its `main' 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 the
`exec...' functions (see Executing a File).

   The symbols in this section are defined in the header file `fcntl.h'.

 - Macro: int F_GETFD
     This macro is used as the COMMAND argument to `fcntl', to specify
     that it should return the file descriptor flags associated with
     the FILEDES argument.

     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 following `errno'
     error conditions are defined for this command:

    `EBADF'
          The FILEDES argument is invalid.

 - Macro: int F_SETFD
     This macro is used as the COMMAND argument to `fcntl', to specify
     that it should set the file descriptor flags associated with the
     FILEDES argument.  This requires a third `int' argument to specify
     the new flags, so the form of the call is:

          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 the `F_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.

 - Macro: int FD_CLOEXEC
     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 with `open' or `dup'), this bit
     is initially cleared on the new file descriptor, meaning that
     descriptor will survive into the new program after `exec'.

   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 flag `FD_CLOEXEC'
without altering any other flags:

     /* Set the `FD_CLOEXEC' flag of DESC if VALUE is nonzero,
        or clear the flag if VALUE is 0.
        Return 0 on success, or -1 on error with `errno' 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);
     }