summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/ChangeLog11
-rw-r--r--winsup/cygwin/fhandler.cc7
-rw-r--r--winsup/cygwin/fhandler_disk_file.cc58
3 files changed, 72 insertions, 4 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 47fcb33e4..289b7288c 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,16 @@
2011-05-05 Corinna Vinschen <corinna@vinschen.de>
+ * fhandler.cc (is_at_eof): Drop static storage class. Drop err
+ parameter since we don't change the Win32 error here anymore.
+ (fhandler_base::raw_read): Accommodate change to is_at_eof.
+
+ * fhandler_disk_file.cc (fhandler_disk_file::pread): In binary mode use
+ direct call to NtReadFile, rather than lseek/read.
+ (fhandler_disk_file::pwrite): In binary mode use direct call to
+ NtWriteFile, rather than lseek/write.
+
+2011-05-05 Corinna Vinschen <corinna@vinschen.de>
+
* dcrt0.cc (dll_crt0_1): Reset locale to "C" even when dynamically
loaded.
diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc
index 858be1088..a4a256383 100644
--- a/winsup/cygwin/fhandler.cc
+++ b/winsup/cygwin/fhandler.cc
@@ -163,8 +163,8 @@ char *fhandler_base::get_proc_fd_name (char *buf)
/* Detect if we are sitting at EOF for conditions where Windows
returns an error but UNIX doesn't. */
-static int __stdcall
-is_at_eof (HANDLE h, DWORD err)
+int __stdcall
+is_at_eof (HANDLE h)
{
IO_STATUS_BLOCK io;
FILE_POSITION_INFORMATION fpi;
@@ -176,7 +176,6 @@ is_at_eof (HANDLE h, DWORD err)
FilePositionInformation))
&& fsi.EndOfFile.QuadPart == fpi.CurrentByteOffset.QuadPart)
return 1;
- SetLastError (err);
return 0;
}
@@ -237,7 +236,7 @@ retry:
/* `bytes_read' is supposedly valid. */
break;
case ERROR_NOACCESS:
- if (is_at_eof (get_handle (), errcode))
+ if (is_at_eof (get_handle ()))
{
bytes_read = 0;
break;
diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index 89501cc71..1c586f3c6 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -1415,6 +1415,47 @@ out:
ssize_t __stdcall
fhandler_disk_file::pread (void *buf, size_t count, _off64_t offset)
{
+ /* In binary mode, we can use an atomic NtReadFile call. */
+ if (rbinary ())
+ {
+ extern int __stdcall is_at_eof (HANDLE h);
+ NTSTATUS status;
+ IO_STATUS_BLOCK io;
+ LARGE_INTEGER off = { QuadPart:offset };
+
+ status = NtReadFile (get_handle (), NULL, NULL, NULL, &io, buf, count,
+ &off, NULL);
+ if (!NT_SUCCESS (status))
+ {
+ if (pc.isdir ())
+ {
+ set_errno (EISDIR);
+ return -1;
+ }
+ if (status == (NTSTATUS) STATUS_ACCESS_VIOLATION)
+ {
+ if (is_at_eof (get_handle ()))
+ return 0;
+ switch (mmap_is_attached_or_noreserve (buf, count))
+ {
+ case MMAP_NORESERVE_COMMITED:
+ status = NtReadFile (get_handle (), NULL, NULL, NULL, &io,
+ buf, count, &off, NULL);
+ if (NT_SUCCESS (status))
+ return io.Information;
+ break;
+ case MMAP_RAISE_SIGBUS:
+ raise (SIGBUS);
+ default:
+ break;
+ }
+ }
+ __seterrno_from_nt_status (status);
+ return -1;
+ }
+ return io.Information;
+ }
+ /* Text mode stays slow and non-atomic. */
ssize_t res;
_off64_t curpos = lseek (0, SEEK_CUR);
if (curpos < 0 || lseek (offset, SEEK_SET) < 0)
@@ -1435,6 +1476,23 @@ fhandler_disk_file::pread (void *buf, size_t count, _off64_t offset)
ssize_t __stdcall
fhandler_disk_file::pwrite (void *buf, size_t count, _off64_t offset)
{
+ /* In binary mode, we can use an atomic NtWriteFile call. */
+ if (wbinary ())
+ {
+ NTSTATUS status;
+ IO_STATUS_BLOCK io;
+ LARGE_INTEGER off = { QuadPart:offset };
+
+ status = NtWriteFile (get_handle (), NULL, NULL, NULL, &io, buf, count,
+ &off, NULL);
+ if (!NT_SUCCESS (status))
+ {
+ __seterrno_from_nt_status (status);
+ return -1;
+ }
+ return io.Information;
+ }
+ /* Text mode stays slow and non-atomic. */
int res;
_off64_t curpos = lseek (0, SEEK_CUR);
if (curpos < 0 || lseek (offset, SEEK_SET) < 0)