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 MonoString *name = mono_string_new_checked (domain, (const char *)g_ptr_array_index (names, i), &error);
409 if (mono_error_set_pending_exception (&error))
411 mono_array_setref (result, i, name);
412 g_free (g_ptr_array_index (names, i));
415 g_ptr_array_free (names, TRUE);
426 incremental_find_check_match (IncrementalFind *handle, WIN32_FIND_DATA *data, MonoString **result, MonoError *error)
432 if ((data->cFileName[0] == '.' && data->cFileName[1] == 0) || (data->cFileName[0] == '.' && data->cFileName[1] == '.' && data->cFileName[2] == 0))
435 utf8_result = g_utf16_to_utf8 (data->cFileName, -1, NULL, NULL, NULL);
436 if (utf8_result == NULL)
439 full_name = g_build_filename (handle->utf8_path, utf8_result, NULL);
440 g_free (utf8_result);
441 *result = mono_string_new_checked (mono_domain_get (), full_name, error);
450 ves_icall_System_IO_MonoIO_FindFirstFile (MonoString *path_with_pattern, MonoString **file_name, gint32 *file_attr, gint32 *ioerror)
453 WIN32_FIND_DATA data;
456 hnd = mono_w32file_find_first (mono_string_chars (path_with_pattern), &data);
458 if (hnd == INVALID_HANDLE_VALUE) {
461 *ioerror = mono_w32error_get_last ();
465 mono_gc_wbarrier_generic_store (file_name, (MonoObject*) mono_string_from_utf16_checked (data.cFileName, &error));
466 mono_error_set_pending_exception (&error);
468 *file_attr = data.dwFileAttributes;
469 *ioerror = ERROR_SUCCESS;
475 ves_icall_System_IO_MonoIO_FindNextFile (HANDLE hnd, MonoString **file_name, gint32 *file_attr, gint32 *ioerror)
478 WIN32_FIND_DATA data;
481 res = mono_w32file_find_next (hnd, &data);
486 *ioerror = mono_w32error_get_last ();
490 mono_gc_wbarrier_generic_store (file_name, (MonoObject*) mono_string_from_utf16_checked (data.cFileName, &error));
491 mono_error_set_pending_exception (&error);
493 *file_attr = data.dwFileAttributes;
494 *ioerror = ERROR_SUCCESS;
500 ves_icall_System_IO_MonoIO_FindCloseFile (HANDLE hnd)
502 return mono_w32file_find_close (hnd);
505 /* FIXME make gc suspendable */
507 ves_icall_System_IO_MonoIO_FindFirst (MonoString *path,
508 MonoString *path_with_pattern,
509 gint32 *result_attr, gint32 *ioerror,
513 WIN32_FIND_DATA data;
515 IncrementalFind *ifh;
518 *ioerror = ERROR_SUCCESS;
520 find_handle = mono_w32file_find_first (mono_string_chars (path_with_pattern), &data);
522 if (find_handle == INVALID_HANDLE_VALUE) {
523 gint32 find_error = mono_w32error_get_last ();
526 if (find_error == ERROR_FILE_NOT_FOUND)
529 *ioerror = find_error;
533 ifh = g_new (IncrementalFind, 1);
534 ifh->find_handle = find_handle;
535 ifh->utf8_path = mono_string_to_utf8_checked (path, &error);
536 if (mono_error_set_pending_exception (&error)) {
537 mono_w32file_find_close (find_handle);
541 ifh->domain = mono_domain_get ();
544 while (incremental_find_check_match (ifh, &data, &result, &error) == 0){
545 if (!is_ok (&error)) {
546 mono_error_set_pending_exception (&error);
549 if (mono_w32file_find_next (find_handle, &data) == FALSE){
550 int e = mono_w32error_get_last ();
551 if (e != ERROR_NO_MORE_FILES)
556 *result_attr = data.dwFileAttributes;
561 /* FIXME make gc suspendable */
563 ves_icall_System_IO_MonoIO_FindNext (gpointer handle, gint32 *result_attr, gint32 *ioerror)
566 IncrementalFind *ifh = (IncrementalFind *)handle;
567 WIN32_FIND_DATA data;
571 *ioerror = ERROR_SUCCESS;
573 if (!is_ok (&error)) {
574 mono_error_set_pending_exception (&error);
577 if (mono_w32file_find_next (ifh->find_handle, &data) == FALSE){
578 int e = mono_w32error_get_last ();
579 if (e != ERROR_NO_MORE_FILES)
583 } while (incremental_find_check_match (ifh, &data, &result, &error) == 0);
585 *result_attr = data.dwFileAttributes;
590 ves_icall_System_IO_MonoIO_FindClose (gpointer handle)
592 IncrementalFind *ifh = (IncrementalFind *)handle;
595 if (mono_w32file_find_close (ifh->find_handle) == FALSE){
596 error = mono_w32error_get_last ();
598 error = ERROR_SUCCESS;
599 g_free (ifh->utf8_path);
606 ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *io_error)
613 len = MAX_PATH + 1; /*FIXME this is too smal under most unix systems.*/
614 buf = g_new (gunichar2, len);
617 *io_error=ERROR_SUCCESS;
620 res_len = mono_w32file_get_cwd (len, buf);
621 if (res_len > len) { /*buf is too small.*/
622 int old_res_len = res_len;
624 buf = g_new (gunichar2, res_len);
625 res_len = mono_w32file_get_cwd (res_len, buf) == old_res_len;
633 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
635 *io_error=mono_w32error_get_last ();
639 mono_error_set_pending_exception (&error);
644 ves_icall_System_IO_MonoIO_SetCurrentDirectory (MonoString *path,
649 *error=ERROR_SUCCESS;
651 ret=mono_w32file_set_cwd (mono_string_chars (path));
653 *error=mono_w32error_get_last ();
660 ves_icall_System_IO_MonoIO_MoveFile (MonoString *path, MonoString *dest, gint32 *error)
662 *error=ERROR_SUCCESS;
663 return mono_w32file_move (mono_string_chars (path), mono_string_chars (dest), error);
667 ves_icall_System_IO_MonoIO_ReplaceFile (MonoString *sourceFileName, MonoString *destinationFileName,
668 MonoString *destinationBackupFileName, MonoBoolean ignoreMetadataErrors,
671 gunichar2 *utf16_sourceFileName = NULL, *utf16_destinationFileName = NULL, *utf16_destinationBackupFileName = NULL;
672 guint32 replaceFlags = REPLACEFILE_WRITE_THROUGH;
675 utf16_sourceFileName = mono_string_chars (sourceFileName);
676 if (destinationFileName)
677 utf16_destinationFileName = mono_string_chars (destinationFileName);
678 if (destinationBackupFileName)
679 utf16_destinationBackupFileName = mono_string_chars (destinationBackupFileName);
681 *error = ERROR_SUCCESS;
682 if (ignoreMetadataErrors)
683 replaceFlags |= REPLACEFILE_IGNORE_MERGE_ERRORS;
685 /* FIXME: source and destination file names must not be NULL, but apparently they might be! */
686 return mono_w32file_replace (utf16_destinationFileName, utf16_sourceFileName,
687 utf16_destinationBackupFileName, replaceFlags, error);
691 ves_icall_System_IO_MonoIO_CopyFile (MonoString *path, MonoString *dest,
692 MonoBoolean overwrite, gint32 *error)
694 *error=ERROR_SUCCESS;
695 return mono_w32file_copy (mono_string_chars (path), mono_string_chars (dest), overwrite, error);
699 ves_icall_System_IO_MonoIO_DeleteFile (MonoString *path, gint32 *error)
703 *error=ERROR_SUCCESS;
705 ret=mono_w32file_delete (mono_string_chars (path));
707 *error=mono_w32error_get_last ();
714 ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path, gint32 *error)
717 *error=ERROR_SUCCESS;
719 ret=get_file_attributes (mono_string_chars (path));
722 * The definition of INVALID_FILE_ATTRIBUTES in the cygwin win32
723 * headers is wrong, hence this temporary workaround.
725 * http://cygwin.com/ml/cygwin/2003-09/msg01771.html
728 /* if(ret==INVALID_FILE_ATTRIBUTES) { */
729 *error=mono_w32error_get_last ();
735 ves_icall_System_IO_MonoIO_SetFileAttributes (MonoString *path, gint32 attrs,
739 *error=ERROR_SUCCESS;
741 ret=mono_w32file_set_attributes (mono_string_chars (path),
742 convert_attrs ((MonoFileAttributes)attrs));
744 *error=mono_w32error_get_last ();
750 ves_icall_System_IO_MonoIO_GetFileType (HANDLE handle, gint32 *error)
754 *error=ERROR_SUCCESS;
756 ret=mono_w32file_get_type (handle);
757 if(ret==FILE_TYPE_UNKNOWN) {
758 /* Not necessarily an error, but the caller will have
759 * to decide based on the error value.
761 *error=mono_w32error_get_last ();
768 ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat, gint32 *error)
772 *error=ERROR_SUCCESS;
774 result = get_file_attributes_ex (mono_string_chars (path), stat);
777 *error=mono_w32error_get_last ();
778 memset (stat, 0, sizeof (MonoIOStat));
785 ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode,
786 gint32 access_mode, gint32 share, gint32 options,
790 int attributes, attrs;
793 chars = mono_string_chars (filename);
794 *error=ERROR_SUCCESS;
797 if (options & FileOptions_Encrypted)
798 attributes = FILE_ATTRIBUTE_ENCRYPTED;
800 attributes = FILE_ATTRIBUTE_NORMAL;
801 if (options & FileOptions_DeleteOnClose)
802 attributes |= FILE_FLAG_DELETE_ON_CLOSE;
803 if (options & FileOptions_SequentialScan)
804 attributes |= FILE_FLAG_SEQUENTIAL_SCAN;
805 if (options & FileOptions_RandomAccess)
806 attributes |= FILE_FLAG_RANDOM_ACCESS;
808 if (options & FileOptions_Temporary)
809 attributes |= FILE_ATTRIBUTE_TEMPORARY;
811 if (options & FileOptions_WriteThrough)
812 attributes |= FILE_FLAG_WRITE_THROUGH;
814 attributes = FILE_ATTRIBUTE_NORMAL;
816 /* If we're opening a directory we need to set the extra flag
818 attrs = get_file_attributes (chars);
819 if (attrs != INVALID_FILE_ATTRIBUTES) {
820 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
821 attributes |= FILE_FLAG_BACKUP_SEMANTICS;
825 ret=mono_w32file_create (chars, convert_access ((MonoFileAccess)access_mode), convert_share ((MonoFileShare)share), convert_mode ((MonoFileMode)mode), attributes);
826 if(ret==INVALID_HANDLE_VALUE) {
827 *error=mono_w32error_get_last ();
834 ves_icall_System_IO_MonoIO_Close (HANDLE handle, gint32 *error)
837 *error=ERROR_SUCCESS;
839 ret=mono_w32file_close (handle);
841 *error=mono_w32error_get_last ();
847 ves_icall_System_IO_MonoIO_Read (HANDLE handle, MonoArray *dest,
848 gint32 dest_offset, gint32 count,
855 *error=ERROR_SUCCESS;
857 MONO_CHECK_ARG_NULL (dest, 0);
859 if (dest_offset > mono_array_length (dest) - count) {
860 mono_set_pending_exception (mono_get_exception_argument ("array", "array too small. numBytes/offset wrong."));
864 buffer = mono_array_addr (dest, guchar, dest_offset);
866 result = mono_w32file_read (handle, buffer, count, &n);
869 *error=mono_w32error_get_last ();
877 ves_icall_System_IO_MonoIO_Write (HANDLE handle, MonoArray *src,
878 gint32 src_offset, gint32 count,
885 *error=ERROR_SUCCESS;
887 MONO_CHECK_ARG_NULL (src, 0);
889 if (src_offset > mono_array_length (src) - count) {
890 mono_set_pending_exception (mono_get_exception_argument ("array", "array too small. numBytes/offset wrong."));
894 buffer = mono_array_addr (src, guchar, src_offset);
895 result = mono_w32file_write (handle, buffer, count, &n);
898 *error=mono_w32error_get_last ();
906 ves_icall_System_IO_MonoIO_Seek (HANDLE handle, gint64 offset, gint32 origin,
911 *error=ERROR_SUCCESS;
913 offset_hi = offset >> 32;
914 offset = mono_w32file_seek (handle, (gint32) (offset & 0xFFFFFFFF), &offset_hi,
915 convert_seekorigin ((MonoSeekOrigin)origin));
917 if(offset==INVALID_SET_FILE_POINTER) {
918 *error=mono_w32error_get_last ();
921 return offset | ((gint64)offset_hi << 32);
925 ves_icall_System_IO_MonoIO_Flush (HANDLE handle, gint32 *error)
929 *error=ERROR_SUCCESS;
931 ret=mono_w32file_flush (handle);
933 *error=mono_w32error_get_last ();
940 ves_icall_System_IO_MonoIO_GetLength (HANDLE handle, gint32 *error)
942 *error=ERROR_SUCCESS;
943 return mono_w32file_get_file_size (handle, error);
946 /* FIXME make gc suspendable */
948 ves_icall_System_IO_MonoIO_SetLength (HANDLE handle, gint64 length,
951 gint64 offset, offset_set;
956 *error=ERROR_SUCCESS;
958 /* save file pointer */
961 offset = mono_w32file_seek (handle, 0, &offset_hi, FILE_CURRENT);
962 if(offset==INVALID_SET_FILE_POINTER) {
963 *error=mono_w32error_get_last ();
967 /* extend or truncate */
969 length_hi = length >> 32;
970 offset_set=mono_w32file_seek (handle, length & 0xFFFFFFFF, &length_hi,
972 if(offset_set==INVALID_SET_FILE_POINTER) {
973 *error=mono_w32error_get_last ();
977 result = mono_w32file_truncate (handle);
979 *error=mono_w32error_get_last ();
983 /* restore file pointer */
985 offset_set=mono_w32file_seek (handle, offset & 0xFFFFFFFF, &offset_hi,
987 if(offset_set==INVALID_SET_FILE_POINTER) {
988 *error=mono_w32error_get_last ();
996 ves_icall_System_IO_MonoIO_SetFileTime (HANDLE handle, gint64 creation_time,
997 gint64 last_access_time,
998 gint64 last_write_time, gint32 *error)
1001 const FILETIME *creation_filetime;
1002 const FILETIME *access_filetime;
1003 const FILETIME *write_filetime;
1005 *error=ERROR_SUCCESS;
1007 if (creation_time < 0)
1008 creation_filetime = NULL;
1010 creation_filetime = (FILETIME *)&creation_time;
1012 if (last_access_time < 0)
1013 access_filetime = NULL;
1015 access_filetime = (FILETIME *)&last_access_time;
1017 if (last_write_time < 0)
1018 write_filetime = NULL;
1020 write_filetime = (FILETIME *)&last_write_time;
1022 ret=mono_w32file_set_times (handle, creation_filetime, access_filetime, write_filetime);
1024 *error=mono_w32error_get_last ();
1031 ves_icall_System_IO_MonoIO_get_ConsoleOutput ()
1033 return mono_w32file_get_console_output ();
1037 ves_icall_System_IO_MonoIO_get_ConsoleInput ()
1039 return mono_w32file_get_console_input ();
1043 ves_icall_System_IO_MonoIO_get_ConsoleError ()
1045 return mono_w32file_get_console_error ();
1049 ves_icall_System_IO_MonoIO_CreatePipe (HANDLE *read_handle, HANDLE *write_handle, gint32 *error)
1053 ret=mono_w32file_create_pipe (read_handle, write_handle, 0);
1056 *error = mono_w32error_get_last ();
1057 /* FIXME: throw an exception? */
1065 ves_icall_System_IO_MonoIO_DuplicateHandle (HANDLE source_process_handle, HANDLE source_handle,
1066 HANDLE target_process_handle, HANDLE *target_handle, gint32 access, gint32 inherit, gint32 options, gint32 *error)
1069 *target_handle = mono_w32handle_duplicate (source_handle);
1074 ret=DuplicateHandle (source_process_handle, source_handle, target_process_handle, target_handle, access, inherit, options);
1078 *error = mono_w32error_get_last ();
1079 /* FIXME: throw an exception? */
1089 ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar ()
1091 return (gunichar2) '/'; /* forward slash */
1095 ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar ()
1097 return (gunichar2) '/'; /* forward slash */
1101 ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar ()
1103 if (IS_PORTABILITY_SET)
1104 return (gunichar2) '\\'; /* backslash */
1106 return (gunichar2) '/'; /* forward slash */
1110 ves_icall_System_IO_MonoIO_get_PathSeparator ()
1112 return (gunichar2) ':'; /* colon */
1114 #endif /* !HOST_WIN32 */
1116 static const gunichar2
1117 invalid_path_chars [] = {
1118 #if defined (TARGET_WIN32)
1119 0x0022, /* double quote, which seems allowed in MS.NET but should be rejected */
1120 0x003c, /* less than */
1121 0x003e, /* greater than */
1138 ves_icall_System_IO_MonoIO_get_InvalidPathChars ()
1145 domain = mono_domain_get ();
1146 n = sizeof (invalid_path_chars) / sizeof (gunichar2);
1147 chars = mono_array_new_checked (domain, mono_defaults.char_class, n, &error);
1148 if (mono_error_set_pending_exception (&error))
1151 for (i = 0; i < n; ++ i)
1152 mono_array_set (chars, gunichar2, i, invalid_path_chars [i]);
1157 void ves_icall_System_IO_MonoIO_Lock (HANDLE handle, gint64 position,
1158 gint64 length, gint32 *error)
1160 *error=ERROR_SUCCESS;
1161 mono_w32file_lock (handle, position, length, error);
1164 void ves_icall_System_IO_MonoIO_Unlock (HANDLE handle, gint64 position,
1165 gint64 length, gint32 *error)
1167 *error=ERROR_SUCCESS;
1168 mono_w32file_unlock (handle, position, length, error);
1171 //Support for io-layer free mmap'd files.
1173 #if defined (TARGET_IOS) || defined (TARGET_ANDROID)
1176 mono_filesize_from_path (MonoString *string)
1181 char *path = mono_string_to_utf8_checked (string, &error);
1182 mono_error_raise_exception (&error); /* OK to throw, external only without a good alternative */
1186 stat_res = stat (path, &buf);
1191 res = (gint64)buf.st_size;
1199 mono_filesize_from_fd (int fd)
1205 res = fstat (fd, &buf);
1211 return (gint64)buf.st_size;
1217 void mono_w32handle_dump (void);
1219 void ves_icall_System_IO_MonoIO_DumpHandles (void)
1221 mono_w32handle_dump ();
1223 #endif /* !HOST_WIN32 */