summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2022-04-04 13:54:49 +0900
committerNIIBE Yutaka <gniibe@fsij.org>2022-04-04 13:54:49 +0900
commit018ea46a30cf4eda70070ba42c4fee642fb2fd8a (patch)
treebfc099c365b8e39d202a9c77bf3308a97c9547b1
parent660db9c9a90f377fc14a5d659d974d68d782b2d1 (diff)
downloadlibgpg-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.c256
-rw-r--r--src/gpg-error.h.in2
-rw-r--r--src/gpgrt-int.h1
-rw-r--r--src/mkheader.c7
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)