[SCM] GNU Mailutils branch, stream-cleanup, updated. rel-2_1-128-gbfb29ce

"Sergey Poznyakoff" <[email protected]>
Newsgroups gmane.comp.gnu.mailutils.cvs
Message-ID <[email protected]>
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Mailutils".

http://git.savannah.gnu.org/cgit/mailutils.git/commit/?id=bfb29ced5d88dbe449347d5b8b86e6ee887c450b

The branch, stream-cleanup has been updated
       via  bfb29ced5d88dbe449347d5b8b86e6ee887c450b (commit)
      from  d0b037c48bc8ccdb0c4a094289d6489ec280c2af (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit bfb29ced5d88dbe449347d5b8b86e6ee887c450b
Author: Sergey Poznyakoff <[email protected]>
Date:   Mon Sep 6 19:18:32 2010 +0300

    Implement "read cache" streams. Rewrite stdio and socket streams.
    
    * include/mailutils/sys/stdio_stream.h: Remove.
    * include/mailutils/sys/socket_stream.h: Remove.
    * include/mailutils/sys/rdcache_stream.h: New file.
    * include/mailutils/sys/Makefile.am: Update.
    * mailbox/rdcache_stream.c: New file.
    * mailbox/Makefile.am: Update.
    
    * examples/mucat.c: New example.
    * examples/musocio.c: New example.
    * examples/Makefile.am (noinst_PROGRAMS): Build new examples.
    
    * include/mailutils/stream.h (mu_fd_stream_create): New proto.
    (mu_rdcache_stream_create): New proto.
    * include/mailutils/sys/file_stream.h (_mu_file_stream_create): Change
    prototype.
    * mailbox/file_stream.c (fd_open): Raise the MU_STREAM_AUTOCLOSE bit.
    (fd_ioctl): Support MU_IOCTL_SET_TRANSPORT.
    (_mu_file_stream_create): Change signature. All uses updated.
    Allocate a copy of the filename argument, unless it is NULL.
    (mu_fd_stream_create): New function.
    
    * mailbox/socket_stream.c: Rewrite using file_stream directly.
    * mailbox/stdio_stream.c: Rewrite. Use rdcache_stream if
    the seek capability is required on an input stream.
    * mailbox/streamcpy.c (mu_stream_copy): Handle eventual
    EACCES return from mu_stream_seek as equivalent to ENOSYS.

-----------------------------------------------------------------------

Summary of changes:
 examples/Makefile.am                               |    2 +
 examples/mucat.c                                   |   87 +++++++++
 examples/musocio.c                                 |  124 ++++++++++++
 include/mailutils/stream.h                         |    5 +
 include/mailutils/sys/Makefile.am                  |    3 +-
 include/mailutils/sys/file_stream.h                |    4 +-
 .../sys/{xscript-stream.h => rdcache_stream.h}     |   12 +-
 include/mailutils/sys/socket_stream.h              |   28 ---
 include/mailutils/sys/stdio_stream.h               |   34 ----
 mailbox/Makefile.am                                |    1 +
 mailbox/file_stream.c                              |   54 ++++--
 mailbox/rdcache_stream.c                           |  201 ++++++++++++++++++++
 mailbox/socket_stream.c                            |   73 ++++----
 mailbox/stdio_stream.c                             |  194 ++++---------------
 mailbox/streamcpy.c                                |    2 +
 mailbox/temp_file_stream.c                         |   22 +--
 16 files changed, 546 insertions(+), 300 deletions(-)
 create mode 100644 examples/mucat.c
 create mode 100644 examples/musocio.c
 copy include/mailutils/sys/{xscript-stream.h => rdcache_stream.h} (85%)
 delete mode 100644 include/mailutils/sys/socket_stream.h
 delete mode 100644 include/mailutils/sys/stdio_stream.h
 create mode 100644 mailbox/rdcache_stream.c

diff --git a/examples/Makefile.am b/examples/Makefile.am
index f3fe13b..57992ac 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -49,9 +49,11 @@ noinst_PROGRAMS = \
  mimetest\
  msg-send\
  mta\
+ mucat\
  muauth\
  muemail\
  murun\
+ musocio\
  $(NNTPCLIENT)\
  $(POP3CLIENT)\
  sfrom\
diff --git a/examples/mucat.c b/examples/mucat.c
new file mode 100644
index 0000000..b8cb314
--- /dev/null
+++ b/examples/mucat.c
@@ -0,0 +1,87 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 1999, 2000, 2001, 2002, 2005, 2007, 2010 Free Software
+   Foundation, Inc.
+
+   GNU Mailutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GNU Mailutils 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Mailutils; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+   MA 02110-1301 USA */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <unistd.h>
+#include <stdio.h>
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
+#include <mailutils/mailutils.h>
+
+int
+main (int argc, char * argv [])
+{
+  int c;
+  mu_stream_t in, out;
+  int reread_option = 0;
+  mu_off_t reread_off;
+  int skip_option = 0;
+  mu_off_t skip_off;
+  
+  while ((c = getopt (argc, argv, "hs:r:")) != EOF)
+    switch (c)
+      {
+      case 'r':
+	reread_option = 1;
+	reread_off = strtoul (optarg, NULL, 10);
+	break;
+
+      case 's':
+	skip_option = 1;
+	skip_off = strtoul (optarg, NULL, 10);
+	break;
+
+      case 'h':
+	printf ("usage: cat [-s off]\n");
+	exit (0);
+
+      default:
+	exit (1);
+      }
+	
+
+  MU_ASSERT (mu_stdio_stream_create (&in, MU_STDIN_FD, MU_STREAM_SEEK));
+  MU_ASSERT (mu_stdio_stream_create (&out, MU_STDOUT_FD, 0));
+
+  if (skip_option)
+    {
+      mu_stream_printf (out, "skipping to %lu:\n",
+			(unsigned long) skip_off);
+      MU_ASSERT (mu_stream_seek (in, skip_off, MU_SEEK_SET, NULL));
+    }
+  
+  MU_ASSERT (mu_stream_copy (out, in, 0));
+
+  if (reread_option)
+    {
+      mu_stream_printf (out, "rereading from %lu:\n",
+			(unsigned long) reread_off);
+      MU_ASSERT (mu_stream_seek (in, reread_off, MU_SEEK_SET, NULL));
+      MU_ASSERT (mu_stream_copy (out, in, 0));
+    }
+  
+  mu_stream_close (in);
+  mu_stream_destroy (&in);
+  mu_stream_close (out);
+  mu_stream_destroy (&out);
+  return 0;
+}
diff --git a/examples/musocio.c b/examples/musocio.c
new file mode 100644
index 0000000..66bf346
--- /dev/null
+++ b/examples/musocio.c
@@ -0,0 +1,124 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 1999, 2000, 2001, 2002, 2005, 2007, 2010 Free Software
+   Foundation, Inc.
+
+   GNU Mailutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GNU Mailutils 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Mailutils; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+   MA 02110-1301 USA */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
+#include <mailutils/mailutils.h>
+
+int verbose;
+
+void
+ioloop (char *id, mu_stream_t in, mu_stream_t out)
+{
+  char *buf = NULL;
+  size_t size = 0, n;
+  int rc;
+  
+  while ((rc = mu_stream_getline (in, &buf, &size, &n)) == 0 && n > 0)
+    {
+      if (rc)
+	{
+	  mu_error("%s: read error: %s", id, mu_stream_strerror (in, rc));
+	  exit (1);
+	}
+      MU_ASSERT (mu_stream_write (out, buf, n, NULL));
+    }
+  mu_stream_flush (out);
+  if (verbose)
+    fprintf (stderr, "%s exited\n", id);
+}
+
+int
+main (int argc, char * argv [])
+{
+  mu_stream_t in, out, sock;
+  pid_t pid;
+  int status, c;
+
+  while ((c = getopt (argc, argv, "v")) != EOF)
+    switch (c)
+      {
+      case 'v':
+	verbose++;
+	break;
+
+      case 'h':
+	printf ("usage: musocio file\n");
+	return 0;
+
+      default:
+	return 1;
+      }
+
+  argc -= optind;
+  argv += optind;
+  
+  if (argc != 2)
+    {
+      mu_error ("usage: musocio file");
+      return 1;
+    }
+
+  MU_ASSERT (mu_stdio_stream_create (&in, MU_STDIN_FD, 0));
+  mu_stream_set_buffer (in, mu_buffer_line, 1024);
+  MU_ASSERT (mu_stdio_stream_create (&out, MU_STDOUT_FD, 0));
+  mu_stream_set_buffer (out, mu_buffer_line, 1024);
+  MU_ASSERT (mu_socket_stream_create (&sock, argv[1], MU_STREAM_RDWR));
+  mu_stream_set_buffer (sock, mu_buffer_line, 1024);
+  MU_ASSERT (mu_stream_open (sock));
+  
+  pid = fork ();
+  if (pid == -1)
+    {
+      mu_error ("fork failed: %s", mu_strerror (errno));
+      return 1;
+    }
+
+  if (pid == 0)
+    {
+      mu_stream_close (in);
+      mu_stream_destroy (&in);
+      ioloop ("reader", sock, out);
+      exit (0);
+    }
+
+  ioloop ("writer", in, sock);
+
+  mu_stream_close (in);
+  mu_stream_destroy (&in);
+
+  mu_stream_shutdown (sock, MU_STREAM_WRITE);
+  waitpid (pid, &status, 0);
+
+  mu_stream_close (sock);
+  mu_stream_destroy (&sock);
+  
+  mu_stream_close (out);
+  mu_stream_destroy (&out);
+  return 0;
+}
diff --git a/include/mailutils/stream.h b/include/mailutils/stream.h
index d9d3b5b..f2af9b3 100644
--- a/include/mailutils/stream.h
+++ b/include/mailutils/stream.h
@@ -120,6 +120,8 @@ int mu_stream_copy (mu_stream_t dst, mu_stream_t src, size_t size);
 
 int mu_file_stream_create (mu_stream_t *pstream, const char *filename, int flags);
 int mu_temp_file_stream_create (mu_stream_t *pstream, const char *dir);
+int mu_fd_stream_create (mu_stream_t *pstream, char *filename, int fd,
+			 int flags);
 
 #define MU_STDIN_FD  0
 #define MU_STDOUT_FD 1
@@ -157,4 +159,7 @@ int mu_iostream_create (mu_stream_t *pref, mu_stream_t in, mu_stream_t out);
 int mu_dbgstream_create(mu_stream_t *pref, mu_debug_t debug,
 			mu_log_level_t level, int flags);
 
+int mu_rdcache_stream_create (mu_stream_t *pstream, mu_stream_t transport,
+			      int flags);
+
 #endif
diff --git a/include/mailutils/sys/Makefile.am b/include/mailutils/sys/Makefile.am
index e8f073c..57a5dc0 100644
--- a/include/mailutils/sys/Makefile.am
+++ b/include/mailutils/sys/Makefile.am
@@ -49,9 +49,8 @@ sysinclude_HEADERS = \
  pop3.h\
  prog_stream.h\
  property.h\
+ rdcache_stream.h\
  registrar.h\
- socket_stream.h\
- stdio_stream.h\
  streamref.h\
  streamtrans.h\
  stream.h\
diff --git a/include/mailutils/sys/file_stream.h b/include/mailutils/sys/file_stream.h
index 0f1f8d2..70c576a 100644
--- a/include/mailutils/sys/file_stream.h
+++ b/include/mailutils/sys/file_stream.h
@@ -31,7 +31,7 @@ struct _mu_file_stream
   char *filename;
 };
 
