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
Java_sun_nio_ch_FileDispatcherImpl_read0(JNIEnv * env,jclass clazz,jobject fdo,jlong address,jint len)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
Java_sun_nio_ch_FileDispatcherImpl_readv0(JNIEnv * env,jclass clazz,jobject fdo,jlong address,jint len)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
Java_sun_nio_ch_FileDispatcherImpl_pread0(JNIEnv * env,jclass clazz,jobject fdo,jlong address,jint len,jlong offset)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
Java_sun_nio_ch_FileDispatcherImpl_write0(JNIEnv * env,jclass clazz,jobject fdo,jlong address,jint len,jboolean append)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
Java_sun_nio_ch_FileDispatcherImpl_writev0(JNIEnv * env,jclass clazz,jobject fdo,jlong address,jint len,jboolean append)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
Java_sun_nio_ch_FileDispatcherImpl_pwrite0(JNIEnv * env,jclass clazz,jobject fdo,jlong address,jint len,jlong offset)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
Java_sun_nio_ch_FileDispatcherImpl_seek0(JNIEnv * env,jclass clazz,jobject fdo,jlong offset)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
Java_sun_nio_ch_FileDispatcherImpl_force0(JNIEnv * env,jobject this,jobject fdo,jboolean md)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
Java_sun_nio_ch_FileDispatcherImpl_truncate0(JNIEnv * env,jobject this,jobject fdo,jlong size)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
Java_sun_nio_ch_FileDispatcherImpl_size0(JNIEnv * env,jobject this,jobject fdo)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
Java_sun_nio_ch_FileDispatcherImpl_lock0(JNIEnv * env,jobject this,jobject fdo,jboolean block,jlong pos,jlong size,jboolean shared)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
Java_sun_nio_ch_FileDispatcherImpl_release0(JNIEnv * env,jobject this,jobject fdo,jlong pos,jlong size)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
Java_sun_nio_ch_FileDispatcherImpl_close0(JNIEnv * env,jclass clazz,jobject fdo)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
Java_sun_nio_ch_FileDispatcherImpl_duplicateHandle(JNIEnv * env,jclass this,jlong handle)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
Java_sun_nio_ch_FileDispatcherImpl_setDirect0(JNIEnv * env,jclass this,jobject fdObj,jobject buffer)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 }
514