diff options
author | NIIBE Yutaka <gniibe@fsij.org> | 2022-04-04 13:54:49 +0900 |
---|---|---|
committer | NIIBE Yutaka <gniibe@fsij.org> | 2022-04-04 13:54:49 +0900 |
commit | 018ea46a30cf4eda70070ba42c4fee642fb2fd8a (patch) | |
tree | bfc099c365b8e39d202a9c77bf3308a97c9547b1 | |
parent | 660db9c9a90f377fc14a5d659d974d68d782b2d1 (diff) | |
download | libgpg-error-018ea46a30cf4eda70070ba42c4fee642fb2fd8a.tar.gz |
w32: Add ES_SYSHD_SOCK support for gpgrt_sysopen.
* src/mkheader.c (write_special): Support @SOCKET_t@ substitution.
* src/gpgrt-int.h (gpgrt_stream_backend_kind_t): Add BACKEND_SOCK.
* src/gpg-error.h.in (struct _gpgrt_syshd): Use @SOCKET_t@.
* src/estream.c [HAVE_W32_SYSTEM] (estream_cookie_sock_t): New.
[HAVE_W32_SYSTEM] (func_sock_create, func_sock_read): New.
[HAVE_W32_SYSTEM] (func_sock_write, func_sock_seek): New.
[HAVE_W32_SYSTEM] (func_sock_destroy, func_sock_ioctl): New.
[HAVE_W32_SYSTEM] (estream_functions_sock, do_sockopen): New.
[HAVE_W32_SYSTEM] (do_sysopen): Call do_sockopen.
--
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
-rw-r--r-- | src/estream.c | 256 | ||||
-rw-r--r-- | src/gpg-error.h.in | 2 | ||||
-rw-r--r-- | src/gpgrt-int.h | 1 | ||||
-rw-r--r-- | src/mkheader.c | 7 |
4 files changed, 264 insertions, 2 deletions
diff --git a/src/estream.c b/src/estream.c index 0542f59..32f8f48 100644 --- a/src/estream.c +++ b/src/estream.c @@ -1197,12 +1197,214 @@ static struct cookie_io_functions_s estream_functions_fd = }; + +#ifdef HAVE_W32_SYSTEM +/* + * Implementation of SOCKET based I/O. + */ + +/* Cookie for SOCKET objects. */ +typedef struct estream_cookie_sock +{ + SOCKET sock; /* The SOCKET we are using for actual output. */ + int no_close; /* If set we won't close the file descriptor. */ + int nonblock; /* Non-blocking mode is enabled. */ +} *estream_cookie_sock_t; + + +/* + * Create function for objects indentified by a libc file descriptor. + */ +static int +func_sock_create (void **cookie, SOCKET sock, + unsigned int modeflags, int no_close) +{ + estream_cookie_sock_t sock_cookie; + int err; + + trace (("enter: sock=%d mf=%x nc=%d", (int)sock, modeflags, no_close)); + + sock_cookie = mem_alloc (sizeof (*sock_cookie)); + if (! sock_cookie) + err = -1; + else + { + sock_cookie->sock = sock; + sock_cookie->no_close = no_close; + sock_cookie->nonblock = !!(modeflags & O_NONBLOCK); + *cookie = sock_cookie; + err = 0; + } + + trace_errno (err, ("leave: cookie=%p err=%d", *cookie, err)); + return err; +} + + +/* + * Read function for SOCKET objects. + */ +static gpgrt_ssize_t +func_sock_read (void *cookie, void *buffer, size_t size) + +{ + estream_cookie_sock_t file_cookie = cookie; + gpgrt_ssize_t bytes_read; + + trace (("enter: cookie=%p buffer=%p size=%d", cookie, buffer, (int)size)); + + if (!size) + bytes_read = -1; /* We don't know whether anything is pending. */ + else if (IS_INVALID_FD (file_cookie->sock)) + { + _gpgrt_yield (); + bytes_read = 0; + } + else + { + _gpgrt_pre_syscall (); + do + { + bytes_read = recv (file_cookie->sock, buffer, size, 0); + } + while (bytes_read == -1 && errno == EINTR); + _gpgrt_post_syscall (); + } + trace_errno (bytes_read == -1, ("leave: bytes_read=%d", (int)bytes_read)); + return bytes_read; +} + + +/* + * Write function for SOCKET objects. + */ +static gpgrt_ssize_t +func_sock_write (void *cookie, const void *buffer, size_t size) +{ + estream_cookie_sock_t file_cookie = cookie; + gpgrt_ssize_t bytes_written; + + trace (("enter: cookie=%p buffer=%p size=%d", cookie, buffer, (int)size)); + + if (IS_INVALID_FD (file_cookie->sock)) + { + _gpgrt_yield (); + bytes_written = size; /* Yeah: Success writing to the bit bucket. */ + } + else if (buffer) + { + _gpgrt_pre_syscall (); + do + { + bytes_written = send (file_cookie->sock, buffer, size, 0); + } + while (bytes_written == -1 && errno == EINTR); + _gpgrt_post_syscall (); + } + else + bytes_written = size; /* Note that for a flush SIZE should be 0. */ + + trace_errno (bytes_written == -1, + ("leave: bytes_written=%d", (int)bytes_written)); + return bytes_written; +} + + +/* + * Seek function for SOCKET objects. + */ +static int +func_sock_seek (void *cookie, gpgrt_off_t *offset, int whence) +{ + (void)cookie; + (void)offset; + (void)whence; + _set_errno (ESPIPE); + return -1; +} + + +/* + * The IOCTL function for SOCKET objects. + */ +static int +func_sock_ioctl (void *cookie, int cmd, void *ptr, size_t *len) +{ + estream_cookie_sock_t sock_cookie = cookie; + int ret; + + if (cmd == COOKIE_IOCTL_NONBLOCK && !len) + { + sock_cookie->nonblock = !!ptr; + if (IS_INVALID_FD (sock_cookie->sock)) + { + _set_errno (EINVAL); + ret = -1; + } + else + { + u_long mode = 0; + + if (sock_cookie->nonblock) + mode = 1; + + ret = ioctlsocket (sock_cookie->sock, FIONBIO, &mode); + } + } + else + { + _set_errno (EINVAL); + ret = -1; + } + + return ret; +} + +/* + * The destroy function for SOCKET objects. + */ +static int +func_sock_destroy (void *cookie) +{ + estream_cookie_sock_t sock_cookie = cookie; + int err; + + trace (("enter: cookie=%p", cookie)); + + if (sock_cookie) + { + if (IS_INVALID_FD (sock_cookie->sock)) + err = 0; + else + err = sock_cookie->no_close? 0 : closesocket (sock_cookie->sock); + mem_free (sock_cookie); + } + else + err = 0; + + trace_errno (err,("leave: err=%d", err)); + return err; +} + + +/* + * Access object for the fd functions. + */ +static struct cookie_io_functions_s estream_functions_sock = + { + { + func_sock_read, + func_sock_write, + func_sock_seek, + func_sock_destroy, + }, + func_sock_ioctl, + }; /* * Implementation of W32 handle based I/O. */ -#ifdef HAVE_W32_SYSTEM /* Cookie for fd objects. */ typedef struct estream_cookie_w32 @@ -3645,6 +3847,53 @@ _gpgrt_fpopen_nc (FILE *fp, const char *mode) #ifdef HAVE_W32_SYSTEM +static estream_t +do_sockopen (SOCKET sock, const char *mode, int no_close, int with_locked_list) +{ + int create_called = 0; + estream_t stream = NULL; + void *cookie = NULL; + unsigned int modeflags, xmode; + int err; + es_syshd_t syshd; + + err = parse_mode (mode, &modeflags, &xmode, NULL); + if (err) + goto out; + if ((xmode & X_SYSOPEN)) + { + /* Not allowed for sockopen. */ + _set_errno (EINVAL); + err = -1; + goto out; + } + + err = func_sock_create (&cookie, sock, modeflags, no_close); + if (err) + goto out; + + syshd.type = ES_SYSHD_SOCK; + syshd.u.sock = sock; + create_called = 1; + err = create_stream (&stream, cookie, &syshd, + BACKEND_SOCK, estream_functions_sock, + modeflags, xmode, with_locked_list); + + if (!err && stream) + { + if ((modeflags & O_NONBLOCK)) + err = stream->intern->func_ioctl (cookie, COOKIE_IOCTL_NONBLOCK, + "", NULL); + } + + out: + if (err && create_called) + (*estream_functions_sock.public.func_close) (cookie); + + return stream; +} + + estream_t do_w32open (HANDLE hd, const char *mode, int no_close, int with_locked_list) @@ -3692,11 +3941,16 @@ do_sysopen (es_syshd_t *syshd, const char *mode, int no_close) switch (syshd->type) { case ES_SYSHD_FD: +#ifndef HAVE_W32_SYSTEM case ES_SYSHD_SOCK: +#endif stream = do_fdopen (syshd->u.fd, mode, no_close, 0); break; #ifdef HAVE_W32_SYSTEM + case ES_SYSHD_SOCK: + stream = do_sockopen (syshd->u.sock, mode, no_close, 0); + break; case ES_SYSHD_HANDLE: stream = do_w32open (syshd->u.handle, mode, no_close, 0); break; diff --git a/src/gpg-error.h.in b/src/gpg-error.h.in index b97f38a..ccacf35 100644 --- a/src/gpg-error.h.in +++ b/src/gpg-error.h.in @@ -620,7 +620,7 @@ struct _gpgrt_syshd enum gpgrt_syshd_types type; union { int fd; - int sock; + @SOCKET_t@ sock; int rvid; void *handle; } u; diff --git a/src/gpgrt-int.h b/src/gpgrt-int.h index b53ebe9..a541620 100644 --- a/src/gpgrt-int.h +++ b/src/gpgrt-int.h @@ -234,6 +234,7 @@ typedef enum { BACKEND_MEM, BACKEND_FD, + BACKEND_SOCK, BACKEND_W32, BACKEND_FP, BACKEND_USER, diff --git a/src/mkheader.c b/src/mkheader.c index 1d2ea20..154d79f 100644 --- a/src/mkheader.c +++ b/src/mkheader.c @@ -563,6 +563,13 @@ write_special (const char *fname, int lnr, const char *tag) else fputs ("ssize_t", stdout); } + else if (!strcmp (tag, "SOCKET_t")) + { + if (have_w32_system) + fputs ("uintptr_t", stdout); + else + fputs ("int", stdout); + } else if (!strcmp (tag, "define:pid_t")) { if (have_sys_types_h) |