summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--byterun/caml/osdeps.h12
-rw-r--r--byterun/io.c64
-rw-r--r--byterun/unix.c29
-rw-r--r--byterun/win32.c30
-rw-r--r--otherlibs/win32unix/accept.c16
-rw-r--r--otherlibs/win32unix/socket.c16
6 files changed, 101 insertions, 66 deletions
diff --git a/byterun/caml/osdeps.h b/byterun/caml/osdeps.h
index 8204205f74..dde9a114bb 100644
--- a/byterun/caml/osdeps.h
+++ b/byterun/caml/osdeps.h
@@ -18,6 +18,18 @@
#include "misc.h"
+/* Read at most [n] bytes from file descriptor [fd] into buffer [buf].
+ [is_socket] is true if [fd] refers to a socket. (This distinction
+ matters for Win32, but not for Unix.) Return number of bytes
+ read, or -1 if error. */
+extern int caml_read_fd(int fd, int is_socket, void * buf, int n);
+
+/* Write at most [n] bytes from buffer [buf] onto file descriptor [fd].
+ [is_socket] is true if [fd] refers to a socket. (This distinction
+ matters for Win32, but not for Unix.) Return number of bytes
+ written, or -1 if error. */
+extern int caml_write_fd(int fd, int is_socket, void * buf, int n);
+
/* Decompose the given path into a list of directories, and add them
to the given table. Return the block to be freed later. */
extern char * caml_decompose_path(struct ext_table * tbl, char * path);
diff --git a/byterun/io.c b/byterun/io.c
index 60504f5862..48c9c00542 100644
--- a/byterun/io.c
+++ b/byterun/io.c
@@ -33,6 +33,7 @@
#include "caml/memory.h"
#include "caml/misc.h"
#include "caml/mlvalues.h"
+#include "caml/osdeps.h"
#include "caml/signals.h"
#include "caml/sys.h"
@@ -158,25 +159,12 @@ CAMLexport int caml_channel_binary_mode(struct channel *channel)
#define EWOULDBLOCK (-1)
#endif
-static int do_write(int fd, char *p, int n)
+static int do_write(int fd, int flags, char *p, int n)
{
int retcode;
-
-again:
caml_enter_blocking_section();
- retcode = write(fd, p, n);
+ retcode = caml_write_fd(fd, flags & CHANNEL_FLAG_FROM_SOCKET, p, n);
caml_leave_blocking_section();
- if (retcode == -1) {
- if (errno == EINTR) goto again;
- if ((errno == EAGAIN || errno == EWOULDBLOCK) && n > 1) {
- /* We couldn't do a partial write here, probably because
- n <= PIPE_BUF and POSIX says that writes of less than
- PIPE_BUF characters must be atomic.
- We first try again with a partial write of 1 character.
- If that fails too, we'll raise Sys_blocked_io below. */
- n = 1; goto again;
- }
- }
if (retcode == -1) caml_sys_io_error(NO_ARG);
CAMLassert (retcode > 0);
return retcode;
@@ -194,7 +182,7 @@ CAMLexport int caml_flush_partial(struct channel *channel)
towrite = channel->curr - channel->buff;
CAMLassert (towrite >= 0);
if (towrite > 0) {
- written = do_write(channel->fd, channel->buff, towrite);
+ written = do_write(channel->fd, channel->flags, channel->buff, towrite);
channel->offset += written;
if (written < towrite)
memmove(channel->buff, channel->buff + written, towrite - written);
@@ -238,7 +226,7 @@ CAMLexport int caml_putblock(struct channel *channel, char *p, intnat len)
fits to buffer and write the buffer */
memmove(channel->curr, p, free);
towrite = channel->end - channel->buff;
- written = do_write(channel->fd, channel->buff, towrite);
+ written = do_write(channel->fd, channel->flags, channel->buff, towrite);
if (written < towrite)
memmove(channel->buff, channel->buff + written, towrite - written);
channel->offset += written;
@@ -277,30 +265,28 @@ CAMLexport file_offset caml_pos_out(struct channel *channel)
/* Input */
-/* caml_do_read is exported for Cash */
-CAMLexport int caml_do_read(int fd, char *p, unsigned int n)
+static int do_read(int fd, int flags, char *p, unsigned int n)
{
int retcode;
- do {
- caml_enter_blocking_section();
- retcode = read(fd, p, n);
-#if defined(_WIN32)
- if (retcode == -1 && errno == ENOMEM && n > 16384){
- retcode = read(fd, p, 16384);
- }
-#endif
- caml_leave_blocking_section();
- } while (retcode == -1 && errno == EINTR);
+ caml_enter_blocking_section();
+ retcode = caml_read_fd(fd, flags & CHANNEL_FLAG_FROM_SOCKET, p, n);
if (retcode == -1) caml_sys_io_error(NO_ARG);
return retcode;
}
+/* caml_do_read is exported for Cash */
+CAMLexport int caml_do_read(int fd, char *p, unsigned int n)
+{
+ return do_read(fd, 0, p, n);
+}
+
CAMLexport unsigned char caml_refill(struct channel *channel)
{
int n;
- n = caml_do_read(channel->fd, channel->buff, channel->end - channel->buff);
+ n = do_read(channel->fd, channel->flags,
+ channel->buff, channel->end - channel->buff);
if (n == 0) caml_raise_end_of_file();
channel->offset += n;
channel->max = channel->buff + n;
@@ -337,8 +323,8 @@ CAMLexport int caml_getblock(struct channel *channel, char *p, intnat len)
channel->curr += avail;
return avail;
} else {
- nread = caml_do_read(channel->fd, channel->buff,
- channel->end - channel->buff);
+ nread = do_read(channel->fd, channel->flags, channel->buff,
+ channel->end - channel->buff);
channel->offset += nread;
channel->max = channel->buff + nread;
if (n > nread) n = nread;
@@ -407,7 +393,8 @@ CAMLexport intnat caml_input_scan_line(struct channel *channel)
return -(channel->max - channel->curr);
}
/* Fill the buffer as much as possible */
- n = caml_do_read(channel->fd, channel->max, channel->end - channel->max);
+ n = do_read(channel->fd, channel->flags,
+ channel->max, channel->end - channel->max);
if (n == 0) {
/* End-of-file encountered. Return the number of characters in the
buffer, with negative sign since we haven't encountered
@@ -603,6 +590,15 @@ CAMLprim value caml_ml_set_binary_mode(value vchannel, value mode)
{
#if defined(_WIN32) || defined(__CYGWIN__)
struct channel * channel = Channel(vchannel);
+#if defined(_WIN32)
+ /* The implementation of [caml_read_fd] and [caml_write_fd] in win32.c
+ doesn't support socket I/O with CRLF conversion. */
+ if (channel->flags & CHANNEL_FLAG_FROM_SOCKET != 0
+ && ! Bool_val(mode)) {
+ errno = EINVAL;
+ caml_sys_error(NO_ARG);
+ }
+#endif
if (setmode(channel->fd, Bool_val(mode) ? O_BINARY : O_TEXT) == -1)
caml_sys_error(NO_ARG);
#endif
@@ -778,7 +774,7 @@ CAMLprim value caml_ml_input(value vchannel, value buff, value vstart,
channel->curr += avail;
n = avail;
} else {
- nread = caml_do_read(channel->fd, channel->buff,
+ nread = do_read(channel->fd, channel->flags, channel->buff,
channel->end - channel->buff);
channel->offset += nread;
channel->max = channel->buff + nread;
diff --git a/byterun/unix.c b/byterun/unix.c
index 38ddee0056..c0fb1d8dcf 100644
--- a/byterun/unix.c
+++ b/byterun/unix.c
@@ -21,6 +21,7 @@
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <errno.h>
#include <fcntl.h>
#include "caml/config.h"
#ifdef SUPPORT_DYNAMIC_LINKING
@@ -46,6 +47,34 @@
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
#endif
+int caml_read_fd(int fd, int is_socket, void * buf, int n)
+{
+ int retcode;
+ do {
+ retcode = read(fd, buf, n);
+ } while (retcode == -1 && errno == EINTR);
+ return retcode;
+}
+
+int caml_write_fd(int fd, int is_socket, void * buf, int n)
+{
+ int retcode;
+ again:
+ retcode = write(fd, buf, n);
+ if (retcode == -1) {
+ if (errno == EINTR) goto again;
+ if ((errno == EAGAIN || errno == EWOULDBLOCK) && n > 1) {
+ /* We couldn't do a partial write here, probably because
+ n <= PIPE_BUF and POSIX says that writes of less than
+ PIPE_BUF characters must be atomic.
+ We first try again with a partial write of 1 character.
+ If that fails too, we'll return an error code. */
+ n = 1; goto again;
+ }
+ }
+ return retcode;
+}
+
char * caml_decompose_path(struct ext_table * tbl, char * path)
{
char * p, * q;
diff --git a/byterun/win32.c b/byterun/win32.c
index f26caf8fd7..13153c73bc 100644
--- a/byterun/win32.c
+++ b/byterun/win32.c
@@ -21,6 +21,7 @@
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <winsock2.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
@@ -39,6 +40,35 @@
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
#endif
+int caml_read_fd(int fd, int is_socket, void * buf, int n)
+{
+ int retcode;
+ if (! is_socket) {
+ retcode = read(fd, buf, n);
+ /* Large reads from console can fail with ENOMEM. Reduce requested size
+ and try again. */
+ if (retcode == -1 && errno == ENOMEM && n > 16384) {
+ retcode = read(fd, p, 16384);
+ }
+ } else {
+ retcode = recv((SOCKET) _getosfhandle(fd), buf, n, 0);
+ if (ret == -1) _dosmaperr(WSAGetLastError());
+ }
+ return retcode;
+}
+
+int caml_write_fd(int fd, int is_socket, void * buf, int n)
+{
+ int retcode;
+ if (! is_socket) {
+ retcode = write(fd, buf, n);
+ } else {
+ retcode = send((SOCKET) _getosfhandle(fd), buf, n, 0);
+ if (ret == -1) _dosmaperr(WSAGetLastError());
+ }
+ return retcode;
+}
+
char * caml_decompose_path(struct ext_table * tbl, char * path)
{
char * p, * q;
diff --git a/otherlibs/win32unix/accept.c b/otherlibs/win32unix/accept.c
index f705f0f090..ab4747fbfd 100644
--- a/otherlibs/win32unix/accept.c
+++ b/otherlibs/win32unix/accept.c
@@ -16,7 +16,6 @@
#include <caml/memory.h>
#include <caml/signals.h>
#include "unixsupport.h"
-#include <mswsock.h> // for SO_OPENTYPE and SO_SYNCHRONOUS_NONALERT
#include "socketaddr.h"
CAMLprim value unix_accept(sock)
@@ -25,30 +24,15 @@ CAMLprim value unix_accept(sock)
SOCKET sconn = Socket_val(sock);
SOCKET snew;
value fd = Val_unit, adr = Val_unit, res;
- int oldvalue, oldvaluelen, newvalue, retcode;
union sock_addr_union addr;
socklen_param_type addr_len;
DWORD err = 0;
- oldvaluelen = sizeof(oldvalue);
- retcode = getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
- (char *) &oldvalue, &oldvaluelen);
- if (retcode == 0) {
- /* Set sockets to synchronous mode */
- newvalue = SO_SYNCHRONOUS_NONALERT;
- setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
- (char *) &newvalue, sizeof(newvalue));
- }
addr_len = sizeof(sock_addr);
enter_blocking_section();
snew = accept(sconn, &addr.s_gen, &addr_len);
if (snew == INVALID_SOCKET) err = WSAGetLastError ();
leave_blocking_section();
- if (retcode == 0) {
- /* Restore initial mode */
- setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
- (char *) &oldvalue, oldvaluelen);
- }
if (snew == INVALID_SOCKET) {
win32_maperr(err);
uerror("accept", Nothing);
diff --git a/otherlibs/win32unix/socket.c b/otherlibs/win32unix/socket.c
index 9385e82e7e..29b3479b8e 100644
--- a/otherlibs/win32unix/socket.c
+++ b/otherlibs/win32unix/socket.c
@@ -13,7 +13,6 @@
#include <caml/mlvalues.h>
#include "unixsupport.h"
-#include <mswsock.h> // for SO_OPENTYPE and SO_SYNCHRONOUS_NONALERT
int socket_domain_table[] = {
PF_UNIX, PF_INET,
@@ -32,7 +31,6 @@ CAMLprim value unix_socket(domain, type, proto)
value domain, type, proto;
{
SOCKET s;
- int oldvalue, oldvaluelen, newvalue, retcode;
#ifndef HAS_IPV6
/* IPv6 requires WinSock2, we must raise an error on PF_INET6 */
@@ -42,23 +40,9 @@ CAMLprim value unix_socket(domain, type, proto)
}
#endif
- oldvaluelen = sizeof(oldvalue);
- retcode = getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
- (char *) &oldvalue, &oldvaluelen);
- if (retcode == 0) {
- /* Set sockets to synchronous mode */
- newvalue = SO_SYNCHRONOUS_NONALERT;
- setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
- (char *) &newvalue, sizeof(newvalue));
- }
s = socket(socket_domain_table[Int_val(domain)],
socket_type_table[Int_val(type)],
Int_val(proto));
- if (retcode == 0) {
- /* Restore initial mode */
- setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
- (char *) &oldvalue, oldvaluelen);
- }
if (s == INVALID_SOCKET) {
win32_maperr(WSAGetLastError());
uerror("socket", Nothing);