-int _mu_file_stream_create (mu_stream_t *pstream, size_t size,
-			    char *filename, int flags);
+int _mu_file_stream_create (struct _mu_file_stream **pstream, size_t size,
+			    const char *filename, int fd, int flags);
 
 #endif
diff --git a/include/mailutils/sys/xscript-stream.h b/include/mailutils/sys/rdcache_stream.h
similarity index 85%
copy from include/mailutils/sys/xscript-stream.h
copy to include/mailutils/sys/rdcache_stream.h
index c6b4538..b6434be 100644
--- a/include/mailutils/sys/xscript-stream.h
+++ b/include/mailutils/sys/rdcache_stream.h
@@ -14,20 +14,20 @@
    You should have received a copy of the GNU Lesser General Public License
    along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
 
-#ifndef _MAILUTILS_SYS_XSCRIPT_STREAM_H
-# define _MAILUTILS_SYS_XSCRIPT_STREAM_H
+#ifndef _MAILUTILS_SYS_RDCACHE_STREAM_H
+# define _MAILUTILS_SYS_RDCACHE_STREAM_H
 
 # include <mailutils/types.h>
 # include <mailutils/stream.h>
 # include <mailutils/sys/stream.h>
 
-struct _mu_xscript_stream
+struct _mu_rdcache_stream
 {
   struct _mu_stream stream;
   mu_stream_t transport;
-  mu_stream_t logstr;
-  int flags;
-  char *prefix[2];
+  mu_stream_t cache;
+  mu_off_t size;
+  mu_off_t offset;
 };
 
 #endif
