   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.

Controlling Which Kind of Buffering
-----------------------------------

   After opening a stream (but before any other operations have been
performed on it), you can explicitly specify what kind of buffering you
want it to have using the `setvbuf' function.

   The facilities listed in this section are declared in the header
file `stdio.h'.

 - Function: int setvbuf (FILE *STREAM, char *BUF, int MODE, size_t
          SIZE)
     This function is used to specify that the stream STREAM should
     have the buffering mode MODE, which can be either `_IOFBF' (for
     full buffering), `_IOLBF' (for line buffering), or `_IONBF' (for
     unbuffered input/output).

     If you specify a null pointer as the BUF argument, then `setvbuf'
     allocates a buffer itself using `malloc'.  This buffer will be
     freed when you close the stream.

     Otherwise, BUF should be a character array that can hold at least
     SIZE characters.  You should not free the space for this array as
     long as the stream remains open and this array remains its buffer.
     You should usually either allocate it statically, or `malloc'
     (see Unconstrained Allocation) the buffer.  Using an automatic
     array is not a good idea unless you close the file before exiting
     the block that declares the array.

     While the array remains a stream buffer, the stream I/O functions
     will use the buffer for their internal purposes.  You shouldn't
     try to access the values in the array directly while the stream is
     using it for buffering.

     The `setvbuf' function returns zero on success, or a nonzero value
     if the value of MODE is not valid or if the request could not be
     honored.

 - Macro: int _IOFBF
     The value of this macro is an integer constant expression that can
     be used as the MODE argument to the `setvbuf' function to specify
     that the stream should be fully buffered.

 - Macro: int _IOLBF
     The value of this macro is an integer constant expression that can
     be used as the MODE argument to the `setvbuf' function to specify
     that the stream should be line buffered.

 - Macro: int _IONBF
     The value of this macro is an integer constant expression that can
     be used as the MODE argument to the `setvbuf' function to specify
     that the stream should be unbuffered.

 - Macro: int BUFSIZ
     The value of this macro is an integer constant expression that is
     good to use for the SIZE argument to `setvbuf'.  This value is
     guaranteed to be at least `256'.

     The value of `BUFSIZ' is chosen on each system so as to make stream
     I/O efficient.  So it is a good idea to use `BUFSIZ' as the size
     for the buffer when you call `setvbuf'.

     Actually, you can get an even better value to use for the buffer
     size by means of the `fstat' system call: it is found in the
     `st_blksize' field of the file attributes.  See Attribute Meanings.

     Sometimes people also use `BUFSIZ' as the allocation size of
     buffers used for related purposes, such as strings used to receive
     a line of input with `fgets' (see Character Input).  There is
     no particular reason to use `BUFSIZ' for this instead of any other
     integer, except that it might lead to doing I/O in chunks of an
     efficient size.

 - Function: void setbuf (FILE *STREAM, char *BUF)
     If BUF is a null pointer, the effect of this function is
     equivalent to calling `setvbuf' with a MODE argument of `_IONBF'.
     Otherwise, it is equivalent to calling `setvbuf' with BUF, and a
     MODE of `_IOFBF' and a SIZE argument of `BUFSIZ'.

     The `setbuf' function is provided for compatibility with old code;
     use `setvbuf' in all new programs.

 - Function: void setbuffer (FILE *STREAM, char *BUF, size_t SIZE)
     If BUF is a null pointer, this function makes STREAM unbuffered.
     Otherwise, it makes STREAM fully buffered using BUF as the buffer.
     The SIZE argument specifies the length of BUF.

     This function is provided for compatibility with old BSD code.  Use
     `setvbuf' instead.

 - Function: void setlinebuf (FILE *STREAM)
     This function makes STREAM be line buffered, and allocates the
     buffer for you.

     This function is provided for compatibility with old BSD code.  Use
     `setvbuf' instead.

Other Kinds of Streams
======================

   The GNU library provides ways for you to define additional kinds of
streams that do not necessarily correspond to an open file.

   One such type of stream takes input from or writes output to a
string.  These kinds of streams are used internally to implement the
`sprintf' and `sscanf' functions.  You can also create such a stream
explicitly, using the functions described in String Streams.

   More generally, you can define streams that do input/output to
arbitrary objects using functions supplied by your program.  This
protocol is discussed in Custom Streams.

   *Portability Note:* The facilities described in this section are
