#define DEBUG
+/* conversion functions */
+
static guint32 convert_mode(MonoFileMode mono_mode)
{
guint32 mode;
return(share);
}
+#if 0
static guint32 convert_stdhandle(guint32 fd)
{
guint32 stdhandle;
return(stdhandle);
}
+#endif
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"));
- }
-
- handle=GetStdHandle(convert_stdhandle(fd));
-
- return(handle);
+ ticks = (gint64 *)filetime;
+ return *ticks;
}
-void ves_icall_System_PAL_OpSys_DeleteFile(MonoObject *this, MonoString *path)
+static void convert_win32_file_attribute_data (const WIN32_FILE_ATTRIBUTE_DATA *data, const gunichar2 *name, MonoIOStat *stat)
{
- char *filename;
+ int len;
- filename=mono_string_to_utf16(path);
-
- DeleteFile(filename);
+ 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);
+}
- g_free(filename);
+/* System.IO.MonoIO internal calls */
+
+gint32
+ves_icall_System_IO_MonoIO_GetLastError ()
+{
+ return GetLastError ();
}
-gboolean ves_icall_System_PAL_OpSys_ExistsFile(MonoObject *this, MonoString *path)
+gboolean
+ves_icall_System_IO_MonoIO_CreateDirectory (MonoString *path)
{
- return(FALSE);
+ gunichar2 *utf16_path;
+ gboolean result;
+
+ utf16_path = mono_string_to_utf16 (path);
+ result = CreateDirectory (utf16_path, NULL);
+ g_free (utf16_path);
+
+ return result;
}
-gboolean ves_icall_System_PAL_OpSys_GetFileTime(HANDLE handle, gint64 *createtime, gint64 *lastaccess, gint64 *lastwrite)
+gboolean
+ves_icall_System_IO_MonoIO_RemoveDirectory (MonoString *path)
{
- gboolean ret;
- FILETIME cr, ac, wr;
+ gunichar2 *utf16_path;
+ gboolean result;
+
+ utf16_path = mono_string_to_utf16 (path);
+ result = RemoveDirectory (utf16_path);
+ g_free (utf16_path);
+
+ return result;
+}
+
+HANDLE
+ves_icall_System_IO_MonoIO_FindFirstFile (MonoString *path, MonoIOStat *stat)
+{
+ gunichar2 *utf16_path;
+ WIN32_FIND_DATA data;
+ HANDLE result;
+
+ utf16_path = mono_string_to_utf16 (path);
+ result = FindFirstFile (utf16_path, &data);
+ g_free (utf16_path);
+
+ /* 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);
+
+ return result;
+}
+
+gboolean
+ves_icall_System_IO_MonoIO_FindNextFile (HANDLE find, MonoIOStat *stat)
+{
+ WIN32_FIND_DATA data;
+ gboolean result;
+
+ result = FindNextFile (find, &data);
+ if (result)
+ convert_win32_file_attribute_data ((const WIN32_FILE_ATTRIBUTE_DATA *)&data,
+ &data.cFileName [0], stat);
+
+ return result;
+}
+
+gboolean
+ves_icall_System_IO_MonoIO_FindClose (HANDLE find)
+{
+ return FindClose (find);
+}
+
+MonoString *
+ves_icall_System_IO_MonoIO_GetCurrentDirectory ()
+{
+ MonoString *result;
+ gunichar2 *buf;
+ int len;
+
+ len = MAX_PATH + 1;
+ buf = g_new (gunichar2, len);
- if(handle == INVALID_HANDLE_VALUE)
- mono_raise_exception(mono_get_exception_io("Invalid handle"));
-
- 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;
+ result = NULL;
+ if (GetCurrentDirectory (len, buf) > 0) {
+ len = 0;
+ while (buf [len])
+ ++ len;
+
+ result = mono_string_new_utf16 (mono_domain_get (), buf, len);
}
-
- return(ret);
+
+ g_free (buf);
+ return result;
}
-gboolean ves_icall_System_PAL_OpSys_SetFileTime(HANDLE handle, gint64 createtime, gint64 lastaccess, gint64 lastwrite)
+gboolean
+ves_icall_System_IO_MonoIO_SetCurrentDirectory (MonoString *path)
{
- gboolean ret;
- FILETIME cr, ac, wr;
+ gunichar2 *utf16_path;
+ gboolean result;
- if(handle == INVALID_HANDLE_VALUE)
- mono_raise_exception(mono_get_exception_io("Invalid handle"));
+ utf16_path = mono_string_to_utf16 (path);
+ result = SetCurrentDirectory (utf16_path);
+ g_free (utf16_path);
- cr.dwLowDateTime= createtime & 0xFFFFFFFF;
- cr.dwHighDateTime= createtime >> 32;
-
- ac.dwLowDateTime= lastaccess & 0xFFFFFFFF;
- ac.dwHighDateTime= lastaccess >> 32;
-
- wr.dwLowDateTime= lastwrite & 0xFFFFFFFF;
- wr.dwHighDateTime= lastwrite >> 32;
+ return result;
+}
- ret=SetFileTime(handle, &cr, &ac, &wr);
-
- return(ret);
+gboolean
+ves_icall_System_IO_MonoIO_MoveFile (MonoString *path, MonoString *dest)
+{
+ gunichar2 *utf16_path, *utf16_dest;
+ gboolean result;
+
+ utf16_path = mono_string_to_utf16 (path);
+ utf16_dest = mono_string_to_utf16 (dest);
+ result = MoveFile (utf16_path, utf16_dest);
+ g_free (utf16_path);
+ g_free (utf16_dest);
+
+ return result;
}
-/* System.IO.FileStream */
+gboolean
+ves_icall_System_IO_MonoIO_CopyFile (MonoString *path, MonoString *dest, gboolean overwrite)
+{
+ gunichar2 *utf16_path, *utf16_dest;
+ gboolean result;
-HANDLE
-ves_icall_System_IO_FileStream_FileOpen (MonoString *path, gint32 mode, gint32 access, gint32 share) {
- HANDLE handle;
- char *filename;
-
- filename=mono_string_to_utf16(path);
-
- handle=CreateFile(filename, convert_access(access),
- convert_share(share), NULL, convert_mode(mode),
- FILE_ATTRIBUTE_NORMAL, NULL);
+ utf16_path = mono_string_to_utf16 (path);
+ utf16_dest = mono_string_to_utf16 (dest);
+ result = CopyFile (utf16_path, utf16_dest, !overwrite);
+ g_free (utf16_path);
+ g_free (utf16_dest);
- g_free(filename);
-
- /* fixme: raise mor appropriate exceptions (errno) */
- if(handle == INVALID_HANDLE_VALUE) {
- mono_raise_exception(mono_get_exception_io("Invalid handle"));
- }
+ return result;
+}
+
+gboolean
+ves_icall_System_IO_MonoIO_DeleteFile (MonoString *path)
+{
+ gunichar2 *utf16_path;
+ gboolean result;
- return(handle);
+ utf16_path = mono_string_to_utf16 (path);
+ result = DeleteFile (utf16_path);
+ g_free (utf16_path);
+
+ return result;
}
-void
-ves_icall_System_IO_FileStream_FileClose (gpointer handle) {
- if(handle == INVALID_HANDLE_VALUE) {
- mono_raise_exception(mono_get_exception_io("Invalid handle"));
- }
+gint32
+ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path)
+{
+ gunichar2 *utf16_path;
+ gint32 result;
+
+ utf16_path = mono_string_to_utf16 (path);
+ result = GetFileAttributes (utf16_path);
+ g_free (utf16_path);
+
+ return result;
+}
+
+gboolean
+ves_icall_System_IO_MonoIO_SetFileAttributes (MonoString *path, gint32 attrs)
+{
+ gunichar2 *utf16_path;
+ gboolean result;
+
+ utf16_path = mono_string_to_utf16 (path);
+ result = SetFileAttributes (utf16_path, attrs);
+ g_free (utf16_path);
+
+ return result;
+}
+
+gboolean
+ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat)
+{
+ gunichar2 *utf16_path;
+ gboolean result;
+ WIN32_FILE_ATTRIBUTE_DATA data;
+
+ utf16_path = mono_string_to_utf16 (path);
+ result = GetFileAttributesEx (utf16_path, GetFileExInfoStandard, &data);
+ g_free (utf16_path);
+
+ if (result)
+ convert_win32_file_attribute_data (&data, utf16_path, stat);
+
+ return result;
+}
+
+HANDLE
+ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode, gint32 access_mode, gint32 share)
+{
+ gunichar2 *utf16_filename;
+ HANDLE result;
- CloseHandle(handle);
+ utf16_filename = mono_string_to_utf16 (filename);
+ result = CreateFile (utf16_filename, convert_access (access_mode), convert_share (share),
+ NULL, convert_mode (mode), FILE_ATTRIBUTE_NORMAL, NULL);
+ g_free (utf16_filename);
+
+ return result;
+}
+
+gboolean
+ves_icall_System_IO_MonoIO_Close (HANDLE handle)
+{
+ return CloseHandle (handle);
}
gint32
-ves_icall_System_IO_FileStream_FileRead (gpointer handle, MonoArray *dest, gint32 dest_offset, gint32 count) {
- gboolean ret;
- guint32 bytesread;
- guchar *buf;
- gint32 alen;
-
- if(handle == INVALID_HANDLE_VALUE) {
- mono_raise_exception(mono_get_exception_io("Invalid handle"));
- }
+ves_icall_System_IO_MonoIO_Read (HANDLE handle, MonoArray *dest, gint32 dest_offset, gint32 count)
+{
+ guchar *buffer;
+ gboolean result;
+ guint32 n;
- alen=mono_array_length(dest);
- if(dest_offset+count>alen) {
- return(0);
- }
-
- buf=mono_array_addr(dest, guchar, dest_offset);
-
- ret=ReadFile(handle, buf, count, &bytesread, NULL);
-
- return(bytesread);
+ 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)
+ return -1;
+
+ return (gint32)n;
}
gint32
-ves_icall_System_IO_FileStream_FileWrite (gpointer handle, MonoArray *src, gint32 src_offset, gint32 count) {
- gboolean ret;
- guint32 byteswritten;
- guchar *buf;
- gint32 alen;
-
- if(handle == INVALID_HANDLE_VALUE) {
- mono_raise_exception(mono_get_exception_io("Invalid handle"));
- }
+ves_icall_System_IO_MonoIO_Write (HANDLE handle, MonoArray *src, gint32 src_offset, gint32 count)
+{
+ guchar *buffer;
+ gboolean result;
+ guint32 n;
- alen=mono_array_length(src);
- if(src_offset+count>alen) {
- return(0);
- }
-
- buf=mono_array_addr(src, guchar, src_offset);
+ if (src_offset + count > mono_array_length (src))
+ return 0;
- ret=WriteFile(handle, buf, count, &byteswritten, NULL);
-
- return(byteswritten);
+ buffer = mono_array_addr (src, guchar, src_offset);
+ result = WriteFile (handle, buffer, count, &n, NULL);
+
+ if (!result)
+ return -1;
+
+ return (gint32)n;
}
gint64
-ves_icall_System_IO_FileStream_FileSeek (gpointer handle, gint64 offset, gint32 origin) {
- gint64 ret;
- gint32 offsetlo, offsethi, retlo;
-
- if(handle == INVALID_HANDLE_VALUE) {
- mono_raise_exception(mono_get_exception_io("Invalid handle"));
- }
+ves_icall_System_IO_MonoIO_Seek (HANDLE handle, gint64 offset, gint32 origin)
+{
+ guint32 offset_hi;
- offsetlo=offset & 0xFFFFFFFF;
- offsethi=offset >> 32;
+ offset_hi = offset >> 32;
+ offset = SetFilePointer (handle, offset & 0xFFFFFFFF, &offset_hi,
+ convert_seekorigin (origin));
- retlo=SetFilePointer(handle, offset, &offsethi,
- convert_seekorigin(origin));
-
- ret=((gint64)offsethi << 32) + offsetlo;
+ return offset | ((gint64)offset_hi << 32);
+}
- return(ret);
+gboolean
+ves_icall_System_IO_MonoIO_Flush (HANDLE handle)
+{
+ return FlushFileBuffers (handle);
}
gint64
-ves_icall_System_IO_FileStream_FileGetLength (gpointer handle) {
- gint32 length_lo, length_hi;
+ves_icall_System_IO_MonoIO_GetLength (HANDLE handle)
+{
+ gint64 length;
+ guint32 length_hi;
- if (handle == INVALID_HANDLE_VALUE)
- mono_raise_exception (mono_get_exception_io ("Invalid handle"));
-
- length_lo = GetFileSize (handle, &length_hi);
-
- return ((gint64)length_hi << 32) | length_lo;
+ length = GetFileSize (handle, &length_hi);
+ return length | ((gint64)length_hi << 32);
}
-void
-ves_icall_System_IO_FileStream_FileSetLength (gpointer 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
- */
+gboolean
+ves_icall_System_IO_MonoIO_SetLength (HANDLE handle, gint64 length)
+{
+ gint64 offset;
+ gint32 offset_hi;
+ gint32 length_hi;
+ gboolean result;
- gboolean ret;
- gint32 lenlo, lenhi, retlo;
-
- if(handle == INVALID_HANDLE_VALUE) {
- mono_raise_exception(mono_get_exception_io("Invalid handle"));
- }
+ /* save file pointer */
- lenlo=length & 0xFFFFFFFF;
- lenhi=length >> 32;
+ offset_hi = 0;
+ offset = SetFilePointer (handle, 0, &offset_hi, FILE_CURRENT);
- retlo=SetFilePointer(handle, lenlo, &lenhi, FILE_BEGIN);
- ret=SetEndOfFile(handle);
-
- if(ret==FALSE) {
- mono_raise_exception(mono_get_exception_io("IO Exception"));
- }
+ /* extend or truncate */
+
+ length_hi = length >> 32;
+ SetFilePointer (handle, length & 0xFFFFFFFF, &length_hi, FILE_BEGIN);
+ result = SetEndOfFile (handle);
+
+ /* restore file pointer */
+
+ SetFilePointer (handle, offset & 0xFFFFFFFF, &offset_hi, FILE_BEGIN);
+
+ return result;
+}
+
+gboolean
+ves_icall_System_IO_MonoIO_SetFileTime (HANDLE handle, gint64 creation_time, gint64 last_access_time, gint64 last_write_time)
+{
+ const FILETIME *creation_filetime;
+ const FILETIME *last_access_filetime;
+ const FILETIME *last_write_filetime;
+
+ 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;
+
+ return SetFileTime (handle, creation_filetime, last_access_filetime, last_write_filetime);
}
-void
-ves_icall_System_IO_FileStream_FileFlush (gpointer handle) {
- /* FIXME: implement FlushFileBuffers */
+HANDLE
+ves_icall_System_IO_MonoIO_get_ConsoleOutput ()
+{
+ return GetStdHandle (STD_OUTPUT_HANDLE);
+}
+
+HANDLE
+ves_icall_System_IO_MonoIO_get_ConsoleInput ()
+{
+ return GetStdHandle (STD_INPUT_HANDLE);
}
+HANDLE
+ves_icall_System_IO_MonoIO_get_ConsoleError ()
+{
+ return GetStdHandle (STD_ERROR_HANDLE);
+}
+
+gunichar2
+ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar ()
+{
+#if defined (PLATFORM_WIN32)
+ return (gunichar2) 0x003a; /* colon */
+#else
+ return (gunichar2) 0x002f; /* forward slash */
+#endif
+}
+
+gunichar2
+ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar ()
+{
+#if defined (PLATFORM_WIN32)
+ return (gunichar2) 0x005c; /* backslash */
+#else
+ return (gunichar2) 0x002f; /* forward slash */
+#endif
+}
+
+gunichar2
+ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar ()
+{
+#if defined (PLATFORM_WIN32)
+ return (gunichar2) 0x002f; /* forward slash */
+#else
+ return (gunichar2) 0x005c; /* backslash */
+#endif
+}
+
+gunichar2
+ves_icall_System_IO_MonoIO_get_PathSeparator ()
+{
+#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;
+
+ 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;
+}