diff --git a/include/mailutils/sys/socket_stream.h b/include/mailutils/sys/socket_stream.h
deleted file mode 100644
index c4e382a..0000000
--- a/include/mailutils/sys/socket_stream.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 2009 Free Software Foundation, Inc.
-
-   This 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 3, or (at your option)
-   any later version.
-
-   This 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 GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
-
-#ifndef _MAILUTILS_SYS_SOCKET_STREAM_H
-#define _MAILUTILS_SYS_SOCKET_STREAM_H
-
-#include <mailutils/sys/stdio_stream.h>
-
-struct _mu_socket_stream
-{
-  struct _mu_stdio_stream stdio_stream;
-  char *filename;
-};
-
-#endif
diff --git a/include/mailutils/sys/stdio_stream.h b/include/mailutils/sys/stdio_stream.h
deleted file mode 100644
index 3b274dc..0000000
--- a/include/mailutils/sys/stdio_stream.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 2009 Free Software Foundation, Inc.
-
-   This 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 3, or (at your option)
-   any later version.
-
-   This 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 GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
-
-#ifndef _MAILUTILS_SYS_STDIO_STREAM_H
-#define _MAILUTILS_SYS_STDIO_STREAM_H
-
-#include <mailutils/sys/file_stream.h>
-
-#define _MU_STDIO_SIZE_COMPUTED 0x02
-
-struct _mu_stdio_stream
-{
-  struct _mu_file_stream file_stream;
-  mu_stream_t cache;
-  mu_off_t size;
-  mu_off_t offset;
-};
-
-int _mu_stdio_stream_create (mu_stream_t *pstream, size_t size, int flags);
-
-#endif
diff --git a/mailbox/Makefile.am b/mailbox/Makefile.am
index 1fd892d..7a82437 100644
--- a/mailbox/Makefile.am
+++ b/mailbox/Makefile.am
@@ -126,6 +126,7 @@ libmailutils_la_SOURCES = \
  prog_stream.c\
  property.c\
  qpflt.c\
