2 * file-io.c: File IO internal calls
5 * Dick Porter (dick@ximian.com)
7 * (C) 2001 Ximian, Inc.
13 #include <mono/metadata/object.h>
14 #include <mono/io-layer/io-layer.h>
15 #include <mono/metadata/file-io.h>
16 #include <mono/metadata/exception.h>
17 #include <mono/metadata/appdomain.h>
21 static guint32 convert_mode(MonoFileMode mono_mode)
26 case FileMode_CreateNew:
35 case FileMode_OpenOrCreate:
38 case FileMode_Truncate:
39 mode=TRUNCATE_EXISTING;
45 g_warning("System.IO.FileMode has unknown value 0x%x",
54 static guint32 convert_access(MonoFileAccess mono_access)
62 case FileAccess_Write:
65 case FileAccess_ReadWrite:
66 access=GENERIC_READ|GENERIC_WRITE;
69 g_warning("System.IO.FileAccess has unknown value 0x%x",
78 static guint32 convert_share(MonoFileShare mono_share)
87 share=FILE_SHARE_READ;
90 share=FILE_SHARE_WRITE;
92 case FileShare_ReadWrite:
93 share=FILE_SHARE_READ|FILE_SHARE_WRITE;
96 g_warning("System.IO.FileShare has unknown value 0x%x",
105 static guint32 convert_stdhandle(guint32 fd)
111 stdhandle=STD_INPUT_HANDLE;
114 stdhandle=STD_OUTPUT_HANDLE;
117 stdhandle=STD_ERROR_HANDLE;
120 g_warning("unknown standard file descriptor %d", fd);
121 stdhandle=STD_INPUT_HANDLE;
127 static guint32 convert_seekorigin(MonoSeekOrigin origin)
132 case SeekOrigin_Begin:
133 w32origin=FILE_BEGIN;
135 case SeekOrigin_Current:
136 w32origin=FILE_CURRENT;
142 g_warning("System.IO.SeekOrigin has unknown value 0x%x",
145 w32origin=FILE_CURRENT;
151 /* fd must be one of stdin (value 0), stdout (1) or stderr (2). These
152 * values must be hardcoded in corlib.
154 HANDLE ves_icall_System_PAL_OpSys_GetStdHandle(MonoObject *this,
159 if(fd!=0 && fd!=1 && fd!=2) {
160 mono_raise_exception(mono_get_exception_io("Invalid file descriptor"));
163 handle=GetStdHandle(convert_stdhandle(fd));
168 void ves_icall_System_PAL_OpSys_DeleteFile(MonoObject *this, MonoString *path)
172 filename=mono_string_to_utf16(path);
174 DeleteFile(filename);
179 gboolean ves_icall_System_PAL_OpSys_ExistsFile(MonoObject *this, MonoString *path)
184 gboolean ves_icall_System_PAL_OpSys_GetFileTime(HANDLE handle, gint64 *createtime, gint64 *lastaccess, gint64 *lastwrite)
189 if(handle == INVALID_HANDLE_VALUE)
190 mono_raise_exception(mono_get_exception_io("Invalid handle"));
192 ret=GetFileTime(handle, &cr, &ac, &wr);
194 /* The FILETIME struct holds two unsigned 32 bit
195 * values for the low and high bytes, but the .net
196 * file time insists on being signed :(
198 *createtime=((gint64)cr.dwHighDateTime << 32) +
200 *lastaccess=((gint64)ac.dwHighDateTime << 32) +
202 *lastwrite=((gint64)wr.dwHighDateTime << 32) +
209 gboolean ves_icall_System_PAL_OpSys_SetFileTime(HANDLE handle, gint64 createtime, gint64 lastaccess, gint64 lastwrite)
214 if(handle == INVALID_HANDLE_VALUE)
215 mono_raise_exception(mono_get_exception_io("Invalid handle"));
217 cr.dwLowDateTime= createtime & 0xFFFFFFFF;
218 cr.dwHighDateTime= createtime >> 32;
220 ac.dwLowDateTime= lastaccess & 0xFFFFFFFF;
221 ac.dwHighDateTime= lastaccess >> 32;
223 wr.dwLowDateTime= lastwrite & 0xFFFFFFFF;
224 wr.dwHighDateTime= lastwrite >> 32;
226 ret=SetFileTime(handle, &cr, &ac, &wr);
231 /* System.IO.FileStream */
234 ves_icall_System_IO_FileStream_FileOpen (MonoString *path, gint32 mode, gint32 access, gint32 share) {
238 filename=mono_string_to_utf16(path);
240 handle=CreateFile(filename, convert_access(access),
241 convert_share(share), NULL, convert_mode(mode),
242 FILE_ATTRIBUTE_NORMAL, NULL);
246 /* fixme: raise mor appropriate exceptions (errno) */
247 if(handle == INVALID_HANDLE_VALUE) {
248 mono_raise_exception(mono_get_exception_io("Invalid handle"));
255 ves_icall_System_IO_FileStream_FileClose (gpointer handle) {
256 if(handle == INVALID_HANDLE_VALUE) {
257 mono_raise_exception(mono_get_exception_io("Invalid handle"));
264 ves_icall_System_IO_FileStream_FileRead (gpointer handle, MonoArray *dest, gint32 dest_offset, gint32 count) {
270 if(handle == INVALID_HANDLE_VALUE) {
271 mono_raise_exception(mono_get_exception_io("Invalid handle"));
274 alen=mono_array_length(dest);
275 if(dest_offset+count>alen) {
279 buf=mono_array_addr(dest, guchar, dest_offset);
281 ret=ReadFile(handle, buf, count, &bytesread, NULL);
287 ves_icall_System_IO_FileStream_FileWrite (gpointer handle, MonoArray *src, gint32 src_offset, gint32 count) {
289 guint32 byteswritten;
293 if(handle == INVALID_HANDLE_VALUE) {
294 mono_raise_exception(mono_get_exception_io("Invalid handle"));
297 alen=mono_array_length(src);
298 if(src_offset+count>alen) {
302 buf=mono_array_addr(src, guchar, src_offset);
304 ret=WriteFile(handle, buf, count, &byteswritten, NULL);
306 return(byteswritten);
310 ves_icall_System_IO_FileStream_FileSeek (gpointer handle, gint64 offset, gint32 origin) {
312 gint32 offsetlo, offsethi, retlo;
314 if(handle == INVALID_HANDLE_VALUE) {
315 mono_raise_exception(mono_get_exception_io("Invalid handle"));
318 offsetlo=offset & 0xFFFFFFFF;
319 offsethi=offset >> 32;
321 retlo=SetFilePointer(handle, offset, &offsethi,
322 convert_seekorigin(origin));
324 ret=((gint64)offsethi << 32) + offsetlo;
330 ves_icall_System_IO_FileStream_FileGetLength (gpointer handle) {
331 gint32 length_lo, length_hi;
333 if (handle == INVALID_HANDLE_VALUE)
334 mono_raise_exception (mono_get_exception_io ("Invalid handle"));
336 length_lo = GetFileSize (handle, &length_hi);
338 return ((gint64)length_hi << 32) | length_lo;
342 ves_icall_System_IO_FileStream_FileSetLength (gpointer handle, gint64 length) {
343 /* FIXME: Should this put the file pointer back to where it
344 * was before we started setting the length? The spec doesnt
349 gint32 lenlo, lenhi, retlo;
351 if(handle == INVALID_HANDLE_VALUE) {
352 mono_raise_exception(mono_get_exception_io("Invalid handle"));
355 lenlo=length & 0xFFFFFFFF;
358 retlo=SetFilePointer(handle, lenlo, &lenhi, FILE_BEGIN);
359 ret=SetEndOfFile(handle);
362 mono_raise_exception(mono_get_exception_io("IO Exception"));
367 ves_icall_System_IO_FileStream_FileFlush (gpointer handle) {
368 /* FIXME: implement FlushFileBuffers */