X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Ffile-io.c;h=818a0420e6261609f4387c3a77ecb26ef178867b;hb=dcdd5a25d92ca46ae14f74e974b4def640920e33;hp=e56ab9aef38ef3d37c0717245f52d40445b86772;hpb=df114a9d2fc19b2f18cad20d9aa8c7c8320fbd8b;p=mono.git diff --git a/mono/metadata/file-io.c b/mono/metadata/file-io.c index e56ab9aef38..818a0420e62 100644 --- a/mono/metadata/file-io.c +++ b/mono/metadata/file-io.c @@ -14,8 +14,11 @@ #include #include #include +#include -#define DEBUG +#undef DEBUG + +/* conversion functions */ static guint32 convert_mode(MonoFileMode mono_mode) { @@ -101,6 +104,7 @@ static guint32 convert_share(MonoFileShare mono_share) return(share); } +#if 0 static guint32 convert_stdhandle(guint32 fd) { guint32 stdhandle; @@ -122,6 +126,7 @@ static guint32 convert_stdhandle(guint32 fd) return(stdhandle); } +#endif static guint32 convert_seekorigin(MonoSeekOrigin origin) { @@ -147,210 +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")); - } - - handle=GetStdHandle(convert_stdhandle(fd)); + 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; - return(handle); + 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); } -gint32 ves_icall_System_PAL_OpSys_ReadFile(MonoObject *this, HANDLE handle, MonoArray *buffer, gint32 offset, gint32 count) +/* System.IO.MonoIO internal calls */ + +MonoBoolean +ves_icall_System_IO_MonoIO_CreateDirectory (MonoString *path, 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=CreateDirectory (mono_string_chars (path), NULL); + if(ret==FALSE) { + *error=GetLastError (); } + + return(ret); +} - alen=mono_array_length(buffer); - if(offset+count>alen) { - return(0); +MonoBoolean +ves_icall_System_IO_MonoIO_RemoveDirectory (MonoString *path, gint32 *error) +{ + gboolean ret; + + MONO_ARCH_SAVE_REGS; + + *error=ERROR_SUCCESS; + + ret=RemoveDirectory (mono_string_chars (path)); + if(ret==FALSE) { + *error=GetLastError (); } - buf=mono_array_addr(buffer, guchar, offset); + return(ret); +} + +HANDLE +ves_icall_System_IO_MonoIO_FindFirstFile (MonoString *path, MonoIOStat *stat, + gint32 *error) +{ + WIN32_FIND_DATA data; + HANDLE result; + + MONO_ARCH_SAVE_REGS; + + *error=ERROR_SUCCESS; - ret=ReadFile(handle, buf, count, &bytesread, NULL); + 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; +} + +MonoBoolean +ves_icall_System_IO_MonoIO_FindNextFile (HANDLE find, MonoIOStat *stat, + gint32 *error) +{ + WIN32_FIND_DATA data; + gboolean result; + + MONO_ARCH_SAVE_REGS; + + *error=ERROR_SUCCESS; - return(bytesread); + 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; } -gint32 ves_icall_System_PAL_OpSys_WriteFile(MonoObject *this, HANDLE handle, MonoArray *buffer, gint32 offset, gint32 count) +MonoBoolean +ves_icall_System_IO_MonoIO_FindClose (HANDLE find, 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; + + *error=ERROR_SUCCESS; + + ret=FindClose (find); + if(ret==FALSE) { + *error=GetLastError (); } + + return(ret); +} + +MonoString * +ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *error) +{ + MonoString *result; + gunichar2 *buf; + int len; + + MONO_ARCH_SAVE_REGS; - alen=mono_array_length(buffer); - if(offset+count>alen) { - return(0); + 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; - buf=mono_array_addr(buffer, guchar, offset); + MONO_ARCH_SAVE_REGS; + + *error=ERROR_SUCCESS; - ret=WriteFile(handle, buf, count, &byteswritten, NULL); + ret=SetCurrentDirectory (mono_string_chars (path)); + if(ret==FALSE) { + *error=GetLastError (); + } - return(byteswritten); + return(ret); } -gint32 ves_icall_System_PAL_OpSys_SetLengthFile(MonoObject *this, HANDLE handle, gint64 length) +MonoBoolean +ves_icall_System_IO_MonoIO_MoveFile (MonoString *path, MonoString *dest, + gint32 *error) { - /* 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 ret; + + MONO_ARCH_SAVE_REGS; + *error=ERROR_SUCCESS; + + ret=MoveFile (mono_string_chars (path), mono_string_chars (dest)); + if(ret==FALSE) { + *error=GetLastError (); + } + + return(ret); +} + +MonoBoolean +ves_icall_System_IO_MonoIO_CopyFile (MonoString *path, MonoString *dest, + MonoBoolean overwrite, gint32 *error) +{ gboolean ret; - gint32 lenlo, lenhi, retlo; - if(handle == INVALID_HANDLE_VALUE) { - mono_raise_exception(mono_get_exception_io("Invalid handle")); + MONO_ARCH_SAVE_REGS; + + *error=ERROR_SUCCESS; + + ret=CopyFile (mono_string_chars (path), mono_string_chars (dest), !overwrite); + if(ret==FALSE) { + *error=GetLastError (); } + + return(ret); +} - lenlo=length & 0xFFFFFFFF; - lenhi=length >> 32; +MonoBoolean +ves_icall_System_IO_MonoIO_DeleteFile (MonoString *path, gint32 *error) +{ + gboolean ret; + + MONO_ARCH_SAVE_REGS; - retlo=SetFilePointer(handle, lenlo, &lenhi, FILE_BEGIN); - ret=SetEndOfFile(handle); + *error=ERROR_SUCCESS; + ret=DeleteFile (mono_string_chars (path)); if(ret==FALSE) { - mono_raise_exception(mono_get_exception_io("IO Exception")); + *error=GetLastError (); } - return(0); + return(ret); } -HANDLE ves_icall_System_PAL_OpSys_OpenFile(MonoObject *this, MonoString *path, gint32 mode, gint32 access, gint32 share) +gint32 +ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path, gint32 *error) { - HANDLE handle; - char *filename; + gint32 ret; + + MONO_ARCH_SAVE_REGS; + + *error=ERROR_SUCCESS; + + ret=GetFileAttributes (mono_string_chars (path)); + if(ret==INVALID_FILE_ATTRIBUTES) { + *error=GetLastError (); + } - filename=mono_string_to_utf16(path); + return(ret); +} + +MonoBoolean +ves_icall_System_IO_MonoIO_SetFileAttributes (MonoString *path, gint32 attrs, + 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=SetFileAttributes (mono_string_chars (path), attrs); + if(ret==FALSE) { + *error=GetLastError (); } + + return(ret); +} - return(handle); +gint32 +ves_icall_System_IO_MonoIO_GetFileType (HANDLE handle, gint32 *error) +{ + gboolean ret; + + MONO_ARCH_SAVE_REGS; + + *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); } -void ves_icall_System_PAL_OpSys_CloseFile(MonoObject *this, HANDLE handle) +MonoBoolean +ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat, + gint32 *error) { - if(handle == INVALID_HANDLE_VALUE) { - mono_raise_exception(mono_get_exception_io("Invalid handle")); + 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 (); } - CloseHandle(handle); + return result; } -gint64 ves_icall_System_PAL_OpSys_SeekFile(MonoObject *this, HANDLE handle, - gint64 offset, gint32 origin) +HANDLE +ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode, + gint32 access_mode, gint32 share, + gint32 *error) { - gint64 ret; - gint32 offsetlo, offsethi, retlo; + HANDLE ret; - if(handle == INVALID_HANDLE_VALUE) { - mono_raise_exception(mono_get_exception_io("Invalid handle")); - } + MONO_ARCH_SAVE_REGS; - offsetlo=offset & 0xFFFFFFFF; - offsethi=offset >> 32; + *error=ERROR_SUCCESS; + + 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(ret); +} - retlo=SetFilePointer(handle, offset, &offsethi, - convert_seekorigin(origin)); +MonoBoolean +ves_icall_System_IO_MonoIO_Close (HANDLE handle, gint32 *error) +{ + gboolean ret; - ret=((gint64)offsethi << 32) + offsetlo; + MONO_ARCH_SAVE_REGS; + *error=ERROR_SUCCESS; + + ret=CloseHandle (handle); + if(ret==FALSE) { + *error=GetLastError (); + } + return(ret); } -void ves_icall_System_PAL_OpSys_DeleteFile(MonoObject *this, MonoString *path) +gint32 +ves_icall_System_IO_MonoIO_Read (HANDLE handle, MonoArray *dest, + gint32 dest_offset, gint32 count, + gint32 *error) { - char *filename; + guchar *buffer; + gboolean result; + guint32 n; + + MONO_ARCH_SAVE_REGS; + + *error=ERROR_SUCCESS; - filename=mono_string_to_utf16(path); + 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; - DeleteFile(filename); + if (src_offset + count > mono_array_length (src)) + return 0; + + buffer = mono_array_addr (src, guchar, src_offset); + result = WriteFile (handle, buffer, count, &n, NULL); + + if (!result) { + *error=GetLastError (); + return -1; + } - g_free(filename); + return (gint32)n; } -gboolean ves_icall_System_PAL_OpSys_ExistsFile(MonoObject *this, MonoString *path) +gint64 +ves_icall_System_IO_MonoIO_Seek (HANDLE handle, gint64 offset, gint32 origin, + gint32 *error) { - return(FALSE); + guint32 offset_hi; + + MONO_ARCH_SAVE_REGS; + + *error=ERROR_SUCCESS; + + offset_hi = offset >> 32; + offset = SetFilePointer (handle, offset & 0xFFFFFFFF, &offset_hi, + convert_seekorigin (origin)); + + if(offset==INVALID_SET_FILE_POINTER) { + *error=GetLastError (); + } + + return offset | ((gint64)offset_hi << 32); } -gboolean ves_icall_System_PAL_OpSys_GetFileTime(HANDLE handle, gint64 *createtime, gint64 *lastaccess, gint64 *lastwrite) +MonoBoolean +ves_icall_System_IO_MonoIO_Flush (HANDLE handle, 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=FlushFileBuffers (handle); + if(ret==FALSE) { + *error=GetLastError (); } return(ret); } -gboolean ves_icall_System_PAL_OpSys_SetFileTime(HANDLE handle, gint64 createtime, gint64 lastaccess, gint64 lastwrite) +gint64 +ves_icall_System_IO_MonoIO_GetLength (HANDLE handle, gint32 *error) { - gboolean ret; - FILETIME cr, ac, wr; + gint64 length; + guint32 length_hi; + + MONO_ARCH_SAVE_REGS; + + *error=ERROR_SUCCESS; - if(handle == INVALID_HANDLE_VALUE) { - mono_raise_exception(mono_get_exception_io("Invalid handle")); + length = GetFileSize (handle, &length_hi); + if(length==INVALID_FILE_SIZE) { + *error=GetLastError (); } + + return length | ((gint64)length_hi << 32); +} + +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; - cr.dwLowDateTime= createtime & 0xFFFFFFFF; - cr.dwHighDateTime= createtime >> 32; + MONO_ARCH_SAVE_REGS; + + *error=ERROR_SUCCESS; - ac.dwLowDateTime= lastaccess & 0xFFFFFFFF; - ac.dwHighDateTime= lastaccess >> 32; + /* 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; + const FILETIME *creation_filetime; + const FILETIME *last_access_filetime; + const FILETIME *last_write_filetime; + + MONO_ARCH_SAVE_REGS; + + *error=ERROR_SUCCESS; - wr.dwLowDateTime= lastwrite & 0xFFFFFFFF; - wr.dwHighDateTime= lastwrite >> 32; + 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, &cr, &ac, &wr); + 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; + + return GetStdHandle (STD_INPUT_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) { + /* 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 +} + +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; +}