📄 gnu_java_nio_channels_filechannelimpl.c
字号:
JCL_ThrowException (env, IO_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING ()); return; } /* write a byte Note: This will fail if we somehow get here in read only mode * That shouldn't happen */ data = '\0'; TARGET_NATIVE_FILE_WRITE (native_fd, &data, 1, bytes_written, result); if (result != TARGET_NATIVE_OK) { JCL_ThrowException (env, IO_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING ()); return; } /* Reposition file pointer to where we started if not beyond new len. */ if (TARGET_NATIVE_MATH_INT_INT64_LT (save_offset, len)) { TARGET_NATIVE_FILE_SEEK_BEGIN (native_fd, save_offset, new_offset, result); if (result != TARGET_NATIVE_OK) { JCL_ThrowException (env, IO_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING ()); return; } } } else if (TARGET_NATIVE_MATH_INT_INT64_GT (file_size, len)) { /* File is too long - use ftruncate if available */#ifdef HAVE_FTRUNCATE TARGET_NATIVE_FILE_TRUNCATE (native_fd, len, result); if (result != TARGET_NATIVE_OK) { JCL_ThrowException (env, IO_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING ()); return; }#else /* HAVE_FTRUNCATE */ /* FIXME: Probably operation isn't supported, but this exception * is too harsh as it will probably crash the program without need JCL_ThrowException(env, "java/lang/UnsupportedOperationException", "not implemented - can't shorten files on this platform"); */ JCL_ThrowException (env, IO_EXCEPTION, "Unable to shorten file length");#endif /* HAVE_FTRUNCATE */ /* Reposition file pointer when it now is beyond the end of file. */ if (TARGET_NATIVE_MATH_INT_INT64_GT (save_offset, len)) { TARGET_NATIVE_FILE_SEEK_BEGIN (native_fd, len, new_offset, result); if (result != TARGET_NATIVE_OK) { JCL_ThrowException (env, IO_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING ()); return; } } }}JNIEXPORT jobject JNICALLJava_gnu_java_nio_channels_FileChannelImpl_mapImpl (JNIEnv *env, jobject obj, jchar mode, jlong position, jint size){#ifdef HAVE_MMAP jclass MappedByteBufferImpl_class; jmethodID MappedByteBufferImpl_init = NULL; jobject Pointer_instance; volatile jobject buffer; long pagesize; int prot, flags; int fd; void *p; void *address; /* FIXME: should we just assume we're on an OS modern enough to have 'sysconf'? And not check for 'getpagesize'? */#if defined(HAVE_GETPAGESIZE) pagesize = getpagesize ();#elif defined(HAVE_SYSCONF) pagesize = sysconf (_SC_PAGESIZE);#else JCL_ThrowException (env, IO_EXCEPTION, "can't determine memory page size"); return NULL;#endif /* HAVE_GETPAGESIZE/HAVE_SYSCONF */ if ((*env)->ExceptionOccurred (env)) { return NULL; } prot = PROT_READ; if (mode == '+') prot |= PROT_WRITE; flags = (mode == 'c' ? MAP_PRIVATE : MAP_SHARED); fd = get_native_fd (env, obj); p = mmap (NULL, (size_t) ALIGN_UP (size, pagesize), prot, flags, fd, ALIGN_DOWN (position, pagesize)); if (p == MAP_FAILED) { JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); return NULL; } /* Unalign the mapped value back up, since we aligned offset down to a multiple of the page size. */ address = (void *) ((char *) p + (position % pagesize)); Pointer_instance = JCL_NewRawDataObject(env, address); MappedByteBufferImpl_class = (*env)->FindClass (env, "java/nio/MappedByteBufferImpl"); if (MappedByteBufferImpl_class != NULL) { MappedByteBufferImpl_init = (*env)->GetMethodID (env, MappedByteBufferImpl_class, "<init>", "(Lgnu/classpath/Pointer;IZ)V"); } if ((*env)->ExceptionOccurred (env)) { munmap (p, ALIGN_UP (size, pagesize)); return NULL; } if (MappedByteBufferImpl_init == NULL) { JCL_ThrowException (env, "java/lang/InternalError", "could not get MappedByteBufferImpl constructor"); munmap (p, ALIGN_UP (size, pagesize)); return NULL; } buffer = (*env)->NewObject (env, MappedByteBufferImpl_class, MappedByteBufferImpl_init, Pointer_instance, (jint) size, mode == 'r'); return buffer;#else (void) obj; (void) mode; (void) position; (void) size; JCL_ThrowException (env, IO_EXCEPTION, "memory-mapped files not implemented"); return 0;#endif /* HAVE_MMAP */}/* * Read a single byte from the file descriptor * Return byte read or -1 on eof, exception on error */JNIEXPORT jint JNICALLJava_gnu_java_nio_channels_FileChannelImpl_read__ (JNIEnv * env, jobject obj){ int native_fd; char data; ssize_t bytes_read; int result; native_fd = get_native_fd (env, obj); bytes_read = 0; do { TARGET_NATIVE_FILE_READ (native_fd, &data, 1, bytes_read, result); if ((result == TARGET_NATIVE_OK) && (bytes_read == 0)) { return (-1); } if ((result != TARGET_NATIVE_OK) && (TARGET_NATIVE_LAST_ERROR () != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL)) { JCL_ThrowException (env, IO_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING ()); return (-1); } } while (result != TARGET_NATIVE_OK); return ((jint) (data & 0xFF));}/* * Reads to a byte buffer from the specified file descriptor * Return number of bytes read or -1 on eof, exception on error */JNIEXPORT jint JNICALLJava_gnu_java_nio_channels_FileChannelImpl_read___3BII (JNIEnv * env, jobject obj, jbyteArray buffer, jint offset, jint length){ int native_fd; jbyte *bufptr; ssize_t bytes_read; ssize_t n; int result; native_fd = get_native_fd (env, obj); /* Must return 0 if an attempt is made to read 0 bytes. */ if (length == 0) return 0; if (offset < 0) { JCL_ThrowException (env, IO_EXCEPTION, "negative offset"); return -1; } bufptr = (*env)->GetByteArrayElements (env, buffer, 0); if (!bufptr) { JCL_ThrowException (env, IO_EXCEPTION, "Unexpected JNI error"); return (-1); } if (length + offset > (*env)->GetArrayLength (env, buffer)) { JCL_ThrowException (env, IO_EXCEPTION, "length + offset > buffer.length"); return -1; } bytes_read = 0; do { TARGET_NATIVE_FILE_READ (native_fd, (bufptr + offset + bytes_read), (length - bytes_read), n, result); if ((result == TARGET_NATIVE_OK) && (n == 0)) { (*env)->ReleaseByteArrayElements (env, buffer, bufptr, 0); if (bytes_read == 0) return -1; /* Signal end of file to Java */ else return CONVERT_SSIZE_T_TO_JINT (bytes_read); } if ((result != TARGET_NATIVE_OK) && (TARGET_NATIVE_LAST_ERROR () != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL)) { JCL_ThrowException (env, IO_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING ()); (*env)->ReleaseByteArrayElements (env, buffer, bufptr, 0); return -1; } if (result == TARGET_NATIVE_OK) bytes_read += n; } while (bytes_read < 1); (*env)->ReleaseByteArrayElements (env, buffer, bufptr, 0); return CONVERT_SSIZE_T_TO_JINT (bytes_read);}/* * Writes a single byte to the specified file descriptor * Return status code, exception on error */JNIEXPORT void JNICALLJava_gnu_java_nio_channels_FileChannelImpl_write__I (JNIEnv * env, jobject obj, jint b){ int native_fd; char native_data; ssize_t bytes_written; int result; native_fd = get_native_fd (env, obj); native_data = (char) (CONVERT_JINT_TO_INT (b) & 0xFF); do { TARGET_NATIVE_FILE_WRITE (native_fd, &native_data, 1, bytes_written, result); if ((result != TARGET_NATIVE_OK) && (TARGET_NATIVE_LAST_ERROR () != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL)) { JCL_ThrowException (env, IO_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING ()); return; } } while (result != TARGET_NATIVE_OK);}/* * Copies all parts of a file to disk. */JNIEXPORT void JNICALLJava_gnu_java_nio_channels_FileChannelImpl_force (JNIEnv * env, jobject obj){ int native_fd; int result; native_fd = get_native_fd (env, obj); TARGET_NATIVE_FILE_FSYNC (native_fd, result); if (result != TARGET_NATIVE_OK) JCL_ThrowException (env, IO_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING ());}/* * Writes a byte buffer to the specified file descriptor * Return status code, exception on error */JNIEXPORT void JNICALLJava_gnu_java_nio_channels_FileChannelImpl_write___3BII (JNIEnv * env, jobject obj, jbyteArray buffer, jint offset, jint length){ int native_fd; jbyte *bufptr; ssize_t bytes_written; ssize_t n; int result; native_fd = get_native_fd (env, obj); /* Just return if an attempt is made to write 0 bytes. */ if (length == 0) return; bufptr = (*env)->GetByteArrayElements (env, buffer, 0); if (!bufptr) { JCL_ThrowException (env, IO_EXCEPTION, "Unexpected JNI error"); return; } bytes_written = 0; while (bytes_written < CONVERT_JINT_TO_SSIZE_T (length)) { TARGET_NATIVE_FILE_WRITE (native_fd, (bufptr + offset + bytes_written), (length - bytes_written), n, result); if ((result != TARGET_NATIVE_OK) && (TARGET_NATIVE_LAST_ERROR () != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL)) { JCL_ThrowException (env, IO_EXCEPTION, TARGET_NATIVE_LAST_ERROR_STRING ()); (*env)->ReleaseByteArrayElements (env, buffer, bufptr, 0); return; } if (result == TARGET_NATIVE_OK) bytes_written += n; } (*env)->ReleaseByteArrayElements (env, buffer, bufptr, 0);}JNIEXPORT jboolean JNICALLJava_gnu_java_nio_channels_FileChannelImpl_lock (JNIEnv *env, jobject obj, jlong position, jlong size, jboolean shared, jboolean wait){#ifdef HAVE_FCNTL int fd = get_native_fd (env, obj); int cmd = wait ? F_SETLKW : F_SETLK; struct flock flock; int ret; flock.l_type = shared ? F_RDLCK : F_WRLCK; flock.l_whence = SEEK_SET; flock.l_start = (off_t) position; /* Long.MAX_VALUE means lock everything possible starting at pos. */ if (size == 9223372036854775807LL) flock.l_len = 0; else flock.l_len = (off_t) size; ret = fcntl (fd, cmd, &flock); /* 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); */ if (ret) { /* Linux man pages for fcntl state that errno might be either EACCES or EAGAIN if we try F_SETLK, and another process has an overlapping lock. We should not get an unexpected errno. */ if (errno != EACCES && errno != EAGAIN) { JCL_ThrowException (env, "java/lang/InternalError", strerror (errno)); } return JNI_FALSE; } return JNI_TRUE;#else (void) obj; (void) position; (void) size; (void) shared; (void) wait; JCL_ThrowException (env, "java/lang/UnsupportedOperationException", "file locks not implemented on this platform"); return JNI_FALSE;#endif /* HAVE_FCNTL */}JNIEXPORT void JNICALLJava_gnu_java_nio_channels_FileChannelImpl_unlock (JNIEnv *env, jobject obj, jlong position, jlong length){#ifdef HAVE_FCNTL int fd = get_native_fd (env, obj); struct flock flock; int ret; flock.l_type = F_UNLCK; flock.l_whence = SEEK_SET; flock.l_start = (off_t) position; /* Long.MAX_VALUE means unlock everything possible starting at pos. */ if (length == 9223372036854775807LL) flock.l_len = 0; else flock.l_len = (off_t) length; ret = fcntl (fd, F_SETLK, &flock); if (ret) { JCL_ThrowException (env, "java/lang/InternalError", strerror (errno)); }#else (void) obj; (void) position; (void) length; JCL_ThrowException (env, "java/lang/UnsupportedOperationException", "file locks not implemented on this platform");#endif /* HAVE_FCNTL */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -