This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH 6/6][BZ #13152] fmemopen does not honor append mode.
- From: Ondrej Bilka <neleai at seznam dot cz>
- To: libc-alpha at sourceware dot org
- Cc: Ondrej Bilka <neleai at seznam dot cz>
- Date: Sat, 1 Jun 2013 17:11:28 +0200
- Subject: [PATCH 6/6][BZ #13152] fmemopen does not honor append mode.
- References: <1370099488-13916-1-git-send-email-neleai at seznam dot cz>
This change is more complicated that I initialy thougth.
I needed to add append field to support a+ mode like with fopen.
I keept this last as I needed do relatively large changes.
Comments?
* libio/fmemopen.c (fmemopen_read, fmemopen_write, fmemopen_seek,
fmemopen_close, fmemopen): Add append mode support.
* libio/bug-fmemopen-append-mode.c: New file.
* libio/Makefile (tests): Add bug-fmemopen-append-mode.
---
libio/Makefile | 1 +
libio/bug-fmemopen-append-mode.c | 26 ++++++++++
libio/fmemopen.c | 103 +++++++++++++++++++-------------------
5 files changed, 81 insertions(+), 53 deletions(-)
create mode 100644 libio/bug-fmemopen-append-mode.c
diff --git a/libio/Makefile b/libio/Makefile
index e5553de..e7b35bd 100644
--- a/libio/Makefile
+++ b/libio/Makefile
@@ -60,6 +60,7 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \
tst-wmemstream1 tst-wmemstream2 \
bug-memstream1 bug-wmemstream1 \
test-fmemopen bug-fmemopen1 bug-fmemopen-openmode \
+ bug-fmemopen-append-mode \
bug-openmodes-parsing \
tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos tst-fseek \
tst-fwrite-error
diff --git a/libio/bug-fmemopen-append-mode.c b/libio/bug-fmemopen-append-mode.c
new file mode 100644
index 0000000..a903493
--- /dev/null
+++ b/libio/bug-fmemopen-append-mode.c
@@ -0,0 +1,26 @@
+#include <stdio.h>
+#include <string.h>
+
+int
+do_test (int argc, char **argv)
+{
+ char buf[20] = "hello, world";
+ char expected[20] = "hello, worldX";
+ FILE *fp = fmemopen (buf, 20, "a+");
+ fseek (fp, 0, SEEK_SET);
+
+ fflush (fp);
+ fprintf (fp, "X");
+ fclose (fp);
+
+ for (int i = 0; i < strlen (expected); i++)
+ if (buf[i] != expected[i])
+ {
+ printf ("Disagree at position %i\n", i);
+ return 1;
+ }
+
+ return 0;
+}
+
+#include "../test-skeleton.c"
diff --git a/libio/fmemopen.c b/libio/fmemopen.c
index dcc031b..42632c2 100644
--- a/libio/fmemopen.c
+++ b/libio/fmemopen.c
@@ -85,28 +85,30 @@ struct fmemopen_cookie_struct
size_t size;
_IO_off64_t pos;
size_t maxpos;
+ int append;
};
static ssize_t
fmemopen_read (void *cookie, char *b, size_t s)
{
- fmemopen_cookie_t *c;
-
- c = (fmemopen_cookie_t *) cookie;
+ fmemopen_cookie_t *c = (fmemopen_cookie_t *) cookie;
+ _IO_off64_t pos = c->pos;
- if (c->pos + s > c->size)
+ if (pos + s > c->size)
{
- if ((size_t) c->pos == c->size)
+ if ((size_t) pos == c->size)
return 0;
- s = c->size - c->pos;
+ s = c->size - pos;
}
- memcpy (b, &(c->buffer[c->pos]), s);
+ memcpy (b, &(c->buffer[pos]), s);
- c->pos += s;
- if ((size_t) c->pos > c->maxpos)
- c->maxpos = c->pos;
+ pos += s;
+ c->pos = pos;
+
+ if ((size_t) pos > c->maxpos)
+ c->maxpos = pos;
return s;
}
@@ -115,29 +117,32 @@ fmemopen_read (void *cookie, char *b, size_t 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;
+ fmemopen_cookie_t *c = (fmemopen_cookie_t *) cookie;
+ _IO_off64_t pos = c->append ? c->maxpos : c->pos;
addnullc = c->binmode == 0 && (s == 0 || b[s - 1] != '\0');
- if (c->pos + s + addnullc > c->size)
+ if (pos + s + addnullc > c->size)
{
- if ((size_t) (c->pos + addnullc) == c->size)
+ if ((size_t) (pos + addnullc) == c->size)
{
__set_errno (ENOSPC);
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);
+
+ pos += s;
+
+ if (!c->append)
+ c->pos = pos;
- c->pos += s;
- if ((size_t) c->pos > c->maxpos)
+ if ((size_t) pos > c->maxpos)
{
- c->maxpos = c->pos;
+ c->maxpos = pos;
if (addnullc)
c->buffer[c->maxpos] = '\0';
}
@@ -150,9 +155,7 @@ 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;
+ fmemopen_cookie_t *c = (fmemopen_cookie_t *) cookie;
switch (w)
{
@@ -184,9 +187,7 @@ fmemopen_seek (void *cookie, _IO_off64_t *p, int w)
static int
fmemopen_close (void *cookie)
{
- fmemopen_cookie_t *c;
-
- c = (fmemopen_cookie_t *) cookie;
+ fmemopen_cookie_t *c = (fmemopen_cookie_t *) cookie;
if (c->mybuffer)
free (c->buffer);
@@ -204,7 +205,6 @@ fmemopen (void *buf, size_t len, const char *mode)
if (__glibc_unlikely (len == 0))
{
-einval:
__set_errno (EINVAL);
return NULL;
}
@@ -213,46 +213,45 @@ einval:
if (c == NULL)
return NULL;
- c->mybuffer = (buf == NULL);
-
- if (c->mybuffer)
+ if (buf == NULL)
{
- c->buffer = (char *) malloc (len);
- if (c->buffer == NULL)
+ buf = (char *) malloc (len);
+ if (buf == NULL)
{
free (c);
return NULL;
}
- c->buffer[0] = '\0';
- c->maxpos = 0;
+ c->mybuffer = 1;
}
else
- {
- if (__glibc_unlikely ((uintptr_t) len > -(uintptr_t) buf))
- {
- free (c);
- goto einval;
- }
-
- c->buffer = buf;
+ c->mybuffer = 0;
- if (mode[0] == 'w')
- c->buffer[0] = '\0';
-
- c->maxpos = strnlen (c->buffer, len);
+ if (__glibc_unlikely ((uintptr_t) len > -(uintptr_t) buf))
+ {
+ free (c);
+ __set_errno (EINVAL);
+ return NULL;
}
+ c->buffer = buf;
+ c->binmode = 0;
+ c->pos = 0;
c->size = len;
+ c->append = (mode[0] == 'a');
+ if (c->mybuffer || mode[0] == 'w')
+ c->buffer[0] = '\0';
+ c->maxpos = strnlen (c->buffer, len);
- if (mode[0] == 'a')
+ if (c->append)
c->pos = c->maxpos;
- else
- c->pos = 0;
- c->binmode = 0;
for (int i = 0; mode[i] != '\0'; i++)
- if (mode[i] == 'b')
- c->binmode = 1;
+ {
+ if (mode[i] == 'b')
+ c->binmode = 1;
+ if (c->append && mode[i] == '+')
+ c->pos = 0;
+ }
iof.read = fmemopen_read;
iof.write = fmemopen_write;
--
1.7.10.4