This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Revised fmemopen(3) man page


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)
> 
> 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]