.TH MPU_FOPEN 3 "August 2026" "libmpuio" "LIBMPUIO Programmer's Manual" .SH NAME mpu_fopen, mpu_fdopen, mpu_fclose, mpu_fflush, mpu_flushlbf, mpu_fileno \- open, attach, close and synchronize LIBMPUIO streams .SH SYNOPSIS .nf #include mpu_FILE *mpu_fopen( const char *filename, const char *mode ); mpu_FILE *mpu_fdopen( int fd, const char *mode ); int mpu_fclose( mpu_FILE *stream ); int mpu_fflush( mpu_FILE *stream ); void mpu_flushlbf( void ); int mpu_fileno( mpu_FILE *stream ); .fi .SH DESCRIPTION .B mpu_fopen opens the UTF-8 pathname named by .I filename using the ISO C stdio mode grammar. The first character is exactly one of .B r (read an existing file), .B w (create or truncate for writing), or .B a (create if necessary and append every write). At most one .B + (update: both reading and writing) and at most one .B b (binary spelling) may follow, in either order. Thus r, rb, r+, rb+, r+b and the corresponding w and a forms are accepted. Since LIBMPUIO raw byte I/O and UTF-8 text conversion are explicit operations, b does not alter the underlying POSIX descriptor semantics. Unknown, duplicated, or misplaced mode characters are rejected with EINVAL. .B mpu_fdopen attaches an existing POSIX descriptor. The requested read/write access must be compatible with the descriptor access mode. Append mode enables O_APPEND when necessary. After successful attachment the descriptor belongs to the stream and is closed by .BR mpu_fclose . .PP .B mpu_fflush synchronizes a stream. With a null argument it flushes all currently linked streams that are actively writing. This includes descriptor and cookie output/update streams and publishes an actively writing .BR mpu_open_memstream (3) stream. .PP .B mpu_flushlbf is the LIBMPUIO counterpart of the glibc _flushlbf() extension. It visits the current global stream list and synchronizes only streams that are both actively writing and configured for line buffering with MPU_IOLBF. Fully buffered and unbuffered streams are not selected merely because they are writable. Failures do not stop traversal of later line-buffered streams. Because the interface has no return value, errno from the first failed synchronization is retained; when every selected synchronization succeeds, the caller's incoming errno value is preserved. .B mpu_fileno returns the POSIX descriptor of a real-file stream. The ordinary form holds the stream mutex while reading descriptor state; mpu_fileno_unlocked() omits that lock. .SH RETURN VALUE Open functions return a stream pointer or NULL. Close/flush return zero on success and .B mpu_EOF on failure. mpu_flushlbf has no return value. mpu_fileno returns a descriptor or -1. .PP If pending buffered output cannot be written while mpu_fclose() is closing a stream, mpu_fclose() still closes and releases the stream but returns .B mpu_EOF and preserves the errno value from the flush failure. .SH ERRORS Failures set .B errno as appropriate. EINVAL is used for invalid modes and incompatible operations; EBADF is used for invalid descriptors and non-file streams where applicable. .SH LOCKING AND THREADING The ordinary functions in this family are synchronized. Successful .BR mpu_fdopen () transfers descriptor ownership to the stream; after that point the application must not independently close the descriptor while the stream is live. .PP .BR mpu_fclose () is a lifetime operation. Application code must synchronize it against any other direct use of the same stream pointer. Internally, close and .B mpu_fflush(NULL) use the global-list-before-stream lock order so an all-stream traversal cannot observe a half-destroyed stream. mpu_flushlbf() uses the same lock order. .SH LOCKED AND UNLOCKED FORMS .BR mpu_fflush_unlocked () and .BR mpu_fileno_unlocked () omit the stream mutex. They are suitable only under an explicit .BR mpu_flockfile (3) or equivalent external synchronization. There is no unlocked fopen, fdopen, or fclose operation. .PP Unlike .BR mpu_fflush (), the unlocked flush requires a non-NULL stream and never means "flush all streams". .SH NOTES Mode strings are deliberately strict: the first character is r, w, or a, followed by at most one + and at most one b in either order. Unknown, repeated, or misplaced mode characters are rejected with EINVAL. .SH SEE ALSO .BR libmpuio (3), .BR mpu_freopen (3), .BR mpu_tmpfile (3), .BR mpu_fmemopen (3), .BR mpu_fseek (3), .BR mpu_setvbuf (3), .BR mpu_fpurge (3) .SH ALL-STREAM FLUSH ERRORS .B mpu_fflush(NULL) attempts to synchronize every linked stream that currently has pending output. A failure on one stream does not prevent later streams from being visited. If one or more streams fail, the function returns .B mpu_EOF and restores .B errno from the first failed stream. .SH CONCURRENT ALL-STREAM FLUSH AND CLOSE The global stream list is serialized with a dedicated internal mutex. Its lock order is defined before an individual stream lock. mpu_fclose() removes the stream from the global list while holding both locks and only then begins the close operation. Therefore a concurrent mpu_fflush(NULL) sees either the fully live stream or no stream at all; it does not traverse a half-closed stream and cannot race the stream object's destruction. .PP This lifetime guarantee applies to the library's global-list operations. It does not make arbitrary concurrent use of the same mpu_FILE pointer after or during mpu_fclose() valid; applications must still synchronize ownership of a stream being explicitly closed. .SH LINE-BUFFERED ALL-STREAM FLUSH .B mpu_flushlbf() uses the same global stream-list lifetime discipline as mpu_fflush(NULL), but selects only streams whose state is both WRITING and MPU_IOLBF. It is useful when an application needs to publish pending line-buffered text without forcing unrelated fully buffered output to the underlying backend. The operation is backend-independent and therefore also applies to line-buffered cookie streams.