diff --git a/common/iobuf.c b/common/iobuf.c
index 07edbbefd..6370efbfe 100644
--- a/common/iobuf.c
+++ b/common/iobuf.c
@@ -1,2698 +1,2698 @@
 /* iobuf.c  -  File Handling for OpenPGP.
  * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2006, 2007, 2008,
  *               2009, 2010, 2011  Free Software Foundation, Inc.
  * Copyright (C) 2015  g10 Code GmbH
  *
  * This file is part of GnuPG.
  *
  * This file is free software; you can redistribute it and/or modify
  * it under the terms of either
  *
  *   - the GNU Lesser General Public License as published by the Free
  *     Software Foundation; either version 3 of the License, or (at
  *     your option) any later version.
  *
  * or
  *
  *   - the GNU General Public License as published by the Free
  *     Software Foundation; either version 2 of the License, or (at
  *     your option) any later version.
  *
  * or both in parallel, as here.
  *
  * This file is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
 #include <ctype.h>
 #include <assert.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
 #ifdef HAVE_W32_SYSTEM
 # ifdef HAVE_WINSOCK2_H
 #  include <winsock2.h>
 # endif
 # include <windows.h>
 #endif
 #ifdef __riscos__
 # include <kernel.h>
 # include <swis.h>
 #endif /* __riscos__ */
 
 #include <assuan.h>
 
 #include "util.h"
 #include "sysutils.h"
 #include "iobuf.h"
 
 /*-- Begin configurable part.  --*/
 
 /* The size of the internal buffers.
    NOTE: If you change this value you MUST also adjust the regression
    test "armored_key_8192" in armor.test! */
 #define IOBUF_BUFFER_SIZE  8192
 
 /* To avoid a potential DoS with compression packets we better limit
    the number of filters in a chain.  */
 #define MAX_NESTING_FILTER 64
 
 /*-- End configurable part.  --*/
 
 
 #ifdef HAVE_W32_SYSTEM
 # ifdef HAVE_W32CE_SYSTEM
 #  define FD_FOR_STDIN  (es_fileno (es_stdin))
 #  define FD_FOR_STDOUT (es_fileno (es_stdout))
 # else
 #  define FD_FOR_STDIN  (GetStdHandle (STD_INPUT_HANDLE))
 #  define FD_FOR_STDOUT (GetStdHandle (STD_OUTPUT_HANDLE))
 # endif
 #else /*!HAVE_W32_SYSTEM*/
 # define FD_FOR_STDIN  (0)
 # define FD_FOR_STDOUT (1)
 #endif /*!HAVE_W32_SYSTEM*/
 
 
 /* The context used by the file filter.  */
 typedef struct
 {
   gnupg_fd_t fp;       /* Open file pointer or handle.  */
   int keep_open;
   int no_cache;
   int eof_seen;
   int print_only_name; /* Flags indicating that fname is not a real file.  */
   char fname[1];       /* Name of the file.  */
 } file_filter_ctx_t;
 
 /* The context used by the estream filter.  */
 typedef struct
 {
   estream_t fp;        /* Open estream handle.  */
   int keep_open;
   int no_cache;
   int eof_seen;
   int print_only_name; /* Flags indicating that fname is not a real file.  */
   char fname[1];       /* Name of the file.  */
 } file_es_filter_ctx_t;
 
 
 /* Object to control the "close cache".  */
 struct close_cache_s
 {
   struct close_cache_s *next;
   gnupg_fd_t fp;
   char fname[1];
 };
 typedef struct close_cache_s *close_cache_t;
 static close_cache_t close_cache;
 
 int iobuf_debug_mode;
 
 
 #ifdef HAVE_W32_SYSTEM
 typedef struct
 {
   int sock;
   int keep_open;
   int no_cache;
   int eof_seen;
   int print_only_name;	/* Flag indicating that fname is not a real file.  */
   char fname[1];	/* Name of the file */
 
 } sock_filter_ctx_t;
 #endif /*HAVE_W32_SYSTEM*/
 
 /* The first partial length header block must be of size 512 to make
  * it easier (and more efficient) we use a min. block size of 512 for
  * all chunks (but the last one) */
 #define OP_MIN_PARTIAL_CHUNK	  512
 #define OP_MIN_PARTIAL_CHUNK_2POW 9
 
 /* The context we use for the block filter (used to handle OpenPGP
    length information header).  */
 typedef struct
 {
   int use;
   size_t size;
   size_t count;
   int partial;	   /* 1 = partial header, 2 in last partial packet.  */
   char *buffer;	   /* Used for partial header.  */
   size_t buflen;   /* Used size of buffer.  */
   int first_c;	   /* First character of a partial header (which is > 0).  */
   int eof;
 }
 block_filter_ctx_t;
 
 
 /* Local prototypes.  */
 static int underflow (iobuf_t a, int clear_pending_eof);
 static int underflow_target (iobuf_t a, int clear_pending_eof, size_t target);
 static int translate_file_handle (int fd, int for_write);
 
 /* Sends any pending data to the filter's FILTER function.  Note: this
    works on the filter and not on the whole pipeline.  That is,
    iobuf_flush doesn't necessarily cause data to be written to any
    underlying file; it just causes any data buffered at the filter A
    to be sent to A's filter function.
 
    If A is a IOBUF_OUTPUT_TEMP filter, then this also enlarges the
    buffer by IOBUF_BUFFER_SIZE.
 
    May only be called on an IOBUF_OUTPUT or IOBUF_OUTPUT_TEMP filters.  */
 static int filter_flush (iobuf_t a);
 
 
 
 /* This is a replacement for strcmp.  Under W32 it does not
    distinguish between backslash and slash.  */
 static int
 fd_cache_strcmp (const char *a, const char *b)
 {
 #ifdef HAVE_DOSISH_SYSTEM
   for (; *a && *b; a++, b++)
     {
       if (*a != *b && !((*a == '/' && *b == '\\')
                         || (*a == '\\' && *b == '/')) )
         break;
     }
   return *(const unsigned char *)a - *(const unsigned char *)b;
 #else
   return strcmp (a, b);
 #endif
 }
 
 
 /*
  * Invalidate (i.e. close) a cached iobuf
  */
 static int
 fd_cache_invalidate (const char *fname)
 {
   close_cache_t cc;
   int rc = 0;
 
   assert (fname);
   if (DBG_IOBUF)
     log_debug ("fd_cache_invalidate (%s)\n", fname);
 
   for (cc = close_cache; cc; cc = cc->next)
     {
       if (cc->fp != GNUPG_INVALID_FD && !fd_cache_strcmp (cc->fname, fname))
 	{
 	  if (DBG_IOBUF)
 	    log_debug ("                did (%s)\n", cc->fname);
 #ifdef HAVE_W32_SYSTEM
 	  if (!CloseHandle (cc->fp))
             rc = -1;
 #else
 	  rc = close (cc->fp);
 #endif
 	  cc->fp = GNUPG_INVALID_FD;
 	}
     }
   return rc;
 }
 
 
 /* Try to sync changes to the disk.  This is to avoid data loss during
    a system crash in write/close/rename cycle on some file
    systems.  */
 static int
 fd_cache_synchronize (const char *fname)
 {
   int err = 0;
 
 #ifdef HAVE_FSYNC
   close_cache_t cc;
 
   if (DBG_IOBUF)
     log_debug ("fd_cache_synchronize (%s)\n", fname);
 
   for (cc=close_cache; cc; cc = cc->next )
     {
       if (cc->fp != GNUPG_INVALID_FD && !fd_cache_strcmp (cc->fname, fname))
 	{
 	  if (DBG_IOBUF)
 	    log_debug ("                 did (%s)\n", cc->fname);
 
 	  err = fsync (cc->fp);
 	}
     }
 #else
   (void)fname;
 #endif /*HAVE_FSYNC*/
 
   return err;
 }
 
 
 static gnupg_fd_t
 direct_open (const char *fname, const char *mode, int mode700)
 {
 #ifdef HAVE_W32_SYSTEM
   unsigned long da, cd, sm;
   HANDLE hfile;
 
   (void)mode700;
   /* Note, that we do not handle all mode combinations */
 
   /* According to the ReactOS source it seems that open() of the
    * standard MSW32 crt does open the file in shared mode which is
    * something new for MS applications ;-)
    */
   if (strchr (mode, '+'))
     {
       if (fd_cache_invalidate (fname))
         return GNUPG_INVALID_FD;
       da = GENERIC_READ | GENERIC_WRITE;
       cd = OPEN_EXISTING;
       sm = FILE_SHARE_READ | FILE_SHARE_WRITE;
     }
   else if (strchr (mode, 'w'))
     {
       if (fd_cache_invalidate (fname))
         return GNUPG_INVALID_FD;
       da = GENERIC_WRITE;
       cd = CREATE_ALWAYS;
       sm = FILE_SHARE_WRITE;
     }
   else
     {
       da = GENERIC_READ;
       cd = OPEN_EXISTING;
       sm = FILE_SHARE_READ;
     }
 
   /* We always use the Unicode version because it supports file names
    * longer than MAX_PATH.  (requires gpgrt 1.45) */
   if (1)
     {
       wchar_t *wfname = gpgrt_fname_to_wchar (fname);
       if (wfname)
         {
           hfile = CreateFileW (wfname, da, sm, NULL, cd,
                                FILE_ATTRIBUTE_NORMAL, NULL);
           xfree (wfname);
         }
       else
         hfile = INVALID_HANDLE_VALUE;
     }
 
   return hfile;
 
 #else /*!HAVE_W32_SYSTEM*/
 
   int oflag;
   int cflag = S_IRUSR | S_IWUSR;
 
   if (!mode700)
     cflag |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
 
   /* Note, that we do not handle all mode combinations */
   if (strchr (mode, '+'))
     {
       if (fd_cache_invalidate (fname))
         return GNUPG_INVALID_FD;
       oflag = O_RDWR;
     }
   else if (strchr (mode, 'w'))
     {
       if (fd_cache_invalidate (fname))
         return GNUPG_INVALID_FD;
       oflag = O_WRONLY | O_CREAT | O_TRUNC;
     }
   else
     {
       oflag = O_RDONLY;
     }
 #ifdef O_BINARY
   if (strchr (mode, 'b'))
     oflag |= O_BINARY;
 #endif
 
 #ifdef __riscos__
   {
     struct stat buf;
 
     /* Don't allow iobufs on directories */
     if (!stat (fname, &buf) && S_ISDIR (buf.st_mode) && !S_ISREG (buf.st_mode))
       return __set_errno (EISDIR);
   }
 #endif
   return open (fname, oflag, cflag);
 
 #endif /*!HAVE_W32_SYSTEM*/
 }
 
 
 /*
  * Instead of closing an FD we keep it open and cache it for later reuse
  * Note that this caching strategy only works if the process does not chdir.
  */
 static void
 fd_cache_close (const char *fname, gnupg_fd_t fp)
 {
   close_cache_t cc;
 
   assert (fp);
   if (!fname || !*fname)
     {
 #ifdef HAVE_W32_SYSTEM
       CloseHandle (fp);
 #else
       close (fp);
 #endif
       if (DBG_IOBUF)
 	log_debug ("fd_cache_close (%d) real\n", (int)fp);
       return;
     }
   /* try to reuse a slot */
   for (cc = close_cache; cc; cc = cc->next)
     {
       if (cc->fp == GNUPG_INVALID_FD && !fd_cache_strcmp (cc->fname, fname))
 	{
 	  cc->fp = fp;
 	  if (DBG_IOBUF)
 	    log_debug ("fd_cache_close (%s) used existing slot\n", fname);
 	  return;
 	}
     }
   /* add a new one */
   if (DBG_IOBUF)
     log_debug ("fd_cache_close (%s) new slot created\n", fname);
   cc = xcalloc (1, sizeof *cc + strlen (fname));
   strcpy (cc->fname, fname);
   cc->fp = fp;
   cc->next = close_cache;
   close_cache = cc;
 }
 
 /*
  * Do a direct_open on FNAME but first try to reuse one from the fd_cache
  */
 static gnupg_fd_t
 fd_cache_open (const char *fname, const char *mode)
 {
   close_cache_t cc;
 
   assert (fname);
   for (cc = close_cache; cc; cc = cc->next)
     {
       if (cc->fp != GNUPG_INVALID_FD && !fd_cache_strcmp (cc->fname, fname))
 	{
 	  gnupg_fd_t fp = cc->fp;
 	  cc->fp = GNUPG_INVALID_FD;
 	  if (DBG_IOBUF)
 	    log_debug ("fd_cache_open (%s) using cached fp\n", fname);
 #ifdef HAVE_W32_SYSTEM
 	  if (SetFilePointer (fp, 0, NULL, FILE_BEGIN) == 0xffffffff)
 	    {
 	      log_error ("rewind file failed on handle %p: ec=%d\n",
 			 fp, (int) GetLastError ());
 	      fp = GNUPG_INVALID_FD;
 	    }
 #else
 	  if (lseek (fp, 0, SEEK_SET) == (off_t) - 1)
 	    {
 	      log_error ("can't rewind fd %d: %s\n", fp, strerror (errno));
 	      fp = GNUPG_INVALID_FD;
 	    }
 #endif
 	  return fp;
 	}
     }
   if (DBG_IOBUF)
     log_debug ("fd_cache_open (%s) not cached\n", fname);
   return direct_open (fname, mode, 0);
 }
 
 
 static int
 file_filter (void *opaque, int control, iobuf_t chain, byte * buf,
 	     size_t * ret_len)
 {
   file_filter_ctx_t *a = opaque;
   gnupg_fd_t f = a->fp;
   size_t size = *ret_len;
   size_t nbytes = 0;
   int rc = 0;
 
   (void)chain; /* Not used.  */
 
   if (control == IOBUFCTRL_UNDERFLOW)
     {
       assert (size); /* We need a buffer.  */
       if (a->eof_seen)
 	{
 	  rc = -1;
 	  *ret_len = 0;
 	}
       else
 	{
 #ifdef HAVE_W32_SYSTEM
 	  unsigned long nread;
 
 	  nbytes = 0;
 	  if (!ReadFile (f, buf, size, &nread, NULL))
 	    {
 	      int ec = (int) GetLastError ();
 	      if (ec != ERROR_BROKEN_PIPE)
 		{
 		  rc = gpg_error_from_errno (ec);
 		  log_error ("%s: read error: ec=%d\n", a->fname, ec);
 		}
 	    }
 	  else if (!nread)
 	    {
 	      a->eof_seen = 1;
 	      rc = -1;
 	    }
 	  else
 	    {
 	      nbytes = nread;
 	    }
 
 #else
 
 	  int n;
 
 	  nbytes = 0;
 	  do
 	    {
 	      n = read (f, buf, size);
 	    }
 	  while (n == -1 && errno == EINTR);
 	  if (n == -1)
 	    {			/* error */
 	      if (errno != EPIPE)
 		{
 		  rc = gpg_error_from_syserror ();
 		  log_error ("%s: read error: %s\n",
 			     a->fname, strerror (errno));
 		}
 	    }
 	  else if (!n)
 	    {			/* eof */
 	      a->eof_seen = 1;
 	      rc = -1;
 	    }
 	  else
 	    {
 	      nbytes = n;
 	    }
 #endif
 	  *ret_len = nbytes;
 	}
     }
   else if (control == IOBUFCTRL_FLUSH)
     {
       if (size)
 	{
 #ifdef HAVE_W32_SYSTEM
 	  byte *p = buf;
 	  unsigned long n;
 
 	  nbytes = size;
 	  do
 	    {
 	      if (size && !WriteFile (f, p, nbytes, &n, NULL))
 		{
 		  int ec = (int) GetLastError ();
 		  rc = gpg_error_from_errno (ec);
 		  log_error ("%s: write error: ec=%d\n", a->fname, ec);
 		  break;
 		}
 	      p += n;
 	      nbytes -= n;
 	    }
 	  while (nbytes);
 	  nbytes = p - buf;
 #else
 	  byte *p = buf;
 	  int n;
 
 	  nbytes = size;
 	  do
 	    {
 	      do
 		{
 		  n = write (f, p, nbytes);
 		}
 	      while (n == -1 && errno == EINTR);
 	      if (n > 0)
 		{
 		  p += n;
 		  nbytes -= n;
 		}
 	    }
 	  while (n != -1 && nbytes);
 	  if (n == -1)
 	    {
 	      rc = gpg_error_from_syserror ();
 	      log_error ("%s: write error: %s\n", a->fname, strerror (errno));
 	    }
 	  nbytes = p - buf;
 #endif
 	}
       *ret_len = nbytes;
     }
   else if (control == IOBUFCTRL_INIT)
     {
       a->eof_seen = 0;
       a->keep_open = 0;
       a->no_cache = 0;
     }
   else if (control == IOBUFCTRL_DESC)
     {
       mem2str (buf, "file_filter(fd)", *ret_len);
     }
   else if (control == IOBUFCTRL_FREE)
     {
       if (f != FD_FOR_STDIN && f != FD_FOR_STDOUT)
 	{
 	  if (DBG_IOBUF)
 	    log_debug ("%s: close fd/handle %d\n", a->fname, FD2INT (f));
 	  if (!a->keep_open)
 	    fd_cache_close (a->no_cache ? NULL : a->fname, f);
 	}
       xfree (a); /* We can free our context now. */
     }
 
   return rc;
 }
 
 
 /* Similar to file_filter but using the estream system.  */
 static int
 file_es_filter (void *opaque, int control, iobuf_t chain, byte * buf,
                 size_t * ret_len)
 {
   file_es_filter_ctx_t *a = opaque;
   estream_t f = a->fp;
   size_t size = *ret_len;
   size_t nbytes = 0;
   int rc = 0;
 
   (void)chain; /* Not used.  */
 
   if (control == IOBUFCTRL_UNDERFLOW)
     {
       assert (size); /* We need a buffer.  */
       if (a->eof_seen)
 	{
 	  rc = -1;
 	  *ret_len = 0;
 	}
       else
 	{
           nbytes = 0;
           rc = es_read (f, buf, size, &nbytes);
 	  if (rc == -1)
 	    {			/* error */
               rc = gpg_error_from_syserror ();
               log_error ("%s: read error: %s\n", a->fname, strerror (errno));
 	    }
 	  else if (!nbytes)
 	    {			/* eof */
 	      a->eof_seen = 1;
 	      rc = -1;
 	    }
 	  *ret_len = nbytes;
 	}
     }
   else if (control == IOBUFCTRL_FLUSH)
     {
       if (size)
 	{
 	  byte *p = buf;
 	  size_t nwritten;
 
 	  nbytes = size;
 	  do
 	    {
               nwritten = 0;
               if (es_write (f, p, nbytes, &nwritten))
                 {
                   rc = gpg_error_from_syserror ();
                   log_error ("%s: write error: %s\n",
                              a->fname, strerror (errno));
                   break;
                 }
               p += nwritten;
               nbytes -= nwritten;
 	    }
 	  while (nbytes);
 	  nbytes = p - buf;
 	}
       *ret_len = nbytes;
     }
   else if (control == IOBUFCTRL_INIT)
     {
       a->eof_seen = 0;
       a->no_cache = 0;
     }
   else if (control == IOBUFCTRL_DESC)
     {
       mem2str (buf, "estream_filter", *ret_len);
     }
   else if (control == IOBUFCTRL_FREE)
     {
       if (f != es_stdin && f != es_stdout)
 	{
 	  if (DBG_IOBUF)
 	    log_debug ("%s: es_fclose %p\n", a->fname, f);
 	  if (!a->keep_open)
 	    es_fclose (f);
 	}
       f = NULL;
       xfree (a); /* We can free our context now. */
     }
 
   return rc;
 }
 
 
 #ifdef HAVE_W32_SYSTEM
 /* Because network sockets are special objects under Lose32 we have to
    use a dedicated filter for them. */
 static int
 sock_filter (void *opaque, int control, iobuf_t chain, byte * buf,
 	     size_t * ret_len)
 {
   sock_filter_ctx_t *a = opaque;
   size_t size = *ret_len;
   size_t nbytes = 0;
   int rc = 0;
 
   (void)chain;
 
   if (control == IOBUFCTRL_UNDERFLOW)
     {
       assert (size);		/* need a buffer */
       if (a->eof_seen)
 	{
 	  rc = -1;
 	  *ret_len = 0;
 	}
       else
 	{
 	  int nread;
 
 	  nread = recv (a->sock, buf, size, 0);
 	  if (nread == SOCKET_ERROR)
 	    {
 	      int ec = (int) WSAGetLastError ();
 	      rc = gpg_error_from_errno (ec);
 	      log_error ("socket read error: ec=%d\n", ec);
 	    }
 	  else if (!nread)
 	    {
 	      a->eof_seen = 1;
 	      rc = -1;
 	    }
 	  else
 	    {
 	      nbytes = nread;
 	    }
 	  *ret_len = nbytes;
 	}
     }
   else if (control == IOBUFCTRL_FLUSH)
     {
       if (size)
 	{
 	  byte *p = buf;
 	  int n;
 
 	  nbytes = size;
 	  do
 	    {
 	      n = send (a->sock, p, nbytes, 0);
 	      if (n == SOCKET_ERROR)
 		{
 		  int ec = (int) WSAGetLastError ();
 		  rc = gpg_error_from_errno (ec);
 		  log_error ("socket write error: ec=%d\n", ec);
 		  break;
 		}
 	      p += n;
 	      nbytes -= n;
 	    }
 	  while (nbytes);
 	  nbytes = p - buf;
 	}
       *ret_len = nbytes;
     }
   else if (control == IOBUFCTRL_INIT)
     {
       a->eof_seen = 0;
       a->keep_open = 0;
       a->no_cache = 0;
     }
   else if (control == IOBUFCTRL_DESC)
     {
       mem2str (buf, "sock_filter", *ret_len);
     }
   else if (control == IOBUFCTRL_FREE)
     {
       if (!a->keep_open)
 	closesocket (a->sock);
       xfree (a);		/* we can free our context now */
     }
   return rc;
 }
 #endif /*HAVE_W32_SYSTEM*/
 
 /****************
  * This is used to implement the block write mode.
  * Block reading is done on a byte by byte basis in readbyte(),
  * without a filter
  */
 static int
 block_filter (void *opaque, int control, iobuf_t chain, byte * buffer,
 	      size_t * ret_len)
 {
   block_filter_ctx_t *a = opaque;
   char *buf = (char *)buffer;
   size_t size = *ret_len;
   int c, needed, rc = 0;
   char *p;
 
   if (control == IOBUFCTRL_UNDERFLOW)
     {
       size_t n = 0;
 
       p = buf;
       assert (size);		/* need a buffer */
       if (a->eof)		/* don't read any further */
 	rc = -1;
       while (!rc && size)
 	{
 	  if (!a->size)
 	    {			/* get the length bytes */
 	      if (a->partial == 2)
 		{
 		  a->eof = 1;
 		  if (!n)
 		    rc = -1;
 		  break;
 		}
 	      else if (a->partial)
 		{
 		  /* These OpenPGP introduced huffman like encoded length
 		   * bytes are really a mess :-( */
 		  if (a->first_c)
 		    {
 		      c = a->first_c;
 		      a->first_c = 0;
 		    }
 		  else if ((c = iobuf_get (chain)) == -1)
 		    {
 		      log_error ("block_filter: 1st length byte missing\n");
 		      rc = GPG_ERR_BAD_DATA;
 		      break;
 		    }
 		  if (c < 192)
 		    {
 		      a->size = c;
 		      a->partial = 2;
 		      if (!a->size)
 			{
 			  a->eof = 1;
 			  if (!n)
 			    rc = -1;
 			  break;
 			}
 		    }
 		  else if (c < 224)
 		    {
 		      a->size = (c - 192) * 256;
 		      if ((c = iobuf_get (chain)) == -1)
 			{
 			  log_error
 			    ("block_filter: 2nd length byte missing\n");
 			  rc = GPG_ERR_BAD_DATA;
 			  break;
 			}
 		      a->size += c + 192;
 		      a->partial = 2;
 		      if (!a->size)
 			{
 			  a->eof = 1;
 			  if (!n)
 			    rc = -1;
 			  break;
 			}
 		    }
 		  else if (c == 255)
 		    {
 		      a->size = iobuf_get_noeof (chain) << 24;
 		      a->size |= iobuf_get_noeof (chain) << 16;
 		      a->size |= iobuf_get_noeof (chain) << 8;
 		      if ((c = iobuf_get (chain)) == -1)
 			{
 			  log_error ("block_filter: invalid 4 byte length\n");
 			  rc = GPG_ERR_BAD_DATA;
 			  break;
 			}
 		      a->size |= c;
                       a->partial = 2;
                       if (!a->size)
                         {
                           a->eof = 1;
                           if (!n)
                             rc = -1;
                           break;
 			}
 		    }
 		  else
 		    { /* Next partial body length. */
 		      a->size = 1 << (c & 0x1f);
 		    }
 		  /*  log_debug("partial: ctx=%p c=%02x size=%u\n", a, c, a->size); */
 		}
 	      else
 		BUG ();
 	    }
 
 	  while (!rc && size && a->size)
 	    {
 	      needed = size < a->size ? size : a->size;
 	      c = iobuf_read (chain, p, needed);
 	      if (c < needed)
 		{
 		  if (c == -1)
 		    c = 0;
 		  log_error
 		    ("block_filter %p: read error (size=%lu,a->size=%lu)\n",
 		     a, (ulong) size + c, (ulong) a->size + c);
 		  rc = GPG_ERR_BAD_DATA;
 		}
 	      else
 		{
 		  size -= c;
 		  a->size -= c;
 		  p += c;
 		  n += c;
 		}
 	    }
 	}
       *ret_len = n;
     }
   else if (control == IOBUFCTRL_FLUSH)
     {
       if (a->partial)
 	{			/* the complicated openpgp scheme */
 	  size_t blen, n, nbytes = size + a->buflen;
 
 	  assert (a->buflen <= OP_MIN_PARTIAL_CHUNK);
 	  if (nbytes < OP_MIN_PARTIAL_CHUNK)
 	    {
 	      /* not enough to write a partial block out; so we store it */
 	      if (!a->buffer)
 		a->buffer = xmalloc (OP_MIN_PARTIAL_CHUNK);
 	      memcpy (a->buffer + a->buflen, buf, size);
 	      a->buflen += size;
 	    }
 	  else
 	    {			/* okay, we can write out something */
 	      /* do this in a loop to use the most efficient block lengths */
 	      p = buf;
 	      do
 		{
 		  /* find the best matching block length - this is limited
 		   * by the size of the internal buffering */
 		  for (blen = OP_MIN_PARTIAL_CHUNK * 2,
 		       c = OP_MIN_PARTIAL_CHUNK_2POW + 1; blen <= nbytes;
 		       blen *= 2, c++)
 		    ;
 		  blen /= 2;
 		  c--;
 		  /* write the partial length header */
 		  assert (c <= 0x1f);	/*;-) */
 		  c |= 0xe0;
 		  iobuf_put (chain, c);
 		  if ((n = a->buflen))
 		    {		/* write stuff from the buffer */
 		      assert (n == OP_MIN_PARTIAL_CHUNK);
 		      if (iobuf_write (chain, a->buffer, n))
 			rc = gpg_error_from_syserror ();
 		      a->buflen = 0;
 		      nbytes -= n;
 		    }
 		  if ((n = nbytes) > blen)
 		    n = blen;
 		  if (n && iobuf_write (chain, p, n))
 		    rc = gpg_error_from_syserror ();
 		  p += n;
 		  nbytes -= n;
 		}
 	      while (!rc && nbytes >= OP_MIN_PARTIAL_CHUNK);
 	      /* store the rest in the buffer */
 	      if (!rc && nbytes)
 		{
 		  assert (!a->buflen);
 		  assert (nbytes < OP_MIN_PARTIAL_CHUNK);
 		  if (!a->buffer)
 		    a->buffer = xmalloc (OP_MIN_PARTIAL_CHUNK);
 		  memcpy (a->buffer, p, nbytes);
 		  a->buflen = nbytes;
 		}
 	    }
 	}
       else
 	BUG ();
     }
   else if (control == IOBUFCTRL_INIT)
     {
       if (DBG_IOBUF)
 	log_debug ("init block_filter %p\n", a);
       if (a->partial)
 	a->count = 0;
       else if (a->use == IOBUF_INPUT)
 	a->count = a->size = 0;
       else
 	a->count = a->size;	/* force first length bytes */
       a->eof = 0;
       a->buffer = NULL;
       a->buflen = 0;
     }
   else if (control == IOBUFCTRL_DESC)
     {
       mem2str (buf, "block_filter", *ret_len);
     }
   else if (control == IOBUFCTRL_FREE)
     {
       if (a->use == IOBUF_OUTPUT)
 	{			/* write the end markers */
 	  if (a->partial)
 	    {
 	      u32 len;
 	      /* write out the remaining bytes without a partial header
 	       * the length of this header may be 0 - but if it is
 	       * the first block we are not allowed to use a partial header
 	       * and frankly we can't do so, because this length must be
 	       * a power of 2. This is _really_ complicated because we
 	       * have to check the possible length of a packet prior
 	       * to it's creation: a chain of filters becomes complicated
 	       * and we need a lot of code to handle compressed packets etc.
 	       *   :-(((((((
 	       */
 	      /* construct header */
 	      len = a->buflen;
 	      /*log_debug("partial: remaining length=%u\n", len ); */
 	      if (len < 192)
 		rc = iobuf_put (chain, len);
 	      else if (len < 8384)
 		{
 		  if (!(rc = iobuf_put (chain, ((len - 192) / 256) + 192)))
 		    rc = iobuf_put (chain, ((len - 192) % 256));
 		}
 	      else
 		{		/* use a 4 byte header */
 		  if (!(rc = iobuf_put (chain, 0xff)))
 		    if (!(rc = iobuf_put (chain, (len >> 24) & 0xff)))
 		      if (!(rc = iobuf_put (chain, (len >> 16) & 0xff)))
 			if (!(rc = iobuf_put (chain, (len >> 8) & 0xff)))
 			  rc = iobuf_put (chain, len & 0xff);
 		}
 	      if (!rc && len)
 		rc = iobuf_write (chain, a->buffer, len);
 	      if (rc)
 		{
 		  log_error ("block_filter: write error: %s\n",
 			     strerror (errno));
 		  rc = gpg_error_from_syserror ();
 		}
 	      xfree (a->buffer);
 	      a->buffer = NULL;
 	      a->buflen = 0;
 	    }
 	  else
 	    BUG ();
 	}
       else if (a->size)
 	{
 	  log_error ("block_filter: pending bytes!\n");
 	}
       if (DBG_IOBUF)
 	log_debug ("free block_filter %p\n", a);
       xfree (a);		/* we can free our context now */
     }
 
   return rc;
 }
 
 #define MAX_IOBUF_DESC 32
 /*
  * Fill the buffer by the description of iobuf A.
  * The buffer size should be MAX_IOBUF_DESC (or larger).
  * Returns BUF as (const char *).
  */
 static const char *
 iobuf_desc (iobuf_t a, byte *buf)
 {
   size_t len = MAX_IOBUF_DESC;
 
   if (! a || ! a->filter)
     memcpy (buf, "?", 2);
   else
     a->filter (a->filter_ov, IOBUFCTRL_DESC, NULL, buf, &len);
 
   return buf;
 }
 
 static void
 print_chain (iobuf_t a)
 {
   if (!DBG_IOBUF)
     return;
   for (; a; a = a->chain)
     {
       byte desc[MAX_IOBUF_DESC];
 
       log_debug ("iobuf chain: %d.%d '%s' filter_eof=%d start=%d len=%d\n",
 		 a->no, a->subno, iobuf_desc (a, desc), a->filter_eof,
 		 (int) a->d.start, (int) a->d.len);
     }
 }
 
 int
 iobuf_print_chain (iobuf_t a)
 {
   print_chain (a);
   return 0;
 }
 
 iobuf_t
 iobuf_alloc (int use, size_t bufsize)
 {
   iobuf_t a;
   static int number = 0;
 
   assert (use == IOBUF_INPUT || use == IOBUF_INPUT_TEMP
 	  || use == IOBUF_OUTPUT || use == IOBUF_OUTPUT_TEMP);
   if (bufsize == 0)
     {
       log_bug ("iobuf_alloc() passed a bufsize of 0!\n");
       bufsize = IOBUF_BUFFER_SIZE;
     }
 
   a = xcalloc (1, sizeof *a);
   a->use = use;
   a->d.buf = xmalloc (bufsize);
   a->d.size = bufsize;
   a->no = ++number;
   a->subno = 0;
   a->real_fname = NULL;
   return a;
 }
 
 int
 iobuf_close (iobuf_t a)
 {
   iobuf_t a_chain;
   size_t dummy_len = 0;
   int rc = 0;
 
   for (; a; a = a_chain)
     {
       byte desc[MAX_IOBUF_DESC];
       int rc2 = 0;
 
       a_chain = a->chain;
 
       if (a->use == IOBUF_OUTPUT && (rc = filter_flush (a)))
 	log_error ("filter_flush failed on close: %s\n", gpg_strerror (rc));
 
       if (DBG_IOBUF)
 	log_debug ("iobuf-%d.%d: close '%s'\n",
 		   a->no, a->subno, iobuf_desc (a, desc));
 
       if (a->filter && (rc2 = a->filter (a->filter_ov, IOBUFCTRL_FREE,
 					 a->chain, NULL, &dummy_len)))
 	log_error ("IOBUFCTRL_FREE failed on close: %s\n", gpg_strerror (rc));
       if (! rc && rc2)
 	/* Whoops!  An error occurred.  Save it in RC if we haven't
 	   already recorded an error.  */
 	rc = rc2;
 
       xfree (a->real_fname);
       if (a->d.buf)
 	{
 	  memset (a->d.buf, 0, a->d.size);	/* erase the buffer */
 	  xfree (a->d.buf);
 	}
       xfree (a);
     }
   return rc;
 }
 
 int
 iobuf_cancel (iobuf_t a)
 {
   const char *s;
   iobuf_t a2;
   int rc;
 #if defined(HAVE_W32_SYSTEM) || defined(__riscos__)
   char *remove_name = NULL;
 #endif
 
   if (a && a->use == IOBUF_OUTPUT)
     {
       s = iobuf_get_real_fname (a);
       if (s && *s)
 	{
 #if defined(HAVE_W32_SYSTEM) || defined(__riscos__)
 	  remove_name = xstrdup (s);
 #else
 	  remove (s);
 #endif
 	}
     }
 
   /* send a cancel message to all filters */
   for (a2 = a; a2; a2 = a2->chain)
     {
       size_t dummy;
       if (a2->filter)
 	a2->filter (a2->filter_ov, IOBUFCTRL_CANCEL, a2->chain, NULL, &dummy);
     }
 
   rc = iobuf_close (a);
 #if defined(HAVE_W32_SYSTEM) || defined(__riscos__)
   if (remove_name)
     {
       /* Argg, MSDOS does not allow removing open files.  So
        * we have to do it here */
       gnupg_remove (remove_name);
       xfree (remove_name);
     }
 #endif
   return rc;
 }
 
 
 iobuf_t
 iobuf_temp (void)
 {
   return iobuf_alloc (IOBUF_OUTPUT_TEMP, IOBUF_BUFFER_SIZE);
 }
 
 iobuf_t
 iobuf_temp_with_content (const char *buffer, size_t length)
 {
   iobuf_t a;
   int i;
 
   a = iobuf_alloc (IOBUF_INPUT_TEMP, length);
   assert (length == a->d.size);
   /* memcpy (a->d.buf, buffer, length); */
   for (i=0; i < length; i++)
     a->d.buf[i] = buffer[i];
   a->d.len = length;
 
   return a;
 }
 
 
 int
 iobuf_is_pipe_filename (const char *fname)
 {
   if (!fname || (*fname=='-' && !fname[1]) )
     return 1;
   return check_special_filename (fname, 0, 1) != -1;
 }
 
 
 static iobuf_t
 do_open (const char *fname, int special_filenames,
 	 int use, const char *opentype, int mode700)
 {
   iobuf_t a;
   gnupg_fd_t fp;
   file_filter_ctx_t *fcx;
   size_t len = 0;
   int print_only = 0;
   int fd;
   byte desc[MAX_IOBUF_DESC];
 
   assert (use == IOBUF_INPUT || use == IOBUF_OUTPUT);
 
   if (special_filenames
       /* NULL or '-'.  */
       && (!fname || (*fname == '-' && !fname[1])))
     {
       if (use == IOBUF_INPUT)
 	{
 	  fp = FD_FOR_STDIN;
 	  fname = "[stdin]";
 	}
       else
 	{
 	  fp = FD_FOR_STDOUT;
 	  fname = "[stdout]";
 	}
       print_only = 1;
     }
   else if (!fname)
     return NULL;
   else if (special_filenames
            && (fd = check_special_filename (fname, 0, 1)) != -1)
     return iobuf_fdopen (translate_file_handle (fd, use == IOBUF_INPUT ? 0 : 1),
 			 opentype);
   else
     {
       if (use == IOBUF_INPUT)
 	fp = fd_cache_open (fname, opentype);
       else
 	fp = direct_open (fname, opentype, mode700);
       if (fp == GNUPG_INVALID_FD)
 	return NULL;
     }
 
   a = iobuf_alloc (use, IOBUF_BUFFER_SIZE);
   fcx = xmalloc (sizeof *fcx + strlen (fname));
   fcx->fp = fp;
   fcx->print_only_name = print_only;
   strcpy (fcx->fname, fname);
   if (!print_only)
     a->real_fname = xstrdup (fname);
   a->filter = file_filter;
   a->filter_ov = fcx;
   file_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len);
   if (DBG_IOBUF)
     log_debug ("iobuf-%d.%d: open '%s' desc=%s fd=%d\n",
 	       a->no, a->subno, fname, iobuf_desc (a, desc), FD2INT (fcx->fp));
 
   return a;
 }
 
 iobuf_t
 iobuf_open (const char *fname)
 {
   return do_open (fname, 1, IOBUF_INPUT, "rb", 0);
 }
 
 iobuf_t
 iobuf_create (const char *fname, int mode700)
 {
   return do_open (fname, 1, IOBUF_OUTPUT, "wb", mode700);
 }
 
 iobuf_t
 iobuf_openrw (const char *fname)
 {
   return do_open (fname, 0, IOBUF_OUTPUT, "r+b", 0);
 }
 
 
 static iobuf_t
 do_iobuf_fdopen (int fd, const char *mode, int keep_open)
 {
   iobuf_t a;
   gnupg_fd_t fp;
   file_filter_ctx_t *fcx;
   size_t len;
 
   fp = INT2FD (fd);
 
   a = iobuf_alloc (strchr (mode, 'w') ? IOBUF_OUTPUT : IOBUF_INPUT,
 		   IOBUF_BUFFER_SIZE);
   fcx = xmalloc (sizeof *fcx + 20);
   fcx->fp = fp;
   fcx->print_only_name = 1;
   fcx->keep_open = keep_open;
   sprintf (fcx->fname, "[fd %d]", fd);
   a->filter = file_filter;
   a->filter_ov = fcx;
   file_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len);
   if (DBG_IOBUF)
     log_debug ("iobuf-%d.%d: fdopen%s '%s'\n",
                a->no, a->subno, keep_open? "_nc":"", fcx->fname);
   iobuf_ioctl (a, IOBUF_IOCTL_NO_CACHE, 1, NULL);
   return a;
 }
 
 
 iobuf_t
 iobuf_fdopen (int fd, const char *mode)
 {
   return do_iobuf_fdopen (fd, mode, 0);
 }
 
 iobuf_t
 iobuf_fdopen_nc (int fd, const char *mode)
 {
   return do_iobuf_fdopen (fd, mode, 1);
 }
 
 
 iobuf_t
 iobuf_esopen (estream_t estream, const char *mode, int keep_open)
 {
   iobuf_t a;
   file_es_filter_ctx_t *fcx;
   size_t len = 0;
 
   a = iobuf_alloc (strchr (mode, 'w') ? IOBUF_OUTPUT : IOBUF_INPUT,
 		   IOBUF_BUFFER_SIZE);
   fcx = xtrymalloc (sizeof *fcx + 30);
   fcx->fp = estream;
   fcx->print_only_name = 1;
   fcx->keep_open = keep_open;
   sprintf (fcx->fname, "[fd %p]", estream);
   a->filter = file_es_filter;
   a->filter_ov = fcx;
   file_es_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len);
   if (DBG_IOBUF)
     log_debug ("iobuf-%d.%d: esopen%s '%s'\n",
                a->no, a->subno, keep_open? "_nc":"", fcx->fname);
   return a;
 }
 
 
 iobuf_t
 iobuf_sockopen (int fd, const char *mode)
 {
   iobuf_t a;
 #ifdef HAVE_W32_SYSTEM
   sock_filter_ctx_t *scx;
   size_t len;
 
   a = iobuf_alloc (strchr (mode, 'w') ? IOBUF_OUTPUT : IOBUF_INPUT,
 		   IOBUF_BUFFER_SIZE);
   scx = xmalloc (sizeof *scx + 25);
   scx->sock = fd;
   scx->print_only_name = 1;
   sprintf (scx->fname, "[sock %d]", fd);
   a->filter = sock_filter;
   a->filter_ov = scx;
   sock_filter (scx, IOBUFCTRL_INIT, NULL, NULL, &len);
   if (DBG_IOBUF)
     log_debug ("iobuf-%d.%d: sockopen '%s'\n", a->no, a->subno, scx->fname);
   iobuf_ioctl (a, IOBUF_IOCTL_NO_CACHE, 1, NULL);
 #else
   a = iobuf_fdopen (fd, mode);
 #endif
   return a;
 }
 
 int
 iobuf_ioctl (iobuf_t a, iobuf_ioctl_t cmd, int intval, void *ptrval)
 {
   byte desc[MAX_IOBUF_DESC];
 
   if (cmd == IOBUF_IOCTL_KEEP_OPEN)
     {
       /* Keep system filepointer/descriptor open.  This was used in
          the past by http.c; this ioctl is not directly used
          anymore.  */
       if (DBG_IOBUF)
 	log_debug ("iobuf-%d.%d: ioctl '%s' keep_open=%d\n",
 		   a ? a->no : -1, a ? a->subno : -1, iobuf_desc (a, desc),
 		   intval);
       for (; a; a = a->chain)
 	if (!a->chain && a->filter == file_filter)
 	  {
 	    file_filter_ctx_t *b = a->filter_ov;
 	    b->keep_open = intval;
 	    return 0;
 	  }
 #ifdef HAVE_W32_SYSTEM
 	else if (!a->chain && a->filter == sock_filter)
 	  {
 	    sock_filter_ctx_t *b = a->filter_ov;
 	    b->keep_open = intval;
 	    return 0;
 	  }
 #endif
     }
   else if (cmd == IOBUF_IOCTL_INVALIDATE_CACHE)
     {
       if (DBG_IOBUF)
 	log_debug ("iobuf-*.*: ioctl '%s' invalidate\n",
 		   ptrval ? (char *) ptrval : "?");
       if (!a && !intval && ptrval)
 	{
 	  if (fd_cache_invalidate (ptrval))
             return -1;
 	  return 0;
 	}
     }
   else if (cmd == IOBUF_IOCTL_NO_CACHE)
     {
       if (DBG_IOBUF)
 	log_debug ("iobuf-%d.%d: ioctl '%s' no_cache=%d\n",
 		   a ? a->no : -1, a ? a->subno : -1, iobuf_desc (a, desc),
 		   intval);
       for (; a; a = a->chain)
 	if (!a->chain && a->filter == file_filter)
 	  {
 	    file_filter_ctx_t *b = a->filter_ov;
 	    b->no_cache = intval;
 	    return 0;
 	  }
 #ifdef HAVE_W32_SYSTEM
 	else if (!a->chain && a->filter == sock_filter)
 	  {
 	    sock_filter_ctx_t *b = a->filter_ov;
 	    b->no_cache = intval;
 	    return 0;
 	  }
 #endif
     }
   else if (cmd == IOBUF_IOCTL_FSYNC)
     {
       /* Do a fsync on the open fd and return any errors to the caller
          of iobuf_ioctl.  Note that we work on a file name here. */
       if (DBG_IOBUF)
         log_debug ("iobuf-*.*: ioctl '%s' fsync\n",
                    ptrval? (const char*)ptrval:"<null>");
 
       if (!a && !intval && ptrval)
         {
           return fd_cache_synchronize (ptrval);
         }
     }
 
 
   return -1;
 }
 
 
 /****************
  * Register an i/o filter.
  */
 int
 iobuf_push_filter (iobuf_t a,
 		   int (*f) (void *opaque, int control,
 			     iobuf_t chain, byte * buf, size_t * len),
                    void *ov)
 {
   return iobuf_push_filter2 (a, f, ov, 0);
 }
 
 int
 iobuf_push_filter2 (iobuf_t a,
 		    int (*f) (void *opaque, int control,
 			      iobuf_t chain, byte * buf, size_t * len),
 		    void *ov, int rel_ov)
 {
   iobuf_t b;
   size_t dummy_len = 0;
   int rc = 0;
 
   if (a->use == IOBUF_OUTPUT && (rc = filter_flush (a)))
     return rc;
 
   if (a->subno >= MAX_NESTING_FILTER)
     {
       log_error ("i/o filter too deeply nested - corrupted data?\n");
       return GPG_ERR_BAD_DATA;
     }
 
   /* We want to create a new filter and put it in front of A.  A
      simple implementation would do:
 
        b = iobuf_alloc (...);
        b->chain = a;
        return a;
 
      This is a bit problematic: A is the head of the pipeline and
      there are potentially many pointers to it.  Requiring the caller
      to update all of these pointers is a burden.
 
      An alternative implementation would add a level of indirection.
      For instance, we could use a pipeline object, which contains a
      pointer to the first filter in the pipeline.  This is not what we
      do either.
 
      Instead, we allocate a new buffer (B) and copy the first filter's
      state into that and use the initial buffer (A) for the new
      filter.  One limitation of this approach is that it is not
      practical to maintain a pointer to a specific filter's state.
 
      Before:
 
            A
            |
            v 0x100               0x200
            +----------+          +----------+
            | filter x |--------->| filter y |---->....
            +----------+          +----------+
 
      After:           B
                       |
                       v 0x300
                       +----------+
            A          | filter x |
            |          +----------+
            v 0x100    ^          v 0x200
            +----------+          +----------+
            | filter w |          | filter y |---->....
            +----------+          +----------+
 
      Note: filter x's address changed from 0x100 to 0x300, but A still
      points to the head of the pipeline.
   */
 
   b = xmalloc (sizeof *b);
   memcpy (b, a, sizeof *b);
   /* fixme: it is stupid to keep a copy of the name at every level
    * but we need the name somewhere because the name known by file_filter
    * may have been released when we need the name of the file */
   b->real_fname = a->real_fname ? xstrdup (a->real_fname) : NULL;
   /* remove the filter stuff from the new stream */
   a->filter = NULL;
   a->filter_ov = NULL;
   a->filter_ov_owner = 0;
   a->filter_eof = 0;
   if (a->use == IOBUF_OUTPUT_TEMP)
     /* A TEMP filter buffers any data sent to it; it does not forward
        any data down the pipeline.  If we add a new filter to the
        pipeline, it shouldn't also buffer data.  It should send it
        downstream to be buffered.  Thus, the correct type for a filter
        added in front of an IOBUF_OUTPUT_TEMP filter is IOBUF_OUPUT, not
        IOBUF_OUTPUT_TEMP.  */
     {
       a->use = IOBUF_OUTPUT;
 
       /* When pipeline is written to, the temp buffer's size is
 	 increased accordingly.  We don't need to allocate a 10 MB
 	 buffer for a non-terminal filter.  Just use the default
 	 size.  */
       a->d.size = IOBUF_BUFFER_SIZE;
     }
   else if (a->use == IOBUF_INPUT_TEMP)
     /* Same idea as above.  */
     {
       a->use = IOBUF_INPUT;
       a->d.size = IOBUF_BUFFER_SIZE;
     }
 
   /* The new filter (A) gets a new buffer.
 
      If the pipeline is an output or temp pipeline, then giving the
      buffer to the new filter means that data that was written before
      the filter was pushed gets sent to the filter.  That's clearly
      wrong.
 
      If the pipeline is an input pipeline, then giving the buffer to
      the new filter (A) means that data that has read from (B), but
      not yet read from the pipeline won't be processed by the new
      filter (A)!  That's certainly not what we want.  */
   a->d.buf = xmalloc (a->d.size);
   a->d.len = 0;
   a->d.start = 0;
 
   /* disable nlimit for the new stream */
   a->ntotal = b->ntotal + b->nbytes;
   a->nlimit = a->nbytes = 0;
   a->nofast = 0;
   /* make a link from the new stream to the original stream */
   a->chain = b;
 
   /* setup the function on the new stream */
   a->filter = f;
   a->filter_ov = ov;
   a->filter_ov_owner = rel_ov;
 
   a->subno = b->subno + 1;
 
   if (DBG_IOBUF)
     {
       byte desc[MAX_IOBUF_DESC];
       log_debug ("iobuf-%d.%d: push '%s'\n",
 		 a->no, a->subno, iobuf_desc (a, desc));
       print_chain (a);
     }
 
   /* now we can initialize the new function if we have one */
   if (a->filter && (rc = a->filter (a->filter_ov, IOBUFCTRL_INIT, a->chain,
 				    NULL, &dummy_len)))
     log_error ("IOBUFCTRL_INIT failed: %s\n", gpg_strerror (rc));
   return rc;
 }
 
 /****************
  * Remove an i/o filter.
  */
 int
 iobuf_pop_filter (iobuf_t a, int (*f) (void *opaque, int control,
                                        iobuf_t chain, byte * buf, size_t * len),
                   void *ov)
 {
   iobuf_t b;
   size_t dummy_len = 0;
   int rc = 0;
   byte desc[MAX_IOBUF_DESC];
 
   if (DBG_IOBUF)
     log_debug ("iobuf-%d.%d: pop '%s'\n",
 	       a->no, a->subno, iobuf_desc (a, desc));
   if (a->use == IOBUF_INPUT_TEMP || a->use == IOBUF_OUTPUT_TEMP)
     {
       /* This should be the last filter in the pipeline.  */
       assert (! a->chain);
       return 0;
     }
   if (!a->filter)
     {				/* this is simple */
       b = a->chain;
       assert (b);
       xfree (a->d.buf);
       xfree (a->real_fname);
       memcpy (a, b, sizeof *a);
       xfree (b);
       return 0;
     }
   for (b = a; b; b = b->chain)
     if (b->filter == f && (!ov || b->filter_ov == ov))
       break;
   if (!b)
     log_bug ("iobuf_pop_filter(): filter function not found\n");
 
   /* flush this stream if it is an output stream */
   if (a->use == IOBUF_OUTPUT && (rc = filter_flush (b)))
     {
       log_error ("filter_flush failed in iobuf_pop_filter: %s\n",
                  gpg_strerror (rc));
       return rc;
     }
   /* and tell the filter to free it self */
   if (b->filter && (rc = b->filter (b->filter_ov, IOBUFCTRL_FREE, b->chain,
 				    NULL, &dummy_len)))
     {
       log_error ("IOBUFCTRL_FREE failed: %s\n", gpg_strerror (rc));
       return rc;
     }
   if (b->filter_ov && b->filter_ov_owner)
     {
       xfree (b->filter_ov);
       b->filter_ov = NULL;
     }
 
 
   /* and see how to remove it */
   if (a == b && !b->chain)
     log_bug ("can't remove the last filter from the chain\n");
   else if (a == b)
     {				/* remove the first iobuf from the chain */
       /* everything from b is copied to a. This is save because
        * a flush has been done on the to be removed entry
        */
       b = a->chain;
       xfree (a->d.buf);
       xfree (a->real_fname);
       memcpy (a, b, sizeof *a);
       xfree (b);
       if (DBG_IOBUF)
 	log_debug ("iobuf-%d.%d: popped filter\n", a->no, a->subno);
     }
   else if (!b->chain)
     {				/* remove the last iobuf from the chain */
       log_bug ("Ohh jeee, trying to remove a head filter\n");
     }
   else
     {				/* remove an intermediate iobuf from the chain */
       log_bug ("Ohh jeee, trying to remove an intermediate filter\n");
     }
 
   return rc;
 }
 
 
 /****************
  * read underflow: read at least one byte into the buffer and return
  * the first byte or -1 on EOF.
  */
 static int
 underflow (iobuf_t a, int clear_pending_eof)
 {
   return underflow_target (a, clear_pending_eof, 1);
 }
 
 
 /****************
  * read underflow: read TARGET bytes into the buffer and return
  * the first byte or -1 on EOF.
  */
 static int
 underflow_target (iobuf_t a, int clear_pending_eof, size_t target)
 {
   size_t len;
   int rc;
 
   if (DBG_IOBUF)
     log_debug ("iobuf-%d.%d: underflow: buffer size: %d; still buffered: %d => space for %d bytes\n",
 	       a->no, a->subno,
 	       (int) a->d.size, (int) (a->d.len - a->d.start),
 	       (int) (a->d.size - (a->d.len - a->d.start)));
 
   if (a->use == IOBUF_INPUT_TEMP)
     /* By definition, there isn't more data to read into the
        buffer.  */
     return -1;
 
   assert (a->use == IOBUF_INPUT);
 
   /* If there is still some buffered data, then move it to the start
      of the buffer and try to fill the end of the buffer.  (This is
      useful if we are called from iobuf_peek().)  */
   assert (a->d.start <= a->d.len);
   a->d.len -= a->d.start;
   memmove (a->d.buf, &a->d.buf[a->d.start], a->d.len);
   a->d.start = 0;
 
   if (a->d.len < target && a->filter_eof)
     /* The last time we tried to read from this filter, we got an EOF.
        We couldn't return the EOF, because there was buffered data.
        Since there is no longer any buffered data, return the
        error.  */
     {
       if (DBG_IOBUF)
 	log_debug ("iobuf-%d.%d: underflow: eof (pending eof)\n",
 		   a->no, a->subno);
       if (! clear_pending_eof)
 	return -1;
 
       if (a->chain)
 	/* A filter follows this one.  Free this filter.  */
 	{
 	  iobuf_t b = a->chain;
 	  if (DBG_IOBUF)
 	    log_debug ("iobuf-%d.%d: filter popped (pending EOF returned)\n",
 		       a->no, a->subno);
 	  xfree (a->d.buf);
 	  xfree (a->real_fname);
 	  memcpy (a, b, sizeof *a);
 	  xfree (b);
 	  print_chain (a);
 	}
       else
 	a->filter_eof = 0;	/* for the top level filter */
       return -1;		/* return one(!) EOF */
     }
 
   if (a->d.len == 0 && a->error)
     /* The last time we tried to read from this filter, we got an
        error.  We couldn't return the error, because there was
        buffered data.  Since there is no longer any buffered data,
        return the error.  */
     {
       if (DBG_IOBUF)
 	log_debug ("iobuf-%d.%d: pending error (%s) returned\n",
 		   a->no, a->subno, gpg_strerror (a->error));
       return -1;
     }
 
   if (a->filter && ! a->filter_eof && ! a->error)
     /* We have a filter function and the last time we tried to read we
        didn't get an EOF or an error.  Try to fill the buffer.  */
     {
       /* Be careful to account for any buffered data.  */
       len = a->d.size - a->d.len;
       if (DBG_IOBUF)
 	log_debug ("iobuf-%d.%d: underflow: A->FILTER (%lu bytes)\n",
 		   a->no, a->subno, (ulong) len);
       if (len == 0)
 	/* There is no space for more data.  Don't bother calling
 	   A->FILTER.  */
 	rc = 0;
       else
 	rc = a->filter (a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain,
 			&a->d.buf[a->d.len], &len);
       a->d.len += len;
 
       if (DBG_IOBUF)
 	log_debug ("iobuf-%d.%d: A->FILTER() returned rc=%d (%s), read %lu bytes\n",
 		   a->no, a->subno,
 		   rc, rc == 0 ? "ok" : rc == -1 ? "EOF" : gpg_strerror (rc),
 		   (ulong) len);
 /*  	    if( a->no == 1 ) */
 /*                   log_hexdump ("     data:", a->d.buf, len); */
 
       if (rc == -1)
 	/* EOF.  */
 	{
 	  size_t dummy_len = 0;
 
 	  /* Tell the filter to free itself */
 	  if ((rc = a->filter (a->filter_ov, IOBUFCTRL_FREE, a->chain,
 			       NULL, &dummy_len)))
 	    log_error ("IOBUFCTRL_FREE failed: %s\n", gpg_strerror (rc));
 
 	  /* Free everything except for the internal buffer.  */
 	  if (a->filter_ov && a->filter_ov_owner)
 	    xfree (a->filter_ov);
 	  a->filter_ov = NULL;
 	  a->filter = NULL;
 	  a->filter_eof = 1;
 
 	  if (clear_pending_eof && a->d.len == 0 && a->chain)
 	    /* We don't need to keep this filter around at all:
 
 	         - we got an EOF
 		 - we have no buffered data
 		 - a filter follows this one.
 
 	      Unlink this filter.  */
 	    {
 	      iobuf_t b = a->chain;
 	      if (DBG_IOBUF)
 		log_debug ("iobuf-%d.%d: pop in underflow (nothing buffered, got EOF)\n",
 			   a->no, a->subno);
 	      xfree (a->d.buf);
 	      xfree (a->real_fname);
 	      memcpy (a, b, sizeof *a);
 	      xfree (b);
 
 	      print_chain (a);
 
 	      return -1;
 	    }
 	  else if (a->d.len == 0)
 	    /* We can't unlink this filter (it is the only one in the
 	       pipeline), but we can immediately return EOF.  */
 	    return -1;
 	}
       else if (rc)
 	/* Record the error.  */
 	{
 	  a->error = rc;
 
 	  if (a->d.len == 0)
 	    /* There is no buffered data.  Immediately return EOF.  */
 	    return -1;
 	}
     }
 
   assert (a->d.start <= a->d.len);
   if (a->d.start < a->d.len)
     return a->d.buf[a->d.start++];
 
   /* EOF.  */
   return -1;
 }
 
 
 static int
 filter_flush (iobuf_t a)
 {
   size_t len;
   int rc;
 
   if (a->use == IOBUF_OUTPUT_TEMP)
     {				/* increase the temp buffer */
       size_t newsize = a->d.size + IOBUF_BUFFER_SIZE;
 
       if (DBG_IOBUF)
 	log_debug ("increasing temp iobuf from %lu to %lu\n",
 		   (ulong) a->d.size, (ulong) newsize);
 
       a->d.buf = xrealloc (a->d.buf, newsize);
       a->d.size = newsize;
       return 0;
     }
   else if (a->use != IOBUF_OUTPUT)
     log_bug ("flush on non-output iobuf\n");
   else if (!a->filter)
     log_bug ("filter_flush: no filter\n");
   len = a->d.len;
   rc = a->filter (a->filter_ov, IOBUFCTRL_FLUSH, a->chain, a->d.buf, &len);
   if (!rc && len != a->d.len)
     {
       log_info ("filter_flush did not write all!\n");
       rc = GPG_ERR_INTERNAL;
     }
   else if (rc)
     a->error = rc;
   a->d.len = 0;
 
   return rc;
 }
 
 
 int
 iobuf_readbyte (iobuf_t a)
 {
   int c;
 
   if (a->use == IOBUF_OUTPUT || a->use == IOBUF_OUTPUT_TEMP)
     {
       log_bug ("iobuf_readbyte called on a non-INPUT pipeline!\n");
       return -1;
     }
 
   assert (a->d.start <= a->d.len);
 
   if (a->nlimit && a->nbytes >= a->nlimit)
     return -1;			/* forced EOF */
 
   if (a->d.start < a->d.len)
     {
       c = a->d.buf[a->d.start++];
     }
   else if ((c = underflow (a, 1)) == -1)
     return -1;			/* EOF */
 
   assert (a->d.start <= a->d.len);
 
   /* Note: if underflow doesn't return EOF, then it returns the first
      byte that was read and advances a->d.start appropriately.  */
 
   a->nbytes++;
   return c;
 }
 
 
 int
 iobuf_read (iobuf_t a, void *buffer, unsigned int buflen)
 {
   unsigned char *buf = (unsigned char *)buffer;
   int c, n;
 
   if (a->use == IOBUF_OUTPUT || a->use == IOBUF_OUTPUT_TEMP)
     {
       log_bug ("iobuf_read called on a non-INPUT pipeline!\n");
       return -1;
     }
 
   if (a->nlimit)
     {
       /* Handle special cases. */
       for (n = 0; n < buflen; n++)
 	{
 	  if ((c = iobuf_readbyte (a)) == -1)
 	    {
 	      if (!n)
 		return -1;	/* eof */
 	      break;
 	    }
 
 	  if (buf)
 	    {
 	      *buf = c;
 	      buf++;
 	    }
 	}
       return n;
     }
 
   n = 0;
   do
     {
       if (n < buflen && a->d.start < a->d.len)
 	/* Drain the buffer.  */
 	{
 	  unsigned size = a->d.len - a->d.start;
 	  if (size > buflen - n)
 	    size = buflen - n;
 	  if (buf)
 	    memcpy (buf, a->d.buf + a->d.start, size);
 	  n += size;
 	  a->d.start += size;
 	  if (buf)
 	    buf += size;
 	}
       if (n < buflen)
 	/* Draining the internal buffer didn't fill BUFFER.  Call
 	   underflow to read more data into the filter's internal
 	   buffer.  */
 	{
 	  if ((c = underflow (a, 1)) == -1)
 	    /* EOF.  If we managed to read something, don't return EOF
 	       now.  */
 	    {
 	      a->nbytes += n;
 	      return n ? n : -1 /*EOF*/;
 	    }
 	  if (buf)
 	    *buf++ = c;
 	  n++;
 	}
     }
   while (n < buflen);
   a->nbytes += n;
   return n;
 }
 
 
 
 int
 iobuf_peek (iobuf_t a, byte * buf, unsigned buflen)
 {
   int n = 0;
 
   assert (buflen > 0);
   assert (a->use == IOBUF_INPUT || a->use == IOBUF_INPUT_TEMP);
 
   if (buflen > a->d.size)
     /* We can't peek more than we can buffer.  */
     buflen = a->d.size;
 
   /* Try to fill the internal buffer with enough data to satisfy the
      request.  */
   while (buflen > a->d.len - a->d.start)
     {
       if (underflow_target (a, 0, buflen) == -1)
 	/* EOF.  We can't read any more.  */
 	break;
 
       /* Underflow consumes the first character (it's the return
 	 value).  unget() it by resetting the "file position".  */
       assert (a->d.start == 1);
       a->d.start = 0;
     }
 
   n = a->d.len - a->d.start;
   if (n > buflen)
     n = buflen;
 
   if (n == 0)
     /* EOF.  */
     return -1;
 
   memcpy (buf, &a->d.buf[a->d.start], n);
 
   return n;
 }
 
 
 
 
 int
 iobuf_writebyte (iobuf_t a, unsigned int c)
 {
   int rc;
 
   if (a->use == IOBUF_INPUT || a->use == IOBUF_INPUT_TEMP)
     {
       log_bug ("iobuf_writebyte called on an input pipeline!\n");
       return -1;
     }
 
   if (a->d.len == a->d.size)
     if ((rc=filter_flush (a)))
       return rc;
 
   assert (a->d.len < a->d.size);
   a->d.buf[a->d.len++] = c;
   return 0;
 }
 
 
 int
 iobuf_write (iobuf_t a, const void *buffer, unsigned int buflen)
 {
   const unsigned char *buf = (const unsigned char *)buffer;
   int rc;
 
   if (a->use == IOBUF_INPUT || a->use == IOBUF_INPUT_TEMP)
     {
       log_bug ("iobuf_write called on an input pipeline!\n");
       return -1;
     }
 
   do
     {
       if (buflen && a->d.len < a->d.size)
 	{
 	  unsigned size = a->d.size - a->d.len;
 	  if (size > buflen)
 	    size = buflen;
 	  memcpy (a->d.buf + a->d.len, buf, size);
 	  buflen -= size;
 	  buf += size;
 	  a->d.len += size;
 	}
       if (buflen)
 	{
 	  rc = filter_flush (a);
           if (rc)
 	    return rc;
 	}
     }
   while (buflen);
   return 0;
 }
 
 
 int
 iobuf_writestr (iobuf_t a, const char *buf)
 {
   if (a->use == IOBUF_INPUT || a->use == IOBUF_INPUT_TEMP)
     {
       log_bug ("iobuf_writestr called on an input pipeline!\n");
       return -1;
     }
 
   return iobuf_write (a, buf, strlen (buf));
 }
 
 
 
 int
 iobuf_write_temp (iobuf_t dest, iobuf_t source)
 {
   assert (source->use == IOBUF_OUTPUT || source->use == IOBUF_OUTPUT_TEMP);
   assert (dest->use == IOBUF_OUTPUT || dest->use == IOBUF_OUTPUT_TEMP);
 
   iobuf_flush_temp (source);
   return iobuf_write (dest, source->d.buf, source->d.len);
 }
 
 size_t
 iobuf_temp_to_buffer (iobuf_t a, byte * buffer, size_t buflen)
 {
   byte desc[MAX_IOBUF_DESC];
   size_t n;
 
   while (1)
     {
       int rc = filter_flush (a);
       if (rc)
 	log_bug ("Flushing iobuf %d.%d (%s) from iobuf_temp_to_buffer failed.  Ignoring.\n",
 		 a->no, a->subno, iobuf_desc (a, desc));
       if (! a->chain)
 	break;
       a = a->chain;
     }
 
   n = a->d.len;
   if (n > buflen)
     n = buflen;
   memcpy (buffer, a->d.buf, n);
   return n;
 }
 
 /* Copies the data from the input iobuf SOURCE to the output iobuf
    DEST until either an error is encountered or EOF is reached.
-   Returns the number of bytes copies.  */
+   Returns the number of bytes copies or (size_t)(-1) on error.  */
 size_t
 iobuf_copy (iobuf_t dest, iobuf_t source)
 {
   char *temp;
   /* Use a 32 KB buffer.  */
   const size_t temp_size = 32 * 1024;
 
   size_t nread;
   size_t nwrote = 0;
   size_t max_read = 0;
   int err;
 
-  assert (source->use == IOBUF_INPUT || source->use == IOBUF_INPUT_TEMP);
-  assert (dest->use == IOBUF_OUTPUT || source->use == IOBUF_OUTPUT_TEMP);
+  log_assert (source->use == IOBUF_INPUT || source->use == IOBUF_INPUT_TEMP);
+  log_assert (dest->use == IOBUF_OUTPUT || source->use == IOBUF_OUTPUT_TEMP);
 
   if (iobuf_error (dest))
-    return -1;
+    return (size_t)(-1);
 
   temp = xmalloc (temp_size);
   while (1)
     {
       nread = iobuf_read (source, temp, temp_size);
       if (nread == -1)
         /* EOF.  */
         break;
 
       if (nread > max_read)
         max_read = nread;
 
       err = iobuf_write (dest, temp, nread);
       if (err)
         break;
       nwrote += nread;
     }
 
   /* Burn the buffer.  */
   if (max_read)
     wipememory (temp, max_read);
   xfree (temp);
 
   return nwrote;
 }
 
 
 void
 iobuf_flush_temp (iobuf_t temp)
 {
   if (temp->use == IOBUF_INPUT || temp->use == IOBUF_INPUT_TEMP)
     log_bug ("iobuf_flush_temp called on an input pipeline!\n");
   while (temp->chain)
     iobuf_pop_filter (temp, temp->filter, NULL);
 }
 
 
 void
 iobuf_set_limit (iobuf_t a, off_t nlimit)
 {
   if (nlimit)
     a->nofast = 1;
   else
     a->nofast = 0;
   a->nlimit = nlimit;
   a->ntotal += a->nbytes;
   a->nbytes = 0;
 }
 
 
 
 off_t
 iobuf_get_filelength (iobuf_t a, int *overflow)
 {
   if (overflow)
     *overflow = 0;
 
   /* Hmmm: file_filter may have already been removed */
   for ( ; a->chain; a = a->chain )
     ;
 
   if (a->filter != file_filter)
     return 0;
 
   {
     file_filter_ctx_t *b = a->filter_ov;
     gnupg_fd_t fp = b->fp;
 
 #if defined(HAVE_W32_SYSTEM)
     ulong size;
     static int (* __stdcall get_file_size_ex) (void *handle,
 					       LARGE_INTEGER *r_size);
     static int get_file_size_ex_initialized;
 
     if (!get_file_size_ex_initialized)
       {
 	void *handle;
 
 	handle = dlopen ("kernel32.dll", RTLD_LAZY);
 	if (handle)
 	  {
 	    get_file_size_ex = dlsym (handle, "GetFileSizeEx");
 	    if (!get_file_size_ex)
 	      dlclose (handle);
 	  }
 	get_file_size_ex_initialized = 1;
       }
 
     if (get_file_size_ex)
       {
 	/* This is a newer system with GetFileSizeEx; we use this
 	   then because it seem that GetFileSize won't return a
 	   proper error in case a file is larger than 4GB. */
 	LARGE_INTEGER exsize;
 
 	if (get_file_size_ex (fp, &exsize))
 	  {
 	    if (!exsize.u.HighPart)
 	      return exsize.u.LowPart;
 	    if (overflow)
 	      *overflow = 1;
 	    return 0;
 	  }
       }
     else
       {
 	if ((size=GetFileSize (fp, NULL)) != 0xffffffff)
 	  return size;
       }
     log_error ("GetFileSize for handle %p failed: %s\n",
 	       fp, w32_strerror (-1));
 #else /*!HAVE_W32_SYSTEM*/
     {
       struct stat st;
 
       if ( !fstat (FD2INT (fp), &st) )
         return st.st_size;
       log_error("fstat() failed: %s\n", strerror(errno) );
     }
 #endif /*!HAVE_W32_SYSTEM*/
   }
 
   return 0;
 }
 
 
 int
 iobuf_get_fd (iobuf_t a)
 {
   for (; a->chain; a = a->chain)
     ;
 
   if (a->filter != file_filter)
     return -1;
 
   {
     file_filter_ctx_t *b = a->filter_ov;
     gnupg_fd_t fp = b->fp;
 
     return FD2INT (fp);
   }
 }
 
 
 off_t
 iobuf_tell (iobuf_t a)
 {
   return a->ntotal + a->nbytes;
 }
 
 
 #if !defined(HAVE_FSEEKO) && !defined(fseeko)
 
 #ifdef HAVE_LIMITS_H
 # include <limits.h>
 #endif
 #ifndef LONG_MAX
 # define LONG_MAX ((long) ((unsigned long) -1 >> 1))
 #endif
 #ifndef LONG_MIN
 # define LONG_MIN (-1 - LONG_MAX)
 #endif
 
 /****************
  * A substitute for fseeko, for hosts that don't have it.
  */
 static int
 fseeko (FILE * stream, off_t newpos, int whence)
 {
   while (newpos != (long) newpos)
     {
       long pos = newpos < 0 ? LONG_MIN : LONG_MAX;
       if (fseek (stream, pos, whence) != 0)
 	return -1;
       newpos -= pos;
       whence = SEEK_CUR;
     }
   return fseek (stream, (long) newpos, whence);
 }
 #endif
 
 int
 iobuf_seek (iobuf_t a, off_t newpos)
 {
   file_filter_ctx_t *b = NULL;
 
   if (a->use == IOBUF_OUTPUT || a->use == IOBUF_INPUT)
     {
       /* Find the last filter in the pipeline.  */
       for (; a->chain; a = a->chain)
 	;
 
       if (a->filter != file_filter)
 	return -1;
 
       b = a->filter_ov;
 
 #ifdef HAVE_W32_SYSTEM
       if (SetFilePointer (b->fp, newpos, NULL, FILE_BEGIN) == 0xffffffff)
 	{
 	  log_error ("SetFilePointer failed on handle %p: ec=%d\n",
 		     b->fp, (int) GetLastError ());
 	  return -1;
 	}
 #else
       if (lseek (b->fp, newpos, SEEK_SET) == (off_t) - 1)
 	{
 	  log_error ("can't lseek: %s\n", strerror (errno));
 	  return -1;
 	}
 #endif
       /* Discard the buffer it is not a temp stream.  */
       a->d.len = 0;
     }
   a->d.start = 0;
   a->nbytes = 0;
   a->nlimit = 0;
   a->nofast = 0;
   a->ntotal = newpos;
   a->error = 0;
 
   /* It is impossible for A->CHAIN to be non-NULL.  If A is an INPUT
      or OUTPUT buffer, then we find the last filter, which is defined
      as A->CHAIN being NULL.  If A is a TEMP filter, then A must be
      the only filter in the pipe: when iobuf_push_filter adds a filter
      to the front of a pipeline, it sets the new filter to be an
      OUTPUT filter if the pipeline is an OUTPUT or TEMP pipeline and
      to be an INPUT filter if the pipeline is an INPUT pipeline.
      Thus, only the last filter in a TEMP pipeline can be a */
 
   /* remove filters, but the last */
   if (a->chain)
     log_debug ("iobuf_pop_filter called in iobuf_seek - please report\n");
   while (a->chain)
     iobuf_pop_filter (a, a->filter, NULL);
 
   return 0;
 }
 
 
 const char *
 iobuf_get_real_fname (iobuf_t a)
 {
   if (a->real_fname)
     return a->real_fname;
 
   /* the old solution */
   for (; a; a = a->chain)
     if (!a->chain && a->filter == file_filter)
       {
 	file_filter_ctx_t *b = a->filter_ov;
 	return b->print_only_name ? NULL : b->fname;
       }
 
   return NULL;
 }
 
 const char *
 iobuf_get_fname (iobuf_t a)
 {
   for (; a; a = a->chain)
     if (!a->chain && a->filter == file_filter)
       {
 	file_filter_ctx_t *b = a->filter_ov;
 	return b->fname;
       }
   return NULL;
 }
 
 const char *
 iobuf_get_fname_nonnull (iobuf_t a)
 {
   const char *fname;
 
   fname = iobuf_get_fname (a);
   return fname? fname : "[?]";
 }
 
 
 /****************
  * Enable or disable partial body length mode (RFC 4880 4.2.2.4).
  *
  * If LEN is 0, this disables partial block mode by popping the
  * partial body length filter, which must be the most recently
  * added filter.
  *
  * If LEN is non-zero, it pushes a partial body length filter.  If
  * this is a read filter, LEN must be the length byte from the first
  * chunk and A should be position just after this first partial body
  * length header.
  */
 void
 iobuf_set_partial_body_length_mode (iobuf_t a, size_t len)
 {
   if (!len)
     /* Disable partial body length mode.  */
     {
       if (a->use == IOBUF_INPUT)
 	log_debug ("iobuf_pop_filter called in set_partial_block_mode"
 		   " - please report\n");
 
       log_assert (a->filter == block_filter);
       iobuf_pop_filter (a, block_filter, NULL);
     }
   else
     /* Enabled partial body length mode.  */
     {
       block_filter_ctx_t *ctx = xcalloc (1, sizeof *ctx);
       ctx->use = a->use;
       ctx->partial = 1;
       ctx->size = 0;
       ctx->first_c = len;
       iobuf_push_filter (a, block_filter, ctx);
     }
 }
 
 
 
 unsigned int
 iobuf_read_line (iobuf_t a, byte ** addr_of_buffer,
 		 unsigned *length_of_buffer, unsigned *max_length)
 {
   int c;
   char *buffer = (char *)*addr_of_buffer;
   unsigned length = *length_of_buffer;
   unsigned nbytes = 0;
   unsigned maxlen = *max_length;
   char *p;
 
   /* The code assumes that we have space for at least a newline and a
      NUL character in the buffer.  This requires at least 2 bytes.  We
      don't complicate the code by handling the stupid corner case, but
      simply assert that it can't happen.  */
   assert (!buffer || length >= 2 || maxlen >= 2);
 
   if (!buffer || length <= 1)
     /* must allocate a new buffer */
     {
       length = 256 <= maxlen ? 256 : maxlen;
       buffer = xrealloc (buffer, length);
       *addr_of_buffer = (unsigned char *)buffer;
       *length_of_buffer = length;
     }
 
   p = buffer;
   while ((c = iobuf_get (a)) != -1)
     {
       *p++ = c;
       nbytes++;
       if (c == '\n')
 	break;
 
       if (nbytes == length - 1)
 	/* We don't have enough space to add a \n and a \0.  Increase
 	   the buffer size.  */
 	{
 	  if (length == maxlen)
 	    /* We reached the buffer's size limit!  */
 	    {
 	      /* Skip the rest of the line.  */
 	      while (c != '\n' && (c = iobuf_get (a)) != -1)
 		;
 
 	      /* p is pointing at the last byte in the buffer.  We
 		 always terminate the line with "\n\0" so overwrite
 		 the previous byte with a \n.  */
 	      assert (p > buffer);
 	      p[-1] = '\n';
 
 	      /* Indicate truncation.  */
 	      *max_length = 0;
 	      break;
 	    }
 
 	  length += length < 1024 ? 256 : 1024;
 	  if (length > maxlen)
 	    length = maxlen;
 
 	  buffer = xrealloc (buffer, length);
 	  *addr_of_buffer = (unsigned char *)buffer;
 	  *length_of_buffer = length;
 	  p = buffer + nbytes;
 	}
     }
   /* Add the terminating NUL.  */
   *p = 0;
 
   /* Return the number of characters written to the buffer including
      the newline, but not including the terminating NUL.  */
   return nbytes;
 }
 
 static int
 translate_file_handle (int fd, int for_write)
 {
 #if defined(HAVE_W32CE_SYSTEM)
   /* This is called only with one of the special filenames.  Under
      W32CE the FD here is not a file descriptor but a rendezvous id,
      thus we need to finish the pipe first.  */
   fd = _assuan_w32ce_finish_pipe (fd, for_write);
 #elif defined(HAVE_W32_SYSTEM)
   {
     int x;
 
     (void)for_write;
 
     if (fd == 0)
       x = (int) GetStdHandle (STD_INPUT_HANDLE);
     else if (fd == 1)
       x = (int) GetStdHandle (STD_OUTPUT_HANDLE);
     else if (fd == 2)
       x = (int) GetStdHandle (STD_ERROR_HANDLE);
     else
       x = fd;
 
     if (x == -1)
       log_debug ("GetStdHandle(%d) failed: ec=%d\n",
 		 fd, (int) GetLastError ());
 
     fd = x;
   }
 #else
   (void)for_write;
 #endif
   return fd;
 }
 
 
 void
 iobuf_skip_rest (iobuf_t a, unsigned long n, int partial)
 {
   if ( partial )
     {
       for (;;)
         {
           if (a->nofast || a->d.start >= a->d.len)
             {
               if (iobuf_readbyte (a) == -1)
                 {
                   break;
                 }
 	    }
           else
             {
               unsigned long count = a->d.len - a->d.start;
               a->nbytes += count;
               a->d.start = a->d.len;
 	    }
 	}
     }
   else
     {
       unsigned long remaining = n;
       while (remaining > 0)
         {
           if (a->nofast || a->d.start >= a->d.len)
             {
               if (iobuf_readbyte (a) == -1)
                 {
                   break;
 		}
               --remaining;
 	    }
           else
             {
               unsigned long count = a->d.len - a->d.start;
               if (count > remaining)
                 {
                   count = remaining;
 		}
               a->nbytes += count;
               a->d.start += count;
               remaining -= count;
 	    }
 	}
     }
 }
