Initial revision

From-SVN: r102074
This commit is contained in:
Tom Tromey
2005-07-16 00:30:23 +00:00
parent 6f4434b39b
commit f911ba985a
4557 changed files with 1000262 additions and 0 deletions
@@ -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);
}