using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Security; using System.Security.Permissions; namespace Trinet.Core.IO.Ntfs { using Resources = Properties.Resources; /// /// File-system utilities. /// public static class FileSystem { #region Create FileSystemInfo /// /// Creates a for the specified path. /// /// /// The path of the file or directory. /// /// /// The representing the file or directory. /// /// /// is or empty. /// private static FileSystemInfo CreateInfo(string path) { if (string.IsNullOrEmpty(path)) throw new ArgumentNullException("path"); path = Path.GetFullPath(path); if (!File.Exists(path) && Directory.Exists(path)) return new DirectoryInfo(path); return new FileInfo(path); } #endregion #region List Streams /// /// (Extension Method)
/// Returns a read-only list of alternate data streams for the specified file. ///
/// /// The to inspect. /// /// /// A read-only list of objects /// representing the alternate data streams for the specified file, if any. /// If no streams are found, returns an empty list. /// /// /// is . /// /// /// The specified does not exist. /// /// /// The caller does not have the required permission. /// /// /// The caller does not have the required permission. /// public static IList ListAlternateDataStreams(this FileSystemInfo file) { if (null == file) throw new ArgumentNullException("file"); if (!file.Exists) throw new FileNotFoundException(null, file.FullName); string path = file.FullName; new FileIOPermission(FileIOPermissionAccess.Read, path).Demand(); return SafeNativeMethods.ListStreams(path) .Select(s => new AlternateDataStreamInfo(path, s)) .ToList().AsReadOnly(); } /// /// Returns a read-only list of alternate data streams for the specified file. /// /// /// The full path of the file to inspect. /// /// /// A read-only list of objects /// representing the alternate data streams for the specified file, if any. /// /// /// is or an empty string. /// /// /// is not a valid file path. /// /// /// The specified does not exist. /// /// /// The caller does not have the required permission. /// /// /// The caller does not have the required permission. /// public static IList ListAlternateDataStreams(string filePath) { if (string.IsNullOrEmpty(filePath)) throw new ArgumentNullException("filePath"); return CreateInfo(filePath).ListAlternateDataStreams(); } #endregion #region Stream Exists /// /// (Extension Method)
/// Returns a flag indicating whether the specified alternate data stream exists. ///
/// /// The to inspect. /// /// /// The name of the stream to find. /// /// /// if the specified stream exists; /// otherwise, . /// /// /// is . /// /// /// contains invalid characters. /// public static bool AlternateDataStreamExists(this FileSystemInfo file, string streamName) { if (null == file) throw new ArgumentNullException("file"); SafeNativeMethods.ValidateStreamName(streamName); string path = SafeNativeMethods.BuildStreamPath(file.FullName, streamName); return -1 != SafeNativeMethods.SafeGetFileAttributes(path); } /// /// Returns a flag indicating whether the specified alternate data stream exists. /// /// /// The path of the file to inspect. /// /// /// The name of the stream to find. /// /// /// if the specified stream exists; /// otherwise, . /// /// /// is or an empty string. /// /// /// is not a valid file path. /// -or- /// contains invalid characters. /// public static bool AlternateDataStreamExists(string filePath, string streamName) { if (string.IsNullOrEmpty(filePath)) throw new ArgumentNullException("filePath"); return CreateInfo(filePath).AlternateDataStreamExists(streamName); } #endregion #region Open Stream /// /// (Extension Method)
/// Opens an alternate data stream. ///
/// /// The which contains the stream. /// /// /// The name of the stream to open. /// /// /// One of the values, indicating how the stream is to be opened. /// /// /// An representing the stream. /// /// /// is . /// /// /// The specified was not found. /// /// /// contains invalid characters. /// /// /// is either or . /// /// /// is , and the stream doesn't exist. /// -or- /// is , and the stream already exists. /// /// /// The caller does not have the required permission. /// /// /// The caller does not have the required permission, or the file is read-only. /// public static AlternateDataStreamInfo GetAlternateDataStream(this FileSystemInfo file, string streamName, FileMode mode) { if (null == file) throw new ArgumentNullException("file"); if (!file.Exists) throw new FileNotFoundException(null, file.FullName); SafeNativeMethods.ValidateStreamName(streamName); if (FileMode.Truncate == mode || FileMode.Append == mode) { throw new NotSupportedException(string.Format(Resources.Culture, Resources.Error_InvalidMode, mode)); } FileIOPermissionAccess permAccess = (FileMode.Open == mode) ? FileIOPermissionAccess.Read : FileIOPermissionAccess.Read | FileIOPermissionAccess.Write; new FileIOPermission(permAccess, file.FullName).Demand(); string path = SafeNativeMethods.BuildStreamPath(file.FullName, streamName); bool exists = -1 != SafeNativeMethods.SafeGetFileAttributes(path); if (!exists && FileMode.Open == mode) { throw new IOException(string.Format(Resources.Culture, Resources.Error_StreamNotFound, streamName, file.Name)); } if (exists && FileMode.CreateNew == mode) { throw new IOException(string.Format(Resources.Culture, Resources.Error_StreamExists, streamName, file.Name)); } return new AlternateDataStreamInfo(file.FullName, streamName, path, exists); } /// /// (Extension Method)
/// Opens an alternate data stream. ///
/// /// The which contains the stream. /// /// /// The name of the stream to open. /// /// /// An representing the stream. /// /// /// is . /// /// /// The specified was not found. /// /// /// contains invalid characters. /// /// /// The caller does not have the required permission. /// /// /// The caller does not have the required permission, or the file is read-only. /// public static AlternateDataStreamInfo GetAlternateDataStream(this FileSystemInfo file, string streamName) { return file.GetAlternateDataStream(streamName, FileMode.OpenOrCreate); } /// /// Opens an alternate data stream. /// /// /// The path of the file which contains the stream. /// /// /// The name of the stream to open. /// /// /// One of the values, indicating how the stream is to be opened. /// /// /// An representing the stream. /// /// /// is or an empty string. /// /// /// The specified was not found. /// /// /// is not a valid file path. /// -or- /// contains invalid characters. /// /// /// is either or . /// /// /// is , and the stream doesn't exist. /// -or- /// is , and the stream already exists. /// /// /// The caller does not have the required permission. /// /// /// The caller does not have the required permission, or the file is read-only. /// public static AlternateDataStreamInfo GetAlternateDataStream(string filePath, string streamName, FileMode mode) { if (string.IsNullOrEmpty(filePath)) throw new ArgumentNullException("filePath"); return CreateInfo(filePath).GetAlternateDataStream(streamName, mode); } /// /// Opens an alternate data stream. /// /// /// The path of the file which contains the stream. /// /// /// The name of the stream to open. /// /// /// An representing the stream. /// /// /// is or an empty string. /// /// /// The specified was not found. /// /// /// is not a valid file path. /// -or- /// contains invalid characters. /// /// /// The caller does not have the required permission. /// /// /// The caller does not have the required permission, or the file is read-only. /// public static AlternateDataStreamInfo GetAlternateDataStream(string filePath, string streamName) { return GetAlternateDataStream(filePath, streamName, FileMode.OpenOrCreate); } #endregion #region Delete Stream /// /// (Extension Method)
/// Deletes the specified alternate data stream if it exists. ///
/// /// The to inspect. /// /// /// The name of the stream to delete. /// /// /// if the specified stream is deleted; /// otherwise, . /// /// /// is . /// /// /// contains invalid characters. /// /// /// The caller does not have the required permission. /// /// /// The caller does not have the required permission, or the file is read-only. /// /// /// The specified file is in use. /// public static bool DeleteAlternateDataStream(this FileSystemInfo file, string streamName) { if (null == file) throw new ArgumentNullException("file"); SafeNativeMethods.ValidateStreamName(streamName); const FileIOPermissionAccess permAccess = FileIOPermissionAccess.Write; new FileIOPermission(permAccess, file.FullName).Demand(); var result = false; if (file.Exists) { string path = SafeNativeMethods.BuildStreamPath(file.FullName, streamName); if (-1 != SafeNativeMethods.SafeGetFileAttributes(path)) { result = SafeNativeMethods.SafeDeleteFile(path); } } return result; } /// /// Deletes the specified alternate data stream if it exists. /// /// /// The path of the file to inspect. /// /// /// The name of the stream to find. /// /// /// if the specified stream is deleted; /// otherwise, . /// /// /// is or an empty string. /// /// /// is not a valid file path. /// -or- /// contains invalid characters. /// /// /// The caller does not have the required permission. /// /// /// The caller does not have the required permission, or the file is read-only. /// /// /// The specified file is in use. /// public static bool DeleteAlternateDataStream(string filePath, string streamName) { if (string.IsNullOrEmpty(filePath)) throw new ArgumentNullException("filePath"); return CreateInfo(filePath).DeleteAlternateDataStream(streamName); } #endregion } }