diff options
author | scottc <scottc> | 2002-08-30 22:08:50 +0000 |
---|---|---|
committer | scottc <scottc> | 2002-08-30 22:08:50 +0000 |
commit | d41dd3bb324b98e2fe6e35c9b03cbbb9f098f2c2 (patch) | |
tree | 913ab219b616850ea5b6ac74cd846cb21e199b0f | |
parent | 1776a3897992ee296fc131876efb6c1144890392 (diff) | |
download | gdb-d41dd3bb324b98e2fe6e35c9b03cbbb9f098f2c2.tar.gz |
Merged changes from HEAD
-rw-r--r-- | winsup/cygwin/ChangeLog | 39 | ||||
-rw-r--r-- | winsup/cygwin/autoload.cc | 1 | ||||
-rw-r--r-- | winsup/cygwin/cygwin.din | 52 | ||||
-rw-r--r-- | winsup/cygwin/fhandler.cc | 104 | ||||
-rw-r--r-- | winsup/cygwin/fhandler.h | 3 | ||||
-rw-r--r-- | winsup/cygwin/fhandler_socket.cc | 4 | ||||
-rw-r--r-- | winsup/cygwin/include/cygwin/version.h | 5 | ||||
-rw-r--r-- | winsup/cygwin/include/sys/uio.h | 38 | ||||
-rw-r--r-- | winsup/cygwin/miscfuncs.cc | 73 | ||||
-rw-r--r-- | winsup/cygwin/syscalls.cc | 197 | ||||
-rw-r--r-- | winsup/cygwin/tty.cc | 10 | ||||
-rw-r--r-- | winsup/cygwin/winsup.h | 4 |
12 files changed, 400 insertions, 130 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 67d6eaa9184..b3e509073b4 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -4,6 +4,45 @@ definition of the placement new operator. (safe_delete): Remove unnecessary ## operator. +2002-08-30 Christopher January <chris@atomice.net> + Christopher Faylor <cgf@redhat.com> + + * tty.cc (tty_list::allocate_tty): Use GetConsoleWindow, if available. + Call FindWindow in a loop. + +2002-08-30 Christopher Faylor <cgf@redhat.com> + + * miscfuncs.cc (check_iovec_for_read): Don't check buffer when zero + length iov_len. + (check_iovec_for_write): Ditto. + +2002-08-27 Conrad Scott <conrad.scott@dsl.pipex.com> + + * 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. + +2002-08-30 Corinna Vinschen <corinna@vinschen.de> + + * cygwin.din: Add more prototypes for new wchar functions in newlib. + +2002-08-30 Corinna Vinschen <corinna@vinschen.de> + + * cygwin.din: Add prototypes for new wchar functions in newlib. + * include/cygwin/version.h: Bump API minor number. + 2002-08-29 Boris Schaeling <boriss@web.de> Corinna Vinschen <corinna@vinschen.de> diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index e3d34f42c0c..0c0334f1106 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -494,6 +494,7 @@ LoadDLLfunc (CoCreateInstance, 20, ole32) LoadDLLfuncEx (CancelIo, 4, kernel32, 1) LoadDLLfuncEx (CreateHardLinkA, 12, kernel32, 1) LoadDLLfuncEx (CreateToolhelp32Snapshot, 8, kernel32, 1) +LoadDLLfuncEx (GetConsoleWindow, 4, kernel32, 1) LoadDLLfuncEx2 (IsDebuggerPresent, 0, kernel32, 1, 1) LoadDLLfuncEx (Process32First, 8, kernel32, 1) LoadDLLfuncEx (Process32Next, 8, kernel32, 1) diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din index 1a9de94c377..cf17eedd7e3 100644 --- a/winsup/cygwin/cygwin.din +++ b/winsup/cygwin/cygwin.din @@ -1031,6 +1031,58 @@ wcscmp _wcscmp = wcscmp wcslen _wcslen = wcslen +wcscat +_wcscat = wcscat +wcschr +_wcschr = wcschr +wcscpy +_wcscpy = wcscpy +wcscspn +_wcscspn = wcscspn +wcslcat +_wcslcat = wcslcat +wcslcpy +_wcslcpy = wcslcpy +wcsncat +_wcsncat = wcsncat +wcsncmp +_wcsncmp = wcsncmp +wcsncpy +_wcsncpy = wcsncpy +wcspbrk +_wcspbrk = wcspbrk +wcsrchr +_wcsrchr = wcsrchr +wcsspn +_wcsspn = wcsspn +wcsstr +_wcsstr = wcsstr +wmemchr +_wmemchr = wmemchr +wmemcmp +_wmemcmp = wmemcmp +wmemcpy +_wmemcpy = wmemcpy +wmemmove +_wmemmove = wmemmove +wmemset +_wmemset = wmemset +btowc +_btowc = btowc +wctob +_wctob = wctob +mbsinit +_mbsinit = mbsinit +mbrlen +_mbrlen = mbrlen +mbrtowc +_mbrtowc = mbrtowc +mbsrtowcs +_mbsrtowcs = mbsrtowcs +wcrtomb +_wcrtomb = wcrtomb +wcsrtombs +_wcsrtombs = wcsrtombs wprintf _wprintf = wprintf memccpy diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index 591bc72f50c..8ac42acdb4d 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -13,6 +13,7 @@ details. */ #include <unistd.h> #include <stdlib.h> #include <sys/cygwin.h> +#include <sys/uio.h> #include <signal.h> #include "cygerrno.h" #include "perprocess.h" @@ -697,6 +698,109 @@ fhandler_base::write (const void *ptr, size_t 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 = (char *) 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, (ssize_t) 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 = (char *) 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, (ssize_t) iovptr->iov_len); + memcpy (bufptr, iovptr->iov_base, frag); + bufptr += frag; + iovptr += 1; + nbytes -= frag; + } + + return write (buf, tot); +} + __off64_t fhandler_base::lseek (__off64_t offset, int whence) { diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index ec72091e364..a63c0514e2b 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -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 (); diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc index 85b2107525b..94866e3feb7 100644 --- a/winsup/cygwin/fhandler_socket.cc +++ b/winsup/cygwin/fhandler_socket.cc @@ -736,7 +736,9 @@ fhandler_socket::recvmsg (struct msghdr *msg, int flags) p = buf; while (nb > 0) { - ssize_t cnt = min(nb, iov->iov_len); + ssize_t cnt = iov->iov_len; + if (nb < cnt) + cnt = nb; memcpy (iov->iov_base, p, cnt); p += cnt; nb -= cnt; diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h index 69a1d04addf..f4f50e1d5d9 100644 --- a/winsup/cygwin/include/cygwin/version.h +++ b/winsup/cygwin/include/cygwin/version.h @@ -161,12 +161,15 @@ details. */ 60: MSG_NOSIGNAL 61: Export getc_unlocked, getchar_unlocked, putc_unlocked, putchar_unlocked + 62: Export wcscat, wcschr, wcscpy, wcscspn, wcslcat, wcslcpy, wcsncat, + wcsncmp, wcsncpy, wcspbrk, wcsrchr, wcsspn, wcsstr, wmemchr, + wmemcmp, wmemcpy, wmemmove, wmemset */ /* Note that we forgot to bump the api for ualarm, strtoll, strtoull */ #define CYGWIN_VERSION_API_MAJOR 0 -#define CYGWIN_VERSION_API_MINOR 61 +#define CYGWIN_VERSION_API_MINOR 62 /* There is also a compatibity version number associated with the shared memory regions. It is incremented when incompatible diff --git a/winsup/cygwin/include/sys/uio.h b/winsup/cygwin/include/sys/uio.h new file mode 100644 index 00000000000..e28f14e7e53 --- /dev/null +++ b/winsup/cygwin/include/sys/uio.h @@ -0,0 +1,38 @@ +/* sys/uio.h + + Copyright 1996, 2000, 2001, 2002 Red Hat, Inc. + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#ifndef _UIO_H_ +#define _UIO_H_ + +/* For size_t */ +#include <stddef.h> +/* For ssize_t */ +#include <sys/types.h> + +#include <sys/cdefs.h> + +__BEGIN_DECLS + +/* + * Define the uio buffers used for writev, readv. + */ + +struct iovec +{ + void *iov_base; + size_t iov_len; +}; + +extern ssize_t readv __P ((int filedes, const struct iovec *vector, int count)); +extern ssize_t writev __P ((int filedes, const struct iovec *vector, int count)); + +__END_DECLS + +#endif /* _UIO_H_ */ diff --git a/winsup/cygwin/miscfuncs.cc b/winsup/cygwin/miscfuncs.cc index 0849da51c97..a6fec0ddc4a 100644 --- a/winsup/cygwin/miscfuncs.cc +++ b/winsup/cygwin/miscfuncs.cc @@ -11,6 +11,9 @@ details. */ #include "winsup.h" #include "cygerrno.h" #include <sys/errno.h> +#include <sys/uio.h> +#include <assert.h> +#include <limits.h> #include <winbase.h> #include <winnls.h> @@ -179,6 +182,76 @@ __check_invalid_read_ptr_errno (const void *s, unsigned sz) 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 (iov->iov_len + && __check_null_invalid_struct_errno (iov->iov_base, iov->iov_len)) + return -1; + + iov += 1; + iovcnt -= 1; + } + + assert (tot <= SSIZE_MAX); + + return (ssize_t) 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 (iov->iov_len + && __check_invalid_read_ptr_errno (iov->iov_base, iov->iov_len)) + return -1; + + iov += 1; + iovcnt -= 1; + } + + assert (tot <= SSIZE_MAX); + + return (ssize_t) tot; +} + UINT get_cp () { diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index f047cbd1cb8..657a40cfc3e 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 */ diff --git a/winsup/cygwin/tty.cc b/winsup/cygwin/tty.cc index 2a2995e5954..3f55a6c23b2 100644 --- a/winsup/cygwin/tty.cc +++ b/winsup/cygwin/tty.cc @@ -195,7 +195,7 @@ tty_list::allocate_tty (int with_console) if (!with_console) console = NULL; - else + else if (!(console = GetConsoleWindow ())) { char *oldtitle = new char [TITLESIZE]; @@ -217,8 +217,12 @@ tty_list::allocate_tty (int with_console) __small_sprintf (buf, "cygwin.find.console.%d", myself->pid); SetConsoleTitle (buf); - Sleep (40); - console = FindWindow (NULL, buf); + for (int times = 0; times < 25; times++) + { + Sleep (10); + if ((console = FindWindow (NULL, buf))) + break; + } SetConsoleTitle (oldtitle); Sleep (40); ReleaseMutex (title_mutex); diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index 0739cb4dc9d..9e39728cca0 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -221,6 +221,10 @@ int __stdcall __check_invalid_read_ptr_errno (const void *s, unsigned sz) __attr #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))); |