Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/native/sun/nio/ch/FileChannelImpl.c
32288 views
/*1* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include <sys/mman.h>26#include <sys/stat.h>27#include <fcntl.h>28#include <sys/types.h>29#include <unistd.h>3031#if defined(__ANDROID__) || defined(__linux__) || defined(__solaris__)32# include <sys/sendfile.h>33#elif defined(_AIX)34# include <sys/socket.h>35#elif defined(_ALLBSD_SOURCE) || defined(__ANDROID__)36# if defined(_ALLBSD_SOURCE)37# include <sys/socket.h>38# include <sys/uio.h>39# endif40# define lseek64 lseek41# define mmap64 mmap42#endif4344#include "jni.h"45#include "jni_util.h"46#include "jlong.h"47#include "nio.h"48#include "nio_util.h"49#include "sun_nio_ch_FileChannelImpl.h"50#include "java_lang_Integer.h"5152static jfieldID chan_fd; /* jobject 'fd' in sun.io.FileChannelImpl */5354JNIEXPORT jlong JNICALL55Java_sun_nio_ch_FileChannelImpl_initIDs(JNIEnv *env, jclass clazz)56{57jlong pageSize = sysconf(_SC_PAGESIZE);58chan_fd = (*env)->GetFieldID(env, clazz, "fd", "Ljava/io/FileDescriptor;");59return pageSize;60}6162static jlong63handle(JNIEnv *env, jlong rv, char *msg)64{65if (rv >= 0)66return rv;67if (errno == EINTR)68return IOS_INTERRUPTED;69JNU_ThrowIOExceptionWithLastError(env, msg);70return IOS_THROWN;71}727374JNIEXPORT jlong JNICALL75Java_sun_nio_ch_FileChannelImpl_map0(JNIEnv *env, jobject this,76jint prot, jlong off, jlong len)77{78void *mapAddress = 0;79jobject fdo = (*env)->GetObjectField(env, this, chan_fd);80jint fd = fdval(env, fdo);81int protections = 0;82int flags = 0;8384if (prot == sun_nio_ch_FileChannelImpl_MAP_RO) {85protections = PROT_READ;86flags = MAP_SHARED;87} else if (prot == sun_nio_ch_FileChannelImpl_MAP_RW) {88protections = PROT_WRITE | PROT_READ;89flags = MAP_SHARED;90} else if (prot == sun_nio_ch_FileChannelImpl_MAP_PV) {91protections = PROT_WRITE | PROT_READ;92flags = MAP_PRIVATE;93}9495mapAddress = mmap64(960, /* Let OS decide location */97len, /* Number of bytes to map */98protections, /* File permissions */99flags, /* Changes are shared */100fd, /* File descriptor of mapped file */101off); /* Offset into file */102103if (mapAddress == MAP_FAILED) {104if (errno == ENOMEM) {105JNU_ThrowOutOfMemoryError(env, "Map failed");106return IOS_THROWN;107}108return handle(env, -1, "Map failed");109}110111return ((jlong) (unsigned long) mapAddress);112}113114115JNIEXPORT jint JNICALL116Java_sun_nio_ch_FileChannelImpl_unmap0(JNIEnv *env, jobject this,117jlong address, jlong len)118{119void *a = (void *)jlong_to_ptr(address);120return handle(env,121munmap(a, (size_t)len),122"Unmap failed");123}124125126JNIEXPORT void JNICALL127Java_sun_nio_ch_FileChannelImpl_close0(JNIEnv *env, jobject this, jobject fdo)128{129jint fd = fdval(env, fdo);130if (fd != -1) {131jlong result = close(fd);132if (result < 0) {133JNU_ThrowIOExceptionWithLastError(env, "Close failed");134}135}136}137138JNIEXPORT jlong JNICALL139Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this,140jobject srcFDO,141jlong position, jlong count,142jobject dstFDO)143{144jint srcFD = fdval(env, srcFDO);145jint dstFD = fdval(env, dstFDO);146147#if defined(__linux__)148off64_t offset = (off64_t)position;149jlong n = sendfile64(dstFD, srcFD, &offset, (size_t)count);150if (n < 0) {151if (errno == EAGAIN)152return IOS_UNAVAILABLE;153if ((errno == EINVAL) && ((ssize_t)count >= 0))154return IOS_UNSUPPORTED_CASE;155if (errno == EINTR) {156return IOS_INTERRUPTED;157}158JNU_ThrowIOExceptionWithLastError(env, "Transfer failed");159return IOS_THROWN;160}161return n;162#elif defined (__solaris__)163sendfilevec64_t sfv;164size_t numBytes = 0;165jlong result;166167sfv.sfv_fd = srcFD;168sfv.sfv_flag = 0;169sfv.sfv_off = (off64_t)position;170sfv.sfv_len = count;171172result = sendfilev64(dstFD, &sfv, 1, &numBytes);173174/* Solaris sendfilev() will return -1 even if some bytes have been175* transferred, so we check numBytes first.176*/177if (numBytes > 0)178return numBytes;179if (result < 0) {180if (errno == EAGAIN)181return IOS_UNAVAILABLE;182if (errno == EOPNOTSUPP)183return IOS_UNSUPPORTED_CASE;184if ((errno == EINVAL) && ((ssize_t)count >= 0))185return IOS_UNSUPPORTED_CASE;186if (errno == EINTR)187return IOS_INTERRUPTED;188JNU_ThrowIOExceptionWithLastError(env, "Transfer failed");189return IOS_THROWN;190}191return result;192#elif defined(__APPLE__)193off_t numBytes;194int result;195196numBytes = count;197198result = sendfile(srcFD, dstFD, position, &numBytes, NULL, 0);199200if (numBytes > 0)201return numBytes;202203if (result == -1) {204if (errno == EAGAIN)205return IOS_UNAVAILABLE;206if (errno == EOPNOTSUPP || errno == ENOTSOCK || errno == ENOTCONN)207return IOS_UNSUPPORTED_CASE;208if ((errno == EINVAL) && ((ssize_t)count >= 0))209return IOS_UNSUPPORTED_CASE;210if (errno == EINTR)211return IOS_INTERRUPTED;212JNU_ThrowIOExceptionWithLastError(env, "Transfer failed");213return IOS_THROWN;214}215216return result;217218#elif defined(_AIX)219jlong max = (jlong)java_lang_Integer_MAX_VALUE;220struct sf_parms sf_iobuf;221jlong result;222223if (position > max)224return IOS_UNSUPPORTED_CASE;225226if (count > max)227count = max;228229memset(&sf_iobuf, 0, sizeof(sf_iobuf));230sf_iobuf.file_descriptor = srcFD;231sf_iobuf.file_offset = (off_t)position;232sf_iobuf.file_bytes = count;233234result = send_file(&dstFD, &sf_iobuf, SF_SYNC_CACHE);235236/* AIX send_file() will return 0 when this operation complete successfully,237* return 1 when partial bytes transfered and return -1 when an error has238* Occured.239*/240if (result == -1) {241if (errno == EWOULDBLOCK)242return IOS_UNAVAILABLE;243if ((errno == EINVAL) && ((ssize_t)count >= 0))244return IOS_UNSUPPORTED_CASE;245if (errno == EINTR)246return IOS_INTERRUPTED;247if (errno == ENOTSOCK)248return IOS_UNSUPPORTED;249JNU_ThrowIOExceptionWithLastError(env, "Transfer failed");250return IOS_THROWN;251}252253if (sf_iobuf.bytes_sent > 0)254return (jlong)sf_iobuf.bytes_sent;255256return IOS_UNSUPPORTED_CASE;257#else258return IOS_UNSUPPORTED_CASE;259#endif260}261262263264