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 <windows.h> 27 #include "jni.h" 28 #include "jni_util.h" 29 #include "jvm.h" 30 #include "jlong.h" 31 #include "sun_nio_ch_FileDispatcherImpl.h" 32 #include <io.h> 33 #include "nio.h" 34 #include "nio_util.h" 35 #include "jlong.h" 36 37 38 /************************************************************** 39 * FileDispatcherImpl.c 40 */ 41 42 JNIEXPORT jint JNICALL 43 Java_sun_nio_ch_FileDispatcherImpl_read0(JNIEnv *env, jclass clazz, jobject fdo, 44 jlong address, jint len) 45 { 46 DWORD read = 0; 47 BOOL result = 0; 48 HANDLE h = (HANDLE)(handleval(env, fdo)); 49 50 if (h == INVALID_HANDLE_VALUE) { 51 JNU_ThrowIOExceptionWithLastError(env, "Invalid handle"); 52 return IOS_THROWN; 53 } 54 result = ReadFile(h, /* File handle to read */ 55 (LPVOID)address, /* address to put data */ 56 len, /* number of bytes to read */ 57 &read, /* number of bytes read */ 58 NULL); /* no overlapped struct */ 59 if (result == 0) { 60 int error = GetLastError(); 61 if (error == ERROR_BROKEN_PIPE) { 62 return IOS_EOF; 63 } 64 if (error == ERROR_NO_DATA) { 65 return IOS_UNAVAILABLE; 66 } 67 JNU_ThrowIOExceptionWithLastError(env, "Read failed"); 68 return IOS_THROWN; 69 } 70 return convertReturnVal(env, (jint)read, JNI_TRUE); 71 } 72 73 JNIEXPORT jlong JNICALL 74 Java_sun_nio_ch_FileDispatcherImpl_readv0(JNIEnv *env, jclass clazz, jobject fdo, 75 jlong address, jint len) 76 { 77 DWORD read = 0; 78 BOOL result = 0; 79 jlong totalRead = 0; 80 LPVOID loc; 81 int i = 0; 82 DWORD num = 0; 83 struct iovec *iovecp = (struct iovec *)jlong_to_ptr(address); 84 HANDLE h = (HANDLE)(handleval(env, fdo)); 85 86 if (h == INVALID_HANDLE_VALUE) { 87 JNU_ThrowIOExceptionWithLastError(env, "Invalid handle"); 88 return IOS_THROWN; 89 } 90 91 for(i=0; i<len; i++) { 92 loc = (LPVOID)jlong_to_ptr(iovecp[i].iov_base); 93 num = iovecp[i].iov_len; 94 result = ReadFile(h, /* File handle to read */ 95 loc, /* address to put data */ 96 num, /* number of bytes to read */ 97 &read, /* number of bytes read */ 98 NULL); /* no overlapped struct */ 99 if (read > 0) { 100 totalRead += read; 101 } 102 if (read < num) { 103 break; 104 } 105 } 106 107 if (result == 0) { 108 int error = GetLastError(); 109 if (error == ERROR_BROKEN_PIPE) { 110 return IOS_EOF; 111 } 112 if (error == ERROR_NO_DATA) { 113 return IOS_UNAVAILABLE; 114 } 115 JNU_ThrowIOExceptionWithLastError(env, "Read failed"); 116 return IOS_THROWN; 117 } 118 119 return convertLongReturnVal(env, totalRead, JNI_TRUE); 120 } 121 122 JNIEXPORT jint JNICALL 123 Java_sun_nio_ch_FileDispatcherImpl_pread0(JNIEnv *env, jclass clazz, jobject fdo, 124 jlong address, jint len, jlong offset) 125 { 126 DWORD read = 0; 127 BOOL result = 0; 128 HANDLE h = (HANDLE)(handleval(env, fdo)); 129 LARGE_INTEGER currPos; 130 OVERLAPPED ov; 131 132 if (h == INVALID_HANDLE_VALUE) { 133 JNU_ThrowIOExceptionWithLastError(env, "Invalid handle"); 134 return IOS_THROWN; 135 } 136 137 currPos.QuadPart = 0; 138 result = SetFilePointerEx(h, currPos, &currPos, FILE_CURRENT); 139 if (result == 0) { 140 JNU_ThrowIOExceptionWithLastError(env, "Seek failed"); 141 return IOS_THROWN; 142 } 143 144 ZeroMemory(&ov, sizeof(ov)); 145 ov.Offset = (DWORD)offset; 146 ov.OffsetHigh = (DWORD)(offset >> 32); 147 148 result = ReadFile(h, /* File handle to read */ 149 (LPVOID)address, /* address to put data */ 150 len, /* number of bytes to read */ 151 &read, /* number of bytes read */ 152 &ov); /* position to read from */ 153 154 if (result == 0) { 155 int error = GetLastError(); 156 if (error == ERROR_BROKEN_PIPE) { 157 return IOS_EOF; 158 } 159 if (error == ERROR_NO_DATA) { 160 return IOS_UNAVAILABLE; 161 } 162 if (error != ERROR_HANDLE_EOF) { 163 JNU_ThrowIOExceptionWithLastError(env, "Read failed"); 164 return IOS_THROWN; 165 } 166 } 167 168 result = SetFilePointerEx(h, currPos, NULL, FILE_BEGIN); 169 if (result == 0) { 170 JNU_ThrowIOExceptionWithLastError(env, "Seek failed"); 171 return IOS_THROWN; 172 } 173 174 return convertReturnVal(env, (jint)read, JNI_TRUE); 175 } 176 177 JNIEXPORT jint JNICALL 178 Java_sun_nio_ch_FileDispatcherImpl_write0(JNIEnv *env, jclass clazz, jobject fdo, 179 jlong address, jint len, jboolean append) 180 { 181 BOOL result = 0; 182 DWORD written = 0; 183 HANDLE h = (HANDLE)(handleval(env, fdo)); 184 185 if (h != INVALID_HANDLE_VALUE) { 186 OVERLAPPED ov; 187 LPOVERLAPPED lpOv; 188 if (append == JNI_TRUE) { 189 ZeroMemory(&ov, sizeof(ov)); 190 ov.Offset = (DWORD)0xFFFFFFFF; 191 ov.OffsetHigh = (DWORD)0xFFFFFFFF; 192 lpOv = &ov; 193 } else { 194 lpOv = NULL; 195 } 196 result = WriteFile(h, /* File handle to write */ 197 (LPCVOID)address, /* pointer to the buffer */ 198 len, /* number of bytes to write */ 199 &written, /* receives number of bytes written */ 200 lpOv); /* overlapped struct */ 201 } 202 203 if ((h == INVALID_HANDLE_VALUE) || (result == 0)) { 204 JNU_ThrowIOExceptionWithLastError(env, "Write failed"); 205 return IOS_THROWN; 206 } 207 208 return convertReturnVal(env, (jint)written, JNI_FALSE); 209 } 210 211 JNIEXPORT jlong JNICALL 212 Java_sun_nio_ch_FileDispatcherImpl_writev0(JNIEnv *env, jclass clazz, jobject fdo, 213 jlong address, jint len, jboolean append) 214 { 215 BOOL result = 0; 216 DWORD written = 0; 217 HANDLE h = (HANDLE)(handleval(env, fdo)); 218 jlong totalWritten = 0; 219 220 if (h != INVALID_HANDLE_VALUE) { 221 LPVOID loc; 222 int i = 0; 223 DWORD num = 0; 224 struct iovec *iovecp = (struct iovec *)jlong_to_ptr(address); 225 OVERLAPPED ov; 226 LPOVERLAPPED lpOv; 227 if (append == JNI_TRUE) { 228 ZeroMemory(&ov, sizeof(ov)); 229 ov.Offset = (DWORD)0xFFFFFFFF; 230 ov.OffsetHigh = (DWORD)0xFFFFFFFF; 231 lpOv = &ov; 232 } else { 233 lpOv = NULL; 234 } 235 for(i=0; i<len; i++) { 236 loc = (LPVOID)jlong_to_ptr(iovecp[i].iov_base); 237 num = iovecp[i].iov_len; 238 result = WriteFile(h, /* File handle to write */ 239 loc, /* pointers to the buffers */ 240 num, /* number of bytes to write */ 241 &written,/* receives number of bytes written */ 242 lpOv); /* overlapped struct */ 243 if (written > 0) { 244 totalWritten += written; 245 } 246 if (written < num) { 247 break; 248 } 249 } 250 } 251 252 if ((h == INVALID_HANDLE_VALUE) || (result == 0)) { 253 JNU_ThrowIOExceptionWithLastError(env, "Write failed"); 254 return IOS_THROWN; 255 } 256 257 return convertLongReturnVal(env, totalWritten, JNI_FALSE); 258 } 259 260 JNIEXPORT jint JNICALL 261 Java_sun_nio_ch_FileDispatcherImpl_pwrite0(JNIEnv *env, jclass clazz, jobject fdo, 262 jlong address, jint len, jlong offset) 263 { 264 BOOL result = 0; 265 DWORD written = 0; 266 HANDLE h = (HANDLE)(handleval(env, fdo)); 267 LARGE_INTEGER currPos; 268 OVERLAPPED ov; 269 270 currPos.QuadPart = 0; 271 result = SetFilePointerEx(h, currPos, &currPos, FILE_CURRENT); 272 if (result == 0) { 273 JNU_ThrowIOExceptionWithLastError(env, "Seek failed"); 274 return IOS_THROWN; 275 } 276 277 ZeroMemory(&ov, sizeof(ov)); 278 ov.Offset = (DWORD)offset; 279 ov.OffsetHigh = (DWORD)(offset >> 32); 280 281 result = WriteFile(h, /* File handle to write */ 282 (LPCVOID)address, /* pointer to the buffer */ 283 len, /* number of bytes to write */ 284 &written, /* receives number of bytes written */ 285 &ov); /* position to write at */ 286 287 if ((h == INVALID_HANDLE_VALUE) || (result == 0)) { 288 JNU_ThrowIOExceptionWithLastError(env, "Write failed"); 289 return IOS_THROWN; 290 } 291 292 result = SetFilePointerEx(h, currPos, NULL, FILE_BEGIN); 293 if (result == 0) { 294 JNU_ThrowIOExceptionWithLastError(env, "Seek failed"); 295 return IOS_THROWN; 296 } 297 298 return convertReturnVal(env, (jint)written, JNI_FALSE); 299 } 300 301 JNIEXPORT jint JNICALL 302 Java_sun_nio_ch_FileDispatcherImpl_force0(JNIEnv *env, jobject this, 303 jobject fdo, jboolean md) 304 { 305 int result = 0; 306 HANDLE h = (HANDLE)(handleval(env, fdo)); 307 308 if (h != INVALID_HANDLE_VALUE) { 309 result = FlushFileBuffers(h); 310 if (result == 0) { 311 int error = GetLastError(); 312 if (error != ERROR_ACCESS_DENIED) { 313 JNU_ThrowIOExceptionWithLastError(env, "Force failed"); 314 return IOS_THROWN; 315 } 316 } 317 } else { 318 JNU_ThrowIOExceptionWithLastError(env, "Force failed"); 319 return IOS_THROWN; 320 } 321 return 0; 322 } 323 324 JNIEXPORT jint JNICALL 325 Java_sun_nio_ch_FileDispatcherImpl_truncate0(JNIEnv *env, jobject this, 326 jobject fdo, jlong size) 327 { 328 BOOL result = 0; 329 HANDLE h = (HANDLE)(handleval(env, fdo)); 330 FILE_END_OF_FILE_INFO eofInfo; 331 332 eofInfo.EndOfFile.QuadPart = size; 333 result = SetFileInformationByHandle(h, 334 FileEndOfFileInfo, 335 &eofInfo, 336 sizeof(eofInfo)); 337 if (result == 0) { 338 JNU_ThrowIOExceptionWithLastError(env, "Truncation failed"); 339 return IOS_THROWN; 340 } 341 return 0; 342 } 343 344 JNIEXPORT jlong JNICALL 345 Java_sun_nio_ch_FileDispatcherImpl_size0(JNIEnv *env, jobject this, jobject fdo) 346 { 347 BOOL result = 0; 348 HANDLE h = (HANDLE)(handleval(env, fdo)); 349 LARGE_INTEGER size; 350 351 result = GetFileSizeEx(h, &size); 352 if (result == 0) { 353 JNU_ThrowIOExceptionWithLastError(env, "Size failed"); 354 return IOS_THROWN; 355 } 356 return (jlong)size.QuadPart; 357 } 358 359 JNIEXPORT jint JNICALL 360 Java_sun_nio_ch_FileDispatcherImpl_lock0(JNIEnv *env, jobject this, jobject fdo, 361 jboolean block, jlong pos, jlong size, 362 jboolean shared) 363 { 364 HANDLE h = (HANDLE)(handleval(env, fdo)); 365 DWORD lowPos = (DWORD)pos; 366 long highPos = (long)(pos >> 32); 367 DWORD lowNumBytes = (DWORD)size; 368 DWORD highNumBytes = (DWORD)(size >> 32); 369 BOOL result; 370 DWORD flags = 0; 371 OVERLAPPED o; 372 o.hEvent = 0; 373 o.Offset = lowPos; 374 o.OffsetHigh = highPos; 375 if (block == JNI_FALSE) { 376 flags |= LOCKFILE_FAIL_IMMEDIATELY; 377 } 378 if (shared == JNI_FALSE) { 379 flags |= LOCKFILE_EXCLUSIVE_LOCK; 380 } 381 result = LockFileEx(h, flags, 0, lowNumBytes, highNumBytes, &o); 382 if (result == 0) { 383 int error = GetLastError(); 384 if (error == ERROR_IO_PENDING) { 385 DWORD dwBytes; 386 result = GetOverlappedResult(h, &o, &dwBytes, TRUE); 387 if (result != 0) { 388 return sun_nio_ch_FileDispatcherImpl_LOCKED; 389 } 390 error = GetLastError(); 391 } 392 if (error != ERROR_LOCK_VIOLATION) { 393 JNU_ThrowIOExceptionWithLastError(env, "Lock failed"); 394 return sun_nio_ch_FileDispatcherImpl_NO_LOCK; 395 } 396 if (flags & LOCKFILE_FAIL_IMMEDIATELY) { 397 return sun_nio_ch_FileDispatcherImpl_NO_LOCK; 398 } 399 JNU_ThrowIOExceptionWithLastError(env, "Lock failed"); 400 return sun_nio_ch_FileDispatcherImpl_NO_LOCK; 401 } 402 return sun_nio_ch_FileDispatcherImpl_LOCKED; 403 } 404 405 JNIEXPORT void JNICALL 406 Java_sun_nio_ch_FileDispatcherImpl_release0(JNIEnv *env, jobject this, 407 jobject fdo, jlong pos, jlong size) 408 { 409 HANDLE h = (HANDLE)(handleval(env, fdo)); 410 DWORD lowPos = (DWORD)pos; 411 long highPos = (long)(pos >> 32); 412 DWORD lowNumBytes = (DWORD)size; 413 DWORD highNumBytes = (DWORD)(size >> 32); 414 BOOL result = 0; 415 OVERLAPPED o; 416 o.hEvent = 0; 417 o.Offset = lowPos; 418 o.OffsetHigh = highPos; 419 result = UnlockFileEx(h, 0, lowNumBytes, highNumBytes, &o); 420 if (result == 0) { 421 int error = GetLastError(); 422 if (error == ERROR_IO_PENDING) { 423 DWORD dwBytes; 424 result = GetOverlappedResult(h, &o, &dwBytes, TRUE); 425 if (result != 0) { 426 return; 427 } 428 error = GetLastError(); 429 } 430 if (error != ERROR_NOT_LOCKED) { 431 JNU_ThrowIOExceptionWithLastError(env, "Release failed"); 432 } 433 } 434 } 435 436 JNIEXPORT void JNICALL 437 Java_sun_nio_ch_FileDispatcherImpl_close0(JNIEnv *env, jclass clazz, jobject fdo) 438 { 439 HANDLE h = (HANDLE)handleval(env, fdo); 440 if (h != INVALID_HANDLE_VALUE) { 441 int result = CloseHandle(h); 442 if (result == 0) 443 JNU_ThrowIOExceptionWithLastError(env, "Close failed"); 444 } 445 } 446 447 JNIEXPORT jlong JNICALL 448 Java_sun_nio_ch_FileDispatcherImpl_duplicateHandle(JNIEnv *env, jclass this, jlong handle) 449 { 450 HANDLE hProcess = GetCurrentProcess(); 451 HANDLE hFile = jlong_to_ptr(handle); 452 HANDLE hResult; 453 BOOL res = DuplicateHandle(hProcess, hFile, hProcess, &hResult, 0, FALSE, 454 DUPLICATE_SAME_ACCESS); 455 if (res == 0) 456 JNU_ThrowIOExceptionWithLastError(env, "DuplicateHandle failed"); 457 return ptr_to_jlong(hResult); 458 }