+ rdcache_stream.c\
  registrar.c\
  refcount.c\
  rfc2047.c\
diff --git a/mailbox/file_stream.c b/mailbox/file_stream.c
index b74bfb0..7ffde02 100644
--- a/mailbox/file_stream.c
+++ b/mailbox/file_stream.c
@@ -146,6 +146,9 @@ fd_open (struct _mu_stream *str)
   if (fd < 0)
     return errno;
 
+  /* Make sure it will be closed */
+  fstr->flags |= MU_STREAM_AUTOCLOSE;
+
   fstr->fd = fd;
   return 0;
 }
@@ -207,6 +210,13 @@ fd_ioctl (struct _mu_stream *str, int code, void *ptr)
       ptrans[1] = NULL;
       break;
 
+    case MU_IOCTL_SET_TRANSPORT:
+      if (!ptr)
+	return EINVAL;
+      ptrans = ptr;
+      fstr->fd = (int) ptrans[0];
+      break;
+      
     default:
       return EINVAL;
     }
@@ -233,12 +243,11 @@ fd_truncate (mu_stream_t stream, mu_off_t size)
 }
 
 int
-_mu_file_stream_create (mu_stream_t *pstream, size_t size,
-			char *filename, int flags)
+_mu_file_stream_create (struct _mu_file_stream **pstream, size_t size,
+			const char *filename, int fd, int flags)
 {
   struct _mu_file_stream *str =
-    (struct _mu_file_stream *)
-      _mu_stream_create (size, flags | MU_STREAM_SEEK);
+    (struct _mu_file_stream *) _mu_stream_create (size, flags);
   if (!str)
     return ENOMEM;
 
@@ -254,25 +263,38 @@ _mu_file_stream_create (mu_stream_t *pstream, size_t size,
   str->stream.truncate = fd_truncate;
   str->stream.error_string = fd_error_string;
 
-  str->filename = filename;
-  str->fd = -1;
+  if (filename)
+    str->filename = mu_strdup (filename);
+  else
+    str->filename = NULL;
+  str->fd = fd;
   str->flags = 0;
-  *pstream = (mu_stream_t) str;
+  *pstream = str;
   return 0;
 }
 
 int
 mu_file_stream_create (mu_stream_t *pstream, const char *filename, int flags)
 {
-  int rc;
-  char *fname = mu_strdup (filename);
-  if (!fname)
-    return ENOMEM;
-  rc = _mu_file_stream_create (pstream,
-			       sizeof (struct _mu_file_stream),
-			       fname, flags | MU_STREAM_AUTOCLOSE);
-  if (rc)
-    free (fname);
+  struct _mu_file_stream *fstr;
+  int rc = _mu_file_stream_create (&fstr,
+				   sizeof (struct _mu_file_stream),
+				   filename, -1,
+				   flags | MU_STREAM_SEEK | MU_STREAM_AUTOCLOSE);
+  if (rc == 0)
+    *pstream = (mu_stream_t) fstr;
+  return rc;
+}
+
+int
+mu_fd_stream_create (mu_stream_t *pstream, char *filename, int fd, int flags)
+{
+  struct _mu_file_stream *fstr;
+  int rc = _mu_file_stream_create (&fstr,
+				   sizeof (struct _mu_file_stream),
+				   filename, fd, flags);
+  if (rc == 0)
+    *pstream = (mu_stream_t) fstr;
   return rc;
 }
 
diff --git a/mailbox/rdcache_stream.c b/mailbox/rdcache_stream.c
new file mode 100644
index 0000000..8a8afbf
--- /dev/null
+++ b/mailbox/rdcache_stream.c
@@ -0,0 +1,201 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
+
+   This 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 3, or (at your option)
+   any later version.
+
+   This 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 GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <errno.h>
+#include <mailutils/types.h>
+#include <mailutils/sys/rdcache_stream.h>
+
+size_t mu_rdcache_stream_max_memory_size = 4096;
+
+static int
+rdcache_read (struct _mu_stream *str, char *buf, size_t size, size_t *pnbytes)
+{
+  struct _mu_rdcache_stream *sp = (struct _mu_rdcache_stream *) str;
+  int status = 0;
+  size_t nbytes = 0;
+  
+  if (sp->offset < sp->size)
+    {
+      status = mu_stream_read (sp->cache, buf, size, &nbytes);
+      if (status)
+	return status;
+      sp->offset += nbytes;
+      sp->size += nbytes;
+      buf += nbytes;
+      size -= nbytes;
+    }
+  else if (sp->offset > sp->size)
+    {
+      size_t left = sp->offset - sp->size;
+      status = mu_stream_seek (sp->cache, 0, MU_SEEK_END, NULL);
+      if (status)
+	return status;
+      status = mu_stream_copy (sp->cache, sp->transport, left);
+      if (status)
+	return status;
+      sp->size = sp->offset;
+    }
+
+  if (size)
+    {
+      size_t rdbytes;
+      status = mu_stream_read (sp->transport, buf, size, &rdbytes);
+      if (rdbytes)
+	{
+	  int rc;
+
+	  sp->offset += rdbytes;
+	  sp->size += rdbytes;
+	  nbytes += rdbytes;
+	  rc = mu_stream_write (sp->cache, buf, rdbytes, NULL);
+	  if (rc)
+	    {
+	      if (status == 0)
+		status = rc;
+	    }
+	}
+    }
+  if (pnbytes)
+    *pnbytes = nbytes;
+  return status;
+}
+
+static int
+rdcache_size (struct _mu_stream *str, off_t *psize)
+{
+  struct _mu_rdcache_stream *sp = (struct _mu_rdcache_stream *) str;
+  *psize = sp->size;
+  return 0;
+}
+
+static int
+rdcache_seek (struct _mu_stream *str, mu_off_t off, mu_off_t *presult)
+{ 
+  struct _mu_rdcache_stream *sp = (struct _mu_rdcache_stream *) str;
+
+  if (off < 0)
+    return ESPIPE;
+
+  if (off < sp->size)
+    {
+      int status = mu_stream_seek (sp->cache, off, MU_SEEK_SET, NULL);
+      if (status)
+	return status;
+    }
+  
+  sp->offset = off;
+  *presult = sp->offset;
+  return 0;
+}
+
+static int
+rdcache_wait (struct _mu_stream *str, int *pflags, struct timeval *tvp)
+{
+  struct _mu_rdcache_stream *sp = (struct _mu_rdcache_stream *) str;
+  return mu_stream_wait (sp->transport, pflags, tvp);
+}
+
+/* FIXME: Truncate? */
+
+static int
+rdcache_ioctl (struct _mu_stream *str, int op, void *arg)
+{
+  struct _mu_rdcache_stream *sp = (struct _mu_rdcache_stream *) str;
+  mu_transport_t *ptrans;
+
+  switch (op)
+    {
+    case MU_IOCTL_GET_TRANSPORT:
+      if (!arg)
+	return EINVAL;
+      ptrans = arg;
+      ptrans[0] = (mu_transport_t) sp->transport;
+      ptrans[1] = NULL;
+      break;
+
+    default:
+      return EINVAL;
+    }
+  return 0;
+}
+
+static int
+rdcache_open (struct _mu_stream *str)
+{
+  struct _mu_rdcache_stream *sp = (struct _mu_rdcache_stream *) str;
+  return mu_stream_open (sp->transport);
+}
+
+static int
+rdcache_close (struct _mu_stream *str)
+{
+  struct _mu_rdcache_stream *sp = (struct _mu_rdcache_stream *) str;
+  return mu_stream_close (sp->transport);
+}
+
+static void
+rdcache_done (struct _mu_stream *str)
+{
+  struct _mu_rdcache_stream *sp = (struct _mu_rdcache_stream *) str;
+  mu_stream_unref (sp->transport);
+  mu_stream_unref (sp->cache);
+}
+  
+int
+mu_rdcache_stream_create (mu_stream_t *pstream, mu_stream_t transport,
+			  int flags)
+{
+  struct _mu_rdcache_stream *sp;
+  int rc;
+  int sflags = MU_STREAM_READ | MU_STREAM_SEEK | (flags & MU_STREAM_AUTOCLOSE);
+
+  if (flags & ~sflags)
+    return EINVAL;
+  
+  sp = (struct _mu_rdcache_stream *)
+          _mu_stream_create (sizeof (*sp), sflags);
+  if (!sp)
+    return ENOMEM;
+
+  sp->stream.read = rdcache_read;
+  sp->stream.open = rdcache_open;
+  sp->stream.close = rdcache_close;
+  sp->stream.done = rdcache_done;
+  sp->stream.seek = rdcache_seek; 
+  sp->stream.size = rdcache_size; 
+  sp->stream.ctl = rdcache_ioctl;
+  sp->stream.wait = rdcache_wait;
+
+  if (!(flags & MU_STREAM_AUTOCLOSE))
+    mu_stream_ref (transport);
+  sp->transport = transport;
+
+  if ((rc = mu_memory_stream_create (&sp->cache, MU_STREAM_RDWR))
+      || (rc = mu_stream_open (sp->cache)))
+    {
+      mu_stream_destroy ((mu_stream_t*) &sp);
+      return rc;
+    }
+  
+  *pstream = (mu_stream_t) sp;
+  return 0;
+}
+
diff --git a/mailbox/socket_stream.c b/mailbox/socket_stream.c
index 7ec4adc..2764b2b 100644
--- a/mailbox/socket_stream.c
+++ b/mailbox/socket_stream.c
@@ -31,22 +31,13 @@
 #include <mailutils/errno.h>
 #include <mailutils/nls.h>
 #include <mailutils/stream.h>
-#include <mailutils/sys/socket_stream.h>
-
-static void
-_socket_done (mu_stream_t stream)
-{
-  struct _mu_socket_stream *s = (struct _mu_socket_stream *) stream;
-
-  if (s->filename)
-    free (s->filename);
-}
+#include <mailutils/sys/file_stream.h>
 
 static int
 _socket_open (mu_stream_t stream)
 {
-  struct _mu_socket_stream *s = (struct _mu_socket_stream *) stream;
-  int fd, rc;
+  struct _mu_file_stream *s = (struct _mu_file_stream *) stream;
+  int fd;
   struct sockaddr_un addr;
   
   if (!s)
@@ -66,31 +57,15 @@ _socket_open (mu_stream_t stream)
       return errno;
     }
 
-  s->stdio_stream.file_stream.fd = fd;
-  s->stdio_stream.size = 0;
-  s->stdio_stream.offset = 0;
-  if (s->stdio_stream.cache)
-    mu_stream_truncate (s->stdio_stream.cache, 0);
+  s->fd = fd;
       
-  return rc;
-}
-
-static int
-_socket_close (mu_stream_t stream)
-{
-  struct _mu_socket_stream *s = (struct _mu_socket_stream *) stream;
-  if (s->stdio_stream.file_stream.fd != -1)
-    {
-      close (s->stdio_stream.file_stream.fd);
-      s->stdio_stream.file_stream.fd = -1;
-    }
   return 0;
 }
 
 int
 _socket_shutdown (mu_stream_t stream, int how)
 {
-  struct _mu_socket_stream *s = (struct _mu_socket_stream *) stream;
+  struct _mu_file_stream *s = (struct _mu_file_stream *) stream;
   int flag;
 
   switch (how)
@@ -103,7 +78,7 @@ _socket_shutdown (mu_stream_t stream, int how)
       flag = SHUT_WR;
     }
   
