/* * Copyright (c) 2000, 2009, 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 "jlong.h" #include #include "nio.h" #include "nio_util.h" #include "sun_nio_ch_FileChannelImpl.h" #include "java_lang_Integer.h" #include #pragma comment(lib, "Mswsock.lib") static jfieldID chan_fd; /* id for jobject 'fd' in java.io.FileChannel */ /************************************************************** * static method to store field ID's in initializers * and retrieve the allocation granularity */ JNIEXPORT jlong JNICALL Java_sun_nio_ch_FileChannelImpl_initIDs(JNIEnv *env, jclass clazz) { SYSTEM_INFO si; jint align; GetSystemInfo(&si); align = si.dwAllocationGranularity; chan_fd = (*env)->GetFieldID(env, clazz, "fd", "Ljava/io/FileDescriptor;"); return align; } /************************************************************** * Channel */ JNIEXPORT jlong JNICALL Java_sun_nio_ch_FileChannelImpl_map0(JNIEnv *env, jobject this, jint prot, jlong off, jlong len) { void *mapAddress = 0; jint lowOffset = (jint)off; jint highOffset = (jint)(off >> 32); jlong maxSize = off + len; jint lowLen = (jint)(maxSize); jint highLen = (jint)(maxSize >> 32); jobject fdo = (*env)->GetObjectField(env, this, chan_fd); HANDLE fileHandle = (HANDLE)(handleval(env, fdo)); HANDLE mapping; DWORD mapAccess = FILE_MAP_READ; DWORD fileProtect = PAGE_READONLY; DWORD mapError; BOOL result; if (prot == sun_nio_ch_FileChannelImpl_MAP_RO) { fileProtect = PAGE_READONLY; mapAccess = FILE_MAP_READ; } else if (prot == sun_nio_ch_FileChannelImpl_MAP_RW) { fileProtect = PAGE_READWRITE; mapAccess = FILE_MAP_WRITE; } else if (prot == sun_nio_ch_FileChannelImpl_MAP_PV) { fileProtect = PAGE_WRITECOPY; mapAccess = FILE_MAP_COPY; } mapping = CreateFileMapping( fileHandle, /* Handle of file */ NULL, /* Not inheritable */ fileProtect, /* Read and write */ highLen, /* High word of max size */ lowLen, /* Low word of max size */ NULL); /* No name for object */ if (mapping == NULL) { JNU_ThrowIOExceptionWithLastError(env, "Map failed"); return IOS_THROWN; } mapAddress = MapViewOfFile( mapping, /* Handle of file mapping object */ mapAccess, /* Read and write access */ highOffset, /* High word of offset */ lowOffset, /* Low word of offset */ (DWORD)len); /* Number of bytes to map */ mapError = GetLastError(); result = CloseHandle(mapping); if (result == 0) { JNU_ThrowIOExceptionWithLastError(env, "Map failed"); return IOS_THROWN; } if (mapAddress == NULL) { if (mapError == ERROR_NOT_ENOUGH_MEMORY) JNU_ThrowOutOfMemoryError(env, "Map failed"); else JNU_ThrowIOExceptionWithLastError(env, "Map failed"); return IOS_THROWN; } return ptr_to_jlong(mapAddress); } JNIEXPORT jint JNICALL Java_sun_nio_ch_FileChannelImpl_unmap0(JNIEnv *env, jobject this, jlong address, jlong len) { BOOL result; void *a = (void *) jlong_to_ptr(address); result = UnmapViewOfFile(a); if (result == 0) { JNU_ThrowIOExceptionWithLastError(env, "Unmap failed"); return IOS_THROWN; } return 0; } JNIEXPORT jlong JNICALL Java_sun_nio_ch_FileChannelImpl_position0(JNIEnv *env, jobject this, jobject fdo, jlong offset) { BOOL result = 0; HANDLE h = (HANDLE)(handleval(env, fdo)); LARGE_INTEGER where; DWORD whence; if (offset < 0) { where.QuadPart = 0; whence = FILE_CURRENT; } else { where.QuadPart = offset; whence = FILE_BEGIN; } result = SetFilePointerEx(h, where, &where, whence); if (result == 0) { JNU_ThrowIOExceptionWithLastError(env, "Seek failed"); return IOS_THROWN; } return (jlong)where.QuadPart; } JNIEXPORT void JNICALL Java_sun_nio_ch_FileChannelImpl_close0(JNIEnv *env, jobject this, jobject fdo) { HANDLE h = (HANDLE)(handleval(env, fdo)); if (h != INVALID_HANDLE_VALUE) { jint result = CloseHandle(h); if (result < 0) { JNU_ThrowIOExceptionWithLastError(env, "Close failed"); } } } JNIEXPORT jlong JNICALL Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this, jobject srcFD, jlong position, jlong count, jobject dstFD) { const int PACKET_SIZE = 524288; HANDLE src = (HANDLE)(handleval(env, srcFD)); SOCKET dst = (SOCKET)(fdval(env, dstFD)); DWORD chunkSize = (count > java_lang_Integer_MAX_VALUE) ? java_lang_Integer_MAX_VALUE : (DWORD)count; BOOL result = 0; jlong pos = Java_sun_nio_ch_FileChannelImpl_position0(env, this, srcFD, position); if (pos == IOS_THROWN) { return IOS_THROWN; } result = TransmitFile( dst, src, chunkSize, PACKET_SIZE, NULL, NULL, TF_USE_KERNEL_APC ); if (!result) { int error = WSAGetLastError(); if (WSAEINVAL == error && count >= 0) { return IOS_UNSUPPORTED_CASE; } if (WSAENOTSOCK == error) { return IOS_UNSUPPORTED_CASE; } JNU_ThrowIOExceptionWithLastError(env, "transfer failed"); return IOS_THROWN; } return chunkSize; } JNIEXPORT jint JNICALL Java_sun_nio_ch_FileChannelImpl_setDirect0(JNIEnv *env, jobject this, jobject fObj) { return 0; }