Author: mturk
Date: Sat Dec 12 13:32:43 2009
New Revision: 889933

URL: http://svn.apache.org/viewvc?rev=889933&view=rev
Log:
Implement windows positional read/write

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

Modified: 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=889933&r1=889932&r2=889933&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/win32/fsysrw.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/win32/fsysrw.c Sat Dec 12 
13:32:43 2009
@@ -674,13 +674,913 @@
     return -1;
 }
 
+ACR_IO_EXPORT_DECLARE(jint, FileSystemIo, read4)(ACR_JNISTDARGS,
+                                                 jint file,
+                                                 jlong pos)
+{
+    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;
+    }
+
+    f->pos          = pos;
+    lpo             = &f->overlap;
+    lpo->Offset     = (DWORD)(f->pos);
+    lpo->OffsetHigh = (DWORD)(f->pos >> 32);
+    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;
+                }
+            }
+        }
+        if (IS_INVALID_HANDLE(lpo->hEvent))
+            lpo->hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
+        if (IS_INVALID_HANDLE(lpo->hEvent))
+            return ACR_GET_OS_ERROR();
+    }
+    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, read5)(ACR_JNISTDARGS,
+                                                 jint file,
+                                                 jbyteArray buf,
+                                                 jint off,
+                                                 jint len,
+                                                 jlong pos)
+{
+    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;
+    }
+
+    f->pos          = pos;
+    lpo             = &f->overlap;
+    lpo->Offset     = (DWORD)(f->pos);
+    lpo->OffsetHigh = (DWORD)(f->pos >> 32);
+
+    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;
+                }
+            }
+        }
+        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;
+        }
+    }
+    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, read6)(ACR_JNISTDARGS,
+                                                  jint file,
+                                                  jobject ptr,
+                                                  jlong off,
+                                                  jlong len,
+                                                  jlong pos)
+{
+    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;
+    }
+
+    f->pos          = pos;
+    lpo             = &f->overlap;
+    lpo->Offset     = (DWORD)(f->pos);
+    lpo->OffsetHigh = (DWORD)(f->pos >> 32);
+
+    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;
+                }
+            }
+        }
+        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;
+        }
+    }
+    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, read7)(ACR_JNISTDARGS,
+                                                 jint file,
+                                                 jobject dbb,
+                                                 jint off,
+                                                 jint len,
+                                                 jlong pos)
+{
+#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;
+    }
+
+    f->pos          = pos;
+    lpo             = &f->overlap;
+    lpo->Offset     = (DWORD)(f->pos);
+    lpo->OffsetHigh = (DWORD)(f->pos >> 32);
+
+    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;
+                }
+            }
+        }
+        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;
+        }
+    }
+    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)
+                                                  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)
 {
-    unsigned char c = (unsigned char)(b & 0xFF);
-    DWORD rc   = 0;
-    DWORD wr   = 0;
+#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);
@@ -734,7 +1634,23 @@
         lpo->Offset     = (DWORD)(f->pos);
         lpo->OffsetHigh = (DWORD)(f->pos >> 32);
     }
-    if (WriteFile(f->fd, &c, 1, &wr, lpo)) {
+    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)
@@ -777,18 +1693,23 @@
     return -1;
 }
 
-ACR_IO_EXPORT_DECLARE(jint, FileSystemIo, write1)(ACR_JNISTDARGS,
-                                                  jint file,
-                                                  jbyteArray buf,
-                                                  jint off,
-                                                  jint len)
+ACR_IO_EXPORT_DECLARE(jlong, FileSystemIo, write4)(ACR_JNISTDARGS,
+                                                   jint file,
+                                                   jobjectArray vec,
+                                                   jint off,
+                                                   jint len)
 {
-    jbyte  *bb;
+    DWORD   i;
+    DWORD   pl;
     DWORD   rc = 0;
+    DWORD   wr;
     DWORD   po = (DWORD)off;
     DWORD   cs = (DWORD)len;
-    DWORD   wr = 0;
-    int locked = 0;
+    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);
 
