fopen(3)

๐Ÿ‘‘ fopen(3) โ€” stream open functions ๐Ÿ’…

okay bestie, pull up a chair, grab a boba, because we're about to talk about the three functions that open streams and honestly they're the backbone of like, everything you've ever done with files in C. this page lives in the Library Functions Manual, section 3, and it's all about fopen, fdopen, and freopen. no cap. ๐Ÿฆ‹


โœจ NAME โœจ

fopen, fdopen, freopen โ€” stream open functions. that's the whole vibe. three lil doors into the same room. ๐Ÿšชโœจ


๐ŸŒธ LIBRARY ๐ŸŒธ

Standard C library (libc, -lc). yeah she's built in, she's everywhere, she's the moment. ๐Ÿ’–


๐ŸŽ€ SYNOPSIS ๐ŸŽ€

#include <stdio.h>

FILE *fopen(const char *restrict path, const char *restrict mode);
FILE *fdopen(int fd, const char *mode);
FILE *freopen(const char *restrict path, const char *restrict mode,
              FILE *restrict stream);

๐Ÿงš Feature Test Macro Requirements for glibc (see feature_test_macros(7)) ๐Ÿงš

  • fdopen(): _POSIX_C_SOURCE
yes bestie, you have to ask for fdopen() by defining that macro. she doesn't just show up. she's exclusive like that. ๐Ÿ™ˆ

๐Ÿ’… DESCRIPTION ๐Ÿ’…

so. fopen() opens the file whose name is the string pointed to by path, and associates a stream with it. that's it, that's the whole gig. file in, stream out. ๐Ÿซถ

the mode argument points to a string that starts with one of these sequences (and yeah, there can be extra characters after it, we get to that):

  • r โ€” open a text file for reading. the stream gets positioned at the beginning of the file.
  • r+ โ€” open for reading and writing. stream starts at the beginning of the file.
  • w โ€” truncate the file to zero length, or create a text file for writing. stream sits at the beginning of the file.
  • w+ โ€” open for reading and writing. if the file doesn't exist it gets created; if it does exist, it gets truncated. stream is at the beginning of the file.
  • a โ€” open for appending (writing at the end of the file). file gets created if it doesn't exist. stream is positioned at the end of the file.
  • a+ โ€” open for reading and appending (writing at end of file). file is created if it doesn't exist. output is always appended to the end of the file. now here's the tea: POSIX is silent on what the initial read position is with this mode. on glibc, the initial file position for reading is at the beginning of the file. but on Android/BSD/MacOS, it's at the end of the file. so like, portability check, bestie. ๐ŸŒˆ

the mode string can also include the letter 'b' โ€” either as the last character, or sandwiched between the characters of any of those two-character strings above. and listen: this is strictly for compatibility with ISO C and it has no effect. the 'b' is ignored on all POSIX-conforming systems, including Linux. (other systems may treat text files and binary files differently, and adding the 'b' may be a good idea if you do I/O to a binary file and you expect your program might get ported to non-UNIX environments. so like, harmless, sometimes helpful, mostly just vibes.) ๐Ÿ’€

see NOTES down below for the details of the glibc extensions for mode.

any file that gets created will have the mode S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH (0666), as modified by the process's umask value (see umask(2)). iconic permission behavior, truly.

