Fixing a GC hole in Number.BigInteger (dotnet/coreclr#22334)
[mono-project.git] / mcs / class / corlib / System.IO / File.cs
blobd6fef5a1304bb5b698f9f74625e9f9c6d13e877a
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)
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)
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.
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 using System.Security.AccessControl;
43 namespace System.IO
45 [ComVisible (true)]
46 public static class File
48 public static void AppendAllText (string path, string contents)
50 using (TextWriter w = new StreamWriter (path, true)) {
51 w.Write (contents);
55 public static void AppendAllText (string path, string contents, Encoding encoding)
57 using (TextWriter w = new StreamWriter (path, true, encoding)) {
58 w.Write (contents);
62 public static StreamWriter AppendText (string path)
64 return new StreamWriter (path, true);
67 public static void Copy (string sourceFileName, string destFileName)
69 Copy (sourceFileName, destFileName, false);
72 public static void Copy (string sourceFileName, string destFileName, bool overwrite)
74 MonoIOError error;
76 if (sourceFileName == null)
77 throw new ArgumentNullException ("sourceFileName");
78 if (destFileName == null)
79 throw new ArgumentNullException ("destFileName");
80 if (sourceFileName.Length == 0)
81 throw new ArgumentException ("An empty file name is not valid.", "sourceFileName");
82 if (sourceFileName.Trim ().Length == 0 || sourceFileName.IndexOfAny (Path.InvalidPathChars) != -1)
83 throw new ArgumentException ("The file name is not valid.");
84 if (destFileName.Length == 0)
85 throw new ArgumentException ("An empty file name is not valid.", "destFileName");
86 if (destFileName.Trim ().Length == 0 || destFileName.IndexOfAny (Path.InvalidPathChars) != -1)
87 throw new ArgumentException ("The file name is not valid.");
89 SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
91 if (!MonoIO.Exists (sourceFileName, out error))
92 throw new FileNotFoundException (Locale.GetText ("{0} does not exist", sourceFileName), sourceFileName);
93 if ((GetAttributes (sourceFileName) & FileAttributes.Directory) == FileAttributes.Directory)
94 throw new ArgumentException (Locale.GetText ("{0} is a directory", sourceFileName));
96 if (MonoIO.Exists (destFileName, out error)) {
97 if ((GetAttributes (destFileName) & FileAttributes.Directory) == FileAttributes.Directory)
98 throw new ArgumentException (Locale.GetText ("{0} is a directory", destFileName));
99 if (!overwrite)
100 throw new IOException (Locale.GetText ("{0} already exists", destFileName));
103 string DirName = Path.GetDirectoryName (destFileName);
104 if (DirName != String.Empty && !Directory.Exists (DirName))
105 throw new DirectoryNotFoundException (Locale.GetText ("Destination directory not found: {0}",DirName));
107 if (!MonoIO.CopyFile (sourceFileName, destFileName, overwrite, out error)) {
108 string p = Locale.GetText ("{0}\" or \"{1}", sourceFileName, destFileName);
109 throw MonoIO.GetException (p, error);
113 internal static String InternalCopy (String sourceFileName, String destFileName, bool overwrite, bool checkHost)
115 String fullSourceFileName = Path.GetFullPathInternal(sourceFileName);
116 String fullDestFileName = Path.GetFullPathInternal(destFileName);
118 MonoIOError error;
120 if (!MonoIO.CopyFile (fullSourceFileName, fullDestFileName, overwrite, out error)) {
121 string p = Locale.GetText ("{0}\" or \"{1}", sourceFileName, destFileName);
122 throw MonoIO.GetException (p, error);
125 return fullDestFileName;
128 public static FileStream Create (string path)
130 return Create (path, 8192);
133 public static FileStream Create (string path, int bufferSize)
135 return new FileStream (path, FileMode.Create, FileAccess.ReadWrite,
136 FileShare.None, bufferSize);
139 [MonoLimitation ("FileOptions are ignored")]
140 public static FileStream Create (string path, int bufferSize,
141 FileOptions options)
143 return new FileStream (path, FileMode.Create, FileAccess.ReadWrite,
144 FileShare.None, bufferSize, options);
147 [MonoLimitation ("FileOptions and FileSecurity are ignored")]
148 public static FileStream Create (string path, int bufferSize,
149 FileOptions options,
150 FileSecurity fileSecurity)
152 return new FileStream (path, FileMode.Create, FileAccess.ReadWrite,
153 FileShare.None, bufferSize, options);
156 public static StreamWriter CreateText (string path)
158 return new StreamWriter (path, false);
161 public static void Delete (string path)
163 Path.Validate (path);
164 if (Directory.Exists (path))
165 throw new UnauthorizedAccessException(Locale.GetText ("{0} is a directory", path));
167 string DirName = Path.GetDirectoryName(path);
168 if (DirName != String.Empty && !Directory.Exists (DirName))
169 throw new DirectoryNotFoundException (Locale.GetText ("Could not find a part of the path \"{0}\".", path));
171 SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
173 MonoIOError error;
175 if (!MonoIO.DeleteFile (path, out error)){
176 if (error != MonoIOError.ERROR_FILE_NOT_FOUND)
177 throw MonoIO.GetException (path, error);
181 public static bool Exists (string path)
183 // For security reasons no exceptions are
184 // thrown, only false is returned if there is
185 // any problem with the path or permissions.
186 // Minimizes what information can be
187 // discovered by using this method.
188 if (String.IsNullOrWhiteSpace (path) || path.IndexOfAny(Path.InvalidPathChars) >= 0)
189 return false;
191 // on Moonlight this does not throw but returns false
192 if (!SecurityManager.CheckElevatedPermissions ())
193 return false;
195 MonoIOError error;
196 return MonoIO.ExistsFile (path, out error);
199 public static FileSecurity GetAccessControl (string path)
201 // AccessControlSections.Audit requires special permissions.
202 return GetAccessControl (path,
203 AccessControlSections.Owner |
204 AccessControlSections.Group |
205 AccessControlSections.Access);
208 public static FileSecurity GetAccessControl (string path, AccessControlSections includeSections)
210 return new FileSecurity (path, includeSections);
213 public static FileAttributes GetAttributes (string path)
215 Path.Validate (path);
216 SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
218 MonoIOError error;
219 FileAttributes attrs;
221 attrs = MonoIO.GetFileAttributes (path, out error);
222 if (error != MonoIOError.ERROR_SUCCESS)
223 throw MonoIO.GetException (path, error);
224 return attrs;
227 public static DateTime GetCreationTime (string path)
229 MonoIOStat stat;
230 MonoIOError error;
231 Path.Validate (path);
232 SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
234 if (!MonoIO.GetFileStat (path, out stat, out error)) {
235 if (error == MonoIOError.ERROR_PATH_NOT_FOUND || error == MonoIOError.ERROR_FILE_NOT_FOUND)
236 return DefaultLocalFileTime;
237 else
238 throw new IOException (path);
240 return DateTime.FromFileTime (stat.CreationTime);
243 public static DateTime GetCreationTimeUtc (string path)
245 return GetCreationTime (path).ToUniversalTime ();
248 public static DateTime GetLastAccessTime (string path)
250 MonoIOStat stat;
251 MonoIOError error;
252 Path.Validate (path);
253 SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
255 if (!MonoIO.GetFileStat (path, out stat, out error)) {
256 if (error == MonoIOError.ERROR_PATH_NOT_FOUND || error == MonoIOError.ERROR_FILE_NOT_FOUND)
257 return DefaultLocalFileTime;
258 else
259 throw new IOException (path);
261 return DateTime.FromFileTime (stat.LastAccessTime);
264 public static DateTime GetLastAccessTimeUtc (string path)
266 return GetLastAccessTime (path).ToUniversalTime ();
269 public static DateTime GetLastWriteTime (string path)
271 MonoIOStat stat;
272 MonoIOError error;
273 Path.Validate (path);
274 SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
276 if (!MonoIO.GetFileStat (path, out stat, out error)) {
277 if (error == MonoIOError.ERROR_PATH_NOT_FOUND || error == MonoIOError.ERROR_FILE_NOT_FOUND)
278 return DefaultLocalFileTime;
279 else
280 throw new IOException (path);
282 return DateTime.FromFileTime (stat.LastWriteTime);
285 public static DateTime GetLastWriteTimeUtc (string path)
287 return GetLastWriteTime (path).ToUniversalTime ();
290 public static void Move (string sourceFileName, string destFileName)
292 if (sourceFileName == null)
293 throw new ArgumentNullException ("sourceFileName");
294 if (destFileName == null)
295 throw new ArgumentNullException ("destFileName");
296 if (sourceFileName.Length == 0)
297 throw new ArgumentException ("An empty file name is not valid.", "sourceFileName");
298 if (sourceFileName.Trim ().Length == 0 || sourceFileName.IndexOfAny (Path.InvalidPathChars) != -1)
299 throw new ArgumentException ("The file name is not valid.");
300 if (destFileName.Length == 0)
301 throw new ArgumentException ("An empty file name is not valid.", "destFileName");
302 if (destFileName.Trim ().Length == 0 || destFileName.IndexOfAny (Path.InvalidPathChars) != -1)
303 throw new ArgumentException ("The file name is not valid.");
305 SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
307 MonoIOError error;
308 if (!MonoIO.Exists (sourceFileName, out error))
309 throw new FileNotFoundException (Locale.GetText ("{0} does not exist", sourceFileName), sourceFileName);
311 // Don't check for this error here to allow the runtime
312 // to check if sourceFileName and destFileName are equal.
313 // Comparing sourceFileName and destFileName is not enough.
314 //if (MonoIO.Exists (destFileName, out error))
315 // throw new IOException (Locale.GetText ("{0} already exists", destFileName));
317 string DirName;
318 DirName = Path.GetDirectoryName (destFileName);
319 if (DirName != String.Empty && !Directory.Exists (DirName))
320 throw new DirectoryNotFoundException (Locale.GetText ("Could not find a part of the path."));
322 if (!MonoIO.MoveFile (sourceFileName, destFileName, out error)) {
323 if (error == MonoIOError.ERROR_ALREADY_EXISTS)
324 throw MonoIO.GetException (error);
325 else if (error == MonoIOError.ERROR_SHARING_VIOLATION)
326 throw MonoIO.GetException (sourceFileName, error);
328 throw MonoIO.GetException (error);
332 public static FileStream Open (string path, FileMode mode)
334 return new FileStream (path, mode, mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite, FileShare.None);
337 public static FileStream Open (string path, FileMode mode, FileAccess access)
339 return new FileStream (path, mode, access, FileShare.None);
342 public static FileStream Open (string path, FileMode mode, FileAccess access,
343 FileShare share)
345 return new FileStream (path, mode, access, share);
348 public static FileStream OpenRead (string path)
350 return new FileStream (path, FileMode.Open, FileAccess.Read, FileShare.Read);
353 public static StreamReader OpenText (string path)
355 return new StreamReader (path);
358 public static FileStream OpenWrite (string path)
360 return new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
363 public static void Replace (string sourceFileName,
364 string destinationFileName,
365 string destinationBackupFileName)
367 Replace (sourceFileName, destinationFileName, destinationBackupFileName, false);
370 public static void Replace (string sourceFileName,
371 string destinationFileName,
372 string destinationBackupFileName,
373 bool ignoreMetadataErrors)
375 MonoIOError error;
377 if (sourceFileName == null)
378 throw new ArgumentNullException ("sourceFileName");
379 if (destinationFileName == null)
380 throw new ArgumentNullException ("destinationFileName");
381 if (sourceFileName.Trim ().Length == 0 || sourceFileName.IndexOfAny (Path.InvalidPathChars) != -1)
382 throw new ArgumentException ("sourceFileName");
383 if (destinationFileName.Trim ().Length == 0 || destinationFileName.IndexOfAny (Path.InvalidPathChars) != -1)
384 throw new ArgumentException ("destinationFileName");
386 string fullSource = Path.GetFullPath (sourceFileName);
387 string fullDest = Path.GetFullPath (destinationFileName);
388 if (MonoIO.ExistsDirectory (fullSource, out error))
389 throw new IOException (Locale.GetText ("{0} is a directory", sourceFileName));
390 if (MonoIO.ExistsDirectory (fullDest, out error))
391 throw new IOException (Locale.GetText ("{0} is a directory", destinationFileName));
393 if (!Exists (fullSource))
394 throw new FileNotFoundException (Locale.GetText ("{0} does not exist", sourceFileName),
395 sourceFileName);
396 if (!Exists (fullDest))
397 throw new FileNotFoundException (Locale.GetText ("{0} does not exist", destinationFileName),
398 destinationFileName);
399 if (fullSource == fullDest)
400 throw new IOException (Locale.GetText ("Source and destination arguments are the same file."));
402 string fullBackup = null;
403 if (destinationBackupFileName != null) {
404 if (destinationBackupFileName.Trim ().Length == 0 ||
405 destinationBackupFileName.IndexOfAny (Path.InvalidPathChars) != -1)
406 throw new ArgumentException ("destinationBackupFileName");
408 fullBackup = Path.GetFullPath (destinationBackupFileName);
409 if (MonoIO.ExistsDirectory (fullBackup, out error))
410 throw new IOException (Locale.GetText ("{0} is a directory", destinationBackupFileName));
411 if (fullSource == fullBackup)
412 throw new IOException (Locale.GetText ("Source and backup arguments are the same file."));
413 if (fullDest == fullBackup)
414 throw new IOException (Locale.GetText (
415 "Destination and backup arguments are the same file."));
418 var attrs = GetAttributes (fullDest);
420 // TODO: Should be done in wapi, win32 api handles this already
421 if ((attrs & FileAttributes.ReadOnly) != 0)
422 throw MonoIO.GetException (MonoIOError.ERROR_ACCESS_DENIED);
424 if (!MonoIO.ReplaceFile (fullSource, fullDest, fullBackup,
425 ignoreMetadataErrors, out error)) {
426 throw MonoIO.GetException (error);
430 public static void SetAccessControl (string path,
431 FileSecurity fileSecurity)
433 if (null == fileSecurity)
434 throw new ArgumentNullException ("fileSecurity");
436 fileSecurity.PersistModifications (path);
439 public static void SetAttributes (string path,
440 FileAttributes fileAttributes)
442 MonoIOError error;
443 Path.Validate (path);
445 if (!MonoIO.SetFileAttributes (path, fileAttributes, out error))
446 throw MonoIO.GetException (path, error);
449 public static void SetCreationTime (string path, DateTime creationTime)
451 MonoIOError error;
452 Path.Validate (path);
453 if (!MonoIO.Exists (path, out error))
454 throw MonoIO.GetException (path, error);
455 if (!MonoIO.SetCreationTime (path, creationTime, out error))
456 throw MonoIO.GetException (path, error);
459 public static void SetCreationTimeUtc (string path, DateTime creationTimeUtc)
461 SetCreationTime (path, creationTimeUtc.ToLocalTime ());
464 public static void SetLastAccessTime (string path, DateTime lastAccessTime)
466 MonoIOError error;
467 Path.Validate (path);
468 if (!MonoIO.Exists (path, out error))
469 throw MonoIO.GetException (path, error);
470 if (!MonoIO.SetLastAccessTime (path, lastAccessTime, out error))
471 throw MonoIO.GetException (path, error);
474 public static void SetLastAccessTimeUtc (string path, DateTime lastAccessTimeUtc)
476 SetLastAccessTime (path, lastAccessTimeUtc.ToLocalTime ());
479 public static void SetLastWriteTime (string path,
480 DateTime lastWriteTime)
482 MonoIOError error;
483 Path.Validate (path);
484 if (!MonoIO.Exists (path, out error))
485 throw MonoIO.GetException (path, error);
486 if (!MonoIO.SetLastWriteTime (path, lastWriteTime, out error))
487 throw MonoIO.GetException (path, error);
490 public static void SetLastWriteTimeUtc (string path,
491 DateTime lastWriteTimeUtc)
493 SetLastWriteTime (path, lastWriteTimeUtc.ToLocalTime ());
497 // The documentation for this method is most likely wrong, it
498 // talks about doing a "binary read", but the remarks say
499 // that this "detects the encoding".
501 // This can not detect and do anything useful with the encoding
502 // since the result is a byte [] not a char [].
504 public static byte [] ReadAllBytes (string path)
506 using (FileStream s = OpenRead (path)) {
507 long size = s.Length;
508 // limited to 2GB according to http://msdn.microsoft.com/en-us/library/system.io.file.readallbytes.aspx
509 if (size > Int32.MaxValue)
510 throw new IOException ("Reading more than 2GB with this call is not supported");
512 int pos = 0;
513 int count = (int) size;
514 byte [] result = new byte [size];
515 while (count > 0) {
516 int n = s.Read (result, pos, count);
517 if (n == 0)
518 throw new IOException ("Unexpected end of stream");
519 pos += n;
520 count -= n;
522 return result;
526 public static string [] ReadAllLines (string path)
528 using (StreamReader reader = File.OpenText (path)) {
529 return ReadAllLines (reader);
533 public static string [] ReadAllLines (string path, Encoding encoding)
535 using (StreamReader reader = new StreamReader (path, encoding)) {
536 return ReadAllLines (reader);
540 static string [] ReadAllLines (StreamReader reader)
542 List<string> list = new List<string> ();
543 while (!reader.EndOfStream)
544 list.Add (reader.ReadLine ());
545 return list.ToArray ();
548 public static string ReadAllText (string path)
550 using (StreamReader sr = new StreamReader (path)) {
551 return sr.ReadToEnd ();
555 public static string ReadAllText (string path, Encoding encoding)
557 using (StreamReader sr = new StreamReader (path, encoding)) {
558 return sr.ReadToEnd ();
562 public static void WriteAllBytes (string path, byte [] bytes)
564 using (Stream stream = File.Create (path)) {
565 stream.Write (bytes, 0, bytes.Length);
569 public static void WriteAllLines (string path, string [] contents)
571 using (StreamWriter writer = new StreamWriter (path)) {
572 WriteAllLines (writer, contents);
576 public static void WriteAllLines (string path, string [] contents, Encoding encoding)
578 using (StreamWriter writer = new StreamWriter (path, false, encoding)) {
579 WriteAllLines (writer, contents);
583 static void WriteAllLines (StreamWriter writer, string [] contents)
585 foreach (string line in contents)
586 writer.WriteLine (line);
589 public static void WriteAllText (string path, string contents)
591 WriteAllText (path, contents, EncodingHelper.UTF8Unmarked);
594 public static void WriteAllText (string path, string contents, Encoding encoding)
596 using (StreamWriter sw = new StreamWriter (path, false, encoding)) {
597 sw.Write (contents);
601 static DateTime? defaultLocalFileTime;
602 static DateTime DefaultLocalFileTime {
603 get {
604 if (defaultLocalFileTime == null)
605 defaultLocalFileTime = new DateTime (1601, 1, 1).ToLocalTime ();
607 return defaultLocalFileTime.Value;
612 [MonoLimitation ("File encryption isn't supported (even on NTFS).")]
613 public static void Encrypt (string path)
615 // MS.NET support this only on NTFS file systems, i.e. it's a file-system (not a framework) feature.
616 // otherwise it throws a NotSupportedException (or a PlatformNotSupportedException on older OS).
617 // we throw the same (instead of a NotImplementedException) because most code should already be
618 // handling this exception to work properly.
619 throw new NotSupportedException (Locale.GetText ("File encryption isn't supported on any file system."));
622 [MonoLimitation ("File encryption isn't supported (even on NTFS).")]
623 public static void Decrypt (string path)
625 // MS.NET support this only on NTFS file systems, i.e. it's a file-system (not a framework) feature.
626 // otherwise it throws a NotSupportedException (or a PlatformNotSupportedException on older OS).
627 // we throw the same (instead of a NotImplementedException) because most code should already be
628 // handling this exception to work properly.
629 throw new NotSupportedException (Locale.GetText ("File encryption isn't supported on any file system."));
632 public static IEnumerable<string> ReadLines (string path)
634 return ReadLines (File.OpenText (path));
637 public static IEnumerable<string> ReadLines (string path, Encoding encoding)
639 return ReadLines (new StreamReader (path, encoding));
642 // refactored in order to avoid compiler-generated names for Moonlight tools
643 static IEnumerable<string> ReadLines (StreamReader reader)
645 using (reader) {
646 string s;
647 while ((s = reader.ReadLine ()) != null) {
648 yield return s;
653 public static void AppendAllLines (string path, IEnumerable<string> contents)
655 Path.Validate (path);
657 if (contents == null)
658 return;
660 using (TextWriter w = new StreamWriter (path, true)) {
661 foreach (var line in contents)
662 w.WriteLine (line);
666 public static void AppendAllLines (string path, IEnumerable<string> contents, Encoding encoding)
668 Path.Validate (path);
670 if (contents == null)
671 return;
673 using (TextWriter w = new StreamWriter (path, true, encoding)) {
674 foreach (var line in contents)
675 w.WriteLine (line);
679 public static void WriteAllLines (string path, IEnumerable<string> contents)
681 Path.Validate (path);
683 if (contents == null)
684 return;
686 using (TextWriter w = new StreamWriter (path, false)) {
687 foreach (var line in contents)
688 w.WriteLine (line);
692 public static void WriteAllLines (string path, IEnumerable<string> contents, Encoding encoding)
694 Path.Validate (path);
696 if (contents == null)
697 return;
699 using (TextWriter w = new StreamWriter (path, false, encoding)) {
700 foreach (var line in contents)
701 w.WriteLine (line);
705 internal static int FillAttributeInfo (String path, ref MonoIOStat data, bool tryagain, bool returnErrorOnNotFound)
707 if (tryagain)
708 throw new NotImplementedException ();
710 MonoIOError error;
711 MonoIO.GetFileStat (path, out data, out error);
713 if (!returnErrorOnNotFound && (error == MonoIOError.ERROR_FILE_NOT_FOUND || error == MonoIOError.ERROR_PATH_NOT_FOUND || error == MonoIOError.ERROR_NOT_READY)) {
714 data = default (MonoIOStat);
715 data.fileAttributes = (FileAttributes) (-1);
716 return 0;
719 return (int) error;
721 #region Copied from corefx
723 internal static DateTimeOffset GetUtcDateTimeOffset(DateTime dateTime)
725 // File and Directory UTC APIs treat a DateTimeKind.Unspecified as UTC whereas
726 // ToUniversalTime treats this as local.
727 if (dateTime.Kind == DateTimeKind.Unspecified)
729 return DateTime.SpecifyKind(dateTime, DateTimeKind.Utc);
732 return dateTime.ToUniversalTime();
734 #endregion