1 /* gnu_java_nio_VMChannel.c -
2 Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
43 #include <config-int.h>
45 #include <sys/types.h>
46 #include <sys/ioctl.h>
48 #include <sys/socket.h>
52 #include <netinet/in.h>
63 #include "gnu_java_nio_VMChannel.h"
68 #endif /* HAVE_FCNTL_H */
70 #define CONNECT_EXCEPTION "java/net/ConnectException"
71 #define IO_EXCEPTION "java/io/IOException"
72 #define SOCKET_EXCEPTION "java/net/SocketException"
73 #define INTERRUPTED_IO_EXCEPTION "java/io/InterruptedIOException"
74 #define NON_READABLE_CHANNEL_EXCEPTION "java/nio/channels/NonReadableChannelException"
75 #define NON_WRITABLE_CHANNEL_EXCEPTION "java/nio/channels/NonWritableChannelException"
76 #define SOCKET_TIMEOUT_EXCEPTION "java/net/SocketTimeoutException"
78 /* Align a value up or down to a multiple of the pagesize. */
79 #define ALIGN_DOWN(p,s) ((p) - ((p) % (s)))
80 #define ALIGN_UP(p,s) ((p) + ((s) - ((p) % (s))))
83 * Limit to maximum of 16 buffers
85 #define JCL_IOV_MAX 16
92 enum JCL_buffer_type { DIRECT, HEAP, ARRAY, UNKNOWN };
96 enum JCL_buffer_type type;
104 jmethodID get_method_id(JNIEnv *, jclass, const char *, const char *);
105 void JCL_print_buffer(JNIEnv *, struct JCL_buffer *);
106 int JCL_init_buffer(JNIEnv *, struct JCL_buffer *, jobject);
107 void JCL_release_buffer(JNIEnv *, struct JCL_buffer *, jobject, jint);
108 void JCL_cleanup_buffers(JNIEnv *, struct JCL_buffer *, jint, jobjectArray, jint, jlong);
109 int JCL_thread_interrupted(JNIEnv *);
111 static jfieldID address_fid;
112 static jmethodID get_position_mid;
113 static jmethodID set_position_mid;
114 static jmethodID get_limit_mid;
115 static jmethodID set_limit_mid;
116 static jmethodID has_array_mid;
117 static jmethodID array_mid;
118 static jmethodID array_offset_mid;
119 static jmethodID thread_interrupted_mid;
120 static jclass vm_channel_class;
123 get_method_id(JNIEnv *env, jclass clazz, const char *name,
126 jmethodID mid = (*env)->GetMethodID(env, clazz, name, sig);
127 /* NIODBG("name: %s; sig: %s", name, sig); */
130 JCL_ThrowException(env, "java/lang/InternalError", name);
138 JCL_print_buffer(JNIEnv *env __attribute__((__unused__)), struct JCL_buffer *buf)
140 fprintf (stderr, "Buffer - type: %d, ptr: %p\n", buf->type, buf->ptr);
145 JCL_init_buffer(JNIEnv *env, struct JCL_buffer *buf, jobject bbuf)
147 void *addr = (*env)->GetDirectBufferAddress (env, bbuf);
149 /* NIODBG("buf: %p; bbuf: %p; addr: %p", (void *) buf, bbuf, addr); */
151 buf->position = (*env)->CallIntMethod(env, bbuf, get_position_mid);
152 buf->limit = (*env)->CallIntMethod(env, bbuf, get_limit_mid);
159 buf->ptr = (jbyte *) addr;
165 has_array = (*env)->CallBooleanMethod(env, bbuf, has_array_mid);
167 if (has_array == JNI_TRUE)
170 buf->offset = (*env)->CallIntMethod(env, bbuf, array_offset_mid);
171 arr = (*env)->CallObjectMethod(env, bbuf, array_mid);
172 buf->ptr = (*env)->GetByteArrayElements(env, arr, 0);
174 (*env)->DeleteLocalRef(env, arr);
178 jobject address = (*env)->GetObjectField (env, bbuf, address_fid);
180 return -1; /* XXX handle non-array, non-native buffers? */
181 buf->ptr = (jbyte *) JCL_GetRawData(env, address);
183 (*env)->DeleteLocalRef(env, address);
191 JCL_release_buffer(JNIEnv *env, struct JCL_buffer *buf, jobject bbuf,
196 /* NIODBG("buf: %p; bbuf: %p; action: %x", (void *) buf, bbuf, action); */
198 /* Set the position to the appropriate value */
202 bbufTemp = (*env)->CallObjectMethod(env, bbuf, set_position_mid,
203 buf->position + buf->count);
204 (*env)->DeleteLocalRef(env, bbufTemp);
213 arr = (*env)->CallObjectMethod(env, bbuf, array_mid);
214 (*env)->ReleaseByteArrayElements(env, arr, buf->ptr, action);
215 (*env)->DeleteLocalRef(env, arr);
218 /* TODO: Handle buffers that are not direct or array backed */
224 JCL_cleanup_buffers(JNIEnv *env,
225 struct JCL_buffer *bi_list,
233 /* NIODBG("bi_list: %p; vec_len: %d; bbufs: %p; offset: %d; num_bytes: %lld", */
234 /* (void *) bi_list, vec_len, bbufs, offset, num_bytes); */
236 /* Update all of the bbufs with the approriate information */
237 for (i = 0; i < vec_len; i++)
239 struct JCL_buffer* buf;
243 bbuf = (*env)->GetObjectArrayElement(env, bbufs, offset + i);
245 if (num_bytes > (buf->limit - buf->position))
246 buf->count = (buf->limit - buf->position);
248 buf->count = num_bytes;
250 num_bytes -= buf->count;
252 JCL_release_buffer(env, buf, bbuf, JNI_ABORT);
253 (*env)->DeleteLocalRef(env, bbuf);
259 JCL_thread_interrupted(JNIEnv *env)
261 return (int) (*env)->CallStaticBooleanMethod(env, vm_channel_class,
262 thread_interrupted_mid);
267 * Class: gnu_java_nio_VMChannel
271 JNIEXPORT jint JNICALL
272 Java_gnu_java_nio_VMChannel_stdin_1fd (JNIEnv *env __attribute__((unused)),
273 jclass c __attribute__((unused)))
275 /* NIODBG("%d", fileno (stdin)); */
276 return fileno (stdin);
281 * Class: gnu_java_nio_VMChannel
285 JNIEXPORT jint JNICALL
286 Java_gnu_java_nio_VMChannel_stdout_1fd (JNIEnv *env __attribute__((unused)),
287 jclass c __attribute__((unused)))
289 /* NIODBG("%d", fileno (stdout)); */
290 return fileno (stdout);
295 * Class: gnu_java_nio_VMChannel
299 JNIEXPORT jint JNICALL
300 Java_gnu_java_nio_VMChannel_stderr_1fd (JNIEnv *env __attribute__((unused)),
301 jclass c __attribute__((unused)))
303 /* NIODBG("%d", fileno (stderr)); */
304 return fileno (stderr);
308 JNIEXPORT void JNICALL
309 Java_gnu_java_nio_VMChannel_initIDs (JNIEnv *env,
312 jclass bufferClass = JCL_FindClass(env, "java/nio/Buffer");
313 jclass byteBufferClass = JCL_FindClass(env, "java/nio/ByteBuffer");
315 /* NIODBG("%s", "..."); */
317 address_fid = (*env)->GetFieldID(env, bufferClass, "address",
318 "Lgnu/classpath/Pointer;");
319 if (address_fid == NULL)
321 JCL_ThrowException(env, "java/lang/InternalError",
322 "Unable to find internal field");
326 get_position_mid = get_method_id(env, bufferClass, "position", "()I");
327 set_position_mid = get_method_id(env, bufferClass, "position",
328 "(I)Ljava/nio/Buffer;");
329 get_limit_mid = get_method_id(env, bufferClass, "limit", "()I");
330 set_limit_mid = get_method_id(env, bufferClass, "limit",
331 "(I)Ljava/nio/Buffer;");
332 has_array_mid = get_method_id(env, byteBufferClass, "hasArray", "()Z");
333 array_mid = get_method_id(env, byteBufferClass, "array", "()[B");
334 array_offset_mid = get_method_id(env, byteBufferClass, "arrayOffset", "()I");
336 vm_channel_class = clazz;
337 thread_interrupted_mid = (*env)->GetStaticMethodID(env, clazz,
338 "isThreadInterrupted",
342 JNIEXPORT void JNICALL
343 Java_gnu_java_nio_VMChannel_setBlocking (JNIEnv *env,
344 jobject o __attribute__ ((__unused__)),
350 /* NIODBG("fd: %d; blocking: %d", fd, blocking); */
352 opts = fcntl(fd, F_GETFL);
355 JCL_ThrowException(env, IO_EXCEPTION,
356 "Failed to get flags for file desriptor");
360 if (blocking == JNI_TRUE)
361 opts &= ~(O_NONBLOCK);
365 opts = fcntl(fd, F_SETFL, opts);
369 JCL_ThrowException(env, IO_EXCEPTION,
370 "Failed to set flags for file desriptor");
375 /* Return true if fd is in non-blocking mode. */
377 is_non_blocking_fd(jint fd)
380 opts = fcntl(fd, F_GETFL);
383 /* Assume blocking on error. */
386 return (opts & O_NONBLOCK) != 0;
389 JNIEXPORT jint JNICALL
390 Java_gnu_java_nio_VMChannel_read__ILjava_nio_ByteBuffer_2 (JNIEnv *env,
391 jobject o __attribute__ ((__unused__)),
398 struct JCL_buffer buf;
401 /* NIODBG("fd: %d; bbuf: %p", fd, bbuf); */
403 if (JCL_init_buffer(env, &buf, bbuf) < 0)
405 /* TODO: Rethrown exception */
406 JCL_ThrowException (env, IO_EXCEPTION, "Buffer initialisation failed");
410 len = buf.limit - buf.position;
414 JCL_release_buffer (env, &buf, bbuf, JNI_ABORT);
420 result = cpnio_read (fd, &(buf.ptr[buf.position + buf.offset]), len);
423 while (result == -1 && errno == EINTR && ! JCL_thread_interrupted(env));
431 else if (result == -1)
436 if (is_non_blocking_fd(fd))
443 /* Read timeout on a socket with SO_RCVTIMEO != 0. */
444 JCL_release_buffer(env, &buf, bbuf, JNI_ABORT);
445 JCL_ThrowException(env, SOCKET_TIMEOUT_EXCEPTION, "read timed out");
449 else if (errno == EBADF) /* Bad fd */
451 JCL_release_buffer(env, &buf, bbuf, JNI_ABORT);
452 JCL_ThrowException (env, NON_READABLE_CHANNEL_EXCEPTION,
456 else if (EINTR == errno) /* read interrupted */
458 JCL_release_buffer(env, &buf, bbuf, JNI_ABORT);
459 JCL_ThrowException(env, INTERRUPTED_IO_EXCEPTION, strerror (errno));
464 JCL_release_buffer(env, &buf, bbuf, JNI_ABORT);
465 JCL_ThrowException (env, IO_EXCEPTION, strerror(errno));
472 JCL_release_buffer(env, &buf, bbuf, 0);
478 JCL_ThrowException (env, IO_EXCEPTION, "read not supported");
480 #endif /* HAVE_READ */
483 JNIEXPORT jint JNICALL
484 Java_gnu_java_nio_VMChannel_write__ILjava_nio_ByteBuffer_2 (JNIEnv *env,
485 jobject o __attribute__ ((__unused__)),
492 struct JCL_buffer buf;
495 /* NIODBG("fd: %d; bbuf: %p", fd, bbuf); */
497 if (JCL_init_buffer(env, &buf, bbuf) < 0)
499 /* TODO: Rethrown exception */
500 JCL_ThrowException (env, IO_EXCEPTION, "Buffer initialisation failed");
504 len = buf.limit - buf.position;
508 JCL_release_buffer (env, &buf, bbuf, JNI_ABORT);
514 result = cpnio_write (fd, &(buf.ptr[buf.position + buf.offset]), len);
517 while (result == -1 && errno == EINTR && ! JCL_thread_interrupted(env));
524 if (errno == EAGAIN) /* Non-blocking */
530 JCL_release_buffer(env, &buf, bbuf, JNI_ABORT);
531 JCL_ThrowException(env, IO_EXCEPTION, strerror(errno));
536 JCL_release_buffer(env, &buf, bbuf, JNI_ABORT);
542 JCL_ThrowException (env, IO_EXCEPTION, "write not supported");
544 #endif /* HAVE_WRITE */
549 * Implementation of a scattering read. Will use the appropriate
550 * vector based read call (currently readv on Linux).
552 * This has a limit to the number of buffers that will be read. It
553 * will not make muliple readv calls. This is to ensure that operations
554 * are atomic. Currently it is limited to 16 buffers. This is for
555 * compatibiliy with Sun.
557 JNIEXPORT jlong JNICALL
558 Java_gnu_java_nio_VMChannel_readScattering (JNIEnv *env,
559 jobject o __attribute__ ((__unused__)),
566 /* jboolean is_error = JNI_FALSE; */
567 /* char *error_msg; */
568 struct iovec buffers[JCL_IOV_MAX];
569 struct JCL_buffer bi_list[JCL_IOV_MAX];
571 jint vec_len = length < JCL_IOV_MAX ? length : JCL_IOV_MAX;
572 jlong bytes_read = 0;
575 /* NIODBG("fd: %d; bbufs: %p; offset: %d; length: %d", */
576 /* fd, bbufs, offset, length); */
578 /* Build the vector of buffers to read into */
579 for (i = 0; i < vec_len; i++)
581 struct JCL_buffer* buf;
585 bbuf = (*env)->GetObjectArrayElement(env, bbufs, offset + i);
587 JCL_init_buffer(env, buf, bbuf);
589 /* JCL_print_buffer (env, buf); */
591 buffers[i].iov_base = &(buf->ptr[buf->position + buf->offset]);
592 buffers[i].iov_len = buf->limit - buf->position;
593 (*env)->DeleteLocalRef(env, bbuf);
596 /* Work the scattering magic */
599 result = cpnio_readv (fd, buffers, vec_len);
602 while (result == -1 && errno == EINTR && ! JCL_thread_interrupted(env));
604 bytes_read = (jlong) result;
606 /* Handle the response */
611 if (is_non_blocking_fd(fd))
618 /* Read timeout on a socket with SO_RCVTIMEO != 0. */
619 JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset, bytes_read);
620 JCL_ThrowException(env, SOCKET_TIMEOUT_EXCEPTION, "read timed out");
624 else if (errno == EBADF) /* Bad fd */
626 JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset, bytes_read);
627 JCL_ThrowException (env, NON_READABLE_CHANNEL_EXCEPTION,
633 JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset, bytes_read);
634 JCL_ThrowException (env, IO_EXCEPTION, strerror(errno));
639 else if (result == 0) /* EOF */
644 JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset, bytes_read);
646 return (jlong) result;
651 * Implementation of a gathering write. Will use the appropriate
652 * vector based read call (currently readv on Linux).
654 * This has a limit to the number of buffers that will be read. It
655 * will not make muliple readv calls. This is to ensure that operations
656 * are atomic. Currently it is limited to 16 buffers. This is for
657 * compatibiliy with Sun.
659 JNIEXPORT jlong JNICALL
660 Java_gnu_java_nio_VMChannel_writeGathering (JNIEnv *env,
661 jobject o __attribute__ ((__unused__)),
668 /* jboolean is_error = JNI_FALSE; */
669 /* char *error_msg; */
670 struct iovec buffers[JCL_IOV_MAX];
671 struct JCL_buffer bi_list[JCL_IOV_MAX];
673 jint vec_len = length < JCL_IOV_MAX ? length : JCL_IOV_MAX;
677 /* NIODBG("fd: %d; bbufs: %p; offset: %d; length: %d", */
678 /* fd, bbufs, offset, length); */
680 /* Build the vector of buffers to read into */
681 for (i = 0; i < vec_len; i++)
683 struct JCL_buffer* buf;
687 bbuf = (*env)->GetObjectArrayElement(env, bbufs, offset + i);
689 JCL_init_buffer(env, buf, bbuf);
691 /* JCL_print_buffer(env, buf); */
693 buffers[i].iov_base = &(buf->ptr[buf->position + buf->offset]);
694 buffers[i].iov_len = buf->limit - buf->position;
695 (*env)->DeleteLocalRef(env, bbuf);
698 /* Work the gathering magic */
701 result = cpnio_writev (fd, buffers, vec_len);
704 while (result == -1 && tmp_errno == EINTR && ! JCL_thread_interrupted(env));
707 bytes_written = (jlong) result;
712 if (errno == EAGAIN) /* Non blocking */
714 else if (errno == EBADF) /* Bad fd */
716 JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset,
718 JCL_ThrowException (env, NON_WRITABLE_CHANNEL_EXCEPTION,
724 JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset,
726 JCL_ThrowException (env, IO_EXCEPTION, strerror(errno));
730 else if (result == 0) /* EOF?? Does this happen on a write */
733 JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset, bytes_written);
734 return (jlong) result;
739 * Class: gnu_java_nio_VMChannel
741 * Signature: (Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;)I
743 JNIEXPORT jint JNICALL
744 Java_gnu_java_nio_VMChannel_receive (JNIEnv *env,
745 jclass c __attribute__((unused)),
746 jint fd, jobject dst, jobject addrPort)
749 char *addrPortPtr = (*env)->GetDirectBufferAddress (env, addrPort);
750 struct JCL_buffer buf;
752 struct sockaddr_in6 sock_storage;
753 struct sockaddr_in6 *sock6;
754 socklen_t slen = sizeof (struct sockaddr_in6);
756 struct sockaddr_in sock_storage;
757 socklen_t slen = sizeof (struct sockaddr_in);
758 #endif /* HAVE_INET6 */
759 struct sockaddr *sockaddr = (struct sockaddr *) &sock_storage;
760 struct sockaddr_in *sock4;
764 if (JCL_init_buffer (env, &buf, dst) == -1)
765 JCL_ThrowException (env, IO_EXCEPTION, "loading buffer failed");
767 ret = cpnio_recvfrom (fd, &(buf.ptr[buf.position + buf.offset]),
768 buf.limit - buf.position, MSG_WAITALL,
773 JCL_release_buffer (env, &buf, dst, JNI_ABORT);
775 JCL_ThrowException (env, "java/io/InterruptedIOException", strerror (errno));
776 else if (EAGAIN == errno)
778 /* If the socket is in blocking mode, our timeout expired. */
779 int val = fcntl (fd, F_GETFL, 0);
781 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
782 else if ((val & O_NONBLOCK) == 0)
783 JCL_ThrowException (env, "java/net/SocketTimeoutException",
787 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
791 if (sockaddr->sa_family == AF_INET)
793 sock4 = (struct sockaddr_in *) sockaddr;
794 memcpy (addrPortPtr, &(sock4->sin_addr.s_addr), 4);
795 ;memcpy (addrPortPtr + 4, &(sock4->sin_port), 2);
799 else if (sockaddr->sa_family == AF_INET6)
801 sock6 = (struct sockaddr_in6 *) sockaddr;
802 memcpy (addrPortPtr, &(sock6->sin6_addr.s6_addr), 16);
803 memcpy (addrPortPtr + 16, &(sock6->sin6_port), 2);
806 #endif /* HAVE_INET6 */
813 JCL_ThrowException (env, "java/net/SocketException",
814 "unsupported address type returned");
818 JCL_release_buffer (env, &buf, dst, 0);
824 JCL_ThrowException (env, IO_EXCEPTION, "recvfrom not supported");
825 #endif /* HAVE_RECVFROM */
830 * Class: gnu_java_nio_VMChannel
832 * Signature: (Ljava/nio/ByteBuffer;[BI)I
834 JNIEXPORT jint JNICALL
835 Java_gnu_java_nio_VMChannel_send (JNIEnv *env,
836 jclass c __attribute__((unused)),
837 int fd, jobject src, jbyteArray addr, jint port)
840 struct sockaddr_in sockaddr;
842 struct JCL_buffer buf;
845 /* NIODBG("fd: %d; src: %p; addr: %p; port: %d", */
846 /* fd, src, addr, port); */
848 if (JCL_init_buffer (env, &buf, src) == -1)
850 JCL_ThrowException (env, IO_EXCEPTION, "loading buffer failed");
854 /* JCL_print_buffer (env, &buf); */
856 elems = (*env)->GetByteArrayElements (env, addr, NULL);
858 sockaddr.sin_family = AF_INET;
859 sockaddr.sin_addr.s_addr = *((uint32_t *) elems);
860 sockaddr.sin_port = htons (port);
864 ret = cpnio_sendto (fd, &(buf.ptr[buf.position + buf.offset]),
865 buf.limit - buf.position,
866 0, (const struct sockaddr *) &sockaddr,
867 sizeof (struct sockaddr_in));
869 while (-1 == ret && EINTR == errno);
871 (*env)->ReleaseByteArrayElements (env, addr, elems, JNI_ABORT);
876 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
877 JCL_release_buffer (env, &buf, src, JNI_ABORT);
882 JCL_release_buffer (env, &buf, src, JNI_ABORT);
889 #endif /* HAVE_SENDTO */
894 * Class: gnu_java_nio_VMChannel
896 * Signature: (Ljava/nio/ByteBuffer;[BI)I
898 JNIEXPORT jint JNICALL
899 Java_gnu_java_nio_VMChannel_send6 (JNIEnv *env,
900 jclass c __attribute__((unused)),
901 int fd, jobject src, jbyteArray addr, jint port)
903 #if defined(HAVE_SENDTO) && defined(HAVE_INET6)
904 struct sockaddr_in6 sockaddr;
906 struct JCL_buffer buf;
909 /* NIODBG("fd: %d; src: %p; addr: %p; port: %d", */
910 /* fd, src, addr, port); */
912 if (JCL_init_buffer (env, &buf, src) == -1)
914 JCL_ThrowException (env, IO_EXCEPTION, "loading buffer failed");
918 /* JCL_print_buffer (env, &buf); */
920 elems = (*env)->GetByteArrayElements (env, addr, NULL);
922 sockaddr.sin6_family = AF_INET6;
923 memcpy (&sockaddr.sin6_addr.s6_addr, elems, 16);
924 sockaddr.sin6_port = htons (port);
928 ret = cpnio_sendto (fd, (const void *) (buf.ptr + buf.offset),
929 buf.limit - buf.position,
930 0, (const struct sockaddr *) &sockaddr,
931 sizeof (struct sockaddr_in6));
933 while (-1 == ret && EINTR == errno);
935 (*env)->ReleaseByteArrayElements (env, addr, elems, JNI_ABORT);
940 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
941 JCL_release_buffer (env, &buf, src, JNI_ABORT);
946 JCL_release_buffer (env, &buf, src, JNI_ABORT);
953 JCL_ThrowException (env, IO_EXCEPTION, "IPv6 sendto not supported");
955 #endif /* HAVE_SENDTO && HAVE_INET6 */
960 * Class: gnu_java_nio_VMChannel
964 JNIEXPORT jint JNICALL
965 Java_gnu_java_nio_VMChannel_read__I (JNIEnv *env,
966 jclass c __attribute__((unused)),
974 /* NIODBG("fd: %d", fd); */
978 ret = cpnio_read (fd, &in, 1);
981 while (ret == -1 && errno == EINTR && ! JCL_thread_interrupted(env));
986 if (errno == EAGAIN && !is_non_blocking_fd(fd))
988 /* Read timeout on a socket with SO_RCVTIMEO != 0. */
989 JCL_ThrowException(env, SOCKET_TIMEOUT_EXCEPTION, "read timed out");
992 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1002 JCL_ThrowException (env, IO_EXCEPTION, "read not supported");
1003 #endif /* HAVE_READ */
1008 * Class: gnu_java_nio_VMChannel
1012 JNIEXPORT void JNICALL
1013 Java_gnu_java_nio_VMChannel_write__II (JNIEnv *env,
1014 jclass c __attribute__((unused)),
1018 char out = (char) data;
1022 /* NIODBG("fd: %d; data: %d", fd, data); */
1026 ret = cpnio_write (fd, &out, 1);
1029 while (ret == -1 && errno == EINTR && ! JCL_thread_interrupted(env));
1033 JCL_ThrowException(env, IO_EXCEPTION, strerror (errno));
1037 JCL_ThrowException (env, IO_EXCEPTION, "write not supported");
1038 #endif /* HAVE_WRITE */
1043 * Class: gnu_java_nio_VMChannel
1047 JNIEXPORT jint JNICALL
1048 Java_gnu_java_nio_VMChannel_socket (JNIEnv *env, jclass clazz __attribute__((unused)),
1056 ret = cpnio_socket (AF_INET, stream ? SOCK_STREAM : SOCK_DGRAM, 0);
1058 while (-1 == ret && EINTR == errno);
1061 JCL_ThrowException (env, "java/net/SocketException", strerror (errno));
1062 /* NIODBG("created socket %d", ret); */
1067 JCL_ThrowException (env, IO_EXCEPTION, "socket not supported");
1069 #endif /* HAVE_SOCKET */
1074 * Class: gnu_java_nio_VMChannel
1076 * Signature: (I[BI)Z
1078 JNIEXPORT jboolean JNICALL
1079 Java_gnu_java_nio_VMChannel_connect (JNIEnv *env, jclass clazz __attribute__((unused)),
1080 jint fd, jbyteArray addr, jint port, jint timeout)
1083 struct sockaddr_in sockaddr;
1084 struct timeval timeo;
1085 int origflags = 0, flags;
1090 if ((*env)->GetArrayLength (env, addr) != 4)
1092 JCL_ThrowException (env, SOCKET_EXCEPTION,
1093 "expecting 4-byte address");
1099 timeo.tv_sec = timeout / 1000;
1100 timeo.tv_usec = (timeout % 1000) * 1000;
1101 origflags = fcntl (fd, F_GETFL, 0);
1102 if (origflags == -1)
1104 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
1107 /* Set nonblocking mode, if not already set. */
1108 if (!(origflags & O_NONBLOCK))
1110 flags = origflags | O_NONBLOCK;
1111 if (fcntl (fd, F_SETFL, flags) == -1)
1113 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
1119 addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
1121 memset (&sockaddr, 0, sizeof (struct sockaddr_in));
1122 sockaddr.sin_family = AF_INET;
1123 sockaddr.sin_port = htons (port);
1124 sockaddr.sin_addr.s_addr = *((uint32_t *) addr_elems);
1129 ret = cpnio_connect (fd, (struct sockaddr *) &sockaddr,
1130 sizeof (struct sockaddr_in));
1133 while (ret == -1 && errno == EINTR && ! JCL_thread_interrupted(env));
1136 (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
1138 /* If a timeout was specified, select on the file descriptor with
1140 if (timeout > 0 && ret == -1)
1142 /* Reset the non-blocking flag, if needed. */
1143 if (!(origflags & O_NONBLOCK))
1145 if (fcntl (fd, F_SETFL, origflags) == -1)
1148 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
1152 if (EINPROGRESS == errno)
1157 ret = cpnio_select (fd + 1, NULL, &wrfds, NULL, &timeo);
1160 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
1163 if (ret == 0) /* connect timed out */
1165 JCL_ThrowException (env, SOCKET_TIMEOUT_EXCEPTION,
1166 "connect timed out");
1169 return JNI_TRUE; /* Connected! */
1171 else if (ECONNREFUSED == errno)
1173 JCL_ThrowException (env, CONNECT_EXCEPTION,
1179 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
1186 if (EINPROGRESS == errno)
1188 else if (ECONNREFUSED == errno)
1190 JCL_ThrowException (env, CONNECT_EXCEPTION,
1196 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
1207 JCL_ThrowException (env, SOCKET_EXCEPTION, "connect not supported");
1209 #endif /* HAVE_CONNECT */
1214 * Class: gnu_java_nio_VMChannel
1216 * Signature: (I[BI)Z
1218 JNIEXPORT jboolean JNICALL
1219 Java_gnu_java_nio_VMChannel_connect6 (JNIEnv *env, jclass clazz __attribute__((unused)),
1220 jint fd, jbyteArray addr, jint port, int timeout)
1222 #if defined(HAVE_CONNECT) && defined(HAVE_INET6)
1223 struct sockaddr_in6 sockaddr;
1224 struct timeval timeo;
1225 int flags, origflags = 0;
1231 timeo.tv_sec = timeout / 1000;
1232 timeo.tv_usec = (timeout % 1000) * 1000;
1233 origflags = fcntl (fd, F_GETFL, 0);
1234 if (origflags == -1)
1236 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
1239 /* Set nonblocking mode, if not already set. */
1240 if (!(origflags & O_NONBLOCK))
1242 flags = origflags | O_NONBLOCK;
1243 if (fcntl (fd, F_SETFL, flags) == -1)
1245 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
1251 addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
1253 memset (&sockaddr, 0, sizeof (struct sockaddr_in6));
1254 sockaddr.sin6_family = AF_INET6;
1255 sockaddr.sin6_port = htons (port);
1256 memcpy (&sockaddr.sin6_addr.s6_addr, addr_elems, 16);
1258 ret = cpnio_connect (fd, (struct sockaddr *) &sockaddr,
1259 sizeof (struct sockaddr_in6));
1261 (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
1263 /* If a timeout was specified, select on the file descriptor with
1265 if (timeout > 0 && ret == -1)
1267 /* Reset the non-blocking flag, if needed. */
1268 if (!(origflags & O_NONBLOCK))
1270 if (fcntl (fd, F_SETFL, origflags) == -1)
1273 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
1277 if (EINPROGRESS == errno)
1282 ret = cpnio_select (fd + 1, NULL, &wrfds, NULL, &timeo);
1285 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
1288 if (ret == 0) /* connect timed out */
1290 JCL_ThrowException (env, SOCKET_TIMEOUT_EXCEPTION,
1291 "connect timed out");
1294 return JNI_TRUE; /* Connected! */
1296 else if (ECONNREFUSED == errno)
1298 JCL_ThrowException (env, CONNECT_EXCEPTION,
1304 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
1311 if (EAGAIN == errno)
1313 else if (ECONNREFUSED == errno)
1315 JCL_ThrowException (env, CONNECT_EXCEPTION,
1321 JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
1332 JCL_ThrowException (env, SOCKET_EXCEPTION, "IPv6 connect not supported");
1334 #endif /* HAVE_CONNECT && HAVE_INET6 */
1339 * Class: gnu_java_nio_VMChannel
1340 * Method: getsockname
1341 * Signature: (ILjava/nio/ByteBuffer;)I
1343 JNIEXPORT jint JNICALL
1344 Java_gnu_java_nio_VMChannel_getsockname (JNIEnv *env, jclass clazz __attribute__((unused)),
1345 jint fd, jobject name)
1347 #ifdef HAVE_GETSOCKNAME
1349 struct sockaddr_in6 *addr6;
1350 struct sockaddr_in6 sock_storage;
1351 socklen_t socklen = sizeof (struct sockaddr_in6);
1353 struct sockaddr_in sock_storage;
1354 socklen_t socklen = sizeof (struct sockaddr_in);
1355 #endif /* HAVE_INET6 */
1357 struct sockaddr *sockaddr = (struct sockaddr *) &sock_storage;
1358 struct sockaddr_in *addr4;
1360 char *nameptr = (*env)->GetDirectBufferAddress (env, name);
1362 ret = getsockname (fd, sockaddr, &socklen);
1365 JCL_ThrowException (env, "java/net/SocketException", strerror (errno));
1369 if (sockaddr->sa_family == AF_INET)
1371 addr4 = (struct sockaddr_in *) sockaddr;
1372 memcpy (nameptr, &(addr4->sin_addr.s_addr), 4);
1373 memcpy (nameptr + 4, &(addr4->sin_port), 2);
1379 if (sockaddr->sa_family == AF_INET6)
1381 addr6 = (struct sockaddr_in6 *) sockaddr;
1382 memcpy (nameptr, &(addr6->sin6_addr.s6_addr), 16);
1383 memcpy (nameptr + 16, &(addr6->sin6_port), 2);
1386 #endif /* HAVE_INET6 */
1387 JCL_ThrowException (env, IO_EXCEPTION, "unsupported address format");
1392 JCL_ThrowException (env, IO_EXCEPTION, "getsockname not supported");
1394 #endif /* HAVE_GETSOCKNAME */
1399 * Class: gnu_java_nio_VMChannel
1400 * Method: getpeername
1401 * Signature: (ILjava/nio/ByteBuffer;)I
1403 JNIEXPORT jint JNICALL
1404 Java_gnu_java_nio_VMChannel_getpeername (JNIEnv *env, jclass clazz __attribute__((unused)),
1405 jint fd, jobject name)
1407 #ifdef HAVE_GETPEERNAME
1409 struct sockaddr_in6 *addr6;
1410 struct sockaddr_in6 sock_storage;
1411 socklen_t socklen = sizeof (struct sockaddr_in6);
1413 struct sockaddr_in sock_storage;
1414 socklen_t socklen = sizeof (struct sockaddr_in);
1415 #endif /* HAVE_INET6 */
1417 struct sockaddr *sockaddr = (struct sockaddr *) &sock_storage;
1418 struct sockaddr_in *addr4;
1420 char *nameptr = (*env)->GetDirectBufferAddress (env, name);
1422 ret = getpeername (fd, sockaddr, &socklen);
1425 if (ENOTCONN != errno)
1426 JCL_ThrowException (env, "java/net/SocketException", strerror (errno));
1430 if (sockaddr->sa_family == AF_INET)
1432 addr4 = (struct sockaddr_in *) sockaddr;
1433 memcpy (nameptr, &(addr4->sin_addr.s_addr), 4);
1434 memcpy (nameptr + 4, &(addr4->sin_port), 2);
1438 else if (sockaddr->sa_family == AF_INET6)
1440 addr6 = (struct sockaddr_in6 *) sockaddr;
1441 memcpy (nameptr, &(addr6->sin6_addr.s6_addr), 16);
1442 memcpy (nameptr + 16, &(addr6->sin6_port), 2);
1445 #endif /* HAVE_INET6 */
1447 JCL_ThrowException (env, "java/net/SocketException",
1448 "unsupported address type");
1453 JCL_ThrowException (env, IO_EXCEPTION, "getpeername not supported");
1455 #endif /* HAVE_GETPEERNAME */
1460 * Class: gnu_java_nio_VMChannel
1464 JNIEXPORT jint JNICALL
1465 Java_gnu_java_nio_VMChannel_accept (JNIEnv *env,
1466 jclass c __attribute__((unused)),
1474 struct sockaddr_in6 addr;
1475 socklen_t alen = sizeof (struct sockaddr_in6);
1477 struct sockaddr_in addr;
1478 socklen_t alen = sizeof (struct sockaddr_in);
1479 #endif /* HAVE_INET6 */
1483 ret = cpnio_accept (fd, (struct sockaddr *) &addr, &alen);
1490 /* Check if interrupted by Thread.interrupt(). If not then some
1491 * other unrelated signal interrupted the system function and
1492 * we should start over again.
1494 if (JCL_thread_interrupted(env))
1496 JCL_ThrowException (env, "java/net/SocketException", strerror (tmp_errno));
1500 #if defined(EWOULDBLOCK) && defined(EAGAIN) && EWOULDBLOCK != EAGAIN
1504 /* Socket in non-blocking mode and no pending connection. */
1507 JCL_ThrowException (env, "java/net/SocketException", strerror (tmp_errno));
1515 cpio_closeOnExec(ret);
1520 JCL_ThrowException (env, IO_EXCEPTION, "accept not supported");
1522 #endif /* HAVE_ACCEPT */
1528 * Class: gnu_java_nio_VMChannel
1529 * Method: disconnect
1532 JNIEXPORT void JNICALL
1533 Java_gnu_java_nio_VMChannel_disconnect (JNIEnv *env,
1534 jclass c __attribute__((unused)),
1537 struct sockaddr sockaddr;
1539 sockaddr.sa_family = AF_UNSPEC;
1540 if (connect (fd, &sockaddr, sizeof (struct sockaddr)) == -1)
1542 /* The expected error for a successful disconnect is EAFNOSUPPORT. */
1543 if (errno != EAFNOSUPPORT)
1544 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1550 * Class: gnu_java_nio_VMChannel
1554 JNIEXPORT void JNICALL
1555 Java_gnu_java_nio_VMChannel_close (JNIEnv *env,
1556 jclass c __attribute__((unused)),
1559 if (close (fd) == -1)
1560 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1565 * Class: gnu_java_nio_VMChannel
1569 JNIEXPORT jint JNICALL
1570 Java_gnu_java_nio_VMChannel_available (JNIEnv *env,
1571 jclass c __attribute__((unused)),
1576 /* NIODBG("fd: %d", fd); */
1577 if (ioctl (fd, FIONREAD, &avail) == -1)
1578 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1579 /* NIODBG("avail: %d", avail); */
1585 enum FileChannel_mode {
1596 * Class: gnu_java_nio_VMChannel
1598 * Signature: (Ljava/lang/String;I)I
1600 JNIEXPORT jint JNICALL
1601 Java_gnu_java_nio_VMChannel_open (JNIEnv *env,
1602 jclass c __attribute__((unused)),
1603 jstring path, jint mode)
1608 mode_t mask = umask (0);
1611 if ((mode & CPNIO_READ) && (mode & CPNIO_WRITE))
1613 else if (mode & CPNIO_WRITE)
1619 | ((nmode == O_RDWR || nmode == O_WRONLY) ? O_CREAT : 0)
1620 | ((mode & CPNIO_APPEND) ? O_APPEND :
1621 ((nmode == O_RDWR || nmode == O_WRONLY) ? O_TRUNC : 0))
1622 | ((mode & CPNIO_EXCL) ? O_EXCL : 0)
1623 | ((mode & CPNIO_SYNC) ? O_SYNC : 0));
1625 npath = JCL_jstring_to_cstring (env, path);
1627 /* NIODBG("path: %s; mode: %x", npath, nmode); */
1629 ret = open (npath, nmode, 0777 & ~mask);
1631 /* NIODBG("ret: %d\n", ret); */
1633 JCL_free_cstring (env, path, npath);
1636 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1643 * Class: gnu_java_nio_VMChannel
1647 JNIEXPORT jlong JNICALL
1648 Java_gnu_java_nio_VMChannel_position (JNIEnv *env,
1649 jclass c __attribute__((unused)),
1655 ret = lseek (fd, 0, SEEK_CUR);
1658 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1662 JCL_ThrowException (env, IO_EXCEPTION, "position not supported");
1664 #endif /* HAVE_LSEEK */
1669 * Class: gnu_java_nio_VMChannel
1673 JNIEXPORT void JNICALL
1674 Java_gnu_java_nio_VMChannel_seek (JNIEnv *env,
1675 jclass c __attribute__((unused)),
1679 if (lseek (fd, (off_t) pos, SEEK_SET) == -1)
1680 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1682 JCL_ThrowException (env, IO_EXCEPTION, "seek not supported");
1683 #endif /* HAVE_LSEEK */
1688 * Class: gnu_java_nio_VMChannel
1692 JNIEXPORT void JNICALL
1693 Java_gnu_java_nio_VMChannel_truncate (JNIEnv *env,
1694 jclass c __attribute__((unused)),
1697 #if defined(HAVE_FTRUNCATE) && defined(HAVE_LSEEK)
1698 off_t pos = lseek (fd, 0, SEEK_CUR);
1701 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1704 if (ftruncate (fd, (off_t) len) == -1)
1706 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1711 if (lseek (fd, len, SEEK_SET) == -1)
1712 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1715 JCL_ThrowException (env, IO_EXCEPTION, "truncate not supported");
1716 #endif /* HAVE_FTRUNCATE && HAVE_LSEEK */
1721 * Class: gnu_java_nio_VMChannel
1723 * Signature: (IJJZZ)Z
1725 JNIEXPORT jboolean JNICALL
1726 Java_gnu_java_nio_VMChannel_lock (JNIEnv *env,
1727 jclass c __attribute__((unused)),
1728 jint fd, jlong pos, jlong len,
1729 jboolean shared, jboolean wait)
1734 fl.l_start = (off_t) pos;
1735 /* Long.MAX_VALUE means lock everything possible starting at pos. */
1736 if (len == 9223372036854775807LL)
1739 fl.l_len = (off_t) len;
1740 fl.l_pid = getpid ();
1741 fl.l_type = (shared ? F_RDLCK : F_WRLCK);
1742 fl.l_whence = SEEK_SET;
1744 if (cpnio_fcntl (fd, (wait ? F_SETLKW : F_SETLK), (long) &fl) == -1)
1746 if (errno != EAGAIN)
1747 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1753 JCL_ThrowException (env, IO_EXCEPTION, "lock not supported");
1755 #endif /* HAVE_FCNTL */
1759 * Class: gnu_java_nio_VMChannel
1763 JNIEXPORT void JNICALL
1764 Java_gnu_java_nio_VMChannel_unlock (JNIEnv *env,
1765 jclass c __attribute__((unused)),
1766 jint fd, jlong pos, jlong len)
1771 fl.l_start = (off_t) pos;
1772 fl.l_len = (off_t) len;
1773 fl.l_pid = getpid ();
1774 fl.l_type = F_UNLCK;
1775 fl.l_whence = SEEK_SET;
1777 if (cpnio_fcntl (fd, F_SETLK, (long) &fl) == -1)
1779 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1782 JCL_ThrowException (env, IO_EXCEPTION, "unlock not supported");
1783 #endif /* HAVE_FCNTL */
1787 * Class: gnu_java_nio_VMChannel
1791 JNIEXPORT jlong JNICALL
1792 Java_gnu_java_nio_VMChannel_size (JNIEnv *env,
1793 jclass c __attribute__((unused)),
1799 if (fstat (fd, &st) == -1)
1800 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1802 return (jlong) st.st_size;
1804 JCL_ThrowException (env, IO_EXCEPTION, "size not supported");
1810 * Class: gnu_java_nio_VMChannel
1812 * Signature: (ICJI)Lgnu/classpath/Pointer;
1814 JNIEXPORT jobject JNICALL
1815 Java_gnu_java_nio_VMChannel_map (JNIEnv *env,
1816 jclass clazz __attribute__((unused)),
1817 jint fd, jchar mode, jlong position, jint size)
1820 jclass MappedByteBufferImpl_class;
1821 jmethodID MappedByteBufferImpl_init = NULL;
1822 jobject Pointer_instance;
1823 volatile jobject buffer;
1829 /* NIODBG("fd: %d; mode: %x; position: %lld; size: %d", */
1830 /* fd, mode, position, size); */
1832 /* FIXME: should we just assume we're on an OS modern enough to
1833 have 'sysconf'? And not check for 'getpagesize'? */
1834 #if defined(HAVE_GETPAGESIZE)
1835 pagesize = getpagesize ();
1836 #elif defined(HAVE_SYSCONF)
1837 pagesize = sysconf (_SC_PAGESIZE);
1839 JCL_ThrowException (env, IO_EXCEPTION,
1840 "can't determine memory page size");
1842 #endif /* HAVE_GETPAGESIZE/HAVE_SYSCONF */
1844 if ((*env)->ExceptionOccurred (env))
1850 if (mode == '+' || mode == 'c')
1852 /* When writing we need to make sure the file is big enough,
1853 otherwise the result of mmap is undefined. */
1855 if (fstat (fd, &st) == -1)
1857 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1860 if (position + size > st.st_size)
1862 if (ftruncate(fd, position + size) == -1)
1864 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1871 flags = (mode == 'c' ? MAP_PRIVATE : MAP_SHARED);
1872 p = mmap (NULL, (size_t) ALIGN_UP (size, pagesize), prot, flags,
1873 fd, ALIGN_DOWN (position, pagesize));
1874 if (p == MAP_FAILED)
1876 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1880 /* Unalign the mapped value back up, since we aligned offset
1881 down to a multiple of the page size. */
1882 address = (void *) ((char *) p + (position % pagesize));
1884 Pointer_instance = JCL_NewRawDataObject(env, address);
1886 MappedByteBufferImpl_class = (*env)->FindClass (env,
1887 "java/nio/MappedByteBufferImpl");
1888 if (MappedByteBufferImpl_class != NULL)
1890 MappedByteBufferImpl_init =
1891 (*env)->GetMethodID (env, MappedByteBufferImpl_class,
1892 "<init>", "(Lgnu/classpath/Pointer;IZ)V");
1895 if ((*env)->ExceptionOccurred (env))
1897 munmap (p, ALIGN_UP (size, pagesize));
1900 if (MappedByteBufferImpl_init == NULL)
1902 JCL_ThrowException (env, "java/lang/InternalError",
1903 "could not get MappedByteBufferImpl constructor");
1904 munmap (p, ALIGN_UP (size, pagesize));
1908 buffer = (*env)->NewObject (env, MappedByteBufferImpl_class,
1909 MappedByteBufferImpl_init, Pointer_instance,
1910 (jint) size, mode == 'r');
1917 JCL_ThrowException (env, IO_EXCEPTION,
1918 "memory-mapped files not implemented");
1920 #endif /* HAVE_MMAP */
1924 * Class: gnu_java_nio_VMChannel
1928 JNIEXPORT jboolean JNICALL
1929 Java_gnu_java_nio_VMChannel_flush (JNIEnv *env,
1930 jclass c __attribute__((unused)),
1931 jint fd, jboolean metadata __attribute__((unused)))
1935 if (fsync (fd) == -1)
1937 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1942 JCL_ThrowException (env, IO_EXCEPTION, "flush not implemented");
1944 #endif /* HAVE_FSYNC */