Moving BSTR conv to native code in SecureStringToBSTR.
[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 #if !NET_2_1
143                 [MonoLimitation ("FileOptions are ignored")]
144                 public static FileStream Create (string path, int bufferSize,
145                                                  FileOptions options)
146                 {
147                         return Create (path, bufferSize, options, null);
148                 }
149                 
150                 [MonoLimitation ("FileOptions and FileSecurity are ignored")]
151                 public static FileStream Create (string path, int bufferSize,
152                                                  FileOptions options,
153                                                  FileSecurity fileSecurity)
154                 {
155                         return new FileStream (path, FileMode.Create, FileAccess.ReadWrite,
156                                 FileShare.None, bufferSize, options);
157                 }
158 #endif
159
160                 public static StreamWriter CreateText (string path)
161                 {
162                         return new StreamWriter (path, false);
163                 }
164
165                 public static void Delete (string path)
166                 {
167                         Path.Validate (path);
168                         if (Directory.Exists (path))
169                                 throw new UnauthorizedAccessException(Locale.GetText ("{0} is a directory", path));
170
171                         string DirName = Path.GetDirectoryName(path);
172                         if (DirName != String.Empty && !Directory.Exists (DirName))
173                                 throw new DirectoryNotFoundException (Locale.GetText ("Could not find a part of the path \"{0}\".", path));
174
175                         SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
176
177                         MonoIOError error;
178                         
179                         if (!MonoIO.DeleteFile (path, out error)){
180                                 if (error != MonoIOError.ERROR_FILE_NOT_FOUND)
181                                         throw MonoIO.GetException (path, error);
182                         }
183                 }
184
185                 public static bool Exists (string path)
186                 {
187                         // For security reasons no exceptions are
188                         // thrown, only false is returned if there is
189                         // any problem with the path or permissions.
190                         // Minimizes what information can be
191                         // discovered by using this method.
192                         if (String.IsNullOrWhiteSpace (path) || path.IndexOfAny(Path.InvalidPathChars) >= 0)
193                                 return false;
194
195                         // on Moonlight this does not throw but returns false
196                         if (!SecurityManager.CheckElevatedPermissions ())
197                                 return false;
198
199                         MonoIOError error;
200                         return MonoIO.ExistsFile (path, out error);
201                 }
202
203 #if !NET_2_1
204                 public static FileSecurity GetAccessControl (string path)
205                 {
206                         // AccessControlSections.Audit requires special permissions.
207                         return GetAccessControl (path,
208                                                  AccessControlSections.Owner |
209                                                  AccessControlSections.Group |
210                                                  AccessControlSections.Access);
211                 }
212                 
213                 public static FileSecurity GetAccessControl (string path, AccessControlSections includeSections)
214                 {
215                         return new FileSecurity (path, includeSections);
216                 }
217 #endif
218
219                 public static FileAttributes GetAttributes (string path)
220                 {
221                         Path.Validate (path);
222                         SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
223
224                         MonoIOError error;
225                         FileAttributes attrs;
226                         
227                         attrs = MonoIO.GetFileAttributes (path, out error);
228                         if (error != MonoIOError.ERROR_SUCCESS)
229                                 throw MonoIO.GetException (path, error);
230                         return attrs;
231                 }
232
233                 public static DateTime GetCreationTime (string path)
234                 {
235                         MonoIOStat stat;
236                         MonoIOError error;
237                         Path.Validate (path);
238                         SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
239
240                         if (!MonoIO.GetFileStat (path, out stat, out error)) {
241                                 if (error == MonoIOError.ERROR_PATH_NOT_FOUND || error == MonoIOError.ERROR_FILE_NOT_FOUND)
242                                         return DefaultLocalFileTime;
243                                 else
244                                         throw new IOException (path);
245                         }
246                         return DateTime.FromFileTime (stat.CreationTime);
247                 }
248
249                 public static DateTime GetCreationTimeUtc (string path)
250                 {
251                         return GetCreationTime (path).ToUniversalTime ();
252                 }
253
254                 public static DateTime GetLastAccessTime (string path)
255                 {
256                         MonoIOStat stat;
257                         MonoIOError error;
258                         Path.Validate (path);
259                         SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
260
261                         if (!MonoIO.GetFileStat (path, out stat, out error)) {
262                                 if (error == MonoIOError.ERROR_PATH_NOT_FOUND || error == MonoIOError.ERROR_FILE_NOT_FOUND)
263                                         return DefaultLocalFileTime;
264                                 else
265                                         throw new IOException (path);
266                         }
267                         return DateTime.FromFileTime (stat.LastAccessTime);
268                 }
269
270                 public static DateTime GetLastAccessTimeUtc (string path)
271                 {
272                         return GetLastAccessTime (path).ToUniversalTime ();
273                 }
274
275                 public static DateTime GetLastWriteTime (string path)
276                 {
277                         MonoIOStat stat;
278                         MonoIOError error;
279                         Path.Validate (path);
280                         SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
281
282                         if (!MonoIO.GetFileStat (path, out stat, out error)) {
283                                 if (error == MonoIOError.ERROR_PATH_NOT_FOUND || error == MonoIOError.ERROR_FILE_NOT_FOUND)
284                                         return DefaultLocalFileTime;
285                                 else
286                                         throw new IOException (path);
287                         }
288                         return DateTime.FromFileTime (stat.LastWriteTime);
289                 }
290
291                 public static DateTime GetLastWriteTimeUtc (string path)
292                 {
293                         return GetLastWriteTime (path).ToUniversalTime ();
294                 }
295
296                 public static void Move (string sourceFileName, string destFileName)
297                 {
298                         if (sourceFileName == null)
299                                 throw new ArgumentNullException ("sourceFileName");
300                         if (destFileName == null)
301                                 throw new ArgumentNullException ("destFileName");
302                         if (sourceFileName.Length == 0)
303                                 throw new ArgumentException ("An empty file name is not valid.", "sourceFileName");
304                         if (sourceFileName.Trim ().Length == 0 || sourceFileName.IndexOfAny (Path.InvalidPathChars) != -1)
305                                 throw new ArgumentException ("The file name is not valid.");
306                         if (destFileName.Length == 0)
307                                 throw new ArgumentException ("An empty file name is not valid.", "destFileName");
308                         if (destFileName.Trim ().Length == 0 || destFileName.IndexOfAny (Path.InvalidPathChars) != -1)
309                                 throw new ArgumentException ("The file name is not valid.");
310
311                         SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
312
313                         MonoIOError error;
314                         if (!MonoIO.Exists (sourceFileName, out error))
315                                 throw new FileNotFoundException (Locale.GetText ("{0} does not exist", sourceFileName), sourceFileName);
316
317                         // Don't check for this error here to allow the runtime
318                         // to check if sourceFileName and destFileName are equal.
319                         // Comparing sourceFileName and destFileName is not enough.
320                         //if (MonoIO.Exists (destFileName, out error))
321                         //      throw new IOException (Locale.GetText ("{0} already exists", destFileName));
322
323                         string DirName;
324                         DirName = Path.GetDirectoryName (destFileName);
325                         if (DirName != String.Empty && !Directory.Exists (DirName))
326                                 throw new DirectoryNotFoundException (Locale.GetText ("Could not find a part of the path."));
327
328                         if (!MonoIO.MoveFile (sourceFileName, destFileName, out error)) {
329                                 if (error == MonoIOError.ERROR_ALREADY_EXISTS)
330                                         throw MonoIO.GetException (error);
331                                 else if (error == MonoIOError.ERROR_SHARING_VIOLATION)
332                                         throw MonoIO.GetException (sourceFileName, error);
333                                 
334                                 throw MonoIO.GetException (error);
335                         }
336                 }
337                 
338                 public static FileStream Open (string path, FileMode mode)
339                 {
340                         return new FileStream (path, mode, mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite, FileShare.None);
341                 }
342                 
343                 public static FileStream Open (string path, FileMode mode, FileAccess access)
344                 {
345                         return new FileStream (path, mode, access, FileShare.None);
346                 }
347
348                 public static FileStream Open (string path, FileMode mode, FileAccess access,
349                                                FileShare share)
350                 {
351                         return new FileStream (path, mode, access, share);
352                 }
353                 
354                 public static FileStream OpenRead (string path)
355                 {
356                         return new FileStream (path, FileMode.Open, FileAccess.Read, FileShare.Read);
357                 }
358
359                 public static StreamReader OpenText (string path)
360                 {
361                         return new StreamReader (path);
362                 }
363
364                 public static FileStream OpenWrite (string path)
365                 {
366                         return new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
367                 }
368
369                 public static void Replace (string sourceFileName,
370                                             string destinationFileName,
371                                             string destinationBackupFileName)
372                 {
373                         Replace (sourceFileName, destinationFileName, destinationBackupFileName, false);
374                 }
375                 
376                 public static void Replace (string sourceFileName,
377                                             string destinationFileName,
378                                             string destinationBackupFileName,
379                                             bool ignoreMetadataErrors)
380                 {
381                         MonoIOError error;
382
383                         if (sourceFileName == null)
384                                 throw new ArgumentNullException ("sourceFileName");
385                         if (destinationFileName == null)
386                                 throw new ArgumentNullException ("destinationFileName");
387                         if (sourceFileName.Trim ().Length == 0 || sourceFileName.IndexOfAny (Path.InvalidPathChars) != -1)
388                                 throw new ArgumentException ("sourceFileName");
389                         if (destinationFileName.Trim ().Length == 0 || destinationFileName.IndexOfAny (Path.InvalidPathChars) != -1)
390                                 throw new ArgumentException ("destinationFileName");
391
392                         string fullSource = Path.GetFullPath (sourceFileName);
393                         string fullDest = Path.GetFullPath (destinationFileName);
394                         if (MonoIO.ExistsDirectory (fullSource, out error))
395                                 throw new IOException (Locale.GetText ("{0} is a directory", sourceFileName));
396                         if (MonoIO.ExistsDirectory (fullDest, out error))
397                                 throw new IOException (Locale.GetText ("{0} is a directory", destinationFileName));
398
399                         if (!Exists (fullSource))
400                                 throw new FileNotFoundException (Locale.GetText ("{0} does not exist", sourceFileName), 
401                                                                  sourceFileName);
402                         if (!Exists (fullDest))
403                                 throw new FileNotFoundException (Locale.GetText ("{0} does not exist", destinationFileName), 
404                                                                  destinationFileName);
405                         if (fullSource == fullDest) 
406                                 throw new IOException (Locale.GetText ("Source and destination arguments are the same file."));
407
408                         string fullBackup = null;
409                         if (destinationBackupFileName != null) {
410                                 if (destinationBackupFileName.Trim ().Length == 0 || 
411                                     destinationBackupFileName.IndexOfAny (Path.InvalidPathChars) != -1)
412                                         throw new ArgumentException ("destinationBackupFileName");
413
414                                 fullBackup = Path.GetFullPath (destinationBackupFileName);
415                                 if (MonoIO.ExistsDirectory (fullBackup, out error))
416                                         throw new IOException (Locale.GetText ("{0} is a directory", destinationBackupFileName));
417                                 if (fullSource == fullBackup)
418                                         throw new IOException (Locale.GetText ("Source and backup arguments are the same file."));
419                                 if (fullDest == fullBackup)
420                                         throw new IOException (Locale.GetText (
421                                                                "Destination and backup arguments are the same file."));
422                         }
423
424                         var attrs = GetAttributes (fullDest);
425
426                         // TODO: Should be done in wapi, win32 api handles this already
427                         if ((attrs & FileAttributes.ReadOnly) != 0)
428                                 throw MonoIO.GetException (MonoIOError.ERROR_ACCESS_DENIED);
429
430                         if (!MonoIO.ReplaceFile (fullSource, fullDest, fullBackup, 
431                                                  ignoreMetadataErrors, out error)) {
432                                 throw MonoIO.GetException (error);
433                         }
434                 }
435
436 #if !NET_2_1
437                 public static void SetAccessControl (string path,
438                                                      FileSecurity fileSecurity)
439                 {
440                         if (null == fileSecurity)
441                                 throw new ArgumentNullException ("fileSecurity");
442
443                         fileSecurity.PersistModifications (path);
444                 }
445 #endif
446
447                 public static void SetAttributes (string path,
448                                                   FileAttributes fileAttributes)
449                 {
450                         MonoIOError error;
451                         Path.Validate (path);
452
453                         if (!MonoIO.SetFileAttributes (path, fileAttributes, out error))
454                                 throw MonoIO.GetException (path, error);
455                 }
456
457                 public static void SetCreationTime (string path, DateTime creationTime)
458                 {
459                         MonoIOError error;
460                         Path.Validate (path);
461                         if (!MonoIO.Exists (path, out error))
462                                 throw MonoIO.GetException (path, error);
463                         if (!MonoIO.SetCreationTime (path, creationTime, out error))
464                                 throw MonoIO.GetException (path, error);
465                 }
466
467                 public static void SetCreationTimeUtc (string path, DateTime creationTimeUtc)
468                 {
469                         SetCreationTime (path, creationTimeUtc.ToLocalTime ());
470                 }
471
472                 public static void SetLastAccessTime (string path, DateTime lastAccessTime)
473                 {
474                         MonoIOError error;
475                         Path.Validate (path);
476                         if (!MonoIO.Exists (path, out error))
477                                 throw MonoIO.GetException (path, error);
478                         if (!MonoIO.SetLastAccessTime (path, lastAccessTime, out error))
479                                 throw MonoIO.GetException (path, error);
480                 }
481
482                 public static void SetLastAccessTimeUtc (string path, DateTime lastAccessTimeUtc)
483                 {
484                         SetLastAccessTime (path, lastAccessTimeUtc.ToLocalTime ());
485                 }
486
487                 public static void SetLastWriteTime (string path,
488                                                      DateTime lastWriteTime)
489                 {
490                         MonoIOError error;
491                         Path.Validate (path);
492                         if (!MonoIO.Exists (path, out error))
493                                 throw MonoIO.GetException (path, error);
494                         if (!MonoIO.SetLastWriteTime (path, lastWriteTime, out error))
495                                 throw MonoIO.GetException (path, error);
496                 }
497
498                 public static void SetLastWriteTimeUtc (string path,
499                                                      DateTime lastWriteTimeUtc)
500                 {
501                         SetLastWriteTime (path, lastWriteTimeUtc.ToLocalTime ());
502                 }
503
504                 //
505                 // The documentation for this method is most likely wrong, it
506                 // talks about doing a "binary read", but the remarks say
507                 // that this "detects the encoding".
508                 //
509                 // This can not detect and do anything useful with the encoding
510                 // since the result is a byte [] not a char [].
511                 //
512                 public static byte [] ReadAllBytes (string path)
513                 {
514                         using (FileStream s = OpenRead (path)) {
515                                 long size = s.Length;
516                                 // limited to 2GB according to http://msdn.microsoft.com/en-us/library/system.io.file.readallbytes.aspx
517                                 if (size > Int32.MaxValue)
518                                         throw new IOException ("Reading more than 2GB with this call is not supported");
519
520                                 int pos = 0;
521                                 int count = (int) size;
522                                 byte [] result = new byte [size];
523                                 while (count > 0) {
524                                         int n = s.Read (result, pos, count);
525                                         if (n == 0)
526                                                 throw new IOException ("Unexpected end of stream");
527                                         pos += n;
528                                         count -= n;
529                                 }
530                                 return result;
531                         }
532                 }
533
534                 public static string [] ReadAllLines (string path)
535                 {
536                         using (StreamReader reader = File.OpenText (path)) {
537                                 return ReadAllLines (reader);
538                         }
539                 }
540
541                 public static string [] ReadAllLines (string path, Encoding encoding)
542                 {
543                         using (StreamReader reader = new StreamReader (path, encoding)) {
544                                 return ReadAllLines (reader);
545                         }
546                 }
547
548                 static string [] ReadAllLines (StreamReader reader)
549                 {
550                         List<string> list = new List<string> ();
551                         while (!reader.EndOfStream)
552                                 list.Add (reader.ReadLine ());
553                         return list.ToArray ();
554                 }
555
556                 public static string ReadAllText (string path)
557                 {
558                         using (StreamReader sr = new StreamReader (path)) {
559                                 return sr.ReadToEnd ();
560                         }
561                 }
562
563                 public static string ReadAllText (string path, Encoding encoding)
564                 {
565                         using (StreamReader sr = new StreamReader (path, encoding)) {
566                                 return sr.ReadToEnd ();
567                         }
568                 }
569
570                 public static void WriteAllBytes (string path, byte [] bytes)
571                 {
572                         using (Stream stream = File.Create (path)) {
573                                 stream.Write (bytes, 0, bytes.Length);
574                         }
575                 }
576
577                 public static void WriteAllLines (string path, string [] contents)
578                 {
579                         using (StreamWriter writer = new StreamWriter (path)) {
580                                 WriteAllLines (writer, contents);
581                         }
582                 }
583
584                 public static void WriteAllLines (string path, string [] contents, Encoding encoding)
585                 {
586                         using (StreamWriter writer = new StreamWriter (path, false, encoding)) {
587                                 WriteAllLines (writer, contents);
588                         }
589                 }
590
591                 static void WriteAllLines (StreamWriter writer, string [] contents)
592                 {
593                         foreach (string line in contents)
594                                 writer.WriteLine (line);
595                 }
596
597                 public static void WriteAllText (string path, string contents)
598                 {
599                         WriteAllText (path, contents, EncodingHelper.UTF8Unmarked);
600                 }
601
602                 public static void WriteAllText (string path, string contents, Encoding encoding)
603                 {
604                         using (StreamWriter sw = new StreamWriter (path, false, encoding)) {
605                                 sw.Write (contents);
606                         }
607                 }
608
609                 static DateTime? defaultLocalFileTime;
610                 static DateTime DefaultLocalFileTime {
611                         get {
612                                 if (defaultLocalFileTime == null)
613                                         defaultLocalFileTime = new DateTime (1601, 1, 1).ToLocalTime ();
614                                         
615                                 return defaultLocalFileTime.Value;
616                         }
617                 }
618
619
620                 [MonoLimitation ("File encryption isn't supported (even on NTFS).")]
621                 public static void Encrypt (string path)
622                 {
623                         // MS.NET support this only on NTFS file systems, i.e. it's a file-system (not a framework) feature.
624                         // otherwise it throws a NotSupportedException (or a PlatformNotSupportedException on older OS).
625                         // we throw the same (instead of a NotImplementedException) because most code should already be
626                         // handling this exception to work properly.
627                         throw new NotSupportedException (Locale.GetText ("File encryption isn't supported on any file system."));
628                 }
629
630                 [MonoLimitation ("File encryption isn't supported (even on NTFS).")]
631                 public static void Decrypt (string path)
632                 {
633                         // MS.NET support this only on NTFS file systems, i.e. it's a file-system (not a framework) feature.
634                         // otherwise it throws a NotSupportedException (or a PlatformNotSupportedException on older OS).
635                         // we throw the same (instead of a NotImplementedException) because most code should already be
636                         // handling this exception to work properly.
637                         throw new NotSupportedException (Locale.GetText ("File encryption isn't supported on any file system."));
638                 }
639
640                 public static IEnumerable<string> ReadLines (string path)
641                 {
642                         return ReadLines (File.OpenText (path));
643                 }
644
645                 public static IEnumerable<string> ReadLines (string path, Encoding encoding)
646                 {
647                         return ReadLines (new StreamReader (path, encoding));
648                 }
649
650                 // refactored in order to avoid compiler-generated names for Moonlight tools
651                 static IEnumerable<string> ReadLines (StreamReader reader)
652                 {
653                         using (reader) {
654                                 string s;
655                                 while ((s = reader.ReadLine ()) != null) {
656                                         yield return s;
657                                 }
658                         }
659                 }
660
661                 public static void AppendAllLines (string path, IEnumerable<string> contents)
662                 {
663                         Path.Validate (path);
664
665                         if (contents == null)
666                                 return;
667
668                         using (TextWriter w = new StreamWriter (path, true)) {
669                                 foreach (var line in contents)
670                                         w.WriteLine (line);
671                         }
672                 }
673
674                 public static void AppendAllLines (string path, IEnumerable<string> contents, Encoding encoding)
675                 {
676                         Path.Validate (path);
677
678                         if (contents == null)
679                                 return;
680
681                         using (TextWriter w = new StreamWriter (path, true, encoding)) {
682                                 foreach (var line in contents)
683                                         w.WriteLine (line);
684                         }
685                 }
686
687                 public static void WriteAllLines (string path, IEnumerable<string> contents)
688                 {
689                         Path.Validate (path);
690
691                         if (contents == null)
692                                 return;
693
694                         using (TextWriter w = new StreamWriter (path, false)) {
695                                 foreach (var line in contents)
696                                         w.WriteLine (line);
697                         }
698                 }
699
700                 public static void WriteAllLines (string path, IEnumerable<string> contents, Encoding encoding)
701                 {
702                         Path.Validate (path);
703
704                         if (contents == null)
705                                 return;
706
707                         using (TextWriter w = new StreamWriter (path, false, encoding)) {
708                                 foreach (var line in contents)
709                                         w.WriteLine (line);
710                         }
711                 }
712
713                 internal static int FillAttributeInfo (String path, ref MonoIOStat data, bool tryagain, bool returnErrorOnNotFound)
714                 {
715                         if (tryagain)
716                                 throw new NotImplementedException ();
717
718                         MonoIOError error;
719                         MonoIO.GetFileStat (path, out data, out error);
720
721                         if (!returnErrorOnNotFound && (error == MonoIOError.ERROR_FILE_NOT_FOUND || error == MonoIOError.ERROR_PATH_NOT_FOUND || error == MonoIOError.ERROR_NOT_READY)) {
722                                 data = default (MonoIOStat);
723                                 data.fileAttributes = (FileAttributes) (-1);
724                                 return 0;
725                         }
726
727                         return (int) error;
728                 }
729         }
730 }