Standard I/O Streams
A stream is associated with an external file (which may be a physical device) by opening a file, which may involve creating a new file. Creating an existing file causes its former contents to be discarded if necessary. If a file can support positioning requests, (such as a disk file, as opposed to a terminal), then a file position indicator associated with the stream is positioned at the start (byte number 0) of the file, unless the file is opened with append mode, in which case it is implementation-dependent whether the file position indicator is initially positioned at the beginning or end of the file. The file position indicator is maintained by subsequent reads, writes and positioning requests, to facilitate an orderly progression through the file. All input takes place as if bytes were read by successive calls to fgetc(); all output takes place as if bytes were written by successive calls to fputc().
When a stream is unbuffered, bytes are intended to appear from the source or at the destination as soon as possible. Otherwise bytes may be accumulated and transmitted as a block. When a stream is fully buffered, bytes are intended to be transmitted as a block when a buffer is filled. When a stream is line buffered, bytes are intended to be transmitted as a block when a newline byte is encountered. Furthermore, bytes are intended to be transmitted as a block when a buffer is filled, when input is requested on an unbuffered stream, or when input is requested on a line-buffered stream that requires the transmission of bytes. Support for these characteristics is implementation-dependent, and may be affected via setbuf() and setvbuf().
A file may be disassociated from a controlling stream by closing the file. Output streams are flushed (any unwritten buffer contents are transmitted) before the stream is disassociated from the file. The value of a pointer to a FILE object is indeterminate after the associated file is closed (including the standard streams).
A file may be subsequently reopened, by the same or another program execution, and its contents reclaimed or modified (if it can be repositioned at its start). If the main() function returns to its original caller, or if the exit() function is called, all open files are closed (hence all output streams are flushed) before program termination. Other paths to program termination, such as calling abort(), need not close all files properly.
The address of the FILE object used to control a stream may be significant; a copy of a FILE object need not necessarily serve in place of the original.
At program startup, three streams are predefined and need not be opened explicitly: standard input (for reading conventional input), standard output (for writing conventional output), and standard error (for writing diagnostic output). When opened, the standard error stream is not fully buffered; the standard input and standard output streams are fully buffered if and only if the stream can be determined not to refer to an interactive device.
Interaction of File Descriptors and Standard I/O Streams
An open file description may be accessed through a file descriptor, which is created using functions such as open() or pipe(), or through a stream, which is created using functions such as fopen() or popen(). Either a file descriptor or a stream will be called a handle on the open file description to which it refers; an open file description may have several handles.
Handles can be created or destroyed by explicit user action, without affecting the underlying open file description. Some of the ways to create them include fcntl(), dup(), fdopen(), fileno() and fork(). They can be destroyed by at least fclose(), close() and the exec functions.
A file descriptor that is never used in an operation that could affect the file offset (for example, read(), write() or lseek()) is not considered a handle for this discussion, but could give rise to one (for example, as a consequence of fdopen(), dup() or fork()). This exception does not include the file descriptor underlying a stream, whether created with fopen() or fdopen(), so long as it is not used directly by the application to affect the file offset. The read() and write() functions implicitly affect the file offset; lseek() explicitly affects it.
The result of function calls involving any one handle (the active handle) are defined elsewhere in this specification, but if two or more handles are used, and any one of them is a stream, their actions must be coordinated as described below. If this is not done, the result is undefined.
A handle which is a stream is considered to be closed when either an fclose() or freopen() is executed on it (the result of freopen() is a new stream, which cannot be a handle on the same open file description as its previous value), or when the process owning that stream terminates with exit() or abort(). A file descriptor is closed by close(), _exit() or the exec functions when FD_CLOEXEC is set on that file descriptor.
For a handle to become the active handle, the actions below must be performed between the last use of the handle (the current active handle) and the first use of the second handle (the future active handle). The second handle then becomes the active handle. All activity by the application affecting the file offset on the first handle must be suspended until it again becomes the active file handle. (If a stream function has as an underlying function one that affects the file offset, the stream function will be considered to affect the file offset.)
The handles need not be in the same process for these rules to apply.
Note that after a fork(), two handles exist where one existed before. The application must assure that, if both handles will ever be accessed, that they will both be in a state where the other could become the active handle first. The application must prepare for a fork() exactly as if it were a change of active handle. (If the only action performed by one of the processes is one of the exec functions or _exit() (not exit()), the handle is never accessed in that process.)
For the first handle, the first applicable condition below applies. After the actions required below are taken, if the handle is still open, the application can close it.
- If it is a file descriptor, no action is required.
- If the only further action to be performed on any handle to this open file descriptor is to close it, no action need be taken.
- If it is a stream which is unbuffered, no action need be taken.
- If it is a stream which is line buffered, and the last byte written to the stream was a newline (that is, as if a:putc('\n')was the most recent operation on that stream), no action need be taken.
- If it is a stream which is open for writing or appending (but not also open for reading), either an fflush() must be done, or the stream must be closed.
- If the stream is open for reading and it is at the end of the file (.Fn feof is true), no action need be taken.
- If the stream is open with a mode that allows reading and the underlying open file description refers to a device that is capable of seeking, either an fflush() must occur or the stream must be closed.
Otherwise, the result is undefined.
For the second handle:
- If any previous active handle has been used by a function that explicitly changed the file offset, except as required above for the first handle, the application must perform an lseek() or fseek() (as appropriate to the type of handle) to an appropriate location.
If the active handle ceases to be accessible before the requirements on the first handle, above, have been met, the state of the open file description becomes undefined. This might occur during functions such as a fork() or _exit().
The exec functions make inaccessible all streams that are open at the time they are called, independent of which streams or file descriptors may be available to the new process image.
When these rules are followed, regardless of the sequence of handles used, implementations will ensure that an application, even one consisting of several processes, will yield correct results: no data will be lost or duplicated when writing, and all data will be written in order, except as requested by seeks. It is implementation-dependent whether, and under what conditions, all input is seen exactly once.
If the rules above are not followed, the result is unspecified.
For conformance to the Multibyte Support Extension, the definition of a stream is adjusted to include an orientation for both text and binary streams. After a stream is associated with an external file, but before any operations are performed on it, the stream is without orientation. Once a wide-character input/output function has been applied to a stream without orientation, the stream becomes wide-orientated. Similarly, once a byte input/output function has been applied to a stream without orientation, the stream becomes byte-orientated. Only a call to the freopen() function or the fwide() function can otherwise alter the orientation of a stream.
A successful call to freopen() removes any orientation. The three predefined streams standard input, standard output and standard error are unorientated at program startup.
Byte input/output functions cannot be applied to a wide-orientated stream, and wide-character input/output functions cannot be applied to a byte-orientated stream. The remaining stream operations do not affect and are not affected by a stream's orientation, except for the following additional restrictions:
- Binary wide-orientated streams have the file positioning restrictions ascribed to both text and binary streams.
- For wide-orientated streams, after a successful call to a file-positioning function that leaves the file position indicator prior to the end-of-file, a wide-character output function can overwrite a partial character; any file contents beyond the byte(s) written are henceforth undefined.
Each wide-orientated stream has an associated mbstate_t object that stores the current parse state of the stream. A successful call to fgetpos() stores a representation of the value of this mbstate_t object as part of the value of the fpos_t object. A later successful call to fsetpos() using the same stored fpos_t value restores the value of the associated mbstate_t object as well as the position within the controlled stream.
Although both text and binary wide-orientated streams are conceptually sequences of wide-characters, the external file associated with a wide-orientated stream is a sequence of (possibly multibyte) characters generalised as follows:
- Multibyte encodings within files may contain embedded null bytes (unlike multibyte encodings valid for use internal to the program).
- A file need not begin nor end in the initial shift state.
Moreover, the encodings used for characters may differ among files. Both the nature and choice of such encodings are implementation-dependent.
The wide-character input functions read characters from the stream and convert them to wide-characters as if they were read by successive calls to the fgetwc() function. Each conversion occurs as if by a call to the mbrtowc() function, with the conversion state described by the stream's own mbstate_t object.
The wide-character output functions convert wide-characters to (possibly multibyte) characters and write them to the stream as if they were written by successive calls to the fputwc() function. Each conversion occurs as if by a call to the wcrtomb() function, with the conversion state described by the stream's own mbstate_t object.
An encoding error occurs if the character sequence presented to the underlying mbrtowc() function does not form a valid (generalised) character, or if the code value passed to the underlying wcrtomb() function does not correspond to a valid (generalised) character. The wide-character input/output functions and the byte input/output functions store the value of the macro EILSEQ in errno if and only if an encoding error occurs.