g10: Make sure to have the directory for trustdb.
authorNIIBE Yutaka <gniibe@fsij.org>
Fri, 12 Feb 2016 01:10:33 +0000 (10:10 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Fri, 12 Feb 2016 01:10:33 +0000 (10:10 +0900)
* g10/tdbio.c (tdbio_set_dbname): Return earlier if !CREATE.  Check
the directory and create it if none before calling take_write_lock.

--

Thanks to Marc Deslauriers for the bug report and his patch.

GnuPG-bug-id: 2246

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
g10/tdbio.c

index 3cc8bd3..79e1e83 100644 (file)
@@ -603,9 +603,10 @@ create_version_record (void)
 int
 tdbio_set_dbname (const char *new_dbname, int create, int *r_nofile)
 {
-  char *fname;
+  char *fname, *p;
   struct stat statbuf;
   static int initialized = 0;
+  int save_slash;
 
   if (!initialized)
     {
@@ -643,11 +644,48 @@ tdbio_set_dbname (const char *new_dbname, int create, int *r_nofile)
       /* OK, we have the valid trustdb.gpg already.  */
       return 0;
     }
+  else if (!create)
+    {
+      *r_nofile = 1;
+      return 0;
+    }
+
+  /* Here comes: No valid trustdb.gpg AND CREATE==1 */
+
+  /*
+   * Make sure the directory exists.  This should be done before
+   * acquiring the lock, which assumes the existence of the directory.
+   */
+  p = strrchr (fname, DIRSEP_C);
+#if HAVE_W32_SYSTEM
+  {
+    /* Windows may either have a slash or a backslash.  Take
+       care of it.  */
+    char *pp = strrchr (fname, '/');
+    if (!p || pp > p)
+      p = pp;
+  }
+#endif /*HAVE_W32_SYSTEM*/
+  assert (p);
+  save_slash = *p;
+  *p = 0;
+  if (access (fname, F_OK))
+    {
+      try_make_homedir (fname);
+      if (access (fname, F_OK))
+        log_fatal (_("%s: directory does not exist!\n"), fname);
+    }
+  *p = save_slash;
 
   take_write_lock ();
 
   if (access (fname, R_OK))
     {
+      FILE *fp;
+      TRUSTREC rec;
+      int rc;
+      mode_t oldmask;
+
 #ifdef HAVE_W32CE_SYSTEM
       /* We know how the cegcc implementation of access works ;-). */
       if (GetLastError () == ERROR_FILE_NOT_FOUND)
@@ -658,66 +696,34 @@ tdbio_set_dbname (const char *new_dbname, int create, int *r_nofile)
       if (errno != ENOENT)
         log_fatal ( _("can't access '%s': %s\n"), fname, strerror (errno));
 
-      if (!create)
-        *r_nofile = 1;
-      else
+      oldmask = umask (077);
+      if (is_secured_filename (fname))
         {
-          FILE *fp;
-          TRUSTREC rec;
-          int rc;
-          char *p = strrchr (fname, DIRSEP_C);
-          mode_t oldmask;
-          int save_slash;
-
-#if HAVE_W32_SYSTEM
-          {
-            /* Windows may either have a slash or a backslash.  Take
-               care of it.  */
-            char *pp = strrchr (fname, '/');
-            if (!p || pp > p)
-              p = pp;
-          }
-#endif /*HAVE_W32_SYSTEM*/
-          assert (p);
-          save_slash = *p;
-          *p = 0;
-          if (access (fname, F_OK))
-            {
-              try_make_homedir (fname);
-              if (access (fname, F_OK))
-                log_fatal (_("%s: directory does not exist!\n"), fname);
-           }
-          *p = save_slash;
-
-          oldmask = umask (077);
-          if (is_secured_filename (fname))
-            {
-              fp = NULL;
-              gpg_err_set_errno (EPERM);
-            }
-          else
-            fp = fopen (fname, "wb");
-          umask(oldmask);
-          if (!fp)
-            log_fatal (_("can't create '%s': %s\n"), fname, strerror (errno));
-          fclose (fp);
+          fp = NULL;
+          gpg_err_set_errno (EPERM);
+        }
+      else
+        fp = fopen (fname, "wb");
+      umask(oldmask);
+      if (!fp)
+        log_fatal (_("can't create '%s': %s\n"), fname, strerror (errno));
+      fclose (fp);
 
-          db_fd = open (db_name, O_RDWR | MY_O_BINARY);
-          if (db_fd == -1)
-            log_fatal (_("can't open '%s': %s\n"), db_name, strerror (errno));
+      db_fd = open (db_name, O_RDWR | MY_O_BINARY);
+      if (db_fd == -1)
+        log_fatal (_("can't open '%s': %s\n"), db_name, strerror (errno));
 
-          rc = create_version_record ();
-          if (rc)
-            log_fatal (_("%s: failed to create version record: %s"),
-                       fname, gpg_strerror (rc));
+      rc = create_version_record ();
+      if (rc)
+        log_fatal (_("%s: failed to create version record: %s"),
+                   fname, gpg_strerror (rc));
 
-          /* Read again to check that we are okay. */
-          if (tdbio_read_record (0, &rec, RECTYPE_VER))
-            log_fatal (_("%s: invalid trustdb created\n"), db_name);
+      /* Read again to check that we are okay. */
+      if (tdbio_read_record (0, &rec, RECTYPE_VER))
+        log_fatal (_("%s: invalid trustdb created\n"), db_name);
 
-          if (!opt.quiet)
-            log_info (_("%s: trustdb created\n"), db_name);
-       }
+      if (!opt.quiet)
+        log_info (_("%s: trustdb created\n"), db_name);
     }
 
   release_write_lock ();