You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by mt...@apache.org on 2009/09/30 20:24:39 UTC
svn commit: r820372 -
/commons/sandbox/runtime/trunk/src/main/native/os/win32/fsysio.c
Author: mturk
Date: Wed Sep 30 18:24:39 2009
New Revision: 820372
URL: http://svn.apache.org/viewvc?rev=820372&view=rev
Log:
Implement win32 write methods
Modified:
commons/sandbox/runtime/trunk/src/main/native/os/win32/fsysio.c
Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/fsysio.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/fsysio.c?rev=820372&r1=820371&r2=820372&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/win32/fsysio.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/win32/fsysio.c Wed Sep 30 18:24:39 2009
@@ -286,33 +286,18 @@
return fdo;
}
-ACR_IO_EXPORT_DECLARE(jint, FileSystem, lock0)(ACR_JNISTDARGS,
- jint file,
- jint type)
+static int do_lock(acr_file_t *f, DWORD flags)
{
- OVERLAPPED opp;
- DWORD flags = 0;
- acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file);
-
- if (ACR_IOH_FTYPE(file) != ACR_DT_FILE)
- return ACR_EFTYPE;
- if (IS_INVALID_HANDLE(f))
- return ACR_EBADF;
-
- if (type & ACR_FLOCK_NONBLOCK)
- flags = LOCKFILE_FAIL_IMMEDIATELY;
- else if (f->blocking == BLK_OFF) {
+ if (f->blocking == BLK_OFF) {
if (IS_INVALID_HANDLE(f->overlap.hEvent)) {
f->overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (IS_INVALID_HANDLE(f->overlap.hEvent))
return ACR_GET_OS_ERROR();
}
}
- if ((type & ACR_FLOCK_TYPEMASK) != ACR_FLOCK_SHARED)
- flags |= LOCKFILE_EXCLUSIVE_LOCK;
f->overlap.Offset = 0;
f->overlap.OffsetHigh = 0;
- if (!LockFileEx(f->fd, flags, 0, 0xFFFFFFFF, 0xFFFFFFFF, &opp)) {
+ if (!LockFileEx(f->fd, flags, 0, 0xFFFFFFFF, 0xFFFFFFFF, &f->overlap)) {
int rc = ACR_GET_OS_ERROR();
if (rc == ERROR_IO_PENDING) {
do {
@@ -347,6 +332,27 @@
}
else
return 0;
+
+}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystem, lock0)(ACR_JNISTDARGS,
+ jint file,
+ jint type)
+{
+ DWORD flags = 0;
+ acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file);
+
+ if (ACR_IOH_FTYPE(file) != ACR_DT_FILE)
+ return ACR_EFTYPE;
+ if (IS_INVALID_HANDLE(f))
+ return ACR_EBADF;
+
+ if ((type & ACR_FLOCK_TYPEMASK) != ACR_FLOCK_SHARED)
+ flags |= LOCKFILE_EXCLUSIVE_LOCK;
+ if (type & ACR_FLOCK_NONBLOCK)
+ flags = LOCKFILE_FAIL_IMMEDIATELY;
+
+ return do_lock(f, flags);
}
ACR_IO_EXPORT_DECLARE(jint, FileSystem, lock1)(ACR_JNISTDARGS,
@@ -356,7 +362,6 @@
jlong len)
{
LARGE_INTEGER lii;
- OVERLAPPED opp;
DWORD flags = 0;
acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file);
@@ -367,20 +372,20 @@
if (type & ACR_FLOCK_NONBLOCK)
flags = LOCKFILE_FAIL_IMMEDIATELY;
- else if (f->blocking == BLK_OFF) {
+ if ((type & ACR_FLOCK_TYPEMASK) != ACR_FLOCK_SHARED)
+ flags |= LOCKFILE_EXCLUSIVE_LOCK;
+ if (f->blocking == BLK_OFF) {
if (IS_INVALID_HANDLE(f->overlap.hEvent)) {
f->overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (IS_INVALID_HANDLE(f->overlap.hEvent))
return ACR_GET_OS_ERROR();
}
}
- if ((type & ACR_FLOCK_TYPEMASK) != ACR_FLOCK_SHARED)
- flags |= LOCKFILE_EXCLUSIVE_LOCK;
f->overlap.Offset = (DWORD)(off);
f->overlap.OffsetHigh = (DWORD)(off >> 32);
lii.QuadPart = len;
- if (!LockFileEx(f->fd, flags, 0, lii.LowPart, lii.HighPart, &opp)) {
+ if (!LockFileEx(f->fd, flags, 0, lii.LowPart, lii.HighPart, &f->overlap)) {
int rc = ACR_GET_OS_ERROR();
if (rc == ERROR_IO_PENDING) {
do {
@@ -953,7 +958,7 @@
ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ENULL, 0);
return -1;
}
- if ((po + cs) > pl) {
+ if ((po + cs) > (DWORD)pl) {
ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EINDEX, 0);
return -1;
}
@@ -1137,3 +1142,663 @@
return f->err == ACR_TIMEUP ? 0 : -1;
return -1;
}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystem, write0)(ACR_JNISTDARGS,
+ jint file,
+ jint b)
+{
+ unsigned char c = (unsigned char)(b & 0xFF);
+ DWORD rc;
+ 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_IO_IF_ERR(ACR_EFTYPE);
+ return -1;
+ }
+ if (IS_INVALID_HANDLE(f)) {
+ ACR_THROW_IO_IF_ERR(ACR_EBADF);
+ return -1;
+ }
+ if (f->flags & ACR_FOPEN_APPEND) {
+ LARGE_INTEGER os;
+ LARGE_INTEGER op;
+
+ EnterCriticalSection(&f->lock);
+ /* apr_file_lock will mutex the file across processes.
+ * The call to apr_thread_mutex_lock is added to avoid
+ * a race condition between LockFile and WriteFile
+ * that occasionally leads to deadlocked threads.
+ */
+ rc = do_lock(f, LOCKFILE_EXCLUSIVE_LOCK);
+ if (rc) {
+ ACR_THROW_IO_IF_ERR(rc);
+ LeaveCriticalSection(&f->lock);
+ return -1;
+ }
+ /* Set the position to the file end
+ */
+ os.QuadPart = 0;
+ op.QuadPart = 0;
+ if (!SetFilePointerEx(f->fd, os, &op, FILE_END)) {
+ ACR_THROW_IO_ERRNO();
+ LeaveCriticalSection(&f->lock);
+ 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)
+ LeaveCriticalSection(&f->lock);
+ return -1;
+ }
+ lpo->Offset = (DWORD)(f->pos);
+ lpo->OffsetHigh = (DWORD)(f->pos >> 32);
+ }
+ f->err = 0;
+ if (WriteFile(f->fd, &c, 1, &wr, lpo)) {
+ /* All done. Update the position and return
+ */
+ if (wr)
+ f->pos += wr;
+ goto finally;
+ }
+ switch (f->err = GetLastError()) {
+ case ERROR_IO_PENDING:
+ if ((f->err = overlapped_wait(f, &wr)) == 0) {
+ if (wr) {
+ f->pos += wr;
+ goto finally;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+finally:
+ if (locked)
+ LeaveCriticalSection(&f->lock);
+ if (wr)
+ return (jint)wr;
+ if (f->err)
+ return f->err == ACR_TIMEUP ? 0 : -1;
+ return -1;
+}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystem, write1)(ACR_JNISTDARGS,
+ jint file,
+ jbyteArray buf,
+ jint off,
+ jint len)
+{
+ jbyte *bb;
+ DWORD rc;
+ 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_IO_IF_ERR(ACR_EFTYPE);
+ return -1;
+ }
+ if (IS_INVALID_HANDLE(f)) {
+ ACR_THROW_IO_IF_ERR(ACR_EBADF);
+ return -1;
+ }
+
+ if (f->flags & ACR_FOPEN_APPEND) {
+ LARGE_INTEGER os;
+ LARGE_INTEGER op;
+
+ EnterCriticalSection(&f->lock);
+ /* apr_file_lock will mutex the file across processes.
+ * The call to apr_thread_mutex_lock is added to avoid
+ * a race condition between LockFile and WriteFile
+ * that occasionally leads to deadlocked threads.
+ */
+ rc = do_lock(f, LOCKFILE_EXCLUSIVE_LOCK);
+ if (rc) {
+ ACR_THROW_IO_IF_ERR(rc);
+ LeaveCriticalSection(&f->lock);
+ return -1;
+ }
+ /* Set the position to the file end
+ */
+ os.QuadPart = 0;
+ op.QuadPart = 0;
+ if (!SetFilePointerEx(f->fd, os, &op, FILE_END)) {
+ ACR_THROW_IO_ERRNO();
+ LeaveCriticalSection(&f->lock);
+ 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)
+ LeaveCriticalSection(&f->lock);
+ return -1;
+ }
+ lpo->Offset = (DWORD)(f->pos);
+ lpo->OffsetHigh = (DWORD)(f->pos >> 32);
+ }
+
+ bb = (*_E)->GetByteArrayElements(_E, buf, NULL);
+ if (!bb) {
+ if (locked)
+ LeaveCriticalSection(&f->lock);
+ return -1;
+ }
+ f->err = 0;
+ if (WriteFile(f->fd, bb + po, cs, &wr, lpo)) {
+ /* All done. Update the position and return
+ */
+ if (wr)
+ f->pos += wr;
+ goto finally;
+ }
+ switch (f->err = GetLastError()) {
+ case ERROR_IO_PENDING:
+ if ((f->err = overlapped_wait(f, &wr)) == 0) {
+ if (wr) {
+ f->pos += wr;
+ goto finally;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+finally:
+ if (locked)
+ LeaveCriticalSection(&f->lock);
+ (*_E)->ReleaseByteArrayElements(_E, buf, bb, JNI_ABORT);
+ if (wr)
+ return (jint)wr;
+ if (f->err)
+ return f->err == ACR_TIMEUP ? 0 : -1;
+ return -1;
+}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystem, write2)(ACR_JNISTDARGS,
+ jint file,
+ jobject ptr,
+ jlong off,
+ jlong len)
+{
+ size_t pl;
+ jbyte *pb;
+ DWORD rc;
+ 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_IO_IF_ERR(ACR_EFTYPE);
+ return -1;
+ }
+ if (IS_INVALID_HANDLE(f)) {
+ ACR_THROW_IO_IF_ERR(ACR_EBADF);
+ return -1;
+ }
+ if (f->flags & ACR_FOPEN_APPEND) {
+ LARGE_INTEGER os;
+ LARGE_INTEGER op;
+
+ EnterCriticalSection(&f->lock);
+ /* apr_file_lock will mutex the file across processes.
+ * The call to apr_thread_mutex_lock is added to avoid
+ * a race condition between LockFile and WriteFile
+ * that occasionally leads to deadlocked threads.
+ */
+ rc = do_lock(f, LOCKFILE_EXCLUSIVE_LOCK);
+ if (rc) {
+ ACR_THROW_IO_IF_ERR(rc);
+ LeaveCriticalSection(&f->lock);
+ return -1;
+ }
+ /* Set the position to the file end
+ */
+ os.QuadPart = 0;
+ op.QuadPart = 0;
+ if (!SetFilePointerEx(f->fd, os, &op, FILE_END)) {
+ ACR_THROW_IO_ERRNO();
+ LeaveCriticalSection(&f->lock);
+ 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)
+ LeaveCriticalSection(&f->lock);
+ 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)
+ LeaveCriticalSection(&f->lock);
+ return -1;
+ }
+ if ((po + cs) > (DWORD)pl) {
+ ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EINDEX, 0);
+ if (locked)
+ LeaveCriticalSection(&f->lock);
+ return -1;
+ }
+
+ f->err = 0;
+ if (WriteFile(f->fd, pb + po, cs, &wr, lpo)) {
+ /* All done. Update the position and return
+ */
+ if (wr)
+ f->pos += wr;
+ goto finally;
+ }
+ switch (f->err = GetLastError()) {
+ case ERROR_IO_PENDING:
+ if ((f->err = overlapped_wait(f, &wr)) == 0) {
+ if (wr) {
+ f->pos += wr;
+ goto finally;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+finally:
+ if (locked)
+ LeaveCriticalSection(&f->lock);
+ if (wr)
+ return (jint)wr;
+ if (f->err)
+ return f->err == ACR_TIMEUP ? 0 : -1;
+ return -1;
+}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystem, write3)(ACR_JNISTDARGS,
+ jint file,
+ jobject dbb,
+ jlong off,
+ jlong len)
+{
+#if defined(_DEBUG)
+ DWORD pl;
+#endif
+ jbyte *pb;
+ DWORD rc;
+ 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_IO_IF_ERR(ACR_EFTYPE);
+ return -1;
+ }
+ if (IS_INVALID_HANDLE(f)) {
+ ACR_THROW_IO_IF_ERR(ACR_EBADF);
+ return -1;
+ }
+ if (f->flags & ACR_FOPEN_APPEND) {
+ LARGE_INTEGER os;
+ LARGE_INTEGER op;
+
+ EnterCriticalSection(&f->lock);
+ /* apr_file_lock will mutex the file across processes.
+ * The call to apr_thread_mutex_lock is added to avoid
+ * a race condition between LockFile and WriteFile
+ * that occasionally leads to deadlocked threads.
+ */
+ rc = do_lock(f, LOCKFILE_EXCLUSIVE_LOCK);
+ if (rc) {
+ ACR_THROW_IO_IF_ERR(rc);
+ LeaveCriticalSection(&f->lock);
+ return -1;
+ }
+ /* Set the position to the file end
+ */
+ os.QuadPart = 0;
+ op.QuadPart = 0;
+ if (!SetFilePointerEx(f->fd, os, &op, FILE_END)) {
+ ACR_THROW_IO_ERRNO();
+ LeaveCriticalSection(&f->lock);
+ 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)
+ LeaveCriticalSection(&f->lock);
+ 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)
+ LeaveCriticalSection(&f->lock);
+ 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)
+ LeaveCriticalSection(&f->lock);
+ return -1;
+ }
+#endif
+ f->err = 0;
+ if (WriteFile(f->fd, pb + po, cs, &wr, lpo)) {
+ /* All done. Update the position and return
+ */
+ if (wr)
+ f->pos += wr;
+ goto finally;
+ }
+ switch (f->err = GetLastError()) {
+ case ERROR_IO_PENDING:
+ if ((f->err = overlapped_wait(f, &wr)) == 0) {
+ if (wr) {
+ f->pos += wr;
+ goto finally;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+finally:
+ if (locked)
+ LeaveCriticalSection(&f->lock);
+ if (wr)
+ return (jint)wr;
+ if (f->err)
+ return f->err == ACR_TIMEUP ? 0 : -1;
+ return -1;
+}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystem, write4)(ACR_JNISTDARGS,
+ jint file,
+ jobjectArray vec,
+ jint off,
+ jint len)
+{
+ DWORD i;
+ DWORD pl;
+ DWORD rc;
+ DWORD wr;
+ DWORD po = (DWORD)off;
+ DWORD cs = (DWORD)len;
+ jbyteArray bae;
+ jbyte *bab;
+ DWORD bal;
+ int locked = 0;
+ DWORD 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_IO_IF_ERR(ACR_EFTYPE);
+ return -1;
+ }
+ if (IS_INVALID_HANDLE(f)) {
+ ACR_THROW_IO_IF_ERR(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 ((*_E)->EnsureLocalCapacity(_E, (jint)(cs * 2)))
+ 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();
+ LeaveCriticalSection(&f->lock);
+ 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)
+ LeaveCriticalSection(&f->lock);
+ return -1;
+ }
+ }
+
+ f->err = 0;
+ for (i = 0; i < cs, f->err == 0; i++) {
+ bae = (*_E)->GetObjectArrayElement(_E, vec, (jsize)(i + po));
+ bal = (DWORD)(*_E)->GetArrayLength(_E, bae);
+ 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 (f->err = GetLastError()) {
+ case ERROR_IO_PENDING:
+ if ((f->err = overlapped_wait(f, &wr)) == 0) {
+ if (wr) {
+ f->pos += wr;
+ nbytes += wr;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ (*_E)->ReleaseByteArrayElements(_E, bae, bab, JNI_ABORT);
+ }
+
+ if (locked)
+ LeaveCriticalSection(&f->lock);
+ if (nbytes)
+ return (jint)nbytes;
+ if (f->err)
+ return f->err == ACR_TIMEUP ? 0 : -1;
+ return -1;
+}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystem, write5)(ACR_JNISTDARGS,
+ jint file,
+ jobjectArray vec,
+ jint off,
+ jint len)
+{
+ DWORD i;
+ DWORD pl;
+ DWORD rc;
+ DWORD wr;
+ DWORD po = (DWORD)off;
+ DWORD cs = (DWORD)len;
+ jobject bbe;
+ void *bbb;
+ DWORD bbl;
+ int locked = 0;
+ DWORD 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_IO_IF_ERR(ACR_EFTYPE);
+ return -1;
+ }
+ if (IS_INVALID_HANDLE(f)) {
+ ACR_THROW_IO_IF_ERR(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 ((*_E)->EnsureLocalCapacity(_E, (jint)(cs * 2)))
+ 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();
+ LeaveCriticalSection(&f->lock);
+ 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)
+ LeaveCriticalSection(&f->lock);
+ return -1;
+ }
+ }
+
+ f->err = 0;
+ for (i = 0; i < cs, f->err == 0; i++) {
+ bbe = (*_E)->GetObjectArrayElement(_E, vec, (jsize)(i + po));
+ bbl = (DWORD)(*_E)->GetDirectBufferCapacity(_E, bbe);
+ 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 (f->err = GetLastError()) {
+ case ERROR_IO_PENDING:
+ if ((f->err = overlapped_wait(f, &wr)) == 0) {
+ if (wr) {
+ f->pos += wr;
+ nbytes += wr;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ if (locked)
+ LeaveCriticalSection(&f->lock);
+ if (nbytes)
+ return (jint)nbytes;
+ if (f->err)
+ return f->err == ACR_TIMEUP ? 0 : -1;
+ return -1;
+}