2010-06-10 Marcus Brinkmann <marcus@g10code.de>

* debug.h (TRACE_SUC6): New macro.
	* w32-io.c (MAX_SLAFD): New macro.
	(fd_table): New static variable.
	(new_fd, release_fd): New functions.
	(fd_to_handle, handle_to_fd, handle_to_socket): Remove macros.
	(MAX_READERS, MAX_WRITERS): Increase to 64.
	(notify_table): Increase to MAX_SLAFD.
	(struct reader_context_s, struct writer_context_s): Add member
	file_sock.
	(reader, writer): Use file_hd vs file_sock to decide if socket
	operations to use.  Remove auto-detect mode.
	(create_reader, create_writer): Set file_sock.  Unblock pending
	thread only if this is a pipe fd.
	(_gpgme_io_pipe): Allocate fds from table and return slot indices
	instead of windows handles.  This allows to properly handle RVIDs.
	(_gpgme_io_close): Handle dup'ed file descriptors.
	(build_commandline) [HAVE_W32_SYSTEM]: Use RVID from fd table now.
	(_gpgme_io_spawn): Use fd table now.
	(_gpgme_io_fd2str): Use RVID from fd table now.
	(_gpgme_io_dup): Implement using fd table.
	(_gpgme_io_socket): Allocate fds from table.
	(_gpgme_io_connect): Use fd from table.
This commit is contained in:
Marcus Brinkmann 2010-06-10 13:49:19 +00:00
parent b243c4263e
commit dbb1112da1
3 changed files with 293 additions and 130 deletions

View File

@ -1,3 +1,30 @@
2010-06-10 Marcus Brinkmann <marcus@g10code.de>
* debug.h (TRACE_SUC6): New macro.
* w32-io.c (MAX_SLAFD): New macro.
(fd_table): New static variable.
(new_fd, release_fd): New functions.
(fd_to_handle, handle_to_fd, handle_to_socket): Remove macros.
(MAX_READERS, MAX_WRITERS): Increase to 64.
(notify_table): Increase to MAX_SLAFD.
(struct reader_context_s, struct writer_context_s): Add member
file_sock.
(reader, writer): Use file_hd vs file_sock to decide if socket
operations to use. Remove auto-detect mode.
(create_reader, create_writer): Set file_sock. Unblock pending
thread only if this is a pipe fd.
(_gpgme_io_pipe): Allocate fds from table and return slot indices
instead of windows handles. This allows to properly handle RVIDs.
(_gpgme_io_close): Handle dup'ed file descriptors.
(build_commandline) [HAVE_W32_SYSTEM]: Use RVID from fd table now.
(_gpgme_io_spawn): Use fd table now.
(_gpgme_io_fd2str): Use RVID from fd table now.
(_gpgme_io_dup): Implement using fd table.
(_gpgme_io_socket): Allocate fds from table.
(_gpgme_io_connect): Use fd from table.
* w32-glib-io.c (find_channel): Check that the slot is used.
2010-06-09 Marcus Brinkmann <marcus@g10code.de>
* w32-io.c [HAVE_W32CE_SYSTEM]: Include assuan.h and winioctl.h.

View File

