Tue May 13 16:41:49 CEST 2003 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / metadata / file-io.c
index 168bca429862194acd04b5cfe9e624431e757b65..818a0420e6261609f4387c3a77ecb26ef178867b 100644 (file)
@@ -16,7 +16,9 @@
 #include <mono/metadata/exception.h>
 #include <mono/metadata/appdomain.h>
 
-#define DEBUG
+#undef DEBUG
+
+/* conversion functions */
 
 static guint32 convert_mode(MonoFileMode mono_mode)
 {
@@ -102,6 +104,7 @@ static guint32 convert_share(MonoFileShare mono_share)
        return(share);
 }
 
+#if 0
 static guint32 convert_stdhandle(guint32 fd)
 {
        guint32 stdhandle;
@@ -123,6 +126,7 @@ static guint32 convert_stdhandle(guint32 fd)
        
        return(stdhandle);
 }
+#endif
 
 static guint32 convert_seekorigin(MonoSeekOrigin origin)
 {
@@ -148,223 +152,666 @@ static guint32 convert_seekorigin(MonoSeekOrigin origin)
        return(w32origin);
 }
 
-/* fd must be one of stdin (value 0), stdout (1) or stderr (2).  These
- * values must be hardcoded in corlib.
- */
-HANDLE ves_icall_System_PAL_OpSys_GetStdHandle(MonoObject *this,
-                                              gint32 fd)
+static gint64 convert_filetime (const FILETIME *filetime)
 {
-       HANDLE handle;
+       gint64 *ticks;
 
-       if(fd!=0 && fd!=1 && fd!=2) {
-               mono_raise_exception(mono_get_exception_io("Invalid file descriptor"));
-       }
+       ticks = (gint64 *)filetime;
+       return *ticks;
+}
+
+static void convert_win32_file_attribute_data (const WIN32_FILE_ATTRIBUTE_DATA *data, const gunichar2 *name, MonoIOStat *stat)
+{
+       int len;
+       
+       stat->attributes = data->dwFileAttributes;
+       stat->creation_time = convert_filetime (&data->ftCreationTime);
+       stat->last_access_time = convert_filetime (&data->ftLastAccessTime);
+       stat->last_write_time = convert_filetime (&data->ftLastWriteTime);
+       stat->length = ((gint64)data->nFileSizeHigh << 32) | data->nFileSizeLow;
+
+       len = 0;
+       while (name [len])
+               ++ len;
+
+       stat->name = mono_string_new_utf16 (mono_domain_get (), name, len);
+}
+
+/* System.IO.MonoIO internal calls */
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_CreateDirectory (MonoString *path, gint32 *error)
+{
+       gboolean ret;
        
-       handle=GetStdHandle(convert_stdhandle(fd));
+       MONO_ARCH_SAVE_REGS;
+
+       *error=ERROR_SUCCESS;
+       
+       ret=CreateDirectory (mono_string_chars (path), NULL);
+       if(ret==FALSE) {
+               *error=GetLastError ();
+       }
        
-       return(handle);
+       return(ret);
 }
 
-void ves_icall_System_PAL_OpSys_DeleteFile(MonoObject *this, MonoString *path)
+MonoBoolean
+ves_icall_System_IO_MonoIO_RemoveDirectory (MonoString *path, gint32 *error)
 {
-       char *filename;
+       gboolean ret;
+       
+       MONO_ARCH_SAVE_REGS;
+
+       *error=ERROR_SUCCESS;
        
-       filename=mono_string_to_utf16(path);
+       ret=RemoveDirectory (mono_string_chars (path));
+       if(ret==FALSE) {
+               *error=GetLastError ();
+       }
        
-       DeleteFile(filename);
+       return(ret);
+}
+
+HANDLE 
+ves_icall_System_IO_MonoIO_FindFirstFile (MonoString *path, MonoIOStat *stat,
+                                         gint32 *error)
+{
+       WIN32_FIND_DATA data;
+       HANDLE result;
 
-       g_free(filename);
+       MONO_ARCH_SAVE_REGS;
+
+       *error=ERROR_SUCCESS;
+       
+       result = FindFirstFile (mono_string_chars (path), &data);
+
+       /* note: WIN32_FIND_DATA is an extension of WIN32_FILE_ATTRIBUTE_DATA */
+
+       if (result != INVALID_HANDLE_VALUE) {
+               convert_win32_file_attribute_data ((const WIN32_FILE_ATTRIBUTE_DATA *)&data,
+                                                  &data.cFileName [0], stat);
+       } else {
+               *error=GetLastError ();
+       }
+
+       return result;
 }
 
