aboutsummaryrefslogtreecommitdiffstats
path: root/common/iobuf.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2011-01-18 11:50:02 +0000
committerWerner Koch <[email protected]>2011-01-18 11:50:02 +0000
commitc2c5d30db8c0411afaaaeb1653096498894a38a8 (patch)
tree88ff681139f7d72967cf3d41793264e6b86869f5 /common/iobuf.c
parentFix es_fopenmem and es_mopen bug. (diff)
downloadgnupg-c2c5d30db8c0411afaaaeb1653096498894a38a8.tar.gz
gnupg-c2c5d30db8c0411afaaaeb1653096498894a38a8.zip
estream support for iobuf and new memuf functions.
Diffstat (limited to 'common/iobuf.c')
-rw-r--r--common/iobuf.c127
1 files changed, 126 insertions, 1 deletions
diff --git a/common/iobuf.c b/common/iobuf.c
index b9bed3218..9813d3da6 100644
--- a/common/iobuf.c
+++ b/common/iobuf.c
@@ -1,6 +1,6 @@
/* iobuf.c - File Handling for OpenPGP.
* Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2006, 2007, 2008,
- * 2009, 2010 Free Software Foundation, Inc.
+ * 2009, 2010, 2011 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -78,6 +78,17 @@ typedef struct
char fname[1]; /* Name of the file. */
} file_filter_ctx_t;
+/* The context used by the estream filter. */
+typedef struct
+{
+ estream_t fp; /* Open estream handle. */
+ int keep_open;
+ int no_cache;
+ int eof_seen;
+ int print_only_name; /* Flags indicating that fname is not a real file. */
+ char fname[1]; /* Name of the file. */
+} file_es_filter_ctx_t;
+
/* Object to control the "close cache". */
struct close_cache_s
@@ -577,6 +588,96 @@ file_filter (void *opaque, int control, iobuf_t chain, byte * buf,
}
+/* Similar to file_filter but using the estream system. */
+static int
+file_es_filter (void *opaque, int control, iobuf_t chain, byte * buf,
+ size_t * ret_len)
+{
+ file_es_filter_ctx_t *a = opaque;
+ estream_t f = a->fp;
+ size_t size = *ret_len;
+ size_t nbytes = 0;
+ int rc = 0;
+
+ (void)chain; /* Not used. */
+
+ if (control == IOBUFCTRL_UNDERFLOW)
+ {
+ assert (size); /* We need a buffer. */
+ if (a->eof_seen)
+ {
+ rc = -1;
+ *ret_len = 0;
+ }
+ else
+ {
+ nbytes = 0;
+ rc = es_read (f, buf, size, &nbytes);
+ if (rc == -1)
+ { /* error */
+ rc = gpg_error_from_syserror ();
+ log_error ("%s: read error: %s\n", a->fname, strerror (errno));
+ }
+ else if (!nbytes)
+ { /* eof */
+ a->eof_seen = 1;
+ rc = -1;
+ }
+ *ret_len = nbytes;
+ }
+ }
+ else if (control == IOBUFCTRL_FLUSH)
+ {
+ if (size)
+ {
+ byte *p = buf;
+ size_t nwritten;
+
+ nbytes = size;
+ do
+ {
+ nwritten = 0;
+ if (es_write (f, p, nbytes, &nwritten))
+ {
+ rc = gpg_error_from_syserror ();
+ log_error ("%s: write error: %s\n",
+ a->fname, strerror (errno));
+ break;
+ }
+ p += nwritten;
+ nbytes -= nwritten;
+ }
+ while (nbytes);
+ nbytes = p - buf;
+ }
+ *ret_len = nbytes;
+ }
+ else if (control == IOBUFCTRL_INIT)
+ {
+ a->eof_seen = 0;
+ a->no_cache = 0;
+ }
+ else if (control == IOBUFCTRL_DESC)
+ {
+ *(char **) buf = "estream_filter";
+ }
+ else if (control == IOBUFCTRL_FREE)
+ {
+ if (f != es_stdin && f != es_stdout)
+ {
+ if (DBG_IOBUF)
+ log_debug ("%s: es_fclose %p\n", a->fname, f);
+ if (!a->keep_open)
+ es_fclose (f);
+ }
+ f = NULL;
+ xfree (a); /* We can free our context now. */
+ }
+
+ return rc;
+}
+
+
#ifdef HAVE_W32_SYSTEM
/* Because network sockets are special objects under Lose32 we have to
use a dedicated filter for them. */
@@ -1258,6 +1359,30 @@ iobuf_fdopen_nc (int fd, const char *mode)
iobuf_t
+iobuf_esopen (estream_t estream, const char *mode, int keep_open)
+{
+ iobuf_t a;
+ file_es_filter_ctx_t *fcx;
+ size_t len;
+
+ a = iobuf_alloc (strchr (mode, 'w') ? 2 : 1, IOBUF_BUFFER_SIZE);
+ fcx = xtrymalloc (sizeof *fcx + 30);
+ fcx->fp = estream;
+ fcx->print_only_name = 1;
+ fcx->keep_open = keep_open;
+ sprintf (fcx->fname, "[fd %p]", estream);
+ a->filter = file_es_filter;
+ a->filter_ov = fcx;
+ file_es_filter (fcx, IOBUFCTRL_DESC, NULL, (byte *) & a->desc, &len);
+ file_es_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len);
+ if (DBG_IOBUF)
+ log_debug ("iobuf-%d.%d: esopen%s `%s'\n",
+ a->no, a->subno, keep_open? "_nc":"", fcx->fname);
+ return a;
+}
+
+
+iobuf_t
iobuf_sockopen (int fd, const char *mode)
{
iobuf_t a;