1 /* 2 * Copyright (c) 2000, 2009, 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 DWORD lowPos = 0; 130 long highPos = 0; 131 DWORD lowOffset = 0; 132 long highOffset = 0; 133 134 if (h == INVALID_HANDLE_VALUE) { 135 JNU_ThrowIOExceptionWithLastError(env, "Invalid handle"); 136 return IOS_THROWN; 137 } 138 139 lowPos = SetFilePointer(h, 0, &highPos, FILE_CURRENT); 140 if (lowPos == ((DWORD)-1)) { 141 if (GetLastError() != ERROR_SUCCESS) { 142 JNU_ThrowIOExceptionWithLastError(env, "Seek failed"); 143 return IOS_THROWN; 144 } 145 } 146 147 lowOffset = (DWORD)offset; 148 highOffset = (DWORD)(offset >> 32); 149 lowOffset = SetFilePointer(h, lowOffset, &highOffset, FILE_BEGIN); 150 if (lowOffset == ((DWORD)-1)) { 151 if (GetLastError() != ERROR_SUCCESS) { 152 JNU_ThrowIOExceptionWithLastError(env, "Seek failed"); 153 return IOS_THROWN; 154 } 155 } 156 157 result = ReadFile(h, /* File handle to read */ 158 (LPVOID)address, /* address to put data */ 159 len, /* number of bytes to read */ 160 &read, /* number of bytes read */ 161 NULL); /* struct with offset */ 162 163 if (result == 0) { 164 int error = GetLastError(); 165 if (error == ERROR_BROKEN_PIPE) { 166 return IOS_EOF; 167 } 168 if (error == ERROR_NO_DATA) { 169 return IOS_UNAVAILABLE; 170 } 171 JNU_ThrowIOExceptionWithLastError(env, "Read failed"); 172 return IOS_THROWN; 173 } 174 175 lowPos = SetFilePointer(h, lowPos, &highPos, FILE_BEGIN); 176 if (lowPos == ((DWORD)-1)) { 177 if (GetLastError() != ERROR_SUCCESS) { 178 JNU_ThrowIOExceptionWithLastError(env, "Seek failed"); 179 return IOS_THROWN; 180 } 181 } 182 return convertReturnVal(env, (jint)read, JNI_TRUE); 183 } 184 185 JNIEXPORT jint JNICALL 186 Java_sun_nio_ch_FileDispatcherImpl_write0(JNIEnv *env, jclass clazz, jobject fdo, 187 jlong address, jint len, jboolean append) 188 { 189 BOOL result = 0; 190 DWORD written = 0; 191 HANDLE h = (HANDLE)(handleval(env, fdo)); 192 193 if (h != INVALID_HANDLE_VALUE) { 194 OVERLAPPED ov; 195 LPOVERLAPPED lpOv; 196 if (append == JNI_TRUE) { 197 ov.Offset = (DWORD)0xFFFFFFFF; 198 ov.OffsetHigh = (DWORD)0xFFFFFFFF; 199 ov.hEvent = NULL; 200 lpOv = &ov; 201 } else { 202 lpOv = NULL; 203 } 204 result = WriteFile(h, /* File handle to write */ 205 (LPCVOID)address, /* pointers to the buffers */ 206 len, /* number of bytes to write */ 207 &written, /* receives number of bytes written */ 208 lpOv); /* overlapped struct */ 209 } 210 211 if ((h == INVALID_HANDLE_VALUE) || (result == 0)) { 212 JNU_ThrowIOExceptionWithLastError(env, "Write failed"); 213 } 214 215 return convertReturnVal(env, (jint)written, JNI_FALSE); 216 } 217 218 JNIEXPORT jlong JNICALL 219 Java_sun_nio_ch_FileDispatcherImpl_writev0(JNIEnv *env, jclass clazz, jobject fdo, 220 jlong address, jint len, jboolean append) 221 { 222 BOOL result = 0; 223 DWORD written = 0; 224 HANDLE h = (HANDLE)(handleval(env, fdo)); 225 jlong totalWritten = 0; 226 227 if (h != INVALID_HANDLE_VALUE) { 228 LPVOID loc; 229 int i = 0; 230 DWORD num = 0; 231 struct iovec *iovecp = (struct iovec *)jlong_to_ptr(address); 232 OVERLAPPED ov; 233 LPOVERLAPPED lpOv; 234 if (append == JNI_TRUE) { 235 ov.Offset = (DWORD)0xFFFFFFFF; 236 ov.OffsetHigh = (DWORD)0xFFFFFFFF; 237 ov.hEvent = NULL; 238 lpOv = &ov; 239 } else { 240 lpOv = NULL; 241 } 242 for(i=0; i<len; i++) { 243 loc = (LPVOID)jlong_to_ptr(iovecp[i].iov_base); 244 num = iovecp[i].iov_len; 245 result = WriteFile(h, /* File handle to write */ 246 loc, /* pointers to the buffers */ 247 num, /* number of bytes to write */ 248 &written,/* receives number of bytes written */ 249 lpOv); /* overlapped struct */ 250 if (written > 0) { 251 totalWritten += written; 252 } 253 if (written < num) { 254 break; 255 } 256 } 257 } 258 259 if ((h == INVALID_HANDLE_VALUE) || (result == 0)) { 260 JNU_ThrowIOExceptionWithLastError(env, "Write failed"); 261 } 262 263 return convertLongReturnVal(env, totalWritten, JNI_FALSE); 264 } 265 266 JNIEXPORT jint JNICALL 267 Java_sun_nio_ch_FileDispatcherImpl_pwrite0(JNIEnv *env, jclass clazz, jobject fdo, 268 jlong address, jint len, jlong offset) 269 { 270 BOOL result = 0; 271 DWORD written = 0; 272 HANDLE h = (HANDLE)(handleval(env, fdo)); 273 DWORD lowPos = 0; 274 long highPos = 0; 275 DWORD lowOffset = 0; 276 long highOffset = 0; 277 278 lowPos = SetFilePointer(h, 0, &highPos, FILE_CURRENT); 279 if (lowPos == ((DWORD)-1)) { 280 if (GetLastError() != ERROR_SUCCESS) { 281 JNU_ThrowIOExceptionWithLastError(env, "Seek failed"); 282 return IOS_THROWN; 283 } 284 } 285 286 lowOffset = (DWORD)offset; 287 highOffset = (DWORD)(offset >> 32); 288 lowOffset = SetFilePointer(h, lowOffset, &highOffset, FILE_BEGIN); 289 if (lowOffset == ((DWORD)-1)) { 290 if (GetLastError() != ERROR_SUCCESS) { 291 JNU_ThrowIOExceptionWithLastError(env, "Seek failed"); 292 return IOS_THROWN; 293 } 294 } 295 296 result = WriteFile(h, /* File handle to write */ 297 (LPCVOID)address, /* pointers to the buffers */ 298 len, /* number of bytes to write */ 299 &written, /* receives number of bytes written */ 300 NULL); /* no overlapped struct */ 301 302 if ((h == INVALID_HANDLE_VALUE) || (result == 0)) { 303 JNU_ThrowIOExceptionWithLastError(env, "Write failed"); 304 return IOS_THROWN; 305 } 306 307 lowPos = SetFilePointer(h, lowPos, &highPos, FILE_BEGIN); 308 if (lowPos == ((DWORD)-1)) { 309 if (GetLastError() != ERROR_SUCCESS) { 310 JNU_ThrowIOExceptionWithLastError(env, "Seek failed"); 311 return IOS_THROWN; 312 } 313 } 314 315 return convertReturnVal(env, (jint)written, JNI_FALSE); 316 } 317 318 JNIEXPORT jint JNICALL 319 Java_sun_nio_ch_FileDispatcherImpl_force0(JNIEnv *env, jobject this, 320 jobject fdo, jboolean md) 321 { 322 int result = 0; 323 HANDLE h = (HANDLE)(handleval(env, fdo)); 324 325 if (h != INVALID_HANDLE_VALUE) { 326 result = FlushFileBuffers(h); 327 if (result == 0) { 328 int error = GetLastError(); 329 if (error != ERROR_ACCESS_DENIED) { 330 JNU_ThrowIOExceptionWithLastError(env, "Force failed"); 331 return IOS_THROWN; 332 } 333 } 334 } else { 335 JNU_ThrowIOExceptionWithLastError(env, "Force failed"); 336 return IOS_THROWN; 337 } 338 return 0; 339 } 340 341 JNIEXPORT jint JNICALL 342 Java_sun_nio_ch_FileDispatcherImpl_truncate0(JNIEnv *env, jobject this, 343 jobject fdo, jlong size) 344 { 345 DWORD lowPos = 0; 346 long highPos = 0; 347 BOOL result = 0; 348 HANDLE h = (HANDLE)(handleval(env, fdo)); 349 350 lowPos = (DWORD)size; 351 highPos = (long)(size >> 32); 352 lowPos = SetFilePointer(h, lowPos, &highPos, FILE_BEGIN); 353 if (lowPos == ((DWORD)-1)) { 354 if (GetLastError() != ERROR_SUCCESS) { 355 JNU_ThrowIOExceptionWithLastError(env, "Truncation failed"); 356 return IOS_THROWN; 357 } 358 } 359 result = SetEndOfFile(h); 360 if (result == 0) { 361 JNU_ThrowIOExceptionWithLastError(env, "Truncation failed"); 362 return IOS_THROWN; 363 } 364 return 0; 365 } 366 367 JNIEXPORT jlong JNICALL 368 Java_sun_nio_ch_FileDispatcherImpl_size0(JNIEnv *env, jobject this, jobject fdo) 369 { 370 DWORD sizeLow = 0; 371 DWORD sizeHigh = 0; 372 HANDLE h = (HANDLE)(handleval(env, fdo)); 373 374 sizeLow = GetFileSize(h, &sizeHigh); 375 if (sizeLow == ((DWORD)-1)) { 376 if (GetLastError() != ERROR_SUCCESS) { 377 JNU_ThrowIOExceptionWithLastError(env, "Size failed"); 378 return IOS_THROWN; 379 } 380 } 381 return (((jlong)sizeHigh) << 32) | sizeLow; 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_LOCK_VIOLATION) { 410 JNU_ThrowIOExceptionWithLastError(env, "Lock failed"); 411 return sun_nio_ch_FileDispatcherImpl_NO_LOCK; 412 } 413 if (flags & LOCKFILE_FAIL_IMMEDIATELY) { 414 return sun_nio_ch_FileDispatcherImpl_NO_LOCK; 415 } 416 JNU_ThrowIOExceptionWithLastError(env, "Lock failed"); 417 return sun_nio_ch_FileDispatcherImpl_NO_LOCK; 418 } 419 return sun_nio_ch_FileDispatcherImpl_LOCKED; 420 } 421 422 JNIEXPORT void JNICALL 423 Java_sun_nio_ch_FileDispatcherImpl_release0(JNIEnv *env, jobject this, 424 jobject fdo, jlong pos, jlong size) 425 { 426 HANDLE h = (HANDLE)(handleval(env, fdo)); 427 DWORD lowPos = (DWORD)pos; 428 long highPos = (long)(pos >> 32); 429 DWORD lowNumBytes = (DWORD)size; 430 DWORD highNumBytes = (DWORD)(size >> 32); 431 jint result = 0; 432 OVERLAPPED o; 433 o.hEvent = 0; 434 o.Offset = lowPos; 435 o.OffsetHigh = highPos; 436 result = UnlockFileEx(h, 0, lowNumBytes, highNumBytes, &o); 437 if (result == 0 && GetLastError() != ERROR_NOT_LOCKED) { 438 JNU_ThrowIOExceptionWithLastError(env, "Release failed"); 439 } 440 } 441 442 static void closeFile(JNIEnv *env, jlong fd) { 443 HANDLE h = (HANDLE)fd; 444 if (h != INVALID_HANDLE_VALUE) { 445 int result = CloseHandle(h); 446 if (result < 0) 447 JNU_ThrowIOExceptionWithLastError(env, "Close failed"); 448 } 449 } 450 451 JNIEXPORT void JNICALL 452 Java_sun_nio_ch_FileDispatcherImpl_close0(JNIEnv *env, jclass clazz, jobject fdo) 453 { 454 jlong fd = handleval(env, fdo); 455 closeFile(env, fd); 456 } 457 458 JNIEXPORT void JNICALL 459 Java_sun_nio_ch_FileDispatcherImpl_closeByHandle(JNIEnv *env, jclass clazz, 460 jlong fd) 461 { 462 closeFile(env, fd); 463 } 464 465 JNIEXPORT jlong JNICALL 466 Java_sun_nio_ch_FileDispatcherImpl_duplicateHandle(JNIEnv *env, jclass this, jlong handle) 467 { 468 HANDLE hProcess = GetCurrentProcess(); 469 HANDLE hFile = jlong_to_ptr(handle); 470 HANDLE hResult; 471 BOOL res = DuplicateHandle(hProcess, hFile, hProcess, &hResult, 0, FALSE, 472 DUPLICATE_SAME_ACCESS); 473 if (res == 0) 474 JNU_ThrowIOExceptionWithLastError(env, "DuplicateHandle failed"); 475 return ptr_to_jlong(hResult); 476 }