You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by mt...@apache.org on 2009/10/01 08:29:59 UTC

svn commit: r820546 - in /commons/sandbox/runtime/trunk/src/main/native/os: unix/fsysio.c win32/fsysio.c

Author: mturk
Date: Thu Oct  1 06:29:59 2009
New Revision: 820546

URL: http://svn.apache.org/viewvc?rev=820546&view=rev
Log:
Throw exceptions on write in case of write error

Modified:
    commons/sandbox/runtime/trunk/src/main/native/os/unix/fsysio.c
    commons/sandbox/runtime/trunk/src/main/native/os/win32/fsysio.c

Modified: commons/sandbox/runtime/trunk/src/main/native/os/unix/fsysio.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/fsysio.c?rev=820546&r1=820545&r2=820546&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/unix/fsysio.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/unix/fsysio.c Thu Oct  1 06:29:59 2009
@@ -579,7 +579,7 @@
         f->err = ACR_GET_OS_ERROR();
         if (!ACR_STATUS_IS_EAGAIN(f->err)) {
             /* Throw only if not EAGAIN
-             */            
+             */
             ACR_THROW_IO_IF_ERR(f->err);
         }
     }
@@ -811,6 +811,7 @@
 {
     unsigned char c = (unsigned char)(b & 0xFF);
     ssize_t wr;
+    int     rc = 0;
     acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file);
 
     if (ACR_IOH_FTYPE(file) != ACR_DT_FILE) {
@@ -824,23 +825,27 @@
     wr = r_write(f->fd, &c, 1);
     if (wr == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
         f->timeout != 0) {
-        int rc;
-        if ((rc = wait_for_io_or_timeout(f, 0))) {
-            f->err = rc;
-            return rc == ACR_TIMEUP ? 0 : -1;
-        }
-        else {
+        if ((rc = wait_for_io_or_timeout(f, 0)) == 0) {
             wr = r_write(f->fd, &c, 1);
         }
     }
-    if (wr == -1) {
-        f->err = ACR_GET_OS_ERROR();
-        if (ACR_STATUS_IS_EAGAIN(f->err))
+    if (wr < 0) {
+        rc = ACR_GET_OS_ERROR();
+        if (ACR_STATUS_IS_EAGAIN(rc))
+            rc = ACR_TIMEUP;
+    }
+    switch (f->err = rc) {
+        case 0:
+            return (jint)wr;
+        break;
+        case ACR_TIMEUP:
             return 0;
+        break;
+        default:
+            ACR_THROW_IO_IF_ERR(rc);
+        break;
     }
-    else if (wr == 1)
-        f->err = 0;
-    return wr;
+    return -1;
 }
 
 ACR_IO_EXPORT_DECLARE(jint, FileSystem, write1)(ACR_JNISTDARGS,
@@ -853,6 +858,7 @@
     size_t  po = (size_t)off;
     size_t  cs = (size_t)len;
     ssize_t wr;
+    int     rc = 0;
     acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file);
 
     if (ACR_IOH_FTYPE(file) != ACR_DT_FILE) {
@@ -867,28 +873,32 @@
     if (!bb) {
         return -1;
     }
+    f->err = 0;
     wr = r_write(f->fd, bb + po, cs);
     if (wr == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
         f->timeout != 0) {
-        int rc;
-        if ((rc = wait_for_io_or_timeout(f, 0))) {
-            f->err = rc;
-            (*_E)->ReleaseByteArrayElements(_E, buf, bb, JNI_ABORT);
-            return rc == ACR_TIMEUP ? 0 : -1;
-        }
-        else {
+        if ((rc = wait_for_io_or_timeout(f, 0)) == 0) {
             wr = r_write(f->fd, bb + po, cs);
         }
     }
-    if (wr == -1) {
-        f->err = ACR_GET_OS_ERROR();
-        if (ACR_STATUS_IS_EAGAIN(f->err))
-            wr = 0;
+    if (wr < 0) {
+        rc = ACR_GET_OS_ERROR();
+        if (ACR_STATUS_IS_EAGAIN(rc))
+            rc = ACR_TIMEUP;
     }
-    else if (wr > 0)
-        f->err = 0;
    (*_E)->ReleaseByteArrayElements(_E, buf, bb, JNI_ABORT);
-    return (jint)wr;
+    switch (f->err = rc) {
+        case 0:
+            return (jint)wr;
+        break;
+        case ACR_TIMEUP:
+            return 0;
+        break;
+        default:
+            ACR_THROW_IO_IF_ERR(rc);
+        break;
+    }
+    return -1;
 }
 
 ACR_IO_EXPORT_DECLARE(jint, FileSystem, write2)(ACR_JNISTDARGS,
@@ -902,6 +912,7 @@
     size_t  cs = (size_t)len;
     jbyte  *pb;
     ssize_t wr;
+    int     rc = 0;
     acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file);
 
     if (ACR_IOH_FTYPE(file) != ACR_DT_FILE) {
@@ -924,23 +935,27 @@
     wr = r_write(f->fd, pb + po, cs);
     if (wr == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
         f->timeout != 0) {
-        int rc;
-        if ((rc = wait_for_io_or_timeout(f, 0))) {
-            f->err = rc;
-            return rc == ACR_TIMEUP ? 0 : -1;
-        }
-        else {
+        if ((rc = wait_for_io_or_timeout(f, 0)) == 0) {
             wr = r_write(f->fd, pb + po, cs);
         }
     }
-    if (wr == -1) {
-        f->err = ACR_GET_OS_ERROR();
-        if (ACR_STATUS_IS_EAGAIN(f->err))
-            wr = 0;
+    if (wr < 0) {
+        rc = ACR_GET_OS_ERROR();
+        if (ACR_STATUS_IS_EAGAIN(rc))
+            rc = ACR_TIMEUP;
+    }
+    switch (f->err = rc) {
+        case 0:
+            return (jint)wr;
+        break;
+        case ACR_TIMEUP:
+            return 0;
+        break;
+        default:
+            ACR_THROW_IO_IF_ERR(rc);
+        break;
     }
-    else if (wr > 0)
-        f->err = 0;
-    return (jint)wr;
+    return -1;
 }
 
 ACR_IO_EXPORT_DECLARE(jint, FileSystem, write3)(ACR_JNISTDARGS,
@@ -956,6 +971,7 @@
     size_t  cs = (size_t)len;
     jbyte  *pb;
     ssize_t wr;
+    int     rc = 0;
     acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file);
 
     if (ACR_IOH_FTYPE(file) != ACR_DT_FILE) {
@@ -981,23 +997,27 @@
     wr = r_write(f->fd, pb + po, cs);
     if (wr == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
         f->timeout != 0) {
-        int rc;
-        if ((rc = wait_for_io_or_timeout(f, 0))) {
-            f->err = rc;
-            return rc == ACR_TIMEUP ? 0 : -1;
-        }
-        else {
+        if ((rc = wait_for_io_or_timeout(f, 0)) == 0) {
             wr = r_write(f->fd, pb + po, cs);
         }
     }
-    if (wr == -1) {
-        f->err = ACR_GET_OS_ERROR();
-        if (ACR_STATUS_IS_EAGAIN(f->err))
-            wr = 0;
+    if (wr < 0) {
+        rc = ACR_GET_OS_ERROR();
+        if (ACR_STATUS_IS_EAGAIN(rc))
+            rc = ACR_TIMEUP;
+    }
+    switch (f->err = rc) {
+        case 0:
+            return (jint)wr;
+        break;
+        case ACR_TIMEUP:
+            return 0;
+        break;
+        default:
+            ACR_THROW_IO_IF_ERR(rc);
+        break;
     }
-    else if (wr > 0)
-        f->err = 0;
-    return (jint)wr;
+    return -1;
 }
 
 #define ACR_IOVEC_ON_STACK 32
@@ -1012,6 +1032,7 @@
     size_t  po = (size_t)off;
     size_t  cs = (size_t)len;
     ssize_t wr;
+    int     rc = 0;
     struct iovec *iov;
     struct iovec  onstack[ACR_IOVEC_ON_STACK];
     jbyteArray    bastack[ACR_IOVEC_ON_STACK];
@@ -1057,32 +1078,17 @@
     } while (wr == -1 && errno == EAGAIN);
     if (wr == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
         f->timeout != 0) {
-        int rc;
-        if ((rc = wait_for_io_or_timeout(f, 0))) {
-            f->err = rc;
-            for (i = 0; i < cs; i++) {
-                (*_E)->ReleaseByteArrayElements(_E, boa[i], iov[i].iov_base,
-                                                JNI_ABORT);
-            }
-            if (iov != onstack) {
-                x_free(iov);
-                x_free(boa);
-            }
-            return rc == ACR_TIMEUP ? 0 : -1;
-        }
-        else {
+        if ((rc = wait_for_io_or_timeout(f, 0)) == 0) {
             do {
                 wr = writev(f->fd, iov, pl);
             } while (wr == -1 && errno == EAGAIN);
         }
     }
-    if (wr == -1) {
-        f->err = ACR_GET_OS_ERROR();
-        if (ACR_STATUS_IS_EAGAIN(f->err))
-            wr = 0;
+    if (wr < 0) {
+        rc = ACR_GET_OS_ERROR();
+        if (ACR_STATUS_IS_EAGAIN(rc))
+            rc = ACR_TIMEUP;
     }
-    else if (wr > 0)
-        f->err = 0;
     for (i = 0; i < cs; i++) {
         (*_E)->ReleaseByteArrayElements(_E, boa[i], iov[i].iov_base, JNI_ABORT);
     }
@@ -1090,7 +1096,18 @@
         x_free(iov);
         x_free(boa);
     }
-    return (jint)wr;
+    switch (f->err = rc) {
+        case 0:
+            return (jint)wr;
+        break;
+        case ACR_TIMEUP:
+            return 0;
+        break;
+        default:
+            ACR_THROW_IO_IF_ERR(rc);
+        break;
+    }
+    return -1;
 }
 
 ACR_IO_EXPORT_DECLARE(jint, FileSystem, write5)(ACR_JNISTDARGS,
@@ -1104,6 +1121,7 @@
     size_t  po = (size_t)off;
     size_t  cs = (size_t)len;
     ssize_t wr;
+    int     rc = 0;
     struct iovec *iov;
     struct iovec  onstack[ACR_IOVEC_ON_STACK];
     acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file);
@@ -1139,29 +1157,31 @@
     } while (wr == -1 && errno == EAGAIN);
     if (wr == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
         f->timeout != 0) {
-        int rc;
-        if ((rc = wait_for_io_or_timeout(f, 0))) {
-            f->err = rc;
-            if (iov != onstack)
-                x_free(iov);
-            return rc == ACR_TIMEUP ? 0 : -1;
-        }
-        else {
+        if ((rc = wait_for_io_or_timeout(f, 0)) == 0) {
             do {
                 wr = writev(f->fd, iov, pl);
             } while (wr == -1 && errno == EAGAIN);
         }
     }
-    if (wr == -1) {
-        f->err = ACR_GET_OS_ERROR();
-        if (ACR_STATUS_IS_EAGAIN(f->err))
-            wr = 0;
+    if (wr < 0) {
+        rc = ACR_GET_OS_ERROR();
+        if (ACR_STATUS_IS_EAGAIN(rc))
+            rc = ACR_TIMEUP;
     }
-    else if (wr > 0)
-        f->err = 0;
     if (iov != onstack)
         x_free(iov);
-    return (jint)wr;
+    switch (f->err = rc) {
+        case 0:
+            return (jint)wr;
+        break;
+        case ACR_TIMEUP:
+            return 0;
+        break;
+        default:
+            ACR_THROW_IO_IF_ERR(rc);
+        break;
+    }
+    return -1;
 }
 
 ACR_IO_EXPORT_DECLARE(jint, FileSystem, fullw0)(ACR_JNISTDARGS,
@@ -1176,6 +1196,7 @@
     ssize_t cs = (ssize_t)len;
     ssize_t wt = 0;
     ssize_t wr;
+    int     rc = 0;
     acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file);
 
     if (ACR_IOH_FTYPE(file) != ACR_DT_FILE) {
@@ -1191,21 +1212,15 @@
         return -1;
     }
     wb = bb + po;
-    f->err = 0;
     do {
         wr = r_write(f->fd, wb, cs);
         if (wr == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
             f->timeout != 0) {
-            int rc;
-            if ((rc = wait_for_io_or_timeout(f, 0))) {
-                f->err = rc;
-                if (rc != ACR_TIMEUP) {
-                    break;
-                }
-            }
-            else {
+            if ((rc = wait_for_io_or_timeout(f, 0)) == 0) {
                 wr = r_write(f->fd, wb, cs);
             }
+            else if (rc != ACR_TIMEUP)
+                break;
         }
         if (wr > 0) {
             wb += wr;
@@ -1213,10 +1228,24 @@
             wt += wr;
         }
     } while (wr >= 0 && cs > 0);
-    if (wt == 0)
-        f->err = ACR_GET_OS_ERROR();
+    if (wt == 0) {
+        rc = ACR_GET_OS_ERROR();
+        if (ACR_STATUS_IS_EAGAIN(rc))
+            rc = ACR_TIMEUP;
+    }
    (*_E)->ReleaseByteArrayElements(_E, buf, bb, JNI_ABORT);
-    return (jint)wt;
+    switch (f->err = rc) {
+        case 0:
+            return (jint)wt;
+        break;
+        case ACR_TIMEUP:
+            return 0;
+        break;
+        default:
+            ACR_THROW_IO_IF_ERR(rc);
+        break;
+    }
+    return -1;
 }
 
 ACR_IO_EXPORT_DECLARE(jint, FileSystem, fullw1)(ACR_JNISTDARGS,
@@ -1231,6 +1260,7 @@
     jbyte  *pb;
     ssize_t wr;
     ssize_t wt = 0;
+    int     rc = 0;
     acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file);
 
     if (ACR_IOH_FTYPE(file) != ACR_DT_FILE) {
@@ -1251,20 +1281,15 @@
         return -1;
     }
     pb = pb + po;
-    f->err = 0;
     do {
         wr = r_write(f->fd, pb, cs);
         if (wr == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
             f->timeout != 0) {
-            int rc;
-            if ((rc = wait_for_io_or_timeout(f, 0))) {
-                f->err = rc;
-                if (rc != ACR_TIMEUP)
-                    break;
-            }
-            else {
+            if ((rc = wait_for_io_or_timeout(f, 0)) == 0) {
                 wr = r_write(f->fd, pb, cs);
             }
+            else if (rc != ACR_TIMEUP)
+                break;
         }
         if (wr > 0) {
             pb += wr;
@@ -1272,9 +1297,23 @@
             wt += wr;
         }
     } while (wr >= 0 && cs > 0);
-    if (wt == 0)
-        f->err = ACR_GET_OS_ERROR();
-    return (jint)wr;
+    if (wt == 0) {
+        rc = ACR_GET_OS_ERROR();
+        if (ACR_STATUS_IS_EAGAIN(rc))
+            rc = ACR_TIMEUP;
+    }
+    switch (f->err = rc) {
+        case 0:
+            return (jint)wt;
+        break;
+        case ACR_TIMEUP:
+            return 0;
+        break;
+        default:
+            ACR_THROW_IO_IF_ERR(rc);
+        break;
+    }
+    return -1;
 }
 
 ACR_IO_EXPORT_DECLARE(jint, FileSystem, fullw2)(ACR_JNISTDARGS,
@@ -1291,6 +1330,7 @@
     jbyte  *pb;
     ssize_t wr;
     ssize_t wt = 0;
+    int     rc = 0;
     acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file);
 
     if (ACR_IOH_FTYPE(file) != ACR_DT_FILE) {
@@ -1314,20 +1354,15 @@
     }
 #endif
     pb = pb + po;
-    f->err = 0;
     do {
         wr = r_write(f->fd, pb, cs);
         if (wr == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
             f->timeout != 0) {
-            int rc;
-            if ((rc = wait_for_io_or_timeout(f, 0))) {
-                f->err = rc;
-                if (rc != ACR_TIMEUP)
-                    break;
-            }
-            else {
+            if ((rc = wait_for_io_or_timeout(f, 0)) == 0) {
                 wr = r_write(f->fd, pb, cs);
             }
+            else if (rc != ACR_TIMEUP)
+                break;
         }
         if (wr > 0) {
             pb += wr;
@@ -1335,7 +1370,21 @@
             wt += wr;
         }
     } while (wr >= 0 && cs > 0);
-    if (wt == 0)
-        f->err = ACR_GET_OS_ERROR();
-    return (jint)wr;
+    if (wt == 0) {
+        rc = ACR_GET_OS_ERROR();
+        if (ACR_STATUS_IS_EAGAIN(rc))
+            rc = ACR_TIMEUP;
+    }
+    switch (f->err = rc) {
+        case 0:
+            return (jint)wt;
+        break;
+        case ACR_TIMEUP:
+            return 0;
+        break;
+        default:
+            ACR_THROW_IO_IF_ERR(rc);
+        break;
+    }
+    return -1;
 }

Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/fsysio.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/fsysio.c?rev=820546&r1=820545&r2=820546&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/win32/fsysio.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/win32/fsysio.c Thu Oct  1 06:29:59 2009
@@ -335,6 +335,18 @@
 
 }
 
+static int do_unlock(acr_file_t *f)
+{
+    int rc = 0;
+    OVERLAPPED  opp;
+
+    memset(&opp, 0, sizeof(OVERLAPPED));
+    if (!UnlockFileEx(f->fd, 0, 0xFFFFFFFF, 0xFFFFFFFF, &opp))
+        rc = ACR_GET_OS_ERROR();
+    LeaveCriticalSection(&f->lock);
+    return rc;
+}
+
 ACR_IO_EXPORT_DECLARE(jint, FileSystem, lock0)(ACR_JNISTDARGS,
                                                jint file,
                                                jint type)
@@ -1148,7 +1160,7 @@
                                                 jint b)
 {
     unsigned char c = (unsigned char)(b & 0xFF);
-    DWORD rc;
+    DWORD rc   = 0;
     DWORD wr   = 0;
     int locked = 0;
     LPOVERLAPPED lpo = NULL;
@@ -1184,7 +1196,7 @@
         op.QuadPart = 0;
         if (!SetFilePointerEx(f->fd, os, &op, FILE_END)) {
             ACR_THROW_IO_ERRNO();
-            LeaveCriticalSection(&f->lock);
+            do_unlock(f);
             return -1;
         }
         f->pos = op.QuadPart;
@@ -1197,13 +1209,12 @@
         if (IS_INVALID_HANDLE(lpo->hEvent)) {
             ACR_THROW_IO_ERRNO();
             if (locked)
-                LeaveCriticalSection(&f->lock);
+                do_unlock(f);
             return -1;
         }
         lpo->Offset     = (DWORD)(f->pos);
         lpo->OffsetHigh = (DWORD)(f->pos >> 32);
     }
-    f->err = 0;
     if (WriteFile(f->fd, &c, 1, &wr, lpo)) {
         /* All done. Update the position and return
          */
@@ -1211,9 +1222,9 @@
             f->pos += wr;
         goto finally;
     }
-    switch (f->err = GetLastError()) {
+    switch (rc = GetLastError()) {
         case ERROR_IO_PENDING:
-            if ((f->err = overlapped_wait(f, &wr)) == 0) {
+            if ((rc = overlapped_wait(f, &wr)) == 0) {
                 if (wr) {
                     f->pos += wr;
                     goto finally;
@@ -1226,11 +1237,19 @@
 
 finally:
     if (locked)
-        LeaveCriticalSection(&f->lock);
+        do_unlock(f);
     if (wr)
         return (jint)wr;
-    if (f->err)
-        return f->err == ACR_TIMEUP ? 0 : -1;
+    switch (f->err = rc) {
+        case 0:
+        case ACR_TIMEUP:
+            return 0;
+        break;
+
+        default:
+            ACR_THROW_IO_IF_ERR(f->err);
+        break;
+    }
     return -1;
 }
 
@@ -1241,7 +1260,7 @@
                                                 jint len)
 {
     jbyte  *bb;
-    DWORD   rc;
+    DWORD   rc = 0;
     DWORD   po = (DWORD)off;
     DWORD   cs = (DWORD)len;
     DWORD   wr = 0;
@@ -1280,7 +1299,7 @@
         op.QuadPart = 0;
         if (!SetFilePointerEx(f->fd, os, &op, FILE_END)) {
             ACR_THROW_IO_ERRNO();
-            LeaveCriticalSection(&f->lock);
+            do_unlock(f);
             return -1;
         }
         f->pos = op.QuadPart;
@@ -1293,7 +1312,7 @@
         if (IS_INVALID_HANDLE(lpo->hEvent)) {
             ACR_THROW_IO_ERRNO();
             if (locked)
-                LeaveCriticalSection(&f->lock);
+                do_unlock(f);
             return -1;
         }
         lpo->Offset     = (DWORD)(f->pos);
@@ -1303,10 +1322,9 @@
     bb = (*_E)->GetByteArrayElements(_E, buf, NULL);
     if (!bb) {
         if (locked)
-            LeaveCriticalSection(&f->lock);
+            do_unlock(f);
         return -1;
     }
-    f->err = 0;
     if (WriteFile(f->fd, bb + po, cs, &wr, lpo)) {
         /* All done. Update the position and return
          */
@@ -1314,9 +1332,9 @@
             f->pos += wr;
         goto finally;
     }
-    switch (f->err = GetLastError()) {
+    switch (rc = GetLastError()) {
         case ERROR_IO_PENDING:
-            if ((f->err = overlapped_wait(f, &wr)) == 0) {
+            if ((rc = overlapped_wait(f, &wr)) == 0) {
                 if (wr) {
                     f->pos += wr;
                     goto finally;
@@ -1329,12 +1347,20 @@
 
 finally:
     if (locked)
-        LeaveCriticalSection(&f->lock);
+        do_unlock(f);
    (*_E)->ReleaseByteArrayElements(_E, buf, bb, JNI_ABORT);
     if (wr)
         return (jint)wr;
-    if (f->err)
-        return f->err == ACR_TIMEUP ? 0 : -1;
+    switch (f->err = rc) {
+        case 0:
+        case ACR_TIMEUP:
+            return 0;
+        break;
+
+        default:
+            ACR_THROW_IO_IF_ERR(f->err);
+        break;
+    }
     return -1;
 }
 
@@ -1346,7 +1372,7 @@
 {
     size_t  pl;
     jbyte  *pb;
-    DWORD   rc;
+    DWORD   rc = 0;
     DWORD   po = (DWORD)off;
     DWORD   cs = (DWORD)len;
     DWORD   wr = 0;
@@ -1384,7 +1410,7 @@
         op.QuadPart = 0;
         if (!SetFilePointerEx(f->fd, os, &op, FILE_END)) {
             ACR_THROW_IO_ERRNO();
-            LeaveCriticalSection(&f->lock);
+            do_unlock(f);
             return -1;
         }
         f->pos = op.QuadPart;
@@ -1397,7 +1423,7 @@
         if (IS_INVALID_HANDLE(lpo->hEvent)) {
             ACR_THROW_IO_ERRNO();
             if (locked)
-                LeaveCriticalSection(&f->lock);
+                do_unlock(f);
             return -1;
         }
         lpo->Offset     = (DWORD)(f->pos);
@@ -1407,17 +1433,16 @@
     if (!pb) {
         ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ENULL, 0);
         if (locked)
-            LeaveCriticalSection(&f->lock);
+            do_unlock(f);
         return -1;
     }
     if ((po + cs) > (DWORD)pl) {
         ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EINDEX, 0);
         if (locked)
-            LeaveCriticalSection(&f->lock);
+            do_unlock(f);
         return -1;
     }
 
-    f->err = 0;
     if (WriteFile(f->fd, pb + po, cs, &wr, lpo)) {
         /* All done. Update the position and return
          */
@@ -1425,9 +1450,9 @@
             f->pos += wr;
         goto finally;
     }
-    switch (f->err = GetLastError()) {
+    switch (rc = GetLastError()) {
         case ERROR_IO_PENDING:
-            if ((f->err = overlapped_wait(f, &wr)) == 0) {
+            if ((rc = overlapped_wait(f, &wr)) == 0) {
                 if (wr) {
                     f->pos += wr;
                     goto finally;
@@ -1440,11 +1465,19 @@
 
 finally:
     if (locked)
-        LeaveCriticalSection(&f->lock);
+        do_unlock(f);
     if (wr)
         return (jint)wr;
-    if (f->err)
-        return f->err == ACR_TIMEUP ? 0 : -1;
+    switch (f->err = rc) {
+        case 0:
+        case ACR_TIMEUP:
+            return 0;
+        break;
+
+        default:
+            ACR_THROW_IO_IF_ERR(f->err);
+        break;
+    }
     return -1;
 }
 
@@ -1458,7 +1491,7 @@
     DWORD   pl;
 #endif
     jbyte  *pb;
-    DWORD   rc;
+    DWORD   rc = 0;
     DWORD   po = (DWORD)off;
     DWORD   cs = (DWORD)len;
     DWORD   wr = 0;
@@ -1496,7 +1529,7 @@
         op.QuadPart = 0;
         if (!SetFilePointerEx(f->fd, os, &op, FILE_END)) {
             ACR_THROW_IO_ERRNO();
-            LeaveCriticalSection(&f->lock);
+            do_unlock(f);
             return -1;
         }
         f->pos = op.QuadPart;
@@ -1509,7 +1542,7 @@
         if (IS_INVALID_HANDLE(lpo->hEvent)) {
             ACR_THROW_IO_ERRNO();
             if (locked)
-                LeaveCriticalSection(&f->lock);
+                do_unlock(f);
             return -1;
         }
         lpo->Offset     = (DWORD)(f->pos);
@@ -1519,7 +1552,7 @@
     if (!pb) {
         ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ENULL, 0);
         if (locked)
-            LeaveCriticalSection(&f->lock);
+            do_unlock(f);
         return -1;
     }
 #if defined(_DEBUG)
@@ -1527,11 +1560,10 @@
     if ((po + cs) > pl) {
         ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EINDEX, 0);
         if (locked)
-            LeaveCriticalSection(&f->lock);
+            do_unlock(f);
         return -1;
     }
 #endif
-    f->err = 0;
     if (WriteFile(f->fd, pb + po, cs, &wr, lpo)) {
         /* All done. Update the position and return
          */
@@ -1539,9 +1571,9 @@
             f->pos += wr;
         goto finally;
     }
-    switch (f->err = GetLastError()) {
+    switch (rc = GetLastError()) {
         case ERROR_IO_PENDING:
-            if ((f->err = overlapped_wait(f, &wr)) == 0) {
+            if ((rc = overlapped_wait(f, &wr)) == 0) {
                 if (wr) {
                     f->pos += wr;
                     goto finally;
@@ -1554,11 +1586,19 @@
 
 finally:
     if (locked)
-        LeaveCriticalSection(&f->lock);
+        do_unlock(f);
     if (wr)
         return (jint)wr;
-    if (f->err)
-        return f->err == ACR_TIMEUP ? 0 : -1;
+    switch (f->err = rc) {
+        case 0:
+        case ACR_TIMEUP:
+            return 0;
+        break;
+
+        default:
+            ACR_THROW_IO_IF_ERR(f->err);
+        break;
+    }
     return -1;
 }
 
@@ -1570,7 +1610,7 @@
 {
     DWORD   i;
     DWORD   pl;
-    DWORD   rc;
+    DWORD   rc = 0;
     DWORD   wr;
     DWORD   po = (DWORD)off;
     DWORD   cs = (DWORD)len;
@@ -1596,8 +1636,6 @@
         ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EINDEX, 0);
         return -1;
     }
-    if ((*_E)->EnsureLocalCapacity(_E, (jint)(cs * 2)))
-        return -1;
     if (f->flags & ACR_FOPEN_APPEND) {
         LARGE_INTEGER os;
         LARGE_INTEGER op;
@@ -1620,7 +1658,7 @@
         op.QuadPart = 0;
         if (!SetFilePointerEx(f->fd, os, &op, FILE_END)) {
             ACR_THROW_IO_ERRNO();
-            LeaveCriticalSection(&f->lock);
+            do_unlock(f);
             return -1;
         }
         f->pos = op.QuadPart;
@@ -1633,12 +1671,11 @@
         if (IS_INVALID_HANDLE(lpo->hEvent)) {
             ACR_THROW_IO_ERRNO();
             if (locked)
-                LeaveCriticalSection(&f->lock);
+                do_unlock(f);
             return -1;
         }
     }
 
-    f->err = 0;
     for (i = 0; i < cs, f->err == 0; i++) {
         bae = (*_E)->GetObjectArrayElement(_E, vec, (jsize)(i + po));
         bal = (DWORD)(*_E)->GetArrayLength(_E, bae);
@@ -1657,9 +1694,9 @@
             }
         }
         else {
-            switch (f->err = GetLastError()) {
+            switch (rc = GetLastError()) {
                 case ERROR_IO_PENDING:
-                    if ((f->err = overlapped_wait(f, &wr)) == 0) {
+                    if ((rc = overlapped_wait(f, &wr)) == 0) {
                         if (wr) {
                             f->pos += wr;
                             nbytes += wr;
@@ -1671,14 +1708,23 @@
             }
         }
         (*_E)->ReleaseByteArrayElements(_E, bae, bab, JNI_ABORT);
+        (*_E)->DeleteLocalRef(_E, bae);
     }
 
     if (locked)
-        LeaveCriticalSection(&f->lock);
+        do_unlock(f);
     if (nbytes)
         return (jint)nbytes;
-    if (f->err)
-        return f->err == ACR_TIMEUP ? 0 : -1;
+    switch (f->err = rc) {
+        case 0:
+        case ACR_TIMEUP:
+            return 0;
+        break;
+
+        default:
+            ACR_THROW_IO_IF_ERR(f->err);
+        break;
+    }
     return -1;
 }
 
@@ -1690,7 +1736,7 @@
 {
     DWORD   i;
     DWORD   pl;
-    DWORD   rc;
+    DWORD   rc = 0;
     DWORD   wr;
     DWORD   po = (DWORD)off;
     DWORD   cs = (DWORD)len;
@@ -1716,8 +1762,6 @@
         ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EINDEX, 0);
         return -1;
     }
-    if ((*_E)->EnsureLocalCapacity(_E, (jint)(cs * 2)))
-        return -1;
     if (f->flags & ACR_FOPEN_APPEND) {
         LARGE_INTEGER os;
         LARGE_INTEGER op;
@@ -1740,7 +1784,7 @@
         op.QuadPart = 0;
         if (!SetFilePointerEx(f->fd, os, &op, FILE_END)) {
             ACR_THROW_IO_ERRNO();
-            LeaveCriticalSection(&f->lock);
+            do_unlock(f);
             return -1;
         }
         f->pos = op.QuadPart;
@@ -1753,12 +1797,11 @@
         if (IS_INVALID_HANDLE(lpo->hEvent)) {
             ACR_THROW_IO_ERRNO();
             if (locked)
-                LeaveCriticalSection(&f->lock);
+                do_unlock(f);
             return -1;
         }
     }
 
-    f->err = 0;
     for (i = 0; i < cs, f->err == 0; i++) {
         bbe = (*_E)->GetObjectArrayElement(_E, vec, (jsize)(i + po));
         bbl = (DWORD)(*_E)->GetDirectBufferCapacity(_E, bbe);
@@ -1779,9 +1822,9 @@
             }
         }
         else {
-            switch (f->err = GetLastError()) {
+            switch (rc = GetLastError()) {
                 case ERROR_IO_PENDING:
-                    if ((f->err = overlapped_wait(f, &wr)) == 0) {
+                    if ((rc = overlapped_wait(f, &wr)) == 0) {
                         if (wr) {
                             f->pos += wr;
                             nbytes += wr;
@@ -1795,10 +1838,404 @@
     }
 
     if (locked)
-        LeaveCriticalSection(&f->lock);
+        do_unlock(f);
     if (nbytes)
         return (jint)nbytes;
-    if (f->err)
-        return f->err == ACR_TIMEUP ? 0 : -1;
+    switch (f->err = rc) {
+        case 0:
+        case ACR_TIMEUP:
+            return 0;
+        break;
+
+        default:
+            ACR_THROW_IO_IF_ERR(f->err);
+        break;
+    }
+    return -1;
+}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystem, fullw0)(ACR_JNISTDARGS,
+                                                jint file,
+                                                jbyteArray buf,
+                                                jint off,
+                                                jint len)
+{
+    jbyte  *bb;
+    jbyte  *wb;
+    DWORD   rc = 0;
+    DWORD   po = (DWORD)off;
+    DWORD   cs = (DWORD)len;
+    DWORD   wr;
+    DWORD nbytes = 0;
+    int   locked = 0;
+    LPOVERLAPPED lpo = NULL;
+    acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file);
+
+    if (ACR_IOH_FTYPE(file) != ACR_DT_FILE) {
+        ACR_THROW_IO_IF_ERR(ACR_EFTYPE);
+        return -1;
+    }
+    if (IS_INVALID_HANDLE(f)) {
+        ACR_THROW_IO_IF_ERR(ACR_EBADF);
+        return -1;
+    }
+    if (f->flags & ACR_FOPEN_APPEND) {
+        LARGE_INTEGER os;
+        LARGE_INTEGER op;
+
+        EnterCriticalSection(&f->lock);
+        /* apr_file_lock will mutex the file across processes.
+         * The call to apr_thread_mutex_lock is added to avoid
+         * a race condition between LockFile and WriteFile
+         * that occasionally leads to deadlocked threads.
+         */
+        rc = do_lock(f, LOCKFILE_EXCLUSIVE_LOCK);
+        if (rc) {
+            ACR_THROW_IO_IF_ERR(rc);
+            LeaveCriticalSection(&f->lock);
+            return -1;
+        }
+        /* Set the position to the file end
+         */
+        os.QuadPart = 0;
+        op.QuadPart = 0;
+        if (!SetFilePointerEx(f->fd, os, &op, FILE_END)) {
+            ACR_THROW_IO_ERRNO();
+            do_unlock(f);
+            return -1;
+        }
+        f->pos = op.QuadPart;
+        locked = 1;
+    }
+    if (f->blocking == BLK_OFF) {
+        lpo = &f->overlap;
+        if (IS_INVALID_HANDLE(lpo->hEvent))
+            lpo->hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
+        if (IS_INVALID_HANDLE(lpo->hEvent)) {
+            ACR_THROW_IO_ERRNO();
+            if (locked)
+                do_unlock(f);
+            return -1;
+        }
+    }
+    bb = (*_E)->GetByteArrayElements(_E, buf, NULL);
+    if (!bb) {
+        if (locked)
+            do_unlock(f);
+        return -1;
+    }
+    wb = bb + po;
+    do {
+        if (lpo) {
+            lpo->Offset     = (DWORD)(f->pos);
+            lpo->OffsetHigh = (DWORD)(f->pos >> 32);
+        }
+        wr = 0;
+        if (WriteFile(f->fd, wb, cs, &wr, lpo)) {
+            /* All done. Update the position and return
+             */
+            if (wr) {
+                f->pos += wr;
+                nbytes += wr;
+                wb     += wr;
+                cs     -= wr;
+            }
+        }
+        else {
+            switch (rc = GetLastError()) {
+                case ERROR_IO_PENDING:
+                    if ((rc = overlapped_wait_all(f, &wr)) == 0) {
+                        if (wr) {
+                            f->pos += wr;
+                            nbytes += wr;
+                            wb     += wr;
+                            cs     -= wr;
+                        }
+                    }
+                break;
+                default:
+                break;
+            }
+        }
+        if (rc && rc != ACR_TIMEUP)
+            break;
+    } while (cs > 0);
+
+    if (locked)
+        do_unlock(f);
+   (*_E)->ReleaseByteArrayElements(_E, buf, bb, JNI_ABORT);
+    if (nbytes)
+        return (jint)nbytes;
+    switch (f->err = rc) {
+        case 0:
+        case ACR_TIMEUP:
+            return 0;
+        break;
+
+        default:
+            ACR_THROW_IO_IF_ERR(f->err);
+        break;
+    }
+    return -1;
+}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystem, fullw1)(ACR_JNISTDARGS,
+                                                jint file,
+                                                jobject ptr,
+                                                jlong off,
+                                                jlong len)
+{
+    size_t  pl;
+    jbyte  *pb;
+    DWORD   rc = 0;
+    DWORD   po = (DWORD)off;
+    DWORD   cs = (DWORD)len;
+    DWORD   wr;
+    DWORD nbytes = 0;
+    int   locked = 0;
+    LPOVERLAPPED lpo = NULL;
+    acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file);
+
+    if (ACR_IOH_FTYPE(file) != ACR_DT_FILE) {
+        ACR_THROW_IO_IF_ERR(ACR_EFTYPE);
+        return -1;
+    }
+    if (IS_INVALID_HANDLE(f)) {
+        ACR_THROW_IO_IF_ERR(ACR_EBADF);
+        return -1;
+    }
+    pb = (jbyte *)ACR_PointerGet(_E, ptr, &pl);
+    if (!pb) {
+        ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ENULL, 0);
+        return -1;
+    }
+    if ((po + cs) > (DWORD)pl) {
+        ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EINDEX, 0);
+        return -1;
+    }
+    pb = pb + po;
+    if (f->flags & ACR_FOPEN_APPEND) {
+        LARGE_INTEGER os;
+        LARGE_INTEGER op;
+
+        EnterCriticalSection(&f->lock);
+        /* apr_file_lock will mutex the file across processes.
+         * The call to apr_thread_mutex_lock is added to avoid
+         * a race condition between LockFile and WriteFile
+         * that occasionally leads to deadlocked threads.
+         */
+        rc = do_lock(f, LOCKFILE_EXCLUSIVE_LOCK);
+        if (rc) {
+            ACR_THROW_IO_IF_ERR(rc);
+            LeaveCriticalSection(&f->lock);
+            return -1;
+        }
+        /* Set the position to the file end
+         */
+        os.QuadPart = 0;
+        op.QuadPart = 0;
+        if (!SetFilePointerEx(f->fd, os, &op, FILE_END)) {
+            ACR_THROW_IO_ERRNO();
+            do_unlock(f);
+            return -1;
+        }
+        f->pos = op.QuadPart;
+        locked = 1;
+    }
+    if (f->blocking == BLK_OFF) {
+        lpo = &f->overlap;
+        if (IS_INVALID_HANDLE(lpo->hEvent))
+            lpo->hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
+        if (IS_INVALID_HANDLE(lpo->hEvent)) {
+            ACR_THROW_IO_ERRNO();
+            if (locked)
+                do_unlock(f);
+            return -1;
+        }
+    }
+
+    do {
+        if (lpo) {
+            lpo->Offset     = (DWORD)(f->pos);
+            lpo->OffsetHigh = (DWORD)(f->pos >> 32);
+        }
+        wr = 0;
+        if (WriteFile(f->fd, pb, cs, &wr, lpo)) {
+            /* All done. Update the position and return
+             */
+            if (wr) {
+                f->pos += wr;
+                nbytes += wr;
+                pb     += wr;
+                cs     -= wr;
+            }
+        }
+        else {
+            switch (rc = GetLastError()) {
+                case ERROR_IO_PENDING:
+                    if ((rc = overlapped_wait_all(f, &wr)) == 0) {
+                        if (wr) {
+                            f->pos += wr;
+                            nbytes += wr;
+                            pb     += wr;
+                            cs     -= wr;
+                        }
+                    }
+                break;
+                default:
+                break;
+            }
+        }
+        if (rc && rc != ACR_TIMEUP)
+            break;
+    } while (cs > 0);
+
+    if (locked)
+        do_unlock(f);
+    if (nbytes)
+        return (jint)nbytes;
+    switch (f->err = rc) {
+        case 0:
+        case ACR_TIMEUP:
+            return 0;
+        break;
+
+        default:
+            ACR_THROW_IO_IF_ERR(f->err);
+        break;
+    }
+    return -1;
+}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystem, fullw2)(ACR_JNISTDARGS,
+                                                jint file,
+                                                jobject dbb,
+                                                jlong off,
+                                                jlong len)
+{
+#if defined(_DEBUG)
+    DWORD   pl;
+#endif
+    jbyte  *pb;
+    DWORD   rc = 0;
+    DWORD   po = (DWORD)off;
+    DWORD   cs = (DWORD)len;
+    DWORD   wr;
+    DWORD nbytes = 0;
+    int   locked = 0;
+    LPOVERLAPPED lpo = NULL;
+    acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file);
+
+    if (ACR_IOH_FTYPE(file) != ACR_DT_FILE) {
+        ACR_THROW_IO_IF_ERR(ACR_EFTYPE);
+        return -1;
+    }
+    if (IS_INVALID_HANDLE(f)) {
+        ACR_THROW_IO_IF_ERR(ACR_EBADF);
+        return -1;
+    }
+    pb = (jbyte *)(*_E)->GetDirectBufferAddress(_E, dbb);
+    if (!pb) {
+        ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ENULL, 0);
+        return -1;
+    }
+#if defined(_DEBUG)
+    pl = (DWORD)(*_E)->GetDirectBufferCapacity(_E, dbb);
+    if ((po + cs) > pl) {
+        ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EINDEX, 0);
+        return -1;
+    }
+#endif
+    pb = pb + po;
+    if (f->flags & ACR_FOPEN_APPEND) {
+        LARGE_INTEGER os;
+        LARGE_INTEGER op;
+
+        EnterCriticalSection(&f->lock);
+        /* apr_file_lock will mutex the file across processes.
+         * The call to apr_thread_mutex_lock is added to avoid
+         * a race condition between LockFile and WriteFile
+         * that occasionally leads to deadlocked threads.
+         */
+        rc = do_lock(f, LOCKFILE_EXCLUSIVE_LOCK);
+        if (rc) {
+            ACR_THROW_IO_IF_ERR(rc);
+            LeaveCriticalSection(&f->lock);
+            return -1;
+        }
+        /* Set the position to the file end
+         */
+        os.QuadPart = 0;
+        op.QuadPart = 0;
+        if (!SetFilePointerEx(f->fd, os, &op, FILE_END)) {
+            ACR_THROW_IO_ERRNO();
+            do_unlock(f);
+            return -1;
+        }
+        f->pos = op.QuadPart;
+        locked = 1;
+    }
+    if (f->blocking == BLK_OFF) {
+        lpo = &f->overlap;
+        if (IS_INVALID_HANDLE(lpo->hEvent))
+            lpo->hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
+        if (IS_INVALID_HANDLE(lpo->hEvent)) {
+            ACR_THROW_IO_ERRNO();
+            if (locked)
+                do_unlock(f);
+            return -1;
+        }
+    }
+
+    do {
+        if (lpo) {
+            lpo->Offset     = (DWORD)(f->pos);
+            lpo->OffsetHigh = (DWORD)(f->pos >> 32);
+        }
+        wr = 0;
+        if (WriteFile(f->fd, pb, cs, &wr, lpo)) {
+            /* All done. Update the position and return
+             */
+            if (wr) {
+                f->pos += wr;
+                nbytes += wr;
+                pb     += wr;
+                cs     -= wr;
+            }
+        }
+        else {
+            switch (rc = GetLastError()) {
+                case ERROR_IO_PENDING:
+                    if ((rc = overlapped_wait_all(f, &wr)) == 0) {
+                        if (wr) {
+                            f->pos += wr;
+                            nbytes += wr;
+                            pb     += wr;
+                            cs     -= wr;
+                        }
+                    }
+                break;
+                default:
+                break;
+            }
+        }
+        if (rc && rc != ACR_TIMEUP)
+            break;
+    } while (cs > 0);
+
+    if (locked)
+        do_unlock(f);
+    if (nbytes)
+        return (jint)nbytes;
+    switch (f->err = rc) {
+        case 0:
+        case ACR_TIMEUP:
+            return 0;
+        break;
+
+        default:
+            ACR_THROW_IO_IF_ERR(f->err);
+        break;
+    }
     return -1;
 }