Implemeneted imprecise.
[mono-project.git] / mono / metadata / w32file.c
blob4086e3fa0b351bae8f26dc736cc5aafc22c13cd2
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 gint32
510 ves_icall_System_IO_MonoIO_Read (HANDLE handle, MonoArrayHandle dest,
511 gint32 dest_offset, gint32 count,
512 gint32 *io_error,
513 MonoError *error)
515 void *buffer;
516 gboolean result;
517 guint32 n;
519 *io_error=ERROR_SUCCESS;
521 MONO_CHECK_ARG_NULL_HANDLE (dest, 0);
523 if (dest_offset > mono_array_handle_length (dest) - count) {
524 mono_error_set_argument (error, "array", "array too small. numBytes/offset wrong.");
525 return 0;
528 guint32 buffer_handle = 0;
529 buffer = MONO_ARRAY_HANDLE_PIN (dest, guchar, dest_offset, &buffer_handle);
530 result = mono_w32file_read (handle, buffer, count, &n, io_error);
531 mono_gchandle_free_internal (buffer_handle);
533 if (!result)
534 return -1;
536 return (gint32)n;
539 gint32
540 ves_icall_System_IO_MonoIO_Write (HANDLE handle, MonoArrayHandle src,
541 gint32 src_offset, gint32 count,
542 gint32 *io_error,
543 MonoError *error)
545 void *buffer;
546 gboolean result;
547 guint32 n;
549 *io_error=ERROR_SUCCESS;
551 MONO_CHECK_ARG_NULL_HANDLE (src, 0);
553 if (src_offset > mono_array_handle_length (src) - count) {
554 mono_error_set_argument (error, "array", "array too small. numBytes/offset wrong.");
555 return 0;
558 guint32 src_handle = 0;
559 buffer = MONO_ARRAY_HANDLE_PIN (src, guchar, src_offset, &src_handle);
560 result = mono_w32file_write (handle, buffer, count, &n, io_error);
561 mono_gchandle_free_internal (src_handle);
563 if (!result)
564 return -1;
566 return (gint32)n;
569 gint64
570 ves_icall_System_IO_MonoIO_Seek (HANDLE handle, gint64 offset, gint32 origin,
571 gint32 *error)
573 gint32 offset_hi;
575 *error=ERROR_SUCCESS;
577 offset_hi = offset >> 32;
578 offset = mono_w32file_seek (handle, (gint32) (offset & 0xFFFFFFFF), &offset_hi,
579 convert_seekorigin ((MonoSeekOrigin)origin));
581 if(offset==INVALID_SET_FILE_POINTER) {
582 *error=mono_w32error_get_last ();
585 return offset | ((gint64)offset_hi << 32);
588 MonoBoolean
589 ves_icall_System_IO_MonoIO_Flush (HANDLE handle, gint32 *error)
591 gboolean ret;
593 *error=ERROR_SUCCESS;
595 ret=mono_w32file_flush (handle);
596 if(ret==FALSE) {
597 *error=mono_w32error_get_last ();
600 return(ret);
603 gint64
604 ves_icall_System_IO_MonoIO_GetLength (HANDLE handle, gint32 *error)
606 *error=ERROR_SUCCESS;
607 return mono_w32file_get_file_size (handle, error);
610 /* FIXME make gc suspendable */
611 MonoBoolean
612 ves_icall_System_IO_MonoIO_SetLength (HANDLE handle, gint64 length,
613 gint32 *error)
615 gint64 offset, offset_set;
616 gint32 offset_hi;
617 gint32 length_hi;
618 gboolean result;
620 *error=ERROR_SUCCESS;
622 /* save file pointer */
624 offset_hi = 0;
625 offset = mono_w32file_seek (handle, 0, &offset_hi, FILE_CURRENT);
626 if(offset==INVALID_SET_FILE_POINTER) {
627 *error=mono_w32error_get_last ();
628 return(FALSE);
631 /* extend or truncate */
633 length_hi = length >> 32;
634 offset_set=mono_w32file_seek (handle, length & 0xFFFFFFFF, &length_hi,
635 FILE_BEGIN);
636 if(offset_set==INVALID_SET_FILE_POINTER) {
637 *error=mono_w32error_get_last ();
638 return(FALSE);
641 result = mono_w32file_truncate (handle);
642 if(result==FALSE) {
643 *error=mono_w32error_get_last ();
644 return(FALSE);
647 /* restore file pointer */
649 offset_set=mono_w32file_seek (handle, offset & 0xFFFFFFFF, &offset_hi,
650 FILE_BEGIN);
651 if(offset_set==INVALID_SET_FILE_POINTER) {
652 *error=mono_w32error_get_last ();
653 return(FALSE);
656 return result;
659 MonoBoolean
660 ves_icall_System_IO_MonoIO_SetFileTime (HANDLE handle, gint64 creation_time,
661 gint64 last_access_time,
662 gint64 last_write_time, gint32 *error)
664 gboolean ret;
665 const FILETIME *creation_filetime;
666 const FILETIME *access_filetime;
667 const FILETIME *write_filetime;
669 *error=ERROR_SUCCESS;
671 if (creation_time < 0)
672 creation_filetime = NULL;
673 else
674 creation_filetime = (FILETIME *)&creation_time;
676 if (last_access_time < 0)
677 access_filetime = NULL;
678 else
679 access_filetime = (FILETIME *)&last_access_time;
681 if (last_write_time < 0)
682 write_filetime = NULL;
683 else
684 write_filetime = (FILETIME *)&last_write_time;
686 ret=mono_w32file_set_times (handle, creation_filetime, access_filetime, write_filetime);
687 if(ret==FALSE) {
688 *error=mono_w32error_get_last ();
691 return(ret);
694 HANDLE
695 ves_icall_System_IO_MonoIO_get_ConsoleOutput (void)
697 return mono_w32file_get_console_output ();
700 HANDLE
701 ves_icall_System_IO_MonoIO_get_ConsoleInput (void)
703 return mono_w32file_get_console_input ();
706 HANDLE
707 ves_icall_System_IO_MonoIO_get_ConsoleError (void)
709 return mono_w32file_get_console_error ();
712 MonoBoolean
713 ves_icall_System_IO_MonoIO_CreatePipe (HANDLE *read_handle, HANDLE *write_handle, gint32 *error)
715 *error = ERROR_SUCCESS;
717 gboolean ret;
719 ret=mono_w32file_create_pipe (read_handle, write_handle, 0);
721 if(ret==FALSE) {
722 *error = mono_w32error_get_last ();
723 /* FIXME: throw an exception? */
724 return(FALSE);
727 return(TRUE);
730 MonoBoolean
731 ves_icall_System_IO_MonoIO_DuplicateHandle (HANDLE source_process_handle, HANDLE source_handle,
732 HANDLE target_process_handle, HANDLE *target_handle, gint32 access, gint32 inherit, gint32 options, gint32 *error)
734 #ifndef HOST_WIN32
735 MonoW32Handle *source_handle_data;
737 if (!mono_w32handle_lookup_and_ref (source_handle, &source_handle_data)) {
738 *error = ERROR_INVALID_HANDLE;
739 return FALSE;
742 *target_handle = mono_w32handle_duplicate (source_handle_data);
744 mono_w32handle_unref ((MonoW32Handle*)source_handle);
745 #else
746 gboolean ret;
748 MONO_ENTER_GC_SAFE;
749 ret=DuplicateHandle (source_process_handle, source_handle, target_process_handle, target_handle, access, inherit, options);
750 MONO_EXIT_GC_SAFE;
752 if (!ret) {
753 *error = mono_w32error_get_last ();
754 /* FIXME: throw an exception? */
755 return(FALSE);
757 #endif
759 return(TRUE);
762 #ifndef HOST_WIN32
763 gunichar2
764 ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar (void)
766 return (gunichar2) '/'; /* forward slash */
769 gunichar2
770 ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar (void)
772 return (gunichar2) '/'; /* forward slash */
775 gunichar2
776 ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar (void)
778 if (IS_PORTABILITY_SET)
779 return (gunichar2) '\\'; /* backslash */
780 else
781 return (gunichar2) '/'; /* forward slash */
784 gunichar2
785 ves_icall_System_IO_MonoIO_get_PathSeparator (void)
787 return (gunichar2) ':'; /* colon */
789 #endif /* !HOST_WIN32 */
791 static const gunichar2
792 invalid_path_chars [] = {
793 #if defined (TARGET_WIN32)
794 0x0022, /* double quote, which seems allowed in MS.NET but should be rejected */
795 0x003c, /* less than */
796 0x003e, /* greater than */
797 0x007c, /* pipe */
798 0x0008,
799 0x0010,
800 0x0011,
801 0x0012,
802 0x0014,
803 0x0015,
804 0x0016,
805 0x0017,
806 0x0018,
807 0x0019,
808 #endif
809 0x0000 /* null */
812 MonoArrayHandle
813 ves_icall_System_IO_MonoIO_get_InvalidPathChars (MonoError *error)
815 MonoArrayHandle chars = MONO_HANDLE_NEW (MonoArray, NULL);
816 MonoDomain *domain;
817 int i, n;
819 domain = mono_domain_get ();
820 n = sizeof (invalid_path_chars) / sizeof (gunichar2);
821 MONO_HANDLE_ASSIGN (chars, mono_array_new_handle (domain, mono_defaults.char_class, n, error));
822 return_val_if_nok (error, MONO_HANDLE_CAST (MonoArray, mono_new_null ()));
824 for (i = 0; i < n; ++ i)
825 MONO_HANDLE_ARRAY_SETVAL (chars, gunichar2, i, invalid_path_chars [i]);
827 return chars;
830 void ves_icall_System_IO_MonoIO_Lock (HANDLE handle, gint64 position,
831 gint64 length, gint32 *error)
833 *error=ERROR_SUCCESS;
834 mono_w32file_lock (handle, position, length, error);
837 void ves_icall_System_IO_MonoIO_Unlock (HANDLE handle, gint64 position,
838 gint64 length, gint32 *error)
840 *error=ERROR_SUCCESS;
841 mono_w32file_unlock (handle, position, length, error);
845 #ifndef HOST_WIN32
846 void mono_w32handle_dump (void);
848 void ves_icall_System_IO_MonoIO_DumpHandles (void)
850 mono_w32handle_dump ();
852 #endif /* !HOST_WIN32 */
854 #endif /* !ENABLE_NETCORE */
856 //Support for io-layer free mmap'd files.
858 #if defined (TARGET_IOS) || defined (TARGET_ANDROID)
860 gint64
861 mono_filesize_from_path (MonoString *string)
863 ERROR_DECL (error);
864 struct stat buf;
865 gint64 res;
866 char *path = mono_string_to_utf8_checked_internal (string, error);
867 mono_error_raise_exception_deprecated (error); /* OK to throw, external only without a good alternative */
869 gint stat_res;
870 MONO_ENTER_GC_SAFE;
871 stat_res = stat (path, &buf);
872 MONO_EXIT_GC_SAFE;
873 if (stat_res == -1)
874 res = -1;
875 else
876 res = (gint64)buf.st_size;
878 g_free (path);
880 return res;
883 gint64
884 mono_filesize_from_fd (int fd)
886 struct stat buf;
887 int res;
889 MONO_ENTER_GC_SAFE;
890 res = fstat (fd, &buf);
891 MONO_EXIT_GC_SAFE;
893 if (res == -1)
894 return (gint64)-1;
896 return (gint64)buf.st_size;
899 #endif