1 /* gnu_java_nio_VMChannel.c -
2 Copyright (C) 2003, 2004, 2005, 2006, 2007 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>
47 #include <sys/socket.h>
51 #include <netinet/in.h>
62 #include "gnu_java_nio_VMChannel.h"
67 #endif /* HAVE_FCNTL_H */
69 #if defined(HAVE_SYS_IOCTL_H)
70 #define BSD_COMP /* Get FIONREAD on Solaris2 */
71 #include <sys/ioctl.h>
73 #if defined(HAVE_SYS_FILIO_H) /* Get FIONREAD on Solaris 2.5 */
74 #include <sys/filio.h>
77 #define CONNECT_EXCEPTION "java/net/ConnectException"
78 #define IO_EXCEPTION "java/io/IOException"
79 #define SOCKET_EXCEPTION "java/net/SocketException"
80 #define INTERRUPTED_IO_EXCEPTION "java/io/InterruptedIOException"
81 #define NON_READABLE_CHANNEL_EXCEPTION "java/nio/channels/NonReadableChannelException"
82 #define NON_WRITABLE_CHANNEL_EXCEPTION "java/nio/channels/NonWritableChannelException"
83 #define SOCKET_TIMEOUT_EXCEPTION "java/net/SocketTimeoutException"
85 /* Align a value up or down to a multiple of the pagesize. */
86 #define ALIGN_DOWN(p,s) ((p) - ((p) % (s)))
87 #define ALIGN_UP(p,s) ((p) + ((s) - ((p) % (s))))
90 * Limit to maximum of 16 buffers
92 #define JCL_IOV_MAX 16
99 enum JCL_buffer_type
{ DIRECT
, HEAP
, ARRAY
, UNKNOWN
};
103 enum JCL_buffer_type type
;
111 jmethodID
get_method_id(JNIEnv
*, jclass
, const char *, const char *);
112 void JCL_print_buffer(JNIEnv
*, struct JCL_buffer
*);
113 int JCL_init_buffer(JNIEnv
*, struct JCL_buffer
*, jobject
);
114 void JCL_release_buffer(JNIEnv
*, struct JCL_buffer
*, jobject
, jint
);
115 void JCL_cleanup_buffers(JNIEnv
*, struct JCL_buffer
*, jint
, jobjectArray
, jint
, jlong
);
116 int JCL_thread_interrupted(JNIEnv
*);
118 static jfieldID address_fid
;
119 static jmethodID get_position_mid
;
120 static jmethodID set_position_mid
;
121 static jmethodID get_limit_mid
;
122 static jmethodID set_limit_mid
;
123 static jmethodID has_array_mid
;
124 static jmethodID array_mid
;
125 static jmethodID array_offset_mid
;
126 static jmethodID thread_interrupted_mid
;
127 static jclass vm_channel_class
;
130 get_method_id(JNIEnv
*env
, jclass clazz
, const char *name
,
133 jmethodID mid
= (*env
)->GetMethodID(env
, clazz
, name
, sig
);
134 /* NIODBG("name: %s; sig: %s", name, sig); */
137 JCL_ThrowException(env
, "java/lang/InternalError", name
);
145 JCL_print_buffer(JNIEnv
*env
__attribute__((__unused__
)), struct JCL_buffer
*buf
)
147 fprintf (stderr
, "Buffer - type: %d, ptr: %p\n", buf
->type
, buf
->ptr
);
152 JCL_init_buffer(JNIEnv
*env
, struct JCL_buffer
*buf
, jobject bbuf
)
154 void *addr
= (*env
)->GetDirectBufferAddress (env
, bbuf
);
156 /* NIODBG("buf: %p; bbuf: %p; addr: %p", (void *) buf, bbuf, addr); */
158 buf
->position
= (*env
)->CallIntMethod(env
, bbuf
, get_position_mid
);
159 buf
->limit
= (*env
)->CallIntMethod(env
, bbuf
, get_limit_mid
);
166 buf
->ptr
= (jbyte
*) addr
;
172 has_array
= (*env
)->CallBooleanMethod(env
, bbuf
, has_array_mid
);
174 if (has_array
== JNI_TRUE
)
177 buf
->offset
= (*env
)->CallIntMethod(env
, bbuf
, array_offset_mid
);
178 arr
= (*env
)->CallObjectMethod(env
, bbuf
, array_mid
);
179 buf
->ptr
= (*env
)->GetByteArrayElements(env
, arr
, 0);
181 (*env
)->DeleteLocalRef(env
, arr
);
185 jobject address
= (*env
)->GetObjectField (env
, bbuf
, address_fid
);
187 return -1; /* XXX handle non-array, non-native buffers? */
188 buf
->ptr
= (jbyte
*) JCL_GetRawData(env
, address
);
190 (*env
)->DeleteLocalRef(env
, address
);
198 JCL_release_buffer(JNIEnv
*env
, struct JCL_buffer
*buf
, jobject bbuf
,
203 /* NIODBG("buf: %p; bbuf: %p; action: %x", (void *) buf, bbuf, action); */
205 /* Set the position to the appropriate value */
209 bbufTemp
= (*env
)->CallObjectMethod(env
, bbuf
, set_position_mid
,
210 buf
->position
+ buf
->count
);
211 (*env
)->DeleteLocalRef(env
, bbufTemp
);
220 arr
= (*env
)->CallObjectMethod(env
, bbuf
, array_mid
);
221 (*env
)->ReleaseByteArrayElements(env
, arr
, buf
->ptr
, action
);
222 (*env
)->DeleteLocalRef(env
, arr
);
225 /* TODO: Handle buffers that are not direct or array backed */
231 JCL_cleanup_buffers(JNIEnv
*env
,
232 struct JCL_buffer
*bi_list
,
240 /* NIODBG("bi_list: %p; vec_len: %d; bbufs: %p; offset: %d; num_bytes: %lld", */
241 /* (void *) bi_list, vec_len, bbufs, offset, num_bytes); */
243 /* Update all of the bbufs with the approriate information */
244 for (i
= 0; i
< vec_len
; i
++)
246 struct JCL_buffer
* buf
;
250 bbuf
= (*env
)->GetObjectArrayElement(env
, bbufs
, offset
+ i
);
252 if (num_bytes
> (buf
->limit
- buf
->position
))
253 buf
->count
= (buf
->limit
- buf
->position
);
255 buf
->count
= num_bytes
;
257 num_bytes
-= buf
->count
;
259 JCL_release_buffer(env
, buf
, bbuf
, JNI_ABORT
);
260 (*env
)->DeleteLocalRef(env
, bbuf
);
266 JCL_thread_interrupted(JNIEnv
*env
)
268 return (int) (*env
)->CallStaticBooleanMethod(env
, vm_channel_class
,
269 thread_interrupted_mid
);
274 * Class: gnu_java_nio_VMChannel
278 JNIEXPORT jint JNICALL
279 Java_gnu_java_nio_VMChannel_stdin_1fd (JNIEnv
*env
__attribute__((unused
)),
280 jclass c
__attribute__((unused
)))
282 /* NIODBG("%d", fileno (stdin)); */
283 return fileno (stdin
);
288 * Class: gnu_java_nio_VMChannel
292 JNIEXPORT jint JNICALL
293 Java_gnu_java_nio_VMChannel_stdout_1fd (JNIEnv
*env
__attribute__((unused
)),
294 jclass c
__attribute__((unused
)))
296 /* NIODBG("%d", fileno (stdout)); */
297 return fileno (stdout
);
302 * Class: gnu_java_nio_VMChannel
306 JNIEXPORT jint JNICALL
307 Java_gnu_java_nio_VMChannel_stderr_1fd (JNIEnv
*env
__attribute__((unused
)),
308 jclass c
__attribute__((unused
)))
310 /* NIODBG("%d", fileno (stderr)); */
311 return fileno (stderr
);
315 JNIEXPORT
void JNICALL
316 Java_gnu_java_nio_VMChannel_initIDs (JNIEnv
*env
,
319 jclass bufferClass
= JCL_FindClass(env
, "java/nio/Buffer");
320 jclass byteBufferClass
= JCL_FindClass(env
, "java/nio/ByteBuffer");
322 /* NIODBG("%s", "..."); */
324 address_fid
= (*env
)->GetFieldID(env
, bufferClass
, "address",
325 "Lgnu/classpath/Pointer;");
326 if (address_fid
== NULL
)
328 JCL_ThrowException(env
, "java/lang/InternalError",
329 "Unable to find internal field");
333 get_position_mid
= get_method_id(env
, bufferClass
, "position", "()I");
334 set_position_mid
= get_method_id(env
, bufferClass
, "position",
335 "(I)Ljava/nio/Buffer;");
336 get_limit_mid
= get_method_id(env
, bufferClass
, "limit", "()I");
337 set_limit_mid
= get_method_id(env
, bufferClass
, "limit",
338 "(I)Ljava/nio/Buffer;");
339 has_array_mid
= get_method_id(env
, byteBufferClass
, "hasArray", "()Z");
340 array_mid
= get_method_id(env
, byteBufferClass
, "array", "()[B");
341 array_offset_mid
= get_method_id(env
, byteBufferClass
, "arrayOffset", "()I");
343 vm_channel_class
= clazz
;
344 thread_interrupted_mid
= (*env
)->GetStaticMethodID(env
, clazz
,
345 "isThreadInterrupted",
349 JNIEXPORT
void JNICALL
350 Java_gnu_java_nio_VMChannel_setBlocking (JNIEnv
*env
,
351 jobject o
__attribute__ ((__unused__
)),
357 /* NIODBG("fd: %d; blocking: %d", fd, blocking); */
359 opts
= fcntl(fd
, F_GETFL
);
362 JCL_ThrowException(env
, IO_EXCEPTION
,
363 "Failed to get flags for file desriptor");
367 if (blocking
== JNI_TRUE
)
368 opts
&= ~(O_NONBLOCK
);
372 opts
= fcntl(fd
, F_SETFL
, opts
);
376 JCL_ThrowException(env
, IO_EXCEPTION
,
377 "Failed to set flags for file desriptor");
382 /* Return true if fd is in non-blocking mode. */
384 is_non_blocking_fd(jint fd
)
387 opts
= fcntl(fd
, F_GETFL
);
390 /* Assume blocking on error. */
393 return (opts
& O_NONBLOCK
) != 0;
396 JNIEXPORT jint JNICALL
397 Java_gnu_java_nio_VMChannel_read__ILjava_nio_ByteBuffer_2 (JNIEnv
*env
,
398 jobject o
__attribute__ ((__unused__
)),
405 struct JCL_buffer buf
;
408 /* NIODBG("fd: %d; bbuf: %p", fd, bbuf); */
410 if (JCL_init_buffer(env
, &buf
, bbuf
) < 0)
412 /* TODO: Rethrown exception */
413 JCL_ThrowException (env
, IO_EXCEPTION
, "Buffer initialisation failed");
417 len
= buf
.limit
- buf
.position
;
421 JCL_release_buffer (env
, &buf
, bbuf
, JNI_ABORT
);
427 result
= cpnio_read (fd
, &(buf
.ptr
[buf
.position
+ buf
.offset
]), len
);
430 while (result
== -1 && errno
== EINTR
&& ! JCL_thread_interrupted(env
));
438 else if (result
== -1)
443 if (is_non_blocking_fd(fd
))
450 /* Read timeout on a socket with SO_RCVTIMEO != 0. */
451 JCL_release_buffer(env
, &buf
, bbuf
, JNI_ABORT
);
452 JCL_ThrowException(env
, SOCKET_TIMEOUT_EXCEPTION
, "read timed out");
456 else if (errno
== EBADF
) /* Bad fd */
458 JCL_release_buffer(env
, &buf
, bbuf
, JNI_ABORT
);
459 JCL_ThrowException (env
, NON_READABLE_CHANNEL_EXCEPTION
,
463 else if (EINTR
== errno
) /* read interrupted */
465 JCL_release_buffer(env
, &buf
, bbuf
, JNI_ABORT
);
466 JCL_ThrowException(env
, INTERRUPTED_IO_EXCEPTION
, strerror (errno
));
471 JCL_release_buffer(env
, &buf
, bbuf
, JNI_ABORT
);
472 JCL_ThrowException (env
, IO_EXCEPTION
, strerror(errno
));
479 JCL_release_buffer(env
, &buf
, bbuf
, 0);
485 JCL_ThrowException (env
, IO_EXCEPTION
, "read not supported");
487 #endif /* HAVE_READ */
490 JNIEXPORT jint JNICALL
491 Java_gnu_java_nio_VMChannel_write__ILjava_nio_ByteBuffer_2 (JNIEnv
*env
,
492 jobject o
__attribute__ ((__unused__
)),
499 struct JCL_buffer buf
;
502 /* NIODBG("fd: %d; bbuf: %p", fd, bbuf); */
504 if (JCL_init_buffer(env
, &buf
, bbuf
) < 0)
506 /* TODO: Rethrown exception */
507 JCL_ThrowException (env
, IO_EXCEPTION
, "Buffer initialisation failed");
511 len
= buf
.limit
- buf
.position
;
515 JCL_release_buffer (env
, &buf
, bbuf
, JNI_ABORT
);
521 result
= cpnio_write (fd
, &(buf
.ptr
[buf
.position
+ buf
.offset
]), len
);
524 while (result
== -1 && errno
== EINTR
&& ! JCL_thread_interrupted(env
));
531 if (errno
== EAGAIN
) /* Non-blocking */
537 JCL_release_buffer(env
, &buf
, bbuf
, JNI_ABORT
);
538 JCL_ThrowException(env
, IO_EXCEPTION
, strerror(errno
));
543 JCL_release_buffer(env
, &buf
, bbuf
, JNI_ABORT
);
549 JCL_ThrowException (env
, IO_EXCEPTION
, "write not supported");
551 #endif /* HAVE_WRITE */
556 * Implementation of a scattering read. Will use the appropriate
557 * vector based read call (currently readv on Linux).
559 * This has a limit to the number of buffers that will be read. It
560 * will not make muliple readv calls. This is to ensure that operations
561 * are atomic. Currently it is limited to 16 buffers. This is for
562 * compatibiliy with Sun.
564 JNIEXPORT jlong JNICALL
565 Java_gnu_java_nio_VMChannel_readScattering (JNIEnv
*env
,
566 jobject o
__attribute__ ((__unused__
)),
573 /* jboolean is_error = JNI_FALSE; */
574 /* char *error_msg; */
575 struct iovec buffers
[JCL_IOV_MAX
];
576 struct JCL_buffer bi_list
[JCL_IOV_MAX
];
578 jint vec_len
= length
< JCL_IOV_MAX
? length
: JCL_IOV_MAX
;
579 jlong bytes_read
= 0;
582 /* NIODBG("fd: %d; bbufs: %p; offset: %d; length: %d", */
583 /* fd, bbufs, offset, length); */
585 /* Build the vector of buffers to read into */
586 for (i
= 0; i
< vec_len
; i
++)
588 struct JCL_buffer
* buf
;
592 bbuf
= (*env
)->GetObjectArrayElement(env
, bbufs
, offset
+ i
);
594 JCL_init_buffer(env
, buf
, bbuf
);
596 /* JCL_print_buffer (env, buf); */
598 buffers
[i
].iov_base
= &(buf
->ptr
[buf
->position
+ buf
->offset
]);
599 buffers
[i
].iov_len
= buf
->limit
- buf
->position
;
600 (*env
)->DeleteLocalRef(env
, bbuf
);
603 /* Work the scattering magic */
606 result
= cpnio_readv (fd
, buffers
, vec_len
);
609 while (result
== -1 && errno
== EINTR
&& ! JCL_thread_interrupted(env
));
611 bytes_read
= (jlong
) result
;
613 /* Handle the response */
618 if (is_non_blocking_fd(fd
))
625 /* Read timeout on a socket with SO_RCVTIMEO != 0. */
626 JCL_cleanup_buffers(env
, bi_list
, vec_len
, bbufs
, offset
, bytes_read
);
627 JCL_ThrowException(env
, SOCKET_TIMEOUT_EXCEPTION
, "read timed out");
631 else if (errno
== EBADF
) /* Bad fd */
633 JCL_cleanup_buffers(env
, bi_list
, vec_len
, bbufs
, offset
, bytes_read
);
634 JCL_ThrowException (env
, NON_READABLE_CHANNEL_EXCEPTION
,
640 JCL_cleanup_buffers(env
, bi_list
, vec_len
, bbufs
, offset
, bytes_read
);
641 JCL_ThrowException (env
, IO_EXCEPTION
, strerror(errno
));
646 else if (result
== 0) /* EOF */
651 JCL_cleanup_buffers(env
, bi_list
, vec_len
, bbufs
, offset
, bytes_read
);
653 return (jlong
) result
;
658 * Implementation of a gathering write. Will use the appropriate
659 * vector based read call (currently readv on Linux).
661 * This has a limit to the number of buffers that will be read. It
662 * will not make muliple readv calls. This is to ensure that operations
663 * are atomic. Currently it is limited to 16 buffers. This is for
664 * compatibiliy with Sun.
666 JNIEXPORT jlong JNICALL
667 Java_gnu_java_nio_VMChannel_writeGathering (JNIEnv
*env
,
668 jobject o
__attribute__ ((__unused__
)),
675 /* jboolean is_error = JNI_FALSE; */
676 /* char *error_msg; */
677 struct iovec buffers
[JCL_IOV_MAX
];
678 struct JCL_buffer bi_list
[JCL_IOV_MAX
];
680 jint vec_len
= length
< JCL_IOV_MAX
? length
: JCL_IOV_MAX
;
684 /* NIODBG("fd: %d; bbufs: %p; offset: %d; length: %d", */
685 /* fd, bbufs, offset, length); */
687 /* Build the vector of buffers to read into */
688 for (i
= 0; i
< vec_len
; i
++)
690 struct JCL_buffer
* buf
;
694 bbuf
= (*env
)->GetObjectArrayElement(env
, bbufs
, offset
+ i
);
696 JCL_init_buffer(env
, buf
, bbuf
);
698 /* JCL_print_buffer(env, buf); */
700 buffers
[i
].iov_base
= &(buf
->ptr
[buf
->position
+ buf
->offset
]);
701 buffers
[i
].iov_len
= buf
->limit
- buf
->position
;
702 (*env
)->DeleteLocalRef(env
, bbuf
);
705 /* Work the gathering magic */
708 result
= cpnio_writev (fd
, buffers
, vec_len
);
711 while (result
== -1 && tmp_errno
== EINTR
&& ! JCL_thread_interrupted(env
));
714 bytes_written
= (jlong
) result
;
719 if (errno
== EAGAIN
) /* Non blocking */
721 else if (errno
== EBADF
) /* Bad fd */
723 JCL_cleanup_buffers(env
, bi_list
, vec_len
, bbufs
, offset
,
725 JCL_ThrowException (env
, NON_WRITABLE_CHANNEL_EXCEPTION
,
731 JCL_cleanup_buffers(env
, bi_list
, vec_len
, bbufs
, offset
,
733 JCL_ThrowException (env
, IO_EXCEPTION
, strerror(errno
));
737 else if (result
== 0) /* EOF?? Does this happen on a write */
740 JCL_cleanup_buffers(env
, bi_list
, vec_len
, bbufs
, offset
, bytes_written
);
741 return (jlong
) result
;
746 * Class: gnu_java_nio_VMChannel
748 * Signature: (Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;)I
750 JNIEXPORT jint JNICALL
751 Java_gnu_java_nio_VMChannel_receive (JNIEnv
*env
,
752 jclass c
__attribute__((unused
)),
753 jint fd
, jobject dst
, jobject addrPort
)
756 char *addrPortPtr
= (*env
)->GetDirectBufferAddress (env
, addrPort
);
757 struct JCL_buffer buf
;
759 struct sockaddr_in6 sock_storage
;
760 struct sockaddr_in6
*sock6
;
761 socklen_t slen
= sizeof (struct sockaddr_in6
);
763 struct sockaddr_in sock_storage
;
764 socklen_t slen
= sizeof (struct sockaddr_in
);
765 #endif /* HAVE_INET6 */
766 struct sockaddr
*sockaddr
= (struct sockaddr
*) &sock_storage
;
767 struct sockaddr_in
*sock4
;
771 if (JCL_init_buffer (env
, &buf
, dst
) == -1)
772 JCL_ThrowException (env
, IO_EXCEPTION
, "loading buffer failed");
774 #ifndef HAVE_MSG_WAITALL
775 #define MSG_WAITALL 0
778 ret
= cpnio_recvfrom (fd
, &(buf
.ptr
[buf
.position
+ buf
.offset
]),
779 buf
.limit
- buf
.position
, MSG_WAITALL
,
784 JCL_release_buffer (env
, &buf
, dst
, JNI_ABORT
);
786 JCL_ThrowException (env
, "java/io/InterruptedIOException", strerror (errno
));
787 else if (EAGAIN
== errno
)
789 /* If the socket is in blocking mode, our timeout expired. */
790 int val
= fcntl (fd
, F_GETFL
, 0);
792 JCL_ThrowException (env
, IO_EXCEPTION
, strerror (errno
));
793 else if ((val
& O_NONBLOCK
) == 0)
794 JCL_ThrowException (env
, "java/net/SocketTimeoutException",
798 JCL_ThrowException (env
, IO_EXCEPTION
, strerror (errno
));
802 if (sockaddr
->sa_family
== AF_INET
)
804 sock4
= (struct sockaddr_in
*) sockaddr
;
805 memcpy (addrPortPtr
, &(sock4
->sin_addr
.s_addr
), 4);
806 ;memcpy (addrPortPtr
+ 4, &(sock4
->sin_port
), 2);
810 else if (sockaddr
->sa_family
== AF_INET6
)
812 sock6
= (struct sockaddr_in6
*) sockaddr
;
813 memcpy (addrPortPtr
, &(sock6
->sin6_addr
.s6_addr
), 16);
814 memcpy (addrPortPtr
+ 16, &(sock6
->sin6_port
), 2);
817 #endif /* HAVE_INET6 */
824 JCL_ThrowException (env
, "java/net/SocketException",
825 "unsupported address type returned");
829 JCL_release_buffer (env
, &buf
, dst
, 0);
835 JCL_ThrowException (env
, IO_EXCEPTION
, "recvfrom not supported");
836 #endif /* HAVE_RECVFROM */
841 * Class: gnu_java_nio_VMChannel
843 * Signature: (Ljava/nio/ByteBuffer;[BI)I
845 JNIEXPORT jint JNICALL
846 Java_gnu_java_nio_VMChannel_send (JNIEnv
*env
,
847 jclass c
__attribute__((unused
)),
848 int fd
, jobject src
, jbyteArray addr
, jint port
)
851 struct sockaddr_in sockaddr
;
853 struct JCL_buffer buf
;
856 /* NIODBG("fd: %d; src: %p; addr: %p; port: %d", */
857 /* fd, src, addr, port); */
859 if (JCL_init_buffer (env
, &buf
, src
) == -1)
861 JCL_ThrowException (env
, IO_EXCEPTION
, "loading buffer failed");
865 /* JCL_print_buffer (env, &buf); */
867 elems
= (*env
)->GetByteArrayElements (env
, addr
, NULL
);
869 sockaddr
.sin_family
= AF_INET
;
870 sockaddr
.sin_addr
.s_addr
= *((uint32_t *) elems
);
871 sockaddr
.sin_port
= htons (port
);
875 ret
= cpnio_sendto (fd
, &(buf
.ptr
[buf
.position
+ buf
.offset
]),
876 buf
.limit
- buf
.position
,
877 0, (const struct sockaddr
*) &sockaddr
,
878 sizeof (struct sockaddr_in
));
880 while (-1 == ret
&& EINTR
== errno
);
882 (*env
)->ReleaseByteArrayElements (env
, addr
, elems
, JNI_ABORT
);
887 JCL_ThrowException (env
, IO_EXCEPTION
, strerror (errno
));
888 JCL_release_buffer (env
, &buf
, src
, JNI_ABORT
);
893 JCL_release_buffer (env
, &buf
, src
, JNI_ABORT
);
900 #endif /* HAVE_SENDTO */
905 * Class: gnu_java_nio_VMChannel
907 * Signature: (Ljava/nio/ByteBuffer;[BI)I
909 JNIEXPORT jint JNICALL
910 Java_gnu_java_nio_VMChannel_send6 (JNIEnv
*env
,
911 jclass c
__attribute__((unused
)),
912 int fd
, jobject src
, jbyteArray addr
, jint port
)
914 #if defined(HAVE_SENDTO) && defined(HAVE_INET6)
915 struct sockaddr_in6 sockaddr
;
917 struct JCL_buffer buf
;
920 /* NIODBG("fd: %d; src: %p; addr: %p; port: %d", */
921 /* fd, src, addr, port); */
923 if (JCL_init_buffer (env
, &buf
, src
) == -1)
925 JCL_ThrowException (env
, IO_EXCEPTION
, "loading buffer failed");
929 /* JCL_print_buffer (env, &buf); */
931 elems
= (*env
)->GetByteArrayElements (env
, addr
, NULL
);
933 sockaddr
.sin6_family
= AF_INET6
;
934 memcpy (&sockaddr
.sin6_addr
.s6_addr
, elems
, 16);
935 sockaddr
.sin6_port
= htons (port
);
939 ret
= cpnio_sendto (fd
, (const void *) (buf
.ptr
+ buf
.offset
),
940 buf
.limit
- buf
.position
,
941 0, (const struct sockaddr
*) &sockaddr
,
942 sizeof (struct sockaddr_in6
));
944 while (-1 == ret
&& EINTR
== errno
);
946 (*env
)->ReleaseByteArrayElements (env
, addr
, elems
, JNI_ABORT
);
951 JCL_ThrowException (env
, IO_EXCEPTION
, strerror (errno
));
952 JCL_release_buffer (env
, &buf
, src
, JNI_ABORT
);
957 JCL_release_buffer (env
, &buf
, src
, JNI_ABORT
);
964 JCL_ThrowException (env
, IO_EXCEPTION
, "IPv6 sendto not supported");
966 #endif /* HAVE_SENDTO && HAVE_INET6 */
971 * Class: gnu_java_nio_VMChannel
975 JNIEXPORT jint JNICALL
976 Java_gnu_java_nio_VMChannel_read__I (JNIEnv
*env
,
977 jclass c
__attribute__((unused
)),
985 /* NIODBG("fd: %d", fd); */
989 ret
= cpnio_read (fd
, &in
, 1);
992 while (ret
== -1 && errno
== EINTR
&& ! JCL_thread_interrupted(env
));
997 if (errno
== EAGAIN
&& !is_non_blocking_fd(fd
))
999 /* Read timeout on a socket with SO_RCVTIMEO != 0. */
1000 JCL_ThrowException(env
, SOCKET_TIMEOUT_EXCEPTION
, "read timed out");
1003 JCL_ThrowException (env
, IO_EXCEPTION
, strerror (errno
));
1013 JCL_ThrowException (env
, IO_EXCEPTION
, "read not supported");
1014 #endif /* HAVE_READ */
1019 * Class: gnu_java_nio_VMChannel
1023 JNIEXPORT
void JNICALL
1024 Java_gnu_java_nio_VMChannel_write__II (JNIEnv
*env
,
1025 jclass c
__attribute__((unused
)),
1029 char out
= (char) data
;
1033 /* NIODBG("fd: %d; data: %d", fd, data); */
1037 ret
= cpnio_write (fd
, &out
, 1);
1040 while (ret
== -1 && errno
== EINTR
&& ! JCL_thread_interrupted(env
));
1044 JCL_ThrowException(env
, IO_EXCEPTION
, strerror (errno
));
1048 JCL_ThrowException (env
, IO_EXCEPTION
, "write not supported");
1049 #endif /* HAVE_WRITE */
1054 * Class: gnu_java_nio_VMChannel
1058 JNIEXPORT jint JNICALL
1059 Java_gnu_java_nio_VMChannel_socket (JNIEnv
*env
, jclass clazz
__attribute__((unused
)),
1067 ret
= cpnio_socket (AF_INET
, stream
? SOCK_STREAM
: SOCK_DGRAM
, 0);
1069 while (-1 == ret
&& EINTR
== errno
);
1072 JCL_ThrowException (env
, "java/net/SocketException", strerror (errno
));
1073 /* NIODBG("created socket %d", ret); */
1078 JCL_ThrowException (env
, IO_EXCEPTION
, "socket not supported");
1080 #endif /* HAVE_SOCKET */
1085 * Class: gnu_java_nio_VMChannel
1087 * Signature: (I[BI)Z
1089 JNIEXPORT jboolean JNICALL
1090 Java_gnu_java_nio_VMChannel_connect (JNIEnv
*env
, jclass clazz
__attribute__((unused
)),
1091 jint fd
, jbyteArray addr
, jint port
, jint timeout
)
1094 struct sockaddr_in sockaddr
;
1095 struct timeval timeo
;
1096 int origflags
= 0, flags
;
1101 if ((*env
)->GetArrayLength (env
, addr
) != 4)
1103 JCL_ThrowException (env
, SOCKET_EXCEPTION
,
1104 "expecting 4-byte address");
1110 timeo
.tv_sec
= timeout
/ 1000;
1111 timeo
.tv_usec
= (timeout
% 1000) * 1000;
1112 origflags
= fcntl (fd
, F_GETFL
, 0);
1113 if (origflags
== -1)
1115 JCL_ThrowException (env
, SOCKET_EXCEPTION
, strerror (errno
));
1118 /* Set nonblocking mode, if not already set. */
1119 if (!(origflags
& O_NONBLOCK
))
1121 flags
= origflags
| O_NONBLOCK
;
1122 if (fcntl (fd
, F_SETFL
, flags
) == -1)
1124 JCL_ThrowException (env
, SOCKET_EXCEPTION
, strerror (errno
));
1130 addr_elems
= (*env
)->GetByteArrayElements (env
, addr
, NULL
);
1132 memset (&sockaddr
, 0, sizeof (struct sockaddr_in
));
1133 sockaddr
.sin_family
= AF_INET
;
1134 sockaddr
.sin_port
= htons (port
);
1135 sockaddr
.sin_addr
.s_addr
= *((uint32_t *) addr_elems
);
1140 ret
= cpnio_connect (fd
, (struct sockaddr
*) &sockaddr
,
1141 sizeof (struct sockaddr_in
));
1144 while (ret
== -1 && errno
== EINTR
&& ! JCL_thread_interrupted(env
));
1147 (*env
)->ReleaseByteArrayElements (env
, addr
, addr_elems
, JNI_ABORT
);
1149 /* If a timeout was specified, select on the file descriptor with
1151 if (timeout
> 0 && ret
== -1)
1153 /* Reset the non-blocking flag, if needed. */
1154 if (!(origflags
& O_NONBLOCK
))
1156 if (fcntl (fd
, F_SETFL
, origflags
) == -1)
1159 JCL_ThrowException (env
, SOCKET_EXCEPTION
, strerror (errno
));
1163 if (EINPROGRESS
== errno
)
1168 ret
= cpnio_select (fd
+ 1, NULL
, &wrfds
, NULL
, &timeo
);
1171 JCL_ThrowException (env
, SOCKET_EXCEPTION
, strerror (errno
));
1174 if (ret
== 0) /* connect timed out */
1176 JCL_ThrowException (env
, SOCKET_TIMEOUT_EXCEPTION
,
1177 "connect timed out");
1180 return JNI_TRUE
; /* Connected! */
1182 else if (ECONNREFUSED
== errno
)
1184 JCL_ThrowException (env
, CONNECT_EXCEPTION
,
1190 JCL_ThrowException (env
, SOCKET_EXCEPTION
, strerror (errno
));
1197 if (EINPROGRESS
== errno
)
1199 else if (ECONNREFUSED
== errno
)
1201 JCL_ThrowException (env
, CONNECT_EXCEPTION
,
1207 JCL_ThrowException (env
, SOCKET_EXCEPTION
, strerror (errno
));
1218 JCL_ThrowException (env
, SOCKET_EXCEPTION
, "connect not supported");
1220 #endif /* HAVE_CONNECT */
1225 * Class: gnu_java_nio_VMChannel
1227 * Signature: (I[BI)Z
1229 JNIEXPORT jboolean JNICALL
1230 Java_gnu_java_nio_VMChannel_connect6 (JNIEnv
*env
, jclass clazz
__attribute__((unused
)),
1231 jint fd
, jbyteArray addr
, jint port
, int timeout
)
1233 #if defined(HAVE_CONNECT) && defined(HAVE_INET6)
1234 struct sockaddr_in6 sockaddr
;
1235 struct timeval timeo
;
1236 int flags
, origflags
= 0;
1242 timeo
.tv_sec
= timeout
/ 1000;
1243 timeo
.tv_usec
= (timeout
% 1000) * 1000;
1244 origflags
= fcntl (fd
, F_GETFL
, 0);
1245 if (origflags
== -1)
1247 JCL_ThrowException (env
, SOCKET_EXCEPTION
, strerror (errno
));
1250 /* Set nonblocking mode, if not already set. */
1251 if (!(origflags
& O_NONBLOCK
))
1253 flags
= origflags
| O_NONBLOCK
;
1254 if (fcntl (fd
, F_SETFL
, flags
) == -1)
1256 JCL_ThrowException (env
, SOCKET_EXCEPTION
, strerror (errno
));
1262 addr_elems
= (*env
)->GetByteArrayElements (env
, addr
, NULL
);
1264 memset (&sockaddr
, 0, sizeof (struct sockaddr_in6
));
1265 sockaddr
.sin6_family
= AF_INET6
;
1266 sockaddr
.sin6_port
= htons (port
);
1267 memcpy (&sockaddr
.sin6_addr
.s6_addr
, addr_elems
, 16);
1269 ret
= cpnio_connect (fd
, (struct sockaddr
*) &sockaddr
,
1270 sizeof (struct sockaddr_in6
));
1272 (*env
)->ReleaseByteArrayElements (env
, addr
, addr_elems
, JNI_ABORT
);
1274 /* If a timeout was specified, select on the file descriptor with
1276 if (timeout
> 0 && ret
== -1)
1278 /* Reset the non-blocking flag, if needed. */
1279 if (!(origflags
& O_NONBLOCK
))
1281 if (fcntl (fd
, F_SETFL
, origflags
) == -1)
1284 JCL_ThrowException (env
, SOCKET_EXCEPTION
, strerror (errno
));
1288 if (EINPROGRESS
== errno
)
1293 ret
= cpnio_select (fd
+ 1, NULL
, &wrfds
, NULL
, &timeo
);
1296 JCL_ThrowException (env
, SOCKET_EXCEPTION
, strerror (errno
));
1299 if (ret
== 0) /* connect timed out */
1301 JCL_ThrowException (env
, SOCKET_TIMEOUT_EXCEPTION
,
1302 "connect timed out");
1305 return JNI_TRUE
; /* Connected! */
1307 else if (ECONNREFUSED
== errno
)
1309 JCL_ThrowException (env
, CONNECT_EXCEPTION
,
1315 JCL_ThrowException (env
, SOCKET_EXCEPTION
, strerror (errno
));
1322 if (EAGAIN
== errno
)
1324 else if (ECONNREFUSED
== errno
)
1326 JCL_ThrowException (env
, CONNECT_EXCEPTION
,
1332 JCL_ThrowException (env
, SOCKET_EXCEPTION
, strerror (errno
));
1343 JCL_ThrowException (env
, SOCKET_EXCEPTION
, "IPv6 connect not supported");
1345 #endif /* HAVE_CONNECT && HAVE_INET6 */
1350 * Class: gnu_java_nio_VMChannel
1351 * Method: getsockname
1352 * Signature: (ILjava/nio/ByteBuffer;)I
1354 JNIEXPORT jint JNICALL
1355 Java_gnu_java_nio_VMChannel_getsockname (JNIEnv
*env
, jclass clazz
__attribute__((unused
)),
1356 jint fd
, jobject name
)
1358 #ifdef HAVE_GETSOCKNAME
1360 struct sockaddr_in6
*addr6
;
1361 struct sockaddr_in6 sock_storage
;
1362 socklen_t socklen
= sizeof (struct sockaddr_in6
);
1364 struct sockaddr_in sock_storage
;
1365 socklen_t socklen
= sizeof (struct sockaddr_in
);
1366 #endif /* HAVE_INET6 */
1368 struct sockaddr
*sockaddr
= (struct sockaddr
*) &sock_storage
;
1369 struct sockaddr_in
*addr4
;
1371 char *nameptr
= (*env
)->GetDirectBufferAddress (env
, name
);
1373 ret
= getsockname (fd
, sockaddr
, &socklen
);
1376 JCL_ThrowException (env
, "java/net/SocketException", strerror (errno
));
1380 if (sockaddr
->sa_family
== AF_INET
)
1382 addr4
= (struct sockaddr_in
*) sockaddr
;
1383 memcpy (nameptr
, &(addr4
->sin_addr
.s_addr
), 4);
1384 memcpy (nameptr
+ 4, &(addr4
->sin_port
), 2);
1390 if (sockaddr
->sa_family
== AF_INET6
)
1392 addr6
= (struct sockaddr_in6
*) sockaddr
;
1393 memcpy (nameptr
, &(addr6
->sin6_addr
.s6_addr
), 16);
1394 memcpy (nameptr
+ 16, &(addr6
->sin6_port
), 2);
1397 #endif /* HAVE_INET6 */
1398 JCL_ThrowException (env
, IO_EXCEPTION
, "unsupported address format");
1403 JCL_ThrowException (env
, IO_EXCEPTION
, "getsockname not supported");
1405 #endif /* HAVE_GETSOCKNAME */
1410 * Class: gnu_java_nio_VMChannel
1411 * Method: getpeername
1412 * Signature: (ILjava/nio/ByteBuffer;)I
1414 JNIEXPORT jint JNICALL
1415 Java_gnu_java_nio_VMChannel_getpeername (JNIEnv
*env
, jclass clazz
__attribute__((unused
)),
1416 jint fd
, jobject name
)
1418 #ifdef HAVE_GETPEERNAME
1420 struct sockaddr_in6
*addr6
;
1421 struct sockaddr_in6 sock_storage
;
1422 socklen_t socklen
= sizeof (struct sockaddr_in6
);
1424 struct sockaddr_in sock_storage
;
1425 socklen_t socklen
= sizeof (struct sockaddr_in
);
1426 #endif /* HAVE_INET6 */
1428 struct sockaddr
*sockaddr
= (struct sockaddr
*) &sock_storage
;
1429 struct sockaddr_in
*addr4
;
1431 char *nameptr
= (*env
)->GetDirectBufferAddress (env
, name
);
1433 ret
= getpeername (fd
, sockaddr
, &socklen
);
1436 if (ENOTCONN
!= errno
)
1437 JCL_ThrowException (env
, "java/net/SocketException", strerror (errno
));
1441 if (sockaddr
->sa_family
== AF_INET
)
1443 addr4
= (struct sockaddr_in
*) sockaddr
;
1444 memcpy (nameptr
, &(addr4
->sin_addr
.s_addr
), 4);
1445 memcpy (nameptr
+ 4, &(addr4
->sin_port
), 2);
1449 else if (sockaddr
->sa_family
== AF_INET6
)
1451 addr6
= (struct sockaddr_in6
*) sockaddr
;
1452 memcpy (nameptr
, &(addr6
->sin6_addr
.s6_addr
), 16);
1453 memcpy (nameptr
+ 16, &(addr6
->sin6_port
), 2);
1456 #endif /* HAVE_INET6 */
1458 JCL_ThrowException (env
, "java/net/SocketException",
1459 "unsupported address type");
1464 JCL_ThrowException (env
, IO_EXCEPTION
, "getpeername not supported");
1466 #endif /* HAVE_GETPEERNAME */
1471 * Class: gnu_java_nio_VMChannel
1475 JNIEXPORT jint JNICALL
1476 Java_gnu_java_nio_VMChannel_accept (JNIEnv
*env
,
1477 jclass c
__attribute__((unused
)),
1485 struct sockaddr_in6 addr
;
1486 socklen_t alen
= sizeof (struct sockaddr_in6
);
1488 struct sockaddr_in addr
;
1489 socklen_t alen
= sizeof (struct sockaddr_in
);
1490 #endif /* HAVE_INET6 */
1494 ret
= cpnio_accept (fd
, (struct sockaddr
*) &addr
, &alen
);
1501 /* Check if interrupted by Thread.interrupt(). If not then some
1502 * other unrelated signal interrupted the system function and
1503 * we should start over again.
1505 if (JCL_thread_interrupted(env
))
1507 JCL_ThrowException (env
, "java/net/SocketException", strerror (tmp_errno
));
1511 #if defined(EWOULDBLOCK) && defined(EAGAIN) && EWOULDBLOCK != EAGAIN
1515 if (!is_non_blocking_fd(fd
))
1517 JCL_ThrowException(env
, SOCKET_TIMEOUT_EXCEPTION
, "Accept timed out");
1519 /* Socket in non-blocking mode and no pending connection. */
1522 JCL_ThrowException (env
, "java/net/SocketException", strerror (tmp_errno
));
1530 cpio_closeOnExec(ret
);
1535 JCL_ThrowException (env
, IO_EXCEPTION
, "accept not supported");
1537 #endif /* HAVE_ACCEPT */
1543 * Class: gnu_java_nio_VMChannel
1544 * Method: disconnect
1547 JNIEXPORT
void JNICALL
1548 Java_gnu_java_nio_VMChannel_disconnect (JNIEnv
*env
,
1549 jclass c
__attribute__((unused
)),
1552 struct sockaddr sockaddr
;
1554 sockaddr
.sa_family
= AF_UNSPEC
;
1555 if (connect (fd
, &sockaddr
, sizeof (struct sockaddr
)) == -1)
1557 /* The expected error for a successful disconnect is EAFNOSUPPORT. */
1558 if (errno
!= EAFNOSUPPORT
)
1559 JCL_ThrowException (env
, IO_EXCEPTION
, strerror (errno
));
1565 * Class: gnu_java_nio_VMChannel
1569 JNIEXPORT
void JNICALL
1570 Java_gnu_java_nio_VMChannel_close (JNIEnv
*env
,
1571 jclass c
__attribute__((unused
)),
1574 if (close (fd
) == -1)
1575 JCL_ThrowException (env
, IO_EXCEPTION
, strerror (errno
));
1580 * Class: gnu_java_nio_VMChannel
1584 JNIEXPORT jint JNICALL
1585 Java_gnu_java_nio_VMChannel_available (JNIEnv
*env
,
1586 jclass c
__attribute__((unused
)),
1589 #if defined (FIONREAD)
1593 #if defined(ENOTTY) && defined(HAVE_FSTAT)
1594 struct stat statBuffer
;
1598 /* NIODBG("fd: %d", fd); */
1599 if (ioctl (fd
, FIONREAD
, &avail
) == -1)
1601 #if defined(ENOTTY) && defined(HAVE_FSTAT)
1602 if (errno
== ENOTTY
)
1604 if ((fstat (fd
, &statBuffer
) == 0) && S_ISREG (statBuffer
.st_mode
))
1606 n
= lseek (fd
, 0, SEEK_CUR
);
1609 avail
= statBuffer
.st_size
- n
;
1615 JCL_ThrowException (env
, IO_EXCEPTION
, strerror (errno
));
1617 /* NIODBG("avail: %d", avail); */
1621 #elif defined(HAVE_FSTAT)
1625 struct stat statBuffer
;
1628 if ((fstat (fd
, &statBuffer
) == 0) && S_ISREG (statBuffer
.st_mode
))
1630 n
= lseek (fd
, 0, SEEK_CUR
);
1633 avail
= statBuffer
.st_size
- n
;
1637 JCL_ThrowException (env
, IO_EXCEPTION
, strerror (errno
));
1639 #elif defined(HAVE_SELECT)
1642 fd_set filedescriptset
;
1645 FD_ZERO (&filedescriptset
);
1646 FD_SET (fd
,&filedescriptset
);
1647 memset (&tv
, 0, sizeof(tv
));
1649 switch (select (fd
+1, &filedescriptset
, NULL
, NULL
, &tv
))
1660 JCL_ThrowException (env
, IO_EXCEPTION
, strerror (errno
));
1664 JCL_ThrowException (env
, IO_EXCEPTION
, "No native method for available");
1670 enum FileChannel_mode
{
1681 * Class: gnu_java_nio_VMChannel
1683 * Signature: (Ljava/lang/String;I)I
1685 JNIEXPORT jint JNICALL
1686 Java_gnu_java_nio_VMChannel_open (JNIEnv
*env
,
1687 jclass c
__attribute__((unused
)),
1688 jstring path
, jint mode
)
1694 if ((mode
& CPNIO_READ
) && (mode
& CPNIO_WRITE
))
1696 else if (mode
& CPNIO_WRITE
)
1702 | ((nmode
== O_RDWR
|| nmode
== O_WRONLY
) ? O_CREAT
: 0)
1703 | ((mode
& CPNIO_APPEND
) ? O_APPEND
:
1704 ((nmode
== O_WRONLY
) ? O_TRUNC
: 0))
1705 | ((mode
& CPNIO_EXCL
) ? O_EXCL
: 0)
1706 | ((mode
& CPNIO_SYNC
) ? O_SYNC
: 0));
1708 npath
= JCL_jstring_to_cstring (env
, path
);
1710 /* NIODBG("path: %s; mode: %x", npath, nmode); */
1712 ret
= open (npath
, nmode
, 0666);
1714 /* NIODBG("ret: %d\n", ret); */
1716 JCL_free_cstring (env
, path
, npath
);
1719 JCL_ThrowException (env
, IO_EXCEPTION
, strerror (errno
));
1726 * Class: gnu_java_nio_VMChannel
1730 JNIEXPORT jlong JNICALL
1731 Java_gnu_java_nio_VMChannel_position (JNIEnv
*env
,
1732 jclass c
__attribute__((unused
)),
1738 ret
= lseek (fd
, 0, SEEK_CUR
);
1741 JCL_ThrowException (env
, IO_EXCEPTION
, strerror (errno
));
1745 JCL_ThrowException (env
, IO_EXCEPTION
, "position not supported");
1747 #endif /* HAVE_LSEEK */
1752 * Class: gnu_java_nio_VMChannel
1756 JNIEXPORT
void JNICALL
1757 Java_gnu_java_nio_VMChannel_seek (JNIEnv
*env
,
1758 jclass c
__attribute__((unused
)),
1762 if (lseek (fd
, (off_t
) pos
, SEEK_SET
) == -1)
1763 JCL_ThrowException (env
, IO_EXCEPTION
, strerror (errno
));
1765 JCL_ThrowException (env
, IO_EXCEPTION
, "seek not supported");
1766 #endif /* HAVE_LSEEK */
1771 * Class: gnu_java_nio_VMChannel
1775 JNIEXPORT
void JNICALL
1776 Java_gnu_java_nio_VMChannel_truncate (JNIEnv
*env
,
1777 jclass c
__attribute__((unused
)),
1780 #if defined(HAVE_FTRUNCATE) && defined(HAVE_LSEEK)
1781 off_t pos
= lseek (fd
, 0, SEEK_CUR
);
1784 JCL_ThrowException (env
, IO_EXCEPTION
, strerror (errno
));
1787 if (ftruncate (fd
, (off_t
) len
) == -1)
1789 JCL_ThrowException (env
, IO_EXCEPTION
, strerror (errno
));
1794 if (lseek (fd
, len
, SEEK_SET
) == -1)
1795 JCL_ThrowException (env
, IO_EXCEPTION
, strerror (errno
));
1798 JCL_ThrowException (env
, IO_EXCEPTION
, "truncate not supported");
1799 #endif /* HAVE_FTRUNCATE && HAVE_LSEEK */
1804 * Class: gnu_java_nio_VMChannel
1806 * Signature: (IJJZZ)Z
1808 JNIEXPORT jboolean JNICALL
1809 Java_gnu_java_nio_VMChannel_lock (JNIEnv
*env
,
1810 jclass c
__attribute__((unused
)),
1811 jint fd
, jlong pos
, jlong len
,
1812 jboolean shared
, jboolean wait
)
1817 fl
.l_start
= (off_t
) pos
;
1818 /* Long.MAX_VALUE means lock everything possible starting at pos. */
1819 if (len
== 9223372036854775807LL)
1822 fl
.l_len
= (off_t
) len
;
1823 fl
.l_pid
= getpid ();
1824 fl
.l_type
= (shared
? F_RDLCK
: F_WRLCK
);
1825 fl
.l_whence
= SEEK_SET
;
1827 if (cpnio_fcntl (fd
, (wait
? F_SETLKW
: F_SETLK
), (long) &fl
) == -1)
1829 if (errno
!= EAGAIN
)
1830 JCL_ThrowException (env
, IO_EXCEPTION
, strerror (errno
));
1836 JCL_ThrowException (env
, IO_EXCEPTION
, "lock not supported");
1838 #endif /* HAVE_FCNTL */
1842 * Class: gnu_java_nio_VMChannel
1846 JNIEXPORT
void JNICALL
1847 Java_gnu_java_nio_VMChannel_unlock (JNIEnv
*env
,
1848 jclass c
__attribute__((unused
)),
1849 jint fd
, jlong pos
, jlong len
)
1854 fl
.l_start
= (off_t
) pos
;
1855 fl
.l_len
= (off_t
) len
;
1856 fl
.l_pid
= getpid ();
1857 fl
.l_type
= F_UNLCK
;
1858 fl
.l_whence
= SEEK_SET
;
1860 if (cpnio_fcntl (fd
, F_SETLK
, (long) &fl
) == -1)
1862 JCL_ThrowException (env
, IO_EXCEPTION
, strerror (errno
));
1865 JCL_ThrowException (env
, IO_EXCEPTION
, "unlock not supported");
1866 #endif /* HAVE_FCNTL */
1870 * Class: gnu_java_nio_VMChannel
1874 JNIEXPORT jlong JNICALL
1875 Java_gnu_java_nio_VMChannel_size (JNIEnv
*env
,
1876 jclass c
__attribute__((unused
)),
1882 if (fstat (fd
, &st
) == -1)
1883 JCL_ThrowException (env
, IO_EXCEPTION
, strerror (errno
));
1885 return (jlong
) st
.st_size
;
1887 JCL_ThrowException (env
, IO_EXCEPTION
, "size not supported");
1893 * Class: gnu_java_nio_VMChannel
1895 * Signature: (ICJI)Lgnu/classpath/Pointer;
1897 JNIEXPORT jobject JNICALL
1898 Java_gnu_java_nio_VMChannel_map (JNIEnv
*env
,
1899 jclass clazz
__attribute__((unused
)),
1900 jint fd
, jchar mode
, jlong position
, jint size
)
1903 jclass MappedByteBufferImpl_class
;
1904 jmethodID MappedByteBufferImpl_init
= NULL
;
1905 jobject Pointer_instance
;
1906 volatile jobject buffer
;
1912 /* NIODBG("fd: %d; mode: %x; position: %lld; size: %d", */
1913 /* fd, mode, position, size); */
1915 /* FIXME: should we just assume we're on an OS modern enough to
1916 have 'sysconf'? And not check for 'getpagesize'? */
1917 #if defined(HAVE_GETPAGESIZE)
1918 pagesize
= getpagesize ();
1919 #elif defined(HAVE_SYSCONF)
1920 pagesize
= sysconf (_SC_PAGESIZE
);
1922 JCL_ThrowException (env
, IO_EXCEPTION
,
1923 "can't determine memory page size");
1925 #endif /* HAVE_GETPAGESIZE/HAVE_SYSCONF */
1927 if ((*env
)->ExceptionOccurred (env
))
1933 if (mode
== '+' || mode
== 'c')
1935 /* When writing we need to make sure the file is big enough,
1936 otherwise the result of mmap is undefined. */
1938 if (fstat (fd
, &st
) == -1)
1940 JCL_ThrowException (env
, IO_EXCEPTION
, strerror (errno
));
1943 if (position
+ size
> st
.st_size
)
1945 if (ftruncate(fd
, position
+ size
) == -1)
1947 JCL_ThrowException (env
, IO_EXCEPTION
, strerror (errno
));
1954 flags
= (mode
== 'c' ? MAP_PRIVATE
: MAP_SHARED
);
1955 p
= mmap (NULL
, (size_t) ALIGN_UP (size
, pagesize
), prot
, flags
,
1956 fd
, ALIGN_DOWN (position
, pagesize
));
1957 if (p
== MAP_FAILED
)
1959 JCL_ThrowException (env
, IO_EXCEPTION
, strerror (errno
));
1963 /* Unalign the mapped value back up, since we aligned offset
1964 down to a multiple of the page size. */
1965 address
= (void *) ((char *) p
+ (position
% pagesize
));
1967 Pointer_instance
= JCL_NewRawDataObject(env
, address
);
1969 MappedByteBufferImpl_class
= (*env
)->FindClass (env
,
1970 "java/nio/MappedByteBufferImpl");
1971 if (MappedByteBufferImpl_class
!= NULL
)
1973 MappedByteBufferImpl_init
=
1974 (*env
)->GetMethodID (env
, MappedByteBufferImpl_class
,
1975 "<init>", "(Lgnu/classpath/Pointer;IZ)V");
1978 if ((*env
)->ExceptionOccurred (env
))
1980 munmap (p
, ALIGN_UP (size
, pagesize
));
1983 if (MappedByteBufferImpl_init
== NULL
)
1985 JCL_ThrowException (env
, "java/lang/InternalError",
1986 "could not get MappedByteBufferImpl constructor");
1987 munmap (p
, ALIGN_UP (size
, pagesize
));
1991 buffer
= (*env
)->NewObject (env
, MappedByteBufferImpl_class
,
1992 MappedByteBufferImpl_init
, Pointer_instance
,
1993 (jint
) size
, mode
== 'r');
2000 JCL_ThrowException (env
, IO_EXCEPTION
,
2001 "memory-mapped files not implemented");
2003 #endif /* HAVE_MMAP */
2007 * Class: gnu_java_nio_VMChannel
2011 JNIEXPORT jboolean JNICALL
2012 Java_gnu_java_nio_VMChannel_flush (JNIEnv
*env
,
2013 jclass c
__attribute__((unused
)),
2014 jint fd
, jboolean metadata
__attribute__((unused
)))
2018 if (fsync (fd
) == -1)
2020 JCL_ThrowException (env
, IO_EXCEPTION
, strerror (errno
));
2025 JCL_ThrowException (env
, IO_EXCEPTION
, "flush not implemented");
2027 #endif /* HAVE_FSYNC */