1 /* 2 * Copyright (c) 2000, 2018, 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 71 if (read > 0) { 72 JVM_callFileReadBytes(env, (jint) read); 73 } 74 75 76 return convertReturnVal(env, (jint)read, JNI_TRUE); 77 } 78 79 JNIEXPORT jlong JNICALL 80 Java_sun_nio_ch_FileDispatcherImpl_readv0(JNIEnv *env, jclass clazz, jobject fdo, 81 jlong address, jint len) 82 { 83 DWORD read = 0; 84 BOOL result = 0; 85 jlong totalRead = 0; 86 LPVOID loc; 87 int i = 0; 88 DWORD num = 0; 89 struct iovec *iovecp = (struct iovec *)jlong_to_ptr(address); 90 HANDLE h = (HANDLE)(handleval(env, fdo)); 91 92 if (h == INVALID_HANDLE_VALUE) { 93 JNU_ThrowIOExceptionWithLastError(env, "Invalid handle"); 94 return IOS_THROWN; 95 } 96 97 for(i=0; i<len; i++) { 98 loc = (LPVOID)jlong_to_ptr(iovecp[i].iov_base); 99 num = iovecp[i].iov_len; 100 result = ReadFile(h, /* File handle to read */ 101 loc, /* address to put data */ 102 num, /* number of bytes to read */ 103 &read, /* number of bytes read */ 104 NULL); /* no overlapped struct */ 105 if (read > 0) { 106 totalRead += read; 107 JVM_callFileReadBytes(env, (jint) read); 108 } 109 if (read < num) { 110 break; 111 } 112 } 113 114 if (result == 0) { 115 int error = GetLastError(); 116 if (error == ERROR_BROKEN_PIPE) { 117 return IOS_EOF; 118 } 119 if (error == ERROR_NO_DATA) { 120 return IOS_UNAVAILABLE; 121 } 122 JNU_ThrowIOExceptionWithLastError(env, "Read failed"); 123 return IOS_THROWN; 124 } 125 126 return convertLongReturnVal(env, totalRead, JNI_TRUE); 127 } 128 129 JNIEXPORT jint JNICALL 130 Java_sun_nio_ch_FileDispatcherImpl_pread0(JNIEnv *env, jclass clazz, jobject fdo, 131 jlong address, jint len, jlong offset) 132 { 133 DWORD read = 0; 134 BOOL result = 0; 135 HANDLE h = (HANDLE)(handleval(env, fdo)); 136 LARGE_INTEGER currPos; 137 OVERLAPPED ov; 138 139 if (h == INVALID_HANDLE_VALUE) { 140 JNU_ThrowIOExceptionWithLastError(env, "Invalid handle"); 141 return IOS_THROWN; 142 } 143 144 currPos.QuadPart = 0; 145 result = SetFilePointerEx(h, currPos, &currPos, FILE_CURRENT); 146 if (result == 0) { 147 JNU_ThrowIOExceptionWithLastError(env, "Seek failed"); 148 return IOS_THROWN; 149 } 150 151 ZeroMemory(&ov, sizeof(ov)); 152 ov.Offset = (DWORD)offset; 153 ov.OffsetHigh = (DWORD)(offset >> 32); 154 155 result = ReadFile(h, /* File handle to read */ 156 (LPVOID)address, /* address to put data */ 157 len, /* number of bytes to read */ 158 &read, /* number of bytes read */ 159 &ov); /* position to read from */ 160 161 if (read > 0) { 162 JVM_callFileReadBytes(env, (jint) read); 163 } 164 165 if (result == 0) { 166 int error = GetLastError(); 167 if (error == ERROR_BROKEN_PIPE) { 168 return IOS_EOF; 169 } 170 if (error == ERROR_NO_DATA) { 171 return IOS_UNAVAILABLE; 172 } 173 if (error != ERROR_HANDLE_EOF) { 174 JNU_ThrowIOExceptionWithLastError(env, "Read failed"); 175 return IOS_THROWN; 176 } 177 } 178 179 result = SetFilePointerEx(h, currPos, NULL, FILE_BEGIN); 180 if (result == 0) { 181 JNU_ThrowIOExceptionWithLastError(env, "Seek failed"); 182 return IOS_THROWN; 183 } 184 185 return convertReturnVal(env, (jint)read, JNI_TRUE); 186 } 187 188 JNIEXPORT jint JNICALL 189 Java_sun_nio_ch_FileDispatcherImpl_write0(JNIEnv *env, jclass clazz, jobject fdo, 190 jlong address, jint len, jboolean append) 191 { 192 BOOL result = 0; 193 DWORD written = 0; 194 HANDLE h = (HANDLE)(handleval(env, fdo)); 195 196 if (h != INVALID_HANDLE_VALUE) { 197 OVERLAPPED ov; 198 LPOVERLAPPED lpOv; 199 if (append == JNI_TRUE) { 200 ZeroMemory(&ov, sizeof(ov)); 201 ov.Offset = (DWORD)0xFFFFFFFF; 202 ov.OffsetHigh = (DWORD)0xFFFFFFFF; 203 lpOv = &ov; 204 } else { 205 lpOv = NULL; 206 } 207 result = WriteFile(h, /* File handle to write */ 208 (LPCVOID)address, /* pointer to the buffer */ 209 len, /* number of bytes to write */ 210 &written, /* receives number of bytes written */ 211 lpOv); /* overlapped struct */ 212 JVM_callFileWriteBytes(env, (jint) written); 213 214 } 215 216 if ((h == INVALID_HANDLE_VALUE) || (result == 0)) { 217 JNU_ThrowIOExceptionWithLastError(env, "Write failed"); 218 return IOS_THROWN; 219 } 220 221 return convertReturnVal(env, (jint)written, JNI_FALSE); 222 } 223 224 JNIEXPORT jlong JNICALL 225 Java_sun_nio_ch_FileDispatcherImpl_writev0(JNIEnv *env, jclass clazz, jobject fdo, 226 jlong address, jint len, jboolean append) 227 { 228 BOOL result = 0; 229 DWORD written = 0; 230 HANDLE h = (HANDLE)(handleval(env, fdo)); 231 jlong totalWritten = 0; 232 233 if (h != INVALID_HANDLE_VALUE) { 234 LPVOID loc; 235 int i = 0; 236 DWORD num = 0; 237 struct iovec *iovecp = (struct iovec *)jlong_to_ptr(address); 238 OVERLAPPED ov; 239 LPOVERLAPPED lpOv; 240 if (append == JNI_TRUE) { 241 ZeroMemory(&ov, sizeof(ov)); 242 ov.Offset = (DWORD)0xFFFFFFFF; 243 ov.OffsetHigh = (DWORD)0xFFFFFFFF; 244 lpOv = &ov; 245 } else { 246 lpOv = NULL; 247 } 248 for(i=0; i<len; i++) { 249 loc = (LPVOID)jlong_to_ptr(iovecp[i].iov_base); 250 num = iovecp[i].iov_len; 251 result = WriteFile(h, /* File handle to write */ 252 loc, /* pointers to the buffers */ 253 num, /* number of bytes to write */ 254 &written,/* receives number of bytes written */ 255 lpOv); /* overlapped struct */ 256 if (written > 0) { 257 totalWritten += written; 258 JVM_callFileWriteBytes(env, (jint) written); 259 } 260 if (written < num) { 261 break; 262 } 263 } 264 } 265 266 if ((h == INVALID_HANDLE_VALUE) || (result == 0)) { 267 JNU_ThrowIOExceptionWithLastError(env, "Write failed"); 268 return IOS_THROWN; 269 } 270 271 return convertLongReturnVal(env, totalWritten, JNI_FALSE); 272 } 273 274 JNIEXPORT jint JNICALL 275 Java_sun_nio_ch_FileDispatcherImpl_pwrite0(JNIEnv *env, jclass clazz, jobject fdo, 276 jlong address, jint len, jlong offset) 277 { 278 BOOL result = 0; 279 DWORD written = 0; 280 HANDLE h = (HANDLE)(handleval(env, fdo)); 281 LARGE_INTEGER currPos; 282 OVERLAPPED ov; 283 284 currPos.QuadPart = 0; 285 result = SetFilePointerEx(h, currPos, &currPos, FILE_CURRENT); 286 if (result == 0) { 287 JNU_ThrowIOExceptionWithLastError(env, "Seek failed"); 288 return IOS_THROWN; 289 } 290 291 ZeroMemory(&ov, sizeof(ov)); 292 ov.Offset = (DWORD)offset; 293 ov.OffsetHigh = (DWORD)(offset >> 32); 294 295 result = WriteFile(h, /* File handle to write */ 296 (LPCVOID)address, /* pointer to the buffer */ 297 len, /* number of bytes to write */ 298 &written, /* receives number of bytes written */ 299 &ov); /* position to write at */ 300 301 if (written > 0) { 302 JVM_callFileWriteBytes(env, (jint) written); 303 } 304 305 if ((h == INVALID_HANDLE_VALUE) || (result == 0)) { 306 JNU_ThrowIOExceptionWithLastError(env, "Write failed"); 307 return IOS_THROWN; 308 } 309 310 result = SetFilePointerEx(h, currPos, NULL, FILE_BEGIN); 311 if (result == 0) { 312 JNU_ThrowIOExceptionWithLastError(env, "Seek failed"); 313 return IOS_THROWN; 314 } 315 316 return convertReturnVal(env, (jint)written, JNI_FALSE); 317 } 318 319 JNIEXPORT jlong JNICALL 320 Java_sun_nio_ch_FileDispatcherImpl_seek0(JNIEnv *env, jclass clazz, 321 jobject fdo, jlong offset) 322 { 323 BOOL result = 0; 324 HANDLE h = (HANDLE)(handleval(env, fdo)); 325 LARGE_INTEGER where; 326 DWORD whence; 327 328 if (offset < 0) { 329 where.QuadPart = 0; 330 whence = FILE_CURRENT; 331 } else { 332 where.QuadPart = offset; 333 whence = FILE_BEGIN; 334 } 335 336 result = SetFilePointerEx(h, where, &where, whence); 337 if (result == 0) { 338 JNU_ThrowIOExceptionWithLastError(env, "SetFilePointerEx failed"); 339 return IOS_THROWN; 340 } 341 return (jlong)where.QuadPart; 342 } 343 344 JNIEXPORT jint JNICALL 345 Java_sun_nio_ch_FileDispatcherImpl_force0(JNIEnv *env, jobject this, 346 jobject fdo, jboolean md) 347 { 348 int result = 0; 349 HANDLE h = (HANDLE)(handleval(env, fdo)); 350 351 if (h != INVALID_HANDLE_VALUE) { 352 result = FlushFileBuffers(h); 353 if (result == 0) { 354 int error = GetLastError(); 355 if (error != ERROR_ACCESS_DENIED) { 356 JNU_ThrowIOExceptionWithLastError(env, "Force failed"); 357 return IOS_THROWN; 358 } 359 } 360 } else { 361 JNU_ThrowIOExceptionWithLastError(env, "Force failed"); 362 return IOS_THROWN; 363 } 364 return 0; 365 } 366 367 JNIEXPORT jint JNICALL 368 Java_sun_nio_ch_FileDispatcherImpl_truncate0(JNIEnv *env, jobject this, 369 jobject fdo, jlong size) 370 { 371 BOOL result = 0; 372 HANDLE h = (HANDLE)(handleval(env, fdo)); 373 FILE_END_OF_FILE_INFO eofInfo; 374 375 eofInfo.EndOfFile.QuadPart = size; 376 result = SetFileInformationByHandle(h, 377 FileEndOfFileInfo, 378 &eofInfo, 379 sizeof(eofInfo)); 380 if (result == 0) { 381 JNU_ThrowIOExceptionWithLastError(env, "Truncation failed"); 382 return IOS_THROWN; 383 } 384 return 0; 385 } 386 387 JNIEXPORT jlong JNICALL 388 Java_sun_nio_ch_FileDispatcherImpl_size0(JNIEnv *env, jobject this, jobject fdo) 389 { 390 BOOL result = 0; 391 HANDLE h = (HANDLE)(handleval(env, fdo)); 392 LARGE_INTEGER size; 393 394 result = GetFileSizeEx(h, &size); 395 if (result == 0) { 396 JNU_ThrowIOExceptionWithLastError(env, "Size failed"); 397 return IOS_THROWN; 398 } 399 return (jlong)size.QuadPart; 400 } 401 402 JNIEXPORT jint JNICALL 403 Java_sun_nio_ch_FileDispatcherImpl_lock0(JNIEnv *env, jobject this, jobject fdo, 404 jboolean block, jlong pos, jlong size, 405 jboolean shared) 406 { 407 HANDLE h = (HANDLE)(handleval(env, fdo)); 408 DWORD lowPos = (DWORD)pos; 409 long highPos = (long)(pos >> 32); 410 DWORD lowNumBytes = (DWORD)size; 411 DWORD highNumBytes = (DWORD)(size >> 32); 412 BOOL result; 413 DWORD flags = 0; 414 OVERLAPPED o; 415 o.hEvent = 0; 416 o.Offset = lowPos; 417 o.OffsetHigh = highPos; 418 if (block == JNI_FALSE) { 419 flags |= LOCKFILE_FAIL_IMMEDIATELY; 420 } 421 if (shared == JNI_FALSE) { 422 flags |= LOCKFILE_EXCLUSIVE_LOCK; 423 } 424 result = LockFileEx(h, flags, 0, lowNumBytes, highNumBytes, &o); 425 if (result == 0) { 426 int error = GetLastError(); 427 if (error == ERROR_IO_PENDING) { 428 DWORD dwBytes; 429 result = GetOverlappedResult(h, &o, &dwBytes, TRUE); 430 if (result != 0) { 431 return sun_nio_ch_FileDispatcherImpl_LOCKED; 432 } 433 error = GetLastError(); 434 } 435 if (error != ERROR_LOCK_VIOLATION) { 436 JNU_ThrowIOExceptionWithLastError(env, "Lock failed"); 437 return sun_nio_ch_FileDispatcherImpl_NO_LOCK; 438 } 439 if (flags & LOCKFILE_FAIL_IMMEDIATELY) { 440 return sun_nio_ch_FileDispatcherImpl_NO_LOCK; 441 } 442 JNU_ThrowIOExceptionWithLastError(env, "Lock failed"); 443 return sun_nio_ch_FileDispatcherImpl_NO_LOCK; 444 } 445 return sun_nio_ch_FileDispatcherImpl_LOCKED; 446 } 447 448 JNIEXPORT void JNICALL 449 Java_sun_nio_ch_FileDispatcherImpl_release0(JNIEnv *env, jobject this, 450 jobject fdo, jlong pos, jlong size) 451 { 452 HANDLE h = (HANDLE)(handleval(env, fdo)); 453 DWORD lowPos = (DWORD)pos; 454 long highPos = (long)(pos >> 32); 455 DWORD lowNumBytes = (DWORD)size; 456 DWORD highNumBytes = (DWORD)(size >> 32); 457 BOOL result = 0; 458 OVERLAPPED o; 459 o.hEvent = 0; 460 o.Offset = lowPos; 461 o.OffsetHigh = highPos; 462 result = UnlockFileEx(h, 0, lowNumBytes, highNumBytes, &o); 463 if (result == 0) { 464 int error = GetLastError(); 465 if (error == ERROR_IO_PENDING) { 466 DWORD dwBytes; 467 result = GetOverlappedResult(h, &o, &dwBytes, TRUE); 468 if (result != 0) { 469 return; 470 } 471 error = GetLastError(); 472 } 473 if (error != ERROR_NOT_LOCKED) { 474 JNU_ThrowIOExceptionWithLastError(env, "Release failed"); 475 } 476 } 477 } 478 479 JNIEXPORT void JNICALL 480 Java_sun_nio_ch_FileDispatcherImpl_close0(JNIEnv *env, jclass clazz, jobject fdo) 481 { 482 HANDLE h = (HANDLE)handleval(env, fdo); 483 if (h != INVALID_HANDLE_VALUE) { 484 int result = CloseHandle(h); 485 if (result == 0) 486 JNU_ThrowIOExceptionWithLastError(env, "Close failed"); 487 } 488 } 489 490 JNIEXPORT jlong JNICALL 491 Java_sun_nio_ch_FileDispatcherImpl_duplicateHandle(JNIEnv *env, jclass this, jlong handle) 492 { 493 HANDLE hProcess = GetCurrentProcess(); 494 HANDLE hFile = jlong_to_ptr(handle); 495 HANDLE hResult; 496 BOOL res = DuplicateHandle(hProcess, hFile, hProcess, &hResult, 0, FALSE, 497 DUPLICATE_SAME_ACCESS); 498 if (res == 0) 499 JNU_ThrowIOExceptionWithLastError(env, "DuplicateHandle failed"); 500 return ptr_to_jlong(hResult); 501 } 502 503 JNIEXPORT jint JNICALL 504 Java_sun_nio_ch_FileDispatcherImpl_setDirect0(JNIEnv *env, jclass this, 505 jobject fdObj, jobject buffer) 506 { 507 jint result = -1; 508 509 HANDLE orig = (HANDLE)(handleval(env, fdObj)); 510 511 HANDLE modify = ReOpenFile(orig, 0, 0, 512 FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH); 513 514 if (modify != INVALID_HANDLE_VALUE) { 515 DWORD sectorsPerCluster; 516 DWORD bytesPerSector; 517 DWORD numberOfFreeClusters; 518 DWORD totalNumberOfClusters; 519 LPCWSTR lpRootPathName = (*env)->GetDirectBufferAddress(env, buffer); 520 BOOL res = GetDiskFreeSpaceW(lpRootPathName, 521 §orsPerCluster, 522 &bytesPerSector, 523 &numberOfFreeClusters, 524 &totalNumberOfClusters); 525 if (res == 0) { 526 JNU_ThrowIOExceptionWithLastError(env, "DirectIO setup failed"); 527 } 528 result = bytesPerSector; 529 } 530 return result; 531 }