X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Ffile-io.c;h=99970866f4e38217f29765e12983d1947dd7e304;hb=bc00e94e0159f6f3c6a2436e9d0269ce3253f8b1;hp=81e18903d9fe1e04fea28fd7b783c2eb056513ff;hpb=f9f7b65e0c27f58c66ca93598da0f28435d0377d;p=mono.git diff --git a/mono/metadata/file-io.c b/mono/metadata/file-io.c index 81e18903d9f..99970866f4e 100644 --- a/mono/metadata/file-io.c +++ b/mono/metadata/file-io.c @@ -5,8 +5,8 @@ * Dick Porter (dick@ximian.com) * Gonzalo Paniagua Javier (gonzalo@ximian.com) * - * (C) 2001,2002,2003 Ximian, Inc. - * Copyright (c) 2004,2005,2006 Novell, Inc. (http://www.novell.com) + * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com) + * Copyright 2004-2009 Novell, Inc (http://www.novell.com) */ #include @@ -14,7 +14,6 @@ #include #include #include -#include #ifdef HAVE_UNISTD_H #include #endif @@ -188,7 +187,7 @@ static void convert_win32_file_attribute_data (const WIN32_FILE_ATTRIBUTE_DATA * while (name [len]) ++ len; - stat->name = mono_string_new_utf16 (mono_domain_get (), name, len); + MONO_STRUCT_SETREF (stat, name, mono_string_new_utf16 (mono_domain_get (), name, len)); } /* Managed file attributes have nearly but not quite the same values @@ -306,6 +305,18 @@ ves_icall_System_IO_MonoIO_RemoveDirectory (MonoString *path, gint32 *error) return(ret); } +static gchar * +get_search_dir (MonoString *pattern) +{ + gchar *p; + gchar *result; + + p = mono_string_to_utf8 (pattern); + result = g_path_get_dirname (p); + g_free (p); + return result; +} + MonoArray * ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *path, MonoString *path_with_pattern, @@ -345,8 +356,8 @@ ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *path, return(NULL); } + utf8_path = get_search_dir (path_with_pattern); names = g_ptr_array_new (); - utf8_path = mono_string_to_utf8 (path); do { if ((data.cFileName[0] == '.' && data.cFileName[1] == 0) || @@ -386,6 +397,115 @@ ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *path, return result; } +typedef struct { + MonoDomain *domain; + gchar *utf8_path; + HANDLE find_handle; +} IncrementalFind; + +static gboolean +incremental_find_check_match (IncrementalFind *handle, WIN32_FIND_DATA *data, MonoString **result) +{ + gchar *utf8_result; + gchar *full_name; + + if ((data->cFileName[0] == '.' && data->cFileName[1] == 0) || (data->cFileName[0] == '.' && data->cFileName[1] == '.' && data->cFileName[2] == 0)) + return FALSE; + + utf8_result = g_utf16_to_utf8 (data->cFileName, -1, NULL, NULL, NULL); + if (utf8_result == NULL) + return FALSE; + + full_name = g_build_filename (handle->utf8_path, utf8_result, NULL); + g_free (utf8_result); + *result = mono_string_new (mono_domain_get (), full_name); + g_free (full_name); + + return TRUE; +} + +MonoString * +ves_icall_System_IO_MonoIO_FindFirst (MonoString *path, + MonoString *path_with_pattern, + gint32 *result_attr, gint32 *error, + gpointer *handle) +{ + WIN32_FIND_DATA data; + HANDLE find_handle; + IncrementalFind *ifh; + MonoString *result; + + *error = ERROR_SUCCESS; + + find_handle = FindFirstFile (mono_string_chars (path_with_pattern), &data); + + if (find_handle == INVALID_HANDLE_VALUE) { + gint32 find_error = GetLastError (); + *handle = NULL; + + if (find_error == ERROR_FILE_NOT_FOUND) + return NULL; + + *error = find_error; + return NULL; + } + + ifh = g_new (IncrementalFind, 1); + ifh->find_handle = find_handle; + ifh->utf8_path = mono_string_to_utf8 (path); + ifh->domain = mono_domain_get (); + *handle = ifh; + + while (incremental_find_check_match (ifh, &data, &result) == 0){ + if (FindNextFile (find_handle, &data) == FALSE){ + int e = GetLastError (); + if (e != ERROR_NO_MORE_FILES) + *error = e; + return NULL; + } + } + *result_attr = data.dwFileAttributes; + + return result; +} + +MonoString * +ves_icall_System_IO_MonoIO_FindNext (gpointer handle, gint32 *result_attr, gint32 *error) +{ + IncrementalFind *ifh = handle; + WIN32_FIND_DATA data; + MonoString *result; + + error = ERROR_SUCCESS; + do { + if (FindNextFile (ifh->find_handle, &data) == FALSE){ + int e = GetLastError (); + if (e != ERROR_NO_MORE_FILES) + *error = e; + return NULL; + } + } while (incremental_find_check_match (ifh, &data, &result) == 0); + + *result_attr = data.dwFileAttributes; + return result; +} + +int +ves_icall_System_IO_MonoIO_FindClose (gpointer handle) +{ + IncrementalFind *ifh = handle; + gint32 error; + + if (FindClose (ifh->find_handle) == FALSE){ + error = GetLastError (); + } else + error = ERROR_SUCCESS; + g_free (ifh->utf8_path); + g_free (ifh); + + return error; +} + MonoString * ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *error) { @@ -403,9 +523,10 @@ ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *error) res_len = GetCurrentDirectory (len, buf); if (res_len > len) { /*buf is too small.*/ + int old_res_len = res_len; g_free (buf); buf = g_new (gunichar2, res_len); - res_len = GetCurrentDirectory (res_len, buf); + res_len = GetCurrentDirectory (res_len, buf) == old_res_len; } if (res_len) { @@ -606,6 +727,7 @@ ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat, stat); } else { *error=GetLastError (); + memset (stat, 0, sizeof (MonoIOStat)); } return result; @@ -696,6 +818,8 @@ ves_icall_System_IO_MonoIO_Read (HANDLE handle, MonoArray *dest, MONO_ARCH_SAVE_REGS; *error=ERROR_SUCCESS; + + MONO_CHECK_ARG_NULL (dest); if (dest_offset + count > mono_array_length (dest)) return 0; @@ -723,6 +847,8 @@ ves_icall_System_IO_MonoIO_Write (HANDLE handle, MonoArray *src, MONO_ARCH_SAVE_REGS; *error=ERROR_SUCCESS; + + MONO_CHECK_ARG_NULL (src); if (src_offset + count > mono_array_length (src)) return 0; @@ -749,7 +875,7 @@ ves_icall_System_IO_MonoIO_Seek (HANDLE handle, gint64 offset, gint32 origin, *error=ERROR_SUCCESS; offset_hi = offset >> 32; - offset = SetFilePointer (handle, offset & 0xFFFFFFFF, &offset_hi, + offset = SetFilePointer (handle, (gint32) (offset & 0xFFFFFFFF), &offset_hi, convert_seekorigin (origin)); if(offset==INVALID_SET_FILE_POINTER) { @@ -948,7 +1074,7 @@ MonoBoolean ves_icall_System_IO_MonoIO_DuplicateHandle (HANDLE source_process_ha gunichar2 ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar () { -#if defined (PLATFORM_WIN32) +#if defined (TARGET_WIN32) return (gunichar2) ':'; /* colon */ #else return (gunichar2) '/'; /* forward slash */ @@ -958,7 +1084,7 @@ ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar () gunichar2 ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar () { -#if defined (PLATFORM_WIN32) +#if defined (TARGET_WIN32) return (gunichar2) '\\'; /* backslash */ #else return (gunichar2) '/'; /* forward slash */ @@ -968,7 +1094,7 @@ ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar () gunichar2 ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar () { -#if defined (PLATFORM_WIN32) +#if defined (TARGET_WIN32) return (gunichar2) '/'; /* forward slash */ #else return (gunichar2) '/'; /* slash, same as DirectorySeparatorChar */ @@ -978,7 +1104,7 @@ ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar () gunichar2 ves_icall_System_IO_MonoIO_get_PathSeparator () { -#if defined (PLATFORM_WIN32) +#if defined (TARGET_WIN32) return (gunichar2) ';'; /* semicolon */ #else return (gunichar2) ':'; /* colon */ @@ -987,7 +1113,7 @@ ves_icall_System_IO_MonoIO_get_PathSeparator () static const gunichar2 invalid_path_chars [] = { -#if defined (PLATFORM_WIN32) +#if defined (TARGET_WIN32) 0x0022, /* double quote, which seems allowed in MS.NET but should be rejected */ 0x003c, /* less than */ 0x003e, /* greater than */ @@ -1043,12 +1169,11 @@ ves_icall_System_IO_MonoIO_GetTempPath (MonoString **mono_name) if(ret>0) { #ifdef DEBUG - g_message (G_GNUC_PRETTY_FUNCTION - ": Temp path is [%s] (len %d)", name, ret); + g_message ("%s: Temp path is [%s] (len %d)", __func__, name, ret); #endif - *mono_name=mono_string_new_utf16 (mono_domain_get (), name, - ret); + mono_gc_wbarrier_generic_store ((gpointer) mono_name, + (MonoObject*) mono_string_new_utf16 (mono_domain_get (), name, ret)); } g_free (name);