/// <summary> /// Represents an open file in the runtime of Kuriimu. /// </summary> /// <param name="filePlugin">The entry class of the plugin for this file.</param> /// <param name="pluginState">The plugin state of this file.</param> /// <param name="parentState">The parent state for this file.</param> /// <param name="fileSystem">The file system around the initially opened file.</param> /// <param name="filePath">The path of the file to be opened in the file system.</param> /// <param name="streamManager">The stream manager used for this opened state.</param> /// <param name="pluginManager">The plugin manager for this state.</param> public StateInfo(IFilePlugin filePlugin, IPluginState pluginState, IStateInfo parentState, IFileSystem fileSystem, UPath filePath, IStreamManager streamManager, IPluginManager pluginManager) { ContractAssertions.IsNotNull(filePlugin, nameof(filePlugin)); ContractAssertions.IsNotNull(pluginState, nameof(pluginState)); ContractAssertions.IsNotNull(fileSystem, nameof(fileSystem)); ContractAssertions.IsNotNull(streamManager, nameof(streamManager)); ContractAssertions.IsNotNull(pluginManager, nameof(pluginManager)); if (filePath == UPath.Empty || filePath.IsDirectory) { throw new InvalidOperationException($"'{filePath}' has to be a path to a file."); } if (!fileSystem.FileExists(filePath)) { throw FileSystemExceptionHelper.NewFileNotFoundException(filePath); } FilePlugin = filePlugin; PluginState = pluginState; FilePath = filePath; FileSystem = fileSystem; StreamManager = streamManager; PluginManager = pluginManager; ParentStateInfo = parentState; ArchiveChildren = new List <IStateInfo>(); }
/// <inheritdoc /> public void ReplaceFile(UPath srcPath, UPath destPath, UPath destBackupPath, bool ignoreMetadataErrors) { AssertNotDisposed(); AssertTrue(CanReplaceFiles, nameof(ReplaceFile)); srcPath = ValidatePath(srcPath, nameof(srcPath)); destPath = ValidatePath(destPath, nameof(destPath)); destBackupPath = ValidatePath(destBackupPath, nameof(destBackupPath), true); if (!FileExistsImpl(srcPath)) { throw FileSystemExceptionHelper.NewFileNotFoundException(srcPath); } if (!FileExistsImpl(destPath)) { throw FileSystemExceptionHelper.NewFileNotFoundException(srcPath); } if (destBackupPath == srcPath) { throw new IOException($"The source and backup cannot have the same path `{srcPath}`"); } ReplaceFileImpl(srcPath, destPath, destBackupPath, ignoreMetadataErrors); }
/// <summary> /// Initializes a new instance of the <see cref="SubFileSystem"/> class. /// </summary> /// <param name="fileSystem">The file system to create a view from.</param> /// <param name="subPath">The sub path view to create filesystem.</param> /// <param name="owned">True if <paramref name="fileSystem"/> should be disposed when this instance is disposed.</param> /// <exception cref="DirectoryNotFoundException">If the directory subPath does not exist in the delegate FileSystem</exception> public SubFileSystem(IFileSystem fileSystem, UPath subPath, bool owned = true) : base(fileSystem, owned) { SubPath = subPath.AssertAbsolute(nameof(subPath)); if (!fileSystem.DirectoryExists(SubPath)) { throw FileSystemExceptionHelper.NewDirectoryNotFoundException(SubPath); } }
/// <inheritdoc /> protected override void DeleteDirectoryImpl(UPath path, bool isRecursive) { if (IsWithinSpecialDirectory(path)) { if (!SpecialDirectoryExists(path)) { throw FileSystemExceptionHelper.NewDirectoryNotFoundException(path); } throw new UnauthorizedAccessException($"Cannot delete directory `{path}`"); } Directory.Delete(ConvertPathToInternal(path), isRecursive); }
/// <inheritdoc /> protected override void MoveDirectoryImpl(UPath srcPath, UPath destPath) { if (IsOnWindows) { if (IsWithinSpecialDirectory(srcPath)) { if (!SpecialDirectoryExists(srcPath)) { throw FileSystemExceptionHelper.NewDirectoryNotFoundException(srcPath); } throw new UnauthorizedAccessException($"Cannot move the special directory `{srcPath}`"); } if (IsWithinSpecialDirectory(destPath)) { if (!SpecialDirectoryExists(destPath)) { throw FileSystemExceptionHelper.NewDirectoryNotFoundException(destPath); } throw new UnauthorizedAccessException($"Cannot move to the special directory `{destPath}`"); } } var systemSrcPath = ConvertPathToInternal(srcPath); var systemDestPath = ConvertPathToInternal(destPath); // If the source path is a file var fileInfo = new FileInfo(systemSrcPath); if (fileInfo.Exists) { throw new IOException($"The source `{srcPath}` is not a directory"); } Directory.Move(systemSrcPath, systemDestPath); }
// ---------------------------------------------- // Search API // ---------------------------------------------- /// <inheritdoc /> protected override IEnumerable <UPath> EnumeratePathsImpl(UPath path, string searchPattern, SearchOption searchOption, SearchTarget searchTarget) { // Special case for Windows as we need to provide list for: // - the root folder / (which should just return the /drive folder) // - the drive folders /drive/c, drive/e...etc. var search = SearchPattern.Parse(ref path, ref searchPattern); if (IsOnWindows) { if (IsWithinSpecialDirectory(path)) { if (!SpecialDirectoryExists(path)) { throw FileSystemExceptionHelper.NewDirectoryNotFoundException(path); } var searchForDirectory = searchTarget == SearchTarget.Both || searchTarget == SearchTarget.Directory; // Only sub folder "/drive/" on root folder / if (path == UPath.Root) { if (!searchForDirectory) { yield break; } yield return(PathDrivePrefixOnWindows); if (searchOption != SearchOption.AllDirectories) { yield break; } foreach (var subPath in EnumeratePathsImpl(PathDrivePrefixOnWindows, searchPattern, searchOption, searchTarget)) { yield return(subPath); } yield break; } // When listing for /drive, return the list of drives available if (path == PathDrivePrefixOnWindows) { var pathDrives = new List <UPath>(); foreach (var drive in DriveInfo.GetDrives()) { if (drive.Name.Length < 2 || drive.Name[1] != ':') { continue; } var pathDrive = PathDrivePrefixOnWindows / char.ToLowerInvariant(drive.Name[0]).ToString(); if (search.Match(pathDrive)) { pathDrives.Add(pathDrive); if (searchForDirectory) { yield return(pathDrive); } } } if (searchOption == SearchOption.AllDirectories) { foreach (var pathDrive in pathDrives) { foreach (var subPath in EnumeratePathsImpl(pathDrive, searchPattern, searchOption, searchTarget)) { yield return(subPath); } } } yield break; } } } IEnumerable <string> results; switch (searchTarget) { case SearchTarget.File: results = Directory.EnumerateFiles(ConvertPathToInternal(path), searchPattern, searchOption); break; case SearchTarget.Directory: results = Directory.EnumerateDirectories(ConvertPathToInternal(path), searchPattern, searchOption); break; case SearchTarget.Both: results = Directory.EnumerateFileSystemEntries(ConvertPathToInternal(path), searchPattern, searchOption); break; default: yield break; } foreach (var subPath in results) { // Windows will truncate the search pattern's extension to three characters if the filesystem // has 8.3 paths enabled. This means searching for *.docx will list *.doc as well which is // not what we want. Check against the search pattern again to filter out those false results. if (!IsOnWindows || search.Match(Path.GetFileName(subPath))) { yield return(ConvertPathFromInternal(subPath)); } } }