-  if (shutdown (s->stdio_stream.file_stream.fd, flag))
+  if (shutdown (s->fd, flag))
     return errno;
   return 0;
 }
@@ -111,17 +86,37 @@ _socket_shutdown (mu_stream_t stream, int how)
 int
 mu_socket_stream_create (mu_stream_t *pstream, const char *filename, int flags)
 {
-  struct _mu_socket_stream *s;
   int rc;
+  mu_stream_t transport;
+  int need_cache;
+  struct _mu_file_stream *fstr;
   
-  rc = _mu_stdio_stream_create (pstream, sizeof (*s),
-                                flags | MU_STREAM_AUTOCLOSE);
+  need_cache = flags & MU_STREAM_SEEK;
+  if (need_cache && (flags & MU_STREAM_WRITE))
+    /* Write caches are not supported */
+    return EINVAL;
+
+  /* Create transport stream. */
+  rc = _mu_file_stream_create (&fstr, sizeof (*fstr),
+			       filename, -1,
+			       (flags | MU_STREAM_AUTOCLOSE) & ~MU_STREAM_SEEK);
   if (rc)
     return rc;
-  s = (struct _mu_socket_stream *) *pstream;
-  s->stdio_stream.file_stream.stream.done = _socket_done;
-  s->stdio_stream.file_stream.stream.open = _socket_open;
-  s->stdio_stream.file_stream.stream.close = _socket_close;
-  s->stdio_stream.file_stream.stream.shutdown = _socket_shutdown;
+  fstr->stream.open = _socket_open;
+  fstr->stream.shutdown = _socket_shutdown;
+  transport = (mu_stream_t) fstr;
+  
+  /* Wrap it in cache, if required */
+  if (need_cache)
+    {
+      mu_stream_t str;
+      rc = mu_rdcache_stream_create (&str, transport, flags);
+      mu_stream_unref (transport);
+      if (rc)
+	return rc;
+      transport = str;
+    }
+
+  *pstream = transport;
   return 0;
 }
