gpg: Fix regression in secret key export.
[gnupg.git] / kbx / keybox-init.c
index ea95c5f..d329941 100644 (file)
@@ -1,4 +1,4 @@
-/* keybox-init.c - Initalization of the library 
+/* keybox-init.c - Initalization of the library
  *     Copyright (C) 2001 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
 #include <unistd.h>
 #include <assert.h>
 
+#include "../common/mischelp.h"
 #include "keybox-defs.h"
 
-#define compare_filenames strcmp
-
 static KB_NAME kb_names;
 
 
-/* 
-  Register a filename for plain keybox files.  Returns a pointer to be
-  used to create a handles etc or NULL to indicate that it has already
-  been registered */
+/* Register a filename for plain keybox files.  Returns a pointer to
+   be used to create a handles and so on.  Returns NULL to indicate
+   that FNAME has already been registered.  */
 void *
 keybox_register_file (const char *fname, int secret)
 {
@@ -42,8 +40,8 @@ keybox_register_file (const char *fname, int secret)
 
   for (kr=kb_names; kr; kr = kr->next)
     {
-      if ( !compare_filenames (kr->fname, fname) )
-        return NULL; /* already registered */
+      if (same_file_p (kr->fname, fname) )
+        return NULL; /* Already registered. */
     }
 
   kr = xtrymalloc (sizeof *kr + strlen (fname));
@@ -51,13 +49,17 @@ keybox_register_file (const char *fname, int secret)
     return NULL;
   strcpy (kr->fname, fname);
   kr->secret = !!secret;
+
+  kr->handle_table = NULL;
+  kr->handle_table_size = 0;
+
   /* kr->lockhd = NULL;*/
   kr->is_locked = 0;
   kr->did_full_scan = 0;
   /* keep a list of all issued pointers */
   kr->next = kb_names;
   kb_names = kr;
-  
+
   /* create the offset table the first time a function here is used */
 /*      if (!kb_offtbl) */
 /*        kb_offtbl = new_offset_hash_table (); */
@@ -73,17 +75,18 @@ keybox_is_writable (void *token)
   return r? !access (r->fname, W_OK) : 0;
 }
 
-    
+
 
 /* Create a new handle for the resource associated with TOKEN.  SECRET
    is just a cross-check.
-   
+
    The returned handle must be released using keybox_release (). */
 KEYBOX_HANDLE
 keybox_new (void *token, int secret)
 {
   KEYBOX_HANDLE hd;
   KB_NAME resource = token;
+  int idx;
 
   assert (resource && !resource->secret == !secret);
   hd = xtrycalloc (1, sizeof *hd);
@@ -91,15 +94,59 @@ keybox_new (void *token, int secret)
     {
       hd->kb = resource;
       hd->secret = !!secret;
+      if (!resource->handle_table)
+        {
+          resource->handle_table_size = 3;
+          resource->handle_table = xtrycalloc (resource->handle_table_size,
+                                               sizeof *resource->handle_table);
+          if (!resource->handle_table)
+            {
+              resource->handle_table_size = 0;
+              xfree (hd);
+              return NULL;
+            }
+        }
+      for (idx=0; idx < resource->handle_table_size; idx++)
+        if (!resource->handle_table[idx])
+          {
+            resource->handle_table[idx] = hd;
+            break;
+          }
+      if (!(idx < resource->handle_table_size))
+        {
+          KEYBOX_HANDLE *tmptbl;
+          size_t newsize;
+
+          newsize = resource->handle_table_size + 5;
+          tmptbl = xtryrealloc (resource->handle_table,
+                                newsize * sizeof (*tmptbl));
+          if (!tmptbl)
+            {
+              xfree (hd);
+              return NULL;
+            }
+          resource->handle_table = tmptbl;
+          resource->handle_table_size = newsize;
+          resource->handle_table[idx] = hd;
+          for (idx++; idx < resource->handle_table_size; idx++)
+            resource->handle_table[idx] = NULL;
+        }
     }
   return hd;
 }
 
-void 
+void
 keybox_release (KEYBOX_HANDLE hd)
 {
   if (!hd)
     return;
+  if (hd->kb->handle_table)
+    {
+      int idx;
+      for (idx=0; idx < hd->kb->handle_table_size; idx++)
+        if (hd->kb->handle_table[idx] == hd)
+          hd->kb->handle_table[idx] = NULL;
+    }
   _keybox_release_blob (hd->found.blob);
   if (hd->fp)
     {
@@ -124,8 +171,49 @@ int
 keybox_set_ephemeral (KEYBOX_HANDLE hd, int yes)
 {
   if (!hd)
-    return gpg_error (GPG_ERR_INV_HANDLE); 
+    return gpg_error (GPG_ERR_INV_HANDLE);
   hd->ephemeral = yes;
   return 0;
 }
 
+
+/* Close the file of the resource identified by HD.  For consistent
+   results this fucntion closes the files of all handles pointing to
+   the resource identified by HD.  */
+void
+_keybox_close_file (KEYBOX_HANDLE hd)
+{
+  int idx;
+  KEYBOX_HANDLE roverhd;
+
+  if (!hd || !hd->kb || !hd->kb->handle_table)
+    return;
+
+  for (idx=0; idx < hd->kb->handle_table_size; idx++)
+    if ((roverhd = hd->kb->handle_table[idx]))
+      {
+        if (roverhd->fp)
+          {
+            fclose (roverhd->fp);
+            roverhd->fp = NULL;
+          }
+      }
+  assert (!hd->fp);
+}
+
+
+/*
+ * Lock the keybox at handle HD, or unlock if YES is false.  Note that
+ * we currently ignore the handle and lock all registered keyboxes.
+ */
+int
+keybox_lock (KEYBOX_HANDLE hd, int yes)
+{
+  /* FIXME: We need to implement it before we can use it with gpg.
+     gpgsm does the locking in its local keydb.c driver; this should
+     be changed as well.  */
+
+  (void)hd;
+  (void)yes;
+  return 0;
+}