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) {