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>
20 static guint32 convert_mode(MonoFileMode mono_mode)
25 case FileMode_CreateNew:
34 case FileMode_OpenOrCreate:
37 case FileMode_Truncate:
38 mode=TRUNCATE_EXISTING;
44 g_warning("System.IO.FileMode has unknown value 0x%x",
53 static guint32 convert_access(MonoFileAccess mono_access)
61 case FileAccess_Write:
64 case FileAccess_ReadWrite:
65 access=GENERIC_READ|GENERIC_WRITE;
68 g_warning("System.IO.FileAccess has unknown value 0x%x",
77 static guint32 convert_share(MonoFileShare mono_share)
86 share=FILE_SHARE_READ;
89 share=FILE_SHARE_WRITE;
91 case FileShare_ReadWrite:
92 share=FILE_SHARE_READ|FILE_SHARE_WRITE;
95 g_warning("System.IO.FileShare has unknown value 0x%x",
104 static guint32 convert_stdhandle(guint32 fd)
110 stdhandle=STD_INPUT_HANDLE;
113 stdhandle=STD_OUTPUT_HANDLE;
116 stdhandle=STD_ERROR_HANDLE;
119 g_warning("unknown standard file descriptor %d", fd);
120 stdhandle=STD_INPUT_HANDLE;
126 static guint32 convert_seekorigin(MonoSeekOrigin origin)
131 case SeekOrigin_Begin:
132 w32origin=FILE_BEGIN;
134 case SeekOrigin_Current:
135 w32origin=FILE_CURRENT;
141 g_warning("System.IO.SeekOrigin has unknown value 0x%x",
144 w32origin=FILE_CURRENT;
150 static MonoException *get_io_exception(const guchar *msg)
152 static MonoException *ex = NULL;
155 ex=(MonoException *)mono_exception_from_name(
156 mono_defaults.corlib, "System.IO", "IOException");
159 ex->message=mono_string_new(msg);
164 /* fd must be one of stdin (value 0), stdout (1) or stderr (2). These
165 * values must be hardcoded in corlib.
167 HANDLE ves_icall_System_PAL_OpSys_GetStdHandle(MonoObject *this,
172 if(fd!=0 && fd!=1 && fd!=2) {
173 mono_raise_exception(
174 get_io_exception("Invalid file descriptor"));
177 handle=GetStdHandle(convert_stdhandle(fd));
182 gint32 ves_icall_System_PAL_OpSys_ReadFile(MonoObject *this, HANDLE handle, MonoArray *buffer, gint32 offset, gint32 count)
189 if(handle == INVALID_HANDLE_VALUE) {
190 mono_raise_exception(get_io_exception("Invalid handle"));
193 alen=mono_array_length(buffer);
194 if(offset+count>alen) {
198 buf=mono_array_addr(buffer, guchar, offset);
200 ret=ReadFile(handle, buf, count, &bytesread, NULL);
205 gint32 ves_icall_System_PAL_OpSys_WriteFile(MonoObject *this, HANDLE handle, MonoArray *buffer, gint32 offset, gint32 count)
208 guint32 byteswritten;
212 if(handle == INVALID_HANDLE_VALUE) {
213 mono_raise_exception(get_io_exception("Invalid handle"));
216 alen=mono_array_length(buffer);
217 if(offset+count>alen) {
221 buf=mono_array_addr(buffer, guchar, offset);
223 ret=WriteFile(handle, buf, count, &byteswritten, NULL);
225 return(byteswritten);
228 gint32 ves_icall_System_PAL_OpSys_SetLengthFile(MonoObject *this, HANDLE handle, gint64 length)
230 /* FIXME: Should this put the file pointer back to where it
231 * was before we started setting the length? The spec doesnt
236 gint32 lenlo, lenhi, retlo;
238 if(handle == INVALID_HANDLE_VALUE) {
239 mono_raise_exception(get_io_exception("Invalid handle"));
242 lenlo=length & 0xFFFFFFFF;
245 retlo=SetFilePointer(handle, lenlo, &lenhi, FILE_BEGIN);
246 ret=SetEndOfFile(handle);
249 mono_raise_exception(get_io_exception("IO Exception"));
255 HANDLE ves_icall_System_PAL_OpSys_OpenFile(MonoObject *this, MonoString *path, gint32 mode, gint32 access, gint32 share)
260 filename=mono_string_to_utf16(path);
262 handle=CreateFile(filename, convert_access(access),
263 convert_share(share), NULL, convert_mode(mode),
264 FILE_ATTRIBUTE_NORMAL, NULL);
268 /* fixme: raise mor appropriate exceptions (errno) */
269 if(handle == INVALID_HANDLE_VALUE) {
270 mono_raise_exception(get_io_exception("Invalid handle"));
276 void ves_icall_System_PAL_OpSys_CloseFile(MonoObject *this, HANDLE handle)
278 if(handle == INVALID_HANDLE_VALUE) {
279 mono_raise_exception(get_io_exception("Invalid handle"));
285 gint64 ves_icall_System_PAL_OpSys_SeekFile(MonoObject *this, HANDLE handle,
286 gint64 offset, gint32 origin)
289 gint32 offsetlo, offsethi, retlo;
291 if(handle == INVALID_HANDLE_VALUE) {
292 mono_raise_exception(get_io_exception("Invalid handle"));
295 offsetlo=offset & 0xFFFFFFFF;
296 offsethi=offset >> 32;
298 retlo=SetFilePointer(handle, offset, &offsethi,
299 convert_seekorigin(origin));
301 ret=((gint64)offsethi << 32) + offsetlo;
306 void ves_icall_System_PAL_OpSys_DeleteFile(MonoObject *this, MonoString *path)
310 filename=mono_string_to_utf16(path);
312 DeleteFile(filename);
317 gboolean ves_icall_System_PAL_OpSys_ExistsFile(MonoObject *this, MonoString *path)
322 gboolean ves_icall_System_PAL_OpSys_GetFileTime(HANDLE handle, gint64 *createtime, gint64 *lastaccess, gint64 *lastwrite)
327 if(handle == INVALID_HANDLE_VALUE) {
328 mono_raise_exception(get_io_exception("Invalid handle"));
331 ret=GetFileTime(handle, &cr, &ac, &wr);
333 /* The FILETIME struct holds two unsigned 32 bit
334 * values for the low and high bytes, but the .net
335 * file time insists on being signed :(
337 *createtime=((gint64)cr.dwHighDateTime << 32) +
339 *lastaccess=((gint64)ac.dwHighDateTime << 32) +
341 *lastwrite=((gint64)wr.dwHighDateTime << 32) +
348 gboolean ves_icall_System_PAL_OpSys_SetFileTime(HANDLE handle, gint64 createtime, gint64 lastaccess, gint64 lastwrite)
353 if(handle == INVALID_HANDLE_VALUE) {
354 mono_raise_exception(get_io_exception("Invalid handle"));
357 cr.dwLowDateTime= createtime & 0xFFFFFFFF;
358 cr.dwHighDateTime= createtime >> 32;
360 ac.dwLowDateTime= lastaccess & 0xFFFFFFFF;
361 ac.dwHighDateTime= lastaccess >> 32;
363 wr.dwLowDateTime= lastwrite & 0xFFFFFFFF;
364 wr.dwHighDateTime= lastwrite >> 32;
366 ret=SetFileTime(handle, &cr, &ac, &wr);