reads and writes may be intermixed on read/write streams in any order. but โ€” and this is the important part โ€” ANSI C requires that a file positioning function intervene between output and input, unless an input operation hits end-of-file. (if that condition isn't met, then a read is allowed to return the result of writes other than the most recent one. messy.) so it is good practice โ€” and indeed sometimes necessary under Linux โ€” to put an fseek(3) or fsetpos(3) operation between write and read operations on such a stream. that operation may be an apparent no-op, like fseek(..., 0L, SEEK_CUR) called purely for its synchronizing side effect. yes bestie, a no-op with a job. main character energy. ๐Ÿ‘‘

opening a file in append mode (a as the first character of mode) causes all subsequent write operations to this stream to happen at end-of-file, as if preceded by this call:

fseek(stream, 0, SEEK_END);

the file descriptor associated with the stream is opened as if by a call to open(2) with these flags:

  • mode r โ†’ O_RDONLY
  • mode w โ†’ O_WRONLY | O_CREAT | O_TRUNC
  • mode a โ†’ O_WRONLY | O_CREAT | O_APPEND
  • mode r+ โ†’ O_RDWR
  • mode w+ โ†’ O_RDWR | O_CREAT | O_TRUNC
  • mode a+ โ†’ O_RDWR | O_CREAT | O_APPEND

๐Ÿฆ‹ fdopen() ๐Ÿฆ‹

fdopen() associates a stream with the existing file descriptor, fd. the mode of the stream โ€” one of the values "r", "r+", "w", "w+", "a", "a+" โ€” must be compatible with the mode of the file descriptor. like, they have to match energy-wise or it's not happening. ๐Ÿ’…

the file position indicator of the new stream is set to that belonging to fd, and the error and end-of-file indicators are cleared. modes "w" or "w+" do not cause truncation of the file. the file descriptor is not dup'ed, and it will be closed when the stream created by fdopen() is closed. and heads up: the result of applying fdopen() to a shared memory object is undefined. don't do it. just don't. ๐Ÿ˜ญ

๐Ÿ“ freopen() ๐Ÿ“

freopen() opens the file whose name is the string pointed to by path and associates the stream pointed to by stream with it. the original stream (if it exists) gets closed. the mode argument is used just like in fopen().

if path is a null pointer, then freopen() changes the mode of the stream to the one specified in mode โ€” that is, freopen() reopens the pathname that is associated with the stream. the spec for this behavior got added in the C99 standard, and it says, and I quote:

In this case, the file descriptor associated with the stream need not be closed if the call to freopen() succeeds. It is implementation-defined which changes of mode are permitted (if any), and under what circumstances.

the primary use of freopen() is to change the file associated with a standard text stream โ€” stderr, stdin, or stdout. that's her whole thing, and she ate. ๐Ÿ”ฅ


โญ RETURN VALUE โญ

upon successful completion, fopen(), fdopen(), and freopen() all return a FILE pointer. and if it doesn't go well? NULL is returned, and errno is set to indicate the error. so like, check your returns bestie, please, for me. ๐Ÿฅบ


๐Ÿ’€ ERRORS ๐Ÿ’€

  • EINVAL โ€” the mode provided to fopen(), fdopen(), or freopen() was invalid. wrong string, no stream for you. ๐Ÿ™ˆ

fopen(), fdopen(), and freopen() may also fail and set errno for any of the errors specified for the routine malloc(3).

fopen() may also fail and set errno for any of the errors specified for the routine open(2).

fdopen() may also fail and set errno for any of the errors specified for the routine fcntl(2).

freopen() may also fail and set errno for any of the errors specified for the routines open(2), fclose(3), and fflush(3).


๐ŸŒˆ ATTRIBUTES ๐ŸŒˆ

for an explanation of the terms used in this section, see attributes(7).

  • interface fopen(), fdopen(), freopen() โ€” attribute: Thread safety โ€” value: MT-Safe

yes girl, all three of them, thread safe. we love a stable queen. ๐Ÿ’–


๐ŸŽ€ STANDARDS ๐ŸŽ€

  • fopen(), freopen() โ€” C11, POSIX.1-2008.
  • fdopen() โ€” POSIX.1-2008.

๐Ÿ“œ HISTORY ๐Ÿ“œ

  • fopen(), freopen() โ€” POSIX.1-2001, C89.
  • fdopen() โ€” POSIX.1-2001.

ancient. legendary. still running in everything. ๐Ÿ‘‘


๐Ÿงš NOTES ๐Ÿงš

glibc notes ๐ŸŒธ

the GNU C library allows these extra extensions for the string specified in mode:

  • c (since glibc 2.3.3) โ€” do not make the open operation, or subsequent read and write operations, thread cancelation points. this flag is ignored for fdopen().
  • e (since glibc 2.7) โ€” open the file with the O_CLOEXEC flag. see open(2) for more info. this flag is ignored for fdopen().
  • m (since glibc 2.3) โ€” attempt to access the file using mmap(2) rather than I/O system calls (read(2), write(2)). currently, use of mmap(2) is only attempted for a file opened for reading.
  • x โ€” open the file exclusively (like the O_EXCL flag of open(2)). if the file already exists, fopen() fails and sets errno to EEXIST. this flag is ignored for fdopen().

and on top of all those characters, fopen() and freopen() also support this syntax in mode:

,ccs=string

the given string is taken as the name of a coded character set, and the stream is marked as wide-oriented. after that, internal conversion functions convert I/O to and from the character set string. if the ,ccs=string syntax is not specified, then the wide-orientation of the stream is determined by the first file operation. if that first operation is a wide-character operation, the stream gets marked wide-oriented, and functions to convert to the coded character set get loaded. cute, right? ๐Ÿฆ‹


๐Ÿ˜ญ BUGS ๐Ÿ˜ญ

when parsing for individual flag characters in mode โ€” that's the characters preceding the "ccs" specification โ€” the glibc implementation of fopen() and freopen() limits the number of characters examined in mode to 7 (or, before glibc 2.14, to 6, which wasn't enough to include possible specifications such as "rb+cmxe"). and the current implementation of fdopen() parses at most 5 characters in mode.

so yeah. keep your mode strings short and sweet, bestie. she's not reading past a certain point and there's nothing you can do about it. ๐Ÿ’€

๐Ÿซถ SEE ALSO ๐Ÿซถ

open(2), fclose(3), fileno(3), fmemopen(3), fopencookie(3), open_memstream(3)


and that's the page, bestie!! โœจ this was Linux man-pages 6.20, dated 2025-09-21, and honestly? she served. go forth and open your streams responsibly. love u, bye!! ๐Ÿ’–๐ŸŽ€๐Ÿฆ‹๐ŸŒธ๐Ÿ’…๐Ÿซถโœจ

๐Ÿ“ฆ where this page comes from
  • arch rolling: man-pages 6.20-1 ยท BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
  • nixpkgs unstable: man-pages 6.20
  • ๐Ÿ“œ the page's license: BSD-4-Clause-UC
  • ๐Ÿ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms