Merge pull request #2003 from esdrubal/seq_test_fix2
[mono.git] / mcs / class / corlib / System.IO / MonoIO.cs
index 7385f3446c7615b9559a376154e9608eb1ebdae2..9d816f40a5952a5e7edcb570a187b34eec2d5427 100644 (file)
@@ -5,6 +5,7 @@
 //   Dick Porter (dick@ximian.com)
 //
 // (C) 2002
+// Copyright 2011 Xamarin Inc (http://www.xamarin.com).
 //
 
 //
@@ -34,11 +35,17 @@ using System;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Threading;
+using Microsoft.Win32.SafeHandles;
+#if NET_2_1
+using System.IO.IsolatedStorage;
+#endif
 
 namespace System.IO
 {
-       unsafe internal sealed class MonoIO {
-               public static readonly FileAttributes
+       unsafe static class MonoIO {
+               public const int FileAlreadyExistsHResult = unchecked ((int) 0x80070000) | (int)MonoIOError.ERROR_FILE_EXISTS;
+
+               public const FileAttributes
                        InvalidFileAttributes = (FileAttributes)(-1);
 
                public static readonly IntPtr
@@ -47,7 +54,27 @@ namespace System.IO
                // error methods
                public static Exception GetException (MonoIOError error)
                {
-                       return GetException (String.Empty, error);
+                       /* This overload is currently only called from
+                        * File.MoveFile(), Directory.Move() and
+                        * Directory.GetCurrentDirectory() -
+                        * everywhere else supplies a path to format
+                        * with the error text.
+                        */
+                       switch(error) {
+                       case MonoIOError.ERROR_ACCESS_DENIED:
+                               return new UnauthorizedAccessException ("Access to the path is denied.");
+                       case MonoIOError.ERROR_FILE_EXISTS:
+                               string message = "Cannot create a file that already exist.";
+                               return new IOException (message, FileAlreadyExistsHResult);
+                       default:
+                               /* Add more mappings here if other
+                                * errors trigger the named but empty
+                                * path bug (see bug 82141.) For
+                                * everything else, fall through to
+                                * the other overload
+                                */
+                               return GetException (String.Empty, error);
+                       }
                }
 
                public static Exception GetException (string path,
@@ -59,8 +86,7 @@ namespace System.IO
                        // FIXME: add more exception mappings here
                        case MonoIOError.ERROR_FILE_NOT_FOUND:
                                message = String.Format ("Could not find file \"{0}\"", path);
-                               return new FileNotFoundException (message,
-                                                                 path);
+                               return new FileNotFoundException (message, path);
 
                        case MonoIOError.ERROR_TOO_MANY_OPEN_FILES:
                                return new IOException ("Too many open files", unchecked((int)0x80070000) | (int)error);
@@ -78,7 +104,7 @@ namespace System.IO
                                return new IOException (message, unchecked((int)0x80070000) | (int)error);
                        case MonoIOError.ERROR_INVALID_DRIVE:
                                message = String.Format ("Could not find the drive  '{0}'. The drive might not be ready or might not be mapped.", path);
-#if NET_2_0
+#if !NET_2_1
                                return new DriveNotFoundException (message);
 #else
                                return new IOException (message, unchecked((int)0x80070000) | (int)error);
@@ -122,6 +148,10 @@ namespace System.IO
                                message = String.Format ("Path {0} is a directory", path);
                                return new IOException (message, unchecked((int)0x80070000) | (int)error);
                                
+                       case MonoIOError.ERROR_NOT_SAME_DEVICE:
+                               message = "Source and destination are not on the same device";
+                               return new IOException (message, unchecked((int)0x80070000) | (int)error);
+                               
                        default:
                                message = String.Format ("Win32 IO returned {0}. Path: {1}", error, path);
                                return new IOException (message, unchecked((int)0x80070000) | (int)error);
@@ -137,7 +167,7 @@ namespace System.IO
                public extern static bool RemoveDirectory (string path, out MonoIOError error);
 
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static string [] GetFileSystemEntries (string path, string pattern, int attrs, int mask, out MonoIOError error);
+               public extern static string [] GetFileSystemEntries (string path, string path_with_pattern, int attrs, int mask, out MonoIOError error);
 
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
                public extern static string GetCurrentDirectory (out MonoIOError error);
@@ -160,6 +190,13 @@ namespace System.IO
                public extern static bool DeleteFile (string path,
                                                      out MonoIOError error);
 
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               public extern static bool ReplaceFile (string sourceFileName, 
+                                                      string destinationFileName, 
+                                                      string destinationBackupFileName, 
+                                                      bool ignoreMetadataErrors,
+                                                      out MonoIOError error);
+
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
                public extern static FileAttributes GetFileAttributes (string path, out MonoIOError error);
 
@@ -167,8 +204,32 @@ namespace System.IO
                public extern static bool SetFileAttributes (string path, FileAttributes attrs, out MonoIOError error);
 
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static MonoFileType GetFileType (IntPtr handle, out MonoIOError error);
+               private extern static MonoFileType GetFileType (IntPtr handle, out MonoIOError error);
+
+               public static MonoFileType GetFileType (SafeHandle safeHandle, out MonoIOError error)
+               {
+                       bool release = false;
+                       try {
+                               safeHandle.DangerousAddRef (ref release);
+                               return GetFileType (safeHandle.DangerousGetHandle (), out error);
+                       } finally {
+                               if (release)
+                                       safeHandle.DangerousRelease ();
+                       }
+               }
 
+               //
+               // Find file methods
+               //
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               public extern static string FindFirst (string path, string pattern, out FileAttributes result_attr, out MonoIOError error, out IntPtr handle);
+               
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               public extern static string FindNext (IntPtr handle, out FileAttributes result_attr, out MonoIOError error);
+               
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               public extern static int FindClose (IntPtr handle);
+               
                public static bool Exists (string path, out MonoIOError error)
                {
                        FileAttributes attrs = GetFileAttributes (path,
@@ -240,46 +301,144 @@ namespace System.IO
                                                  FileShare share,
                                                  FileOptions options,
                                                  out MonoIOError error);
-               
+
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
                public extern static bool Close (IntPtr handle,
                                                 out MonoIOError error);
                
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static int Read (IntPtr handle, byte [] dest,
+               private extern static int Read (IntPtr handle, byte [] dest,
                                               int dest_offset, int count,
                                               out MonoIOError error);
+
+               public static int Read (SafeHandle safeHandle, byte [] dest,
+                                              int dest_offset, int count,
+                                              out MonoIOError error)
+               {
+                       bool release = false;
+                       try {
+                               safeHandle.DangerousAddRef (ref release);
+                               return Read (safeHandle.DangerousGetHandle (), dest, dest_offset, count, out error);
+                       } finally {
+                               if (release)
+                                       safeHandle.DangerousRelease ();
+                       }
+               }
                
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static int Write (IntPtr handle, [In] byte [] src,
+               private extern static int Write (IntPtr handle, [In] byte [] src,
                                                int src_offset, int count,
                                                out MonoIOError error);
+
+               public static int Write (SafeHandle safeHandle, byte [] src,
+                                               int src_offset, int count,
+                                               out MonoIOError error)
+               {
+                       bool release = false;
+                       try {
+                               safeHandle.DangerousAddRef (ref release);
+                               return Write (safeHandle.DangerousGetHandle (), src, src_offset, count, out error);
+                       } finally {
+                               if (release)
+                                       safeHandle.DangerousRelease ();
+                       }
+               }
                
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static long Seek (IntPtr handle, long offset,
+               private extern static long Seek (IntPtr handle, long offset,
                                                SeekOrigin origin,
                                                out MonoIOError error);
+
+               public static long Seek (SafeHandle safeHandle, long offset,
+                                               SeekOrigin origin,
+                                               out MonoIOError error)
+               {
+                       bool release = false;
+                       try {
+                               safeHandle.DangerousAddRef (ref release);
+                               return Seek (safeHandle.DangerousGetHandle (), offset, origin, out error);
+                       } finally {
+                               if (release)
+                                       safeHandle.DangerousRelease ();
+                       }
+               }
                
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static bool Flush (IntPtr handle,
+               private extern static bool Flush (IntPtr handle,
                                                 out MonoIOError error);
 
+               public static bool Flush (SafeHandle safeHandle,
+                                                out MonoIOError error)
+               {
+                       bool release = false;
+                       try {
+                               safeHandle.DangerousAddRef (ref release);
+                               return Flush (safeHandle.DangerousGetHandle (), out error);
+                       } finally {
+                               if (release)
+                                       safeHandle.DangerousRelease ();
+                       }
+               }
+
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static long GetLength (IntPtr handle,
+               private extern static long GetLength (IntPtr handle,
                                                     out MonoIOError error);
 
+               public static long GetLength (SafeHandle safeHandle,
+                                                    out MonoIOError error)
+               {
+                       bool release = false;
+                       try {
+                               safeHandle.DangerousAddRef (ref release);
+                               return GetLength (safeHandle.DangerousGetHandle (), out error);
+                       } finally {
+                               if (release)
+                                       safeHandle.DangerousRelease ();
+                       }
+               }
+
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static bool SetLength (IntPtr handle,
+               private extern static bool SetLength (IntPtr handle,
                                                     long length,
                                                     out MonoIOError error);
 
+               public static bool SetLength (SafeHandle safeHandle,
+                                                    long length,
+                                                    out MonoIOError error)
+               {
+                       bool release = false;
+                       try {
+                               safeHandle.DangerousAddRef (ref release);
+                               return SetLength (safeHandle.DangerousGetHandle (), length, out error);
+                       } finally {
+                               if (release)
+                                       safeHandle.DangerousRelease ();
+                       }
+               }
+
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static bool SetFileTime (IntPtr handle,
+               private extern static bool SetFileTime (IntPtr handle,
                                                       long creation_time,
                                                       long last_access_time,
                                                       long last_write_time,
                                                       out MonoIOError error);
 
+               public static bool SetFileTime (SafeHandle safeHandle,
+                                                      long creation_time,
+                                                      long last_access_time,
+                                                      long last_write_time,
+                                                      out MonoIOError error)
+               {
+                       bool release = false;
+                       try {
+                               safeHandle.DangerousAddRef (ref release);
+                               return SetFileTime (safeHandle.DangerousGetHandle (), creation_time, last_access_time, last_write_time, out error);
+                       } finally {
+                               if (release)
+                                       safeHandle.DangerousRelease ();
+                       }
+               }
+
                public static bool SetFileTime (string path,
                                                long creation_time,
                                                long last_access_time,
@@ -345,7 +504,7 @@ namespace System.IO
                                break;
                        }
 
-                       result = SetFileTime (handle, creation_time,
+                       result = SetFileTime (new SafeFileHandle(handle, false), creation_time,
                                              last_access_time,
                                              last_write_time, out error);
 
@@ -356,15 +515,43 @@ namespace System.IO
                }
 
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static void Lock (IntPtr handle,
+               private extern static void Lock (IntPtr handle,
                                                long position, long length,
                                                out MonoIOError error);
 
+               public static void Lock (SafeHandle safeHandle,
+                                               long position, long length,
+                                               out MonoIOError error)
+               {
+                       bool release = false;
+                       try {
+                               safeHandle.DangerousAddRef (ref release);
+                               Lock (safeHandle.DangerousGetHandle (), position, length, out error);
+                       } finally {
+                               if (release)
+                                       safeHandle.DangerousRelease ();
+                       }
+               }
+
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static void Unlock (IntPtr handle,
+               private extern static void Unlock (IntPtr handle,
                                                  long position, long length,
                                                  out MonoIOError error);
 
+               public static void Unlock (SafeHandle safeHandle,
+                                                 long position, long length,
+                                                 out MonoIOError error)
+               {
+                       bool release = false;
+                       try {
+                               safeHandle.DangerousAddRef (ref release);
+                               Unlock (safeHandle.DangerousGetHandle (), position, length, out error);
+                       } finally {
+                               if (release)
+                                       safeHandle.DangerousRelease ();
+                       }
+               }
+
                // console handles
 
                public extern static IntPtr ConsoleOutput {
@@ -387,6 +574,10 @@ namespace System.IO
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
                public extern static bool CreatePipe (out IntPtr read_handle, out IntPtr write_handle);
 
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               public extern static bool DuplicateHandle (IntPtr source_process_handle, IntPtr source_handle,
+                       IntPtr target_process_handle, out IntPtr target_handle, int access, int inherit, int options);
+
                // path characters
 
                public extern static char VolumeSeparatorChar {
@@ -408,9 +599,6 @@ namespace System.IO
                        [MethodImplAttribute (MethodImplOptions.InternalCall)]
                        get;
                }
-
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern static int GetTempPath(out string path);
        }
 }