This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: Revised fmemopen(3) man page
- From: Adhemerval Zanella <adhemerval dot zanella at linaro dot org>
- To: "Michael Kerrisk (man-pages)" <mtk dot manpages at gmail dot com>, Paul Pluzhnikov <ppluzhnikov at google dot com>
- Cc: linux-man <linux-man at vger dot kernel dot org>, libc-alpha <libc-alpha at sourceware dot org>
- Date: Fri, 11 Mar 2016 11:15:13 +0700
- Subject: Re: Revised fmemopen(3) man page
- Authentication-results: sourceware.org; auth=none
- References: <56DFA46F dot 1050509 at gmail dot com>
I am not the most qualified person to correct syntactic issues or
grammar, but regarding the contents it covers current functionalities
and previous bugs as I would expect, thanks!
On 09-03-2016 11:19, Michael Kerrisk (man-pages) wrote:
> Hello Adhemerval
>
> Since you recently did a reimplementation of fmemopen() (which
> Paul reminded me of) I've similarly just now done a major rework
> of the man page. Might you (or Paul, feel free to also chin in!),
> be willing to take a look at the text below and let me know if
> anything needs fixing?
>
> Thanks,
>
> Michael
>
> NAME
> fmemopen - open memory as stream
>
> SYNOPSIS
> #include <stdio.h>
>
> FILE *fmemopen(void *buf, size_t size, const char *mode);
>
> Feature Test Macro Requirements for glibc (see feaâ
> ture_test_macros(7)):
>
> fmemopen():
> Since glibc 2.10:
> _POSIX_C_SOURCE >= 200809L
> Before glibc 2.10:
> _GNU_SOURCE
>
> DESCRIPTION
> The fmemopen() function opens a stream that permits the access
> specified by mode. The stream allows I/O to be performed on
> the string or memory buffer pointed to by buf.
>
> The mode argument specifies the semantics of I/O on the stream,
> and is one of the following:
>
> r The stream is opened for reading.
>
> w The stream is opened for writing.
>
> a Append; open the stream for writing, with the file iniâ
> tial position set to the first null byte.
>
> r+ Open the stream for reading and writing.
>
> w+ Open the stream for reading and writing. The buffer
> contents are truncated (i.e., '\0' is placed in the
> first byte of the buffer).
>
> a+ Append; open the stream for reading and writing, with
> the file initial position set to the first null byte.
>
> 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 fseek(3), and determined using
> 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
> size+1.
>
> If buf is specified as NULL, then fmemopen() allocates a buffer
> of 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 open_memstream(3)).
>
> If buf is not NULL, then it should point to a buffer of at
> least len bytes allocated by the caller.
>
> When a stream that has been opened for writing is flushed
> (fflush(3)) or closed (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
> size counts that byte) to allow for this.
>
> In a stream opened for reading, null bytes ('\0') in the buffer
> do not cause read operations to return an end-of-file indicaâ
> tion. A read from the buffer will indicate end-of-file only
> when the file current position advances 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 size bytes to the buffer result in
> an error. By default, such errors will be visible (by the
> absence of data) only when the stdio buffer is flushed. Disâ
> abling 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 buf as the stdio
> stream buffer, at the same time informing stdio of the buffer's
> size, using:
>
> setbuffer(stream, buf, size);
>
> RETURN VALUE
> Upon successful completion, fmemopen() returns a FILE pointer.
> Otherwise, NULL is returned and errno is set to indicate the
> error.
>
> VERSIONS
> fmemopen() was already available in glibc 1.0.x.
>
> ATTRIBUTES
> For an explanation of the terms used in this section, see
> attributes(7).
>
> ââââââââââââââââââââââââââââââââââââââââ
> âInterface â Attribute â Value â
> ââââââââââââââââââââââââââââââââââââââââ
> âfmemopen(), â Thread safety â MT-Safe â
> ââââââââââââââââââââââââââââââââââââââââ
>
> 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 'b' in mode shall be ignored. Howâ
> ever, Technical Corrigendum 1 adjusts the standard to allow
> implementation-specific treatment for this case, thus permitâ
> ting the glibc treatment of 'b'.
>
> NOTES
> There is no file descriptor associated with the file stream
> returned by this function (i.e., 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 fmemopen() were
> fixed, and a new versioned symbol was created for this interâ
> face.
>
> Binary mode
> From version 2.9 to 2.21, the glibc implementation of fmemoâ
> pen() supported a "binary" mode, enabled by specifying the letâ
> ter 'b' as the second character in mode. In this mode, writes
> don't implicitly add a terminating null byte, and fseek(3)
> SEEK_END is relative to the end of the buffer (i.e., the value
> specified by the size argument), rather than the current string
> length.
>
> An API bug afflicted the implementation of binary mode: to
> specify binary mode, the 'b' must be the second character in
> mode. Thus, for example, "wb+" has the desired effect, but
> "w+b" does not. This is inconsistent with the treatment of
> mode by fopen(3).
>
> Binary mode was removed in glibc 2.22; a 'b' specified in mode
> has no effect.
>
> BUGS
> In versions of glibc before 2.22, if size is specified as zero,
> fmemopen() fails with the error EINVAL. It would be more conâ
> sistent 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 fmemopen() sets the initial buffer position to the
> first null byte, but (if the file offset 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 mode argument to fmemâ
> open() specifies append ("a" or "a+"), and the size argument
> does not cover a null byte in 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 fmemopen() sets the buffer position to -1. This bug
> is fixed in glibc 2.22.
>
> In versions of glibc before 2.22, when a call to fseek(3) with
> a whence value of SEEK_END was performed on a stream created by
> fmemopen(), the offset was 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 fmemopen() silently
> changed the ABI: previously, fmemopen() ignored 'b' in mode.
>
> EXAMPLE
> The program below uses fmemopen() to open an input buffer, and
> 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:
>
> $ ./a.out '1 23 43'
> size=11; ptr=1 529 1849
>
> Program source
>
> #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 '<num>...'\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);
> }
>
> SEE ALSO
> fopen(3), fopencookie(3), open_memstream(3)
>
>