// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== //============================================================ // // Class: File // // Purpose: A collection of methods for manipulating Files. // //=========================================================== using System; using System.Runtime.InteropServices; using System.Text; using FileSystem.Utils; using Microsoft.Singularity.Directory; namespace System.IO { // Class for creating FileStream objects, and some basic file management // routines such as Delete, etc. //| public sealed class File { private const int GetFileExInfoStandard = 0; private File() { } //| public static StreamReader OpenText(String path) { if (path == null) throw new ArgumentNullException("path"); return new StreamReader(path); } //| public static StreamWriter CreateText(String path) { if (path == null) throw new ArgumentNullException("path"); return new StreamWriter(path,false); } //| public static StreamWriter AppendText(String path) { if (path == null) throw new ArgumentNullException("path"); return new StreamWriter(path,true); } // Copies an existing file to a new file. An exception is raised if the // destination file already exists. Use the // Copy(String, String, boolean) method to allow // overwriting an existing file. // //| public static void Copy(String sourceFileName, String destFileName) { Copy(sourceFileName, destFileName, false); } // Copies an existing file to a new file. If overwrite is // false, then an IOException is thrown if the destination file // already exists. If overwrite is true, the file is // overwritten. // //| public static void Copy(String sourceFileName, String destFileName, bool overwrite) { InternalCopy(sourceFileName, destFileName,overwrite); } //| /// /// Note: This returns the fully qualified name of the destination file. /// internal static String! InternalCopy(String sourceFileName, String destFileName, bool overwrite) { if (sourceFileName == null || destFileName == null) throw new ArgumentNullException((sourceFileName==null ? "sourceFileName" : "destFileName"), "ArgumentNull_FileName"); if (sourceFileName.Length == 0 || destFileName.Length == 0) throw new ArgumentException("Argument_EmptyFileName", (sourceFileName.Length==0 ? "sourceFileName" : "destFileName")); String fullSourceFileName = Path.GetFullPathInternal(sourceFileName); String fullDestFileName = Path.GetFullPathInternal(destFileName); bool r = Native.CopyFile(fullSourceFileName, fullDestFileName, !overwrite); if (!r) { __Error.WinIOError(0, destFileName); } return fullDestFileName; } // Creates a file in a particular path. If the file exists, it is replaced. // The file is opened with ReadWrite accessand cannot be opened by another // application until it has been closed. An IOException is thrown if the // directory specified doesn't exist. // // Your application must have Create, Read, and Write permissions to // the file. // //| public static FileStream Create(String path) { return Create(path, FileStream.DefaultBufferSize); } // Creates a file in a particular path. If the file exists, it is replaced. // The file is opened with ReadWrite access and cannot be opened by another // application until it has been closed. An IOException is thrown if the // directory specified doesn't exist. // // Your application must have Create, Read, and Write permissions to // the file. // //| public static FileStream Create(String path, int bufferSize) { return new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.None, bufferSize); } // Deletes a file. The file specified by the designated path is deleted. // If the file does not exist, Delete succeeds without throwing // an exception. // // On NT, Delete will fail for a file that is open for normal I/O // or a file that is memory mapped. // // Your application must have Delete permission to the target file. // //| public static void Delete(String path) { if (path == null) throw new ArgumentNullException("path"); String fullPath = Path.GetFullPathInternal(path); ErrorCode error; bool r = Native.DeleteFile(fullPath, out error); if (!r) { //int err = __Error.ErrorCodeToWin32Error(error); //__Error.WinIOError(err, path); __Error.SingularityIOError(error,path); } } // Tests if a file exists. The result is true if the file // given by the specified path exists; otherwise, the result is // false. Note that if path describes a directory, // Exists will return true. // // Your application must have Read permission for the target directory. // //| public static bool Exists(String! path) { DirectoryServiceContract.Imp dsRoot = DirectoryService.NewClientEndpoint(); if (dsRoot == null) throw new Exception("No directory service endpoint."); bool ok = Exists(dsRoot, path); delete dsRoot; return ok; } public static bool Exists(DirectoryServiceContract.Imp:Ready! dsRoot, String! path) { try { path = Path.GetFullPathInternal(path); if (path == null) return false; if (path.Length == 0) return false; bool exists = FileUtils.FileExists(dsRoot, (!)path); #if false // uncomment to debug file access. Console.WriteLine("FileExists({0}) = {1}", path, exists); #endif return exists; } catch (ArgumentException) { } catch (NotSupportedException) {} // To deal with the fact that security can now throw this on : catch (IOException) { } return false; } internal static bool InternalExists(String path) { Native.FILE_ATTRIBUTE_DATA data = new Native.FILE_ATTRIBUTE_DATA(); int dataInitialised = FillAttributeInfo(path,ref data); if (dataInitialised != 0) return false; return (data.fileAttributes & Native.FILE_ATTRIBUTE_DIRECTORY) == 0; } //| public static FileStream Open(String path,FileMode mode) { return Open(path, mode, (mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite), FileShare.None); } //| public static FileStream Open(String path,FileMode mode, FileAccess access) { return Open(path,mode, access, FileShare.None); } //| public static FileStream Open(String path, FileMode mode, FileAccess access, FileShare share) { return new FileStream(path, mode, access, share); } //| public static void SetCreationTime(String path, DateTime creationTime) { SetCreationTimeUtc(path, creationTime.ToUniversalTime()); } //| public static void SetCreationTimeUtc(String path, DateTime creationTimeUtc) { IntPtr handle = IntPtr.Zero; FileStream fs = OpenFile(path, FileAccess.Write, ref handle); bool r = Native.SetFileTime(handle, new long[] {creationTimeUtc.ToFileTimeUtc()}, null, null); if (!r) { fs.Close(); __Error.WinIOError(0, path); } fs.Close(); } //| public static DateTime GetCreationTimeUtc(String! path) { String fullPath = Path.GetFullPathInternal(path); Native.FILE_ATTRIBUTE_DATA data = new Native.FILE_ATTRIBUTE_DATA(); int dataInitialised = FillAttributeInfo(fullPath,ref data); if (dataInitialised != 0) __Error.WinIOError(dataInitialised, path); if (data.fileAttributes == -1) throw new IOException(String.Format("IO.PathNotFound_Path", path)); return DateTime.FromFileTimeUtc(data.ftCreationTime); } //| public static void SetLastAccessTimeUtc(String path, DateTime lastAccessTimeUtc) { IntPtr handle = IntPtr.Zero; FileStream fs = OpenFile(path, FileAccess.Write, ref handle); bool r = Native.SetFileTime(handle, null, new long[] {lastAccessTimeUtc.ToFileTimeUtc()}, null); if (!r) { fs.Close(); __Error.WinIOError(0, path); } fs.Close(); } //| public static DateTime GetLastAccessTimeUtc(String! path) { String fullPath = Path.GetFullPathInternal(path); Native.FILE_ATTRIBUTE_DATA data = new Native.FILE_ATTRIBUTE_DATA(); int dataInitialised = FillAttributeInfo(fullPath,ref data); if (dataInitialised != 0) __Error.WinIOError(dataInitialised, path); if (data.fileAttributes == -1) throw new IOException(String.Format("IO.PathNotFound_Path", path)); return DateTime.FromFileTimeUtc(data.ftLastAccessTime); } //| public static void SetLastWriteTimeUtc(String path, DateTime lastWriteTimeUtc) { IntPtr handle = IntPtr.Zero; FileStream fs = OpenFile(path, FileAccess.Write, ref handle); bool r = Native.SetFileTime(handle, null, null, new long[] {lastWriteTimeUtc.ToFileTimeUtc()}); if (!r) { fs.Close(); __Error.WinIOError(0, path); } fs.Close(); } public static DateTime GetLastWriteTime(String! path) { //TODO: FIXFIX need to convert to local time some day return GetLastWriteTimeUtc(path); } //| public static DateTime GetLastWriteTimeUtc(String! path) { String fullPath = Path.GetFullPathInternal(path); Native.FILE_ATTRIBUTE_DATA data = new Native.FILE_ATTRIBUTE_DATA(); int dataInitialised = FillAttributeInfo(fullPath,ref data); if (dataInitialised != 0) __Error.WinIOError(dataInitialised, path); if (data.fileAttributes == -1) throw new IOException(String.Format("IO.PathNotFound_Path", path)); return DateTime.FromFileTimeUtc(data.ftLastWriteTime); } //| public static FileAttributes GetAttributes(String! path) { String fullPath = Path.GetFullPathInternal(path); Native.FILE_ATTRIBUTE_DATA data = new Native.FILE_ATTRIBUTE_DATA(); int dataInitialised = FillAttributeInfo(fullPath,ref data); if (dataInitialised != 0) __Error.WinIOError(dataInitialised, path); if (data.fileAttributes == -1) __Error.WinIOError(Native.ERROR_FILE_NOT_FOUND, path); return (FileAttributes) data.fileAttributes; } //| public static void SetAttributes(String! path,FileAttributes fileAttributes) { String fullPath = Path.GetFullPathInternal(path); bool r = Native.SetFileAttributes(fullPath, (int) fileAttributes); if (!r) { __Error.WinIOError(0, path); } } //| public static FileStream OpenRead(String path) { return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); } //| public static FileStream OpenWrite(String path) { return new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None); } // Moves a specified file to a new location and potentially a new file name. // This method does work across volumes. // //| public static void Move(String sourceFileName, String destFileName) { if (sourceFileName == null || destFileName == null) throw new ArgumentNullException((sourceFileName==null ? "sourceFileName" : "destFileName"), "ArgumentNull_FileName"); if (sourceFileName.Length == 0 || destFileName.Length == 0) throw new ArgumentException("Argument_EmptyFileName", (sourceFileName.Length==0 ? "sourceFileName" : "destFileName")); String fullSourceFileName = Path.GetFullPathInternal(sourceFileName); String fullDestFileName = Path.GetFullPathInternal(destFileName); if (!InternalExists(fullSourceFileName)) __Error.WinIOError(Native.ERROR_FILE_NOT_FOUND,sourceFileName); if (!Native.MoveFile(fullSourceFileName, fullDestFileName)) { __Error.WinIOError(0, destFileName); } } internal static int FillAttributeInfo(String path, ref Native.FILE_ATTRIBUTE_DATA data) { int dataInitialised = 0; // For floppy drives, normally the OS will pop up a dialog saying // there is no disk in drive A:, please insert one. We don't want that. bool success = Native.GetFileAttributesEx(path, GetFileExInfoStandard, ref data); if (!success) { data.fileAttributes = -1; dataInitialised = 0; } return dataInitialised; } private static FileStream! OpenFile(String path, FileAccess access, ref IntPtr handle) { return new FileStream(path, FileMode.Open, access, FileShare.ReadWrite, 1); } // Defined in WinError.h private const int ERROR_INVALID_PARAMETER = 87; private const int ERROR_ACCESS_DENIED = 0x5; } }