-gboolean ves_icall_System_PAL_OpSys_ExistsFile(MonoObject *this, MonoString *path)
+MonoBoolean
+ves_icall_System_IO_MonoIO_FindNextFile (HANDLE find, MonoIOStat *stat,
+                                        gint32 *error)
 {
-       return(FALSE);
+       WIN32_FIND_DATA data;
+       gboolean result;
+
+       MONO_ARCH_SAVE_REGS;
+
+       *error=ERROR_SUCCESS;
+       
+       result = FindNextFile (find, &data);
+       if (result) {
+               convert_win32_file_attribute_data ((const WIN32_FILE_ATTRIBUTE_DATA *)&data,
+                                                  &data.cFileName [0], stat);
+       } else {
+               *error=GetLastError ();
+       }
+
+       return result;
 }
 
-gboolean ves_icall_System_PAL_OpSys_GetFileTime(HANDLE handle, gint64 *createtime, gint64 *lastaccess, gint64 *lastwrite)
+MonoBoolean
+ves_icall_System_IO_MonoIO_FindClose (HANDLE find, gint32 *error)
 {
        gboolean ret;
-       FILETIME cr, ac, wr;
        
-       if(handle == INVALID_HANDLE_VALUE) 
-               mono_raise_exception(mono_get_exception_io("Invalid handle"));
+       MONO_ARCH_SAVE_REGS;
 
-       ret=GetFileTime(handle, &cr, &ac, &wr);
-       if(ret==TRUE) {
-               /* The FILETIME struct holds two unsigned 32 bit
-                * values for the low and high bytes, but the .net
-                * file time insists on being signed :(
-                */
-               *createtime=((gint64)cr.dwHighDateTime << 32) +
-                       cr.dwLowDateTime;
-               *lastaccess=((gint64)ac.dwHighDateTime << 32) +
-                       ac.dwLowDateTime;
-               *lastwrite=((gint64)wr.dwHighDateTime << 32) +
-                       wr.dwLowDateTime;
+       *error=ERROR_SUCCESS;
+       
+       ret=FindClose (find);
+       if(ret==FALSE) {
+               *error=GetLastError ();
        }
        
        return(ret);
 }
 
-gboolean ves_icall_System_PAL_OpSys_SetFileTime(HANDLE handle, gint64 createtime, gint64 lastaccess, gint64 lastwrite)
+MonoString *
+ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *error)
+{
+       MonoString *result;
+       gunichar2 *buf;
+       int len;
+
+       MONO_ARCH_SAVE_REGS;
+
+       len = MAX_PATH + 1;
+       buf = g_new (gunichar2, len);
+       
+       *error=ERROR_SUCCESS;
+       result = NULL;
+
+       if (GetCurrentDirectory (len, buf) > 0) {
+               len = 0;
+               while (buf [len])
+                       ++ len;
+
+               result = mono_string_new_utf16 (mono_domain_get (), buf, len);
+       } else {
+               *error=GetLastError ();
+       }
+
+       g_free (buf);
+       return result;
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_SetCurrentDirectory (MonoString *path,
+                                               gint32 *error)
 {
        gboolean ret;
-       FILETIME cr, ac, wr;
        
-       if(handle == INVALID_HANDLE_VALUE)
-               mono_raise_exception(mono_get_exception_io("Invalid handle"));
+       MONO_ARCH_SAVE_REGS;
 
-       cr.dwLowDateTime= createtime & 0xFFFFFFFF;
-       cr.dwHighDateTime= createtime >> 32;
+       *error=ERROR_SUCCESS;
+       
+       ret=SetCurrentDirectory (mono_string_chars (path));
+       if(ret==FALSE) {
+               *error=GetLastError ();
+       }
        
-       ac.dwLowDateTime= lastaccess & 0xFFFFFFFF;
-       ac.dwHighDateTime= lastaccess >> 32;
+       return(ret);
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_MoveFile (MonoString *path, MonoString *dest,
+                                    gint32 *error)
+{
+       gboolean ret;
        
-       wr.dwLowDateTime= lastwrite & 0xFFFFFFFF;
-       wr.dwHighDateTime= lastwrite >> 32;
+       MONO_ARCH_SAVE_REGS;
 
-       ret=SetFileTime(handle, &cr, &ac, &wr);
+       *error=ERROR_SUCCESS;
+       
+       ret=MoveFile (mono_string_chars (path), mono_string_chars (dest));
+       if(ret==FALSE) {
+               *error=GetLastError ();
+       }
        
        return(ret);
 }
 
-/* System.IO.FileStream */
+MonoBoolean
+ves_icall_System_IO_MonoIO_CopyFile (MonoString *path, MonoString *dest,
+                                    MonoBoolean overwrite, gint32 *error)
+{
+       gboolean ret;
+       
+       MONO_ARCH_SAVE_REGS;
 
-HANDLE
-ves_icall_System_IO_FileStream_FileOpen (MonoString *path, gint32 mode, gint32 access, gint32 share) {
-       HANDLE handle;
-       char *filename;
+       *error=ERROR_SUCCESS;
+       
+       ret=CopyFile (mono_string_chars (path), mono_string_chars (dest), !overwrite);
+       if(ret==FALSE) {
+               *error=GetLastError ();
+       }
        
-       filename=mono_string_to_utf16(path);
+       return(ret);
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_DeleteFile (MonoString *path, gint32 *error)
+{
+       gboolean ret;
        
-       handle=CreateFile(filename, convert_access(access),
-                         convert_share(share), NULL, convert_mode(mode),
-                         FILE_ATTRIBUTE_NORMAL, NULL);
+       MONO_ARCH_SAVE_REGS;
 
-       g_free(filename);
+       *error=ERROR_SUCCESS;
        
-       /* fixme: raise mor appropriate exceptions (errno) */
-       if(handle == INVALID_HANDLE_VALUE) {
-               mono_raise_exception(mono_get_exception_io("Invalid handle"));
+       ret=DeleteFile (mono_string_chars (path));
+       if(ret==FALSE) {
+               *error=GetLastError ();
        }
-
-       return(handle);
+       
+       return(ret);
 }
 
-void 
-ves_icall_System_IO_FileStream_FileClose (HANDLE handle) {
-       if(handle == INVALID_HANDLE_VALUE) {
-               mono_raise_exception(mono_get_exception_io("Invalid handle"));
+gint32 
+ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path, gint32 *error)
+{
+       gint32 ret;
+       
+       MONO_ARCH_SAVE_REGS;
+
+       *error=ERROR_SUCCESS;
+       
+       ret=GetFileAttributes (mono_string_chars (path));
+       if(ret==INVALID_FILE_ATTRIBUTES) {
+               *error=GetLastError ();
        }
+       
+       return(ret);
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_SetFileAttributes (MonoString *path, gint32 attrs,
+                                             gint32 *error)
+{
+       gboolean ret;
+       
+       MONO_ARCH_SAVE_REGS;
 
-       CloseHandle(handle);
+       *error=ERROR_SUCCESS;
+       
+       ret=SetFileAttributes (mono_string_chars (path), attrs);
+       if(ret==FALSE) {
+               *error=GetLastError ();
+       }
+       
+       return(ret);
 }
 
-gint32 
-ves_icall_System_IO_FileStream_FileRead (HANDLE handle, MonoArray *dest, gint32 dest_offset, gint32 count) {
+gint32
+ves_icall_System_IO_MonoIO_GetFileType (HANDLE handle, gint32 *error)
+{
        gboolean ret;
-       guint32 bytesread;
-       guchar *buf;
-       gint32 alen;
+       
+       MONO_ARCH_SAVE_REGS;
 
-       if(handle == INVALID_HANDLE_VALUE) {
-               mono_raise_exception(mono_get_exception_io("Invalid handle"));
+       *error=ERROR_SUCCESS;
+       
+       ret=GetFileType (handle);
+       if(ret==FILE_TYPE_UNKNOWN) {
+               /* Not necessarily an error, but the caller will have
+                * to decide based on the error value.
+                */
+               *error=GetLastError ();
        }
+       
+       return(ret);
+}
 
-       alen=mono_array_length(dest);
-       if(dest_offset+count>alen) {
-               return(0);
+MonoBoolean
+ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat,
+                                       gint32 *error)
+{
+       gboolean result;
+       WIN32_FILE_ATTRIBUTE_DATA data;
+
+       MONO_ARCH_SAVE_REGS;
+
+       *error=ERROR_SUCCESS;
+       
+       result = GetFileAttributesEx (mono_string_chars (path), GetFileExInfoStandard, &data);
+
+       if (result) {
+               convert_win32_file_attribute_data (&data,
+                                                  mono_string_chars (path),
+                                                  stat);
+       } else {
+               *error=GetLastError ();
        }
+
+       return result;
+}
+
+HANDLE 
+ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode,
+                                gint32 access_mode, gint32 share,
+                                gint32 *error)
+{
+       HANDLE ret;
        
-       buf=mono_array_addr(dest, guchar, dest_offset);
+       MONO_ARCH_SAVE_REGS;
+
+       *error=ERROR_SUCCESS;
        
-       ret=ReadFile(handle, buf, count, &bytesread, NULL);
+       ret=CreateFile (mono_string_chars (filename),
+                       convert_access (access_mode), convert_share (share),
+                       NULL, convert_mode (mode), FILE_ATTRIBUTE_NORMAL,
+                       NULL);
+       if(ret==INVALID_HANDLE_VALUE) {
+               *error=GetLastError ();
+       }
        
-       return(bytesread);
+       return(ret);
 }
 
-gint32 
-ves_icall_System_IO_FileStream_FileWrite (HANDLE handle, MonoArray *src, gint32 src_offset, gint32 count) {
+MonoBoolean
+ves_icall_System_IO_MonoIO_Close (HANDLE handle, gint32 *error)
+{
        gboolean ret;
-       guint32 byteswritten;
-       guchar *buf;
-       gint32 alen;
        
-       if(handle == INVALID_HANDLE_VALUE) {
-               mono_raise_exception(mono_get_exception_io("Invalid handle"));
-       }
+       MONO_ARCH_SAVE_REGS;
 
-       alen=mono_array_length(src);
-       if(src_offset+count>alen) {
-               return(0);
+       *error=ERROR_SUCCESS;
+       
+       ret=CloseHandle (handle);
+       if(ret==FALSE) {
+               *error=GetLastError ();
        }
        
-       buf=mono_array_addr(src, guchar, src_offset);
+       return(ret);
+}
+
+gint32 
+ves_icall_System_IO_MonoIO_Read (HANDLE handle, MonoArray *dest,
+                                gint32 dest_offset, gint32 count,
+                                gint32 *error)
+{
+       guchar *buffer;
+       gboolean result;
+       guint32 n;
+
+       MONO_ARCH_SAVE_REGS;
+
+       *error=ERROR_SUCCESS;
+       
+       if (dest_offset + count > mono_array_length (dest))
+               return 0;
+
+       buffer = mono_array_addr (dest, guchar, dest_offset);
+       result = ReadFile (handle, buffer, count, &n, NULL);
+
+       if (!result) {
+               *error=GetLastError ();
+               return -1;
+       }
+
+       return (gint32)n;
+}
+
+gint32 
+ves_icall_System_IO_MonoIO_Write (HANDLE handle, MonoArray *src,
+                                 gint32 src_offset, gint32 count,
+                                 gint32 *error)
+{
+       guchar *buffer;
+       gboolean result;
+       guint32 n;
+
+       MONO_ARCH_SAVE_REGS;
+
+       *error=ERROR_SUCCESS;
        
-       ret=WriteFile(handle, buf, count, &byteswritten, NULL);
+       if (src_offset + count > mono_array_length (src))
+               return 0;
        
-       return(byteswritten);
+       buffer = mono_array_addr (src, guchar, src_offset);
+       result = WriteFile (handle, buffer, count, &n, NULL);
+
+       if (!result) {
+               *error=GetLastError ();
+               return -1;
+       }
+
+       return (gint32)n;
 }
 
 gint64 
-ves_icall_System_IO_FileStream_FileSeek (HANDLE handle, gint64 offset, gint32 origin) {
-       gint64 ret;
-       gint32 offsetlo, offsethi, retlo;
+ves_icall_System_IO_MonoIO_Seek (HANDLE handle, gint64 offset, gint32 origin,
+                                gint32 *error)
+{
+       guint32 offset_hi;
+
+       MONO_ARCH_SAVE_REGS;
+
+       *error=ERROR_SUCCESS;
        
-       if(handle == INVALID_HANDLE_VALUE) {
-               mono_raise_exception(mono_get_exception_io("Invalid handle"));
-       }
+       offset_hi = offset >> 32;
+       offset = SetFilePointer (handle, offset & 0xFFFFFFFF, &offset_hi,
+                                convert_seekorigin (origin));
 
-       offsetlo=offset & 0xFFFFFFFF;
-       offsethi=offset >> 32;
+       if(offset==INVALID_SET_FILE_POINTER) {
+               *error=GetLastError ();
+       }
+       
+       return offset | ((gint64)offset_hi << 32);
+}
 
-       retlo=SetFilePointer(handle, offset, &offsethi,
-                            convert_seekorigin(origin));
+MonoBoolean
+ves_icall_System_IO_MonoIO_Flush (HANDLE handle, gint32 *error)
+{
+       gboolean ret;
        
-       ret=((gint64)offsethi << 32) + offsetlo;
+       MONO_ARCH_SAVE_REGS;
 
+       *error=ERROR_SUCCESS;
+       
+       ret=FlushFileBuffers (handle);
+       if(ret==FALSE) {
+               *error=GetLastError ();
+       }
+       
        return(ret);
 }
 
 gint64 
-ves_icall_System_IO_FileStream_FileGetLength (HANDLE handle) {
-       gint32 length_lo, length_hi;
+ves_icall_System_IO_MonoIO_GetLength (HANDLE handle, gint32 *error)
+{
+       gint64 length;
+       guint32 length_hi;
+
+       MONO_ARCH_SAVE_REGS;
 
-       if (handle == INVALID_HANDLE_VALUE)
-               mono_raise_exception (mono_get_exception_io ("Invalid handle"));
+       *error=ERROR_SUCCESS;
        
-       length_lo = GetFileSize (handle, &length_hi);
+       length = GetFileSize (handle, &length_hi);
+       if(length==INVALID_FILE_SIZE) {
+               *error=GetLastError ();
+       }
        
-       return ((gint64)length_hi << 32) | length_lo;
+       return length | ((gint64)length_hi << 32);
 }
 
-void 
-ves_icall_System_IO_FileStream_FileSetLength (HANDLE handle, gint64 length) {
-       /* FIXME: Should this put the file pointer back to where it
-        * was before we started setting the length? The spec doesnt
-        * say, as usual
-        */
+MonoBoolean
+ves_icall_System_IO_MonoIO_SetLength (HANDLE handle, gint64 length,
+                                     gint32 *error)
+{
+       gint64 offset, offset_set;
+       gint32 offset_hi;
+       gint32 length_hi;
+       gboolean result;
+
+       MONO_ARCH_SAVE_REGS;
+
+       *error=ERROR_SUCCESS;
+       
+       /* save file pointer */
+
+       offset_hi = 0;
+       offset = SetFilePointer (handle, 0, &offset_hi, FILE_CURRENT);
+       if(offset==INVALID_SET_FILE_POINTER) {
+               *error=GetLastError ();
+               return(FALSE);
+       }
+
+       /* extend or truncate */
+
+       length_hi = length >> 32;
+       offset_set=SetFilePointer (handle, length & 0xFFFFFFFF, &length_hi,
+                                  FILE_BEGIN);
+       if(offset_set==INVALID_SET_FILE_POINTER) {
+               *error=GetLastError ();
+               return(FALSE);
+       }
+
+       result = SetEndOfFile (handle);
+       if(result==FALSE) {
+               *error=GetLastError ();
+               return(FALSE);
+       }
+
+       /* restore file pointer */
+
+       offset_set=SetFilePointer (handle, offset & 0xFFFFFFFF, &offset_hi,
+                                  FILE_BEGIN);
+       if(offset_set==INVALID_SET_FILE_POINTER) {
+               *error=GetLastError ();
+               return(FALSE);
+       }
+
+       return result;
+}
 
+MonoBoolean
+ves_icall_System_IO_MonoIO_SetFileTime (HANDLE handle, gint64 creation_time,
+                                       gint64 last_access_time,
+                                       gint64 last_write_time, gint32 *error)
+{
        gboolean ret;
-       gint32 lenlo, lenhi, retlo;
+       const FILETIME *creation_filetime;
+       const FILETIME *last_access_filetime;
+       const FILETIME *last_write_filetime;
+
+       MONO_ARCH_SAVE_REGS;
+
+       *error=ERROR_SUCCESS;
        
-       if(handle == INVALID_HANDLE_VALUE) {
-               mono_raise_exception(mono_get_exception_io("Invalid handle"));
+       if (creation_time < 0)
+               creation_filetime = NULL;
+       else
+               creation_filetime = (FILETIME *)&creation_time;
+
+       if (last_access_time < 0)
+               last_access_filetime = NULL;
+       else
+               last_access_filetime = (FILETIME *)&last_access_time;
+
+       if (last_write_time < 0)
+               last_write_filetime = NULL;
+       else
+               last_write_filetime = (FILETIME *)&last_write_time;
+
+       ret=SetFileTime (handle, creation_filetime, last_access_filetime, last_write_filetime);
+       if(ret==FALSE) {
+               *error=GetLastError ();
        }
+       
+       return(ret);
+}
+
+HANDLE 
+ves_icall_System_IO_MonoIO_get_ConsoleOutput ()
+{
+       MONO_ARCH_SAVE_REGS;
+
+       return GetStdHandle (STD_OUTPUT_HANDLE);
+}
+
+HANDLE 
+ves_icall_System_IO_MonoIO_get_ConsoleInput ()
+{
+       MONO_ARCH_SAVE_REGS;
 
-       lenlo=length & 0xFFFFFFFF;
-       lenhi=length >> 32;
+       return GetStdHandle (STD_INPUT_HANDLE);
+}
 
-       retlo=SetFilePointer(handle, lenlo, &lenhi, FILE_BEGIN);
-       ret=SetEndOfFile(handle);
+HANDLE 
+ves_icall_System_IO_MonoIO_get_ConsoleError ()
+{
+       MONO_ARCH_SAVE_REGS;
+
+       return GetStdHandle (STD_ERROR_HANDLE);
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_CreatePipe (HANDLE *read_handle,
+                                      HANDLE *write_handle)
+{
+       SECURITY_ATTRIBUTES attr;
+       gboolean ret;
        
+       MONO_ARCH_SAVE_REGS;
+
+       attr.nLength=sizeof(SECURITY_ATTRIBUTES);
+       attr.bInheritHandle=TRUE;
+       attr.lpSecurityDescriptor=NULL;
+       
+       ret=CreatePipe (read_handle, write_handle, &attr, 0);
        if(ret==FALSE) {
-               mono_raise_exception(mono_get_exception_io("IO Exception"));
+               /* FIXME: throw an exception? */
+               return(FALSE);
        }
+       
+       return(TRUE);
+}
+
+gunichar2 
+ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar ()
+{
+       MONO_ARCH_SAVE_REGS;
+
+#if defined (PLATFORM_WIN32)
+       return (gunichar2) 0x003a;      /* colon */
+#else
+       return (gunichar2) 0x002f;      /* forward slash */
+#endif
 }
 
-void 
-ves_icall_System_IO_FileStream_FileFlush (HANDLE handle) {
-       /* FIXME: implement FlushFileBuffers */
+gunichar2 
+ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar ()
+{
+       MONO_ARCH_SAVE_REGS;
+
+#if defined (PLATFORM_WIN32)
+       return (gunichar2) 0x005c;      /* backslash */
+#else
+       return (gunichar2) 0x002f;      /* forward slash */
+#endif
 }
 
+gunichar2 
+ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar ()
+{
+       MONO_ARCH_SAVE_REGS;
+
+#if defined (PLATFORM_WIN32)
+       return (gunichar2) 0x002f;      /* forward slash */
+#else
+       return (gunichar2) 0x005c;      /* backslash */
+#endif
+}
+
+gunichar2 
+ves_icall_System_IO_MonoIO_get_PathSeparator ()
+{
+       MONO_ARCH_SAVE_REGS;
+
+#if defined (PLATFORM_WIN32)
+       return (gunichar2) 0x003b;      /* semicolon */
+#else
+       return (gunichar2) 0x003a;      /* colon */
+#endif
+}
+
+static gunichar2 invalid_path_chars [] = {
+#if defined (PLATFORM_WIN32)
+       0x0022,                         /* double quote */
+       0x003c,                         /* less than */
+       0x003e,                         /* greater than */
+       0x007c,                         /* pipe */
+#endif
+       0x0000                          /* null */
+};
+
+MonoArray *
+ves_icall_System_IO_MonoIO_get_InvalidPathChars ()
+{
+       MonoArray *chars;
+       MonoDomain *domain;
+       int i, n;
+
+       MONO_ARCH_SAVE_REGS;
+
+       domain = mono_domain_get ();
+       chars = mono_array_new (domain, mono_defaults.char_class, 5);
+
+       n = sizeof (invalid_path_chars) / sizeof (gunichar2);
+
+       for (i = 0; i < n; ++ i)
+               mono_array_set (chars, gunichar2, i, invalid_path_chars [i]);
+       
+       return chars;
+}