mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Rewrite SubdirectoryFileSystem
This commit is contained in:
parent
1c28c08c94
commit
ecf7bcd8ad
7 changed files with 234 additions and 61 deletions
|
@ -74,7 +74,13 @@ namespace LibHac.Common
|
|||
|
||||
public U8String ToU8String()
|
||||
{
|
||||
return new U8String(_buffer.ToArray());
|
||||
int length = StringUtils.GetLength(_buffer);
|
||||
|
||||
// Allocate an extra byte for the null terminator
|
||||
var buffer = new byte[length + 1];
|
||||
_buffer.Slice(0, length).CopyTo(buffer);
|
||||
|
||||
return new U8String(buffer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -41,7 +41,9 @@ namespace LibHac.FsService.Creators
|
|||
// Actual FS does this check
|
||||
// if (!allowDirectorySaveData) return ResultFs.InvalidSaveDataEntryType.Log();
|
||||
|
||||
var subDirFs = new SubdirectoryFileSystem(sourceFileSystem, saveDataPath);
|
||||
rc = SubdirectoryFileSystem.CreateNew(out SubdirectoryFileSystem subDirFs, sourceFileSystem, saveDataPath.ToU8String());
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
bool isPersistentSaveData = type != SaveDataType.Temporary;
|
||||
bool isUserSaveData = type == SaveDataType.Account || type == SaveDataType.Device;
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using LibHac.Fs;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.FsSystem;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
|
@ -12,9 +13,9 @@ namespace LibHac.FsService.Creators
|
|||
Result rc = baseFileSystem.OpenDirectory(out IDirectory _, path, OpenDirectoryMode.Directory);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
subDirFileSystem = new SubdirectoryFileSystem(baseFileSystem, path);
|
||||
|
||||
return Result.Success;
|
||||
rc = SubdirectoryFileSystem.CreateNew(out SubdirectoryFileSystem fs, baseFileSystem, path.ToU8String());
|
||||
subDirFileSystem = fs;
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using LibHac.Fs;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.FsSystem;
|
||||
|
||||
namespace LibHac.FsService
|
||||
|
@ -36,9 +37,9 @@ namespace LibHac.FsService
|
|||
Result rc = baseFileSystem.OpenDirectory(out IDirectory _, path, OpenDirectoryMode.Directory);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
subFileSystem = new SubdirectoryFileSystem(baseFileSystem, path);
|
||||
|
||||
return Result.Success;
|
||||
rc = SubdirectoryFileSystem.CreateNew(out SubdirectoryFileSystem fs, baseFileSystem, path.ToU8String());
|
||||
subFileSystem = fs;
|
||||
return rc;
|
||||
}
|
||||
|
||||
public static bool UseDeviceUniqueSaveMac(SaveDataSpaceId spaceId)
|
||||
|
|
|
@ -1,134 +1,263 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
public class SubdirectoryFileSystem : FileSystemBase
|
||||
{
|
||||
private string RootPath { get; }
|
||||
private IFileSystem ParentFileSystem { get; }
|
||||
private IFileSystem BaseFileSystem { get; }
|
||||
private U8String RootPath { get; set; }
|
||||
private bool PreserveUnc { get; }
|
||||
|
||||
private string ResolveFullPath(string path)
|
||||
public static Result CreateNew(out SubdirectoryFileSystem created, IFileSystem baseFileSystem, U8Span rootPath, bool preserveUnc = false)
|
||||
{
|
||||
return PathTools.Combine(RootPath, path);
|
||||
var obj = new SubdirectoryFileSystem(baseFileSystem, preserveUnc);
|
||||
Result rc = obj.Initialize(rootPath);
|
||||
|
||||
if (rc.IsSuccess())
|
||||
{
|
||||
created = obj;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
obj.Dispose();
|
||||
created = default;
|
||||
return rc;
|
||||
}
|
||||
|
||||
public SubdirectoryFileSystem(IFileSystem fs, string rootPath)
|
||||
public SubdirectoryFileSystem(IFileSystem baseFileSystem, bool preserveUnc = false)
|
||||
{
|
||||
ParentFileSystem = fs;
|
||||
RootPath = PathTools.Normalize(rootPath);
|
||||
BaseFileSystem = baseFileSystem;
|
||||
PreserveUnc = preserveUnc;
|
||||
}
|
||||
|
||||
private Result Initialize(U8Span rootPath)
|
||||
{
|
||||
if (StringUtils.GetLength(rootPath, PathTools.MaxPathLength + 1) > PathTools.MaxPathLength)
|
||||
return ResultFs.TooLongPath.Log();
|
||||
|
||||
Span<byte> normalizedPath = stackalloc byte[PathTools.MaxPathLength + 2];
|
||||
|
||||
Result rc = PathTool.Normalize(normalizedPath, out long normalizedPathLen, rootPath, PreserveUnc, false);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
// Ensure a trailing separator
|
||||
if (!PathTool.IsSeparator(normalizedPath[(int)normalizedPathLen - 1]))
|
||||
{
|
||||
Debug.Assert(normalizedPathLen + 2 <= normalizedPath.Length);
|
||||
|
||||
normalizedPath[(int)normalizedPathLen] = StringTraits.DirectorySeparator;
|
||||
normalizedPath[(int)normalizedPathLen + 1] = StringTraits.NullTerminator;
|
||||
normalizedPathLen++;
|
||||
}
|
||||
|
||||
var buffer = new byte[normalizedPathLen + 1];
|
||||
normalizedPath.Slice(0, (int)normalizedPathLen).CopyTo(buffer);
|
||||
RootPath = new U8String(buffer);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private Result ResolveFullPath(Span<byte> outPath, U8Span relativePath)
|
||||
{
|
||||
if (RootPath.Length + StringUtils.GetLength(relativePath, PathTools.MaxPathLength + 1) > outPath.Length)
|
||||
return ResultFs.TooLongPath.Log();
|
||||
|
||||
// Copy root path to the output
|
||||
RootPath.Value.CopyTo(outPath);
|
||||
|
||||
// Copy the normalized relative path to the output
|
||||
return PathTool.Normalize(outPath.Slice(RootPath.Length - 2), out _, relativePath, PreserveUnc, false);
|
||||
}
|
||||
|
||||
protected override Result CreateDirectoryImpl(string path)
|
||||
{
|
||||
string fullPath = ResolveFullPath(PathTools.Normalize(path));
|
||||
var u8Path = new U8String(path);
|
||||
|
||||
return ParentFileSystem.CreateDirectory(fullPath);
|
||||
Span<byte> fullPath = stackalloc byte[PathTools.MaxPathLength + 1];
|
||||
Result rc = ResolveFullPath(fullPath, u8Path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFileSystem.CreateDirectory(StringUtils.Utf8ZToString(fullPath));
|
||||
}
|
||||
|
||||
protected override Result CreateFileImpl(string path, long size, CreateFileOptions options)
|
||||
{
|
||||
string fullPath = ResolveFullPath(PathTools.Normalize(path));
|
||||
var u8Path = new U8String(path);
|
||||
|
||||
return ParentFileSystem.CreateFile(fullPath, size, options);
|
||||
Span<byte> fullPath = stackalloc byte[PathTools.MaxPathLength + 1];
|
||||
Result rc = ResolveFullPath(fullPath, u8Path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFileSystem.CreateFile(StringUtils.Utf8ZToString(fullPath), size, options);
|
||||
}
|
||||
|
||||
protected override Result DeleteDirectoryImpl(string path)
|
||||
{
|
||||
string fullPath = ResolveFullPath(PathTools.Normalize(path));
|
||||
var u8Path = new U8String(path);
|
||||
|
||||
return ParentFileSystem.DeleteDirectory(fullPath);
|
||||
Span<byte> fullPath = stackalloc byte[PathTools.MaxPathLength + 1];
|
||||
Result rc = ResolveFullPath(fullPath, u8Path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFileSystem.DeleteDirectory(StringUtils.Utf8ZToString(fullPath));
|
||||
}
|
||||
|
||||
protected override Result DeleteDirectoryRecursivelyImpl(string path)
|
||||
{
|
||||
string fullPath = ResolveFullPath(PathTools.Normalize(path));
|
||||
var u8Path = new U8String(path);
|
||||
|
||||
return ParentFileSystem.DeleteDirectoryRecursively(fullPath);
|
||||
Span<byte> fullPath = stackalloc byte[PathTools.MaxPathLength + 1];
|
||||
Result rc = ResolveFullPath(fullPath, u8Path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFileSystem.DeleteDirectoryRecursively(StringUtils.Utf8ZToString(fullPath));
|
||||
}
|
||||
|
||||
protected override Result CleanDirectoryRecursivelyImpl(string path)
|
||||
{
|
||||
string fullPath = ResolveFullPath(PathTools.Normalize(path));
|
||||
var u8Path = new U8String(path);
|
||||
|
||||
return ParentFileSystem.CleanDirectoryRecursively(fullPath);
|
||||
Span<byte> fullPath = stackalloc byte[PathTools.MaxPathLength + 1];
|
||||
Result rc = ResolveFullPath(fullPath, u8Path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFileSystem.CleanDirectoryRecursively(StringUtils.Utf8ZToString(fullPath));
|
||||
}
|
||||
|
||||
protected override Result DeleteFileImpl(string path)
|
||||
{
|
||||
string fullPath = ResolveFullPath(PathTools.Normalize(path));
|
||||
var u8Path = new U8String(path);
|
||||
|
||||
return ParentFileSystem.DeleteFile(fullPath);
|
||||
Span<byte> fullPath = stackalloc byte[PathTools.MaxPathLength + 1];
|
||||
Result rc = ResolveFullPath(fullPath, u8Path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFileSystem.DeleteFile(StringUtils.Utf8ZToString(fullPath));
|
||||
}
|
||||
|
||||
protected override Result OpenDirectoryImpl(out IDirectory directory, string path, OpenDirectoryMode mode)
|
||||
{
|
||||
string fullPath = ResolveFullPath(PathTools.Normalize(path));
|
||||
directory = default;
|
||||
var u8Path = new U8String(path);
|
||||
|
||||
return ParentFileSystem.OpenDirectory(out directory, fullPath, mode);
|
||||
Span<byte> fullPath = stackalloc byte[PathTools.MaxPathLength + 1];
|
||||
Result rc = ResolveFullPath(fullPath, u8Path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFileSystem.OpenDirectory(out directory, StringUtils.Utf8ZToString(fullPath), mode);
|
||||
}
|
||||
|
||||
protected override Result OpenFileImpl(out IFile file, string path, OpenMode mode)
|
||||
{
|
||||
string fullPath = ResolveFullPath(PathTools.Normalize(path));
|
||||
file = default;
|
||||
var u8Path = new U8String(path);
|
||||
|
||||
return ParentFileSystem.OpenFile(out file, fullPath, mode);
|
||||
Span<byte> fullPath = stackalloc byte[PathTools.MaxPathLength + 1];
|
||||
Result rc = ResolveFullPath(fullPath, u8Path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFileSystem.OpenFile(out file, StringUtils.Utf8ZToString(fullPath), mode);
|
||||
}
|
||||
|
||||
protected override Result RenameDirectoryImpl(string oldPath, string newPath)
|
||||
{
|
||||
string fullOldPath = ResolveFullPath(PathTools.Normalize(oldPath));
|
||||
string fullNewPath = ResolveFullPath(PathTools.Normalize(newPath));
|
||||
var u8OldPath = new U8String(oldPath);
|
||||
var u8NewPath = new U8String(newPath);
|
||||
|
||||
return ParentFileSystem.RenameDirectory(fullOldPath, fullNewPath);
|
||||
Span<byte> fullOldPath = stackalloc byte[PathTools.MaxPathLength + 1];
|
||||
Span<byte> fullNewPath = stackalloc byte[PathTools.MaxPathLength + 1];
|
||||
|
||||
Result rc = ResolveFullPath(fullOldPath, u8OldPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = ResolveFullPath(fullNewPath, u8NewPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFileSystem.RenameDirectory(StringUtils.Utf8ZToString(fullOldPath), StringUtils.Utf8ZToString(fullNewPath));
|
||||
}
|
||||
|
||||
protected override Result RenameFileImpl(string oldPath, string newPath)
|
||||
{
|
||||
string fullOldPath = ResolveFullPath(PathTools.Normalize(oldPath));
|
||||
string fullNewPath = ResolveFullPath(PathTools.Normalize(newPath));
|
||||
var u8OldPath = new U8String(oldPath);
|
||||
var u8NewPath = new U8String(newPath);
|
||||
|
||||
return ParentFileSystem.RenameFile(fullOldPath, fullNewPath);
|
||||
Span<byte> fullOldPath = stackalloc byte[PathTools.MaxPathLength + 1];
|
||||
Span<byte> fullNewPath = stackalloc byte[PathTools.MaxPathLength + 1];
|
||||
|
||||
Result rc = ResolveFullPath(fullOldPath, u8OldPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = ResolveFullPath(fullNewPath, u8NewPath);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFileSystem.RenameFile(StringUtils.Utf8ZToString(fullOldPath), StringUtils.Utf8ZToString(fullNewPath));
|
||||
}
|
||||
|
||||
protected override Result GetEntryTypeImpl(out DirectoryEntryType entryType, string path)
|
||||
{
|
||||
string fullPath = ResolveFullPath(PathTools.Normalize(path));
|
||||
entryType = default;
|
||||
var u8Path = new U8String(path);
|
||||
|
||||
return ParentFileSystem.GetEntryType(out entryType, fullPath);
|
||||
Span<byte> fullPath = stackalloc byte[PathTools.MaxPathLength + 1];
|
||||
Result rc = ResolveFullPath(fullPath, u8Path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFileSystem.GetEntryType(out entryType, StringUtils.Utf8ZToString(fullPath));
|
||||
}
|
||||
|
||||
protected override Result CommitImpl()
|
||||
{
|
||||
return ParentFileSystem.Commit();
|
||||
return BaseFileSystem.Commit();
|
||||
}
|
||||
|
||||
protected override Result GetFreeSpaceSizeImpl(out long freeSpace, string path)
|
||||
{
|
||||
string fullPath = ResolveFullPath(PathTools.Normalize(path));
|
||||
freeSpace = default;
|
||||
var u8Path = new U8String(path);
|
||||
|
||||
return ParentFileSystem.GetFreeSpaceSize(out freeSpace, fullPath);
|
||||
Span<byte> fullPath = stackalloc byte[PathTools.MaxPathLength + 1];
|
||||
Result rc = ResolveFullPath(fullPath, u8Path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFileSystem.GetFreeSpaceSize(out freeSpace, StringUtils.Utf8ZToString(fullPath));
|
||||
}
|
||||
|
||||
protected override Result GetTotalSpaceSizeImpl(out long totalSpace, string path)
|
||||
{
|
||||
string fullPath = ResolveFullPath(PathTools.Normalize(path));
|
||||
totalSpace = default;
|
||||
var u8Path = new U8String(path);
|
||||
|
||||
return ParentFileSystem.GetTotalSpaceSize(out totalSpace, fullPath);
|
||||
Span<byte> fullPath = stackalloc byte[PathTools.MaxPathLength + 1];
|
||||
Result rc = ResolveFullPath(fullPath, u8Path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFileSystem.GetTotalSpaceSize(out totalSpace, StringUtils.Utf8ZToString(fullPath));
|
||||
}
|
||||
|
||||
protected override Result GetFileTimeStampRawImpl(out FileTimeStampRaw timeStamp, string path)
|
||||
{
|
||||
string fullPath = ResolveFullPath(PathTools.Normalize(path));
|
||||
timeStamp = default;
|
||||
var u8Path = new U8String(path);
|
||||
|
||||
return ParentFileSystem.GetFileTimeStampRaw(out timeStamp, fullPath);
|
||||
Span<byte> fullPath = stackalloc byte[PathTools.MaxPathLength + 1];
|
||||
Result rc = ResolveFullPath(fullPath, u8Path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFileSystem.GetFileTimeStampRaw(out timeStamp, StringUtils.Utf8ZToString(fullPath));
|
||||
}
|
||||
|
||||
protected override Result QueryEntryImpl(Span<byte> outBuffer, ReadOnlySpan<byte> inBuffer, QueryId queryId, string path)
|
||||
{
|
||||
string fullPath = ResolveFullPath(PathTools.Normalize(path));
|
||||
var u8Path = new U8String(path);
|
||||
|
||||
return ParentFileSystem.QueryEntry(outBuffer, inBuffer, queryId, fullPath);
|
||||
Span<byte> fullPath = stackalloc byte[PathTools.MaxPathLength + 1];
|
||||
Result rc = ResolveFullPath(fullPath, u8Path);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseFileSystem.QueryEntry(outBuffer, inBuffer, queryId, StringUtils.Utf8ZToString(fullPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.FsSystem;
|
||||
using LibHac.FsSystem.NcaUtils;
|
||||
|
@ -38,12 +39,12 @@ namespace LibHac
|
|||
public static SwitchFs OpenSdCard(Keyset keyset, IAttributeFileSystem fileSystem)
|
||||
{
|
||||
var concatFs = new ConcatenationFileSystem(fileSystem);
|
||||
var contentDirFs = new SubdirectoryFileSystem(concatFs, "/Nintendo/Contents");
|
||||
SubdirectoryFileSystem.CreateNew(out SubdirectoryFileSystem contentDirFs, concatFs, "/Nintendo/Contents".ToU8String()).ThrowIfFailure();
|
||||
|
||||
AesXtsFileSystem encSaveFs = null;
|
||||
if (fileSystem.DirectoryExists("/Nintendo/save"))
|
||||
{
|
||||
var saveDirFs = new SubdirectoryFileSystem(concatFs, "/Nintendo/save");
|
||||
SubdirectoryFileSystem.CreateNew(out SubdirectoryFileSystem saveDirFs, concatFs, "/Nintendo/save".ToU8String()).ThrowIfFailure();
|
||||
encSaveFs = new AesXtsFileSystem(saveDirFs, keyset.SdCardKeys[0], 0x4000);
|
||||
}
|
||||
|
||||
|
@ -55,8 +56,14 @@ namespace LibHac
|
|||
public static SwitchFs OpenNandPartition(Keyset keyset, IAttributeFileSystem fileSystem)
|
||||
{
|
||||
var concatFs = new ConcatenationFileSystem(fileSystem);
|
||||
IFileSystem saveDirFs = concatFs.DirectoryExists("/save") ? new SubdirectoryFileSystem(concatFs, "/save") : null;
|
||||
var contentDirFs = new SubdirectoryFileSystem(concatFs, "/Contents");
|
||||
SubdirectoryFileSystem saveDirFs = null;
|
||||
|
||||
if (concatFs.DirectoryExists("/save"))
|
||||
{
|
||||
SubdirectoryFileSystem.CreateNew(out saveDirFs, concatFs, "/save".ToU8String()).ThrowIfFailure();
|
||||
}
|
||||
|
||||
SubdirectoryFileSystem.CreateNew(out SubdirectoryFileSystem contentDirFs, concatFs, "/Contents".ToU8String()).ThrowIfFailure();
|
||||
|
||||
return new SwitchFs(keyset, contentDirFs, saveDirFs);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
using System.Diagnostics;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.FsSystem;
|
||||
using LibHac.Tests.Fs.IFileSystemTestBase;
|
||||
using Xunit;
|
||||
|
||||
namespace LibHac.Tests.Fs
|
||||
{
|
||||
|
@ -9,25 +10,51 @@ namespace LibHac.Tests.Fs
|
|||
{
|
||||
protected override IFileSystem CreateFileSystem()
|
||||
{
|
||||
Trace.Listeners.Clear();
|
||||
return CreateFileSystemInternal().subDirFs;
|
||||
}
|
||||
|
||||
private (IFileSystem baseFs, IFileSystem subDirFs) CreateFileSystemInternal()
|
||||
{
|
||||
var baseFs = new InMemoryFileSystem();
|
||||
baseFs.CreateDirectory("/sub");
|
||||
baseFs.CreateDirectory("/sub/path");
|
||||
|
||||
var subFs = new SubdirectoryFileSystem(baseFs, "/sub/path");
|
||||
SubdirectoryFileSystem.CreateNew(out SubdirectoryFileSystem subFs, baseFs, "/sub/path".ToU8String()).ThrowIfFailure();
|
||||
return (baseFs, subFs);
|
||||
}
|
||||
|
||||
return subFs;
|
||||
[Fact]
|
||||
public void CreateFile_CreatedInBaseFileSystem()
|
||||
{
|
||||
(IFileSystem baseFs, IFileSystem subDirFs) = CreateFileSystemInternal();
|
||||
|
||||
subDirFs.CreateFile("/file", 0, CreateFileOptions.None);
|
||||
Result rc = baseFs.GetEntryType(out DirectoryEntryType type, "/sub/path/file");
|
||||
|
||||
Assert.True(rc.IsSuccess());
|
||||
Assert.Equal(DirectoryEntryType.File, type);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateDirectory_CreatedInBaseFileSystem()
|
||||
{
|
||||
(IFileSystem baseFs, IFileSystem subDirFs) = CreateFileSystemInternal();
|
||||
|
||||
subDirFs.CreateDirectory("/dir");
|
||||
Result rc = baseFs.GetEntryType(out DirectoryEntryType type, "/sub/path/dir");
|
||||
|
||||
Assert.True(rc.IsSuccess());
|
||||
Assert.Equal(DirectoryEntryType.Directory, type);
|
||||
}
|
||||
}
|
||||
|
||||
public class SubdirectoryFileSystemTestsRoot : IFileSystemTests
|
||||
{
|
||||
protected override IFileSystem CreateFileSystem()
|
||||
{
|
||||
Trace.Listeners.Clear();
|
||||
var baseFs = new InMemoryFileSystem();
|
||||
|
||||
var subFs = new SubdirectoryFileSystem(baseFs, "/");
|
||||
|
||||
SubdirectoryFileSystem.CreateNew(out SubdirectoryFileSystem subFs, baseFs, "/".ToU8String()).ThrowIfFailure();
|
||||
return subFs;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue