gpgscm: Reduce opcode dispatch overhead.
[gnupg.git] / kbx / keybox-update.c
index 0cd50e5..dcf8b2e 100644 (file)
@@ -1,5 +1,5 @@
 /* keybox-update.c - keybox update operations
 /* keybox-update.c - keybox update operations
- *     Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2003, 2004, 2012 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
  *
  * This file is part of GnuPG.
  *
@@ -14,7 +14,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * 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 <http://www.gnu.org/licenses/>.
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
  */
 
 #include <config.h>
 #include <errno.h>
 #include <time.h>
 #include <unistd.h>
 #include <errno.h>
 #include <time.h>
 #include <unistd.h>
+#include <assert.h>
 
 #include "keybox-defs.h"
 
 #include "keybox-defs.h"
+#include "../common/sysutils.h"
+#include "../common/host2net.h"
+#include "../common/utilproto.h"
 
 #define EXTSEP_S "."
 
 
 #define EXTSEP_S "."
 
+#define FILECOPY_INSERT 1
+#define FILECOPY_DELETE 2
+#define FILECOPY_UPDATE 3
+
 
 #if !defined(HAVE_FSEEKO) && !defined(fseeko)
 
 
 #if !defined(HAVE_FSEEKO) && !defined(fseeko)
 
@@ -61,85 +69,27 @@ fseeko (FILE * stream, off_t newpos, int whence)
 #endif /* !defined(HAVE_FSEEKO) && !defined(fseeko) */
 
 
 #endif /* !defined(HAVE_FSEEKO) && !defined(fseeko) */
 
 
-
 static int
 create_tmp_file (const char *template,
                  char **r_bakfname, char **r_tmpfname, FILE **r_fp)
 static int
 create_tmp_file (const char *template,
                  char **r_bakfname, char **r_tmpfname, FILE **r_fp)
-{  
-  char *bakfname, *tmpfname;
-  
-  *r_bakfname = NULL;
-  *r_tmpfname = NULL;
-  
-# ifdef USE_ONLY_8DOT3
-  /* Here is another Windoze bug?:
-   * you cant rename("pubring.kbx.tmp", "pubring.kbx");
-   * but       rename("pubring.kbx.tmp", "pubring.aaa");
-   * works.  So we replace .kbx by .bak or .tmp
-   */
-  if (strlen (template) > 4
-      && !strcmp (template+strlen(template)-4, EXTSEP_S "kbx") )
+{
+  gpg_error_t err;
+
+  err = keybox_tmp_names (template, 0, r_bakfname, r_tmpfname);
+  if (!err)
     {
     {
-      bakfname = xtrymalloc (strlen (template) + 1);
-      if (!bakfname)
-        return gpg_error (gpg_err_code_from_errno (errno));
-      strcpy (bakfname, template);
-      strcpy (bakfname+strlen(template)-4, EXTSEP_S "bak");
-      
-      tmpfname = xtrymalloc (strlen (template) + 1);
-      if (!tmpfname)
-        {
-          gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
-          xfree (bakfname);
-          return tmperr;
-        }
-      strcpy (tmpfname,template);
-      strcpy (tmpfname + strlen (template)-4, EXTSEP_S "tmp");
-    }
-  else 
-    { /* File does not end with kbx; hmmm. */
-      bakfname = xtrymalloc ( strlen (template) + 5);
-      if (!bakfname)
-        return gpg_error (gpg_err_code_from_errno (errno));
-      strcpy (stpcpy (bakfname, template), EXTSEP_S "bak");
-      
-      tmpfname = xtrymalloc ( strlen (template) + 5);
-      if (!tmpfname)
+      *r_fp = fopen (*r_tmpfname, "wb");
+      if (!*r_fp)
         {
         {
-          gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
-          xfree (bakfname);
-          return tmperr;
+          err = gpg_error_from_syserror ();
+          xfree (*r_tmpfname);
+          *r_tmpfname = NULL;
+          xfree (*r_bakfname);
+          *r_bakfname = NULL;
         }
         }
-      strcpy (stpcpy (tmpfname, template), EXTSEP_S "tmp");
     }
     }
-# else /* Posix file names */
-  bakfname = xtrymalloc (strlen (template) + 2);
-  if (!bakfname)
-    return gpg_error (gpg_err_code_from_errno (errno));
-  strcpy (stpcpy (bakfname,template),"~");
-  
-  tmpfname = xtrymalloc ( strlen (template) + 5);
-  if (!tmpfname)
-    {
-      gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
-      xfree (bakfname);
-      return tmperr;
-    }
-  strcpy (stpcpy (tmpfname,template), EXTSEP_S "tmp");
-# endif /* Posix filename */
 
 
-  *r_fp = fopen (tmpfname, "wb");
-  if (!*r_fp)
-    {
-      gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
-      xfree (tmpfname);
-      xfree (bakfname);
-      return tmperr;
-    }
-  
-  *r_bakfname = bakfname;
-  *r_tmpfname = tmpfname;
-  return 0;
+  return err;
 }
 
 
 }
 
 
