blob: da96a109a7ff2440286018102617fcd6b5015b29 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2000-2007 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26#include "jni.h"
27#include "jni_util.h"
28#include "jvm.h"
29#include "jlong.h"
30#include <io.h>
31#include "nio.h"
32#include "nio_util.h"
33#include "sun_nio_ch_FileChannelImpl.h"
34
35static jfieldID chan_fd; /* id for jobject 'fd' in java.io.FileChannel */
36
37
38/* false for 95/98/ME, true for NT/W2K */
39static jboolean onNT = JNI_FALSE;
40
41/**************************************************************
42 * static method to store field ID's in initializers
43 * and retrieve the allocation granularity
44 */
45JNIEXPORT jlong JNICALL
46Java_sun_nio_ch_FileChannelImpl_initIDs(JNIEnv *env, jclass clazz)
47{
48 SYSTEM_INFO si;
49 jint align;
50 OSVERSIONINFO ver;
51 GetSystemInfo(&si);
52 align = si.dwAllocationGranularity;
53 chan_fd = (*env)->GetFieldID(env, clazz, "fd", "Ljava/io/FileDescriptor;");
54 ver.dwOSVersionInfoSize = sizeof(ver);
55 GetVersionEx(&ver);
56 if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
57 onNT = JNI_TRUE;
58 }
59 return align;
60}
61
62
63/**************************************************************
64 * Channel
65 */
66
67JNIEXPORT jlong JNICALL
68Java_sun_nio_ch_FileChannelImpl_map0(JNIEnv *env, jobject this,
69 jint prot, jlong off, jlong len)
70{
71 void *mapAddress = 0;
72 jint lowOffset = (jint)off;
73 jint highOffset = (jint)(off >> 32);
74 jlong maxSize = off + len;
75 jint lowLen = (jint)(maxSize);
76 jint highLen = (jint)(maxSize >> 32);
77 jobject fdo = (*env)->GetObjectField(env, this, chan_fd);
78 HANDLE fileHandle = (HANDLE)(handleval(env, fdo));
79 HANDLE mapping;
80 DWORD mapAccess = FILE_MAP_READ;
81 DWORD fileProtect = PAGE_READONLY;
82 DWORD mapError;
83 BOOL result;
84
85 if (prot == sun_nio_ch_FileChannelImpl_MAP_RO) {
86 fileProtect = PAGE_READONLY;
87 mapAccess = FILE_MAP_READ;
88 } else if (prot == sun_nio_ch_FileChannelImpl_MAP_RW) {
89 fileProtect = PAGE_READWRITE;
90 mapAccess = FILE_MAP_WRITE;
91 } else if (prot == sun_nio_ch_FileChannelImpl_MAP_PV) {
92 fileProtect = PAGE_WRITECOPY;
93 mapAccess = FILE_MAP_COPY;
94 }
95
96 mapping = CreateFileMapping(
97 fileHandle, /* Handle of file */
98 NULL, /* Not inheritable */
99 fileProtect, /* Read and write */
100 highLen, /* High word of max size */
101 lowLen, /* Low word of max size */
102 NULL); /* No name for object */
103
104 if (mapping == NULL) {
105 JNU_ThrowIOExceptionWithLastError(env, "Map failed");
106 return IOS_THROWN;
107 }
108
109 mapAddress = MapViewOfFile(
110 mapping, /* Handle of file mapping object */
111 mapAccess, /* Read and write access */
112 highOffset, /* High word of offset */
113 lowOffset, /* Low word of offset */
114 (DWORD)len); /* Number of bytes to map */
115 mapError = GetLastError();
116
117 result = CloseHandle(mapping);
118 if (result == 0) {
119 JNU_ThrowIOExceptionWithLastError(env, "Map failed");
120 return IOS_THROWN;
121 }
122
123 if (mapAddress == NULL) {
124 if (mapError == ERROR_NOT_ENOUGH_MEMORY)
125 JNU_ThrowOutOfMemoryError(env, "Map failed");
126 else
127 JNU_ThrowIOExceptionWithLastError(env, "Map failed");
128 return IOS_THROWN;
129 }
130
131 return ptr_to_jlong(mapAddress);
132}
133
134JNIEXPORT jint JNICALL
135Java_sun_nio_ch_FileChannelImpl_unmap0(JNIEnv *env, jobject this,
136 jlong address, jlong len)
137{
138 BOOL result;
139 void *a = (void *) jlong_to_ptr(address);
140
141 result = UnmapViewOfFile(a);
142 if (result == 0) {
143 JNU_ThrowIOExceptionWithLastError(env, "Unmap failed");
144 return IOS_THROWN;
145 }
146 return 0;
147}
148
149JNIEXPORT jint JNICALL
150Java_sun_nio_ch_FileChannelImpl_truncate0(JNIEnv *env, jobject this,
151 jobject fdo, jlong size)
152{
153 DWORD lowPos = 0;
154 long highPos = 0;
155 BOOL result = 0;
156 HANDLE h = (HANDLE)(handleval(env, fdo));
157
158 lowPos = (DWORD)size;
159 highPos = (long)(size >> 32);
160 lowPos = SetFilePointer(h, lowPos, &highPos, FILE_BEGIN);
161 if (lowPos == ((DWORD)-1)) {
162 if (GetLastError() != ERROR_SUCCESS) {
163 JNU_ThrowIOExceptionWithLastError(env, "Truncation failed");
164 return IOS_THROWN;
165 }
166 }
167 result = SetEndOfFile(h);
168 if (result == 0) {
169 JNU_ThrowIOExceptionWithLastError(env, "Truncation failed");
170 return IOS_THROWN;
171 }
172 return 0;
173}
174
175
176JNIEXPORT jint JNICALL
177Java_sun_nio_ch_FileChannelImpl_force0(JNIEnv *env, jobject this,
178 jobject fdo, jboolean md)
179{
180 int result = 0;
181 HANDLE h = (HANDLE)(handleval(env, fdo));
182
183 if (h != INVALID_HANDLE_VALUE) {
184 result = FlushFileBuffers(h);
185 if (result == 0) {
186 int error = GetLastError();
187 if (error != ERROR_ACCESS_DENIED) {
188 JNU_ThrowIOExceptionWithLastError(env, "Force failed");
189 return IOS_THROWN;
190 }
191 }
192 } else {
193 JNU_ThrowIOExceptionWithLastError(env, "Force failed");
194 return IOS_THROWN;
195 }
196 return 0;
197}
198
199JNIEXPORT jlong JNICALL
200Java_sun_nio_ch_FileChannelImpl_position0(JNIEnv *env, jobject this,
201 jobject fdo, jlong offset)
202{
203 DWORD lowPos = 0;
204 long highPos = 0;
205 HANDLE h = (HANDLE)(handleval(env, fdo));
206
207 if (offset < 0) {
208 lowPos = SetFilePointer(h, 0, &highPos, FILE_CURRENT);
209 } else {
210 lowPos = (DWORD)offset;
211 highPos = (long)(offset >> 32);
212 lowPos = SetFilePointer(h, lowPos, &highPos, FILE_BEGIN);
213 }
214 if (lowPos == ((DWORD)-1)) {
215 if (GetLastError() != ERROR_SUCCESS) {
216 JNU_ThrowIOExceptionWithLastError(env, "Seek failed");
217 return IOS_THROWN;
218 }
219 }
220 return (((jlong)highPos) << 32) | lowPos;
221}
222
223JNIEXPORT jlong JNICALL
224Java_sun_nio_ch_FileChannelImpl_size0(JNIEnv *env, jobject this, jobject fdo)
225{
226 DWORD sizeLow = 0;
227 DWORD sizeHigh = 0;
228 HANDLE h = (HANDLE)(handleval(env, fdo));
229
230 sizeLow = GetFileSize(h, &sizeHigh);
231 if (sizeLow == ((DWORD)-1)) {
232 if (GetLastError() != ERROR_SUCCESS) {
233 JNU_ThrowIOExceptionWithLastError(env, "Size failed");
234 return IOS_THROWN;
235 }
236 }
237 return (((jlong)sizeHigh) << 32) | sizeLow;
238}
239
240JNIEXPORT void JNICALL
241Java_sun_nio_ch_FileChannelImpl_close0(JNIEnv *env, jobject this, jobject fdo)
242{
243 HANDLE h = (HANDLE)(handleval(env, fdo));
244 if (h != INVALID_HANDLE_VALUE) {
245 jint result = CloseHandle(h);
246 if (result < 0) {
247 JNU_ThrowIOExceptionWithLastError(env, "Close failed");
248 }
249 }
250}
251
252JNIEXPORT jlong JNICALL
253Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this,
254 jint srcFD,
255 jlong position, jlong count,
256 jint dstFD)
257{
258 return IOS_UNSUPPORTED;
259}
260
261JNIEXPORT jint JNICALL
262Java_sun_nio_ch_FileChannelImpl_lock0(JNIEnv *env, jobject this, jobject fdo,
263 jboolean block, jlong pos, jlong size,
264 jboolean shared)
265{
266 HANDLE h = (HANDLE)(handleval(env, fdo));
267 DWORD lowPos = (DWORD)pos;
268 long highPos = (long)(pos >> 32);
269 DWORD lowNumBytes = (DWORD)size;
270 DWORD highNumBytes = (DWORD)(size >> 32);
271 jint result = 0;
272 if (onNT) {
273 DWORD flags = 0;
274 OVERLAPPED o;
275 o.hEvent = 0;
276 o.Offset = lowPos;
277 o.OffsetHigh = highPos;
278 if (block == JNI_FALSE) {
279 flags |= LOCKFILE_FAIL_IMMEDIATELY;
280 }
281 if (shared == JNI_FALSE) {
282 flags |= LOCKFILE_EXCLUSIVE_LOCK;
283 }
284 result = LockFileEx(h, flags, 0, lowNumBytes, highNumBytes, &o);
285 if (result == 0) {
286 int error = GetLastError();
287 if (error != ERROR_LOCK_VIOLATION) {
288 JNU_ThrowIOExceptionWithLastError(env, "Lock failed");
289 return sun_nio_ch_FileChannelImpl_NO_LOCK;
290 }
291 if (flags & LOCKFILE_FAIL_IMMEDIATELY) {
292 return sun_nio_ch_FileChannelImpl_NO_LOCK;
293 }
294 JNU_ThrowIOExceptionWithLastError(env, "Lock failed");
295 return sun_nio_ch_FileChannelImpl_NO_LOCK;
296 }
297 return sun_nio_ch_FileChannelImpl_LOCKED;
298 } else {
299 for(;;) {
300 if (size > 0x7fffffff) {
301 size = 0x7fffffff;
302 }
303 lowNumBytes = (DWORD)size;
304 highNumBytes = 0;
305 result = LockFile(h, lowPos, highPos, lowNumBytes, highNumBytes);
306 if (result != 0) {
307 if (shared == JNI_TRUE) {
308 return sun_nio_ch_FileChannelImpl_RET_EX_LOCK;
309 } else {
310 return sun_nio_ch_FileChannelImpl_LOCKED;
311 }
312 } else {
313 int error = GetLastError();
314 if (error != ERROR_LOCK_VIOLATION) {
315 JNU_ThrowIOExceptionWithLastError(env, "Lock failed");
316 return sun_nio_ch_FileChannelImpl_NO_LOCK;
317 }
318 if (block == JNI_FALSE) {
319 return sun_nio_ch_FileChannelImpl_NO_LOCK;
320 }
321 }
322 Sleep(100);
323 }
324 }
325 return sun_nio_ch_FileChannelImpl_NO_LOCK;
326}
327
328JNIEXPORT void JNICALL
329Java_sun_nio_ch_FileChannelImpl_release0(JNIEnv *env, jobject this,
330 jobject fdo, jlong pos, jlong size)
331{
332 HANDLE h = (HANDLE)(handleval(env, fdo));
333 DWORD lowPos = (DWORD)pos;
334 long highPos = (long)(pos >> 32);
335 DWORD lowNumBytes = (DWORD)size;
336 DWORD highNumBytes = (DWORD)(size >> 32);
337 jint result = 0;
338 if (onNT) {
339 OVERLAPPED o;
340 o.hEvent = 0;
341 o.Offset = lowPos;
342 o.OffsetHigh = highPos;
343 result = UnlockFileEx(h, 0, lowNumBytes, highNumBytes, &o);
344 } else {
345 if (size > 0x7fffffff) {
346 size = 0x7fffffff;
347 }
348 lowNumBytes = (DWORD)size;
349 highNumBytes = 0;
350 result = UnlockFile(h, lowPos, highPos, lowNumBytes, highNumBytes);
351 }
352 if (result == 0) {
353 JNU_ThrowIOExceptionWithLastError(env, "Release failed");
354 }
355}