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 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 jlong JNICALL 302 Java_sun_nio_ch_FileDispatcherImpl_seek0(JNIEnv *env, jclass clazz, 303 jobject fdo, jlong offset) 304 { 305 BOOL result = 0; 306 HANDLE h = (HANDLE)(handleval(env, fdo)); 307 LARGE_INTEGER where; 308 DWORD whence; 309 310 if (offset < 0) { 311 where.QuadPart = 0; 312 whence = FILE_CURRENT; 313 } else { 314 where.QuadPart = offset; 315 whence = FILE_BEGIN; 316 } 317 318 result = SetFilePointerEx(h, where, &where, whence); 319 if (result == 0) { 320 JNU_ThrowIOExceptionWithLastError(env, "SetFilePointerEx failed"); 321 return IOS_THROWN; 322 } 323 return (jlong)where.QuadPart; 324 } 325 326 JNIEXPORT jint JNICALL 327 Java_sun_nio_ch_FileDispatcherImpl_force0(JNIEnv *env, jobject this, 328 jobject fdo, jboolean md) 329 { 330 int result = 0; 331 HANDLE h = (HANDLE)(handleval(env, fdo)); 332 333 if (h != INVALID_HANDLE_VALUE) { 334 result = FlushFileBuffers(h); 335 if (result == 0) { 336 int error = GetLastError(); 337 if (error != ERROR_ACCESS_DENIED) { 338 JNU_ThrowIOExceptionWithLastError(env, "Force failed"); 339 return IOS_THROWN; 340 } 341 } 342 } else { 343 JNU_ThrowIOExceptionWithLastError(env, "Force failed"); 344 return IOS_THROWN; 345 } 346 return 0; 347 } 348 349 JNIEXPORT jint JNICALL 350 Java_sun_nio_ch_FileDispatcherImpl_truncate0(JNIEnv *env, jobject this, 351 jobject fdo, jlong size) 352 { 353 BOOL result = 0; 354 HANDLE h = (HANDLE)(handleval(env, fdo)); 355 FILE_END_OF_FILE_INFO eofInfo; 356 357 eofInfo.EndOfFile.QuadPart = size; 358 result = SetFileInformationByHandle(h, 359 FileEndOfFileInfo, 360 &eofInfo, 361 sizeof(eofInfo)); 362 if (result == 0) { 363 JNU_ThrowIOExceptionWithLastError(env, "Truncation failed"); 364 return IOS_THROWN; 365 } 366 return 0; 367 } 368 369 JNIEXPORT jlong JNICALL 370 Java_sun_nio_ch_FileDispatcherImpl_size0(JNIEnv *env, jobject this, jobject fdo) 371 { 372 BOOL result = 0; 373 HANDLE h = (HANDLE)(handleval(env, fdo)); 374 LARGE_INTEGER size; 375 376 result = GetFileSizeEx(h, &size); 377 if (result == 0) { 378 JNU_ThrowIOExceptionWithLastError(env, "Size failed"); 379 return IOS_THROWN; 380 } 381 return (jlong)size.QuadPart; 382 } 383 384 JNIEXPORT jint JNICALL 385 Java_sun_nio_ch_FileDispatcherImpl_lock0(JNIEnv *env, jobject this, jobject fdo, 386 jboolean block, jlong pos, jlong size, 387 jboolean shared) 388 { 389 HANDLE h = (HANDLE)(handleval(env, fdo)); 390 DWORD lowPos = (DWORD)pos; 391 long highPos = (long)(pos >> 32); 392 DWORD lowNumBytes = (DWORD)size; 393 DWORD highNumBytes = (DWORD)(size >> 32); 394 BOOL result; 395 DWORD flags = 0; 396 OVERLAPPED o; 397 o.hEvent = 0; 398 o.Offset = lowPos; 399 o.OffsetHigh = highPos; 400 if (block == JNI_FALSE) { 401 flags |= LOCKFILE_FAIL_IMMEDIATELY; 402 } 403 if (shared == JNI_FALSE) { 404 flags |= LOCKFILE_EXCLUSIVE_LOCK; 405 } 406 result = LockFileEx(h, flags, 0, lowNumBytes, highNumBytes, &o); 407 if (result == 0) { 408 int error = GetLastError(); 409 if (error == ERROR_IO_PENDING) { 410 DWORD dwBytes; 411 result = GetOverlappedResult(h, &o, &dwBytes, TRUE); 412 if (result != 0) { 413 return sun_nio_ch_FileDispatcherImpl_LOCKED; 414 } 415 error = GetLastError(); 416 } 417 if (error != ERROR_LOCK_VIOLATION) { 418 JNU_ThrowIOExceptionWithLastError(env, "Lock failed"); 419 return sun_nio_ch_FileDispatcherImpl_NO_LOCK; 420 } 421 if (flags & LOCKFILE_FAIL_IMMEDIATELY) { 422 return sun_nio_ch_FileDispatcherImpl_NO_LOCK; 423 } 424 JNU_ThrowIOExceptionWithLastError(env, "Lock failed"); 425 return sun_nio_ch_FileDispatcherImpl_NO_LOCK; 426 } 427 return sun_nio_ch_FileDispatcherImpl_LOCKED; 428 } 429 430 JNIEXPORT void JNICALL 431 Java_sun_nio_ch_FileDispatcherImpl_release0(JNIEnv *env, jobject this, 432 jobject fdo, jlong pos, jlong size) 433 { 434 HANDLE h = (HANDLE)(handleval(env, fdo)); 435 DWORD lowPos = (DWORD)pos; 436 long highPos = (long)(pos >> 32); 437 DWORD lowNumBytes = (DWORD)size; 438 DWORD highNumBytes = (DWORD)(size >> 32); 439 BOOL result = 0; 440 OVERLAPPED o; 441 o.hEvent = 0; 442 o.Offset = lowPos; 443 o.OffsetHigh = highPos; 444 result = UnlockFileEx(h, 0, lowNumBytes, highNumBytes, &o); 445 if (result == 0) { 446 int error = GetLastError(); 447 if (error == ERROR_IO_PENDING) { 448 DWORD dwBytes; 449 result = GetOverlappedResult(h, &o, &dwBytes, TRUE); 450 if (result != 0) { 451 return; 452 } 453 error = GetLastError(); 454 } 455 if (error != ERROR_NOT_LOCKED) { 456 JNU_ThrowIOExceptionWithLastError(env, "Release failed"); 457 } 458 } 459 } 460 461 JNIEXPORT void JNICALL 462 Java_sun_nio_ch_FileDispatcherImpl_close0(JNIEnv *env, jclass clazz, jobject fdo) 463 { 464 HANDLE h = (HANDLE)handleval(env, fdo); 465 if (h != INVALID_HANDLE_VALUE) { 466 int result = CloseHandle(h); 467 if (result == 0) 468 JNU_ThrowIOExceptionWithLastError(env, "Close failed"); 469 } 470 } 471 472 JNIEXPORT jlong JNICALL 473 Java_sun_nio_ch_FileDispatcherImpl_duplicateHandle(JNIEnv *env, jclass this, jlong handle) 474 { 475 HANDLE hProcess = GetCurrentProcess(); 476 HANDLE hFile = jlong_to_ptr(handle); 477 HANDLE hResult; 478 BOOL res = DuplicateHandle(hProcess, hFile, hProcess, &hResult, 0, FALSE, 479 DUPLICATE_SAME_ACCESS); 480 if (res == 0) 481 JNU_ThrowIOExceptionWithLastError(env, "DuplicateHandle failed"); 482 return ptr_to_jlong(hResult); 483 } 484 485 JNIEXPORT jint JNICALL 486 Java_sun_nio_ch_FileDispatcherImpl_setDirect0(JNIEnv *env, jclass this, 487 jobject fdObj, jobject buffer) 488 { 489 jint result = -1; 490 491 HANDLE orig = (HANDLE)(handleval(env, fdObj)); 492 493 HANDLE modify = ReOpenFile(orig, 0, 0, 494 FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH); 495 496 if (modify != INVALID_HANDLE_VALUE) { 497 DWORD sectorsPerCluster; 498 DWORD bytesPerSector; 499 DWORD numberOfFreeClusters; 500 DWORD totalNumberOfClusters; 501 LPCWSTR lpRootPathName = (*env)->GetDirectBufferAddress(env, buffer); 502 BOOL res = GetDiskFreeSpaceW(lpRootPathName, 503 §orsPerCluster, 504 &bytesPerSector, 505 &numberOfFreeClusters, 506 &totalNumberOfClusters); 507 if (res == 0) { 508 JNU_ThrowIOExceptionWithLastError(env, "DirectIO setup failed"); 509 } 510 result = bytesPerSector; 511 } 512 return result; 513 }