3 * File IO internal calls
6 * Dick Porter (dick@ximian.com)
7 * Gonzalo Paniagua Javier (gonzalo@ximian.com)
9 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
11 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
12 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
23 #ifdef HAVE_SYS_STAT_H
26 #ifdef HAVE_SYS_TYPES_H
27 #include <sys/types.h>
30 #include <mono/metadata/object.h>
31 #include <mono/metadata/w32file.h>
32 #include <mono/metadata/w32error.h>
33 #include <mono/metadata/w32file-internals.h>
34 #include <mono/metadata/exception.h>
35 #include <mono/metadata/appdomain.h>
36 #include <mono/metadata/marshal.h>
37 #include <mono/utils/strenc.h>
38 #include <utils/mono-io-portability.h>
39 #include <mono/metadata/w32handle.h>
40 #include <mono/utils/w32api.h>
44 /* conversion functions */
46 static guint32 convert_mode(MonoFileMode mono_mode)
51 case FileMode_CreateNew:
60 case FileMode_OpenOrCreate:
63 case FileMode_Truncate:
64 mode=TRUNCATE_EXISTING;
70 g_warning("System.IO.FileMode has unknown value 0x%x",
79 static guint32 convert_access(MonoFileAccess mono_access)
87 case FileAccess_Write:
90 case FileAccess_ReadWrite:
91 access=GENERIC_READ|GENERIC_WRITE;
94 g_warning("System.IO.FileAccess has unknown value 0x%x",
103 static guint32 convert_share(MonoFileShare mono_share)
107 if (mono_share & FileShare_Read) {
108 share |= FILE_SHARE_READ;
110 if (mono_share & FileShare_Write) {
111 share |= FILE_SHARE_WRITE;
113 if (mono_share & FileShare_Delete) {
114 share |= FILE_SHARE_DELETE;
117 if (mono_share & ~(FileShare_Read|FileShare_Write|FileShare_Delete)) {
118 g_warning("System.IO.FileShare has unknown value 0x%x",
128 static guint32 convert_stdhandle(guint32 fd)
134 stdhandle=STD_INPUT_HANDLE;
137 stdhandle=STD_OUTPUT_HANDLE;
140 stdhandle=STD_ERROR_HANDLE;
143 g_warning("unknown standard file descriptor %d", fd);
144 stdhandle=STD_INPUT_HANDLE;
151 static guint32 convert_seekorigin(MonoSeekOrigin origin)
156 case SeekOrigin_Begin:
157 w32origin=FILE_BEGIN;
159 case SeekOrigin_Current:
160 w32origin=FILE_CURRENT;
166 g_warning("System.IO.SeekOrigin has unknown value 0x%x",
169 w32origin=FILE_CURRENT;
175 static gint64 convert_filetime (const FILETIME *filetime)
177 return (gint64) ((((guint64) filetime->dwHighDateTime) << 32) + filetime->dwLowDateTime);
180 /* Managed file attributes have nearly but not quite the same values
181 * as the w32 equivalents.
183 static guint32 convert_attrs(MonoFileAttributes attrs)
185 if(attrs & FileAttributes_Encrypted) {
186 attrs = (MonoFileAttributes)(attrs | FILE_ATTRIBUTE_ENCRYPTED);
193 * On Win32, mono_w32file_get_attributes|_ex () seems to try opening the file,
194 * which might lead to sharing violation errors, whereas mono_w32file_find_first
195 * always succeeds. These 2 wrappers resort to mono_w32file_find_first if
196 * mono_w32file_get_attributes|_ex () has failed.
199 get_file_attributes (const gunichar2 *path)
202 WIN32_FIND_DATA find_data;
206 res = mono_w32file_get_attributes (path);
210 error = mono_w32error_get_last ();
212 if (error != ERROR_SHARING_VIOLATION)
215 find_handle = mono_w32file_find_first (path, &find_data);
217 if (find_handle == INVALID_HANDLE_VALUE)
220 mono_w32file_find_close (find_handle);
222 return find_data.dwFileAttributes;
226 get_file_attributes_ex (const gunichar2 *path, MonoIOStat *stat)
229 WIN32_FIND_DATA find_data;
233 res = mono_w32file_get_attributes_ex (path, stat);
237 error = mono_w32error_get_last ();
238 if (error != ERROR_SHARING_VIOLATION)
241 find_handle = mono_w32file_find_first (path, &find_data);
243 if (find_handle == INVALID_HANDLE_VALUE)
246 mono_w32file_find_close (find_handle);
248 stat->attributes = find_data.dwFileAttributes;
249 stat->creation_time = convert_filetime (&find_data.ftCreationTime);
250 stat->last_access_time = convert_filetime (&find_data.ftLastAccessTime);
251 stat->last_write_time = convert_filetime (&find_data.ftLastWriteTime);
252 stat->length = ((gint64)find_data.nFileSizeHigh << 32) | find_data.nFileSizeLow;
256 /* System.IO.MonoIO internal calls */
259 ves_icall_System_IO_MonoIO_CreateDirectory (MonoString *path, gint32 *error)
263 *error=ERROR_SUCCESS;
265 ret=mono_w32file_create_directory (mono_string_chars (path));
267 *error=mono_w32error_get_last ();
274 ves_icall_System_IO_MonoIO_RemoveDirectory (MonoString *path, gint32 *error)
278 *error=ERROR_SUCCESS;
280 ret=mono_w32file_remove_directory (mono_string_chars (path));
282 *error=mono_w32error_get_last ();
289 get_search_dir (const gunichar2 *pattern)
294 p = g_utf16_to_utf8 (pattern, -1, NULL, NULL, NULL);
295 result = g_path_get_dirname (p);
301 get_filesystem_entries (const gunichar2 *path,
302 const gunichar2 *path_with_pattern,
303 gint attrs, gint mask,
307 WIN32_FIND_DATA data;
309 GPtrArray *names = NULL;
310 gchar *utf8_path = NULL, *utf8_result, *full_name;
313 mask = convert_attrs ((MonoFileAttributes)mask);
314 attributes = get_file_attributes (path);
315 if (attributes != -1) {
316 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
317 *error = ERROR_INVALID_NAME;
321 *error = mono_w32error_get_last ();
325 find_handle = mono_w32file_find_first (path_with_pattern, &data);
326 if (find_handle == INVALID_HANDLE_VALUE) {
327 gint32 find_error = mono_w32error_get_last ();
329 if (find_error == ERROR_FILE_NOT_FOUND || find_error == ERROR_NO_MORE_FILES) {
330 /* No files, so just return an empty array */
338 utf8_path = get_search_dir (path_with_pattern);
339 names = g_ptr_array_new ();
342 if ((data.cFileName[0] == '.' && data.cFileName[1] == 0) ||
343 (data.cFileName[0] == '.' && data.cFileName[1] == '.' && data.cFileName[2] == 0)) {
347 if ((data.dwFileAttributes & mask) == attrs) {
348 utf8_result = g_utf16_to_utf8 (data.cFileName, -1, NULL, NULL, NULL);
349 if (utf8_result == NULL) {
353 full_name = g_build_filename (utf8_path, utf8_result, NULL);
354 g_ptr_array_add (names, full_name);
356 g_free (utf8_result);
358 } while(mono_w32file_find_next (find_handle, &data));
360 if (mono_w32file_find_close (find_handle) == FALSE) {
361 *error = mono_w32error_get_last ();
369 for (i = 0; i < names->len; i++)
370 g_free (g_ptr_array_index (names, i));
371 g_ptr_array_free (names, TRUE);
379 ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *path,
380 MonoString *path_with_pattern,
381 gint attrs, gint mask,
385 MonoDomain *domain = mono_domain_get ();
390 *ioerror = ERROR_SUCCESS;
392 names = get_filesystem_entries (mono_string_chars (path), mono_string_chars (path_with_pattern), attrs, mask, ioerror);
395 // If there's no array and no error, then return an empty array.
396 if (*ioerror == ERROR_SUCCESS) {
397 MonoArray *arr = mono_array_new_checked (domain, mono_defaults.string_class, 0, &error);
398 mono_error_set_pending_exception (&error);
404 result = mono_array_new_checked (domain, mono_defaults.string_class, names->len, &error);
405 if (mono_error_set_pending_exception (&error))
407 for (i = 0; i < names->len; i++) {
408 mono_array_setref (result, i, mono_string_new (domain, (const char *)g_ptr_array_index (names, i)));
409 g_free (g_ptr_array_index (names, i));
412 g_ptr_array_free (names, TRUE);
423 incremental_find_check_match (IncrementalFind *handle, WIN32_FIND_DATA *data, MonoString **result)
428 if ((data->cFileName[0] == '.' && data->cFileName[1] == 0) || (data->cFileName[0] == '.' && data->cFileName[1] == '.' && data->cFileName[2] == 0))
431 utf8_result = g_utf16_to_utf8 (data->cFileName, -1, NULL, NULL, NULL);
432 if (utf8_result == NULL)
435 full_name = g_build_filename (handle->utf8_path, utf8_result, NULL);
436 g_free (utf8_result);
437 *result = mono_string_new (mono_domain_get (), full_name);
444 ves_icall_System_IO_MonoIO_FindFirstFile (MonoString *path_with_pattern, MonoString **file_name, gint32 *file_attr, gint32 *ioerror)
447 WIN32_FIND_DATA data;
450 hnd = mono_w32file_find_first (mono_string_chars (path_with_pattern), &data);
452 if (hnd == INVALID_HANDLE_VALUE) {
455 *ioerror = mono_w32error_get_last ();
459 mono_gc_wbarrier_generic_store (file_name, (MonoObject*) mono_string_from_utf16_checked (data.cFileName, &error));
460 mono_error_set_pending_exception (&error);
462 *file_attr = data.dwFileAttributes;
463 *ioerror = ERROR_SUCCESS;
469 ves_icall_System_IO_MonoIO_FindNextFile (HANDLE hnd, MonoString **file_name, gint32 *file_attr, gint32 *ioerror)
472 WIN32_FIND_DATA data;
475 res = mono_w32file_find_next (hnd, &data);
480 *ioerror = mono_w32error_get_last ();
484 mono_gc_wbarrier_generic_store (file_name, (MonoObject*) mono_string_from_utf16_checked (data.cFileName, &error));
485 mono_error_set_pending_exception (&error);
487 *file_attr = data.dwFileAttributes;
488 *ioerror = ERROR_SUCCESS;
494 ves_icall_System_IO_MonoIO_FindCloseFile (HANDLE hnd)
496 return mono_w32file_find_close (hnd);
499 /* FIXME make gc suspendable */
501 ves_icall_System_IO_MonoIO_FindFirst (MonoString *path,
502 MonoString *path_with_pattern,
503 gint32 *result_attr, gint32 *ioerror,
507 WIN32_FIND_DATA data;
509 IncrementalFind *ifh;
512 *ioerror = ERROR_SUCCESS;
514 find_handle = mono_w32file_find_first (mono_string_chars (path_with_pattern), &data);
516 if (find_handle == INVALID_HANDLE_VALUE) {
517 gint32 find_error = mono_w32error_get_last ();
520 if (find_error == ERROR_FILE_NOT_FOUND)
523 *ioerror = find_error;
527 ifh = g_new (IncrementalFind, 1);
528 ifh->find_handle = find_handle;
529 ifh->utf8_path = mono_string_to_utf8_checked (path, &error);
530 if (mono_error_set_pending_exception (&error)) {
531 mono_w32file_find_close (find_handle);
535 ifh->domain = mono_domain_get ();
538 while (incremental_find_check_match (ifh, &data, &result) == 0){
539 if (mono_w32file_find_next (find_handle, &data) == FALSE){
540 int e = mono_w32error_get_last ();
541 if (e != ERROR_NO_MORE_FILES)
546 *result_attr = data.dwFileAttributes;
551 /* FIXME make gc suspendable */
553 ves_icall_System_IO_MonoIO_FindNext (gpointer handle, gint32 *result_attr, gint32 *error)
555 IncrementalFind *ifh = (IncrementalFind *)handle;
556 WIN32_FIND_DATA data;
559 *error = ERROR_SUCCESS;
561 if (mono_w32file_find_next (ifh->find_handle, &data) == FALSE){
562 int e = mono_w32error_get_last ();
563 if (e != ERROR_NO_MORE_FILES)
567 } while (incremental_find_check_match (ifh, &data, &result) == 0);
569 *result_attr = data.dwFileAttributes;
574 ves_icall_System_IO_MonoIO_FindClose (gpointer handle)
576 IncrementalFind *ifh = (IncrementalFind *)handle;
579 if (mono_w32file_find_close (ifh->find_handle) == FALSE){
580 error = mono_w32error_get_last ();
582 error = ERROR_SUCCESS;
583 g_free (ifh->utf8_path);
590 ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *io_error)
597 len = MAX_PATH + 1; /*FIXME this is too smal under most unix systems.*/
598 buf = g_new (gunichar2, len);
601 *io_error=ERROR_SUCCESS;
604 res_len = mono_w32file_get_cwd (len, buf);
605 if (res_len > len) { /*buf is too small.*/
606 int old_res_len = res_len;
608 buf = g_new (gunichar2, res_len);
609 res_len = mono_w32file_get_cwd (res_len, buf) == old_res_len;
617 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
619 *io_error=mono_w32error_get_last ();
623 mono_error_set_pending_exception (&error);
628 ves_icall_System_IO_MonoIO_SetCurrentDirectory (MonoString *path,
633 *error=ERROR_SUCCESS;
635 ret=mono_w32file_set_cwd (mono_string_chars (path));
637 *error=mono_w32error_get_last ();
644 ves_icall_System_IO_MonoIO_MoveFile (MonoString *path, MonoString *dest, gint32 *error)
646 *error=ERROR_SUCCESS;
647 return mono_w32file_move (mono_string_chars (path), mono_string_chars (dest), error);
651 ves_icall_System_IO_MonoIO_ReplaceFile (MonoString *sourceFileName, MonoString *destinationFileName,
652 MonoString *destinationBackupFileName, MonoBoolean ignoreMetadataErrors,
655 gunichar2 *utf16_sourceFileName = NULL, *utf16_destinationFileName = NULL, *utf16_destinationBackupFileName = NULL;
656 guint32 replaceFlags = REPLACEFILE_WRITE_THROUGH;
659 utf16_sourceFileName = mono_string_chars (sourceFileName);
660 if (destinationFileName)
661 utf16_destinationFileName = mono_string_chars (destinationFileName);
662 if (destinationBackupFileName)
663 utf16_destinationBackupFileName = mono_string_chars (destinationBackupFileName);
665 *error = ERROR_SUCCESS;
666 if (ignoreMetadataErrors)
667 replaceFlags |= REPLACEFILE_IGNORE_MERGE_ERRORS;
669 /* FIXME: source and destination file names must not be NULL, but apparently they might be! */
670 return mono_w32file_replace (utf16_destinationFileName, utf16_sourceFileName,
671 utf16_destinationBackupFileName, replaceFlags, error);
675 ves_icall_System_IO_MonoIO_CopyFile (MonoString *path, MonoString *dest,
676 MonoBoolean overwrite, gint32 *error)
678 *error=ERROR_SUCCESS;
679 return mono_w32file_copy (mono_string_chars (path), mono_string_chars (dest), overwrite, error);
683 ves_icall_System_IO_MonoIO_DeleteFile (MonoString *path, gint32 *error)
687 *error=ERROR_SUCCESS;
689 ret=mono_w32file_delete (mono_string_chars (path));
691 *error=mono_w32error_get_last ();
698 ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path, gint32 *error)
701 *error=ERROR_SUCCESS;
703 ret=get_file_attributes (mono_string_chars (path));
706 * The definition of INVALID_FILE_ATTRIBUTES in the cygwin win32
707 * headers is wrong, hence this temporary workaround.
709 * http://cygwin.com/ml/cygwin/2003-09/msg01771.html
712 /* if(ret==INVALID_FILE_ATTRIBUTES) { */
713 *error=mono_w32error_get_last ();
719 ves_icall_System_IO_MonoIO_SetFileAttributes (MonoString *path, gint32 attrs,
723 *error=ERROR_SUCCESS;
725 ret=mono_w32file_set_attributes (mono_string_chars (path),
726 convert_attrs ((MonoFileAttributes)attrs));
728 *error=mono_w32error_get_last ();
734 ves_icall_System_IO_MonoIO_GetFileType (HANDLE handle, gint32 *error)
738 *error=ERROR_SUCCESS;
740 ret=mono_w32file_get_type (handle);
741 if(ret==FILE_TYPE_UNKNOWN) {
742 /* Not necessarily an error, but the caller will have
743 * to decide based on the error value.
745 *error=mono_w32error_get_last ();
752 ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat, gint32 *error)
756 *error=ERROR_SUCCESS;
758 result = get_file_attributes_ex (mono_string_chars (path), stat);
761 *error=mono_w32error_get_last ();
762 memset (stat, 0, sizeof (MonoIOStat));
769 ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode,
770 gint32 access_mode, gint32 share, gint32 options,
774 int attributes, attrs;
777 chars = mono_string_chars (filename);
778 *error=ERROR_SUCCESS;
781 if (options & FileOptions_Encrypted)
782 attributes = FILE_ATTRIBUTE_ENCRYPTED;
784 attributes = FILE_ATTRIBUTE_NORMAL;
785 if (options & FileOptions_DeleteOnClose)
786 attributes |= FILE_FLAG_DELETE_ON_CLOSE;
787 if (options & FileOptions_SequentialScan)
788 attributes |= FILE_FLAG_SEQUENTIAL_SCAN;
789 if (options & FileOptions_RandomAccess)
790 attributes |= FILE_FLAG_RANDOM_ACCESS;
792 if (options & FileOptions_Temporary)
793 attributes |= FILE_ATTRIBUTE_TEMPORARY;
795 if (options & FileOptions_WriteThrough)
796 attributes |= FILE_FLAG_WRITE_THROUGH;
798 attributes = FILE_ATTRIBUTE_NORMAL;
800 /* If we're opening a directory we need to set the extra flag
802 attrs = get_file_attributes (chars);
803 if (attrs != INVALID_FILE_ATTRIBUTES) {
804 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
805 attributes |= FILE_FLAG_BACKUP_SEMANTICS;
809 ret=mono_w32file_create (chars, convert_access ((MonoFileAccess)access_mode), convert_share ((MonoFileShare)share), convert_mode ((MonoFileMode)mode), attributes);
810 if(ret==INVALID_HANDLE_VALUE) {
811 *error=mono_w32error_get_last ();
818 ves_icall_System_IO_MonoIO_Close (HANDLE handle, gint32 *error)
821 *error=ERROR_SUCCESS;
823 ret=mono_w32file_close (handle);
825 *error=mono_w32error_get_last ();
831 ves_icall_System_IO_MonoIO_Read (HANDLE handle, MonoArray *dest,
832 gint32 dest_offset, gint32 count,
839 *error=ERROR_SUCCESS;
841 MONO_CHECK_ARG_NULL (dest, 0);
843 if (dest_offset > mono_array_length (dest) - count) {
844 mono_set_pending_exception (mono_get_exception_argument ("array", "array too small. numBytes/offset wrong."));
848 buffer = mono_array_addr (dest, guchar, dest_offset);
850 result = mono_w32file_read (handle, buffer, count, &n);
853 *error=mono_w32error_get_last ();
861 ves_icall_System_IO_MonoIO_Write (HANDLE handle, MonoArray *src,
862 gint32 src_offset, gint32 count,
869 *error=ERROR_SUCCESS;
871 MONO_CHECK_ARG_NULL (src, 0);
873 if (src_offset > mono_array_length (src) - count) {
874 mono_set_pending_exception (mono_get_exception_argument ("array", "array too small. numBytes/offset wrong."));
878 buffer = mono_array_addr (src, guchar, src_offset);
879 result = mono_w32file_write (handle, buffer, count, &n);
882 *error=mono_w32error_get_last ();
890 ves_icall_System_IO_MonoIO_Seek (HANDLE handle, gint64 offset, gint32 origin,
895 *error=ERROR_SUCCESS;
897 offset_hi = offset >> 32;
898 offset = mono_w32file_seek (handle, (gint32) (offset & 0xFFFFFFFF), &offset_hi,
899 convert_seekorigin ((MonoSeekOrigin)origin));
901 if(offset==INVALID_SET_FILE_POINTER) {
902 *error=mono_w32error_get_last ();
905 return offset | ((gint64)offset_hi << 32);
909 ves_icall_System_IO_MonoIO_Flush (HANDLE handle, gint32 *error)
913 *error=ERROR_SUCCESS;
915 ret=mono_w32file_flush (handle);
917 *error=mono_w32error_get_last ();
924 ves_icall_System_IO_MonoIO_GetLength (HANDLE handle, gint32 *error)
926 *error=ERROR_SUCCESS;
927 return mono_w32file_get_file_size (handle, error);
930 /* FIXME make gc suspendable */
932 ves_icall_System_IO_MonoIO_SetLength (HANDLE handle, gint64 length,
935 gint64 offset, offset_set;
940 *error=ERROR_SUCCESS;
942 /* save file pointer */
945 offset = mono_w32file_seek (handle, 0, &offset_hi, FILE_CURRENT);
946 if(offset==INVALID_SET_FILE_POINTER) {
947 *error=mono_w32error_get_last ();
951 /* extend or truncate */
953 length_hi = length >> 32;
954 offset_set=mono_w32file_seek (handle, length & 0xFFFFFFFF, &length_hi,
956 if(offset_set==INVALID_SET_FILE_POINTER) {
957 *error=mono_w32error_get_last ();
961 result = mono_w32file_truncate (handle);
963 *error=mono_w32error_get_last ();
967 /* restore file pointer */
969 offset_set=mono_w32file_seek (handle, offset & 0xFFFFFFFF, &offset_hi,
971 if(offset_set==INVALID_SET_FILE_POINTER) {
972 *error=mono_w32error_get_last ();
980 ves_icall_System_IO_MonoIO_SetFileTime (HANDLE handle, gint64 creation_time,
981 gint64 last_access_time,
982 gint64 last_write_time, gint32 *error)
985 const FILETIME *creation_filetime;
986 const FILETIME *access_filetime;
987 const FILETIME *write_filetime;
989 *error=ERROR_SUCCESS;
991 if (creation_time < 0)
992 creation_filetime = NULL;
994 creation_filetime = (FILETIME *)&creation_time;
996 if (last_access_time < 0)
997 access_filetime = NULL;
999 access_filetime = (FILETIME *)&last_access_time;
1001 if (last_write_time < 0)
1002 write_filetime = NULL;
1004 write_filetime = (FILETIME *)&last_write_time;
1006 ret=mono_w32file_set_times (handle, creation_filetime, access_filetime, write_filetime);
1008 *error=mono_w32error_get_last ();
1015 ves_icall_System_IO_MonoIO_get_ConsoleOutput ()
1017 return mono_w32file_get_console_output ();
1021 ves_icall_System_IO_MonoIO_get_ConsoleInput ()
1023 return mono_w32file_get_console_input ();
1027 ves_icall_System_IO_MonoIO_get_ConsoleError ()
1029 return mono_w32file_get_console_error ();
1033 ves_icall_System_IO_MonoIO_CreatePipe (HANDLE *read_handle, HANDLE *write_handle, gint32 *error)
1037 ret=mono_w32file_create_pipe (read_handle, write_handle, 0);
1040 *error = mono_w32error_get_last ();
1041 /* FIXME: throw an exception? */
1049 ves_icall_System_IO_MonoIO_DuplicateHandle (HANDLE source_process_handle, HANDLE source_handle,
1050 HANDLE target_process_handle, HANDLE *target_handle, gint32 access, gint32 inherit, gint32 options, gint32 *error)
1052 /* This is only used on Windows */
1057 ret=DuplicateHandle (source_process_handle, source_handle, target_process_handle, target_handle, access, inherit, options);
1060 mono_w32handle_ref (source_handle);
1061 *target_handle = source_handle;
1066 *error = mono_w32error_get_last ();
1067 /* FIXME: throw an exception? */
1076 ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar ()
1078 return (gunichar2) '/'; /* forward slash */
1082 ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar ()
1084 return (gunichar2) '/'; /* forward slash */
1088 ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar ()
1090 if (IS_PORTABILITY_SET)
1091 return (gunichar2) '\\'; /* backslash */
1093 return (gunichar2) '/'; /* forward slash */
1097 ves_icall_System_IO_MonoIO_get_PathSeparator ()
1099 return (gunichar2) ':'; /* colon */
1101 #endif /* !HOST_WIN32 */
1103 static const gunichar2
1104 invalid_path_chars [] = {
1105 #if defined (TARGET_WIN32)
1106 0x0022, /* double quote, which seems allowed in MS.NET but should be rejected */
1107 0x003c, /* less than */
1108 0x003e, /* greater than */
1125 ves_icall_System_IO_MonoIO_get_InvalidPathChars ()
1132 domain = mono_domain_get ();
1133 n = sizeof (invalid_path_chars) / sizeof (gunichar2);
1134 chars = mono_array_new_checked (domain, mono_defaults.char_class, n, &error);
1135 if (mono_error_set_pending_exception (&error))
1138 for (i = 0; i < n; ++ i)
1139 mono_array_set (chars, gunichar2, i, invalid_path_chars [i]);
1144 void ves_icall_System_IO_MonoIO_Lock (HANDLE handle, gint64 position,
1145 gint64 length, gint32 *error)
1147 *error=ERROR_SUCCESS;
1148 mono_w32file_lock (handle, position, length, error);
1151 void ves_icall_System_IO_MonoIO_Unlock (HANDLE handle, gint64 position,
1152 gint64 length, gint32 *error)
1154 *error=ERROR_SUCCESS;
1155 mono_w32file_unlock (handle, position, length, error);
1158 //Support for io-layer free mmap'd files.
1160 #if defined (TARGET_IOS) || defined (TARGET_ANDROID)
1163 mono_filesize_from_path (MonoString *string)
1168 char *path = mono_string_to_utf8_checked (string, &error);
1169 mono_error_raise_exception (&error); /* OK to throw, external only without a good alternative */
1173 stat_res = stat (path, &buf);
1178 res = (gint64)buf.st_size;
1186 mono_filesize_from_fd (int fd)
1192 res = fstat (fd, &buf);
1198 return (gint64)buf.st_size;
1204 void mono_w32handle_dump (void);
1206 void ves_icall_System_IO_MonoIO_DumpHandles (void)
1208 mono_w32handle_dump ();
1210 #endif /* !HOST_WIN32 */