[LoongArch64] Part-5:add loongarch support in some files for LoongArch64. (#21769)
[mono-project.git] / mcs / class / corlib / System.IO / MonoIO.cs
blob46774397bcdc3677b0e8a1cb332088e8d3468254
1 // System.IO.MonoIO.cs: static interface to native filesystem.
2 //
3 // Author:
4 // Dan Lewis (dihlewis@yahoo.co.uk)
5 // Dick Porter (dick@ximian.com)
6 //
7 // (C) 2002
8 // Copyright 2011 Xamarin Inc (http://www.xamarin.com).
9 //
12 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 //
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 //
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System;
35 using System.Runtime.CompilerServices;
36 using System.Runtime.InteropServices;
37 using System.Threading;
38 using Microsoft.Win32.SafeHandles;
39 #if MOBILE
40 using System.IO.IsolatedStorage;
41 #endif
43 namespace System.IO
45 unsafe static class MonoIO {
46 public const int FileAlreadyExistsHResult = unchecked ((int) 0x80070000) | (int)MonoIOError.ERROR_FILE_EXISTS;
48 public const FileAttributes
49 InvalidFileAttributes = (FileAttributes)(-1);
51 public static readonly IntPtr
52 InvalidHandle = (IntPtr)(-1L);
54 static bool dump_handles = Environment.GetEnvironmentVariable ("MONO_DUMP_HANDLES_ON_ERROR_TOO_MANY_OPEN_FILES") != null;
56 // error methods
57 public static Exception GetException (MonoIOError error)
59 /* This overload is currently only called from
60 * File.MoveFile(), Directory.Move() and
61 * Directory.GetCurrentDirectory() -
62 * everywhere else supplies a path to format
63 * with the error text.
65 switch(error) {
66 case MonoIOError.ERROR_ACCESS_DENIED:
67 return new UnauthorizedAccessException ("Access to the path is denied.");
68 case MonoIOError.ERROR_FILE_EXISTS:
69 string message = "Cannot create a file that already exist.";
70 return new IOException (message, FileAlreadyExistsHResult);
71 default:
72 /* Add more mappings here if other
73 * errors trigger the named but empty
74 * path bug (see bug 82141.) For
75 * everything else, fall through to
76 * the other overload
78 return GetException (String.Empty, error);
82 public static Exception GetException (string path,
83 MonoIOError error)
85 string message;
87 switch (error) {
88 // FIXME: add more exception mappings here
89 case MonoIOError.ERROR_FILE_NOT_FOUND:
90 message = String.Format ("Could not find file \"{0}\"", path);
91 return new FileNotFoundException (message, path);
93 case MonoIOError.ERROR_TOO_MANY_OPEN_FILES:
94 if (dump_handles)
95 DumpHandles ();
96 return new IOException ("Too many open files", unchecked((int)0x80070000) | (int)error);
98 case MonoIOError.ERROR_PATH_NOT_FOUND:
99 message = String.Format ("Could not find a part of the path \"{0}\"", path);
100 return new DirectoryNotFoundException (message);
102 case MonoIOError.ERROR_ACCESS_DENIED:
103 message = String.Format ("Access to the path \"{0}\" is denied.", path);
104 return new UnauthorizedAccessException (message);
106 case MonoIOError.ERROR_INVALID_HANDLE:
107 message = String.Format ("Invalid handle to path \"{0}\"", path);
108 return new IOException (message, unchecked((int)0x80070000) | (int)error);
109 case MonoIOError.ERROR_INVALID_DRIVE:
110 message = String.Format ("Could not find the drive '{0}'. The drive might not be ready or might not be mapped.", path);
111 #if !MOBILE
112 return new DriveNotFoundException (message);
113 #else
114 return new IOException (message, unchecked((int)0x80070000) | (int)error);
115 #endif
116 case MonoIOError.ERROR_FILE_EXISTS:
117 message = String.Format ("Could not create file \"{0}\". File already exists.", path);
118 return new IOException (message, unchecked((int)0x80070000) | (int)error);
120 case MonoIOError.ERROR_FILENAME_EXCED_RANGE:
121 message = String.Format ("Path is too long. Path: {0}", path);
122 return new PathTooLongException (message);
124 case MonoIOError.ERROR_INVALID_PARAMETER:
125 message = String.Format ("Invalid parameter");
126 return new IOException (message, unchecked((int)0x80070000) | (int)error);
128 case MonoIOError.ERROR_WRITE_FAULT:
129 message = String.Format ("Write fault on path {0}", path);
130 return new IOException (message, unchecked((int)0x80070000) | (int)error);
132 case MonoIOError.ERROR_SHARING_VIOLATION:
133 message = String.Format ("Sharing violation on path {0}", path);
134 return new IOException (message, unchecked((int)0x80070000) | (int)error);
136 case MonoIOError.ERROR_LOCK_VIOLATION:
137 message = String.Format ("Lock violation on path {0}", path);
138 return new IOException (message, unchecked((int)0x80070000) | (int)error);
140 case MonoIOError.ERROR_HANDLE_DISK_FULL:
141 message = String.Format ("Disk full. Path {0}", path);
142 return new IOException (message, unchecked((int)0x80070000) | (int)error);
144 case MonoIOError.ERROR_DIR_NOT_EMPTY:
145 message = String.Format ("Directory {0} is not empty", path);
146 return new IOException (message, unchecked((int)0x80070000) | (int)error);
148 case MonoIOError.ERROR_ENCRYPTION_FAILED:
149 return new IOException ("Encryption failed", unchecked((int)0x80070000) | (int)error);
151 case MonoIOError.ERROR_CANNOT_MAKE:
152 message = String.Format ("Path {0} is a directory", path);
153 return new IOException (message, unchecked((int)0x80070000) | (int)error);
155 case MonoIOError.ERROR_NOT_SAME_DEVICE:
156 message = "Source and destination are not on the same device";
157 return new IOException (message, unchecked((int)0x80070000) | (int)error);
159 case MonoIOError.ERROR_DIRECTORY:
160 message = "The directory name is invalid";
161 return new IOException (message, unchecked((int)0x80070000) | (int)error);
163 default:
164 message = String.Format ("Win32 IO returned {0}. Path: {1}", error, path);
165 return new IOException (message, unchecked((int)0x80070000) | (int)error);
169 // directory methods
171 [MethodImplAttribute (MethodImplOptions.InternalCall)]
172 private unsafe extern static bool CreateDirectory (char* path, out MonoIOError error);
174 public static bool CreateDirectory (string path, out MonoIOError error)
176 unsafe {
177 fixed (char* pathChars = path) {
178 return CreateDirectory (pathChars, out error);
183 [MethodImplAttribute (MethodImplOptions.InternalCall)]
184 private unsafe extern static bool RemoveDirectory (char* path, out MonoIOError error);
186 public static bool RemoveDirectory (string path, out MonoIOError error)
188 unsafe {
189 fixed (char* pathChars = path) {
190 return RemoveDirectory (pathChars, out error);
195 [MethodImplAttribute (MethodImplOptions.InternalCall)]
196 public extern static string GetCurrentDirectory (out MonoIOError error);
198 [MethodImplAttribute (MethodImplOptions.InternalCall)]
199 private unsafe extern static bool SetCurrentDirectory (char* path, out MonoIOError error);
201 public static bool SetCurrentDirectory (string path, out MonoIOError error)
203 unsafe {
204 fixed (char* pathChars = path) {
205 return SetCurrentDirectory (pathChars, out error);
210 // file methods
212 [MethodImplAttribute (MethodImplOptions.InternalCall)]
213 private unsafe extern static bool MoveFile (char* path, char* dest,
214 out MonoIOError error);
216 public static bool MoveFile (string path, string dest,
217 out MonoIOError error)
219 unsafe {
220 fixed (char* pathChars = path, destChars = dest) {
221 return MoveFile (pathChars, destChars, out error);
226 [MethodImplAttribute (MethodImplOptions.InternalCall)]
227 private unsafe extern static bool CopyFile (char* path, char* dest,
228 bool overwrite,
229 out MonoIOError error);
231 public static bool CopyFile (string path, string dest,
232 bool overwrite,
233 out MonoIOError error)
235 unsafe {
236 fixed (char* pathChars = path, destChars = dest) {
237 return CopyFile (pathChars, destChars, overwrite, out error);
242 [MethodImplAttribute (MethodImplOptions.InternalCall)]
243 private unsafe extern static bool DeleteFile (char* path,
244 out MonoIOError error);
246 public static bool DeleteFile (string path,
247 out MonoIOError error)
249 unsafe {
250 fixed (char* pathChars = path) {
251 return DeleteFile (pathChars, out error);
256 [MethodImplAttribute (MethodImplOptions.InternalCall)]
257 private unsafe extern static bool ReplaceFile (char* sourceFileName,
258 char* destinationFileName,
259 char* destinationBackupFileName,
260 bool ignoreMetadataErrors,
261 out MonoIOError error);
263 public static bool ReplaceFile (string sourceFileName,
264 string destinationFileName,
265 string destinationBackupFileName,
266 bool ignoreMetadataErrors,
267 out MonoIOError error)
269 unsafe {
270 fixed (char* sourceFileNameChars = sourceFileName,
271 destinationFileNameChars = destinationFileName,
272 destinationBackupFileNameChars = destinationBackupFileName) {
273 return ReplaceFile (sourceFileNameChars, destinationFileNameChars, destinationBackupFileNameChars, ignoreMetadataErrors, out error);
278 [MethodImplAttribute (MethodImplOptions.InternalCall)]
279 private unsafe extern static FileAttributes GetFileAttributes (char* path, out MonoIOError error);
281 public static FileAttributes GetFileAttributes (string path, out MonoIOError error)
283 unsafe {
284 fixed (char* pathChars = path) {
285 return GetFileAttributes (pathChars, out error);
290 [MethodImplAttribute (MethodImplOptions.InternalCall)]
291 private extern static bool SetFileAttributes (char* path, FileAttributes attrs, out MonoIOError error);
293 public static bool SetFileAttributes (string path, FileAttributes attrs, out MonoIOError error)
295 unsafe {
296 fixed (char* pathChars = path) {
297 return SetFileAttributes (pathChars, attrs, out error);
302 [MethodImplAttribute (MethodImplOptions.InternalCall)]
303 private extern static MonoFileType GetFileType (IntPtr handle, out MonoIOError error);
305 public static MonoFileType GetFileType (SafeHandle safeHandle, out MonoIOError error)
307 bool release = false;
308 try {
309 safeHandle.DangerousAddRef (ref release);
310 return GetFileType (safeHandle.DangerousGetHandle (), out error);
311 } finally {
312 if (release)
313 safeHandle.DangerousRelease ();
318 // Find file methods
321 [MethodImplAttribute (MethodImplOptions.InternalCall)]
322 private unsafe extern static IntPtr FindFirstFile (char* pathWithPattern, out string fileName, out int fileAttr, out int error);
324 public static IntPtr FindFirstFile (string pathWithPattern, out string fileName, out int fileAttr, out int error)
326 unsafe {
327 fixed (char* pathWithPatternChars = pathWithPattern) {
328 return FindFirstFile (pathWithPatternChars, out fileName, out fileAttr, out error);
333 [MethodImplAttribute (MethodImplOptions.InternalCall)]
334 public extern static bool FindNextFile (IntPtr hnd, out string fileName, out int fileAttr, out int error);
336 [MethodImplAttribute (MethodImplOptions.InternalCall)]
337 public extern static bool FindCloseFile (IntPtr hnd);
339 public static bool Exists (string path, out MonoIOError error)
341 FileAttributes attrs = GetFileAttributes (path,
342 out error);
343 if (attrs == InvalidFileAttributes)
344 return false;
346 return true;
349 public static bool ExistsFile (string path,
350 out MonoIOError error)
352 FileAttributes attrs = GetFileAttributes (path,
353 out error);
354 if (attrs == InvalidFileAttributes)
355 return false;
357 if ((attrs & FileAttributes.Directory) != 0)
358 return false;
360 return true;
363 public static bool ExistsDirectory (string path,
364 out MonoIOError error)
366 FileAttributes attrs = GetFileAttributes (path,
367 out error);
369 // Actually, we are looking for a directory, not a file
370 if (error == MonoIOError.ERROR_FILE_NOT_FOUND)
371 error = MonoIOError.ERROR_PATH_NOT_FOUND;
373 if (attrs == InvalidFileAttributes)
374 return false;
376 if ((attrs & FileAttributes.Directory) == 0)
377 return false;
379 return true;
382 public static bool ExistsSymlink (string path,
383 out MonoIOError error)
385 FileAttributes attrs = GetFileAttributes (path,
386 out error);
387 if (attrs == InvalidFileAttributes)
388 return false;
390 if ((attrs & FileAttributes.ReparsePoint) == 0)
391 return false;
393 return true;
396 [MethodImplAttribute (MethodImplOptions.InternalCall)]
397 private unsafe extern static bool GetFileStat (char* path,
398 out MonoIOStat stat,
399 out MonoIOError error);
401 public static bool GetFileStat (string path,
402 out MonoIOStat stat,
403 out MonoIOError error)
405 unsafe {
406 fixed (char* pathChars = path) {
407 return GetFileStat (pathChars, out stat, out error);
412 // handle methods
414 [MethodImplAttribute (MethodImplOptions.InternalCall)]
415 private unsafe extern static IntPtr Open (char* filename,
416 FileMode mode,
417 FileAccess access,
418 FileShare share,
419 FileOptions options,
420 out MonoIOError error);
422 public static IntPtr Open (string filename,
423 FileMode mode,
424 FileAccess access,
425 FileShare share,
426 FileOptions options,
427 out MonoIOError error)
429 unsafe {
430 fixed (char* filenameChars = filename) {
431 return Open (filenameChars, mode, access, share, options, out error);
436 [MethodImplAttribute (MethodImplOptions.InternalCall)]
437 private extern static bool Cancel_internal (IntPtr handle, out MonoIOError error);
439 internal static bool Cancel (SafeHandle safeHandle, out MonoIOError error)
441 bool release = false;
442 try {
443 safeHandle.DangerousAddRef (ref release);
444 return Cancel_internal (safeHandle.DangerousGetHandle (), out error);
445 } finally {
446 if (release)
447 safeHandle.DangerousRelease ();
451 [MethodImplAttribute (MethodImplOptions.InternalCall)]
452 public extern static bool Close (IntPtr handle,
453 out MonoIOError error);
455 [MethodImplAttribute (MethodImplOptions.InternalCall)]
456 private extern static int Read (IntPtr handle, byte [] dest,
457 int dest_offset, int count,
458 out MonoIOError error);
460 public static int Read (SafeHandle safeHandle, byte [] dest,
461 int dest_offset, int count,
462 out MonoIOError error)
464 bool release = false;
465 try {
466 safeHandle.DangerousAddRef (ref release);
467 return Read (safeHandle.DangerousGetHandle (), dest, dest_offset, count, out error);
468 } finally {
469 if (release)
470 safeHandle.DangerousRelease ();
474 [MethodImplAttribute (MethodImplOptions.InternalCall)]
475 private extern static int Write (IntPtr handle, [In] byte [] src,
476 int src_offset, int count,
477 out MonoIOError error);
479 public static int Write (SafeHandle safeHandle, byte [] src,
480 int src_offset, int count,
481 out MonoIOError error)
483 bool release = false;
484 try {
485 safeHandle.DangerousAddRef (ref release);
486 return Write (safeHandle.DangerousGetHandle (), src, src_offset, count, out error);
487 } finally {
488 if (release)
489 safeHandle.DangerousRelease ();
493 [MethodImplAttribute (MethodImplOptions.InternalCall)]
494 private extern static long Seek (IntPtr handle, long offset,
495 SeekOrigin origin,
496 out MonoIOError error);
498 public static long Seek (SafeHandle safeHandle, long offset,
499 SeekOrigin origin,
500 out MonoIOError error)
502 bool release = false;
503 try {
504 safeHandle.DangerousAddRef (ref release);
505 return Seek (safeHandle.DangerousGetHandle (), offset, origin, out error);
506 } finally {
507 if (release)
508 safeHandle.DangerousRelease ();
512 [MethodImplAttribute (MethodImplOptions.InternalCall)]
513 private extern static bool Flush (IntPtr handle,
514 out MonoIOError error);
516 public static bool Flush (SafeHandle safeHandle,
517 out MonoIOError error)
519 bool release = false;
520 try {
521 safeHandle.DangerousAddRef (ref release);
522 return Flush (safeHandle.DangerousGetHandle (), out error);
523 } finally {
524 if (release)
525 safeHandle.DangerousRelease ();
529 [MethodImplAttribute (MethodImplOptions.InternalCall)]
530 private extern static long GetLength (IntPtr handle,
531 out MonoIOError error);
533 public static long GetLength (SafeHandle safeHandle,
534 out MonoIOError error)
536 bool release = false;
537 try {
538 safeHandle.DangerousAddRef (ref release);
539 return GetLength (safeHandle.DangerousGetHandle (), out error);
540 } finally {
541 if (release)
542 safeHandle.DangerousRelease ();
546 [MethodImplAttribute (MethodImplOptions.InternalCall)]
547 private extern static bool SetLength (IntPtr handle,
548 long length,
549 out MonoIOError error);
551 public static bool SetLength (SafeHandle safeHandle,
552 long length,
553 out MonoIOError error)
555 bool release = false;
556 try {
557 safeHandle.DangerousAddRef (ref release);
558 return SetLength (safeHandle.DangerousGetHandle (), length, out error);
559 } finally {
560 if (release)
561 safeHandle.DangerousRelease ();
565 [MethodImplAttribute (MethodImplOptions.InternalCall)]
566 private extern static bool SetFileTime (IntPtr handle,
567 long creation_time,
568 long last_access_time,
569 long last_write_time,
570 out MonoIOError error);
572 public static bool SetFileTime (SafeHandle safeHandle,
573 long creation_time,
574 long last_access_time,
575 long last_write_time,
576 out MonoIOError error)
578 bool release = false;
579 try {
580 safeHandle.DangerousAddRef (ref release);
581 return SetFileTime (safeHandle.DangerousGetHandle (), creation_time, last_access_time, last_write_time, out error);
582 } finally {
583 if (release)
584 safeHandle.DangerousRelease ();
588 public static bool SetFileTime (string path,
589 long creation_time,
590 long last_access_time,
591 long last_write_time,
592 out MonoIOError error)
594 return SetFileTime (path,
596 creation_time,
597 last_access_time,
598 last_write_time,
599 DateTime.MinValue,
600 out error);
603 public static bool SetCreationTime (string path,
604 DateTime dateTime,
605 out MonoIOError error)
607 return SetFileTime (path, 1, -1, -1, -1, dateTime, out error);
610 public static bool SetLastAccessTime (string path,
611 DateTime dateTime,
612 out MonoIOError error)
614 return SetFileTime (path, 2, -1, -1, -1, dateTime, out error);
617 public static bool SetLastWriteTime (string path,
618 DateTime dateTime,
619 out MonoIOError error)
621 return SetFileTime (path, 3, -1, -1, -1, dateTime, out error);
624 public static bool SetFileTime (string path,
625 int type,
626 long creation_time,
627 long last_access_time,
628 long last_write_time,
629 DateTime dateTime,
630 out MonoIOError error)
632 IntPtr handle;
633 bool result;
635 handle = Open (path, FileMode.Open,
636 FileAccess.ReadWrite,
637 FileShare.ReadWrite, FileOptions.None, out error);
638 if (handle == MonoIO.InvalidHandle)
639 return false;
641 switch (type) {
642 case 1:
643 creation_time = dateTime.ToFileTime ();
644 break;
645 case 2:
646 last_access_time = dateTime.ToFileTime ();
647 break;
648 case 3:
649 last_write_time = dateTime.ToFileTime ();
650 break;
653 result = SetFileTime (new SafeFileHandle(handle, false), creation_time,
654 last_access_time,
655 last_write_time, out error);
657 MonoIOError ignore_error;
658 Close (handle, out ignore_error);
660 return result;
663 [MethodImplAttribute (MethodImplOptions.InternalCall)]
664 private extern static void Lock (IntPtr handle,
665 long position, long length,
666 out MonoIOError error);
668 public static void Lock (SafeHandle safeHandle,
669 long position, long length,
670 out MonoIOError error)
672 bool release = false;
673 try {
674 safeHandle.DangerousAddRef (ref release);
675 Lock (safeHandle.DangerousGetHandle (), position, length, out error);
676 } finally {
677 if (release)
678 safeHandle.DangerousRelease ();
682 [MethodImplAttribute (MethodImplOptions.InternalCall)]
683 private extern static void Unlock (IntPtr handle,
684 long position, long length,
685 out MonoIOError error);
687 public static void Unlock (SafeHandle safeHandle,
688 long position, long length,
689 out MonoIOError error)
691 bool release = false;
692 try {
693 safeHandle.DangerousAddRef (ref release);
694 Unlock (safeHandle.DangerousGetHandle (), position, length, out error);
695 } finally {
696 if (release)
697 safeHandle.DangerousRelease ();
701 // console handles
703 public extern static IntPtr ConsoleOutput {
704 [MethodImplAttribute (MethodImplOptions.InternalCall)]
705 get;
708 public extern static IntPtr ConsoleInput {
709 [MethodImplAttribute (MethodImplOptions.InternalCall)]
710 get;
713 public extern static IntPtr ConsoleError {
714 [MethodImplAttribute (MethodImplOptions.InternalCall)]
715 get;
718 // pipe handles
720 [MethodImplAttribute (MethodImplOptions.InternalCall)]
721 public extern static bool CreatePipe (out IntPtr read_handle, out IntPtr write_handle, out MonoIOError error);
723 [MethodImplAttribute (MethodImplOptions.InternalCall)]
724 public extern static bool DuplicateHandle (IntPtr source_process_handle, IntPtr source_handle,
725 IntPtr target_process_handle, out IntPtr target_handle, int access, int inherit, int options, out MonoIOError error);
727 // path characters
729 public extern static char VolumeSeparatorChar {
730 [MethodImplAttribute (MethodImplOptions.InternalCall)]
731 get;
734 public extern static char DirectorySeparatorChar {
735 [MethodImplAttribute (MethodImplOptions.InternalCall)]
736 get;
739 public extern static char AltDirectorySeparatorChar {
740 [MethodImplAttribute (MethodImplOptions.InternalCall)]
741 get;
744 public extern static char PathSeparator {
745 [MethodImplAttribute (MethodImplOptions.InternalCall)]
746 get;
749 [MethodImplAttribute (MethodImplOptions.InternalCall)]
750 extern static void DumpHandles ();