Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2002-08-30 19:47:10 +0400
committerChristopher Faylor <me@cgf.cx>2002-08-30 19:47:10 +0400
commitab7f9b938f8f0008fe71e8c790afb7f86a267e1c (patch)
treef8149696d46c25222099b0d51dab157e891e3037 /winsup/cygwin/syscalls.cc
parent70c306d781b881d7142d2d99f481b0aace248270 (diff)
* miscfuncs.cc (check_iovec_for_read): Don't check buffer when zero length
iov_len. (check_iovec_for_write): Ditto. * fhandler.h (fhandler_base::readv): New method. (fhandler_base::writev): Ditto. * fhandler.cc (fhandler_base::readv): New method. (fhandler_base::writev): Ditto. * syscalls.cc (_read): Delegate to readv(2). (_write): Ditto, mutatis mutandi. (readv): Rewrite, based on the old _read code, to use the new fhandler_base::readv method. Improve access mode handling and ensure all calls reach the final strace statement. (writev): Ditto, mutatis mutandi. * include/sys/uio.h (struct iovec): Change field types to match SUSv3. * winsup.h (check_iovec_for_read): New function. (check_iovec_for_write): Ditto. * miscfuncs.cc (check_iovec_for_read): Ditto. (check_iovec_for_write): Ditto.
Diffstat (limited to 'winsup/cygwin/syscalls.cc')
-rw-r--r--winsup/cygwin/syscalls.cc197
1 files changed, 72 insertions, 125 deletions
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index f047cbd1c..657a40cfc 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -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
+ };
- if (__check_null_invalid_struct_errno (ptr, len))
- return -1;
+ return readv (fd, &iov, 1);
+}
- int res;
+extern "C" ssize_t
+_write (int fd, const void *ptr, size_t len)
+{
+ const struct iovec iov =
+ {
+ iov_base: (void *) ptr, // const_cast
+ iov_len: len
+ };
+
+ return writev (fd, &iov, 1);
+}
+
+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,13 +364,19 @@ _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");
@@ -357,177 +390,91 @@ _read (int fd, void *ptr, size_t len)
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)))
- {
- 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,
+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;
- }
+ syscall_printf ("%d = write (%d, %p, %d), errno %d",
+ res, fd, iov, iovcnt, get_errno ());
- /* 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;
-}
-
-/*
- * 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 */