@@ -800,7 +1721,11 @@
         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;
@@ -839,42 +1764,176 @@
                 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);
+    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 (WriteFile(f->fd, bb + po, cs, &wr, lpo)) {
-        /* All done. Update the position and return
+    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.
          */
-        if (wr)
-            f->pos += wr;
-        goto finally;
+        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;
     }
-    switch (rc = GetLastError()) {
-        case ERROR_IO_PENDING:
-            if ((rc = overlapped_wait(f, &wr)) == 0) {
-                if (wr) {
-                    f->pos += wr;
-                    goto finally;
-                }
+    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;
             }
-        break;
-        default:
-        break;
+        }
+        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;
+            }
+        }
     }
 
-finally:
     if (locked)
         do_unlock(f);
-   (*_E)->ReleaseByteArrayElements(_E, buf, bb, JNI_ABORT);
-    if (wr)
-        return (jint)wr;
+    if (nbytes)
+        return (jlong)nbytes;
 
     ACR_DescriptorSetErrEx(_E, f->descriptor, rc);
     switch (rc) {
@@ -893,18 +1952,14 @@
     return -1;
 }
 
-ACR_IO_EXPORT_DECLARE(jlong, FileSystemIo, write2)(ACR_JNISTDARGS,
-                                                   jint file,
-                                                   jobject ptr,
-                                                   jlong off,
-                                                   jlong len)
+ACR_IO_EXPORT_DECLARE(jint, FileSystemIo, write6)(ACR_JNISTDARGS,
+                                                  jint file,
+                                                  jint b,
+                                                  jlong pos)
 {
-    size_t  pl;
-    jbyte  *pb;
-    DWORD   rc = 0;
-    DWORD   po = (DWORD)off;
-    DWORD   cs = (DWORD)len;
-    DWORD   wr = 0;
+    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);
@@ -917,6 +1972,7 @@
         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;
@@ -945,8 +2001,16 @@
         f->pos = op.QuadPart;
         locked = 1;
     }
+    else {
+        /* Use provided offset
+         */
+        f->pos = pos;        
+    }
+    lpo             = &f->overlap;
+    lpo->Offset     = (DWORD)(f->pos);
+    lpo->OffsetHigh = (DWORD)(f->pos >> 32);        
+
     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)) {
@@ -955,24 +2019,8 @@
                 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)) {
+    if (WriteFile(f->fd, &c, 1, &wr, lpo)) {
         /* All done. Update the position and return
          */
         if (wr)
@@ -996,7 +2044,7 @@
     if (locked)
         do_unlock(f);
     if (wr)
-        return (jlong)wr;
+        return (jint)wr;
 
     ACR_DescriptorSetErrEx(_E, f->descriptor, rc);
     switch (rc) {
@@ -1015,16 +2063,14 @@
     return -1;
 }
 
-ACR_IO_EXPORT_DECLARE(jint, FileSystemIo, write3)(ACR_JNISTDARGS,
+ACR_IO_EXPORT_DECLARE(jint, FileSystemIo, write7)(ACR_JNISTDARGS,
                                                   jint file,
-                                                  jobject dbb,
+                                                  jbyteArray buf,
                                                   jint off,
-                                                  jint len)
+                                                  jint len,
+                                                  jlong pos)
 {
-#if defined(_DEBUG)
-    DWORD   pl;
-#endif
-    jbyte  *pb;
+    jbyte  *bb;
     DWORD   rc = 0;
     DWORD   po = (DWORD)off;
     DWORD   cs = (DWORD)len;
@@ -1041,6 +2087,7 @@
         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;
@@ -1069,8 +2116,16 @@
         f->pos = op.QuadPart;
         locked = 1;
     }
+    else {
+        /* Use provided offset
+         */
+        f->pos = pos;        
+    }
+    lpo             = &f->overlap;
+    lpo->Offset     = (DWORD)(f->pos);
+    lpo->OffsetHigh = (DWORD)(f->pos >> 32);        
+
     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)) {
@@ -1079,26 +2134,15 @@
                 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);
