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
}
}