@@ -148,6 +98,7 @@ rename_tmp_file (const char *bakfname, const char *tmpfname,
                  const char *fname, int secret )
 {
   int rc=0;
                  const char *fname, int secret )
 {
   int rc=0;
+  int block = 0;
 
   /* restrict the permissions for secret keyboxs */
 #ifndef HAVE_DOSISH_SYSTEM
 
   /* restrict the permissions for secret keyboxs */
 #ifndef HAVE_DOSISH_SYSTEM
@@ -155,7 +106,7 @@ rename_tmp_file (const char *bakfname, const char *tmpfname,
 /*      { */
 /*        if (chmod (tmpfname, S_IRUSR | S_IWUSR) )  */
 /*          { */
 /*      { */
 /*        if (chmod (tmpfname, S_IRUSR | S_IWUSR) )  */
 /*          { */
-/*            log_debug ("chmod of `%s' failed: %s\n", */
+/*            log_debug ("chmod of '%s' failed: %s\n", */
 /*                       tmpfname, strerror(errno) ); */
 /*            return KEYBOX_Write_File; */
 /*     } */
 /*                       tmpfname, strerror(errno) ); */
 /*            return KEYBOX_Write_File; */
 /*     } */
@@ -163,85 +114,90 @@ rename_tmp_file (const char *bakfname, const char *tmpfname,
 #endif
 
   /* fixme: invalidate close caches (not used with stdio)*/
 #endif
 
   /* fixme: invalidate close caches (not used with stdio)*/
-/*    iobuf_ioctl (NULL, 2, 0, (char*)tmpfname ); */
-/*    iobuf_ioctl (NULL, 2, 0, (char*)bakfname ); */
-/*    iobuf_ioctl (NULL, 2, 0, (char*)fname ); */
+/*    iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)tmpfname ); */
+/*    iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)bakfname ); */
+/*    iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)fname ); */
 
 
-  /* first make a backup file except for secret keyboxs */
+  /* First make a backup file except for secret keyboxes. */
   if (!secret)
   if (!secret)
-    { 
-#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
-      remove (bakfname);
-#endif
-      if (rename (fname, bakfname) )
-        {
-          return gpg_error (gpg_err_code_from_errno (errno));
-       }
+    {
+      block = 1;
+      rc = keybox_file_rename (fname, bakfname, &block);
+      if (rc)
+        goto leave;
     }
     }
-  
-  /* then rename the file */
-#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
-  remove (fname);
-#endif
-  if (rename (tmpfname, fname) )
+
+  /* Then rename the file. */
+  rc = keybox_file_rename (tmpfname, fname, NULL);
+  if (block)
     {
     {
-      rc = gpg_error (gpg_err_code_from_errno (errno));
-      if (secret)
-        {
-/*            log_info ("WARNING: 2 files with confidential" */
-/*                       " information exists.\n"); */
-/*            log_info ("%s is the unchanged one\n", fname ); */
-/*            log_info ("%s is the new one\n", tmpfname ); */
-/*            log_info ("Please fix this possible security flaw\n"); */
-       }
-      return rc;
+      gnupg_unblock_all_signals ();
+      block = 0;
     }
     }
-  
-  return 0;
+  /* if (rc) */
+  /*   { */
+  /*     if (secret) */
+  /*       { */
+  /*         log_info ("WARNING: 2 files with confidential" */
+  /*                   " information exists.\n"); */
+  /*         log_info ("%s is the unchanged one\n", fname ); */
+  /*         log_info ("%s is the new one\n", tmpfname ); */
+  /*         log_info ("Please fix this possible security flaw\n"); */
+  /*       } */
+  /*   } */
+
+ leave:
+  if (block)
+    gnupg_unblock_all_signals ();
+  return rc;
 }
 
 
 
 }
 
 
 
-/* Perform insert/delete/update operation.
-    mode 1 = insert
-        2 = delete
-        3 = update
-*/
+/* Perform insert/delete/update operation.  MODE is one of
+   FILECOPY_INSERT, FILECOPY_DELETE, FILECOPY_UPDATE.  FOR_OPENPGP
+   indicates that this is called due to an OpenPGP keyblock change.  */
 static int
 static int
-blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob, 
-               int secret, off_t start_offset, unsigned int n_packets )
+blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
+               int secret, int for_openpgp, off_t start_offset)
 {
   FILE *fp, *newfp;
   int rc=0;
   char *bakfname = NULL;
   char *tmpfname = NULL;
 {
   FILE *fp, *newfp;
   int rc=0;
   char *bakfname = NULL;
   char *tmpfname = NULL;
-  char buffer[4096];
+  char buffer[4096];  /* (Must be at least 32 bytes) */
   int nread, nbytes;
 
   int nread, nbytes;
 
-  /* Open the source file. Because we do a rename, we have to check the 
+  /* Open the source file. Because we do a rename, we have to check the
      permissions of the file */
   if (access (fname, W_OK))
      permissions of the file */
   if (access (fname, W_OK))
-    return gpg_error (gpg_err_code_from_errno (errno));
+    return gpg_error_from_syserror ();
 
   fp = fopen (fname, "rb");
 
   fp = fopen (fname, "rb");
-  if (mode == 1 && !fp && errno == ENOENT)
-    { 
+  if (mode == FILECOPY_INSERT && !fp && errno == ENOENT)
+    {
       /* Insert mode but file does not exist:
          Create a new keybox file. */
       newfp = fopen (fname, "wb");
       if (!newfp )
       /* Insert mode but file does not exist:
          Create a new keybox file. */
       newfp = fopen (fname, "wb");
       if (!newfp )
-        return gpg_error (gpg_err_code_from_errno (errno));
+        return gpg_error_from_syserror ();
 
 
-      rc = _keybox_write_header_blob (newfp);
+      rc = _keybox_write_header_blob (newfp, for_openpgp);
       if (rc)
       if (rc)
-        return rc;
+        {
+          fclose (newfp);
+          return rc;
+        }
 
       rc = _keybox_write_blob (blob, newfp);
       if (rc)
 
       rc = _keybox_write_blob (blob, newfp);
       if (rc)
-        return rc;
+        {
+          fclose (newfp);
+          return rc;
+        }
 
       if ( fclose (newfp) )
 
       if ( fclose (newfp) )
-        return gpg_error (gpg_err_code_from_errno (errno));
+        return gpg_error_from_syserror ();
 
 /*        if (chmod( fname, S_IRUSR | S_IWUSR )) */
 /*          { */
 
 /*        if (chmod( fname, S_IRUSR | S_IWUSR )) */
 /*          { */
@@ -253,42 +209,57 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
 
   if (!fp)
     {
 
   if (!fp)
     {
-      rc = gpg_error (gpg_err_code_from_errno (errno));
+      rc = gpg_error_from_syserror ();
       goto leave;
     }
 
       goto leave;
     }
 
-  /* Create the new file. */
+  /* Create the new file.  On success NEWFP is initialized.  */
   rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp);
   if (rc)
     {
   rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp);
   if (rc)
     {
-      fclose(fp);
+      fclose (fp);
       goto leave;
     }
       goto leave;
     }
-  
+
   /* prepare for insert */
   /* prepare for insert */
-  if (mode == 1)
-    { 
-      /* Copy everything to the new file. */
+  if (mode == FILECOPY_INSERT)
+    {
+      int first_record = 1;
+
+      /* Copy everything to the new file.  If this is for OpenPGP, we
+         make sure that the openpgp flag is set in the header.  (We
+         failsafe the blob type.) */
       while ( (nread = fread (buffer, 1, DIM(buffer), fp)) > 0 )
         {
       while ( (nread = fread (buffer, 1, DIM(buffer), fp)) > 0 )
         {
+          if (first_record && for_openpgp
+              && buffer[4] == KEYBOX_BLOBTYPE_HEADER)
+            {
+              first_record = 0;
+              buffer[7] |= 0x02; /* OpenPGP data may be available.  */
+            }
+
           if (fwrite (buffer, nread, 1, newfp) != 1)
             {
           if (fwrite (buffer, nread, 1, newfp) != 1)
             {
-              rc = gpg_error (gpg_err_code_from_errno (errno));
+              rc = gpg_error_from_syserror ();
+              fclose (fp);
+              fclose (newfp);
               goto leave;
             }
         }
       if (ferror (fp))
         {
               goto leave;
             }
         }
       if (ferror (fp))
         {
-          rc = gpg_error (gpg_err_code_from_errno (errno));
+          rc = gpg_error_from_syserror ();
+          fclose (fp);
+          fclose (newfp);
           goto leave;
         }
     }
           goto leave;
         }
     }
-  
+
   /* Prepare for delete or update. */
   /* Prepare for delete or update. */
-  if ( mode == 2 || mode == 3 ) 
-    { 
+  if ( mode == FILECOPY_DELETE || mode == FILECOPY_UPDATE )
+    {
       off_t current = 0;
       off_t current = 0;
-      
+
       /* Copy first part to the new file. */
       while ( current < start_offset )
         {
       /* Copy first part to the new file. */
       while ( current < start_offset )
         {
@@ -299,61 +270,77 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
           if (!nread)
             break;
           current += nread;
           if (!nread)
             break;
           current += nread;
-          
+
           if (fwrite (buffer, nread, 1, newfp) != 1)
             {
           if (fwrite (buffer, nread, 1, newfp) != 1)
             {
-              rc = gpg_error (gpg_err_code_from_errno (errno));
+              rc = gpg_error_from_syserror ();
+              fclose (fp);
+              fclose (newfp);
               goto leave;
             }
         }
       if (ferror (fp))
         {
               goto leave;
             }
         }
       if (ferror (fp))
         {
-          rc = gpg_error (gpg_err_code_from_errno (errno));
+          rc = gpg_error_from_syserror ();
+          fclose (fp);
+          fclose (newfp);
           goto leave;
         }
           goto leave;
         }
-      
+
       /* Skip this blob. */
       rc = _keybox_read_blob (NULL, fp);
       if (rc)
       /* Skip this blob. */
       rc = _keybox_read_blob (NULL, fp);
       if (rc)
-        return rc;
+        {
+          fclose (fp);
+          fclose (newfp);
+          return rc;
+        }
     }
     }
-  
+
   /* Do an insert or update. */
   /* Do an insert or update. */
-  if ( mode == 1 || mode == 3 )
-    { 
+  if ( mode == FILECOPY_INSERT || mode == FILECOPY_UPDATE )
+    {
       rc = _keybox_write_blob (blob, newfp);
       if (rc)
       rc = _keybox_write_blob (blob, newfp);
       if (rc)
+        {
+          fclose (fp);
+          fclose (newfp);
           return rc;
           return rc;
+        }
     }
     }
-  
+
   /* Copy the rest of the packet for an delete or update. */
   /* Copy the rest of the packet for an delete or update. */
-  if (mode == 2 || mode == 3)
-    { 
+  if (mode == FILECOPY_DELETE || mode == FILECOPY_UPDATE)
+    {
       while ( (nread = fread (buffer, 1, DIM(buffer), fp)) > 0 )
         {
           if (fwrite (buffer, nread, 1, newfp) != 1)
             {
       while ( (nread = fread (buffer, 1, DIM(buffer), fp)) > 0 )
         {
           if (fwrite (buffer, nread, 1, newfp) != 1)
             {
-              rc = gpg_error (gpg_err_code_from_errno (errno));
+              rc = gpg_error_from_syserror ();
+              fclose (fp);
+              fclose (newfp);
               goto leave;
             }
         }
       if (ferror (fp))
         {
               goto leave;
             }
         }
       if (ferror (fp))
         {
-          rc = gpg_error (gpg_err_code_from_errno (errno));
+          rc = gpg_error_from_syserror ();
+          fclose (fp);
+          fclose (newfp);
           goto leave;
         }
     }
           goto leave;
         }
     }
-    
+
   /* Close both files. */
   if (fclose(fp))
     {
   /* Close both files. */
   if (fclose(fp))
     {
-      rc = gpg_error (gpg_err_code_from_errno (errno));
+      rc = gpg_error_from_syserror ();
       fclose (newfp);
       goto leave;
     }
   if (fclose(newfp))
     {
       fclose (newfp);
       goto leave;
     }
   if (fclose(newfp))
     {
-      rc = gpg_error (gpg_err_code_from_errno (errno));
+      rc = gpg_error_from_syserror ();
       goto leave;
     }
 
       goto leave;
     }
 
@@ -366,8 +353,104 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob,
 }
 
 
 }
 
 
