| .\" Copyright 2005, 2012, 2016 Michael Kerrisk <mtk.manpages@gmail.com> |
| .\" |
| .\" %%%LICENSE_START(GPL_NOVERSION_ONELINE) |
| .\" Distributed under the GPL. |
| .\" %%%LICENSE_END |
| .\" |
| .TH FMEMOPEN 3 2016-03-11 "GNU" "Linux Programmer's Manual" |
| .SH NAME |
| fmemopen \- open memory as stream |
| .SH SYNOPSIS |
| .nf |
| .B #include <stdio.h> |
| |
| .BI "FILE *fmemopen(void *"buf ", size_t "size ", const char *" mode ");" |
| .fi |
| .sp |
| .in -4n |
| Feature Test Macro Requirements for glibc (see |
| .BR feature_test_macros (7)): |
| .in |
| .sp |
| .BR fmemopen (): |
| .PD 0 |
| .ad l |
| .RS 4 |
| .TP 4 |
| Since glibc 2.10: |
| _POSIX_C_SOURCE\ >=\ 200809L |
| .TP |
| Before glibc 2.10: |
| _GNU_SOURCE |
| .RE |
| .ad |
| .PD |
| .SH DESCRIPTION |
| The |
| .BR fmemopen () |
| function opens a stream that permits the access specified by |
| .IR mode . |
| The stream allows I/O to be performed on the string or memory buffer |
| pointed to by |
| .IR buf . |
| |
| The |
| .I mode |
| argument specifies the semantics of I/O on the stream, |
| and is one of the following: |
| .TP 8 |
| .I r |
| The stream is opened for reading. |
| .TP |
| .I w |
| The stream is opened for writing. |
| .TP |
| .I a |
| Append; open the stream for writing, |
| with the initial buffer position set to the first null byte. |
| .TP |
| .I r+ |
| Open the stream for reading and writing. |
| .TP |
| .I w+ |
| Open the stream for reading and writing. |
| The buffer contents are truncated |
| (i.e., \(aq\\0\(aq is placed in the first byte of the buffer). |
| .TP |
| .I a+ |
| Append; open the stream for reading and writing, |
| with the initial buffer position set to the first null byte. |
| .PP |
| The stream maintains the notion of a current position, |
| the location where the next I/O operation will be performed. |
| The current position is implicitly updated by I/O operations. |
| It can be explicitly updated using |
| .BR fseek (3), |
| and determined using |
| .BR ftell (3). |
| In all modes other than append, |
| the initial position is set to the start of the buffer. |
| In append mode, if no null byte is found within the buffer, |
| then the initial position is |
| .IR size+1 . |
| .PP |
| If |
| .I buf |
| is specified as NULL, then |
| .BR fmemopen () |
| allocates a buffer of |
| .I size |
| bytes. |
| This is useful for an application that wants to write data to |
| a temporary buffer and then read it back again. |
| The initial position is set to the start of the buffer. |
| The buffer is automatically freed when the stream is closed. |
| Note that the caller has no way to obtain a pointer to the |
| temporary buffer allocated by this call (but see |
| .BR open_memstream (3)). |
| .PP |
| If |
| .I buf |
| is not NULL, then it should point to a buffer of at least |
| .I len |
| bytes allocated by the caller. |
| .PP |
| When a stream that has been opened for writing is flushed |
| .RB ( fflush (3)) |
| or closed |
| .RB ( fclose (3)), |
| a null byte is written at the end of the buffer if there is space. |
| The caller should ensure that an extra byte is available in the |
| buffer |
| (and that |
| .I size |
| counts that byte) |
| to allow for this. |
| |
| In a stream opened for reading, |
| null bytes (\(aq\\0\(aq) in the buffer do not cause read |
| operations to return an end-of-file indication. |
| A read from the buffer will indicate end-of-file |
| only when the current buffer position advances |
| .I size |
| bytes past the start of the buffer. |
| |
| Write operations take place either at the current position |
| (for modes other than append), or at the current size of the stream |
| (for append modes). |
| |
| Attempts to write more than |
| .I size |
| bytes to the buffer result in an error. |
| By default, such errors will be visible |
| (by the absence of data) only when the |
| .I stdio |
| buffer is flushed. |
| Disabling buffering with the following call |
| may be useful to detect errors at the time of an output operation: |
| |
| setbuf(stream, NULL); |
| |
| Alternatively, the caller can explicitly set |
| .I buf |
| as the stdio stream buffer, at the same time informing stdio |
| of the buffer's size, using: |
| |
| setbuffer(stream, buf, size); |
| .\" |
| .\" See http://sourceware.org/bugzilla/show_bug.cgi?id=1995 |
| .\" and |
| .\" http://sources.redhat.com/ml/libc-alpha/2006-04/msg00064.html |
| .\" |
| .SH RETURN VALUE |
| Upon successful completion, |
| .BR fmemopen () |
| returns a |
| .I FILE |
| pointer. |
| Otherwise, NULL is returned and |
| .I errno |
| is set to indicate the error. |
| .SH VERSIONS |
| .BR fmemopen () |
| was already available in glibc 1.0.x. |
| .SH ATTRIBUTES |
| For an explanation of the terms used in this section, see |
| .BR attributes (7). |
| .TS |
| allbox; |
| lb lb lb |
| l l l. |
| Interface Attribute Value |
| T{ |
| .BR fmemopen (), |
| T} Thread safety MT-Safe |
| .TE |
| |
| .SH CONFORMING TO |
| POSIX.1-2008. |
| This function is not specified in POSIX.1-2001, |
| and is not widely available on other systems. |
| |
| POSIX.1-2008 specifies that \(aqb\(aq in |
| .IR mode |
| shall be ignored. |
| However, Technical Corrigendum 1 |
| .\" http://austingroupbugs.net/view.php?id=396 |
| adjusts the standard to allow implementation-specific treatment for this case, |
| thus permitting the glibc treatment of \(aqb\(aq. |
| .SH NOTES |
| There is no file descriptor associated with the file stream |
| returned by this function |
| (i.e., |
| .BR fileno (3) |
| will return an error if called on the returned stream). |
| |
| With version 2.22, binary mode (see below) was removed, |
| many longstanding bugs in the implementation of |
| .BR fmemopen () |
| were fixed, and a new versioned symbol was created for this interface. |
| .\" |
| .SS Binary mode |
| From version 2.9 to 2.21, the glibc implementation of |
| .BR fmemopen () |
| supported a "binary" mode, |
| enabled by specifying the letter \(aqb\(aq as the second character in |
| .IR mode . |
| In this mode, |
| writes don't implicitly add a terminating null byte, and |
| .BR fseek (3) |
| .B SEEK_END |
| is relative to the end of the buffer (i.e., the value specified by the |
| .I size |
| argument), rather than the current string length. |
| |
| An API bug afflicted the implementation of binary mode: |
| to specify binary mode, the \(aqb\(aq must be the |
| .I second |
| character in |
| .IR mode . |
| Thus, for example, "wb+" has the desired effect, but "w+b" does not. |
| This is inconsistent with the treatment of |
| .\" http://sourceware.org/bugzilla/show_bug.cgi?id=12836 |
| .IR mode |
| by |
| .BR fopen (3). |
| |
| Binary mode was removed in glibc 2.22; a \(aqb\(aq specified in |
| .I mode |
| has no effect. |
| .SH BUGS |
| In versions of glibc before 2.22, if |
| .I size |
| is specified as zero, |
| .BR fmemopen () |
| fails with the error |
| .BR EINVAL . |
| .\" http://sourceware.org/bugzilla/show_bug.cgi?id=11216 |
| It would be more consistent if this case successfully created |
| a stream that then returned end-of-file on the first attempt at reading; |
| since version 2.22, the glibc implementation provides that behavior. |
| |
| In versions of glibc before 2.22, |
| specifying append mode ("a" or "a+") for |
| .BR fmemopen () |
| sets the initial buffer position to the first null byte, but |
| .\" http://sourceware.org/bugzilla/show_bug.cgi?id=13152 |
| (if the current position is reset to a location other than |
| the end of the stream) |
| does not force subsequent writes to append at the end of the stream. |
| This bug is fixed in glibc 2.22. |
| |
| In versions of glibc before 2.22, if the |
| .I mode |
| argument to |
| .BR fmemopen () |
| specifies append ("a" or "a+"), and the |
| .I size |
| argument does not cover a null byte in |
| .IR buf , |
| then, according to POSIX.1-2008, |
| the initial buffer position should be set to |
| the next byte after the end of the buffer. |
| However, in this case the glibc |
| .\" http://sourceware.org/bugzilla/show_bug.cgi?id=13151 |
| .BR fmemopen () |
| sets the buffer position to \-1. |
| This bug is fixed in glibc 2.22. |
| |
| In versions of glibc before 2.22, |
| .\" https://sourceware.org/bugzilla/show_bug.cgi?id=14292 |
| when a call to |
| .BR fseek (3) |
| with a |
| .I whence |
| value of |
| .B SEEK_END |
| was performed on a stream created by |
| .BR fmemopen (), |
| the |
| .I offset |
| was |
| .IR subtracted |
| from the end-of-stream position, instead of being added. |
| This bug is fixed in glibc 2.22. |
| |
| The glibc 2.9 addition of "binary" mode for |
| .BR fmemopen () |
| .\" http://sourceware.org/bugzilla/show_bug.cgi?id=6544 |
| silently changed the ABI: previously, |
| .BR fmemopen () |
| ignored \(aqb\(aq in |
| .IR mode . |
| .SH EXAMPLE |
| The program below uses |
| .BR fmemopen () |
| to open an input buffer, and |
| .BR open_memstream (3) |
| to open a dynamically sized output buffer. |
| The program scans its input string (taken from the program's |
| first command-line argument) reading integers, |
| and writes the squares of these integers to the output buffer. |
| An example of the output produced by this program is the following: |
| .in +4n |
| .nf |
| |
| .RB "$" " ./a.out \(aq1 23 43\(aq" |
| size=11; ptr=1 529 1849 |
| .fi |
| .in |
| .SS Program source |
| \& |
| .nf |
| #define _GNU_SOURCE |
| #include <string.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| |
| #define handle_error(msg) \\ |
| do { perror(msg); exit(EXIT_FAILURE); } while (0) |
| |
| int |
| main(int argc, char *argv[]) |
| { |
| FILE *out, *in; |
| int v, s; |
| size_t size; |
| char *ptr; |
| |
| if (argc != 2) { |
| fprintf(stderr, "Usage: %s \(aq<num>...\(aq\\n", argv[0]); |
| exit(EXIT_FAILURE); |
| } |
| |
| in = fmemopen(argv[1], strlen(argv[1]), "r"); |
| if (in == NULL) |
| handle_error("fmemopen"); |
| |
| out = open_memstream(&ptr, &size); |
| if (out == NULL) |
| handle_error("open_memstream"); |
| |
| for (;;) { |
| s = fscanf(in, "%d", &v); |
| if (s <= 0) |
| break; |
| |
| s = fprintf(out, "%d ", v * v); |
| if (s == \-1) |
| handle_error("fprintf"); |
| } |
| |
| fclose(in); |
| fclose(out); |
| |
| printf("size=%zu; ptr=%s\\n", size, ptr); |
| |
| free(ptr); |
| exit(EXIT_SUCCESS); |
| } |
| .fi |
| .SH SEE ALSO |
| .BR fopen (3), |
| .BR fopencookie (3), |
| .BR open_memstream (3) |