diff --git a/mailbox/stdio_stream.c b/mailbox/stdio_stream.c
index ae77d12..93ff011 100644
--- a/mailbox/stdio_stream.c
+++ b/mailbox/stdio_stream.c
@@ -22,166 +22,21 @@
 #include <unistd.h>
 #include <fcntl.h>
 
+#include <errno.h>
 #include <mailutils/types.h>
-#include <mailutils/alloc.h>
-#include <mailutils/error.h>
-#include <mailutils/errno.h>
-#include <mailutils/nls.h>
 #include <mailutils/stream.h>
 #include <mailutils/sys/stream.h>
-#include <mailutils/sys/stdio_stream.h>
-#include <mailutils/mutil.h>
-
-static int
-stdin_read (struct _mu_stream *str, char *buf, size_t size, size_t *pnbytes)
-{
-  struct _mu_stdio_stream *fs = (struct _mu_stdio_stream *) str;
-  int fd = fs->file_stream.fd;
-  int status = 0;
-  size_t nbytes;
-  ssize_t rdbytes;
-  
-  if (fs->offset < fs->size)
-    {
-      status = mu_stream_read (fs->cache, buf, size, &nbytes);
-      if (status)
-	fs->offset += nbytes;
-    }
-  else if (fs->offset > fs->size)
-    {
-      size_t left = fs->offset - fs->size + 1;
-      char sbuf[1024];
-      size_t bufsize;
-      char *tmpbuf = malloc (left);
-      if (tmpbuf)
-	bufsize = left;
-      else
-	{
-	  tmpbuf = sbuf;
-	  bufsize = sizeof sbuf;
-	}
-
-      while (left > 0)
-	{
-	  size_t n;
-	  
-	  rdbytes = read (fd, tmpbuf, bufsize);
-	  if (rdbytes < 0)
-	    {
-	      status = errno;
-	      break;
-	    }
-	  if (rdbytes == 0)
-	    {
-	      status = EIO; /* FIXME: EOF?? */
-	      break;
-	    }
-	  
-	  status = mu_stream_write (fs->cache, tmpbuf, rdbytes, &n);
-	  fs->offset += n;
-	  left -= n;
-	  if (status)
-	    break;
-	}
-      if (tmpbuf != sbuf)
-	free (tmpbuf);
-      if (status)
-	return status;
-    }
-  
-  nbytes = read (fd, buf, size);
-  if (nbytes <= 0)
-    return EIO;
-  else
-    {
-      status = mu_stream_write (fs->cache, buf, nbytes, NULL);
-      if (status)
-	return status;
-    }
-  fs->offset += nbytes;
-  fs->size += nbytes;
-  
-  if (pnbytes)
-    *pnbytes = nbytes;
-  return status;
-}
-
-static int
-stdout_write (struct _mu_stream *str, const char *buf, size_t size,
-	      size_t *pret)
-{
-  struct _mu_stdio_stream *fstr = (struct _mu_stdio_stream *) str;
-  int n = write (fstr->file_stream.fd, (char*) buf, size);
-  if (n == -1)
-    return errno;
-  fstr->size += n;
-  fstr->offset += n;
-  return 0;
-}
-
-static int
-stdio_size (struct _mu_stream *str, off_t *psize)
-{
-  struct _mu_stdio_stream *fs = (struct _mu_stdio_stream *) str;
-  *psize = fs->size;
-  return 0;
-}
-
-static int
-stdio_seek (struct _mu_stream *str, mu_off_t off, mu_off_t *presult)
-{ 
-  struct _mu_stdio_stream *fs = (struct _mu_stdio_stream *) str;
-
-  if (off < 0)
-    return ESPIPE;
-
-  fs->offset = off;
-  *presult = fs->offset;
-  return 0;
-}
-
-int
-_mu_stdio_stream_create (mu_stream_t *pstream, size_t size, int flags)
-{
-  struct _mu_stdio_stream *fs;
-  int rc;
-
-  rc = _mu_file_stream_create (pstream, size, NULL, flags);
-  if (rc)
-    return rc;
-  fs = (struct _mu_stdio_stream *) *pstream;
-  
-  if (flags & MU_STREAM_SEEK)
-    {
-      if ((rc = mu_memory_stream_create (&fs->cache, MU_STREAM_RDWR))
-	  || (rc = mu_stream_open (fs->cache)))
-	{
-	  mu_stream_destroy ((mu_stream_t*) &fs);
-	  return rc;
-	}
-      fs->file_stream.stream.read = stdin_read;
-      fs->file_stream.stream.write = stdout_write;
-      fs->file_stream.stream.size = stdio_size;
-      fs->file_stream.stream.seek = stdio_seek;
-    }
-  else
-    {
-      fs->file_stream.stream.flags &= ~MU_STREAM_SEEK;
-      fs->file_stream.stream.seek = NULL;
-    }
-  fs->file_stream.stream.open = NULL;
-  fs->file_stream.fd = -1;
-  return 0;
-}
+#include <mailutils/sys/file_stream.h>
 
 int
 mu_stdio_stream_create (mu_stream_t *pstream, int fd, int flags)
 {
   int rc;
-  struct _mu_stdio_stream *fs;
-
-  if (flags & MU_STREAM_SEEK && lseek (fd, 0, 0) == 0)
-    flags &= ~MU_STREAM_SEEK;
+  char *filename;
+  mu_stream_t transport;
+  int need_cache;
+  struct _mu_file_stream *fstr;
+  
   switch (fd)
     {
     case MU_STDIN_FD:
@@ -193,11 +48,36 @@ mu_stdio_stream_create (mu_stream_t *pstream, int fd, int flags)
       flags |= MU_STREAM_WRITE;
     }
 
-  rc = _mu_stdio_stream_create (pstream, sizeof (*fs), flags);
-  if (rc == 0)
+  need_cache = flags & MU_STREAM_SEEK;
+  if (need_cache && (flags & MU_STREAM_WRITE))
+    /* Write caches are not supported */
+    return EINVAL;
+
+  if (flags & MU_STREAM_READ)
+    filename = "<stdin>";
+  else
+    filename = "<stdout>";
+
+  /* Create transport stream. */
+  rc = _mu_file_stream_create (&fstr, sizeof (*fstr),
+			       filename, fd, flags & ~MU_STREAM_SEEK);
+  if (rc)
+    return rc;
+  fstr->stream.open = NULL;
+  transport = (mu_stream_t) fstr;
+  
+  /* Wrap it in cache, if required */
+  if (need_cache)
     {
-      fs = (struct _mu_stdio_stream *) *pstream;
-      fs->file_stream.fd = fd;
+      mu_stream_t str;
+      rc = mu_rdcache_stream_create (&str, transport, flags);
+      mu_stream_unref (transport);
+      if (rc)
+	return rc;
+      transport = str;
     }
-  return rc;
+
+  *pstream = transport;
+  return 0;
 }