@ -204,6 +204,10 @@ void _gpgme_debug_frame_end (void);
_gpgme_debug (_gpgme_trace_level, "%s: leave: " fmt "\n", \
_gpgme_trace_func, arg1, arg2, arg3, arg4, arg5), \
_gpgme_debug_frame_end (), 0
#define TRACE_SUC6(fmt, arg1, arg2, arg3, arg4, arg5, arg6) \
_gpgme_debug (_gpgme_trace_level, "%s: leave: " fmt "\n", \
_gpgme_trace_func, arg1, arg2, arg3, arg4, arg5, arg6), \
_gpgme_debug_frame_end (), 0
#define TRACE_LOG(fmt) \
_gpgme_debug (_gpgme_trace_level, "%s: check: %s=%p, " fmt "\n", \

View File

@ -46,22 +46,87 @@
#include "debug.h"
/* We assume that a HANDLE can be represented by an int which should
be true for all i386 systems (HANDLE is defined as void *) and
these are the only systems for which Windows is available. Further
we assume that -1 denotes an invalid handle. */
/* FIXME: Optimize. */
#define MAX_SLAFD 512
static struct
{
int used;
/* If this is not INVALID_HANDLE_VALUE, then it's a handle. */
HANDLE handle;
/* If this is not INVALID_SOCKET, then it's a Windows socket. */
int socket;
/* If this is not 0, then it's a rendezvous ID for the pipe server. */
int rvid;
/* DUP_FROM is -1 if this file descriptor was allocated by pipe or
socket functions. Only then should the handle or socket be
destroyed when this FD is closed. This, together with the fact
that dup'ed file descriptors are closed before the file
descriptors from which they are dup'ed are closed, ensures that
the handle or socket is always valid, and shared among all file
descriptors refering to the same underlying object.
The logic behind this is that there is only one reason for us to
dup file descriptors anyway: to allow simpler book-keeping of
file descriptors shared between GPGME and libassuan, which both
want to close something. Using the same handle for these
duplicates works just fine. */
int dup_from;
} fd_table[MAX_SLAFD];
/* Returns the FD or -1 on resource limit. */
int
new_fd (void)
{
int idx;
for (idx = 0; idx < MAX_SLAFD; idx++)
if (! fd_table[idx].used)
break;
if (idx == MAX_SLAFD)
{
gpg_err_set_errno (EIO);
return -1;
}
fd_table[idx].used = 1;
fd_table[idx].handle = INVALID_HANDLE_VALUE;
fd_table[idx].socket = INVALID_SOCKET;
fd_table[idx].rvid = 0;
fd_table[idx].dup_from = -1;
return idx;
}
void
release_fd (int fd)
{
if (fd < 0 || fd >= MAX_SLAFD || !fd_table[fd].used)
return;
fd_table[fd].used = 0;
fd_table[fd].handle = INVALID_HANDLE_VALUE;
fd_table[fd].socket = INVALID_SOCKET;
fd_table[fd].rvid = 0;
fd_table[fd].dup_from = -1;
}
#define fd_to_handle(a) ((HANDLE)(a))
#define handle_to_fd(a) ((int)(a))
#define pid_to_handle(a) ((HANDLE)(a))
#define handle_to_pid(a) ((int)(a))
#define handle_to_socket(a) ((unsigned int)(a))
#define READBUF_SIZE 4096
#define WRITEBUF_SIZE 4096
#define PIPEBUF_SIZE 4096
#define MAX_READERS 40
#define MAX_WRITERS 40
#define MAX_READERS 64
#define MAX_WRITERS 64
static struct
{
@ -69,13 +134,14 @@ static struct
int fd;
_gpgme_close_notify_handler_t handler;
void *value;
} notify_table[256];
} notify_table[MAX_SLAFD];
DEFINE_STATIC_LOCK (notify_table_lock);
struct reader_context_s
{
HANDLE file_hd;
int file_sock;
HANDLE thread_hd;
int refcount;
@ -110,6 +176,7 @@ DEFINE_STATIC_LOCK (reader_table_lock);
struct writer_context_s
{
HANDLE file_hd;
int file_sock;
HANDLE thread_hd;
int refcount;
@ -229,7 +296,10 @@ reader (void *arg)
TRACE_BEG1 (DEBUG_SYSIO, "gpgme:reader", ctx->file_hd,
"thread=%p", ctx->thread_hd);
sock = is_socket (ctx->file_hd);
if (ctx->file_hd != INVALID_HANDLE_VALUE)
sock = 0;
else
sock = 1;
for (;;)
{
@ -260,25 +330,13 @@ reader (void *arg)
TRACE_LOG2 ("%s %d bytes", sock? "receiving":"reading", nbytes);
if (sock == -1 || sock == 1)
if (sock)
{
int n;
n = recv (handle_to_socket (ctx->file_hd),
ctx->buffer + ctx->writepos, nbytes, 0);
n = recv (ctx->file_sock, 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)
{
@ -296,7 +354,6 @@ reader (void *arg)
}
else
{
try_readfile:
if (!ReadFile (ctx->file_hd,
ctx->buffer + ctx->writepos, nbytes, &nread, NULL))
{
@ -348,7 +405,7 @@ reader (void *arg)
static struct reader_context_s *
create_reader (HANDLE fd)
create_reader (int fd)
{
struct reader_context_s *ctx;
SECURITY_ATTRIBUTES sec_attr;
@ -367,7 +424,14 @@ create_reader (HANDLE fd)
return NULL;
}
ctx->file_hd = fd;
if (fd < 0 || fd >= MAX_SLAFD || !fd_table[fd].used)
{
TRACE_SYSERR (EIO);
return NULL;
}
ctx->file_hd = fd_table[fd].handle;
ctx->file_sock = fd_table[fd].socket;
ctx->refcount = 1;
ctx->have_data_ev = CreateEvent (&sec_attr, TRUE, FALSE, NULL);
if (ctx->have_data_ev)
@ -440,11 +504,14 @@ destroy_reader (struct reader_context_s *ctx)
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))
if (ctx->file_hd != INVALID_HANDLE_VALUE)
{
TRACE1 (DEBUG_SYSIO, "gpgme:destroy_reader", ctx->file_hd,
"unblock control call failed for thread %p", ctx->thread_hd);
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
@ -491,7 +558,7 @@ find_reader (int fd, int start_it)
if (i != reader_table_size)
{
rd = create_reader (fd_to_handle (fd));
rd = create_reader (fd);
if (rd)
{
reader_table[i].fd = fd;
@ -614,7 +681,10 @@ writer (void *arg)
TRACE_BEG1 (DEBUG_SYSIO, "gpgme:writer", ctx->file_hd,
"thread=%p", ctx->thread_hd);
sock = is_socket (ctx->file_hd);
if (ctx->file_hd != INVALID_HANDLE_VALUE)
sock = 0;
else
sock = 1;
for (;;)
{
@ -648,27 +718,15 @@ writer (void *arg)
/* 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 == -1 || sock == 1)
if (sock)
{
/* 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);
n = send (ctx->file_sock, 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);
@ -678,7 +736,6 @@ writer (void *arg)
}
else
{
try_writefile:
if (!WriteFile (ctx->file_hd, ctx->buffer,
ctx->nbytes, &nwritten, NULL))
{
@ -711,7 +768,7 @@ writer (void *arg)
static struct writer_context_s *
create_writer (HANDLE fd)
create_writer (int fd)
{
struct writer_context_s *ctx;
SECURITY_ATTRIBUTES sec_attr;
@ -730,7 +787,14 @@ create_writer (HANDLE fd)
return NULL;
}
ctx->file_hd = fd;
if (fd < 0 || fd >= MAX_SLAFD || !fd_table[fd].used)
{
TRACE_SYSERR (EIO);
return NULL;
}
ctx->file_hd = fd_table[fd].handle;
ctx->file_sock = fd_table[fd].socket;
ctx->refcount = 1;
ctx->have_data = CreateEvent (&sec_attr, TRUE, FALSE, NULL);
if (ctx->have_data)
@ -853,7 +917,7 @@ find_writer (int fd, int start_it)
if (i != writer_table_size)
{
wt = create_writer (fd_to_handle (fd));
wt = create_writer (fd);
if (wt)
{
writer_table[i].fd = fd;
@ -969,22 +1033,39 @@ _gpgme_io_write (int fd, const void *buffer, size_t count)
int
_gpgme_io_pipe (int filedes[2], int inherit_idx)
{
HANDLE rh;
HANDLE wh;
int rfd;
int wfd;
#ifdef HAVE_W32CE_SYSTEM
HANDLE hd;
int rvid;
#else
HANDLE rh;
HANDLE wh;
SECURITY_ATTRIBUTES sec_attr;
#endif
TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_pipe", filedes,
"inherit_idx=%i (GPGME uses it for %s)",
inherit_idx, inherit_idx ? "reading" : "writing");
rfd = new_fd ();
if (rfd == -1)
return TRACE_SYSRES (-1);
wfd = new_fd ();
if (wfd == -1)
{
release_fd (rfd);
return TRACE_SYSRES (-1);
}
#ifdef HAVE_W32CE_SYSTEM
hd = _assuan_w32ce_prepare_pipe (&rvid, !inherit_idx);
if (hd == INVALID_HANDLE_VALUE)
{
TRACE_LOG1 ("_assuan_w32ce_prepare_pipe failed: ec=%d",
(int) GetLastError ());
release_fd (rfd);
release_fd (wfd);
/* FIXME: Should translate the error code. */
gpg_err_set_errno (EIO);
return TRACE_SYSRES (-1);
@ -992,18 +1073,16 @@ _gpgme_io_pipe (int filedes[2], int inherit_idx)
if (inherit_idx == 0)
{
/* FIXME: For now. We need to detect them at close. */
rh = (void*) ((rvid << 1) | 1);
wh = hd;
fd_table[rfd].rvid = rvid;
fd_table[wfd].handle = hd;
}
else
{
rh = hd;
/* FIXME: For now. We need to detect them at close. */
wh = (void*) ((rvid << 1) | 1);
fd_table[rfd].handle = hd;
fd_table[wfd].rvid = rvid;
}
#else
SECURITY_ATTRIBUTES sec_attr;
memset (&sec_attr, 0, sizeof (sec_attr));
sec_attr.nLength = sizeof (sec_attr);
@ -1012,6 +1091,8 @@ _gpgme_io_pipe (int filedes[2], int inherit_idx)
if (!CreatePipe (&rh, &wh, &sec_attr, PIPEBUF_SIZE))
{
TRACE_LOG1 ("CreatePipe failed: ec=%d", (int) GetLastError ());
release_fd (rfd);
release_fd (wfd);
/* FIXME: Should translate the error code. */
gpg_err_set_errno (EIO);
return TRACE_SYSRES (-1);
@ -1027,6 +1108,8 @@ _gpgme_io_pipe (int filedes[2], int inherit_idx)
{
TRACE_LOG1 ("DuplicateHandle failed: ec=%d",
(int) GetLastError ());
release_fd (rfd);
release_fd (wfd);
CloseHandle (rh);
CloseHandle (wh);
/* FIXME: Should translate the error code. */
@ -1045,6 +1128,8 @@ _gpgme_io_pipe (int filedes[2], int inherit_idx)
{
TRACE_LOG1 ("DuplicateHandle failed: ec=%d",
(int) GetLastError ());
release_fd (rfd);
release_fd (wfd);
CloseHandle (rh);
CloseHandle (wh);
/* FIXME: Should translate the error code. */
@ -1054,20 +1139,25 @@ _gpgme_io_pipe (int filedes[2], int inherit_idx)
CloseHandle (wh);
wh = hd;
}
fd_table[rfd].handle = rh;
fd_table[wfd].handle = wh;
#endif
if (inherit_idx == 0)
{
struct writer_context_s *ctx;
ctx = find_writer (handle_to_fd (wh), 0);
ctx = find_writer (wfd, 0);
assert (ctx == NULL);
ctx = find_writer (handle_to_fd (wh), 1);
ctx = find_writer (wfd, 1);
if (!ctx)
{
#ifndef HAVE_W32CE_SYSTEM
CloseHandle (rh);
#endif
CloseHandle (wh);
/* No way/need to close RVIDs on Windows CE. */
if (fd_table[rfd].handle)
CloseHandle (fd_table[rfd].handle);
if (fd_table[wfd].handle)
CloseHandle (fd_table[wfd].handle);
release_fd (rfd);
release_fd (wfd);
/* FIXME: Should translate the error code. */
gpg_err_set_errno (EIO);
return TRACE_SYSRES (-1);
@ -1076,24 +1166,29 @@ _gpgme_io_pipe (int filedes[2], int inherit_idx)
else if (inherit_idx == 1)
{
struct reader_context_s *ctx;
ctx = find_reader (handle_to_fd (rh), 0);
ctx = find_reader (rfd, 0);
assert (ctx == NULL);
ctx = find_reader (handle_to_fd (rh), 1);
ctx = find_reader (rfd, 1);
if (!ctx)
{
CloseHandle (rh);
#ifndef HAVE_W32CE_SYSTEM
CloseHandle (wh);
#endif
if (fd_table[rfd].handle)
CloseHandle (fd_table[rfd].handle);
/* No way/need to close RVIDs on Windows CE. */
if (fd_table[wfd].handle)
CloseHandle (fd_table[wfd].handle);
release_fd (rfd);
release_fd (wfd);
/* FIXME: Should translate the error code. */
gpg_err_set_errno (EIO);
return TRACE_SYSRES (-1);
}
}
filedes[0] = handle_to_fd (rh);
filedes[1] = handle_to_fd (wh);
return TRACE_SUC2 ("read=%p, write=%p", rh, wh);
filedes[0] = rfd;
filedes[1] = wfd;
return TRACE_SUC6 ("read=0x%x (%p/0x%x), write=0x%x (%p/0x%x)",
rfd, fd_table[rfd].handle, fd_table[rfd].rvid,
wfd, fd_table[wfd].handle, fd_table[wfd].rvid);
}
@ -1103,6 +1198,7 @@ _gpgme_io_close (int fd)
int i;
_gpgme_close_notify_handler_t handler = NULL;
void *value = NULL;
TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_close", fd);
if (fd == -1)
@ -1110,12 +1206,11 @@ _gpgme_io_close (int fd)
gpg_err_set_errno (EBADF);
return TRACE_SYSRES (-1);
}
#ifdef HAVE_W32CE_SYSTEM
/* FIXME: For now: This is a rendezvous id. */
if (fd & 1)
return TRACE_SYSRES (0);
#endif
if (fd < 0 || fd >= MAX_SLAFD || !fd_table[fd].used)
{
gpg_err_set_errno (EBADF);
return TRACE_SYSRES (-1);
}
kill_reader (fd);
kill_writer (fd);
@ -1136,14 +1231,33 @@ _gpgme_io_close (int fd)
if (handler)
handler (fd, value);
if (!CloseHandle (fd_to_handle (fd)))
{
TRACE_LOG1 ("CloseHandle failed: ec=%d", (int) GetLastError ());
/* FIXME: Should translate the error code. */
gpg_err_set_errno (EIO);
return TRACE_SYSRES (-1);
if (fd_table[fd].dup_from == -1)
{
if (fd_table[fd].handle != INVALID_HANDLE_VALUE)
{
if (!CloseHandle (fd_table[fd].handle))
{
TRACE_LOG1 ("CloseHandle failed: ec=%d", (int) GetLastError ());
/* FIXME: Should translate the error code. */
gpg_err_set_errno (EIO);
return TRACE_SYSRES (-1);
}
}
else if (fd_table[fd].socket != INVALID_SOCKET)
{
if (closesocket (fd_table[fd].socket))
{
TRACE_LOG1 ("closesocket failed: ec=%d", (int) WSAGetLastError ());
/* FIXME: Should translate the error code. */
gpg_err_set_errno (EIO);
return TRACE_SYSRES (-1);
}
}
/* Nothing to do for RVIDs. */
}
release_fd (fd);
return TRACE_SYSRES (0);
}
@ -1188,6 +1302,7 @@ _gpgme_io_set_nonblocking (int fd)
return 0;
}
#ifdef HAVE_W32CE_SYSTEM
static char *
build_commandline (char **argv, int fd0, int fd0_isnull,
@ -1202,42 +1317,28 @@ build_commandline (char **argv, int fd0, int fd0_isnull,
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);
snprintf (p, 25, "-&S0=%d ", fd_table[fd0].rvid);
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);
snprintf (p, 25, "-&S1=%d ", fd_table[fd1].rvid);
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);
snprintf (p, 25, "-&S2=%d ", fd_table[fd2].rvid);
p += strlen (p);
}
strcpy (p, "-&S2=null ");
@ -1378,7 +1479,22 @@ _gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags,
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);
int fd = fd_list[i].fd;
TRACE_LOG3 ("fd_list[%2i] = fd %i, dup_to %i", i, fd, fd_list[i].dup_to);
if (fd < 0 || fd >= MAX_SLAFD || !fd_table[fd].used)
{
TRACE_LOG1 ("invalid fd 0x%x", fd);
gpg_err_set_errno (EBADF);
return TRACE_SYSRES (-1);
}
if (fd_table[fd].rvid == 0)
{
TRACE_LOG1 ("fd 0x%x not inheritable (not an RVID)", fd);
gpg_err_set_errno (EBADF);
return TRACE_SYSRES (-1);
}
if (fd_list[i].dup_to == 0)
{
fd_in = fd_list[i].fd;
@ -1428,7 +1544,7 @@ _gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags,
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;
fd_list[i].peer_name = fd_table[fd_list[i].fd].rvid;
}
#else
@ -1749,6 +1865,7 @@ _gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock)
else if (code == WAIT_FAILED)
{
int le = (int) GetLastError ();
#if 0
if (le == ERROR_INVALID_HANDLE)
{
int k;
@ -1765,6 +1882,7 @@ _gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock)
}
TRACE_LOG (" oops, or not???");
}
#endif
TRACE_LOG1 ("WFMO failed: %d", le);
count = -1;
}
@ -1813,9 +1931,11 @@ _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! */
if (fd < 0 || fd >= MAX_SLAFD || !fd_table[fd].used
|| fd_table[fd].rvid == 0)
fd = -1;
else
fd = fd_table[fd].rvid;
#endif
return snprintf (buf, buflen, "%d", fd);
@ -1825,28 +1945,28 @@ _gpgme_io_fd2str (char *buf, int buflen, int fd)
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;
int newfd;
struct reader_context_s *rd_ctx;
struct writer_context_s *wt_ctx;
int i;
TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_dup", fd);
if (!DuplicateHandle (GetCurrentProcess(), handle,
GetCurrentProcess(), &new_handle,
0, FALSE, DUPLICATE_SAME_ACCESS))
if (fd < 0 || fd >= MAX_SLAFD || !fd_table[fd].used)
{
TRACE_LOG1 ("DuplicateHandle failed: ec=%d\n", (int) GetLastError ());
/* FIXME: Translate error code. */
gpg_err_set_errno (EIO);
gpg_err_set_errno (EINVAL);
return TRACE_SYSRES (-1);
}
newfd = new_fd();
if (newfd == -1)
return TRACE_SYSRES (-1);
fd_table[newfd].handle = fd_table[fd].handle;
fd_table[newfd].socket = fd_table[fd].socket;
fd_table[newfd].rvid = fd_table[fd].rvid;
fd_table[newfd].dup_from = fd;
rd_ctx = find_reader (fd, 0);
if (rd_ctx)
{
@ -1860,7 +1980,7 @@ _gpgme_io_dup (int fd)
break;
/* FIXME. */
assert (i != reader_table_size);
reader_table[i].fd = handle_to_fd (new_handle);
reader_table[i].fd = newfd;
reader_table[i].context = rd_ctx;
reader_table[i].used = 1;
UNLOCK (reader_table_lock);
@ -1879,14 +1999,13 @@ _gpgme_io_dup (int fd)
break;
/* FIXME. */
assert (i != writer_table_size);
writer_table[i].fd = handle_to_fd (new_handle);
writer_table[i].fd = newfd;
writer_table[i].context = wt_ctx;
writer_table[i].used = 1;
UNLOCK (writer_table_lock);
}
return TRACE_SYSRES (handle_to_fd (new_handle));
#endif
return TRACE_SYSRES (newfd);
}
@ -1931,18 +2050,25 @@ int
_gpgme_io_socket (int domain, int type, int proto)
{
int res;
int fd;
TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_socket", domain,
"type=%i, protp=%i", type, proto);
fd = new_fd();
if (fd == -1)
return TRACE_SYSRES (-1);
res = socket (domain, type, proto);
if (res == INVALID_SOCKET)
{
release_fd (fd);
gpg_err_set_errno (wsa2errno (WSAGetLastError ()));
return TRACE_SYSRES (-1);
}
fd_table[fd].socket = res;
TRACE_SUC1 ("socket=0x%x", res);
TRACE_SUC2 ("socket=0x%x (0x%x)", fd, fd_table[fd].socket);
return res;
}
@ -1956,7 +2082,13 @@ _gpgme_io_connect (int fd, struct sockaddr *addr, int addrlen)
TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_connect", fd,
"addr=%p, addrlen=%i", addr, addrlen);
res = connect (fd, addr, addrlen);
if (fd < 0 || fd >= MAX_SLAFD || !fd_table[fd].used)
{
gpg_err_set_errno (EBADF);
return TRACE_SYSRES (-1);
}
res = connect (fd_table[fd].socket, addr, addrlen);
if (res)
{
gpg_err_set_errno (wsa2errno (WSAGetLastError ()));