common: Allow a readlimit for iobuf_esopen.
authorWerner Koch <wk@gnupg.org>
Tue, 10 Sep 2019 13:45:58 +0000 (15:45 +0200)
committerWerner Koch <wk@gnupg.org>
Tue, 10 Sep 2019 13:45:58 +0000 (15:45 +0200)
* common/iobuf.c (file_es_filter_ctx_t): Add fields use_readlimit and
readlimit.
(file_es_filter): Implement them.
(iobuf_esopen): Add new arg readlimit.
* g10/decrypt-data.c (decrypt_data): Adjust for change.
* g10/import.c (import_keys_es_stream): Ditto.
--

This comes handy for (length,datablob) style streams.

Signed-off-by: Werner Koch <wk@gnupg.org>
common/iobuf.c
common/iobuf.h
g10/decrypt-data.c
g10/import.c

index 0594425..db5d062 100644 (file)
@@ -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);
index 1615638..9c9650c 100644 (file)
@@ -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
index c73d5fb..5fd4588 100644 (file)
@@ -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)
index cab36e0..17afaa6 100644 (file)
@@ -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 ();