commit-mailutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, stream-cleanup, updated. rel-2_1-128-gbfb29ce
Date: Mon, 06 Sep 2010 16:27:24 +0000

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 <address@hidden>
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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]