diff --git a/g10/build-packet.c b/g10/build-packet.c
index 266bf54e4..a40ed0d82 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -1,1805 +1,1808 @@
 /* build-packet.c - assemble packets and write them
  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
  *               2006, 2010, 2011  Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
  * GnuPG is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * GnuPG is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
 
 #include "gpg.h"
 #include "../common/util.h"
 #include "packet.h"
 #include "../common/status.h"
 #include "../common/iobuf.h"
 #include "../common/i18n.h"
 #include "options.h"
 #include "../common/host2net.h"
 
 static gpg_error_t do_ring_trust (iobuf_t out, PKT_ring_trust *rt);
 static int do_user_id( IOBUF out, int ctb, PKT_user_id *uid );
 static int do_key (iobuf_t out, int ctb, PKT_public_key *pk);
 static int do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc );
 static int do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc );
 static u32 calc_plaintext( PKT_plaintext *pt );
 static int do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt );
 static int do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed );
 static int do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed );
 static int do_compressed( IOBUF out, int ctb, PKT_compressed *cd );
 static int do_signature( IOBUF out, int ctb, PKT_signature *sig );
 static int do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops );
 
 static int calc_header_length( u32 len, int new_ctb );
 static int write_16(IOBUF inp, u16 a);
 static int write_32(IOBUF inp, u32 a);
 static int write_header( IOBUF out, int ctb, u32 len );
 static int write_sign_packet_header( IOBUF out, int ctb, u32 len );
 static int write_header2( IOBUF out, int ctb, u32 len, int hdrlen );
 static int write_new_header( IOBUF out, int ctb, u32 len, int hdrlen );
 
 /* Returns 1 if CTB is a new format ctb and 0 if CTB is an old format
    ctb.  */
 static int
 ctb_new_format_p (int ctb)
 {
   /* Bit 7 must always be set.  */
   log_assert ((ctb & (1 << 7)));
   /* Bit 6 indicates whether the packet is a new format packet.  */
   return (ctb & (1 << 6));
 }
 
 /* Extract the packet type from a CTB.  */
 static int
 ctb_pkttype (int ctb)
 {
   if (ctb_new_format_p (ctb))
     /* Bits 0 through 5 are the packet type.  */
     return (ctb & ((1 << 6) - 1));
   else
     /* Bits 2 through 5 are the packet type.  */
     return (ctb & ((1 << 6) - 1)) >> 2;
 }
 
 
 /* Build a packet and write it to the stream OUT.
  * Returns: 0 on success or on an error code.  */
 int
 build_packet (IOBUF out, PACKET *pkt)
 {
   int rc = 0;
   int new_ctb = 0;
   int ctb, pkttype;
 
   if (DBG_PACKET)
     log_debug ("build_packet() type=%d\n", pkt->pkttype);
   log_assert (pkt->pkt.generic);
 
   switch ((pkttype = pkt->pkttype))
     {
     case PKT_PUBLIC_KEY:
       if (pkt->pkt.public_key->seckey_info)
         pkttype = PKT_SECRET_KEY;
       break;
     case PKT_PUBLIC_SUBKEY:
       if (pkt->pkt.public_key->seckey_info)
         pkttype = PKT_SECRET_SUBKEY;
       break;
     case PKT_PLAINTEXT:
       new_ctb = pkt->pkt.plaintext->new_ctb;
       break;
     case PKT_ENCRYPTED:
     case PKT_ENCRYPTED_MDC:
       new_ctb = pkt->pkt.encrypted->new_ctb;
       break;
     case PKT_COMPRESSED:
       new_ctb = pkt->pkt.compressed->new_ctb;
       break;
     case PKT_USER_ID:
       if (pkt->pkt.user_id->attrib_data)
         pkttype = PKT_ATTRIBUTE;
       break;
     default:
       break;
     }
 
   if (new_ctb || pkttype > 15) /* new format */
     ctb = (0xc0 | (pkttype & 0x3f));
   else
     ctb = (0x80 | ((pkttype & 15)<<2));
   switch (pkttype)
     {
     case PKT_ATTRIBUTE:
     case PKT_USER_ID:
       rc = do_user_id (out, ctb, pkt->pkt.user_id);
       break;
     case PKT_OLD_COMMENT:
     case PKT_COMMENT:
       /* Ignore these.  Theoretically, this will never be called as we
        * have no way to output comment packets any longer, but just in
        * case there is some code path that would end up outputting a
        * comment that was written before comments were dropped (in the
        * public key?) this is a no-op. 	*/
       break;
     case PKT_PUBLIC_SUBKEY:
     case PKT_PUBLIC_KEY:
     case PKT_SECRET_SUBKEY:
     case PKT_SECRET_KEY:
       rc = do_key (out, ctb, pkt->pkt.public_key);
       break;
     case PKT_SYMKEY_ENC:
       rc = do_symkey_enc (out, ctb, pkt->pkt.symkey_enc);
       break;
     case PKT_PUBKEY_ENC:
       rc = do_pubkey_enc (out, ctb, pkt->pkt.pubkey_enc);
       break;
     case PKT_PLAINTEXT:
       rc = do_plaintext (out, ctb, pkt->pkt.plaintext);
       break;
     case PKT_ENCRYPTED:
       rc = do_encrypted (out, ctb, pkt->pkt.encrypted);
       break;
     case PKT_ENCRYPTED_MDC:
       rc = do_encrypted_mdc (out, ctb, pkt->pkt.encrypted);
       break;
     case PKT_COMPRESSED:
       rc = do_compressed (out, ctb, pkt->pkt.compressed);
       break;
     case PKT_SIGNATURE:
       rc = do_signature (out, ctb, pkt->pkt.signature);
       break;
     case PKT_ONEPASS_SIG:
       rc = do_onepass_sig (out, ctb, pkt->pkt.onepass_sig);
       break;
     case PKT_RING_TRUST:
       /* Ignore it (only written by build_packet_and_meta)  */
       break;
     case PKT_MDC:
       /* We write it directly, so we should never see it here. */
     default:
       log_bug ("invalid packet type in build_packet()\n");
       break;
     }
 
   return rc;
 }
 
 
 /* Build a packet and write it to the stream OUT.  This variant also
  * writes the meta data using ring trust packets.  Returns: 0 on
  * success or on error code.  */
 gpg_error_t
 build_packet_and_meta (iobuf_t out, PACKET *pkt)
 {
   gpg_error_t err;
   PKT_ring_trust rt = {0};
 
   err = build_packet (out, pkt);
   if (err)
     ;
   else if (pkt->pkttype == PKT_SIGNATURE)
     {
       PKT_signature *sig = pkt->pkt.signature;
 
       rt.subtype = RING_TRUST_SIG;
       /* Note: trustval is not yet used.  */
       if (sig->flags.checked)
         {
           rt.sigcache = 1;
           if (sig->flags.valid)
             rt.sigcache |= 2;
         }
       err = do_ring_trust (out, &rt);
     }
   else if (pkt->pkttype == PKT_USER_ID
            || pkt->pkttype == PKT_ATTRIBUTE)
     {
       PKT_user_id *uid = pkt->pkt.user_id;
 
       rt.subtype = RING_TRUST_UID;
       rt.keyorg = uid->keyorg;
       rt.keyupdate = uid->keyupdate;
       rt.url = uid->updateurl;
       err = do_ring_trust (out, &rt);
       rt.url = NULL;
     }
   else if (pkt->pkttype == PKT_PUBLIC_KEY
            || pkt->pkttype == PKT_SECRET_KEY)
     {
       PKT_public_key *pk = pkt->pkt.public_key;
 
       rt.subtype = RING_TRUST_KEY;
       rt.keyorg = pk->keyorg;
       rt.keyupdate = pk->keyupdate;
       rt.url = pk->updateurl;
       err = do_ring_trust (out, &rt);
       rt.url = NULL;
 
     }
 
   return err;
 }
 
 
 /*
  * Write the mpi A to OUT.
  */
 gpg_error_t
 gpg_mpi_write (iobuf_t out, gcry_mpi_t a)
 {
   int rc;
 
   if (gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE))
     {
       unsigned int nbits;
       const unsigned char *p;
       unsigned char lenhdr[2];
 
       /* gcry_log_debugmpi ("a", a); */
       p = gcry_mpi_get_opaque (a, &nbits);
       if (p)
         {
           /* Strip leading zero bits.  */
           for (; nbits >= 8 && !*p; p++, nbits -= 8)
             ;
           if (nbits >= 8 && !(*p & 0x80))
             if (--nbits >= 7 && !(*p & 0x40))
               if (--nbits >= 6 && !(*p & 0x20))
                 if (--nbits >= 5 && !(*p & 0x10))
                   if (--nbits >= 4 && !(*p & 0x08))
                     if (--nbits >= 3 && !(*p & 0x04))
                       if (--nbits >= 2 && !(*p & 0x02))
                         if (--nbits >= 1 && !(*p & 0x01))
                           --nbits;
         }
       /* gcry_log_debug ("   [%u bit]\n", nbits); */
       /* gcry_log_debughex (" ", p, (nbits+7)/8); */
       lenhdr[0] = nbits >> 8;
       lenhdr[1] = nbits;
       rc = iobuf_write (out, lenhdr, 2);
       if (!rc && p)
         rc = iobuf_write (out, p, (nbits+7)/8);
     }
   else
     {
       char buffer[(MAX_EXTERN_MPI_BITS+7)/8+2]; /* 2 is for the mpi length. */
       size_t nbytes;
 
       nbytes = DIM(buffer);
       rc = gcry_mpi_print (GCRYMPI_FMT_PGP, buffer, nbytes, &nbytes, a );
       if( !rc )
         rc = iobuf_write( out, buffer, nbytes );
       else if (gpg_err_code(rc) == GPG_ERR_TOO_SHORT )
         {
           log_info ("mpi too large (%u bits)\n", gcry_mpi_get_nbits (a));
           /* The buffer was too small. We better tell the user about the MPI. */
           rc = gpg_error (GPG_ERR_TOO_LARGE);
         }
     }
 
   return rc;
 }
 
 
 /*
  * Write an opaque MPI to the output stream without length info.
  */
 gpg_error_t
 gpg_mpi_write_nohdr (iobuf_t out, gcry_mpi_t a)
 {
   int rc;
 
   if (gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE))
     {
       unsigned int nbits;
       const void *p;
 
       p = gcry_mpi_get_opaque (a, &nbits);
       rc = p ? iobuf_write (out, p, (nbits+7)/8) : 0;
     }
   else
     rc = gpg_error (GPG_ERR_BAD_MPI);
 
   return rc;
 }
 
 
 /* Calculate the length of a packet described by PKT.  */
 u32
 calc_packet_length( PACKET *pkt )
 {
   u32 n = 0;
   int new_ctb = 0;
 
   log_assert (pkt->pkt.generic);
   switch (pkt->pkttype)
     {
     case PKT_PLAINTEXT:
       n = calc_plaintext (pkt->pkt.plaintext);
       new_ctb = pkt->pkt.plaintext->new_ctb;
       break;
     case PKT_ATTRIBUTE:
     case PKT_USER_ID:
     case PKT_COMMENT:
     case PKT_PUBLIC_KEY:
     case PKT_SECRET_KEY:
     case PKT_SYMKEY_ENC:
     case PKT_PUBKEY_ENC:
     case PKT_ENCRYPTED:
     case PKT_SIGNATURE:
     case PKT_ONEPASS_SIG:
     case PKT_RING_TRUST:
     case PKT_COMPRESSED:
     default:
       log_bug ("invalid packet type in calc_packet_length()");
       break;
     }
 
   n += calc_header_length (n, new_ctb);
   return n;
 }
 
 
 static gpg_error_t
 write_fake_data (IOBUF out, gcry_mpi_t a)
 {
   unsigned int n;
   void *p;
 
   if (!a)
     return 0;
   if (!gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE))
     return 0; /* e.g. due to generating a key with wrong usage.  */
   p = gcry_mpi_get_opaque ( a, &n);
   if (!p)
     return 0; /* For example due to a read error in
                  parse-packet.c:read_rest.  */
   return iobuf_write (out, p, (n+7)/8 );
 }
 
 
 /* Write a ring trust meta packet.  */
 static gpg_error_t
 do_ring_trust (iobuf_t out, PKT_ring_trust *rt)
 {
   unsigned int namelen = 0;
   unsigned int pktlen = 6;
 
   if (rt->subtype == RING_TRUST_KEY || rt->subtype == RING_TRUST_UID)
     {
       if (rt->url)
         namelen = strlen (rt->url);
       pktlen += 1 + 4 + 1 + namelen;
     }
 
   write_header (out, (0x80 | ((PKT_RING_TRUST & 15)<<2)), pktlen);
   iobuf_put (out, rt->trustval);
   iobuf_put (out, rt->sigcache);
   iobuf_write (out, "gpg", 3);
   iobuf_put (out, rt->subtype);
   if (rt->subtype == RING_TRUST_KEY || rt->subtype == RING_TRUST_UID)
     {
       iobuf_put (out, rt->keyorg);
       write_32 (out, rt->keyupdate);
       iobuf_put (out, namelen);
       if (namelen)
         iobuf_write (out, rt->url, namelen);
     }
 
   return 0;
 }
 
 
 /* Serialize the user id (RFC 4880, Section 5.11) or the user
  * attribute UID (Section 5.12) and write it to OUT.
  *
  * CTB is the serialization's CTB.  It specifies the header format and
  * the packet's type.  The header length must not be set.  */
 static int
 do_user_id( IOBUF out, int ctb, PKT_user_id *uid )
 {
   int rc;
   int hdrlen;
 
   log_assert (ctb_pkttype (ctb) == PKT_USER_ID
               || ctb_pkttype (ctb) == PKT_ATTRIBUTE);
 
   /* We need to take special care of a user ID with a length of 0:
    * Without forcing HDRLEN to 2 in this case an indeterminate length
    * packet would be written which is not allowed.  Note that we are
    * always called with a CTB indicating an old packet header format,
    * so that forcing a 2 octet header works.  We also check for the
    * maximum allowed packet size by the parser using an arbitrary
    * extra 10 bytes for header data. */
   if (uid->attrib_data)
     {
       if (uid->attrib_len > MAX_ATTR_PACKET_LENGTH - 10)
         return gpg_error (GPG_ERR_TOO_LARGE);
       hdrlen = uid->attrib_len? 0 : 2;
       write_header2 (out, ctb, uid->attrib_len, hdrlen);
       rc = iobuf_write( out, uid->attrib_data, uid->attrib_len );
     }
   else
     {
       if (uid->len > MAX_UID_PACKET_LENGTH - 10)
         return gpg_error (GPG_ERR_TOO_LARGE);
       hdrlen = uid->len? 0 : 2;
       write_header2 (out, ctb, uid->len, hdrlen);
       rc = iobuf_write( out, uid->name, uid->len );
     }
   return rc;
 }
 
 
 /* Serialize the key (RFC 4880, Section 5.5) described by PK and write
  * it to OUT.
  *
  * This function serializes both primary keys and subkeys with or
  * without a secret part.
  *
  * CTB is the serialization's CTB.  It specifies the header format and
  * the packet's type.  The header length must not be set.
  *
  * PK->VERSION specifies the serialization format.  A value of 0 means
  * to use the default version.  Currently, only version 4 packets are
  * supported.
  */
 static int
 do_key (iobuf_t out, int ctb, PKT_public_key *pk)
 {
   gpg_error_t err = 0;
   /* The length of the body is stored in the packet's header, which
      occurs before the body.  Unfortunately, we don't know the length
      of the packet's body until we've written all of the data!  To
      work around this, we first write the data into this temporary
      buffer, then generate the header, and finally copy the contents
      of this buffer to OUT.  */
   iobuf_t a = iobuf_temp();
   int i, nskey, npkey;
 
   log_assert (pk->version == 0 || pk->version == 4);
   log_assert (ctb_pkttype (ctb) == PKT_PUBLIC_KEY
               || ctb_pkttype (ctb) == PKT_PUBLIC_SUBKEY
               || ctb_pkttype (ctb) == PKT_SECRET_KEY
               || ctb_pkttype (ctb) == PKT_SECRET_SUBKEY);
 
   /* Write the version number - if none is specified, use 4 */
   if ( !pk->version )
     iobuf_put ( a, 4 );
   else
     iobuf_put ( a, pk->version );
   write_32 (a, pk->timestamp );
 
   iobuf_put (a, pk->pubkey_algo );
 
   /* Get number of secret and public parameters.  They are held in one
      array: the public ones followed by the secret ones.  */
   nskey = pubkey_get_nskey (pk->pubkey_algo);
   npkey = pubkey_get_npkey (pk->pubkey_algo);
 
   /* If we don't have any public parameters - which is for example the
      case if we don't know the algorithm used - the parameters are
      stored as one blob in a faked (opaque) MPI. */
   if (!npkey)
     {
       write_fake_data (a, pk->pkey[0]);
       goto leave;
     }
   log_assert (npkey < nskey);
 
   for (i=0; i < npkey; i++ )
     {
       if (   (pk->pubkey_algo == PUBKEY_ALGO_ECDSA && (i == 0))
           || (pk->pubkey_algo == PUBKEY_ALGO_EDDSA && (i == 0))
           || (pk->pubkey_algo == PUBKEY_ALGO_ECDH  && (i == 0 || i == 2)))
         err = gpg_mpi_write_nohdr (a, pk->pkey[i]);
       else
         err = gpg_mpi_write (a, pk->pkey[i]);
       if (err)
         goto leave;
     }
 
 
   if (pk->seckey_info)
     {
       /* This is a secret key packet.  */
       struct seckey_info *ski = pk->seckey_info;
 
       /* Build the header for protected (encrypted) secret parameters.  */
       if (ski->is_protected)
         {
           /* OpenPGP protection according to rfc2440. */
           iobuf_put (a, ski->sha1chk? 0xfe : 0xff);
           iobuf_put (a, ski->algo);
           if (ski->s2k.mode >= 1000)
             {
               /* These modes are not possible in OpenPGP, we use them
                  to implement our extensions, 101 can be viewed as a
                  private/experimental extension (this is not specified
                  in rfc2440 but the same scheme is used for all other
                  algorithm identifiers). */
               iobuf_put (a, 101);
               iobuf_put (a, ski->s2k.hash_algo);
               iobuf_write (a, "GNU", 3 );
               iobuf_put (a, ski->s2k.mode - 1000);
             }
           else
             {
               iobuf_put (a, ski->s2k.mode);
               iobuf_put (a, ski->s2k.hash_algo);
             }
 
           if (ski->s2k.mode == 1 || ski->s2k.mode == 3)
             iobuf_write (a, ski->s2k.salt, 8);
 
           if (ski->s2k.mode == 3)
             iobuf_put (a, ski->s2k.count);
 
           /* For our special modes 1001, 1002 we do not need an IV. */
           if (ski->s2k.mode != 1001 && ski->s2k.mode != 1002)
             iobuf_write (a, ski->iv, ski->ivlen);
 
         }
       else /* Not protected. */
         iobuf_put (a, 0 );
 
       if (ski->s2k.mode == 1001)
         ; /* GnuPG extension - don't write a secret key at all. */
       else if (ski->s2k.mode == 1002)
         {
           /* GnuPG extension - divert to OpenPGP smartcard. */
           /* Length of the serial number or 0 for no serial number. */
           iobuf_put (a, ski->ivlen );
           /* The serial number gets stored in the IV field.  */
           iobuf_write (a, ski->iv, ski->ivlen);
         }
       else if (ski->is_protected)
         {
           /* The secret key is protected - write it out as it is.  */
           byte *p;
           unsigned int ndatabits;
 
           log_assert (gcry_mpi_get_flag (pk->pkey[npkey], GCRYMPI_FLAG_OPAQUE));
           p = gcry_mpi_get_opaque (pk->pkey[npkey], &ndatabits);
           if (p)
             iobuf_write (a, p, (ndatabits+7)/8 );
         }
       else
         {
           /* Non-protected key. */
           for ( ; i < nskey; i++ )
             if ( (err = gpg_mpi_write (a, pk->pkey[i])))
               goto leave;
           write_16 (a, ski->csum );
         }
     }
 
  leave:
   if (!err)
     {
       /* Build the header of the packet - which we must do after
          writing all the other stuff, so that we know the length of
          the packet */
       write_header2 (out, ctb, iobuf_get_temp_length(a), 0);
        /* And finally write it out to the real stream. */
       err = iobuf_write_temp (out, a);
     }
 
   iobuf_close (a); /* Close the temporary buffer */
   return err;
 }
 
 
 /* Serialize the symmetric-key encrypted session key packet (RFC 4880,
  * 5.3) described by ENC and write it to OUT.
  *
  * CTB is the serialization's CTB.  It specifies the header format and
  * the packet's type.  The header length must not be set.  */
 static int
 do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc )
 {
   int rc = 0;
   IOBUF a = iobuf_temp();
 
   log_assert (ctb_pkttype (ctb) == PKT_SYMKEY_ENC);
 
   /* The only acceptable version.  */
   log_assert( enc->version == 4 );
 
   /* RFC 4880, Section 3.7.  */
   switch (enc->s2k.mode)
     {
     case 0: /* Simple S2K.  */
     case 1: /* Salted S2K.  */
     case 3: /* Iterated and salted S2K.  */
       break; /* Reasonable values.  */
 
     default:
       log_bug ("do_symkey_enc: s2k=%d\n", enc->s2k.mode);
     }
     iobuf_put( a, enc->version );
     iobuf_put( a, enc->cipher_algo );
     iobuf_put( a, enc->s2k.mode );
     iobuf_put( a, enc->s2k.hash_algo );
     if( enc->s2k.mode == 1 || enc->s2k.mode == 3 ) {
 	iobuf_write(a, enc->s2k.salt, 8 );
 	if( enc->s2k.mode == 3 )
 	    iobuf_put(a, enc->s2k.count);
     }
     if( enc->seskeylen )
 	iobuf_write(a, enc->seskey, enc->seskeylen );
 
     write_header(out, ctb, iobuf_get_temp_length(a) );
     rc = iobuf_write_temp( out, a );
 
     iobuf_close(a);
     return rc;
 }
 
 
 /* Serialize the public-key encrypted session key packet (RFC 4880,
    5.1) described by ENC and write it to OUT.
 
    CTB is the serialization's CTB.  It specifies the header format and
    the packet's type.  The header length must not be set.  */
 static int
 do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc )
 {
   int rc = 0;
   int n, i;
   IOBUF a = iobuf_temp();
 
   log_assert (ctb_pkttype (ctb) == PKT_PUBKEY_ENC);
 
   iobuf_put (a, 3); /* Version.  */
 
   if ( enc->throw_keyid )
     {
       write_32(a, 0 );  /* Don't tell Eve who can decrypt the message.  */
       write_32(a, 0 );
     }
   else
     {
       write_32(a, enc->keyid[0] );
       write_32(a, enc->keyid[1] );
     }
   iobuf_put(a,enc->pubkey_algo );
   n = pubkey_get_nenc( enc->pubkey_algo );
   if ( !n )
     write_fake_data( a, enc->data[0] );
 
   for (i=0; i < n && !rc ; i++ )
     {
       if (enc->pubkey_algo == PUBKEY_ALGO_ECDH && i == 1)
         rc = gpg_mpi_write_nohdr (a, enc->data[i]);
       else
         rc = gpg_mpi_write (a, enc->data[i]);
     }
 
   if (!rc)
     {
       write_header (out, ctb, iobuf_get_temp_length(a) );
       rc = iobuf_write_temp (out, a);
     }
   iobuf_close(a);
   return rc;
 }
 
 
 /* Calculate the length of the serialized plaintext packet PT (RFC
    4480, Section 5.9).  */
 static u32
 calc_plaintext( PKT_plaintext *pt )
 {
   /* Truncate namelen to the maximum 255 characters.  Note this means
      that a function that calls build_packet with an illegal literal
      packet will get it back legalized. */
 
   if(pt->namelen>255)
     pt->namelen=255;
 
   return pt->len? (1 + 1 + pt->namelen + 4 + pt->len) : 0;
 }
 
 /* Serialize the plaintext packet (RFC 4880, 5.9) described by PT and
    write it to OUT.
 
    The body of the message is stored in PT->BUF.  The amount of data
    to write is PT->LEN.  (PT->BUF should be configured to return EOF
    after this much data has been read.)  If PT->LEN is 0 and CTB
    indicates that this is a new format packet, then partial block mode
    is assumed to have been enabled on OUT.  On success, partial block
    mode is disabled.
 
    If PT->BUF is NULL, the caller must write out the data.  In
    this case, if PT->LEN was 0, then partial body length mode was
    enabled and the caller must disable it by calling
    iobuf_set_partial_body_length_mode (out, 0).  */
 static int
 do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt )
 {
     int rc = 0;
     size_t nbytes;
 
     log_assert (ctb_pkttype (ctb) == PKT_PLAINTEXT);
 
     write_header(out, ctb, calc_plaintext( pt ) );
     log_assert (pt->mode == 'b' || pt->mode == 't' || pt->mode == 'u'
                 || pt->mode == 'm'
                 || pt->mode == 'l' || pt->mode == '1');
     iobuf_put(out, pt->mode );
     iobuf_put(out, pt->namelen );
     iobuf_write (out, pt->name, pt->namelen);
     rc = write_32(out, pt->timestamp );
     if (rc)
       return rc;
 
     if (pt->buf)
       {
         nbytes = iobuf_copy (out, pt->buf);
+        if (nbytes == (size_t)(-1)
+            && (iobuf_error (out) || iobuf_error (pt->buf)))
+            return iobuf_error (out)? iobuf_error (out):iobuf_error (pt->buf);
         if(ctb_new_format_p (ctb) && !pt->len)
           /* Turn off partial body length mode.  */
           iobuf_set_partial_body_length_mode (out, 0);
         if( pt->len && nbytes != pt->len )
           log_error("do_plaintext(): wrote %lu bytes but expected %lu bytes\n",
                     (ulong)nbytes, (ulong)pt->len );
       }
 
     return rc;
 }
 
 
 
 /* Serialize the symmetrically encrypted data packet (RFC 4880,
    Section 5.7) described by ED and write it to OUT.
 
    Note: this only writes the packets header!  The call must then
    follow up and write the initial random data and the body to OUT.
    (If you use the encryption iobuf filter (cipher_filter), then this
    is done automatically.)  */
 static int
 do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed )
 {
     int rc = 0;
     u32 n;
 
     log_assert (! ed->mdc_method);
     log_assert (ctb_pkttype (ctb) == PKT_ENCRYPTED);
 
     n = ed->len ? (ed->len + ed->extralen) : 0;
     write_header(out, ctb, n );
 
     /* This is all. The caller has to write the real data */
 
     return rc;
 }
 
 /* Serialize the symmetrically encrypted integrity protected data
    packet (RFC 4880, Section 5.13) described by ED and write it to
    OUT.
 
    Note: this only writes the packet's header!  The caller must then
    follow up and write the initial random data, the body and the MDC
    packet to OUT.  (If you use the encryption iobuf filter
    (cipher_filter), then this is done automatically.)  */
 static int
 do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed )
 {
     int rc = 0;
     u32 n;
 
     log_assert (ed->mdc_method);
     log_assert (ctb_pkttype (ctb) == PKT_ENCRYPTED_MDC);
 
     /* Take version number and the following MDC packet in account. */
     n = ed->len ? (ed->len + ed->extralen + 1 + 22) : 0;
     write_header(out, ctb, n );
     iobuf_put(out, 1 );  /* version */
 
     /* This is all. The caller has to write the real data */
 
     return rc;
 }
 
 
 /* Serialize the compressed packet (RFC 4880, Section 5.6) described
    by CD and write it to OUT.
 
    Note: this only writes the packet's header!  The caller must then
    follow up and write the body to OUT.  */
 static int
 do_compressed( IOBUF out, int ctb, PKT_compressed *cd )
 {
     int rc = 0;
 
     log_assert (ctb_pkttype (ctb) == PKT_COMPRESSED);
 
     /* We must use the old convention and don't use blockmode for the
        sake of PGP 2 compatibility.  However if the new_ctb flag was
        set, CTB is already formatted as new style and write_header2
        does create a partial length encoding using new the new
        style. */
     write_header2(out, ctb, 0, 0);
     iobuf_put(out, cd->algorithm );
 
     /* This is all. The caller has to write the real data */
 
     return rc;
 }
 
 
 /****************
  * Delete all subpackets of type REQTYPE and return a bool whether a packet
  * was deleted.
  */
 int
 delete_sig_subpkt (subpktarea_t *area, sigsubpkttype_t reqtype )
 {
     int buflen;
     sigsubpkttype_t type;
     byte *buffer, *bufstart;
     size_t n;
     size_t unused = 0;
     int okay = 0;
 
     if( !area )
 	return 0;
     buflen = area->len;
     buffer = area->data;
     for(;;) {
 	if( !buflen ) {
             okay = 1;
             break;
         }
 	bufstart = buffer;
 	n = *buffer++; buflen--;
 	if( n == 255 ) {
 	    if( buflen < 4 )
 		break;
 	    n = buf32_to_size_t (buffer);
 	    buffer += 4;
 	    buflen -= 4;
 	}
 	else if( n >= 192 ) {
 	    if( buflen < 2 )
 		break;
 	    n = (( n - 192 ) << 8) + *buffer + 192;
 	    buffer++;
 	    buflen--;
 	}
 	if( buflen < n )
 	    break;
 
 	type = *buffer & 0x7f;
 	if( type == reqtype ) {
 	    buffer++;
             buflen--;
 	    n--;
 	    if( n > buflen )
 		break;
             buffer += n; /* point to next subpkt */
             buflen -= n;
             memmove (bufstart, buffer, buflen); /* shift */
             unused +=  buffer - bufstart;
             buffer = bufstart;
 	}
         else {
             buffer += n; buflen -=n;
         }
     }
 
     if (!okay)
         log_error ("delete_subpkt: buffer shorter than subpacket\n");
     log_assert (unused <= area->len);
     area->len -= unused;
     return !!unused;
 }
 
 
 /****************
  * Create or update a signature subpacket for SIG of TYPE.  This
  * functions knows where to put the data (hashed or unhashed).  The
  * function may move data from the unhashed part to the hashed one.
  * Note: All pointers into sig->[un]hashed (e.g. returned by
  * parse_sig_subpkt) are not valid after a call to this function.  The
  * data to put into the subpaket should be in a buffer with a length
  * of buflen.
  */
 void
 build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type,
 		  const byte *buffer, size_t buflen )
 {
     byte *p;
     int critical, hashed;
     subpktarea_t *oldarea, *newarea;
     size_t nlen, n, n0;
 
     critical = (type & SIGSUBPKT_FLAG_CRITICAL);
     type &= ~SIGSUBPKT_FLAG_CRITICAL;
 
     /* Sanity check buffer sizes */
     if(parse_one_sig_subpkt(buffer,buflen,type)<0)
       BUG();
 
     switch(type)
       {
       case SIGSUBPKT_NOTATION:
       case SIGSUBPKT_POLICY:
       case SIGSUBPKT_REV_KEY:
       case SIGSUBPKT_SIGNATURE:
 	/* we do allow multiple subpackets */
 	break;
 
       default:
 	/* we don't allow multiple subpackets */
 	delete_sig_subpkt(sig->hashed,type);
 	delete_sig_subpkt(sig->unhashed,type);
 	break;
       }
 
     /* Any special magic that needs to be done for this type so the
        packet doesn't need to be reparsed? */
     switch(type)
       {
       case SIGSUBPKT_NOTATION:
 	sig->flags.notation=1;
 	break;
 
       case SIGSUBPKT_POLICY:
 	sig->flags.policy_url=1;
 	break;
 
       case SIGSUBPKT_PREF_KS:
 	sig->flags.pref_ks=1;
 	break;
 
       case SIGSUBPKT_EXPORTABLE:
 	if(buffer[0])
 	  sig->flags.exportable=1;
 	else
 	  sig->flags.exportable=0;
 	break;
 
       case SIGSUBPKT_REVOCABLE:
 	if(buffer[0])
 	  sig->flags.revocable=1;
 	else
 	  sig->flags.revocable=0;
 	break;
 
       case SIGSUBPKT_TRUST:
 	sig->trust_depth=buffer[0];
 	sig->trust_value=buffer[1];
 	break;
 
       case SIGSUBPKT_REGEXP:
 	sig->trust_regexp=buffer;
 	break;
 
 	/* This should never happen since we don't currently allow
 	   creating such a subpacket, but just in case... */
       case SIGSUBPKT_SIG_EXPIRE:
 	if(buf32_to_u32(buffer)+sig->timestamp<=make_timestamp())
 	  sig->flags.expired=1;
 	else
 	  sig->flags.expired=0;
 	break;
 
       default:
 	break;
       }
 
     if( (buflen+1) >= 8384 )
 	nlen = 5; /* write 5 byte length header */
     else if( (buflen+1) >= 192 )
 	nlen = 2; /* write 2 byte length header */
     else
 	nlen = 1; /* just a 1 byte length header */
 
     switch( type )
       {
 	/* The issuer being unhashed is a historical oddity.  It
 	   should work equally as well hashed.  Of course, if even an
 	   unhashed issuer is tampered with, it makes it awfully hard
 	   to verify the sig... */
       case SIGSUBPKT_ISSUER:
       case SIGSUBPKT_SIGNATURE:
         hashed = 0;
         break;
       default:
         hashed = 1;
         break;
       }
 
     if( critical )
 	type |= SIGSUBPKT_FLAG_CRITICAL;
 
     oldarea = hashed? sig->hashed : sig->unhashed;
 
     /* Calculate new size of the area and allocate */
     n0 = oldarea? oldarea->len : 0;
     n = n0 + nlen + 1 + buflen; /* length, type, buffer */
     if (oldarea && n <= oldarea->size) { /* fits into the unused space */
         newarea = oldarea;
         /*log_debug ("updating area for type %d\n", type );*/
     }
     else if (oldarea) {
         newarea = xrealloc (oldarea, sizeof (*newarea) + n - 1);
         newarea->size = n;
         /*log_debug ("reallocating area for type %d\n", type );*/
     }
     else {
         newarea = xmalloc (sizeof (*newarea) + n - 1);
         newarea->size = n;
         /*log_debug ("allocating area for type %d\n", type );*/
     }
     newarea->len = n;
 
     p = newarea->data + n0;
     if (nlen == 5) {
 	*p++ = 255;
 	*p++ = (buflen+1) >> 24;
 	*p++ = (buflen+1) >> 16;
 	*p++ = (buflen+1) >>  8;
 	*p++ = (buflen+1);
 	*p++ = type;
 	memcpy (p, buffer, buflen);
     }
     else if (nlen == 2) {
 	*p++ = (buflen+1-192) / 256 + 192;
 	*p++ = (buflen+1-192) % 256;
 	*p++ = type;
 	memcpy (p, buffer, buflen);
     }
     else {
 	*p++ = buflen+1;
 	*p++ = type;
 	memcpy (p, buffer, buflen);
     }
 
     if (hashed)
 	sig->hashed = newarea;
     else
 	sig->unhashed = newarea;
 }
 
 /*
  * Put all the required stuff from SIG into subpackets of sig.
  * PKSK is the signing key.
  * Hmmm, should we delete those subpackets which are in a wrong area?
  */
 void
 build_sig_subpkt_from_sig (PKT_signature *sig, PKT_public_key *pksk)
 {
     u32  u;
     byte buf[1+MAX_FINGERPRINT_LEN];
     size_t fprlen;
 
     /* For v4 keys we need to write the ISSUER subpacket.  We do not
      * want that for a future v5 format.  */
     if (pksk->version < 5)
       {
         u = sig->keyid[0];
         buf[0] = (u >> 24) & 0xff;
         buf[1] = (u >> 16) & 0xff;
         buf[2] = (u >>  8) & 0xff;
         buf[3] = u & 0xff;
         u = sig->keyid[1];
         buf[4] = (u >> 24) & 0xff;
         buf[5] = (u >> 16) & 0xff;
         buf[6] = (u >>  8) & 0xff;
         buf[7] = u & 0xff;
         build_sig_subpkt (sig, SIGSUBPKT_ISSUER, buf, 8);
       }
 
     /* Write the new ISSUER_FPR subpacket.  */
     fingerprint_from_pk (pksk, buf+1, &fprlen);
     if (fprlen == 20)
       {
         buf[0] = pksk->version;
         build_sig_subpkt (sig, SIGSUBPKT_ISSUER_FPR, buf, 21);
       }
 
     /* Write the timestamp.  */
     u = sig->timestamp;
     buf[0] = (u >> 24) & 0xff;
     buf[1] = (u >> 16) & 0xff;
     buf[2] = (u >>  8) & 0xff;
     buf[3] = u & 0xff;
     build_sig_subpkt( sig, SIGSUBPKT_SIG_CREATED, buf, 4 );
 
     if(sig->expiredate)
       {
 	if(sig->expiredate>sig->timestamp)
 	  u=sig->expiredate-sig->timestamp;
 	else
 	  u=1; /* A 1-second expiration time is the shortest one
 		  OpenPGP has */
 
 	buf[0] = (u >> 24) & 0xff;
 	buf[1] = (u >> 16) & 0xff;
 	buf[2] = (u >>  8) & 0xff;
 	buf[3] = u & 0xff;
 
 	/* Mark this CRITICAL, so if any implementation doesn't
            understand sigs that can expire, it'll just disregard this
            sig altogether. */
 
 	build_sig_subpkt( sig, SIGSUBPKT_SIG_EXPIRE | SIGSUBPKT_FLAG_CRITICAL,
 			  buf, 4 );
       }
 }
 
 void
 build_attribute_subpkt(PKT_user_id *uid,byte type,
 		       const void *buf,u32 buflen,
 		       const void *header,u32 headerlen)
 {
   byte *attrib;
   int idx;
 
   if(1+headerlen+buflen>8383)
     idx=5;
   else if(1+headerlen+buflen>191)
     idx=2;
   else
     idx=1;
 
   /* realloc uid->attrib_data to the right size */
 
   uid->attrib_data=xrealloc(uid->attrib_data,
 			     uid->attrib_len+idx+1+headerlen+buflen);
 
   attrib=&uid->attrib_data[uid->attrib_len];
 
   if(idx==5)
     {
       attrib[0]=255;
       attrib[1]=(1+headerlen+buflen) >> 24;
       attrib[2]=(1+headerlen+buflen) >> 16;
       attrib[3]=(1+headerlen+buflen) >> 8;
       attrib[4]=1+headerlen+buflen;
     }
   else if(idx==2)
     {
       attrib[0]=(1+headerlen+buflen-192) / 256 + 192;
       attrib[1]=(1+headerlen+buflen-192) % 256;
     }
   else
     attrib[0]=1+headerlen+buflen; /* Good luck finding a JPEG this small! */
 
   attrib[idx++]=type;
 
   /* Tack on our data at the end */
 
   if(headerlen>0)
     memcpy(&attrib[idx],header,headerlen);
   memcpy(&attrib[idx+headerlen],buf,buflen);
   uid->attrib_len+=idx+headerlen+buflen;
 }
 
 /* Returns a human-readable string corresponding to the notation.
    This ignores notation->value.  The caller must free the result.  */
 static char *
 notation_value_to_human_readable_string (struct notation *notation)
 {
   if(notation->bdat)
     /* Binary data.  */
     {
       size_t len = notation->blen;
       int i;
       char preview[20];
 
       for (i = 0; i < len && i < sizeof (preview) - 1; i ++)
         if (isprint (notation->bdat[i]))
           preview[i] = notation->bdat[i];
         else
           preview[i] = '?';
       preview[i] = 0;
 
       return xasprintf (_("[ not human readable (%zu bytes: %s%s) ]"),
                         len, preview, i < len ? "..." : "");
     }
   else
     /* The value is human-readable.  */
     return xstrdup (notation->value);
 }
 
 /* Turn the notation described by the string STRING into a notation.
 
    STRING has the form:
 
      - -name - Delete the notation.
      - name@domain.name=value - Normal notation
      - !name@domain.name=value - Notation with critical bit set.
 
    The caller must free the result using free_notation().  */
 struct notation *
 string_to_notation(const char *string,int is_utf8)
 {
   const char *s;
   int saw_at=0;
   struct notation *notation;
 
   notation=xmalloc_clear(sizeof(*notation));
 
   if(*string=='-')
     {
       notation->flags.ignore=1;
       string++;
     }
 
   if(*string=='!')
     {
       notation->flags.critical=1;
       string++;
     }
 
   /* If and when the IETF assigns some official name tags, we'll have
      to add them here. */
 
   for( s=string ; *s != '='; s++ )
     {
       if( *s=='@')
 	saw_at++;
 
       /* -notationname is legal without an = sign */
       if(!*s && notation->flags.ignore)
 	break;
 
       if( !*s || !isascii (*s) || (!isgraph(*s) && !isspace(*s)) )
 	{
 	  log_error(_("a notation name must have only printable characters"
 		      " or spaces, and end with an '='\n") );
 	  goto fail;
 	}
     }
 
   notation->name=xmalloc((s-string)+1);
   memcpy(notation->name,string,s-string);
   notation->name[s-string]='\0';
 
   if(!saw_at && !opt.expert)
     {
       log_error(_("a user notation name must contain the '@' character\n"));
       goto fail;
     }
 
   if (saw_at > 1)
     {
       log_error(_("a notation name must not contain more than"
 		  " one '@' character\n"));
       goto fail;
     }
 
   if(*s)
     {
       const char *i=s+1;
       int highbit=0;
 
       /* we only support printable text - therefore we enforce the use
 	 of only printable characters (an empty value is valid) */
       for(s++; *s ; s++ )
 	{
 	  if ( !isascii (*s) )
 	    highbit=1;
 	  else if (iscntrl(*s))
 	    {
 	      log_error(_("a notation value must not use any"
 			  " control characters\n"));
 	      goto fail;
 	    }
 	}
 
       if(!highbit || is_utf8)
 	notation->value=xstrdup(i);
       else
 	notation->value=native_to_utf8(i);
     }
 
   return notation;
 
  fail:
   free_notation(notation);
   return NULL;
 }
 
 /* Like string_to_notation, but store opaque data rather than human
    readable data.  */
 struct notation *
 blob_to_notation(const char *name, const char *data, size_t len)
 {
   const char *s;
   int saw_at=0;
   struct notation *notation;
 
   notation=xmalloc_clear(sizeof(*notation));
 
   if(*name=='-')
     {
       notation->flags.ignore=1;
       name++;
     }
 
   if(*name=='!')
     {
       notation->flags.critical=1;
       name++;
     }
 
   /* If and when the IETF assigns some official name tags, we'll have
      to add them here. */
 
   for( s=name ; *s; s++ )
     {
       if( *s=='@')
 	saw_at++;
 
       /* -notationname is legal without an = sign */
       if(!*s && notation->flags.ignore)
 	break;
 
       if (*s == '=')
         {
           log_error(_("a notation name may not contain an '=' character\n"));
           goto fail;
         }
 
       if (!isascii (*s) || (!isgraph(*s) && !isspace(*s)))
 	{
 	  log_error(_("a notation name must have only printable characters"
 		      " or spaces\n") );
 	  goto fail;
 	}
     }
 
   notation->name=xstrdup (name);
 
   if(!saw_at && !opt.expert)
     {
       log_error(_("a user notation name must contain the '@' character\n"));
       goto fail;
     }
 
   if (saw_at > 1)
     {
       log_error(_("a notation name must not contain more than"
 		  " one '@' character\n"));
       goto fail;
     }
 
   notation->bdat = xmalloc (len);
   memcpy (notation->bdat, data, len);
   notation->blen = len;
 
   notation->value = notation_value_to_human_readable_string (notation);
 
   return notation;
 
  fail:
   free_notation(notation);
   return NULL;
 }
 
 struct notation *
 sig_to_notation(PKT_signature *sig)
 {
   const byte *p;
   size_t len;
   int seq = 0;
   int crit;
   notation_t list = NULL;
 
   /* See RFC 4880, 5.2.3.16 for the format of notation data.  In
      short, a notation has:
 
        - 4 bytes of flags
        - 2 byte name length (n1)
        - 2 byte value length (n2)
        - n1 bytes of name data
        - n2 bytes of value data
    */
   while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_NOTATION,&len,&seq,&crit)))
     {
       int n1,n2;
       struct notation *n=NULL;
 
       if(len<8)
 	{
 	  log_info(_("WARNING: invalid notation data found\n"));
 	  continue;
 	}
 
       /* name length.  */
       n1=(p[4]<<8)|p[5];
       /* value length.  */
       n2=(p[6]<<8)|p[7];
 
       if(8+n1+n2!=len)
 	{
 	  log_info(_("WARNING: invalid notation data found\n"));
 	  continue;
 	}
 
       n=xmalloc_clear(sizeof(*n));
       n->name=xmalloc(n1+1);
 
       memcpy(n->name,&p[8],n1);
       n->name[n1]='\0';
 
       if(p[0]&0x80)
         /* The value is human-readable.  */
 	{
 	  n->value=xmalloc(n2+1);
 	  memcpy(n->value,&p[8+n1],n2);
 	  n->value[n2]='\0';
           n->flags.human = 1;
 	}
       else
         /* Binary data.  */
 	{
 	  n->bdat=xmalloc(n2);
 	  n->blen=n2;
 	  memcpy(n->bdat,&p[8+n1],n2);
 
           n->value = notation_value_to_human_readable_string (n);
 	}
 
       n->flags.critical=crit;
 
       n->next=list;
       list=n;
     }
 
   return list;
 }
 
 /* Release the resources associated with the *list* of notations.  To
    release a single notation, make sure that notation->next is
    NULL.  */
 void
 free_notation(struct notation *notation)
 {
   while(notation)
     {
       struct notation *n=notation;
 
       xfree(n->name);
       xfree(n->value);
       xfree(n->altvalue);
       xfree(n->bdat);
       notation=n->next;
       xfree(n);
     }
 }
 
 /* Serialize the signature packet (RFC 4880, Section 5.2) described by
    SIG and write it to OUT.  */
 static int
 do_signature( IOBUF out, int ctb, PKT_signature *sig )
 {
   int rc = 0;
   int n, i;
   IOBUF a = iobuf_temp();
 
   log_assert (ctb_pkttype (ctb) == PKT_SIGNATURE);
 
   if ( !sig->version || sig->version == 3)
     {
       iobuf_put( a, 3 );
 
       /* Version 3 packets don't support subpackets.  Actually we
        * should never get to here but real life is different and thus
        * we now use a log_fatal instead of a log_assert here. */
       if (sig->hashed || sig->unhashed)
         log_fatal ("trying to write a subpacket to a v3 signature (%d,%d)\n",
                    !!sig->hashed, !!sig->unhashed);
     }
   else
     iobuf_put( a, sig->version );
   if ( sig->version < 4 )
     iobuf_put (a, 5 ); /* Constant */
   iobuf_put (a, sig->sig_class );
   if ( sig->version < 4 )
     {
       write_32(a, sig->timestamp );
       write_32(a, sig->keyid[0] );
       write_32(a, sig->keyid[1] );
     }
   iobuf_put(a, sig->pubkey_algo );
   iobuf_put(a, sig->digest_algo );
   if ( sig->version >= 4 )
     {
       size_t nn;
       /* Timestamp and keyid must have been packed into the subpackets
 	 prior to the call of this function, because these subpackets
 	 are hashed. */
       nn = sig->hashed? sig->hashed->len : 0;
       write_16(a, nn);
       if (nn)
         iobuf_write( a, sig->hashed->data, nn );
       nn = sig->unhashed? sig->unhashed->len : 0;
       write_16(a, nn);
       if (nn)
         iobuf_write( a, sig->unhashed->data, nn );
     }
   iobuf_put(a, sig->digest_start[0] );
   iobuf_put(a, sig->digest_start[1] );
   n = pubkey_get_nsig( sig->pubkey_algo );
   if ( !n )
     write_fake_data( a, sig->data[0] );
   for (i=0; i < n && !rc ; i++ )
     rc = gpg_mpi_write (a, sig->data[i] );
 
   if (!rc)
     {
       if ( is_RSA(sig->pubkey_algo) && sig->version < 4 )
         write_sign_packet_header(out, ctb, iobuf_get_temp_length(a) );
       else
         write_header(out, ctb, iobuf_get_temp_length(a) );
       rc = iobuf_write_temp( out, a );
     }
 
   iobuf_close(a);
   return rc;
 }
 
 
 /* Serialize the one-pass signature packet (RFC 4880, Section 5.4)
    described by OPS and write it to OUT.  */
 static int
 do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops )
 {
     log_assert (ctb_pkttype (ctb) == PKT_ONEPASS_SIG);
 
     write_header(out, ctb, 4 + 8 + 1);
 
     iobuf_put (out, 3);  /* Version.  */
     iobuf_put(out, ops->sig_class );
     iobuf_put(out, ops->digest_algo );
     iobuf_put(out, ops->pubkey_algo );
     write_32(out, ops->keyid[0] );
     write_32(out, ops->keyid[1] );
     iobuf_put(out, ops->last );
 
     return 0;
 }
 
 
 /* Write a 16-bit quantity to OUT in big endian order.  */
 static int
 write_16(IOBUF out, u16 a)
 {
     iobuf_put(out, a>>8);
     if( iobuf_put(out,a) )
 	return -1;
     return 0;
 }
 
 /* Write a 32-bit quantity to OUT in big endian order.  */
 static int
 write_32(IOBUF out, u32 a)
 {
     iobuf_put(out, a>> 24);
     iobuf_put(out, a>> 16);
     iobuf_put(out, a>> 8);
     return iobuf_put(out, a);
 }
 
 
 /****************
  * calculate the length of a header.
  *
  * LEN is the length of the packet's body.  NEW_CTB is whether we are
  * using a new or old format packet.
  *
  * This function does not handle indeterminate lengths or partial body
  * lengths.  (If you pass LEN as 0, then this function assumes you
  * really mean an empty body.)
  */
 static int
 calc_header_length( u32 len, int new_ctb )
 {
     if( new_ctb ) {
 	if( len < 192 )
 	    return 2;
 	if( len < 8384 )
 	    return 3;
 	else
 	    return 6;
     }
     if( len < 256 )
 	return 2;
     if( len < 65536 )
 	return 3;
 
     return 5;
 }
 
 /****************
  * Write the CTB and the packet length
  */
 static int
 write_header( IOBUF out, int ctb, u32 len )
 {
     return write_header2( out, ctb, len, 0 );
 }
 
 
 static int
 write_sign_packet_header (IOBUF out, int ctb, u32 len)
 {
   (void)ctb;
 
   /* Work around a bug in the pgp read function for signature packets,
      which are not correctly coded and silently assume at some point 2
      byte length headers.*/
   iobuf_put (out, 0x89 );
   iobuf_put (out, len >> 8 );
   return iobuf_put (out, len) == -1 ? -1:0;
 }
 
 /****************
  * Write a packet header to OUT.
  *
  * CTB is the ctb.  It determines whether a new or old format packet
  * header should be written.  The length field is adjusted, but the
  * CTB is otherwise written out as is.
  *
  * LEN is the length of the packet's body.
  *
  * If HDRLEN is set, then we don't necessarily use the most efficient
  * encoding to store LEN, but the specified length.  (If this is not
  * possible, this is a bug.)  In this case, LEN=0 means a 0 length
  * packet.  Note: setting HDRLEN is only supported for old format
  * packets!
  *
  * If HDRLEN is not set, then the shortest encoding is used.  In this
  * case, LEN=0 means the body has an indeterminate length and a
  * partial body length header (if a new format packet) or an
  * indeterminate length header (if an old format packet) is written
  * out.  Further, if using partial body lengths, this enables partial
  * body length mode on OUT.
  */
 static int
 write_header2( IOBUF out, int ctb, u32 len, int hdrlen )
 {
   if (ctb_new_format_p (ctb))
     return write_new_header( out, ctb, len, hdrlen );
 
   /* An old format packet.  Refer to RFC 4880, Section 4.2.1 to
      understand how lengths are encoded in this case.  */
 
   /* The length encoding is stored in the two least significant bits.
      Make sure they are cleared.  */
   log_assert ((ctb & 3) == 0);
 
   log_assert (hdrlen == 0 || hdrlen == 2 || hdrlen == 3 || hdrlen == 5);
 
   if (hdrlen)
     /* Header length is given.  */
     {
       if( hdrlen == 2 && len < 256 )
         /* 00 => 1 byte length.  */
 	;
       else if( hdrlen == 3 && len < 65536 )
         /* 01 => 2 byte length.  If len < 256, this is not the most
            compact encoding, but it is a correct encoding.  */
 	ctb |= 1;
       else if (hdrlen == 5)
         /* 10 => 4 byte length.  If len < 65536, this is not the most
            compact encoding, but it is a correct encoding.  */
 	ctb |= 2;
       else
         log_bug ("Can't encode length=%d in a %d byte header!\n",
                  len, hdrlen);
     }
   else
     {
       if( !len )
         /* 11 => Indeterminate length.  */
 	ctb |= 3;
       else if( len < 256 )
         /* 00 => 1 byte length.  */
 	;
       else if( len < 65536 )
         /* 01 => 2 byte length.  */
 	ctb |= 1;
       else
         /* 10 => 4 byte length.  */
 	ctb |= 2;
     }
 
   if( iobuf_put(out, ctb ) )
     return -1;
 
   if( len || hdrlen )
     {
       if( ctb & 2 )
 	{
 	  if(iobuf_put(out, len >> 24 ))
 	    return -1;
 	  if(iobuf_put(out, len >> 16 ))
 	    return -1;
 	}
 
       if( ctb & 3 )
 	if(iobuf_put(out, len >> 8 ))
 	  return -1;
 
       if( iobuf_put(out, len ) )
 	return -1;
     }
 
   return 0;
 }
 
 
 /* Write a new format header to OUT.
 
    CTB is the ctb.
 
    LEN is the length of the packet's body.  If LEN is 0, then enables
    partial body length mode (i.e., the body is of an indeterminant
    length) on OUT.  Note: this function cannot be used to generate a
    header for a zero length packet.
 
    HDRLEN is the length of the packet's header.  If HDRLEN is 0, the
    shortest encoding is chosen based on the length of the packet's
    body.  Currently, values other than 0 are not supported.
 
    Returns 0 on success.  */
 static int
 write_new_header( IOBUF out, int ctb, u32 len, int hdrlen )
 {
     if( hdrlen )
 	log_bug("can't cope with hdrlen yet\n");
 
     if( iobuf_put(out, ctb ) )
 	return -1;
     if( !len ) {
 	iobuf_set_partial_body_length_mode(out, 512 );
     }
     else {
 	if( len < 192 ) {
 	    if( iobuf_put(out, len ) )
 		return -1;
 	}
 	else if( len < 8384 ) {
 	    len -= 192;
 	    if( iobuf_put( out, (len / 256) + 192) )
 		return -1;
 	    if( iobuf_put( out, (len % 256) )  )
 		return -1;
 	}
 	else {
 	    if( iobuf_put( out, 0xff ) )
 		return -1;
 	    if( iobuf_put( out, (len >> 24)&0xff ) )
 		return -1;
 	    if( iobuf_put( out, (len >> 16)&0xff ) )
 		return -1;
 	    if( iobuf_put( out, (len >> 8)&0xff )  )
 		return -1;
 	    if( iobuf_put( out, len & 0xff ) )
 		return -1;
 	}
     }
     return 0;
 }