+/* Insert the OpenPGP keyblock {IMAGE,IMAGELEN} into HD.  SIGSTATUS is
+   a vector describing the status of the signatures; its first element
+   gives the number of following elements.  */
+gpg_error_t
+keybox_insert_keyblock (KEYBOX_HANDLE hd, const void *image, size_t imagelen,
+                        u32 *sigstatus)
+{
+  gpg_error_t err;
+  const char *fname;
+  KEYBOXBLOB blob;
+  size_t nparsed;
+  struct _keybox_openpgp_info info;
+
+  if (!hd)
+    return gpg_error (GPG_ERR_INV_HANDLE);
+  if (!hd->kb)
+    return gpg_error (GPG_ERR_INV_HANDLE);
+  fname = hd->kb->fname;
+  if (!fname)
+    return gpg_error (GPG_ERR_INV_HANDLE);
+
+
+  /* Close this one otherwise we will mess up the position for a next
+     search.  Fixme: it would be better to adjust the position after
+     the write operation.  */
+  _keybox_close_file (hd);
+
+  err = _keybox_parse_openpgp (image, imagelen, &nparsed, &info);
+  if (err)
+    return err;
+  assert (nparsed <= imagelen);
+  err = _keybox_create_openpgp_blob (&blob, &info, image, imagelen,
+                                     sigstatus, hd->ephemeral);
+  _keybox_destroy_openpgp_info (&info);
+  if (!err)
+    {
+      err = blob_filecopy (FILECOPY_INSERT, fname, blob, hd->secret, 1, 0);
+      _keybox_release_blob (blob);
+      /*    if (!rc && !hd->secret && kb_offtbl) */
+      /*      { */
+      /*        update_offset_hash_table_from_kb (kb_offtbl, kb, 0); */
+      /*      } */
+    }
+  return err;
+}
+
+
+/* Update the current key at HD with the given OpenPGP keyblock in
+   {IMAGE,IMAGELEN}.  */
+gpg_error_t
+keybox_update_keyblock (KEYBOX_HANDLE hd, const void *image, size_t imagelen)
+{
+  gpg_error_t err;
+  const char *fname;
+  off_t off;
+  KEYBOXBLOB blob;
+  size_t nparsed;
+  struct _keybox_openpgp_info info;
 
 
-#ifdef KEYBOX_WITH_X509 
+  if (!hd || !image || !imagelen)
+    return gpg_error (GPG_ERR_INV_VALUE);
+  if (!hd->found.blob)
+    return gpg_error (GPG_ERR_NOTHING_FOUND);
+  if (blob_get_type (hd->found.blob) != KEYBOX_BLOBTYPE_PGP)
+    return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
+  fname = hd->kb->fname;
+  if (!fname)
+    return gpg_error (GPG_ERR_INV_HANDLE);
+
+  off = _keybox_get_blob_fileoffset (hd->found.blob);
+  if (off == (off_t)-1)
+    return gpg_error (GPG_ERR_GENERAL);
+
+  /* Close this the file so that we do no mess up the position for a
+     next search.  */
+  _keybox_close_file (hd);
+
+  /* Build a new blob.  */
+  err = _keybox_parse_openpgp (image, imagelen, &nparsed, &info);
+  if (err)
+    return err;
+  assert (nparsed <= imagelen);
+  err = _keybox_create_openpgp_blob (&blob, &info, image, imagelen,
+                                     NULL, hd->ephemeral);
+  _keybox_destroy_openpgp_info (&info);
+
+  /* Update the keyblock.  */
+  if (!err)
+    {
+      err = blob_filecopy (FILECOPY_UPDATE, fname, blob, hd->secret, 1, off);
+      _keybox_release_blob (blob);
+    }
+  return err;
+}
+
+
+
+#ifdef KEYBOX_WITH_X509
 int
 keybox_insert_cert (KEYBOX_HANDLE hd, ksba_cert_t cert,
                     unsigned char *sha1_digest)
 int
 keybox_insert_cert (KEYBOX_HANDLE hd, ksba_cert_t cert,
                     unsigned char *sha1_digest)
