Fix infrequent hangs in test-runner. (#16793)
[mono-project.git] / mono / metadata / w32file.c
blobea45fe74cc5af0d4eafd0c33e181f45692dfbe55
1 /**
2 * \file
3 * File IO internal calls
5 * Author:
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.
15 #include <config.h>
17 #include <glib.h>
18 #include <string.h>
19 #include <errno.h>
20 #ifdef HAVE_UNISTD_H
21 #include <unistd.h>
22 #endif
23 #ifdef HAVE_SYS_STAT_H
24 #include <sys/stat.h>
25 #endif
26 #ifdef HAVE_SYS_TYPES_H
27 #include <sys/types.h>
28 #endif
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 <mono/utils/mono-io-portability.h>
39 #include <mono/metadata/w32handle.h>
40 #include <mono/utils/w32api.h>
41 #include "icall-decl.h"
43 #undef DEBUG
45 /* conversion functions */
47 static guint32 convert_mode(MonoFileMode mono_mode)
49 guint32 mode;
51 switch(mono_mode) {
52 case FileMode_CreateNew:
53 mode=CREATE_NEW;
54 break;
55 case FileMode_Create:
56 mode=CREATE_ALWAYS;
57 break;
58 case FileMode_Open:
59 mode=OPEN_EXISTING;
60 break;
61 case FileMode_OpenOrCreate:
62 mode=OPEN_ALWAYS;
63 break;
64 case FileMode_Truncate:
65 mode=TRUNCATE_EXISTING;
66 break;
67 case FileMode_Append:
68 mode=OPEN_ALWAYS;
69 break;
70 default:
71 g_warning("System.IO.FileMode has unknown value 0x%x",
72 mono_mode);
73 /* Safe fallback */
74 mode=OPEN_EXISTING;
77 return(mode);
80 static guint32 convert_access(MonoFileAccess mono_access)
82 guint32 access;
84 switch(mono_access) {
85 case FileAccess_Read:
86 access=GENERIC_READ;
87 break;
88 case FileAccess_Write:
89 access=GENERIC_WRITE;
90 break;
91 case FileAccess_ReadWrite:
92 access=GENERIC_READ|GENERIC_WRITE;
93 break;
94 default:
95 g_warning("System.IO.FileAccess has unknown value 0x%x",
96 mono_access);
97 /* Safe fallback */
98 access=GENERIC_READ;
101 return(access);
104 static guint32 convert_share(MonoFileShare mono_share)
106 guint32 share = 0;
108 if (mono_share & FileShare_Read) {
109 share |= FILE_SHARE_READ;
111 if (mono_share & FileShare_Write) {
112 share |= FILE_SHARE_WRITE;
114 if (mono_share & FileShare_Delete) {
115 share |= FILE_SHARE_DELETE;
118 if (mono_share & ~(FileShare_Read|FileShare_Write|FileShare_Delete)) {
119 g_warning("System.IO.FileShare has unknown value 0x%x",
120 mono_share);
121 /* Safe fallback */
122 share=0;
125 return(share);
128 #if 0
129 static guint32 convert_stdhandle(guint32 fd)
131 guint32 stdhandle;
133 switch(fd) {
134 case 0:
135 stdhandle=STD_INPUT_HANDLE;
136 break;
137 case 1:
138 stdhandle=STD_OUTPUT_HANDLE;
139 break;
140 case 2:
141 stdhandle=STD_ERROR_HANDLE;
142 break;
143 default:
144 g_warning("unknown standard file descriptor %d", fd);
145 stdhandle=STD_INPUT_HANDLE;
148 return(stdhandle);
150 #endif
152 static guint32 convert_seekorigin(MonoSeekOrigin origin)
154 guint32 w32origin;
156 switch(origin) {
157 case SeekOrigin_Begin:
158 w32origin=FILE_BEGIN;
159 break;
160 case SeekOrigin_Current:
161 w32origin=FILE_CURRENT;
162 break;
163 case SeekOrigin_End:
164 w32origin=FILE_END;
165 break;
166 default:
167 g_warning("System.IO.SeekOrigin has unknown value 0x%x",
168 origin);
169 /* Safe fallback */
170 w32origin=FILE_CURRENT;
173 return(w32origin);
176 /* Managed file attributes have nearly but not quite the same values
177 * as the w32 equivalents.
179 static guint32 convert_attrs(MonoFileAttributes attrs)
181 if(attrs & FileAttributes_Encrypted) {
182 attrs = (MonoFileAttributes)(attrs | FILE_ATTRIBUTE_ENCRYPTED);
185 return(attrs);
188 /* System.IO.MonoIO internal calls */
190 #if !ENABLE_NETCORE
192 MonoBoolean
193 ves_icall_System_IO_MonoIO_CreateDirectory (const gunichar2 *path, gint32 *error)
195 gboolean ret;
197 *error=ERROR_SUCCESS;
199 ret=mono_w32file_create_directory (path);
200 if(ret==FALSE) {
201 *error=mono_w32error_get_last ();
204 return(ret);
207 MonoBoolean
208 ves_icall_System_IO_MonoIO_RemoveDirectory (const gunichar2 *path, gint32 *error)
210 gboolean ret;
212 *error=ERROR_SUCCESS;
214 ret=mono_w32file_remove_directory (path);
215 if(ret==FALSE) {
216 *error=mono_w32error_get_last ();
219 return(ret);
222 HANDLE
223 ves_icall_System_IO_MonoIO_FindFirstFile (const gunichar2 *path_with_pattern, MonoStringHandleOut file_name, gint32 *file_attr, gint32 *ioerror, MonoError *error)
225 HANDLE hnd;
226 WIN32_FIND_DATA data;
228 hnd = mono_w32file_find_first (path_with_pattern, &data);
230 if (hnd == INVALID_HANDLE_VALUE) {
231 MONO_HANDLE_ASSIGN (file_name, NULL_HANDLE_STRING);
232 *file_attr = 0;
233 *ioerror = mono_w32error_get_last ();
234 return hnd;
237 int len = 0;
238 while (data.cFileName [len]) len++;
239 MONO_HANDLE_ASSIGN (file_name, mono_string_new_utf16_handle (mono_domain_get (), data.cFileName, len, error));
240 return_val_if_nok (error, INVALID_HANDLE_VALUE);
242 *file_attr = data.dwFileAttributes;
243 *ioerror = ERROR_SUCCESS;
245 return hnd;
248 MonoBoolean
249 ves_icall_System_IO_MonoIO_FindNextFile (HANDLE hnd, MonoStringHandleOut file_name, gint32 *file_attr, gint32 *ioerror, MonoError *error)
251 MonoBoolean res;
252 WIN32_FIND_DATA data;
254 res = mono_w32file_find_next (hnd, &data);
256 if (res == FALSE) {
257 MONO_HANDLE_ASSIGN (file_name, NULL_HANDLE_STRING);
258 *file_attr = 0;
259 *ioerror = mono_w32error_get_last ();
260 return res;
263 int len = 0;
264 while (data.cFileName [len]) len++;
265 MONO_HANDLE_ASSIGN (file_name, mono_string_new_utf16_handle (mono_domain_get (), data.cFileName, len, error));
266 return_val_if_nok (error, FALSE);
268 *file_attr = data.dwFileAttributes;
269 *ioerror = ERROR_SUCCESS;
271 return res;
274 MonoBoolean
275 ves_icall_System_IO_MonoIO_FindCloseFile (HANDLE hnd)
277 return mono_w32file_find_close (hnd);
280 MonoStringHandle
281 ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *io_error, MonoError *error)
283 MonoStringHandle result;
284 gunichar2 *buf;
285 int len, res_len;
287 len = MAX_PATH + 1; /*FIXME this is too smal under most unix systems.*/
288 buf = g_new (gunichar2, len);
290 *io_error = ERROR_SUCCESS;
291 result = MONO_HANDLE_NEW (MonoString, NULL);
293 res_len = mono_w32file_get_cwd (len, buf);
294 if (res_len > len) { /*buf is too small.*/
295 int old_res_len = res_len;
296 g_free (buf);
297 buf = g_new (gunichar2, res_len);
298 res_len = mono_w32file_get_cwd (res_len, buf) == old_res_len;
301 if (res_len) {
302 len = 0;
303 while (buf [len])
304 ++ len;
306 MONO_HANDLE_ASSIGN (result, mono_string_new_utf16_handle (mono_domain_get (), buf, len, error));
307 } else {
308 *io_error=mono_w32error_get_last ();
311 g_free (buf);
312 return_val_if_nok (error, NULL_HANDLE_STRING);
313 return result;
316 MonoBoolean
317 ves_icall_System_IO_MonoIO_SetCurrentDirectory (const gunichar2 *path,
318 gint32 *error)
320 gboolean ret;
322 *error=ERROR_SUCCESS;
324 ret=mono_w32file_set_cwd (path);
325 if(ret==FALSE) {
326 *error=mono_w32error_get_last ();
329 return(ret);
332 MonoBoolean
333 ves_icall_System_IO_MonoIO_MoveFile (const gunichar2 *path, const gunichar2 *dest, gint32 *error)
335 *error=ERROR_SUCCESS;
336 return mono_w32file_move (path, dest, error);
339 MonoBoolean
340 ves_icall_System_IO_MonoIO_ReplaceFile (const gunichar2 *source_file_name, const gunichar2 *destination_file_name,
341 const gunichar2 *destination_backup_file_name, MonoBoolean ignore_metadata_errors,
342 gint32 *error)
344 guint32 replace_flags = REPLACEFILE_WRITE_THROUGH;
346 *error = ERROR_SUCCESS;
347 if (ignore_metadata_errors)
348 replace_flags |= REPLACEFILE_IGNORE_MERGE_ERRORS;
350 /* FIXME: source and destination file names must not be NULL, but apparently they might be! */
351 return mono_w32file_replace (destination_file_name, source_file_name,
352 destination_backup_file_name, replace_flags, error);
355 MonoBoolean
356 ves_icall_System_IO_MonoIO_CopyFile (const gunichar2 *path, const gunichar2 *dest,
357 MonoBoolean overwrite, gint32 *error)
359 *error=ERROR_SUCCESS;
360 return mono_w32file_copy (path, dest, overwrite, error);
363 MonoBoolean
364 ves_icall_System_IO_MonoIO_DeleteFile (const gunichar2 *path, gint32 *error)
366 gboolean ret;
368 *error=ERROR_SUCCESS;
370 ret=mono_w32file_delete (path);
371 if(ret==FALSE) {
372 *error=mono_w32error_get_last ();
375 return(ret);
378 gint32
379 ves_icall_System_IO_MonoIO_GetFileAttributes (const gunichar2 *path, gint32 *error)
381 gint32 ret;
382 *error=ERROR_SUCCESS;
384 ret = mono_w32file_get_attributes (path);
387 * The definition of INVALID_FILE_ATTRIBUTES in the cygwin win32
388 * headers is wrong, hence this temporary workaround.
389 * See
390 * http://cygwin.com/ml/cygwin/2003-09/msg01771.html
392 if (ret==-1) {
393 /* if(ret==INVALID_FILE_ATTRIBUTES) { */
394 *error=mono_w32error_get_last ();
396 return(ret);
399 MonoBoolean
400 ves_icall_System_IO_MonoIO_SetFileAttributes (const gunichar2 *path, gint32 attrs,
401 gint32 *error)
403 gboolean ret;
404 *error=ERROR_SUCCESS;
406 ret=mono_w32file_set_attributes (path,
407 convert_attrs ((MonoFileAttributes)attrs));
408 if(ret==FALSE) {
409 *error=mono_w32error_get_last ();
411 return(ret);
414 gint32
415 ves_icall_System_IO_MonoIO_GetFileType (HANDLE handle, gint32 *error)
417 gboolean ret;
419 *error=ERROR_SUCCESS;
421 ret=mono_w32file_get_type (handle);
422 if(ret==FILE_TYPE_UNKNOWN) {
423 /* Not necessarily an error, but the caller will have
424 * to decide based on the error value.
426 *error=mono_w32error_get_last ();
429 return(ret);
432 MonoBoolean
433 ves_icall_System_IO_MonoIO_GetFileStat (const gunichar2 *path, MonoIOStat *stat, gint32 *error)
435 gboolean result;
437 *error=ERROR_SUCCESS;
439 result = mono_w32file_get_attributes_ex (path, stat);
441 if (!result) {
442 *error=mono_w32error_get_last ();
443 memset (stat, 0, sizeof (MonoIOStat));
446 return result;
449 HANDLE
450 ves_icall_System_IO_MonoIO_Open (const gunichar2 *filename, gint32 mode,
451 gint32 access_mode, gint32 share, gint32 options,
452 gint32 *error)
454 HANDLE ret;
455 int attributes, attrs;
457 *error=ERROR_SUCCESS;
459 if (options != 0){
460 if (options & FileOptions_Encrypted)
461 attributes = FILE_ATTRIBUTE_ENCRYPTED;
462 else
463 attributes = FILE_ATTRIBUTE_NORMAL;
464 if (options & FileOptions_DeleteOnClose)
465 attributes |= FILE_FLAG_DELETE_ON_CLOSE;
466 if (options & FileOptions_SequentialScan)
467 attributes |= FILE_FLAG_SEQUENTIAL_SCAN;
468 if (options & FileOptions_RandomAccess)
469 attributes |= FILE_FLAG_RANDOM_ACCESS;
471 if (options & FileOptions_Temporary)
472 attributes |= FILE_ATTRIBUTE_TEMPORARY;
474 if (options & FileOptions_WriteThrough)
475 attributes |= FILE_FLAG_WRITE_THROUGH;
476 } else
477 attributes = FILE_ATTRIBUTE_NORMAL;
479 /* If we're opening a directory we need to set the extra flag
481 attrs = mono_w32file_get_attributes (filename);
482 if (attrs != INVALID_FILE_ATTRIBUTES) {
483 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
484 attributes |= FILE_FLAG_BACKUP_SEMANTICS;
488 ret=mono_w32file_create (filename, convert_access ((MonoFileAccess)access_mode), convert_share ((MonoFileShare)share), convert_mode ((MonoFileMode)mode), attributes);
489 if(ret==INVALID_HANDLE_VALUE) {
490 *error=mono_w32error_get_last ();
493 return(ret);
496 MonoBoolean
497 ves_icall_System_IO_MonoIO_Close (HANDLE handle, gint32 *error)
499 gboolean ret;
500 *error=ERROR_SUCCESS;
502 ret=mono_w32file_close (handle);
503 if(ret==FALSE) {
504 *error=mono_w32error_get_last ();
506 return(ret);
509 MonoBoolean
510 ves_icall_System_IO_MonoIO_Cancel (HANDLE handle, gint32 *error)
512 gboolean ret;
513 *error=ERROR_SUCCESS;
515 ret = mono_w32file_cancel (handle);
516 if (ret == FALSE)
517 *error = mono_w32error_get_last ();
519 return ret;
522 gint32
523 ves_icall_System_IO_MonoIO_Read (HANDLE handle, MonoArrayHandle dest,
524 gint32 dest_offset, gint32 count,
525 gint32 *io_error,
526 MonoError *error)
528 void *buffer;
529 gboolean result;
530 guint32 n;
532 *io_error=ERROR_SUCCESS;
534 MONO_CHECK_ARG_NULL_HANDLE (dest, 0);
536 if (dest_offset > mono_array_handle_length (dest) - count) {
537 mono_error_set_argument (error, "array", "array too small. numBytes/offset wrong.");
538 return 0;
541 guint32 buffer_handle = 0;
542 buffer = MONO_ARRAY_HANDLE_PIN (dest, guchar, dest_offset, &buffer_handle);
543 result = mono_w32file_read (handle, buffer, count, &n, io_error);
544 mono_gchandle_free_internal (buffer_handle);
546 if (!result)
547 return -1;
549 return (gint32)n;
552 gint32
553 ves_icall_System_IO_MonoIO_Write (HANDLE handle, MonoArrayHandle src,
554 gint32 src_offset, gint32 count,
555 gint32 *io_error,
556 MonoError *error)
558 void *buffer;
559 gboolean result;
560 guint32 n;
562 *io_error=ERROR_SUCCESS;
564 MONO_CHECK_ARG_NULL_HANDLE (src, 0);
566 if (src_offset > mono_array_handle_length (src) - count) {
567 mono_error_set_argument (error, "array", "array too small. numBytes/offset wrong.");
568 return 0;
571 guint32 src_handle = 0;
572 buffer = MONO_ARRAY_HANDLE_PIN (src, guchar, src_offset, &src_handle);
573 result = mono_w32file_write (handle, buffer, count, &n, io_error);
574 mono_gchandle_free_internal (src_handle);
576 if (!result)
577 return -1;
579 return (gint32)n;
582 gint64
583 ves_icall_System_IO_MonoIO_Seek (HANDLE handle, gint64 offset, gint32 origin,
584 gint32 *error)
586 gint32 offset_hi;
588 *error=ERROR_SUCCESS;
590 offset_hi = offset >> 32;
591 offset = mono_w32file_seek (handle, (gint32) (offset & 0xFFFFFFFF), &offset_hi,
592 convert_seekorigin ((MonoSeekOrigin)origin));
594 if(offset==INVALID_SET_FILE_POINTER) {
595 *error=mono_w32error_get_last ();
598 return offset | ((gint64)offset_hi << 32);
601 MonoBoolean
602 ves_icall_System_IO_MonoIO_Flush (HANDLE handle, gint32 *error)
604 gboolean ret;
606 *error=ERROR_SUCCESS;
608 ret=mono_w32file_flush (handle);
609 if(ret==FALSE) {
610 *error=mono_w32error_get_last ();
613 return(ret);
616 gint64
617 ves_icall_System_IO_MonoIO_GetLength (HANDLE handle, gint32 *error)
619 *error=ERROR_SUCCESS;
620 return mono_w32file_get_file_size (handle, error);
623 /* FIXME make gc suspendable */
624 MonoBoolean
625 ves_icall_System_IO_MonoIO_SetLength (HANDLE handle, gint64 length,
626 gint32 *error)
628 gint64 offset, offset_set;
629 gint32 offset_hi;
630 gint32 length_hi;
631 gboolean result;
633 *error=ERROR_SUCCESS;
635 /* save file pointer */
637 offset_hi = 0;
638 offset = mono_w32file_seek (handle, 0, &offset_hi, FILE_CURRENT);
639 if(offset==INVALID_SET_FILE_POINTER) {
640 *error=mono_w32error_get_last ();
641 return(FALSE);
644 /* extend or truncate */
646 length_hi = length >> 32;
647 offset_set=mono_w32file_seek (handle, length & 0xFFFFFFFF, &length_hi,
648 FILE_BEGIN);
649 if(offset_set==INVALID_SET_FILE_POINTER) {
650 *error=mono_w32error_get_last ();
651 return(FALSE);
654 result = mono_w32file_truncate (handle);
655 if(result==FALSE) {
656 *error=mono_w32error_get_last ();
657 return(FALSE);
660 /* restore file pointer */
662 offset_set=mono_w32file_seek (handle, offset & 0xFFFFFFFF, &offset_hi,
663 FILE_BEGIN);
664 if(offset_set==INVALID_SET_FILE_POINTER) {
665 *error=mono_w32error_get_last ();
666 return(FALSE);
669 return result;
672 MonoBoolean
673 ves_icall_System_IO_MonoIO_SetFileTime (HANDLE handle, gint64 creation_time,
674 gint64 last_access_time,
675 gint64 last_write_time, gint32 *error)
677 gboolean ret;
678 const FILETIME *creation_filetime;
679 const FILETIME *access_filetime;
680 const FILETIME *write_filetime;
682 *error=ERROR_SUCCESS;
684 if (creation_time < 0)
685 creation_filetime = NULL;
686 else
687 creation_filetime = (FILETIME *)&creation_time;
689 if (last_access_time < 0)
690 access_filetime = NULL;
691 else
692 access_filetime = (FILETIME *)&last_access_time;
694 if (last_write_time < 0)
695 write_filetime = NULL;
696 else
697 write_filetime = (FILETIME *)&last_write_time;
699 ret=mono_w32file_set_times (handle, creation_filetime, access_filetime, write_filetime);
700 if(ret==FALSE) {
701 *error=mono_w32error_get_last ();
704 return(ret);
707 HANDLE
708 ves_icall_System_IO_MonoIO_get_ConsoleOutput (void)
710 return mono_w32file_get_console_output ();
713 HANDLE
714 ves_icall_System_IO_MonoIO_get_ConsoleInput (void)
716 return mono_w32file_get_console_input ();
719 HANDLE
720 ves_icall_System_IO_MonoIO_get_ConsoleError (void)
722 return mono_w32file_get_console_error ();
725 MonoBoolean
726 ves_icall_System_IO_MonoIO_CreatePipe (HANDLE *read_handle, HANDLE *write_handle, gint32 *error)
728 *error = ERROR_SUCCESS;
730 gboolean ret;
732 ret=mono_w32file_create_pipe (read_handle, write_handle, 0);
734 if(ret==FALSE) {
735 *error = mono_w32error_get_last ();
736 /* FIXME: throw an exception? */
737 return(FALSE);
740 return(TRUE);
743 MonoBoolean
744 ves_icall_System_IO_MonoIO_DuplicateHandle (HANDLE source_process_handle, HANDLE source_handle,
745 HANDLE target_process_handle, HANDLE *target_handle, gint32 access, gint32 inherit, gint32 options, gint32 *error)
747 #ifndef HOST_WIN32
748 MonoW32Handle *source_handle_data;
750 if (!mono_w32handle_lookup_and_ref (source_handle, &source_handle_data)) {
751 *error = ERROR_INVALID_HANDLE;
752 return FALSE;
755 *target_handle = mono_w32handle_duplicate (source_handle_data);
757 mono_w32handle_unref ((MonoW32Handle*)source_handle);
758 #else
759 gboolean ret;
761 MONO_ENTER_GC_SAFE;
762 ret=DuplicateHandle (source_process_handle, source_handle, target_process_handle, target_handle, access, inherit, options);
763 MONO_EXIT_GC_SAFE;
765 if (!ret) {
766 *error = mono_w32error_get_last ();
767 /* FIXME: throw an exception? */
768 return(FALSE);
770 #endif
772 return(TRUE);
775 #ifndef HOST_WIN32
776 gunichar2
777 ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar (void)
779 return (gunichar2) '/'; /* forward slash */
782 gunichar2
783 ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar (void)
785 return (gunichar2) '/'; /* forward slash */
788 gunichar2
789 ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar (void)
791 if (IS_PORTABILITY_SET)
792 return (gunichar2) '\\'; /* backslash */
793 else
794 return (gunichar2) '/'; /* forward slash */
797 gunichar2
798 ves_icall_System_IO_MonoIO_get_PathSeparator (void)
800 return (gunichar2) ':'; /* colon */
802 #endif /* !HOST_WIN32 */
804 static const gunichar2
805 invalid_path_chars [] = {
806 #if defined (TARGET_WIN32)
807 0x0022, /* double quote, which seems allowed in MS.NET but should be rejected */
808 0x003c, /* less than */
809 0x003e, /* greater than */
810 0x007c, /* pipe */
811 0x0008,
812 0x0010,
813 0x0011,
814 0x0012,
815 0x0014,
816 0x0015,
817 0x0016,
818 0x0017,
819 0x0018,
820 0x0019,
821 #endif
822 0x0000 /* null */
825 MonoArrayHandle
826 ves_icall_System_IO_MonoIO_get_InvalidPathChars (MonoError *error)
828 MonoArrayHandle chars = MONO_HANDLE_NEW (MonoArray, NULL);
829 MonoDomain *domain;
830 int i, n;
832 domain = mono_domain_get ();
833 n = sizeof (invalid_path_chars) / sizeof (gunichar2);
834 MONO_HANDLE_ASSIGN (chars, mono_array_new_handle (domain, mono_defaults.char_class, n, error));
835 return_val_if_nok (error, MONO_HANDLE_CAST (MonoArray, mono_new_null ()));
837 for (i = 0; i < n; ++ i)
838 MONO_HANDLE_ARRAY_SETVAL (chars, gunichar2, i, invalid_path_chars [i]);
840 return chars;
843 void ves_icall_System_IO_MonoIO_Lock (HANDLE handle, gint64 position,
844 gint64 length, gint32 *error)
846 *error=ERROR_SUCCESS;
847 mono_w32file_lock (handle, position, length, error);
850 void ves_icall_System_IO_MonoIO_Unlock (HANDLE handle, gint64 position,
851 gint64 length, gint32 *error)
853 *error=ERROR_SUCCESS;
854 mono_w32file_unlock (handle, position, length, error);
858 #ifndef HOST_WIN32
859 void mono_w32handle_dump (void);
861 void ves_icall_System_IO_MonoIO_DumpHandles (void)
863 mono_w32handle_dump ();
865 #endif /* !HOST_WIN32 */
867 #endif /* !ENABLE_NETCORE */
869 //Support for io-layer free mmap'd files.
871 #if defined (TARGET_IOS) || defined (TARGET_ANDROID)
873 gint64
874 mono_filesize_from_path (MonoString *string)
876 ERROR_DECL (error);
877 struct stat buf;
878 gint64 res;
879 char *path = mono_string_to_utf8_checked_internal (string, error);
880 mono_error_raise_exception_deprecated (error); /* OK to throw, external only without a good alternative */
882 gint stat_res;
883 MONO_ENTER_GC_SAFE;
884 stat_res = stat (path, &buf);
885 MONO_EXIT_GC_SAFE;
886 if (stat_res == -1)
887 res = -1;
888 else
889 res = (gint64)buf.st_size;
891 g_free (path);
893 return res;
896 gint64
897 mono_filesize_from_fd (int fd)
899 struct stat buf;
900 int res;
902 MONO_ENTER_GC_SAFE;
903 res = fstat (fd, &buf);
904 MONO_EXIT_GC_SAFE;
906 if (res == -1)
907 return (gint64)-1;
909 return (gint64)buf.st_size;
912 #endif