LCOV - code coverage report
Current view: top level - common - iobuf.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 641 981 65.3 %
Date: 2016-11-29 15:00:56 Functions: 45 58 77.6 %

          Line data    Source code
       1             : /* iobuf.c  -  File Handling for OpenPGP.
       2             :  * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2006, 2007, 2008,
       3             :  *               2009, 2010, 2011  Free Software Foundation, Inc.
       4             :  * Copyright (C) 2015  g10 Code GmbH
       5             :  *
       6             :  * This file is part of GnuPG.
       7             :  *
       8             :  * This file is free software; you can redistribute it and/or modify
       9             :  * it under the terms of either
      10             :  *
      11             :  *   - the GNU Lesser General Public License as published by the Free
      12             :  *     Software Foundation; either version 3 of the License, or (at
      13             :  *     your option) any later version.
      14             :  *
      15             :  * or
      16             :  *
      17             :  *   - the GNU General Public License as published by the Free
      18             :  *     Software Foundation; either version 2 of the License, or (at
      19             :  *     your option) any later version.
      20             :  *
      21             :  * or both in parallel, as here.
      22             :  *
      23             :  * This file is distributed in the hope that it will be useful,
      24             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      25             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      26             :  * GNU General Public License for more details.
      27             :  *
      28             :  * You should have received a copy of the GNU General Public License
      29             :  * along with this program; if not, see <https://www.gnu.org/licenses/>.
      30             :  */
      31             : 
      32             : #include <config.h>
      33             : #include <stdio.h>
      34             : #include <stdlib.h>
      35             : #include <string.h>
      36             : #include <errno.h>
      37             : #include <ctype.h>
      38             : #include <assert.h>
      39             : #include <sys/types.h>
      40             : #include <sys/stat.h>
      41             : #include <fcntl.h>
      42             : #include <unistd.h>
      43             : #ifdef HAVE_W32_SYSTEM
      44             : # ifdef HAVE_WINSOCK2_H
      45             : #  include <winsock2.h>
      46             : # endif
      47             : # include <windows.h>
      48             : #endif
      49             : #ifdef __riscos__
      50             : # include <kernel.h>
      51             : # include <swis.h>
      52             : #endif /* __riscos__ */
      53             : 
      54             : #include <assuan.h>
      55             : 
      56             : #include "util.h"
      57             : #include "sysutils.h"
      58             : #include "iobuf.h"
      59             : 
      60             : /*-- Begin configurable part.  --*/
      61             : 
      62             : /* The size of the internal buffers.
      63             :    NOTE: If you change this value you MUST also adjust the regression
      64             :    test "armored_key_8192" in armor.test! */
      65             : #define IOBUF_BUFFER_SIZE  8192
      66             : 
      67             : /* To avoid a potential DoS with compression packets we better limit
      68             :    the number of filters in a chain.  */
      69             : #define MAX_NESTING_FILTER 64
      70             : 
      71             : /*-- End configurable part.  --*/
      72             : 
      73             : 
      74             : #ifdef HAVE_W32_SYSTEM
      75             : # ifdef HAVE_W32CE_SYSTEM
      76             : #  define FD_FOR_STDIN  (es_fileno (es_stdin))
      77             : #  define FD_FOR_STDOUT (es_fileno (es_stdout))
      78             : # else
      79             : #  define FD_FOR_STDIN  (GetStdHandle (STD_INPUT_HANDLE))
      80             : #  define FD_FOR_STDOUT (GetStdHandle (STD_OUTPUT_HANDLE))
      81             : # endif
      82             : #else /*!HAVE_W32_SYSTEM*/
      83             : # define FD_FOR_STDIN  (0)
      84             : # define FD_FOR_STDOUT (1)
      85             : #endif /*!HAVE_W32_SYSTEM*/
      86             : 
      87             : 
      88             : /* The context used by the file filter.  */
      89             : typedef struct
      90             : {
      91             :   gnupg_fd_t fp;       /* Open file pointer or handle.  */
      92             :   int keep_open;
      93             :   int no_cache;
      94             :   int eof_seen;
      95             :   int print_only_name; /* Flags indicating that fname is not a real file.  */
      96             :   char fname[1];       /* Name of the file.  */
      97             : } file_filter_ctx_t;
      98             : 
      99             : /* The context used by the estream filter.  */
     100             : typedef struct
     101             : {
     102             :   estream_t fp;        /* Open estream handle.  */
     103             :   int keep_open;
     104             :   int no_cache;
     105             :   int eof_seen;
     106             :   int print_only_name; /* Flags indicating that fname is not a real file.  */
     107             :   char fname[1];       /* Name of the file.  */
     108             : } file_es_filter_ctx_t;
     109             : 
     110             : 
     111             : /* Object to control the "close cache".  */
     112             : struct close_cache_s
     113             : {
     114             :   struct close_cache_s *next;
     115             :   gnupg_fd_t fp;
     116             :   char fname[1];
     117             : };
     118             : typedef struct close_cache_s *close_cache_t;
     119             : static close_cache_t close_cache;
     120             : 
     121             : 
     122             : 
     123             : #ifdef HAVE_W32_SYSTEM
     124             : typedef struct
     125             : {
     126             :   int sock;
     127             :   int keep_open;
     128             :   int no_cache;
     129             :   int eof_seen;
     130             :   int print_only_name;  /* Flag indicating that fname is not a real file.  */
     131             :   char fname[1];        /* Name of the file */
     132             : 
     133             : } sock_filter_ctx_t;
     134             : #endif /*HAVE_W32_SYSTEM*/
     135             : 
     136             : /* The first partial length header block must be of size 512 to make
     137             :  * it easier (and more efficient) we use a min. block size of 512 for
     138             :  * all chunks (but the last one) */
     139             : #define OP_MIN_PARTIAL_CHUNK      512
     140             : #define OP_MIN_PARTIAL_CHUNK_2POW 9
     141             : 
     142             : /* The context we use for the block filter (used to handle OpenPGP
     143             :    length information header).  */
     144             : typedef struct
     145             : {
     146             :   int use;
     147             :   size_t size;
     148             :   size_t count;
     149             :   int partial;     /* 1 = partial header, 2 in last partial packet.  */
     150             :   char *buffer;    /* Used for partial header.  */
     151             :   size_t buflen;   /* Used size of buffer.  */
     152             :   int first_c;     /* First character of a partial header (which is > 0).  */
     153             :   int eof;
     154             : }
     155             : block_filter_ctx_t;
     156             : 
     157             : 
     158             : /* Global flag to tell whether special file names are enabled.  See
     159             :    gpg.c for an explanation of these file names.  FIXME: This does not
     160             :    belong in the iobuf subsystem. */
     161             : static int special_names_enabled;
     162             : 
     163             : /* Local prototypes.  */
     164             : static int underflow (iobuf_t a, int clear_pending_eof);
     165             : static int underflow_target (iobuf_t a, int clear_pending_eof, size_t target);
     166             : static int translate_file_handle (int fd, int for_write);
     167             : 
     168             : /* Sends any pending data to the filter's FILTER function.  Note: this
     169             :    works on the filter and not on the whole pipeline.  That is,
     170             :    iobuf_flush doesn't necessarily cause data to be written to any
     171             :    underlying file; it just causes any data buffered at the filter A
     172             :    to be sent to A's filter function.
     173             : 
     174             :    If A is a IOBUF_OUTPUT_TEMP filter, then this also enlarges the
     175             :    buffer by IOBUF_BUFFER_SIZE.
     176             : 
     177             :    May only be called on an IOBUF_OUTPUT or IOBUF_OUTPUT_TEMP filters.  */
     178             : static int filter_flush (iobuf_t a);
     179             : 
     180             : 
     181             : 
     182             : /* This is a replacement for strcmp.  Under W32 it does not
     183             :    distinguish between backslash and slash.  */
     184             : static int
     185         499 : fd_cache_strcmp (const char *a, const char *b)
     186             : {
     187             : #ifdef HAVE_DOSISH_SYSTEM
     188             :   for (; *a && *b; a++, b++)
     189             :     {
     190             :       if (*a != *b && !((*a == '/' && *b == '\\')
     191             :                         || (*a == '\\' && *b == '/')) )
     192             :         break;
     193             :     }
     194             :   return *(const unsigned char *)a - *(const unsigned char *)b;
     195             : #else
     196         499 :   return strcmp (a, b);
     197             : #endif
     198             : }
     199             : 
     200             : /*
     201             :  * Invalidate (i.e. close) a cached iobuf
     202             :  */
     203             : static int
     204         519 : fd_cache_invalidate (const char *fname)
     205             : {
     206             :   close_cache_t cc;
     207         519 :   int rc = 0;
     208             : 
     209         519 :   assert (fname);
     210         519 :   if (DBG_IOBUF)
     211           0 :     log_debug ("fd_cache_invalidate (%s)\n", fname);
     212             : 
     213         817 :   for (cc = close_cache; cc; cc = cc->next)
     214             :     {
     215         298 :       if (cc->fp != GNUPG_INVALID_FD && !fd_cache_strcmp (cc->fname, fname))
     216             :         {
     217         140 :           if (DBG_IOBUF)
     218           0 :             log_debug ("                did (%s)\n", cc->fname);
     219             : #ifdef HAVE_W32_SYSTEM
     220             :           if (!CloseHandle (cc->fp))
     221             :             rc = -1;
     222             : #else
     223         140 :           rc = close (cc->fp);
     224             : #endif
     225         140 :           cc->fp = GNUPG_INVALID_FD;
     226             :         }
     227             :     }
     228         519 :   return rc;
     229             : }
     230             : 
     231             : 
     232             : /* Try to sync changes to the disk.  This is to avoid data loss during
     233             :    a system crash in write/close/rename cycle on some file
     234             :    systems.  */
     235             : static int
     236           0 : fd_cache_synchronize (const char *fname)
     237             : {
     238           0 :   int err = 0;
     239             : 
     240             : #ifdef HAVE_FSYNC
     241             :   close_cache_t cc;
     242             : 
     243           0 :   if (DBG_IOBUF)
     244           0 :     log_debug ("fd_cache_synchronize (%s)\n", fname);
     245             : 
     246           0 :   for (cc=close_cache; cc; cc = cc->next )
     247             :     {
     248           0 :       if (cc->fp != GNUPG_INVALID_FD && !fd_cache_strcmp (cc->fname, fname))
     249             :         {
     250           0 :           if (DBG_IOBUF)
     251           0 :             log_debug ("                 did (%s)\n", cc->fname);
     252             : 
     253           0 :           err = fsync (cc->fp);
     254             :         }
     255             :     }
     256             : #else
     257             :   (void)fname;
     258             : #endif /*HAVE_FSYNC*/
     259             : 
     260           0 :   return err;
     261             : }
     262             : 
     263             : 
     264             : static gnupg_fd_t
     265        1523 : direct_open (const char *fname, const char *mode, int mode700)
     266             : {
     267             : #ifdef HAVE_W32_SYSTEM
     268             :   unsigned long da, cd, sm;
     269             :   HANDLE hfile;
     270             : 
     271             :   (void)mode700;
     272             :   /* Note, that we do not handle all mode combinations */
     273             : 
     274             :   /* According to the ReactOS source it seems that open() of the
     275             :    * standard MSW32 crt does open the file in shared mode which is
     276             :    * something new for MS applications ;-)
     277             :    */
     278             :   if (strchr (mode, '+'))
     279             :     {
     280             :       if (fd_cache_invalidate (fname))
     281             :         return GNUPG_INVALID_FD;
     282             :       da = GENERIC_READ | GENERIC_WRITE;
     283             :       cd = OPEN_EXISTING;
     284             :       sm = FILE_SHARE_READ | FILE_SHARE_WRITE;
     285             :     }
     286             :   else if (strchr (mode, 'w'))
     287             :     {
     288             :       if (fd_cache_invalidate (fname))
     289             :         return GNUPG_INVALID_FD;
     290             :       da = GENERIC_WRITE;
     291             :       cd = CREATE_ALWAYS;
     292             :       sm = FILE_SHARE_WRITE;
     293             :     }
     294             :   else
     295             :     {
     296             :       da = GENERIC_READ;
     297             :       cd = OPEN_EXISTING;
     298             :       sm = FILE_SHARE_READ;
     299             :     }
     300             : 
     301             : #ifdef HAVE_W32CE_SYSTEM
     302             :   {
     303             :     wchar_t *wfname = utf8_to_wchar (fname);
     304             :     if (wfname)
     305             :       {
     306             :         hfile = CreateFile (wfname, da, sm, NULL, cd,
     307             :                             FILE_ATTRIBUTE_NORMAL, NULL);
     308             :         xfree (wfname);
     309             :       }
     310             :     else
     311             :       hfile = INVALID_HANDLE_VALUE;
     312             :   }
     313             : #else
     314             :   hfile = CreateFile (fname, da, sm, NULL, cd, FILE_ATTRIBUTE_NORMAL, NULL);
     315             : #endif
     316             :   return hfile;
     317             : 
     318             : #else /*!HAVE_W32_SYSTEM*/
     319             : 
     320             :   int oflag;
     321        1523 :   int cflag = S_IRUSR | S_IWUSR;
     322             : 
     323        1523 :   if (!mode700)
     324        1518 :     cflag |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
     325             : 
     326             :   /* Note, that we do not handle all mode combinations */
     327        1523 :   if (strchr (mode, '+'))
     328             :     {
     329           0 :       if (fd_cache_invalidate (fname))
     330           0 :         return GNUPG_INVALID_FD;
     331           0 :       oflag = O_RDWR;
     332             :     }
     333        1523 :   else if (strchr (mode, 'w'))
     334             :     {
     335         375 :       if (fd_cache_invalidate (fname))
     336           0 :         return GNUPG_INVALID_FD;
     337         375 :       oflag = O_WRONLY | O_CREAT | O_TRUNC;
     338             :     }
     339             :   else
     340             :     {
     341        1148 :       oflag = O_RDONLY;
     342             :     }
     343             : #ifdef O_BINARY
     344             :   if (strchr (mode, 'b'))
     345             :     oflag |= O_BINARY;
     346             : #endif
     347             : 
     348             : #ifdef __riscos__
     349             :   {
     350             :     struct stat buf;
     351             : 
     352             :     /* Don't allow iobufs on directories */
     353             :     if (!stat (fname, &buf) && S_ISDIR (buf.st_mode) && !S_ISREG (buf.st_mode))
     354             :       return __set_errno (EISDIR);
     355             :   }
     356             : #endif
     357        1523 :   return open (fname, oflag, cflag);
     358             : 
     359             : #endif /*!HAVE_W32_SYSTEM*/
     360             : }
     361             : 
     362             : 
     363             : /*
     364             :  * Instead of closing an FD we keep it open and cache it for later reuse
     365             :  * Note that this caching strategy only works if the process does not chdir.
     366             :  */
     367             : static void
     368        1587 : fd_cache_close (const char *fname, gnupg_fd_t fp)
     369             : {
     370             :   close_cache_t cc;
     371             : 
     372        1587 :   assert (fp);
     373        1587 :   if (!fname || !*fname)
     374             :     {
     375             : #ifdef HAVE_W32_SYSTEM
     376             :       CloseHandle (fp);
     377             : #else
     378         611 :       close (fp);
     379             : #endif
     380         611 :       if (DBG_IOBUF)
     381           0 :         log_debug ("fd_cache_close (%d) real\n", (int)fp);
     382         611 :       return;
     383             :     }
     384             :   /* try to reuse a slot */
     385        1204 :   for (cc = close_cache; cc; cc = cc->next)
     386             :     {
     387         293 :       if (cc->fp == GNUPG_INVALID_FD && !fd_cache_strcmp (cc->fname, fname))
     388             :         {
     389          65 :           cc->fp = fp;
     390          65 :           if (DBG_IOBUF)
     391           0 :             log_debug ("fd_cache_close (%s) used existing slot\n", fname);
     392          65 :           return;
     393             :         }
     394             :     }
     395             :   /* add a new one */
     396         911 :   if (DBG_IOBUF)
     397           0 :     log_debug ("fd_cache_close (%s) new slot created\n", fname);
     398         911 :   cc = xcalloc (1, sizeof *cc + strlen (fname));
     399         911 :   strcpy (cc->fname, fname);
     400         911 :   cc->fp = fp;
     401         911 :   cc->next = close_cache;
     402         911 :   close_cache = cc;
     403             : }
     404             : 
     405             : /*
     406             :  * Do a direct_open on FNAME but first try to reuse one from the fd_cache
     407             :  */
     408             : static gnupg_fd_t
     409        1212 : fd_cache_open (const char *fname, const char *mode)
     410             : {
     411             :   close_cache_t cc;
     412             : 
     413        1212 :   assert (fname);
     414        1422 :   for (cc = close_cache; cc; cc = cc->next)
     415             :     {
     416         274 :       if (cc->fp != GNUPG_INVALID_FD && !fd_cache_strcmp (cc->fname, fname))
     417             :         {
     418          64 :           gnupg_fd_t fp = cc->fp;
     419          64 :           cc->fp = GNUPG_INVALID_FD;
     420          64 :           if (DBG_IOBUF)
     421           0 :             log_debug ("fd_cache_open (%s) using cached fp\n", fname);
     422             : #ifdef HAVE_W32_SYSTEM
     423             :           if (SetFilePointer (fp, 0, NULL, FILE_BEGIN) == 0xffffffff)
     424             :             {
     425             :               log_error ("rewind file failed on handle %p: ec=%d\n",
     426             :                          fp, (int) GetLastError ());
     427             :               fp = GNUPG_INVALID_FD;
     428             :             }
     429             : #else
     430          64 :           if (lseek (fp, 0, SEEK_SET) == (off_t) - 1)
     431             :             {
     432           0 :               log_error ("can't rewind fd %d: %s\n", fp, strerror (errno));
     433           0 :               fp = GNUPG_INVALID_FD;
     434             :             }
     435             : #endif
     436          64 :           return fp;
     437             :         }
     438             :     }
     439        1148 :   if (DBG_IOBUF)
     440           0 :     log_debug ("fd_cache_open (%s) not cached\n", fname);
     441        1148 :   return direct_open (fname, mode, 0);
     442             : }
     443             : 
     444             : 
     445             : static int
     446       10130 : file_filter (void *opaque, int control, iobuf_t chain, byte * buf,
     447             :              size_t * ret_len)
     448             : {
     449       10130 :   file_filter_ctx_t *a = opaque;
     450       10130 :   gnupg_fd_t f = a->fp;
     451       10130 :   size_t size = *ret_len;
     452       10130 :   size_t nbytes = 0;
     453       10130 :   int rc = 0;
     454             : 
     455             :   (void)chain; /* Not used.  */
     456             : 
     457       10130 :   if (control == IOBUFCTRL_UNDERFLOW)
     458             :     {
     459        4438 :       assert (size); /* We need a buffer.  */
     460        4438 :       if (a->eof_seen)
     461             :         {
     462           0 :           rc = -1;
     463           0 :           *ret_len = 0;
     464             :         }
     465             :       else
     466             :         {
     467             : #ifdef HAVE_W32_SYSTEM
     468             :           unsigned long nread;
     469             : 
     470             :           nbytes = 0;
     471             :           if (!ReadFile (f, buf, size, &nread, NULL))
     472             :             {
     473             :               int ec = (int) GetLastError ();
     474             :               if (ec != ERROR_BROKEN_PIPE)
     475             :                 {
     476             :                   rc = gpg_error_from_errno (ec);
     477             :                   log_error ("%s: read error: ec=%d\n", a->fname, ec);
     478             :                 }
     479             :             }
     480             :           else if (!nread)
     481             :             {
     482             :               a->eof_seen = 1;
     483             :               rc = -1;
     484             :             }
     485             :           else
     486             :             {
     487             :               nbytes = nread;
     488             :             }
     489             : 
     490             : #else
     491             : 
     492             :           int n;
     493             : 
     494        4438 :           nbytes = 0;
     495             :           do
     496             :             {
     497        4438 :               n = read (f, buf, size);
     498             :             }
     499        4438 :           while (n == -1 && errno == EINTR);
     500        4438 :           if (n == -1)
     501             :             {                   /* error */
     502           0 :               if (errno != EPIPE)
     503             :                 {
     504           0 :                   rc = gpg_error_from_syserror ();
     505           0 :                   log_error ("%s: read error: %s\n",
     506           0 :                              a->fname, strerror (errno));
     507             :                 }
     508             :             }
     509        4438 :           else if (!n)
     510             :             {                   /* eof */
     511        1112 :               a->eof_seen = 1;
     512        1112 :               rc = -1;
     513             :             }
     514             :           else
     515             :             {
     516        3326 :               nbytes = n;
     517             :             }
     518             : #endif
     519        4438 :           *ret_len = nbytes;
     520             :         }
     521             :     }
     522        5692 :   else if (control == IOBUFCTRL_FLUSH)
     523             :     {
     524        2032 :       if (size)
     525             :         {
     526             : #ifdef HAVE_W32_SYSTEM
     527             :           byte *p = buf;
     528             :           unsigned long n;
     529             : 
     530             :           nbytes = size;
     531             :           do
     532             :             {
     533             :               if (size && !WriteFile (f, p, nbytes, &n, NULL))
     534             :                 {
     535             :                   int ec = (int) GetLastError ();
     536             :                   rc = gpg_error_from_errno (ec);
     537             :                   log_error ("%s: write error: ec=%d\n", a->fname, ec);
     538             :                   break;
     539             :                 }
     540             :               p += n;
     541             :               nbytes -= n;
     542             :             }
     543             :           while (nbytes);
     544             :           nbytes = p - buf;
     545             : #else
     546        1902 :           byte *p = buf;
     547             :           int n;
     548             : 
     549        1902 :           nbytes = size;
     550             :           do
     551             :             {
     552             :               do
     553             :                 {
     554        1902 :                   n = write (f, p, nbytes);
     555             :                 }
     556        1902 :               while (n == -1 && errno == EINTR);
     557        1902 :               if (n > 0)
     558             :                 {
     559        1902 :                   p += n;
     560        1902 :                   nbytes -= n;
     561             :                 }
     562             :             }
     563        1902 :           while (n != -1 && nbytes);
     564        1902 :           if (n == -1)
     565             :             {
     566           0 :               rc = gpg_error_from_syserror ();
     567           0 :               log_error ("%s: write error: %s\n", a->fname, strerror (errno));
     568             :             }
     569        1902 :           nbytes = p - buf;
     570             : #endif
     571             :         }
     572        2032 :       *ret_len = nbytes;
     573             :     }
     574        3660 :   else if (control == IOBUFCTRL_INIT)
     575             :     {
     576        1830 :       a->eof_seen = 0;
     577        1830 :       a->keep_open = 0;
     578        1830 :       a->no_cache = 0;
     579             :     }
     580        1830 :   else if (control == IOBUFCTRL_DESC)
     581             :     {
     582           0 :       mem2str (buf, "file_filter(fd)", *ret_len);
     583             :     }
     584        1830 :   else if (control == IOBUFCTRL_FREE)
     585             :     {
     586        1830 :       if (f != FD_FOR_STDIN && f != FD_FOR_STDOUT)
     587             :         {
     588        1587 :           if (DBG_IOBUF)
     589           0 :             log_debug ("%s: close fd/handle %d\n", a->fname, FD2INT (f));
     590        1587 :           if (!a->keep_open)
     591        1587 :             fd_cache_close (a->no_cache ? NULL : a->fname, f);
     592             :         }
     593        1830 :       xfree (a); /* We can free our context now. */
     594             :     }
     595             : 
     596       10130 :   return rc;
     597             : }
     598             : 
     599             : 
     600             : /* Similar to file_filter but using the estream system.  */
     601             : static int
     602           0 : file_es_filter (void *opaque, int control, iobuf_t chain, byte * buf,
     603             :                 size_t * ret_len)
     604             : {
     605           0 :   file_es_filter_ctx_t *a = opaque;
     606           0 :   estream_t f = a->fp;
     607           0 :   size_t size = *ret_len;
     608           0 :   size_t nbytes = 0;
     609           0 :   int rc = 0;
     610             : 
     611             :   (void)chain; /* Not used.  */
     612             : 
     613           0 :   if (control == IOBUFCTRL_UNDERFLOW)
     614             :     {
     615           0 :       assert (size); /* We need a buffer.  */
     616           0 :       if (a->eof_seen)
     617             :         {
     618           0 :           rc = -1;
     619           0 :           *ret_len = 0;
     620             :         }
     621             :       else
     622             :         {
     623           0 :           nbytes = 0;
     624           0 :           rc = es_read (f, buf, size, &nbytes);
     625           0 :           if (rc == -1)
     626             :             {                   /* error */
     627           0 :               rc = gpg_error_from_syserror ();
     628           0 :               log_error ("%s: read error: %s\n", a->fname, strerror (errno));
     629             :             }
     630           0 :           else if (!nbytes)
     631             :             {                   /* eof */
     632           0 :               a->eof_seen = 1;
     633           0 :               rc = -1;
     634             :             }
     635           0 :           *ret_len = nbytes;
     636             :         }
     637             :     }
     638           0 :   else if (control == IOBUFCTRL_FLUSH)
     639             :     {
     640           0 :       if (size)
     641             :         {
     642           0 :           byte *p = buf;
     643             :           size_t nwritten;
     644             : 
     645           0 :           nbytes = size;
     646             :           do
     647             :             {
     648           0 :               nwritten = 0;
     649           0 :               if (es_write (f, p, nbytes, &nwritten))
     650             :                 {
     651           0 :                   rc = gpg_error_from_syserror ();
     652           0 :                   log_error ("%s: write error: %s\n",
     653           0 :                              a->fname, strerror (errno));
     654           0 :                   break;
     655             :                 }
     656           0 :               p += nwritten;
     657           0 :               nbytes -= nwritten;
     658             :             }
     659           0 :           while (nbytes);
     660           0 :           nbytes = p - buf;
     661             :         }
     662           0 :       *ret_len = nbytes;
     663             :     }
     664           0 :   else if (control == IOBUFCTRL_INIT)
     665             :     {
     666           0 :       a->eof_seen = 0;
     667           0 :       a->no_cache = 0;
     668             :     }
     669           0 :   else if (control == IOBUFCTRL_DESC)
     670             :     {
     671           0 :       mem2str (buf, "estream_filter", *ret_len);
     672             :     }
     673           0 :   else if (control == IOBUFCTRL_FREE)
     674             :     {
     675           0 :       if (f != es_stdin && f != es_stdout)
     676             :         {
     677           0 :           if (DBG_IOBUF)
     678           0 :             log_debug ("%s: es_fclose %p\n", a->fname, f);
     679           0 :           if (!a->keep_open)
     680           0 :             es_fclose (f);
     681             :         }
     682           0 :       f = NULL;
     683           0 :       xfree (a); /* We can free our context now. */
     684             :     }
     685             : 
     686           0 :   return rc;
     687             : }
     688             : 
     689             : 
     690             : #ifdef HAVE_W32_SYSTEM
     691             : /* Because network sockets are special objects under Lose32 we have to
     692             :    use a dedicated filter for them. */
     693             : static int
     694             : sock_filter (void *opaque, int control, iobuf_t chain, byte * buf,
     695             :              size_t * ret_len)
     696             : {
     697             :   sock_filter_ctx_t *a = opaque;
     698             :   size_t size = *ret_len;
     699             :   size_t nbytes = 0;
     700             :   int rc = 0;
     701             : 
     702             :   (void)chain;
     703             : 
     704             :   if (control == IOBUFCTRL_UNDERFLOW)
     705             :     {
     706             :       assert (size);            /* need a buffer */
     707             :       if (a->eof_seen)
     708             :         {
     709             :           rc = -1;
     710             :           *ret_len = 0;
     711             :         }
     712             :       else
     713             :         {
     714             :           int nread;
     715             : 
     716             :           nread = recv (a->sock, buf, size, 0);
     717             :           if (nread == SOCKET_ERROR)
     718             :             {
     719             :               int ec = (int) WSAGetLastError ();
     720             :               rc = gpg_error_from_errno (ec);
     721             :               log_error ("socket read error: ec=%d\n", ec);
     722             :             }
     723             :           else if (!nread)
     724             :             {
     725             :               a->eof_seen = 1;
     726             :               rc = -1;
     727             :             }
     728             :           else
     729             :             {
     730             :               nbytes = nread;
     731             :             }
     732             :           *ret_len = nbytes;
     733             :         }
     734             :     }
     735             :   else if (control == IOBUFCTRL_FLUSH)
     736             :     {
     737             :       if (size)
     738             :         {
     739             :           byte *p = buf;
     740             :           int n;
     741             : 
     742             :           nbytes = size;
     743             :           do
     744             :             {
     745             :               n = send (a->sock, p, nbytes, 0);
     746             :               if (n == SOCKET_ERROR)
     747             :                 {
     748             :                   int ec = (int) WSAGetLastError ();
     749             :                   rc = gpg_error_from_errno (ec);
     750             :                   log_error ("socket write error: ec=%d\n", ec);
     751             :                   break;
     752             :                 }
     753             :               p += n;
     754             :               nbytes -= n;
     755             :             }
     756             :           while (nbytes);
     757             :           nbytes = p - buf;
     758             :         }
     759             :       *ret_len = nbytes;
     760             :     }
     761             :   else if (control == IOBUFCTRL_INIT)
     762             :     {
     763             :       a->eof_seen = 0;
     764             :       a->keep_open = 0;
     765             :       a->no_cache = 0;
     766             :     }
     767             :   else if (control == IOBUFCTRL_DESC)
     768             :     {
     769             :       mem2str (buf, "sock_filter", *ret_len);
     770             :     }
     771             :   else if (control == IOBUFCTRL_FREE)
     772             :     {
     773             :       if (!a->keep_open)
     774             :         closesocket (a->sock);
     775             :       xfree (a);                /* we can free our context now */
     776             :     }
     777             :   return rc;
     778             : }
     779             : #endif /*HAVE_W32_SYSTEM*/
     780             : 
     781             : /****************
     782             :  * This is used to implement the block write mode.
     783             :  * Block reading is done on a byte by byte basis in readbyte(),
     784             :  * without a filter
     785             :  */
     786             : static int
     787        4202 : block_filter (void *opaque, int control, iobuf_t chain, byte * buffer,
     788             :               size_t * ret_len)
     789             : {
     790        4202 :   block_filter_ctx_t *a = opaque;
     791        4202 :   char *buf = (char *)buffer;
     792        4202 :   size_t size = *ret_len;
     793        4202 :   int c, needed, rc = 0;
     794             :   char *p;
     795             : 
     796        4202 :   if (control == IOBUFCTRL_UNDERFLOW)
     797             :     {
     798        1703 :       size_t n = 0;
     799             : 
     800        1703 :       p = buf;
     801        1703 :       assert (size);            /* need a buffer */
     802        1703 :       if (a->eof)            /* don't read any further */
     803         315 :         rc = -1;
     804        5651 :       while (!rc && size)
     805             :         {
     806        2560 :           if (!a->size)
     807             :             {                   /* get the length bytes */
     808        2536 :               if (a->partial == 2)
     809             :                 {
     810         315 :                   a->eof = 1;
     811         315 :                   if (!n)
     812           0 :                     rc = -1;
     813         315 :                   break;
     814             :                 }
     815        2221 :               else if (a->partial)
     816             :                 {
     817             :                   /* These OpenPGP introduced huffman like encoded length
     818             :                    * bytes are really a mess :-( */
     819        2221 :                   if (a->first_c)
     820             :                     {
     821         315 :                       c = a->first_c;
     822         315 :                       a->first_c = 0;
     823             :                     }
     824        1906 :                   else if ((c = iobuf_get (chain)) == -1)
     825             :                     {
     826           0 :                       log_error ("block_filter: 1st length byte missing\n");
     827           0 :                       rc = GPG_ERR_BAD_DATA;
     828           0 :                       break;
     829             :                     }
     830        2221 :                   if (c < 192)
     831             :                     {
     832          84 :                       a->size = c;
     833          84 :                       a->partial = 2;
     834          84 :                       if (!a->size)
     835             :                         {
     836           0 :                           a->eof = 1;
     837           0 :                           if (!n)
     838           0 :                             rc = -1;
     839           0 :                           break;
     840             :                         }
     841             :                     }
     842        2137 :                   else if (c < 224)
     843             :                     {
     844         231 :                       a->size = (c - 192) * 256;
     845         231 :                       if ((c = iobuf_get (chain)) == -1)
     846             :                         {
     847           0 :                           log_error
     848             :                             ("block_filter: 2nd length byte missing\n");
     849           0 :                           rc = GPG_ERR_BAD_DATA;
     850           0 :                           break;
     851             :                         }
     852         231 :                       a->size += c + 192;
     853         231 :                       a->partial = 2;
     854         231 :                       if (!a->size)
     855             :                         {
     856           0 :                           a->eof = 1;
     857           0 :                           if (!n)
     858           0 :                             rc = -1;
     859           0 :                           break;
     860             :                         }
     861             :                     }
     862        1906 :                   else if (c == 255)
     863             :                     {
     864           0 :                       a->size = (size_t)iobuf_get (chain) << 24;
     865           0 :                       a->size |= iobuf_get (chain) << 16;
     866           0 :                       a->size |= iobuf_get (chain) << 8;
     867           0 :                       if ((c = iobuf_get (chain)) == -1)
     868             :                         {
     869           0 :                           log_error ("block_filter: invalid 4 byte length\n");
     870           0 :                           rc = GPG_ERR_BAD_DATA;
     871           0 :                           break;
     872             :                         }
     873           0 :                       a->size |= c;
     874           0 :                       a->partial = 2;
     875           0 :                       if (!a->size)
     876             :                         {
     877           0 :                           a->eof = 1;
     878           0 :                           if (!n)
     879           0 :                             rc = -1;
     880           0 :                           break;
     881             :                         }
     882             :                     }
     883             :                   else
     884             :                     { /* Next partial body length. */
     885        1906 :                       a->size = 1 << (c & 0x1f);
     886             :                     }
     887             :                   /*  log_debug("partial: ctx=%p c=%02x size=%u\n", a, c, a->size); */
     888             :                 }
     889             :               else
     890           0 :                 BUG ();
     891             :             }
     892             : 
     893        6735 :           while (!rc && size && a->size)
     894             :             {
     895        2245 :               needed = size < a->size ? size : a->size;
     896        2245 :               c = iobuf_read (chain, p, needed);
     897        2245 :               if (c < needed)
     898             :                 {
     899           0 :                   if (c == -1)
     900           0 :                     c = 0;
     901           0 :                   log_error
     902             :                     ("block_filter %p: read error (size=%lu,a->size=%lu)\n",
     903           0 :                      a, (ulong) size + c, (ulong) a->size + c);
     904           0 :                   rc = GPG_ERR_BAD_DATA;
     905             :                 }
     906             :               else
     907             :                 {
     908        2245 :                   size -= c;
     909        2245 :                   a->size -= c;
     910        2245 :                   p += c;
     911        2245 :                   n += c;
     912             :                 }
     913             :             }
     914             :         }
     915        1703 :       *ret_len = n;
     916             :     }
     917        2499 :   else if (control == IOBUFCTRL_FLUSH)
     918             :     {
     919        1183 :       if (a->partial)
     920             :         {                       /* the complicated openpgp scheme */
     921        1183 :           size_t blen, n, nbytes = size + a->buflen;
     922             : 
     923        1183 :           assert (a->buflen <= OP_MIN_PARTIAL_CHUNK);
     924        1183 :           if (nbytes < OP_MIN_PARTIAL_CHUNK)
     925             :             {
     926             :               /* not enough to write a partial block out; so we store it */
     927          70 :               if (!a->buffer)
     928          70 :                 a->buffer = xmalloc (OP_MIN_PARTIAL_CHUNK);
     929          70 :               memcpy (a->buffer + a->buflen, buf, size);
     930          70 :               a->buflen += size;
     931             :             }
     932             :           else
     933             :             {                   /* okay, we can write out something */
     934             :               /* do this in a loop to use the most efficient block lengths */
     935        1113 :               p = buf;
     936             :               do
     937             :                 {
     938             :                   /* find the best matching block length - this is limited
     939             :                    * by the size of the internal buffering */
     940        7632 :                   for (blen = OP_MIN_PARTIAL_CHUNK * 2,
     941        1248 :                        c = OP_MIN_PARTIAL_CHUNK_2POW + 1; blen <= nbytes;
     942        3888 :                        blen *= 2, c++)
     943             :                     ;
     944        1248 :                   blen /= 2;
     945        1248 :                   c--;
     946             :                   /* write the partial length header */
     947        1248 :                   assert (c <= 0x1f);        /*;-) */
     948        1248 :                   c |= 0xe0;
     949        1248 :                   iobuf_put (chain, c);
     950        1248 :                   if ((n = a->buflen))
     951             :                     {           /* write stuff from the buffer */
     952           0 :                       assert (n == OP_MIN_PARTIAL_CHUNK);
     953           0 :                       if (iobuf_write (chain, a->buffer, n))
     954           0 :                         rc = gpg_error_from_syserror ();
     955           0 :                       a->buflen = 0;
     956           0 :                       nbytes -= n;
     957             :                     }
     958        1248 :                   if ((n = nbytes) > blen)
     959         408 :                     n = blen;
     960        1248 :                   if (n && iobuf_write (chain, p, n))
     961           0 :                     rc = gpg_error_from_syserror ();
     962        1248 :                   p += n;
     963        1248 :                   nbytes -= n;
     964             :                 }
     965        1248 :               while (!rc && nbytes >= OP_MIN_PARTIAL_CHUNK);
     966             :               /* store the rest in the buffer */
     967        1113 :               if (!rc && nbytes)
     968             :                 {
     969         273 :                   assert (!a->buflen);
     970         273 :                   assert (nbytes < OP_MIN_PARTIAL_CHUNK);
     971         273 :                   if (!a->buffer)
     972         273 :                     a->buffer = xmalloc (OP_MIN_PARTIAL_CHUNK);
     973         273 :                   memcpy (a->buffer, p, nbytes);
     974         273 :                   a->buflen = nbytes;
     975             :                 }
     976             :             }
     977             :         }
     978             :       else
     979           0 :         BUG ();
     980             :     }
     981        1316 :   else if (control == IOBUFCTRL_INIT)
     982             :     {
     983         658 :       if (DBG_IOBUF)
     984           0 :         log_debug ("init block_filter %p\n", a);
     985         658 :       if (a->partial)
     986         658 :         a->count = 0;
     987           0 :       else if (a->use == IOBUF_INPUT)
     988           0 :         a->count = a->size = 0;
     989             :       else
     990           0 :         a->count = a->size;       /* force first length bytes */
     991         658 :       a->eof = 0;
     992         658 :       a->buffer = NULL;
     993         658 :       a->buflen = 0;
     994             :     }
     995         658 :   else if (control == IOBUFCTRL_DESC)
     996             :     {
     997           0 :       mem2str (buf, "block_filter", *ret_len);
     998             :     }
     999         658 :   else if (control == IOBUFCTRL_FREE)
    1000             :     {
    1001         658 :       if (a->use == IOBUF_OUTPUT)
    1002             :         {                       /* write the end markers */
    1003         343 :           if (a->partial)
    1004             :             {
    1005             :               u32 len;
    1006             :               /* write out the remaining bytes without a partial header
    1007             :                * the length of this header may be 0 - but if it is
    1008             :                * the first block we are not allowed to use a partial header
    1009             :                * and frankly we can't do so, because this length must be
    1010             :                * a power of 2. This is _really_ complicated because we
    1011             :                * have to check the possible length of a packet prior
    1012             :                * to it's creation: a chain of filters becomes complicated
    1013             :                * and we need a lot of code to handle compressed packets etc.
    1014             :                *   :-(((((((
    1015             :                */
    1016             :               /* construct header */
    1017         343 :               len = a->buflen;
    1018             :               /*log_debug("partial: remaining length=%u\n", len ); */
    1019         343 :               if (len < 192)
    1020         121 :                 rc = iobuf_put (chain, len);
    1021         222 :               else if (len < 8384)
    1022             :                 {
    1023         222 :                   if (!(rc = iobuf_put (chain, ((len - 192) / 256) + 192)))
    1024         222 :                     rc = iobuf_put (chain, ((len - 192) % 256));
    1025             :                 }
    1026             :               else
    1027             :                 {               /* use a 4 byte header */
    1028           0 :                   if (!(rc = iobuf_put (chain, 0xff)))
    1029           0 :                     if (!(rc = iobuf_put (chain, (len >> 24) & 0xff)))
    1030           0 :                       if (!(rc = iobuf_put (chain, (len >> 16) & 0xff)))
    1031           0 :                         if (!(rc = iobuf_put (chain, (len >> 8) & 0xff)))
    1032           0 :                           rc = iobuf_put (chain, len & 0xff);
    1033             :                 }
    1034         343 :               if (!rc && len)
    1035         343 :                 rc = iobuf_write (chain, a->buffer, len);
    1036         343 :               if (rc)
    1037             :                 {
    1038           0 :                   log_error ("block_filter: write error: %s\n",
    1039           0 :                              strerror (errno));
    1040           0 :                   rc = gpg_error_from_syserror ();
    1041             :                 }
    1042         343 :               xfree (a->buffer);
    1043         343 :               a->buffer = NULL;
    1044         343 :               a->buflen = 0;
    1045             :             }
    1046             :           else
    1047           0 :             BUG ();
    1048             :         }
    1049         315 :       else if (a->size)
    1050             :         {
    1051           0 :           log_error ("block_filter: pending bytes!\n");
    1052             :         }
    1053         658 :       if (DBG_IOBUF)
    1054           0 :         log_debug ("free block_filter %p\n", a);
    1055         658 :       xfree (a);                /* we can free our context now */
    1056             :     }
    1057             : 
    1058        4202 :   return rc;
    1059             : }
    1060             : 
    1061             : #define MAX_IOBUF_DESC 32
    1062             : /*
    1063             :  * Fill the buffer by the description of iobuf A.
    1064             :  * The buffer size should be MAX_IOBUF_DESC (or larger).
    1065             :  * Returns BUF as (const char *).
    1066             :  */
    1067             : static const char *
    1068           0 : iobuf_desc (iobuf_t a, byte *buf)
    1069             : {
    1070           0 :   size_t len = MAX_IOBUF_DESC;
    1071             : 
    1072           0 :   if (! a || ! a->filter)
    1073           0 :     memcpy (buf, "?", 2);
    1074             :   else
    1075           0 :     a->filter (a->filter_ov, IOBUFCTRL_DESC, NULL, buf, &len);
    1076             : 
    1077           0 :   return buf;
    1078             : }
    1079             : 
    1080             : static void
    1081        1446 : print_chain (iobuf_t a)
    1082             : {
    1083        1446 :   if (!DBG_IOBUF)
    1084        2892 :     return;
    1085           0 :   for (; a; a = a->chain)
    1086             :     {
    1087             :       byte desc[MAX_IOBUF_DESC];
    1088             : 
    1089           0 :       log_debug ("iobuf chain: %d.%d '%s' filter_eof=%d start=%d len=%d\n",
    1090             :                  a->no, a->subno, iobuf_desc (a, desc), a->filter_eof,
    1091           0 :                  (int) a->d.start, (int) a->d.len);
    1092             :     }
    1093             : }
    1094             : 
    1095             : int
    1096           0 : iobuf_print_chain (iobuf_t a)
    1097             : {
    1098           0 :   print_chain (a);
    1099           0 :   return 0;
    1100             : }
    1101             : 
    1102             : iobuf_t
    1103        6687 : iobuf_alloc (int use, size_t bufsize)
    1104             : {
    1105             :   iobuf_t a;
    1106             :   static int number = 0;
    1107             : 
    1108        6687 :   assert (use == IOBUF_INPUT || use == IOBUF_INPUT_TEMP
    1109             :           || use == IOBUF_OUTPUT || use == IOBUF_OUTPUT_TEMP);
    1110        6687 :   if (bufsize == 0)
    1111             :     {
    1112           0 :       log_bug ("iobuf_alloc() passed a bufsize of 0!\n");
    1113             :       bufsize = IOBUF_BUFFER_SIZE;
    1114             :     }
    1115             : 
    1116        6687 :   a = xcalloc (1, sizeof *a);
    1117        6687 :   a->use = use;
    1118        6687 :   a->d.buf = xmalloc (bufsize);
    1119        6687 :   a->d.size = bufsize;
    1120        6687 :   a->no = ++number;
    1121        6687 :   a->subno = 0;
    1122        6687 :   a->real_fname = NULL;
    1123        6687 :   return a;
    1124             : }
    1125             : 
    1126             : int
    1127       17021 : iobuf_close (iobuf_t a)
    1128             : {
    1129             :   iobuf_t a_chain;
    1130       17021 :   size_t dummy_len = 0;
    1131       17021 :   int rc = 0;
    1132             : 
    1133       24762 :   for (; a; a = a_chain)
    1134             :     {
    1135             :       byte desc[MAX_IOBUF_DESC];
    1136        7741 :       int rc2 = 0;
    1137             : 
    1138        7741 :       a_chain = a->chain;
    1139             : 
    1140        7741 :       if (a->use == IOBUF_OUTPUT && (rc = filter_flush (a)))
    1141           0 :         log_error ("filter_flush failed on close: %s\n", gpg_strerror (rc));
    1142             : 
    1143        7741 :       if (DBG_IOBUF)
    1144           0 :         log_debug ("iobuf-%d.%d: close '%s'\n",
    1145             :                    a->no, a->subno, iobuf_desc (a, desc));
    1146             : 
    1147        7741 :       if (a->filter && (rc2 = a->filter (a->filter_ov, IOBUFCTRL_FREE,
    1148             :                                          a->chain, NULL, &dummy_len)))
    1149           0 :         log_error ("IOBUFCTRL_FREE failed on close: %s\n", gpg_strerror (rc));
    1150        7741 :       if (! rc && rc2)
    1151             :         /* Whoops!  An error occurred.  Save it in RC if we haven't
    1152             :            already recorded an error.  */
    1153           0 :         rc = rc2;
    1154             : 
    1155        7741 :       xfree (a->real_fname);
    1156        7741 :       if (a->d.buf)
    1157             :         {
    1158        7741 :           memset (a->d.buf, 0, a->d.size);        /* erase the buffer */
    1159        7741 :           xfree (a->d.buf);
    1160             :         }
    1161        7741 :       xfree (a);
    1162             :     }
    1163       17021 :   return rc;
    1164             : }
    1165             : 
    1166             : int
    1167           6 : iobuf_cancel (iobuf_t a)
    1168             : {
    1169             :   const char *s;
    1170             :   iobuf_t a2;
    1171             :   int rc;
    1172             : #if defined(HAVE_W32_SYSTEM) || defined(__riscos__)
    1173             :   char *remove_name = NULL;
    1174             : #endif
    1175             : 
    1176           6 :   if (a && a->use == IOBUF_OUTPUT)
    1177             :     {
    1178           0 :       s = iobuf_get_real_fname (a);
    1179           0 :       if (s && *s)
    1180             :         {
    1181             : #if defined(HAVE_W32_SYSTEM) || defined(__riscos__)
    1182             :           remove_name = xstrdup (s);
    1183             : #else
    1184           0 :           remove (s);
    1185             : #endif
    1186             :         }
    1187             :     }
    1188             : 
    1189             :   /* send a cancel message to all filters */
    1190           6 :   for (a2 = a; a2; a2 = a2->chain)
    1191             :     {
    1192             :       size_t dummy;
    1193           0 :       if (a2->filter)
    1194           0 :         a2->filter (a2->filter_ov, IOBUFCTRL_CANCEL, a2->chain, NULL, &dummy);
    1195             :     }
    1196             : 
    1197           6 :   rc = iobuf_close (a);
    1198             : #if defined(HAVE_W32_SYSTEM) || defined(__riscos__)
    1199             :   if (remove_name)
    1200             :     {
    1201             :       /* Argg, MSDOS does not allow removing open files.  So
    1202             :        * we have to do it here */
    1203             : #ifdef HAVE_W32CE_SYSTEM
    1204             :       wchar_t *wtmp = utf8_to_wchar (remove_name);
    1205             :       if (wtmp)
    1206             :         DeleteFile (wtmp);
    1207             :       xfree (wtmp);
    1208             : #else
    1209             :       remove (remove_name);
    1210             : #endif
    1211             :       xfree (remove_name);
    1212             :     }
    1213             : #endif
    1214           6 :   return rc;
    1215             : }
    1216             : 
    1217             : 
    1218             : iobuf_t
    1219        1496 : iobuf_temp (void)
    1220             : {
    1221        1496 :   return iobuf_alloc (IOBUF_OUTPUT_TEMP, IOBUF_BUFFER_SIZE);
    1222             : }
    1223             : 
    1224             : iobuf_t
    1225        3361 : iobuf_temp_with_content (const char *buffer, size_t length)
    1226             : {
    1227             :   iobuf_t a;
    1228             :   int i;
    1229             : 
    1230        3361 :   a = iobuf_alloc (IOBUF_INPUT_TEMP, length);
    1231        3361 :   assert (length == a->d.size);
    1232             :   /* memcpy (a->d.buf, buffer, length); */
    1233     3204499 :   for (i=0; i < length; i++)
    1234     3201138 :     a->d.buf[i] = buffer[i];
    1235        3361 :   a->d.len = length;
    1236             : 
    1237        3361 :   return a;
    1238             : }
    1239             : 
    1240             : void
    1241           0 : iobuf_enable_special_filenames (int yes)
    1242             : {
    1243           0 :   special_names_enabled = yes;
    1244           0 : }
    1245             : 
    1246             : 
    1247             : /* See whether the filename has the form "-&nnnn", where n is a
    1248             :    non-zero number.  Returns this number or -1 if it is not the
    1249             :    case.  */
    1250             : static int
    1251        3951 : check_special_filename (const char *fname)
    1252             : {
    1253        3951 :   if (special_names_enabled && fname && *fname == '-' && fname[1] == '&')
    1254             :     {
    1255             :       int i;
    1256             : 
    1257           0 :       fname += 2;
    1258           0 :       for (i = 0; digitp (fname+i); i++)
    1259             :         ;
    1260           0 :       if (!fname[i])
    1261           0 :         return atoi (fname);
    1262             :     }
    1263        3951 :   return -1;
    1264             : }
    1265             : 
    1266             : 
    1267             : int
    1268        2761 : iobuf_is_pipe_filename (const char *fname)
    1269             : {
    1270        2761 :   if (!fname || (*fname=='-' && !fname[1]) )
    1271         397 :     return 1;
    1272        2364 :   return check_special_filename (fname) != -1;
    1273             : }
    1274             : 
    1275             : static iobuf_t
    1276        1830 : do_open (const char *fname, int special_filenames,
    1277             :          int use, const char *opentype, int mode700)
    1278             : {
    1279             :   iobuf_t a;
    1280             :   gnupg_fd_t fp;
    1281             :   file_filter_ctx_t *fcx;
    1282        1830 :   size_t len = 0;
    1283        1830 :   int print_only = 0;
    1284             :   int fd;
    1285             :   byte desc[MAX_IOBUF_DESC];
    1286             : 
    1287        1830 :   assert (use == IOBUF_INPUT || use == IOBUF_OUTPUT);
    1288             : 
    1289        1830 :   if (special_filenames
    1290             :       /* NULL or '-'.  */
    1291        1830 :       && (!fname || (*fname == '-' && !fname[1])))
    1292             :     {
    1293         243 :       if (use == IOBUF_INPUT)
    1294             :         {
    1295         163 :           fp = FD_FOR_STDIN;
    1296         163 :           fname = "[stdin]";
    1297             :         }
    1298             :       else
    1299             :         {
    1300          80 :           fp = FD_FOR_STDOUT;
    1301          80 :           fname = "[stdout]";
    1302             :         }
    1303         243 :       print_only = 1;
    1304             :     }
    1305        1587 :   else if (!fname)
    1306           0 :     return NULL;
    1307        1587 :   else if (special_filenames && (fd = check_special_filename (fname)) != -1)
    1308           0 :     return iobuf_fdopen (translate_file_handle (fd, use == IOBUF_INPUT ? 0 : 1),
    1309             :                          opentype);
    1310             :   else
    1311             :     {
    1312        1587 :       if (use == IOBUF_INPUT)
    1313        1212 :         fp = fd_cache_open (fname, opentype);
    1314             :       else
    1315         375 :         fp = direct_open (fname, opentype, mode700);
    1316        1587 :       if (fp == GNUPG_INVALID_FD)
    1317           0 :         return NULL;
    1318             :     }
    1319             : 
    1320        1830 :   a = iobuf_alloc (use, IOBUF_BUFFER_SIZE);
    1321        1830 :   fcx = xmalloc (sizeof *fcx + strlen (fname));
    1322        1830 :   fcx->fp = fp;
    1323        1830 :   fcx->print_only_name = print_only;
    1324        1830 :   strcpy (fcx->fname, fname);
    1325        1830 :   if (!print_only)
    1326        1587 :     a->real_fname = xstrdup (fname);
    1327        1830 :   a->filter = file_filter;
    1328        1830 :   a->filter_ov = fcx;
    1329        1830 :   file_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len);
    1330        1830 :   if (DBG_IOBUF)
    1331           0 :     log_debug ("iobuf-%d.%d: open '%s' desc=%s fd=%d\n",
    1332             :                a->no, a->subno, fname, iobuf_desc (a, desc), FD2INT (fcx->fp));
    1333             : 
    1334        1830 :   return a;
    1335             : }
    1336             : 
    1337             : iobuf_t
    1338        1375 : iobuf_open (const char *fname)
    1339             : {
    1340        1375 :   return do_open (fname, 1, IOBUF_INPUT, "rb", 0);
    1341             : }
    1342             : 
    1343             : iobuf_t
    1344         455 : iobuf_create (const char *fname, int mode700)
    1345             : {
    1346         455 :   return do_open (fname, 1, IOBUF_OUTPUT, "wb", mode700);
    1347             : }
    1348             : 
    1349             : iobuf_t
    1350           0 : iobuf_openrw (const char *fname)
    1351             : {
    1352           0 :   return do_open (fname, 0, IOBUF_OUTPUT, "r+b", 0);
    1353             : }
    1354             : 
    1355             : 
    1356             : static iobuf_t
    1357           0 : do_iobuf_fdopen (int fd, const char *mode, int keep_open)
    1358             : {
    1359             :   iobuf_t a;
    1360             :   gnupg_fd_t fp;
    1361             :   file_filter_ctx_t *fcx;
    1362             :   size_t len;
    1363             : 
    1364           0 :   fp = INT2FD (fd);
    1365             : 
    1366           0 :   a = iobuf_alloc (strchr (mode, 'w') ? IOBUF_OUTPUT : IOBUF_INPUT,
    1367             :                    IOBUF_BUFFER_SIZE);
    1368           0 :   fcx = xmalloc (sizeof *fcx + 20);
    1369           0 :   fcx->fp = fp;
    1370           0 :   fcx->print_only_name = 1;
    1371           0 :   fcx->keep_open = keep_open;
    1372           0 :   sprintf (fcx->fname, "[fd %d]", fd);
    1373           0 :   a->filter = file_filter;
    1374           0 :   a->filter_ov = fcx;
    1375           0 :   file_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len);
    1376           0 :   if (DBG_IOBUF)
    1377           0 :     log_debug ("iobuf-%d.%d: fdopen%s '%s'\n",
    1378           0 :                a->no, a->subno, keep_open? "_nc":"", fcx->fname);
    1379           0 :   iobuf_ioctl (a, IOBUF_IOCTL_NO_CACHE, 1, NULL);
    1380           0 :   return a;
    1381             : }
    1382             : 
    1383             : 
    1384             : iobuf_t
    1385           0 : iobuf_fdopen (int fd, const char *mode)
    1386             : {
    1387           0 :   return do_iobuf_fdopen (fd, mode, 0);
    1388             : }
    1389             : 
    1390             : iobuf_t
    1391           0 : iobuf_fdopen_nc (int fd, const char *mode)
    1392             : {
    1393           0 :   return do_iobuf_fdopen (fd, mode, 1);
    1394             : }
    1395             : 
    1396             : 
    1397             : iobuf_t
    1398           0 : iobuf_esopen (estream_t estream, const char *mode, int keep_open)
    1399             : {
    1400             :   iobuf_t a;
    1401             :   file_es_filter_ctx_t *fcx;
    1402           0 :   size_t len = 0;
    1403             : 
    1404           0 :   a = iobuf_alloc (strchr (mode, 'w') ? IOBUF_OUTPUT : IOBUF_INPUT,
    1405             :                    IOBUF_BUFFER_SIZE);
    1406           0 :   fcx = xtrymalloc (sizeof *fcx + 30);
    1407           0 :   fcx->fp = estream;
    1408           0 :   fcx->print_only_name = 1;
    1409           0 :   fcx->keep_open = keep_open;
    1410           0 :   sprintf (fcx->fname, "[fd %p]", estream);
    1411           0 :   a->filter = file_es_filter;
    1412           0 :   a->filter_ov = fcx;
    1413           0 :   file_es_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len);
    1414           0 :   if (DBG_IOBUF)
    1415           0 :     log_debug ("iobuf-%d.%d: esopen%s '%s'\n",
    1416           0 :                a->no, a->subno, keep_open? "_nc":"", fcx->fname);
    1417           0 :   return a;
    1418             : }
    1419             : 
    1420             : 
    1421             : iobuf_t
    1422           0 : iobuf_sockopen (int fd, const char *mode)
    1423             : {
    1424             :   iobuf_t a;
    1425             : #ifdef HAVE_W32_SYSTEM
    1426             :   sock_filter_ctx_t *scx;
    1427             :   size_t len;
    1428             : 
    1429             :   a = iobuf_alloc (strchr (mode, 'w') ? IOBUF_OUTPUT : IOBUF_INPUT,
    1430             :                    IOBUF_BUFFER_SIZE);
    1431             :   scx = xmalloc (sizeof *scx + 25);
    1432             :   scx->sock = fd;
    1433             :   scx->print_only_name = 1;
    1434             :   sprintf (scx->fname, "[sock %d]", fd);
    1435             :   a->filter = sock_filter;
    1436             :   a->filter_ov = scx;
    1437             :   sock_filter (scx, IOBUFCTRL_INIT, NULL, NULL, &len);
    1438             :   if (DBG_IOBUF)
    1439             :     log_debug ("iobuf-%d.%d: sockopen '%s'\n", a->no, a->subno, scx->fname);
    1440             :   iobuf_ioctl (a, IOBUF_IOCTL_NO_CACHE, 1, NULL);
    1441             : #else
    1442           0 :   a = iobuf_fdopen (fd, mode);
    1443             : #endif
    1444           0 :   return a;
    1445             : }
    1446             : 
    1447             : int
    1448         859 : iobuf_ioctl (iobuf_t a, iobuf_ioctl_t cmd, int intval, void *ptrval)
    1449             : {
    1450             :   byte desc[MAX_IOBUF_DESC];
    1451             : 
    1452         859 :   if (cmd == IOBUF_IOCTL_KEEP_OPEN)
    1453             :     {
    1454             :       /* Keep system filepointer/descriptor open.  This was used in
    1455             :          the past by http.c; this ioctl is not directly used
    1456             :          anymore.  */
    1457           0 :       if (DBG_IOBUF)
    1458           0 :         log_debug ("iobuf-%d.%d: ioctl '%s' keep_open=%d\n",
    1459             :                    a ? a->no : -1, a ? a->subno : -1, iobuf_desc (a, desc),
    1460             :                    intval);
    1461           0 :       for (; a; a = a->chain)
    1462           0 :         if (!a->chain && a->filter == file_filter)
    1463             :           {
    1464           0 :             file_filter_ctx_t *b = a->filter_ov;
    1465           0 :             b->keep_open = intval;
    1466           0 :             return 0;
    1467             :           }
    1468             : #ifdef HAVE_W32_SYSTEM
    1469             :         else if (!a->chain && a->filter == sock_filter)
    1470             :           {
    1471             :             sock_filter_ctx_t *b = a->filter_ov;
    1472             :             b->keep_open = intval;
    1473             :             return 0;
    1474             :           }
    1475             : #endif
    1476             :     }
    1477         859 :   else if (cmd == IOBUF_IOCTL_INVALIDATE_CACHE)
    1478             :     {
    1479         144 :       if (DBG_IOBUF)
    1480           0 :         log_debug ("iobuf-*.*: ioctl '%s' invalidate\n",
    1481             :                    ptrval ? (char *) ptrval : "?");
    1482         144 :       if (!a && !intval && ptrval)
    1483             :         {
    1484         144 :           if (fd_cache_invalidate (ptrval))
    1485           0 :             return -1;
    1486         144 :           return 0;
    1487             :         }
    1488             :     }
    1489         715 :   else if (cmd == IOBUF_IOCTL_NO_CACHE)
    1490             :     {
    1491         715 :       if (DBG_IOBUF)
    1492           0 :         log_debug ("iobuf-%d.%d: ioctl '%s' no_cache=%d\n",
    1493             :                    a ? a->no : -1, a ? a->subno : -1, iobuf_desc (a, desc),
    1494             :                    intval);
    1495         715 :       for (; a; a = a->chain)
    1496         715 :         if (!a->chain && a->filter == file_filter)
    1497             :           {
    1498         715 :             file_filter_ctx_t *b = a->filter_ov;
    1499         715 :             b->no_cache = intval;
    1500         715 :             return 0;
    1501             :           }
    1502             : #ifdef HAVE_W32_SYSTEM
    1503             :         else if (!a->chain && a->filter == sock_filter)
    1504             :           {
    1505             :             sock_filter_ctx_t *b = a->filter_ov;
    1506             :             b->no_cache = intval;
    1507             :             return 0;
    1508             :           }
    1509             : #endif
    1510             :     }
    1511           0 :   else if (cmd == IOBUF_IOCTL_FSYNC)
    1512             :     {
    1513             :       /* Do a fsync on the open fd and return any errors to the caller
    1514             :          of iobuf_ioctl.  Note that we work on a file name here. */
    1515           0 :       if (DBG_IOBUF)
    1516           0 :         log_debug ("iobuf-*.*: ioctl '%s' fsync\n",
    1517             :                    ptrval? (const char*)ptrval:"<null>");
    1518             : 
    1519           0 :       if (!a && !intval && ptrval)
    1520             :         {
    1521           0 :           return fd_cache_synchronize (ptrval);
    1522             :         }
    1523             :     }
    1524             : 
    1525             : 
    1526           0 :   return -1;
    1527             : }
    1528             : 
    1529             : 
    1530             : /****************
    1531             :  * Register an i/o filter.
    1532             :  */
    1533             : int
    1534        1748 : iobuf_push_filter (iobuf_t a,
    1535             :                    int (*f) (void *opaque, int control,
    1536             :                              iobuf_t chain, byte * buf, size_t * len),
    1537             :                    void *ov)
    1538             : {
    1539        1748 :   return iobuf_push_filter2 (a, f, ov, 0);
    1540             : }
    1541             : 
    1542             : int
    1543        2544 : iobuf_push_filter2 (iobuf_t a,
    1544             :                     int (*f) (void *opaque, int control,
    1545             :                               iobuf_t chain, byte * buf, size_t * len),
    1546             :                     void *ov, int rel_ov)
    1547             : {
    1548             :   iobuf_t b;
    1549        2544 :   size_t dummy_len = 0;
    1550        2544 :   int rc = 0;
    1551             : 
    1552        2544 :   if (a->use == IOBUF_OUTPUT && (rc = filter_flush (a)))
    1553           0 :     return rc;
    1554             : 
    1555        2544 :   if (a->subno >= MAX_NESTING_FILTER)
    1556             :     {
    1557           0 :       log_error ("i/o filter too deeply nested - corrupted data?\n");
    1558           0 :       return GPG_ERR_BAD_DATA;
    1559             :     }
    1560             : 
    1561             :   /* We want to create a new filter and put it in front of A.  A
    1562             :      simple implementation would do:
    1563             : 
    1564             :        b = iobuf_alloc (...);
    1565             :        b->chain = a;
    1566             :        return a;
    1567             : 
    1568             :      This is a bit problematic: A is the head of the pipeline and
    1569             :      there are potentially many pointers to it.  Requiring the caller
    1570             :      to update all of these pointers is a burden.
    1571             : 
    1572             :      An alternative implementation would add a level of indirection.
    1573             :      For instance, we could use a pipeline object, which contains a
    1574             :      pointer to the first filter in the pipeline.  This is not what we
    1575             :      do either.
    1576             : 
    1577             :      Instead, we allocate a new buffer (B) and copy the first filter's
    1578             :      state into that and use the initial buffer (A) for the new
    1579             :      filter.  One limitation of this approach is that it is not
    1580             :      practical to maintain a pointer to a specific filter's state.
    1581             : 
    1582             :      Before:
    1583             : 
    1584             :            A
    1585             :            |
    1586             :            v 0x100               0x200
    1587             :            +----------+          +----------+
    1588             :            | filter x |--------->| filter y |---->....
    1589             :            +----------+          +----------+
    1590             : 
    1591             :      After:           B
    1592             :                       |
    1593             :                       v 0x300
    1594             :                       +----------+
    1595             :            A          | filter x |
    1596             :            |          +----------+
    1597             :            v 0x100    ^          v 0x200
    1598             :            +----------+          +----------+
    1599             :            | filter w |          | filter y |---->....
    1600             :            +----------+          +----------+
    1601             : 
    1602             :      Note: filter x's address changed from 0x100 to 0x300, but A still
    1603             :      points to the head of the pipeline.
    1604             :   */
    1605             : 
    1606        2544 :   b = xmalloc (sizeof *b);
    1607        2544 :   memcpy (b, a, sizeof *b);
    1608             :   /* fixme: it is stupid to keep a copy of the name at every level
    1609             :    * but we need the name somewhere because the name known by file_filter
    1610             :    * may have been released when we need the name of the file */
    1611        2544 :   b->real_fname = a->real_fname ? xstrdup (a->real_fname) : NULL;
    1612             :   /* remove the filter stuff from the new stream */
    1613        2544 :   a->filter = NULL;
    1614        2544 :   a->filter_ov = NULL;
    1615        2544 :   a->filter_ov_owner = 0;
    1616        2544 :   a->filter_eof = 0;
    1617        2544 :   if (a->use == IOBUF_OUTPUT_TEMP)
    1618             :     /* A TEMP filter buffers any data sent to it; it does not forward
    1619             :        any data down the pipeline.  If we add a new filter to the
    1620             :        pipeline, it shouldn't also buffer data.  It should send it
    1621             :        downstream to be buffered.  Thus, the correct type for a filter
    1622             :        added in front of an IOBUF_OUTPUT_TEMP filter is IOBUF_OUPUT, not
    1623             :        IOBUF_OUTPUT_TEMP.  */
    1624             :     {
    1625           1 :       a->use = IOBUF_OUTPUT;
    1626             : 
    1627             :       /* When pipeline is written to, the temp buffer's size is
    1628             :          increased accordingly.  We don't need to allocate a 10 MB
    1629             :          buffer for a non-terminal filter.  Just use the default
    1630             :          size.  */
    1631           1 :       a->d.size = IOBUF_BUFFER_SIZE;
    1632             :     }
    1633        2543 :   else if (a->use == IOBUF_INPUT_TEMP)
    1634             :     /* Same idea as above.  */
    1635             :     {
    1636           4 :       a->use = IOBUF_INPUT;
    1637           4 :       a->d.size = IOBUF_BUFFER_SIZE;
    1638             :     }
    1639             : 
    1640             :   /* The new filter (A) gets a new buffer.
    1641             : 
    1642             :      If the pipeline is an output or temp pipeline, then giving the
    1643             :      buffer to the new filter means that data that was written before
    1644             :      the filter was pushed gets sent to the filter.  That's clearly
    1645             :      wrong.
    1646             : 
    1647             :      If the pipeline is an input pipeline, then giving the buffer to
    1648             :      the new filter (A) means that data that has read from (B), but
    1649             :      not yet read from the pipeline won't be processed by the new
    1650             :      filter (A)!  That's certainly not what we want.  */
    1651        2544 :   a->d.buf = xmalloc (a->d.size);
    1652        2544 :   a->d.len = 0;
    1653        2544 :   a->d.start = 0;
    1654             : 
    1655             :   /* disable nlimit for the new stream */
    1656        2544 :   a->ntotal = b->ntotal + b->nbytes;
    1657        2544 :   a->nlimit = a->nbytes = 0;
    1658        2544 :   a->nofast = 0;
    1659             :   /* make a link from the new stream to the original stream */
    1660        2544 :   a->chain = b;
    1661             : 
    1662             :   /* setup the function on the new stream */
    1663        2544 :   a->filter = f;
    1664        2544 :   a->filter_ov = ov;
    1665        2544 :   a->filter_ov_owner = rel_ov;
    1666             : 
    1667        2544 :   a->subno = b->subno + 1;
    1668             : 
    1669        2544 :   if (DBG_IOBUF)
    1670             :     {
    1671             :       byte desc[MAX_IOBUF_DESC];
    1672           0 :       log_debug ("iobuf-%d.%d: push '%s'\n",
    1673             :                  a->no, a->subno, iobuf_desc (a, desc));
    1674           0 :       print_chain (a);
    1675             :     }
    1676             : 
    1677             :   /* now we can initialize the new function if we have one */
    1678        2544 :   if (a->filter && (rc = a->filter (a->filter_ov, IOBUFCTRL_INIT, a->chain,
    1679             :                                     NULL, &dummy_len)))
    1680           0 :     log_error ("IOBUFCTRL_INIT failed: %s\n", gpg_strerror (rc));
    1681        2544 :   return rc;
    1682             : }
    1683             : 
    1684             : /****************
    1685             :  * Remove an i/o filter.
    1686             :  */
    1687             : int
    1688          41 : iobuf_pop_filter (iobuf_t a, int (*f) (void *opaque, int control,
    1689             :                                        iobuf_t chain, byte * buf, size_t * len),
    1690             :                   void *ov)
    1691             : {
    1692             :   iobuf_t b;
    1693          41 :   size_t dummy_len = 0;
    1694          41 :   int rc = 0;
    1695             :   byte desc[MAX_IOBUF_DESC];
    1696             : 
    1697          41 :   if (DBG_IOBUF)
    1698           0 :     log_debug ("iobuf-%d.%d: pop '%s'\n",
    1699             :                a->no, a->subno, iobuf_desc (a, desc));
    1700          41 :   if (a->use == IOBUF_INPUT_TEMP || a->use == IOBUF_OUTPUT_TEMP)
    1701             :     {
    1702             :       /* This should be the last filter in the pipeline.  */
    1703           0 :       assert (! a->chain);
    1704           0 :       return 0;
    1705             :     }
    1706          41 :   if (!a->filter)
    1707             :     {                           /* this is simple */
    1708           0 :       b = a->chain;
    1709           0 :       assert (b);
    1710           0 :       xfree (a->d.buf);
    1711           0 :       xfree (a->real_fname);
    1712           0 :       memcpy (a, b, sizeof *a);
    1713           0 :       xfree (b);
    1714           0 :       return 0;
    1715             :     }
    1716          41 :   for (b = a; b; b = b->chain)
    1717          41 :     if (b->filter == f && (!ov || b->filter_ov == ov))
    1718             :       break;
    1719          41 :   if (!b)
    1720           0 :     log_bug ("iobuf_pop_filter(): filter function not found\n");
    1721             : 
    1722             :   /* flush this stream if it is an output stream */
    1723          41 :   if (a->use == IOBUF_OUTPUT && (rc = filter_flush (b)))
    1724             :     {
    1725           0 :       log_error ("filter_flush failed in iobuf_pop_filter: %s\n",
    1726             :                  gpg_strerror (rc));
    1727           0 :       return rc;
    1728             :     }
    1729             :   /* and tell the filter to free it self */
    1730          41 :   if (b->filter && (rc = b->filter (b->filter_ov, IOBUFCTRL_FREE, b->chain,
    1731             :                                     NULL, &dummy_len)))
    1732             :     {
    1733           0 :       log_error ("IOBUFCTRL_FREE failed: %s\n", gpg_strerror (rc));
    1734           0 :       return rc;
    1735             :     }
    1736          41 :   if (b->filter_ov && b->filter_ov_owner)
    1737             :     {
    1738           0 :       xfree (b->filter_ov);
    1739           0 :       b->filter_ov = NULL;
    1740             :     }
    1741             : 
    1742             : 
    1743             :   /* and see how to remove it */
    1744          41 :   if (a == b && !b->chain)
    1745           0 :     log_bug ("can't remove the last filter from the chain\n");
    1746          41 :   else if (a == b)
    1747             :     {                           /* remove the first iobuf from the chain */
    1748             :       /* everything from b is copied to a. This is save because
    1749             :        * a flush has been done on the to be removed entry
    1750             :        */
    1751          41 :       b = a->chain;
    1752          41 :       xfree (a->d.buf);
    1753          41 :       xfree (a->real_fname);
    1754          41 :       memcpy (a, b, sizeof *a);
    1755          41 :       xfree (b);
    1756          41 :       if (DBG_IOBUF)
    1757           0 :         log_debug ("iobuf-%d.%d: popped filter\n", a->no, a->subno);
    1758             :     }
    1759           0 :   else if (!b->chain)
    1760             :     {                           /* remove the last iobuf from the chain */
    1761           0 :       log_bug ("Ohh jeee, trying to remove a head filter\n");
    1762             :     }
    1763             :   else
    1764             :     {                           /* remove an intermediate iobuf from the chain */
    1765           0 :       log_bug ("Ohh jeee, trying to remove an intermediate filter\n");
    1766             :     }
    1767             : 
    1768          41 :   return rc;
    1769             : }
    1770             : 
    1771             : 
    1772             : /****************
    1773             :  * read underflow: read at least one byte into the buffer and return
    1774             :  * the first byte or -1 on EOF.
    1775             :  */
    1776             : static int
    1777      538872 : underflow (iobuf_t a, int clear_pending_eof)
    1778             : {
    1779      538872 :   return underflow_target (a, clear_pending_eof, 1);
    1780             : }
    1781             : 
    1782             : 
    1783             : /****************
    1784             :  * read underflow: read TARGET bytes into the buffer and return
    1785             :  * the first byte or -1 on EOF.
    1786             :  */
    1787             : static int
    1788      539356 : underflow_target (iobuf_t a, int clear_pending_eof, size_t target)
    1789             : {
    1790             :   size_t len;
    1791             :   int rc;
    1792             : 
    1793      539356 :   if (DBG_IOBUF)
    1794           0 :     log_debug ("iobuf-%d.%d: underflow: buffer size: %d; still buffered: %d => space for %d bytes\n",
    1795             :                a->no, a->subno,
    1796           0 :                (int) a->d.size, (int) (a->d.len - a->d.start),
    1797           0 :                (int) (a->d.size - (a->d.len - a->d.start)));
    1798             : 
    1799      539356 :   if (a->use == IOBUF_INPUT_TEMP)
    1800             :     /* By definition, there isn't more data to read into the
    1801             :        buffer.  */
    1802        3236 :     return -1;
    1803             : 
    1804      536120 :   assert (a->use == IOBUF_INPUT);
    1805             : 
    1806             :   /* If there is still some buffered data, then move it to the start
    1807             :      of the buffer and try to fill the end of the buffer.  (This is
    1808             :      useful if we are called from iobuf_peek().)  */
    1809      536120 :   assert (a->d.start <= a->d.len);
    1810      536120 :   a->d.len -= a->d.start;
    1811      536120 :   memmove (a->d.buf, &a->d.buf[a->d.start], a->d.len);
    1812      536120 :   a->d.start = 0;
    1813             : 
    1814      536120 :   if (a->d.len < target && a->filter_eof)
    1815             :     /* The last time we tried to read from this filter, we got an EOF.
    1816             :        We couldn't return the EOF, because there was buffered data.
    1817             :        Since there is no longer any buffered data, return the
    1818             :        error.  */
    1819             :     {
    1820        1427 :       if (DBG_IOBUF)
    1821           0 :         log_debug ("iobuf-%d.%d: underflow: eof (pending eof)\n",
    1822             :                    a->no, a->subno);
    1823        1427 :       if (! clear_pending_eof)
    1824           1 :         return -1;
    1825             : 
    1826        1426 :       if (a->chain)
    1827             :         /* A filter follows this one.  Free this filter.  */
    1828             :         {
    1829         424 :           iobuf_t b = a->chain;
    1830         424 :           if (DBG_IOBUF)
    1831           0 :             log_debug ("iobuf-%d.%d: filter popped (pending EOF returned)\n",
    1832             :                        a->no, a->subno);
    1833         424 :           xfree (a->d.buf);
    1834         424 :           xfree (a->real_fname);
    1835         424 :           memcpy (a, b, sizeof *a);
    1836         424 :           xfree (b);
    1837         424 :           print_chain (a);
    1838             :         }
    1839             :       else
    1840        1002 :         a->filter_eof = 0;   /* for the top level filter */
    1841        1426 :       return -1;                /* return one(!) EOF */
    1842             :     }
    1843             : 
    1844      534693 :   if (a->d.len == 0 && a->error)
    1845             :     /* The last time we tried to read from this filter, we got an
    1846             :        error.  We couldn't return the error, because there was
    1847             :        buffered data.  Since there is no longer any buffered data,
    1848             :        return the error.  */
    1849             :     {
    1850           0 :       if (DBG_IOBUF)
    1851           0 :         log_debug ("iobuf-%d.%d: pending error (%s) returned\n",
    1852           0 :                    a->no, a->subno, gpg_strerror (a->error));
    1853           0 :       return -1;
    1854             :     }
    1855             : 
    1856      534693 :   if (a->filter && ! a->filter_eof && ! a->error)
    1857             :     /* We have a filter function and the last time we tried to read we
    1858             :        didn't get an EOF or an error.  Try to fill the buffer.  */
    1859             :     {
    1860             :       /* Be careful to account for any buffered data.  */
    1861      534420 :       len = a->d.size - a->d.len;
    1862      534420 :       if (DBG_IOBUF)
    1863           0 :         log_debug ("iobuf-%d.%d: underflow: A->FILTER (%lu bytes)\n",
    1864             :                    a->no, a->subno, (ulong) len);
    1865      534420 :       if (len == 0)
    1866             :         /* There is no space for more data.  Don't bother calling
    1867             :            A->FILTER.  */
    1868           0 :         rc = 0;
    1869             :       else
    1870     1068840 :         rc = a->filter (a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain,
    1871      534420 :                         &a->d.buf[a->d.len], &len);
    1872      534420 :       a->d.len += len;
    1873             : 
    1874      534420 :       if (DBG_IOBUF)
    1875           0 :         log_debug ("iobuf-%d.%d: A->FILTER() returned rc=%d (%s), read %lu bytes\n",
    1876             :                    a->no, a->subno,
    1877           0 :                    rc, rc == 0 ? "ok" : rc == -1 ? "EOF" : gpg_strerror (rc),
    1878             :                    (ulong) len);
    1879             : /*          if( a->no == 1 ) */
    1880             : /*                   log_hexdump ("     data:", a->d.buf, len); */
    1881             : 
    1882      534420 :       if (rc == -1)
    1883             :         /* EOF.  */
    1884             :         {
    1885        2558 :           size_t dummy_len = 0;
    1886             : 
    1887             :           /* Tell the filter to free itself */
    1888        2558 :           if ((rc = a->filter (a->filter_ov, IOBUFCTRL_FREE, a->chain,
    1889             :                                NULL, &dummy_len)))
    1890           0 :             log_error ("IOBUFCTRL_FREE failed: %s\n", gpg_strerror (rc));
    1891             : 
    1892             :           /* Free everything except for the internal buffer.  */
    1893        2558 :           if (a->filter_ov && a->filter_ov_owner)
    1894           0 :             xfree (a->filter_ov);
    1895        2558 :           a->filter_ov = NULL;
    1896        2558 :           a->filter = NULL;
    1897        2558 :           a->filter_eof = 1;
    1898             : 
    1899        2558 :           if (clear_pending_eof && a->d.len == 0 && a->chain)
    1900             :             /* We don't need to keep this filter around at all:
    1901             : 
    1902             :                  - we got an EOF
    1903             :                  - we have no buffered data
    1904             :                  - a filter follows this one.
    1905             : 
    1906             :               Unlink this filter.  */
    1907             :             {
    1908        1022 :               iobuf_t b = a->chain;
    1909        1022 :               if (DBG_IOBUF)
    1910           0 :                 log_debug ("iobuf-%d.%d: pop in underflow (nothing buffered, got EOF)\n",
    1911             :                            a->no, a->subno);
    1912        1022 :               xfree (a->d.buf);
    1913        1022 :               xfree (a->real_fname);
    1914        1022 :               memcpy (a, b, sizeof *a);
    1915        1022 :               xfree (b);
    1916             : 
    1917        1022 :               print_chain (a);
    1918             : 
    1919        3155 :               return -1;
    1920             :             }
    1921        1536 :           else if (a->d.len == 0)
    1922             :             /* We can't unlink this filter (it is the only one in the
    1923             :                pipeline), but we can immediately return EOF.  */
    1924        1111 :             return -1;
    1925             :         }
    1926      531862 :       else if (rc)
    1927             :         /* Record the error.  */
    1928             :         {
    1929           0 :           a->error = rc;
    1930             : 
    1931           0 :           if (a->d.len == 0)
    1932             :             /* There is no buffered data.  Immediately return EOF.  */
    1933           0 :             return -1;
    1934             :         }
    1935             :     }
    1936             : 
    1937      532560 :   assert (a->d.start <= a->d.len);
    1938      532560 :   if (a->d.start < a->d.len)
    1939      532285 :     return a->d.buf[a->d.start++];
    1940             : 
    1941             :   /* EOF.  */
    1942         275 :   return -1;
    1943             : }
    1944             : 
    1945             : 
    1946             : static int
    1947        6085 : filter_flush (iobuf_t a)
    1948             : {
    1949             :   size_t len;
    1950             :   int rc;
    1951             : 
    1952        6085 :   if (a->use == IOBUF_OUTPUT_TEMP)
    1953             :     {                           /* increase the temp buffer */
    1954          50 :       size_t newsize = a->d.size + IOBUF_BUFFER_SIZE;
    1955             : 
    1956          50 :       if (DBG_IOBUF)
    1957           0 :         log_debug ("increasing temp iobuf from %lu to %lu\n",
    1958             :                    (ulong) a->d.size, (ulong) newsize);
    1959             : 
    1960          50 :       a->d.buf = xrealloc (a->d.buf, newsize);
    1961          50 :       a->d.size = newsize;
    1962          50 :       return 0;
    1963             :     }
    1964        6035 :   else if (a->use != IOBUF_OUTPUT)
    1965           0 :     log_bug ("flush on non-output iobuf\n");
    1966        6035 :   else if (!a->filter)
    1967           0 :     log_bug ("filter_flush: no filter\n");
    1968        6035 :   len = a->d.len;
    1969        6035 :   rc = a->filter (a->filter_ov, IOBUFCTRL_FLUSH, a->chain, a->d.buf, &len);
    1970        6035 :   if (!rc && len != a->d.len)
    1971             :     {
    1972           0 :       log_info ("filter_flush did not write all!\n");
    1973           0 :       rc = GPG_ERR_INTERNAL;
    1974             :     }
    1975        6035 :   else if (rc)
    1976           0 :     a->error = rc;
    1977        6035 :   a->d.len = 0;
    1978             : 
    1979        6035 :   return rc;
    1980             : }
    1981             : 
    1982             : 
    1983             : int
    1984        9416 : iobuf_readbyte (iobuf_t a)
    1985             : {
    1986             :   int c;
    1987             : 
    1988        9416 :   if (a->use == IOBUF_OUTPUT || a->use == IOBUF_OUTPUT_TEMP)
    1989             :     {
    1990           0 :       log_bug ("iobuf_readbyte called on a non-INPUT pipeline!\n");
    1991             :       return -1;
    1992             :     }
    1993             : 
    1994        9416 :   assert (a->d.start <= a->d.len);
    1995             : 
    1996        9416 :   if (a->nlimit && a->nbytes >= a->nlimit)
    1997           0 :     return -1;                  /* forced EOF */
    1998             : 
    1999        9416 :   if (a->d.start < a->d.len)
    2000             :     {
    2001         884 :       c = a->d.buf[a->d.start++];
    2002             :     }
    2003        8532 :   else if ((c = underflow (a, 1)) == -1)
    2004        5653 :     return -1;                  /* EOF */
    2005             : 
    2006        3763 :   assert (a->d.start <= a->d.len);
    2007             : 
    2008             :   /* Note: if underflow doesn't return EOF, then it returns the first
    2009             :      byte that was read and advances a->d.start appropriately.  */
    2010             : 
    2011        3763 :   a->nbytes++;
    2012        3763 :   return c;
    2013             : }
    2014             : 
    2015             : 
    2016             : int
    2017       26215 : iobuf_read (iobuf_t a, void *buffer, unsigned int buflen)
    2018             : {
    2019       26215 :   unsigned char *buf = (unsigned char *)buffer;
    2020             :   int c, n;
    2021             : 
    2022       26215 :   if (a->use == IOBUF_OUTPUT || a->use == IOBUF_OUTPUT_TEMP)
    2023             :     {
    2024           0 :       log_bug ("iobuf_read called on a non-INPUT pipeline!\n");
    2025             :       return -1;
    2026             :     }
    2027             : 
    2028       26215 :   if (a->nlimit)
    2029             :     {
    2030             :       /* Handle special cases. */
    2031           0 :       for (n = 0; n < buflen; n++)
    2032             :         {
    2033           0 :           if ((c = iobuf_readbyte (a)) == -1)
    2034             :             {
    2035           0 :               if (!n)
    2036           0 :                 return -1;      /* eof */
    2037           0 :               break;
    2038             :             }
    2039             : 
    2040           0 :           if (buf)
    2041             :             {
    2042           0 :               *buf = c;
    2043           0 :               buf++;
    2044             :             }
    2045             :         }
    2046           0 :       return n;
    2047             :     }
    2048             : 
    2049       26215 :   n = 0;
    2050             :   do
    2051             :     {
    2052      555137 :       if (n < buflen && a->d.start < a->d.len)
    2053             :         /* Drain the buffer.  */
    2054             :         {
    2055      553574 :           unsigned size = a->d.len - a->d.start;
    2056      553574 :           if (size > buflen - n)
    2057       23794 :             size = buflen - n;
    2058      553574 :           if (buf)
    2059       29279 :             memcpy (buf, a->d.buf + a->d.start, size);
    2060      553574 :           n += size;
    2061      553574 :           a->d.start += size;
    2062      553574 :           if (buf)
    2063       29279 :             buf += size;
    2064             :         }
    2065      555137 :       if (n < buflen)
    2066             :         /* Draining the internal buffer didn't fill BUFFER.  Call
    2067             :            underflow to read more data into the filter's internal
    2068             :            buffer.  */
    2069             :         {
    2070      530340 :           if ((c = underflow (a, 1)) == -1)
    2071             :             /* EOF.  If we managed to read something, don't return EOF
    2072             :                now.  */
    2073             :             {
    2074        1417 :               a->nbytes += n;
    2075        1417 :               return n ? n : -1 /*EOF*/;
    2076             :             }
    2077      528923 :           if (buf)
    2078        4635 :             *buf++ = c;
    2079      528923 :           n++;
    2080             :         }
    2081             :     }
    2082      553720 :   while (n < buflen);
    2083       24798 :   a->nbytes += n;
    2084       24798 :   return n;
    2085             : }
    2086             : 
    2087             : 
    2088             : 
    2089             : int
    2090         482 : iobuf_peek (iobuf_t a, byte * buf, unsigned buflen)
    2091             : {
    2092         482 :   int n = 0;
    2093             : 
    2094         482 :   assert (buflen > 0);
    2095         482 :   assert (a->use == IOBUF_INPUT || a->use == IOBUF_INPUT_TEMP);
    2096             : 
    2097         482 :   if (buflen > a->d.size)
    2098             :     /* We can't peek more than we can buffer.  */
    2099           0 :     buflen = a->d.size;
    2100             : 
    2101             :   /* Try to fill the internal buffer with enough data to satisfy the
    2102             :      request.  */
    2103        1447 :   while (buflen > a->d.len - a->d.start)
    2104             :     {
    2105         484 :       if (underflow_target (a, 0, buflen) == -1)
    2106             :         /* EOF.  We can't read any more.  */
    2107           1 :         break;
    2108             : 
    2109             :       /* Underflow consumes the first character (it's the return
    2110             :          value).  unget() it by resetting the "file position".  */
    2111         483 :       assert (a->d.start == 1);
    2112         483 :       a->d.start = 0;
    2113             :     }
    2114             : 
    2115         482 :   n = a->d.len - a->d.start;
    2116         482 :   if (n > buflen)
    2117         481 :     n = buflen;
    2118             : 
    2119         482 :   if (n == 0)
    2120             :     /* EOF.  */
    2121           0 :     return -1;
    2122             : 
    2123         482 :   memcpy (buf, &a->d.buf[a->d.start], n);
    2124             : 
    2125         482 :   return n;
    2126             : }
    2127             : 
    2128             : 
    2129             : 
    2130             : 
    2131             : int
    2132      970450 : iobuf_writebyte (iobuf_t a, unsigned int c)
    2133             : {
    2134             :   int rc;
    2135             : 
    2136      970450 :   if (a->use == IOBUF_INPUT || a->use == IOBUF_INPUT_TEMP)
    2137             :     {
    2138           0 :       log_bug ("iobuf_writebyte called on an input pipeline!\n");
    2139             :       return -1;
    2140             :     }
    2141             : 
    2142      970450 :   if (a->d.len == a->d.size)
    2143         106 :     if ((rc=filter_flush (a)))
    2144           0 :       return rc;
    2145             : 
    2146      970450 :   assert (a->d.len < a->d.size);
    2147      970450 :   a->d.buf[a->d.len++] = c;
    2148      970450 :   return 0;
    2149             : }
    2150             : 
    2151             : 
    2152             : int
    2153       28262 : iobuf_write (iobuf_t a, const void *buffer, unsigned int buflen)
    2154             : {
    2155       28262 :   const unsigned char *buf = (const unsigned char *)buffer;
    2156             :   int rc;
    2157             : 
    2158       28262 :   if (a->use == IOBUF_INPUT || a->use == IOBUF_INPUT_TEMP)
    2159             :     {
    2160           0 :       log_bug ("iobuf_write called on an input pipeline!\n");
    2161             :       return -1;
    2162             :     }
    2163             : 
    2164             :   do
    2165             :     {
    2166       31541 :       if (buflen && a->d.len < a->d.size)
    2167             :         {
    2168       30692 :           unsigned size = a->d.size - a->d.len;
    2169       30692 :           if (size > buflen)
    2170       27411 :             size = buflen;
    2171       30692 :           memcpy (a->d.buf + a->d.len, buf, size);
    2172       30692 :           buflen -= size;
    2173       30692 :           buf += size;
    2174       30692 :           a->d.len += size;
    2175             :         }
    2176       31541 :       if (buflen)
    2177             :         {
    2178        3279 :           rc = filter_flush (a);
    2179        3279 :           if (rc)
    2180           0 :             return rc;
    2181             :         }
    2182             :     }
    2183       31541 :   while (buflen);
    2184       28262 :   return 0;
    2185             : }
    2186             : 
    2187             : 
    2188             : int
    2189       11161 : iobuf_writestr (iobuf_t a, const char *buf)
    2190             : {
    2191       11161 :   if (a->use == IOBUF_INPUT || a->use == IOBUF_INPUT_TEMP)
    2192             :     {
    2193           0 :       log_bug ("iobuf_writestr called on an input pipeline!\n");
    2194             :       return -1;
    2195             :     }
    2196             : 
    2197       11161 :   return iobuf_write (a, buf, strlen (buf));
    2198             : }
    2199             : 
    2200             : 
    2201             : 
    2202             : int
    2203        1285 : iobuf_write_temp (iobuf_t dest, iobuf_t source)
    2204             : {
    2205        1285 :   assert (source->use == IOBUF_OUTPUT || source->use == IOBUF_OUTPUT_TEMP);
    2206        1285 :   assert (dest->use == IOBUF_OUTPUT || dest->use == IOBUF_OUTPUT_TEMP);
    2207             : 
    2208        1285 :   iobuf_flush_temp (source);
    2209        1285 :   return iobuf_write (dest, source->d.buf, source->d.len);
    2210             : }
    2211             : 
    2212             : size_t
    2213          50 : iobuf_temp_to_buffer (iobuf_t a, byte * buffer, size_t buflen)
    2214             : {
    2215             :   byte desc[MAX_IOBUF_DESC];
    2216             :   size_t n;
    2217             : 
    2218             :   while (1)
    2219             :     {
    2220          50 :       int rc = filter_flush (a);
    2221          50 :       if (rc)
    2222           0 :         log_bug ("Flushing iobuf %d.%d (%s) from iobuf_temp_to_buffer failed.  Ignoring.\n",
    2223             :                  a->no, a->subno, iobuf_desc (a, desc));
    2224          50 :       if (! a->chain)
    2225          49 :         break;
    2226           1 :       a = a->chain;
    2227           1 :     }
    2228             : 
    2229          49 :   n = a->d.len;
    2230          49 :   if (n > buflen)
    2231           0 :     n = buflen;
    2232          49 :   memcpy (buffer, a->d.buf, n);
    2233          49 :   return n;
    2234             : }
    2235             : 
    2236             : /* Copies the data from the input iobuf SOURCE to the output iobuf
    2237             :    DEST until either an error is encountered or EOF is reached.
    2238             :    Returns the number of bytes copies.  */
    2239             : size_t
    2240         372 : iobuf_copy (iobuf_t dest, iobuf_t source)
    2241             : {
    2242             :   char *temp;
    2243             :   /* Use a 32 KB buffer.  */
    2244         372 :   const size_t temp_size = 32 * 1024;
    2245             : 
    2246             :   size_t nread;
    2247         372 :   size_t nwrote = 0;
    2248             :   int err;
    2249             : 
    2250         372 :   assert (source->use == IOBUF_INPUT || source->use == IOBUF_INPUT_TEMP);
    2251         372 :   assert (dest->use == IOBUF_OUTPUT || source->use == IOBUF_OUTPUT_TEMP);
    2252             : 
    2253         372 :   if (iobuf_error (dest))
    2254           0 :     return -1;
    2255             : 
    2256         372 :   temp = xmalloc (temp_size);
    2257             :   while (1)
    2258             :     {
    2259         868 :       nread = iobuf_read (source, temp, temp_size);
    2260         868 :       if (nread == -1)
    2261             :         /* EOF.  */
    2262         372 :         break;
    2263             : 
    2264         496 :       err = iobuf_write (dest, temp, nread);
    2265         496 :       if (err)
    2266           0 :         break;
    2267         496 :       nwrote += nread;
    2268         496 :     }
    2269             : 
    2270             :   /* Burn the buffer.  */
    2271         372 :   wipememory (temp, sizeof (temp));
    2272         372 :   xfree (temp);
    2273             : 
    2274         372 :   return nwrote;
    2275             : }
    2276             : 
    2277             : 
    2278             : void
    2279        1285 : iobuf_flush_temp (iobuf_t temp)
    2280             : {
    2281        1285 :   if (temp->use == IOBUF_INPUT || temp->use == IOBUF_INPUT_TEMP)
    2282           0 :     log_bug ("iobuf_flush_temp called on an input pipeline!\n");
    2283        2570 :   while (temp->chain)
    2284           0 :     iobuf_pop_filter (temp, temp->filter, NULL);
    2285        1285 : }
    2286             : 
    2287             : 
    2288             : void
    2289           0 : iobuf_set_limit (iobuf_t a, off_t nlimit)
    2290             : {
    2291           0 :   if (nlimit)
    2292           0 :     a->nofast = 1;
    2293             :   else
    2294           0 :     a->nofast = 0;
    2295           0 :   a->nlimit = nlimit;
    2296           0 :   a->ntotal += a->nbytes;
    2297           0 :   a->nbytes = 0;
    2298           0 : }
    2299             : 
    2300             : 
    2301             : 
    2302             : off_t
    2303         536 : iobuf_get_filelength (iobuf_t a, int *overflow)
    2304             : {
    2305         536 :   if (overflow)
    2306         536 :     *overflow = 0;
    2307             : 
    2308             :   /* Hmmm: file_filter may have already been removed */
    2309         536 :   for ( ; a->chain; a = a->chain )
    2310             :     ;
    2311             : 
    2312         536 :   if (a->filter != file_filter)
    2313           0 :     return 0;
    2314             : 
    2315             :   {
    2316         536 :     file_filter_ctx_t *b = a->filter_ov;
    2317         536 :     gnupg_fd_t fp = b->fp;
    2318             : 
    2319             : #if defined(HAVE_W32_SYSTEM)
    2320             :     ulong size;
    2321             :     static int (* __stdcall get_file_size_ex) (void *handle,
    2322             :                                                LARGE_INTEGER *r_size);
    2323             :     static int get_file_size_ex_initialized;
    2324             : 
    2325             :     if (!get_file_size_ex_initialized)
    2326             :       {
    2327             :         void *handle;
    2328             : 
    2329             :         handle = dlopen ("kernel32.dll", RTLD_LAZY);
    2330             :         if (handle)
    2331             :           {
    2332             :             get_file_size_ex = dlsym (handle, "GetFileSizeEx");
    2333             :             if (!get_file_size_ex)
    2334             :               dlclose (handle);
    2335             :           }
    2336             :         get_file_size_ex_initialized = 1;
    2337             :       }
    2338             : 
    2339             :     if (get_file_size_ex)
    2340             :       {
    2341             :         /* This is a newer system with GetFileSizeEx; we use this
    2342             :            then because it seem that GetFileSize won't return a
    2343             :            proper error in case a file is larger than 4GB. */
    2344             :         LARGE_INTEGER exsize;
    2345             : 
    2346             :         if (get_file_size_ex (fp, &exsize))
    2347             :           {
    2348             :             if (!exsize.u.HighPart)
    2349             :               return exsize.u.LowPart;
    2350             :             if (overflow)
    2351             :               *overflow = 1;
    2352             :             return 0;
    2353             :           }
    2354             :       }
    2355             :     else
    2356             :       {
    2357             :         if ((size=GetFileSize (fp, NULL)) != 0xffffffff)
    2358             :           return size;
    2359             :       }
    2360             :     log_error ("GetFileSize for handle %p failed: %s\n",
    2361             :                fp, w32_strerror (0));
    2362             : #else /*!HAVE_W32_SYSTEM*/
    2363             :     {
    2364             :       struct stat st;
    2365             : 
    2366         536 :       if ( !fstat (FD2INT (fp), &st) )
    2367         536 :         return st.st_size;
    2368           0 :       log_error("fstat() failed: %s\n", strerror(errno) );
    2369             :     }
    2370             : #endif /*!HAVE_W32_SYSTEM*/
    2371             :   }
    2372             : 
    2373           0 :   return 0;
    2374             : }
    2375             : 
    2376             : 
    2377             : int
    2378        1058 : iobuf_get_fd (iobuf_t a)
    2379             : {
    2380        1058 :   for (; a->chain; a = a->chain)
    2381             :     ;
    2382             : 
    2383        1058 :   if (a->filter != file_filter)
    2384           0 :     return -1;
    2385             : 
    2386             :   {
    2387        1058 :     file_filter_ctx_t *b = a->filter_ov;
    2388        1058 :     gnupg_fd_t fp = b->fp;
    2389             : 
    2390        1058 :     return FD2INT (fp);
    2391             :   }
    2392             : }
    2393             : 
    2394             : 
    2395             : off_t
    2396         916 : iobuf_tell (iobuf_t a)
    2397             : {
    2398         916 :   return a->ntotal + a->nbytes;
    2399             : }
    2400             : 
    2401             : 
    2402             : #if !defined(HAVE_FSEEKO) && !defined(fseeko)
    2403             : 
    2404             : #ifdef HAVE_LIMITS_H
    2405             : # include <limits.h>
    2406             : #endif
    2407             : #ifndef LONG_MAX
    2408             : # define LONG_MAX ((long) ((unsigned long) -1 >> 1))
    2409             : #endif
    2410             : #ifndef LONG_MIN
    2411             : # define LONG_MIN (-1 - LONG_MAX)
    2412             : #endif
    2413             : 
    2414             : /****************
    2415             :  * A substitute for fseeko, for hosts that don't have it.
    2416             :  */
    2417             : static int
    2418             : fseeko (FILE * stream, off_t newpos, int whence)
    2419             : {
    2420             :   while (newpos != (long) newpos)
    2421             :     {
    2422             :       long pos = newpos < 0 ? LONG_MIN : LONG_MAX;
    2423             :       if (fseek (stream, pos, whence) != 0)
    2424             :         return -1;
    2425             :       newpos -= pos;
    2426             :       whence = SEEK_CUR;
    2427             :     }
    2428             :   return fseek (stream, (long) newpos, whence);
    2429             : }
    2430             : #endif
    2431             : 
    2432             : int
    2433          51 : iobuf_seek (iobuf_t a, off_t newpos)
    2434             : {
    2435          51 :   file_filter_ctx_t *b = NULL;
    2436             : 
    2437          51 :   if (a->use == IOBUF_OUTPUT || a->use == IOBUF_INPUT)
    2438             :     {
    2439             :       /* Find the last filter in the pipeline.  */
    2440          51 :       for (; a->chain; a = a->chain)
    2441             :         ;
    2442             : 
    2443          51 :       if (a->filter != file_filter)
    2444           0 :         return -1;
    2445             : 
    2446          51 :       b = a->filter_ov;
    2447             : 
    2448             : #ifdef HAVE_W32_SYSTEM
    2449             :       if (SetFilePointer (b->fp, newpos, NULL, FILE_BEGIN) == 0xffffffff)
    2450             :         {
    2451             :           log_error ("SetFilePointer failed on handle %p: ec=%d\n",
    2452             :                      b->fp, (int) GetLastError ());
    2453             :           return -1;
    2454             :         }
    2455             : #else
    2456          51 :       if (lseek (b->fp, newpos, SEEK_SET) == (off_t) - 1)
    2457             :         {
    2458           0 :           log_error ("can't lseek: %s\n", strerror (errno));
    2459           0 :           return -1;
    2460             :         }
    2461             : #endif
    2462             :       /* Discard the buffer it is not a temp stream.  */
    2463          51 :       a->d.len = 0;
    2464             :     }
    2465          51 :   a->d.start = 0;
    2466          51 :   a->nbytes = 0;
    2467          51 :   a->nlimit = 0;
    2468          51 :   a->nofast = 0;
    2469          51 :   a->ntotal = newpos;
    2470          51 :   a->error = 0;
    2471             : 
    2472             :   /* It is impossible for A->CHAIN to be non-NULL.  If A is an INPUT
    2473             :      or OUTPUT buffer, then we find the last filter, which is defined
    2474             :      as A->CHAIN being NULL.  If A is a TEMP filter, then A must be
    2475             :      the only filter in the pipe: when iobuf_push_filter adds a filter
    2476             :      to the front of a pipeline, it sets the new filter to be an
    2477             :      OUTPUT filter if the pipeline is an OUTPUT or TEMP pipeline and
    2478             :      to be an INPUT filter if the pipeline is an INPUT pipeline.
    2479             :      Thus, only the last filter in a TEMP pipeline can be a */
    2480             : 
    2481             :   /* remove filters, but the last */
    2482          51 :   if (a->chain)
    2483           0 :     log_debug ("iobuf_pop_filter called in iobuf_seek - please report\n");
    2484         102 :   while (a->chain)
    2485           0 :     iobuf_pop_filter (a, a->filter, NULL);
    2486             : 
    2487          51 :   return 0;
    2488             : }
    2489             : 
    2490             : 
    2491             : const char *
    2492         353 : iobuf_get_real_fname (iobuf_t a)
    2493             : {
    2494         353 :   if (a->real_fname)
    2495         353 :     return a->real_fname;
    2496             : 
    2497             :   /* the old solution */
    2498           0 :   for (; a; a = a->chain)
    2499           0 :     if (!a->chain && a->filter == file_filter)
    2500             :       {
    2501           0 :         file_filter_ctx_t *b = a->filter_ov;
    2502           0 :         return b->print_only_name ? NULL : b->fname;
    2503             :       }
    2504             : 
    2505           0 :   return NULL;
    2506             : }
    2507             : 
    2508             : const char *
    2509           3 : iobuf_get_fname (iobuf_t a)
    2510             : {
    2511           3 :   for (; a; a = a->chain)
    2512           3 :     if (!a->chain && a->filter == file_filter)
    2513             :       {
    2514           3 :         file_filter_ctx_t *b = a->filter_ov;
    2515           3 :         return b->fname;
    2516             :       }
    2517           0 :   return NULL;
    2518             : }
    2519             : 
    2520             : const char *
    2521           3 : iobuf_get_fname_nonnull (iobuf_t a)
    2522             : {
    2523             :   const char *fname;
    2524             : 
    2525           3 :   fname = iobuf_get_fname (a);
    2526           3 :   return fname? fname : "[?]";
    2527             : }
    2528             : 
    2529             : 
    2530             : /****************
    2531             :  * Enable or disable partial body length mode (RFC 4880 4.2.2.4).
    2532             :  *
    2533             :  * If LEN is 0, this disables partial block mode by popping the
    2534             :  * partial body length filter, which which must be the most recently
    2535             :  * added filter.
    2536             :  *
    2537             :  * If LEN is non-zero, it pushes a partial body length filter.  If
    2538             :  * this is a read filter, LEN must be the length byte from the first
    2539             :  * chunk and A should be position just after this first partial body
    2540             :  * length header.
    2541             :  */
    2542             : void
    2543         699 : iobuf_set_partial_body_length_mode (iobuf_t a, size_t len)
    2544             : {
    2545         699 :   if (!len)
    2546             :     /* Disable partial body length mode.  */
    2547             :     {
    2548          41 :       if (a->use == IOBUF_INPUT)
    2549           0 :         log_debug ("iobuf_pop_filter called in set_partial_block_mode"
    2550             :                    " - please report\n");
    2551             : 
    2552          41 :       log_assert (a->filter == block_filter);
    2553          41 :       iobuf_pop_filter (a, block_filter, NULL);
    2554             :     }
    2555             :   else
    2556             :     /* Enabled partial body length mode.  */
    2557             :     {
    2558         658 :       block_filter_ctx_t *ctx = xcalloc (1, sizeof *ctx);
    2559         658 :       ctx->use = a->use;
    2560         658 :       ctx->partial = 1;
    2561         658 :       ctx->size = 0;
    2562         658 :       ctx->first_c = len;
    2563         658 :       iobuf_push_filter (a, block_filter, ctx);
    2564             :     }
    2565         699 : }
    2566             : 
    2567             : 
    2568             : 
    2569             : unsigned int
    2570       35138 : iobuf_read_line (iobuf_t a, byte ** addr_of_buffer,
    2571             :                  unsigned *length_of_buffer, unsigned *max_length)
    2572             : {
    2573             :   int c;
    2574       35138 :   char *buffer = (char *)*addr_of_buffer;
    2575       35138 :   unsigned length = *length_of_buffer;
    2576       35138 :   unsigned nbytes = 0;
    2577       35138 :   unsigned maxlen = *max_length;
    2578             :   char *p;
    2579             : 
    2580             :   /* The code assumes that we have space for at least a newline and a
    2581             :      NUL character in the buffer.  This requires at least 2 bytes.  We
    2582             :      don't complicate the code by handling the stupid corner case, but
    2583             :      simply assert that it can't happen.  */
    2584       35138 :   assert (length >= 2 || maxlen >= 2);
    2585             : 
    2586       35138 :   if (!buffer || length <= 1)
    2587             :     /* must allocate a new buffer */
    2588             :     {
    2589         263 :       length = 256 <= maxlen ? 256 : maxlen;
    2590         263 :       buffer = xrealloc (buffer, length);
    2591         263 :       *addr_of_buffer = (unsigned char *)buffer;
    2592         263 :       *length_of_buffer = length;
    2593             :     }
    2594             : 
    2595       35138 :   p = buffer;
    2596     1950263 :   while ((c = iobuf_get (a)) != -1)
    2597             :     {
    2598     1914624 :       *p++ = c;
    2599     1914624 :       nbytes++;
    2600     1914624 :       if (c == '\n')
    2601       34635 :         break;
    2602             : 
    2603     1879989 :       if (nbytes == length - 1)
    2604             :         /* We don't have enough space to add a \n and a \0.  Increase
    2605             :            the buffer size.  */
    2606             :         {
    2607          16 :           if (length == maxlen)
    2608             :             /* We reached the buffer's size limit!  */
    2609             :             {
    2610             :               /* Skip the rest of the line.  */
    2611           2 :               while (c != '\n' && (c = iobuf_get (a)) != -1)
    2612             :                 ;
    2613             : 
    2614             :               /* p is pointing at the last byte in the buffer.  We
    2615             :                  always terminate the line with "\n\0" so overwrite
    2616             :                  the previous byte with a \n.  */
    2617           2 :               assert (p > buffer);
    2618           2 :               p[-1] = '\n';
    2619             : 
    2620             :               /* Indicate truncation.  */
    2621           2 :               *max_length = 0;
    2622           2 :               break;
    2623             :             }
    2624             : 
    2625          14 :           length += length < 1024 ? 256 : 1024;
    2626          14 :           if (length > maxlen)
    2627           1 :             length = maxlen;
    2628             : 
    2629          14 :           buffer = xrealloc (buffer, length);
    2630          14 :           *addr_of_buffer = (unsigned char *)buffer;
    2631          14 :           *length_of_buffer = length;
    2632          14 :           p = buffer + nbytes;
    2633             :         }
    2634             :     }
    2635             :   /* Add the terminating NUL.  */
    2636       35138 :   *p = 0;
    2637             : 
    2638             :   /* Return the number of characters written to the buffer including
    2639             :      the newline, but not including the terminating NUL.  */
    2640       35138 :   return nbytes;
    2641             : }
    2642             : 
    2643             : static int
    2644           0 : translate_file_handle (int fd, int for_write)
    2645             : {
    2646             : #if defined(HAVE_W32CE_SYSTEM)
    2647             :   /* This is called only with one of the special filenames.  Under
    2648             :      W32CE the FD here is not a file descriptor but a rendezvous id,
    2649             :      thus we need to finish the pipe first.  */
    2650             :   fd = _assuan_w32ce_finish_pipe (fd, for_write);
    2651             : #elif defined(HAVE_W32_SYSTEM)
    2652             :   {
    2653             :     int x;
    2654             : 
    2655             :     (void)for_write;
    2656             : 
    2657             :     if (fd == 0)
    2658             :       x = (int) GetStdHandle (STD_INPUT_HANDLE);
    2659             :     else if (fd == 1)
    2660             :       x = (int) GetStdHandle (STD_OUTPUT_HANDLE);
    2661             :     else if (fd == 2)
    2662             :       x = (int) GetStdHandle (STD_ERROR_HANDLE);
    2663             :     else
    2664             :       x = fd;
    2665             : 
    2666             :     if (x == -1)
    2667             :       log_debug ("GetStdHandle(%d) failed: ec=%d\n",
    2668             :                  fd, (int) GetLastError ());
    2669             : 
    2670             :     fd = x;
    2671             :   }
    2672             : #else
    2673             :   (void)for_write;
    2674             : #endif
    2675           0 :   return fd;
    2676             : }
    2677             : 
    2678             : 
    2679             : void
    2680       18167 : iobuf_skip_rest (iobuf_t a, unsigned long n, int partial)
    2681             : {
    2682       18167 :   if ( partial )
    2683             :     {
    2684             :       for (;;)
    2685             :         {
    2686           0 :           if (a->nofast || a->d.start >= a->d.len)
    2687             :             {
    2688           0 :               if (iobuf_readbyte (a) == -1)
    2689             :                 {
    2690           0 :                   break;
    2691             :                 }
    2692             :             }
    2693             :           else
    2694             :             {
    2695           0 :               unsigned long count = a->d.len - a->d.start;
    2696           0 :               a->nbytes += count;
    2697           0 :               a->d.start = a->d.len;
    2698             :             }
    2699           0 :         }
    2700             :     }
    2701             :   else
    2702             :     {
    2703       18167 :       unsigned long remaining = n;
    2704       36932 :       while (remaining > 0)
    2705             :         {
    2706         599 :           if (a->nofast || a->d.start >= a->d.len)
    2707             :             {
    2708           2 :               if (iobuf_readbyte (a) == -1)
    2709             :                 {
    2710           1 :                   break;
    2711             :                 }
    2712           1 :               --remaining;
    2713             :             }
    2714             :           else
    2715             :             {
    2716         597 :               unsigned long count = a->d.len - a->d.start;
    2717         597 :               if (count > remaining)
    2718             :                 {
    2719         579 :                   count = remaining;
    2720             :                 }
    2721         597 :               a->nbytes += count;
    2722         597 :               a->d.start += count;
    2723         597 :               remaining -= count;
    2724             :             }
    2725             :         }
    2726             :     }
    2727       18167 : }

Generated by: LCOV version 1.11