diff --git a/g10/encrypt.c b/g10/encrypt.c
index 4b055fd26..aba161ddd 100644
--- a/g10/encrypt.c
+++ b/g10/encrypt.c
@@ -1,1057 +1,1057 @@
 /* encrypt.c - Main encryption driver
  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
  *               2006, 2009 Free Software Foundation, Inc.
  * Copyright (C) 2016, 2022 g10 Code GmbH
  *
  * This file is part of GnuPG.
  *
  * GnuPG is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * GnuPG is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
 
 #include "gpg.h"
 #include "options.h"
 #include "packet.h"
 #include "../common/status.h"
 #include "../common/iobuf.h"
 #include "keydb.h"
 #include "../common/util.h"
 #include "main.h"
 #include "filter.h"
 #include "trustdb.h"
 #include "../common/i18n.h"
 #include "../common/status.h"
 #include "pkglue.h"
 #include "../common/compliance.h"
 
 
 static int encrypt_simple( const char *filename, int mode, int use_seskey );
 static int write_pubkey_enc_from_list (ctrl_t ctrl,
                                        PK_LIST pk_list, DEK *dek, iobuf_t out);
 
 /****************
  * Encrypt FILENAME with only the symmetric cipher.  Take input from
  * stdin if FILENAME is NULL.
  */
 int
 encrypt_symmetric (const char *filename)
 {
   return encrypt_simple( filename, 1, 0 );
 }
 
 
 /****************
  * Encrypt FILENAME as a literal data packet only. Take input from
  * stdin if FILENAME is NULL.
  */
 int
 encrypt_store (const char *filename)
 {
   return encrypt_simple( filename, 0, 0 );
 }
 
 
 /* Create an setup DEK structure and print approriate warnings.  The
  * FALLBACK_TO_3DES flag is used to handle the two different ways we
  * use this code.  PK_LIST gives the list of public keys.  Always
  * returns a DEK.  The actual session needs to be added later.  */
 static DEK *
 create_dek_with_warnings (int fallback_to_3des, pk_list_t pk_list)
 {
   DEK *dek;
 
   dek = xmalloc_secure_clear (sizeof *dek);
   if (!opt.def_cipher_algo)
     {
       /* Try to get it from the prefs.  */
       dek->algo = select_algo_from_prefs (pk_list, PREFTYPE_SYM, -1, NULL);
       if (dek->algo == -1 && fallback_to_3des)
         {
           /* The only way select_algo_from_prefs can fail here is when
            * mixing v3 and v4 keys, as v4 keys have an implicit
            * preference entry for 3DES, and the pk_list cannot be
            * empty.  In this case, use 3DES anyway as it's the safest
            * choice - perhaps the v3 key is being used in an OpenPGP
            * implementation and we know that the implementation behind
            * any v4 key can handle 3DES. */
           dek->algo = CIPHER_ALGO_3DES;
         }
       else if (dek->algo == -1)
         {
           /* Because 3DES is implicitly in the prefs, this can only
            * happen if we do not have any public keys in the list.  */
           dek->algo = DEFAULT_CIPHER_ALGO;
         }
 
       /* In case 3DES has been selected, print a warning if any key
        * does not have a preference for AES.  This should help to
        * indentify why encrypting to several recipients falls back to
        * 3DES. */
       if (opt.verbose && dek->algo == CIPHER_ALGO_3DES)
         warn_missing_aes_from_pklist (pk_list);
     }
   else
     {
       if (!opt.expert
           && (select_algo_from_prefs (pk_list, PREFTYPE_SYM,
                                       opt.def_cipher_algo, NULL)
               != opt.def_cipher_algo))
         {
           log_info(_("WARNING: forcing symmetric cipher %s (%d)"
                      " violates recipient preferences\n"),
                    openpgp_cipher_algo_name (opt.def_cipher_algo),
                    opt.def_cipher_algo);
         }
 
       dek->algo = opt.def_cipher_algo;
     }
 
   return dek;
 }
 
 
 /* *SESKEY contains the unencrypted session key ((*SESKEY)->KEY) and
    the algorithm that will be used to encrypt the contents of the SED
    packet ((*SESKEY)->ALGO).  If *SESKEY is NULL, then a random
    session key that is appropriate for DEK->ALGO is generated and
    stored there.
 
    Encrypt that session key using DEK and store the result in ENCKEY,
    which must be large enough to hold (*SESKEY)->KEYLEN + 1 bytes.  */
 void
 encrypt_seskey (DEK *dek, DEK **seskey, byte *enckey)
 {
   gcry_cipher_hd_t hd;
   byte buf[33];
 
   log_assert ( dek->keylen <= 32 );
   if (!*seskey)
     {
       *seskey=xmalloc_clear(sizeof(DEK));
       (*seskey)->algo=dek->algo;
       make_session_key(*seskey);
       /*log_hexdump( "thekey", c->key, c->keylen );*/
     }
 
   /* The encrypted session key is prefixed with a one-octet algorithm id.  */
   buf[0] = (*seskey)->algo;
   memcpy( buf + 1, (*seskey)->key, (*seskey)->keylen );
 
   /* We only pass already checked values to the following function,
      thus we consider any failure as fatal.  */
   if (openpgp_cipher_open (&hd, dek->algo, GCRY_CIPHER_MODE_CFB, 1))
     BUG ();
   if (gcry_cipher_setkey (hd, dek->key, dek->keylen))
     BUG ();
   gcry_cipher_setiv (hd, NULL, 0);
   gcry_cipher_encrypt (hd, buf, (*seskey)->keylen + 1, NULL, 0);
   gcry_cipher_close (hd);
 
   memcpy( enckey, buf, (*seskey)->keylen + 1 );
   wipememory( buf, sizeof buf ); /* burn key */
 }
 
 
 /* Shall we use the MDC?  Yes - unless rfc-2440 compatibility is
  * requested.  Must return 1 or 0. */
 int
 use_mdc (pk_list_t pk_list,int algo)
 {
   (void)pk_list;
   (void)algo;
 
   /* RFC-2440 don't has MDC - this is the only way to create a legacy
    * non-MDC encryption packet.  */
   if (RFC2440)
     return 0;
 
   return 1; /* In all other cases we use the MDC */
 }
 
 
 /* We don't want to use use_seskey yet because older gnupg versions
    can't handle it, and there isn't really any point unless we're
    making a message that can be decrypted by a public key or
    passphrase. */
 static int
 encrypt_simple (const char *filename, int mode, int use_seskey)
 {
   iobuf_t inp, out;
   PACKET pkt;
   PKT_plaintext *pt = NULL;
   STRING2KEY *s2k = NULL;
   byte enckey[33];
   int rc = 0;
   int seskeylen = 0;
   u32 filesize;
   cipher_filter_context_t cfx;
   armor_filter_context_t  *afx = NULL;
   compress_filter_context_t zfx;
   text_filter_context_t tfx;
   progress_filter_context_t *pfx;
   int do_compress = !!default_compress_algo();
 
   if (!gnupg_rng_is_compliant (opt.compliance))
     {
       rc = gpg_error (GPG_ERR_FORBIDDEN);
       log_error (_("%s is not compliant with %s mode\n"),
                  "RNG",
                  gnupg_compliance_option_string (opt.compliance));
       write_status_error ("random-compliance", rc);
       return rc;
     }
 
   pfx = new_progress_context ();
   memset( &cfx, 0, sizeof cfx);
   memset( &zfx, 0, sizeof zfx);
   memset( &tfx, 0, sizeof tfx);
   init_packet(&pkt);
 
   /* Prepare iobufs. */
   inp = iobuf_open(filename);
   if (inp)
     iobuf_ioctl (inp, IOBUF_IOCTL_NO_CACHE, 1, NULL);
   if (inp && is_secured_file (iobuf_get_fd (inp)))
     {
       iobuf_close (inp);
       inp = NULL;
       gpg_err_set_errno (EPERM);
     }
   if (!inp)
     {
       rc = gpg_error_from_syserror ();
       log_error(_("can't open '%s': %s\n"), filename? filename: "[stdin]",
                 strerror(errno) );
       release_progress_context (pfx);
       return rc;
     }
 
   handle_progress (pfx, inp, filename);
 
   if (opt.textmode)
     iobuf_push_filter( inp, text_filter, &tfx );
 
   cfx.dek = NULL;
   if ( mode )
     {
       rc = setup_symkey (&s2k, &cfx.dek);
       if (rc)
         {
           iobuf_close (inp);
           if (gpg_err_code (rc) == GPG_ERR_CIPHER_ALGO
               || gpg_err_code (rc) == GPG_ERR_DIGEST_ALGO)
             ; /* Error has already been printed.  */
           else
             log_error (_("error creating passphrase: %s\n"), gpg_strerror (rc));
           release_progress_context (pfx);
           return rc;
         }
       if (use_seskey && s2k->mode != 1 && s2k->mode != 3)
         {
           use_seskey = 0;
           log_info (_("can't use a symmetric ESK packet "
                       "due to the S2K mode\n"));
         }
 
       if ( use_seskey )
         {
           DEK *dek = NULL;  /* Dummy.  */
 
           seskeylen = openpgp_cipher_get_algo_keylen (default_cipher_algo ());
           encrypt_seskey( cfx.dek, &dek, enckey );
           xfree( cfx.dek ); cfx.dek = dek;
         }
 
       if (opt.verbose)
         log_info(_("using cipher %s\n"),
                  openpgp_cipher_algo_name (cfx.dek->algo));
 
       cfx.dek->use_mdc=use_mdc(NULL,cfx.dek->algo);
     }
 
   if (do_compress && cfx.dek && cfx.dek->use_mdc
       && is_file_compressed(filename, &rc))
     {
       if (opt.verbose)
         log_info(_("'%s' already compressed\n"), filename);
       do_compress = 0;
     }
 
   if ( rc || (rc = open_outfile (-1, filename, opt.armor? 1:0, 0, &out )))
     {
       iobuf_cancel (inp);
       xfree (cfx.dek);
       xfree (s2k);
       release_progress_context (pfx);
       return rc;
     }
 
   if ( opt.armor )
     {
       afx = new_armor_context ();
       push_armor_filter (afx, out);
     }
 
   if ( s2k )
     {
       PKT_symkey_enc *enc = xmalloc_clear( sizeof *enc + seskeylen + 1 );
       enc->version = 4;
       enc->cipher_algo = cfx.dek->algo;
       enc->s2k = *s2k;
       if ( use_seskey && seskeylen )
         {
           enc->seskeylen = seskeylen + 1; /* algo id */
           memcpy (enc->seskey, enckey, seskeylen + 1 );
         }
       pkt.pkttype = PKT_SYMKEY_ENC;
       pkt.pkt.symkey_enc = enc;
       if ((rc = build_packet( out, &pkt )))
         log_error("build symkey packet failed: %s\n", gpg_strerror (rc) );
       xfree (enc);
     }
 
   if (!opt.no_literal)
     pt = setup_plaintext_name (filename, inp);
 
   /* Note that PGP 5 has problems decrypting symmetrically encrypted
      data if the file length is in the inner packet. It works when
      only partial length headers are use.  In the past, we always used
      partial body length here, but since PGP 2, PGP 6, and PGP 7 need
      the file length, and nobody should be using PGP 5 nowadays
      anyway, this is now set to the file length.  Note also that this
      only applies to the RFC-1991 style symmetric messages, and not
      the RFC-2440 style.  PGP 6 and 7 work with either partial length
      or fixed length with the new style messages. */
 
   if ( !iobuf_is_pipe_filename (filename) && *filename && !opt.textmode )
     {
       off_t tmpsize;
       int overflow;
 
       if ( !(tmpsize = iobuf_get_filelength(inp, &overflow))
            && !overflow && opt.verbose)
         log_info(_("WARNING: '%s' is an empty file\n"), filename );
       /* We can't encode the length of very large files because
          OpenPGP uses only 32 bit for file sizes.  So if the
          size of a file is larger than 2^32 minus some bytes for
          packet headers, we switch to partial length encoding. */
       if ( tmpsize < (IOBUF_FILELENGTH_LIMIT - 65536) )
         filesize = tmpsize;
       else
         filesize = 0;
     }
   else
     filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */
 
   if (!opt.no_literal)
     {
       /* Note that PT has been initialized above in !no_literal mode.  */
       pt->timestamp = make_timestamp();
       pt->mode = opt.mimemode? 'm' : opt.textmode? 't' : 'b';
       pt->len = filesize;
       pt->new_ctb = !pt->len;
       pt->buf = inp;
       pkt.pkttype = PKT_PLAINTEXT;
       pkt.pkt.plaintext = pt;
       cfx.datalen = filesize && !do_compress ? calc_packet_length( &pkt ) : 0;
     }
   else
     {
       cfx.datalen = filesize && !do_compress ? filesize : 0;
       pkt.pkttype = 0;
       pkt.pkt.generic = NULL;
     }
 
   /* Register the cipher filter. */
   if (mode)
     iobuf_push_filter ( out, cipher_filter_cfb, &cfx );
 
   /* Register the compress filter. */
   if ( do_compress )
     {
       if (cfx.dek && cfx.dek->use_mdc)
         zfx.new_ctb = 1;
       push_compress_filter (out, &zfx, default_compress_algo());
     }
 
   /* Do the work. */
   if (!opt.no_literal)
     {
       if ( (rc = build_packet( out, &pkt )) )
         log_error("build_packet failed: %s\n", gpg_strerror (rc) );
     }
   else
     {
       /* User requested not to create a literal packet, so we copy the
          plain data.  */
     byte copy_buffer[4096];
     int  bytes_copied;
     while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1)
       if ( (rc=iobuf_write(out, copy_buffer, bytes_copied)) ) {
         log_error ("copying input to output failed: %s\n",
                    gpg_strerror (rc) );
         break;
       }
     wipememory (copy_buffer, 4096); /* burn buffer */
     }
 
   /* Finish the stuff.  */
   iobuf_close (inp);
   if (rc)
     iobuf_cancel(out);
   else
     {
       iobuf_close (out); /* fixme: check returncode */
       if (mode)
         write_status ( STATUS_END_ENCRYPTION );
     }
   if (pt)
     pt->buf = NULL;
   free_packet (&pkt, NULL);
   xfree (cfx.dek);
   xfree (s2k);
   release_armor_context (afx);
   release_progress_context (pfx);
   return rc;
 }
 
 
 gpg_error_t
 setup_symkey (STRING2KEY **symkey_s2k, DEK **symkey_dek)
 {
   int canceled;
   int defcipher;
   int s2kdigest;
 
   defcipher = default_cipher_algo ();
   if (!gnupg_cipher_is_allowed (opt.compliance, 1, defcipher,
                                 GCRY_CIPHER_MODE_CFB))
     {
       log_error (_("cipher algorithm '%s' may not be used in %s mode\n"),
 		 openpgp_cipher_algo_name (defcipher),
 		 gnupg_compliance_option_string (opt.compliance));
       return gpg_error (GPG_ERR_CIPHER_ALGO);
     }
 
   s2kdigest = S2K_DIGEST_ALGO;
   if (!gnupg_digest_is_allowed (opt.compliance, 1, s2kdigest))
     {
       log_error (_("digest algorithm '%s' may not be used in %s mode\n"),
 		 gcry_md_algo_name (s2kdigest),
 		 gnupg_compliance_option_string (opt.compliance));
       return gpg_error (GPG_ERR_DIGEST_ALGO);
     }
 
   *symkey_s2k = xmalloc_clear (sizeof **symkey_s2k);
   (*symkey_s2k)->mode = opt.s2k_mode;
   (*symkey_s2k)->hash_algo = s2kdigest;
 
   *symkey_dek = passphrase_to_dek (defcipher,
                                    *symkey_s2k, 1, 0, NULL, 0, &canceled);
   if (!*symkey_dek || !(*symkey_dek)->keylen)
     {
       xfree(*symkey_dek);
       xfree(*symkey_s2k);
       return gpg_error (canceled?GPG_ERR_CANCELED:GPG_ERR_INV_PASSPHRASE);
     }
 
   return 0;
 }
 
 
 static int
 write_symkey_enc (STRING2KEY *symkey_s2k, DEK *symkey_dek, DEK *dek,
                   iobuf_t out)
 {
   int rc, seskeylen = openpgp_cipher_get_algo_keylen (dek->algo);
 
   PKT_symkey_enc *enc;
   byte enckey[33];
   PACKET pkt;
 
   enc=xmalloc_clear(sizeof(PKT_symkey_enc)+seskeylen+1);
   encrypt_seskey(symkey_dek,&dek,enckey);
 
   enc->version = 4;
   enc->cipher_algo = opt.s2k_cipher_algo;
   enc->s2k = *symkey_s2k;
   enc->seskeylen = seskeylen + 1; /* algo id */
   memcpy( enc->seskey, enckey, seskeylen + 1 );
 
   pkt.pkttype = PKT_SYMKEY_ENC;
   pkt.pkt.symkey_enc = enc;
 
   if ((rc=build_packet(out,&pkt)))
     log_error("build symkey_enc packet failed: %s\n",gpg_strerror (rc));
 
   xfree(enc);
   return rc;
 }
 
 
 /* Check whether all encryption keys are compliant with the current
  * mode and issue respective status lines.  DEK has the info about the
  * session key and PK_LIST the list of public keys.  */
 static gpg_error_t
 check_encryption_compliance (DEK *dek, pk_list_t pk_list)
 {
   gpg_error_t err = 0;
   pk_list_t pkr;
   int compliant;
 
   if (! gnupg_cipher_is_allowed (opt.compliance, 1, dek->algo,
                                  GCRY_CIPHER_MODE_CFB))
     {
       log_error (_("cipher algorithm '%s' may not be used in %s mode\n"),
 		 openpgp_cipher_algo_name (dek->algo),
 		 gnupg_compliance_option_string (opt.compliance));
       err = gpg_error (GPG_ERR_CIPHER_ALGO);
       goto leave;
     }
 
   if (!gnupg_rng_is_compliant (opt.compliance))
     {
       err = gpg_error (GPG_ERR_FORBIDDEN);
       log_error (_("%s is not compliant with %s mode\n"),
                  "RNG",
                  gnupg_compliance_option_string (opt.compliance));
       write_status_error ("random-compliance", err);
       goto leave;
     }
 
   compliant = gnupg_cipher_is_compliant (CO_DE_VS, dek->algo,
                                          GCRY_CIPHER_MODE_CFB);
 
   for (pkr = pk_list; pkr; pkr = pkr->next)
     {
       PKT_public_key *pk = pkr->pk;
       unsigned int nbits = nbits_from_pk (pk);
 
       if (!gnupg_pk_is_compliant (opt.compliance, pk->pubkey_algo, 0,
                                   pk->pkey, nbits, NULL))
         log_info (_("WARNING: key %s is not suitable for encryption"
                     " in %s mode\n"),
                   keystr_from_pk (pk),
                   gnupg_compliance_option_string (opt.compliance));
 
       if (compliant
           && !gnupg_pk_is_compliant (CO_DE_VS, pk->pubkey_algo, 0, pk->pkey,
                                      nbits, NULL))
         compliant = 0; /* Not compliant - reset flag.  */
     }
 
   /* If we are compliant print the status for de-vs compliance.  */
   if (compliant)
     write_status_strings (STATUS_ENCRYPTION_COMPLIANCE_MODE,
                           gnupg_status_compliance_flag (CO_DE_VS),
                           NULL);
 
   /* Check whether we should fail the operation.  */
   if (opt.flags.require_compliance
       && opt.compliance == CO_DE_VS
       && !compliant)
     {
       log_error (_("operation forced to fail due to"
                    " unfulfilled compliance rules\n"));
       err = gpg_error (GPG_ERR_FORBIDDEN);
       g10_errors_seen = 1;
       goto leave;
     }
 
  leave:
   return err;
 }
 
 
 /*
  * Encrypt the file with the given userids (or ask if none is
  * supplied).  Either FILENAME or FILEFD must be given, but not both.
  * The caller may provide a checked list of public keys in
  * PROVIDED_PKS; if not the function builds a list of keys on its own.
  *
  * Note that FILEFD is currently only used by cmd_encrypt in the
  * not yet finished server.c.
  */
 int
 encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
                strlist_t remusr, int use_symkey, pk_list_t provided_keys,
                int outputfd)
 {
   iobuf_t inp = NULL;
   iobuf_t out = NULL;
   PACKET pkt;
   PKT_plaintext *pt = NULL;
   DEK *symkey_dek = NULL;
   STRING2KEY *symkey_s2k = NULL;
   int rc = 0, rc2 = 0;
   u32 filesize;
   cipher_filter_context_t cfx;
   armor_filter_context_t *afx = NULL;
   compress_filter_context_t zfx;
   text_filter_context_t tfx;
   progress_filter_context_t *pfx;
   PK_LIST pk_list;
   int do_compress;
 
   if (filefd != -1 && filename)
     return gpg_error (GPG_ERR_INV_ARG);  /* Both given.  */
 
   do_compress = !!opt.compress_algo;
 
   pfx = new_progress_context ();
   memset( &cfx, 0, sizeof cfx);
   memset( &zfx, 0, sizeof zfx);
   memset( &tfx, 0, sizeof tfx);
   init_packet(&pkt);
 
   if (use_symkey
       && (rc=setup_symkey(&symkey_s2k,&symkey_dek)))
     {
       release_progress_context (pfx);
       return rc;
     }
 
   if (provided_keys)
     pk_list = provided_keys;
   else
     {
       if ((rc = build_pk_list (ctrl, remusr, &pk_list)))
         {
           release_progress_context (pfx);
           return rc;
         }
     }
 
   /* Prepare iobufs. */
 #ifdef HAVE_W32_SYSTEM
   if (filefd == -1)
     inp = iobuf_open (filename);
   else
     {
       inp = NULL;
       gpg_err_set_errno (ENOSYS);
     }
 #else
   if (filefd == GNUPG_INVALID_FD)
     inp = iobuf_open (filename);
   else
     inp = iobuf_fdopen_nc (FD2INT(filefd), "rb");
 #endif
   if (inp)
     iobuf_ioctl (inp, IOBUF_IOCTL_NO_CACHE, 1, NULL);
   if (inp && is_secured_file (iobuf_get_fd (inp)))
     {
       iobuf_close (inp);
       inp = NULL;
       gpg_err_set_errno (EPERM);
     }
   if (!inp)
     {
       char xname[64];
 
       rc = gpg_error_from_syserror ();
       if (filefd != -1)
         snprintf (xname, sizeof xname, "[fd %d]", filefd);
       else if (!filename)
         strcpy (xname, "[stdin]");
       else
         *xname = 0;
       log_error (_("can't open '%s': %s\n"),
                  *xname? xname : filename, gpg_strerror (rc) );
       goto leave;
     }
 
   if (opt.verbose)
     log_info (_("reading from '%s'\n"), iobuf_get_fname_nonnull (inp));
 
   handle_progress (pfx, inp, filename);
 
   if (opt.textmode)
     iobuf_push_filter (inp, text_filter, &tfx);
 
   rc = open_outfile (outputfd, filename, opt.armor? 1:0, 0, &out);
   if (rc)
     goto leave;
 
   if (opt.armor)
     {
       afx = new_armor_context ();
       push_armor_filter (afx, out);
     }
 
   /* Create a session key (a DEK). */
   cfx.dek = create_dek_with_warnings (1, pk_list);
 
   /* Check compliance etc.  */
   rc = check_encryption_compliance (cfx.dek, pk_list);
   if (rc)
     goto leave;
 
   cfx.dek->use_mdc = use_mdc (pk_list,cfx.dek->algo);
 
   /* Only do the is-file-already-compressed check if we are using a
      MDC.  This forces compressed files to be re-compressed if we do
      not have a MDC to give some protection against chosen ciphertext
      attacks. */
 
   if (do_compress && cfx.dek->use_mdc && is_file_compressed(filename, &rc2))
     {
       if (opt.verbose)
         log_info(_("'%s' already compressed\n"), filename);
       do_compress = 0;
     }
   if (rc2)
     {
       rc = rc2;
       goto leave;
     }
 
   make_session_key (cfx.dek);
   if (DBG_CRYPTO)
     log_printhex (cfx.dek->key, cfx.dek->keylen, "DEK is: ");
 
   rc = write_pubkey_enc_from_list (ctrl, pk_list, cfx.dek, out);
   if (rc)
     goto leave;
 
   /* We put the passphrase (if any) after any public keys as this
      seems to be the most useful on the recipient side - there is no
      point in prompting a user for a passphrase if they have the
      secret key needed to decrypt.  */
   if(use_symkey && (rc = write_symkey_enc(symkey_s2k,symkey_dek,cfx.dek,out)))
     goto leave;
 
   if (!opt.no_literal)
     pt = setup_plaintext_name (filename, inp);
 
   /* Get the size of the file if possible, i.e., if it is a real file.  */
   if (filename && *filename
       && !iobuf_is_pipe_filename (filename) && !opt.textmode )
     {
       off_t tmpsize;
       int overflow;
 
       if ( !(tmpsize = iobuf_get_filelength(inp, &overflow))
            && !overflow && opt.verbose)
         log_info(_("WARNING: '%s' is an empty file\n"), filename );
       /* We can't encode the length of very large files because
          OpenPGP uses only 32 bit for file sizes.  So if the size
          of a file is larger than 2^32 minus some bytes for packet
          headers, we switch to partial length encoding. */
       if (tmpsize < (IOBUF_FILELENGTH_LIMIT - 65536) )
         filesize = tmpsize;
       else
         filesize = 0;
     }
   else
     filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */
 
   if (!opt.no_literal)
     {
       pt->timestamp = make_timestamp();
       pt->mode = opt.mimemode? 'm' : opt.textmode ? 't' : 'b';
       pt->len = filesize;
       pt->new_ctb = !pt->len;
       pt->buf = inp;
       pkt.pkttype = PKT_PLAINTEXT;
       pkt.pkt.plaintext = pt;
       cfx.datalen = filesize && !do_compress? calc_packet_length( &pkt ) : 0;
     }
   else
     cfx.datalen = filesize && !do_compress ? filesize : 0;
 
   /* Register the cipher filter. */
   iobuf_push_filter (out, cipher_filter_cfb, &cfx);
 
   /* Register the compress filter. */
   if (do_compress)
     {
       int compr_algo = opt.compress_algo;
 
       if (compr_algo == -1)
         {
           compr_algo = select_algo_from_prefs (pk_list, PREFTYPE_ZIP, -1, NULL);
           if (compr_algo == -1)
             compr_algo = DEFAULT_COMPRESS_ALGO;
           /* Theoretically impossible to get here since uncompressed
              is implicit.  */
         }
       else if (!opt.expert
                && select_algo_from_prefs(pk_list, PREFTYPE_ZIP,
                                          compr_algo, NULL) != compr_algo)
         {
           log_info (_("WARNING: forcing compression algorithm %s (%d)"
                       " violates recipient preferences\n"),
                     compress_algo_to_string(compr_algo), compr_algo);
         }
 
       /* Algo 0 means no compression. */
       if (compr_algo)
         {
           if (cfx.dek && cfx.dek->use_mdc)
             zfx.new_ctb = 1;
           push_compress_filter (out,&zfx,compr_algo);
         }
     }
 
   /* Do the work. */
   if (!opt.no_literal)
     {
       if ((rc = build_packet( out, &pkt )))
         log_error ("build_packet failed: %s\n", gpg_strerror (rc));
     }
   else
     {
       /* User requested not to create a literal packet, so we copy the
          plain data. */
       byte copy_buffer[4096];
       int  bytes_copied;
       while ((bytes_copied = iobuf_read (inp, copy_buffer, 4096)) != -1)
         {
           rc = iobuf_write (out, copy_buffer, bytes_copied);
           if (rc)
             {
               log_error ("copying input to output failed: %s\n",
                          gpg_strerror (rc));
               break;
             }
         }
       wipememory (copy_buffer, 4096); /* Burn the buffer. */
     }
 
   /* Finish the stuff. */
  leave:
   iobuf_close (inp);
   if (rc)
     iobuf_cancel (out);
   else
     {
       iobuf_close (out); /* fixme: check returncode */
       write_status (STATUS_END_ENCRYPTION);
     }
   if (pt)
     pt->buf = NULL;
   free_packet (&pkt, NULL);
   xfree (cfx.dek);
   xfree (symkey_dek);
   xfree (symkey_s2k);
   if (!provided_keys)
     release_pk_list (pk_list);
   release_armor_context (afx);
   release_progress_context (pfx);
   return rc;
 }
 
 
 /*
  * Filter to do a complete public key encryption.
  */
 int
 encrypt_filter (void *opaque, int control,
                 iobuf_t a, byte *buf, size_t *ret_len)
 {
   size_t size = *ret_len;
   encrypt_filter_context_t *efx = opaque;
   int rc = 0;
 
   if (control == IOBUFCTRL_UNDERFLOW) /* decrypt */
     {
       BUG(); /* not used */
     }
   else if ( control == IOBUFCTRL_FLUSH ) /* encrypt */
     {
       if ( !efx->header_okay )
         {
+          efx->header_okay = 1;
+
           efx->cfx.dek = create_dek_with_warnings (0, efx->pk_list);
 
           rc = check_encryption_compliance (efx->cfx.dek, efx->pk_list);
           if (rc)
             return rc;
 
           efx->cfx.dek->use_mdc = use_mdc (efx->pk_list,efx->cfx.dek->algo);
 
           make_session_key ( efx->cfx.dek );
           if (DBG_CRYPTO)
             log_printhex (efx->cfx.dek->key, efx->cfx.dek->keylen, "DEK is: ");
 
           rc = write_pubkey_enc_from_list (efx->ctrl,
                                            efx->pk_list, efx->cfx.dek, a);
           if (rc)
             return rc;
 
           if(efx->symkey_s2k && efx->symkey_dek)
             {
               rc=write_symkey_enc(efx->symkey_s2k,efx->symkey_dek,
                                   efx->cfx.dek,a);
               if(rc)
                 return rc;
             }
 
           iobuf_push_filter (a, cipher_filter_cfb, &efx->cfx);
-
-          efx->header_okay = 1;
         }
       rc = iobuf_write (a, buf, size);
 
     }
   else if (control == IOBUFCTRL_FREE)
     {
       xfree (efx->symkey_dek);
       xfree (efx->symkey_s2k);
     }
   else if ( control == IOBUFCTRL_DESC )
     {
       mem2str (buf, "encrypt_filter", *ret_len);
     }
   return rc;
 }
 
 
 /*
  * Write a pubkey-enc packet for the public key PK to OUT.
  */
 int
 write_pubkey_enc (ctrl_t ctrl,
                   PKT_public_key *pk, int throw_keyid, DEK *dek, iobuf_t out)
 {
   PACKET pkt;
   PKT_pubkey_enc *enc;
   int rc;
   gcry_mpi_t frame;
 
   print_pubkey_algo_note ( pk->pubkey_algo );
   enc = xmalloc_clear ( sizeof *enc );
   enc->pubkey_algo = pk->pubkey_algo;
   keyid_from_pk( pk, enc->keyid );
   enc->throw_keyid = throw_keyid;
 
   /* Okay, what's going on: We have the session key somewhere in
    * the structure DEK and want to encode this session key in an
    * integer value of n bits. pubkey_nbits gives us the number of
    * bits we have to use.  We then encode the session key in some
    * way and we get it back in the big intger value FRAME.  Then
    * we use FRAME, the public key PK->PKEY and the algorithm
    * number PK->PUBKEY_ALGO and pass it to pubkey_encrypt which
    * returns the encrypted value in the array ENC->DATA.  This
    * array has a size which depends on the used algorithm (e.g. 2
    * for Elgamal).  We don't need frame anymore because we have
    * everything now in enc->data which is the passed to
    * build_packet().  */
   frame = encode_session_key (pk->pubkey_algo, dek,
                               pubkey_nbits (pk->pubkey_algo, pk->pkey));
   rc = pk_encrypt (pk->pubkey_algo, enc->data, frame, pk, pk->pkey);
   gcry_mpi_release (frame);
   if (rc)
     log_error ("pubkey_encrypt failed: %s\n", gpg_strerror (rc) );
   else
     {
       if ( opt.verbose )
         {
           char *ustr = get_user_id_string_native (ctrl, enc->keyid);
           log_info (_("%s/%s encrypted for: \"%s\"\n"),
                     openpgp_pk_algo_name (enc->pubkey_algo),
                     openpgp_cipher_algo_name (dek->algo),
                     ustr );
           xfree (ustr);
         }
       /* And write it. */
       init_packet (&pkt);
       pkt.pkttype = PKT_PUBKEY_ENC;
       pkt.pkt.pubkey_enc = enc;
       rc = build_packet (out, &pkt);
       if (rc)
         log_error ("build_packet(pubkey_enc) failed: %s\n",
                    gpg_strerror (rc));
     }
   free_pubkey_enc(enc);
   return rc;
 }
 
 
 /*
  * Write pubkey-enc packets from the list of PKs to OUT.
  */
 static int
 write_pubkey_enc_from_list (ctrl_t ctrl, PK_LIST pk_list, DEK *dek, iobuf_t out)
 {
   if (opt.throw_keyids && (PGP6 || PGP7 || PGP8))
     {
       log_info(_("option '%s' may not be used in %s mode\n"),
                "--throw-keyids",
                gnupg_compliance_option_string (opt.compliance));
       compliance_failure();
     }
 
   for ( ; pk_list; pk_list = pk_list->next )
     {
       PKT_public_key *pk = pk_list->pk;
       int throw_keyid = (opt.throw_keyids || (pk_list->flags&1));
       int rc = write_pubkey_enc (ctrl, pk, throw_keyid, dek, out);
       if (rc)
         return rc;
     }
 
   return 0;
 }
 
 void
 encrypt_crypt_files (ctrl_t ctrl, int nfiles, char **files, strlist_t remusr)
 {
   int rc = 0;
 
   if (opt.outfile)
     {
       log_error(_("--output doesn't work for this command\n"));
       return;
     }
 
   if (!nfiles)
     {
       char line[2048];
       unsigned int lno = 0;
       while ( fgets(line, DIM(line), stdin) )
         {
           lno++;
           if (!*line || line[strlen(line)-1] != '\n')
             {
               log_error("input line %u too long or missing LF\n", lno);
               return;
             }
           line[strlen(line)-1] = '\0';
           print_file_status(STATUS_FILE_START, line, 2);
           rc = encrypt_crypt (ctrl, -1, line, remusr, 0, NULL, -1);
           if (rc)
             log_error ("encryption of '%s' failed: %s\n",
                        print_fname_stdin(line), gpg_strerror (rc) );
           write_status( STATUS_FILE_DONE );
         }
     }
   else
     {
       while (nfiles--)
         {
           print_file_status(STATUS_FILE_START, *files, 2);
           if ( (rc = encrypt_crypt (ctrl, -1, *files, remusr, 0, NULL, -1)) )
             log_error("encryption of '%s' failed: %s\n",
                       print_fname_stdin(*files), gpg_strerror (rc) );
           write_status( STATUS_FILE_DONE );
           files++;
         }
     }
 }