@@ -377,26 +460,22 @@ keybox_insert_cert (KEYBOX_HANDLE hd, ksba_cert_t cert,
   KEYBOXBLOB blob;
 
   if (!hd)
   KEYBOXBLOB blob;
 
   if (!hd)
-    return gpg_error (GPG_ERR_INV_HANDLE); 
+    return gpg_error (GPG_ERR_INV_HANDLE);
   if (!hd->kb)
   if (!hd->kb)
-    return gpg_error (GPG_ERR_INV_HANDLE); 
+    return gpg_error (GPG_ERR_INV_HANDLE);
   fname = hd->kb->fname;
   if (!fname)
   fname = hd->kb->fname;
   if (!fname)
-    return gpg_error (GPG_ERR_INV_HANDLE); 
+    return gpg_error (GPG_ERR_INV_HANDLE);
 
   /* Close this one otherwise we will mess up the position for a next
      search.  Fixme: it would be better to adjust the position after
 
   /* Close this one otherwise we will mess up the position for a next
      search.  Fixme: it would be better to adjust the position after
-     the write opertions.  */
-  if (hd->fp)
-    {
-      fclose (hd->fp);
-      hd->fp = NULL;
-    }
+     the write operation.  */
+  _keybox_close_file (hd);
 
   rc = _keybox_create_x509_blob (&blob, cert, sha1_digest, hd->ephemeral);
   if (!rc)
     {
 
   rc = _keybox_create_x509_blob (&blob, cert, sha1_digest, hd->ephemeral);
   if (!rc)
     {
-      rc = blob_filecopy (1, fname, blob, hd->secret, 0, 0 );
+      rc = blob_filecopy (FILECOPY_INSERT, fname, blob, hd->secret, 0, 0);
       _keybox_release_blob (blob);
       /*    if (!rc && !hd->secret && kb_offtbl) */
       /*      { */
       _keybox_release_blob (blob);
       /*    if (!rc && !hd->secret && kb_offtbl) */
       /*      { */
@@ -410,6 +489,9 @@ int
 keybox_update_cert (KEYBOX_HANDLE hd, ksba_cert_t cert,
                     unsigned char *sha1_digest)
 {
 keybox_update_cert (KEYBOX_HANDLE hd, ksba_cert_t cert,
                     unsigned char *sha1_digest)
 {
+  (void)hd;
+  (void)cert;
+  (void)sha1_digest;
   return -1;
 }
 
   return -1;
 }
 
@@ -430,17 +512,19 @@ keybox_set_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int value)
   const unsigned char *buffer;
   size_t length;
 
   const unsigned char *buffer;
   size_t length;
 
+  (void)idx;  /* Not yet used.  */
+
   if (!hd)
     return gpg_error (GPG_ERR_INV_VALUE);
   if (!hd->found.blob)
     return gpg_error (GPG_ERR_NOTHING_FOUND);
   if (!hd->kb)
   if (!hd)
     return gpg_error (GPG_ERR_INV_VALUE);
   if (!hd->found.blob)
     return gpg_error (GPG_ERR_NOTHING_FOUND);
   if (!hd->kb)
-    return gpg_error (GPG_ERR_INV_HANDLE); 
+    return gpg_error (GPG_ERR_INV_HANDLE);
   if (!hd->found.blob)
     return gpg_error (GPG_ERR_NOTHING_FOUND);
   fname = hd->kb->fname;
   if (!fname)
   if (!hd->found.blob)
     return gpg_error (GPG_ERR_NOTHING_FOUND);
   fname = hd->kb->fname;
   if (!fname)
-    return gpg_error (GPG_ERR_INV_HANDLE); 
+    return gpg_error (GPG_ERR_INV_HANDLE);
 
   off = _keybox_get_blob_fileoffset (hd->found.blob);
   if (off == (off_t)-1)
 
   off = _keybox_get_blob_fileoffset (hd->found.blob);
   if (off == (off_t)-1)
@@ -450,21 +534,17 @@ keybox_set_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int value)
   ec = _keybox_get_flag_location (buffer, length, what, &flag_pos, &flag_size);
   if (ec)
     return gpg_error (ec);
   ec = _keybox_get_flag_location (buffer, length, what, &flag_pos, &flag_size);
   if (ec)
     return gpg_error (ec);
-  
+
   off += flag_pos;
 
   off += flag_pos;
 
-  if (hd->fp)
-    {
-      fclose (hd->fp);
-      hd->fp = NULL;
-    }
+  _keybox_close_file (hd);
   fp = fopen (hd->kb->fname, "r+b");
   if (!fp)
   fp = fopen (hd->kb->fname, "r+b");
   if (!fp)
-    return gpg_error (gpg_err_code_from_errno (errno));
+    return gpg_error_from_syserror ();
 
   ec = 0;
   if (fseeko (fp, off, SEEK_SET))
 
   ec = 0;
   if (fseeko (fp, off, SEEK_SET))
-    ec = gpg_error (gpg_err_code_from_errno (errno));
+    ec = gpg_err_code_from_syserror ();
   else
     {
       unsigned char tmp[4];
   else
     {
       unsigned char tmp[4];
@@ -476,11 +556,11 @@ keybox_set_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int value)
 
       switch (flag_size)
         {
 
       switch (flag_size)
         {
-        case 1: 
+        case 1:
         case 2:
         case 4:
           if (fwrite (tmp+4-flag_size, flag_size, 1, fp) != 1)
         case 2:
         case 4:
           if (fwrite (tmp+4-flag_size, flag_size, 1, fp) != 1)
-            ec = gpg_err_code_from_errno (errno);
+            ec = gpg_err_code_from_syserror ();
           break;
         default:
           ec = GPG_ERR_BUG;
           break;
         default:
           ec = GPG_ERR_BUG;
@@ -491,7 +571,7 @@ keybox_set_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int value)
   if (fclose (fp))
     {
       if (!ec)
   if (fclose (fp))
     {
       if (!ec)
-        ec = gpg_err_code_from_errno (errno);
+        ec = gpg_err_code_from_syserror ();
     }
 
   return gpg_error (ec);
     }
 
   return gpg_error (ec);
@@ -512,37 +592,32 @@ keybox_delete (KEYBOX_HANDLE hd)
   if (!hd->found.blob)
     return gpg_error (GPG_ERR_NOTHING_FOUND);
   if (!hd->kb)
   if (!hd->found.blob)
     return gpg_error (GPG_ERR_NOTHING_FOUND);
   if (!hd->kb)
-    return gpg_error (GPG_ERR_INV_HANDLE); 
+    return gpg_error (GPG_ERR_INV_HANDLE);
   fname = hd->kb->fname;
   if (!fname)
   fname = hd->kb->fname;
   if (!fname)
-    return gpg_error (GPG_ERR_INV_HANDLE); 
+    return gpg_error (GPG_ERR_INV_HANDLE);
 
   off = _keybox_get_blob_fileoffset (hd->found.blob);
   if (off == (off_t)-1)
     return gpg_error (GPG_ERR_GENERAL);
   off += 4;
 
 
   off = _keybox_get_blob_fileoffset (hd->found.blob);
   if (off == (off_t)-1)
     return gpg_error (GPG_ERR_GENERAL);
   off += 4;
 
-  if (hd->fp)
-    {
-      fclose (hd->fp);
-      hd->fp = NULL;
-    }
-  
+  _keybox_close_file (hd);
   fp = fopen (hd->kb->fname, "r+b");
   if (!fp)
   fp = fopen (hd->kb->fname, "r+b");
   if (!fp)
-    return gpg_error (gpg_err_code_from_errno (errno));
+    return gpg_error_from_syserror ();
 
   if (fseeko (fp, off, SEEK_SET))
 
   if (fseeko (fp, off, SEEK_SET))
-    rc = gpg_error (gpg_err_code_from_errno (errno));
+    rc = gpg_error_from_syserror ();
   else if (putc (0, fp) == EOF)
   else if (putc (0, fp) == EOF)
-    rc = gpg_error (gpg_err_code_from_errno (errno));
+    rc = gpg_error_from_syserror ();
   else
     rc = 0;
 
   if (fclose (fp))
     {
       if (!rc)
   else
     rc = 0;
 
   if (fclose (fp))
     {
       if (!rc)
-        rc = gpg_error (gpg_err_code_from_errno (errno));
+        rc = gpg_error_from_syserror ();
     }
 
   return rc;
     }
 
   return rc;
@@ -566,32 +641,28 @@ keybox_compress (KEYBOX_HANDLE hd)
   int skipped_deleted;
 
   if (!hd)
   int skipped_deleted;
 
   if (!hd)
-    return gpg_error (GPG_ERR_INV_HANDLE); 
+    return gpg_error (GPG_ERR_INV_HANDLE);
   if (!hd->kb)
   if (!hd->kb)
-    return gpg_error (GPG_ERR_INV_HANDLE); 
+    return gpg_error (GPG_ERR_INV_HANDLE);
   if (hd->secret)
     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
   fname = hd->kb->fname;
   if (!fname)
   if (hd->secret)
     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
   fname = hd->kb->fname;
   if (!fname)
-    return gpg_error (GPG_ERR_INV_HANDLE); 
+    return gpg_error (GPG_ERR_INV_HANDLE);
 
 
-  if (hd->fp)
-    {
-      fclose (hd->fp);
-      hd->fp = NULL;
-    }
+  _keybox_close_file (hd);
 
 
-  /* Open the source file. Because we do a rename, we have to check the 
+  /* Open the source file. Because we do a rename, we have to check the
      permissions of the file */
   if (access (fname, W_OK))
      permissions of the file */
   if (access (fname, W_OK))
-    return gpg_error (gpg_err_code_from_errno (errno));
+    return gpg_error_from_syserror ();
 
   fp = fopen (fname, "rb");
   if (!fp && errno == ENOENT)
     return 0; /* Ready. File has been deleted right after the access above. */
   if (!fp)
     {
 
   fp = fopen (fname, "rb");
   if (!fp && errno == ENOENT)
     return 0; /* Ready. File has been deleted right after the access above. */
   if (!fp)
     {
-      rc = gpg_error (gpg_err_code_from_errno (errno));
+      rc = gpg_error_from_syserror ();
       return rc;
     }
 
       return rc;
     }
 
@@ -603,11 +674,10 @@ keybox_compress (KEYBOX_HANDLE hd)
       size_t length;
 
       buffer = _keybox_get_blob_image (blob, &length);
       size_t length;
 
       buffer = _keybox_get_blob_image (blob, &length);
-      if (length > 4 && buffer[4] == BLOBTYPE_HEADER)
+      if (length > 4 && buffer[4] == KEYBOX_BLOBTYPE_HEADER)
         {
         {
-          u32 last_maint = ((buffer[20] << 24) | (buffer[20+1] << 16)
-                            | (buffer[20+2] << 8) | (buffer[20+3]));
-          
+          u32 last_maint = buf32_to_u32 (buffer+20);
+
           if ( (last_maint + 3*3600) > time (NULL) )
             {
               fclose (fp);
           if ( (last_maint + 3*3600) > time (NULL) )
             {
               fclose (fp);
@@ -616,18 +686,19 @@ keybox_compress (KEYBOX_HANDLE hd)
             }
         }
       _keybox_release_blob (blob);
             }
         }
       _keybox_release_blob (blob);
-      rewind (fp);
+      fseek (fp, 0, SEEK_SET);
+      clearerr (fp);
     }
 
   /* Create the new file. */
   rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp);
   if (rc)
     {
     }
 
   /* Create the new file. */
   rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp);
   if (rc)
     {
-      fclose(fp);
+      fclose (fp);
       return rc;;
     }
 
       return rc;;
     }
 
