aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2020-10-20 13:38:11 +0200
committerWerner Koch <wk@gnupg.org>2020-10-20 13:38:11 +0200
commitb47c355b18d9537ccc3dd3e80cc1825b018ecff7 (patch)
tree2ca24c9657c4897b67c812a5b6b0249f9d0b6046
parent390497ea115e1aca93feec297a5bd6ae7b1ba6dd (diff)
downloadgnupg-b47c355b18d9537ccc3dd3e80cc1825b018ecff7.tar.gz
w32: Allow Unicode filenames for dotlock
* common/dotlock.c (any8bitchar) [W32]: New. (dotlock_create_w32): Use strconcat and CreateFileW. * common/t-dotlock.c: Source include dotlock.c and modify to allow manual testing on Windows. -- GnuPG-bug-id: 5098 Signed-off-by: Werner Koch <wk@gnupg.org>
-rw-r--r--common/dotlock.c55
-rw-r--r--common/t-dotlock.c164
2 files changed, 192 insertions, 27 deletions
diff --git a/common/dotlock.c b/common/dotlock.c
index 8d9ee5139..f3e4bac28 100644
--- a/common/dotlock.c
+++ b/common/dotlock.c
@@ -471,6 +471,21 @@ map_w32_to_errno (DWORD w32_err)
}
#endif /*HAVE_DOSISH_SYSTEM*/
+
+#ifdef HAVE_W32_SYSTEM
+static int
+any8bitchar (const char *string)
+{
+ if (string)
+ for ( ; *string; string++)
+ if ((*string & 0x80))
+ return 1;
+ return 0;
+}
+#endif /*HAVE_W32_SYSTEM*/
+
+
+
/* Entirely disable all locking. This function should be called
before any locking is done. It may be called right at startup of
@@ -794,7 +809,7 @@ dotlock_create_w32 (dotlock_t h, const char *file_to_lock)
h->next = all_lockfiles;
all_lockfiles = h;
- h->lockname = xtrymalloc ( strlen (file_to_lock) + 6 );
+ h->lockname = strconcat (file_to_lock, EXTSEP_S "lock", NULL);
if (!h->lockname)
{
all_lockfiles = h->next;
@@ -802,7 +817,6 @@ dotlock_create_w32 (dotlock_t h, const char *file_to_lock)
xfree (h);
return NULL;
}
- strcpy (stpcpy(h->lockname, file_to_lock), EXTSEP_S "lock");
/* If would be nice if we would use the FILE_FLAG_DELETE_ON_CLOSE
along with FILE_SHARE_DELETE but that does not work due to a race
@@ -812,25 +826,24 @@ dotlock_create_w32 (dotlock_t h, const char *file_to_lock)
reasons why a lock file can't be created and thus the process
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);
-
- if (wname)
- h->lockhd = CreateFile (wname,
- GENERIC_READ|GENERIC_WRITE,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- NULL, OPEN_ALWAYS, 0, NULL);
- else
- h->lockhd = INVALID_HANDLE_VALUE;
- xfree (wname);
-#else
- h->lockhd = CreateFile (h->lockname,
- GENERIC_READ|GENERIC_WRITE,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- NULL, OPEN_ALWAYS, 0, NULL);
-#endif
- }
+ if (any8bitchar (h->lockname))
+ {
+ wchar_t *wname = utf8_to_wchar (h->lockname);
+
+ if (wname)
+ h->lockhd = CreateFileW (wname,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL, OPEN_ALWAYS, 0, NULL);
+ else
+ h->lockhd = INVALID_HANDLE_VALUE;
+ xfree (wname);
+ }
+ else
+ h->lockhd = CreateFileA (h->lockname,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL, OPEN_ALWAYS, 0, NULL);
if (h->lockhd == INVALID_HANDLE_VALUE)
{
int saveerrno = map_w32_to_errno (GetLastError ());
diff --git a/common/t-dotlock.c b/common/t-dotlock.c
index f7aee09d3..e2d22f66d 100644
--- a/common/t-dotlock.c
+++ b/common/t-dotlock.c
@@ -41,21 +41,165 @@
#include <errno.h>
#include <signal.h>
#include <unistd.h>
+#ifdef HAVE_W32_SYSTEM
+# include "windows.h"
+#endif
#include "dotlock.h"
-#define PGM "t-dotlock"
+#ifdef HAVE_W32_SYSTEM
+#define DIM(v) (sizeof(v)/sizeof((v)[0]))
+
+const char *
+w32_strerror (int ec)
+{
+ static char strerr[256];
+
+ if (ec == -1)
+ ec = (int)GetLastError ();
+#ifdef HAVE_W32CE_SYSTEM
+ /* There is only a wchar_t FormatMessage. It does not make much
+ sense to play the conversion game; we print only the code. */
+ snprintf (strerr, sizeof strerr, "ec=%d", (int)GetLastError ());
+#else
+ FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, ec,
+ MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+ strerr, DIM (strerr)-1, NULL);
+ {
+ /* Strip the CR,LF - we want just the string. */
+ size_t n = strlen (strerr);
+ if (n > 2 && strerr[n-2] == '\r' && strerr[n-1] == '\n' )
+ strerr[n-2] = 0;
+ }
+#endif
+ return strerr;
+}
+
+static wchar_t *
+cp_to_wchar (const char *string, unsigned int codepage)
+{
+ int n;
+ size_t nbytes;
+ wchar_t *result;
+
+ n = MultiByteToWideChar (codepage, 0, string, -1, NULL, 0);
+ if (n < 0)
+ {
+ return NULL;
+ }
+
+ nbytes = (size_t)(n+1) * sizeof(*result);
+ if (nbytes / sizeof(*result) != (n+1))
+ {
+ return NULL;
+ }
+ result = malloc (nbytes);
+ if (!result)
+ return NULL;
+
+ n = MultiByteToWideChar (codepage, 0, string, -1, result, n);
+ if (n < 0)
+ {
+ free (result);
+ result = NULL;
+ }
+ return result;
+}
+
+wchar_t *
+utf8_to_wchar (const char *string)
+{
+ return cp_to_wchar (string, CP_UTF8);
+}
+
+char *
+stpcpy(char *a,const char *b)
+{
+ while( *b )
+ *a++ = *b++;
+ *a = 0;
+
+ return (char*)a;
+}
+
+static char *
+do_strconcat (const char *s1, va_list arg_ptr)
+{
+ const char *argv[48];
+ size_t argc;
+ size_t needed;
+ char *buffer, *p;
+
+ argc = 0;
+ argv[argc++] = s1;
+ needed = strlen (s1);
+ while (((argv[argc] = va_arg (arg_ptr, const char *))))
+ {
+ needed += strlen (argv[argc]);
+ if (argc >= DIM (argv)-1)
+ {
+ return NULL;
+ }
+ argc++;
+ }
+ needed++;
+ buffer = malloc (needed);
+ if (buffer)
+ {
+ for (p = buffer, argc=0; argv[argc]; argc++)
+ p = stpcpy (p, argv[argc]);
+ }
+ return buffer;
+}
+
+/* Concatenate the string S1 with all the following strings up to a
+ NULL. Returns a malloced buffer with the new string or NULL on a
+ malloc error or if too many arguments are given. */
+char *
+strconcat (const char *s1, ...)
+{
+ va_list arg_ptr;
+ char *result;
+
+ if (!s1)
+ result = calloc (1, 1);
+ else
+ {
+ va_start (arg_ptr, s1);
+ result = do_strconcat (s1, arg_ptr);
+ va_end (arg_ptr);
+ }
+ return result;
+}
+#endif /*HAVE_W32_SYSTEM*/
-static volatile int ctrl_c_pending;
+#include "dotlock.c"
+
+#define PGM "t-dotlock"
+#ifndef HAVE_W32_SYSTEM
+static volatile int ctrl_c_pending_flag;
static void
control_c_handler (int signo)
{
(void)signo;
- ctrl_c_pending = 1;
+ ctrl_c_pending_flag = 1;
}
+#endif
+
+
+static int
+ctrl_c_pending (void)
+{
+#if HAVE_W32_SYSTEM
+ static int count;
+ return (++count > 9);
+#else
+ return ctrl_c_pending_flag;
+#endif
+}
static void
@@ -95,7 +239,7 @@ lock_and_unlock (const char *fname)
die ("error creating lock file for '%s': %s", fname, strerror (errno));
inf ("lock created");
- while (!ctrl_c_pending)
+ while (!ctrl_c_pending ())
{
if (dotlock_take (h, -1))
die ("error taking lock");
@@ -119,8 +263,15 @@ main (int argc, char **argv)
if (argc > 1)
fname = argv[1];
else
- fname = "t-dotlock.tmp";
+ {
+#ifdef HAVE_W32_SYSTEM
+ fname = "t-dotâ’¶lock.tmp";
+#else
+ fname = "t-dotlock.tmp";
+#endif
+ }
+#ifndef HAVE_W32_SYSTEM
{
struct sigaction nact;
@@ -128,6 +279,7 @@ main (int argc, char **argv)
nact.sa_flags = 0;
sigaction (SIGINT, &nact, NULL);
}
+#endif
dotlock_create (NULL, 0); /* Initialize (optional). */
@@ -140,6 +292,6 @@ main (int argc, char **argv)
/*
Local Variables:
-compile-command: "cc -Wall -O2 -D_FILE_OFFSET_BITS=64 -o t-dotlock t-dotlock.c dotlock.c"
+compile-command: "cc -Wall -O2 -D_FILE_OFFSET_BITS=64 -o t-dotlock t-dotlock.c"
End:
*/