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]

[PATCH 6/6][BZ #13152] fmemopen does not honor append mode.


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


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