changeset 6785:ef0c60b93a17

8001334: Remove use of JVM_* functions from java.io code Summary: Replace JVM_* functions with direct system calls in java io area Reviewed-by: alanb, uta, martin
author dxu
date Wed, 13 Mar 2013 14:50:40 -0700
parents 94335b6ffb32
children f5c85c0a9af0
files make/java/nio/Makefile makefiles/CompileNativeLibraries.gmk src/share/native/java/io/ObjectOutputStream.c src/share/native/java/io/io_util.c src/share/native/java/io/io_util.h src/solaris/native/common/jdk_util_md.h src/solaris/native/java/io/FileDescriptor_md.c src/solaris/native/java/io/UnixFileSystem_md.c src/solaris/native/java/io/io_util_md.c src/solaris/native/java/io/io_util_md.h src/windows/native/common/jdk_util_md.h src/windows/native/java/io/io_util_md.c src/windows/native/java/io/io_util_md.h
diffstat 13 files changed, 290 insertions(+), 102 deletions(-) [+]
line wrap: on
line diff
--- a/make/java/nio/Makefile	Wed Mar 13 11:24:48 2013 -0400
+++ b/make/java/nio/Makefile	Wed Mar 13 14:50:40 2013 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -384,9 +384,7 @@
 ifeq ($(PLATFORM),windows)
   OTHER_LDLIBS += $(JVMLIB) ws2_32.lib \
      -libpath:$(LIBDIR) java.lib \
-     $(OBJDIR)/../../../../sun/java.net/net/$(OBJDIRNAME)/net.lib \
-     $(OBJDIR)/../../../java.lang/java/$(OBJDIRNAME)/io_util.obj \
-     $(OBJDIR)/../../../java.lang/java/$(OBJDIRNAME)/FileDescriptor_md.obj
+     $(OBJDIR)/../../../../sun/java.net/net/$(OBJDIRNAME)/net.lib
 endif
 ifeq ($(PLATFORM), linux)
 OTHER_LDLIBS += -L$(LIBDIR)/$(LIBARCH) -ljava -lnet -lpthread $(LIBDL)
--- a/makefiles/CompileNativeLibraries.gmk	Wed Mar 13 11:24:48 2013 -0400
+++ b/makefiles/CompileNativeLibraries.gmk	Wed Mar 13 14:50:40 2013 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -1957,8 +1957,6 @@
 				        -lsendfile -ljava -lnet -lc,\
 		LDFLAGS_SUFFIX_windows:=jvm.lib ws2_32.lib $(WIN_JAVA_LIB) \
 					$(JDK_OUTPUTDIR)/objs/libnet/net.lib \
-                                        $(JDK_OUTPUTDIR)/objs/libjava/io_util.obj \
-		                        $(JDK_OUTPUTDIR)/objs/libjava/FileDescriptor_md.obj \
 					advapi32.lib,\
 		LDFLAGS_SUFFIX_macosx:=-ljava -lnet -pthread -framework CoreFoundation,\
 		LDFLAGS_SUFFIX:=,\
--- a/src/share/native/java/io/ObjectOutputStream.c	Wed Mar 13 11:24:48 2013 -0400
+++ b/src/share/native/java/io/ObjectOutputStream.c	Wed Mar 13 14:50:40 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2000, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,10 +23,8 @@
  * questions.
  */
 
-#include "jni.h"
-#include "jvm.h"
 #include "jni_util.h"
-#include "jlong.h"
+#include "jdk_util.h"
 
 #include "java_lang_Float.h"
 #include "java_lang_Double.h"
