Fixed yesterday's W32 fix.
[gnupg.git] / g10 / keydb.c
index c6dbe80..3360f63 100644 (file)
@@ -1,11 +1,12 @@
 /* keydb.c - key database dispatcher
- * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005, 
+ *               2008 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 2 of the License, or
+ * 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,
@@ -14,8 +15,7 @@
  * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
@@ -28,6 +28,7 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
+#include "gpg.h"
 #include "util.h"
 #include "options.h"
 #include "main.h" /*try_make_homedir ()*/
@@ -82,6 +83,7 @@ maybe_create_keyring (char *filename, int force)
   int rc;
   mode_t oldmask;
   char *last_slash_in_filename;
+  int save_slash;
 
   /* A quick test whether the filename already exists. */
   if (!access (filename, F_OK))
@@ -90,7 +92,7 @@ maybe_create_keyring (char *filename, int force)
   /* If we don't want to create a new file at all, there is no need to
      go any further - bail out right here.  */
   if (!force) 
-    return G10ERR_OPEN_FILE;
+    return gpg_error (GPG_ERR_ENOENT);
 
   /* First of all we try to create the home directory.  Note, that we
      don't do any locking here because any sane application of gpg
@@ -98,6 +100,18 @@ maybe_create_keyring (char *filename, int force)
      tricky auto-creation which is anyway only done for some home
      directory name patterns. */
   last_slash_in_filename = strrchr (filename, DIRSEP_C);
+#if HAVE_W32_SYSTEM
+  {
+    /* Windows may either have a slash or a backslash.  Take care of it.  */
+    char *p = strrchr (filename, '/');
+    if (!last_slash_in_filename || p > last_slash_in_filename)
+      last_slash_in_filename = p;
+  }
+#endif /*HAVE_W32_SYSTEM*/
+  if (!last_slash_in_filename)
+    return gpg_error (GPG_ERR_ENOENT);  /* No slash at all - should
+                                           not happen though.  */
+  save_slash = *last_slash_in_filename;
   *last_slash_in_filename = 0;
   if (access(filename, F_OK))
     { 
@@ -110,13 +124,12 @@ maybe_create_keyring (char *filename, int force)
         }
       if (access (filename, F_OK))
         {
-          rc = G10ERR_OPEN_FILE;
-          *last_slash_in_filename = DIRSEP_C;
+          rc = gpg_error_from_syserror ();
+          *last_slash_in_filename = save_slash;
           goto leave;
         }
     }
-  *last_slash_in_filename = DIRSEP_C;
-
+  *last_slash_in_filename = save_slash;
 
   /* To avoid races with other instances of gpg trying to create or
      update the keyring (it is removed during an update for a short
@@ -132,9 +145,9 @@ maybe_create_keyring (char *filename, int force)
         log_info ("can't allocate lock for `%s'\n", filename );
 
       if (!force) 
-        return G10ERR_OPEN_FILE
+        return gpg_error (GPG_ERR_ENOENT)
       else
-        return G10ERR_GENERAL;
+        return gpg_error (GPG_ERR_GENERAL);
     }
 
   if ( make_dotlock (lockhd, -1) )
@@ -164,9 +177,9 @@ maybe_create_keyring (char *filename, int force)
   umask (oldmask);
   if (!iobuf) 
     {
+      rc = gpg_error_from_syserror ();
       log_error ( _("error creating keyring `%s': %s\n"),
                   filename, strerror(errno));
-      rc = G10ERR_OPEN_FILE;
       goto leave;
     }
 
@@ -195,7 +208,8 @@ maybe_create_keyring (char *filename, int force)
  * Note: this function may be called before secure memory is
  * available.
  * Flag 1 == force
- * Flag 2 == default
+ * Flag 2 == mark resource as primary
+ * Flag 4 == This is a default resources
  */
 int
 keydb_add_resource (const char *url, int flags, int secret)
@@ -233,7 +247,7 @@ keydb_add_resource (const char *url, int flags, int secret)
            filename = make_filename (opt.homedir, resname, NULL);
     }
     else
-       filename = m_strdup (resname);
+       filename = xstrdup (resname);
 
     if (!force)
        force = secret? !any_secret : !any_public;
@@ -305,12 +319,23 @@ keydb_add_resource (const char *url, int flags, int secret)
 
   leave:
     if (rc)
-       log_error ("keyblock resource `%s': %s\n", filename, g10_errstr(rc));
+      {
+        /* Secret keyrings are not required in all cases.  To avoid
+           having gpg return failure we use log_info here if the
+           rewsource is a secret one and marked as default
+           resource.  */
+        if ((flags&4) && secret)
+          log_info (_("keyblock resource `%s': %s\n"),
+                    filename, g10_errstr(rc));
+        else
+          log_error (_("keyblock resource `%s': %s\n"),
+                     filename, g10_errstr(rc));
+      }
     else if (secret)
        any_secret = 1;
     else
        any_public = 1;
-    m_free (filename);
+    xfree (filename);
     return rc;
 }
 
@@ -323,7 +348,7 @@ keydb_new (int secret)
   KEYDB_HANDLE hd;
   int i, j;
   
-  hd = m_alloc_clear (sizeof *hd);
+  hd = xmalloc_clear (sizeof *hd);
   hd->found = -1;
   
   assert (used_resources <= MAX_KEYDB_RESOURCES);
@@ -341,7 +366,7 @@ keydb_new (int secret)
           hd->active[j].secret = all_resources[i].secret;
           hd->active[j].u.kr = keyring_new (all_resources[i].token, secret);
           if (!hd->active[j].u.kr) {
-            m_free (hd);
+            xfree (hd);
             return NULL; /* fixme: release all previously allocated handles*/
           }
           j++;
@@ -375,7 +400,7 @@ keydb_release (KEYDB_HANDLE hd)
         }
     }
 
-    m_free (hd);
+    xfree (hd);
 }