commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mt...@apache.org
Subject svn commit: r883810 [3/3] - in /commons/sandbox/runtime/trunk/src/main/native: Makefile.in Makefile.msc.in include/arch/unix/acr_arch.h os/unix/fsysio.c os/unix/fsysrw.c os/win32/fsysio.c os/win32/fsysrw.c
Date Tue, 24 Nov 2009 18:47:16 GMT
Added: commons/sandbox/runtime/trunk/src/main/native/os/win32/fsysrw.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/fsysrw.c?rev=883810&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/win32/fsysrw.c (added)
+++ commons/sandbox/runtime/trunk/src/main/native/os/win32/fsysrw.c Tue Nov 24 18:47:13 2009
@@ -0,0 +1,1747 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "acr.h"
+#include "acr_private.h"
+#include "acr_error.h"
+#include "acr_string.h"
+#include "acr_memory.h"
+#include "acr_descriptor.h"
+#include "acr_pointer.h"
+#include "acr_file.h"
+#include "acr_fileio.h"
+
+#define ACR_WANT_LATE_DLL
+#include "acr_arch.h"
+#include "acr_port.h"
+
+
+extern int do_lock(acr_file_t *f, DWORD flags);
+extern int do_unlock(acr_file_t *f);
+
+static DWORD overlapped_wait_all(acr_file_t *f, DWORD *nbytes)
+{
+    DWORD ws;
+    DWORD rc = 0;
+
+    do {
+        switch (ws = ACR_WaitForObjectOrSignal(f->overlap.hEvent, INFINITE)) {
+            case WAIT_IO_COMPLETION:
+            case WAIT_ABANDONED_0:
+            case WAIT_ABANDONED_1:
+            case WAIT_OBJECT_0:
+                /* Signal event is set.
+                 * Get it's status.
+                 */
+                rc = ACR_DeliverSignals();
+            break;
+            case WAIT_OBJECT_1:
+                /* Operation success */
+                rc = 0;
+            break;
+            case WAIT_FAILED:
+                /* We got the error while waiting
+                 */
+                rc = ACR_GET_OS_ERROR();
+            break;
+            default:
+                rc = ACR_EINVAL;
+            break;
+        }
+    } while (rc == ACR_EINTR);
+
+    if (rc) {
+        /* There is one case that represents entirely
+         * successful operations, otherwise we will cancel
+         * the operation in progress.
+         */
+        CancelIo(f->fd);
+    }
+    if (!GetOverlappedResult(f->fd,
+                             &f->overlap,
+                             nbytes,
+                             FALSE)) {
+        rc = GetLastError();
+        if (rc == ERROR_IO_INCOMPLETE ||
+            rc == ERROR_OPERATION_ABORTED)
+            rc = ACR_TIMEUP;
+    }
+    return rc;
+}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystemIo, read0)(ACR_JNISTDARGS,
+                                                 jint file)
+{
+    unsigned char c;
+    DWORD rd = 0;
+    DWORD rc = 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_EX_IF_ERR(ACR_EX_INVALID_DESC, ACR_EFTYPE);
+        return -1;
+    }
+    if (IS_INVALID_HANDLE(f)) {
+        ACR_THROW_EX_IF_ERR(ACR_EX_CLOSED_DESC, ACR_EBADF);
+        return -1;
+    }
+    if (f->eof) {
+        return -1;
+    }
+
+    if (f->blocking == BLK_OFF) {
+        if (f->timeout == 0 && f->type == ACR_FT_PIPE) {
+            if (!PeekNamedPipe(f->fd, NULL, 0, NULL, &rd, NULL)) {
+                rc = GetLastError();
+                if (rc == ERROR_BROKEN_PIPE) {
+                    f->eof = 1;
+                    return -1;
+                }
+                else {
+                    f->eof = 1;
+                    ACR_THROW_IO_IF_ERR(rc);
+                    return -1;
+                }
+            }
+            else {
+                if (rd == 0) {
+                    ACR_DescriptorSetErrEx(_E, f->descriptor, ACR_TIMEUP);
+                    return -1;
+                }
+            }
+        }
+        lpo = &f->overlap;
+        if (IS_INVALID_HANDLE(lpo->hEvent))
+            lpo->hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
+        if (IS_INVALID_HANDLE(lpo->hEvent))
+            return ACR_GET_OS_ERROR();
+        lpo->Offset     = (DWORD)(f->pos);
+        lpo->OffsetHigh = (DWORD)(f->pos >> 32);
+    }
+    if (ReadFile(f->fd, &c, 1, &rd, lpo)) {
+        /* All done. Update the position and return
+         */
+        if (rd) {
+            f->pos += rd;
+            return c;
+        }
+        else {
+            f->eof = 1;
+            return  -1;
+        }
+    }
+    switch (rc = GetLastError()) {
+        case ERROR_HANDLE_EOF:
+        case ERROR_BROKEN_PIPE:
+            rc     = 0;
+            f->eof = 1;
+        break;
+        case ERROR_IO_PENDING:
+            switch (rc = overlapped_wait(f, &rd)) {
+                case 0:
+                    if (rd) {
+                        f->pos += rd;
+                        return c;
+                    }
+                    else
+                        f->eof = 1;
+                break;
+                case ERROR_HANDLE_EOF:
+                case ERROR_BROKEN_PIPE:
+                    rc     = 0;
+                    f->eof = 1;
+                break;
+                default:
+                break;
+            }
+        break;
+        default:
+        break;
+    }
+    if (f->eof)
+        return -1;
+
+    ACR_DescriptorSetErrEx(_E, f->descriptor, rc);
+    switch (rc) {
+        case 0:
+        case ACR_TIMEUP:
+        case ERROR_OPERATION_ABORTED:
+            ACR_THROW_EX_IF_ERR(ACR_EX_ETIMEOUT, rc);
+        break;
+        case ERROR_INVALID_HANDLE:
+            ACR_THROW_EX_IF_ERR(ACR_EX_ACLOSED_DESC, rc);
+        break;
+        default:
+            ACR_THROW_IO_IF_ERR(rc);
+        break;
+    }
+    return -1;
+}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystemIo, read1)(ACR_JNISTDARGS,
+                                                 jint file,
+                                                 jbyteArray buf,
+                                                 jint off,
+                                                 jint len)
+{
+    jbyte  *bb = NULL;
+    jbyte  *bc = NULL;
+    DWORD   po = (DWORD)off;
+    DWORD   cs = (DWORD)len;
+    DWORD   rd = 0;
+    DWORD   rc = 0;
+    LPOVERLAPPED lpo = NULL;
+    jbyte   onstack[ACR_PBUFF_SIZ];
+    acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file);
+
+    if (ACR_IOH_FTYPE(file) != ACR_DT_FILE) {
+        ACR_THROW_EX_IF_ERR(ACR_EX_INVALID_DESC, ACR_EFTYPE);
+        return -1;
+    }
+    if (IS_INVALID_HANDLE(f)) {
+        ACR_THROW_EX_IF_ERR(ACR_EX_CLOSED_DESC, ACR_EBADF);
+        return -1;
+    }
+    if (f->eof) {
+        return -1;
+    }
+    if (f->blocking == BLK_OFF) {
+        if (f->timeout == 0 && f->type == ACR_FT_PIPE) {
+            if (!PeekNamedPipe(f->fd, NULL, 0, NULL, &rd, NULL)) {
+                rc = GetLastError();
+                if (rc == ERROR_BROKEN_PIPE) {
+                    f->eof = 1;
+                    return -1;
+                }
+                else {
+                    ACR_THROW_IO_IF_ERR(rc);
+                    return -1;
+                }
+            }
+            else {
+                if (rd == 0) {
+                    ACR_DescriptorSetErrEx(_E, f->descriptor, ACR_TIMEUP);
+                    return 0;
+                }
+                else {
+                    /* Update read size that can be done
+                     * without blocking
+                     */
+                    if (cs > rd)
+                        cs = rd;
+                }
+            }
+        }
+        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();
+            return -1;
+        }
+        lpo->Offset     = (DWORD)(f->pos);
+        lpo->OffsetHigh = (DWORD)(f->pos >> 32);
+    }
+    if (cs > (DWORD)sizeof(onstack)) {
+        if (cs > (1024 * 1024)) {
+            bc = (*_E)->GetByteArrayElements(_E, buf, NULL);
+            if (bc)
+                bb = bc + po;
+        }
+        else
+            bb = ACR_Malloc(_E, THROW_FMARK, cs);
+    }
+    else
+        bb = onstack;
+    if (!bb) {
+        /* Exception was already thrown */
+        return -1;
+    }
+    rc = 0;
+    if (ReadFile(f->fd, bb, cs, &rd, lpo)) {
+        /* All done. Update the position and return
+         */
+        if (rd)
+            f->pos += rd;
+        else
+            f->eof = 1;
+        goto finally;
+    }
+    switch (rc = GetLastError()) {
+        case ERROR_HANDLE_EOF:
+        case ERROR_BROKEN_PIPE:
+            rc     = 0;
+            f->eof = 1;
+        break;
+        case ERROR_IO_PENDING:
+            switch (rc = overlapped_wait(f, &rd)) {
+                case 0:
+                    if (rd) {
+                        f->pos += rd;
+                        goto finally;
+                    }
+                    else
+                        f->eof = 1;
+                break;
+                case ERROR_HANDLE_EOF:
+                case ERROR_BROKEN_PIPE:
+                    rc     = 0;
+                    f->eof = 1;
+                break;
+                default:
+                break;
+            }
+        break;
+        default:
+        break;
+    }
+
+finally:
+    if (rd) {
+        if (bc) {
+            (*_E)->ReleaseByteArrayElements(_E, buf, bc, 0);
+            return (jint)rd;
+        }
+        else {
+            (*_E)->SetByteArrayRegion(_E, buf, (jsize)po, (jsize)rd, bb);
+        }
+    }
+    if (bb != onstack) {
+        if (bc)
+            (*_E)->ReleaseByteArrayElements(_E, buf, bc, JNI_ABORT);
+        else
+            x_free(bb);
+    }
+    if (rd > 0)
+        return (jint)rd;
+    if (f->eof)
+        return -1;
+
+    ACR_DescriptorSetErrEx(_E, f->descriptor, rc);
+    switch (rc) {
+        case 0:
+        case ACR_TIMEUP:
+        case ERROR_OPERATION_ABORTED:
+            return 0;
+        break;
+        case ERROR_INVALID_HANDLE:
+            ACR_THROW_EX_IF_ERR(ACR_EX_ACLOSED_DESC, rc);
+        break;
+        default:
+            ACR_THROW_IO_IF_ERR(rc);
+        break;
+    }
+    return -1;
+}
+
+ACR_IO_EXPORT_DECLARE(jlong, FileSystemIo, read2)(ACR_JNISTDARGS,
+                                                  jint file,
+                                                  jobject ptr,
+                                                  jlong off,
+                                                  jlong len)
+{
+    size_t  pl;
+    DWORD   po = (DWORD)off;
+    DWORD   cs = (DWORD)len;
+    DWORD   rd = 0;
+    DWORD   rc = 0;
+    LPOVERLAPPED lpo = NULL;
+    jbyte  *pb;
+    acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file);
+
+    if (ACR_IOH_FTYPE(file) != ACR_DT_FILE) {
+        ACR_THROW_EX_IF_ERR(ACR_EX_INVALID_DESC, ACR_EFTYPE);
+        return -1;
+    }
+    if (IS_INVALID_HANDLE(f)) {
+        ACR_THROW_EX_IF_ERR(ACR_EX_CLOSED_DESC, ACR_EBADF);
+        return -1;
+    }
+    if (f->eof) {
+        return -1;
+    }
+    if (f->blocking == BLK_OFF) {
+        if (f->timeout == 0 && f->type == ACR_FT_PIPE) {
+            if (!PeekNamedPipe(f->fd, NULL, 0, NULL, &rd, NULL)) {
+                rc = GetLastError();
+                if (rc == ERROR_BROKEN_PIPE) {
+                    f->eof = 1;
+                    return -1;
+                }
+                else {
+                    ACR_THROW_IO_IF_ERR(rc);
+                    return -1;
+                }
+            }
+            else {
+                if (rd == 0) {
+                    ACR_DescriptorSetErrEx(_E, f->descriptor, ACR_TIMEUP);
+                    return 0;
+                }
+                else {
+                    /* Update read size that can be done
+                     * without blocking
+                     */
+                    if (cs > rd)
+                        cs = rd;
+                }
+            }
+        }
+        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();
+            return -1;
+        }
+        lpo->Offset     = (DWORD)(f->pos);
+        lpo->OffsetHigh = (DWORD)(f->pos >> 32);
+    }
+    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;
+    }
+    rc = 0;
+    if (ReadFile(f->fd, pb + po, cs, &rd, lpo)) {
+        /* All done. Update the position and return
+         */
+        if (rd)
+            f->pos += rd;
+        else
+            f->eof = 1;
+        goto finally;
+    }
+    switch (rc = GetLastError()) {
+        case ERROR_HANDLE_EOF:
+        case ERROR_BROKEN_PIPE:
+            rc     = 0;
+            f->eof = 1;
+        break;
+        case ERROR_IO_PENDING:
+            switch (rc = overlapped_wait(f, &rd)) {
+                case 0:
+                    if (rd) {
+                        f->pos += rd;
+                        goto finally;
+                    }
+                    else
+                        f->eof = 1;
+                break;
+                case ERROR_HANDLE_EOF:
+                case ERROR_BROKEN_PIPE:
+                    rc     = 0;
+                    f->eof = 1;
+                break;
+                default:
+                break;
+            }
+        break;
+        default:
+        break;
+    }
+
+finally:
+    if (rd > 0)
+        return (jlong)rd;
+    if (f->eof)
+        return -1;
+
+    ACR_DescriptorSetErrEx(_E, f->descriptor, rc);
+    switch (rc) {
+        case 0:
+        case ACR_TIMEUP:
+        case ERROR_OPERATION_ABORTED:
+            return 0;
+        break;
+        case ERROR_INVALID_HANDLE:
+            ACR_THROW_EX_IF_ERR(ACR_EX_ACLOSED_DESC, rc);
+        break;
+        default:
+            ACR_THROW_IO_IF_ERR(rc);
+        break;
+    }
+    return -1;
+}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystemIo, read3)(ACR_JNISTDARGS,
+                                                 jint file,
+                                                 jobject dbb,
+                                                 jint off,
+                                                 jint len)
+{
+#if defined(_DEBUG)
+    DWORD   pl;
+#endif
+    DWORD   po = (DWORD)off;
+    DWORD   cs = (DWORD)len;
+    DWORD   rd = 0;
+    DWORD   rc = 0;
+    LPOVERLAPPED lpo = NULL;
+    jbyte  *pb;
+    acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file);
+
+    if (ACR_IOH_FTYPE(file) != ACR_DT_FILE) {
+        ACR_THROW_EX_IF_ERR(ACR_EX_INVALID_DESC, ACR_EFTYPE);
+        return -1;
+    }
+    if (IS_INVALID_HANDLE(f)) {
+        ACR_THROW_EX_IF_ERR(ACR_EX_CLOSED_DESC, ACR_EBADF);
+        return -1;
+    }
+    if (f->eof) {
+        return -1;
+    }
+    if (f->blocking == BLK_OFF) {
+        if (f->timeout == 0 && f->type == ACR_FT_PIPE) {
+            if (!PeekNamedPipe(f->fd, NULL, 0, NULL, &rd, NULL)) {
+                rc = GetLastError();
+                if (rc == ERROR_BROKEN_PIPE) {
+                    f->eof = 1;
+                    return -1;
+                }
+                else {
+                    ACR_THROW_IO_IF_ERR(rc);
+                    return -1;
+                }
+            }
+            else {
+                if (rd == 0) {
+                    ACR_DescriptorSetErrEx(_E, f->descriptor, ACR_TIMEUP);
+                    return 0;
+                }
+                else {
+                    /* Update read size that can be done
+                     * without blocking
+                     */
+                    if (cs > rd)
+                        cs = rd;
+                }
+            }
+        }
+        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();
+            return -1;
+        }
+        lpo->Offset     = (DWORD)(f->pos);
+        lpo->OffsetHigh = (DWORD)(f->pos >> 32);
+    }
+    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
+    if (ReadFile(f->fd, pb + po, cs, &rd, lpo)) {
+        /* All done. Update the position and return
+         */
+        if (rd)
+            f->pos += rd;
+        else
+            f->eof = 1;
+        goto finally;
+    }
+    switch (rc = GetLastError()) {
+        case ERROR_HANDLE_EOF:
+        case ERROR_BROKEN_PIPE:
+            rc     = 0;
+            f->eof = 1;
+        break;
+        case ERROR_IO_PENDING:
+            switch (rc = overlapped_wait(f, &rd)) {
+                case 0:
+                    if (rd) {
+                        f->pos += rd;
+                        goto finally;
+                    }
+                    else
+                        f->eof = 1;
+                break;
+                case ERROR_HANDLE_EOF:
+                case ERROR_BROKEN_PIPE:
+                    rc     = 0;
+                    f->eof = 1;
+                break;
+                default:
+                break;
+            }
+        break;
+        default:
+        break;
+    }
+
+finally:
+    if (rd > 0)
+        return (jint)rd;
+    if (f->eof)
+        return -1;
+
+    ACR_DescriptorSetErrEx(_E, f->descriptor, rc);
+    switch (rc) {
+        case 0:
+        case ACR_TIMEUP:
+        case ERROR_OPERATION_ABORTED:
+            return 0;
+        break;
+        case ERROR_INVALID_HANDLE:
+            ACR_THROW_EX_IF_ERR(ACR_EX_ACLOSED_DESC, rc);
+        break;
+        default:
+            ACR_THROW_IO_IF_ERR(rc);
+        break;
+    }
+    return -1;
+}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystemIo, write0)(ACR_JNISTDARGS,
+                                                  jint file,
+                                                  jint b)
+{
+    unsigned char c = (unsigned char)(b & 0xFF);
+    DWORD rc   = 0;
+    DWORD wr   = 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_EX_IF_ERR(ACR_EX_INVALID_DESC, ACR_EFTYPE);
+        return -1;
+    }
+    if (IS_INVALID_HANDLE(f)) {
+        ACR_THROW_EX_IF_ERR(ACR_EX_CLOSED_DESC, 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;
+        }
+        lpo->Offset     = (DWORD)(f->pos);
+        lpo->OffsetHigh = (DWORD)(f->pos >> 32);
+    }
+    if (WriteFile(f->fd, &c, 1, &wr, lpo)) {
+        /* All done. Update the position and return
+         */
+        if (wr)
+            f->pos += wr;
+        goto finally;
+    }
+    switch (rc = GetLastError()) {
+        case ERROR_IO_PENDING:
+            if ((rc = overlapped_wait(f, &wr)) == 0) {
+                if (wr) {
+                    f->pos += wr;
+                    goto finally;
+                }
+            }
+        break;
+        default:
+        break;
+    }
+
+finally:
+    if (locked)
+        do_unlock(f);
+    if (wr)
+        return (jint)wr;
+
+    ACR_DescriptorSetErrEx(_E, f->descriptor, rc);
+    switch (rc) {
+        case 0:
+        case ACR_TIMEUP:
+        case ERROR_OPERATION_ABORTED:
+            return 0;
+        break;
+        case ERROR_INVALID_HANDLE:
+            ACR_THROW_EX_IF_ERR(ACR_EX_ACLOSED_DESC, rc);
+        break;
+        default:
+            ACR_THROW_IO_IF_ERR(rc);
+        break;
+    }
+    return -1;
+}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystemIo, write1)(ACR_JNISTDARGS,
+                                                  jint file,
+                                                  jbyteArray buf,
+                                                  jint off,
+                                                  jint len)
+{
+    jbyte  *bb;
+    DWORD   rc = 0;
+    DWORD   po = (DWORD)off;
+    DWORD   cs = (DWORD)len;
+    DWORD   wr = 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_EX_IF_ERR(ACR_EX_INVALID_DESC, ACR_EFTYPE);
+        return -1;
+    }
+    if (IS_INVALID_HANDLE(f)) {
+        ACR_THROW_EX_IF_ERR(ACR_EX_CLOSED_DESC, 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;
+        }
+        lpo->Offset     = (DWORD)(f->pos);
+        lpo->OffsetHigh = (DWORD)(f->pos >> 32);
+    }
+
+    bb = (*_E)->GetByteArrayElements(_E, buf, NULL);
+    if (!bb) {
+        if (locked)
+            do_unlock(f);
+        return -1;
+    }
+    if (WriteFile(f->fd, bb + po, cs, &wr, lpo)) {
+        /* All done. Update the position and return
+         */
+        if (wr)
+            f->pos += wr;
+        goto finally;
+    }
+    switch (rc = GetLastError()) {
+        case ERROR_IO_PENDING:
+            if ((rc = overlapped_wait(f, &wr)) == 0) {
+                if (wr) {
+                    f->pos += wr;
+                    goto finally;
+                }
+            }
+        break;
+        default:
+        break;
+    }
+
+finally:
+    if (locked)
+        do_unlock(f);
+   (*_E)->ReleaseByteArrayElements(_E, buf, bb, JNI_ABORT);
+    if (wr)
+        return (jint)wr;
+
+    ACR_DescriptorSetErrEx(_E, f->descriptor, rc);
+    switch (rc) {
+        case 0:
+        case ACR_TIMEUP:
+        case ERROR_OPERATION_ABORTED:
+            return 0;
+        break;
+        case ERROR_INVALID_HANDLE:
+            ACR_THROW_EX_IF_ERR(ACR_EX_ACLOSED_DESC, rc);
+        break;
+        default:
+            ACR_THROW_IO_IF_ERR(rc);
+        break;
+    }
+    return -1;
+}
+
+ACR_IO_EXPORT_DECLARE(jlong, FileSystemIo, write2)(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 = 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_EX_IF_ERR(ACR_EX_INVALID_DESC, ACR_EFTYPE);
+        return -1;
+    }
+    if (IS_INVALID_HANDLE(f)) {
+        ACR_THROW_EX_IF_ERR(ACR_EX_CLOSED_DESC, 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;
+        }
+        lpo->Offset     = (DWORD)(f->pos);
+        lpo->OffsetHigh = (DWORD)(f->pos >> 32);
+    }
+    pb = (jbyte *)ACR_PointerGet(_E, ptr, &pl);
+    if (!pb) {
+        ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ENULL, 0);
+        if (locked)
+            do_unlock(f);
+        return -1;
+    }
+    if ((po + cs) > (DWORD)pl) {
+        ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EINDEX, 0);
+        if (locked)
+            do_unlock(f);
+        return -1;
+    }
+
+    if (WriteFile(f->fd, pb + po, cs, &wr, lpo)) {
+        /* All done. Update the position and return
+         */
+        if (wr)
+            f->pos += wr;
+        goto finally;
+    }
+    switch (rc = GetLastError()) {
+        case ERROR_IO_PENDING:
+            if ((rc = overlapped_wait(f, &wr)) == 0) {
+                if (wr) {
+                    f->pos += wr;
+                    goto finally;
+                }
+            }
+        break;
+        default:
+        break;
+    }
+
+finally:
+    if (locked)
+        do_unlock(f);
+    if (wr)
+        return (jlong)wr;
+
+    ACR_DescriptorSetErrEx(_E, f->descriptor, rc);
+    switch (rc) {
+        case 0:
+        case ACR_TIMEUP:
+        case ERROR_OPERATION_ABORTED:
+            return 0;
+        break;
+        case ERROR_INVALID_HANDLE:
+            ACR_THROW_EX_IF_ERR(ACR_EX_ACLOSED_DESC, rc);
+        break;
+        default:
+            ACR_THROW_IO_IF_ERR(rc);
+        break;
+    }
+    return -1;
+}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystemIo, write3)(ACR_JNISTDARGS,
+                                                  jint file,
+                                                  jobject dbb,
+                                                  jint off,
+                                                  jint len)
+{
+#if defined(_DEBUG)
+    DWORD   pl;
+#endif
+    jbyte  *pb;
+    DWORD   rc = 0;
+    DWORD   po = (DWORD)off;
+    DWORD   cs = (DWORD)len;
+    DWORD   wr = 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_EX_IF_ERR(ACR_EX_INVALID_DESC, ACR_EFTYPE);
+        return -1;
+    }
+    if (IS_INVALID_HANDLE(f)) {
+        ACR_THROW_EX_IF_ERR(ACR_EX_CLOSED_DESC, 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;
+        }
+        lpo->Offset     = (DWORD)(f->pos);
+        lpo->OffsetHigh = (DWORD)(f->pos >> 32);
+    }
+    pb = (jbyte *)(*_E)->GetDirectBufferAddress(_E, dbb);
+    if (!pb) {
+        ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ENULL, 0);
+        if (locked)
+            do_unlock(f);
+        return -1;
+    }
+#if defined(_DEBUG)
+    pl = (DWORD)(*_E)->GetDirectBufferCapacity(_E, dbb);
+    if ((po + cs) > pl) {
+        ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EINDEX, 0);
+        if (locked)
+            do_unlock(f);
+        return -1;
+    }
+#endif
+    if (WriteFile(f->fd, pb + po, cs, &wr, lpo)) {
+        /* All done. Update the position and return
+         */
+        if (wr)
+            f->pos += wr;
+        goto finally;
+    }
+    switch (rc = GetLastError()) {
+        case ERROR_IO_PENDING:
+            if ((rc = overlapped_wait(f, &wr)) == 0) {
+                if (wr) {
+                    f->pos += wr;
+                    goto finally;
+                }
+            }
+        break;
+        default:
+        break;
+    }
+
+finally:
+    if (locked)
+        do_unlock(f);
+    if (wr)
+        return (jint)wr;
+
+    ACR_DescriptorSetErrEx(_E, f->descriptor, rc);
+    switch (rc) {
+        case 0:
+        case ACR_TIMEUP:
+        case ERROR_OPERATION_ABORTED:
+            return 0;
+        break;
+        case ERROR_INVALID_HANDLE:
+            ACR_THROW_EX_IF_ERR(ACR_EX_ACLOSED_DESC, rc);
+        break;
+        default:
+            ACR_THROW_IO_IF_ERR(rc);
+        break;
+    }
+    return -1;
+}
+
+ACR_IO_EXPORT_DECLARE(jlong, FileSystemIo, write4)(ACR_JNISTDARGS,
+                                                   jint file,
+                                                   jobjectArray vec,
+                                                   jint off,
+                                                   jint len)
+{
+    DWORD   i;
+    DWORD   pl;
+    DWORD   rc = 0;
+    DWORD   wr;
+    DWORD   po = (DWORD)off;
+    DWORD   cs = (DWORD)len;
+    jbyteArray bae;
+    jbyte     *bab;
+    DWORD      bal;
+    int   locked = 0;
+    INT64 nbytes = 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_EX_IF_ERR(ACR_EX_INVALID_DESC, ACR_EFTYPE);
+        return -1;
+    }
+    if (IS_INVALID_HANDLE(f)) {
+        ACR_THROW_EX_IF_ERR(ACR_EX_CLOSED_DESC, ACR_EBADF);
+        return -1;
+    }
+    pl = (DWORD)(*_E)->GetArrayLength(_E, vec);
+    if ((po + cs) > pl) {
+        ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EINDEX, 0);
+        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;
+        }
+    }
+
+    for (i = 0; i < cs, rc == 0; i++) {
+        bae = (*_E)->GetObjectArrayElement(_E, vec, (jsize)(i + po));
+        bal = (DWORD)(*_E)->GetArrayLength(_E, bae);
+        bab = (*_E)->GetByteArrayElements(_E, bae, NULL);
+        if (lpo) {
+            lpo->Offset     = (DWORD)(f->pos);
+            lpo->OffsetHigh = (DWORD)(f->pos >> 32);
+        }
+        wr = 0;
+        if (WriteFile(f->fd, bab, bal, &wr, lpo)) {
+            /* All done. Update the position and return
+             */
+            if (wr) {
+                f->pos += wr;
+                nbytes += wr;
+            }
+        }
+        else {
+            switch (rc = GetLastError()) {
+                case ERROR_IO_PENDING:
+                    if ((rc = overlapped_wait(f, &wr)) == 0) {
+                        if (wr) {
+                            f->pos += wr;
+                            nbytes += wr;
+                        }
+                    }
+                break;
+                default:
+                break;
+            }
+        }
+        (*_E)->ReleaseByteArrayElements(_E, bae, bab, JNI_ABORT);
+        (*_E)->DeleteLocalRef(_E, bae);
+    }
+
+    if (locked)
+        do_unlock(f);
+    if (nbytes)
+        return (jlong)nbytes;
+
+    ACR_DescriptorSetErrEx(_E, f->descriptor, rc);
+    switch (rc) {
+        case 0:
+        case ACR_TIMEUP:
+            return 0;
+        break;
+        case ERROR_INVALID_HANDLE:
+            ACR_THROW_EX_IF_ERR(ACR_EX_ACLOSED_DESC, rc);
+        break;
+        default:
+            ACR_THROW_IO_IF_ERR(rc);
+        break;
+    }
+    return -1;
+}
+
+ACR_IO_EXPORT_DECLARE(jlong, FileSystemIo, write5)(ACR_JNISTDARGS,
+                                                   jint file,
+                                                   jobjectArray vec,
+                                                   jint off,
+                                                   jint len)
+{
+    DWORD   i;
+    DWORD   pl;
+    DWORD   rc = 0;
+    DWORD   wr;
+    DWORD   po = (DWORD)off;
+    DWORD   cs = (DWORD)len;
+    jobject bbe;
+    void   *bbb;
+    DWORD   bbl;
+    int   locked = 0;
+    INT64 nbytes = 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_EX_IF_ERR(ACR_EX_INVALID_DESC, ACR_EFTYPE);
+        return -1;
+    }
+    if (IS_INVALID_HANDLE(f)) {
+        ACR_THROW_EX_IF_ERR(ACR_EX_CLOSED_DESC, ACR_EBADF);
+        return -1;
+    }
+    pl = (DWORD)(*_E)->GetArrayLength(_E, vec);
+    if ((po + cs) > pl) {
+        ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EINDEX, 0);
+        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;
+        }
+    }
+
+    for (i = 0; i < cs, rc == 0; i++) {
+        bbe = (*_E)->GetObjectArrayElement(_E, vec, (jsize)(i + po));
+        bbl = (DWORD)(*_E)->GetDirectBufferCapacity(_E, bbe);
+        bbb = (*_E)->GetDirectBufferAddress(_E, bbe);
+        (*_E)->DeleteLocalRef(_E, bbe);
+
+        if (lpo) {
+            lpo->Offset     = (DWORD)(f->pos);
+            lpo->OffsetHigh = (DWORD)(f->pos >> 32);
+        }
+        wr = 0;
+        if (WriteFile(f->fd, bbb, bbl, &wr, lpo)) {
+            /* All done. Update the position and return
+             */
+            if (wr) {
+                f->pos += wr;
+                nbytes += wr;
+            }
+        }
+        else {
+            switch (rc = GetLastError()) {
+                case ERROR_IO_PENDING:
+                    if ((rc = overlapped_wait(f, &wr)) == 0) {
+                        if (wr) {
+                            f->pos += wr;
+                            nbytes += wr;
+                        }
+                    }
+                break;
+                default:
+                break;
+            }
+        }
+    }
+
+    if (locked)
+        do_unlock(f);
+    if (nbytes)
+        return (jlong)nbytes;
+
+    ACR_DescriptorSetErrEx(_E, f->descriptor, rc);
+    switch (rc) {
+        case 0:
+        case ACR_TIMEUP:
+        case ERROR_OPERATION_ABORTED:
+            return 0;
+        break;
+        case ERROR_INVALID_HANDLE:
+            ACR_THROW_EX_IF_ERR(ACR_EX_ACLOSED_DESC, rc);
+        break;
+        default:
+            ACR_THROW_IO_IF_ERR(rc);
+        break;
+    }
+    return -1;
+}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystemIo, 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_EX_IF_ERR(ACR_EX_INVALID_DESC, ACR_EFTYPE);
+        return -1;
+    }
+    if (IS_INVALID_HANDLE(f)) {
+        ACR_THROW_EX_IF_ERR(ACR_EX_CLOSED_DESC, 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;
+
+    ACR_DescriptorSetErrEx(_E, f->descriptor, rc);
+    switch (rc) {
+        case 0:
+        case ACR_TIMEUP:
+            return 0;
+        break;
+        case ERROR_INVALID_HANDLE:
+            ACR_THROW_EX_IF_ERR(ACR_EX_ACLOSED_DESC, rc);
+        break;
+        default:
+            ACR_THROW_IO_IF_ERR(rc);
+        break;
+    }
+    return -1;
+}
+
+ACR_IO_EXPORT_DECLARE(jlong, FileSystemIo, 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_EX_IF_ERR(ACR_EX_INVALID_DESC, ACR_EFTYPE);
+        return -1;
+    }
+    if (IS_INVALID_HANDLE(f)) {
+        ACR_THROW_EX_IF_ERR(ACR_EX_CLOSED_DESC, 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 (jlong)nbytes;
+
+    ACR_DescriptorSetErrEx(_E, f->descriptor, rc);
+    switch (rc) {
+        case 0:
+        case ACR_TIMEUP:
+        case ERROR_OPERATION_ABORTED:
+            return 0;
+        break;
+        case ERROR_INVALID_HANDLE:
+            ACR_THROW_EX_IF_ERR(ACR_EX_ACLOSED_DESC, rc);
+        break;
+        default:
+            ACR_THROW_IO_IF_ERR(rc);
+        break;
+    }
+    return -1;
+}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystemIo, fullw2)(ACR_JNISTDARGS,
+                                                  jint file,
+                                                  jobject dbb,
+                                                  jint off,
+                                                  jint 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_EX_IF_ERR(ACR_EX_INVALID_DESC, ACR_EFTYPE);
+        return -1;
+    }
+    if (IS_INVALID_HANDLE(f)) {
+        ACR_THROW_EX_IF_ERR(ACR_EX_CLOSED_DESC, 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;
+
+    ACR_DescriptorSetErrEx(_E, f->descriptor, rc);
+    switch (rc) {
+        case 0:
+        case ACR_TIMEUP:
+        case ERROR_OPERATION_ABORTED:
+            return 0;
+        break;
+        case ERROR_INVALID_HANDLE:
+            ACR_THROW_EX_IF_ERR(ACR_EX_ACLOSED_DESC, rc);
+        break;
+        default:
+            ACR_THROW_IO_IF_ERR(rc);
+        break;
+    }
+    return -1;
+}

Propchange: commons/sandbox/runtime/trunk/src/main/native/os/win32/fsysrw.c
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message