1 // natFileChannelImplWin32.cc - Native part of FileChannelImpl class.
3 /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
6 This file is part of libgcj.
8 This software is copyrighted work licensed under the terms of the
9 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
12 // FIXME: In order to support interrupting of IO operations, we
13 // need to change to use the windows asynchronous IO functions
19 #include <gcj/javaprims.h>
24 #include <gnu/gcj/RawData.h>
25 #include <gnu/java/nio/FileLockImpl.h>
26 #include <gnu/java/nio/channels/FileChannelImpl.h>
27 #include <java/io/FileNotFoundException.h>
28 #include <java/io/IOException.h>
29 #include <java/io/SyncFailedException.h>
30 #include <java/io/InterruptedIOException.h>
31 #include <java/io/EOFException.h>
32 #include <java/lang/ArrayIndexOutOfBoundsException.h>
33 #include <java/lang/NullPointerException.h>
34 #include <java/lang/System.h>
35 #include <java/lang/String.h>
36 #include <java/lang/Thread.h>
37 #include <java/nio/ByteBuffer.h>
38 #include <java/nio/MappedByteBufferImpl.h>
39 #include <java/nio/channels/FileChannel.h>
40 #include <java/nio/channels/FileLock.h>
41 #include <gnu/java/nio/channels/FileChannelImpl.h>
43 using gnu::gcj::RawData
;
44 using java::io::IOException
;
45 using java::nio::MappedByteBufferImpl
;
46 using java::io::InterruptedIOException
;
47 using java::io::FileNotFoundException
;
48 using java::lang::ArrayIndexOutOfBoundsException
;
49 using gnu::java::nio::channels::FileChannelImpl
;
53 static bool testCanUseGetHandleInfo()
55 /* Test to see whether GetHandleInformation can be used
56 for console input or screen buffers. This is better
57 a kludgy OS version check. */
59 return GetHandleInformation (GetStdHandle (STD_INPUT_HANDLE
),
63 // FIXME: casting a FILE (pointer) to a jint will not work on Win64 --
64 // we should be using gnu.gcj.RawData's.
67 FileChannelImpl::init(void)
69 in
= new FileChannelImpl((jint
)(GetStdHandle (STD_INPUT_HANDLE
)),
70 FileChannelImpl::READ
);
71 out
= new FileChannelImpl((jint
)(GetStdHandle (STD_OUTPUT_HANDLE
)),
72 FileChannelImpl::WRITE
);
73 err
= new FileChannelImpl((jint
)(GetStdHandle (STD_ERROR_HANDLE
)),
74 FileChannelImpl::WRITE
);
78 FileChannelImpl::sync (void) {
79 if (! FlushFileBuffers ((HANDLE
)fd
))
81 DWORD dwErrorCode
= GetLastError ();
82 throw new SyncFailedException (_Jv_WinStrError (dwErrorCode
));
88 FileChannelImpl::open (jstring path
, jint jflags
) {
92 DWORD create
= OPEN_EXISTING
;
94 JV_TEMP_STRING_WIN32(cpath
, path
)
96 JvAssert((jflags
& READ
) || (jflags
& WRITE
));
98 if ((jflags
& READ
) && (jflags
& WRITE
))
100 access
= GENERIC_READ
| GENERIC_WRITE
;
102 create
= CREATE_NEW
; // this will raise error if file exists.
104 create
= OPEN_ALWAYS
; // equivalent to O_CREAT
106 else if (jflags
& READ
)
108 access
= GENERIC_READ
;
109 create
= OPEN_EXISTING
; // ignore EXCL
113 access
= GENERIC_WRITE
;
116 else if (jflags
& APPEND
)
117 create
= OPEN_ALWAYS
;
119 create
= CREATE_ALWAYS
;
122 handle
= CreateFile(cpath
, access
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
123 NULL
, create
, 0, NULL
);
125 if (handle
== INVALID_HANDLE_VALUE
)
127 DWORD dwErrorCode
= GetLastError ();
128 throw new FileNotFoundException (_Jv_WinStrError (cpath
, dwErrorCode
));
131 // For APPEND mode, move the file pointer to the end of the file.
134 DWORD low
= SetFilePointer (handle
, 0, NULL
, FILE_END
);
135 if ((low
== (DWORD
) 0xffffffff) && (GetLastError () != NO_ERROR
))
137 DWORD dwErrorCode
= GetLastError ();
138 throw new FileNotFoundException (_Jv_WinStrError (cpath
, dwErrorCode
));
142 // Make this handle non-inheritable so that child
143 // processes don't inadvertently prevent us from
144 // closing this file.
145 _Jv_platform_close_on_exec (handle
);
147 return (jint
) handle
;
151 FileChannelImpl::write (jint b
)
154 jbyte buf
= (jbyte
)b
;
156 if (WriteFile ((HANDLE
)fd
, &buf
, 1, &bytesWritten
, NULL
))
158 if (::java::lang::Thread::interrupted())
160 InterruptedIOException
*iioe
= new InterruptedIOException (JvNewStringLatin1 ("write interrupted"));
161 iioe
->bytesTransferred
= bytesWritten
;
164 if (bytesWritten
!= 1)
165 _Jv_ThrowIOException ();
168 _Jv_ThrowIOException ();
169 // FIXME: loop until bytesWritten == 1
173 FileChannelImpl::write(jbyteArray b
, jint offset
, jint len
)
176 throw new ::java::lang::NullPointerException
;
177 if(offset
< 0 || len
< 0 || offset
+ len
> JvGetArrayLength (b
))
178 throw new ArrayIndexOutOfBoundsException
;
180 jbyte
*buf
= elements (b
) + offset
;
183 if (WriteFile ((HANDLE
)fd
, buf
, len
, &bytesWritten
, NULL
))
185 if (::java::lang::Thread::interrupted())
187 InterruptedIOException
*iioe
= new InterruptedIOException (JvNewStringLatin1 ("write interrupted"));
188 iioe
->bytesTransferred
= bytesWritten
;
193 _Jv_ThrowIOException ();
194 // FIXME: loop until bytesWritten == len
198 FileChannelImpl::implCloseChannel (void)
200 HANDLE save
= (HANDLE
)fd
;
201 fd
= (jint
)INVALID_HANDLE_VALUE
;
202 if (! CloseHandle (save
))
203 _Jv_ThrowIOException ();
207 FileChannelImpl::implTruncate (jlong size
)
209 LONG liOrigFilePointer
;
210 LONG liNewFilePointer
;
211 LONG liEndFilePointer
;
213 // Get the original file pointer.
214 if (SetFilePointer((HANDLE
) fd
, (LONG
) 0, &liOrigFilePointer
,
215 FILE_CURRENT
) != (BOOL
) 0
216 && (GetLastError() != NO_ERROR
))
217 _Jv_ThrowIOException ();
219 // Get the length of the file.
220 if (SetFilePointer((HANDLE
) fd
, (LONG
) 0, &liEndFilePointer
,
221 FILE_END
) != (BOOL
) 0
222 && (GetLastError() != NO_ERROR
))
223 _Jv_ThrowIOException ();
225 if ((jlong
)liEndFilePointer
== size
)
227 // Restore the file pointer.
228 if (liOrigFilePointer
!= liEndFilePointer
)
230 if (SetFilePointer((HANDLE
) fd
, liOrigFilePointer
, &liNewFilePointer
,
231 FILE_BEGIN
) != (BOOL
) 0
232 && (GetLastError() != NO_ERROR
))
233 _Jv_ThrowIOException ();
238 // Seek to the new end of file.
239 if (SetFilePointer((HANDLE
) fd
, (LONG
) size
, &liNewFilePointer
,
240 FILE_BEGIN
) != (BOOL
) 0
241 && (GetLastError() != NO_ERROR
))
242 _Jv_ThrowIOException ();
244 // Truncate the file at this point.
245 if (SetEndOfFile((HANDLE
) fd
) != (BOOL
) 0 && (GetLastError() != NO_ERROR
))
246 _Jv_ThrowIOException ();
248 if (liOrigFilePointer
< liNewFilePointer
)
250 // Restore the file pointer.
251 if (SetFilePointer((HANDLE
) fd
, liOrigFilePointer
, &liNewFilePointer
,
252 FILE_BEGIN
) != (BOOL
) 0
253 && (GetLastError() != NO_ERROR
))
254 _Jv_ThrowIOException ();
259 FileChannelImpl::seek (jlong newPos
)
261 LONG high
= pos
>> 32;
262 DWORD low
= SetFilePointer ((HANDLE
)fd
, (DWORD
)(0xffffffff & newPos
), &high
, FILE_BEGIN
);
263 if ((low
== 0xffffffff) && (GetLastError () != NO_ERROR
))
264 _Jv_ThrowIOException ();
268 FileChannelImpl::implPosition (void)
271 DWORD low
= SetFilePointer ((HANDLE
)fd
, 0, &high
, FILE_CURRENT
);
272 if ((low
== 0xffffffff) && (GetLastError() != NO_ERROR
))
273 _Jv_ThrowIOException ();
274 return (((jlong
)high
) << 32L) | (jlong
)low
;
278 FileChannelImpl::size (void)
283 low
= GetFileSize ((HANDLE
)fd
, &high
);
284 // FIXME: Error checking
285 return (((jlong
)high
) << 32L) | (jlong
)low
;
289 FileChannelImpl::read (void)
294 if (! ReadFile ((HANDLE
)fd
, &buf
, 1, &read
, NULL
))
296 if (GetLastError () == ERROR_BROKEN_PIPE
)
299 _Jv_ThrowIOException ();
305 return (jint
)(buf
& 0xff);
309 FileChannelImpl::read (jbyteArray buffer
, jint offset
, jint count
)
312 throw new ::java::lang::NullPointerException
;
314 jsize bsize
= JvGetArrayLength (buffer
);
315 if (offset
< 0 || count
< 0 || offset
+ count
> bsize
)
316 throw new ArrayIndexOutOfBoundsException
;
318 // Must return 0 if an attempt is made to read 0 bytes.
322 jbyte
*bytes
= elements (buffer
) + offset
;
325 if (! ReadFile((HANDLE
)fd
, bytes
, count
, &read
, NULL
))
327 if (GetLastError () == ERROR_BROKEN_PIPE
)
330 _Jv_ThrowIOException ();
333 if (read
== 0) return -1;
339 FileChannelImpl::available (void)
342 return size() - position();
346 FileChannelImpl::lock (jlong pos
, jlong len
, jboolean shared
, jboolean wait
)
351 ZeroMemory(&ovlpd
,sizeof(OVERLAPPED
));
354 flags
|= LOCKFILE_EXCLUSIVE_LOCK
;
356 flags
|= LOCKFILE_FAIL_IMMEDIATELY
;
358 ovlpd
.Offset
= (DWORD
)pos
;
359 ovlpd
.OffsetHigh
= pos
>>32;
361 DWORD lenlow
= (DWORD
)len
;
362 DWORD lenhigh
= len
>>32;
364 BOOL ret
= LockFileEx((HANDLE
)fd
,flags
,0,lenlow
,lenhigh
,&ovlpd
);
366 if(ret
==ERROR_IO_PENDING
&& !shared
&& wait
)
367 ret
= GetOverlappedResult((HANDLE
)fd
,&ovlpd
,NULL
,wait
);
370 _Jv_ThrowIOException(GetLastError());
376 FileChannelImpl::unlock (jlong pos
, jlong len
)
380 ZeroMemory(&ovlpd
,sizeof(OVERLAPPED
));
382 ovlpd
.Offset
= (DWORD
)pos
;
383 ovlpd
.OffsetHigh
= pos
>>32;
385 DWORD lenlow
= (DWORD
)len
;
386 DWORD lenhigh
= len
>>32;
388 BOOL ret
= UnlockFileEx((HANDLE
)fd
,0,lenlow
,lenhigh
,&ovlpd
);
391 _Jv_ThrowIOException(GetLastError());
394 java::nio::MappedByteBuffer
*
395 FileChannelImpl::mapImpl (jchar mmode
, jlong position
, jint size
)
397 SYSTEM_INFO siSysInfo
;
398 GetSystemInfo(&siSysInfo
);
399 DWORD page_size
= siSysInfo
.dwPageSize
;
400 jlong offset
= position
& ~(page_size
-1);
401 jint align
= position
- offset
;
402 jlong high
= position
+ size
;
405 max_size
= high
- offset
;
408 DWORD access
, protect
;
411 access
= FILE_MAP_READ
;
412 protect
= PAGE_READONLY
;
414 else if (mmode
== '+')
416 access
= FILE_MAP_WRITE
;
417 protect
= PAGE_READWRITE
;
421 access
= FILE_MAP_COPY
;
422 protect
= PAGE_WRITECOPY
;
424 HANDLE hFileMapping
= CreateFileMapping((HANDLE
) fd
,
425 (LPSECURITY_ATTRIBUTES
) NULL
,
427 (DWORD
) (max_size
>> 32),
430 if (hFileMapping
== NULL
)
431 throw new IOException();
432 void *ptr
= MapViewOfFile(hFileMapping
, access
,
433 (DWORD
) (offset
>> 32), (DWORD
) offset
,
434 (SIZE_T
) (high
- offset
));
436 throw new IOException();
437 MappedByteBufferImpl
*buf
438 = new MappedByteBufferImpl((RawData
*) ((char *) ptr
+ align
),
440 buf
->implPtr
= reinterpret_cast<RawData
*> (ptr
);
441 buf
->implLen
= (jlong
) (size_t) hFileMapping
;
446 MappedByteBufferImpl::unmapImpl ()
448 UnmapViewOfFile((void*)implPtr
);
449 CloseHandle((HANDLE
) (size_t) implLen
);
453 MappedByteBufferImpl::loadImpl ()
458 MappedByteBufferImpl::isLoadedImpl ()
464 MappedByteBufferImpl::forceImpl ()