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 /* conversion functions */
23 static guint32 convert_mode(MonoFileMode mono_mode)
28 case FileMode_CreateNew:
37 case FileMode_OpenOrCreate:
40 case FileMode_Truncate:
41 mode=TRUNCATE_EXISTING;
47 g_warning("System.IO.FileMode has unknown value 0x%x",
56 static guint32 convert_access(MonoFileAccess mono_access)
64 case FileAccess_Write:
67 case FileAccess_ReadWrite:
68 access=GENERIC_READ|GENERIC_WRITE;
71 g_warning("System.IO.FileAccess has unknown value 0x%x",
80 static guint32 convert_share(MonoFileShare mono_share)
89 share=FILE_SHARE_READ;
92 share=FILE_SHARE_WRITE;
94 case FileShare_ReadWrite:
95 share=FILE_SHARE_READ|FILE_SHARE_WRITE;
98 g_warning("System.IO.FileShare has unknown value 0x%x",
108 static guint32 convert_stdhandle(guint32 fd)
114 stdhandle=STD_INPUT_HANDLE;
117 stdhandle=STD_OUTPUT_HANDLE;
120 stdhandle=STD_ERROR_HANDLE;
123 g_warning("unknown standard file descriptor %d", fd);
124 stdhandle=STD_INPUT_HANDLE;
131 static guint32 convert_seekorigin(MonoSeekOrigin origin)
136 case SeekOrigin_Begin:
137 w32origin=FILE_BEGIN;
139 case SeekOrigin_Current:
140 w32origin=FILE_CURRENT;
146 g_warning("System.IO.SeekOrigin has unknown value 0x%x",
149 w32origin=FILE_CURRENT;
155 static gint64 convert_filetime (const FILETIME *filetime)
159 ticks = (gint64 *)filetime;
163 static void convert_win32_file_attribute_data (const WIN32_FILE_ATTRIBUTE_DATA *data, const gunichar2 *name, MonoIOStat *stat)
167 stat->attributes = data->dwFileAttributes;
168 stat->creation_time = convert_filetime (&data->ftCreationTime);
169 stat->last_access_time = convert_filetime (&data->ftLastAccessTime);
170 stat->last_write_time = convert_filetime (&data->ftLastWriteTime);
171 stat->length = ((gint64)data->nFileSizeHigh << 32) | data->nFileSizeLow;
177 stat->name = mono_string_new_utf16 (mono_domain_get (), name, len);
180 /* System.IO.MonoIO internal calls */
183 ves_icall_System_IO_MonoIO_GetLastError ()
185 return GetLastError ();
189 ves_icall_System_IO_MonoIO_CreateDirectory (MonoString *path)
191 gunichar2 *utf16_path;
194 utf16_path = mono_string_to_utf16 (path);
195 result = CreateDirectory (utf16_path, NULL);
202 ves_icall_System_IO_MonoIO_RemoveDirectory (MonoString *path)
204 gunichar2 *utf16_path;
207 utf16_path = mono_string_to_utf16 (path);
208 result = RemoveDirectory (utf16_path);
215 ves_icall_System_IO_MonoIO_FindFirstFile (MonoString *path, MonoIOStat *stat)
217 gunichar2 *utf16_path;
218 WIN32_FIND_DATA data;
221 utf16_path = mono_string_to_utf16 (path);
222 result = FindFirstFile (utf16_path, &data);
225 /* note: WIN32_FIND_DATA is an extension of WIN32_FILE_ATTRIBUTE_DATA */
227 if (result != INVALID_HANDLE_VALUE)
228 convert_win32_file_attribute_data ((const WIN32_FILE_ATTRIBUTE_DATA *)&data,
229 &data.cFileName [0], stat);
235 ves_icall_System_IO_MonoIO_FindNextFile (HANDLE find, MonoIOStat *stat)
237 WIN32_FIND_DATA data;
240 result = FindNextFile (find, &data);
242 convert_win32_file_attribute_data ((const WIN32_FILE_ATTRIBUTE_DATA *)&data,
243 &data.cFileName [0], stat);
249 ves_icall_System_IO_MonoIO_FindClose (HANDLE find)
251 return FindClose (find);
255 ves_icall_System_IO_MonoIO_GetCurrentDirectory ()
262 buf = g_new (gunichar2, len);
265 if (GetCurrentDirectory (len, buf) > 0) {
270 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
278 ves_icall_System_IO_MonoIO_SetCurrentDirectory (MonoString *path)
280 gunichar2 *utf16_path;
283 utf16_path = mono_string_to_utf16 (path);
284 result = SetCurrentDirectory (utf16_path);
291 ves_icall_System_IO_MonoIO_MoveFile (MonoString *path, MonoString *dest)
293 gunichar2 *utf16_path, *utf16_dest;
296 utf16_path = mono_string_to_utf16 (path);
297 utf16_dest = mono_string_to_utf16 (dest);
298 result = MoveFile (utf16_path, utf16_dest);
306 ves_icall_System_IO_MonoIO_CopyFile (MonoString *path, MonoString *dest, gboolean overwrite)
308 gunichar2 *utf16_path, *utf16_dest;
311 utf16_path = mono_string_to_utf16 (path);
312 utf16_dest = mono_string_to_utf16 (dest);
313 result = CopyFile (utf16_path, utf16_dest, !overwrite);
321 ves_icall_System_IO_MonoIO_DeleteFile (MonoString *path)
323 gunichar2 *utf16_path;
326 utf16_path = mono_string_to_utf16 (path);
327 result = DeleteFile (utf16_path);
334 ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path)
336 gunichar2 *utf16_path;
339 utf16_path = mono_string_to_utf16 (path);
340 result = GetFileAttributes (utf16_path);
347 ves_icall_System_IO_MonoIO_SetFileAttributes (MonoString *path, gint32 attrs)
349 gunichar2 *utf16_path;
352 utf16_path = mono_string_to_utf16 (path);
353 result = SetFileAttributes (utf16_path, attrs);
360 ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat)
362 gunichar2 *utf16_path;
364 WIN32_FILE_ATTRIBUTE_DATA data;
366 utf16_path = mono_string_to_utf16 (path);
367 result = GetFileAttributesEx (utf16_path, GetFileExInfoStandard, &data);
371 convert_win32_file_attribute_data (&data, utf16_path, stat);
377 ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode, gint32 access_mode, gint32 share)
379 gunichar2 *utf16_filename;
382 utf16_filename = mono_string_to_utf16 (filename);
383 result = CreateFile (utf16_filename, convert_access (access_mode), convert_share (share),
384 NULL, convert_mode (mode), FILE_ATTRIBUTE_NORMAL, NULL);
385 g_free (utf16_filename);
391 ves_icall_System_IO_MonoIO_Close (HANDLE handle)
393 return CloseHandle (handle);
397 ves_icall_System_IO_MonoIO_Read (HANDLE handle, MonoArray *dest, gint32 dest_offset, gint32 count)
403 if (dest_offset + count > mono_array_length (dest))
406 buffer = mono_array_addr (dest, guchar, dest_offset);
407 result = ReadFile (handle, buffer, count, &n, NULL);
416 ves_icall_System_IO_MonoIO_Write (HANDLE handle, MonoArray *src, gint32 src_offset, gint32 count)
422 if (src_offset + count > mono_array_length (src))
425 buffer = mono_array_addr (src, guchar, src_offset);
426 result = WriteFile (handle, buffer, count, &n, NULL);
435 ves_icall_System_IO_MonoIO_Seek (HANDLE handle, gint64 offset, gint32 origin)
439 offset_hi = offset >> 32;
440 offset = SetFilePointer (handle, offset & 0xFFFFFFFF, &offset_hi,
441 convert_seekorigin (origin));
443 return offset | ((gint64)offset_hi << 32);
447 ves_icall_System_IO_MonoIO_Flush (HANDLE handle)
449 return FlushFileBuffers (handle);
453 ves_icall_System_IO_MonoIO_GetLength (HANDLE handle)
458 length = GetFileSize (handle, &length_hi);
459 return length | ((gint64)length_hi << 32);
463 ves_icall_System_IO_MonoIO_SetLength (HANDLE handle, gint64 length)
470 /* save file pointer */
473 offset = SetFilePointer (handle, 0, &offset_hi, FILE_CURRENT);
475 /* extend or truncate */
477 length_hi = length >> 32;
478 SetFilePointer (handle, length & 0xFFFFFFFF, &length_hi, FILE_BEGIN);
479 result = SetEndOfFile (handle);
481 /* restore file pointer */
483 SetFilePointer (handle, offset & 0xFFFFFFFF, &offset_hi, FILE_BEGIN);
489 ves_icall_System_IO_MonoIO_SetFileTime (HANDLE handle, gint64 creation_time, gint64 last_access_time, gint64 last_write_time)
491 const FILETIME *creation_filetime;
492 const FILETIME *last_access_filetime;
493 const FILETIME *last_write_filetime;
495 if (creation_time < 0)
496 creation_filetime = NULL;
498 creation_filetime = (FILETIME *)&creation_time;
500 if (last_access_time < 0)
501 last_access_filetime = NULL;
503 last_access_filetime = (FILETIME *)&last_access_time;
505 if (last_write_time < 0)
506 last_write_filetime = NULL;
508 last_write_filetime = (FILETIME *)&last_write_time;
510 return SetFileTime (handle, creation_filetime, last_access_filetime, last_write_filetime);
514 ves_icall_System_IO_MonoIO_get_ConsoleOutput ()
516 return GetStdHandle (STD_OUTPUT_HANDLE);
520 ves_icall_System_IO_MonoIO_get_ConsoleInput ()
522 return GetStdHandle (STD_INPUT_HANDLE);
526 ves_icall_System_IO_MonoIO_get_ConsoleError ()
528 return GetStdHandle (STD_ERROR_HANDLE);
532 ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar ()
534 #if defined (PLATFORM_WIN32)
535 return (gunichar2) 0x003a; /* colon */
537 return (gunichar2) 0x002f; /* forward slash */
542 ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar ()
544 #if defined (PLATFORM_WIN32)
545 return (gunichar2) 0x005c; /* backslash */
547 return (gunichar2) 0x002f; /* forward slash */
552 ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar ()
554 #if defined (PLATFORM_WIN32)
555 return (gunichar2) 0x002f; /* forward slash */
557 return (gunichar2) 0x005c; /* backslash */
562 ves_icall_System_IO_MonoIO_get_PathSeparator ()
564 #if defined (PLATFORM_WIN32)
565 return (gunichar2) 0x003b; /* semicolon */
567 return (gunichar2) 0x003a; /* colon */
571 static gunichar2 invalid_path_chars [] = {
572 #if defined (PLATFORM_WIN32)
573 0x0022, /* double quote */
574 0x003c, /* less than */
575 0x003e, /* greater than */
582 ves_icall_System_IO_MonoIO_get_InvalidPathChars ()
588 domain = mono_domain_get ();
589 chars = mono_array_new (domain, mono_defaults.char_class, 5);
591 n = sizeof (invalid_path_chars) / sizeof (gunichar2);
593 for (i = 0; i < n; ++ i)
594 mono_array_set (chars, gunichar2, i, invalid_path_chars [i]);