summaryrefslogtreecommitdiffstats
path: root/kbx/keybox-init.c
diff options
context:
space:
mode:
Diffstat (limited to 'kbx/keybox-init.c')
-rw-r--r--kbx/keybox-init.c126
1 files changed, 124 insertions, 2 deletions
diff --git a/kbx/keybox-init.c b/kbx/keybox-init.c
index f07ba8d..1318e3e 100644
--- a/kbx/keybox-init.c
+++ b/kbx/keybox-init.c
@@ -28,8 +28,26 @@
#include "../common/sysutils.h"
#include "../common/mischelp.h"
+#ifdef HAVE_W32_SYSTEM
+# define DEFAULT_LL_BUFFER_SIZE 128
+#else
+# define DEFAULT_LL_BUFFER_SIZE 64
+#endif
+
+static unsigned int ll_buffer_size = DEFAULT_LL_BUFFER_SIZE;
+
static KB_NAME kb_names;
+/* This object is used to mahe setvbuf buffers. We use a short arary
+ * to be able to reuse already allocated buffers. */
+struct stream_buffer_s
+{
+ int inuse; /* True if used by a stream. */
+ size_t bufsize;
+ char *buf;
+};
+static struct stream_buffer_s stream_buffers[5];
+
/* Register a filename for plain keybox files. Returns 0 on success,
* GPG_ERR_EEXIST if it has already been registered, or another error
@@ -85,6 +103,16 @@ keybox_is_writable (void *token)
}
+/* Change the default buffering to KBYTES KiB; using 0 uses the syste
+ * buffers. This function must be called early. */
+void
+keybox_set_buffersize (unsigned int kbytes, int reserved)
+{
+ (void)reserved;
+ /* Round down to 8k multiples. */
+ ll_buffer_size = (kbytes + 7)/8 * 8;
+}
+
static KEYBOX_HANDLE
do_keybox_new (KB_NAME resource, int secret, int for_openpgp)
@@ -180,7 +208,7 @@ keybox_release (KEYBOX_HANDLE hd)
_keybox_release_blob (hd->saved_found.blob);
if (hd->fp)
{
- es_fclose (hd->fp);
+ _keybox_ll_close (hd->fp);
hd->fp = NULL;
}
xfree (hd->word_match.name);
@@ -236,6 +264,100 @@ keybox_set_ephemeral (KEYBOX_HANDLE hd, int yes)
}
+/* Low-level open function to be used for keybox files. This function
+ * also manages custom buffering. On success 0 is returned and a new
+ * file pointer stored at RFP; on error an error code is returned and
+ * NULL is stored at RFP. MODE is one of
+ * KEYBOX_LL_OPEN_READ(0) := fopen mode is "rb"
+ * KEYBOX_LL_OPEN_UPDATE := fopen mode is "r+b"
+ * KEYBOX_LL_OPEN_CREATE := fopen mode is "wb"
+ */
+gpg_error_t
+_keybox_ll_open (estream_t *rfp, const char *fname, unsigned int mode)
+{
+ estream_t fp;
+ int i;
+ size_t bufsize;
+
+ *rfp = NULL;
+
+ fp = es_fopen (fname,
+ mode == KEYBOX_LL_OPEN_CREATE
+ ? "wb,sysopen,sequential" :
+ mode == KEYBOX_LL_OPEN_UPDATE
+ ? "r+b,sysopen,sequential" :
+ "rb,sysopen,sequential");
+ if (!fp)
+ return gpg_error_from_syserror ();
+
+ if (ll_buffer_size)
+ {
+ for (i=0; i < DIM (stream_buffers); i++)
+ if (!stream_buffers[i].inuse)
+ {
+ /* There is a free slot - we can use a larger buffer. */
+ stream_buffers[i].inuse = 1;
+ if (!stream_buffers[i].buf)
+ {
+ bufsize = ll_buffer_size * 1024;
+ stream_buffers[i].buf = xtrymalloc (bufsize);
+ if (stream_buffers[i].buf)
+ stream_buffers[i].bufsize = bufsize;
+ else
+ {
+ log_info ("can't allocate a large buffer for a kbx file;"
+ " using default\n");
+ stream_buffers[i].inuse = 0;
+ }
+ }
+
+ if (stream_buffers[i].buf)
+ {
+ es_setvbuf (fp, stream_buffers[i].buf, _IOFBF,
+ stream_buffers[i].bufsize);
+ es_opaque_set (fp, stream_buffers + i);
+ }
+ break;
+ }
+ }
+
+ *rfp = fp;
+ return 0;
+}
+
+
+/* Wrapper around es_fclose to be used for file opened with
+ * _keybox_ll_open. */
+gpg_error_t
+_keybox_ll_close (estream_t fp)
+{
+ gpg_error_t err;
+ struct stream_buffer_s *sbuf;
+ int i;
+
+ if (!fp)
+ return 0;
+
+ sbuf = ll_buffer_size? es_opaque_get (fp) : NULL;
+ if (es_fclose (fp))
+ err = gpg_error_from_syserror ();
+ else
+ err = 0;
+ if (sbuf)
+ {
+ for (i=0; i < DIM (stream_buffers); i++)
+ if (stream_buffers + i == sbuf)
+ break;
+ log_assert (i < DIM (stream_buffers));
+ stream_buffers[i].inuse = 0;
+ }
+
+
+ return err;
+}
+
+
+
/* Close the file of the resource identified by HD. For consistent
results this function closes the files of all handles pointing to
the resource identified by HD. */
@@ -253,7 +375,7 @@ _keybox_close_file (KEYBOX_HANDLE hd)
{
if (roverhd->fp)
{
- es_fclose (roverhd->fp);
+ _keybox_ll_close (roverhd->fp);
roverhd->fp = NULL;
}
}