1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-05-31 22:18:03 +02:00

common/iobuf.c: Improve iobuf_peek.

* common/iobuf.c (underflow): Take additional parameter
clear_pending_eof.  If not set, don't clear a pending eof when
returning EOF.  Update callers.
(iobuf_peek): Fill the internal buffer, if needed, to be able to
better satisfy any request.

--
Signed-off-by: Neal H. Walfield <neal@g10code.com>.
This commit is contained in:
Neal H. Walfield 2015-08-12 22:57:58 +02:00
parent c7ad36eb0d
commit a250f73783

View File

@ -161,7 +161,7 @@ block_filter_ctx_t;
static int special_names_enabled; static int special_names_enabled;
/* Local prototypes. */ /* Local prototypes. */
static int underflow (iobuf_t a); static int underflow (iobuf_t a, int clear_pending_eof);
static int translate_file_handle (int fd, int for_write); static int translate_file_handle (int fd, int for_write);
@ -1762,7 +1762,7 @@ pop_filter (iobuf_t a, int (*f) (void *opaque, int control,
* the first byte or -1 on EOF. * the first byte or -1 on EOF.
*/ */
static int static int
underflow (iobuf_t a) underflow (iobuf_t a, int clear_pending_eof)
{ {
size_t len; size_t len;
int rc; int rc;
@ -1792,6 +1792,9 @@ underflow (iobuf_t a)
if (DBG_IOBUF) if (DBG_IOBUF)
log_debug ("iobuf-%d.%d: underflow: eof (pending eof)\n", log_debug ("iobuf-%d.%d: underflow: eof (pending eof)\n",
a->no, a->subno); a->no, a->subno);
if (! clear_pending_eof)
return -1;
if (a->chain) if (a->chain)
/* A filter follows this one. Free this filter. */ /* A filter follows this one. Free this filter. */
{ {
@ -1865,7 +1868,7 @@ underflow (iobuf_t a)
a->filter = NULL; a->filter = NULL;
a->filter_eof = 1; a->filter_eof = 1;
if (a->d.len == 0 && a->chain) if (clear_pending_eof && a->d.len == 0 && a->chain)
/* We don't need to keep this filter around at all: /* We don't need to keep this filter around at all:
- we got an EOF - we got an EOF
@ -1967,7 +1970,7 @@ iobuf_readbyte (iobuf_t a)
{ {
c = a->d.buf[a->d.start++]; c = a->d.buf[a->d.start++];
} }
else if ((c = underflow (a)) == -1) else if ((c = underflow (a, 1)) == -1)
return -1; /* EOF */ return -1; /* EOF */
a->nbytes++; a->nbytes++;
@ -2017,7 +2020,7 @@ iobuf_read (iobuf_t a, void *buffer, unsigned int buflen)
} }
if (n < buflen) if (n < buflen)
{ {
if ((c = underflow (a)) == -1) if ((c = underflow (a, 1)) == -1)
{ {
a->nbytes += n; a->nbytes += n;
return n ? n : -1 /*EOF*/; return n ? n : -1 /*EOF*/;
@ -2034,29 +2037,42 @@ iobuf_read (iobuf_t a, void *buffer, unsigned int buflen)
/****************
* Have a look at the iobuf.
* NOTE: This only works in special cases.
*/
int int
iobuf_peek (iobuf_t a, byte * buf, unsigned buflen) iobuf_peek (iobuf_t a, byte * buf, unsigned buflen)
{ {
int n = 0; int n = 0;
if (a->filter_eof) assert (buflen > 0);
return -1; assert (a->use == IOBUF_INPUT);
if (!(a->d.start < a->d.len)) if (buflen > a->d.size)
/* We can't peek more than we can buffer. */
buflen = a->d.size;
/* Try to fill the internal buffer with enough data to satisfy the
request. */
while (buflen > a->d.len - a->d.start)
{ {
if (underflow (a) == -1) if (underflow (a, 0) == -1)
return -1; /* EOF. We can't read any more. */
/* And unget this character. */ break;
/* Underflow consumes the first character (it's the return
value). unget() it by resetting the "file position". */
assert (a->d.start == 1); assert (a->d.start == 1);
a->d.start = 0; a->d.start = 0;
} }
for (n = 0; n < buflen && (a->d.start + n) < a->d.len; n++, buf++) n = a->d.len - a->d.start;
*buf = a->d.buf[n]; if (n > buflen)
n = buflen;
if (n == 0)
/* EOF. */
return -1;
memcpy (buf, &a->d.buf[a->d.start], n);
return n; return n;
} }