1.\" 2.\" This file and its contents are supplied under the terms of the 3.\" Common Development and Distribution License ("CDDL"), version 1.0. 4.\" You may only use this file in accordance with the terms of version 5.\" 1.0 of the CDDL. 6.\" 7.\" A full copy of the text of the CDDL should have accompanied this 8.\" source. A copy of the CDDL is also available via the Internet at 9.\" http://www.illumos.org/license/CDDL. 10.\" 11.\" 12.\" Copyright 2020 Robert Mustacchi 13.\" 14.Dd March 25, 2020 15.Dt FMEMOPEN 3C 16.Os 17.Sh NAME 18.Nm fmemopen 19.Nd open a memory stream 20.Sh SYNOPSIS 21.In stdio.h 22.Ft "FILE *" 23.Fo fmemopen 24.Fa "void *restrict buf" 25.Fa "size_t size" 26.Fa "const char *restrict mode" 27.Fc 28.Sh DESCRIPTION 29The 30.Fn fmemopen 31function provides a means of associating a file stream with a 32corresponding memory buffer of a fixed size. 33The resulting stream can then be used just like any other stream, and 34when done should be released by calling the 35.Xr fclose 3C 36function. 37.Pp 38The stream can either dynamically allocate memory or it can use an 39existing memory buffer. 40If 41.Fa buf 42is 43.Dv NULL , 44then a buffer 45.Fa size 46bytes long will be allocated for the stream and initialized to zero. 47This buffer will be allocated as though a call to 48.Xr malloc 3C 49and will be freed when 50.Xr fclose 3C 51is called. 52When using this mode, the stream must be created for update 53.Po 54indicated by a 55.Sq + 56character in the 57.Fa mode 58argument 59.Pc . 60Otherwise, it is assumed that 61.Fa buf 62is at least 63.Fa size 64bytes long. 65.Pp 66The 67.Fa mode 68argument determines whether the stream is opened for read, write, or 69append. 70The 71.Fa mode 72argument accepts all the same values as 73.Xr fopen 3C . 74.Pp 75The resulting stream behaves in a similar way to a stream backed by a 76file. 77The stream can be read and written to. 78The stream is seekeable and can either be byte or wide-character 79oriented. 80A NUL byte has no special meaning when reading. 81.Pp 82The stream logically tracks three different values: 83.Bl -enum -offset indent 84.It 85The current position in the stream. 86.It 87The current size of the stream. 88.It 89The maximum size of the stream. 90.El 91.Pp 92The current position is where reads or writes take place. 93When the stream is opened for read or write 94.Pq r, r+, w, w+ 95then the initial position is set to zero. 96If the stream is opened for update 97.Pq a, a+ 98then the initial position is set to the first NUL byte in the buffer. 99.Pp 100The current size of the stream represents the length of the stream. 101Like a file, this starts at a specific size and then can grow over time. 102Unlike a file, where the maximum size is determined by the file system, 103the maximum size here is determined at the creation of the stream. 104.Pp 105This size is used when using 106.Dv SEEK_END 107as an argument to functions like 108.Xr fseek 3C . 109Reads cannot advance beyond the current size of the stream and 110attempting to read beyond it is considered hitting the end-of-file. 111Writes beyond the end of the current size will cause the current size to 112increase, though it cannot increase beyond the maximum size. 113.Pp 114The initial size of the stream varies. 115It is set depending on the mode and works as follows: 116.Bl -tag -width Sy -offset indent 117.It Sy r, r+ 118The size is set to the 119.Fa size 120argument. 121.It Sy w, w+ 122The initial size is set to zero. 123.It Sy a, a+ 124The initial size is set according to the following rules: 125.Bl -enum 126.It 127If 128.Fa buf 129is a 130.Dv NULL 131pointer, the current size is set to zero. 132.It 133If a NUL byte is found in the first 134.Fa size 135bytes of 136.Fa buf , 137then the current size is set to the first NUL byte. 138.It 139The position is set to the 140.Fa size 141argument 142.Pq the maximum size 143if no NUL byte was found in 144.Fa buf . 145.El 146.El 147.Pp 148The maximum size of the stream is determined by the 149.Fa size 150argument. 151Writes beyond this size are dropped. 152Attempts to seek beyond the maximum size will result in an error. 153.Pp 154If the stream was open for writing or update, when the stream is flushed 155or closed, a NUL byte will be written to terminate the stream based on 156the current position and size of the stream. 157If the stream was open for update, if the stream is flushed or closed 158and the last write changed the current buffer size, a NUL byte will be 159written if there is still space for it within the buffer. 160.Pp 161By default, all streams are buffered. 162This means that writes beyond the size of the memory buffer could fail, 163but not be seen until the stream is flushed or closed. 164To detect errors right away, one can explicitly disable buffering with 165the 166.Xr setvbuf 3C 167function or perform explicit buffer flushes with the 168.Xr fflush 3C 169function. 170.Sh RETURN VALUES 171Upon successful completion, the 172.Fn fmemopen 173function returns a pointer to a stream. 174Otherwise, 175.Dv NULL 176is returned and 177.Dv errno 178is set to indicate the error. 179.Sh ERRORS 180The 181.Fn fmemopen 182function will fail if: 183.Bl -tag -width Er 184.It Er EINVAL 185The value of 186.Fa mode 187is invalid. 188.Pp 189The 190.Fa size 191argument was zero. 192.Pp 193The 194.Fa buf 195argument is 196.Dv NULL 197and the 198.Fa mode 199argument does not contain a 200.Sq + 201character. 202.It Er EMFILE 203.Brq FOPEN_MAX 204streams are currently open in the calling process. 205.Pp 206.Brq STREAM_MAX 207streams are currently open in the calling process. 208.It Er ENOMEM 209The system was unable to allocate memory for the stream or its backing 210buffer. 211.El 212.Sh MT-LEVEL 213.Sy MT-Safe 214.Sh INTERFACE STABILITY 215.Sy Committed 216.Sh SEE ALSO 217.Xr fclose 3C , 218.Xr fflush 3C , 219.Xr fopen 3C , 220.Xr fseek 3C , 221.Xr malloc 3C , 222.Xr open_memstream 3C 223