@@ -88,7 +86,7 @@
     srcend = srcpos + nfloats;
     for ( ; srcpos < srcend; srcpos++) {
         fval = (float) floats[srcpos];
-        if (JVM_IsNaN(fval)) {          /* collapse NaNs */
+        if (ISNANF(fval)) {          /* collapse NaNs */
             ival = 0x7fc00000;
         } else {
             u.f = fval;
@@ -160,7 +158,7 @@
     srcend = srcpos + ndoubles;
     for ( ; srcpos < srcend; srcpos++) {
         dval = doubles[srcpos];
-        if (JVM_IsNaN((double) dval)) {         /* collapse NaNs */
+        if (ISNAND((double) dval)) {         /* collapse NaNs */
             lval = jint_to_jlong(0x7ff80000);
             lval = jlong_shl(lval, 32);
         } else {
--- a/src/share/native/java/io/io_util.c	Wed Mar 13 11:24:48 2013 -0400
+++ b/src/share/native/java/io/io_util.c	Wed Mar 13 14:50:40 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -47,10 +47,8 @@
     nread = IO_Read(fd, &ret, 1);
     if (nread == 0) { /* EOF */
         return -1;
-    } else if (nread == JVM_IO_ERR) { /* error */
+    } else if (nread == -1) { /* error */
         JNU_ThrowIOExceptionWithLastError(env, "Read error");
-    } else if (nread == JVM_IO_INTR) {
-        JNU_ThrowByName(env, "java/io/InterruptedIOException", NULL);
     }
     return ret & 0xFF;
 }
@@ -111,10 +109,8 @@
         nread = IO_Read(fd, buf, len);
         if (nread > 0) {
             (*env)->SetByteArrayRegion(env, bytes, off, nread, (jbyte *)buf);
-        } else if (nread == JVM_IO_ERR) {
+        } else if (nread == -1) {
             JNU_ThrowIOExceptionWithLastError(env, "Read error");
-        } else if (nread == JVM_IO_INTR) {
-            JNU_ThrowByName(env, "java/io/InterruptedIOException", NULL);
         } else { /* EOF */
             nread = -1;
         }
@@ -141,10 +137,8 @@
     } else {
         n = IO_Write(fd, &c, 1);
     }
-    if (n == JVM_IO_ERR) {
+    if (n == -1) {
         JNU_ThrowIOExceptionWithLastError(env, "Write error");
-    } else if (n == JVM_IO_INTR) {
-        JNU_ThrowByName(env, "java/io/InterruptedIOException", NULL);
     }
 }
 
@@ -194,12 +188,9 @@
             } else {
                 n = IO_Write(fd, buf+off, len);
             }
-            if (n == JVM_IO_ERR) {
+            if (n == -1) {
                 JNU_ThrowIOExceptionWithLastError(env, "Write error");
                 break;
-            } else if (n == JVM_IO_INTR) {
-                JNU_ThrowByName(env, "java/io/InterruptedIOException", NULL);
-                break;
             }
             off += n;
             len -= n;
@@ -214,11 +205,11 @@
 throwFileNotFoundException(JNIEnv *env, jstring path)
 {
     char buf[256];
-    jint n;
+    size_t n;
     jobject x;
     jstring why = NULL;
 
-    n = JVM_GetLastErrorString(buf, sizeof(buf));
+    n = getLastErrorString(buf, sizeof(buf));
     if (n > 0) {
         why = JNU_NewStringPlatform(env, buf);
     }
--- a/src/share/native/java/io/io_util.h	Wed Mar 13 11:24:48 2013 -0400
+++ b/src/share/native/java/io/io_util.h	Wed Mar 13 14:50:40 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,7 +54,7 @@
                 jint len, jboolean append, jfieldID fid);
 void fileOpen(JNIEnv *env, jobject this, jstring path, jfieldID fid, int flags);
 void throwFileNotFoundException(JNIEnv *env, jstring path);
-
+size_t getLastErrorString(char *buf, size_t len);
 
 /*
  * Macros for managing platform strings.  The typical usage pattern is:
--- a/src/solaris/native/common/jdk_util_md.h	Wed Mar 13 11:24:48 2013 -0400
+++ b/src/solaris/native/common/jdk_util_md.h	Wed Mar 13 14:50:40 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,4 +23,24 @@
  * questions.
  */
 
-// Currently, there are no unix specific functions defined.
+#ifndef JDK_UTIL_MD_H
+#define JDK_UTIL_MD_H
+
+// checking for nanness
+#ifdef __solaris__
+#include <ieeefp.h>
+#define ISNANF(f) isnanf(f)
+#define ISNAND(d) isnand(d)
+#elif defined(MACOSX)
+#include <math.h>
+#define ISNANF(f) isnan(f)
+#define ISNAND(d) isnan(d)
+#elif defined(__linux__) || defined(_ALLBSD_SOURCE)
+#include <math.h>
+#define ISNANF(f) isnanf(f)
+#define ISNAND(d) isnan(d)
+#else
+#error "missing platform-specific definition here"
+#endif
+
+#endif /* JDK_UTIL_MD_H */
--- a/src/solaris/native/java/io/FileDescriptor_md.c	Wed Mar 13 11:24:48 2013 -0400
+++ b/src/solaris/native/java/io/FileDescriptor_md.c	Wed Mar 13 14:50:40 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,9 +23,8 @@
  * questions.
  */
 
-#include "jni.h"
-#include "jni_util.h"
 #include "jvm.h"
+#include "io_util_md.h"
 
 #include "java_io_FileDescriptor.h"
 
@@ -51,8 +50,8 @@
 
 JNIEXPORT void JNICALL
 Java_java_io_FileDescriptor_sync(JNIEnv *env, jobject this) {
-    int fd = (*env)->GetIntField(env, this, IO_fd_fdID);
-    if (JVM_Sync(fd) == -1) {
+    FD fd = THIS_FD(this);
+    if (IO_Sync(fd) == -1) {
         JNU_ThrowByName(env, "java/io/SyncFailedException", "sync failed");
     }
 }
--- a/src/solaris/native/java/io/UnixFileSystem_md.c	Wed Mar 13 11:24:48 2013 -0400
+++ b/src/solaris/native/java/io/UnixFileSystem_md.c	Wed Mar 13 14:50:40 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -77,7 +77,7 @@
 
     WITH_PLATFORM_STRING(env, pathname, path) {
         char canonicalPath[JVM_MAXPATHLEN];
-        if (canonicalize(JVM_NativePath((char *)path),
+        if (canonicalize((char *)path,
                          canonicalPath, JVM_MAXPATHLEN) < 0) {
             JNU_ThrowIOExceptionWithLastError(env, "Bad pathname");
         } else {
@@ -241,19 +241,18 @@
     jboolean rv = JNI_FALSE;
 
     WITH_PLATFORM_STRING(env, pathname, path) {
-        int fd;
-        if (!strcmp (path, "/")) {
-            fd = JVM_EEXIST;    /* The root directory always exists */
-        } else {
-            fd = JVM_Open(path, JVM_O_RDWR | JVM_O_CREAT | JVM_O_EXCL, 0666);
-        }
-        if (fd < 0) {
-            if (fd != JVM_EEXIST) {
-                JNU_ThrowIOExceptionWithLastError(env, path);
+        FD fd;
+        /* The root directory always exists */
+        if (strcmp (path, "/")) {
+            fd = handleOpen(path, O_RDWR | O_CREAT | O_EXCL, 0666);
+            if (fd < 0) {
+                if (errno != EEXIST)
+                    JNU_ThrowIOExceptionWithLastError(env, path);
+            } else {
+                if (close(fd) == -1)
+                    JNU_ThrowIOExceptionWithLastError(env, path);
+                rv = JNI_TRUE;
             }
-        } else {
-            JVM_Close(fd);
-            rv = JNI_TRUE;
         }
     } END_PLATFORM_STRING(env, path);
     return rv;
--- a/src/solaris/native/java/io/io_util_md.c	Wed Mar 13 11:24:48 2013 -0400
+++ b/src/solaris/native/java/io/io_util_md.c	Wed Mar 13 14:50:40 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,15 @@
 #include "io_util.h"
 #include "io_util_md.h"
 #include <string.h>
+#include <unistd.h>
+
+#ifdef __solaris__
+#include <sys/filio.h>
+#endif
+
+#if defined(__linux__) || defined(_ALLBSD_SOURCE)
+#include <sys/ioctl.h>
+#endif
 
 #ifdef MACOSX
 
@@ -62,6 +71,28 @@
 }
 #endif
 
+FD
+handleOpen(const char *path, int oflag, int mode) {
+    FD fd;
+    RESTARTABLE(open64(path, oflag, mode), fd);
+    if (fd != -1) {
+        struct stat64 buf64;
+        int result;
+        RESTARTABLE(fstat64(fd, &buf64), result);
+        if (result != -1) {
+            if (S_ISDIR(buf64.st_mode)) {
+                close(fd);
+                errno = EISDIR;
+                fd = -1;
+            }
+        } else {
+            close(fd);
+            fd = -1;
+        }
+    }
+    return fd;
+}
+
 void
 fileOpen(JNIEnv *env, jobject this, jstring path, jfieldID fid, int flags)
 {
@@ -74,8 +105,8 @@
         while ((p > ps) && (*p == '/'))
             *p-- = '\0';
 #endif
-        fd = JVM_Open(ps, flags, 0666);
-        if (fd >= 0) {
+        fd = handleOpen(ps, flags, 0666);
+        if (fd != -1) {
             SET_FD(this, fd, fid);
         } else {
             throwFileNotFoundException(env, path);
@@ -83,7 +114,6 @@
     } END_PLATFORM_STRING(env, ps);
 }
 
-
 void
 fileClose(JNIEnv *env, jobject this, jfieldID fid)
 {
@@ -114,7 +144,89 @@
             dup2(devnull, fd);
             close(devnull);
         }
-    } else if (JVM_Close(fd) == -1) {
+    } else if (close(fd) == -1) {
         JNU_ThrowIOExceptionWithLastError(env, "close failed");
     }
 }
+
+ssize_t
+handleRead(FD fd, void *buf, jint len)
+{
+    ssize_t result;
+    RESTARTABLE(read(fd, buf, len), result);
+    return result;
+}
+
+ssize_t
+handleWrite(FD fd, const void *buf, jint len)
+{
+    ssize_t result;
+    RESTARTABLE(write(fd, buf, len), result);
+    return result;
+}
+
+jint
+handleAvailable(FD fd, jlong *pbytes)
+{
+    int mode;
+    struct stat64 buf64;
+    jlong size = -1, current = -1;
+
+    int result;
+    RESTARTABLE(fstat64(fd, &buf64), result);
+    if (result != -1) {
+        mode = buf64.st_mode;
+        if (S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) {
+            int n;
+            int result;
+            RESTARTABLE(ioctl(fd, FIONREAD, &n), result);
+            if (result >= 0) {
+                *pbytes = n;
+                return 1;
+            }
+        } else if (S_ISREG(mode)) {
+            size = buf64.st_size;
+        }
+    }
+
+    if ((current = lseek64(fd, 0, SEEK_CUR)) == -1) {
+        return 0;
+    }
+
+    if (size < current) {
+        if ((size = lseek64(fd, 0, SEEK_END)) == -1)
+            return 0;
+        else if (lseek64(fd, current, SEEK_SET) == -1)
+            return 0;
+    }
+
+    if (size >= current) {
+        *pbytes = size - current;
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+jint
+handleSetLength(FD fd, jlong length)
+{
+    int result;
+    RESTARTABLE(ftruncate64(fd, length), result);
+    return result;
+}
+
+size_t
+getLastErrorString(char *buf, size_t len)
+{
+    if (errno == 0 || len < 1) return 0;
+
+    const char *err = strerror(errno);
+    size_t n = strlen(err);
+    if (n >= len)
+        n = len - 1;
+
+    strncpy(buf, err, n);
+    buf[n] = '\0';
+    return n;
+}
--- a/src/solaris/native/java/io/io_util_md.h	Wed Mar 13 11:24:48 2013 -0400
+++ b/src/solaris/native/java/io/io_util_md.h	Wed Mar 13 14:50:40 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,6 @@
  * questions.
  */
 
-#include "jni.h"
 #include "jni_util.h"
 
 /*
@@ -32,6 +31,18 @@
 #define FD jint
 
 /*
+ * Prototypes for functions in io_util_md.c called from io_util.c,
+ * FileDescriptor.c, FileInputStream.c, FileOutputStream.c,
+ * UnixFileSystem_md.c
+ */
+ssize_t handleWrite(FD fd, const void *buf, jint len);
+ssize_t handleRead(FD fd, void *buf, jint len);
+jint handleAvailable(FD fd, jlong *pbytes);
+jint handleSetLength(FD fd, jlong length);
+
+FD handleOpen(const char *path, int oflag, int mode);
+
+/*
  * Macros to set/get fd from the java.io.FileDescriptor.  These
  * macros rely on having an appropriately defined 'this' object
  * within the scope in which they're used.
@@ -53,15 +64,25 @@
 #define THIS_FD(obj) (*env)->GetIntField(env, obj, IO_fd_fdID)
 
 /*
- * Route the routines through VM
+ * Route the routines
  */
-#define IO_Append JVM_Write
-#define IO_Write JVM_Write
-#define IO_Sync JVM_Sync
-#define IO_Read JVM_Read
-#define IO_Lseek JVM_Lseek
-#define IO_Available JVM_Available
-#define IO_SetLength JVM_SetLength
+#define IO_Sync fsync
+#define IO_Read handleRead
+#define IO_Write handleWrite
+#define IO_Append handleWrite
+#define IO_Available handleAvailable
+#define IO_SetLength handleSetLength
+
+#ifdef _ALLBSD_SOURCE
+#define open64 open
+#define fstat64 fstat
+#define stat64 stat
+#define lseek64 lseek
+#define ftruncate64 ftruncate
+#define IO_Lseek lseek
+#else
+#define IO_Lseek lseek64
+#endif
 
 /*
  * On Solaris, the handle field is unused
@@ -69,6 +90,15 @@
 #define SET_HANDLE(fd) return (jlong)-1
 
 /*
+ * Retry the operation if it is interrupted
+ */
+#define RESTARTABLE(_cmd, _result) do { \
+    do { \
+        _result = _cmd; \
+    } while((_result == -1) && (errno == EINTR)); \
+} while(0)
+
+/*
  * IO helper function(s)
  */
 void fileClose(JNIEnv *env, jobject this, jfieldID fid);
--- a/src/windows/native/common/jdk_util_md.h	Wed Mar 13 11:24:48 2013 -0400
+++ b/src/windows/native/common/jdk_util_md.h	Wed Mar 13 14:50:40 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,11 @@
 #define JDK_UTIL_MD_H
 
 #include "jni.h"
+#include <float.h>
+
+// checking for nanness
+#define ISNANF(f) _isnan(f)
+#define ISNAND(d) _isnan(d)
 
 #ifdef __cplusplus
 extern "C" {
--- a/src/windows/native/java/io/io_util_md.c	Wed Mar 13 11:24:48 2013 -0400
+++ b/src/windows/native/java/io/io_util_md.c	Wed Mar 13 14:50:40 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -208,7 +208,7 @@
     return pathbuf;
 }
 
-jlong
+FD
 winFileHandleOpen(JNIEnv *env, jstring path, int flags)
 {
     const DWORD access =
@@ -264,7 +264,7 @@
 void
 fileOpen(JNIEnv *env, jobject this, jstring path, jfieldID fid, int flags)
 {
-    jlong h = winFileHandleOpen(env, path, flags);
+    FD h = winFileHandleOpen(env, path, flags);
     if (h >= 0) {
         SET_FD(this, h, fid);
     }
@@ -274,12 +274,12 @@
    old C style int fd as is used in HPI layer */
 
 static int
-handleNonSeekAvailable(jlong, long *);
+handleNonSeekAvailable(FD, long *);
 static int
-handleStdinAvailable(jlong, long *);
+handleStdinAvailable(FD, long *);
 
 int
-handleAvailable(jlong fd, jlong *pbytes) {
+handleAvailable(FD fd, jlong *pbytes) {
     HANDLE h = (HANDLE)fd;
     DWORD type = 0;
 
@@ -317,7 +317,7 @@
 }
 
 static int
-handleNonSeekAvailable(jlong fd, long *pbytes) {
+handleNonSeekAvailable(FD fd, long *pbytes) {
     /* This is used for available on non-seekable devices
      * (like both named and anonymous pipes, such as pipes
      *  connected to an exec'd process).
@@ -346,7 +346,7 @@
 }
 
 static int
-handleStdinAvailable(jlong fd, long *pbytes) {
+handleStdinAvailable(FD fd, long *pbytes) {
     HANDLE han;
     DWORD numEventsRead = 0;    /* Number of events read from buffer */
     DWORD numEvents = 0;        /* Number of events in buffer */
@@ -412,8 +412,8 @@
  * denied".
  */
 
-JNIEXPORT int
-handleSync(jlong fd) {
+int
+handleSync(FD fd) {
     /*
      * From the documentation:
      *
@@ -443,7 +443,7 @@
 
 
 int
-handleSetLength(jlong fd, jlong length) {
+handleSetLength(FD fd, jlong length) {
     HANDLE h = (HANDLE)fd;
     long high = (long)(length >> 32);
     DWORD ret;
@@ -459,7 +459,7 @@
 
 JNIEXPORT
 jint
-handleRead(jlong fd, void *buf, jint len)
+handleRead(FD fd, void *buf, jint len)
 {
     DWORD read = 0;
     BOOL result = 0;
@@ -482,7 +482,7 @@
     return (jint)read;
 }
 
-static jint writeInternal(jlong fd, const void *buf, jint len, jboolean append)
+static jint writeInternal(FD fd, const void *buf, jint len, jboolean append)
 {
     BOOL result = 0;
     DWORD written = 0;
@@ -510,13 +510,11 @@
     return (jint)written;
 }
 
-JNIEXPORT
-jint handleWrite(jlong fd, const void *buf, jint len) {
+jint handleWrite(FD fd, const void *buf, jint len) {
     return writeInternal(fd, buf, len, JNI_FALSE);
 }
 
-JNIEXPORT
-jint handleAppend(jlong fd, const void *buf, jint len) {
+jint handleAppend(FD fd, const void *buf, jint len) {
     return writeInternal(fd, buf, len, JNI_TRUE);
 }
 
@@ -545,7 +543,7 @@
 }
 
 jlong
-handleLseek(jlong fd, jlong offset, jint whence)
+handleLseek(FD fd, jlong offset, jint whence)
 {
     LARGE_INTEGER pos, distance;
     DWORD lowPos = 0;
@@ -569,3 +567,44 @@
     }
     return long_to_jlong(pos.QuadPart);
 }
+
+size_t
+getLastErrorString(char *buf, size_t len)
+{
+    DWORD errval;
+    if (len > 0) {
+        if ((errval = GetLastError()) != 0) {
+            // DOS error
+            size_t n = (size_t)FormatMessage(
+                FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
+                NULL,
+                errval,
+                0,
+                buf,
+                (DWORD)len,
+                NULL);
+            if (n > 3) {
+                // Drop final '.', CR, LF
+                if (buf[n - 1] == '\n') n--;
+                if (buf[n - 1] == '\r') n--;
+                if (buf[n - 1] == '.') n--;
+                buf[n] = '\0';
+            }
+            return n;
+        }
+
+        if (errno != 0) {
+            // C runtime error that has no corresponding DOS error code
+            const char *err = strerror(errno);
+            size_t n = strlen(err);
+            if (n >= len)
+                n = len - 1;
+
+            strncpy(buf, err, n);
+            buf[n] = '\0';
+            return n;
+        }
+    }
+
+    return 0;
+}
--- a/src/windows/native/java/io/io_util_md.h	Wed Mar 13 11:24:48 2013 -0400
+++ b/src/windows/native/java/io/io_util_md.h	Wed Mar 13 14:50:40 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,12 @@
 #include "jni_util.h"
 
 /*
- * Prototypes for functions in io_util_md.c called from io_util,
+ * Macros to use the right data type for file descriptors
+ */
+#define FD jlong
+
+/*
+ * Prototypes for functions in io_util_md.c called from io_util.c,
  * FileDescriptor.c, FileInputStream.c, FileOutputStream.c
  */
 WCHAR* pathToNTPath(JNIEnv *env, jstring path, jboolean throwFNFE);
@@ -35,26 +40,20 @@
 WCHAR* getPrefixed(const WCHAR* path, int pathlen);
 WCHAR* currentDir(int di);
 int currentDirLength(const WCHAR* path, int pathlen);
-void fileOpen(JNIEnv *env, jobject this, jstring path, jfieldID fid, int flags);
-int handleAvailable(jlong fd, jlong *pbytes);
-JNIEXPORT int handleSync(jlong fd);
-int handleSetLength(jlong fd, jlong length);
-JNIEXPORT jint handleRead(jlong fd, void *buf, jint len);
-JNIEXPORT jint handleWrite(jlong fd, const void *buf, jint len);
-JNIEXPORT jint handleAppend(jlong fd, const void *buf, jint len);
+int handleAvailable(FD fd, jlong *pbytes);
+int handleSync(FD fd);
+int handleSetLength(FD fd, jlong length);
+JNIEXPORT jint handleRead(FD fd, void *buf, jint len);
+jint handleWrite(FD fd, const void *buf, jint len);
+jint handleAppend(FD fd, const void *buf, jint len);
 jint handleClose(JNIEnv *env, jobject this, jfieldID fid);
-jlong handleLseek(jlong fd, jlong offset, jint whence);
+jlong handleLseek(FD fd, jlong offset, jint whence);
 
 /*
  * Returns an opaque handle to file named by "path".  If an error occurs,
  * returns -1 and an exception is pending.
  */
-jlong winFileHandleOpen(JNIEnv *env, jstring path, int flags);
-
-/*
- * Macros to use the right data type for file descriptors
- */
-#define FD jlong
+FD winFileHandleOpen(JNIEnv *env, jstring path, int flags);
 
 /*
  * Macros to set/get fd from the java.io.FileDescriptor.