diff --git a/openjdk-mobile-aarch64-patch/jdk/src/java.base/unix/native/libnio/ch/FileChannelImpl.c b/openjdk-mobile-aarch64-patch/jdk/src/java.base/unix/native/libnio/ch/FileChannelImpl.c new file mode 100644 index 0000000..fb60eaa --- /dev/null +++ b/openjdk-mobile-aarch64-patch/jdk/src/java.base/unix/native/libnio/ch/FileChannelImpl.c @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "jni.h" +#include "jni_util.h" +#include "jvm.h" +#include "jvm_md.h" +#include "jlong.h" +#include +#include +#include +#include "sun_nio_ch_FileChannelImpl.h" +#include "java_lang_Integer.h" +#include "nio.h" +#include "nio_util.h" +#include + +#if defined(__linux__) || defined(__solaris__) +#include +#ifdef __ANDROID__ +#define mmap64 mmap +// #include +// #define sendfile64(a,b,c,d) syscall(__NR_sendfile64, a, b, c, d); +#endif +#elif defined(_AIX) +#include +#elif defined(_ALLBSD_SOURCE) +#include +#include +#include + +#define lseek64 lseek +#define mmap64 mmap +#endif + +static jfieldID chan_fd; /* jobject 'fd' in sun.io.FileChannelImpl */ + +JNIEXPORT jlong JNICALL +Java_sun_nio_ch_FileChannelImpl_initIDs(JNIEnv *env, jclass clazz) +{ + jlong pageSize = sysconf(_SC_PAGESIZE); + chan_fd = (*env)->GetFieldID(env, clazz, "fd", "Ljava/io/FileDescriptor;"); + return pageSize; +} + +static jlong +handle(JNIEnv *env, jlong rv, char *msg) +{ + if (rv >= 0) + return rv; + if (errno == EINTR) + return IOS_INTERRUPTED; + JNU_ThrowIOExceptionWithLastError(env, msg); + return IOS_THROWN; +} + + +JNIEXPORT jlong JNICALL +Java_sun_nio_ch_FileChannelImpl_map0(JNIEnv *env, jobject this, + jint prot, jlong off, jlong len) +{ + void *mapAddress = 0; + jobject fdo = (*env)->GetObjectField(env, this, chan_fd); + jint fd = fdval(env, fdo); + int protections = 0; + int flags = 0; + + if (prot == sun_nio_ch_FileChannelImpl_MAP_RO) { + protections = PROT_READ; + flags = MAP_SHARED; + } else if (prot == sun_nio_ch_FileChannelImpl_MAP_RW) { + protections = PROT_WRITE | PROT_READ; + flags = MAP_SHARED; + } else if (prot == sun_nio_ch_FileChannelImpl_MAP_PV) { + protections = PROT_WRITE | PROT_READ; + flags = MAP_PRIVATE; + } + + mapAddress = mmap64( + 0, /* Let OS decide location */ + len, /* Number of bytes to map */ + protections, /* File permissions */ + flags, /* Changes are shared */ + fd, /* File descriptor of mapped file */ + off); /* Offset into file */ + + if (mapAddress == MAP_FAILED) { + if (errno == ENOMEM) { + JNU_ThrowOutOfMemoryError(env, "Map failed"); + return IOS_THROWN; + } + return handle(env, -1, "Map failed"); + } + + return ((jlong) (unsigned long) mapAddress); +} + + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_FileChannelImpl_unmap0(JNIEnv *env, jobject this, + jlong address, jlong len) +{ + void *a = (void *)jlong_to_ptr(address); + return handle(env, + munmap(a, (size_t)len), + "Unmap failed"); +} + + +JNIEXPORT jlong JNICALL +Java_sun_nio_ch_FileChannelImpl_position0(JNIEnv *env, jobject this, + jobject fdo, jlong offset) +{ + jint fd = fdval(env, fdo); + jlong result = 0; + + if (offset < 0) { + result = lseek64(fd, 0, SEEK_CUR); + } else { + result = lseek64(fd, offset, SEEK_SET); + } + return handle(env, result, "Position failed"); +} + + +JNIEXPORT void JNICALL +Java_sun_nio_ch_FileChannelImpl_close0(JNIEnv *env, jobject this, jobject fdo) +{ + jint fd = fdval(env, fdo); + if (fd != -1) { + jlong result = close(fd); + if (result < 0) { + JNU_ThrowIOExceptionWithLastError(env, "Close failed"); + } + } +} + +JNIEXPORT jlong JNICALL +Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this, + jobject srcFDO, + jlong position, jlong count, + jobject dstFDO) +{ + jint srcFD = fdval(env, srcFDO); + jint dstFD = fdval(env, dstFDO); + +#if defined(__linux__) + off64_t offset = (off64_t)position; + jlong n = sendfile64(dstFD, srcFD, &offset, (size_t)count); + if (n < 0) { + if (errno == EAGAIN) + return IOS_UNAVAILABLE; + if ((errno == EINVAL) && ((ssize_t)count >= 0)) + return IOS_UNSUPPORTED_CASE; + if (errno == EINTR) { + return IOS_INTERRUPTED; + } + JNU_ThrowIOExceptionWithLastError(env, "Transfer failed"); + return IOS_THROWN; + } + return n; +#elif defined (__solaris__) + sendfilevec64_t sfv; + size_t numBytes = 0; + jlong result; + + sfv.sfv_fd = srcFD; + sfv.sfv_flag = 0; + sfv.sfv_off = (off64_t)position; + sfv.sfv_len = count; + + result = sendfilev64(dstFD, &sfv, 1, &numBytes); + + /* Solaris sendfilev() will return -1 even if some bytes have been + * transferred, so we check numBytes first. + */ + if (numBytes > 0) + return numBytes; + if (result < 0) { + if (errno == EAGAIN) + return IOS_UNAVAILABLE; + if (errno == EOPNOTSUPP) + return IOS_UNSUPPORTED_CASE; + if ((errno == EINVAL) && ((ssize_t)count >= 0)) + return IOS_UNSUPPORTED_CASE; + if (errno == EINTR) + return IOS_INTERRUPTED; + JNU_ThrowIOExceptionWithLastError(env, "Transfer failed"); + return IOS_THROWN; + } + return result; +#elif defined(__APPLE__) + off_t numBytes; + int result; + + numBytes = count; + + result = sendfile(srcFD, dstFD, position, &numBytes, NULL, 0); + + if (numBytes > 0) + return numBytes; + + if (result == -1) { + if (errno == EAGAIN) + return IOS_UNAVAILABLE; + if (errno == EOPNOTSUPP || errno == ENOTSOCK || errno == ENOTCONN) + return IOS_UNSUPPORTED_CASE; + if ((errno == EINVAL) && ((ssize_t)count >= 0)) + return IOS_UNSUPPORTED_CASE; + if (errno == EINTR) + return IOS_INTERRUPTED; + JNU_ThrowIOExceptionWithLastError(env, "Transfer failed"); + return IOS_THROWN; + } + + return result; + +#elif defined(_AIX) + jlong max = (jlong)java_lang_Integer_MAX_VALUE; + struct sf_parms sf_iobuf; + jlong result; + + if (position > max) + return IOS_UNSUPPORTED_CASE; + + if (count > max) + count = max; + + memset(&sf_iobuf, 0, sizeof(sf_iobuf)); + sf_iobuf.file_descriptor = srcFD; + sf_iobuf.file_offset = (off_t)position; + sf_iobuf.file_bytes = count; + + result = send_file(&dstFD, &sf_iobuf, SF_SYNC_CACHE); + + /* AIX send_file() will return 0 when this operation complete successfully, + * return 1 when partial bytes transfered and return -1 when an error has + * Occured. + */ + if (result == -1) { + if (errno == EWOULDBLOCK) + return IOS_UNAVAILABLE; + if ((errno == EINVAL) && ((ssize_t)count >= 0)) + return IOS_UNSUPPORTED_CASE; + if (errno == EINTR) + return IOS_INTERRUPTED; + if (errno == ENOTSOCK) + return IOS_UNSUPPORTED; + JNU_ThrowIOExceptionWithLastError(env, "Transfer failed"); + return IOS_THROWN; + } + + if (sf_iobuf.bytes_sent > 0) + return (jlong)sf_iobuf.bytes_sent; + + return IOS_UNSUPPORTED_CASE; +#else + return IOS_UNSUPPORTED_CASE; +#endif +} +