mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-21 20:40:05 +00:00
libio: fmemopen rewrite to POSIX compliance
This patch added a new fmemopen version, for glibc 2.22, that aims to be POSIX complaint. It fixes some long-stading glibc fmemopen issues, such as: * it changes the way fseek with SEEK_END works on fmemopen to seek relative to buffer size instead of first '\0'. This is default mode and 'b' opening mode does not change internal behavior (bz#6544). * fix apending opening mode to use as start position either first null byte of len specified in function call (bz#13152 and #13151). * remove binary option 'b' and internal different handling (bz#12836) * fix seek/SEE_END with negative values (bz#14292). A compatibility symbol is provided to with old behavior for older symbols version (2.2.5). * include/stdio.h (fmemopen): Remove hidden prototype. (__fmemopen): Add new hidden prototype. * libio/Makefile: Add oldfmemopen object. * libio/Versions [GLIBC_2.22]: Add new fmemopen symbol. * libio/fmemopen.c (__fmemopen): Function rewrite to be POSIX compliance. * libio/oldfmemopen.c: New file: old fmemopen implementation for symbol compatibility. * stdio-common/Makefile [tests]: Add new tst-fmemopen3. * stdio-common/psiginfo.c [psiginfo]: Call __fmemopen instead of fmemopen. * stdio-common/tst-fmemopen3.c: New file: more fmemopen tests, focus on append and read mode. * sysdeps/unix/sysv/linux/aarch64/libc.abilist [GLIBC_2.22]: Add fmemopen. * sysdeps/unix/sysv/linux/alpha/libc.abilist [GLIBC_2.22]: Likewise. * sysdeps/unix/sysv/linux/arm/libc.abilist [GLIBC_2.22]: Likewise. * sysdeps/unix/sysv/linux/i386/libc.abilist [GLIBC_2.22]: Likewise. * sysdeps/unix/sysv/linux/ia64/libc.abilist [GLIBC_2.22]: Likewise. * sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist [GLIBC_2.22]: Likewise. * sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist [GLIBC_2.22]: Likewise. * sysdeps/unix/sysv/linux/microblaze/libc.abilist [GLIBC_2.22]: Likewise. * sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist [GLIBC_2.22]: Likewise. * sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist [GLIBC_2.22]: Likewise. * sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist [GLIBC_2.22]: Likewise. * sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist [GLIBC_2.22]: Likewise. * sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist [GLIBC_2.22]: Likewise. * sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist [GLIBC_2.22]: Likewise. * sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist [GLIBC_2.22]: Likewise. * sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist [GLIBC_2.22]: Likewise. * sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist [GLIBC_2.22]: Likewise. * sysdeps/unix/sysv/linux/sh/libc.abilist [GLIBC_2.22]: Likewise. * sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist [GLIBC_2.22]: Likewise. * sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist [GLIBC_2.22]: Likewise. * sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist [GLIBC_2.22]: Likewise. * sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist [GLIBC_2.22]: Likewise. * sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist [GLIBC_2.22]: Likewise. * sysdeps/unix/sysv/linux/x86_64/64/libc.abilist [GLIBC_2.22]: Likewise. * sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist [GLIBC_2.22]: Likewise. * sysdeps/unix/sysv/linux/hppa/libc.abilist [GLIBC_2.22]: Likewise. * sysdeps/unix/sysv/linux/nios2/libc.abilist [GLIBC_2.22]: Likewise.
This commit is contained in:
parent
1c1e312520
commit
fdb7d390dd
70
ChangeLog
70
ChangeLog
@ -1,3 +1,73 @@
|
|||||||
|
2015-07-08 Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
|
||||||
|
[BZ #6544]
|
||||||
|
[BZ #11216]
|
||||||
|
[BZ #12836]
|
||||||
|
[BZ #13151]
|
||||||
|
[BZ #13152]
|
||||||
|
[BZ #14292]
|
||||||
|
* include/stdio.h (fmemopen): Remove hidden prototype.
|
||||||
|
(__fmemopen): Add new hidden prototype.
|
||||||
|
* libio/Makefile: Add oldfmemopen object.
|
||||||
|
* libio/Versions [GLIBC_2.22]: Add new fmemopen symbol.
|
||||||
|
* libio/fmemopen.c (__fmemopen): Function rewrite to be POSIX
|
||||||
|
compliance.
|
||||||
|
* libio/oldfmemopen.c: New file: old fmemopen implementation for
|
||||||
|
symbol compatibility.
|
||||||
|
* stdio-common/Makefile [tests]: Add new tst-fmemopen3.
|
||||||
|
* stdio-common/psiginfo.c [psiginfo]: Call __fmemopen instead of
|
||||||
|
fmemopen.
|
||||||
|
* stdio-common/tst-fmemopen3.c: New file: more fmemopen tests, focus
|
||||||
|
on append and read mode.
|
||||||
|
* sysdeps/unix/sysv/linux/aarch64/libc.abilist [GLIBC_2.22]: Add
|
||||||
|
fmemopen.
|
||||||
|
* sysdeps/unix/sysv/linux/alpha/libc.abilist [GLIBC_2.22]: Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/arm/libc.abilist [GLIBC_2.22]: Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/i386/libc.abilist [GLIBC_2.22]: Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/ia64/libc.abilist [GLIBC_2.22]:
|
||||||
|
Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
|
||||||
|
[GLIBC_2.22]: Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist [GLIBC_2.22]:
|
||||||
|
Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/microblaze/libc.abilist [GLIBC_2.22]:
|
||||||
|
Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
|
||||||
|
[GLIBC_2.22]: Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
|
||||||
|
[GLIBC_2.22]: Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
|
||||||
|
[GLIBC_2.22]: Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
|
||||||
|
[GLIBC_2.22]: Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
|
||||||
|
[GLIBC_2.22]: Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
|
||||||
|
[GLIBC_2.22]: Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
|
||||||
|
[GLIBC_2.22]: Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist [GLIBC_2.22]:
|
||||||
|
Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist [GLIBC_2.22]:
|
||||||
|
Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/sh/libc.abilist [GLIBC_2.22]: Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
|
||||||
|
[GLIBC_2.22]: Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
|
||||||
|
[GLIBC_2.22]: Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
|
||||||
|
[GLIBC_2.22]: Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
|
||||||
|
[GLIBC_2.22]: Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist [GLIBC_2.22]:
|
||||||
|
Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist [GLIBC_2.22]:
|
||||||
|
Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist [GLIBC_2.22]:
|
||||||
|
Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/hppa/libc.abilist [GLIBC_2.22]: Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/nios2/libc.abilist [GLIBC_2.22]: Likewise.
|
||||||
|
|
||||||
2015-07-08 Carlos O'Donell <carlos@redhat.com>
|
2015-07-08 Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
[BZ #18643]
|
[BZ #18643]
|
||||||
|
42
NEWS
42
NEWS
@ -9,24 +9,25 @@ Version 2.22
|
|||||||
|
|
||||||
* The following bugs are resolved with this release:
|
* The following bugs are resolved with this release:
|
||||||
|
|
||||||
438, 4719, 6792, 13028, 13064, 14094, 14841, 14906, 14958, 15319,
|
438, 4719, 6544, 6792, 11216, 12836, 13028, 13064, 13151, 13152, 14094,
|
||||||
15467, 15790, 15969, 16159, 16339, 16350, 16351, 16352, 16353, 16361,
|
14292, 14841, 14906, 14958, 15319, 15467, 15790, 15969, 16159, 16339,
|
||||||
16512, 16526, 16538, 16559, 16560, 16704, 16783, 16850, 17053, 17090,
|
16350, 16351, 16352, 16353, 16361, 16512, 16526, 16538, 16559, 16560,
|
||||||
17195, 17269, 17293, 17322, 17403, 17523, 17542, 17569, 17581, 17588,
|
16704, 16783, 16850, 17053, 17090, 17195, 17269, 17293, 17322, 17403,
|
||||||
17596, 17620, 17621, 17628, 17631, 17692, 17711, 17715, 17776, 17779,
|
17523, 17542, 17569, 17581, 17588, 17596, 17620, 17621, 17628, 17631,
|
||||||
17792, 17833, 17836, 17841, 17912, 17916, 17930, 17932, 17944, 17949,
|
17692, 17711, 17715, 17776, 17779, 17792, 17833, 17836, 17841, 17912,
|
||||||
17964, 17965, 17967, 17969, 17977, 17978, 17987, 17991, 17996, 17998,
|
17916, 17930, 17932, 17944, 17949, 17964, 17965, 17967, 17969, 17977,
|
||||||
17999, 18007, 18019, 18020, 18029, 18030, 18032, 18034, 18036, 18038,
|
17978, 17987, 17991, 17996, 17998, 17999, 18007, 18019, 18020, 18029,
|
||||||
18039, 18042, 18043, 18046, 18047, 18049, 18068, 18080, 18093, 18100,
|
18030, 18032, 18034, 18036, 18038, 18039, 18042, 18043, 18046, 18047,
|
||||||
18104, 18110, 18111, 18116, 18125, 18128, 18138, 18185, 18196, 18197,
|
18049, 18068, 18080, 18093, 18100, 18104, 18110, 18111, 18116, 18125,
|
||||||
18206, 18210, 18211, 18217, 18219, 18220, 18221, 18234, 18244, 18245,
|
18128, 18138, 18185, 18196, 18197, 18206, 18210, 18211, 18217, 18219,
|
||||||
18247, 18287, 18319, 18324, 18333, 18346, 18371, 18397, 18409, 18410,
|
18220, 18221, 18234, 18244, 18245, 18247, 18287, 18319, 18324, 18333,
|
||||||
18412, 18418, 18422, 18434, 18435, 18444, 18468, 18469, 18470, 18479,
|
18346, 18371, 18397, 18409, 18410, 18412, 18418, 18422, 18434, 18435,
|
||||||
18483, 18495, 18496, 18497, 18498, 18502, 18507, 18508, 18512, 18513,
|
18444, 18468, 18469, 18470, 18479, 18483, 18495, 18496, 18497, 18498,
|
||||||
18519, 18520, 18522, 18527, 18528, 18529, 18530, 18532, 18533, 18534,
|
18502, 18507, 18508, 18512, 18513, 18519, 18520, 18522, 18527, 18528,
|
||||||
18536, 18539, 18540, 18542, 18544, 18545, 18546, 18547, 18549, 18553,
|
18529, 18530, 18532, 18533, 18534, 18536, 18539, 18540, 18542, 18544,
|
||||||
18557, 18558, 18569, 18583, 18585, 18586, 18592, 18593, 18594, 18602,
|
18545, 18546, 18547, 18549, 18553, 18557, 18558, 18569, 18583, 18585,
|
||||||
18612, 18613, 18619, 18633, 18641, 18643.
|
18586, 18592, 18593, 18594, 18602, 18612, 18613, 18619, 18633, 18641.
|
||||||
|
18643.
|
||||||
|
|
||||||
* Cache information can be queried via sysconf() function on s390 e.g. with
|
* Cache information can be queried via sysconf() function on s390 e.g. with
|
||||||
_SC_LEVEL1_ICACHE_SIZE as argument.
|
_SC_LEVEL1_ICACHE_SIZE as argument.
|
||||||
@ -65,6 +66,11 @@ Version 2.22
|
|||||||
Shared library libmvec.so is linked in as needed when using -lm (no need to
|
Shared library libmvec.so is linked in as needed when using -lm (no need to
|
||||||
specify -lmvec explicitly for not static builds).
|
specify -lmvec explicitly for not static builds).
|
||||||
Visit <https://sourceware.org/glibc/wiki/libmvec> for detailed information.
|
Visit <https://sourceware.org/glibc/wiki/libmvec> for detailed information.
|
||||||
|
|
||||||
|
* A new fmemopen implementation has been added with the goal of POSIX
|
||||||
|
compliance. The new implementation fixes the following long-standing
|
||||||
|
issues: BZ#6544, BZ#11216, BZ#12836, BZ#13151, BZ#13152, and BZ#14292. The
|
||||||
|
old implementation is still present for use be by existing binaries.
|
||||||
|
|
||||||
Version 2.21
|
Version 2.21
|
||||||
|
|
||||||
|
@ -197,6 +197,9 @@ gets (char *__str)
|
|||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
extern FILE * __fmemopen (void *buf, size_t len, const char *mode);
|
||||||
|
libc_hidden_proto (__fmemopen)
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ routines := \
|
|||||||
__fbufsize __freading __fwriting __freadable __fwritable __flbf \
|
__fbufsize __freading __fwriting __freadable __fwritable __flbf \
|
||||||
__fpurge __fpending __fsetlocking \
|
__fpurge __fpending __fsetlocking \
|
||||||
\
|
\
|
||||||
libc_fatal fmemopen
|
libc_fatal fmemopen oldfmemopen
|
||||||
|
|
||||||
tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \
|
tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \
|
||||||
tst_wprintf2 tst-widetext test-fmemopen tst-ext tst-ext2 \
|
tst_wprintf2 tst-widetext test-fmemopen tst-ext tst-ext2 \
|
||||||
|
@ -148,6 +148,10 @@ libc {
|
|||||||
GLIBC_2.4 {
|
GLIBC_2.4 {
|
||||||
open_wmemstream;
|
open_wmemstream;
|
||||||
}
|
}
|
||||||
|
GLIBC_2.22 {
|
||||||
|
# f*
|
||||||
|
fmemopen;
|
||||||
|
}
|
||||||
GLIBC_PRIVATE {
|
GLIBC_PRIVATE {
|
||||||
# Used by NPTL and librt
|
# Used by NPTL and librt
|
||||||
__libc_fatal;
|
__libc_fatal;
|
||||||
|
140
libio/fmemopen.c
140
libio/fmemopen.c
@ -1,7 +1,6 @@
|
|||||||
/* Fmemopen implementation.
|
/* fmemopen implementation.
|
||||||
Copyright (C) 2000-2015 Free Software Foundation, Inc.
|
Copyright (C) 2015 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
Contributed by Hanno Mueller, kontakt@hanno.de, 2000.
|
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Lesser General Public
|
modify it under the terms of the GNU Lesser General Public
|
||||||
@ -17,54 +16,10 @@
|
|||||||
License along with the GNU C Library; if not, see
|
License along with the GNU C Library; if not, see
|
||||||
<http://www.gnu.org/licenses/>. */
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
/*
|
/* fmemopen() from 2.22 and forward works as defined by POSIX. It also
|
||||||
* fmemopen() - "my" version of a string stream
|
provides an older symbol, version 2.2.5, that behaves different regarding
|
||||||
* Hanno Mueller, kontakt@hanno.de
|
SEEK_END (libio/oldfmemopen.c). */
|
||||||
*
|
|
||||||
*
|
|
||||||
* I needed fmemopen() for an application that I currently work on,
|
|
||||||
* but couldn't find it in libio. The following snippet of code is an
|
|
||||||
* attempt to implement what glibc's documentation describes.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* I already see some potential problems:
|
|
||||||
*
|
|
||||||
* - I never used the "original" fmemopen(). I am sure that "my"
|
|
||||||
* fmemopen() behaves differently than the original version.
|
|
||||||
*
|
|
||||||
* - The documentation doesn't say wether a string stream allows
|
|
||||||
* seeks. I checked the old fmemopen implementation in glibc's stdio
|
|
||||||
* directory, wasn't quite able to see what is going on in that
|
|
||||||
* source, but as far as I understand there was no seek there. For
|
|
||||||
* my application, I needed fseek() and ftell(), so it's here.
|
|
||||||
*
|
|
||||||
* - "append" mode and fseek(p, SEEK_END) have two different ideas
|
|
||||||
* about the "end" of the stream.
|
|
||||||
*
|
|
||||||
* As described in the documentation, when opening the file in
|
|
||||||
* "append" mode, the position pointer will be set to the first null
|
|
||||||
* character of the string buffer (yet the buffer may already
|
|
||||||
* contain more data). For fseek(), the last byte of the buffer is
|
|
||||||
* used as the end of the stream.
|
|
||||||
*
|
|
||||||
* - It is unclear to me what the documentation tries to say when it
|
|
||||||
* explains what happens when you use fmemopen with a NULL
|
|
||||||
* buffer.
|
|
||||||
*
|
|
||||||
* Quote: "fmemopen [then] allocates an array SIZE bytes long. This
|
|
||||||
* is really only useful if you are going to write things to the
|
|
||||||
* buffer and then read them back in again."
|
|
||||||
*
|
|
||||||
* What does that mean if the original fmemopen() did not allow
|
|
||||||
* seeking? How do you read what you just wrote without seeking back
|
|
||||||
* to the beginning of the stream?
|
|
||||||
*
|
|
||||||
* - I think there should be a second version of fmemopen() that does
|
|
||||||
* not add null characters for each write. (At least in my
|
|
||||||
* application, I am not actually using strings but binary data and
|
|
||||||
* so I don't need the stream to add null characters on its own.)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <libio.h>
|
#include <libio.h>
|
||||||
@ -79,25 +34,23 @@
|
|||||||
typedef struct fmemopen_cookie_struct fmemopen_cookie_t;
|
typedef struct fmemopen_cookie_struct fmemopen_cookie_t;
|
||||||
struct fmemopen_cookie_struct
|
struct fmemopen_cookie_struct
|
||||||
{
|
{
|
||||||
char *buffer;
|
char *buffer; /* memory buffer. */
|
||||||
int mybuffer;
|
int mybuffer; /* allocated my buffer? */
|
||||||
int binmode;
|
int append; /* buffer open for append? */
|
||||||
size_t size;
|
size_t size; /* buffer length in bytes. */
|
||||||
_IO_off64_t pos;
|
_IO_off64_t pos; /* current position at the buffer. */
|
||||||
size_t maxpos;
|
size_t maxpos; /* max position in buffer. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static ssize_t
|
static ssize_t
|
||||||
fmemopen_read (void *cookie, char *b, size_t s)
|
fmemopen_read (void *cookie, char *b, size_t s)
|
||||||
{
|
{
|
||||||
fmemopen_cookie_t *c;
|
fmemopen_cookie_t *c = (fmemopen_cookie_t *) cookie;
|
||||||
|
|
||||||
c = (fmemopen_cookie_t *) cookie;
|
if (c->pos + s > c->maxpos)
|
||||||
|
|
||||||
if (c->pos + s > c->size)
|
|
||||||
{
|
{
|
||||||
if ((size_t) c->pos == c->size)
|
if ((size_t) c->pos == c->maxpos)
|
||||||
return 0;
|
return 0;
|
||||||
s = c->size - c->pos;
|
s = c->size - c->pos;
|
||||||
}
|
}
|
||||||
@ -115,29 +68,28 @@ fmemopen_read (void *cookie, char *b, size_t s)
|
|||||||
static ssize_t
|
static ssize_t
|
||||||
fmemopen_write (void *cookie, const char *b, size_t s)
|
fmemopen_write (void *cookie, const char *b, size_t s)
|
||||||
{
|
{
|
||||||
fmemopen_cookie_t *c;
|
fmemopen_cookie_t *c = (fmemopen_cookie_t *) cookie;;
|
||||||
|
_IO_off64_t pos = c->append ? c->maxpos : c->pos;
|
||||||
int addnullc;
|
int addnullc;
|
||||||
|
|
||||||
c = (fmemopen_cookie_t *) cookie;
|
addnullc = (s == 0 || b[s - 1] != '\0');
|
||||||
|
|
||||||
addnullc = c->binmode == 0 && (s == 0 || b[s - 1] != '\0');
|
if (pos + s + addnullc > c->size)
|
||||||
|
|
||||||
if (c->pos + s + addnullc > c->size)
|
|
||||||
{
|
{
|
||||||
if ((size_t) (c->pos + addnullc) >= c->size)
|
if ((size_t) (c->pos + addnullc) >= c->size)
|
||||||
{
|
{
|
||||||
__set_errno (ENOSPC);
|
__set_errno (ENOSPC);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
s = c->size - c->pos - addnullc;
|
s = c->size - pos - addnullc;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy (&(c->buffer[c->pos]), b, s);
|
memcpy (&(c->buffer[pos]), b, s);
|
||||||
|
|
||||||
c->pos += s;
|
pos += s;
|
||||||
if ((size_t) c->pos > c->maxpos)
|
if ((size_t) pos > c->maxpos)
|
||||||
{
|
{
|
||||||
c->maxpos = c->pos;
|
c->maxpos = pos;
|
||||||
if (addnullc)
|
if (addnullc)
|
||||||
c->buffer[c->maxpos] = '\0';
|
c->buffer[c->maxpos] = '\0';
|
||||||
}
|
}
|
||||||
@ -150,9 +102,7 @@ static int
|
|||||||
fmemopen_seek (void *cookie, _IO_off64_t *p, int w)
|
fmemopen_seek (void *cookie, _IO_off64_t *p, int w)
|
||||||
{
|
{
|
||||||
_IO_off64_t np;
|
_IO_off64_t np;
|
||||||
fmemopen_cookie_t *c;
|
fmemopen_cookie_t *c = (fmemopen_cookie_t *) cookie;
|
||||||
|
|
||||||
c = (fmemopen_cookie_t *) cookie;
|
|
||||||
|
|
||||||
switch (w)
|
switch (w)
|
||||||
{
|
{
|
||||||
@ -165,7 +115,7 @@ fmemopen_seek (void *cookie, _IO_off64_t *p, int w)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SEEK_END:
|
case SEEK_END:
|
||||||
np = (c->binmode ? c->size : c->maxpos) - *p;
|
np = c->maxpos + *p;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -184,9 +134,7 @@ fmemopen_seek (void *cookie, _IO_off64_t *p, int w)
|
|||||||
static int
|
static int
|
||||||
fmemopen_close (void *cookie)
|
fmemopen_close (void *cookie)
|
||||||
{
|
{
|
||||||
fmemopen_cookie_t *c;
|
fmemopen_cookie_t *c = (fmemopen_cookie_t *) cookie;
|
||||||
|
|
||||||
c = (fmemopen_cookie_t *) cookie;
|
|
||||||
|
|
||||||
if (c->mybuffer)
|
if (c->mybuffer)
|
||||||
free (c->buffer);
|
free (c->buffer);
|
||||||
@ -197,18 +145,11 @@ fmemopen_close (void *cookie)
|
|||||||
|
|
||||||
|
|
||||||
FILE *
|
FILE *
|
||||||
fmemopen (void *buf, size_t len, const char *mode)
|
__fmemopen (void *buf, size_t len, const char *mode)
|
||||||
{
|
{
|
||||||
cookie_io_functions_t iof;
|
cookie_io_functions_t iof;
|
||||||
fmemopen_cookie_t *c;
|
fmemopen_cookie_t *c;
|
||||||
|
|
||||||
if (__glibc_unlikely (len == 0))
|
|
||||||
{
|
|
||||||
einval:
|
|
||||||
__set_errno (EINVAL);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
c = (fmemopen_cookie_t *) malloc (sizeof (fmemopen_cookie_t));
|
c = (fmemopen_cookie_t *) malloc (sizeof (fmemopen_cookie_t));
|
||||||
if (c == NULL)
|
if (c == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -231,26 +172,38 @@ fmemopen (void *buf, size_t len, const char *mode)
|
|||||||
if (__glibc_unlikely ((uintptr_t) len > -(uintptr_t) buf))
|
if (__glibc_unlikely ((uintptr_t) len > -(uintptr_t) buf))
|
||||||
{
|
{
|
||||||
free (c);
|
free (c);
|
||||||
goto einval;
|
__set_errno (EINVAL);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
c->buffer = buf;
|
c->buffer = buf;
|
||||||
|
|
||||||
if (mode[0] == 'w')
|
/* POSIX states that w+ mode should truncate the buffer. */
|
||||||
|
if (mode[0] == 'w' && mode[1] == '+')
|
||||||
c->buffer[0] = '\0';
|
c->buffer[0] = '\0';
|
||||||
|
|
||||||
c->maxpos = strnlen (c->buffer, len);
|
c->maxpos = strnlen (c->buffer, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Mode | starting position (cookie::pos) | size (cookie::size)
|
||||||
|
------ |----------------------------------|-----------------------------
|
||||||
|
read | beginning of the buffer | size argument
|
||||||
|
write | beginning of the buffer | zero
|
||||||
|
append | first null or size buffer + 1 | first null or size argument
|
||||||
|
*/
|
||||||
|
|
||||||
c->size = len;
|
c->size = len;
|
||||||
|
|
||||||
if (mode[0] == 'a')
|
if (mode[0] == 'r')
|
||||||
|
c->maxpos = len;
|
||||||
|
|
||||||
|
c->append = mode[0] == 'a';
|
||||||
|
if (c->append)
|
||||||
c->pos = c->maxpos;
|
c->pos = c->maxpos;
|
||||||
else
|
else
|
||||||
c->pos = 0;
|
c->pos = 0;
|
||||||
|
|
||||||
c->binmode = mode[0] != '\0' && mode[1] == 'b';
|
|
||||||
|
|
||||||
iof.read = fmemopen_read;
|
iof.read = fmemopen_read;
|
||||||
iof.write = fmemopen_write;
|
iof.write = fmemopen_write;
|
||||||
iof.seek = fmemopen_seek;
|
iof.seek = fmemopen_seek;
|
||||||
@ -258,4 +211,5 @@ fmemopen (void *buf, size_t len, const char *mode)
|
|||||||
|
|
||||||
return _IO_fopencookie (c, mode, iof);
|
return _IO_fopencookie (c, mode, iof);
|
||||||
}
|
}
|
||||||
libc_hidden_def (fmemopen)
|
libc_hidden_def (__fmemopen)
|
||||||
|
versioned_symbol (libc, __fmemopen, fmemopen, GLIBC_2_22);
|
||||||
|
265
libio/oldfmemopen.c
Normal file
265
libio/oldfmemopen.c
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
/* Fmemopen implementation.
|
||||||
|
Copyright (C) 2000-2015 Free Software Foundation, Inc.
|
||||||
|
This file is part of the GNU C Library.
|
||||||
|
Contributed by Hanno Mueller, kontakt@hanno.de, 2000.
|
||||||
|
|
||||||
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with the GNU C Library; if not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fmemopen() - "my" version of a string stream
|
||||||
|
* Hanno Mueller, kontakt@hanno.de
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* I needed fmemopen() for an application that I currently work on,
|
||||||
|
* but couldn't find it in libio. The following snippet of code is an
|
||||||
|
* attempt to implement what glibc's documentation describes.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* I already see some potential problems:
|
||||||
|
*
|
||||||
|
* - I never used the "original" fmemopen(). I am sure that "my"
|
||||||
|
* fmemopen() behaves differently than the original version.
|
||||||
|
*
|
||||||
|
* - The documentation doesn't say wether a string stream allows
|
||||||
|
* seeks. I checked the old fmemopen implementation in glibc's stdio
|
||||||
|
* directory, wasn't quite able to see what is going on in that
|
||||||
|
* source, but as far as I understand there was no seek there. For
|
||||||
|
* my application, I needed fseek() and ftell(), so it's here.
|
||||||
|
*
|
||||||
|
* - "append" mode and fseek(p, SEEK_END) have two different ideas
|
||||||
|
* about the "end" of the stream.
|
||||||
|
*
|
||||||
|
* As described in the documentation, when opening the file in
|
||||||
|
* "append" mode, the position pointer will be set to the first null
|
||||||
|
* character of the string buffer (yet the buffer may already
|
||||||
|
* contain more data). For fseek(), the last byte of the buffer is
|
||||||
|
* used as the end of the stream.
|
||||||
|
*
|
||||||
|
* - It is unclear to me what the documentation tries to say when it
|
||||||
|
* explains what happens when you use fmemopen with a NULL
|
||||||
|
* buffer.
|
||||||
|
*
|
||||||
|
* Quote: "fmemopen [then] allocates an array SIZE bytes long. This
|
||||||
|
* is really only useful if you are going to write things to the
|
||||||
|
* buffer and then read them back in again."
|
||||||
|
*
|
||||||
|
* What does that mean if the original fmemopen() did not allow
|
||||||
|
* seeking? How do you read what you just wrote without seeking back
|
||||||
|
* to the beginning of the stream?
|
||||||
|
*
|
||||||
|
* - I think there should be a second version of fmemopen() that does
|
||||||
|
* not add null characters for each write. (At least in my
|
||||||
|
* application, I am not actually using strings but binary data and
|
||||||
|
* so I don't need the stream to add null characters on its own.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libioP.h"
|
||||||
|
|
||||||
|
#if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_22)
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <libio.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct fmemopen_cookie_struct fmemopen_cookie_t;
|
||||||
|
struct fmemopen_cookie_struct
|
||||||
|
{
|
||||||
|
char *buffer;
|
||||||
|
int mybuffer;
|
||||||
|
int binmode;
|
||||||
|
size_t size;
|
||||||
|
_IO_off64_t pos;
|
||||||
|
size_t maxpos;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
fmemopen_read (void *cookie, char *b, size_t s)
|
||||||
|
{
|
||||||
|
fmemopen_cookie_t *c;
|
||||||
|
|
||||||
|
c = (fmemopen_cookie_t *) cookie;
|
||||||
|
|
||||||
|
if (c->pos + s > c->size)
|
||||||
|
{
|
||||||
|
if ((size_t) c->pos == c->size)
|
||||||
|
return 0;
|
||||||
|
s = c->size - c->pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy (b, &(c->buffer[c->pos]), s);
|
||||||
|
|
||||||
|
c->pos += s;
|
||||||
|
if ((size_t) c->pos > c->maxpos)
|
||||||
|
c->maxpos = c->pos;
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
fmemopen_write (void *cookie, const char *b, size_t s)
|
||||||
|
{
|
||||||
|
fmemopen_cookie_t *c;
|
||||||
|
int addnullc;
|
||||||
|
|
||||||
|
c = (fmemopen_cookie_t *) cookie;
|
||||||
|
|
||||||
|
addnullc = c->binmode == 0 && (s == 0 || b[s - 1] != '\0');
|
||||||
|
|
||||||
|
if (c->pos + s + addnullc > c->size)
|
||||||
|
{
|
||||||
|
if ((size_t) (c->pos + addnullc) >= c->size)
|
||||||
|
{
|
||||||
|
__set_errno (ENOSPC);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
s = c->size - c->pos - addnullc;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy (&(c->buffer[c->pos]), b, s);
|
||||||
|
|
||||||
|
c->pos += s;
|
||||||
|
if ((size_t) c->pos > c->maxpos)
|
||||||
|
{
|
||||||
|
c->maxpos = c->pos;
|
||||||
|
if (addnullc)
|
||||||
|
c->buffer[c->maxpos] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
fmemopen_seek (void *cookie, _IO_off64_t *p, int w)
|
||||||
|
{
|
||||||
|
_IO_off64_t np;
|
||||||
|
fmemopen_cookie_t *c;
|
||||||
|
|
||||||
|
c = (fmemopen_cookie_t *) cookie;
|
||||||
|
|
||||||
|
switch (w)
|
||||||
|
{
|
||||||
|
case SEEK_SET:
|
||||||
|
np = *p;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SEEK_CUR:
|
||||||
|
np = c->pos + *p;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SEEK_END:
|
||||||
|
np = (c->binmode ? c->size : c->maxpos) - *p;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (np < 0 || (size_t) np > c->size)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*p = c->pos = np;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
fmemopen_close (void *cookie)
|
||||||
|
{
|
||||||
|
fmemopen_cookie_t *c;
|
||||||
|
|
||||||
|
c = (fmemopen_cookie_t *) cookie;
|
||||||
|
|
||||||
|
if (c->mybuffer)
|
||||||
|
free (c->buffer);
|
||||||
|
free (c);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FILE *
|
||||||
|
__old_fmemopen (void *buf, size_t len, const char *mode)
|
||||||
|
{
|
||||||
|
cookie_io_functions_t iof;
|
||||||
|
fmemopen_cookie_t *c;
|
||||||
|
|
||||||
|
if (__glibc_unlikely (len == 0))
|
||||||
|
{
|
||||||
|
einval:
|
||||||
|
__set_errno (EINVAL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
c = (fmemopen_cookie_t *) malloc (sizeof (fmemopen_cookie_t));
|
||||||
|
if (c == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
c->mybuffer = (buf == NULL);
|
||||||
|
|
||||||
|
if (c->mybuffer)
|
||||||
|
{
|
||||||
|
c->buffer = (char *) malloc (len);
|
||||||
|
if (c->buffer == NULL)
|
||||||
|
{
|
||||||
|
free (c);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
c->buffer[0] = '\0';
|
||||||
|
c->maxpos = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (__glibc_unlikely ((uintptr_t) len > -(uintptr_t) buf))
|
||||||
|
{
|
||||||
|
free (c);
|
||||||
|
goto einval;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->buffer = buf;
|
||||||
|
|
||||||
|
if (mode[0] == 'w')
|
||||||
|
c->buffer[0] = '\0';
|
||||||
|
|
||||||
|
c->maxpos = strnlen (c->buffer, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
c->size = len;
|
||||||
|
|
||||||
|
if (mode[0] == 'a')
|
||||||
|
c->pos = c->maxpos;
|
||||||
|
else
|
||||||
|
c->pos = 0;
|
||||||
|
|
||||||
|
c->binmode = mode[0] != '\0' && mode[1] == 'b';
|
||||||
|
|
||||||
|
iof.read = fmemopen_read;
|
||||||
|
iof.write = fmemopen_write;
|
||||||
|
iof.seek = fmemopen_seek;
|
||||||
|
iof.close = fmemopen_close;
|
||||||
|
|
||||||
|
return _IO_fopencookie (c, mode, iof);
|
||||||
|
}
|
||||||
|
compat_symbol (libc, __old_fmemopen, fmemopen, GLIBC_2_2);
|
||||||
|
#endif
|
@ -57,7 +57,7 @@ tests := tstscanf test_rdwr test-popen tstgetln test-fseek \
|
|||||||
bug19 bug19a tst-popen2 scanf13 scanf14 scanf15 bug20 bug21 bug22 \
|
bug19 bug19a tst-popen2 scanf13 scanf14 scanf15 bug20 bug21 bug22 \
|
||||||
scanf16 scanf17 tst-setvbuf1 tst-grouping bug23 bug24 \
|
scanf16 scanf17 tst-setvbuf1 tst-grouping bug23 bug24 \
|
||||||
bug-vfprintf-nargs tst-long-dbl-fphex tst-fphex-wide tst-sprintf3 \
|
bug-vfprintf-nargs tst-long-dbl-fphex tst-fphex-wide tst-sprintf3 \
|
||||||
bug25 tst-printf-round bug23-2 bug23-3 bug23-4 bug26
|
bug25 tst-printf-round bug23-2 bug23-3 bug23-4 bug26 tst-fmemopen3
|
||||||
|
|
||||||
test-srcs = tst-unbputc tst-printf
|
test-srcs = tst-unbputc tst-printf
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ void
|
|||||||
psiginfo (const siginfo_t *pinfo, const char *s)
|
psiginfo (const siginfo_t *pinfo, const char *s)
|
||||||
{
|
{
|
||||||
char buf[512];
|
char buf[512];
|
||||||
FILE *fp = fmemopen (buf, sizeof (buf), "w");
|
FILE *fp = __fmemopen (buf, sizeof (buf), "w");
|
||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
{
|
{
|
||||||
const char *colon;
|
const char *colon;
|
||||||
|
206
stdio-common/tst-fmemopen3.c
Normal file
206
stdio-common/tst-fmemopen3.c
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
/* fmemopen tests for append and read mode.
|
||||||
|
Copyright (C) 2015 Free Software Foundation, Inc.
|
||||||
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with the GNU C Library; if not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_buffer (const char *s, size_t n)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for (i=0; i<n; ++i)
|
||||||
|
printf ("0x%02X (%c), ", s[i], s[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This test check append mode initial position (a/a+) based on POSIX defition
|
||||||
|
(BZ#6544 and BZ#13151). */
|
||||||
|
static int
|
||||||
|
do_test_write_append (const char *mode)
|
||||||
|
{
|
||||||
|
char buf[32] = "testing buffer";
|
||||||
|
char exp[32] = "testing bufferXX";
|
||||||
|
|
||||||
|
FILE *fp = fmemopen (buf, sizeof (buf), mode);
|
||||||
|
|
||||||
|
fflush (fp);
|
||||||
|
fprintf (fp, "X");
|
||||||
|
fseek (fp, 0, SEEK_SET);
|
||||||
|
fprintf (fp, "X");
|
||||||
|
fclose (fp);
|
||||||
|
|
||||||
|
if (strcmp (buf, exp) != 0)
|
||||||
|
{
|
||||||
|
printf ("%s: check failed: %s != %s\n", __FUNCTION__, buf, exp);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This test check append mode initial position (a/a+) based on POSIX defition
|
||||||
|
(BZ#6544 and BZ#13151) for buffer without null byte end. */
|
||||||
|
static int
|
||||||
|
do_test_write_append_without_null (const char *mode)
|
||||||
|
{
|
||||||
|
char buf[] = { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 };
|
||||||
|
char exp[] = { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 };
|
||||||
|
|
||||||
|
/* If '\0' is not found in buffer, POSIX states that SEEK_SET should be
|
||||||
|
the size argument. */
|
||||||
|
FILE *fp = fmemopen (buf, sizeof (buf) - 2, "a");
|
||||||
|
|
||||||
|
fflush (fp);
|
||||||
|
fputc (0x70, fp);
|
||||||
|
fseek (fp, 0, SEEK_SET);
|
||||||
|
fputc (0x70, fp);
|
||||||
|
fputc (0x70, fp);
|
||||||
|
fclose (fp);
|
||||||
|
|
||||||
|
/* POSIX also states that a write operation on the stream shall not advance
|
||||||
|
the current buffer size beyond the size given in fmemopen, so the string
|
||||||
|
should be same. */
|
||||||
|
if (memcmp (buf, exp, sizeof (buf)) != 0)
|
||||||
|
{
|
||||||
|
printf ("%s: check failed: ", __FUNCTION__);
|
||||||
|
print_buffer (buf, sizeof (buf));
|
||||||
|
printf ("!= ");
|
||||||
|
print_buffer (exp, sizeof (exp));
|
||||||
|
printf ("\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This test check for initial position and feek value for fmemopen objects
|
||||||
|
opened with append mode. */
|
||||||
|
static int
|
||||||
|
do_test_read_append (void)
|
||||||
|
{
|
||||||
|
char buf[32] = "testing buffer";
|
||||||
|
size_t buflen = strlen (buf);
|
||||||
|
long fpos;
|
||||||
|
|
||||||
|
/* POSIX defines for 'a+' the initial position is the first null byte. */
|
||||||
|
FILE *fp = fmemopen (buf, sizeof (buf), "a+");
|
||||||
|
|
||||||
|
fpos = ftell (fp);
|
||||||
|
if (fpos != buflen)
|
||||||
|
{
|
||||||
|
printf ("%s: ftell|SEEK_SET (fp) %li != strlen (%s) %zu\n",
|
||||||
|
__FUNCTION__, fpos, buf, buflen);
|
||||||
|
fclose (fp);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek (fp, 0, SEEK_END);
|
||||||
|
|
||||||
|
if (fpos != buflen)
|
||||||
|
{
|
||||||
|
printf ("%s: ftell|SEEK_END (fp) %li != strlen (%s) %zu\n",
|
||||||
|
__FUNCTION__, fpos, buf, buflen);
|
||||||
|
fclose (fp);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
fclose (fp);
|
||||||
|
|
||||||
|
/* Check if attempting to read past the current size, defined as strlen (buf)
|
||||||
|
yield an EOF. */
|
||||||
|
fp = fmemopen (buf, sizeof (buf), "a+");
|
||||||
|
if (getc(fp) != EOF)
|
||||||
|
{
|
||||||
|
printf ("%s: getc(fp) != EOF\n", __FUNCTION__);
|
||||||
|
fclose (fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose (fp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This test check for fseek (SEEK_END) using negative offsets (BZ#14292). The
|
||||||
|
starting position of descriptor is different base on the opening mode. */
|
||||||
|
static int
|
||||||
|
do_test_read_seek_neg (const char *mode, const char *expected)
|
||||||
|
{
|
||||||
|
char buf[] = "abcdefghijklmnopqrstuvxz0123456789";
|
||||||
|
char tmp[10];
|
||||||
|
size_t tmps = sizeof (tmps);
|
||||||
|
long offset = -11;
|
||||||
|
|
||||||
|
FILE *fp = fmemopen (buf, sizeof (buf), mode);
|
||||||
|
fseek (fp, offset, SEEK_END);
|
||||||
|
fread (tmp, tmps, 1, fp);
|
||||||
|
|
||||||
|
if (memcmp (tmp, expected, tmps) != 0)
|
||||||
|
{
|
||||||
|
printf ("%s: fmemopen(%s) - fseek (fp, %li, SEEK_END):\n",
|
||||||
|
__FUNCTION__, mode, offset);
|
||||||
|
printf (" returned: ");
|
||||||
|
print_buffer (tmp, tmps);
|
||||||
|
printf ("\n");
|
||||||
|
printf (" expected: ");
|
||||||
|
print_buffer (expected, tmps);
|
||||||
|
printf ("\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose (fp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_test_read_seek_negative (void)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
/* 'r' and 'w' modes defines the initial position at the buffer start and
|
||||||
|
seek with SEEK_END shall seek relative to its size give in fmemopen
|
||||||
|
call. The expected tmp result is 0 to 9 *without* the ending null */
|
||||||
|
ret += do_test_read_seek_neg ("r", "0123456789");
|
||||||
|
/* 'a+' mode sets the initial position at the first null byte in buffer and
|
||||||
|
SEEK_END shall seek relative to its size as well. The expected result is
|
||||||
|
z012345678, since SEEK_END plus a+ start at '\0', not size. */
|
||||||
|
ret += do_test_read_seek_neg ("a+", "z012345678");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_test (void)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret += do_test_write_append ("a");
|
||||||
|
ret += do_test_write_append_without_null ("a");
|
||||||
|
ret += do_test_write_append ("a+");
|
||||||
|
ret += do_test_write_append_without_null ("a+");
|
||||||
|
|
||||||
|
ret += do_test_read_append ();
|
||||||
|
|
||||||
|
ret += do_test_read_seek_negative ();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TEST_FUNCTION do_test ()
|
||||||
|
#include "../test-skeleton.c"
|
@ -2081,3 +2081,6 @@ GLIBC_2.18
|
|||||||
GLIBC_2.18 A
|
GLIBC_2.18 A
|
||||||
__cxa_thread_atexit_impl F
|
__cxa_thread_atexit_impl F
|
||||||
_mcount F
|
_mcount F
|
||||||
|
GLIBC_2.22
|
||||||
|
GLIBC_2.22 A
|
||||||
|
fmemopen F
|
||||||
|
@ -1822,6 +1822,9 @@ GLIBC_2.17
|
|||||||
GLIBC_2.18
|
GLIBC_2.18
|
||||||
GLIBC_2.18 A
|
GLIBC_2.18 A
|
||||||
__cxa_thread_atexit_impl F
|
__cxa_thread_atexit_impl F
|
||||||
|
GLIBC_2.22
|
||||||
|
GLIBC_2.22 A
|
||||||
|
fmemopen F
|
||||||
GLIBC_2.2
|
GLIBC_2.2
|
||||||
GLIBC_2.2 A
|
GLIBC_2.2 A
|
||||||
_IO_adjust_wcolumn F
|
_IO_adjust_wcolumn F
|
||||||
|
@ -89,6 +89,9 @@ GLIBC_2.17
|
|||||||
GLIBC_2.18
|
GLIBC_2.18
|
||||||
GLIBC_2.18 A
|
GLIBC_2.18 A
|
||||||
__cxa_thread_atexit_impl F
|
__cxa_thread_atexit_impl F
|
||||||
|
GLIBC_2.22
|
||||||
|
GLIBC_2.22 A
|
||||||
|
fmemopen F
|
||||||
GLIBC_2.4
|
GLIBC_2.4
|
||||||
GLIBC_2.4 A
|
GLIBC_2.4 A
|
||||||
_Exit F
|
_Exit F
|
||||||
|
@ -95,6 +95,9 @@ GLIBC_2.18
|
|||||||
GLIBC_2.19
|
GLIBC_2.19
|
||||||
GLIBC_2.19 A
|
GLIBC_2.19 A
|
||||||
fanotify_mark F
|
fanotify_mark F
|
||||||
|
GLIBC_2.22
|
||||||
|
GLIBC_2.22 A
|
||||||
|
fmemopen F
|
||||||
GLIBC_2.2
|
GLIBC_2.2
|
||||||
GLIBC_2.2 A
|
GLIBC_2.2 A
|
||||||
_Exit F
|
_Exit F
|
||||||
|
@ -2023,6 +2023,9 @@ GLIBC_2.2.4
|
|||||||
GLIBC_2.2.6
|
GLIBC_2.2.6
|
||||||
GLIBC_2.2.6 A
|
GLIBC_2.2.6 A
|
||||||
__nanosleep F
|
__nanosleep F
|
||||||
|
GLIBC_2.22
|
||||||
|
GLIBC_2.22 A
|
||||||
|
fmemopen F
|
||||||
GLIBC_2.3
|
GLIBC_2.3
|
||||||
GLIBC_2.3 A
|
GLIBC_2.3 A
|
||||||
__ctype_b_loc F
|
__ctype_b_loc F
|
||||||
|
@ -1881,6 +1881,9 @@ GLIBC_2.2.6
|
|||||||
GLIBC_2.2.6 A
|
GLIBC_2.2.6 A
|
||||||
__nanosleep F
|
__nanosleep F
|
||||||
getunwind F
|
getunwind F
|
||||||
|
GLIBC_2.22
|
||||||
|
GLIBC_2.22 A
|
||||||
|
fmemopen F
|
||||||
GLIBC_2.3
|
GLIBC_2.3
|
||||||
GLIBC_2.3 A
|
GLIBC_2.3 A
|
||||||
__ctype_b_loc F
|
__ctype_b_loc F
|
||||||
|
@ -90,6 +90,9 @@ GLIBC_2.17
|
|||||||
GLIBC_2.18
|
GLIBC_2.18
|
||||||
GLIBC_2.18 A
|
GLIBC_2.18 A
|
||||||
__cxa_thread_atexit_impl F
|
__cxa_thread_atexit_impl F
|
||||||
|
GLIBC_2.22
|
||||||
|
GLIBC_2.22 A
|
||||||
|
fmemopen F
|
||||||
GLIBC_2.4
|
GLIBC_2.4
|
||||||
GLIBC_2.4 A
|
GLIBC_2.4 A
|
||||||
_Exit F
|
_Exit F
|
||||||
|
@ -1979,6 +1979,9 @@ GLIBC_2.2.4
|
|||||||
GLIBC_2.2.6
|
GLIBC_2.2.6
|
||||||
GLIBC_2.2.6 A
|
GLIBC_2.2.6 A
|
||||||
__nanosleep F
|
__nanosleep F
|
||||||
|
GLIBC_2.22
|
||||||
|
GLIBC_2.22 A
|
||||||
|
fmemopen F
|
||||||
GLIBC_2.3
|
GLIBC_2.3
|
||||||
GLIBC_2.3 A
|
GLIBC_2.3 A
|
||||||
__ctype_b_loc F
|
__ctype_b_loc F
|
||||||
|
@ -2080,3 +2080,6 @@ GLIBC_2.18
|
|||||||
xencrypt F
|
xencrypt F
|
||||||
xprt_register F
|
xprt_register F
|
||||||
xprt_unregister F
|
xprt_unregister F
|
||||||
|
GLIBC_2.22
|
||||||
|
GLIBC_2.22 A
|
||||||
|
fmemopen F
|
||||||
|
@ -1951,6 +1951,9 @@ GLIBC_2.2.4
|
|||||||
GLIBC_2.2.6
|
GLIBC_2.2.6
|
||||||
GLIBC_2.2.6 A
|
GLIBC_2.2.6 A
|
||||||
__nanosleep F
|
__nanosleep F
|
||||||
|
GLIBC_2.22
|
||||||
|
GLIBC_2.22 A
|
||||||
|
fmemopen F
|
||||||
GLIBC_2.3
|
GLIBC_2.3
|
||||||
GLIBC_2.3 A
|
GLIBC_2.3 A
|
||||||
__ctype_b_loc F
|
__ctype_b_loc F
|
||||||
|
@ -1949,6 +1949,9 @@ GLIBC_2.2.4
|
|||||||
GLIBC_2.2.6
|
GLIBC_2.2.6
|
||||||
GLIBC_2.2.6 A
|
GLIBC_2.2.6 A
|
||||||
__nanosleep F
|
__nanosleep F
|
||||||
|
GLIBC_2.22
|
||||||
|
GLIBC_2.22 A
|
||||||
|
fmemopen F
|
||||||
GLIBC_2.3
|
GLIBC_2.3
|
||||||
GLIBC_2.3 A
|
GLIBC_2.3 A
|
||||||
__ctype_b_loc F
|
__ctype_b_loc F
|
||||||
|
@ -1947,6 +1947,9 @@ GLIBC_2.2.4
|
|||||||
GLIBC_2.2.6
|
GLIBC_2.2.6
|
||||||
GLIBC_2.2.6 A
|
GLIBC_2.2.6 A
|
||||||
__nanosleep F
|
__nanosleep F
|
||||||
|
GLIBC_2.22
|
||||||
|
GLIBC_2.22 A
|
||||||
|
fmemopen F
|
||||||
GLIBC_2.3
|
GLIBC_2.3
|
||||||
GLIBC_2.3 A
|
GLIBC_2.3 A
|
||||||
__ctype_b_loc F
|
__ctype_b_loc F
|
||||||
|
@ -1941,6 +1941,9 @@ GLIBC_2.2.4
|
|||||||
GLIBC_2.2.6
|
GLIBC_2.2.6
|
||||||
GLIBC_2.2.6 A
|
GLIBC_2.2.6 A
|
||||||
__nanosleep F
|
__nanosleep F
|
||||||
|
GLIBC_2.22
|
||||||
|
GLIBC_2.22 A
|
||||||
|
fmemopen F
|
||||||
GLIBC_2.3
|
GLIBC_2.3
|
||||||
GLIBC_2.3 A
|
GLIBC_2.3 A
|
||||||
__ctype_b_loc F
|
__ctype_b_loc F
|
||||||
|
@ -2121,3 +2121,6 @@ GLIBC_2.21
|
|||||||
xencrypt F
|
xencrypt F
|
||||||
xprt_register F
|
xprt_register F
|
||||||
xprt_unregister F
|
xprt_unregister F
|
||||||
|
GLIBC_2.22
|
||||||
|
GLIBC_2.22 A
|
||||||
|
fmemopen F
|
||||||
|
@ -1983,6 +1983,9 @@ GLIBC_2.2.4
|
|||||||
GLIBC_2.2.6
|
GLIBC_2.2.6
|
||||||
GLIBC_2.2.6 A
|
GLIBC_2.2.6 A
|
||||||
__nanosleep F
|
__nanosleep F
|
||||||
|
GLIBC_2.22
|
||||||
|
GLIBC_2.22 A
|
||||||
|
fmemopen F
|
||||||
GLIBC_2.3
|
GLIBC_2.3
|
||||||
GLIBC_2.3 A
|
GLIBC_2.3 A
|
||||||
__ctype_b_loc F
|
__ctype_b_loc F
|
||||||
|
@ -1989,6 +1989,9 @@ GLIBC_2.2.4
|
|||||||
GLIBC_2.2.6
|
GLIBC_2.2.6
|
||||||
GLIBC_2.2.6 A
|
GLIBC_2.2.6 A
|
||||||
__nanosleep F
|
__nanosleep F
|
||||||
|
GLIBC_2.22
|
||||||
|
GLIBC_2.22 A
|
||||||
|
fmemopen F
|
||||||
GLIBC_2.3
|
GLIBC_2.3
|
||||||
GLIBC_2.3 A
|
GLIBC_2.3 A
|
||||||
__ctype_b_loc F
|
__ctype_b_loc F
|
||||||
|
@ -90,6 +90,9 @@ GLIBC_2.17
|
|||||||
GLIBC_2.18
|
GLIBC_2.18
|
||||||
GLIBC_2.18 A
|
GLIBC_2.18 A
|
||||||
__cxa_thread_atexit_impl F
|
__cxa_thread_atexit_impl F
|
||||||
|
GLIBC_2.22
|
||||||
|
GLIBC_2.22 A
|
||||||
|
fmemopen F
|
||||||
GLIBC_2.3
|
GLIBC_2.3
|
||||||
GLIBC_2.3 A
|
GLIBC_2.3 A
|
||||||
_Exit F
|
_Exit F
|
||||||
|
@ -1984,6 +1984,9 @@ GLIBC_2.2.4
|
|||||||
GLIBC_2.2.6
|
GLIBC_2.2.6
|
||||||
GLIBC_2.2.6 A
|
GLIBC_2.2.6 A
|
||||||
__nanosleep F
|
__nanosleep F
|
||||||
|
GLIBC_2.22
|
||||||
|
GLIBC_2.22 A
|
||||||
|
fmemopen F
|
||||||
GLIBC_2.3
|
GLIBC_2.3
|
||||||
GLIBC_2.3 A
|
GLIBC_2.3 A
|
||||||
__ctype_b_loc F
|
__ctype_b_loc F
|
||||||
|
@ -1880,6 +1880,9 @@ GLIBC_2.2.4
|
|||||||
GLIBC_2.2.6
|
GLIBC_2.2.6
|
||||||
GLIBC_2.2.6 A
|
GLIBC_2.2.6 A
|
||||||
__nanosleep F
|
__nanosleep F
|
||||||
|
GLIBC_2.22
|
||||||
|
GLIBC_2.22 A
|
||||||
|
fmemopen F
|
||||||
GLIBC_2.3
|
GLIBC_2.3
|
||||||
GLIBC_2.3 A
|
GLIBC_2.3 A
|
||||||
__ctype_b_loc F
|
__ctype_b_loc F
|
||||||
|
@ -1864,6 +1864,9 @@ GLIBC_2.2.4
|
|||||||
GLIBC_2.2.6
|
GLIBC_2.2.6
|
||||||
GLIBC_2.2.6 A
|
GLIBC_2.2.6 A
|
||||||
__nanosleep F
|
__nanosleep F
|
||||||
|
GLIBC_2.22
|
||||||
|
GLIBC_2.22 A
|
||||||
|
fmemopen F
|
||||||
GLIBC_2.3
|
GLIBC_2.3
|
||||||
GLIBC_2.3 A
|
GLIBC_2.3 A
|
||||||
__ctype_b_loc F
|
__ctype_b_loc F
|
||||||
|
@ -1975,6 +1975,9 @@ GLIBC_2.2.4
|
|||||||
GLIBC_2.2.6
|
GLIBC_2.2.6
|
||||||
GLIBC_2.2.6 A
|
GLIBC_2.2.6 A
|
||||||
__nanosleep F
|
__nanosleep F
|
||||||
|
GLIBC_2.22
|
||||||
|
GLIBC_2.22 A
|
||||||
|
fmemopen F
|
||||||
GLIBC_2.3
|
GLIBC_2.3
|
||||||
GLIBC_2.3 A
|
GLIBC_2.3 A
|
||||||
__ctype_b_loc F
|
__ctype_b_loc F
|
||||||
|
@ -1908,6 +1908,9 @@ GLIBC_2.2.4
|
|||||||
GLIBC_2.2.6
|
GLIBC_2.2.6
|
||||||
GLIBC_2.2.6 A
|
GLIBC_2.2.6 A
|
||||||
__nanosleep F
|
__nanosleep F
|
||||||
|
GLIBC_2.22
|
||||||
|
GLIBC_2.22 A
|
||||||
|
fmemopen F
|
||||||
GLIBC_2.3
|
GLIBC_2.3
|
||||||
GLIBC_2.3 A
|
GLIBC_2.3 A
|
||||||
__ctype_b_loc F
|
__ctype_b_loc F
|
||||||
|
@ -2091,3 +2091,6 @@ GLIBC_2.17
|
|||||||
GLIBC_2.18
|
GLIBC_2.18
|
||||||
GLIBC_2.18 A
|
GLIBC_2.18 A
|
||||||
__cxa_thread_atexit_impl F
|
__cxa_thread_atexit_impl F
|
||||||
|
GLIBC_2.22
|
||||||
|
GLIBC_2.22 A
|
||||||
|
fmemopen F
|
||||||
|
@ -2091,3 +2091,6 @@ GLIBC_2.17
|
|||||||
GLIBC_2.18
|
GLIBC_2.18
|
||||||
GLIBC_2.18 A
|
GLIBC_2.18 A
|
||||||
__cxa_thread_atexit_impl F
|
__cxa_thread_atexit_impl F
|
||||||
|
GLIBC_2.22
|
||||||
|
GLIBC_2.22 A
|
||||||
|
fmemopen F
|
||||||
|
@ -2091,3 +2091,6 @@ GLIBC_2.17
|
|||||||
GLIBC_2.18
|
GLIBC_2.18
|
||||||
GLIBC_2.18 A
|
GLIBC_2.18 A
|
||||||
__cxa_thread_atexit_impl F
|
__cxa_thread_atexit_impl F
|
||||||
|
GLIBC_2.22
|
||||||
|
GLIBC_2.22 A
|
||||||
|
fmemopen F
|
||||||
|
@ -1854,6 +1854,9 @@ GLIBC_2.2.5
|
|||||||
GLIBC_2.2.6
|
GLIBC_2.2.6
|
||||||
GLIBC_2.2.6 A
|
GLIBC_2.2.6 A
|
||||||
__nanosleep F
|
__nanosleep F
|
||||||
|
GLIBC_2.22
|
||||||
|
GLIBC_2.22 A
|
||||||
|
fmemopen F
|
||||||
GLIBC_2.3
|
GLIBC_2.3
|
||||||
GLIBC_2.3 A
|
GLIBC_2.3 A
|
||||||
__ctype_b_loc F
|
__ctype_b_loc F
|
||||||
|
@ -2089,3 +2089,6 @@ GLIBC_2.17
|
|||||||
GLIBC_2.18
|
GLIBC_2.18
|
||||||
GLIBC_2.18 A
|
GLIBC_2.18 A
|
||||||
__cxa_thread_atexit_impl F
|
__cxa_thread_atexit_impl F
|
||||||
|
GLIBC_2.22
|
||||||
|
GLIBC_2.22 A
|
||||||
|
fmemopen F
|
||||||
|
Loading…
Reference in New Issue
Block a user