assuan/
2009-04-08 Marcus Brinkmann <marcus@g10code.de> * assuan.h (_gpgme_io_socket): New prototype. (_ASSUAN_CUSTOM_IO, _assuan_custom_close, _assuan_custom_read) (_assuan_custom_write, _assuan_custom_pipe, _assuan_custom_socket) (_assuan_custom_connect): New macros. * assuan-socket.c (_assuan_close, _assuan_sock_new) (_assuan_sock_connect) [_ASSUAN_CUSTOM_IO]: Use custom I/O function. * assuan-buffer.c (assuan_read_line): Do not handle EAGAIN anymore. * assuan-client.c (_assuan_read_from_server): Likewise. * assuan-handler.c (process_next): Likewise * assuan-inquire.c (assuan_inquire): Likewise. src/ 2009-04-08 Marcus Brinkmann <marcus@g10code.de> * w32-glib-io.c (giochannel_table): New members used, fd, socket. (find_channel): Drop CREATE argument. (new_dummy_channel_from_fd, new_channel_from_fd) (new_channel_from_socket): New functions. (_gpgm_io_fd2str): Implement for sockets. (_gpgme_io_write, _gpgme_io_read): Translate EAGAIN errors correctly. (_gpgme_io_pipe): Fix for new channel bookkeeping. (_gpgme_io_close, _gpgme_io_dup): Likewise. (wsa2errno, _gpgme_io_socket, _gpgme_io_connect): New. * w32-io.c (MAX_READERS, MAX_WRITERS): Bump up to 40. (wsa2errno, _gpgme_io_socket, _gpgme_io_connect): New. * w32-qt-io.cpp (_gpgme_io_socket, _gpgme_io_connect): New stubs. * version.c [HAVE_W32_SYSTEM]: Include "windows.h. (do_subsystem_inits) [HAVE_W32_SYSTEM]: Call WSAStartup. * engine-assuan.c (llass_status_handler): Ignore EAGAIN errors.
This commit is contained in:
parent
6f8aa0e29d
commit
d255b4bec9
7
TODO
7
TODO
@ -1,5 +1,12 @@
|
||||
Hey Emacs, this is -*- outline -*- mode!
|
||||
|
||||
* IMPORTANT
|
||||
** When using descriptor passing, we need to set the fd to blocking before
|
||||
issueing simple commands, because we are mixing synchronous
|
||||
commands into potentially asynchronous operations.
|
||||
** Might want to implement nonblock for w32 native backend! Right now,
|
||||
we block reading the next line with assuan.
|
||||
|
||||
* Before release:
|
||||
** Figure out if _gpgme_io_pipe should pre-create reader/writer and if we
|
||||
then can use !start_it in most invocations. Note that gpgme_io_dup
|
||||
|
@ -1,3 +1,16 @@
|
||||
2009-04-08 Marcus Brinkmann <marcus@g10code.de>
|
||||
|
||||
* assuan.h (_gpgme_io_socket): New prototype.
|
||||
(_ASSUAN_CUSTOM_IO, _assuan_custom_close, _assuan_custom_read)
|
||||
(_assuan_custom_write, _assuan_custom_pipe, _assuan_custom_socket)
|
||||
(_assuan_custom_connect): New macros.
|
||||
* assuan-socket.c (_assuan_close, _assuan_sock_new)
|
||||
(_assuan_sock_connect) [_ASSUAN_CUSTOM_IO]: Use custom I/O function.
|
||||
* assuan-buffer.c (assuan_read_line): Do not handle EAGAIN anymore.
|
||||
* assuan-client.c (_assuan_read_from_server): Likewise.
|
||||
* assuan-handler.c (process_next): Likewise
|
||||
* assuan-inquire.c (assuan_inquire): Likewise.
|
||||
|
||||
2009-03-23 Marcus Brinkmann <marcus@g10code.de>
|
||||
|
||||
* assuan.h: Add prefix macros for _assuan_close and _assuan_usleep.
|
||||
|
@ -245,11 +245,7 @@ assuan_read_line (assuan_context_t ctx, char **line, size_t *linelen)
|
||||
if (!ctx)
|
||||
return _assuan_error (ASSUAN_Invalid_Value);
|
||||
|
||||
do
|
||||
{
|
||||
err = _assuan_read_line (ctx);
|
||||
}
|
||||
while (_assuan_error_is_eagain (err));
|
||||
err = _assuan_read_line (ctx);
|
||||
|
||||
*line = ctx->inbound.line;
|
||||
*linelen = ctx->inbound.linelen;
|
||||
|
@ -42,16 +42,12 @@ _assuan_read_from_server (assuan_context_t ctx, int *okay, int *off)
|
||||
*off = 0;
|
||||
do
|
||||
{
|
||||
do
|
||||
{
|
||||
rc = _assuan_read_line (ctx);
|
||||
}
|
||||
while (_assuan_error_is_eagain (rc));
|
||||
rc = _assuan_read_line (ctx);
|
||||
if (rc)
|
||||
return rc;
|
||||
line = ctx->inbound.line;
|
||||
linelen = ctx->inbound.linelen;
|
||||
}
|
||||
}
|
||||
while (*line == '#' || !linelen);
|
||||
|
||||
if (linelen >= 1
|
||||
|
@ -630,8 +630,6 @@ process_next (assuan_context_t ctx)
|
||||
required to write full lines without blocking long after starting
|
||||
a partial line. */
|
||||
rc = _assuan_read_line (ctx);
|
||||
if (_assuan_error_is_eagain (rc))
|
||||
return 0;
|
||||
if (rc)
|
||||
return rc;
|
||||
if (*ctx->inbound.line == '#' || !ctx->inbound.linelen)
|
||||
|
@ -169,9 +169,7 @@ assuan_inquire (assuan_context_t ctx, const char *keyword,
|
||||
{
|
||||
do
|
||||
{
|
||||
do
|
||||
rc = _assuan_read_line (ctx);
|
||||
while (_assuan_error_is_eagain (rc));
|
||||
rc = _assuan_read_line (ctx);
|
||||
if (rc)
|
||||
goto leave;
|
||||
line = (unsigned char *) ctx->inbound.line;
|
||||
|
@ -145,7 +145,10 @@ read_port_and_nonce (const char *fname, unsigned short *port, char *nonce)
|
||||
int
|
||||
_assuan_close (assuan_fd_t fd)
|
||||
{
|
||||
#if defined (HAVE_W32_SYSTEM) && !defined(_ASSUAN_IN_GPGME_BUILD_ASSUAN)
|
||||
#ifdef _ASSUAN_CUSTOM_IO
|
||||
return _assuan_custom_close (fd);
|
||||
#else
|
||||
#ifdef (HAVE_W32_SYSTEM)
|
||||
int rc = closesocket (HANDLE2SOCKET(fd));
|
||||
if (rc)
|
||||
errno = _assuan_sock_wsa2errno (WSAGetLastError ());
|
||||
@ -160,6 +163,7 @@ _assuan_close (assuan_fd_t fd)
|
||||
#else
|
||||
return close (fd);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -173,13 +177,25 @@ _assuan_sock_new (int domain, int type, int proto)
|
||||
assuan_fd_t res;
|
||||
if (domain == AF_UNIX || domain == AF_LOCAL)
|
||||
domain = AF_INET;
|
||||
|
||||
#ifdef _ASSUAN_CUSTOM_IO
|
||||
return _assuan_custom_socket (domain, type, proto);
|
||||
#else
|
||||
res = SOCKET2HANDLE(socket (domain, type, proto));
|
||||
if (res == ASSUAN_INVALID_FD)
|
||||
errno = _assuan_sock_wsa2errno (WSAGetLastError ());
|
||||
return res;
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#ifdef _ASSUAN_CUSTOM_IO
|
||||
return _gpgme_io_socket (domain, type, proto);
|
||||
#else
|
||||
return socket (domain, type, proto);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -208,11 +224,18 @@ _assuan_sock_connect (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
|
||||
unaddr->sun_port = myaddr.sin_port;
|
||||
unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr;
|
||||
|
||||
#ifdef _ASSUAN_CUSTOM_IO
|
||||
ret = _assuan_custom_connect (sockfd,
|
||||
(struct sockaddr *)&myaddr, sizeof myaddr);
|
||||
#else
|
||||
ret = connect (HANDLE2SOCKET(sockfd),
|
||||
(struct sockaddr *)&myaddr, sizeof myaddr);
|
||||
#endif
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
/* Send the nonce. */
|
||||
|
||||
ret = _assuan_io_write (sockfd, nonce, 16);
|
||||
if (ret >= 0 && ret != 16)
|
||||
{
|
||||
@ -220,6 +243,8 @@ _assuan_sock_connect (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
errno = _assuan_sock_wsa2errno (WSAGetLastError ());
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
@ -231,8 +256,14 @@ _assuan_sock_connect (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
|
||||
return res;
|
||||
}
|
||||
#else
|
||||
|
||||
#ifdef _ASSUAN_CUSTOM_IO
|
||||
return _assuan_custom_connect (sockfd, addr, addrlen);
|
||||
#else
|
||||
return connect (sockfd, addr, addrlen);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -77,6 +77,7 @@ int _gpgme_io_read (int fd, void *buffer, size_t count);
|
||||
int _gpgme_io_write (int fd, const void *buffer, size_t count);
|
||||
int _gpgme_io_sendmsg (int sock, const struct msghdr *msg, int flags);
|
||||
int _gpgme_io_recvmsg (int sock, struct msghdr *msg, int flags);
|
||||
int _gpgme_io_socket (int domain, int type, int proto);
|
||||
|
||||
#define _assuan_funopen _gpgme_funopen
|
||||
|
||||
@ -90,6 +91,15 @@ int _gpgme_io_recvmsg (int sock, struct msghdr *msg, int flags);
|
||||
#define sendmsg _gpgme_io_sendmsg
|
||||
#define recvmsg _gpgme_io_recvmsg
|
||||
#endif /*_ASSUAN_IN_GPGME_BUILD_ASSUAN*/
|
||||
|
||||
#define _ASSUAN_CUSTOM_IO 1
|
||||
#define _assuan_custom_close _gpgme_io_close
|
||||
#define _assuan_custom_read _gpgme_io_read
|
||||
#define _assuan_custom_write _gpgme_io_write
|
||||
#define _assuan_custom_pipe _gpgme_io_pipe
|
||||
#define _assuan_custom_socket _gpgme_io_socket
|
||||
#define _assuan_custom_connect _gpgme_io_connect
|
||||
|
||||
/**** End GPGME specific modifications. ******/
|
||||
|
||||
|
||||
|
@ -1,3 +1,22 @@
|
||||
2009-04-08 Marcus Brinkmann <marcus@g10code.de>
|
||||
|
||||
* w32-glib-io.c (giochannel_table): New members used, fd, socket.
|
||||
(find_channel): Drop CREATE argument.
|
||||
(new_dummy_channel_from_fd, new_channel_from_fd)
|
||||
(new_channel_from_socket): New functions.
|
||||
(_gpgm_io_fd2str): Implement for sockets.
|
||||
(_gpgme_io_write, _gpgme_io_read): Translate EAGAIN errors
|
||||
correctly.
|
||||
(_gpgme_io_pipe): Fix for new channel bookkeeping.
|
||||
(_gpgme_io_close, _gpgme_io_dup): Likewise.
|
||||
(wsa2errno, _gpgme_io_socket, _gpgme_io_connect): New.
|
||||
* w32-io.c (MAX_READERS, MAX_WRITERS): Bump up to 40.
|
||||
(wsa2errno, _gpgme_io_socket, _gpgme_io_connect): New.
|
||||
* w32-qt-io.cpp (_gpgme_io_socket, _gpgme_io_connect): New stubs.
|
||||
* version.c [HAVE_W32_SYSTEM]: Include "windows.h.
|
||||
(do_subsystem_inits) [HAVE_W32_SYSTEM]: Call WSAStartup.
|
||||
* engine-assuan.c (llass_status_handler): Ignore EAGAIN errors.
|
||||
|
||||
2009-03-18 Werner Koch <wk@g10code.com>
|
||||
|
||||
* gpgme.h.in (GPGME_KEYLIST_MODE_EPHEMERAL): New.
|
||||
|
@ -415,7 +415,18 @@ llass_status_handler (void *opaque, int fd)
|
||||
err = assuan_read_line (llass->assuan_ctx, &line, &linelen);
|
||||
if (err)
|
||||
{
|
||||
TRACE2 (DEBUG_CTX, "gpgme:llass_status_handler", llass,
|
||||
/* Reading a full line may not be possible when
|
||||
communicating over a socket in nonblocking mode. In this
|
||||
case, we are done for now. */
|
||||
if (gpg_err_code (err) == GPG_ERR_EAGAIN)
|
||||
{
|
||||
TRACE1 (DEBUG_CTX, "gpgme:llass_status_handler", llass,
|
||||
"fd 0x%x: EAGAIN reading assuan line (ignored)", fd);
|
||||
err = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
TRACE2 (DEBUG_CTX, "gpgme:llass_status_handler", llass,
|
||||
"fd 0x%x: error reading assuan line: %s",
|
||||
fd, gpg_strerror (err));
|
||||
}
|
||||
|
@ -40,6 +40,10 @@
|
||||
#include "assuan.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
#include "windows.h"
|
||||
#endif
|
||||
|
||||
|
||||
/* Bootstrap the subsystems needed for concurrent operation. This
|
||||
must be done once at startup. We can not guarantee this using a
|
||||
@ -54,6 +58,14 @@ do_subsystem_inits (void)
|
||||
if (done)
|
||||
return;
|
||||
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
{
|
||||
WSADATA wsadat;
|
||||
|
||||
WSAStartup (0x202, &wsadat);
|
||||
}
|
||||
#endif
|
||||
|
||||
_gpgme_sema_subsystem_init ();
|
||||
#ifdef HAVE_ASSUAN_H
|
||||
assuan_set_assuan_err_source (GPG_ERR_SOURCE_GPGME);
|
||||
|
@ -80,6 +80,13 @@
|
||||
|
||||
static struct
|
||||
{
|
||||
int used;
|
||||
|
||||
/* If this is not -1, then it's a libc file descriptor. */
|
||||
int fd;
|
||||
/* If fd is -1, this is the Windows socket handle. */
|
||||
int socket;
|
||||
|
||||
GIOChannel *chan;
|
||||
/* The boolean PRIMARY is true if this file descriptor caused the
|
||||
allocation of CHAN. Only then should CHAN be destroyed when this
|
||||
@ -102,20 +109,96 @@ static struct
|
||||
|
||||
|
||||
static GIOChannel *
|
||||
find_channel (int fd, int create)
|
||||
find_channel (int fd)
|
||||
{
|
||||
if (fd < 0 || fd >= MAX_SLAFD)
|
||||
return NULL;
|
||||
|
||||
if (create && !giochannel_table[fd].chan)
|
||||
return giochannel_table[fd].chan;
|
||||
}
|
||||
|
||||
|
||||
/* Returns the FD or -1 on resource limit. */
|
||||
int
|
||||
new_dummy_channel_from_fd (int cfd)
|
||||
{
|
||||
int idx;
|
||||
|
||||
for (idx = 0; idx < MAX_SLAFD; idx++)
|
||||
if (! giochannel_table[idx].used)
|
||||
break;
|
||||
|
||||
if (idx == MAX_SLAFD)
|
||||
{
|
||||
giochannel_table[fd].chan = g_io_channel_win32_new_fd (fd);
|
||||
giochannel_table[fd].primary = 1;
|
||||
g_io_channel_set_encoding (giochannel_table[fd].chan, NULL, NULL);
|
||||
g_io_channel_set_buffered (giochannel_table[fd].chan, FALSE);
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return giochannel_table[fd].chan;
|
||||
giochannel_table[idx].used = 1;
|
||||
giochannel_table[idx].chan = NULL;
|
||||
giochannel_table[idx].fd = cfd;
|
||||
giochannel_table[idx].socket = INVALID_SOCKET;
|
||||
giochannel_table[idx].primary = 1;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
|
||||
/* Returns the FD or -1 on resource limit. */
|
||||
int
|
||||
new_channel_from_fd (int cfd)
|
||||
{
|
||||
int idx;
|
||||
|
||||
for (idx = 0; idx < MAX_SLAFD; idx++)
|
||||
if (! giochannel_table[idx].used)
|
||||
break;
|
||||
|
||||
if (idx == MAX_SLAFD)
|
||||
{
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
giochannel_table[idx].used = 1;
|
||||
giochannel_table[idx].chan = g_io_channel_win32_new_fd (cfd);
|
||||
giochannel_table[idx].fd = cfd;
|
||||
giochannel_table[idx].socket = INVALID_SOCKET;
|
||||
giochannel_table[idx].primary = 1;
|
||||
|
||||
g_io_channel_set_encoding (giochannel_table[idx].chan, NULL, NULL);
|
||||
g_io_channel_set_buffered (giochannel_table[idx].chan, FALSE);
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
|
||||
/* Returns the FD or -1 on resource limit. */
|
||||
int
|
||||
new_channel_from_socket (int sock)
|
||||
{
|
||||
int idx;
|
||||
|
||||
for (idx = 0; idx < MAX_SLAFD; idx++)
|
||||
if (! giochannel_table[idx].used)
|
||||
break;
|
||||
|
||||
if (idx == MAX_SLAFD)
|
||||
{
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
giochannel_table[idx].used = 1;
|
||||
giochannel_table[idx].chan = g_io_channel_win32_new_socket (sock);
|
||||
giochannel_table[idx].fd = -1;
|
||||
giochannel_table[idx].socket = sock;
|
||||
giochannel_table[idx].primary = 1;
|
||||
|
||||
g_io_channel_set_encoding (giochannel_table[idx].chan, NULL, NULL);
|
||||
g_io_channel_set_buffered (giochannel_table[idx].chan, FALSE);
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
|
||||
@ -123,7 +206,7 @@ find_channel (int fd, int create)
|
||||
void *
|
||||
gpgme_get_giochannel (int fd)
|
||||
{
|
||||
return find_channel (fd, 0);
|
||||
return find_channel (fd);
|
||||
}
|
||||
|
||||
|
||||
@ -131,7 +214,7 @@ gpgme_get_giochannel (int fd)
|
||||
void *
|
||||
gpgme_get_fdptr (int fd)
|
||||
{
|
||||
return find_channel (fd, 0);
|
||||
return find_channel (fd);
|
||||
}
|
||||
|
||||
|
||||
@ -141,9 +224,17 @@ gpgme_get_fdptr (int fd)
|
||||
int
|
||||
_gpgme_io_fd2str (char *buf, int buflen, int fd)
|
||||
{
|
||||
HANDLE hndl;
|
||||
|
||||
TRACE_BEG1 (DEBUG_SYSIO, "_gpgme_io_fd2str", fd, "fd=%d", fd);
|
||||
TRACE_SUC1 ("syshd=%p", _get_osfhandle (fd));
|
||||
return snprintf (buf, buflen, "%d", (int) _get_osfhandle (fd));
|
||||
if (giochannel_table[fd].fd != -1)
|
||||
hndl = (HANDLE) _get_osfhandle (giochannel_table[fd].fd);
|
||||
else
|
||||
hndl = (HANDLE) giochannel_table[fd].socket;
|
||||
|
||||
TRACE_SUC1 ("syshd=%p", hndl);
|
||||
|
||||
return snprintf (buf, buflen, "%d", (int) hndl);
|
||||
}
|
||||
|
||||
|
||||
@ -170,7 +261,7 @@ _gpgme_io_read (int fd, void *buffer, size_t count)
|
||||
TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_read", fd,
|
||||
"buffer=%p, count=%u", buffer, count);
|
||||
|
||||
chan = find_channel (fd, 0);
|
||||
chan = find_channel (fd);
|
||||
if (!chan)
|
||||
{
|
||||
TRACE_LOG ("no channel registered");
|
||||
@ -192,14 +283,20 @@ _gpgme_io_read (int fd, void *buffer, size_t count)
|
||||
|
||||
if (status == G_IO_STATUS_EOF)
|
||||
nread = 0;
|
||||
else if (status == G_IO_STATUS_AGAIN)
|
||||
{
|
||||
nread = -1;
|
||||
saved_errno = EAGAIN;
|
||||
}
|
||||
else if (status != G_IO_STATUS_NORMAL)
|
||||
{
|
||||
TRACE_LOG1 ("status %d", status);
|
||||
nread = -1;
|
||||
saved_errno = EIO;
|
||||
}
|
||||
|
||||
TRACE_LOGBUF (buffer, nread);
|
||||
|
||||
if (nread != 0 && nread != -1)
|
||||
TRACE_LOGBUF (buffer, nread);
|
||||
|
||||
errno = saved_errno;
|
||||
return TRACE_SYSRES (nread);
|
||||
@ -213,11 +310,13 @@ _gpgme_io_write (int fd, const void *buffer, size_t count)
|
||||
gsize nwritten;
|
||||
GIOChannel *chan;
|
||||
GIOStatus status;
|
||||
GError *err = NULL;
|
||||
|
||||
TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_write", fd,
|
||||
"buffer=%p, count=%u", buffer, count);
|
||||
TRACE_LOGBUF (buffer, count);
|
||||
|
||||
chan = find_channel (fd, 0);
|
||||
chan = find_channel (fd);
|
||||
if (!chan)
|
||||
{
|
||||
TRACE_LOG ("fd %d: no channel registered");
|
||||
@ -226,8 +325,19 @@ _gpgme_io_write (int fd, const void *buffer, size_t count)
|
||||
}
|
||||
|
||||
status = g_io_channel_write_chars (chan, (gchar *) buffer, count,
|
||||
&nwritten, NULL);
|
||||
if (status != G_IO_STATUS_NORMAL)
|
||||
&nwritten, &err);
|
||||
if (err)
|
||||
{
|
||||
TRACE_LOG1 ("write error: %s", err->message);
|
||||
g_error_free (err);
|
||||
}
|
||||
|
||||
if (status == G_IO_STATUS_AGAIN)
|
||||
{
|
||||
nwritten = -1;
|
||||
saved_errno = EAGAIN;
|
||||
}
|
||||
else if (status != G_IO_STATUS_NORMAL)
|
||||
{
|
||||
nwritten = -1;
|
||||
saved_errno = EIO;
|
||||
@ -241,13 +351,14 @@ _gpgme_io_write (int fd, const void *buffer, size_t count)
|
||||
int
|
||||
_gpgme_io_pipe (int filedes[2], int inherit_idx)
|
||||
{
|
||||
GIOChannel *chan;
|
||||
int fds[2];
|
||||
|
||||
TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_pipe", filedes,
|
||||
"inherit_idx=%i (GPGME uses it for %s)",
|
||||
inherit_idx, inherit_idx ? "reading" : "writing");
|
||||
|
||||
#define PIPEBUF_SIZE 4096
|
||||
if (_pipe (filedes, PIPEBUF_SIZE, O_NOINHERIT | O_BINARY) == -1)
|
||||
if (_pipe (fds, PIPEBUF_SIZE, O_NOINHERIT | O_BINARY) == -1)
|
||||
return TRACE_SYSRES (-1);
|
||||
|
||||
/* Make one end inheritable. */
|
||||
@ -255,13 +366,13 @@ _gpgme_io_pipe (int filedes[2], int inherit_idx)
|
||||
{
|
||||
int new_read;
|
||||
|
||||
new_read = _dup (filedes[0]);
|
||||
_close (filedes[0]);
|
||||
filedes[0] = new_read;
|
||||
new_read = _dup (fds[0]);
|
||||
_close (fds[0]);
|
||||
fds[0] = new_read;
|
||||
|
||||
if (new_read < 0)
|
||||
{
|
||||
_close (filedes[1]);
|
||||
_close (fds[1]);
|
||||
return TRACE_SYSRES (-1);
|
||||
}
|
||||
}
|
||||
@ -269,33 +380,48 @@ _gpgme_io_pipe (int filedes[2], int inherit_idx)
|
||||
{
|
||||
int new_write;
|
||||
|
||||
new_write = _dup (filedes[1]);
|
||||
_close (filedes[1]);
|
||||
filedes[1] = new_write;
|
||||
new_write = _dup (fds[1]);
|
||||
_close (fds[1]);
|
||||
fds[1] = new_write;
|
||||
|
||||
if (new_write < 0)
|
||||
{
|
||||
_close (filedes[0]);
|
||||
_close (fds[0]);
|
||||
return TRACE_SYSRES (-1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we have a pipe with the right end inheritable. The other end
|
||||
should have a giochannel. */
|
||||
chan = find_channel (filedes[1 - inherit_idx], 1);
|
||||
if (!chan)
|
||||
/* For _gpgme_io_close. */
|
||||
filedes[inherit_idx] = new_dummy_channel_from_fd (fds[inherit_idx]);
|
||||
if (filedes[inherit_idx] < 0)
|
||||
{
|
||||
int saved_errno = errno;
|
||||
_close (filedes[0]);
|
||||
_close (filedes[1]);
|
||||
|
||||
_close (fds[0]);
|
||||
_close (fds[1]);
|
||||
errno = saved_errno;
|
||||
return TRACE_SYSRES (-1);
|
||||
}
|
||||
|
||||
/* Now we have a pipe with the correct end inheritable. The other end
|
||||
should have a giochannel. */
|
||||
filedes[1 - inherit_idx] = new_channel_from_fd (fds[1 - inherit_idx]);
|
||||
if (filedes[1 - inherit_idx] < 0)
|
||||
{
|
||||
int saved_errno = errno;
|
||||
|
||||
_gpgme_io_close (fds[inherit_idx]);
|
||||
_close (fds[1 - inherit_idx]);
|
||||
errno = saved_errno;
|
||||
return TRACE_SYSRES (-1);
|
||||
}
|
||||
|
||||
return TRACE_SUC5 ("read=0x%x/%p, write=0x%x/%p, channel=%p",
|
||||
filedes[0], (HANDLE) _get_osfhandle (filedes[0]),
|
||||
filedes[1], (HANDLE) _get_osfhandle (filedes[1]),
|
||||
chan);
|
||||
filedes[0],
|
||||
(HANDLE) _get_osfhandle (giochannel_table[filedes[0]].fd),
|
||||
filedes[1],
|
||||
(HANDLE) _get_osfhandle (giochannel_table[filedes[1]].fd),
|
||||
giochannel_table[1 - inherit_idx].chan);
|
||||
}
|
||||
|
||||
|
||||
@ -310,6 +436,8 @@ _gpgme_io_close (int fd)
|
||||
return TRACE_SYSRES (-1);
|
||||
}
|
||||
|
||||
assert (giochannel_table[fd].used);
|
||||
|
||||
/* First call the notify handler. */
|
||||
if (notify_table[fd].handler)
|
||||
{
|
||||
@ -318,19 +446,26 @@ _gpgme_io_close (int fd)
|
||||
notify_table[fd].value = NULL;
|
||||
}
|
||||
|
||||
/* Then do the close. */
|
||||
/* Then do the close. */
|
||||
if (giochannel_table[fd].chan)
|
||||
{
|
||||
if (giochannel_table[fd].primary)
|
||||
g_io_channel_shutdown (giochannel_table[fd].chan, 1, NULL);
|
||||
else
|
||||
_close (fd);
|
||||
|
||||
|
||||
g_io_channel_unref (giochannel_table[fd].chan);
|
||||
giochannel_table[fd].chan = NULL;
|
||||
}
|
||||
else
|
||||
_close (fd);
|
||||
{
|
||||
/* Dummy entry, just close. */
|
||||
assert (giochannel_table[fd].fd != -1);
|
||||
_close (giochannel_table[fd].fd);
|
||||
}
|
||||
|
||||
giochannel_table[fd].used = 0;
|
||||
giochannel_table[fd].fd = -1;
|
||||
giochannel_table[fd].socket = INVALID_SOCKET;
|
||||
giochannel_table[fd].chan = NULL;
|
||||
giochannel_table[fd].primary = 0;
|
||||
|
||||
TRACE_SUC ();
|
||||
return 0;
|
||||
@ -365,16 +500,17 @@ _gpgme_io_set_nonblocking (int fd)
|
||||
|
||||
TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_set_nonblocking", fd);
|
||||
|
||||
chan = find_channel (fd, 0);
|
||||
chan = find_channel (fd);
|
||||
if (!chan)
|
||||
{
|
||||
errno = EIO;
|
||||
return TRACE_SYSRES (-1);
|
||||
}
|
||||
|
||||
status = g_io_channel_set_flags (chan,
|
||||
status = g_io_channel_set_flags (chan,
|
||||
g_io_channel_get_flags (chan) |
|
||||
G_IO_FLAG_NONBLOCK, NULL);
|
||||
|
||||
if (status != G_IO_STATUS_NORMAL)
|
||||
{
|
||||
#if 0
|
||||
@ -549,7 +685,8 @@ _gpgme_io_spawn (const char *path, char * const argv[],
|
||||
HANDLE hd;
|
||||
|
||||
/* Make it inheritable for the wrapper process. */
|
||||
if (!DuplicateHandle (GetCurrentProcess(), _get_osfhandle (fd_list[i].fd),
|
||||
if (!DuplicateHandle (GetCurrentProcess(),
|
||||
_get_osfhandle (giochannel_table[fd_list[i].fd].fd),
|
||||
pi.hProcess, &hd, 0, TRUE, DUPLICATE_SAME_ACCESS))
|
||||
{
|
||||
TRACE_LOG1 ("DuplicateHandle failed: ec=%d", (int) GetLastError ());
|
||||
@ -694,7 +831,7 @@ _gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock)
|
||||
continue;
|
||||
|
||||
if ((fds[i].for_read || fds[i].for_write)
|
||||
&& !(chan = find_channel (fds[i].fd, 0)))
|
||||
&& !(chan = find_channel (fds[i].fd)))
|
||||
{
|
||||
TRACE_ADD1 (dbg_help, "[BAD0x%x ", fds[i].fd);
|
||||
TRACE_END (dbg_help, "]");
|
||||
@ -786,27 +923,147 @@ _gpgme_io_dup (int fd)
|
||||
{
|
||||
int newfd;
|
||||
GIOChannel *chan;
|
||||
|
||||
TRACE_BEG1 (DEBUG_SYSIO, "_gpgme_io_dup", fd, "dup (%d)", fd);
|
||||
|
||||
newfd = _dup (fd);
|
||||
if (newfd == -1)
|
||||
return TRACE_SYSRES (-1);
|
||||
if (newfd < 0 || newfd >= MAX_SLAFD)
|
||||
TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_dup", fd);
|
||||
|
||||
if (fd < 0 || fd >= MAX_SLAFD || !giochannel_table[fd].used)
|
||||
{
|
||||
/* New FD won't fit into our table. */
|
||||
_close (newfd);
|
||||
errno = EIO;
|
||||
errno = EINVAL;
|
||||
return TRACE_SYSRES (-1);
|
||||
}
|
||||
assert (giochannel_table[newfd].chan == NULL);
|
||||
|
||||
chan = find_channel (fd, 0);
|
||||
assert (chan);
|
||||
|
||||
for (newfd = 0; newfd < MAX_SLAFD; newfd++)
|
||||
if (! giochannel_table[newfd].used)
|
||||
break;
|
||||
if (newfd == MAX_SLAFD)
|
||||
{
|
||||
errno = EIO;
|
||||
return TRACE_SYSRES (-1);
|
||||
}
|
||||
|
||||
chan = giochannel_table[fd].chan;
|
||||
g_io_channel_ref (chan);
|
||||
giochannel_table[newfd].used = 1;
|
||||
giochannel_table[newfd].chan = chan;
|
||||
giochannel_table[newfd].fd = -1;
|
||||
giochannel_table[newfd].socket = INVALID_SOCKET;
|
||||
giochannel_table[newfd].primary = 0;
|
||||
|
||||
return TRACE_SYSRES (newfd);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static int
|
||||
wsa2errno (int err)
|
||||
{
|
||||
switch (err)
|
||||
{
|
||||
case WSAENOTSOCK:
|
||||
return EINVAL;
|
||||
case WSAEWOULDBLOCK:
|
||||
return EAGAIN;
|
||||
case ERROR_BROKEN_PIPE:
|
||||
return EPIPE;
|
||||
case WSANOTINITIALISED:
|
||||
return ENOSYS;
|
||||
default:
|
||||
return EIO;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
||||
res = socket (domain, type, proto);
|
||||
if (res == INVALID_SOCKET)
|
||||
{
|
||||
errno = wsa2errno (WSAGetLastError ());
|
||||
return TRACE_SYSRES (-1);
|
||||
}
|
||||
|
||||
fd = new_channel_from_socket (res);
|
||||
if (fd < 0)
|
||||
{
|
||||
int saved_errno = errno;
|
||||
closesocket (res);
|
||||
errno = saved_errno;
|
||||
return TRACE_SYSRES (-1);
|
||||
}
|
||||
|
||||
TRACE_SUC2 ("fd=%i, socket=0x%x", fd, res);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
_gpgme_io_connect (int fd, struct sockaddr *addr, int addrlen)
|
||||
{
|
||||
GIOChannel *chan;
|
||||
int sockfd;
|
||||
int res;
|
||||
GIOFlags flags;
|
||||
GIOStatus status;
|
||||
GError *err = NULL;
|
||||
|
||||
TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_connect", fd,
|
||||
"addr=%p, addrlen=%i", addr, addrlen);
|
||||
|
||||
chan = find_channel (fd);
|
||||
if (! chan)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return TRACE_SYSRES (-1);
|
||||
}
|
||||
|
||||
flags = g_io_channel_get_flags (chan);
|
||||
if (flags & G_IO_FLAG_NONBLOCK)
|
||||
{
|
||||
status = g_io_channel_set_flags (chan, flags & ~G_IO_FLAG_NONBLOCK, &err);
|
||||
if (err)
|
||||
{
|
||||
TRACE_LOG1 ("setting flags error: %s", err->message);
|
||||
g_error_free (err);
|
||||
err = NULL;
|
||||
}
|
||||
if (status != G_IO_STATUS_NORMAL)
|
||||
{
|
||||
errno = EIO;
|
||||
return TRACE_SYSRES (-1);
|
||||
}
|
||||
}
|
||||
|
||||
sockfd = giochannel_table[fd].socket;
|
||||
if (sockfd == INVALID_SOCKET)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return TRACE_SYSRES (-1);
|
||||
}
|
||||
|
||||
TRACE_LOG1 ("connect sockfd=0x%x", sockfd);
|
||||
res = connect (sockfd, addr, addrlen);
|
||||
|
||||
/* FIXME: Error ignored here. */
|
||||
if (! (flags & G_IO_FLAG_NONBLOCK))
|
||||
g_io_channel_set_flags (chan, flags, NULL);
|
||||
|
||||
if (res)
|
||||
{
|
||||
TRACE_LOG2 ("connect failed: %i %i", res, WSAGetLastError ());
|
||||
|
||||
errno = wsa2errno (WSAGetLastError ());
|
||||
return TRACE_SYSRES (-1);
|
||||
}
|
||||
|
||||
return TRACE_SUC ();
|
||||
}
|
||||
|
64
src/w32-io.c
64
src/w32-io.c
@ -53,8 +53,8 @@
|
||||
#define READBUF_SIZE 4096
|
||||
#define WRITEBUF_SIZE 4096
|
||||
#define PIPEBUF_SIZE 4096
|
||||
#define MAX_READERS 20
|
||||
#define MAX_WRITERS 20
|
||||
#define MAX_READERS 40
|
||||
#define MAX_WRITERS 40
|
||||
|
||||
static struct
|
||||
{
|
||||
@ -1469,3 +1469,63 @@ gpgme_get_fdptr (int fd)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
wsa2errno (int err)
|
||||
{
|
||||
switch (err)
|
||||
{
|
||||
case WSAENOTSOCK:
|
||||
return EINVAL;
|
||||
case WSAEWOULDBLOCK:
|
||||
return EAGAIN;
|
||||
case ERROR_BROKEN_PIPE:
|
||||
return EPIPE;
|
||||
case WSANOTINITIALISED:
|
||||
return ENOSYS;
|
||||
default:
|
||||
return EIO;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
_gpgme_io_socket (int domain, int type, int proto)
|
||||
{
|
||||
int res;
|
||||
|
||||
TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_socket", domain,
|
||||
"type=%i, protp=%i", type, proto);
|
||||
|
||||
res = socket (domain, type, proto);
|
||||
if (res == INVALID_SOCKET)
|
||||
{
|
||||
errno = wsa2errno (WSAGetLastError ());
|
||||
return TRACE_SYSRES (-1);
|
||||
}
|
||||
|
||||
TRACE_SUC1 ("socket=0x%x", res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
_gpgme_io_connect (int fd, struct sockaddr *addr, int addrlen)
|
||||
{
|
||||
int sockfd;
|
||||
int res;
|
||||
|
||||
TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_connect", fd,
|
||||
"addr=%p, addrlen=%i", addr, addrlen);
|
||||
|
||||
res = connect (sockfd, addr, addrlen);
|
||||
if (!res)
|
||||
{
|
||||
errno = wsa2errno (WSAGetLastError ());
|
||||
return TRACE_SYSRES (-1);
|
||||
}
|
||||
|
||||
return TRACE_SUC ();
|
||||
}
|
||||
|
@ -674,3 +674,20 @@ _gpgme_io_dup (int fd)
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
extern "C"
|
||||
int
|
||||
_gpgme_io_socket (int domain, int type, int proto)
|
||||
{
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
extern "C"
|
||||
int
|
||||
_gpgme_io_connect (int fd, struct sockaddr *addr, int addrlen)
|
||||
{
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user