1 /* gnu_java_nio_channels_FileChannelImpl.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. */
38 /* do not move; needed here because of some macro definitions */
47 #include "target_native.h"
48 #ifndef WITHOUT_FILESYSTEM
49 #include "target_native_file.h"
51 #include "target_native_math_int.h"
53 #include "gnu_java_nio_channels_FileChannelImpl.h"
57 #endif /* HAVE_FCNTL_H */
59 #ifdef HAVE_SYS_MMAN_H
61 #endif /* HAVE_SYS_MMAN_H */
63 /* These values must be kept in sync with FileChannelImpl.java. */
64 #define FILECHANNELIMPL_READ 1
65 #define FILECHANNELIMPL_WRITE 2
66 #define FILECHANNELIMPL_APPEND 4
68 /* These values must be kept in sync with FileChannelImpl.java. */
69 /* #define FILECHANNELIMPL_FILESEEK_SET 0 */
70 /* #define FILECHANNELIMPL_FILESEEK_CUR 1 */
71 /* #define FILECHANNELIMPL_FILESEEK_END 2 */
73 #define FILECHANNELIMPL_FILEOPEN_FLAG_READ 1
74 #define FILECHANNELIMPL_FILEOPEN_FLAG_WRITE 2
75 #define FILECHANNELIMPL_FILEOPEN_FLAG_APPEND 4
76 #define FILECHANNELIMPL_FILEOPEN_FLAG_EXCL 8
77 #define FILECHANNELIMPL_FILEOPEN_FLAG_SYNC 16
78 #define FILECHANNELIMPL_FILEOPEN_FLAG_DSYNC 32
80 #define IO_EXCEPTION "java/io/IOException"
82 /* FIXME: This can't be right. Need converter macros. */
83 #define CONVERT_JLONG_TO_INT(x) TARGET_NATIVE_MATH_INT_INT64_TO_INT32(x)
84 #define CONVERT_INT_TO_JLONG(x) TARGET_NATIVE_MATH_INT_INT32_TO_INT64(x)
86 /* FIXME: This can't be right. Need converter macros. */
87 #define CONVERT_JLONG_TO_OFF_T(x) TARGET_NATIVE_MATH_INT_INT64_TO_INT32(x)
88 #define CONVERT_OFF_T_TO_JLONG(x) TARGET_NATIVE_MATH_INT_INT32_TO_INT64(x)
90 /* FIXME: This can't be right. Need converter macros */
91 #define CONVERT_JINT_TO_INT(x) ((int)(x & 0xFFFFFFFF))
92 #define CONVERT_INT_TO_JINT(x) ((int)(x & 0xFFFFFFFF))
94 /* FIXME: This can't be right. Need converter macros. */
95 #define CONVERT_SSIZE_T_TO_JINT(x) ((jint)(x & 0xFFFFFFFF))
96 #define CONVERT_JINT_TO_SSIZE_T(x) (x)
98 /* Align a value up or down to a multiple of the pagesize. */
99 #define ALIGN_DOWN(p,s) ((p) - ((p) % (s)))
100 #define ALIGN_UP(p,s) ((p) + ((s) - ((p) % (s))))
102 /* cached fieldID of gnu.java.nio.channels.FileChannelImpl.fd */
103 static jfieldID native_fd_fieldID;
106 get_native_fd (JNIEnv * env, jobject obj)
108 return (*env)->GetIntField (env, obj, native_fd_fieldID);
112 * Library initialization routine. Called as part of java.io.FileDescriptor
113 * static initialization.
115 JNIEXPORT void JNICALL
116 Java_gnu_java_nio_channels_FileChannelImpl_init (JNIEnv * env,
118 __attribute__ ((__unused__)))
123 /* Initialize native_fd_fieldID so we only compute it once! */
124 clazz_fc = (*env)->FindClass (env, "gnu/java/nio/channels/FileChannelImpl");
127 JCL_ThrowException (env, IO_EXCEPTION, "Internal error");
131 field = (*env)->GetFieldID (env, clazz_fc, "fd", "I");
134 JCL_ThrowException (env, IO_EXCEPTION, "Internal error");
138 native_fd_fieldID = field;
142 * Open the specified file and return a native file descriptor
144 JNIEXPORT jint JNICALL
145 Java_gnu_java_nio_channels_FileChannelImpl_open (JNIEnv * env,
147 __attribute__ ((__unused__)),
148 jstring name, jint mode)
150 const char *filename;
156 filename = JCL_jstring_to_cstring (env, name);
157 if (filename == NULL)
158 return (-1); /* Exception will already have been thrown */
160 /* get file/permission flags for open() */
161 if ((mode & FILECHANNELIMPL_FILEOPEN_FLAG_READ)
162 && (mode & FILECHANNELIMPL_FILEOPEN_FLAG_WRITE))
166 TARGET_NATIVE_FILE_FILEFLAG_CREATE |
167 TARGET_NATIVE_FILE_FILEFLAG_READWRITE;
168 permissions = TARGET_NATIVE_FILE_FILEPERMISSION_NORMAL;
170 else if ((mode & FILECHANNELIMPL_FILEOPEN_FLAG_READ))
173 flags = TARGET_NATIVE_FILE_FILEFLAG_READ;
174 permissions = TARGET_NATIVE_FILE_FILEPERMISSION_NORMAL;
180 TARGET_NATIVE_FILE_FILEFLAG_CREATE |
181 TARGET_NATIVE_FILE_FILEFLAG_WRITE;
182 if ((mode & FILECHANNELIMPL_FILEOPEN_FLAG_APPEND))
184 flags |= TARGET_NATIVE_FILE_FILEFLAG_APPEND;
188 flags |= TARGET_NATIVE_FILE_FILEFLAG_TRUNCATE;
190 permissions = TARGET_NATIVE_FILE_FILEPERMISSION_NORMAL;
193 if ((mode & FILECHANNELIMPL_FILEOPEN_FLAG_SYNC))
195 flags |= TARGET_NATIVE_FILE_FILEFLAG_SYNC;
198 if ((mode & FILECHANNELIMPL_FILEOPEN_FLAG_DSYNC))
200 flags |= TARGET_NATIVE_FILE_FILEFLAG_DSYNC;
203 flags |= TARGET_NATIVE_FILE_FILEFLAG_BINARY;
206 TARGET_NATIVE_FILE_OPEN (filename, native_fd, flags, permissions, result);
208 if (result != TARGET_NATIVE_OK)
210 char message[256]; /* Fixed size we don't need to malloc. */
211 char *error_string = TARGET_NATIVE_LAST_ERROR_STRING ();
213 snprintf(message, 256, "%s: %s", error_string, filename);
214 /* We are only allowed to throw FileNotFoundException. */
215 JCL_ThrowException (env,
216 "java/io/FileNotFoundException",
218 JCL_free_cstring (env, name, filename);
219 return TARGET_NATIVE_MATH_INT_INT64_CONST_MINUS_1;
222 JCL_free_cstring (env, name, filename);
227 * Closes the specified file descriptor and return status code.
230 JNIEXPORT void JNICALL
231 Java_gnu_java_nio_channels_FileChannelImpl_implCloseChannel (JNIEnv * env,
237 native_fd = get_native_fd (env, obj);
241 TARGET_NATIVE_FILE_CLOSE (native_fd, result);
242 if (result != TARGET_NATIVE_OK
243 && (TARGET_NATIVE_LAST_ERROR ()
244 != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL))
246 JCL_ThrowException (env, IO_EXCEPTION,
247 TARGET_NATIVE_LAST_ERROR_STRING ());
251 while (result != TARGET_NATIVE_OK);
255 * Return number of bytes that can be read from the file w/o blocking.
258 JNIEXPORT jint JNICALL
259 Java_gnu_java_nio_channels_FileChannelImpl_available (JNIEnv * env,
263 jlong bytes_available;
266 native_fd = get_native_fd (env, obj);
270 TARGET_NATIVE_FILE_AVAILABLE (native_fd, bytes_available, result);
271 if (result != TARGET_NATIVE_OK
272 && (TARGET_NATIVE_LAST_ERROR ()
273 != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL))
275 JCL_ThrowException (env, IO_EXCEPTION,
276 TARGET_NATIVE_LAST_ERROR_STRING ());
280 while (result != TARGET_NATIVE_OK);
282 /* FIXME NYI ??? why only jint and not jlong? */
283 return TARGET_NATIVE_MATH_INT_INT64_TO_INT32 (bytes_available);
286 JNIEXPORT jlong JNICALL
287 Java_gnu_java_nio_channels_FileChannelImpl_size (JNIEnv * env, jobject obj)
293 native_fd = get_native_fd (env, obj);
295 TARGET_NATIVE_FILE_SIZE (native_fd, file_size, result);
296 if (result != TARGET_NATIVE_OK)
298 JCL_ThrowException (env, IO_EXCEPTION,
299 TARGET_NATIVE_LAST_ERROR_STRING ());
300 return TARGET_NATIVE_MATH_INT_INT64_CONST_MINUS_1;
307 * Return the current position of the file pointer
310 JNIEXPORT jlong JNICALL
311 Java_gnu_java_nio_channels_FileChannelImpl_implPosition (JNIEnv * env,
315 jlong current_offset;
318 native_fd = get_native_fd (env, obj);
320 TARGET_NATIVE_FILE_TELL (native_fd, current_offset, result);
321 if (result != TARGET_NATIVE_OK)
323 JCL_ThrowException (env, IO_EXCEPTION,
324 TARGET_NATIVE_LAST_ERROR_STRING ());
325 return TARGET_NATIVE_MATH_INT_INT64_CONST_MINUS_1;
328 return current_offset;
332 * Wrapper around lseek call. Return new file position
335 JNIEXPORT void JNICALL
336 Java_gnu_java_nio_channels_FileChannelImpl_seek (JNIEnv * env, jobject obj,
343 native_fd = get_native_fd (env, obj);
346 /* Should there be such an exception? All native layer macros should
347 be accepting 64bit-values if needed. It some target is not able
348 to handle such values it should simply operate with 32bit-values
349 and convert 64bit-values appriopated. In this case I assume
350 problems should not occurre: if some specific target is not able
351 to handle 64bit-values the system is limited to 32bit at all, thus
352 the application can not do a seek() or something else beyond the
353 32bit limit. It this true?
356 /* FIXME: What do we do if offset > the max value of off_t on this 32bit
357 * system? How do we detect that and what do we do? */
358 if (CONVERT_OFF_T_TO_JLONG (native_offset) != offset)
360 JCL_ThrowException (env, IO_EXCEPTION,
361 "Cannot represent position correctly on this system");
365 result = TARGET_NATIVE_ERROR;
366 new_offset = TARGET_NATIVE_MATH_INT_INT64_CONST_MINUS_1;
367 TARGET_NATIVE_FILE_SEEK_BEGIN (native_fd, offset, new_offset, result);
369 if (result != TARGET_NATIVE_OK)
371 JCL_ThrowException (env, IO_EXCEPTION,
372 TARGET_NATIVE_LAST_ERROR_STRING ());
377 * Set the length of the file
380 JNIEXPORT void JNICALL
381 Java_gnu_java_nio_channels_FileChannelImpl_implTruncate (JNIEnv * env,
388 jlong save_offset, new_offset;
392 native_fd = get_native_fd (env, obj);
395 /* Should there be such an exception? All native layer macros should
396 be accepting 64bit-values if needed. It some target is not able
397 to handle such values it should simply operate with 32bit-values
398 and convert 64bit-values appriopated. In this case I assume
399 problems should not occurre: if some specific target is not able
400 to handle 64bit-values the system is limited to 32bit at all, thus
401 the application can not do a seek() or something else beyond the
402 32bit limit. It this true?
405 /* FIXME: What do we do if len > the max value of off_t on this 32bit
406 * system? How do we detect that and what do we do? */
407 if (CONVERT_OFF_T_TO_JLONG (native_len) != len)
409 JCL_ThrowException (env, IO_EXCEPTION,
410 "Cannot represent position correctly on this system");
416 TARGET_NATIVE_FILE_SIZE (native_fd, file_size, result);
417 if (result != TARGET_NATIVE_OK)
419 JCL_ThrowException (env, IO_EXCEPTION,
420 TARGET_NATIVE_LAST_ERROR_STRING ());
424 /* Save off current position */
425 TARGET_NATIVE_FILE_TELL (native_fd, save_offset, result);
426 if (result != TARGET_NATIVE_OK)
428 JCL_ThrowException (env, IO_EXCEPTION,
429 TARGET_NATIVE_LAST_ERROR_STRING ());
433 if (TARGET_NATIVE_MATH_INT_INT64_LT (file_size, len))
435 /* File is too short -- seek to one byte short of where we want,
436 * then write a byte */
438 /* move to position n-1 */
439 TARGET_NATIVE_FILE_SEEK_BEGIN (native_fd,
440 TARGET_NATIVE_MATH_INT_INT64_SUB (len,
443 if (result != TARGET_NATIVE_OK)
445 JCL_ThrowException (env, IO_EXCEPTION,
446 TARGET_NATIVE_LAST_ERROR_STRING ());
451 Note: This will fail if we somehow get here in read only mode
452 * That shouldn't happen */
454 TARGET_NATIVE_FILE_WRITE (native_fd, &data, 1, bytes_written, result);
455 if (result != TARGET_NATIVE_OK)
457 JCL_ThrowException (env, IO_EXCEPTION,
458 TARGET_NATIVE_LAST_ERROR_STRING ());
462 /* Reposition file pointer to where we started if not beyond new len. */
463 if (TARGET_NATIVE_MATH_INT_INT64_LT (save_offset, len))
465 TARGET_NATIVE_FILE_SEEK_BEGIN (native_fd, save_offset,
467 if (result != TARGET_NATIVE_OK)
469 JCL_ThrowException (env, IO_EXCEPTION,
470 TARGET_NATIVE_LAST_ERROR_STRING ());
475 else if (TARGET_NATIVE_MATH_INT_INT64_GT (file_size, len))
477 /* File is too long - use ftruncate if available */
478 #ifdef HAVE_FTRUNCATE
479 TARGET_NATIVE_FILE_TRUNCATE (native_fd, len, result);
480 if (result != TARGET_NATIVE_OK)
482 JCL_ThrowException (env, IO_EXCEPTION,
483 TARGET_NATIVE_LAST_ERROR_STRING ());
486 #else /* HAVE_FTRUNCATE */
487 /* FIXME: Probably operation isn't supported, but this exception
488 * is too harsh as it will probably crash the program without need
489 JCL_ThrowException(env, "java/lang/UnsupportedOperationException",
490 "not implemented - can't shorten files on this platform");
492 JCL_ThrowException (env, IO_EXCEPTION, "Unable to shorten file length");
493 #endif /* HAVE_FTRUNCATE */
495 /* Reposition file pointer when it now is beyond the end of file. */
496 if (TARGET_NATIVE_MATH_INT_INT64_GT (save_offset, len))
498 TARGET_NATIVE_FILE_SEEK_BEGIN (native_fd, len, new_offset, result);
499 if (result != TARGET_NATIVE_OK)
501 JCL_ThrowException (env, IO_EXCEPTION,
502 TARGET_NATIVE_LAST_ERROR_STRING ());
509 JNIEXPORT jobject JNICALL
510 Java_gnu_java_nio_channels_FileChannelImpl_mapImpl (JNIEnv *env, jobject obj,
511 jchar mode, jlong position, jint size)
514 jclass MappedByteBufferImpl_class;
515 jmethodID MappedByteBufferImpl_init = NULL;
516 jobject Pointer_instance;
517 volatile jobject buffer;
524 /* FIXME: should we just assume we're on an OS modern enough to
525 have 'sysconf'? And not check for 'getpagesize'? */
526 #if defined(HAVE_GETPAGESIZE)
527 pagesize = getpagesize ();
528 #elif defined(HAVE_SYSCONF)
529 pagesize = sysconf (_SC_PAGESIZE);
531 JCL_ThrowException (env, IO_EXCEPTION,
532 "can't determine memory page size");
534 #endif /* HAVE_GETPAGESIZE/HAVE_SYSCONF */
536 if ((*env)->ExceptionOccurred (env))
541 fd = get_native_fd (env, obj);
544 if (mode == '+' || mode == 'c')
546 /* When writing we need to make sure the file is big enough,
547 otherwise the result of mmap is undefined. */
549 filesize = Java_gnu_java_nio_channels_FileChannelImpl_size(env, obj);
552 if (position + size > filesize)
553 if (ftruncate(fd, position + size) == -1)
555 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
561 flags = (mode == 'c' ? MAP_PRIVATE : MAP_SHARED);
562 p = mmap (NULL, (size_t) ALIGN_UP (size, pagesize), prot, flags,
563 fd, ALIGN_DOWN (position, pagesize));
566 JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
570 /* Unalign the mapped value back up, since we aligned offset
571 down to a multiple of the page size. */
572 address = (void *) ((char *) p + (position % pagesize));
574 Pointer_instance = JCL_NewRawDataObject(env, address);
576 MappedByteBufferImpl_class = (*env)->FindClass (env,
577 "java/nio/MappedByteBufferImpl");
578 if (MappedByteBufferImpl_class != NULL)
580 MappedByteBufferImpl_init =
581 (*env)->GetMethodID (env, MappedByteBufferImpl_class,
582 "<init>", "(Lgnu/classpath/Pointer;IZ)V");
585 if ((*env)->ExceptionOccurred (env))
587 munmap (p, ALIGN_UP (size, pagesize));
590 if (MappedByteBufferImpl_init == NULL)
592 JCL_ThrowException (env, "java/lang/InternalError",
593 "could not get MappedByteBufferImpl constructor");
594 munmap (p, ALIGN_UP (size, pagesize));
598 buffer = (*env)->NewObject (env, MappedByteBufferImpl_class,
599 MappedByteBufferImpl_init, Pointer_instance,
600 (jint) size, mode == 'r');
607 JCL_ThrowException (env, IO_EXCEPTION,
608 "memory-mapped files not implemented");
610 #endif /* HAVE_MMAP */
614 * Read a single byte from the file descriptor
615 * Return byte read or -1 on eof, exception on error
617 JNIEXPORT jint JNICALL
618 Java_gnu_java_nio_channels_FileChannelImpl_read__ (JNIEnv * env, jobject obj)
625 native_fd = get_native_fd (env, obj);
630 TARGET_NATIVE_FILE_READ (native_fd, &data, 1, bytes_read, result);
631 if ((result == TARGET_NATIVE_OK) && (bytes_read == 0))
635 if ((result != TARGET_NATIVE_OK)
636 && (TARGET_NATIVE_LAST_ERROR () !=
637 TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL))
639 JCL_ThrowException (env, IO_EXCEPTION,
640 TARGET_NATIVE_LAST_ERROR_STRING ());
644 while (result != TARGET_NATIVE_OK);
646 return ((jint) (data & 0xFF));
650 * Reads to a byte buffer from the specified file descriptor
651 * Return number of bytes read or -1 on eof, exception on error
653 JNIEXPORT jint JNICALL
654 Java_gnu_java_nio_channels_FileChannelImpl_read___3BII (JNIEnv * env,
666 native_fd = get_native_fd (env, obj);
668 /* Must return 0 if an attempt is made to read 0 bytes. */
674 JCL_ThrowException (env, IO_EXCEPTION, "negative offset");
678 bufptr = (*env)->GetByteArrayElements (env, buffer, 0);
681 JCL_ThrowException (env, IO_EXCEPTION, "Unexpected JNI error");
685 if (length + offset > (*env)->GetArrayLength (env, buffer))
687 JCL_ThrowException (env, IO_EXCEPTION,
688 "length + offset > buffer.length");
695 TARGET_NATIVE_FILE_READ (native_fd, (bufptr + offset + bytes_read),
696 (length - bytes_read), n, result);
697 if ((result == TARGET_NATIVE_OK) && (n == 0))
699 (*env)->ReleaseByteArrayElements (env, buffer, bufptr, 0);
701 return -1; /* Signal end of file to Java */
703 return CONVERT_SSIZE_T_TO_JINT (bytes_read);
705 if ((result != TARGET_NATIVE_OK)
706 && (TARGET_NATIVE_LAST_ERROR () !=
707 TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL))
709 JCL_ThrowException (env, IO_EXCEPTION,
710 TARGET_NATIVE_LAST_ERROR_STRING ());
711 (*env)->ReleaseByteArrayElements (env, buffer, bufptr, 0);
714 if (result == TARGET_NATIVE_OK)
717 while (bytes_read < 1);
719 (*env)->ReleaseByteArrayElements (env, buffer, bufptr, 0);
720 return CONVERT_SSIZE_T_TO_JINT (bytes_read);
724 * Writes a single byte to the specified file descriptor
725 * Return status code, exception on error
727 JNIEXPORT void JNICALL
728 Java_gnu_java_nio_channels_FileChannelImpl_write__I (JNIEnv * env,
733 ssize_t bytes_written;
736 native_fd = get_native_fd (env, obj);
737 native_data = (char) (CONVERT_JINT_TO_INT (b) & 0xFF);
741 TARGET_NATIVE_FILE_WRITE (native_fd, &native_data, 1, bytes_written,
743 if ((result != TARGET_NATIVE_OK)
744 && (TARGET_NATIVE_LAST_ERROR () !=
745 TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL))
747 JCL_ThrowException (env, IO_EXCEPTION,
748 TARGET_NATIVE_LAST_ERROR_STRING ());
752 while (result != TARGET_NATIVE_OK);
756 * Copies all parts of a file to disk.
758 JNIEXPORT void JNICALL
759 Java_gnu_java_nio_channels_FileChannelImpl_force (JNIEnv * env,
764 native_fd = get_native_fd (env, obj);
765 TARGET_NATIVE_FILE_FSYNC (native_fd, result);
766 if (result != TARGET_NATIVE_OK)
767 JCL_ThrowException (env, IO_EXCEPTION,
768 TARGET_NATIVE_LAST_ERROR_STRING ());
772 * Writes a byte buffer to the specified file descriptor
773 * Return status code, exception on error
775 JNIEXPORT void JNICALL
776 Java_gnu_java_nio_channels_FileChannelImpl_write___3BII (JNIEnv * env,
784 ssize_t bytes_written;
788 native_fd = get_native_fd (env, obj);
790 /* Just return if an attempt is made to write 0 bytes. */
794 bufptr = (*env)->GetByteArrayElements (env, buffer, 0);
797 JCL_ThrowException (env, IO_EXCEPTION, "Unexpected JNI error");
802 while (bytes_written < CONVERT_JINT_TO_SSIZE_T (length))
804 TARGET_NATIVE_FILE_WRITE (native_fd, (bufptr + offset + bytes_written),
805 (length - bytes_written), n, result);
806 if ((result != TARGET_NATIVE_OK)
807 && (TARGET_NATIVE_LAST_ERROR () !=
808 TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL))
810 JCL_ThrowException (env, IO_EXCEPTION,
811 TARGET_NATIVE_LAST_ERROR_STRING ());
812 (*env)->ReleaseByteArrayElements (env, buffer, bufptr, 0);
815 if (result == TARGET_NATIVE_OK)
819 (*env)->ReleaseByteArrayElements (env, buffer, bufptr, 0);
822 JNIEXPORT jboolean JNICALL
823 Java_gnu_java_nio_channels_FileChannelImpl_lock (JNIEnv *env, jobject obj,
824 jlong position, jlong size,
825 jboolean shared, jboolean wait)
828 int fd = get_native_fd (env, obj);
829 int cmd = wait ? F_SETLKW : F_SETLK;
833 flock.l_type = shared ? F_RDLCK : F_WRLCK;
834 flock.l_whence = SEEK_SET;
835 flock.l_start = (off_t) position;
836 /* Long.MAX_VALUE means lock everything possible starting at pos. */
837 if (size == 9223372036854775807LL)
840 flock.l_len = (off_t) size;
842 ret = fcntl (fd, cmd, &flock);
843 /* fprintf(stderr, "fd %d, wait %d, shared %d, ret %d, position %lld, size %lld, l_start %ld, l_len %ld\n", fd, wait, shared,ret, position, size, (long) flock.l_start, (long) flock.l_len); */
846 /* Linux man pages for fcntl state that errno might be either
847 EACCES or EAGAIN if we try F_SETLK, and another process has
848 an overlapping lock. We should not get an unexpected errno. */
849 if (errno != EACCES && errno != EAGAIN)
851 JCL_ThrowException (env, "java/lang/InternalError",
863 JCL_ThrowException (env, "java/lang/UnsupportedOperationException",
864 "file locks not implemented on this platform");
866 #endif /* HAVE_FCNTL */
869 JNIEXPORT void JNICALL
870 Java_gnu_java_nio_channels_FileChannelImpl_unlock (JNIEnv *env,
876 int fd = get_native_fd (env, obj);
880 flock.l_type = F_UNLCK;
881 flock.l_whence = SEEK_SET;
882 flock.l_start = (off_t) position;
883 /* Long.MAX_VALUE means unlock everything possible starting at pos. */
884 if (length == 9223372036854775807LL)
887 flock.l_len = (off_t) length;
889 ret = fcntl (fd, F_SETLK, &flock);
892 JCL_ThrowException (env, "java/lang/InternalError",
899 JCL_ThrowException (env, "java/lang/UnsupportedOperationException",
900 "file locks not implemented on this platform");
901 #endif /* HAVE_FCNTL */