+
diff --git a/mailbox/streamcpy.c b/mailbox/streamcpy.c
index 7b2d70b..ec56a7a 100644
--- a/mailbox/streamcpy.c
+++ b/mailbox/streamcpy.c
@@ -69,6 +69,8 @@ mu_stream_copy (mu_stream_t dst, mu_stream_t src, size_t size)
 	      size -= pos;
 	      break;
       
+	    case EACCES:
+	      mu_stream_clearerr (src);
 	    case ENOSYS:
 	      break;
 
diff --git a/mailbox/temp_file_stream.c b/mailbox/temp_file_stream.c
index f81dada..c5346b2 100644
--- a/mailbox/temp_file_stream.c
+++ b/mailbox/temp_file_stream.c
@@ -48,28 +48,18 @@ int
 mu_temp_file_stream_create (mu_stream_t *pstream, const char *dir)
 {
   int rc;
-  char *fname;
   struct _mu_file_stream *str;
 
-  if (!dir)
-    fname = NULL;
-  else if ((fname = mu_strdup (dir)) == NULL)
-    return ENOMEM;
-  
-  rc = _mu_file_stream_create (pstream,
+  rc = _mu_file_stream_create (&str,
 			       sizeof (struct _mu_file_stream),
-			       fname, 
-			       MU_STREAM_RDWR | MU_STREAM_CREAT | 
+			       dir,
+			       -1,
+			       MU_STREAM_RDWR | MU_STREAM_SEEK |
+			       MU_STREAM_CREAT | 
 			       MU_STREAM_AUTOCLOSE);
-  if (rc)
-    {
-      free (fname);
-      return rc;
-    }
-  str = (struct _mu_file_stream *) *pstream;
 
   str->stream.open = fd_temp_open;
   str->flags = _MU_FILE_STREAM_TEMP;
-
+  *pstream = (mu_stream_t) str;
   return 0;
 }


hooks/post-receive
-- 
GNU Mailutils
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.