specific to GNU.  Other systems or C implementations might or might not
provide equivalent functionality.

String Streams
--------------

   The `fmemopen' and `open_memstream' functions allow you to do I/O to
a string or memory buffer.  These facilities are declared in `stdio.h'.

 - Function: FILE * fmemopen (void *BUF, size_t SIZE, const char
          *OPENTYPE)
     This function opens a stream that allows the access specified by
     the OPENTYPE argument, that reads from or writes to the buffer
     specified by the argument BUF.  This array must be at least SIZE
     bytes long.

     If you specify a null pointer as the BUF argument, `fmemopen'
     dynamically allocates (as with `malloc'; see Unconstrained Allocation)
     an array SIZE bytes long.  This is really only useful
     if you are going to write things to the buffer and then read them
     back in again, because you have no way of actually getting a
     pointer to the buffer (for this, try `open_memstream', below).
     The buffer is freed when the stream is open.

     The argument OPENTYPE is the same as in `fopen' (see Opening Streams).
     If the OPENTYPE specifies append mode, then the
     initial file position is set to the first null character in the
     buffer.  Otherwise the initial file position is at the beginning
     of the buffer.

     When a stream open for writing is flushed or closed, a null
     character (zero byte) is written at the end of the buffer if it
     fits.  You should add an extra byte to the SIZE argument to
     account for this.  Attempts to write more than SIZE bytes to the
     buffer result in an error.

     For a stream open for reading, null characters (zero bytes) in the
     buffer do not count as "end of file".  Read operations indicate
     end of file only when the file position advances past SIZE bytes.
     So, if you want to read characters from a null-terminated string,
     you should supply the length of the string as the SIZE argument.

   Here is an example of using `fmemopen' to create a stream for
reading from a string:

     #include <stdio.h>

     static char buffer[] = "foobar";

     int
     main (void)
     {
       int ch;
       FILE *stream;

       stream = fmemopen (buffer, strlen (buffer), "r");
       while ((ch = fgetc (stream)) != EOF)
         printf ("Got %c\n", ch);
       fclose (stream);

       return 0;
     }

   This program produces the following output:

     Got f
     Got o
     Got o
     Got b
     Got a
     Got r

 - Function: FILE * open_memstream (char **PTR, size_t *SIZELOC)
     This function opens a stream for writing to a buffer.  The buffer
     is allocated dynamically (as with `malloc'; see Unconstrained Allocation)
     and grown as necessary.

     When the stream is closed with `fclose' or flushed with `fflush',
     the locations PTR and SIZELOC are updated to contain the pointer
     to the buffer and its size.  The values thus stored remain valid
     only as long as no further output on the stream takes place.  If
     you do more output, you must flush the stream again to store new
     values before you use them again.

     A null character is written at the end of the buffer.  This null
     character is _not_ included in the size value stored at SIZELOC.

     You can move the stream's file position with `fseek' or `fseeko'
     (see File Positioning).  Moving the file position past the end
     of the data already written fills the intervening space with
     zeroes.

   Here is an example of using `open_memstream':

     #include <stdio.h>

     int
     main (void)
     {
       char *bp;
       size_t size;
       FILE *stream;

       stream = open_memstream (&bp, &size);
       fprintf (stream, "hello");
       fflush (stream);
       printf ("buf = `%s', size = %d\n", bp, size);
       fprintf (stream, ", world");
       fclose (stream);
       printf ("buf = `%s', size = %d\n", bp, size);

       return 0;
     }

   This program produces the following output:

     buf = `hello', size = 5
     buf = `hello, world', size = 12

Obstack Streams
---------------

   You can open an output stream that puts it data in an obstack.
See Obstacks.

 - Function: FILE * open_obstack_stream (struct obstack *OBSTACK)
     This function opens a stream for writing data into the obstack
     OBSTACK.  This starts an object in the obstack and makes it grow
     as data is written (see Growing Objects).

     Calling `fflush' on this stream updates the current size of the
     object to match the amount of data that has been written.  After a
     call to `fflush', you can examine the object temporarily.

     You can move the file position of an obstack stream with `fseek' or
     `fseeko' (see File Positioning).  Moving the file position past
     the end of the data written fills the intervening space with zeros.

     To make the object permanent, update the obstack with `fflush', and
     then use `obstack_finish' to finalize the object and get its
     address.  The following write to the stream starts a new object in
     the obstack, and later writes add to that object until you do
     another `fflush' and `obstack_finish'.

     But how do you find out how long the object is?  You can get the
     length in bytes by calling `obstack_object_size' (see Status of an Obstack),
     or you can null-terminate the object like this:

          obstack_1grow (OBSTACK, 0);

     Whichever one you do, you must do it _before_ calling
     `obstack_finish'.  (You can do both if you wish.)

   Here is a sample function that uses `open_obstack_stream':

     char *
     make_message_string (const char *a, int b)
     {
       FILE *stream = open_obstack_stream (&message_obstack);
       output_task (stream);
       fprintf (stream, ": ");
       fprintf (stream, a, b);
       fprintf (stream, "\n");
       fclose (stream);
       obstack_1grow (&message_obstack, 0);
       return obstack_finish (&message_obstack);
     }

Programming Your Own Custom Streams
-----------------------------------

   This section describes how you can make a stream that gets input
from an arbitrary data source or writes output to an arbitrary data sink
programmed by you.  We call these "custom streams".

Custom Streams and Cookies
..........................

   Inside every custom stream is a special object called the "cookie".
This is an object supplied by you which records where to fetch or store
the data read or written.  It is up to you to define a data type to use
for the cookie.  The stream functions in the library never refer
directly to its contents, and they don't even know what the type is;
they record its address with type `void *'.

   To implement a custom stream, you must specify _how_ to fetch or
store the data in the specified place.  You do this by defining "hook
functions" to read, write, change "file position", and close the
stream.  All four of these functions will be passed the stream's cookie
so they can tell where to fetch or store the data.  The library
functions don't know what's inside the cookie, but your functions will
know.

   When you create a custom stream, you must specify the cookie pointer,
and also the four hook functions stored in a structure of type
`cookie_io_functions_t'.

   These facilities are declared in `stdio.h'.

 - Data Type: cookie_io_functions_t
     This is a structure type that holds the functions that define the
     communications protocol between the stream and its cookie.  It has
     the following members:

    `cookie_read_function_t *read'
          This is the function that reads data from the cookie.  If the
          value is a null pointer instead of a function, then read
          operations on this stream always return `EOF'.

    `cookie_write_function_t *write'
          This is the function that writes data to the cookie.  If the
          value is a null pointer instead of a function, then data
          written to the stream is discarded.

    `cookie_seek_function_t *seek'
          This is the function that performs the equivalent of file
          positioning on the cookie.  If the value is a null pointer
          instead of a function, calls to `fseek' or `fseeko' on this
          stream can only seek to locations within the buffer; any
          attempt to seek outside the buffer will return an `ESPIPE'
          error.

    `cookie_close_function_t *close'
          This function performs any appropriate cleanup on the cookie
          when closing the stream.  If the value is a null pointer
          instead of a function, nothing special is done to close the
          cookie when the stream is closed.

 - Function: FILE * fopencookie (void *COOKIE, const char *OPENTYPE,
          cookie_io_functions_t IO-FUNCTIONS)
     This function actually creates the stream for communicating with
     the COOKIE using the functions in the IO-FUNCTIONS argument.  The
     OPENTYPE argument is interpreted as for `fopen'; see Opening Streams.
     (But note that the "truncate on open" option is
     ignored.)  The new stream is fully buffered.

     The `fopencookie' function returns the newly created stream, or a
     null pointer in case of an error.

Custom Stream Hook Functions
............................

   Here are more details on how you should define the four hook
functions that a custom stream needs.

   You should define the function to read data from the cookie as:

     ssize_t READER (void *COOKIE, void *BUFFER, size_t SIZE)

   This is very similar to the `read' function; see I/O Primitives.
Your function should transfer up to SIZE bytes into the
BUFFER, and return the number of bytes read, or zero to indicate
end-of-file.  You can return a value of `-1' to indicate an error.

   You should define the function to write data to the cookie as:

     ssize_t WRITER (void *COOKIE, const void *BUFFER, size_t SIZE)

   This is very similar to the `write' function; see I/O Primitives.
Your function should transfer up to SIZE bytes from the
buffer, and return the number of bytes written.  You can return a value
of `-1' to indicate an error.

   You should define the function to perform seek operations on the
cookie as:

     int SEEKER (void *COOKIE, fpos_t *POSITION, int WHENCE)

   For this function, the POSITION and WHENCE arguments are interpreted
as for `fgetpos'; see Portable Positioning.  In the GNU
library, `fpos_t' is equivalent to `off_t' or `long int', and simply
represents the number of bytes from the beginning of the file.

   After doing the seek operation, your function should store the
resulting file position relative to the beginning of the file in
POSITION.  Your function should return a value of `0' on success and
`-1' to indicate an error.

   You should define the function to do cleanup operations on the cookie
appropriate for closing the stream as:

     int CLEANER (void *COOKIE)

   Your function should return `-1' to indicate an error, and `0'
otherwise.

 - Data Type: cookie_read_function
     This is the data type that the read function for a custom stream
     should have.  If you declare the function as shown above, this is
     the type it will have.

 - Data Type: cookie_write_function
     The data type of the write function for a custom stream.

 - Data Type: cookie_seek_function
     The data type of the seek function for a custom stream.

 - Data Type: cookie_close_function
     The data type of the close function for a custom stream.

Formatted Messages
==================

   On systems which are based on System V messages of programs
(especially the system tools) are printed in a strict form using the
`fmtmsg' function.  The uniformity sometimes helps the user to
interpret messages and the strictness tests of the `fmtmsg' function
ensure that the programmer follows some minimal requirements.

Printing Formatted Messages
---------------------------

   Messages can be printed to standard error and/or to the console.  To
select the destination the programmer can use the following two values,
bitwise OR combined if wanted, for the CLASSIFICATION parameter of
`fmtmsg':

`MM_PRINT'
     Display the message in standard error.

`MM_CONSOLE'
     Display the message on the system console.

   The erroneous piece of the system can be signalled by exactly one of
the following values which also is bitwise ORed with the CLASSIFICATION
parameter to `fmtmsg':

`MM_HARD'
     The source of the condition is some hardware.

`MM_SOFT'
     The source of the condition is some software.

`MM_FIRM'
     The source of the condition is some firmware.

   A third component of the CLASSIFICATION parameter to `fmtmsg' can
describe the part of the system which detects the problem.  This is
done by using exactly one of the following values:

`MM_APPL'
     The erroneous condition is detected by the application.

`MM_UTIL'
     The erroneous condition is detected by a utility.

`MM_OPSYS'
     The erroneous condition is detected by the operating system.

   A last component of CLASSIFICATION can signal the results of this
message.  Exactly one of the following values can be used:

`MM_RECOVER'
     It is a recoverable error.

`MM_NRECOV'
     It is a non-recoverable error.

 - Function: int fmtmsg (long int CLASSIFICATION, const char *LABEL,
          int SEVERITY, const char *TEXT, const char *ACTION, const
          char *TAG)
     Display a message described by its parameters on the device(s)
     specified in the CLASSIFICATION parameter.  The LABEL parameter
     identifies the source of the message.  The string should consist
     of two colon separated parts where the first part has not more
     than 10 and the second part not more the 14 characters.  The TEXT
     parameter describes the condition of the error, the ACTION
     parameter possible steps to recover from the error and the TAG
     parameter is a reference to the online documentation where more
     information can be found.  It should contain the LABEL value and a
     unique identification number.

     Each of the parameters can be a special value which means this
     value is to be omitted.  The symbolic names for these values are:

    `MM_NULLLBL'
          Ignore LABEL parameter.

    `MM_NULLSEV'
          Ignore SEVERITY parameter.

    `MM_NULLMC'
          Ignore CLASSIFICATION parameter.  This implies that nothing is
          actually printed.

    `MM_NULLTXT'
          Ignore TEXT parameter.

    `MM_NULLACT'
          Ignore ACTION parameter.

    `MM_NULLTAG'
          Ignore TAG parameter.

     There is another way certain fields can be omitted from the output
     to standard error.  This is described below in the description of
     environment variables influencing the behaviour.

     The SEVERITY parameter can have one of the values in the following
     table:

    `MM_NOSEV'
          Nothing is printed, this value is the same as `MM_NULLSEV'.

    `MM_HALT'
          This value is printed as `HALT'.

    `MM_ERROR'
          This value is printed as `ERROR'.

    `MM_WARNING'
          This value is printed as `WARNING'.

    `MM_INFO'
          This value is printed as `INFO'.

     The numeric value of these five macros are between `0' and `4'.
     Using the environment variable `SEV_LEVEL' or using the
     `addseverity' function one can add more severity levels with their
     corresponding string to print.  This is described below (see
     Adding Severity Classes).

     If no parameter is ignored the output looks like this:

          LABEL: SEVERITY-STRING: TEXT
          TO FIX: ACTION TAG

     The colons, new line characters and the `TO FIX' string are
     inserted if necessary, i.e., if the corresponding parameter is not
     ignored.

     This function is specified in the X/Open Portability Guide.  It is
     also available on all system derived from System V.

     The function returns the value `MM_OK' if no error occurred.  If
     only the printing to standard error failed, it returns `MM_NOMSG'.
     If printing to the console fails, it returns `MM_NOCON'.  If
     nothing is printed `MM_NOTOK' is returned.  Among situations where
     all outputs fail this last value is also returned if a parameter
     value is incorrect.

   There are two environment variables which influence the behaviour of
`fmtmsg'.  The first is `MSGVERB'.  It is used to control the output
actually happening on standard error (_not_ the console output).  Each
of the five fields can be explicitly enabled.  To do this the user has
to put the `MSGVERB' variable with a format like the following in the
environment before calling the `fmtmsg' function the first time:

     MSGVERB=KEYWORD[:KEYWORD[:...]]

   Valid KEYWORDs are `label', `severity', `text', `action', and `tag'.
If the environment variable is not given or is the empty string, a not
supported keyword is given or the value is somehow else invalid, no
part of the message is masked out.

   The second environment variable which influences the behaviour of
`fmtmsg' is `SEV_LEVEL'.  This variable and the change in the behaviour
of `fmtmsg' is not specified in the X/Open Portability Guide.  It is
available in System V systems, though.  It can be used to introduce new
severity levels.  By default, only the five severity levels described
above are available.  Any other numeric value would make `fmtmsg' print
nothing.

   If the user puts `SEV_LEVEL' with a format like

     SEV_LEVEL=[DESCRIPTION[:DESCRIPTION[:...]]]

in the environment of the process before the first call to `fmtmsg',
where DESCRIPTION has a value of the form

     SEVERITY-KEYWORD,LEVEL,PRINTSTRING

   The SEVERITY-KEYWORD part is not used by `fmtmsg' but it has to be
present.  The LEVEL part is a string representation of a number.  The
numeric value must be a number greater than 4.  This value must be used
in the SEVERITY parameter of `fmtmsg' to select this class.  It is not
possible to overwrite any of the predefined classes.  The PRINTSTRING
is the string printed when a message of this class is processed by
`fmtmsg' (see above, `fmtsmg' does not print the numeric value but
instead the string representation).

Adding Severity Classes
-----------------------

   There is another possibility to introduce severity classes beside
using the environment variable `SEV_LEVEL'.  This simplifies the task of
introducing new classes in a running program.  One could use the
`setenv' or `putenv' function to set the environment variable, but this
is toilsome.

 - Function: int addseverity (int SEVERITY, const char *STRING)
     This function allows to introduce new severity classes which can be
     addressed by the SEVERITY parameter of the `fmtmsg' function.  The
     SEVERITY parameter of `addseverity' must match the value for the
     parameter with the same name of `fmtmsg' and STRING is the string
     printed in the actual messages instead of the numeric value.

     If STRING is `NULL' the severity class with the numeric value
     according to SEVERITY is removed.

     It is not possible to overwrite or remove one of the default
     severity classes.  All calls to `addseverity' with SEVERITY set to
     one of the values for the default classes will fail.

     The return value is `MM_OK' if the task was successfully performed.
     If the return value is `MM_NOTOK' something went wrong.  This could
     mean that no more memory is available or a class is not available
     when it has to be removed.

     This function is not specified in the X/Open Portability Guide
     although the `fmtsmg' function is.  It is available on System V
     systems.

How to use `fmtmsg' and `addseverity'
-------------------------------------

   Here is a simple example program to illustrate the use of the both
functions described in this section.

     #include <fmtmsg.h>

     int
     main (void)
     {
       addseverity (5, "NOTE2");
       fmtmsg (MM_PRINT, "only1field", MM_INFO, "text2", "action2", "tag2");
       fmtmsg (MM_PRINT, "UX:cat", 5, "invalid syntax", "refer to manual",
               "UX:cat:001");
       fmtmsg (MM_PRINT, "label:foo", 6, "text", "action", "tag");
       return 0;
     }

   The second call to `fmtmsg' illustrates a use of this function how
it usually happens on System V systems which heavily use this function.
It might be worth a thought to follow the scheme used in System V
systems so we give a short explanation here.  The value of the LABEL
field (`UX:cat') says that the error occurred in the Unix program
`cat'.  The explanation of the error follows and the value for the
ACTION parameter is `"refer to manual"'.  One could me more specific
here, if needed.  The TAG field contains, as proposed above, the value
of the string given for the LABEL parameter, and additionally a unique
ID (`001' in this case).  For a GNU environment this string could
contain a reference to the corresponding node in the Info page for the
program.

Running this program without specifying the `MSGVERB' and `SEV_LEVEL'
function produces the following output:

     UX:cat: NOTE2: invalid syntax
     TO FIX: refer to manual UX:cat:001

   We see the different fields of the message and how the extra glue
(the colons and the `TO FIX' string) are printed.  But only one of the
three calls to `fmtmsg' produced output.  The first call does not print
anything because the LABEL parameter is not in the correct form.  The
string must contain two fields, separated by a colon (see Printing Formatted Messages).
The third `fmtmsg' call produced no output
since the class with the numeric value `6' is not defined.  Although a
class with numeric value `5' is also not defined by default, the call
the `addseverity' introduces it and the second call to `fmtmsg'
produces the above output.

   When we change the environment of the program to contain
`SEV_LEVEL=XXX,6,NOTE' when running it we get a different result:

     UX:cat: NOTE2: invalid syntax
     TO FIX: refer to manual UX:cat:001
     label:foo: NOTE: text
     TO FIX: action tag

   Now the third call the `fmtmsg' produced some output and we see how
the string `NOTE' from the environment variable appears in the message.

   Now we can reduce the output by specifying in which fields we are
interested in.  If we additionally set the environment variable
`MSGVERB' to the value `severity:label:action' we get the following
output:

     UX:cat: NOTE2
     TO FIX: refer to manual
     label:foo: NOTE
     TO FIX: action

I.e., the output produced by the TEXT and the TAG parameters to
`fmtmsg' vanished.  Please also note that now there is no colon after
the `NOTE' and `NOTE2' strings in the output.  This is not necessary
since there is no more output on this line since the text is missing.

Low-Level Input/Output
**********************

   This chapter describes functions for performing low-level
input/output operations on file descriptors.  These functions include
the primitives for the higher-level I/O functions described in
I/O on Streams, as well as functions for performing low-level control
operations for which there are no equivalents on streams.

   Stream-level I/O is more flexible and usually more convenient;
therefore, programmers generally use the descriptor-level functions only
when necessary.  These are some of the usual reasons:

   * For reading binary files in large chunks.

   * For reading an entire file into core before parsing it.

   * To perform operations other than data transfer, which can only be
     done with a descriptor.  (You can use `fileno' to get the
     descriptor corresponding to a stream.)

   * To pass descriptors to a child process.  (The child can create its
     own stream to use a descriptor that it inherits, but cannot
     inherit a stream directly.)

Opening and Closing Files
=========================

   This section describes the primitives for opening and closing files
using file descriptors.  The `open' and `creat' functions are declared
in the header file `fcntl.h', while `close' is declared in `unistd.h'.

 - Function: int open (const char *FILENAME, int FLAGS[, mode_t MODE])
     The `open' function creates and returns a new file descriptor for
     the file named by FILENAME.  Initially, the file position
     indicator for the file is at the beginning of the file.  The
     argument MODE is used only when a file is created, but it doesn't
     hurt to supply the argument in any case.

     The FLAGS argument controls how the file is to be opened.  This is
     a bit mask; you create the value by the bitwise OR of the
     appropriate parameters (using the `|' operator in C).  See File Status Flags,
     for the parameters available.

     The normal return value from `open' is a non-negative integer file
     descriptor.  In the case of an error, a value of -1 is returned
     instead.  In addition to the usual file name errors (see File Name Errors),
     the following `errno' error conditions are defined
     for this function:

    `EACCES'
          The file exists but is not readable/writable as requested by
          the FLAGS argument, the file does not exist and the directory
          is unwritable so it cannot be created.

    `EEXIST'
          Both `O_CREAT' and `O_EXCL' are set, and the named file
          already exists.

    `EINTR'
          The `open' operation was interrupted by a signal.  See
          Interrupted Primitives.

    `EISDIR'
          The FLAGS argument specified write access, and the file is a
          directory.

    `EMFILE'
          The process has too many files open.  The maximum number of
          file descriptors is controlled by the `RLIMIT_NOFILE'
          resource limit; see Limits on Resources.

    `ENFILE'
          The entire system, or perhaps the file system which contains
          the directory, cannot support any additional open files at
          the moment.  (This problem cannot happen on the GNU system.)

    `ENOENT'
          The named file does not exist, and `O_CREAT' is not specified.

    `ENOSPC'
          The directory or file system that would contain the new file
          cannot be extended, because there is no disk space left.

    `ENXIO'
          `O_NONBLOCK' and `O_WRONLY' are both set in the FLAGS
          argument, the file named by FILENAME is a FIFO (see Pipes and FIFOs),
          and no process has the file open for reading.

    `EROFS'
          The file resides on a read-only file system and any of
          `O_WRONLY', `O_RDWR', and `O_TRUNC' are set in the FLAGS
          argument, or `O_CREAT' is set and the file does not already
          exist.

     If on a 32 bits machine the sources are translated with
     `_FILE_OFFSET_BITS == 64' the function `open' returns a file
     descriptor opened in the large file mode which enables the file
     handling functions to use files up to 2^63 bytes in size and
     offset from -2^63 to 2^63.  This happens transparently for the user
     since all of the lowlevel file handling functions are equally
     replaced.

     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
     `open' is called.  If the thread gets canceled these resources
     stay allocated until the program ends.  To avoid this calls to
     `open' should be protected using cancelation handlers.

     The `open' function is the underlying primitive for the `fopen'
     and `freopen' functions, that create streams.

 - Function: int open64 (const char *FILENAME, int FLAGS[, mode_t MODE])
     This function is similar to `open'.  It returns a file descriptor
     which can be used to access the file named by FILENAME.  The only
     the difference is that on 32 bits systems the file is opened in the
     large file mode.  I.e., file length and file offsets can exceed 31
     bits.

     When the sources are translated with `_FILE_OFFSET_BITS == 64' this
     function is actually available under the name `open'.  I.e., the
     new, extended API using 64 bit file sizes and offsets transparently
     replaces the old API.

 - Obsolete function: int creat (const char *FILENAME, mode_t MODE)
     This function is obsolete.  The call:

          creat (FILENAME, MODE)

     is equivalent to:

          open (FILENAME, O_WRONLY | O_CREAT | O_TRUNC, MODE)

     If on a 32 bits machine the sources are translated with
     `_FILE_OFFSET_BITS == 64' the function `creat' returns a file
     descriptor opened in the large file mode which enables the file
     handling functions to use files up to 2^63 in size and offset from
     -2^63 to 2^63.  This happens transparently for the user since all
     of the lowlevel file handling functions are equally replaced.

 - Obsolete function: int creat64 (const char *FILENAME, mode_t MODE)
     This function is similar to `creat'.  It returns a file descriptor
     which can be used to access the file named by FILENAME.  The only
     the difference is that on 32 bits systems the file is opened in the
     large file mode.  I.e., file length and file offsets can exceed 31
     bits.

     To use this file descriptor one must not use the normal operations
     but instead the counterparts named `*64', e.g., `read64'.

     When the sources are translated with `_FILE_OFFSET_BITS == 64' this
     function is actually available under the name `open'.  I.e., the
     new, extended API using 64 bit file sizes and offsets transparently
     replaces the old API.

 - Function: int close (int FILEDES)
     The function `close' closes the file descriptor FILEDES.  Closing
     a file has the following consequences:

        * The file descriptor is deallocated.

        * Any record locks owned by the process on the file are
          unlocked.

        * When all file descriptors associated with a pipe or FIFO have
          been closed, any unread data is discarded.

     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
     `close' is called.  If the thread gets canceled these resources
     stay allocated until the program ends.  To avoid this calls to
     `close' should be protected using cancelation handlers.

     The normal return value from `close' is 0; a value of -1 is
     returned in case of failure.  The following `errno' error
     conditions are defined for this function:

    `EBADF'
          The FILEDES argument is not a valid file descriptor.

    `EINTR'
          The `close' call was interrupted by a signal.  See
          Interrupted Primitives.  Here is an example of how to
          handle `EINTR' properly:

               TEMP_FAILURE_RETRY (close (desc));

    `ENOSPC'
    `EIO'
    `EDQUOT'
          When the file is accessed by NFS, these errors from `write'
          can sometimes not be detected until `close'.  See I/O Primitives,
          for details on their meaning.

     Please note that there is _no_ separate `close64' function.  This
     is not necessary since this function does not determine nor depend
     on the mode of the file.  The kernel which performs the `close'
     operation knows for which mode the descriptor is used and can
     handle this situation.

   To close a stream, call `fclose' (see Closing Streams) instead
of trying to close its underlying file descriptor with `close'.  This
flushes any buffered output and updates the stream object to indicate
that it is closed.

Change the size of a file
=========================

   In some situations it is useful to explicitly determine the size of a
file.  Since the 4.2BSD days there is a function to truncate a file to
at most a given number of bytes and POSIX defines one additional
function.  The prototypes for these functions are in `unistd.h'.

 - Function: int truncate (const char *NAME, off_t LENGTH)
     The `truncation' function truncates the file named by NAME to at
     most LENGTH bytes.  I.e., if the file was larger before the extra
     bytes are stripped of.  If the file was small or equal to LENGTH
     in size before nothing is done.  The file must be writable by the
     user to perform this operation.

     When the source file is compiled with `_FILE_OFFSET_BITS == 64' the
     `truncate' function is in fact `truncate64' and the type `off_t'
     has 64 bits which makes it possible to handle files up to 2^63
     bytes in length.

     The return value is zero is everything went ok.  Otherwise the
     return value is -1 and the global variable ERRNO is set to:
    `EACCES'
          The file is not accessible to the user.

    `EINVAL'
          The LENGTH value is illegal.

    `EISDIR'
          The object named by NAME is a directory.

    `ENOENT'
          The file named by NAME does not exist.

    `ENOTDIR'
          One part of the NAME is not a directory.

     This function was introduced in 4.2BSD but also was available in
     later System V systems.  It is not added to POSIX since the
     authors felt it is only of marginally additional utility.  See
     below.

 - Function: int truncate64 (const char *NAME, off64_t LENGTH)
     This function is similar to the `truncate' function.  The
     difference is that the LENGTH argument is 64 bits wide even on 32
     bits machines which allows to handle file with a size up to 2^63
     bytes.

     When the source file is compiled with `_FILE_OFFSET_BITS == 64' on
     a 32 bits machine this function is actually available under the
     name `truncate' and so transparently replaces the 32 bits
     interface.

 - Function: int ftruncate (int FD, off_t LENGTH)
     The `ftruncate' function is similar to the `truncate' function.
     The main difference is that it takes a descriptor for an opened
     file instead of a file name to identify the object.  The file must
     be opened for writing to successfully carry out the operation.

     The POSIX standard leaves it implementation defined what happens
     if the specified new LENGTH of the file is bigger than the
     original size.  The `ftruncate' function might simply leave the
     file alone and do nothing or it can increase the size to the
     desired size.  In this later case the extended area should be
     zero-filled.  So using `ftruncate' is no reliable way to increase
     the file size but if it is possible it is probably the fastest
     way.  The function also operates on POSIX shared memory segments
     if these are implemented by the system.

     When the source file is compiled with `_FILE_OFFSET_BITS == 64' the
     `ftruncate' function is in fact `ftruncate64' and the type `off_t'
     has 64 bits which makes it possible to handle files up to 2^63
     bytes in length.

     On success the function returns zero.  Otherwise it returns -1 and
     set ERRNO to one of these values:
    `EBADF'
          FD is no valid file descriptor or is not opened for writing.

    `EINVAL'
          The object referred to by FD does not permit this operation.

    `EROFS'
          The file is on a read-only file system.

 - Function: int ftruncate64 (int ID, off64_t LENGTH)
     This function is similar to the `ftruncate' function.  The
     difference is that the LENGTH argument is 64 bits wide even on 32
     bits machines which allows to handle file with a size up to 2^63
     bytes.

     When the source file is compiled with `_FILE_OFFSET_BITS == 64' on
     a 32 bits machine this function is actually available under the
     name `ftruncate' and so transparently replaces the 32 bits
     interface.