// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. namespace System.Data.Entity { using System.Diagnostics.CodeAnalysis; using System.IO; using System.Reflection; using System.Security; using System.Security.Permissions; using System.Threading; /// /// This class provides utility methods for common I/O tasks not directly supported by .NET Framework BCL, /// as well as I/O tasks that require elevated privileges. /// public static class IOHelpers { private const int DefaultCopyBufferSize = 65536; #if !SILVERLIGHT /// /// Safely determines whether the given path refers to an existing directory on disk. /// /// The path to test. /// True if path refers to an existing directory; otherwise, false. [SecuritySafeCritical] // Calling Directory.Exists demands FileIOPermission (Read flag) for the specified path. [PermissionSet(SecurityAction.Assert, Unrestricted = true)] public static bool DirectoryExists(string path) { return Directory.Exists(path); } /// /// Creates the specified directory if it doesn't exist or removes all contents of an existing directory. /// /// Path to directory to create. [SecuritySafeCritical] // Calling Directory.Exists demands FileIOPermission (Read flag) for the specified path. [PermissionSet(SecurityAction.Assert, Unrestricted = true)] public static void EnsureDirectoryEmpty(string path) { if (Directory.Exists(path)) { SafeDeleteDirectory(path); } EnsureDirectoryExists(path); } /// /// Creates the specified directory if it doesn't exist. /// /// Path to directory to create. [SecuritySafeCritical] // Calling Directory.Exists and Directory.CreateDirectory demands FileIOPermission (Read | Write) for the specified path. [PermissionSet(SecurityAction.Assert, Unrestricted = true)] public static void EnsureDirectoryExists(string path) { if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } } /// /// Safely determines whether the specified file exists. /// /// The file to check. /// True if the caller has the required permissions and path contains the name of an existing file; otherwise, false. This method also returns false if path is null, an invalid path, or a zero-length string. If the caller does not have sufficient permissions to read the specified file, no exception is thrown and the method returns false regardless of the existence of path. [SecuritySafeCritical] // Calling File.Exists demands FileIOPermission (Read flag) for the specified path. [PermissionSet(SecurityAction.Assert, Unrestricted = true)] public static bool FileExists(string path) { return File.Exists(path); } /// /// Safely returns the absolute path for the specified path string. /// /// The file or directory for which to obtain absolute path information. /// A string containing the fully qualified location of path, such as "C:\MyFile.txt". [SecuritySafeCritical] // Calling Path.GetFullPath demands FileIOPermission (PathDiscovery flag) for the specified path. [PermissionSet(SecurityAction.Assert, Unrestricted = true)] public static string GetFullPath(string path) { return Path.GetFullPath(path); } /// /// Safely deletes the file and ignores any access violation exceptions. /// /// The directory to delete. [SecuritySafeCritical] // Calling File.Delete demands FileIOPermission (Write flag) for the specified path. [PermissionSet(SecurityAction.Assert, Unrestricted = true)] [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Need to catch everything here.")] public static void SafeDeleteFile(string path) { try { File.Delete(path); } catch (Exception) { // ignore exceptions } } /// /// Safely deletes the directory and ignores any access violation exceptions. /// /// The directory to delete. [SecuritySafeCritical] // Calling Directory.Delete demands FileIOPermission (Write flag) for the specified path. [PermissionSet(SecurityAction.Assert, Unrestricted = true)] [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Need to catch everything here.")] public static void SafeDeleteDirectory(string path) { // try different ways of contents of directory, fail after 3 attempts for (var i = 0; i < 3; ++i) { try { Directory.Delete(path, true); return; } catch (Exception) { } Thread.Sleep(500); try { foreach (var file in Directory.GetFiles(path, "*", SearchOption.AllDirectories)) { SafeDeleteFile(file); } return; } catch (Exception) { } Thread.Sleep(500); } } /// /// Creates a uniquely named, empty temporary directory on disk and returns the /// full path of that directory. /// /// A containing the full path of the temporary directory. public static string GetTempDirName() { var tempDir = Path.GetTempFileName(); File.Delete(tempDir); Directory.CreateDirectory(tempDir); return tempDir; } /// /// Copies the specified source files to a given directory. /// /// The destination directory. /// The source files. [SecuritySafeCritical] // Calling File.Copy demands FileIOPermission (Write flag) for the destination file path. [PermissionSet(SecurityAction.Assert, Unrestricted = true)] public static void CopyToDirectory(string destinationDirectory, params string[] sourceFiles) { foreach (var sourceFile in sourceFiles) { var baseName = Path.GetFileName(sourceFile); var destinationFile = Path.Combine(destinationDirectory, baseName); if (new FileInfo(sourceFile).FullName != new FileInfo(destinationFile).FullName) { File.Copy(sourceFile, destinationFile, true); } } } #endif public static void CopyToDir(string sourceFileName, string destDirName) { File.Copy( sourceFileName, Path.Combine( destDirName, Path.GetFileName(sourceFileName))); } /// /// Copies contents of one stream into another. /// /// Stream to read from. /// Stream to write to. /// The number of bytes copied from the source. public static int CopyStream(Stream source, Stream destination) { return CopyStream(source, destination, new byte[DefaultCopyBufferSize]); } /// /// Copies contents of one stream into another. /// /// Stream to read from. /// Stream to write to. /// The copy buffer. /// The number of bytes copied from the source. public static int CopyStream(Stream source, Stream destination, byte[] copyBuffer) { ExceptionHelpers.CheckArgumentNotNull(source, "source"); ExceptionHelpers.CheckArgumentNotNull(destination, "destination"); ExceptionHelpers.CheckArgumentNotNull(copyBuffer, "copyBuffer"); var bytesCopied = 0; int bytesRead; do { bytesRead = source.Read(copyBuffer, 0, copyBuffer.Length); destination.Write(copyBuffer, 0, bytesRead); bytesCopied += bytesRead; } while (bytesRead != 0); return bytesCopied; } /// /// Write an embedded resource to a local file /// /// Resource to be written /// File to write resource to /// Assembly to extract resource from #if !SILVERLIGHT [SecuritySafeCritical] // Calling File.Open demands FileIOPermission (Append flag) for the destination file path. [PermissionSet(SecurityAction.Assert, Unrestricted = true)] #endif public static void WriteResourceToFile(string resourceName, string fileName, Assembly assembly) { using (var resourceStream = assembly.GetManifestResourceStream(resourceName)) { if (resourceStream == null) { throw new IOException("Resource '" + resourceName + "' not found in '" + assembly.FullName + "'"); } using (var fileStream = File.Open(fileName, FileMode.Append)) { CopyStream(resourceStream, fileStream); } } } #if !SILVERLIGHT /// /// Adds the given set of file attributes to the file at the given path /// /// The name/path of the file /// The bit-field of attributes to add public static void AddFileAttributes(string fileName, FileAttributes toAdd) { File.SetAttributes(fileName, File.GetAttributes(fileName) | toAdd); } /// /// Removes the given set of file attributes from the file at the given path /// /// The name/path of the file /// The bit-field of attributes to remove public static void RemoveFileAttributes(string fileName, FileAttributes toRemove) { File.SetAttributes(fileName, File.GetAttributes(fileName) & ~toRemove); } #endif } }