New tests.
[mono.git] / mcs / class / corlib / System.IO / File.cs
index 3d042b11f329245ffa01ee99e2d1a6bed16c0814..733377e8c640e81a15eae4d9e1d7cb1af3b5405c 100644 (file)
@@ -1,5 +1,5 @@
 // 
-// System.IO.FIle.cs 
+// System.IO.File.cs 
 //
 // 
 // Authors:
@@ -10,7 +10,7 @@
 //
 // Copyright 2002 Ximian, Inc. http://www.ximian.com
 // Copyright (C) 2001 Moonlight Enterprises, All Rights Reserved
-// Copyright (C) 2004, 2006 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2004, 2006, 2010 Novell, Inc (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
 //
 
 using System;
-using System.Text;
-#if NET_2_0
 using System.Collections.Generic;
+using System.Diagnostics;
+using System.Security;
+using System.Text;
+using System.Runtime.InteropServices;
+
+#if !NET_2_1
+using System.Security.AccessControl;
 #endif
 
 namespace System.IO
 {
-       /// <summary>
-       /// 
-       /// </summary>
-       public
-#if NET_2_0
-       static
-#else
-       sealed
-#endif
-       class File
+       [ComVisible (true)]
+       public static class File
        {
-
-#if !NET_2_0
-               private File () {}
-#endif
-               
-#if NET_2_0
                public static void AppendAllText (string path, string contents)
-               {       
+               {
                        using (TextWriter w = new StreamWriter (path, true)) {
                                w.Write (contents);
                        }
                }
 
                public static void AppendAllText (string path, string contents, Encoding encoding)
-               {       
+               {
                        using (TextWriter w = new StreamWriter (path, true, encoding)) {
                                w.Write (contents);
                        }
                }
-#endif
 
                public static StreamWriter AppendText (string path)
-               {       
+               {
                        return new StreamWriter (path, true);
                }
 
-               public static void Copy (string sourceFilename, string destFilename)
+               public static void Copy (string sourceFileName, string destFileName)
                {
-                       Copy (sourceFilename, destFilename, false);
+                       Copy (sourceFileName, destFileName, false);
                }
 
-               public static void Copy (string src, string dest, bool overwrite)
-               {       
-                       if (src == null)
-                               throw new ArgumentNullException ("src");
-                       if (dest == null)
-                               throw new ArgumentNullException ("dest");
-                       if (src.Trim () == "" || src.IndexOfAny (Path.InvalidPathChars) != -1)
-                               throw new ArgumentException (Locale.GetText ("src is null"));
-                       if (dest.Trim () == "" || dest.IndexOfAny (Path.InvalidPathChars) != -1)
-                               throw new ArgumentException (Locale.GetText ("dest is empty or contains invalid characters"));
-                       if (!Exists (src))
-                               throw new FileNotFoundException (Locale.GetText ("{0} does not exist", src), src);
+               public static void Copy (string sourceFileName, string destFileName, bool overwrite)
+               {
+                       MonoIOError error;
 
-                       if ((GetAttributes(src) & FileAttributes.Directory) == FileAttributes.Directory){
-                               throw new ArgumentException(Locale.GetText ("{0} is a directory", src));
-                       }
-                       
-                       if (Exists (dest)) {
-                               if ((GetAttributes(dest) & FileAttributes.Directory) == FileAttributes.Directory){
-                                       throw new ArgumentException (Locale.GetText ("{0} is a directory", dest));
-                               }
+                       if (sourceFileName == null)
+                               throw new ArgumentNullException ("sourceFileName");
+                       if (destFileName == null)
+                               throw new ArgumentNullException ("destFileName");
+                       if (sourceFileName.Length == 0)
+                               throw new ArgumentException ("An empty file name is not valid.", "sourceFileName");
+                       if (sourceFileName.Trim ().Length == 0 || sourceFileName.IndexOfAny (Path.InvalidPathChars) != -1)
+                               throw new ArgumentException ("The file name is not valid.");
+                       if (destFileName.Length == 0)
+                               throw new ArgumentException ("An empty file name is not valid.", "destFileName");
+                       if (destFileName.Trim ().Length == 0 || destFileName.IndexOfAny (Path.InvalidPathChars) != -1)
+                               throw new ArgumentException ("The file name is not valid.");
+
+                       SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
+
+                       if (!MonoIO.Exists (sourceFileName, out error))
+                               throw new FileNotFoundException (Locale.GetText ("{0} does not exist", sourceFileName), sourceFileName);
+                       if ((GetAttributes (sourceFileName) & FileAttributes.Directory) == FileAttributes.Directory)
+                               throw new ArgumentException (Locale.GetText ("{0} is a directory", sourceFileName));
+
+                       if (MonoIO.Exists (destFileName, out error)) {
+                               if ((GetAttributes (destFileName) & FileAttributes.Directory) == FileAttributes.Directory)
+                                       throw new ArgumentException (Locale.GetText ("{0} is a directory", destFileName));
                                if (!overwrite)
-                                       throw new IOException (Locale.GetText ("{0} already exists", dest));
+                                       throw new IOException (Locale.GetText ("{0} already exists", destFileName));
                        }
 
-                       string DirName = Path.GetDirectoryName(dest);
+                       string DirName = Path.GetDirectoryName (destFileName);
                        if (DirName != String.Empty && !Directory.Exists (DirName))
                                throw new DirectoryNotFoundException (Locale.GetText ("Destination directory not found: {0}",DirName));
 
-                       MonoIOError error;
-                       
-                       if (!MonoIO.CopyFile (src, dest, overwrite, out error)){
-                               string p = Locale.GetText ("{0}\" or \"{1}", src, dest);
+                       if (!MonoIO.CopyFile (sourceFileName, destFileName, overwrite, out error)) {
+                               string p = Locale.GetText ("{0}\" or \"{1}", sourceFileName, destFileName);
                                throw MonoIO.GetException (p, error);
                        }
                }
@@ -124,47 +118,46 @@ namespace System.IO
                        return Create (path, 8192);
                }
 
-               public static FileStream Create (string path, int buffersize)
+               public static FileStream Create (string path, int bufferSize)
                {
-                       if (null == path)
-                               throw new ArgumentNullException ("path");
-                       if (String.Empty == path.Trim() || path.IndexOfAny(Path.InvalidPathChars) >= 0)
-                               throw new ArgumentException (Locale.GetText ("path is invalid"));
-
-                       string DirName = Path.GetDirectoryName(path);
-                       if (DirName != String.Empty && !Directory.Exists (DirName))
-                               throw new DirectoryNotFoundException (Locale.GetText ("Destination directory not found: {0}", DirName));
-                       if (Exists(path)){
-                               if ((GetAttributes(path) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly){
-                                       throw new UnauthorizedAccessException (Locale.GetText ("{0} is read-only", path));
-                               }
-                       }
-
                        return new FileStream (path, FileMode.Create, FileAccess.ReadWrite,
-                                              FileShare.None, buffersize);
+                               FileShare.None, bufferSize);
                }
 
-               public static StreamWriter CreateText(string path)
+#if !NET_2_1
+               [MonoLimitation ("FileOptions are ignored")]
+               public static FileStream Create (string path, int bufferSize,
+                                                FileOptions options)
+               {
+                       return Create (path, bufferSize, options, null);
+               }
                
+               [MonoLimitation ("FileOptions and FileSecurity are ignored")]
+               public static FileStream Create (string path, int bufferSize,
+                                                FileOptions options,
+                                                FileSecurity fileSecurity)
+               {
+                       return new FileStream (path, FileMode.Create, FileAccess.ReadWrite,
+                               FileShare.None, bufferSize, options);
+               }
+#endif
+
+               public static StreamWriter CreateText (string path)
                {
                        return new StreamWriter (path, false);
-               
                }
-               
-               
-               
+
                public static void Delete (string path)
                {
-                       if (null == path)
-                               throw new ArgumentNullException("path");
-                       if (String.Empty == path.Trim() || path.IndexOfAny(Path.InvalidPathChars) >= 0)
-                               throw new ArgumentException("path");
+                       Path.Validate (path);
                        if (Directory.Exists (path))
                                throw new UnauthorizedAccessException(Locale.GetText ("{0} is a directory", path));
 
                        string DirName = Path.GetDirectoryName(path);
                        if (DirName != String.Empty && !Directory.Exists (DirName))
-                               throw new DirectoryNotFoundException (Locale.GetText ("Destination directory not found: {0}", DirName));
+                               throw new DirectoryNotFoundException (Locale.GetText ("Could not find a part of the path \"{0}\".", path));
+
+                       SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
 
                        MonoIOError error;
                        
@@ -181,55 +174,55 @@ namespace System.IO
                        // any problem with the path or permissions.
                        // Minimizes what information can be
                        // discovered by using this method.
-                       if (null == path || String.Empty == path.Trim()
-                           || path.IndexOfAny(Path.InvalidPathChars) >= 0) {
+                       if (String.IsNullOrWhiteSpace (path) || path.IndexOfAny(Path.InvalidPathChars) >= 0)
+                               return false;
+
+                       // on Moonlight this does not throw but returns false
+                       if (!SecurityManager.CheckElevatedPermissions ())
                                return false;
-                       }
 
                        MonoIOError error;
                        return MonoIO.ExistsFile (path, out error);
                }
 
-               public static FileAttributes GetAttributes (string path)
+#if !NET_2_1
+               public static FileSecurity GetAccessControl (string path)
                {
-                       if (null == path) {
-                               throw new ArgumentNullException("path");
-                       }
-                       
-                       if (String.Empty == path.Trim()) {
-                               throw new ArgumentException (Locale.GetText ("Path is empty"));
-                       }
+                       throw new NotImplementedException ();
+               }
+               
+               public static FileSecurity GetAccessControl (string path, AccessControlSections includeSections)
+               {
+                       throw new NotImplementedException ();
+               }
+#endif
 
-                       if (path.IndexOfAny(Path.InvalidPathChars) >= 0) {
-                               throw new ArgumentException(Locale.GetText ("Path contains invalid chars"));
-                       }
+               public static FileAttributes GetAttributes (string path)
+               {
+                       Path.Validate (path);
+                       SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
 
                        MonoIOError error;
                        FileAttributes attrs;
                        
                        attrs = MonoIO.GetFileAttributes (path, out error);
-                       if (error != MonoIOError.ERROR_SUCCESS) {
+                       if (error != MonoIOError.ERROR_SUCCESS)
                                throw MonoIO.GetException (path, error);
-                       }
-
-                       return(attrs);
+                       return attrs;
                }
 
                public static DateTime GetCreationTime (string path)
                {
                        MonoIOStat stat;
                        MonoIOError error;
-                       CheckPathExceptions (path);
+                       Path.Validate (path);
+                       SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
 
                        if (!MonoIO.GetFileStat (path, out stat, out error)) {
-#if NET_2_0
                                if (error == MonoIOError.ERROR_PATH_NOT_FOUND || error == MonoIOError.ERROR_FILE_NOT_FOUND)
-                                       return _defaultLocalFileTime;
+                                       return DefaultLocalFileTime;
                                else
                                        throw new IOException (path);
-#else
-                               throw new IOException (path);
-#endif
                        }
                        return DateTime.FromFileTime (stat.CreationTime);
                }
@@ -243,17 +236,14 @@ namespace System.IO
                {
                        MonoIOStat stat;
                        MonoIOError error;
-                       CheckPathExceptions (path);
+                       Path.Validate (path);
+                       SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
 
                        if (!MonoIO.GetFileStat (path, out stat, out error)) {
-#if NET_2_0
                                if (error == MonoIOError.ERROR_PATH_NOT_FOUND || error == MonoIOError.ERROR_FILE_NOT_FOUND)
-                                       return _defaultLocalFileTime;
+                                       return DefaultLocalFileTime;
                                else
                                        throw new IOException (path);
-#else
-                               throw new IOException (path);
-#endif
                        }
                        return DateTime.FromFileTime (stat.LastAccessTime);
                }
@@ -267,17 +257,14 @@ namespace System.IO
                {
                        MonoIOStat stat;
                        MonoIOError error;
-                       CheckPathExceptions (path);
+                       Path.Validate (path);
+                       SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
 
                        if (!MonoIO.GetFileStat (path, out stat, out error)) {
-#if NET_2_0
                                if (error == MonoIOError.ERROR_PATH_NOT_FOUND || error == MonoIOError.ERROR_FILE_NOT_FOUND)
-                                       return _defaultLocalFileTime;
+                                       return DefaultLocalFileTime;
                                else
                                        throw new IOException (path);
-#else
-                               throw new IOException (path);
-#endif
                        }
                        return DateTime.FromFileTime (stat.LastWriteTime);
                }
@@ -287,50 +274,55 @@ namespace System.IO
                        return GetLastWriteTime (path).ToUniversalTime ();
                }
 
-               public static void Move (string src, string dest)
+               public static void Move (string sourceFileName, string destFileName)
                {
+                       if (sourceFileName == null)
+                               throw new ArgumentNullException ("sourceFileName");
+                       if (destFileName == null)
+                               throw new ArgumentNullException ("destFileName");
+                       if (sourceFileName.Length == 0)
+                               throw new ArgumentException ("An empty file name is not valid.", "sourceFileName");
+                       if (sourceFileName.Trim ().Length == 0 || sourceFileName.IndexOfAny (Path.InvalidPathChars) != -1)
+                               throw new ArgumentException ("The file name is not valid.");
+                       if (destFileName.Length == 0)
+                               throw new ArgumentException ("An empty file name is not valid.", "destFileName");
+                       if (destFileName.Trim ().Length == 0 || destFileName.IndexOfAny (Path.InvalidPathChars) != -1)
+                               throw new ArgumentException ("The file name is not valid.");
+
+                       SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
+
                        MonoIOError error;
+                       if (!MonoIO.Exists (sourceFileName, out error))
+                               throw new FileNotFoundException (Locale.GetText ("{0} does not exist", sourceFileName), sourceFileName);
 
-                       if (src == null)
-                               throw new ArgumentNullException ("src");
-                       if (dest == null)
-                               throw new ArgumentNullException ("dest");
-                       if (src.Trim () == "" || src.IndexOfAny (Path.InvalidPathChars) != -1)
-                               throw new ArgumentException ("src");
-                       if (dest.Trim () == "" || dest.IndexOfAny (Path.InvalidPathChars) != -1)
-                               throw new ArgumentException ("dest");
-                       if (!MonoIO.Exists (src, out error))
-                               throw new FileNotFoundException (Locale.GetText ("{0} does not exist", src), src);
-                       if (MonoIO.ExistsDirectory (dest, out error))
-                                       throw new IOException (Locale.GetText ("{0} is a directory", dest));    
-
-                       // Don't check for this error here to allow the runtime to check if src and dest
-                       // are equal. Comparing src and dest is not enough.
-                       //if (MonoIO.Exists (dest, out error))
-                       //      throw new IOException (Locale.GetText ("{0} already exists", dest));
+                       // Don't check for this error here to allow the runtime
+                       // to check if sourceFileName and destFileName are equal.
+                       // Comparing sourceFileName and destFileName is not enough.
+                       //if (MonoIO.Exists (destFileName, out error))
+                       //      throw new IOException (Locale.GetText ("{0} already exists", destFileName));
 
                        string DirName;
-                       DirName = Path.GetDirectoryName(src);
-                       if (DirName != String.Empty && !Directory.Exists (DirName))
-                               throw new DirectoryNotFoundException(Locale.GetText ("Source directory not found: {0}", DirName));
-                       DirName = Path.GetDirectoryName(dest);
+                       DirName = Path.GetDirectoryName (destFileName);
                        if (DirName != String.Empty && !Directory.Exists (DirName))
-                               throw new DirectoryNotFoundException(Locale.GetText ("Destination directory not found: {0}", DirName));
+                               throw new DirectoryNotFoundException (Locale.GetText ("Could not find a part of the path."));
 
-                       if (!MonoIO.MoveFile (src, dest, out error)) {
+                       if (!MonoIO.MoveFile (sourceFileName, destFileName, out error)) {
                                if (error == MonoIOError.ERROR_ALREADY_EXISTS)
-                                       throw MonoIO.GetException (dest, error);
+                                       throw MonoIO.GetException (error);
+                               else if (error == MonoIOError.ERROR_SHARING_VIOLATION)
+                                       throw MonoIO.GetException (sourceFileName, error);
+                               
                                throw MonoIO.GetException (error);
                        }
                }
                
                public static FileStream Open (string path, FileMode mode)
-               {       
+               {
                        return new FileStream (path, mode, mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite, FileShare.None);
                }
                
                public static FileStream Open (string path, FileMode mode, FileAccess access)
-               {       
+               {
                        return new FileStream (path, mode, access, FileShare.None);
                }
 
@@ -341,7 +333,7 @@ namespace System.IO
                }
                
                public static FileStream OpenRead (string path)
-               {       
+               {
                        return new FileStream (path, FileMode.Open, FileAccess.Read, FileShare.Read);
                }
 
@@ -355,93 +347,130 @@ namespace System.IO
                        return new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
                }
 
+               public static void Replace (string sourceFileName,
+                                           string destinationFileName,
+                                           string destinationBackupFileName)
+               {
+                       Replace (sourceFileName, destinationFileName, destinationBackupFileName, false);
+               }
+               
+               public static void Replace (string sourceFileName,
+                                           string destinationFileName,
+                                           string destinationBackupFileName,
+                                           bool ignoreMetadataErrors)
+               {
+                       MonoIOError error;
+
+                       if (sourceFileName == null)
+                               throw new ArgumentNullException ("sourceFileName");
+                       if (destinationFileName == null)
+                               throw new ArgumentNullException ("destinationFileName");
+                       if (sourceFileName.Trim ().Length == 0 || sourceFileName.IndexOfAny (Path.InvalidPathChars) != -1)
+                               throw new ArgumentException ("sourceFileName");
+                       if (destinationFileName.Trim ().Length == 0 || destinationFileName.IndexOfAny (Path.InvalidPathChars) != -1)
+                               throw new ArgumentException ("destinationFileName");
+
+                       string fullSource = Path.GetFullPath (sourceFileName);
+                       string fullDest = Path.GetFullPath (destinationFileName);
+                       if (MonoIO.ExistsDirectory (fullSource, out error))
+                               throw new IOException (Locale.GetText ("{0} is a directory", sourceFileName));
+                       if (MonoIO.ExistsDirectory (fullDest, out error))
+                               throw new IOException (Locale.GetText ("{0} is a directory", destinationFileName));
+
+                       if (!Exists (fullSource))
+                               throw new FileNotFoundException (Locale.GetText ("{0} does not exist", sourceFileName), 
+                                                                sourceFileName);
+                       if (!Exists (fullDest))
+                               throw new FileNotFoundException (Locale.GetText ("{0} does not exist", destinationFileName), 
+                                                                destinationFileName);
+                       if (fullSource == fullDest) 
+                               throw new IOException (Locale.GetText ("Source and destination arguments are the same file."));
+
+                       string fullBackup = null;
+                       if (destinationBackupFileName != null) {
+                               if (destinationBackupFileName.Trim ().Length == 0 || 
+                                   destinationBackupFileName.IndexOfAny (Path.InvalidPathChars) != -1)
+                                       throw new ArgumentException ("destinationBackupFileName");
+
+                               fullBackup = Path.GetFullPath (destinationBackupFileName);
+                               if (MonoIO.ExistsDirectory (fullBackup, out error))
+                                       throw new IOException (Locale.GetText ("{0} is a directory", destinationBackupFileName));
+                               if (fullSource == fullBackup)
+                                       throw new IOException (Locale.GetText ("Source and backup arguments are the same file."));
+                               if (fullDest == fullBackup)
+                                       throw new IOException (Locale.GetText (
+                                                              "Destination and backup arguments are the same file."));
+                       }
+
+                       if (!MonoIO.ReplaceFile (fullSource, fullDest, fullBackup, 
+                                                ignoreMetadataErrors, out error)) {
+                               throw MonoIO.GetException (error);
+                       }
+               }
+
+#if !NET_2_1
+               public static void SetAccessControl (string path,
+                                                    FileSecurity fileSecurity)
+               {
+                       throw new NotImplementedException ();
+               }
+#endif
+
                public static void SetAttributes (string path,
-                                                 FileAttributes attributes)
+                                                 FileAttributes fileAttributes)
                {
                        MonoIOError error;
-                       CheckPathExceptions (path);
-                       
-                       if (!MonoIO.SetFileAttributes (path, attributes,
-                                                      out error)) {
+                       Path.Validate (path);
+
+                       if (!MonoIO.SetFileAttributes (path, fileAttributes, out error))
                                throw MonoIO.GetException (path, error);
-                       }
                }
 
-               public static void SetCreationTime (string path,
-                                                   DateTime creation_time)
+               public static void SetCreationTime (string path, DateTime creationTime)
                {
                        MonoIOError error;
-                       CheckPathExceptions (path);
+                       Path.Validate (path);
                        if (!MonoIO.Exists (path, out error))
                                throw MonoIO.GetException (path, error);
-                       
-                       if (!MonoIO.SetCreationTime (path, creation_time, out error)) {
+                       if (!MonoIO.SetCreationTime (path, creationTime, out error))
                                throw MonoIO.GetException (path, error);
-                       }
                }
 
-               public static void SetCreationTimeUtc (string path,
-                                                   DateTime creation_time)
+               public static void SetCreationTimeUtc (string path, DateTime creationTimeUtc)
                {
-                       SetCreationTime (path, creation_time.ToLocalTime ());
+                       SetCreationTime (path, creationTimeUtc.ToLocalTime ());
                }
 
-               public static void SetLastAccessTime (string path,DateTime last_access_time)
+               public static void SetLastAccessTime (string path, DateTime lastAccessTime)
                {
                        MonoIOError error;
-                       CheckPathExceptions (path);
+                       Path.Validate (path);
                        if (!MonoIO.Exists (path, out error))
                                throw MonoIO.GetException (path, error);
-
-                       if (!MonoIO.SetLastAccessTime (path, last_access_time, out error)) {
+                       if (!MonoIO.SetLastAccessTime (path, lastAccessTime, out error))
                                throw MonoIO.GetException (path, error);
-                       }
                }
 
-               public static void SetLastAccessTimeUtc (string path,DateTime last_access_time)
+               public static void SetLastAccessTimeUtc (string path, DateTime lastAccessTimeUtc)
                {
-                       SetLastAccessTime (path, last_access_time.ToLocalTime ());
+                       SetLastAccessTime (path, lastAccessTimeUtc.ToLocalTime ());
                }
 
                public static void SetLastWriteTime (string path,
-                                                    DateTime last_write_time)
+                                                    DateTime lastWriteTime)
                {
                        MonoIOError error;
-                       CheckPathExceptions (path);
+                       Path.Validate (path);
                        if (!MonoIO.Exists (path, out error))
                                throw MonoIO.GetException (path, error);
-
-                       if (!MonoIO.SetLastWriteTime (path, last_write_time, out error)) {
+                       if (!MonoIO.SetLastWriteTime (path, lastWriteTime, out error))
                                throw MonoIO.GetException (path, error);
-                       }
                }
 
                public static void SetLastWriteTimeUtc (string path,
-                                                    DateTime last_write_time)
-               {
-                       SetLastWriteTime (path, last_write_time.ToLocalTime ());
-               }
-
-               #region Private
-
-               private static void CheckPathExceptions (string path)
+                                                    DateTime lastWriteTimeUtc)
                {
-                       if (path == null)
-                               throw new System.ArgumentNullException("path");
-                       if (path == "")
-                               throw new System.ArgumentException(Locale.GetText ("Path is empty"));
-                       if (path.Trim().Length == 0)
-                               throw new ArgumentException (Locale.GetText ("Path is empty"));
-                       if (path.IndexOfAny (Path.InvalidPathChars) != -1)
-                               throw new ArgumentException (Locale.GetText ("Path contains invalid chars"));
-               }
-
-               #endregion
-
-#if NET_2_0
-               static File() {
-                       _defaultLocalFileTime = new DateTime (1601, 1, 1);
-                       _defaultLocalFileTime = _defaultLocalFileTime.ToLocalTime ();
+                       SetLastWriteTime (path, lastWriteTimeUtc.ToLocalTime ());
                }
 
                //
@@ -454,19 +483,22 @@ namespace System.IO
                //
                public static byte [] ReadAllBytes (string path)
                {
-                       using (FileStream s = Open (path, FileMode.Open, FileAccess.Read, FileShare.Read)){
+                       using (FileStream s = OpenRead (path)) {
                                long size = s.Length;
-
-                               //
-                               // Is this worth supporting?
-                               // 
+                               // limited to 2GB according to http://msdn.microsoft.com/en-us/library/system.io.file.readallbytes.aspx
                                if (size > Int32.MaxValue)
-                                       throw new ArgumentException ("Reading more than 4gigs with this call is not supported");
-                               
-                               byte [] result = new byte [s.Length];
-
-                               s.Read (result, 0, (int) size);
-
+                                       throw new IOException ("Reading more than 2GB with this call is not supported");
+
+                               int pos = 0;
+                               int count = (int) size;
+                               byte [] result = new byte [size];
+                               while (count > 0) {
+                                       int n = s.Read (result, pos, count);
+                                       if (n == 0)
+                                               throw new IOException ("Unexpected end of stream");
+                                       pos += n;
+                                       count -= n;
+                               }
                                return result;
                        }
                }
@@ -495,40 +527,42 @@ namespace System.IO
 
                public static string ReadAllText (string path)
                {
-                       return ReadAllText (path, Encoding.UTF8Unmarked);
+                       using (StreamReader sr = new StreamReader (path)) {
+                               return sr.ReadToEnd ();
+                       }
                }
 
-               public static string ReadAllText (string path, Encoding enc)
+               public static string ReadAllText (string path, Encoding encoding)
                {
-                       using (StreamReader sr = new StreamReader (path, enc)) {
+                       using (StreamReader sr = new StreamReader (path, encoding)) {
                                return sr.ReadToEnd ();
                        }
                }
 
-               public static void WriteAllBytes (string path, byte [] data)
+               public static void WriteAllBytes (string path, byte [] bytes)
                {
                        using (Stream stream = File.Create (path)) {
-                               stream.Write (data, 0, data.Length);
+                               stream.Write (bytes, 0, bytes.Length);
                        }
                }
 
-               public static void WriteAllLines (string path, string [] lines)
+               public static void WriteAllLines (string path, string [] contents)
                {
                        using (StreamWriter writer = new StreamWriter (path)) {
-                               WriteAllLines (writer, lines);
+                               WriteAllLines (writer, contents);
                        }
                }
 
-               public static void WriteAllLines (string path, string [] lines, Encoding encoding)
+               public static void WriteAllLines (string path, string [] contents, Encoding encoding)
                {
                        using (StreamWriter writer = new StreamWriter (path, false, encoding)) {
-                               WriteAllLines (writer, lines);
+                               WriteAllLines (writer, contents);
                        }
                }
 
-               static void WriteAllLines (StreamWriter writer, string [] lines)
+               static void WriteAllLines (StreamWriter writer, string [] contents)
                {
-                       foreach (string line in lines)
+                       foreach (string line in contents)
                                writer.WriteLine (line);
                }
 
@@ -537,14 +571,23 @@ namespace System.IO
                        WriteAllText (path, contents, Encoding.UTF8Unmarked);
                }
 
-               public static void WriteAllText (string path, string contents, Encoding enc)
+               public static void WriteAllText (string path, string contents, Encoding encoding)
                {
-                       using (StreamWriter sw = new StreamWriter (path, false, enc)) {
+                       using (StreamWriter sw = new StreamWriter (path, false, encoding)) {
                                sw.Write (contents);
                        }
                }
 
-               private static readonly DateTime _defaultLocalFileTime;
+               static DateTime? defaultLocalFileTime;
+               static DateTime DefaultLocalFileTime {
+                       get {
+                               if (defaultLocalFileTime == null)
+                                       defaultLocalFileTime = new DateTime (1601, 1, 1).ToLocalTime ();
+                                       
+                               return defaultLocalFileTime.Value;
+                       }
+               }
+
 
                [MonoLimitation ("File encryption isn't supported (even on NTFS).")]
                public static void Encrypt (string path)
@@ -565,6 +608,81 @@ namespace System.IO
                        // handling this exception to work properly.
                        throw new NotSupportedException (Locale.GetText ("File encryption isn't supported on any file system."));
                }
+
+#if MOONLIGHT || NET_4_0
+               public static IEnumerable<string> ReadLines (string path)
+               {
+                       using (StreamReader reader = File.OpenText (path)) {
+                               return ReadLines (reader);
+                       }
+               }
+
+               public static IEnumerable<string> ReadLines (string path, Encoding encoding)
+               {
+                       using (StreamReader reader = new StreamReader (path, encoding)) {
+                               return ReadLines (reader);
+                       }
+               }
+
+               // refactored in order to avoid compiler-generated names for Moonlight tools
+               static IEnumerable<string> ReadLines (StreamReader reader)
+               {
+                       string s;
+                       while ((s = reader.ReadLine ()) != null)
+                               yield return s;
+               }
+
+               public static void AppendAllLines (string path, IEnumerable<string> contents)
+               {
+                       Path.Validate (path);
+
+                       if (contents == null)
+                               return;
+
+                       using (TextWriter w = new StreamWriter (path, true)) {
+                               foreach (var line in contents)
+                                       w.Write (line);
+                       }
+               }
+
+               public static void AppendAllLines (string path, IEnumerable<string> contents, Encoding encoding)
+               {
+                       Path.Validate (path);
+
+                       if (contents == null)
+                               return;
+
+                       using (TextWriter w = new StreamWriter (path, true, encoding)) {
+                               foreach (var line in contents)
+                                       w.Write (line);
+                       }
+               }
+
+               public static void WriteAllLines (string path, IEnumerable<string> contents)
+               {
+                       Path.Validate (path);
+
+                       if (contents == null)
+                               return;
+
+                       using (TextWriter w = new StreamWriter (path, false)) {
+                               foreach (var line in contents)
+                                       w.Write (line);
+                       }
+               }
+
+               public static void WriteAllLines (string path, IEnumerable<string> contents, Encoding encoding)
+               {
+                       Path.Validate (path);
+
+                       if (contents == null)
+                               return;
+
+                       using (TextWriter w = new StreamWriter (path, false, encoding)) {
+                               foreach (var line in contents)
+                                       w.Write (line);
+                       }
+               }
 #endif
        }
 }