-  
+
   /* Processing loop.  By reading using _keybox_read_blob we
      automagically skip any blobs flagged as deleted.  Thus what we
      only have to do is to check all ephemeral flagged blocks whether
   /* Processing loop.  By reading using _keybox_read_blob we
      automagically skip any blobs flagged as deleted.  Thus what we
      only have to do is to check all ephemeral flagged blocks whether
@@ -649,10 +720,12 @@ keybox_compress (KEYBOX_HANDLE hd)
       if (first_blob)
         {
           first_blob = 0;
       if (first_blob)
         {
           first_blob = 0;
-          if (length > 4 && buffer[4] == BLOBTYPE_HEADER)
+          if (length > 4 && buffer[4] == KEYBOX_BLOBTYPE_HEADER)
             {
             {
-              /* Write out the blob with an updated maintenance time stamp. */
-              _keybox_update_header_blob (blob);
+              /* Write out the blob with an updated maintenance time
+                 stamp and if needed (ie. used by gpg) set the openpgp
+                 flag.  */
+              _keybox_update_header_blob (blob, hd->for_openpgp);
               rc = _keybox_write_blob (blob, newfp);
               if (rc)
                 break;
               rc = _keybox_write_blob (blob, newfp);
               if (rc)
                 break;
@@ -660,36 +733,35 @@ keybox_compress (KEYBOX_HANDLE hd)
             }
 
           /* The header blob is missing.  Insert it.  */
             }
 
           /* The header blob is missing.  Insert it.  */
