Index: fhandler.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/fhandler.cc,v retrieving revision 1.133 diff -u -p -r1.133 fhandler.cc --- fhandler.cc 14 Jul 2002 19:15:32 -0000 1.133 +++ fhandler.cc 27 Aug 2002 14:42:38 -0000 @@ -13,6 +13,7 @@ details. */ #include #include #include +#include #include #include "cygerrno.h" #include "perprocess.h" @@ -695,6 +696,111 @@ fhandler_base::write (const void *ptr, s debug_printf ("%d = write (%p, %d)", res, ptr, len); return res; +} + +ssize_t +fhandler_base::readv (const struct iovec *const iov, const int iovcnt, + ssize_t tot) +{ + assert (iov); + assert (iovcnt >= 1); + + if (iovcnt == 1) + return read (iov->iov_base, iov->iov_len); + + if (tot == -1) // i.e. if not pre-calculated by the caller. + { + tot = 0; + const struct iovec *iovptr = iov + iovcnt; + do + { + iovptr -= 1; + tot += iovptr->iov_len; + } + while (iovptr != iov); + } + + assert (tot >= 0); + + if (tot == 0) + return 0; + + char *buf = static_cast (alloca (tot)); + + if (!buf) + { + set_errno (ENOMEM); + return -1; + } + + const ssize_t res = read (buf, tot); + + const struct iovec *iovptr = iov; + int nbytes = res; + + while (nbytes > 0) + { + const int frag = min (nbytes, + static_cast (iovptr->iov_len)); + memcpy (iovptr->iov_base, buf, frag); + buf += frag; + iovptr += 1; + nbytes -= frag; + } + + return res; +} + +ssize_t +fhandler_base::writev (const struct iovec *const iov, const int iovcnt, + ssize_t tot) +{ + assert (iov); + assert (iovcnt >= 1); + + if (iovcnt == 1) + return write (iov->iov_base, iov->iov_len); + + if (tot == -1) // i.e. if not pre-calculated by the caller. + { + tot = 0; + const struct iovec *iovptr = iov + iovcnt; + do + { + iovptr -= 1; + tot += iovptr->iov_len; + } + while (iovptr != iov); + } + + assert (tot >= 0); + + if (tot == 0) + return 0; + + char *const buf = static_cast (alloca (tot)); + + if (!buf) + { + set_errno (ENOMEM); + return -1; + } + + char *bufptr = buf; + const struct iovec *iovptr = iov; + int nbytes = tot; + + while (nbytes != 0) + { + const int frag = min (nbytes, + static_cast (iovptr->iov_len)); + memcpy (bufptr, iovptr->iov_base, frag); + bufptr += frag; + iovptr += 1; + nbytes -= frag; + } + + return write (buf, tot); } __off64_t Index: fhandler.h =================================================================== RCS file: /cvs/src/src/winsup/cygwin/fhandler.h,v retrieving revision 1.136 diff -u -p -r1.136 fhandler.h --- fhandler.h 26 Aug 2002 09:57:26 -0000 1.136 +++ fhandler.h 27 Aug 2002 14:42:38 -0000 @@ -116,6 +116,7 @@ class path_conv; class fhandler_disk_file; typedef struct __DIR DIR; struct dirent; +struct iovec; enum bg_check_types { @@ -297,6 +298,8 @@ class fhandler_base virtual char const * ttyname () { return get_name(); } virtual int __stdcall read (void *ptr, size_t len) __attribute__ ((regparm (3))); virtual int write (const void *ptr, size_t len); + virtual ssize_t readv (const struct iovec *, int iovcnt, ssize_t tot = -1); + virtual ssize_t writev (const struct iovec *, int iovcnt, ssize_t tot = -1); virtual __off64_t lseek (__off64_t offset, int whence); virtual int lock (int, struct flock *); virtual void dump (); @@ -397,15 +400,15 @@ class fhandler_socket: public fhandler_b int getsockname (struct sockaddr *name, int *namelen); int getpeername (struct sockaddr *name, int *namelen); - int __stdcall read (void *ptr, size_t len) __attribute__ ((regparm (3))); + ssize_t readv (const struct iovec *, int iovcnt, ssize_t tot = -1); int recvfrom (void *ptr, size_t len, int flags, struct sockaddr *from, int *fromlen); - int recvmsg (struct msghdr *msg, int flags); + int recvmsg (struct msghdr *msg, int flags, ssize_t tot = -1); - int write (const void *ptr, size_t len); + ssize_t writev (const struct iovec *, int iovcnt, ssize_t tot = -1); int sendto (const void *ptr, size_t len, int flags, const struct sockaddr *to, int tolen); - int sendmsg (const struct msghdr *msg, int flags); + int sendmsg (const struct msghdr *msg, int flags, ssize_t tot = -1); int ioctl (unsigned int cmd, void *); int fcntl (int cmd, void *); Index: fhandler_socket.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/fhandler_socket.cc,v retrieving revision 1.60 diff -u -p -r1.60 fhandler_socket.cc --- fhandler_socket.cc 27 Aug 2002 09:24:50 -0000 1.60 +++ fhandler_socket.cc 27 Aug 2002 14:42:38 -0000 @@ -660,59 +660,68 @@ fhandler_socket::getpeername (struct soc return res; } -int __stdcall -fhandler_socket::read (void *ptr, size_t len) +int +fhandler_socket::readv (const struct iovec *const iov, const int iovcnt, + ssize_t tot) { - return recvfrom (ptr, len, 0, NULL, NULL); + struct msghdr msg = + { + msg_name: NULL, + msg_namelen: 0, + msg_iov: const_cast (iov), + msg_iovlen: iovcnt, + msg_accrights: NULL, + msg_accrightslen: 0 + }; + + return recvmsg (&msg, 0, tot); } int fhandler_socket::recvfrom (void *ptr, size_t len, int flags, struct sockaddr *from, int *fromlen) { - int res = -1; - wsock_event wsock_evt; - LPWSAOVERLAPPED ovr; - - if (is_nonblocking () || !(ovr = wsock_evt.prepare ())) - { - debug_printf ("Fallback to winsock 1 recvfrom call"); - if ((res = ::recvfrom (get_socket (), (char *) ptr, len, flags, from, - fromlen)) - == SOCKET_ERROR) - { - set_winsock_errno (); - res = -1; - } - } + int res; + DWORD ret; + + if (!winsock2_active) + ret = res = ::recvfrom (get_socket (), + static_cast (ptr), len, flags, + from, fromlen); else { - WSABUF wsabuf = { len, (char *) ptr }; - DWORD ret = 0; - if (WSARecvFrom (get_socket (), &wsabuf, 1, &ret, (DWORD *)&flags, - from, fromlen, ovr, NULL) != SOCKET_ERROR) - res = ret; - else if ((res = WSAGetLastError ()) != WSA_IO_PENDING) + WSABUF wsabuf = { len, static_cast (ptr) }; + + if (is_nonblocking ()) + res = WSARecvFrom (get_socket (), &wsabuf, 1, &ret, (DWORD *) &flags, + from, fromlen, + NULL, NULL); + else { - set_winsock_errno (); - res = -1; + wsock_event wsock_evt; + res = WSARecvFrom (get_socket (), &wsabuf, 1, &ret, (DWORD *) &flags, + from, fromlen, + wsock_evt.prepare (), NULL); + + if (res == SOCKET_ERROR && WSAGetLastError () == WSA_IO_PENDING) + ret = res = wsock_evt.wait (get_socket (), (DWORD *) &flags); } - else if ((res = wsock_evt.wait (get_socket (), (DWORD *)&flags)) == -1) - set_winsock_errno (); } + if (res == SOCKET_ERROR) + { + res = -1; + set_winsock_errno (); + } + else + res = ret; + return res; } int -fhandler_socket::recvmsg (struct msghdr *msg, int flags) +fhandler_socket::recvmsg (struct msghdr *msg, int flags, ssize_t tot) { - int res = -1; - int nb; - size_t tot = 0; - char *buf, *p; - struct iovec *iov = msg->msg_iov; - if (get_addr_family () == AF_LOCAL) { /* On AF_LOCAL sockets the (fixed-size) name of the shared memory @@ -722,109 +731,285 @@ fhandler_socket::recvmsg (struct msghdr special handling for descriptor passing. */ /*TODO*/ } - for (int i = 0; i < msg->msg_iovlen; ++i) - tot += iov[i].iov_len; - buf = (char *) alloca (tot); - if (tot != 0 && buf == NULL) - { - set_errno (ENOMEM); - return -1; - } - nb = res = recvfrom (buf, tot, flags, (struct sockaddr *) msg->msg_name, - (int *) &msg->msg_namelen); - p = buf; - while (nb > 0) - { - ssize_t cnt = min(nb, iov->iov_len); - memcpy (iov->iov_base, p, cnt); - p += cnt; - nb -= cnt; - ++iov; + + struct iovec *const iov = msg->msg_iov; + const int iovcnt = msg->msg_iovlen; + + int res; + + if (!winsock2_active) + { + if (iovcnt == 1) + res = recvfrom (iov->iov_base, iov->iov_len, flags, + static_cast (msg->msg_name), + &msg->msg_namelen); + else + { + if (tot == -1) // i.e. if not pre-calculated by the caller. + { + tot = 0; + const struct iovec *iovptr = iov + iovcnt; + do + { + iovptr -= 1; + tot += iovptr->iov_len; + } + while (iovptr != iov); + } + + char *buf = static_cast (alloca (tot)); + + if (!buf) + { + set_errno (ENOMEM); + res = -1; + } + else + { + res = recvfrom (buf, tot, flags, + static_cast (msg->msg_name), + &msg->msg_namelen); + + const struct iovec *iovptr = iov; + int nbytes = res; + + while (nbytes > 0) + { + const int frag = min (nbytes, + static_cast (iovptr->iov_len)); + memcpy (iovptr->iov_base, buf, frag); + buf += frag; + iovptr += 1; + nbytes -= frag; + } + } + } } + else + { + WSABUF wsabuf[iovcnt]; + + { + const struct iovec *iovptr = iov + iovcnt; + WSABUF *wsaptr = wsabuf + iovcnt; + do + { + iovptr -= 1; + wsaptr -= 1; + wsaptr->len = iovptr->iov_len; + wsaptr->buf = static_cast (iovptr->iov_base); + } + while (wsaptr != wsabuf); + } + + DWORD ret; + + if (is_nonblocking ()) + res = WSARecvFrom (get_socket (), + wsabuf, iovcnt, &ret, (DWORD *) &flags, + static_cast (msg->msg_name), + &msg->msg_namelen, + NULL, NULL); + else + { + wsock_event wsock_evt; + res = WSARecvFrom (get_socket (), + wsabuf, iovcnt, &ret, (DWORD *) &flags, + static_cast (msg->msg_name), + &msg->msg_namelen, + wsock_evt.prepare (), NULL); + + if (res == SOCKET_ERROR && WSAGetLastError () == WSA_IO_PENDING) + ret = res = wsock_evt.wait (get_socket (), (DWORD *) &flags); + } + + if (res == SOCKET_ERROR) + { + res = -1; + set_winsock_errno (); + } + else + res = ret; + } + return res; } int -fhandler_socket::write (const void *ptr, size_t len) +fhandler_socket::writev (const struct iovec *const iov, const int iovcnt, + ssize_t tot) { - return sendto (ptr, len, 0, NULL, 0); + struct msghdr msg = + { + msg_name: NULL, + msg_namelen: 0, + msg_iov: const_cast (iov), + msg_iovlen: iovcnt, + msg_accrights: NULL, + msg_accrightslen: 0 + }; + + return sendmsg (&msg, 0, tot); } int fhandler_socket::sendto (const void *ptr, size_t len, int flags, const struct sockaddr *to, int tolen) { - int res = -1; - wsock_event wsock_evt; - LPWSAOVERLAPPED ovr; sockaddr_in sin; if (to && !get_inet_addr (to, tolen, &sin, &tolen)) return -1; - if (is_nonblocking () || !(ovr = wsock_evt.prepare ())) - { - debug_printf ("Fallback to winsock 1 sendto call"); - if ((res = ::sendto (get_socket (), (const char *) ptr, len, flags, - (to ? (sockaddr *) &sin : NULL), - tolen)) == SOCKET_ERROR) - { - set_winsock_errno (); - res = -1; - } - } + int res; + DWORD ret; + + if (!winsock2_active) + res = ::sendto (get_socket (), (const char *) ptr, len, flags, + (to ? (sockaddr *) &sin : NULL), tolen); else { WSABUF wsabuf = { len, (char *) ptr }; - DWORD ret = 0; - if (WSASendTo (get_socket (), &wsabuf, 1, &ret, (DWORD)flags, - (to ? (sockaddr *) &sin : NULL), - tolen, - ovr, NULL) != SOCKET_ERROR) - res = ret; - else if ((res = WSAGetLastError ()) != WSA_IO_PENDING) + + if (is_nonblocking ()) + res = WSASendTo (get_socket (), &wsabuf, 1, &ret, flags, + (to ? (const sockaddr *) &sin : NULL), tolen, + NULL, NULL); + else { - set_winsock_errno (); - res = -1; + wsock_event wsock_evt; + res = WSASendTo (get_socket (), &wsabuf, 1, &ret, flags, + (to ? (const sockaddr *) &sin : NULL), tolen, + wsock_evt.prepare (), NULL); + + if (res == SOCKET_ERROR && WSAGetLastError () == WSA_IO_PENDING) + ret = res = wsock_evt.wait (get_socket (), (DWORD *) &flags); } - else if ((res = wsock_evt.wait (get_socket (), (DWORD *)&flags)) == -1) - set_winsock_errno (); } + if (res == SOCKET_ERROR) + { + res = -1; + set_winsock_errno (); + } + else + res = ret; + return res; } int -fhandler_socket::sendmsg (const struct msghdr *msg, int flags) +fhandler_socket::sendmsg (const struct msghdr *msg, int flags, ssize_t tot) { - size_t tot = 0; - char *buf, *p; - struct iovec *iov = msg->msg_iov; - - if (get_addr_family () == AF_LOCAL) - { - /* For AF_LOCAL/AF_UNIX sockets, if descriptors are given, start - the special handling for descriptor passing. Otherwise just - transmit an empty string to tell the receiver that no - descriptor passing is done. */ + if (get_addr_family () == AF_LOCAL) + { + /* For AF_LOCAL/AF_UNIX sockets, if descriptors are given, start + the special handling for descriptor passing. Otherwise just + transmit an empty string to tell the receiver that no + descriptor passing is done. */ /*TODO*/ - } - for(int i = 0; i < msg->msg_iovlen; ++i) - tot += iov[i].iov_len; - buf = (char *) alloca (tot); - if (tot != 0 && buf == NULL) - { - set_errno (ENOMEM); - return -1; - } - p = buf; - for (int i = 0; i < msg->msg_iovlen; ++i) + } + + struct iovec *const iov = msg->msg_iov; + const int iovcnt = msg->msg_iovlen; + + int res; + + if (!winsock2_active) + { + if (iovcnt == 1) + res = sendto (iov->iov_base, iov->iov_len, flags, + static_cast (msg->msg_name), + msg->msg_namelen); + else + { + if (tot == -1) // i.e. if not pre-calculated by the caller. + { + tot = 0; + const struct iovec *iovptr = iov + iovcnt; + do + { + iovptr -= 1; + tot += iovptr->iov_len; + } + while (iovptr != iov); + } + + char *const buf = static_cast (alloca (tot)); + + if (!buf) + { + set_errno (ENOMEM); + res = -1; + } + else + { + char *bufptr = buf; + const struct iovec *iovptr = iov; + int nbytes = tot; + + while (nbytes != 0) + { + const int frag = min (nbytes, + static_cast (iovptr->iov_len)); + memcpy (bufptr, iovptr->iov_base, frag); + bufptr += frag; + iovptr += 1; + nbytes -= frag; + } + + res = sendto (buf, tot, flags, + static_cast (msg->msg_name), + msg->msg_namelen); + } + } + } + else + { + WSABUF wsabuf[iovcnt]; + { - memcpy (p, iov[i].iov_base, iov[i].iov_len); - p += iov[i].iov_len; + const struct iovec *iovptr = iov + iovcnt; + WSABUF *wsaptr = wsabuf + iovcnt; + do + { + iovptr -= 1; + wsaptr -= 1; + wsaptr->len = iovptr->iov_len; + wsaptr->buf = static_cast (iovptr->iov_base); + } + while (wsaptr != wsabuf); } - return sendto (buf, tot, flags, (struct sockaddr *) msg->msg_name, - msg->msg_namelen); + + DWORD ret; + + if (is_nonblocking ()) + res = WSASendTo (get_socket (), wsabuf, iovcnt, &ret, flags, + static_cast (msg->msg_name), + msg->msg_namelen, + NULL, NULL); + else + { + wsock_event wsock_evt; + res = WSASendTo (get_socket (), wsabuf, iovcnt, &ret, flags, + static_cast (msg->msg_name), + msg->msg_namelen, + wsock_evt.prepare (), NULL); + + if (res == SOCKET_ERROR && WSAGetLastError () == WSA_IO_PENDING) + ret = res = wsock_evt.wait (get_socket (), (DWORD *) &flags); + } + + if (res == SOCKET_ERROR) + { + res = -1; + set_winsock_errno (); + } + else + res = ret; + } + + return res; } int Index: miscfuncs.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/miscfuncs.cc,v retrieving revision 1.13 diff -u -p -r1.13 miscfuncs.cc --- miscfuncs.cc 8 Aug 2002 17:03:20 -0000 1.13 +++ miscfuncs.cc 27 Aug 2002 14:42:38 -0000 @@ -11,6 +11,9 @@ details. */ #include "winsup.h" #include "cygerrno.h" #include +#include +#include +#include #include #include @@ -177,6 +180,74 @@ __check_invalid_read_ptr_errno (const vo if (s && !IsBadReadPtr (s, sz)) return 0; return set_errno (EFAULT); +} + +ssize_t +check_iovec_for_read (const struct iovec *iov, int iovcnt) +{ + if (!(iovcnt > 0 && iovcnt <= IOV_MAX)) + { + set_errno (EINVAL); + return -1; + } + + if (__check_invalid_read_ptr_errno (iov, iovcnt * sizeof (*iov))) + return -1; + + size_t tot = 0; + + while (iovcnt != 0) + { + if (iov->iov_len > SSIZE_MAX || (tot += iov->iov_len) > SSIZE_MAX) + { + set_errno (EINVAL); + return -1; + } + + if (__check_null_invalid_struct_errno (iov->iov_base, iov->iov_len)) + return -1; + + iov += 1; + iovcnt -= 1; + } + + assert (tot <= SSIZE_MAX); + + return static_cast (tot); +} + +ssize_t +check_iovec_for_write (const struct iovec *iov, int iovcnt) +{ + if (!(iovcnt > 0 && iovcnt <= IOV_MAX)) + { + set_errno (EINVAL); + return -1; + } + + if (__check_invalid_read_ptr_errno (iov, iovcnt * sizeof (*iov))) + return -1; + + size_t tot = 0; + + while (iovcnt != 0) + { + if (iov->iov_len > SSIZE_MAX || (tot += iov->iov_len) > SSIZE_MAX) + { + set_errno (EINVAL); + return -1; + } + + if (__check_invalid_read_ptr_errno (iov->iov_base, iov->iov_len)) + return -1; + + iov += 1; + iovcnt -= 1; + } + + assert (tot <= SSIZE_MAX); + + return static_cast (tot); } UINT Index: net.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/net.cc,v retrieving revision 1.123 diff -u -p -r1.123 net.cc --- net.cc 27 Aug 2002 09:24:50 -0000 1.123 +++ net.cc 27 Aug 2002 14:42:39 -0000 @@ -2112,7 +2112,11 @@ cygwin_recvmsg (int fd, struct msghdr *m || !fh) res = -1; else - res = fh->recvmsg (msg, flags); + { + res = check_iovec_for_read (msg->msg_iov, msg->msg_iovlen); + if (res > 0) + res = fh->recvmsg (msg, flags, res); // res == iovec tot + } syscall_printf ("%d = recvmsg (%d, %p, %x)", res, fd, msg, flags); return res; @@ -2123,6 +2127,8 @@ extern "C" int cygwin_sendmsg (int fd, const struct msghdr *msg, int flags) { int res; + sigframe thisframe (mainthread); + fhandler_socket *fh = get (fd); if (__check_invalid_read_ptr_errno (msg, sizeof msg) @@ -2131,8 +2137,12 @@ cygwin_sendmsg (int fd, const struct msg (unsigned) msg->msg_namelen)) || !fh) res = -1; - else - res = fh->sendmsg (msg, flags); + else + { + res = check_iovec_for_write (msg->msg_iov, msg->msg_iovlen); + if (res > 0) + res = fh->sendmsg (msg, flags, res); // res == iovec tot + } syscall_printf ("%d = sendmsg (%d, %p, %x)", res, fd, msg, flags); return res; Index: syscalls.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/syscalls.cc,v retrieving revision 1.224 diff -u -p -r1.224 syscalls.cc --- syscalls.cc 18 Aug 2002 05:49:25 -0000 1.224 +++ syscalls.cc 27 Aug 2002 14:42:40 -0000 @@ -321,15 +321,42 @@ getsid (pid_t pid) extern "C" ssize_t _read (int fd, void *ptr, size_t len) { - if (len == 0) - return 0; + const struct iovec iov = + { + iov_base: ptr, + iov_len: len + }; + + return readv (fd, &iov, 1); +} - if (__check_null_invalid_struct_errno (ptr, len)) - return -1; +extern "C" ssize_t +_write (int fd, const void *ptr, size_t len) +{ + const struct iovec iov = + { + iov_base: const_cast (ptr), + iov_len: len + }; + + return writev (fd, &iov, 1); +} - int res; +extern "C" ssize_t +readv (int fd, const struct iovec *const iov, const int iovcnt) +{ extern int sigcatchers; - int e = get_errno (); + const int e = get_errno (); + + int res = -1; + + const ssize_t tot = check_iovec_for_read (iov, iovcnt); + + if (tot <= 0) + { + res = tot; + goto done; + } while (1) { @@ -337,197 +364,119 @@ _read (int fd, void *ptr, size_t len) cygheap_fdget cfd (fd); if (cfd < 0) - return -1; + break; + + if ((cfd->get_flags () & O_ACCMODE) == O_WRONLY) + { + set_errno (EBADF); + break; + } DWORD wait = cfd->is_nonblocking () ? 0 : INFINITE; /* Could block, so let user know we at least got here. */ - syscall_printf ("read (%d, %p, %d) %sblocking, sigcatchers %d", - fd, ptr, len, wait ? "" : "non", sigcatchers); + syscall_printf ("readv (%d, %p, %d) %sblocking, sigcatchers %d", + fd, iov, iovcnt, wait ? "" : "non", sigcatchers); if (wait && (!cfd->is_slow () || cfd->get_r_no_interrupt ())) debug_printf ("no need to call ready_for_read\n"); else if (!cfd->ready_for_read (fd, wait)) - { - res = -1; - goto out; - } + goto out; /* FIXME: This is not thread safe. We need some method to ensure that an fd, closed in another thread, aborts I/O operations. */ if (!cfd.isopen ()) - return -1; + break; /* Check to see if this is a background read from a "tty", sending a SIGTTIN, if appropriate */ res = cfd->bg_check (SIGTTIN); if (!cfd.isopen ()) - return -1; + { + res = -1; + break; + } if (res > bg_eof) { myself->process_state |= PID_TTYIN; if (!cfd.isopen ()) - return -1; - res = cfd->read (ptr, len); + { + res = -1; + break; + } + res = cfd->readv (iov, iovcnt, tot); myself->process_state &= ~PID_TTYIN; } out: - - if (res && get_errno () == EACCES && - !(cfd->get_flags () & (O_RDONLY | O_RDWR))) + if (!(res == -1 + && get_errno () == EINTR + && thisframe.call_signal_handler ())) { - set_errno (EBADF); break; } - if (res >= 0 || get_errno () != EINTR || !thisframe.call_signal_handler ()) - break; set_errno (e); } - syscall_printf ("%d = read (%d, %p, %d), errno %d", res, fd, ptr, len, - get_errno ()); +done: + syscall_printf ("%d = readv (%d, %p, %d), errno %d", + res, fd, iov, iovcnt, get_errno ()); MALLOC_CHECK; return res; } extern "C" ssize_t -_write (int fd, const void *ptr, size_t len) +writev (const int fd, const struct iovec *const iov, const int iovcnt) { int res = -1; + const ssize_t tot = check_iovec_for_write (iov, iovcnt); sigframe thisframe (mainthread); cygheap_fdget cfd (fd); if (cfd < 0) goto done; - /* No further action required for len == 0 */ - if (len == 0) + if (tot <= 0) { - res = 0; + res = tot; goto done; } - if (len && __check_invalid_read_ptr_errno (ptr, len)) - goto done; + if ((cfd->get_flags () & O_ACCMODE) == O_RDONLY) + { + set_errno (EBADF); + goto done; + } /* Could block, so let user know we at least got here. */ if (fd == 1 || fd == 2) - paranoid_printf ("write (%d, %p, %d)", fd, ptr, len); + paranoid_printf ("writev (%d, %p, %d)", fd, iov, iovcnt); else - syscall_printf ("write (%d, %p, %d)", fd, ptr, len); + syscall_printf ("writev (%d, %p, %d)", fd, iov, iovcnt); res = cfd->bg_check (SIGTTOU); if (res > bg_eof) { myself->process_state |= PID_TTYOU; - res = cfd->write (ptr, len); + res = cfd->writev (iov, iovcnt, tot); myself->process_state &= ~PID_TTYOU; - if (res && get_errno () == EACCES && - !(cfd->get_flags () & (O_WRONLY | O_RDWR))) - set_errno (EBADF); } done: if (fd == 1 || fd == 2) - paranoid_printf ("%d = write (%d, %p, %d)", res, fd, ptr, len); + paranoid_printf ("%d = write (%d, %p, %d), errno %d", + res, fd, iov, iovcnt, get_errno ()); else - syscall_printf ("%d = write (%d, %p, %d)", res, fd, ptr, len); - - return (ssize_t) res; -} - -/* - * FIXME - should really move this interface into fhandler, and implement - * write in terms of it. There are devices in Win32 that could do this with - * overlapped I/O much more efficiently - we should eventually use - * these. - */ - -extern "C" ssize_t -writev (int fd, const struct iovec *iov, int iovcnt) -{ - int i; - ssize_t len, total; - char *base; - - if (iovcnt < 1 || iovcnt > IOV_MAX) - { - set_errno (EINVAL); - return -1; - } - - /* Ensure that the sum of the iov_len values is less than - SSIZE_MAX (per spec), if so, we must fail with no output (per spec). - */ - total = 0; - for (i = 0; i < iovcnt; ++i) - { - total += iov[i].iov_len; - if (total > SSIZE_MAX) - { - set_errno (EINVAL); - return -1; - } - } - /* Now write the data */ - for (i = 0, total = 0; i < iovcnt; i++, iov++) - { - len = iov->iov_len; - base = iov->iov_base; - while (len > 0) - { - register int nbytes; - nbytes = write (fd, base, len); - if (nbytes < 0 && total == 0) - return -1; - if (nbytes <= 0) - return total; - len -= nbytes; - total += nbytes; - base += nbytes; - } - } - return total; -} + syscall_printf ("%d = write (%d, %p, %d), errno %d", + res, fd, iov, iovcnt, get_errno ()); -/* - * FIXME - should really move this interface into fhandler, and implement - * read in terms of it. There are devices in Win32 that could do this with - * overlapped I/O much more efficiently - we should eventually use - * these. - */ - -extern "C" ssize_t -readv (int fd, const struct iovec *iov, int iovcnt) -{ - int i; - ssize_t len, total; - char *base; - - for (i = 0, total = 0; i < iovcnt; i++, iov++) - { - len = iov->iov_len; - base = iov->iov_base; - while (len > 0) - { - register int nbytes; - nbytes = read (fd, base, len); - if (nbytes < 0 && total == 0) - return -1; - if (nbytes <= 0) - return total; - len -= nbytes; - total += nbytes; - base += nbytes; - } - } - return total; + MALLOC_CHECK; + return res; } /* _open */ Index: winsup.h =================================================================== RCS file: /cvs/src/src/winsup/cygwin/winsup.h,v retrieving revision 1.99 diff -u -p -r1.99 winsup.h --- winsup.h 16 Aug 2002 19:49:54 -0000 1.99 +++ winsup.h 27 Aug 2002 14:42:40 -0000 @@ -221,6 +221,10 @@ int __stdcall __check_invalid_read_ptr_e #define check_null_invalid_struct_errno(s) \ __check_null_invalid_struct_errno ((s), sizeof (*(s))) +struct iovec; +ssize_t check_iovec_for_read (const struct iovec *, int) __attribute__ ((regparm(2))); +ssize_t check_iovec_for_write (const struct iovec *, int) __attribute__ ((regparm(2))); + #define set_winsock_errno() __set_winsock_errno (__FUNCTION__, __LINE__) void __set_winsock_errno (const char *fn, int ln) __attribute__ ((regparm(2))); Index: include/sys/uio.h =================================================================== RCS file: /cvs/src/src/winsup/cygwin/include/sys/uio.h,v retrieving revision 1.4 diff -u -p -r1.4 uio.h --- include/sys/uio.h 5 Mar 2001 21:29:23 -0000 1.4 +++ include/sys/uio.h 27 Aug 2002 14:42:40 -0000 @@ -25,8 +25,8 @@ __BEGIN_DECLS */ struct iovec { - caddr_t iov_base; - int iov_len; + void *iov_base; + size_t iov_len; }; extern ssize_t readv __P ((int filedes, const struct iovec *vector, int count));