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 return CreateDirectory (mono_string_chars (path), NULL);
195 ves_icall_System_IO_MonoIO_RemoveDirectory (MonoString *path)
197 return RemoveDirectory (mono_string_chars (path));
201 ves_icall_System_IO_MonoIO_FindFirstFile (MonoString *path, MonoIOStat *stat)
203 WIN32_FIND_DATA data;
206 result = FindFirstFile (mono_string_chars (path), &data);
208 /* note: WIN32_FIND_DATA is an extension of WIN32_FILE_ATTRIBUTE_DATA */
210 if (result != INVALID_HANDLE_VALUE)
211 convert_win32_file_attribute_data ((const WIN32_FILE_ATTRIBUTE_DATA *)&data,
212 &data.cFileName [0], stat);
218 ves_icall_System_IO_MonoIO_FindNextFile (HANDLE find, MonoIOStat *stat)
220 WIN32_FIND_DATA data;
223 result = FindNextFile (find, &data);
225 convert_win32_file_attribute_data ((const WIN32_FILE_ATTRIBUTE_DATA *)&data,
226 &data.cFileName [0], stat);
232 ves_icall_System_IO_MonoIO_FindClose (HANDLE find)
234 return FindClose (find);
238 ves_icall_System_IO_MonoIO_GetCurrentDirectory ()
245 buf = g_new (gunichar2, len);
248 if (GetCurrentDirectory (len, buf) > 0) {
253 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
261 ves_icall_System_IO_MonoIO_SetCurrentDirectory (MonoString *path)
263 return SetCurrentDirectory (mono_string_chars (path));
267 ves_icall_System_IO_MonoIO_MoveFile (MonoString *path, MonoString *dest)
269 return MoveFile (mono_string_chars (path), mono_string_chars (dest));
273 ves_icall_System_IO_MonoIO_CopyFile (MonoString *path, MonoString *dest, gboolean overwrite)
275 return CopyFile (mono_string_chars (path), mono_string_chars (dest), !overwrite);
279 ves_icall_System_IO_MonoIO_DeleteFile (MonoString *path)
281 return DeleteFile (mono_string_chars (path));
285 ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path)
287 return GetFileAttributes (mono_string_chars (path));
291 ves_icall_System_IO_MonoIO_SetFileAttributes (MonoString *path, gint32 attrs)
293 return SetFileAttributes (mono_string_chars (path), attrs);
297 ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat)
300 WIN32_FILE_ATTRIBUTE_DATA data;
302 result = GetFileAttributesEx (mono_string_chars (path), GetFileExInfoStandard, &data);
305 convert_win32_file_attribute_data (&data, mono_string_chars (path), stat);
311 ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode, gint32 access_mode, gint32 share)
313 return CreateFile (mono_string_chars (filename), convert_access (access_mode), convert_share (share),
314 NULL, convert_mode (mode), FILE_ATTRIBUTE_NORMAL, NULL);
318 ves_icall_System_IO_MonoIO_Close (HANDLE handle)
320 return CloseHandle (handle);
324 ves_icall_System_IO_MonoIO_Read (HANDLE handle, MonoArray *dest, gint32 dest_offset, gint32 count)
330 if (dest_offset + count > mono_array_length (dest))
333 buffer = mono_array_addr (dest, guchar, dest_offset);
334 result = ReadFile (handle, buffer, count, &n, NULL);
343 ves_icall_System_IO_MonoIO_Write (HANDLE handle, MonoArray *src, gint32 src_offset, gint32 count)
349 if (src_offset + count > mono_array_length (src))
352 buffer = mono_array_addr (src, guchar, src_offset);
353 result = WriteFile (handle, buffer, count, &n, NULL);
362 ves_icall_System_IO_MonoIO_Seek (HANDLE handle, gint64 offset, gint32 origin)
366 offset_hi = offset >> 32;
367 offset = SetFilePointer (handle, offset & 0xFFFFFFFF, &offset_hi,
368 convert_seekorigin (origin));
370 return offset | ((gint64)offset_hi << 32);
374 ves_icall_System_IO_MonoIO_Flush (HANDLE handle)
376 return FlushFileBuffers (handle);
380 ves_icall_System_IO_MonoIO_GetLength (HANDLE handle)
385 length = GetFileSize (handle, &length_hi);
386 return length | ((gint64)length_hi << 32);
390 ves_icall_System_IO_MonoIO_SetLength (HANDLE handle, gint64 length)
397 /* save file pointer */
400 offset = SetFilePointer (handle, 0, &offset_hi, FILE_CURRENT);
402 /* extend or truncate */
404 length_hi = length >> 32;
405 SetFilePointer (handle, length & 0xFFFFFFFF, &length_hi, FILE_BEGIN);
406 result = SetEndOfFile (handle);
408 /* restore file pointer */
410 SetFilePointer (handle, offset & 0xFFFFFFFF, &offset_hi, FILE_BEGIN);
416 ves_icall_System_IO_MonoIO_SetFileTime (HANDLE handle, gint64 creation_time, gint64 last_access_time, gint64 last_write_time)
418 const FILETIME *creation_filetime;
419 const FILETIME *last_access_filetime;
420 const FILETIME *last_write_filetime;
422 if (creation_time < 0)
423 creation_filetime = NULL;
425 creation_filetime = (FILETIME *)&creation_time;
427 if (last_access_time < 0)
428 last_access_filetime = NULL;
430 last_access_filetime = (FILETIME *)&last_access_time;
432 if (last_write_time < 0)
433 last_write_filetime = NULL;
435 last_write_filetime = (FILETIME *)&last_write_time;
437 return SetFileTime (handle, creation_filetime, last_access_filetime, last_write_filetime);
441 ves_icall_System_IO_MonoIO_get_ConsoleOutput ()
443 return GetStdHandle (STD_OUTPUT_HANDLE);
447 ves_icall_System_IO_MonoIO_get_ConsoleInput ()
449 return GetStdHandle (STD_INPUT_HANDLE);
453 ves_icall_System_IO_MonoIO_get_ConsoleError ()
455 return GetStdHandle (STD_ERROR_HANDLE);
459 ves_icall_System_IO_MonoIO_CreatePipe (HANDLE *read_handle,
460 HANDLE *write_handle)
462 SECURITY_ATTRIBUTES attr;
465 attr.nLength=sizeof(SECURITY_ATTRIBUTES);
466 attr.bInheritHandle=TRUE;
467 attr.lpSecurityDescriptor=NULL;
469 ret=CreatePipe (read_handle, write_handle, &attr, 0);
471 /* FIXME: throw an exception? */
479 ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar ()
481 #if defined (PLATFORM_WIN32)
482 return (gunichar2) 0x003a; /* colon */
484 return (gunichar2) 0x002f; /* forward slash */
489 ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar ()
491 #if defined (PLATFORM_WIN32)
492 return (gunichar2) 0x005c; /* backslash */
494 return (gunichar2) 0x002f; /* forward slash */
499 ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar ()
501 #if defined (PLATFORM_WIN32)
502 return (gunichar2) 0x002f; /* forward slash */
504 return (gunichar2) 0x005c; /* backslash */
509 ves_icall_System_IO_MonoIO_get_PathSeparator ()
511 #if defined (PLATFORM_WIN32)
512 return (gunichar2) 0x003b; /* semicolon */
514 return (gunichar2) 0x003a; /* colon */
518 static gunichar2 invalid_path_chars [] = {
519 #if defined (PLATFORM_WIN32)
520 0x0022, /* double quote */
521 0x003c, /* less than */
522 0x003e, /* greater than */
529 ves_icall_System_IO_MonoIO_get_InvalidPathChars ()
535 domain = mono_domain_get ();
536 chars = mono_array_new (domain, mono_defaults.char_class, 5);
538 n = sizeof (invalid_path_chars) / sizeof (gunichar2);
540 for (i = 0; i < n; ++ i)
541 mono_array_set (chars, gunichar2, i, invalid_path_chars [i]);