Initial revision
From-SVN: r102074
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
*.o
|
||||
*.a
|
||||
*.lo
|
||||
*.la
|
||||
.libs
|
||||
.deps
|
||||
Makefile
|
||||
Makefile.in
|
||||
@@ -0,0 +1,16 @@
|
||||
pkglib_LTLIBRARIES = libjavanio.la
|
||||
|
||||
libjavanio_la_SOURCES = gnu_java_nio_VMPipe.c \
|
||||
gnu_java_nio_VMSelector.c \
|
||||
gnu_java_nio_channels_FileChannelImpl.c \
|
||||
gnu_java_nio_charset_iconv_IconvDecoder.c \
|
||||
gnu_java_nio_charset_iconv_IconvEncoder.c \
|
||||
java_nio_MappedByteBufferImpl.c \
|
||||
java_nio_VMDirectByteBuffer.c
|
||||
|
||||
libjavanio_la_LIBADD = $(top_builddir)/native/jni/classpath/jcl.lo \
|
||||
$(LTLIBICONV)
|
||||
|
||||
AM_LDFLAGS = @CLASSPATH_MODULE@
|
||||
AM_CPPFLAGS = @CLASSPATH_INCLUDES@
|
||||
AM_CFLAGS = @WARNING_CFLAGS@ @STRICT_WARNING_CFLAGS@ @ERROR_CFLAGS@
|
||||
@@ -0,0 +1,56 @@
|
||||
/* gnu_java_nio_VMPipe.c - Native methods for PipeImpl class
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
#include <config.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <jni.h>
|
||||
#include <jcl.h>
|
||||
|
||||
#include "gnu_java_nio_VMPipe.h"
|
||||
|
||||
#define IO_EXCEPTION "java/io/IOException"
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_gnu_java_nio_VMPipe_init (JNIEnv * env,
|
||||
jclass cls __attribute__ ((__unused__)),
|
||||
jobject self __attribute__ ((__unused__)),
|
||||
jobject provider __attribute__ ((__unused__)))
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION,
|
||||
"gnu.java.nio.VMPipe.init(): not implemented");
|
||||
}
|
||||
@@ -0,0 +1,296 @@
|
||||
/* gnu_java_nio_VMSelector.c - Native methods for SelectorImpl class
|
||||
Copyright (C) 2004, 2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/* <sys/types.h> needs to be included on OSX before <sys/select.h> */
|
||||
#if defined(HAVE_SYS_TYPES_H)
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include <sys/select.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <jni.h>
|
||||
#include <jcl.h>
|
||||
|
||||
#include "gnu_java_nio_VMSelector.h"
|
||||
|
||||
/* Amount of characters in the error message buffer for strerror_r. */
|
||||
#define BUF_SIZE 250
|
||||
|
||||
void helper_put_filedescriptors (JNIEnv *, jintArray, fd_set *, int *);
|
||||
|
||||
void helper_get_filedescriptors (JNIEnv *, jintArray *, fd_set *);
|
||||
|
||||
void helper_reset (JNIEnv *, jintArray *);
|
||||
|
||||
int
|
||||
helper_select (JNIEnv *, jclass, jmethodID,
|
||||
int, fd_set *, fd_set *, fd_set *, struct timeval *);
|
||||
|
||||
void
|
||||
helper_put_filedescriptors (JNIEnv * env, jintArray fdArray, fd_set * fds,
|
||||
int *max_fd)
|
||||
{
|
||||
jint *tmpFDArray = (*env)->GetIntArrayElements (env, fdArray, 0);
|
||||
int size = (*env)->GetArrayLength (env, fdArray);
|
||||
int index, fd;
|
||||
|
||||
for (index = 0; index < size; index++)
|
||||
{
|
||||
fd = tmpFDArray[index];
|
||||
|
||||
if (fd > 0)
|
||||
{
|
||||
FD_SET (tmpFDArray[index], fds);
|
||||
|
||||
if (tmpFDArray[index] > (*max_fd))
|
||||
(*max_fd) = tmpFDArray[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
helper_get_filedescriptors (JNIEnv * env, jintArray * fdArray, fd_set * fds)
|
||||
{
|
||||
jint *tmpFDArray = (*env)->GetIntArrayElements (env, fdArray, 0);
|
||||
int size = (*env)->GetArrayLength (env, fdArray);
|
||||
int index, fd;
|
||||
|
||||
for (index = 0; index < size; index++)
|
||||
{
|
||||
fd = tmpFDArray[index];
|
||||
if (fd < 0 || !FD_ISSET (fd, fds))
|
||||
tmpFDArray[index] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
helper_reset (JNIEnv * env, jintArray * fdArray)
|
||||
{
|
||||
jint *tmpFDArray = (*env)->GetIntArrayElements (env, fdArray, 0);
|
||||
int size = (*env)->GetArrayLength (env, fdArray);
|
||||
int index;
|
||||
|
||||
for (index = 0; index < size; index++)
|
||||
tmpFDArray[index] = 0;
|
||||
}
|
||||
|
||||
/* A wrapper for select() which ignores EINTR.
|
||||
* Taken from gclib's posix.cc
|
||||
*/
|
||||
int
|
||||
helper_select (JNIEnv * env, jclass thread_class,
|
||||
jmethodID thread_interrupted, int n, fd_set * readfds,
|
||||
fd_set * writefds, fd_set * exceptfds, struct timeval *timeout)
|
||||
{
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
/* If we have a timeout, compute the absolute ending time. */
|
||||
struct timeval end, delay, after;
|
||||
int r;
|
||||
|
||||
if (timeout)
|
||||
{
|
||||
gettimeofday (&end, NULL);
|
||||
|
||||
end.tv_usec += timeout->tv_usec;
|
||||
|
||||
if (end.tv_usec >= 1000000)
|
||||
{
|
||||
++end.tv_sec;
|
||||
end.tv_usec -= 1000000;
|
||||
}
|
||||
|
||||
end.tv_sec += timeout->tv_sec;
|
||||
delay = *timeout;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Placate compiler. */
|
||||
delay.tv_sec = delay.tv_usec = 0;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
r = select (n, readfds, writefds, exceptfds, timeout ? &delay : NULL);
|
||||
|
||||
if (r < 0 && errno != EINTR)
|
||||
return -errno;
|
||||
else if (r >= 0)
|
||||
return r;
|
||||
|
||||
/* Here we know we got EINTR. */
|
||||
if ((*env)->
|
||||
CallStaticBooleanMethod (env, thread_class, thread_interrupted))
|
||||
{
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
if (timeout)
|
||||
{
|
||||
gettimeofday (&after, NULL);
|
||||
|
||||
/* Now compute new timeout argument. */
|
||||
delay.tv_usec = end.tv_usec - after.tv_usec;
|
||||
delay.tv_sec = end.tv_sec - after.tv_sec;
|
||||
|
||||
if (delay.tv_usec < 0)
|
||||
{
|
||||
--delay.tv_sec;
|
||||
delay.tv_usec += 1000000;
|
||||
}
|
||||
|
||||
if (delay.tv_sec < 0)
|
||||
{
|
||||
/* We assume that the user wants a valid select() call
|
||||
* more than precise timing. So if we get a series of
|
||||
* EINTR we just keep trying with delay 0 until we get a
|
||||
* valid result.
|
||||
*/
|
||||
delay.tv_sec = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else /* HAVE_SYS_SELECT_H */
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_gnu_java_nio_VMSelector_select (JNIEnv * env,
|
||||
jclass obj __attribute__ ((__unused__)),
|
||||
jintArray read,
|
||||
jintArray write,
|
||||
jintArray except, jlong timeout)
|
||||
{
|
||||
jint result;
|
||||
jclass thread_class = (*env)->FindClass (env, "java/lang/Thread");
|
||||
jmethodID thread_current_thread =
|
||||
(*env)->GetStaticMethodID (env, thread_class, "currentThread",
|
||||
"()Ljava/lang/Thread;");
|
||||
jmethodID thread_interrupt =
|
||||
(*env)->GetMethodID (env, thread_class, "interrupt", "()V");
|
||||
jmethodID thread_interrupted =
|
||||
(*env)->GetStaticMethodID (env, thread_class, "interrupted", "()Z");
|
||||
jobject current_thread;
|
||||
int max_fd = 0;
|
||||
fd_set read_fds;
|
||||
fd_set write_fds;
|
||||
fd_set except_fds;
|
||||
struct timeval real_time_data;
|
||||
struct timeval *time_data = NULL;
|
||||
char message_buf[BUF_SIZE + 1];
|
||||
|
||||
/* If a legal timeout value isn't given, use NULL.
|
||||
* This means an infinite timeout. The specification
|
||||
* also says that a zero timeout should be treated
|
||||
* as infinite. Otherwise (if the timeout value is legal),
|
||||
* fill our timeval struct and use it for the select.
|
||||
*/
|
||||
if (timeout > 0)
|
||||
{
|
||||
real_time_data.tv_sec = timeout / 1000;
|
||||
real_time_data.tv_usec = (timeout % 1000) * 1000;
|
||||
time_data = &real_time_data;
|
||||
}
|
||||
|
||||
/* Reset all fd_set structures */
|
||||
FD_ZERO (&read_fds);
|
||||
FD_ZERO (&write_fds);
|
||||
FD_ZERO (&except_fds);
|
||||
|
||||
/* Fill the fd_set data structures for the _Jv_select() call. */
|
||||
helper_put_filedescriptors (env, read, &read_fds, &max_fd);
|
||||
helper_put_filedescriptors (env, write, &write_fds, &max_fd);
|
||||
helper_put_filedescriptors (env, except, &except_fds, &max_fd);
|
||||
|
||||
/* Actually do the select */
|
||||
result =
|
||||
helper_select (env, thread_class, thread_interrupted, max_fd + 1,
|
||||
&read_fds, &write_fds, &except_fds, time_data);
|
||||
|
||||
if (result == -EINTR)
|
||||
{
|
||||
/* The behavior of JRE 1.4.1 is that no exception is thrown
|
||||
* when the thread is interrupted, but the thread's interrupt
|
||||
* status is set. Clear all of our select sets and return 0,
|
||||
* indicating that nothing was selected.
|
||||
*/
|
||||
current_thread =
|
||||
(*env)->CallStaticObjectMethod (env, thread_class,
|
||||
thread_current_thread);
|
||||
(*env)->CallVoidMethod (env, current_thread, thread_interrupt);
|
||||
|
||||
helper_reset (env, read);
|
||||
helper_reset (env, write);
|
||||
helper_reset (env, except);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (result < 0)
|
||||
{
|
||||
|
||||
int errorcode = -result;
|
||||
|
||||
if (strerror_r (errorcode, message_buf, BUF_SIZE))
|
||||
{
|
||||
/* This would mean that message_buf was to small
|
||||
* to hold the error message.
|
||||
*/
|
||||
JCL_ThrowException (env, "java/lang/InternalError",
|
||||
"Not enough space in message buffer.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
JCL_ThrowException (env, "java/io/IOException", message_buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set the file descriptors according to the values returned from select(). */
|
||||
helper_get_filedescriptors (env, read, &read_fds);
|
||||
helper_get_filedescriptors (env, write, &write_fds);
|
||||
helper_get_filedescriptors (env, except, &except_fds);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,793 @@
|
||||
/* gnu_java_nio_channels_FileChannelImpl.c -
|
||||
Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
/* do not move; needed here because of some macro definitions */
|
||||
#include <config.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <jni.h>
|
||||
#include <jcl.h>
|
||||
|
||||
#include "target_native.h"
|
||||
#ifndef WITHOUT_FILESYSTEM
|
||||
#include "target_native_file.h"
|
||||
#endif
|
||||
#include "target_native_math_int.h"
|
||||
|
||||
#include "gnu_java_nio_channels_FileChannelImpl.h"
|
||||
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif /* HAVE_FCNTL_H */
|
||||
|
||||
/* These values must be kept in sync with FileChannelImpl.java. */
|
||||
#define FILECHANNELIMPL_READ 1
|
||||
#define FILECHANNELIMPL_WRITE 2
|
||||
#define FILECHANNELIMPL_APPEND 4
|
||||
|
||||
/* These values must be kept in sync with FileChannelImpl.java. */
|
||||
/* #define FILECHANNELIMPL_FILESEEK_SET 0 */
|
||||
/* #define FILECHANNELIMPL_FILESEEK_CUR 1 */
|
||||
/* #define FILECHANNELIMPL_FILESEEK_END 2 */
|
||||
|
||||
#define FILECHANNELIMPL_FILEOPEN_FLAG_READ 1
|
||||
#define FILECHANNELIMPL_FILEOPEN_FLAG_WRITE 2
|
||||
#define FILECHANNELIMPL_FILEOPEN_FLAG_APPEND 4
|
||||
#define FILECHANNELIMPL_FILEOPEN_FLAG_EXCL 8
|
||||
#define FILECHANNELIMPL_FILEOPEN_FLAG_SYNC 16
|
||||
#define FILECHANNELIMPL_FILEOPEN_FLAG_DSYNC 32
|
||||
|
||||
#define IO_EXCEPTION "java/io/IOException"
|
||||
|
||||
/* FIXME: This can't be right. Need converter macros. */
|
||||
#define CONVERT_JLONG_TO_INT(x) TARGET_NATIVE_MATH_INT_INT64_TO_INT32(x)
|
||||
#define CONVERT_INT_TO_JLONG(x) TARGET_NATIVE_MATH_INT_INT32_TO_INT64(x)
|
||||
|
||||
/* FIXME: This can't be right. Need converter macros. */
|
||||
#define CONVERT_JLONG_TO_OFF_T(x) TARGET_NATIVE_MATH_INT_INT64_TO_INT32(x)
|
||||
#define CONVERT_OFF_T_TO_JLONG(x) TARGET_NATIVE_MATH_INT_INT32_TO_INT64(x)
|
||||
|
||||
/* FIXME: This can't be right. Need converter macros */
|
||||
#define CONVERT_JINT_TO_INT(x) ((int)(x & 0xFFFFFFFF))
|
||||
#define CONVERT_INT_TO_JINT(x) ((int)(x & 0xFFFFFFFF))
|
||||
|
||||
/* FIXME: This can't be right. Need converter macros. */
|
||||
#define CONVERT_SSIZE_T_TO_JINT(x) ((jint)(x & 0xFFFFFFFF))
|
||||
#define CONVERT_JINT_TO_SSIZE_T(x) (x)
|
||||
|
||||
/* cached fieldID of gnu.java.nio.channels.FileChannelImpl.fd */
|
||||
static jfieldID native_fd_fieldID;
|
||||
|
||||
static jint
|
||||
get_native_fd (JNIEnv * env, jobject obj)
|
||||
{
|
||||
return (*env)->GetIntField (env, obj, native_fd_fieldID);
|
||||
}
|
||||
|
||||
/*
|
||||
* Library initialization routine. Called as part of java.io.FileDescriptor
|
||||
* static initialization.
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_gnu_java_nio_channels_FileChannelImpl_init (JNIEnv * env, jclass clazz)
|
||||
{
|
||||
jclass clazz_fc;
|
||||
jfieldID field;
|
||||
jmethodID constructor;
|
||||
jobject obj;
|
||||
|
||||
/* Initialize native_fd_fieldID so we only compute it once! */
|
||||
clazz_fc = (*env)->FindClass (env, "gnu/java/nio/channels/FileChannelImpl");
|
||||
if (!clazz_fc)
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION, "Internal error");
|
||||
return;
|
||||
}
|
||||
|
||||
field = (*env)->GetFieldID (env, clazz_fc, "fd", "I");
|
||||
if (!field)
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION, "Internal error");
|
||||
return;
|
||||
}
|
||||
|
||||
native_fd_fieldID = field;
|
||||
|
||||
constructor = (*env)->GetMethodID (env, clazz, "<init>", "(II)V");
|
||||
if (!constructor)
|
||||
return;
|
||||
|
||||
#define INIT_FIELD(FIELDNAME, FDVALUE, MODE) \
|
||||
field = (*env)->GetStaticFieldID (env, clazz, FIELDNAME, \
|
||||
"Lgnu/java/nio/channels/FileChannelImpl;"); \
|
||||
if (! field) \
|
||||
return; \
|
||||
obj = (*env)->NewObject (env, clazz, constructor, FDVALUE, MODE); \
|
||||
if (! obj) \
|
||||
return; \
|
||||
(*env)->SetStaticObjectField (env, clazz, field, obj); \
|
||||
if ((*env)->ExceptionOccurred (env)) \
|
||||
return;
|
||||
|
||||
INIT_FIELD ("in", 0, FILECHANNELIMPL_READ);
|
||||
INIT_FIELD ("out", 1, FILECHANNELIMPL_WRITE);
|
||||
INIT_FIELD ("err", 2, FILECHANNELIMPL_WRITE);
|
||||
|
||||
#undef INIT_FIELD
|
||||
}
|
||||
|
||||
/*
|
||||
* Open the specified file and return a native file descriptor
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_gnu_java_nio_channels_FileChannelImpl_open (JNIEnv * env,
|
||||
jobject obj
|
||||
__attribute__ ((__unused__)),
|
||||
jstring name, jint mode)
|
||||
{
|
||||
const char *filename;
|
||||
int flags;
|
||||
int permissions;
|
||||
int native_fd;
|
||||
int result;
|
||||
|
||||
filename = JCL_jstring_to_cstring (env, name);
|
||||
if (filename == NULL)
|
||||
return (-1); /* Exception will already have been thrown */
|
||||
|
||||
/* get file/permission flags for open() */
|
||||
if ((mode & FILECHANNELIMPL_FILEOPEN_FLAG_READ)
|
||||
&& (mode & FILECHANNELIMPL_FILEOPEN_FLAG_WRITE))
|
||||
{
|
||||
/* read/write */
|
||||
flags =
|
||||
TARGET_NATIVE_FILE_FILEFLAG_CREATE |
|
||||
TARGET_NATIVE_FILE_FILEFLAG_READWRITE;
|
||||
permissions = TARGET_NATIVE_FILE_FILEPERMISSION_NORMAL;
|
||||
}
|
||||
else if ((mode & FILECHANNELIMPL_FILEOPEN_FLAG_READ))
|
||||
{
|
||||
/* read */
|
||||
flags = TARGET_NATIVE_FILE_FILEFLAG_READ;
|
||||
permissions = TARGET_NATIVE_FILE_FILEPERMISSION_NORMAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* write */
|
||||
flags =
|
||||
TARGET_NATIVE_FILE_FILEFLAG_CREATE |
|
||||
TARGET_NATIVE_FILE_FILEFLAG_WRITE;
|
||||
if ((mode & FILECHANNELIMPL_FILEOPEN_FLAG_APPEND))
|
||||
{
|
||||
flags |= TARGET_NATIVE_FILE_FILEFLAG_APPEND;
|
||||
}
|
||||
else
|
||||
{
|
||||
flags |= TARGET_NATIVE_FILE_FILEFLAG_TRUNCATE;
|
||||
}
|
||||
permissions = TARGET_NATIVE_FILE_FILEPERMISSION_NORMAL;
|
||||
}
|
||||
|
||||
if ((mode & FILECHANNELIMPL_FILEOPEN_FLAG_SYNC))
|
||||
{
|
||||
flags |= TARGET_NATIVE_FILE_FILEFLAG_SYNC;
|
||||
}
|
||||
|
||||
if ((mode & FILECHANNELIMPL_FILEOPEN_FLAG_DSYNC))
|
||||
{
|
||||
flags |= TARGET_NATIVE_FILE_FILEFLAG_DSYNC;
|
||||
}
|
||||
#ifdef O_BINARY
|
||||
flags |= TARGET_NATIVE_FILE_FILEFLAG_BINARY;
|
||||
#endif
|
||||
|
||||
TARGET_NATIVE_FILE_OPEN (filename, native_fd, flags, permissions, result);
|
||||
JCL_free_cstring (env, name, filename);
|
||||
|
||||
if (result != TARGET_NATIVE_OK)
|
||||
{
|
||||
/* We can only throw FileNotFoundException. */
|
||||
JCL_ThrowException (env,
|
||||
"java/io/FileNotFoundException",
|
||||
TARGET_NATIVE_LAST_ERROR_STRING ());
|
||||
return TARGET_NATIVE_MATH_INT_INT64_CONST_MINUS_1;
|
||||
}
|
||||
|
||||
return native_fd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Closes the specified file descriptor and return status code.
|
||||
* Exception on error
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_gnu_java_nio_channels_FileChannelImpl_implCloseChannel (JNIEnv * env,
|
||||
jobject obj)
|
||||
{
|
||||
int native_fd;
|
||||
int result;
|
||||
|
||||
native_fd = get_native_fd (env, obj);
|
||||
|
||||
TARGET_NATIVE_FILE_CLOSE (native_fd, result);
|
||||
if (result != TARGET_NATIVE_OK)
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION,
|
||||
TARGET_NATIVE_LAST_ERROR_STRING ());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return number of bytes that can be read from the file w/o blocking.
|
||||
* Exception on error
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_gnu_java_nio_channels_FileChannelImpl_available (JNIEnv * env,
|
||||
jobject obj)
|
||||
{
|
||||
int native_fd;
|
||||
jlong bytes_available;
|
||||
int result;
|
||||
|
||||
native_fd = get_native_fd (env, obj);
|
||||
|
||||
TARGET_NATIVE_FILE_AVAILABLE (native_fd, bytes_available, result);
|
||||
if (result != TARGET_NATIVE_OK)
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION,
|
||||
TARGET_NATIVE_LAST_ERROR_STRING ());
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME NYI ??? why only jint and not jlong? */
|
||||
return TARGET_NATIVE_MATH_INT_INT64_TO_INT32 (bytes_available);
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_gnu_java_nio_channels_FileChannelImpl_size (JNIEnv * env, jobject obj)
|
||||
{
|
||||
int native_fd;
|
||||
jlong file_size;
|
||||
int result;
|
||||
|
||||
native_fd = get_native_fd (env, obj);
|
||||
|
||||
TARGET_NATIVE_FILE_SIZE (native_fd, file_size, result);
|
||||
if (result != TARGET_NATIVE_OK)
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION,
|
||||
TARGET_NATIVE_LAST_ERROR_STRING ());
|
||||
return TARGET_NATIVE_MATH_INT_INT64_CONST_MINUS_1;
|
||||
}
|
||||
|
||||
return file_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the current position of the file pointer
|
||||
* Exception on error
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_gnu_java_nio_channels_FileChannelImpl_implPosition (JNIEnv * env,
|
||||
jobject obj)
|
||||
{
|
||||
int native_fd;
|
||||
jlong current_offset;
|
||||
int result;
|
||||
|
||||
native_fd = get_native_fd (env, obj);
|
||||
|
||||
TARGET_NATIVE_FILE_TELL (native_fd, current_offset, result);
|
||||
if (result != TARGET_NATIVE_OK)
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION,
|
||||
TARGET_NATIVE_LAST_ERROR_STRING ());
|
||||
return TARGET_NATIVE_MATH_INT_INT64_CONST_MINUS_1;
|
||||
}
|
||||
|
||||
return current_offset;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrapper around lseek call. Return new file position
|
||||
* Exception on error
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_gnu_java_nio_channels_FileChannelImpl_seek (JNIEnv * env, jobject obj,
|
||||
jlong offset)
|
||||
{
|
||||
int native_fd;
|
||||
jlong new_offset;
|
||||
int result;
|
||||
|
||||
native_fd = get_native_fd (env, obj);
|
||||
|
||||
#if 0
|
||||
/* Should there be such an exception? All native layer macros should
|
||||
be accepting 64bit-values if needed. It some target is not able
|
||||
to handle such values it should simply operate with 32bit-values
|
||||
and convert 64bit-values appriopated. In this case I assume
|
||||
problems should not occurre: if some specific target is not able
|
||||
to handle 64bit-values the system is limited to 32bit at all, thus
|
||||
the application can not do a seek() or something else beyond the
|
||||
32bit limit. It this true?
|
||||
*/
|
||||
|
||||
/* FIXME: What do we do if offset > the max value of off_t on this 32bit
|
||||
* system? How do we detect that and what do we do? */
|
||||
if (CONVERT_OFF_T_TO_JLONG (native_offset) != offset)
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION,
|
||||
"Cannot represent position correctly on this system");
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
result = TARGET_NATIVE_ERROR;
|
||||
new_offset = TARGET_NATIVE_MATH_INT_INT64_CONST_MINUS_1;
|
||||
TARGET_NATIVE_FILE_SEEK_BEGIN (native_fd, offset, new_offset, result);
|
||||
|
||||
if (result != TARGET_NATIVE_OK)
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION,
|
||||
TARGET_NATIVE_LAST_ERROR_STRING ());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the length of the file
|
||||
* Exception on error
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_gnu_java_nio_channels_FileChannelImpl_implTruncate (JNIEnv * env,
|
||||
jobject obj,
|
||||
jlong len)
|
||||
{
|
||||
int native_fd;
|
||||
jlong file_size;
|
||||
int bytes_written;
|
||||
jlong save_offset, new_offset;
|
||||
char data;
|
||||
int result;
|
||||
|
||||
native_fd = get_native_fd (env, obj);
|
||||
|
||||
#if 0
|
||||
/* Should there be such an exception? All native layer macros should
|
||||
be accepting 64bit-values if needed. It some target is not able
|
||||
to handle such values it should simply operate with 32bit-values
|
||||
and convert 64bit-values appriopated. In this case I assume
|
||||
problems should not occurre: if some specific target is not able
|
||||
to handle 64bit-values the system is limited to 32bit at all, thus
|
||||
the application can not do a seek() or something else beyond the
|
||||
32bit limit. It this true?
|
||||
*/
|
||||
|
||||
/* FIXME: What do we do if len > the max value of off_t on this 32bit
|
||||
* system? How do we detect that and what do we do? */
|
||||
if (CONVERT_OFF_T_TO_JLONG (native_len) != len)
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION,
|
||||
"Cannot represent position correctly on this system");
|
||||
return;
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
/* get file size */
|
||||
TARGET_NATIVE_FILE_SIZE (native_fd, file_size, result);
|
||||
if (result != TARGET_NATIVE_OK)
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION,
|
||||
TARGET_NATIVE_LAST_ERROR_STRING ());
|
||||
return;
|
||||
}
|
||||
|
||||
/* Save off current position */
|
||||
TARGET_NATIVE_FILE_TELL (native_fd, save_offset, result);
|
||||
if (result != TARGET_NATIVE_OK)
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION,
|
||||
TARGET_NATIVE_LAST_ERROR_STRING ());
|
||||
return;
|
||||
}
|
||||
|
||||
if (TARGET_NATIVE_MATH_INT_INT64_LT (file_size, len))
|
||||
{
|
||||
/* File is too short -- seek to one byte short of where we want,
|
||||
* then write a byte */
|
||||
|
||||
/* move to position n-1 */
|
||||
TARGET_NATIVE_FILE_SEEK_BEGIN (native_fd,
|
||||
TARGET_NATIVE_MATH_INT_INT64_SUB (len,
|
||||
1),
|
||||
new_offset, result);
|
||||
if (result != TARGET_NATIVE_OK)
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION,
|
||||
TARGET_NATIVE_LAST_ERROR_STRING ());
|
||||
return;
|
||||
}
|
||||
|
||||
/* write a byte
|
||||
Note: This will fail if we somehow get here in read only mode
|
||||
* That shouldn't happen */
|
||||
data = '\0';
|
||||
TARGET_NATIVE_FILE_WRITE (native_fd, &data, 1, bytes_written, result);
|
||||
if (result != TARGET_NATIVE_OK)
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION,
|
||||
TARGET_NATIVE_LAST_ERROR_STRING ());
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reposition file pointer to where we started if not beyond new len. */
|
||||
if (TARGET_NATIVE_MATH_INT_INT64_LT (save_offset, len))
|
||||
{
|
||||
TARGET_NATIVE_FILE_SEEK_BEGIN (native_fd, save_offset,
|
||||
new_offset, result);
|
||||
if (result != TARGET_NATIVE_OK)
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION,
|
||||
TARGET_NATIVE_LAST_ERROR_STRING ());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (TARGET_NATIVE_MATH_INT_INT64_GT (file_size, len))
|
||||
{
|
||||
/* File is too long - use ftruncate if available */
|
||||
#ifdef HAVE_FTRUNCATE
|
||||
TARGET_NATIVE_FILE_TRUNCATE (native_fd, len, result);
|
||||
if (result != TARGET_NATIVE_OK)
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION,
|
||||
TARGET_NATIVE_LAST_ERROR_STRING ());
|
||||
return;
|
||||
}
|
||||
#else /* HAVE_FTRUNCATE */
|
||||
/* FIXME: Probably operation isn't supported, but this exception
|
||||
* is too harsh as it will probably crash the program without need
|
||||
JCL_ThrowException(env, "java/lang/UnsupportedOperationException",
|
||||
"not implemented - can't shorten files on this platform");
|
||||
*/
|
||||
JCL_ThrowException (env, IO_EXCEPTION, "Unable to shorten file length");
|
||||
#endif /* HAVE_FTRUNCATE */
|
||||
|
||||
/* Reposition file pointer when it now is beyond the end of file. */
|
||||
if (TARGET_NATIVE_MATH_INT_INT64_GT (save_offset, len))
|
||||
{
|
||||
TARGET_NATIVE_FILE_SEEK_BEGIN (native_fd, len, new_offset, result);
|
||||
if (result != TARGET_NATIVE_OK)
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION,
|
||||
TARGET_NATIVE_LAST_ERROR_STRING ());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_gnu_java_nio_channels_FileChannelImpl_mapImpl (JNIEnv * env,
|
||||
jobject obj
|
||||
__attribute__ ((__unused__)), jchar mode __attribute__ ((__unused__)), jlong position __attribute__ ((__unused__)), jint size __attribute__ ((__unused__)))
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION,
|
||||
"java.nio.FileChannelImpl.nio_mmap_file(): not implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a single byte from the file descriptor
|
||||
* Return byte read or -1 on eof, exception on error
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_gnu_java_nio_channels_FileChannelImpl_read__ (JNIEnv * env, jobject obj)
|
||||
{
|
||||
int native_fd;
|
||||
char data;
|
||||
ssize_t bytes_read;
|
||||
int result;
|
||||
|
||||
native_fd = get_native_fd (env, obj);
|
||||
|
||||
bytes_read = 0;
|
||||
do
|
||||
{
|
||||
TARGET_NATIVE_FILE_READ (native_fd, &data, 1, bytes_read, result);
|
||||
if ((result == TARGET_NATIVE_OK) && (bytes_read == 0))
|
||||
{
|
||||
return (-1);
|
||||
}
|
||||
if ((result != TARGET_NATIVE_OK)
|
||||
&& (TARGET_NATIVE_LAST_ERROR () !=
|
||||
TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL))
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION,
|
||||
TARGET_NATIVE_LAST_ERROR_STRING ());
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
while (result != TARGET_NATIVE_OK);
|
||||
|
||||
return ((jint) (data & 0xFF));
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads to a byte buffer from the specified file descriptor
|
||||
* Return number of bytes read or -1 on eof, exception on error
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_gnu_java_nio_channels_FileChannelImpl_read___3BII (JNIEnv * env,
|
||||
jobject obj,
|
||||
jbyteArray buffer,
|
||||
jint offset,
|
||||
jint length)
|
||||
{
|
||||
int native_fd;
|
||||
jbyte *bufptr;
|
||||
ssize_t bytes_read;
|
||||
ssize_t n;
|
||||
int result;
|
||||
|
||||
native_fd = get_native_fd (env, obj);
|
||||
|
||||
/* Must return 0 if an attempt is made to read 0 bytes. */
|
||||
if (length == 0)
|
||||
return 0;
|
||||
|
||||
if (offset < 0)
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION, "negative offset");
|
||||
return -1;
|
||||
}
|
||||
|
||||
bufptr = (*env)->GetByteArrayElements (env, buffer, 0);
|
||||
if (!bufptr)
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION, "Unexpected JNI error");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (length + offset > (*env)->GetArrayLength (env, buffer))
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION,
|
||||
"length + offset > buffer.length");
|
||||
return -1;
|
||||
}
|
||||
|
||||
bytes_read = 0;
|
||||
do
|
||||
{
|
||||
TARGET_NATIVE_FILE_READ (native_fd, (bufptr + offset + bytes_read),
|
||||
(length - bytes_read), n, result);
|
||||
if ((result == TARGET_NATIVE_OK) && (n == 0))
|
||||
{
|
||||
(*env)->ReleaseByteArrayElements (env, buffer, bufptr, 0);
|
||||
if (bytes_read == 0)
|
||||
return -1; /* Signal end of file to Java */
|
||||
else
|
||||
return CONVERT_SSIZE_T_TO_JINT (bytes_read);
|
||||
}
|
||||
if ((result != TARGET_NATIVE_OK)
|
||||
&& (TARGET_NATIVE_LAST_ERROR () !=
|
||||
TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL))
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION,
|
||||
TARGET_NATIVE_LAST_ERROR_STRING ());
|
||||
(*env)->ReleaseByteArrayElements (env, buffer, bufptr, 0);
|
||||
return -1;
|
||||
}
|
||||
if (result == TARGET_NATIVE_OK)
|
||||
bytes_read += n;
|
||||
}
|
||||
while (bytes_read < 1);
|
||||
|
||||
(*env)->ReleaseByteArrayElements (env, buffer, bufptr, 0);
|
||||
return CONVERT_SSIZE_T_TO_JINT (bytes_read);
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes a single byte to the specified file descriptor
|
||||
* Return status code, exception on error
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_gnu_java_nio_channels_FileChannelImpl_write__I (JNIEnv * env,
|
||||
jobject obj, jint b)
|
||||
{
|
||||
int native_fd;
|
||||
char native_data;
|
||||
ssize_t bytes_written;
|
||||
int result;
|
||||
|
||||
native_fd = get_native_fd (env, obj);
|
||||
native_data = (char) (CONVERT_JINT_TO_INT (b) & 0xFF);
|
||||
|
||||
do
|
||||
{
|
||||
TARGET_NATIVE_FILE_WRITE (native_fd, &native_data, 1, bytes_written,
|
||||
result);
|
||||
if ((result != TARGET_NATIVE_OK)
|
||||
&& (TARGET_NATIVE_LAST_ERROR () !=
|
||||
TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL))
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION,
|
||||
TARGET_NATIVE_LAST_ERROR_STRING ());
|
||||
return;
|
||||
}
|
||||
}
|
||||
while (result != TARGET_NATIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copies all parts of a file to disk.
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_gnu_java_nio_channels_FileChannelImpl_force (JNIEnv * env,
|
||||
jobject obj)
|
||||
{
|
||||
int native_fd;
|
||||
int result;
|
||||
native_fd = get_native_fd (env, obj);
|
||||
TARGET_NATIVE_FILE_FSYNC (native_fd, result);
|
||||
if (result != TARGET_NATIVE_OK)
|
||||
JCL_ThrowException (env, IO_EXCEPTION,
|
||||
TARGET_NATIVE_LAST_ERROR_STRING ());
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes a byte buffer to the specified file descriptor
|
||||
* Return status code, exception on error
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_gnu_java_nio_channels_FileChannelImpl_write___3BII (JNIEnv * env,
|
||||
jobject obj,
|
||||
jbyteArray buffer,
|
||||
jint offset,
|
||||
jint length)
|
||||
{
|
||||
int native_fd;
|
||||
jbyte *bufptr;
|
||||
ssize_t bytes_written;
|
||||
ssize_t n;
|
||||
int result;
|
||||
|
||||
native_fd = get_native_fd (env, obj);
|
||||
|
||||
/* Just return if an attempt is made to write 0 bytes. */
|
||||
if (length == 0)
|
||||
return;
|
||||
|
||||
bufptr = (*env)->GetByteArrayElements (env, buffer, 0);
|
||||
if (!bufptr)
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION, "Unexpected JNI error");
|
||||
return;
|
||||
}
|
||||
|
||||
bytes_written = 0;
|
||||
while (bytes_written < CONVERT_JINT_TO_SSIZE_T (length))
|
||||
{
|
||||
TARGET_NATIVE_FILE_WRITE (native_fd, (bufptr + offset + bytes_written),
|
||||
(length - bytes_written), n, result);
|
||||
if ((result != TARGET_NATIVE_OK)
|
||||
&& (TARGET_NATIVE_LAST_ERROR () !=
|
||||
TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL))
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION,
|
||||
TARGET_NATIVE_LAST_ERROR_STRING ());
|
||||
(*env)->ReleaseByteArrayElements (env, buffer, bufptr, 0);
|
||||
return;
|
||||
}
|
||||
if (result == TARGET_NATIVE_OK)
|
||||
bytes_written += n;
|
||||
}
|
||||
|
||||
(*env)->ReleaseByteArrayElements (env, buffer, bufptr, 0);
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_gnu_java_nio_channels_FileChannelImpl_lock (JNIEnv *env, jobject obj,
|
||||
jlong position, jlong size,
|
||||
jboolean shared, jboolean wait)
|
||||
{
|
||||
#ifdef HAVE_FCNTL
|
||||
int fd = get_native_fd (env, obj);
|
||||
int cmd = wait ? F_SETLKW : F_SETLK;
|
||||
struct flock flock;
|
||||
int ret;
|
||||
|
||||
flock.l_type = shared ? F_RDLCK : F_WRLCK;
|
||||
flock.l_whence = SEEK_SET;
|
||||
flock.l_start = (off_t) position;
|
||||
flock.l_len = (off_t) size;
|
||||
|
||||
ret = fcntl (fd, cmd, &flock);
|
||||
if (ret)
|
||||
{
|
||||
/* Linux man pages for fcntl state that errno might be either
|
||||
EACCES or EAGAIN if we try F_SETLK, and another process has
|
||||
an overlapping lock. */
|
||||
if (errno != EACCES && errno != EAGAIN)
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
|
||||
}
|
||||
return JNI_FALSE;
|
||||
}
|
||||
return JNI_TRUE;
|
||||
#else
|
||||
(void) obj;
|
||||
(void) position;
|
||||
(void) size;
|
||||
(void) shared;
|
||||
(void) wait;
|
||||
JCL_ThrowException (env, "java/lang/UnsupportedOperationException",
|
||||
"file locks not implemented on this platform");
|
||||
return JNI_FALSE;
|
||||
#endif /* HAVE_FCNTL */
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_gnu_java_nio_channels_FileChannelImpl_unlock (JNIEnv *env,
|
||||
jobject obj,
|
||||
jlong position,
|
||||
jlong length)
|
||||
{
|
||||
#ifdef HAVE_FCNTL
|
||||
int fd = get_native_fd (env, obj);
|
||||
struct flock flock;
|
||||
int ret;
|
||||
|
||||
flock.l_type = F_UNLCK;
|
||||
flock.l_whence = SEEK_SET;
|
||||
flock.l_start = (off_t) position;
|
||||
flock.l_len = (off_t) length;
|
||||
|
||||
ret = fcntl (fd, F_SETLK, &flock);
|
||||
if (ret)
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
|
||||
}
|
||||
#else
|
||||
(void) obj;
|
||||
(void) position;
|
||||
(void) length;
|
||||
JCL_ThrowException (env, "java/lang/UnsupportedOperationException",
|
||||
"file locks not implemented on this platform");
|
||||
#endif /* HAVE_FCNTL */
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
/* gnu_java_nio_charset_iconv_IconvDecoder.c --
|
||||
Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
#include <config.h>
|
||||
#include <jcl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(HAVE_ICONV)
|
||||
#include <iconv.h>
|
||||
#endif
|
||||
|
||||
#include "gnu_java_nio_charset_iconv_IconvDecoder.h"
|
||||
|
||||
static void createRawData (JNIEnv * env, jobject obj, void *ptr);
|
||||
static void *getData (JNIEnv * env, jobject obj);
|
||||
|
||||
static jfieldID infid = NULL;
|
||||
static jfieldID outfid = NULL;
|
||||
|
||||
/* Union used for type punning. */
|
||||
union char_union
|
||||
{
|
||||
jbyte **jb;
|
||||
jchar **jc;
|
||||
char **c;
|
||||
};
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_gnu_java_nio_charset_iconv_IconvDecoder_openIconv (JNIEnv * env,
|
||||
jobject obj,
|
||||
jstring jname)
|
||||
{
|
||||
#if defined(HAVE_ICONV)
|
||||
iconv_t iconv_object;
|
||||
jclass cls;
|
||||
|
||||
const char *name = JCL_jstring_to_cstring (env, jname);
|
||||
if (name == NULL)
|
||||
return;
|
||||
|
||||
/* Cache fieldIDs for use in decode function. */
|
||||
if (infid == NULL || outfid == NULL)
|
||||
{
|
||||
cls = (*env)->GetObjectClass (env, obj);
|
||||
infid = (*env)->GetFieldID (env, cls, "inremaining", "I");
|
||||
assert (infid != 0);
|
||||
outfid = (*env)->GetFieldID (env, cls, "outremaining", "I");
|
||||
assert (outfid != 0);
|
||||
}
|
||||
|
||||
/* to java from "name", native java format depends on endianness */
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
iconv_object = iconv_open ("UTF-16BE", name);
|
||||
#else
|
||||
iconv_object = iconv_open ("UTF-16LE", name);
|
||||
#endif
|
||||
|
||||
JCL_free_cstring (env, jname, name);
|
||||
if ((long) iconv_object == -1L)
|
||||
{
|
||||
JCL_ThrowException (env, "java/lang/IllegalArgumentException",
|
||||
"Charset not available");
|
||||
return;
|
||||
}
|
||||
createRawData (env, obj, (void *) iconv_object);
|
||||
#else
|
||||
JCL_ThrowException (env, "java/lang/IllegalArgumentException",
|
||||
"iconv not available");
|
||||
#endif
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_gnu_java_nio_charset_iconv_IconvDecoder_decode (JNIEnv * env,
|
||||
jobject obj,
|
||||
jbyteArray inArr,
|
||||
jcharArray outArr,
|
||||
jint posIn, jint remIn,
|
||||
jint posOut, jint remOut)
|
||||
{
|
||||
#if defined(HAVE_ICONV)
|
||||
iconv_t iconv_object = getData (env, obj);
|
||||
size_t retval;
|
||||
union char_union in, out;
|
||||
jbyte *input, *inputcopy;
|
||||
jchar *output, *outputcopy;
|
||||
size_t lenIn = (size_t) remIn;
|
||||
size_t lenOut = (size_t) remOut * 2;
|
||||
|
||||
inputcopy = input = (*env)->GetByteArrayElements (env, inArr, 0);
|
||||
outputcopy = output = (*env)->GetCharArrayElements (env, outArr, 0);
|
||||
|
||||
input += posIn;
|
||||
output += posOut;
|
||||
|
||||
in.jb = &input;
|
||||
out.jc = &output;
|
||||
retval = iconv (iconv_object, (ICONV_CONST char **) in.c, &lenIn,
|
||||
out.c, &lenOut);
|
||||
|
||||
/* XXX: Do we need to relase the input array? It's not modified. */
|
||||
(*env)->ReleaseByteArrayElements (env, inArr, inputcopy, 0);
|
||||
(*env)->ReleaseCharArrayElements (env, outArr, outputcopy, 0);
|
||||
|
||||
if (retval == (size_t) (-1))
|
||||
{
|
||||
if (errno == EILSEQ || errno == EINVAL)
|
||||
retval = 1;
|
||||
else
|
||||
retval = 0;
|
||||
}
|
||||
else
|
||||
retval = 0;
|
||||
|
||||
(*env)->SetIntField (env, obj, infid, (jint) lenIn);
|
||||
(*env)->SetIntField (env, obj, outfid, (jint) (lenOut >> 1));
|
||||
|
||||
return (jint) retval;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_gnu_java_nio_charset_iconv_IconvDecoder_closeIconv (JNIEnv * env,
|
||||
jobject obj)
|
||||
{
|
||||
#if defined(HAVE_ICONV)
|
||||
iconv_t iconv_object;
|
||||
iconv_object = getData (env, obj);
|
||||
iconv_close (iconv_object);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
createRawData (JNIEnv * env, jobject obj, void *ptr)
|
||||
{
|
||||
jclass cls;
|
||||
jmethodID method;
|
||||
jobject data;
|
||||
jfieldID data_fid;
|
||||
|
||||
cls = (*env)->GetObjectClass (env, obj);
|
||||
data_fid = (*env)->GetFieldID (env, cls, "data", "Lgnu/classpath/RawData;");
|
||||
assert (data_fid != 0);
|
||||
|
||||
#ifdef POINTERS_ARE_64BIT
|
||||
cls = (*env)->FindClass (env, "gnu/classpath/RawData64");
|
||||
method = (*env)->GetMethodID (env, cls, "<init>", "(J)V");
|
||||
data = (*env)->NewObject (env, cls, method, (jlong) ptr);
|
||||
#else
|
||||
cls = (*env)->FindClass (env, "gnu/classpath/RawData32");
|
||||
method = (*env)->GetMethodID (env, cls, "<init>", "(I)V");
|
||||
data = (*env)->NewObject (env, cls, method, (jint) ptr);
|
||||
#endif
|
||||
|
||||
(*env)->SetObjectField (env, obj, data_fid, data);
|
||||
}
|
||||
|
||||
static void *
|
||||
getData (JNIEnv * env, jobject obj)
|
||||
{
|
||||
jclass cls;
|
||||
jfieldID field;
|
||||
jfieldID data_fid;
|
||||
jobject data;
|
||||
|
||||
cls = (*env)->GetObjectClass (env, obj);
|
||||
data_fid = (*env)->GetFieldID (env, cls, "data", "Lgnu/classpath/RawData;");
|
||||
assert (data_fid != 0);
|
||||
data = (*env)->GetObjectField (env, obj, data_fid);
|
||||
|
||||
#if SIZEOF_VOID_P == 8
|
||||
cls = (*env)->FindClass (env, "gnu/classpath/RawData64");
|
||||
field = (*env)->GetFieldID (env, cls, "data", "J");
|
||||
return (void *) (*env)->GetLongField (env, data, field);
|
||||
#else
|
||||
cls = (*env)->FindClass (env, "gnu/classpath/RawData32");
|
||||
field = (*env)->GetFieldID (env, cls, "data", "I");
|
||||
return (void *) (*env)->GetIntField (env, data, field);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
/* gnu_java_nio_charset_iconv_IconvEncoder.c --
|
||||
Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
#include <config.h>
|
||||
#include <jcl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(HAVE_ICONV)
|
||||
#include <iconv.h>
|
||||
#endif
|
||||
|
||||
#include "gnu_java_nio_charset_iconv_IconvEncoder.h"
|
||||
|
||||
static void createRawData (JNIEnv * env, jobject obj, void *ptr);
|
||||
static void *getData (JNIEnv * env, jobject obj);
|
||||
|
||||
static jfieldID infid = NULL;
|
||||
static jfieldID outfid = NULL;
|
||||
|
||||
/* Union used for type punning. */
|
||||
union char_union
|
||||
{
|
||||
jbyte **jb;
|
||||
jchar **jc;
|
||||
char **c;
|
||||
};
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_gnu_java_nio_charset_iconv_IconvEncoder_openIconv (JNIEnv * env,
|
||||
jobject obj,
|
||||
jstring jname)
|
||||
{
|
||||
#if defined(HAVE_ICONV)
|
||||
iconv_t iconv_object;
|
||||
jclass cls;
|
||||
|
||||
const char *name = JCL_jstring_to_cstring (env, jname);
|
||||
if (name == NULL)
|
||||
return;
|
||||
|
||||
/* Cache fieldIDs for use in encode function. */
|
||||
if (infid == NULL || outfid == NULL)
|
||||
{
|
||||
cls = (*env)->GetObjectClass (env, obj);
|
||||
infid = (*env)->GetFieldID (env, cls, "inremaining", "I");
|
||||
assert (infid != 0);
|
||||
outfid = (*env)->GetFieldID (env, cls, "outremaining", "I");
|
||||
assert (outfid != 0);
|
||||
}
|
||||
|
||||
/* to "name" from java, native java format depends on endianness */
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
iconv_object = iconv_open (name, "UTF-16BE");
|
||||
#else
|
||||
iconv_object = iconv_open (name, "UTF-16LE");
|
||||
#endif
|
||||
|
||||
JCL_free_cstring (env, jname, name);
|
||||
if ((long) iconv_object == -1L)
|
||||
{
|
||||
JCL_ThrowException (env, "java/lang/IllegalArgumentException",
|
||||
"Charset not available");
|
||||
return;
|
||||
}
|
||||
createRawData (env, obj, (void *) iconv_object);
|
||||
#else
|
||||
JCL_ThrowException (env, "java/lang/IllegalArgumentException",
|
||||
"iconv not available");
|
||||
#endif
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_gnu_java_nio_charset_iconv_IconvEncoder_encode (JNIEnv * env,
|
||||
jobject obj,
|
||||
jcharArray inArr,
|
||||
jbyteArray outArr,
|
||||
jint posIn, jint remIn,
|
||||
jint posOut, jint remOut)
|
||||
{
|
||||
#if defined(HAVE_ICONV)
|
||||
iconv_t iconv_object = getData (env, obj);
|
||||
size_t retval;
|
||||
union char_union in, out;
|
||||
jchar *input, *inputcopy;
|
||||
jbyte *output, *outputcopy;
|
||||
size_t lenIn = (size_t) remIn * 2;
|
||||
size_t lenOut = (size_t) remOut;
|
||||
|
||||
inputcopy = input = (*env)->GetCharArrayElements (env, inArr, 0);
|
||||
outputcopy = output = (*env)->GetByteArrayElements (env, outArr, 0);
|
||||
|
||||
input += posIn;
|
||||
output += posOut;
|
||||
|
||||
in.jc = &input;
|
||||
out.jb = &output;
|
||||
retval = iconv (iconv_object, (ICONV_CONST char **) in.c, &lenIn,
|
||||
out.c, &lenOut);
|
||||
|
||||
/* XXX: Do we need to relase the input array? It's not modified. */
|
||||
(*env)->ReleaseCharArrayElements (env, inArr, inputcopy, 0);
|
||||
(*env)->ReleaseByteArrayElements (env, outArr, outputcopy, 0);
|
||||
|
||||
if (retval == (size_t) (-1))
|
||||
{
|
||||
if (errno == EILSEQ || errno == EINVAL)
|
||||
retval = 1;
|
||||
else
|
||||
retval = 0;
|
||||
}
|
||||
else
|
||||
retval = 0;
|
||||
|
||||
(*env)->SetIntField (env, obj, infid, (jint) (lenIn >> 1));
|
||||
(*env)->SetIntField (env, obj, outfid, (jint) lenOut);
|
||||
|
||||
return (jint) retval;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_gnu_java_nio_charset_iconv_IconvEncoder_closeIconv (JNIEnv * env,
|
||||
jobject obj)
|
||||
{
|
||||
#if defined(HAVE_ICONV)
|
||||
iconv_t iconv_object;
|
||||
iconv_object = getData (env, obj);
|
||||
iconv_close (iconv_object);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
createRawData (JNIEnv * env, jobject obj, void *ptr)
|
||||
{
|
||||
jclass cls;
|
||||
jmethodID method;
|
||||
jobject data;
|
||||
jfieldID data_fid;
|
||||
|
||||
cls = (*env)->GetObjectClass (env, obj);
|
||||
data_fid = (*env)->GetFieldID (env, cls, "data", "Lgnu/classpath/RawData;");
|
||||
assert (data_fid != 0);
|
||||
|
||||
#ifdef POINTERS_ARE_64BIT
|
||||
cls = (*env)->FindClass (env, "gnu/classpath/RawData64");
|
||||
method = (*env)->GetMethodID (env, cls, "<init>", "(J)V");
|
||||
data = (*env)->NewObject (env, cls, method, (jlong) ptr);
|
||||
#else
|
||||
cls = (*env)->FindClass (env, "gnu/classpath/RawData32");
|
||||
method = (*env)->GetMethodID (env, cls, "<init>", "(I)V");
|
||||
data = (*env)->NewObject (env, cls, method, (jint) ptr);
|
||||
#endif
|
||||
|
||||
(*env)->SetObjectField (env, obj, data_fid, data);
|
||||
}
|
||||
|
||||
static void *
|
||||
getData (JNIEnv * env, jobject obj)
|
||||
{
|
||||
jclass cls;
|
||||
jfieldID field;
|
||||
jfieldID data_fid;
|
||||
jobject data;
|
||||
|
||||
cls = (*env)->GetObjectClass (env, obj);
|
||||
data_fid = (*env)->GetFieldID (env, cls, "data", "Lgnu/classpath/RawData;");
|
||||
assert (data_fid != 0);
|
||||
data = (*env)->GetObjectField (env, obj, data_fid);
|
||||
|
||||
#if SIZEOF_VOID_P == 8
|
||||
cls = (*env)->FindClass (env, "gnu/classpath/RawData64");
|
||||
field = (*env)->GetFieldID (env, cls, "data", "J");
|
||||
return (void *) (*env)->GetLongField (env, data, field);
|
||||
#else
|
||||
cls = (*env)->FindClass (env, "gnu/classpath/RawData32");
|
||||
field = (*env)->GetFieldID (env, cls, "data", "I");
|
||||
return (void *) (*env)->GetIntField (env, data, field);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,328 @@
|
||||
/* java_nio.c - Native methods for gnu.java.nio.FileChannelImpl class
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
/* do not move; needed here because of some macro definitions */
|
||||
#include <config.h>
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#include <jni.h>
|
||||
#include <jcl.h>
|
||||
|
||||
#include "target_native.h"
|
||||
#ifndef WITHOUT_NETWORK
|
||||
#include "target_native_network.h"
|
||||
#endif /* WITHOUT_NETWORK */
|
||||
|
||||
#include "java_nio_channels_FileChannelImpl.h"
|
||||
|
||||
#include "javaio.h"
|
||||
|
||||
#define NIO_DEBUG(X) /* no debug */
|
||||
//#define NIO_DEBUG(X) X
|
||||
|
||||
/***************************************
|
||||
*
|
||||
* File Channel implementation
|
||||
*
|
||||
*************/
|
||||
|
||||
|
||||
static char *
|
||||
compare (int i, int lim, char *buffer)
|
||||
{
|
||||
sprintf (buffer, "(%d >= %d)", i, lim);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static inline int
|
||||
convert_Int (int X)
|
||||
{
|
||||
unsigned char *a = (unsigned char *) &X;
|
||||
int res =
|
||||
(((int) a[0]) << 24) +
|
||||
(((int) a[1]) << 16) + (((int) a[2]) << 8) + (((int) a[3]) << 0);
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline jlong
|
||||
convert_Long (jlong X)
|
||||
{
|
||||
unsigned char *a = (unsigned char *) &X;
|
||||
int res1 =
|
||||
(((int) a[0]) << 24) +
|
||||
(((int) a[1]) << 16) + (((int) a[2]) << 8) + (((int) a[3]) << 0);
|
||||
int res2;
|
||||
a += 4;
|
||||
res2 =
|
||||
(((int) a[0]) << 24) +
|
||||
(((int) a[1]) << 16) + (((int) a[2]) << 8) + (((int) a[3]) << 0);
|
||||
return ((jlong) res1) | ((jlong) res2) << 32LL;
|
||||
}
|
||||
|
||||
static inline short
|
||||
convert_Short (short X)
|
||||
{
|
||||
unsigned char *a = (unsigned char *) &X;
|
||||
int res = (((int) a[2]) << 8) + (((int) a[3]) << 0);
|
||||
return res;
|
||||
}
|
||||
static inline short
|
||||
convert_Char (short X)
|
||||
{
|
||||
unsigned char *a = (unsigned char *) &X;
|
||||
int res = (((int) a[2]) << 8) + (((int) a[3]) << 0);
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline unsigned char
|
||||
convert_Byte (unsigned char X)
|
||||
{
|
||||
return X;
|
||||
}
|
||||
|
||||
static inline float
|
||||
convert_Float (float X)
|
||||
{
|
||||
return X;
|
||||
}
|
||||
|
||||
static inline double
|
||||
convert_Double (double X)
|
||||
{
|
||||
return X;
|
||||
}
|
||||
|
||||
|
||||
// Note: do to many get()'s on a buffer and you should throw a BufferUnderflowException
|
||||
// Alas, I only found this out during testing....
|
||||
|
||||
#define READ_WRITE_MMAPED_FILE(TYPE,ELT) \
|
||||
\
|
||||
ELT Java_gnu_java_nio_MappedByteFileBuffer_nio_1read_1 ## TYPE ## _1file_1channel(JNIEnv *env, \
|
||||
jclass c, jobject b, \
|
||||
int index, int limit, jlong jaddress) \
|
||||
{ \
|
||||
char *address = *(void **) &jaddress; char buffer[128]; \
|
||||
if (index >= limit) JCL_ThrowException(env, "java/nio/BufferUnderflowException", compare(index,limit, buffer)); \
|
||||
NIO_DEBUG( fprintf(stderr, "READ:index = %d [0]=%c [1]=%c\n", index, address[0],address[1]); ) \
|
||||
address += index; \
|
||||
return convert_ ## TYPE (*(ELT *) address); \
|
||||
} \
|
||||
\
|
||||
void Java_gnu_java_nio_MappedByteFileBuffer_nio_1write_1 ## TYPE ## _1file_1channel(JNIEnv *env, \
|
||||
jclass c, jobject b, \
|
||||
int index, int limit, ELT value, jlong jaddress) \
|
||||
{ \
|
||||
\
|
||||
char *address = *(void **) &jaddress; char buffer[128]; \
|
||||
if (index >= limit) JCL_ThrowException(env, "java/nio/BufferUnderflowException", compare(index,limit, buffer)); \
|
||||
NIO_DEBUG( fprintf(stderr, "WRITE:index = %d [0]=%c [1]=%c\n", index, address[0],address[1]); ) \
|
||||
address += index; \
|
||||
*(ELT *) address = value; \
|
||||
} \
|
||||
\
|
||||
ELT Java_gnu_java_nio_MappedByteFileBuffer_nio_1get_1 ## TYPE(JNIEnv *env, jclass c, jobject b, \
|
||||
int index, int limit, jlong jaddress) \
|
||||
{ \
|
||||
fprintf(stderr, "unimplemented\n"); return 0; \
|
||||
} \
|
||||
\
|
||||
void Java_gnu_java_nio_MappedByteFileBuffer_nio_1put_1 ## TYPE(JNIEnv *env, jclass c, jobject b, \
|
||||
int index, int limit, \
|
||||
ELT value, jlong jaddress) \
|
||||
{ \
|
||||
fprintf(stderr, "unimplemented\n"); \
|
||||
}
|
||||
|
||||
READ_WRITE_MMAPED_FILE (Byte, u_int8_t);
|
||||
READ_WRITE_MMAPED_FILE (Char, u_int16_t);
|
||||
READ_WRITE_MMAPED_FILE (Short, u_int16_t);
|
||||
READ_WRITE_MMAPED_FILE (Int, u_int32_t);
|
||||
READ_WRITE_MMAPED_FILE (Long, u_int64_t);
|
||||
READ_WRITE_MMAPED_FILE (Float, float);
|
||||
READ_WRITE_MMAPED_FILE (Double, double);
|
||||
|
||||
u_int64_t
|
||||
nio_mmap_file (jint fd, jlong pos, jint size, jint jflags)
|
||||
{
|
||||
#ifdef HAVE_MMAP
|
||||
u_int64_t ret = 0;
|
||||
void *address;
|
||||
|
||||
int flags = (jflags != 2) ? MAP_SHARED : MAP_PRIVATE;
|
||||
int prot = PROT_READ;
|
||||
|
||||
if (jflags == 1)
|
||||
prot |= PROT_WRITE;
|
||||
|
||||
// fprintf(stderr, "mapping file: %d\n", fd);
|
||||
|
||||
address = mmap (0, size, prot, flags, fd, pos);
|
||||
|
||||
if (address == (void *) -1)
|
||||
{
|
||||
perror ("mapping file failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// fprintf(stderr, "address = %p, fd = %d, pos=%lld, size=%d\n", address, fd, pos, size);
|
||||
|
||||
*(void **) &ret = address;
|
||||
|
||||
return ret;
|
||||
#else /* not HAVE_MMAP */
|
||||
return (TARGET_NATIVE_MATH_INT_INT64_CONST_0);
|
||||
#endif /* not HAVE_MMAP */
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nio_msync (int fd, jlong jaddress, int size)
|
||||
{
|
||||
#ifdef HAVE_MMAP
|
||||
int res;
|
||||
char *address = *(void **) &jaddress;
|
||||
|
||||
// fprintf(stderr, "synchronizing with file (%p -> %d bytes (%s))\n", address, size, address);
|
||||
|
||||
res = msync (address, size, MS_SYNC | MS_INVALIDATE);
|
||||
|
||||
if (res == -1)
|
||||
{
|
||||
perror ("synchronize with file failed");
|
||||
}
|
||||
#else /* not HAVE_MMAP */
|
||||
#endif /* not HAVE_MMAP */
|
||||
}
|
||||
|
||||
void
|
||||
nio_unmmap_file (int fd, jlong jaddress, int size)
|
||||
{
|
||||
#ifdef HAVE_MMAP
|
||||
int res = 0;
|
||||
char *address = *(void **) &jaddress;
|
||||
|
||||
// nio_msync(fd, jaddress, size);
|
||||
|
||||
// fprintf(stderr, "unmapping (%p -> %d bytes)\n", address, size);
|
||||
|
||||
res = munmap (address, size);
|
||||
if (res == -1)
|
||||
{
|
||||
perror ("un-mapping file failed");
|
||||
}
|
||||
#else /* not HAVE_MMAP */
|
||||
#endif /* not HAVE_MMAP */
|
||||
}
|
||||
|
||||
|
||||
/***************************************
|
||||
*
|
||||
* Socket Channel implementation
|
||||
*
|
||||
*************/
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* Returns a 32 bit Internet address for the passed in InetAddress object
|
||||
* Ronald: This is a verbatim copy from javanet.c.
|
||||
* It's a copy to avoid a link error in orp.
|
||||
*/
|
||||
|
||||
static int
|
||||
socket_channel_get_net_addr (JNIEnv * env, jobject addr)
|
||||
{
|
||||
#ifndef WITHOUT_NETWORK
|
||||
jclass cls = 0;
|
||||
jmethodID mid;
|
||||
jarray arr = 0;
|
||||
jbyte *octets;
|
||||
int netaddr, len;
|
||||
|
||||
DBG
|
||||
("socket_channel_get_net_addr(): Entered socket_channel_get_net_addr\n");
|
||||
|
||||
/* Call the getAddress method on the object to retrieve the IP address */
|
||||
cls = (*env)->GetObjectClass (env, addr);
|
||||
if (cls == NULL)
|
||||
return (0);
|
||||
|
||||
mid = (*env)->GetMethodID (env, cls, "getAddress", "()[B");
|
||||
if (mid == NULL)
|
||||
return (0);
|
||||
|
||||
DBG ("socket_channel_get_net_addr(): Got getAddress method\n");
|
||||
|
||||
arr = (*env)->CallObjectMethod (env, addr, mid);
|
||||
if (arr == NULL)
|
||||
return (0);
|
||||
|
||||
DBG ("socket_channel_get_net_addr(): Got the address\n");
|
||||
|
||||
/* Turn the IP address into a 32 bit Internet address in network byte order */
|
||||
len = (*env)->GetArrayLength (env, arr);
|
||||
if (len != 4)
|
||||
{
|
||||
JCL_ThrowException (env, "java/io/IOException",
|
||||
"Internal Error: invalid byte array length");
|
||||
return (0);
|
||||
}
|
||||
DBG ("socket_channel_get_net_addr(): Length ok\n");
|
||||
|
||||
octets = (*env)->GetByteArrayElements (env, arr, 0);
|
||||
if (octets == NULL)
|
||||
return (0);
|
||||
|
||||
DBG ("socket_channel_get_net_addr(): Grabbed bytes\n");
|
||||
|
||||
TARGET_NATIVE_NETWORK_IPADDRESS_BYTES_TO_INT (octets[0],
|
||||
octets[1],
|
||||
octets[2],
|
||||
octets[3], netaddr);
|
||||
|
||||
(*env)->ReleaseByteArrayElements (env, arr, octets, 0);
|
||||
DBG ("socket_channel_get_net_addr(): Done getting addr\n");
|
||||
|
||||
return netaddr;
|
||||
#else /* not WITHOUT_NETWORK */
|
||||
return (0);
|
||||
#endif /* not WITHOUT_NETWORK */
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/* java_nio_MappedByteBufferImpl.c - Native methods for MappedByteBufferImpl
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
#include <config.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <jni.h>
|
||||
#include <jcl.h>
|
||||
|
||||
#include "java_nio_MappedByteBufferImpl.h"
|
||||
|
||||
#define IO_EXCEPTION "java/io/IOException"
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_nio_MappedByteBufferImpl_unmapImpl (JNIEnv * env,
|
||||
jclass class
|
||||
__attribute__ ((__unused__)))
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION,
|
||||
"java.nio.MappedByteBufferImpl.unmapImpl(): not implemented");
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_java_nio_MappedByteBufferImpl_isLoadedImpl (JNIEnv * env,
|
||||
jclass class
|
||||
__attribute__ ((__unused__)))
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION,
|
||||
"java.nio.MappedByteBufferImpl.isLoadedImpl(): not implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_nio_MappedByteBufferImpl_loadImpl (JNIEnv * env,
|
||||
jclass clazz
|
||||
__attribute__ ((__unused__)))
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION,
|
||||
"java.nio.MappedByteBufferImpl.loadImpl(): not implemented");
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_nio_MappedByteBufferImpl_forceImpl (JNIEnv * env,
|
||||
jclass class
|
||||
__attribute__ ((__unused__)))
|
||||
{
|
||||
JCL_ThrowException (env, IO_EXCEPTION,
|
||||
"java.nio.MappedByteBufferImpl.forceImpl(): not implemented");
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
/* java_nio_VMDirectByteBuffer.c - Native methods for VMDirectByteBuffer
|
||||
Copyright (C) 2004, 2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
#include <config.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <jni.h>
|
||||
#include <jcl.h>
|
||||
|
||||
#include "java_nio_VMDirectByteBuffer.h"
|
||||
|
||||
static jclass classRawData;
|
||||
static jmethodID methodRawDataInit;
|
||||
static jfieldID fieldNativePointer;
|
||||
|
||||
static void *NIOGetPointer (JNIEnv *, jobject);
|
||||
static jobject NIOGetRawData (JNIEnv *, void *pointer);
|
||||
|
||||
static void *
|
||||
NIOGetPointer (JNIEnv * env, jobject rawdata)
|
||||
{
|
||||
#if SIZEOF_VOID_P == 4
|
||||
return (void *) (*env)->GetIntField (env, rawdata, fieldNativePointer);
|
||||
#elif SIZEOF_VOID_P == 8
|
||||
return (void *) (*env)->GetLongField (env, rawdata, fieldNativePointer);
|
||||
#else
|
||||
#error unsupported pointer size
|
||||
#endif
|
||||
}
|
||||
|
||||
static jobject
|
||||
NIOGetRawData (JNIEnv * env, void *pointer)
|
||||
{
|
||||
#if SIZEOF_VOID_P == 4
|
||||
return (*env)->NewObject (env, classRawData, methodRawDataInit,
|
||||
(jint) pointer);
|
||||
#elif SIZEOF_VOID_P == 8
|
||||
return (*env)->NewObject (env, classRawData, methodRawDataInit,
|
||||
(jlong) pointer);
|
||||
#else
|
||||
#error unsupported pointer size
|
||||
#endif
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_nio_VMDirectByteBuffer_init
|
||||
(JNIEnv * env, jclass clazz __attribute__ ((__unused__)))
|
||||
{
|
||||
#if SIZEOF_VOID_P == 4
|
||||
classRawData = (*env)->FindClass (env, "gnu/classpath/RawData32");
|
||||
if (classRawData == NULL)
|
||||
{
|
||||
JCL_ThrowException (env, "java/lang/InternalError",
|
||||
"unable to find internal class");
|
||||
return;
|
||||
}
|
||||
|
||||
methodRawDataInit = (*env)->GetMethodID (env, classRawData,
|
||||
"<init>", "(I)V");
|
||||
if (methodRawDataInit == NULL)
|
||||
{
|
||||
JCL_ThrowException (env, "java/lang/InternalError",
|
||||
"unable to find internal constructor");
|
||||
return;
|
||||
}
|
||||
|
||||
fieldNativePointer = (*env)->GetFieldID (env, classRawData, "data", "I");
|
||||
if (fieldNativePointer == NULL)
|
||||
{
|
||||
JCL_ThrowException (env, "java/lang/InternalError",
|
||||
"unable to find internal field");
|
||||
return;
|
||||
}
|
||||
#elif SIZEOF_VOID_P == 8
|
||||
classRawData = (*env)->FindClass (env, "gnu/classpath/RawData64");
|
||||
if (classRawData == NULL)
|
||||
{
|
||||
JCL_ThrowException (env, "java/lang/InternalError",
|
||||
"unable to find internal class");
|
||||
return;
|
||||
}
|
||||
|
||||
methodRawDataInit = (*env)->GetMethodID (env, classRawData,
|
||||
"<init>", "(J)V");
|
||||
if (methodRawDataInit == NULL)
|
||||
{
|
||||
JCL_ThrowException (env, "java/lang/InternalError",
|
||||
"unable to find internal constructor");
|
||||
return;
|
||||
}
|
||||
|
||||
fieldNativePointer = (*env)->GetFieldID (env, classRawData, "data", "J");
|
||||
if (fieldNativePointer == NULL)
|
||||
{
|
||||
JCL_ThrowException (env, "java/lang/InternalError",
|
||||
"unable to find internal field");
|
||||
return;
|
||||
}
|
||||
#else
|
||||
#error unsupported pointer size
|
||||
#endif
|
||||
|
||||
/* We need to wrap the jclass in global reference to make it persistent */
|
||||
if ((classRawData = (*env)->NewGlobalRef (env, classRawData)) == NULL)
|
||||
{
|
||||
JCL_ThrowException (env, "java/lang/InternalError",
|
||||
"failed to create global reference");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_java_nio_VMDirectByteBuffer_allocate
|
||||
(JNIEnv * env, jclass clazz __attribute__ ((__unused__)), jint capacity)
|
||||
{
|
||||
void *buffer;
|
||||
|
||||
buffer = malloc (capacity);
|
||||
|
||||
if (buffer == NULL)
|
||||
{
|
||||
JCL_ThrowException (env, "java/lang/OutOfMemoryError",
|
||||
"unable to allocate memory for direct byte buffer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return NIOGetRawData (env, buffer);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_nio_VMDirectByteBuffer_free
|
||||
(JNIEnv * env, jclass clazz __attribute__ ((__unused__)), jobject address)
|
||||
{
|
||||
free (NIOGetPointer (env, address));
|
||||
}
|
||||
|
||||
JNIEXPORT jbyte JNICALL
|
||||
Java_java_nio_VMDirectByteBuffer_get__Lgnu_classpath_RawData_2I
|
||||
(JNIEnv * env, jclass clazz __attribute__ ((__unused__)),
|
||||
jobject address, jint index)
|
||||
{
|
||||
return ((jbyte *) NIOGetPointer (env, address))[index];
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_nio_VMDirectByteBuffer_put
|
||||
(JNIEnv * env, jclass clazz __attribute__ ((__unused__)),
|
||||
jobject address, jint index, jbyte value)
|
||||
{
|
||||
jbyte *pointer = (jbyte *) NIOGetPointer (env, address) + index;
|
||||
*pointer = value;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_nio_VMDirectByteBuffer_get__Lgnu_classpath_RawData_2I_3BII
|
||||
(JNIEnv * env, jclass clazz __attribute__ ((__unused__)),
|
||||
jobject address, jint index, jbyteArray dst, jint dst_offset, jint dst_len)
|
||||
{
|
||||
jbyte *src = (jbyte *) NIOGetPointer (env, address) + index;
|
||||
memcpy ((*env)->GetByteArrayElements (env, dst, NULL) + dst_offset, src,
|
||||
dst_len);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_nio_VMDirectByteBuffer_shiftDown
|
||||
(JNIEnv * env, jclass clazz __attribute__ ((__unused__)),
|
||||
jobject address, jint dst_offset, jint src_offset, jint count)
|
||||
{
|
||||
jbyte *dst = (jbyte *) NIOGetPointer (env, address) + dst_offset;
|
||||
jbyte *src = (jbyte *) NIOGetPointer (env, address) + src_offset;
|
||||
memmove (dst, src, count);
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_java_nio_VMDirectByteBuffer_adjustAddress
|
||||
(JNIEnv * env, jclass clazz __attribute__ ((__unused__)),
|
||||
jobject address, jint offset)
|
||||
{
|
||||
return NIOGetRawData (env, (jbyte *) NIOGetPointer (env, address) + offset);
|
||||
}
|
||||
Reference in New Issue
Block a user