92389257c5c788f84d7050c696d81075ff9109ee
[mono.git] / mcs / class / corlib / System.IO / File.cs
1 // 
2 // System.IO.File.cs 
3 //
4 // 
5 // Authors:
6 //   Miguel de Icaza (miguel@ximian.com)
7 //   Jim Richardson  (develop@wtfo-guru.com)
8 //   Dan Lewis       (dihlewis@yahoo.co.uk)
9 //   Ville Palo      (vi64pa@kolumbus.fi)
10 //
11 // Copyright 2002 Ximian, Inc. http://www.ximian.com
12 // Copyright (C) 2001 Moonlight Enterprises, All Rights Reserved
13 // Copyright (C) 2004, 2006, 2010 Novell, Inc (http://www.novell.com)
14 //
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
22 // 
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
25 // 
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 //
34
35 using System;
36 using System.Collections.Generic;
37 using System.Diagnostics;
38 using System.Security;
39 using System.Text;
40 using System.Runtime.InteropServices;
41
42 #if !NET_2_1
43 using System.Security.AccessControl;
44 #endif
45
46 namespace System.IO
47 {
48         [ComVisible (true)]
49         public static class File
50         {
51                 public static void AppendAllText (string path, string contents)
52                 {
53                         using (TextWriter w = new StreamWriter (path, true)) {
54                                 w.Write (contents);
55                         }
56                 }
57
58                 public static void AppendAllText (string path, string contents, Encoding encoding)
59                 {
60                         using (TextWriter w = new StreamWriter (path, true, encoding)) {
61                                 w.Write (contents);
62                         }
63                 }
64
65                 public static StreamWriter AppendText (string path)
66                 {
67                         return new StreamWriter (path, true);
68                 }
69
70                 public static void Copy (string sourceFileName, string destFileName)
71                 {
72                         Copy (sourceFileName, destFileName, false);
73                 }
74
75                 public static void Copy (string sourceFileName, string destFileName, bool overwrite)
76                 {
77                         MonoIOError error;
78
79                         if (sourceFileName == null)
80                                 throw new ArgumentNullException ("sourceFileName");
81                         if (destFileName == null)
82                                 throw new ArgumentNullException ("destFileName");
83                         if (sourceFileName.Length == 0)
84                                 throw new ArgumentException ("An empty file name is not valid.", "sourceFileName");
85                         if (sourceFileName.Trim ().Length == 0 || sourceFileName.IndexOfAny (Path.InvalidPathChars) != -1)
86                                 throw new ArgumentException ("The file name is not valid.");
87                         if (destFileName.Length == 0)
88                                 throw new ArgumentException ("An empty file name is not valid.", "destFileName");
89                         if (destFileName.Trim ().Length == 0 || destFileName.IndexOfAny (Path.InvalidPathChars) != -1)
90                                 throw new ArgumentException ("The file name is not valid.");
91
92                         SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
93
94                         if (!MonoIO.Exists (sourceFileName, out error))
95                                 throw new FileNotFoundException (Locale.GetText ("{0} does not exist", sourceFileName), sourceFileName);
96                         if ((GetAttributes (sourceFileName) & FileAttributes.Directory) == FileAttributes.Directory)
97                                 throw new ArgumentException (Locale.GetText ("{0} is a directory", sourceFileName));
98
99                         if (MonoIO.Exists (destFileName, out error)) {
100                                 if ((GetAttributes (destFileName) & FileAttributes.Directory) == FileAttributes.Directory)
101                                         throw new ArgumentException (Locale.GetText ("{0} is a directory", destFileName));
102                                 if (!overwrite)
103                                         throw new IOException (Locale.GetText ("{0} already exists", destFileName));
104                         }
105
106                         string DirName = Path.GetDirectoryName (destFileName);
107                         if (DirName != String.Empty && !Directory.Exists (DirName))
108                                 throw new DirectoryNotFoundException (Locale.GetText ("Destination directory not found: {0}",DirName));
109
110                         if (!MonoIO.CopyFile (sourceFileName, destFileName, overwrite, out error)) {
111                                 string p = Locale.GetText ("{0}\" or \"{1}", sourceFileName, destFileName);
112                                 throw MonoIO.GetException (p, error);
113                         }
114                 }
115
116                 internal static String InternalCopy (String sourceFileName, String destFileName, bool overwrite, bool checkHost)
117                 {
118                         String fullSourceFileName = Path.GetFullPathInternal(sourceFileName);
119                         String fullDestFileName = Path.GetFullPathInternal(destFileName);
120
121                         MonoIOError error;
122
123                         if (!MonoIO.CopyFile (fullSourceFileName, fullDestFileName, overwrite, out error)) {
124                                 string p = Locale.GetText ("{0}\" or \"{1}", sourceFileName, destFileName);
125                                 throw MonoIO.GetException (p, error);
126                         }
127
128                         return fullDestFileName;
129                 }
130
131                 public static FileStream Create (string path)
132                 {
133                         return Create (path, 8192);
134                 }
135
136                 public static FileStream Create (string path, int bufferSize)
137                 {
138                         return new FileStream (path, FileMode.Create, FileAccess.ReadWrite,
139                                 FileShare.None, bufferSize);
140                 }
141
142                 [MonoLimitation ("FileOptions are ignored")]
143                 public static FileStream Create (string path, int bufferSize,
144                                                  FileOptions options)
145                 {
146                         return new FileStream (path, FileMode.Create, FileAccess.ReadWrite,
147                                 FileShare.None, bufferSize, options);
148                 }
149
150 #if !NET_2_1
151                 [MonoLimitation ("FileOptions and FileSecurity are ignored")]
152                 public static FileStream Create (string path, int bufferSize,
153                                                  FileOptions options,
154                                                  FileSecurity fileSecurity)
155                 {
156                         return new FileStream (path, FileMode.Create, FileAccess.ReadWrite,
157                                 FileShare.None, bufferSize, options);
158                 }
159 #endif
160
161                 public static StreamWriter CreateText (string path)
162                 {
163                         return new StreamWriter (path, false);
164                 }
165
166                 public static void Delete (string path)
167                 {
168                         Path.Validate (path);
169                         if (Directory.Exists (path))
170                                 throw new UnauthorizedAccessException(Locale.GetText ("{0} is a directory", path));
171
172                         string DirName = Path.GetDirectoryName(path);
173                         if (DirName != String.Empty && !Directory.Exists (DirName))
174                                 throw new DirectoryNotFoundException (Locale.GetText ("Could not find a part of the path \"{0}\".", path));
175
176                         SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
177
178                         MonoIOError error;
179                         
180                         if (!MonoIO.DeleteFile (path, out error)){
181                                 if (error != MonoIOError.ERROR_FILE_NOT_FOUND)
182                                         throw MonoIO.GetException (path, error);
183                         }
184                 }
185
186                 public static bool Exists (string path)
187                 {
188                         // For security reasons no exceptions are
189                         // thrown, only false is returned if there is
190                         // any problem with the path or permissions.
191                         // Minimizes what information can be
192                         // discovered by using this method.
193                         if (String.IsNullOrWhiteSpace (path) || path.IndexOfAny(Path.InvalidPathChars) >= 0)
194                                 return false;
195
196                         // on Moonlight this does not throw but returns false
197                         if (!SecurityManager.CheckElevatedPermissions ())
198                                 return false;
199
200                         MonoIOError error;
201                         return MonoIO.ExistsFile (path, out error);
202                 }
203
204 #if !NET_2_1
205                 public static FileSecurity GetAccessControl (string path)
206                 {
207                         // AccessControlSections.Audit requires special permissions.
208                         return GetAccessControl (path,
209                                                  AccessControlSections.Owner |
210                                                  AccessControlSections.Group |
211                                                  AccessControlSections.Access);
212                 }
213                 
214                 public static FileSecurity GetAccessControl (string path, AccessControlSections includeSections)
215                 {
216                         return new FileSecurity (path, includeSections);
217                 }
218 #endif
219
220                 public static FileAttributes GetAttributes (string path)
221                 {
222                         Path.Validate (path);
223                         SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
224
225                         MonoIOError error;
226                         FileAttributes attrs;
227                         
228                         attrs = MonoIO.GetFileAttributes (path, out error);
229                         if (error != MonoIOError.ERROR_SUCCESS)
230                                 throw MonoIO.GetException (path, error);
231                         return attrs;
232                 }
233
234                 public static DateTime GetCreationTime (string path)
235                 {
236                         MonoIOStat stat;
237                         MonoIOError error;
238                         Path.Validate (path);
239                         SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
240
241                         if (!MonoIO.GetFileStat (path, out stat, out error)) {
242                                 if (error == MonoIOError.ERROR_PATH_NOT_FOUND || error == MonoIOError.ERROR_FILE_NOT_FOUND)
243                                         return DefaultLocalFileTime;
244                                 else
245                                         throw new IOException (path);
246                         }
247                         return DateTime.FromFileTime (stat.CreationTime);
248                 }
249
250                 public static DateTime GetCreationTimeUtc (string path)
251                 {
252                         return GetCreationTime (path).ToUniversalTime ();
253                 }
254
255                 public static DateTime GetLastAccessTime (string path)
256                 {
257                         MonoIOStat stat;
258                         MonoIOError error;
259                         Path.Validate (path);
260                         SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
261
262                         if (!MonoIO.GetFileStat (path, out stat, out error)) {
263                                 if (error == MonoIOError.ERROR_PATH_NOT_FOUND || error == MonoIOError.ERROR_FILE_NOT_FOUND)
264                                         return DefaultLocalFileTime;
265                                 else
266                                         throw new IOException (path);
267                         }
268                         return DateTime.FromFileTime (stat.LastAccessTime);
269                 }
270
271                 public static DateTime GetLastAccessTimeUtc (string path)
272                 {
273                         return GetLastAccessTime (path).ToUniversalTime ();
274                 }
275
276                 public static DateTime GetLastWriteTime (string path)
277                 {
278                         MonoIOStat stat;
279                         MonoIOError error;
280                         Path.Validate (path);
281                         SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
282
283                         if (!MonoIO.GetFileStat (path, out stat, out error)) {
284                                 if (error == MonoIOError.ERROR_PATH_NOT_FOUND || error == MonoIOError.ERROR_FILE_NOT_FOUND)
285                                         return DefaultLocalFileTime;
286                                 else
287                                         throw new IOException (path);
288                         }
289                         return DateTime.FromFileTime (stat.LastWriteTime);
290                 }
291
292                 public static DateTime GetLastWriteTimeUtc (string path)
293                 {
294                         return GetLastWriteTime (path).ToUniversalTime ();
295                 }
296
297                 public static void Move (string sourceFileName, string destFileName)
298                 {
299                         if (sourceFileName == null)
300                                 throw new ArgumentNullException ("sourceFileName");
301                         if (destFileName == null)
302                                 throw new ArgumentNullException ("destFileName");
303                         if (sourceFileName.Length == 0)
304                                 throw new ArgumentException ("An empty file name is not valid.", "sourceFileName");
305                         if (sourceFileName.Trim ().Length == 0 || sourceFileName.IndexOfAny (Path.InvalidPathChars) != -1)
306                                 throw new ArgumentException ("The file name is not valid.");
307                         if (destFileName.Length == 0)
308                                 throw new ArgumentException ("An empty file name is not valid.", "destFileName");
309                         if (destFileName.Trim ().Length == 0 || destFileName.IndexOfAny (Path.InvalidPathChars) != -1)
310                                 throw new ArgumentException ("The file name is not valid.");
311
312                         SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
313
314                         MonoIOError error;
315                         if (!MonoIO.Exists (sourceFileName, out error))
316                                 throw new FileNotFoundException (Locale.GetText ("{0} does not exist", sourceFileName), sourceFileName);
317
318                         // Don't check for this error here to allow the runtime
319                         // to check if sourceFileName and destFileName are equal.
320                         // Comparing sourceFileName and destFileName is not enough.
321                         //if (MonoIO.Exists (destFileName, out error))
322                         //      throw new IOException (Locale.GetText ("{0} already exists", destFileName));
323
324                         string DirName;
325                         DirName = Path.GetDirectoryName (destFileName);
326                         if (DirName != String.Empty && !Directory.Exists (DirName))
327                                 throw new DirectoryNotFoundException (Locale.GetText ("Could not find a part of the path."));
328
329                         if (!MonoIO.MoveFile (sourceFileName, destFileName, out error)) {
330                                 if (error == MonoIOError.ERROR_ALREADY_EXISTS)
331                                         throw MonoIO.GetException (error);
332                                 else if (error == MonoIOError.ERROR_SHARING_VIOLATION)
333                                         throw MonoIO.GetException (sourceFileName, error);
334                                 
335                                 throw MonoIO.GetException (error);
336                         }
337                 }
338                 
339                 public static FileStream Open (string path, FileMode mode)
340                 {
341                         return new FileStream (path, mode, mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite, FileShare.None);
342                 }
343                 
344                 public static FileStream Open (string path, FileMode mode, FileAccess access)
345                 {
346                         return new FileStream (path, mode, access, FileShare.None);
347                 }
348
349                 public static FileStream Open (string path, FileMode mode, FileAccess access,
350                                                FileShare share)
351                 {
352                         return new FileStream (path, mode, access, share);
353                 }
354                 
355                 public static FileStream OpenRead (string path)
356                 {
357                         return new FileStream (path, FileMode.Open, FileAccess.Read, FileShare.Read);
358                 }
359
360                 public static StreamReader OpenText (string path)
361                 {
362                         return new StreamReader (path);
363                 }
364
365                 public static FileStream OpenWrite (string path)
366                 {
367                         return new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
368                 }
369
370                 public static void Replace (string sourceFileName,
371                                             string destinationFileName,
372                                             string destinationBackupFileName)
373                 {
374                         Replace (sourceFileName, destinationFileName, destinationBackupFileName, false);
375                 }
376                 
377                 public static void Replace (string sourceFileName,
378                                             string destinationFileName,
379                                             string destinationBackupFileName,
380                                             bool ignoreMetadataErrors)
381                 {
382                         MonoIOError error;
383
384                         if (sourceFileName == null)
385                                 throw new ArgumentNullException ("sourceFileName");
386                         if (destinationFileName == null)
387                                 throw new ArgumentNullException ("destinationFileName");
388                         if (sourceFileName.Trim ().Length == 0 || sourceFileName.IndexOfAny (Path.InvalidPathChars) != -1)
389                                 throw new ArgumentException ("sourceFileName");
390                         if (destinationFileName.Trim ().Length == 0 || destinationFileName.IndexOfAny (Path.InvalidPathChars) != -1)
391                                 throw new ArgumentException ("destinationFileName");
392
393                         string fullSource = Path.GetFullPath (sourceFileName);
394                         string fullDest = Path.GetFullPath (destinationFileName);
395                         if (MonoIO.ExistsDirectory (fullSource, out error))
396                                 throw new IOException (Locale.GetText ("{0} is a directory", sourceFileName));
397                         if (MonoIO.ExistsDirectory (fullDest, out error))
398                                 throw new IOException (Locale.GetText ("{0} is a directory", destinationFileName));
399
400                         if (!Exists (fullSource))
401                                 throw new FileNotFoundException (Locale.GetText ("{0} does not exist", sourceFileName), 
402                                                                  sourceFileName);
403                         if (!Exists (fullDest))
404                                 throw new FileNotFoundException (Locale.GetText ("{0} does not exist", destinationFileName), 
405                                                                  destinationFileName);
406                         if (fullSource == fullDest) 
407                                 throw new IOException (Locale.GetText ("Source and destination arguments are the same file."));
408
409                         string fullBackup = null;
410                         if (destinationBackupFileName != null) {
411                                 if (destinationBackupFileName.Trim ().Length == 0 || 
412                                     destinationBackupFileName.IndexOfAny (Path.InvalidPathChars) != -1)
413                                         throw new ArgumentException ("destinationBackupFileName");
414
415                                 fullBackup = Path.GetFullPath (destinationBackupFileName);
416                                 if (MonoIO.ExistsDirectory (fullBackup, out error))
417                                         throw new IOException (Locale.GetText ("{0} is a directory", destinationBackupFileName));
418                                 if (fullSource == fullBackup)
419                                         throw new IOException (Locale.GetText ("Source and backup arguments are the same file."));
420                                 if (fullDest == fullBackup)
421                                         throw new IOException (Locale.GetText (
422                                                                "Destination and backup arguments are the same file."));
423                         }
424
425                         var attrs = GetAttributes (fullDest);
426
427                         // TODO: Should be done in wapi, win32 api handles this already
428                         if ((attrs & FileAttributes.ReadOnly) != 0)
429                                 throw MonoIO.GetException (MonoIOError.ERROR_ACCESS_DENIED);
430
431                         if (!MonoIO.ReplaceFile (fullSource, fullDest, fullBackup, 
432                                                  ignoreMetadataErrors, out error)) {
433                                 throw MonoIO.GetException (error);
434                         }
435                 }
436
437 #if !NET_2_1
438                 public static void SetAccessControl (string path,
439                                                      FileSecurity fileSecurity)
440                 {
441                         if (null == fileSecurity)
442                                 throw new ArgumentNullException ("fileSecurity");
443
444                         fileSecurity.PersistModifications (path);
445                 }
446 #endif
447
448                 public static void SetAttributes (string path,
449                                                   FileAttributes fileAttributes)
450                 {
451                         MonoIOError error;
452                         Path.Validate (path);
453
454                         if (!MonoIO.SetFileAttributes (path, fileAttributes, out error))
455                                 throw MonoIO.GetException (path, error);
456                 }
457
458                 public static void SetCreationTime (string path, DateTime creationTime)
459                 {
460                         MonoIOError error;
461                         Path.Validate (path);
462                         if (!MonoIO.Exists (path, out error))
463                                 throw MonoIO.GetException (path, error);
464                         if (!MonoIO.SetCreationTime (path, creationTime, out error))
465                                 throw MonoIO.GetException (path, error);
466                 }
467
468                 public static void SetCreationTimeUtc (string path, DateTime creationTimeUtc)
469                 {
470                         SetCreationTime (path, creationTimeUtc.ToLocalTime ());
471                 }
472
473                 public static void SetLastAccessTime (string path, DateTime lastAccessTime)
474                 {
475                         MonoIOError error;
476                         Path.Validate (path);
477                         if (!MonoIO.Exists (path, out error))
478                                 throw MonoIO.GetException (path, error);
479                         if (!MonoIO.SetLastAccessTime (path, lastAccessTime, out error))
480                                 throw MonoIO.GetException (path, error);
481                 }
482
483                 public static void SetLastAccessTimeUtc (string path, DateTime lastAccessTimeUtc)
484                 {
485                         SetLastAccessTime (path, lastAccessTimeUtc.ToLocalTime ());
486                 }
487
488                 public static void SetLastWriteTime (string path,
489                                                      DateTime lastWriteTime)
490                 {
491                         MonoIOError error;
492                         Path.Validate (path);
493                         if (!MonoIO.Exists (path, out error))
494                                 throw MonoIO.GetException (path, error);
495                         if (!MonoIO.SetLastWriteTime (path, lastWriteTime, out error))
496                                 throw MonoIO.GetException (path, error);
497                 }
498
499                 public static void SetLastWriteTimeUtc (string path,
500                                                      DateTime lastWriteTimeUtc)
501                 {
502                         SetLastWriteTime (path, lastWriteTimeUtc.ToLocalTime ());
503                 }
504
505                 //
506                 // The documentation for this method is most likely wrong, it
507                 // talks about doing a "binary read", but the remarks say
508                 // that this "detects the encoding".
509                 //
510                 // This can not detect and do anything useful with the encoding
511                 // since the result is a byte [] not a char [].
512                 //
513                 public static byte [] ReadAllBytes (string path)
514                 {
515                         using (FileStream s = OpenRead (path)) {
516                                 long size = s.Length;
517                                 // limited to 2GB according to http://msdn.microsoft.com/en-us/library/system.io.file.readallbytes.aspx
518                                 if (size > Int32.MaxValue)
519                                         throw new IOException ("Reading more than 2GB with this call is not supported");
520
521                                 int pos = 0;
522                                 int count = (int) size;
523                                 byte [] result = new byte [size];
524                                 while (count > 0) {
525                                         int n = s.Read (result, pos, count);
526                                         if (n == 0)
527                                                 throw new IOException ("Unexpected end of stream");
528                                         pos += n;
529                                         count -= n;
530                                 }
531                                 return result;
532                         }
533                 }
534
535                 public static string [] ReadAllLines (string path)
536                 {
537                         using (StreamReader reader = File.OpenText (path)) {
538                                 return ReadAllLines (reader);
539                         }
540                 }
541
542                 public static string [] ReadAllLines (string path, Encoding encoding)
543                 {
544                         using (StreamReader reader = new StreamReader (path, encoding)) {
545                                 return ReadAllLines (reader);
546                         }
547                 }
548
549                 static string [] ReadAllLines (StreamReader reader)
550                 {
551                         List<string> list = new List<string> ();
552                         while (!reader.EndOfStream)
553                                 list.Add (reader.ReadLine ());
554                         return list.ToArray ();
555                 }
556
557                 public static string ReadAllText (string path)
558                 {
559                         using (StreamReader sr = new StreamReader (path)) {
560                                 return sr.ReadToEnd ();
561                         }
562                 }
563
564                 public static string ReadAllText (string path, Encoding encoding)
565                 {
566                         using (StreamReader sr = new StreamReader (path, encoding)) {
567                                 return sr.ReadToEnd ();
568                         }
569                 }
570
571                 public static void WriteAllBytes (string path, byte [] bytes)
572                 {
573                         using (Stream stream = File.Create (path)) {
574                                 stream.Write (bytes, 0, bytes.Length);
575                         }
576                 }
577
578                 public static void WriteAllLines (string path, string [] contents)
579                 {
580                         using (StreamWriter writer = new StreamWriter (path)) {
581                                 WriteAllLines (writer, contents);
582                         }
583                 }
584
585                 public static void WriteAllLines (string path, string [] contents, Encoding encoding)
586                 {
587                         using (StreamWriter writer = new StreamWriter (path, false, encoding)) {
588                                 WriteAllLines (writer, contents);
589                         }
590                 }
591
592                 static void WriteAllLines (StreamWriter writer, string [] contents)
593                 {
594                         foreach (string line in contents)
595                                 writer.WriteLine (line);
596                 }
597
598                 public static void WriteAllText (string path, string contents)
599                 {
600                         WriteAllText (path, contents, EncodingHelper.UTF8Unmarked);
601                 }
602
603                 public static void WriteAllText (string path, string contents, Encoding encoding)
604                 {
605                         using (StreamWriter sw = new StreamWriter (path, false, encoding)) {
606                                 sw.Write (contents);
607                         }
608                 }
609
610                 static DateTime? defaultLocalFileTime;
611                 static DateTime DefaultLocalFileTime {
612                         get {
613                                 if (defaultLocalFileTime == null)
614                                         defaultLocalFileTime = new DateTime (1601, 1, 1).ToLocalTime ();
615                                         
616                                 return defaultLocalFileTime.Value;
617                         }
618                 }
619
620
621                 [MonoLimitation ("File encryption isn't supported (even on NTFS).")]
622                 public static void Encrypt (string path)
623                 {
624                         // MS.NET support this only on NTFS file systems, i.e. it's a file-system (not a framework) feature.
625                         // otherwise it throws a NotSupportedException (or a PlatformNotSupportedException on older OS).
626                         // we throw the same (instead of a NotImplementedException) because most code should already be
627                         // handling this exception to work properly.
628                         throw new NotSupportedException (Locale.GetText ("File encryption isn't supported on any file system."));
629                 }
630
631                 [MonoLimitation ("File encryption isn't supported (even on NTFS).")]
632                 public static void Decrypt (string path)
633                 {
634                         // MS.NET support this only on NTFS file systems, i.e. it's a file-system (not a framework) feature.
635                         // otherwise it throws a NotSupportedException (or a PlatformNotSupportedException on older OS).
636                         // we throw the same (instead of a NotImplementedException) because most code should already be
637                         // handling this exception to work properly.
638                         throw new NotSupportedException (Locale.GetText ("File encryption isn't supported on any file system."));
639                 }
640
641                 public static IEnumerable<string> ReadLines (string path)
642                 {
643                         return ReadLines (File.OpenText (path));
644                 }
645
646                 public static IEnumerable<string> ReadLines (string path, Encoding encoding)
647                 {
648                         return ReadLines (new StreamReader (path, encoding));
649                 }
650
651                 // refactored in order to avoid compiler-generated names for Moonlight tools
652                 static IEnumerable<string> ReadLines (StreamReader reader)
653                 {
654                         using (reader) {
655                                 string s;
656                                 while ((s = reader.ReadLine ()) != null) {
657                                         yield return s;
658                                 }
659                         }
660                 }
661
662                 public static void AppendAllLines (string path, IEnumerable<string> contents)
663                 {
664                         Path.Validate (path);
665
666                         if (contents == null)
667                                 return;
668
669                         using (TextWriter w = new StreamWriter (path, true)) {
670                                 foreach (var line in contents)
671                                         w.WriteLine (line);
672                         }
673                 }
674
675                 public static void AppendAllLines (string path, IEnumerable<string> contents, Encoding encoding)
676                 {
677                         Path.Validate (path);
678
679                         if (contents == null)
680                                 return;
681
682                         using (TextWriter w = new StreamWriter (path, true, encoding)) {
683                                 foreach (var line in contents)
684                                         w.WriteLine (line);
685                         }
686                 }
687
688                 public static void WriteAllLines (string path, IEnumerable<string> contents)
689                 {
690                         Path.Validate (path);
691
692                         if (contents == null)
693                                 return;
694
695                         using (TextWriter w = new StreamWriter (path, false)) {
696                                 foreach (var line in contents)
697                                         w.WriteLine (line);
698                         }
699                 }
700
701                 public static void WriteAllLines (string path, IEnumerable<string> contents, Encoding encoding)
702                 {
703                         Path.Validate (path);
704
705                         if (contents == null)
706                                 return;
707
708                         using (TextWriter w = new StreamWriter (path, false, encoding)) {
709                                 foreach (var line in contents)
710                                         w.WriteLine (line);
711                         }
712                 }
713
714                 internal static int FillAttributeInfo (String path, ref MonoIOStat data, bool tryagain, bool returnErrorOnNotFound)
715                 {
716                         if (tryagain)
717                                 throw new NotImplementedException ();
718
719                         MonoIOError error;
720                         MonoIO.GetFileStat (path, out data, out error);
721
722                         if (!returnErrorOnNotFound && (error == MonoIOError.ERROR_FILE_NOT_FOUND || error == MonoIOError.ERROR_PATH_NOT_FOUND || error == MonoIOError.ERROR_NOT_READY)) {
723                                 data = default (MonoIOStat);
724                                 data.fileAttributes = (FileAttributes) (-1);
725                                 return 0;
726                         }
727
728                         return (int) error;
729                 }
730         }
731 }