[git] GnuPG - branch, master, updated. post-nuke-of-trailing-ws-103-g8a033fe

by Werner Koch cvs at cvs.gnupg.org
Tue Sep 27 18:06:55 CEST 2011


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU Privacy Guard".

The branch, master has been updated
       via  8a033fecfb4c73b8f7d1119272c10e64d9176bcb (commit)
       via  537be4ca47eebddd82615d6f1504aa487669536c (commit)
       via  b73ae3ca36547939c9aaf54c0d05fbc93d47c096 (commit)
       via  acde3f8ea660ced34ebe34f7d31185c9fdea8295 (commit)
      from  6cf8890dc1f551a1e87ed8b8e67a733e95b1bb6d (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 8a033fecfb4c73b8f7d1119272c10e64d9176bcb
Author: Werner Koch <wk at gnupg.org>
Date:   Tue Sep 27 17:18:56 2011 +0200

    Improved the dotlock module.
    
    - It is now more portable and may be used outside of GnuPG
    - vfat file systems are now supported.
    - The use of link(2) is more robust.
    - Wrote extensive documentation.

diff --git a/common/ChangeLog b/common/ChangeLog
index 7d80366..e0fc2dd 100644
--- a/common/ChangeLog
+++ b/common/ChangeLog
@@ -1,3 +1,11 @@
+2011-09-27  Werner Koch  <wk at g10code.com>
+
+	* dotlock.c (dotlock_take_unix): Check only the link count and not
+	the error return from link.
+	(use_hardlinks_p): New.
+	(dotlock_create_unix): Test for hardlinks.
+	(dotlock_take_unix): Implement O_EXCL locking.
+
 2011-09-23  Werner Koch  <wk at g10code.com>
 
 	* dotlock.c: Factor Unix and W32 specific code out into specific
diff --git a/common/dotlock.c b/common/dotlock.c
index 7d0ac1f..97a3f74 100644
--- a/common/dotlock.c
+++ b/common/dotlock.c
@@ -18,6 +18,172 @@
  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+/*
+   Overview:
+   =========
+
+   This module implements advisory file locking in a portable way.
+   Due to the problems with POSIX fcntl locking a separate lock file
+   is used.  It would be possible to use fcntl locking on this lock
+   file and thus avoid the weird auto unlock bug of POSIX while still
+   having an unproved better performance of fcntl locking.  However
+   there are still problems left, thus we resort to use a hardlink
+   which has the well defined property that a link call will fail if
+   the target file already exists.
+
+   Given that hardlinks are also available on NTFS file systems since
+   Windows XP; it will be possible to enhance this module to use
+   hardlinks even on Windows and thus allow Windows and Posix clients
+   to use locking on the same directory.  This is not yet implemented;
+   instead we use a lockfile on Windows along with W32 style file
+   locking.
+
+   On FAT file systems hardlinks are not supported.  Thus this method
+   does not work.  Our solution is to use a O_EXCL locking instead.
+   Querying the type of the file system is not easy to do in a
+   portable way (e.g. Linux has a statfs, BSDs have a the same call
+   but using different structures and constants).  What we do instead
+   is to check at runtime whether link(2) works for a specific lock
+   file.
+
+
+   How to use:
+   ===========
+
+   At program initialization time, the module should be explicitly
+   initialized:
+
+      dotlock_create (NULL);
+
+   This installs an atexit handler and may also initialize mutex etc.
+   It is optional for non-threaded applications.  Only the first call
+   has an effect.
+
+   To create a lock file (which  prepares it but does not take the
+   lock) you do:
+
+     dotlock_t h
+
+     h = dotlock_create (fname);
+     if (!h)
+       error ("error creating lock file: %s\n", strerror (errno));
+
+   It is important to handle the error.  For example on a read-only
+   file system a lock can't be created (but is usually not needed).
+   FNAME is the file you want to lock; the actual lockfile is that
+   name with the suffix ".lock" appended.  This call creates a unique
+   file temporary file (".#lk*") in the same directory as FNAME and
+   returns a handle for further operations.  The module keeps track of
+   theses unique files so that they will be unlinked using the atexit
+   handler.  If you don't need the lock file anymore, you may also
+   explicitly remove it with a call to:
+
+     dotlock_destroy (h);
+
+   To actually lock the file, you use:
+
+     if (dotlock_take (h, -1))
+       error ("error taking lock: %s\n", strerror (errno));
+
+   This function will wait until the lock is acquired.  If an
+   unexpected error occurs if will return non-zero and set ERRNO.  If
+   you pass (0) instead of (-1) the function does not wait if the file
+   is already locked but returns -1 and sets ERRNO to EACCES.
+
+   To release the lock you call:
+
+     if (dotlock_release (h))
+       error ("error releasing lock: %s\n", strerror (errno));
+
+   or, if the lock file is not anymore needed, you may call
+   dotlock_destroy.
+
+   If you want to explicitly destroy all lock files you may call
+
+     dotlock_remove_lockfiles ();
+
+   which is the core of the installed atexit handler.  In case your
+   application wants to disable locking completely it may call
+
+     disable_locking ()
+
+   before any locks are created.
+
+
+   How to build:
+   =============
+
+   This module was originally developed for GnuPG but later changed to
+   allow its use without any GnuPG dependency.  If you want to use it
+   with you application you may simply use it and it should figure out
+   most things automagically.
+
+   You may use the common config.h file to pass macros, but take care
+   to pass -DHAVE_CONFIG_H to the compiler.  Macros used by this
+   module are:
+
+     DOTLOCK_GLIB_LOGGING - Define this to use Glib logging functions.
+
+     GNUPG_MAJOR_VERSION - Defined when used by GnuPG.
+
+     HAVE_DOSISH_SYSTEM   - Defined for Windows etc.  Will be
+                            automatically defined if a the target is
+                            Windows.
+     HAVE_POSIX_SYSTEM    - Internally defined to !HAVE_DOSISH_SYSTEM.
+
+     HAVE_SIGNAL_H        - Should be defined on Posix systems.  If config.h
+                            is not used defaults to defined.
+
+     DIRSEP_C            - Separation character for file name parts.
+                           Usually not redefined.
+     EXTSEP_S "."        - Separation string for file name suffixes.
+                           Usually not redefined.
+
+     HAVE_W32CE_SYSTEM   - Currently only used by GnuPG.
+
+   Note that there is a test program t-dotlock which has compile
+   instructions at its end.  At least for SMBFS and CIFS it is
+   important that 64 bit versions of stat are used; most programming
+   environments do this these days, just in case you want to compile
+   it on the command line, remember to pass -D_FILE_OFFSET_BITS=64
+
+
+   Miscellaneous notes:
+   ====================
+
+   On hardlinks:
+   - Hardlinks are supported under Windows with NTFS since XP/Server2003.
+   - In Linux 2.6.33 both SMBFS and CIFS seem to support hardlinks.
+   - NFS supports hard links.  But there are solvable problems.
+   - FAT does not support links
+
+   On the file locking API:
+   - CIFS on Linux 2.6.33 supports several locking methods.
+     SMBFS seems not to support locking.  No closer checks done.
+   - NFS supports Posix locks.  flock is emulated in the server.
+     However there are a couple of problems; see below.
+   - FAT does not support locks.
+   - An advantage of fcntl locking is that R/W locks can be
+     implemented which is not easy with a straight lock file.
+
+   On O_EXCL:
+   - Does not work reliable on NFS
+   - Should work on CIFS and SMBFS but how can we delete lockfiles?
+
+   On NFS problems:
+   - Locks vanish if the server crashes and reboots.
+   - Client crashes keep the lock in the server until the client
+     re-connects.
+   - Communication problems may return unreliable error codes.  The
+     MUA Postfix's workaround is to compare the link count after
+     seeing an error for link.  However that gives a race.  If using a
+     unique file to link to a lockfile and using stat to check the
+     link count instead of looking at the error return of link(2) is
+     the best solution.
+   - O_EXCL seems to have a race and may re-create a file anyway.
+
+*/
+
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
@@ -31,9 +197,14 @@
 # define HAVE_POSIX_SYSTEM 1
 #endif
 
+/* With no config.h assume that we have sitgnal.h.  */
+#if !defined (HAVE_CONFIG_H) && defined (HAVE_POSIX_SYSTEM)
+# define HAVE_SIGNAL_H 1
+#endif
 
 /* Standard headers.  */
 #include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
 #include <errno.h>
 #include <ctype.h>
@@ -43,6 +214,8 @@
 # define WIN32_LEAN_AND_MEAN  /* We only need the OS core stuff.  */
 # include <windows.h>
 #else
+# include <sys/types.h>
+# include <sys/stat.h>
 # include <sys/utsname.h>
 #endif
 #include <sys/types.h>
@@ -53,14 +226,19 @@
 # include <signal.h>
 #endif
 
+#ifdef DOTLOCK_GLIB_LOGGING
+# include <glib.h>
+#endif
 
-#include "libjnlib-config.h"
-#include "stringhelp.h"
-#include "dotlock.h"
+#ifdef GNUPG_MAJOR_VERSION
+# include "libjnlib-config.h"
+#endif
 #ifdef HAVE_W32CE_SYSTEM
 # include "utf8conv.h"  /* WindowsCE requires filename conversion.  */
 #endif
 
+#include "dotlock.h"
+
 
 /* Define constants for file name construction.  */
 #if !defined(DIRSEP_C) && !defined(EXTSEP_S)
@@ -91,15 +269,52 @@
 # endif
 #endif
 
+/* Gettext macro replacement.  */
+#ifndef _
+# define _(a) (a)
+#endif
+
+#ifdef GNUPG_MAJOR_VERSION
+# define my_info_0(a)       log_info ((a))
+# define my_info_1(a,b)     log_info ((a), (b))
+# define my_info_2(a,b,c)   log_info ((a), (b), (c))
+# define my_info_3(a,b,c,d) log_info ((a), (b), (c), (d))
+# define my_error_0(a)      log_error ((a))
+# define my_error_1(a,b)    log_error ((a), (b))
+# define my_error_2(a,b,c)  log_error ((a), (b), (c))
+# define my_debug_1(a,b)    log_debug ((a), (b))
+#elif defined (DOTLOCK_GLIB_LOGGING)
+# define my_info_0(a)       g_message ((a))
+# define my_info_1(a,b)     g_message ((a), (b))
+# define my_info_2(a,b,c)   g_message ((a), (b), (c))
+# define my_info_3(a,b,c,d) g_message ((a), (b), (c), (d))
+# define my_error_0(a)      g_warning ((a))
+# define my_error_1(a,b)    g_warning ((a), (b))
+# define my_error_2(a,b,c   g_warning ((a), (b), (c))
+# define my_debug_1(a,b)    g_debug ((a), (b))
+#else
+# define my_info_0(a)       fprintf (stderr, (a))
+# define my_info_1(a,b)     fprintf (stderr, (a), (b))
+# define my_info_2(a,b,c)   fprintf (stderr, (a), (b), (c))
+# define my_info_3(a,b,c,d) fprintf (stderr, (a), (b), (c), (d))
+# define my_error_0(a)      fprintf (stderr, (a))
+# define my_error_1(a,b)    fprintf (stderr, (a), (b))
+# define my_error_2(a,b,c)  fprintf (stderr, (a), (b), (c))
+# define my_debug_1(a,b)    fprintf (stderr, (a), (b))
+#endif
+
+
+
 
 
 /* The object describing a lock.  */
 struct dotlock_handle
 {
   struct dotlock_handle *next;
-  char *lockname;      /* Name of the actual lockfile.          */
-  int locked;          /* Lock status.                          */
-  int disable;         /* If true, locking is disabled.         */
+  char *lockname;            /* Name of the actual lockfile.          */
+  unsigned int locked:1;     /* Lock status.                          */
+  unsigned int disable:1;    /* If true, locking is disabled.         */
+  unsigned int use_o_excl:1; /* Use open (O_EXCL) for locking.        */
 
 #ifdef HAVE_DOSISH_SYSTEM
   HANDLE lockhd;       /* The W32 handle of the lock file.      */
@@ -175,8 +390,8 @@ read_lockfile (dotlock_t h, int *same_node )
   if ( (fd = open (h->lockname, O_RDONLY)) == -1 )
     {
       int e = errno;
-      log_info ("error opening lockfile `%s': %s\n",
-                h->lockname, strerror(errno) );
+      my_info_2 ("error opening lockfile `%s': %s\n",
+                 h->lockname, strerror(errno) );
       if (buffer != buffer_space)
         jnlib_free (buffer);
       jnlib_set_errno (e); /* Need to return ERRNO here. */
@@ -192,7 +407,7 @@ read_lockfile (dotlock_t h, int *same_node )
         continue;
       if (res < 0)
         {
-          log_info ("error reading lockfile `%s'", h->lockname );
+          my_info_1 ("error reading lockfile `%s'\n", h->lockname );
           close (fd);
           if (buffer != buffer_space)
             jnlib_free (buffer);
@@ -207,7 +422,7 @@ read_lockfile (dotlock_t h, int *same_node )
 
   if (nread < 11)
     {
-      log_info ("invalid size of lockfile `%s'", h->lockname );
+      my_info_1 ("invalid size of lockfile `%s'\n", h->lockname);
       if (buffer != buffer_space)
         jnlib_free (buffer);
       jnlib_set_errno (0); /* Better don't return an inappropriate ERRNO. */
@@ -218,7 +433,7 @@ read_lockfile (dotlock_t h, int *same_node )
       || (buffer[10] = 0, pid = atoi (buffer)) == -1
       || !pid )
     {
-      log_error ("invalid pid %d in lockfile `%s'", pid, h->lockname );
+      my_error_2 ("invalid pid %d in lockfile `%s'\n", pid, h->lockname);
       if (buffer != buffer_space)
         jnlib_free (buffer);
       jnlib_set_errno (0);
@@ -237,6 +452,46 @@ read_lockfile (dotlock_t h, int *same_node )
 #endif /*HAVE_POSIX_SYSTEM */
 
 
+/* Check whether the file system which stores TNAME supports
+   hardlinks.  Instead of using the non-portable statsfs call which
+   differs between various Unix versions, we do a runtime test.
+   Returns: 0 supports hardlinks; 1 no hardlink support, -1 unknown
+   (test error).  */
+#ifdef HAVE_POSIX_SYSTEM
+static int
+use_hardlinks_p (const char *tname)
+{
+  char *lname;
+  struct stat sb;
+  unsigned int nlink;
+  int res;
+
+  if (stat (tname, &sb))
+    return -1;
+  nlink = (unsigned int)sb.st_nlink;
+
+  lname = jnlib_malloc (strlen (tname) + 1 + 1);
+  if (!lname)
+    return -1;
+  strcpy (lname, tname);
+  strcat (lname, "x");
+
+  link (tname, lname);
+
+  if (stat (tname, &sb))
+    res = -1;  /* Ooops.  */
+  else if (sb.st_nlink == nlink + 1)
+    res = 0;   /* Yeah, hardlinks are supported.  */
+  else
+    res = 1;   /* No hardlink support.  */
+
+  unlink (lname);
+  jnlib_free (lname);
+  return res;
+}
+#endif /*HAVE_POSIX_SYSTEM */
+
+
 
 #ifdef  HAVE_POSIX_SYSTEM
 /* Locking core for Unix.  It used a temporary file and the link
@@ -277,7 +532,7 @@ dotlock_create_unix (dotlock_t h, const char *file_to_lock)
   h->next = all_lockfiles;
   all_lockfiles = h;
 
-  tnamelen = dirpartlen + 6 + 30 + strlen(nodename) + 10;
+  tnamelen = dirpartlen + 6 + 30 + strlen(nodename) + 10 + 1;
   h->tname = jnlib_malloc (tnamelen + 1);
   if (!h->tname)
     {
@@ -303,7 +558,7 @@ dotlock_create_unix (dotlock_t h, const char *file_to_lock)
   if ( fd == -1 )
     {
       all_lockfiles = h->next;
-      log_error (_("failed to create temporary file `%s': %s\n"),
+      my_error_2 (_("failed to create temporary file `%s': %s\n"),
                   h->tname, strerror(errno));
       jnlib_free (h->tname);
       jnlib_free (h);
@@ -318,10 +573,25 @@ dotlock_create_unix (dotlock_t h, const char *file_to_lock)
   if ( close (fd) )
     goto write_failed;
 
+  /* Check whether we support hard links.  */
+  switch (use_hardlinks_p (h->tname))
+    {
+    case 0: /* Yes.  */
+      break;
+    case 1: /* No.  */
+      unlink (h->tname);
+      h->use_o_excl = 1;
+      break;
+    default:
+      my_error_2 ("can't check whether hardlinks are supported for `%s': %s\n",
+                  h->tname, strerror(errno));
+      goto write_failed;
+    }
+
 # ifdef _REENTRANT
   /* release mutex */
 # endif
-  h->lockname = jnlib_malloc ( strlen (file_to_lock) + 6 );
+  h->lockname = jnlib_malloc (strlen (file_to_lock) + 6 );
   if (!h->lockname)
     {
       all_lockfiles = h->next;
@@ -331,6 +601,9 @@ dotlock_create_unix (dotlock_t h, const char *file_to_lock)
       return NULL;
     }
   strcpy (stpcpy (h->lockname, file_to_lock), EXTSEP_S "lock");
+  if (h->use_o_excl)
+    my_debug_1 ("locking for `%s' done via O_EXCL\n", h->lockname);
+
   return h;
 
  write_failed:
@@ -338,7 +611,7 @@ dotlock_create_unix (dotlock_t h, const char *file_to_lock)
 # ifdef _REENTRANT
   /* fixme: release mutex */
 # endif
-  log_error ( _("error writing to `%s': %s\n"), h->tname, strerror(errno) );
+  my_error_2 (_("error writing to `%s': %s\n"), h->tname, strerror (errno));
   close (fd);
   unlink (h->tname);
   jnlib_free (h->tname);
@@ -396,7 +669,7 @@ dotlock_create_w32 (dotlock_t h, const char *file_to_lock)
   }
   if (h->lockhd == INVALID_HANDLE_VALUE)
     {
-      log_error (_("can't create `%s': %s\n"), h->lockname, w32_strerror (-1));
+      my_error_2 (_("can't create `%s': %s\n"), h->lockname, w32_strerror (-1));
       all_lockfiles = h->next;
       jnlib_free (h->lockname);
       jnlib_free (h);
@@ -471,7 +744,7 @@ dotlock_destroy_unix (dotlock_t h)
 {
   if (h->locked && h->lockname)
     unlink (h->lockname);
-  if (h->tname)
+  if (h->tname && !h->use_o_excl)
     unlink (h->tname);
   jnlib_free (h->tname);
 }
@@ -541,37 +814,95 @@ dotlock_take_unix (dotlock_t h, long timeout, int *backoff)
   const char *maybe_dead="";
   int same_node;
 
-  if ( !link(h->tname, h->lockname) )
+  if (h->use_o_excl)
     {
-      /* fixme: better use stat to check the link count */
-      h->locked = 1;
-      return 0; /* okay */
+      /* No hardlink support - use open(O_EXCL).  */
+      int fd;
+
+      do
+        {
+          jnlib_set_errno (0);
+          fd = open (h->lockname, O_WRONLY|O_CREAT|O_EXCL,
+                     S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR );
+        }
+      while (fd == -1 && errno == EINTR);
+
+      if (fd == -1 && errno == EEXIST)
+        ; /* Lock held by another process.  */
+      else if (fd == -1)
+        {
+          my_error_2 ("lock not made: open(O_EXCL) of `%s' failed: %s\n",
+                      h->lockname, strerror (errno));
+          return -1;
+        }
+      else
+        {
+          char pidstr[16];
+
+          snprintf (pidstr, sizeof pidstr, "%10d\n", (int)getpid());
+          if (write (fd, pidstr, 11 ) == 11
+              && write (fd, h->tname + h->nodename_off,h->nodename_len)
+              == h->nodename_len
+              && write (fd, "\n", 1) == 1
+              && !close (fd))
+            {
+              h->locked = 1;
+              return 0;
+            }
+          /* Write error.  */
+          my_error_2 ("lock not made: writing to `%s' failed: %s\n",
+                      h->lockname, strerror (errno));
+          close (fd);
+          unlink (h->lockname);
+          return -1;
+        }
     }
-  if ( errno != EEXIST )
+  else /* Standard method:  Use hardlinks.  */
     {
-      log_error ( "lock not made: link() failed: %s\n", strerror(errno) );
-      return -1;
+      struct stat sb;
+
+      link (h->tname, h->lockname);
+
+      if (stat (h->tname, &sb))
+        {
+          my_error_1 ("lock not made: Oops: stat of tmp file failed: %s\n",
+                      strerror (errno));
+          /* In theory this might be a severe error: It is possible
+             that link succeeded but stat failed due to changed
+             permissions.  We can't do anything about it, though.  */
+          return -1;
+        }
+
+      if (sb.st_nlink == 2)
+        {
+          h->locked = 1;
+          return 0; /* Okay.  */
+        }
     }
 
+  /* Check for stale lock files.  */
   if ( (pid = read_lockfile (h, &same_node)) == -1 )
     {
       if ( errno != ENOENT )
         {
-          log_info ("cannot read lockfile\n");
+          my_info_0 ("cannot read lockfile\n");
           return -1;
         }
-      log_info( "lockfile disappeared\n");
+      my_info_0 ("lockfile disappeared\n");
       return 1; /* Try again.  */
     }
   else if ( pid == getpid() && same_node )
     {
-      log_info( "Oops: lock already held by us\n");
+      my_info_0 ("Oops: lock already held by us\n");
       h->locked = 1;
       return 0; /* okay */
     }
   else if ( same_node && kill (pid, 0) && errno == ESRCH )
     {
-      log_info (_("removing stale lockfile (created by %d)\n"), pid );
+      /* Note: It is unlikley that we get a race here unless a pid is
+         reused too fast or a new process with the same pid as the one
+         of the stale file tries to lock right at the same time as we.  */
+      my_info_1 (_("removing stale lockfile (created by %d)\n"), pid);
       unlink (h->lockname);
       return 1; /* Try again.  */
     }
@@ -581,8 +912,8 @@ dotlock_take_unix (dotlock_t h, long timeout, int *backoff)
       /* Wait until lock has been released. */
       struct timeval tv;
 
-      log_info (_("waiting for lock (held by %d%s) %s...\n"),
-                pid, maybe_dead, maybe_deadlock(h)? _("(deadlock?) "):"");
+      my_info_3 (_("waiting for lock (held by %d%s) %s...\n"),
+                 pid, maybe_dead, maybe_deadlock(h)? _("(deadlock?) "):"");
 
       /* We can't use sleep, cause signals may be blocked. */
       tv.tv_sec = 1 + *backoff;
@@ -620,15 +951,15 @@ dotlock_take_w32 (dotlock_t h, long timeout, int *backoff)
   w32err = GetLastError ();
   if (w32err != ERROR_LOCK_VIOLATION)
     {
-      log_error (_("lock `%s' not made: %s\n"),
-                 h->lockname, w32_strerror (w32err));
+      my_error_2 (_("lock `%s' not made: %s\n"),
+                  h->lockname, w32_strerror (w32err));
       return -1;
     }
 
   if ( timeout == -1 )
     {
       /* Wait until lock has been released. */
-      log_info (_("waiting for lock %s...\n"), h->lockname);
+      my_info_1 (_("waiting for lock %s...\n"), h->lockname);
       Sleep ((1 + *backoff)*1000);
       if ( *backoff < 10 )
         ++*backoff;
@@ -655,7 +986,7 @@ dotlock_take (dotlock_t h, long timeout)
 
   if ( h->locked )
     {
-      log_debug ("Oops, `%s' is already locked\n", h->lockname);
+      my_debug_1 ("Oops, `%s' is already locked\n", h->lockname);
       return 0;
     }
 
@@ -684,19 +1015,19 @@ dotlock_release_unix (dotlock_t h)
   pid = read_lockfile (h, &same_node);
   if ( pid == -1 )
     {
-      log_error( "release_dotlock: lockfile error\n");
+      my_error_0 ("release_dotlock: lockfile error\n");
       return -1;
     }
   if ( pid != getpid() || !same_node )
     {
-      log_error( "release_dotlock: not our lock (pid=%d)\n", pid);
+      my_error_1 ("release_dotlock: not our lock (pid=%d)\n", pid);
       return -1;
     }
 
   if ( unlink( h->lockname ) )
     {
-      log_error ("release_dotlock: error removing lockfile `%s'\n",
-                 h->lockname);
+      my_error_1 ("release_dotlock: error removing lockfile `%s'\n",
+                  h->lockname);
       return -1;
     }
   /* Fixme: As an extra check we could check whether the link count is
@@ -716,8 +1047,8 @@ dotlock_release_w32 (dotlock_t h)
   memset (&ovl, 0, sizeof ovl);
   if (!UnlockFileEx (h->lockhd, 0, 1, 0, &ovl))
     {
-      log_error ("release_dotlock: error removing lockfile `%s': %s\n",
-                 h->lockname, w32_strerror (-1));
+      my_error_2 ("release_dotlock: error removing lockfile `%s': %s\n",
+                  h->lockname, w32_strerror (-1));
       return -1;
     }
 
@@ -744,7 +1075,7 @@ dotlock_release (dotlock_t h)
 
   if ( !h->locked )
     {
-      log_debug("Oops, `%s' is not locked\n", h->lockname);
+      my_debug_1 ("Oops, `%s' is not locked\n", h->lockname);
       return 0;
     }
 
diff --git a/common/dotlock.h b/common/dotlock.h
index 276a6cd..5fb7891 100644
--- a/common/dotlock.h
+++ b/common/dotlock.h
@@ -1,5 +1,5 @@
-/* dotlock.h - dotfile locking
- *	Copyright (C) 2000, 2001, 2006, 2011 Free Software Foundation, Inc.
+/* dotlock.h - dotfile locking declarations
+ * Copyright (C) 2000, 2001, 2006, 2011 Free Software Foundation, Inc.
  *
  * This file is part of JNLIB, which is a subsystem of GnuPG.
  *
@@ -20,6 +20,8 @@
 #ifndef LIBJNLIB_DOTLOCK_H
 #define LIBJNLIB_DOTLOCK_H
 
+/* See dotlock.c for a description.  */
+
 struct dotlock_handle;
 typedef struct dotlock_handle *dotlock_t;
 
diff --git a/common/t-dotlock.c b/common/t-dotlock.c
new file mode 100644
index 0000000..a352f6e
--- /dev/null
+++ b/common/t-dotlock.c
@@ -0,0 +1,145 @@
+/* t-dotlock.c - Module test for dotlock.c
+ * Copyright (C) 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 <http://www.gnu.org/licenses/>.
+ */
+
+/* Note: This is a standalone test program which does not rely on any
+   GnuPG helper files.  However, it may also be build as part of the
+   GnuPG build system.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Some quick replacements for stuff we usually expect to be defined
+   in config.h.  Define HAVE_POSIX_SYSTEM for better readability. */
+#if !defined (HAVE_DOSISH_SYSTEM) && defined(_WIN32)
+# define HAVE_DOSISH_SYSTEM 1
+#endif
+#if !defined (HAVE_DOSISH_SYSTEM) && !defined (HAVE_POSIX_SYSTEM)
+# define HAVE_POSIX_SYSTEM 1
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include "dotlock.h"
+
+#define PGM "t-dotlock"
+
+
+static volatile int ctrl_c_pending;
+
+static void
+control_c_handler (int signo)
+{
+  (void)signo;
+  ctrl_c_pending = 1;
+}
+
+
+
+static void
+die (const char *format, ...)
+{
+  va_list arg_ptr;
+
+  va_start (arg_ptr, format);
+  fprintf (stderr, PGM "[%lu]: ", (unsigned long)getpid ());
+  vfprintf (stderr, format, arg_ptr);
+  putc ('\n', stderr);
+  va_end (arg_ptr);
+  exit (1);
+}
+
+
+static void
+inf (const char *format, ...)
+{
+  va_list arg_ptr;
+
+  va_start (arg_ptr, format);
+  fprintf (stderr, PGM "[%lu]: ", (unsigned long)getpid ());
+  vfprintf (stderr, format, arg_ptr);
+  putc ('\n', stderr);
+  va_end (arg_ptr);
+}
+
+
+static void
+lock_and_unlock (const char *fname)
+{
+  dotlock_t h;
+
+  h = dotlock_create (fname);
+  if (!h)
+    die ("error creating lock file for `%s': %s", fname, strerror (errno));
+  inf ("lock created");
+
+  while (!ctrl_c_pending)
+    {
+      if (dotlock_take (h, -1))
+        die ("error taking lock");
+      inf ("lock taken");
+      sleep (1);
+      if (dotlock_release (h))
+        die ("error releasing lock");
+      inf ("lock released");
+      sleep (1);
+    }
+  dotlock_destroy (h);
+  inf ("lock destroyed");
+}
+
+
+int
+main (int argc, char **argv)
+{
+  const char *fname;
+
+  if (argc > 1)
+    fname = argv[1];
+  else
+    fname = "t-dotlock.tmp";
+
+  {
+    struct sigaction nact;
+
+    nact.sa_handler = control_c_handler;
+    nact.sa_flags = 0;
+    sigaction (SIGINT, &nact, NULL);
+  }
+
+  dotlock_create (NULL);  /* Initialize (optional).  */
+
+  lock_and_unlock (fname);
+
+
+  return 0;
+}
+
+
+/*
+Local Variables:
+compile-command: "cc -Wall -O2 -D_FILE_OFFSET_BITS=64 -o t-dotlock t-dotlock.c dotlock.c"
+End:
+*/

commit 537be4ca47eebddd82615d6f1504aa487669536c
Author: Werner Koch <wk at gnupg.org>
Date:   Tue Sep 27 17:17:06 2011 +0200

    Remove check for gcry_kdf_derive
    
    This is not anymore required because we require Libgcrypt 1.5.0 which
    features this function.

diff --git a/ChangeLog b/ChangeLog
index 475aa0c..bd02016 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2011-09-23  Werner Koch  <wk at g10code.com>
+
+	* configure.ac: Remove check for gcry_kdf_derive.
+
 2011-08-10  Werner Koch  <wk at g10code.com>
 
 	* configure.ac: Fix new autoconf warnings.
diff --git a/configure.ac b/configure.ac
index 69c2370..f71b9e8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -742,21 +742,6 @@ AM_PATH_GPG_ERROR("$NEED_GPG_ERROR_VERSION",
 AM_PATH_LIBGCRYPT("$NEED_LIBGCRYPT_API:$NEED_LIBGCRYPT_VERSION",
         have_libgcrypt=yes,have_libgcrypt=no)
 
-# FIxme: Remove this test after libgcrypt 1.5.0 has been released.
-AC_CACHE_CHECK([whether Libgcrypt has gcry_kdf_derive],
-                gnupg_cv_gcry_kdf_derive,
-               [ _gnupg_gcry_save_cflags=$CFLAGS
-                 _gnupg_gcry_save_libs=$LIBS
-                 CFLAGS="$CFLAGS $LIBGCRYPT_CFLAGS"
-                 LIBS="$LIBS $LIBGCRYPT_LIBS"
-                 AC_TRY_LINK(
-                   [#include <gcrypt.h>],
-                   [ return gcry_kdf_derive (NULL,0,0,0,NULL,0,0,0,NULL); ],
-                   gnupg_cv_gcry_kdf_derive=yes,
-                   gnupg_cv_gcry_kdf_derive=no)
-                 LIBS=$_gnupg_gcry_save_libs
-                 CFLAGS=$_gnupg_gcry_save_cflags])
-
 
 #
 # libassuan is used for IPC
@@ -1621,15 +1606,15 @@ if test "$have_libgcrypt" = "no"; then
 ***   ftp://ftp.gnupg.org/gcrypt/alpha/libgcrypt/
 *** (at least version $NEED_LIBGCRYPT_VERSION using API $NEED_LIBGCRYPT_API is required.)
 ***]])
-elif test "$gnupg_cv_gcry_kdf_derive" = no; then
-   die=yes
-   AC_MSG_NOTICE([[
-***
-*** Libgcrypt 1.5.0 has not yet been released and thus the API
-*** is a bit in a flux.  Your version misses the function
-***        gcry_kdf_derive
-*** You need to install a newer Libgcrypt version.
-***]])
+dnl elif test "$gnupg_cv_gcry_kdf_derive" = no; then
+dnl    die=yes
+dnl    AC_MSG_NOTICE([[
+dnl ***
+dnl *** Libgcrypt 1.5.0 has not yet been released and thus the API
+dnl *** is a bit in a flux.  Your version misses the function
+dnl ***        gcry_kdf_derive
+dnl *** You need to install a newer Libgcrypt version.
+dnl #***]])
 fi
 if test "$have_libassuan" = "no"; then
    die=yes

commit b73ae3ca36547939c9aaf54c0d05fbc93d47c096
Author: Werner Koch <wk at gnupg.org>
Date:   Fri Sep 23 14:43:58 2011 +0200

    Renamed the lock functions.
    
    Also cleaned up the dotlock code for easier readability.

diff --git a/common/ChangeLog b/common/ChangeLog
index 95aef65..7d80366 100644
--- a/common/ChangeLog
+++ b/common/ChangeLog
@@ -1,3 +1,17 @@
+2011-09-23  Werner Koch  <wk at g10code.com>
+
+	* dotlock.c: Factor Unix and W32 specific code out into specific
+	functions.  Define HAVE_POSIX_SYSTEM.  Rearrange some functions.
+	(disable_dotlock): Rename to dotlock_disable.
+	(create_dotlock): Rename to dotlock_create.
+	(destroy_dotlock): Rename to dotlock_destroy.
+	(make_dotlock): Rename to dotlock_take.
+	(release_dotlock): Rename to dotlock_release.
+
+2011-09-22  Werner Koch  <wk at g10code.com>
+
+	* dotlock.c: Remove support for RISCOS.
+
 2011-08-10  Werner Koch  <wk at g10code.com>
 
 	* t-exechelp.c (test_close_all_fds): Don't use the DUMMY_FD var.
@@ -2394,7 +2408,7 @@
 
 
  Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
-	   2009, 2010 Free Software Foundation, Inc.
+	   2009, 2010, 2011 Free Software Foundation, Inc.
 
  This file is free software; as a special exception the author gives
  unlimited permission to copy and/or distribute it, with or without
diff --git a/common/asshelp.c b/common/asshelp.c
index c5d5a33..96d9a24 100644
--- a/common/asshelp.c
+++ b/common/asshelp.c
@@ -287,14 +287,14 @@ lock_spawning (lock_spawn_t *lock, const char *homedir, const char *name,
   if (!fname)
     return gpg_error_from_syserror ();
 
-  *lock = create_dotlock (fname);
+  *lock = dotlock_create (fname);
   xfree (fname);
   if (!*lock)
     return gpg_error_from_syserror ();
 
   /* FIXME: We should use a timeout of 5000 here - however
      make_dotlock does not yet support values other than -1 and 0.  */
-  if (make_dotlock (*lock, -1))
+  if (dotlock_take (*lock, -1))
     return gpg_error_from_syserror ();
 
   return 0;
@@ -315,7 +315,7 @@ unlock_spawning (lock_spawn_t *lock, const char *name)
       CloseHandle (*lock);
 #else /*!HAVE_W32_SYSTEM*/
       (void)name;
-      destroy_dotlock (*lock);
+      dotlock_destroy (*lock);
 #endif /*!HAVE_W32_SYSTEM*/
       *lock = NULL;
     }
diff --git a/common/dotlock.c b/common/dotlock.c
index 658e05f..7d0ac1f 100644
--- a/common/dotlock.c
+++ b/common/dotlock.c
@@ -1,6 +1,6 @@
 /* dotlock.c - dotfile locking
  * Copyright (C) 1998, 2000, 2001, 2003, 2004,
- *               2005, 2006, 2008, 2010,2011 Free Software Foundation, Inc.
+ *               2005, 2006, 2008, 2010, 2011 Free Software Foundation, Inc.
  *
  * This file is part of JNLIB, which is a subsystem of GnuPG.
  *
@@ -18,7 +18,21 @@
  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <config.h>
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Some quick replacements for stuff we usually expect to be defined
+   in config.h.  Define HAVE_POSIX_SYSTEM for better readability. */
+#if !defined (HAVE_DOSISH_SYSTEM) && defined(_WIN32)
+# define HAVE_DOSISH_SYSTEM 1
+#endif
+#if !defined (HAVE_DOSISH_SYSTEM) && !defined (HAVE_POSIX_SYSTEM)
+# define HAVE_POSIX_SYSTEM 1
+#endif
+
+
+/* Standard headers.  */
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
@@ -26,7 +40,7 @@
 #include <errno.h>
 #include <unistd.h>
 #ifdef  HAVE_DOSISH_SYSTEM
-# define WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN  /* We only need the OS core stuff.  */
 # include <windows.h>
 #else
 # include <sys/utsname.h>
@@ -39,27 +53,46 @@
 # include <signal.h>
 #endif
 
+
 #include "libjnlib-config.h"
 #include "stringhelp.h"
 #include "dotlock.h"
-#include "utf8conv.h"
+#ifdef HAVE_W32CE_SYSTEM
+# include "utf8conv.h"  /* WindowsCE requires filename conversion.  */
+#endif
 
-#if !defined(DIRSEP_C) && !defined(EXTSEP_C) \
-    && !defined(DIRSEP_S) && !defined(EXTSEP_S)
-#ifdef HAVE_DOSISH_SYSTEM
-#define DIRSEP_C '\\'
-#define EXTSEP_C '.'
-#define DIRSEP_S "\\"
-#define EXTSEP_S "."
+
+/* Define constants for file name construction.  */
+#if !defined(DIRSEP_C) && !defined(EXTSEP_S)
+# ifdef HAVE_DOSISH_SYSTEM
+#  define DIRSEP_C '\\'
+#  define EXTSEP_S "."
 #else
-#define DIRSEP_C '/'
-#define EXTSEP_C '.'
-#define DIRSEP_S "/"
-#define EXTSEP_S "."
+#  define DIRSEP_C '/'
+#  define EXTSEP_S "."
+# endif
+#endif
+
+/* In GnuPG we use wrappers around the malloc fucntions.  If they are
+   not defined we assume that this code is used outside of GnuPG and
+   fall back to the regular malloc functions.  */
+#ifndef jnlib_malloc
+# define jnlib_malloc(a)     malloc ((a))
+# define jnlib_calloc(a,b)   calloc ((a), (b))
+# define jnlib_free(a)	     free ((a))
 #endif
+
+/* Wrapper to set ERRNO.  */
+#ifndef jnlib_set_errno
+# ifdef HAVE_W32CE_SYSTEM
+#  define jnlib_set_errno(e)  gpg_err_set_errno ((e))
+# else
+#  define jnlib_set_errno(e)  do { errno = (e); } while (0)
+# endif
 #endif
 
 
+
 /* The object describing a lock.  */
 struct dotlock_handle
 {
@@ -86,87 +119,138 @@ static volatile dotlock_t all_lockfiles;
 static int never_lock;
 
 
-/* Local protototypes.  */
-#ifndef HAVE_DOSISH_SYSTEM
-static int read_lockfile (dotlock_t h, int *same_node);
-#endif /*!HAVE_DOSISH_SYSTEM*/
-
-
-
 
 /* Entirely disable all locking.  This function should be called
    before any locking is done.  It may be called right at startup of
    the process as it only sets a global value.  */
 void
-disable_dotlock(void)
+dotlock_disable (void)
 {
   never_lock = 1;
 }
 
 
+#ifdef HAVE_POSIX_SYSTEM
+static int
+maybe_deadlock (dotlock_t h)
+{
+  dotlock_t r;
 
-/* Create a lockfile for a file name FILE_TO_LOCK and returns an
-   object of type dotlock_t which may be used later to actually acquire
-   the lock.  A cleanup routine gets installed to cleanup left over
-   locks or other files used internally by the lock mechanism.
-
-   Calling this function with NULL does only install the atexit
-   handler and may thus be used to assure that the cleanup is called
-   after all other atexit handlers.
+  for ( r=all_lockfiles; r; r = r->next )
+    {
+      if ( r != h && r->locked )
+        return 1;
+    }
+  return 0;
+}
+#endif /*HAVE_POSIX_SYSTEM*/
 
-   This function creates a lock file in the same directory as
-   FILE_TO_LOCK using that name and a suffix of ".lock".  Note that on
-   POSIX systems a temporary file ".#lk.<hostname>.pid[.threadid] is
-   used.
 
-   The function returns an new handle which needs to be released using
-   destroy_dotlock but gets also released at the termination of the
-   process.  On error NULL is returned.
- */
-dotlock_t
-create_dotlock (const char *file_to_lock)
+/* Read the lock file and return the pid, returns -1 on error.  True
+   will be stored in the integer at address SAME_NODE if the lock file
+   has been created on the same node. */
+#ifdef HAVE_POSIX_SYSTEM
+static int
+read_lockfile (dotlock_t h, int *same_node )
 {
-  static int initialized;
-  dotlock_t h;
-#ifndef  HAVE_DOSISH_SYSTEM
-  int  fd = -1;
-  char pidstr[16];
-  const char *nodename;
-  const char *dirpart;
-  int dirpartlen;
-  struct utsname utsbuf;
-  size_t tnamelen;
-#endif
+  char buffer_space[10+1+70+1]; /* 70 is just an estimated value; node
+                                   names are usually shorter. */
+  int fd;
+  int pid = -1;
+  char *buffer, *p;
+  size_t expected_len;
+  int res, nread;
 
-  if ( !initialized )
+  *same_node = 0;
+  expected_len = 10 + 1 + h->nodename_len + 1;
+  if ( expected_len >= sizeof buffer_space)
     {
-      atexit (dotlock_remove_lockfiles);
-      initialized = 1;
+      buffer = jnlib_malloc (expected_len);
+      if (!buffer)
+        return -1;
     }
+  else
+    buffer = buffer_space;
 
-  if ( !file_to_lock )
-    return NULL;  /* Only initialization was requested.  */
+  if ( (fd = open (h->lockname, O_RDONLY)) == -1 )
+    {
+      int e = errno;
+      log_info ("error opening lockfile `%s': %s\n",
+                h->lockname, strerror(errno) );
+      if (buffer != buffer_space)
+        jnlib_free (buffer);
+      jnlib_set_errno (e); /* Need to return ERRNO here. */
+      return -1;
+    }
 
-  h = jnlib_calloc (1, sizeof *h);
-  if (!h)
-    return NULL;
+  p = buffer;
+  nread = 0;
+  do
+    {
+      res = read (fd, p, expected_len - nread);
+      if (res == -1 && errno == EINTR)
+        continue;
+      if (res < 0)
+        {
+          log_info ("error reading lockfile `%s'", h->lockname );
+          close (fd);
+          if (buffer != buffer_space)
+            jnlib_free (buffer);
+          jnlib_set_errno (0); /* Do not return an inappropriate ERRNO. */
+          return -1;
+        }
+      p += res;
+      nread += res;
+    }
+  while (res && nread != expected_len);
+  close(fd);
 
-  if (never_lock)
+  if (nread < 11)
     {
-      h->disable = 1;
-#ifdef _REENTRANT
-      /* fixme: aquire mutex on all_lockfiles */
-#endif
-      h->next = all_lockfiles;
-      all_lockfiles = h;
-      return h;
+      log_info ("invalid size of lockfile `%s'", h->lockname );
+      if (buffer != buffer_space)
+        jnlib_free (buffer);
+      jnlib_set_errno (0); /* Better don't return an inappropriate ERRNO. */
+      return -1;
     }
 
-#ifndef HAVE_DOSISH_SYSTEM
-  /*
-     This is the POSIX version which uses a temporary file and the
-     link system call to make locking an atomic operation.
-   */
+  if (buffer[10] != '\n'
+      || (buffer[10] = 0, pid = atoi (buffer)) == -1
+      || !pid )
+    {
+      log_error ("invalid pid %d in lockfile `%s'", pid, h->lockname );
+      if (buffer != buffer_space)
+        jnlib_free (buffer);
+      jnlib_set_errno (0);
+      return -1;
+    }
+
+  if (nread == expected_len
+      && !memcmp (h->tname+h->nodename_off, buffer+11, h->nodename_len)
+      && buffer[11+h->nodename_len] == '\n')
+    *same_node = 1;
+
+  if (buffer != buffer_space)
+    jnlib_free (buffer);
+  return pid;
+}
+#endif /*HAVE_POSIX_SYSTEM */
+
+
+
+#ifdef  HAVE_POSIX_SYSTEM
+/* Locking core for Unix.  It used a temporary file and the link
+   system call to make locking an atomic operation. */
+static dotlock_t
+dotlock_create_unix (dotlock_t h, const char *file_to_lock)
+{
+  int  fd = -1;
+  char pidstr[16];
+  const char *nodename;
+  const char *dirpart;
+  int dirpartlen;
+  struct utsname utsbuf;
+  size_t tnamelen;
 
   snprintf (pidstr, sizeof pidstr, "%10d\n", (int)getpid() );
 
@@ -260,14 +344,19 @@ create_dotlock (const char *file_to_lock)
   jnlib_free (h->tname);
   jnlib_free (h);
   return NULL;
+}
+#endif /*HAVE_POSIX_SYSTEM*/
 
-#else /* HAVE_DOSISH_SYSTEM */
 
-  /* The Windows version does not need a temporary file but uses the
-     plain lock file along with record locking.  We create this file
-     here so that we later do only need to do the file locking.  For
-     error reporting it is useful to keep the name of the file in the
-     handle.  */
+#ifdef HAVE_DOSISH_SYSTEM
+/* Locking core for Windows.  This version does not need a temporary
+   file but uses the plain lock file along with record locking.  We
+   create this file here so that we later only need to do the file
+   locking.  For error reporting it is useful to keep the name of the
+   file in the handle.  */
+static dotlock_t
+dotlock_create_w32 (dotlock_t h, const char *file_to_lock)
+{
   h->next = all_lockfiles;
   all_lockfiles = h;
 
@@ -286,9 +375,8 @@ create_dotlock (const char *file_to_lock)
      error and we can't reliable create/open the lock file unless we
      would wait here until it works - however there are other valid
      reasons why a lock file can't be created and thus the process
-     would not stop as expected but spin til until Windows crashes.
-     Our solution is to keep the lock file open; that does not
-     harm. */
+     would not stop as expected but spin until Windows crashes.  Our
+     solution is to keep the lock file open; that does not harm. */
   {
 #ifdef HAVE_W32CE_SYSTEM
     wchar_t *wname = utf8_to_wchar (h->lockname);
@@ -315,14 +403,101 @@ create_dotlock (const char *file_to_lock)
       return NULL;
     }
   return h;
+}
+#endif /*HAVE_DOSISH_SYSTEM*/
 
-#endif /* HAVE_DOSISH_SYSTEM */
+
+/* Create a lockfile for a file name FILE_TO_LOCK and returns an
+   object of type dotlock_t which may be used later to actually acquire
+   the lock.  A cleanup routine gets installed to cleanup left over
+   locks or other files used internally by the lock mechanism.
+
+   Calling this function with NULL does only install the atexit
+   handler and may thus be used to assure that the cleanup is called
+   after all other atexit handlers.
+
+   This function creates a lock file in the same directory as
+   FILE_TO_LOCK using that name and a suffix of ".lock".  Note that on
+   POSIX systems a temporary file ".#lk.<hostname>.pid[.threadid] is
+   used.
+
+   The function returns an new handle which needs to be released using
+   destroy_dotlock but gets also released at the termination of the
+   process.  On error NULL is returned.
+ */
+dotlock_t
+dotlock_create (const char *file_to_lock)
+{
+  static int initialized;
+  dotlock_t h;
+
+  if ( !initialized )
+    {
+      atexit (dotlock_remove_lockfiles);
+      initialized = 1;
+    }
+
+  if ( !file_to_lock )
+    return NULL;  /* Only initialization was requested.  */
+
+  h = jnlib_calloc (1, sizeof *h);
+  if (!h)
+    return NULL;
+
+  if (never_lock)
+    {
+      h->disable = 1;
+#ifdef _REENTRANT
+      /* fixme: aquire mutex on all_lockfiles */
+#endif
+      h->next = all_lockfiles;
+      all_lockfiles = h;
+      return h;
+    }
+
+#ifdef HAVE_DOSISH_SYSTEM
+  return dotlock_create_w32 (h, file_to_lock);
+#else /*!HAVE_DOSISH_SYSTEM */
+  return dotlock_create_unix (h, file_to_lock);
+#endif /*!HAVE_DOSISH_SYSTEM*/
+}
+
+
+
+#ifdef HAVE_POSIX_SYSTEM
+/* Unix specific code of destroy_dotlock.  */
+static void
+dotlock_destroy_unix (dotlock_t h)
+{
+  if (h->locked && h->lockname)
+    unlink (h->lockname);
+  if (h->tname)
+    unlink (h->tname);
+  jnlib_free (h->tname);
+}
+#endif /*HAVE_POSIX_SYSTEM*/
+
+
+#ifdef HAVE_DOSISH_SYSTEM
+/* Windows specific code of destroy_dotlock.  */
+static void
+dotlock_destroy_w32 (dotlock_t h)
+{
+  if (h->locked)
+    {
+      OVERLAPPED ovl;
+
+      memset (&ovl, 0, sizeof ovl);
+      UnlockFileEx (h->lockhd, 0, 1, 0, &ovl);
+    }
+  CloseHandle (h->lockhd);
 }
+#endif /*HAVE_DOSISH_SYSTEM*/
 
 
-/* Destroy the local handle H and release the lock. */
+/* Destroy the locck handle H and release the lock.  */
 void
-destroy_dotlock (dotlock_t h)
+dotlock_destroy (dotlock_t h)
 {
   dotlock_t hprev, htmp;
 
@@ -345,20 +520,9 @@ destroy_dotlock (dotlock_t h)
   if (!h->disable)
     {
 #ifdef HAVE_DOSISH_SYSTEM
-      if (h->locked)
-        {
-          OVERLAPPED ovl;
-
-          memset (&ovl, 0, sizeof ovl);
-          UnlockFileEx (h->lockhd, 0, 1, 0, &ovl);
-        }
-      CloseHandle (h->lockhd);
+      dotlock_destroy_w32 (h);
 #else /* !HAVE_DOSISH_SYSTEM */
-      if (h->locked && h->lockname)
-        unlink (h->lockname);
-      if (h->tname)
-        unlink (h->tname);
-      jnlib_free (h->tname);
+      dotlock_destroy_unix (h);
 #endif /* HAVE_DOSISH_SYSTEM */
       jnlib_free (h->lockname);
     }
@@ -366,174 +530,156 @@ destroy_dotlock (dotlock_t h)
 }
 
 
-#ifndef HAVE_DOSISH_SYSTEM
+
+#ifdef HAVE_POSIX_SYSTEM
+/* Unix specific code of make_dotlock.  Returns 0 on success, -1 on
+   error and 1 to try again.  */
 static int
-maybe_deadlock (dotlock_t h)
+dotlock_take_unix (dotlock_t h, long timeout, int *backoff)
 {
-  dotlock_t r;
-
-  for ( r=all_lockfiles; r; r = r->next )
-    {
-      if ( r != h && r->locked )
-        return 1;
-    }
-  return 0;
-}
-#endif /*!HAVE_DOSISH_SYSTEM*/
-
-
-
-/* Do a lock on H. A TIMEOUT of 0 returns immediately, -1 waits
-   forever (hopefully not), other values are reserved (should then be
-   timeouts in milliseconds).  Returns: 0 on success  */
-int
-make_dotlock (dotlock_t h, long timeout)
-{
-  int backoff = 0;
-#ifndef HAVE_DOSISH_SYSTEM
   int  pid;
   const char *maybe_dead="";
   int same_node;
-#endif /*!HAVE_DOSISH_SYSTEM*/
 
-  if ( h->disable )
-    return 0; /* Locks are completely disabled.  Return success. */
-
-  if ( h->locked )
+  if ( !link(h->tname, h->lockname) )
     {
-      log_debug ("Oops, `%s' is already locked\n", h->lockname);
-      return 0;
+      /* fixme: better use stat to check the link count */
+      h->locked = 1;
+      return 0; /* okay */
+    }
+  if ( errno != EEXIST )
+    {
+      log_error ( "lock not made: link() failed: %s\n", strerror(errno) );
+      return -1;
     }
 
-  for (;;)
+  if ( (pid = read_lockfile (h, &same_node)) == -1 )
     {
-#ifndef HAVE_DOSISH_SYSTEM
-      if ( !link(h->tname, h->lockname) )
-        {
-          /* fixme: better use stat to check the link count */
-          h->locked = 1;
-          return 0; /* okay */
-	}
-      if ( errno != EEXIST )
+      if ( errno != ENOENT )
         {
-          log_error ( "lock not made: link() failed: %s\n", strerror(errno) );
+          log_info ("cannot read lockfile\n");
           return -1;
-	}
+        }
+      log_info( "lockfile disappeared\n");
+      return 1; /* Try again.  */
+    }
+  else if ( pid == getpid() && same_node )
+    {
+      log_info( "Oops: lock already held by us\n");
+      h->locked = 1;
+      return 0; /* okay */
+    }
+  else if ( same_node && kill (pid, 0) && errno == ESRCH )
+    {
+      log_info (_("removing stale lockfile (created by %d)\n"), pid );
+      unlink (h->lockname);
+      return 1; /* Try again.  */
+    }
 
-      if ( (pid = read_lockfile (h, &same_node)) == -1 )
-        {
-          if ( errno != ENOENT )
-            {
-              log_info ("cannot read lockfile\n");
-              return -1;
-	    }
-          log_info( "lockfile disappeared\n");
-          continue;
-	}
-      else if ( pid == getpid() && same_node )
-        {
-          log_info( "Oops: lock already held by us\n");
-          h->locked = 1;
-          return 0; /* okay */
-	}
-      else if ( same_node && kill (pid, 0) && errno == ESRCH )
-        {
-          log_info (_("removing stale lockfile (created by %d)\n"), pid );
-          unlink (h->lockname);
-          continue;
-	}
+  if ( timeout == -1 )
+    {
+      /* Wait until lock has been released. */
+      struct timeval tv;
+
+      log_info (_("waiting for lock (held by %d%s) %s...\n"),
+                pid, maybe_dead, maybe_deadlock(h)? _("(deadlock?) "):"");
+
+      /* We can't use sleep, cause signals may be blocked. */
+      tv.tv_sec = 1 + *backoff;
+      tv.tv_usec = 0;
+      select (0, NULL, NULL, NULL, &tv);
+      if ( *backoff < 10 )
+        ++*backoff;
+      return 1; /* Try again.  */
+    }
 
-      if ( timeout == -1 )
-        {
-          /* Wait until lock has been released. */
-          struct timeval tv;
+  jnlib_set_errno (EACCES);
+  return -1;
+}
+#endif /*HAVE_POSIX_SYSTEM*/
 
-          log_info (_("waiting for lock (held by %d%s) %s...\n"),
-                    pid, maybe_dead, maybe_deadlock(h)? _("(deadlock?) "):"");
 
+#ifdef HAVE_DOSISH_SYSTEM
+/* Windows specific code of make_dotlock.  Returns 0 on success, -1 on
+   error and 1 to try again.  */
+static int
+dotlock_take_w32 (dotlock_t h, long timeout, int *backoff)
+{
+  int w32err;
+  OVERLAPPED ovl;
 
-          /* We can't use sleep, cause signals may be blocked. */
-          tv.tv_sec = 1 + backoff;
-          tv.tv_usec = 0;
-          select(0, NULL, NULL, NULL, &tv);
-          if ( backoff < 10 )
-            backoff++ ;
-	}
-      else
-        return -1;
-#else /*HAVE_DOSISH_SYSTEM*/
-      int w32err;
-      OVERLAPPED ovl;
+  /* Lock one byte at offset 0.  The offset is given by OVL.  */
+  memset (&ovl, 0, sizeof ovl);
+  if (LockFileEx (h->lockhd, (LOCKFILE_EXCLUSIVE_LOCK
+                              | LOCKFILE_FAIL_IMMEDIATELY), 0, 1, 0, &ovl))
+    {
+      h->locked = 1;
+      return 0; /* okay */
+    }
 
-      /* Lock one byte at offset 0.  The offset is given by OVL.  */
-      memset (&ovl, 0, sizeof ovl);
-      if (LockFileEx (h->lockhd, (LOCKFILE_EXCLUSIVE_LOCK
-                                  | LOCKFILE_FAIL_IMMEDIATELY), 0, 1, 0, &ovl))
-        {
-          h->locked = 1;
-          return 0; /* okay */
-        }
-      w32err = GetLastError ();
-      if (w32err != ERROR_LOCK_VIOLATION)
-        {
-          log_error (_("lock `%s' not made: %s\n"),
-                     h->lockname, w32_strerror (w32err));
-          return -1;
-        }
+  w32err = GetLastError ();
+  if (w32err != ERROR_LOCK_VIOLATION)
+    {
+      log_error (_("lock `%s' not made: %s\n"),
+                 h->lockname, w32_strerror (w32err));
+      return -1;
+    }
 
-      if ( timeout == -1 )
-        {
-          /* Wait until lock has been released. */
-          log_info (_("waiting for lock %s...\n"), h->lockname);
-          Sleep ((1 + backoff)*1000);
-          if ( backoff < 10 )
-            backoff++ ;
-	}
-      else
-        return -1;
-#endif /*HAVE_DOSISH_SYSTEM*/
+  if ( timeout == -1 )
+    {
+      /* Wait until lock has been released. */
+      log_info (_("waiting for lock %s...\n"), h->lockname);
+      Sleep ((1 + *backoff)*1000);
+      if ( *backoff < 10 )
+        ++*backoff;
+      return 1; /* Try again.  */
     }
-  /*NOTREACHED*/
+
+  return -1;
 }
+#endif /*HAVE_DOSISH_SYSTEM*/
 
 
-/* Release a lock.  Returns 0 on success.  */
+/* Take a lock on H.  A value of 0 for TIMEOUT returns immediately if
+   the lock can't be taked, -1 waits forever (hopefully not), other
+   values are reserved (planned to be timeouts in milliseconds).
+   Returns: 0 on success  */
 int
-release_dotlock (dotlock_t h)
+dotlock_take (dotlock_t h, long timeout)
 {
-#ifndef HAVE_DOSISH_SYSTEM
-  int pid, same_node;
-#endif
-
-  /* To avoid atexit race conditions we first check whether there are
-     any locks left.  It might happen that another atexit handler
-     tries to release the lock while the atexit handler of this module
-     already ran and thus H is undefined.  */
-  if (!all_lockfiles)
-    return 0;
+  int backoff = 0;
+  int ret;
 
   if ( h->disable )
-    return 0;
+    return 0; /* Locks are completely disabled.  Return success. */
 
-  if ( !h->locked )
+  if ( h->locked )
     {
-      log_debug("Oops, `%s' is not locked\n", h->lockname);
+      log_debug ("Oops, `%s' is already locked\n", h->lockname);
       return 0;
     }
 
+  do
+    {
 #ifdef HAVE_DOSISH_SYSTEM
-  {
-    OVERLAPPED ovl;
+      ret = dotlock_take_w32 (h, timeout, &backoff);
+#else /*!HAVE_DOSISH_SYSTEM*/
+      ret = dotlock_take_unix (h, timeout, &backoff);
+#endif /*!HAVE_DOSISH_SYSTEM*/
+    }
+  while (ret == 1);
 
-    memset (&ovl, 0, sizeof ovl);
-    if (!UnlockFileEx (h->lockhd, 0, 1, 0, &ovl))
-      {
-        log_error ("release_dotlock: error removing lockfile `%s': %s\n",
-                   h->lockname, w32_strerror (-1));
-        return -1;
-      }
-  }
-#else
+  return ret;
+}
+
+
+
+#ifdef HAVE_POSIX_SYSTEM
+/* Unix specific code of release_dotlock.  */
+static int
+dotlock_release_unix (dotlock_t h)
+{
+  int pid, same_node;
 
   pid = read_lockfile (h, &same_node);
   if ( pid == -1 )
@@ -555,104 +701,66 @@ release_dotlock (dotlock_t h)
     }
   /* Fixme: As an extra check we could check whether the link count is
      now really at 1. */
-
-#endif /* !HAVE_DOSISH_SYSTEM */
-  h->locked = 0;
   return 0;
 }
+#endif /*HAVE_POSIX_SYSTEM */
 
 
-/* Read the lock file and return the pid, returns -1 on error.  True
-   will be stored in the integer at address SAME_NODE if the lock file
-   has been created on the same node. */
-#ifndef HAVE_DOSISH_SYSTEM
+#ifdef HAVE_DOSISH_SYSTEM
+/* Windows specific code of release_dotlock.  */
 static int
-read_lockfile (dotlock_t h, int *same_node )
+dotlock_release_w32 (dotlock_t h)
 {
-  char buffer_space[10+1+70+1]; /* 70 is just an estimated value; node
-                                   name are usually shorter. */
-  int fd;
-  int pid = -1;
-  char *buffer, *p;
-  size_t expected_len;
-  int res, nread;
-
-  *same_node = 0;
-  expected_len = 10 + 1 + h->nodename_len + 1;
-  if ( expected_len >= sizeof buffer_space)
-    {
-      buffer = jnlib_malloc (expected_len);
-      if (!buffer)
-        return -1;
-    }
-  else
-    buffer = buffer_space;
+  OVERLAPPED ovl;
 
-  if ( (fd = open (h->lockname, O_RDONLY)) == -1 )
+  memset (&ovl, 0, sizeof ovl);
+  if (!UnlockFileEx (h->lockhd, 0, 1, 0, &ovl))
     {
-      int e = errno;
-      log_info ("error opening lockfile `%s': %s\n",
-                h->lockname, strerror(errno) );
-      if (buffer != buffer_space)
-        jnlib_free (buffer);
-      jnlib_set_errno (e); /* Need to return ERRNO here. */
+      log_error ("release_dotlock: error removing lockfile `%s': %s\n",
+                 h->lockname, w32_strerror (-1));
       return -1;
     }
 
-  p = buffer;
-  nread = 0;
-  do
-    {
-      res = read (fd, p, expected_len - nread);
-      if (res == -1 && errno == EINTR)
-        continue;
-      if (res < 0)
-        {
-          log_info ("error reading lockfile `%s'", h->lockname );
-          close (fd);
-          if (buffer != buffer_space)
-            jnlib_free (buffer);
-          jnlib_set_errno (0); /* Do not return an inappropriate ERRNO. */
-          return -1;
-        }
-      p += res;
-      nread += res;
-    }
-  while (res && nread != expected_len);
-  close(fd);
+  return 0;
+}
+#endif /*HAVE_DOSISH_SYSTEM */
 
-  if (nread < 11)
-    {
-      log_info ("invalid size of lockfile `%s'", h->lockname );
-      if (buffer != buffer_space)
-        jnlib_free (buffer);
-      jnlib_set_errno (0); /* Better don't return an inappropriate ERRNO. */
-      return -1;
-    }
 
-  if (buffer[10] != '\n'
-      || (buffer[10] = 0, pid = atoi (buffer)) == -1
-      || !pid )
+/* Release a lock.  Returns 0 on success.  */
+int
+dotlock_release (dotlock_t h)
+{
+  int ret;
+
+  /* To avoid atexit race conditions we first check whether there are
+     any locks left.  It might happen that another atexit handler
+     tries to release the lock while the atexit handler of this module
+     already ran and thus H is undefined.  */
+  if (!all_lockfiles)
+    return 0;
+
+  if ( h->disable )
+    return 0;
+
+  if ( !h->locked )
     {
-      log_error ("invalid pid %d in lockfile `%s'", pid, h->lockname );
-      if (buffer != buffer_space)
-        jnlib_free (buffer);
-      jnlib_set_errno (0);
-      return -1;
+      log_debug("Oops, `%s' is not locked\n", h->lockname);
+      return 0;
     }
 
-  if (nread == expected_len
-      && !memcmp (h->tname+h->nodename_off, buffer+11, h->nodename_len)
-      && buffer[11+h->nodename_len] == '\n')
-    *same_node = 1;
+#ifdef HAVE_DOSISH_SYSTEM
+  ret = dotlock_release_w32 (h);
+#else
+  ret = dotlock_release_unix (h);
+#endif
 
-  if (buffer != buffer_space)
-    jnlib_free (buffer);
-  return pid;
+  if (!ret)
+    h->locked = 0;
+  return ret;
 }
-#endif /* !HAVE_DOSISH_SYSTEM */
 
 
+
 /* Remove all lockfiles.  This is usually called by the atexit handler
    installed by this module but may also be called by other
    termination handlers.  */
@@ -667,7 +775,7 @@ dotlock_remove_lockfiles (void)
   while ( h )
     {
       h2 = h->next;
-      destroy_dotlock (h);
+      dotlock_destroy (h);
       h = h2;
     }
 }
diff --git a/common/dotlock.h b/common/dotlock.h
index 407a80b..276a6cd 100644
--- a/common/dotlock.h
+++ b/common/dotlock.h
@@ -1,7 +1,7 @@
-/* dotlock.h
- *	Copyright (C) 2000, 2001, 2006 Free Software Foundation, Inc.
+/* dotlock.h - dotfile locking
+ *	Copyright (C) 2000, 2001, 2006, 2011 Free Software Foundation, Inc.
  *
- * This file is part of JNLIB.
+ * This file is part of JNLIB, which is a subsystem of GnuPG.
  *
  * JNLIB is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as
@@ -23,11 +23,11 @@
 struct dotlock_handle;
 typedef struct dotlock_handle *dotlock_t;
 
-void disable_dotlock (void);
-dotlock_t create_dotlock (const char *file_to_lock);
-void destroy_dotlock ( dotlock_t h );
-int make_dotlock (dotlock_t h, long timeout);
-int release_dotlock (dotlock_t h);
+void dotlock_disable (void);
+dotlock_t dotlock_create (const char *file_to_lock);
+void dotlock_destroy ( dotlock_t h );
+int dotlock_take (dotlock_t h, long timeout);
+int dotlock_release (dotlock_t h);
 void dotlock_remove_lockfiles (void);
 
 #endif /*LIBJNLIB_DOTLOCK_H*/
diff --git a/g10/ChangeLog b/g10/ChangeLog
index be13196..4b5f2f1 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,12 @@
+2011-09-23  Werner Koch  <wk at g10code.com>
+
+	* gpgv.c (disable_dotlock): Rename to dotlock_disable.
+	(create_dotlock): Rename to dotlock_create.
+	(destroy_dotlock): Rename to dotlock_destroy.
+	(make_dotlock): Rename to dotlock_take.
+	(release_dotlock): Rename to dotlock_release.
+	(lockfiles_remove): Rename to dotlock_remove_lockfiles.
+
 2011-09-20  Werner Koch  <wk at g10code.com>
 
 	* free-packet.c (free_public_key): Allow a NULL argument.
diff --git a/g10/gpg.c b/g10/gpg.c
index 8326ee7..51661b3 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -1969,7 +1969,7 @@ main (int argc, char **argv)
 
     gnupg_init_signals (0, emergency_cleanup);
 
-    create_dotlock(NULL); /* Register locking cleanup. */
+    dotlock_create (NULL); /* Register lock file cleanup. */
 
     opt.session_env = session_env_new ();
     if (!opt.session_env)
@@ -2651,7 +2651,7 @@ main (int argc, char **argv)
 	  case oNoEscapeFrom: opt.escape_from = 0; break;
 	  case oLockOnce: opt.lock_once = 1; break;
 	  case oLockNever:
-            disable_dotlock ();
+            dotlock_disable ();
             break;
 	  case oLockMultiple:
 #ifndef __riscos__
diff --git a/g10/gpgv.c b/g10/gpgv.c
index 9f46ab3..9328343 100644
--- a/g10/gpgv.c
+++ b/g10/gpgv.c
@@ -163,7 +163,7 @@ main( int argc, char **argv )
 
   tty_no_terminal(1);
   tty_batchmode(1);
-  disable_dotlock();
+  dotlock_disable ();
 
   pargs.argc = &argc;
   pargs.argv = &argv;
@@ -502,25 +502,25 @@ agent_scd_getattr (const char *name, struct agent_card_info_s *info)
 
 /* We do not do any locking, so use these stubs here */
 void
-disable_dotlock (void)
+dotlock_disable (void)
 {
 }
 
 dotlock_t
-create_dotlock (const char *file_to_lock)
+dotlock_create (const char *file_to_lock)
 {
   (void)file_to_lock;
   return NULL;
 }
 
 void
-destroy_dotlock (dotlock_t h)
+dotlock_destroy (dotlock_t h)
 {
   (void)h;
 }
 
 int
-make_dotlock (dotlock_t h, long timeout)
+dotlock_take (dotlock_t h, long timeout)
 {
   (void)h;
   (void)timeout;
@@ -528,14 +528,14 @@ make_dotlock (dotlock_t h, long timeout)
 }
 
 int
-release_dotlock (dotlock_t h)
+dotlock_release (dotlock_t h)
 {
   (void)h;
   return 0;
 }
 
 void
-remove_lockfiles (void)
+dotlock_remove_lockfiles (void)
 {
 }
 
diff --git a/g10/keydb.c b/g10/keydb.c
index f764248..e4b9709 100644
--- a/g10/keydb.c
+++ b/g10/keydb.c
@@ -136,7 +136,7 @@ maybe_create_keyring (char *filename, int force)
   /* To avoid races with other instances of gpg trying to create or
      update the keyring (it is removed during an update for a short
      time), we do the next stuff in a locked state. */
-  lockhd = create_dotlock (filename);
+  lockhd = dotlock_create (filename);
   if (!lockhd)
     {
       /* A reason for this to fail is that the directory is not
@@ -152,7 +152,7 @@ maybe_create_keyring (char *filename, int force)
         return gpg_error (GPG_ERR_GENERAL);
     }
 
-  if ( make_dotlock (lockhd, -1) )
+  if ( dotlock_take (lockhd, -1) )
     {
       /* This is something bad.  Probably a stale lockfile.  */
       log_info ("can't lock `%s'\n", filename );
@@ -196,8 +196,8 @@ maybe_create_keyring (char *filename, int force)
  leave:
   if (lockhd)
     {
-      release_dotlock (lockhd);
-      destroy_dotlock (lockhd);
+      dotlock_release (lockhd);
+      dotlock_destroy (lockhd);
     }
   return rc;
 }
diff --git a/g10/keyring.c b/g10/keyring.c
index 12356e2..480c0e9 100644
--- a/g10/keyring.c
+++ b/g10/keyring.c
@@ -306,7 +306,7 @@ keyring_lock (KEYRING_HANDLE hd, int yes)
             if (!keyring_is_writable(kr))
                 continue;
             if (!kr->lockhd) {
-                kr->lockhd = create_dotlock( kr->fname );
+                kr->lockhd = dotlock_create( kr->fname );
                 if (!kr->lockhd) {
                     log_info ("can't allocate lock for `%s'\n", kr->fname );
                     rc = G10ERR_GENERAL;
@@ -322,7 +322,7 @@ keyring_lock (KEYRING_HANDLE hd, int yes)
                 continue;
             if (kr->is_locked)
                 ;
-            else if (make_dotlock (kr->lockhd, -1) ) {
+            else if (dotlock_take (kr->lockhd, -1) ) {
                 log_info ("can't lock `%s'\n", kr->fname );
                 rc = G10ERR_GENERAL;
             }
@@ -337,7 +337,7 @@ keyring_lock (KEYRING_HANDLE hd, int yes)
                 continue;
             if (!kr->is_locked)
                 ;
-            else if (release_dotlock (kr->lockhd))
+            else if (dotlock_release (kr->lockhd))
                 log_info ("can't unlock `%s'\n", kr->fname );
             else
                 kr->is_locked = 0;
diff --git a/g10/tdbio.c b/g10/tdbio.c
index 09f31aa..968d06b 100644
--- a/g10/tdbio.c
+++ b/g10/tdbio.c
@@ -257,7 +257,7 @@ put_record_into_cache( ulong recno, const char *data )
 	if( !n )
 	    n = 1;
 	if( !is_locked ) {
-	    if( make_dotlock( lockhandle, -1 ) )
+	    if( dotlock_take( lockhandle, -1 ) )
 		log_fatal("can't acquire lock - giving up\n");
 	    else
 		is_locked = 1;
@@ -276,7 +276,7 @@ put_record_into_cache( ulong recno, const char *data )
 	    }
 	}
 	if( !opt.lock_once ) {
-	    if( !release_dotlock( lockhandle ) )
+	    if( !dotlock_release( lockhandle ) )
 		is_locked = 0;
 	}
 	assert( unused );
@@ -318,7 +318,7 @@ tdbio_sync()
 	return 0;
 
     if( !is_locked ) {
-	if( make_dotlock( lockhandle, -1 ) )
+	if( dotlock_take( lockhandle, -1 ) )
 	    log_fatal("can't acquire lock - giving up\n");
 	else
 	    is_locked = 1;
@@ -333,7 +333,7 @@ tdbio_sync()
     }
     cache_is_dirty = 0;
     if( did_lock && !opt.lock_once ) {
-	if( !release_dotlock( lockhandle ) )
+	if( !dotlock_release (lockhandle) )
 	    is_locked = 0;
     }
 
@@ -373,7 +373,7 @@ tdbio_end_transaction()
     if( !in_transaction )
 	log_bug("tdbio: no active transaction\n");
     if( !is_locked ) {
-	if( make_dotlock( lockhandle, -1 ) )
+	if( dotlock_take( lockhandle, -1 ) )
 	    log_fatal("can't acquire lock - giving up\n");
 	else
 	    is_locked = 1;
@@ -383,7 +383,7 @@ tdbio_end_transaction()
     rc = tdbio_sync();
     unblock_all_signals();
     if( !opt.lock_once ) {
-	if( !release_dotlock( lockhandle ) )
+	if( !dotlock_release (lockhandle) )
 	    is_locked = 0;
     }
     return rc;
@@ -423,7 +423,7 @@ static void
 cleanup(void)
 {
     if( is_locked ) {
-	if( !release_dotlock(lockhandle) )
+	if( !dotlock_release (lockhandle) )
 	    is_locked = 0;
     }
 }
@@ -544,10 +544,10 @@ tdbio_set_dbname( const char *new_dbname, int create )
 	    db_name = fname;
 #ifdef __riscos__
 	    if( !lockhandle )
-		lockhandle = create_dotlock( db_name );
+		lockhandle = dotlock_create (db_name);
 	    if( !lockhandle )
 		log_fatal( _("can't create lock for `%s'\n"), db_name );
-            if( make_dotlock( lockhandle, -1 ) )
+            if( dotlock_make (lockhandle, -1) )
                 log_fatal( _("can't lock `%s'\n"), db_name );
 #endif /* __riscos__ */
 	    oldmask=umask(077);
@@ -567,7 +567,7 @@ tdbio_set_dbname( const char *new_dbname, int create )
 
 #ifndef __riscos__
 	    if( !lockhandle )
-		lockhandle = create_dotlock( db_name );
+		lockhandle = dotlock_create (db_name);
 	    if( !lockhandle )
 		log_fatal( _("can't create lock for `%s'\n"), db_name );
 #endif /* !__riscos__ */
@@ -608,11 +608,11 @@ open_db()
   assert( db_fd == -1 );
 
   if (!lockhandle )
-    lockhandle = create_dotlock( db_name );
+    lockhandle = dotlock_create (db_name);
   if (!lockhandle )
     log_fatal( _("can't create lock for `%s'\n"), db_name );
 #ifdef __riscos__
-  if (make_dotlock( lockhandle, -1 ) )
+  if (dotlock_take (lockhandle, -1) )
     log_fatal( _("can't lock `%s'\n"), db_name );
 #endif /* __riscos__ */
 #ifdef HAVE_W32CE_SYSTEM
diff --git a/g13/create.c b/g13/create.c
index 2b998e2..60c1d3d 100644
--- a/g13/create.c
+++ b/g13/create.c
@@ -246,10 +246,10 @@ g13_create_container (ctrl_t ctrl, const char *filename, strlist_t keys)
   /* Take a lock and proceed with the creation.  If there is a lock we
      immediately return an error because for creation it does not make
      sense to wait.  */
-  lock = create_dotlock (filename);
+  lock = dotlock_create (filename);
   if (!lock)
     return gpg_error_from_syserror ();
-  if (make_dotlock (lock, 0))
+  if (dotlock_take (lock, 0))
     {
       err = gpg_error_from_syserror ();
       goto leave;
@@ -319,7 +319,7 @@ g13_create_container (ctrl_t ctrl, const char *filename, strlist_t keys)
   xfree (detachedname);
   xfree (enckeyblob);
   xfree (keyblob);
-  destroy_dotlock (lock);
+  dotlock_destroy (lock);
 
   return err;
 }
diff --git a/g13/g13.c b/g13/g13.c
index 180b0d9..972a7ea 100644
--- a/g13/g13.c
+++ b/g13/g13.c
@@ -383,7 +383,7 @@ main ( int argc, char **argv)
 
   gnupg_init_signals (0, emergency_cleanup);
 
-  create_dotlock (NULL); /* Register locking cleanup.  */
+  dotlock_create (NULL); /* Register locking cleanup.  */
 
   opt.session_env = session_env_new ();
   if (!opt.session_env)
diff --git a/g13/mount.c b/g13/mount.c
index 387bb6f..198fde0 100644
--- a/g13/mount.c
+++ b/g13/mount.c
@@ -273,14 +273,14 @@ g13_mount_container (ctrl_t ctrl, const char *filename, const char *mountpoint)
     }
 
   /* Try to take a lock.  */
-  lock = create_dotlock (filename);
+  lock = dotlock_create (filename);
   if (!lock)
     {
       xfree (mountpoint_buffer);
       return gpg_error_from_syserror ();
     }
 
-  if (make_dotlock (lock, 0))
+  if (dotlock_take (lock, 0))
     {
       err = gpg_error_from_syserror ();
       goto leave;
@@ -359,7 +359,7 @@ g13_mount_container (ctrl_t ctrl, const char *filename, const char *mountpoint)
   destroy_tupledesc (tuples);
   xfree (keyblob);
   xfree (enckeyblob);
-  destroy_dotlock (lock);
+  dotlock_destroy (lock);
   xfree (mountpoint_buffer);
   return err;
 }
diff --git a/po/de.po b/po/de.po
index dab6c57..5f80e09 100644
--- a/po/de.po
+++ b/po/de.po
@@ -128,16 +128,28 @@ msgid "error writing key: %s\n"
 msgstr "Fehler beim Schreiben des Schlüssels: %s\n"
 
 #, c-format
-msgid "Please enter the passphrase for the ssh key%0A  %c"
+msgid ""
+"An ssh process requested the use of key%%0A  %s%%0A  (%s)%%0ADo you want to "
+"allow this?"
+msgstr ""
+
+msgid "Allow"
+msgstr ""
+
+msgid "Deny"
+msgstr ""
+
+#, fuzzy, c-format
+msgid "Please enter the passphrase for the ssh key%%0A  %F%%0A  (%c)"
 msgstr "Bitte geben Sie die Passphrase für den SSH-Schlüssel %0A  %c ein."
 
 msgid "Please re-enter this passphrase"
 msgstr "Bitte geben Sie die Passphrase noch einmal ein:"
 
-#, c-format
+#, fuzzy, c-format
 msgid ""
-"Please enter a passphrase to protect the received secret key%%0A   %s%%"
-"0Awithin gpg-agent's key storage"
+"Please enter a passphrase to protect the received secret key%%0A   %s%%0A   %"
+"s%%0Awithin gpg-agent's key storage"
 msgstr ""
 "Bitte geben Sie eine Passphrase ein, um den empfangenen geheimen Schlüssel%%"
 "0A   %s%%0A im Schlüsselspeicher des gpg-agenten zu schützen."
@@ -1034,9 +1046,6 @@ msgstr "Fehler beim Schreiben von %s: %s\n"
 msgid "removing stale lockfile (created by %d)\n"
 msgstr "eine übriggebliebene Sperrdatei wird entfernt (erzeugt von %d)\n"
 
-msgid " - probably dead - removing lock"
-msgstr " - existiert wahrscheinlich nicht mehr - entferne Sperre"
-
 #, c-format
 msgid "waiting for lock (held by %d%s) %s...\n"
 msgstr "warte auf die Freigabe der Sperre (gehalten von %d%s) %s...\n"
@@ -1428,6 +1437,10 @@ msgstr "Diesen Schlüssel aus dem Schlüsselbund löschen? (j/N) "
 msgid "This is a secret key! - really delete? (y/N) "
 msgstr "Dies ist ein privater Schlüssel! - Wirklich löschen? (j/N) "
 
+#, fuzzy
+msgid "deleting secret key not implemented\n"
+msgstr "Exportieren geheimer Schlüssel ist nicht erlaubt\n"
+
 #, c-format
 msgid "deleting keyblock failed: %s\n"
 msgstr "löschen des Schlüsselblocks fehlgeschlagen: %s\n"
@@ -2522,10 +2535,6 @@ msgid "importing secret keys not allowed\n"
 msgstr "Importieren geheimer Schlüssel ist nicht erlaubt\n"
 
 #, c-format
-msgid "key %s: secret key part already available\n"
-msgstr "Schlüssel %s: Die geheimen Teile sind bereits vorhanden\n"
-
-#, c-format
 msgid "key %s: no public key - can't apply revocation certificate\n"
 msgstr ""
 "Schlüssel %s: Kein öffentlicher Schlüssel - der Schlüsselwiderruf kann nicht "
@@ -7666,6 +7675,25 @@ msgstr "Liste der LDAP Server"
 msgid "Configuration for OCSP"
 msgstr "Konfiguration zu OCSP"
 
+msgid "GPG for OpenPGP"
+msgstr ""
+
+msgid "GPG Agent"
+msgstr ""
+
+msgid "Smartcard Daemon"
+msgstr ""
+
+msgid "GPG for S/MIME"
+msgstr ""
+
+msgid "Directory Manager"
+msgstr ""
+
+#, fuzzy
+msgid "PIN and Passphrase Entry"
+msgstr "Falsche Passphrase!"
+
 #, c-format
 msgid "External verification of component %s failed"
 msgstr "Die externe Überprüfung der Komponente %s war nicht erfolgreich"
@@ -7878,6 +7906,12 @@ msgstr ""
 "Syntax: gpg-check-pattern [optionen] Musterdatei\n"
 "Die von stdin gelesene Passphrase gegen die Musterdatei prüfen\n"
 
+#~ msgid " - probably dead - removing lock"
+#~ msgstr " - existiert wahrscheinlich nicht mehr - entferne Sperre"
+
+#~ msgid "key %s: secret key part already available\n"
+#~ msgstr "Schlüssel %s: Die geheimen Teile sind bereits vorhanden\n"
+
 #~ msgid "self-signed certificate"
 #~ msgstr "eigenbeglaubigtes Zertifikat"
 
diff --git a/sm/gpgsm.c b/sm/gpgsm.c
index f08e0f8..87f94e2 100644
--- a/sm/gpgsm.c
+++ b/sm/gpgsm.c
@@ -928,7 +928,7 @@ main ( int argc, char **argv)
 
   gnupg_init_signals (0, emergency_cleanup);
 
-  create_dotlock (NULL); /* register locking cleanup */
+  dotlock_create (NULL); /* Register lockfile cleanup.  */
 
   opt.session_env = session_env_new ();
   if (!opt.session_env)
diff --git a/sm/keydb.c b/sm/keydb.c
index fe5d0e7..9d1a6ef 100644
--- a/sm/keydb.c
+++ b/sm/keydb.c
@@ -214,12 +214,12 @@ keydb_add_resource (const char *url, int force, int secret, int *auto_created)
               all_resources[used_resources].secret = secret;
 
               all_resources[used_resources].lockhandle
-                = create_dotlock (filename);
+                = dotlock_create (filename);
               if (!all_resources[used_resources].lockhandle)
                 log_fatal ( _("can't create lock for `%s'\n"), filename);
 
               /* Do a compress run if needed and the file is not locked. */
-              if (!make_dotlock (all_resources[used_resources].lockhandle, 0))
+              if (!dotlock_take (all_resources[used_resources].lockhandle, 0))
                 {
                   KEYBOX_HANDLE kbxhd = keybox_new (token, secret);
 
@@ -228,7 +228,7 @@ keydb_add_resource (const char *url, int force, int secret, int *auto_created)
                       keybox_compress (kbxhd);
                       keybox_release (kbxhd);
                     }
-                  release_dotlock (all_resources[used_resources].lockhandle);
+                  dotlock_release (all_resources[used_resources].lockhandle);
                 }
 
               used_resources++;
@@ -421,7 +421,7 @@ lock_all (KEYDB_HANDLE hd)
           break;
         case KEYDB_RESOURCE_TYPE_KEYBOX:
           if (hd->active[i].lockhandle)
-            rc = make_dotlock (hd->active[i].lockhandle, -1);
+            rc = dotlock_take (hd->active[i].lockhandle, -1);
           break;
         }
       if (rc)
@@ -439,7 +439,7 @@ lock_all (KEYDB_HANDLE hd)
                 break;
               case KEYDB_RESOURCE_TYPE_KEYBOX:
                 if (hd->active[i].lockhandle)
-                  release_dotlock (hd->active[i].lockhandle);
+                  dotlock_release (hd->active[i].lockhandle);
                 break;
               }
           }
@@ -469,7 +469,7 @@ unlock_all (KEYDB_HANDLE hd)
           break;
         case KEYDB_RESOURCE_TYPE_KEYBOX:
           if (hd->active[i].lockhandle)
-            release_dotlock (hd->active[i].lockhandle);
+            dotlock_release (hd->active[i].lockhandle);
           break;
         }
     }

commit acde3f8ea660ced34ebe34f7d31185c9fdea8295
Author: Werner Koch <wk at gnupg.org>
Date:   Thu Sep 22 14:27:32 2011 +0200

    Remove support for RISCOS from dotlock.c

diff --git a/common/dotlock.c b/common/dotlock.c
index 5075465..658e05f 100644
--- a/common/dotlock.c
+++ b/common/dotlock.c
@@ -1,8 +1,8 @@
 /* dotlock.c - dotfile locking
  * Copyright (C) 1998, 2000, 2001, 2003, 2004,
- *               2005, 2006, 2008, 2010 Free Software Foundation, Inc.
+ *               2005, 2006, 2008, 2010,2011 Free Software Foundation, Inc.
  *
- * This file is part of JNLIB.
+ * This file is part of JNLIB, which is a subsystem of GnuPG.
  *
  * JNLIB is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as
@@ -70,15 +70,16 @@ struct dotlock_handle
 
 #ifdef HAVE_DOSISH_SYSTEM
   HANDLE lockhd;       /* The W32 handle of the lock file.      */
-#else
+#else /*!HAVE_DOSISH_SYSTEM */
   char *tname;         /* Name of the lockfile template.        */
   size_t nodename_off; /* Offset in TNAME of the nodename part. */
   size_t nodename_len; /* Length of the nodename part.          */
-#endif /* HAVE_DOSISH_SYSTEM */
+#endif /*!HAVE_DOSISH_SYSTEM */
 };
 
 
-/* A list of of all lock handles. */
+/* A list of of all lock handles.  The volatile attribute might help
+   if used in an atexit handler.  */
 static volatile dotlock_t all_lockfiles;
 
 /* If this has the value true all locking is disabled.  */
@@ -175,15 +176,6 @@ create_dotlock (const char *file_to_lock)
   else
     nodename = utsbuf.nodename;
 
-#ifdef __riscos__
-  {
-    char *iter = (char *) nodename;
-    for (; iter[0]; iter++)
-      if (iter[0] == '.')
-        iter[0] = '/';
-  }
-#endif /* __riscos__ */
-
   if ( !(dirpart = strrchr (file_to_lock, DIRSEP_C)) )
     {
       dirpart = EXTSEP_S;
@@ -211,17 +203,10 @@ create_dotlock (const char *file_to_lock)
     }
   h->nodename_len = strlen (nodename);
 
-#ifndef __riscos__
   snprintf (h->tname, tnamelen, "%.*s/.#lk%p.", dirpartlen, dirpart, h );
   h->nodename_off = strlen (h->tname);
   snprintf (h->tname+h->nodename_off, tnamelen - h->nodename_off,
            "%s.%d", nodename, (int)getpid ());
-#else /* __riscos__ */
-  snprintf (h->tname, tnamelen, "%.*s.lk%p/", dirpartlen, dirpart, h );
-  h->nodename_off = strlen (h->tname);
-  snprintf (h->tname+h->nodename_off, tnamelen - h->modename_off,
-            "%s/%d", nodename, (int)getpid () );
-#endif /* __riscos__ */
 
   do
     {
@@ -416,16 +401,13 @@ make_dotlock (dotlock_t h, long timeout)
 
   if ( h->locked )
     {
-#ifndef __riscos__
       log_debug ("Oops, `%s' is already locked\n", h->lockname);
-#endif /* !__riscos__ */
       return 0;
     }
 
   for (;;)
     {
 #ifndef HAVE_DOSISH_SYSTEM
-# ifndef __riscos__
       if ( !link(h->tname, h->lockname) )
         {
           /* fixme: better use stat to check the link count */
@@ -437,18 +419,6 @@ make_dotlock (dotlock_t h, long timeout)
           log_error ( "lock not made: link() failed: %s\n", strerror(errno) );
           return -1;
 	}
-# else /* __riscos__ */
-      if ( !renamefile(h->tname, h->lockname) )
-        {
-          h->locked = 1;
-          return 0; /* okay */
-        }
-      if ( errno != EEXIST )
-        {
-          log_error( "lock not made: rename() failed: %s\n", strerror(errno) );
-          return -1;
-        }
-# endif /* __riscos__ */
 
       if ( (pid = read_lockfile (h, &same_node)) == -1 )
         {
@@ -468,16 +438,9 @@ make_dotlock (dotlock_t h, long timeout)
 	}
       else if ( same_node && kill (pid, 0) && errno == ESRCH )
         {
-# ifndef __riscos__
           log_info (_("removing stale lockfile (created by %d)\n"), pid );
           unlink (h->lockname);
           continue;
-# else /* __riscos__ */
-          /* Under RISCOS we are *pretty* sure that the other task
-             is dead and therefore we remove the stale lock file. */
-          maybe_dead = _(" - probably dead - removing lock");
-          unlink(h->lockname);
-# endif /* __riscos__ */
 	}
 
       if ( timeout == -1 )
@@ -584,7 +547,6 @@ release_dotlock (dotlock_t h)
       return -1;
     }
 
-#ifndef __riscos__
   if ( unlink( h->lockname ) )
     {
       log_error ("release_dotlock: error removing lockfile `%s'\n",
@@ -593,14 +555,6 @@ release_dotlock (dotlock_t h)
     }
   /* Fixme: As an extra check we could check whether the link count is
      now really at 1. */
-#else /* __riscos__ */
-  if ( renamefile (h->lockname, h->tname) )
-    {
-      log_error ("release_dotlock: error renaming lockfile `%s' to `%s'\n",
-                 h->lockname, h->tname);
-      return -1;
-    }
-#endif /* __riscos__ */
 
 #endif /* !HAVE_DOSISH_SYSTEM */
   h->locked = 0;
@@ -678,12 +632,7 @@ read_lockfile (dotlock_t h, int *same_node )
 
   if (buffer[10] != '\n'
       || (buffer[10] = 0, pid = atoi (buffer)) == -1
-#ifndef __riscos__
-      || !pid
-#else /* __riscos__ */
-      || (!pid && riscos_getpid())
-#endif /* __riscos__ */
-      )
+      || !pid )
     {
       log_error ("invalid pid %d in lockfile `%s'", pid, h->lockname );
       if (buffer != buffer_space)

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog          |    4 +
 common/ChangeLog   |   24 +-
 common/asshelp.c   |    6 +-
 common/dotlock.c   | 1138 +++++++++++++++++++++++++++++++++++-----------------
 common/dotlock.h   |   18 +-
 common/t-dotlock.c |  145 +++++++
 configure.ac       |   33 +--
 g10/ChangeLog      |    9 +
 g10/gpg.c          |    4 +-
 g10/gpgv.c         |   14 +-
 g10/keydb.c        |    8 +-
 g10/keyring.c      |    6 +-
 g10/tdbio.c        |   24 +-
 g13/create.c       |    6 +-
 g13/g13.c          |    2 +-
 g13/mount.c        |    6 +-
 po/de.po           |   56 ++-
 sm/gpgsm.c         |    2 +-
 sm/keydb.c         |   12 +-
 19 files changed, 1053 insertions(+), 464 deletions(-)
 create mode 100644 common/t-dotlock.c


hooks/post-receive
-- 
The GNU Privacy Guard
http://git.gnupg.org




More information about the Gnupg-commits mailing list