diff --git a/common/iobuf.c b/common/iobuf.c index 05944255f..db5d062cd 100644 --- a/common/iobuf.c +++ b/common/iobuf.c @@ -106,6 +106,8 @@ typedef struct int keep_open; int no_cache; int eof_seen; + int use_readlimit; /* Take care of the readlimit. */ + size_t readlimit; /* Number of bytes left to read. */ 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; @@ -635,6 +637,34 @@ file_es_filter (void *opaque, int control, iobuf_t chain, byte * buf, rc = -1; *ret_len = 0; } + else if (a->use_readlimit) + { + nbytes = 0; + if (!a->readlimit) + { /* eof */ + a->eof_seen = 1; + rc = -1; + } + else + { + if (size > a->readlimit) + size = a->readlimit; + 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; + } + else + a->readlimit -= nbytes; + } + *ret_len = nbytes; + } else { nbytes = 0; @@ -1412,7 +1442,8 @@ iobuf_fdopen_nc (int fd, const char *mode) iobuf_t -iobuf_esopen (estream_t estream, const char *mode, int keep_open) +iobuf_esopen (estream_t estream, const char *mode, int keep_open, + size_t readlimit) { iobuf_t a; file_es_filter_ctx_t *fcx; @@ -1424,7 +1455,9 @@ iobuf_esopen (estream_t estream, const char *mode, int keep_open) fcx->fp = estream; fcx->print_only_name = 1; fcx->keep_open = keep_open; - sprintf (fcx->fname, "[fd %p]", estream); + fcx->readlimit = readlimit; + fcx->use_readlimit = !!readlimit; + snprintf (fcx->fname, 30, "[fd %p]", estream); a->filter = file_es_filter; a->filter_ov = fcx; file_es_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len); diff --git a/common/iobuf.h b/common/iobuf.h index 16156383c..9c9650c61 100644 --- a/common/iobuf.h +++ b/common/iobuf.h @@ -328,8 +328,10 @@ iobuf_t iobuf_fdopen_nc (int fd, const char *mode); letter 'w', creates an output filter. Otherwise, creates an input filter. If KEEP_OPEN is TRUE, then the stream is not closed when the filter is destroyed. Otherwise, the stream is closed when the - filter is destroyed. */ -iobuf_t iobuf_esopen (estream_t estream, const char *mode, int keep_open); + filter is destroyed. If READLIMIT is not 0 this gives a limit on + the number of bytes to read from estream. */ +iobuf_t iobuf_esopen (estream_t estream, const char *mode, int keep_open, + size_t readlimit); /* Create a filter using an existing socket. On Windows creates a special socket filter. On non-Windows systems simply, this simply diff --git a/g10/decrypt-data.c b/g10/decrypt-data.c index c73d5fb45..5fd458845 100644 --- a/g10/decrypt-data.c +++ b/g10/decrypt-data.c @@ -475,7 +475,7 @@ decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek) rc = get_output_file ("", 0, ed->buf, &filename, &fp); if (! rc) { - iobuf_t output = iobuf_esopen (fp, "w", 0); + iobuf_t output = iobuf_esopen (fp, "w", 0, 0); armor_filter_context_t *afx = NULL; if (opt.armor) diff --git a/g10/import.c b/g10/import.c index cab36e0b2..17afaa6f6 100644 --- a/g10/import.c +++ b/g10/import.c @@ -550,7 +550,7 @@ import_keys_es_stream (ctrl_t ctrl, estream_t fp, gpg_error_t err; iobuf_t inp; - inp = iobuf_esopen (fp, "rb", 1); + inp = iobuf_esopen (fp, "rb", 1, 0); if (!inp) { err = gpg_error_from_syserror ();