diff --git a/common/ChangeLog b/common/ChangeLog index 95aef653c..7d803660a 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,17 @@ +2011-09-23 Werner Koch + + * 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 + + * dotlock.c: Remove support for RISCOS. + 2011-08-10 Werner Koch * 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 c5d5a3359..96d9a242a 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 658e05fb0..7d0ac1fab 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 . */ -#include +#ifdef HAVE_CONFIG_H +# include +#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 #include #include @@ -26,7 +40,7 @@ #include #include #ifdef HAVE_DOSISH_SYSTEM -# define WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN /* We only need the OS core stuff. */ # include #else # include @@ -39,27 +53,46 @@ # include #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,49 +119,131 @@ 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; } - -/* 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..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) +#ifdef HAVE_POSIX_SYSTEM +static int +maybe_deadlock (dotlock_t h) +{ + dotlock_t r; + + for ( r=all_lockfiles; r; r = r->next ) + { + if ( r != h && r->locked ) + return 1; + } + 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. */ +#ifdef HAVE_POSIX_SYSTEM +static int +read_lockfile (dotlock_t h, int *same_node ) +{ + 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; + + *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; + + 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; + } + + 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 (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 ) + { + 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) { - static int initialized; - dotlock_t h; -#ifndef HAVE_DOSISH_SYSTEM int fd = -1; char pidstr[16]; const char *nodename; @@ -136,37 +251,6 @@ create_dotlock (const char *file_to_lock) int dirpartlen; struct utsname utsbuf; size_t tnamelen; -#endif - - 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; - } - -#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. - */ 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..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*/ } -/* Destroy the local handle H and release the lock. */ + +#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 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,35 +530,125 @@ 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 ( !link(h->tname, h->lockname) ) + { + /* 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; + } + + if ( (pid = read_lockfile (h, &same_node)) == -1 ) + { + if ( errno != ENOENT ) + { + 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 ( 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. */ + } + + jnlib_set_errno (EACCES); + return -1; +} +#endif /*HAVE_POSIX_SYSTEM*/ + + +#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; + + /* 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; + } + + 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. */ + } + + return -1; +} +#endif /*HAVE_DOSISH_SYSTEM*/ + + +/* 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 +dotlock_take (dotlock_t h, long timeout) +{ + int backoff = 0; + int ret; if ( h->disable ) return 0; /* Locks are completely disabled. Return success. */ @@ -405,135 +659,27 @@ make_dotlock (dotlock_t h, long timeout) return 0; } - for (;;) + do { -#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 ) - { - log_error ( "lock not made: link() failed: %s\n", strerror(errno) ); - return -1; - } - - 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++ ; - } - 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 */ - } - 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*/ +#ifdef HAVE_DOSISH_SYSTEM + ret = dotlock_take_w32 (h, timeout, &backoff); +#else /*!HAVE_DOSISH_SYSTEM*/ + ret = dotlock_take_unix (h, timeout, &backoff); +#endif /*!HAVE_DOSISH_SYSTEM*/ } - /*NOTREACHED*/ + while (ret == 1); + + return ret; } -/* Release a lock. Returns 0 on success. */ -int -release_dotlock (dotlock_t h) + +#ifdef HAVE_POSIX_SYSTEM +/* Unix specific code of release_dotlock. */ +static int +dotlock_release_unix (dotlock_t h) { -#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; - - if ( h->disable ) - return 0; - - if ( !h->locked ) - { - log_debug("Oops, `%s' is not locked\n", h->lockname); - return 0; - } - -#ifdef HAVE_DOSISH_SYSTEM - { - OVERLAPPED ovl; - - 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 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; + OVERLAPPED ovl; - *same_node = 0; - expected_len = 10 + 1 + h->nodename_len + 1; - if ( expected_len >= sizeof buffer_space) + memset (&ovl, 0, sizeof ovl); + if (!UnlockFileEx (h->lockhd, 0, 1, 0, &ovl)) { - buffer = jnlib_malloc (expected_len); - if (!buffer) - return -1; - } - else - buffer = buffer_space; - - 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. */ + 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); - - 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 ) - { - 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; + return 0; } -#endif /* !HAVE_DOSISH_SYSTEM */ +#endif /*HAVE_DOSISH_SYSTEM */ +/* 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_debug("Oops, `%s' is not locked\n", h->lockname); + return 0; + } + +#ifdef HAVE_DOSISH_SYSTEM + ret = dotlock_release_w32 (h); +#else + ret = dotlock_release_unix (h); +#endif + + if (!ret) + h->locked = 0; + return ret; +} + + + /* 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 407a80b37..276a6cd0f 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 be131964d..4b5f2f141 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,12 @@ +2011-09-23 Werner Koch + + * 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 * free-packet.c (free_public_key): Allow a NULL argument. diff --git a/g10/gpg.c b/g10/gpg.c index 8326ee7e3..51661b366 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 9f46ab39c..9328343a1 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 f7642485a..e4b97096f 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 12356e23c..480c0e9bd 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 09f31aa5d..968d06b3c 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 2b998e2b2..60c1d3d31 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 180b0d96a..972a7eaaf 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 387bb6f32..198fde076 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 dab6c5739..5f80e0998 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" @@ -2521,10 +2534,6 @@ msgstr "" 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 "" @@ -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 f08e0f80f..87f94e210 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 fe5d0e741..9d1a6ef01 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; } }