1 /* 2 * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include "jni.h" 27 #include "jni_util.h" 28 #include "jvm.h" 29 #include "jlong.h" 30 #include <io.h> 31 #include "nio.h" 32 #include "nio_util.h" 33 #include "sun_nio_ch_FileChannelImpl.h" 34 #include "java_lang_Integer.h" 35 36 #include <Mswsock.h> 37 #pragma comment(lib, "Mswsock.lib") 38 39 static jfieldID chan_fd; /* id for jobject 'fd' in java.io.FileChannel */ 40 41 /************************************************************** 42 * static method to store field ID's in initializers 43 * and retrieve the allocation granularity 44 */ 45 JNIEXPORT jlong JNICALL 46 Java_sun_nio_ch_FileChannelImpl_initIDs(JNIEnv *env, jclass clazz) 47 { 48 SYSTEM_INFO si; 49 jint align; 50 GetSystemInfo(&si); 51 align = si.dwAllocationGranularity; 52 chan_fd = (*env)->GetFieldID(env, clazz, "fd", "Ljava/io/FileDescriptor;"); 53 return align; 54 } 55 56 57 /************************************************************** 58 * Channel 59 */ 60 61 JNIEXPORT jlong JNICALL 62 Java_sun_nio_ch_FileChannelImpl_map0(JNIEnv *env, jobject this, 63 jint prot, jlong off, jlong len) 64 { 65 void *mapAddress = 0; 66 jint lowOffset = (jint)off; 67 jint highOffset = (jint)(off >> 32); 68 jlong maxSize = off + len; 69 jint lowLen = (jint)(maxSize); 70 jint highLen = (jint)(maxSize >> 32); 71 jobject fdo = (*env)->GetObjectField(env, this, chan_fd); 72 HANDLE fileHandle = (HANDLE)(handleval(env, fdo)); 73 HANDLE mapping; 74 DWORD mapAccess = FILE_MAP_READ; 75 DWORD fileProtect = PAGE_READONLY; 76 DWORD mapError; 77 BOOL result; 78 79 if (prot == sun_nio_ch_FileChannelImpl_MAP_RO) { 80 fileProtect = PAGE_READONLY; 81 mapAccess = FILE_MAP_READ; 82 } else if (prot == sun_nio_ch_FileChannelImpl_MAP_RW) { 83 fileProtect = PAGE_READWRITE; 84 mapAccess = FILE_MAP_WRITE; 85 } else if (prot == sun_nio_ch_FileChannelImpl_MAP_PV) { 86 fileProtect = PAGE_WRITECOPY; 87 mapAccess = FILE_MAP_COPY; 88 } 89 90 mapping = CreateFileMapping( 91 fileHandle, /* Handle of file */ 92 NULL, /* Not inheritable */ 93 fileProtect, /* Read and write */ 94 highLen, /* High word of max size */ 95 lowLen, /* Low word of max size */ 96 NULL); /* No name for object */ 97 98 if (mapping == NULL) { 99 JNU_ThrowIOExceptionWithLastError(env, "Map failed"); 100 return IOS_THROWN; 101 } 102 103 mapAddress = MapViewOfFile( 104 mapping, /* Handle of file mapping object */ 105 mapAccess, /* Read and write access */ 106 highOffset, /* High word of offset */ 107 lowOffset, /* Low word of offset */ 108 (DWORD)len); /* Number of bytes to map */ 109 mapError = GetLastError(); 110 111 result = CloseHandle(mapping); 112 if (result == 0) { 113 JNU_ThrowIOExceptionWithLastError(env, "Map failed"); 114 return IOS_THROWN; 115 } 116 117 if (mapAddress == NULL) { 118 if (mapError == ERROR_NOT_ENOUGH_MEMORY) 119 JNU_ThrowOutOfMemoryError(env, "Map failed"); 120 else 121 JNU_ThrowIOExceptionWithLastError(env, "Map failed"); 122 return IOS_THROWN; 123 } 124 125 return ptr_to_jlong(mapAddress); 126 } 127 128 JNIEXPORT jint JNICALL 129 Java_sun_nio_ch_FileChannelImpl_unmap0(JNIEnv *env, jobject this, 130 jlong address, jlong len) 131 { 132 BOOL result; 133 void *a = (void *) jlong_to_ptr(address); 134 135 result = UnmapViewOfFile(a); 136 if (result == 0) { 137 JNU_ThrowIOExceptionWithLastError(env, "Unmap failed"); 138 return IOS_THROWN; 139 } 140 return 0; 141 } 142 143 JNIEXPORT jlong JNICALL 144 Java_sun_nio_ch_FileChannelImpl_position0(JNIEnv *env, jobject this, 145 jobject fdo, jlong offset) 146 { 147 BOOL result = 0; 148 HANDLE h = (HANDLE)(handleval(env, fdo)); 149 LARGE_INTEGER where; 150 DWORD whence; 151 152 if (offset < 0) { 153 where.QuadPart = 0; 154 whence = FILE_CURRENT; 155 } else { 156 where.QuadPart = offset; 157 whence = FILE_BEGIN; 158 } 159 160 result = SetFilePointerEx(h, where, &where, whence); 161 if (result == 0) { 162 JNU_ThrowIOExceptionWithLastError(env, "Seek failed"); 163 return IOS_THROWN; 164 } 165 return (jlong)where.QuadPart; 166 } 167 168 JNIEXPORT jlong JNICALL 169 Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this, 170 jobject srcFD, 171 jlong position, jlong count, 172 jobject dstFD) 173 { 174 const int PACKET_SIZE = 524288; 175 176 HANDLE src = (HANDLE)(handleval(env, srcFD)); 177 SOCKET dst = (SOCKET)(fdval(env, dstFD)); 178 DWORD chunkSize = (count > java_lang_Integer_MAX_VALUE) ? 179 java_lang_Integer_MAX_VALUE : (DWORD)count; 180 BOOL result = 0; 181 182 jlong pos = Java_sun_nio_ch_FileChannelImpl_position0(env, this, srcFD, position); 183 if (pos == IOS_THROWN) { 184 return IOS_THROWN; 185 } 186 187 result = TransmitFile( 188 dst, 189 src, 190 chunkSize, 191 PACKET_SIZE, 192 NULL, 193 NULL, 194 TF_USE_KERNEL_APC 195 ); 196 if (!result) { 197 int error = WSAGetLastError(); 198 if (WSAEINVAL == error && count >= 0) { 199 return IOS_UNSUPPORTED_CASE; 200 } 201 if (WSAENOTSOCK == error) { 202 return IOS_UNSUPPORTED_CASE; 203 } 204 JNU_ThrowIOExceptionWithLastError(env, "transfer failed"); 205 return IOS_THROWN; 206 } 207 return chunkSize; 208 }