diff options
Diffstat (limited to 'kbx/keybox-init.c')
-rw-r--r-- | kbx/keybox-init.c | 126 |
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; } } |