aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/iobuf.c118
-rw-r--r--common/iobuf.h6
2 files changed, 89 insertions, 35 deletions
diff --git a/common/iobuf.c b/common/iobuf.c
index 5a9fd7caf..bf5977843 100644
--- a/common/iobuf.c
+++ b/common/iobuf.c
@@ -62,7 +62,7 @@
/* The size of the internal buffers.
NOTE: If you change this value you MUST also adjust the regression
test "armored_key_8192" in armor.test! */
-#define IOBUF_BUFFER_SIZE 8192
+#define DEFAULT_IOBUF_BUFFER_SIZE (64*1024)
/* To avoid a potential DoS with compression packets we better limit
the number of filters in a chain. */
@@ -70,6 +70,10 @@
/*-- End configurable part. --*/
+/* The size of the iobuffers. This can be chnages using the
+ * iobuf_set_buffer_size fucntion. */
+static unsigned int iobuf_buffer_size = DEFAULT_IOBUF_BUFFER_SIZE;
+
#ifdef HAVE_W32_SYSTEM
# ifdef HAVE_W32CE_SYSTEM
@@ -92,6 +96,7 @@ typedef struct
int keep_open;
int no_cache;
int eof_seen;
+ int delayed_rc;
int print_only_name; /* Flags indicating that fname is not a real file. */
char fname[1]; /* Name of the file. */
} file_filter_ctx_t;
@@ -167,7 +172,7 @@ static int translate_file_handle (int fd, int for_write);
to be sent to A's filter function.
If A is a IOBUF_OUTPUT_TEMP filter, then this also enlarges the
- buffer by IOBUF_BUFFER_SIZE.
+ buffer by iobuf_buffer_size.
May only be called on an IOBUF_OUTPUT or IOBUF_OUTPUT_TEMP filters. */
static int filter_flush (iobuf_t a);
@@ -451,12 +456,20 @@ file_filter (void *opaque, int control, iobuf_t chain, byte * buf,
if (control == IOBUFCTRL_UNDERFLOW)
{
- assert (size); /* We need a buffer. */
+ log_assert (size); /* We need a buffer. */
if (a->eof_seen)
{
rc = -1;
*ret_len = 0;
}
+ else if (a->delayed_rc)
+ {
+ rc = a->delayed_rc;
+ a->delayed_rc = 0;
+ if (rc == -1)
+ a->eof_seen = -1;
+ *ret_len = 0;
+ }
else
{
#ifdef HAVE_W32_SYSTEM
@@ -487,29 +500,39 @@ file_filter (void *opaque, int control, iobuf_t chain, byte * buf,
int n;
nbytes = 0;
- do
- {
- n = read (f, buf, size);
- }
- while (n == -1 && errno == EINTR);
- if (n == -1)
- { /* error */
- if (errno != EPIPE)
- {
- rc = gpg_error_from_syserror ();
- log_error ("%s: read error: %s\n",
- a->fname, strerror (errno));
- }
- }
- else if (!n)
- { /* eof */
- a->eof_seen = 1;
- rc = -1;
- }
- else
- {
- nbytes = n;
- }
+ read_more:
+ do
+ {
+ n = read (f, buf + nbytes, size - nbytes);
+ }
+ while (n == -1 && errno == EINTR);
+ if (n > 0)
+ {
+ nbytes += n;
+ if (nbytes < size)
+ goto read_more;
+ }
+ else if (!n) /* eof */
+ {
+ if (nbytes)
+ a->delayed_rc = -1;
+ else
+ {
+ a->eof_seen = 1;
+ rc = -1;
+ }
+ }
+ else /* error */
+ {
+ rc = gpg_error_from_syserror ();
+ if (gpg_err_code (rc) != GPG_ERR_EPIPE)
+ log_error ("%s: read error: %s\n", a->fname, gpg_strerror (rc));
+ if (nbytes)
+ {
+ a->delayed_rc = rc;
+ rc = 0;
+ }
+ }
#endif
*ret_len = nbytes;
}
@@ -569,6 +592,7 @@ file_filter (void *opaque, int control, iobuf_t chain, byte * buf,
else if (control == IOBUFCTRL_INIT)
{
a->eof_seen = 0;
+ a->delayed_rc = 0;
a->keep_open = 0;
a->no_cache = 0;
}
@@ -1053,6 +1077,30 @@ block_filter (void *opaque, int control, iobuf_t chain, byte * buffer,
return rc;
}
+
+/* Change the default size for all IOBUFs to KILOBYTE. This needs to
+ * be called before any iobufs are used and can only be used once.
+ * Returns the current value. Using 0 has no effect except for
+ * returning the current value. */
+unsigned int
+iobuf_set_buffer_size (unsigned int kilobyte)
+{
+ static int used;
+
+ if (!used && kilobyte)
+ {
+ if (kilobyte < 4)
+ kilobyte = 4;
+ else if (kilobyte > 16*1024)
+ kilobyte = 16*1024;
+
+ iobuf_buffer_size = kilobyte * 1024;
+ used = 1;
+ }
+ return iobuf_buffer_size / 1024;
+}
+
+
#define MAX_IOBUF_DESC 32
/*
* Fill the buffer by the description of iobuf A.
@@ -1105,7 +1153,7 @@ iobuf_alloc (int use, size_t bufsize)
if (bufsize == 0)
{
log_bug ("iobuf_alloc() passed a bufsize of 0!\n");
- bufsize = IOBUF_BUFFER_SIZE;
+ bufsize = iobuf_buffer_size;
}
a = xcalloc (1, sizeof *a);
@@ -1213,7 +1261,7 @@ iobuf_cancel (iobuf_t a)
iobuf_t
iobuf_temp (void)
{
- return iobuf_alloc (IOBUF_OUTPUT_TEMP, IOBUF_BUFFER_SIZE);
+ return iobuf_alloc (IOBUF_OUTPUT_TEMP, iobuf_buffer_size);
}
iobuf_t
@@ -1288,7 +1336,7 @@ do_open (const char *fname, int special_filenames,
return NULL;
}
- a = iobuf_alloc (use, IOBUF_BUFFER_SIZE);
+ a = iobuf_alloc (use, iobuf_buffer_size);
fcx = xmalloc (sizeof *fcx + strlen (fname));
fcx->fp = fp;
fcx->print_only_name = print_only;
@@ -1335,7 +1383,7 @@ do_iobuf_fdopen (int fd, const char *mode, int keep_open)
fp = INT2FD (fd);
a = iobuf_alloc (strchr (mode, 'w') ? IOBUF_OUTPUT : IOBUF_INPUT,
- IOBUF_BUFFER_SIZE);
+ iobuf_buffer_size);
fcx = xmalloc (sizeof *fcx + 20);
fcx->fp = fp;
fcx->print_only_name = 1;
@@ -1373,7 +1421,7 @@ iobuf_esopen (estream_t estream, const char *mode, int keep_open)
size_t len = 0;
a = iobuf_alloc (strchr (mode, 'w') ? IOBUF_OUTPUT : IOBUF_INPUT,
- IOBUF_BUFFER_SIZE);
+ iobuf_buffer_size);
fcx = xtrymalloc (sizeof *fcx + 30);
fcx->fp = estream;
fcx->print_only_name = 1;
@@ -1398,7 +1446,7 @@ iobuf_sockopen (int fd, const char *mode)
size_t len;
a = iobuf_alloc (strchr (mode, 'w') ? IOBUF_OUTPUT : IOBUF_INPUT,
- IOBUF_BUFFER_SIZE);
+ iobuf_buffer_size);
scx = xmalloc (sizeof *scx + 25);
scx->sock = fd;
scx->print_only_name = 1;
@@ -1599,13 +1647,13 @@ iobuf_push_filter2 (iobuf_t a,
increased accordingly. We don't need to allocate a 10 MB
buffer for a non-terminal filter. Just use the default
size. */
- a->d.size = IOBUF_BUFFER_SIZE;
+ a->d.size = iobuf_buffer_size;
}
else if (a->use == IOBUF_INPUT_TEMP)
/* Same idea as above. */
{
a->use = IOBUF_INPUT;
- a->d.size = IOBUF_BUFFER_SIZE;
+ a->d.size = iobuf_buffer_size;
}
/* The new filter (A) gets a new buffer.
@@ -1922,7 +1970,7 @@ filter_flush (iobuf_t a)
if (a->use == IOBUF_OUTPUT_TEMP)
{ /* increase the temp buffer */
- size_t newsize = a->d.size + IOBUF_BUFFER_SIZE;
+ size_t newsize = a->d.size + iobuf_buffer_size;
if (DBG_IOBUF)
log_debug ("increasing temp iobuf from %lu to %lu\n",
diff --git a/common/iobuf.h b/common/iobuf.h
index 22e02daad..16156383c 100644
--- a/common/iobuf.h
+++ b/common/iobuf.h
@@ -259,6 +259,12 @@ struct iobuf_struct
EXTERN_UNLESS_MAIN_MODULE int iobuf_debug_mode;
+/* Change the default size for all IOBUFs to KILOBYTE. This needs to
+ * be called before any iobufs are used and can only be used once.
+ * Returns the current value. Using 0 has no effect except for
+ * returning the current value. */
+unsigned int iobuf_set_buffer_size (unsigned int kilobyte);
+
/* Returns whether the specified filename corresponds to a pipe. In
particular, this function checks if FNAME is "-" and, if special
filenames are enabled (see check_special_filename), whether