[svn] gpgme - r1476 - trunk/src
svn author marcus
cvs at cvs.gnupg.org
Wed Jun 9 15:33:32 CEST 2010
Author: marcus
Date: 2010-06-09 15:33:31 +0200 (Wed, 09 Jun 2010)
New Revision: 1476
Modified:
trunk/src/ChangeLog
trunk/src/w32-io.c
Log:
2010-06-09 Marcus Brinkmann <marcus at g10code.de>
* w32-io.c [HAVE_W32CE_SYSTEM]: Include assuan.h and winioctl.h.
(GPGCEDEV_IOCTL_UNBLOCK) [HAVE_W32CE_SYSTEM]: Define.
(set_synchronize) [HAVE_W32CE_SYSTEM]: Stub it out.
(is_socket): Allow to return -1 for auto-detect (old behaviour).
(is_socket) [HAVE_W32CE_SYSTEM]: Return -1.
(reader): Handle auto-detect case. Handle ctx->stop_me before
checking for EOF.
(destroy_reader) [HAVE_W32CE_SYSTEM]: Unblock a pending reader.
(writer): Handle auto-detect case. Handle ctx->stop_me with
ERROR_BUSY.
(destroy_writer) [HAVE_W32CE_SYSTEM]: Unblock a pending writer.
(_gpgme_io_pipe) [HAVE_W32CE_SYSTEM]: Implement in terms of a
half-pipe.
(build_commandline) [HAVE_W32CE_SYSTEM]: New function.
(_gpgme_io_spawn) [HAVE_W32CE_SYSTEM]: Implement it differently
for this platform.
(_gpgme_io_fd2str) [HAVE_W32CE_SYSTEM]: Implement it for RVIDs.
(_gpgme_io_dup) [HAVE_W32CE_SYSTEM]: Stub it out.
Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog 2010-06-09 13:23:30 UTC (rev 1475)
+++ trunk/src/ChangeLog 2010-06-09 13:33:31 UTC (rev 1476)
@@ -1,5 +1,24 @@
2010-06-09 Marcus Brinkmann <marcus at g10code.de>
+ * w32-io.c [HAVE_W32CE_SYSTEM]: Include assuan.h and winioctl.h.
+ (GPGCEDEV_IOCTL_UNBLOCK) [HAVE_W32CE_SYSTEM]: Define.
+ (set_synchronize) [HAVE_W32CE_SYSTEM]: Stub it out.
+ (is_socket): Allow to return -1 for auto-detect (old behaviour).
+ (is_socket) [HAVE_W32CE_SYSTEM]: Return -1.
+ (reader): Handle auto-detect case. Handle ctx->stop_me before
+ checking for EOF.
+ (destroy_reader) [HAVE_W32CE_SYSTEM]: Unblock a pending reader.
+ (writer): Handle auto-detect case. Handle ctx->stop_me with
+ ERROR_BUSY.
+ (destroy_writer) [HAVE_W32CE_SYSTEM]: Unblock a pending writer.
+ (_gpgme_io_pipe) [HAVE_W32CE_SYSTEM]: Implement in terms of a
+ half-pipe.
+ (build_commandline) [HAVE_W32CE_SYSTEM]: New function.
+ (_gpgme_io_spawn) [HAVE_W32CE_SYSTEM]: Implement it differently
+ for this platform.
+ (_gpgme_io_fd2str) [HAVE_W32CE_SYSTEM]: Implement it for RVIDs.
+ (_gpgme_io_dup) [HAVE_W32CE_SYSTEM]: Stub it out.
+
* gpgme-tool.c (result_add_timestamp): Add missing NULL argument.
(result_sign_to_xml): Protect against NULL fingerprint.
(struct server): New members input_fd, input_filename,
Modified: trunk/src/w32-io.c
===================================================================
--- trunk/src/w32-io.c 2010-06-09 13:23:30 UTC (rev 1475)
+++ trunk/src/w32-io.c 2010-06-09 13:33:31 UTC (rev 1476)
@@ -33,6 +33,13 @@
#include <windows.h>
#include <io.h>
+#ifdef HAVE_W32CE_SYSTEM
+#include <assuan.h>
+#include <winioctl.h>
+#define GPGCEDEV_IOCTL_UNBLOCK \
+ CTL_CODE (FILE_DEVICE_STREAMS, 2050, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#endif
+
#include "util.h"
#include "sema.h"
#include "priv-io.h"
@@ -154,6 +161,9 @@
static HANDLE
set_synchronize (HANDLE hd)
{
+#ifdef HAVE_W32CE_SYSTEM
+ return hd;
+#else
HANDLE new_hd;
/* For NT we have to set the sync flag. It seems that the only way
@@ -171,13 +181,18 @@
CloseHandle (hd);
return new_hd;
+#endif
}
-/* Return true if HD refers to a socket. */
+/* Return 1 if HD refers to a socket, 0 if it does not refer to a
+ socket, and -1 for unknown (autodetect). */
static int
is_socket (HANDLE hd)
{
+#ifdef HAVE_W32CE_SYSTEM
+ return -1;
+#else
/* We need to figure out whether we are working on a socket or on a
handle. A trivial way would be to check for the return code of
recv and see if it is WSAENOTSOCK. However the recv may block
@@ -193,12 +208,14 @@
only if it is supported by the service provider. Tests on a
stock XP using a local TCP socket show that it does not work. */
DWORD dummyflags, dummyoutsize, dummyinsize, dummyinst;
+
if (GetFileType (hd) == FILE_TYPE_PIPE
&& !GetNamedPipeInfo (hd, &dummyflags, &dummyoutsize,
&dummyinsize, &dummyinst))
return 1; /* Function failed; thus we assume it is a socket. */
else
return 0; /* Success; this is not a socket. */
+#endif
}
@@ -243,7 +260,7 @@
TRACE_LOG2 ("%s %d bytes", sock? "receiving":"reading", nbytes);
- if (sock)
+ if (sock == -1 || sock == 1)
{
int n;
@@ -251,6 +268,17 @@
ctx->buffer + ctx->writepos, nbytes, 0);
if (n < 0)
{
+ if (sock == -1)
+ {
+ if (WSAGetLastError () == WSAENOTSOCK)
+ {
+ sock = 0;
+ goto try_readfile;
+ }
+ else
+ sock = 1;
+ }
+
ctx->error_code = (int) WSAGetLastError ();
if (ctx->error_code == ERROR_BROKEN_PIPE)
{
@@ -268,10 +296,13 @@
}
else
{
+ try_readfile:
if (!ReadFile (ctx->file_hd,
ctx->buffer + ctx->writepos, nbytes, &nread, NULL))
{
ctx->error_code = (int) GetLastError ();
+ /* NOTE (W32CE): Do not ignore ERROR_BUSY! Check at
+ least stop_me if that happens. */
if (ctx->error_code == ERROR_BROKEN_PIPE)
{
ctx->eof = 1;
@@ -285,20 +316,21 @@
break;
}
}
+ LOCK (ctx->mutex);
+ if (ctx->stop_me)
+ {
+ UNLOCK (ctx->mutex);
+ break;
+ }
if (!nread)
{
ctx->eof = 1;
TRACE_LOG ("got eof");
+ UNLOCK (ctx->mutex);
break;
}
TRACE_LOG1 ("got %u bytes", nread);
- LOCK (ctx->mutex);
- if (ctx->stop_me)
- {
- UNLOCK (ctx->mutex);
- break;
- }
ctx->writepos = (ctx->writepos + nread) % READBUF_SIZE;
if (!SetEvent (ctx->have_data_ev))
TRACE_LOG2 ("SetEvent (0x%x) failed: ec=%d", ctx->have_data_ev,
@@ -403,6 +435,19 @@
SetEvent (ctx->have_space_ev);
UNLOCK (ctx->mutex);
+#ifdef HAVE_W32CE_SYSTEM
+ /* Scenario: We never create a full pipe, but already started
+ reading. Then we need to unblock the reader in the pipe driver
+ to make our reader thread notice that we want it to go away. */
+
+ if (!DeviceIoControl (ctx->file_hd, GPGCEDEV_IOCTL_UNBLOCK,
+ NULL, 0, NULL, 0, NULL, NULL))
+ {
+ TRACE1 (DEBUG_SYSIO, "gpgme:destroy_reader", ctx->file_hd,
+ "unblock control call failed for thread %p", ctx->thread_hd);
+ }
+#endif
+
TRACE1 (DEBUG_SYSIO, "gpgme:destroy_reader", ctx->file_hd,
"waiting for termination of thread %p", ctx->thread_hd);
WaitForSingleObject (ctx->stopped, INFINITE);
@@ -603,16 +648,27 @@
/* Note that CTX->nbytes is not zero at this point, because
_gpgme_io_write always writes at least 1 byte before waking
us up, unless CTX->stop_me is true, which we catch above. */
- if (sock)
+ if (sock == -1 || sock == 1)
{
/* We need to try send first because a socket handle can't
be used with WriteFile. */
int n;
-
+
n = send (handle_to_socket (ctx->file_hd),
ctx->buffer, ctx->nbytes, 0);
if (n < 0)
{
+ if (sock == -1)
+ {
+ if (WSAGetLastError () == WSAENOTSOCK)
+ {
+ sock = 0;
+ goto try_writefile;
+ }
+ else
+ sock = 1;
+ }
+
ctx->error_code = (int) WSAGetLastError ();
ctx->error = 1;
TRACE_LOG1 ("send error: ec=%d", ctx->error_code);
@@ -622,9 +678,17 @@
}
else
{
+ try_writefile:
if (!WriteFile (ctx->file_hd, ctx->buffer,
ctx->nbytes, &nwritten, NULL))
{
+ if (GetLastError () == ERROR_BUSY)
+ {
+ /* Probably stop_me is set now. */
+ TRACE_LOG ("pipe busy (unblocked?)");
+ continue;
+ }
+
ctx->error_code = (int) GetLastError ();
ctx->error = 1;
TRACE_LOG1 ("write error: ec=%d", ctx->error_code);
@@ -732,6 +796,19 @@
if (ctx->have_data)
SetEvent (ctx->have_data);
UNLOCK (ctx->mutex);
+
+#ifdef HAVE_W32CE_SYSTEM
+ /* Scenario: We never create a full pipe, but already started
+ reading. Then we need to unblock the reader in the pipe driver
+ to make our reader thread notice that we want it to go away. */
+
+ if (!DeviceIoControl (ctx->file_hd, GPGCEDEV_IOCTL_UNBLOCK,
+ NULL, 0, NULL, 0, NULL, NULL))
+ {
+ TRACE1 (DEBUG_SYSIO, "gpgme:destroy_writer", ctx->file_hd,
+ "unblock control call failed for thread %p", ctx->thread_hd);
+ }
+#endif
TRACE1 (DEBUG_SYSIO, "gpgme:destroy_writer", ctx->file_hd,
"waiting for termination of thread %p", ctx->thread_hd);
@@ -894,11 +971,40 @@
{
HANDLE rh;
HANDLE wh;
- SECURITY_ATTRIBUTES sec_attr;
+
+#ifdef HAVE_W32CE_SYSTEM
+ HANDLE hd;
+ int rvid;
+
TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_pipe", filedes,
"inherit_idx=%i (GPGME uses it for %s)",
inherit_idx, inherit_idx ? "reading" : "writing");
+ hd = _assuan_w32ce_prepare_pipe (&rvid, !inherit_idx);
+ if (hd == INVALID_HANDLE_VALUE)
+ {
+ TRACE_LOG1 ("_assuan_w32ce_prepare_pipe failed: ec=%d",
+ (int) GetLastError ());
+ /* FIXME: Should translate the error code. */
+ gpg_err_set_errno (EIO);
+ return TRACE_SYSRES (-1);
+ }
+
+ if (inherit_idx == 0)
+ {
+ /* FIXME: For now. We need to detect them at close. */
+ rh = (void*) ((rvid << 1) | 1);
+ wh = hd;
+ }
+ else
+ {
+ rh = hd;
+ /* FIXME: For now. We need to detect them at close. */
+ wh = (void*) ((rvid << 1) | 1);
+ }
+#else
+ SECURITY_ATTRIBUTES sec_attr;
+
memset (&sec_attr, 0, sizeof (sec_attr));
sec_attr.nLength = sizeof (sec_attr);
sec_attr.bInheritHandle = FALSE;
@@ -914,7 +1020,6 @@
/* Make one end inheritable. */
if (inherit_idx == 0)
{
- struct writer_context_s *ctx;
HANDLE hd;
if (!DuplicateHandle (GetCurrentProcess(), rh,
GetCurrentProcess(), &hd, 0,
@@ -930,22 +1035,9 @@
}
CloseHandle (rh);
rh = hd;
-
- ctx = find_writer (handle_to_fd (wh), 0);
- assert (ctx == NULL);
- ctx = find_writer (handle_to_fd (wh), 1);
- if (!ctx)
- {
- CloseHandle (rh);
- CloseHandle (wh);
- /* FIXME: Should translate the error code. */
- gpg_err_set_errno (EIO);
- return TRACE_SYSRES (-1);
- }
}
else if (inherit_idx == 1)
{
- struct reader_context_s *ctx;
HANDLE hd;
if (!DuplicateHandle( GetCurrentProcess(), wh,
GetCurrentProcess(), &hd, 0,
@@ -961,14 +1053,38 @@
}
CloseHandle (wh);
wh = hd;
+ }
+#endif
+ if (inherit_idx == 0)
+ {
+ struct writer_context_s *ctx;
+ ctx = find_writer (handle_to_fd (wh), 0);
+ assert (ctx == NULL);
+ ctx = find_writer (handle_to_fd (wh), 1);
+ if (!ctx)
+ {
+#ifndef HAVE_W32CE_SYSTEM
+ CloseHandle (rh);
+#endif
+ CloseHandle (wh);
+ /* FIXME: Should translate the error code. */
+ gpg_err_set_errno (EIO);
+ return TRACE_SYSRES (-1);
+ }
+ }
+ else if (inherit_idx == 1)
+ {
+ struct reader_context_s *ctx;
ctx = find_reader (handle_to_fd (rh), 0);
assert (ctx == NULL);
ctx = find_reader (handle_to_fd (rh), 1);
if (!ctx)
{
CloseHandle (rh);
+#ifndef HAVE_W32CE_SYSTEM
CloseHandle (wh);
+#endif
/* FIXME: Should translate the error code. */
gpg_err_set_errno (EIO);
return TRACE_SYSRES (-1);
@@ -995,6 +1111,12 @@
return TRACE_SYSRES (-1);
}
+#ifdef HAVE_W32CE_SYSTEM
+ /* FIXME: For now: This is a rendezvous id. */
+ if (fd & 1)
+ return TRACE_SYSRES (0);
+#endif
+
kill_reader (fd);
kill_writer (fd);
LOCK (notify_table_lock);
@@ -1066,7 +1188,105 @@
return 0;
}
+#ifdef HAVE_W32CE_SYSTEM
+static char *
+build_commandline (char **argv, int fd0, int fd0_isnull,
+ int fd1, int fd1_isnull,
+ int fd2, int fd2_isnull)
+{
+ int i, n;
+ const char *s;
+ char *buf, *p;
+ char fdbuf[3*30];
+ p = fdbuf;
+ *p = 0;
+
+ strcpy (p, "-&S0=null ");
+ p += strlen (p);
+ if (fd0 != -1)
+ {
+ /* FIXME */
+ if (fd0 & 1)
+ fd0 = fd0 >> 1;
+
+ if (fd0_isnull)
+ strcpy (p, "-&S0=null ");
+ else
+ snprintf (p, 25, "-&S0=%d ", (int)fd0);
+ p += strlen (p);
+ }
+ if (fd1 != -1)
+ {
+ /* FIXME */
+ if (fd1 & 1)
+ fd1 = fd1 >> 1;
+
+ if (fd1_isnull)
+ strcpy (p, "-&S1=null ");
+ else
+ snprintf (p, 25, "-&S1=%d ", (int)fd1);
+ p += strlen (p);
+ }
+ if (fd2 != -1)
+ {
+ /* FIXME */
+ if (fd2 & 1)
+ fd2 = fd2 >> 1;
+
+ if (fd2_isnull)
+ strcpy (p, "-&S2=null ");
+ else
+ snprintf (p, 25, "-&S2=%d ", (int)fd2);
+ p += strlen (p);
+ }
+ strcpy (p, "-&S2=null ");
+ p += strlen (p);
+
+ n = strlen (fdbuf);
+ for (i=0; (s = argv[i]); i++)
+ {
+ if (!i)
+ continue; /* Ignore argv[0]. */
+ n += strlen (s) + 1 + 2; /* (1 space, 2 quoting) */
+ for (; *s; s++)
+ if (*s == '\"')
+ n++; /* Need to double inner quotes. */
+ }
+ n++;
+ buf = p = malloc (n);
+ if (! buf)
+ return NULL;
+
+ p = stpcpy (p, fdbuf);
+ for (i = 0; argv[i]; i++)
+ {
+ if (!i)
+ continue; /* Ignore argv[0]. */
+ if (i > 1)
+ p = stpcpy (p, " ");
+
+ if (! *argv[i]) /* Empty string. */
+ p = stpcpy (p, "\"\"");
+ else if (strpbrk (argv[i], " \t\n\v\f\""))
+ {
+ p = stpcpy (p, "\"");
+ for (s = argv[i]; *s; s++)
+ {
+ *p++ = *s;
+ if (*s == '\"')
+ *p++ = *s;
+ }
+ *p++ = '\"';
+ *p = 0;
+ }
+ else
+ p = stpcpy (p, argv[i]);
+ }
+
+ return buf;
+}
+#else
static char *
build_commandline (char **argv)
{
@@ -1120,6 +1340,7 @@
return buf;
}
+#endif
int
@@ -1128,7 +1349,6 @@
void (*atfork) (void *opaque, int reserved),
void *atforkvalue, pid_t *r_pid)
{
- SECURITY_ATTRIBUTES sec_attr;
PROCESS_INFORMATION pi =
{
NULL, /* returns process handle */
@@ -1136,10 +1356,85 @@
0, /* returns pid */
0 /* returns tid */
};
- STARTUPINFO si;
- int cr_flags = (CREATE_DEFAULT_ERROR_MODE
- | GetPriorityClass (GetCurrentProcess ()));
int i;
+
+#ifdef HAVE_W32CE_SYSTEM
+ int fd_in = -1;
+ int fd_out = -1;
+ int fd_err = -1;
+ int fd_in_isnull = 1;
+ int fd_out_isnull = 1;
+ int fd_err_isnull = 1;
+ char *cmdline;
+
+ TRACE_BEG1 (DEBUG_SYSIO, "_gpgme_io_spawn", path,
+ "path=%s", path);
+ i = 0;
+ while (argv[i])
+ {
+ TRACE_LOG2 ("argv[%2i] = %s", i, argv[i]);
+ i++;
+ }
+
+ for (i = 0; fd_list[i].fd != -1; i++)
+ {
+ TRACE_LOG3 ("fd_list[%2i] = fd %i, dup_to %i", i, fd_list[i].fd, fd_list[i].dup_to);
+ if (fd_list[i].dup_to == 0)
+ {
+ fd_in = fd_list[i].fd;
+ fd_in_isnull = 0;
+ }
+ else if (fd_list[i].dup_to == 1)
+ {
+ fd_out = fd_list[i].fd;
+ fd_out_isnull = 0;
+ }
+ else if (fd_list[i].dup_to == 2)
+ {
+ fd_err = fd_list[i].fd;
+ fd_err_isnull = 0;
+ }
+ }
+
+ cmdline = build_commandline (argv, fd_in, fd_in_isnull,
+ fd_out, fd_out_isnull, fd_err, fd_err_isnull);
+ if (!cmdline)
+ {
+ TRACE_LOG1 ("build_commandline failed: %s", strerror (errno));
+ return TRACE_SYSRES (-1);
+ }
+
+ fprintf (stderr, "SPAWNY: %s\n", cmdline);
+
+ if (!CreateProcessA (path, /* Program to start. */
+ cmdline, /* Command line arguments. */
+ NULL, /* (not supported) */
+ NULL, /* (not supported) */
+ FALSE, /* (not supported) */
+ (CREATE_SUSPENDED), /* Creation flags. */
+ NULL, /* (not supported) */
+ NULL, /* (not supported) */
+ NULL, /* (not supported) */
+ &pi /* Returns process information.*/
+ ))
+ {
+ TRACE_LOG1 ("CreateProcess failed: ec=%d", (int) GetLastError ());
+ free (cmdline);
+ gpg_err_set_errno (EIO);
+ return TRACE_SYSRES (-1);
+ }
+
+ /* Insert the inherited handles. */
+ for (i = 0; fd_list[i].fd != -1; i++)
+ {
+ /* Return the child name of this handle. */
+ fd_list[i].peer_name = fd_list[i].fd;
+ }
+
+#else
+ SECURITY_ATTRIBUTES sec_attr;
+ STARTUPINFOA si;
+ int cr_flags = CREATE_DEFAULT_ERROR_MODE;
char **args;
char *arg_string;
/* FIXME. */
@@ -1183,7 +1478,7 @@
if (!arg_string)
{
close (tmp_fd);
- DeleteFile (tmp_name);
+ DeleteFileA (tmp_name);
return TRACE_SYSRES (-1);
}
@@ -1196,7 +1491,10 @@
si.hStdError = INVALID_HANDLE_VALUE;
cr_flags |= CREATE_SUSPENDED;
+#ifndef HAVE_W32CE_SYSTEM
cr_flags |= DETACHED_PROCESS;
+ cr_flags |= GetPriorityClass (GetCurrentProcess ());
+#endif
if (!CreateProcessA (_gpgme_get_w32spawn_path (),
arg_string,
&sec_attr, /* process security attributes */
@@ -1211,7 +1509,7 @@
TRACE_LOG1 ("CreateProcess failed: ec=%d", (int) GetLastError ());
free (arg_string);
close (tmp_fd);
- DeleteFile (tmp_name);
+ DeleteFileA (tmp_name);
/* FIXME: Should translate the error code. */
gpg_err_set_errno (EIO);
@@ -1241,7 +1539,7 @@
CloseHandle (pi.hProcess);
close (tmp_fd);
- DeleteFile (tmp_name);
+ DeleteFileA (tmp_name);
/* FIXME: Should translate the error code. */
gpg_err_set_errno (EIO);
@@ -1294,7 +1592,9 @@
close (tmp_fd);
/* The temporary file is deleted by the gpgme-w32spawn process
(hopefully). */
+#endif
+
TRACE_LOG4 ("CreateProcess ready: hProcess=%p, hThread=%p, "
"dwProcessID=%d, dwThreadId=%d",
pi.hProcess, pi.hThread,
@@ -1511,6 +1811,13 @@
int
_gpgme_io_fd2str (char *buf, int buflen, int fd)
{
+#ifdef HAVE_W32CE_SYSTEM
+ /* FIXME: For now. See above. */
+ if (fd & 1)
+ fd = fd >> 1;
+ /* FIXME: The real problems start if fd is not of this type! */
+#endif
+
return snprintf (buf, buflen, "%d", fd);
}
@@ -1518,6 +1825,10 @@
int
_gpgme_io_dup (int fd)
{
+#ifdef HAVE_W32CE_SYSTEM
+ gpg_err_set_errno (EIO);
+ return -1;
+#else
HANDLE handle = fd_to_handle (fd);
HANDLE new_handle = fd_to_handle (fd);
int i;
@@ -1575,6 +1886,7 @@
}
return TRACE_SYSRES (handle_to_fd (new_handle));
+#endif
}
More information about the Gnupg-commits
mailing list