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/29 07:45:13 UTC
svn commit: r819834 - in /commons/sandbox/runtime/trunk/src/main/native:
include/acr_file.h os/unix/fsysio.c
Author: mturk
Date: Tue Sep 29 05:45:12 2009
New Revision: 819834
URL: http://svn.apache.org/viewvc?rev=819834&view=rev
Log:
Implement Posix file sys I/O methods
Modified:
commons/sandbox/runtime/trunk/src/main/native/include/acr_file.h
commons/sandbox/runtime/trunk/src/main/native/os/unix/fsysio.c
Modified: commons/sandbox/runtime/trunk/src/main/native/include/acr_file.h
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/acr_file.h?rev=819834&r1=819833&r2=819834&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/include/acr_file.h (original)
+++ commons/sandbox/runtime/trunk/src/main/native/include/acr_file.h Tue Sep 29 05:45:12 2009
@@ -144,6 +144,16 @@
file lock */
/** @} */
+/* File seek direction */
+/**
+ * @defgroup acr_seek_direction_types File Seek Direction Types
+ * @{
+ */
+
+#define ACR_FSEEK_CUR 0 /**< Seek from the current position */
+#define ACR_FSEEK_SET 1 /**< Seek from the file begin */
+#define ACR_FSEEK_END 2 /**< Seek from the file end */
+
#define ACR_NO_END_SLASHA(P) \
if (*(P)) { \
size_t _s = strlen((P)) - 1; \
Modified: commons/sandbox/runtime/trunk/src/main/native/os/unix/fsysio.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/fsysio.c?rev=819834&r1=819833&r2=819834&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/unix/fsysio.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/unix/fsysio.c Tue Sep 29 05:45:12 2009
@@ -257,6 +257,173 @@
return errno;
}
+ACR_IO_EXPORT_DECLARE(jint, FileSystemProvider, lock0)(ACR_JNISTDARGS,
+ jint file,
+ jint type)
+{
+ int rc;
+ 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 HAVE_FCNTL_H
+ {
+ struct flock l = { 0 };
+ int fc;
+
+ l.l_whence = SEEK_SET; /* lock from current point */
+ l.l_start = 0; /* begin lock at this offset */
+ l.l_len = 0; /* lock to end of file */
+ if ((type & ACR_FLOCK_TYPEMASK) == ACR_FLOCK_SHARED)
+ l.l_type = F_RDLCK;
+ else
+ l.l_type = F_WRLCK;
+
+ fc = (type & ACR_FLOCK_NONBLOCK) ? F_SETLK : F_SETLKW;
+
+ /* keep trying if fcntl() gets interrupted (by a signal) */
+ while ((rc = fcntl(f->fd, fc, &l)) < 0 && errno == EINTR)
+ continue;
+
+ if (rc == -1) {
+ /* on some Unix boxes (e.g., Tru64), we get EACCES instead
+ * of EAGAIN; we don't want APR_STATUS_IS_EAGAIN() matching EACCES
+ * since that breaks other things, so fix up the retcode here
+ */
+ if (errno == EACCES) {
+ return ACR_EAGAIN;
+ }
+ return ACR_GET_OS_ERROR();
+ }
+ }
+#elif HAVE_SYS_FILE_H
+ {
+ int ltype;
+
+ if ((type & ACR_FLOCK_TYPEMASK) == ACR_FLOCK_SHARED)
+ ltype = LOCK_SH;
+ else
+ ltype = LOCK_EX;
+ if ((type & ACR_FLOCK_NONBLOCK) != 0)
+ ltype |= LOCK_NB;
+
+ /* keep trying if flock() gets interrupted (by a signal) */
+ while ((rc = flock(f->fd, ltype)) < 0 && errno == EINTR)
+ continue;
+
+ if (rc == -1)
+ return ACR_GET_OS_ERROR();
+ }
+#else
+#error No file locking mechanism is available.
+#endif
+ return 0;
+}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystemProvider, unlock0)(ACR_JNISTDARGS,
+ jint file)
+{
+ int rc;
+ 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 HAVE_FCNTL_H
+ {
+ struct flock l = { 0 };
+
+ l.l_whence = SEEK_SET; /* lock from current point */
+ l.l_start = 0; /* begin lock at this offset */
+ l.l_len = 0; /* lock to end of file */
+ l.l_type = F_UNLCK;
+
+ /* keep trying if fcntl() gets interrupted (by a signal) */
+ while ((rc = fcntl(f->fd, F_SETLKW, &l)) < 0
+ && errno == EINTR)
+ continue;
+
+ if (rc == -1)
+ return ACR_GET_OS_ERROR();
+ }
+#elif HAVE_SYS_FILE_H
+ {
+ /* keep trying if flock() gets interrupted (by a signal) */
+ while ((rc = flock(f->fd, LOCK_UN)) < 0 && errno == EINTR)
+ continue;
+
+ if (rc == -1)
+ return ACR_GET_OS_ERROR();
+ }
+#else
+#error No file locking mechanism is available.
+#endif
+
+ return 0;
+}
+
+ACR_IO_EXPORT_DECLARE(jlong, FileSystemProvider, seek0)(ACR_JNISTDARGS,
+ jint file,
+ jint where,
+ jlong off)
+{
+ acr_off_t rc;
+ acr_off_t os = (acr_off_t)off;
+ int whence;
+ 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;
+ }
+ switch (where) {
+ case ACR_FSEEK_CUR:
+ whence = SEEK_CUR;
+ break;
+ case ACR_FSEEK_SET:
+ whence = SEEK_SET;
+ break;
+ case ACR_FSEEK_END:
+ whence = SEEK_END;
+ break;
+ default:
+ ACR_THROW_IO_IF_ERR(ACR_EINVAL);
+ return -1;
+ break;
+ }
+ if ((rc = lseek(f->fd, os, whence)) == (off_t)-1) {
+ ACR_THROW_IO_ERRNO();
+ return -1;
+ }
+ return (jlong)rc;
+}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystemProvider, trunc0)(ACR_JNISTDARGS,
+ jint file,
+ jlong off)
+{
+ acr_off_t os = (acr_off_t)off;
+ 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 (ftruncate(f->fd, os) == -1)
+ return ACR_GET_OS_ERROR();
+ if (lseek(f->fd, os, SEEK_SET) == (off_t)-1)
+ return ACR_GET_OS_ERROR();
+ else
+ return 0;
+}
+
ACR_IO_EXPORT_DECLARE(jint, FileSystemProvider, read0)(ACR_JNISTDARGS,
jint file)
{
@@ -272,6 +439,9 @@
ACR_THROW_IO_IF_ERR(ACR_EBADF);
return -1;
}
+ if (f->eof) {
+ return -1;
+ }
rd = r_read(f->fd, &c, 1);
if (rd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
f->timeout != 0) {
@@ -284,13 +454,598 @@
rd = r_read(f->fd, &c, 1);
}
}
- if (rd == -1)
+ if (rd == -1) {
f->err = ACR_GET_OS_ERROR();
- else if (rd == 0)
+ if (ACR_STATUS_IS_EAGAIN(f->err))
+ return 0;
+ }
+ else if (rd == 0) {
+ f->err = 0;
f->eof = 1;
+ }
else if (rd == 1) {
f->err = 0;
- return (int)c;
+ return c;
}
return -1;
}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystemProvider, read1)(ACR_JNISTDARGS,
+ jint file,
+ jbyteArray buf,
+ jint off,
+ jint len)
+{
+ jbyte *bb = NULL;
+ jbyte *bc = NULL;
+ jbyte onstack[ACR_PBUFF_SIZ];
+ ssize_t rd;
+ 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->eof) {
+ return -1;
+ }
+ if (len > sizeof(onstack)) {
+ if (len > (1024 * 1024)) {
+ bc = (*_E)->GetByteArrayElements(_E, buf, NULL);
+ if (bc)
+ bb = bc + (size_t)off;
+ }
+ else
+ bb = ACR_Malloc(_E, THROW_FMARK, (size_t)len);
+ }
+ else
+ bb = onstack;
+ if (!bb) {
+ /* Exception was already thrown */
+ return -1;
+ }
+ rd = r_read(f->fd, bb, (size_t)len);
+ if (rd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
+ f->timeout != 0) {
+ int rc;
+ if ((rc = wait_for_io_or_timeout(f, 1))) {
+ f->err = rc;
+ if (bb != onstack) {
+ if (bc)
+ (*_E)->ReleaseByteArrayElements(_E, buf, bc, JNI_ABORT);
+ else
+ x_free(bb);
+ }
+ return rc == ACR_TIMEUP ? 0 : -1;
+ }
+ else {
+ rd = r_read(f->fd, bb, (size_t)len);
+ }
+ }
+ if (rd == -1) {
+ f->err = ACR_GET_OS_ERROR();
+ if (ACR_STATUS_IS_EAGAIN(f->err))
+ rd = 0;
+ }
+ else if (rd == 0) {
+ f->err = 0;
+ f->eof = 1;
+ }
+ else if (rd > 0) {
+ f->err = 0;
+ if (bc) {
+ (*_E)->ReleaseByteArrayElements(_E, buf, bc, 0);
+ return (jint)rd;
+ }
+ else {
+ (*_E)->SetByteArrayRegion(_E, buf, (jsize)off, (jsize)rd, bb);
+ }
+ }
+ if (bb != onstack) {
+ if (bc)
+ (*_E)->ReleaseByteArrayElements(_E, buf, bc, JNI_ABORT);
+ else
+ x_free(bb);
+ }
+ return (jint)rd;
+}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystemProvider, read2)(ACR_JNISTDARGS,
+ jint file,
+ jobject ptr,
+ jint off,
+ jint len)
+{
+ size_t pl;
+ size_t po = (size_t)off;
+ size_t cs = (size_t)len;
+ jbyte *pb;
+ ssize_t rd;
+ 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->eof) {
+ 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) > pl) {
+ ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EINDEX, 0);
+ return -1;
+ }
+ rd = r_read(f->fd, pb + po, cs);
+ if (rd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
+ f->timeout != 0) {
+ int rc;
+ if ((rc = wait_for_io_or_timeout(f, 1))) {
+ f->err = rc;
+ return rc == ACR_TIMEUP ? 0 : -1;
+ }
+ else {
+ rd = r_read(f->fd, pb + po, cs);
+ }
+ }
+ if (rd == -1) {
+ f->err = ACR_GET_OS_ERROR();
+ if (ACR_STATUS_IS_EAGAIN(f->err))
+ rd = 0;
+ }
+ else if (rd == 0) {
+ f->err = 0;
+ f->eof = 1;
+ }
+ else if (rd > 0) {
+ f->err = 0;
+ }
+ return (jint)rd;
+}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystemProvider, read3)(ACR_JNISTDARGS,
+ jint file,
+ jobject dbb,
+ jint off,
+ jint len)
+{
+#if defined(_DEBUG)
+ size_t pl;
+#endif
+ size_t po = (size_t)off;
+ size_t cs = (size_t)len;
+ jbyte *pb;
+ ssize_t rd;
+ 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->eof) {
+ 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 = (size_t)(*_E)->GetDirectBufferCapacity(_E, dbb);
+ if ((po + cs) > pl) {
+ ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EINDEX, 0);
+ return -1;
+ }
+#endif
+ rd = r_read(f->fd, pb + po, cs);
+ if (rd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
+ f->timeout != 0) {
+ int rc;
+ if ((rc = wait_for_io_or_timeout(f, 1))) {
+ f->err = rc;
+ return rc == ACR_TIMEUP ? 0 : -1;
+ }
+ else {
+ rd = r_read(f->fd, pb + po, cs);
+ }
+ }
+ if (rd == -1) {
+ f->err = ACR_GET_OS_ERROR();
+ if (ACR_STATUS_IS_EAGAIN(f->err))
+ rd = 0;
+ }
+ else if (rd == 0) {
+ f->err = 0;
+ f->eof = 1;
+ }
+ else if (rd > 0) {
+ f->err = 0;
+ }
+ return (jint)rd;
+}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystemProvider, write0)(ACR_JNISTDARGS,
+ jint file,
+ jint b)
+{
+ unsigned char c = (unsigned char)(b & 0xFF);
+ ssize_t wr;
+ 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;
+ }
+ wr = r_write(f->fd, &c, 1);
+ if (wr == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
+ f->timeout != 0) {
+ int rc;
+ if ((rc = wait_for_io_or_timeout(f, 0))) {
+ f->err = rc;
+ return rc == ACR_TIMEUP ? 0 : -1;
+ }
+ else {
+ wr = r_write(f->fd, &c, 1);
+ }
+ }
+ if (wr == -1) {
+ f->err = ACR_GET_OS_ERROR();
+ if (ACR_STATUS_IS_EAGAIN(f->err))
+ return 0;
+ }
+ else if (wr == 1)
+ f->err = 0;
+ return wr;
+}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystemProvider, write1)(ACR_JNISTDARGS,
+ jint file,
+ jbyteArray buf,
+ jint off,
+ jint len)
+{
+ jbyte *bb;
+ ssize_t wr;
+ 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;
+ }
+ bb = (*_E)->GetByteArrayElements(_E, buf, NULL);
+ if (!bb) {
+ return -1;
+ }
+ wr = r_write(f->fd, bb + (size_t)off, (size_t)len);
+ if (wr == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
+ f->timeout != 0) {
+ int rc;
+ if ((rc = wait_for_io_or_timeout(f, 0))) {
+ f->err = rc;
+ (*_E)->ReleaseByteArrayElements(_E, buf, bb, JNI_ABORT);
+ return rc == ACR_TIMEUP ? 0 : -1;
+ }
+ else {
+ wr = r_write(f->fd, bb + (size_t)off, (size_t)len);
+ }
+ }
+ if (wr == -1) {
+ f->err = ACR_GET_OS_ERROR();
+ if (ACR_STATUS_IS_EAGAIN(f->err))
+ wr = 0;
+ }
+ else if (wr == 1)
+ f->err = 0;
+ (*_E)->ReleaseByteArrayElements(_E, buf, bb, JNI_ABORT);
+ return (jint)wr;
+}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystemProvider, write2)(ACR_JNISTDARGS,
+ jint file,
+ jobject ptr,
+ jint off,
+ jint len)
+{
+ size_t pl;
+ size_t po = (size_t)off;
+ size_t cs = (size_t)len;
+ jbyte *pb;
+ ssize_t wr;
+ acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file);
+
+ if (ACR_IOH_FTYPE(file) != ACR_DT_FILE) {
+ ACR_THROW_IO_IF_ERR(ACR_EFTYPE);
+ return -1;
+ }
+ if (IS_INVALID_HANDLE(f)) {
+ ACR_THROW_IO_IF_ERR(ACR_EBADF);
+ return -1;
+ }
+ pb = (jbyte *)ACR_PointerGet(_E, ptr, &pl);
+ if (!pb) {
+ ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ENULL, 0);
+ return -1;
+ }
+ if ((po + cs) > pl) {
+ ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EINDEX, 0);
+ return -1;
+ }
+ wr = r_write(f->fd, pb + po, cs);
+ if (wr == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
+ f->timeout != 0) {
+ int rc;
+ if ((rc = wait_for_io_or_timeout(f, 0))) {
+ f->err = rc;
+ return rc == ACR_TIMEUP ? 0 : -1;
+ }
+ else {
+ wr = r_write(f->fd, pb + po, cs);
+ }
+ }
+ if (wr == -1) {
+ f->err = ACR_GET_OS_ERROR();
+ if (ACR_STATUS_IS_EAGAIN(f->err))
+ wr = 0;
+ }
+ else if (wr == 1)
+ f->err = 0;
+ return (jint)wr;
+}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystemProvider, write3)(ACR_JNISTDARGS,
+ jint file,
+ jobject dbb,
+ jint off,
+ jint len)
+{
+#if defined(_DEBUG)
+ size_t pl;
+#endif
+ size_t po = (size_t)off;
+ size_t cs = (size_t)len;
+ jbyte *pb;
+ ssize_t wr;
+ acr_file_t *f = (acr_file_t *)ACR_IOH_FDATA(file);
+
+ if (ACR_IOH_FTYPE(file) != ACR_DT_FILE) {
+ ACR_THROW_IO_IF_ERR(ACR_EFTYPE);
+ return -1;
+ }
+ if (IS_INVALID_HANDLE(f)) {
+ ACR_THROW_IO_IF_ERR(ACR_EBADF);
+ return -1;
+ }
+ pb = (jbyte *)(*_E)->GetDirectBufferAddress(_E, dbb);
+ if (!pb) {
+ ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ENULL, 0);
+ return -1;
+ }
+#if defined(_DEBUG)
+ pl = (size_t)(*_E)->GetDirectBufferCapacity(_E, dbb);
+ if ((po + cs) > pl) {
+ ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EINDEX, 0);
+ return -1;
+ }
+#endif
+ wr = r_write(f->fd, pb + po, cs);
+ if (wr == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
+ f->timeout != 0) {
+ int rc;
+ if ((rc = wait_for_io_or_timeout(f, 0))) {
+ f->err = rc;
+ return rc == ACR_TIMEUP ? 0 : -1;
+ }
+ else {
+ wr = r_write(f->fd, pb + po, cs);
+ }
+ }
+ if (wr == -1) {
+ f->err = ACR_GET_OS_ERROR();
+ if (ACR_STATUS_IS_EAGAIN(f->err))
+ wr = 0;
+ }
+ else if (wr == 1)
+ f->err = 0;
+ return (jint)wr;
+}
+
+#define ACR_IOVEC_ON_STACK 32
+ACR_IO_EXPORT_DECLARE(jint, FileSystemProvider, write4)(ACR_JNISTDARGS,
+ jint file,
+ jobjectArray vec,
+ jint off,
+ jint len)
+{
+ size_t i;
+ size_t pl;
+ size_t po = (size_t)off;
+ size_t cs = (size_t)len;
+ ssize_t wr;
+ struct iovec *iov;
+ struct iovec onstack[ACR_IOVEC_ON_STACK];
+ jobject bastack[ACR_IOVEC_ON_STACK];
+ jobject *boa;
+ 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 = (size_t)(*_E)->GetArrayLength(_E, vec);
+ if ((po + cs) > pl) {
+ ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EINDEX, 0);
+ return -1;
+ }
+ if ((*_E)->EnsureLocalCapacity(_E, (jint)(pl * 2)))
+ return -1;
+ if (pl > ACR_IOVEC_ON_STACK) {
+ iov = ACR_MALLOC(struct iovec, pl);
+ boa = ACR_MALLOC(jobject, pl);
+ }
+ else {
+ iov = onstack;
+ boa = bastack;
+ }
+ if (!iov || !boa) {
+ x_free(iov);
+ x_free(boa);
+ return -1;
+ }
+
+ for (i = 0; i < pl; i++) {
+ boa[i] = (*_E)->GetObjectArrayElement(_E, vec, i);
+ iov[i].iov_len = (size_t)(*_E)->GetArrayLength(_E, boa[i]);
+ iov[i].iov_base = (*_E)->GetByteArrayElements(_E, boa[i], NULL);
+ }
+ do {
+ wr = writev(f->fd, iov, pl);
+ } while (wr == -1 && errno == EAGAIN);
+ if (wr == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
+ f->timeout != 0) {
+ int rc;
+ if ((rc = wait_for_io_or_timeout(f, 0))) {
+ f->err = rc;
+ for (i = 0; i < pl; i++) {
+ (*_E)->ReleaseByteArrayElements(_E, boa[i], iov[i].iov_base,
+ JNI_ABORT);
+ }
+ if (iov != onstack) {
+ x_free(iov);
+ x_free(boa);
+ }
+ return rc == ACR_TIMEUP ? 0 : -1;
+ }
+ else {
+ do {
+ wr = writev(f->fd, iov, pl);
+ } while (wr == -1 && errno == EAGAIN);
+ }
+ }
+ if (wr == -1) {
+ f->err = ACR_GET_OS_ERROR();
+ if (ACR_STATUS_IS_EAGAIN(f->err))
+ wr = 0;
+ }
+ else if (wr == 1)
+ f->err = 0;
+ for (i = 0; i < pl; i++) {
+ (*_E)->ReleaseByteArrayElements(_E, boa[i], iov[i].iov_base, JNI_ABORT);
+ }
+ if (iov != onstack) {
+ x_free(iov);
+ x_free(boa);
+ }
+ return (jint)wr;
+}
+
+ACR_IO_EXPORT_DECLARE(jint, FileSystemProvider, write5)(ACR_JNISTDARGS,
+ jint file,
+ jobjectArray vec,
+ jint off,
+ jint len)
+{
+ size_t i;
+ size_t pl;
+ size_t po = (size_t)off;
+ size_t cs = (size_t)len;
+ ssize_t wr;
+ struct iovec *iov;
+ struct iovec onstack[ACR_IOVEC_ON_STACK];
+ jobject bastack[ACR_IOVEC_ON_STACK];
+ jobject *boa;
+ 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 = (size_t)(*_E)->GetArrayLength(_E, vec);
+ if ((po + cs) > pl) {
+ ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EINDEX, 0);
+ return -1;
+ }
+ if ((*_E)->EnsureLocalCapacity(_E, (jint)(pl * 2)))
+ return -1;
+ if (pl > ACR_IOVEC_ON_STACK) {
+ iov = ACR_MALLOC(struct iovec, pl);
+ boa = ACR_MALLOC(jobject, pl);
+ }
+ else {
+ iov = onstack;
+ boa = bastack;
+ }
+ if (!iov || !boa) {
+ x_free(iov);
+ x_free(boa);
+ return -1;
+ }
+
+ for (i = 0; i < pl; i++) {
+ boa[i] = (*_E)->GetObjectArrayElement(_E, vec, i);
+ iov[i].iov_len = (size_t)(*_E)->GetDirectBufferCapacity(_E, boa[i]);
+ iov[i].iov_base = (*_E)->GetDirectBufferAddress(_E, boa[i]);
+ }
+ do {
+ wr = writev(f->fd, iov, pl);
+ } while (wr == -1 && errno == EAGAIN);
+ if (wr == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
+ f->timeout != 0) {
+ int rc;
+ if ((rc = wait_for_io_or_timeout(f, 0))) {
+ f->err = rc;
+ if (iov != onstack) {
+ x_free(iov);
+ x_free(boa);
+ }
+ return rc == ACR_TIMEUP ? 0 : -1;
+ }
+ else {
+ do {
+ wr = writev(f->fd, iov, pl);
+ } while (wr == -1 && errno == EAGAIN);
+ }
+ }
+ if (wr == -1) {
+ f->err = ACR_GET_OS_ERROR();
+ if (ACR_STATUS_IS_EAGAIN(f->err))
+ wr = 0;
+ }
+ else if (wr == 1)
+ f->err = 0;
+ if (iov != onstack) {
+ x_free(iov);
+ x_free(boa);
+ }
+ return (jint)wr;
+}