+
+    bb = (*_E)->GetByteArrayElements(_E, buf, NULL);
+    if (!bb) {
         if (locked)
             do_unlock(f);
         return -1;
     }
-#endif
-    if (WriteFile(f->fd, pb + po, cs, &wr, lpo)) {
+    if (WriteFile(f->fd, bb + po, cs, &wr, lpo)) {
         /* All done. Update the position and return
          */
         if (wr)
@@ -1121,6 +2165,7 @@
 finally:
     if (locked)
         do_unlock(f);
+   (*_E)->ReleaseByteArrayElements(_E, buf, bb, JNI_ABORT);
     if (wr)
         return (jint)wr;
 
@@ -1141,23 +2186,20 @@
     return -1;
 }
 
-ACR_IO_EXPORT_DECLARE(jlong, FileSystemIo, write4)(ACR_JNISTDARGS,
+ACR_IO_EXPORT_DECLARE(jlong, FileSystemIo, write8)(ACR_JNISTDARGS,
                                                    jint file,
-                                                   jobjectArray vec,
-                                                   jint off,
-                                                   jint len)
+                                                   jobject ptr,
+                                                   jlong off,
+                                                   jlong len,
+                                                   jlong pos)
 {
-    DWORD   i;
-    DWORD   pl;
+    size_t  pl;
+    jbyte  *pb;
     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;
+    DWORD   wr = 0;
+    int locked = 0;
     LPOVERLAPPED lpo = NULL;
     acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file);
 
@@ -1169,11 +2211,6 @@
         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;
@@ -1202,8 +2239,16 @@
         f->pos = op.QuadPart;
         locked = 1;
     }
+    else {
+        /* Use provided offset
+         */
+        f->pos = pos;        
+    }
+    lpo             = &f->overlap;
+    lpo->Offset     = (DWORD)(f->pos);
+    lpo->OffsetHigh = (DWORD)(f->pos >> 32);        
+
     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)) {
@@ -1213,51 +2258,51 @@
             return -1;
         }
     }
+    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;
+    }
 
-    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;
+    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;
+                }
             }
-        }
-        (*_E)->ReleaseByteArrayElements(_E, bae, bab, JNI_ABORT);
-        (*_E)->DeleteLocalRef(_E, bae);
+        break;
+        default:
+        break;
     }
 
+finally:
     if (locked)
         do_unlock(f);
-    if (nbytes)
-        return (jlong)nbytes;
+    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:
@@ -1270,23 +2315,22 @@
     return -1;
 }
 
-ACR_IO_EXPORT_DECLARE(jlong, FileSystemIo, write5)(ACR_JNISTDARGS,
-                                                   jint file,
-                                                   jobjectArray vec,
-                                                   jint off,
-                                                   jint len)
+ACR_IO_EXPORT_DECLARE(jint, FileSystemIo, write9)(ACR_JNISTDARGS,
+                                                  jint file,
+                                                  jobject dbb,
+                                                  jint off,
+                                                  jint len,
+                                                  jlong pos)
 {
-    DWORD   i;
+#if defined(_DEBUG)
     DWORD   pl;
+#endif
+    jbyte  *pb;
     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;
+    DWORD   wr = 0;
+    int locked = 0;
     LPOVERLAPPED lpo = NULL;
     acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file);
 
@@ -1298,11 +2342,6 @@
         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;
@@ -1331,8 +2370,16 @@
         f->pos = op.QuadPart;
         locked = 1;
     }
+    else {
+        /* Use provided offset
+         */
+        f->pos = pos;        
+    }
+    lpo             = &f->overlap;
+    lpo->Offset     = (DWORD)(f->pos);
+    lpo->OffsetHigh = (DWORD)(f->pos >> 32);        
+
     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)) {
@@ -1342,46 +2389,47 @@
             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;
+    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 (nbytes)
-        return (jlong)nbytes;
+    if (wr)
+        return (jint)wr;
 
     ACR_DescriptorSetErrEx(_E, f->descriptor, rc);
     switch (rc) {


Reply via email to