-          rc = _keybox_write_header_blob (newfp);
+          rc = _keybox_write_header_blob (newfp, hd->for_openpgp);
           if (rc)
             break;
           any_changes = 1;
         }
           if (rc)
             break;
           any_changes = 1;
         }
-      else if (length > 4 && buffer[4] == BLOBTYPE_HEADER)
+      else if (length > 4 && buffer[4] == KEYBOX_BLOBTYPE_HEADER)
         {
           /* Oops: There is another header record - remove it. */
           any_changes = 1;
           continue;
         }
 
         {
           /* Oops: There is another header record - remove it. */
           any_changes = 1;
           continue;
         }
 
-      if (_keybox_get_flag_location (buffer, length, 
+      if (_keybox_get_flag_location (buffer, length,
                                      KEYBOX_FLAG_BLOB, &pos, &size)
           || size != 2)
         {
           rc = gpg_error (GPG_ERR_BUG);
           break;
         }
                                      KEYBOX_FLAG_BLOB, &pos, &size)
           || size != 2)
         {
           rc = gpg_error (GPG_ERR_BUG);
           break;
         }
-      blobflags = ((buffer[pos] << 8) | (buffer[pos+1]));
+      blobflags = buf16_to_uint (buffer+pos);
       if ((blobflags & KEYBOX_FLAG_BLOB_EPHEMERAL))
         {
           /* This is an ephemeral blob. */
       if ((blobflags & KEYBOX_FLAG_BLOB_EPHEMERAL))
         {
           /* This is an ephemeral blob. */
-          if (_keybox_get_flag_location (buffer, length, 
+          if (_keybox_get_flag_location (buffer, length,
                                          KEYBOX_FLAG_CREATED_AT, &pos, &size)
               || size != 4)
             created_at = 0; /* oops. */
           else
                                          KEYBOX_FLAG_CREATED_AT, &pos, &size)
               || size != 4)
             created_at = 0; /* oops. */
           else
-            created_at = ((buffer[pos] << 24) | (buffer[pos+1] << 16)
-                          | (buffer[pos+2] << 8) | (buffer[pos+3]));
+            created_at = buf32_to_u32 (buffer+pos);
 
           if (created_at && created_at < cut_time)
             {
 
           if (created_at && created_at < cut_time)
             {
@@ -712,13 +784,13 @@ keybox_compress (KEYBOX_HANDLE hd)
 
   /* Close both files. */
   if (fclose(fp) && !rc)
 
   /* Close both files. */
   if (fclose(fp) && !rc)
-    rc = gpg_error (gpg_err_code_from_errno (errno));
+    rc = gpg_error_from_syserror ();
   if (fclose(newfp) && !rc)
   if (fclose(newfp) && !rc)
-    rc = gpg_error (gpg_err_code_from_errno (errno));
+    rc = gpg_error_from_syserror ();
 
   /* Rename or remove the temporary file. */
   if (rc || !any_changes)
 
   /* Rename or remove the temporary file. */
   if (rc || !any_changes)
-    remove (tmpfname);
+    gnupg_remove (tmpfname);
   else
     rc = rename_tmp_file (bakfname, tmpfname, fname, hd->secret);
 
   else
     rc = rename_tmp_file (bakfname, tmpfname, fname, hd->secret);
 
@@ -726,4 +798,3 @@ keybox_compress (KEYBOX_HANDLE hd)
   xfree(tmpfname);
   return rc;
 }
   xfree(tmpfname);
   return rc;
 }
-