mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Add some file system creators
This commit is contained in:
parent
82c5c5d9a0
commit
cb705c5f0f
9 changed files with 363 additions and 2 deletions
|
@ -0,0 +1,99 @@
|
|||
using System.Diagnostics;
|
||||
using LibHac.Fs;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
{
|
||||
public class EmulatedBisFileSystemCreator : IBuiltInStorageFileSystemCreator
|
||||
{
|
||||
private EmulatedBisFileSystemCreatorConfig Config { get; }
|
||||
|
||||
public EmulatedBisFileSystemCreator(IFileSystem rootFileSystem)
|
||||
{
|
||||
Config = new EmulatedBisFileSystemCreatorConfig();
|
||||
Config.RootFileSystem = rootFileSystem;
|
||||
}
|
||||
|
||||
public EmulatedBisFileSystemCreator(EmulatedBisFileSystemCreatorConfig config)
|
||||
{
|
||||
Config = config;
|
||||
}
|
||||
|
||||
public Result Create(out IFileSystem fileSystem, string rootPath, BisPartitionId partitionId)
|
||||
{
|
||||
fileSystem = default;
|
||||
|
||||
if (!IsValidPartitionId(partitionId)) return ResultFs.InvalidArgument;
|
||||
if (rootPath == null) return ResultFs.NullArgument;
|
||||
|
||||
if (Config.TryGetFileSystem(out fileSystem, partitionId))
|
||||
{
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
if (Config.RootFileSystem == null)
|
||||
{
|
||||
return ResultFs.PreconditionViolation;
|
||||
}
|
||||
|
||||
string partitionPath = GetPartitionPath(partitionId);
|
||||
|
||||
Result subFsResult =
|
||||
Util.CreateSubFileSystem(out IFileSystem subFileSystem, Config.RootFileSystem, partitionPath, true);
|
||||
|
||||
if (subFsResult.IsFailure()) return subFsResult;
|
||||
|
||||
if (rootPath == string.Empty)
|
||||
{
|
||||
fileSystem = subFileSystem;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
return Util.CreateSubFileSystemImpl(out fileSystem, subFileSystem, rootPath);
|
||||
}
|
||||
|
||||
public Result CreateFatFileSystem(out IFileSystem fileSystem, BisPartitionId partitionId)
|
||||
{
|
||||
fileSystem = default;
|
||||
return ResultFs.NotImplemented;
|
||||
}
|
||||
|
||||
public Result SetBisRootForHost(BisPartitionId partitionId, string rootPath)
|
||||
{
|
||||
return Config.SetPath(rootPath, partitionId);
|
||||
}
|
||||
|
||||
private bool IsValidPartitionId(BisPartitionId id)
|
||||
{
|
||||
return id >= BisPartitionId.CalibrationFile && id <= BisPartitionId.System;
|
||||
}
|
||||
|
||||
private string GetPartitionPath(BisPartitionId id)
|
||||
{
|
||||
if (Config.TryGetPartitionPath(out string path, id))
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
return GetDefaultPartitionPath(id);
|
||||
}
|
||||
|
||||
private string GetDefaultPartitionPath(BisPartitionId id)
|
||||
{
|
||||
Debug.Assert(IsValidPartitionId(id));
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case BisPartitionId.CalibrationFile:
|
||||
return "/bis/cal";
|
||||
case BisPartitionId.SafeMode:
|
||||
return "/bis/safe";
|
||||
case BisPartitionId.User:
|
||||
return "/bis/user";
|
||||
case BisPartitionId.System:
|
||||
return "/bis/system";
|
||||
default:
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
using System.Diagnostics;
|
||||
using LibHac.Fs;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
{
|
||||
public class EmulatedBisFileSystemCreatorConfig
|
||||
{
|
||||
private const int ValidPartitionCount = 4;
|
||||
|
||||
public IFileSystem RootFileSystem { get; set; }
|
||||
|
||||
private IFileSystem[] PartitionFileSystems { get; } = new IFileSystem[ValidPartitionCount];
|
||||
private string[] PartitionPaths { get; } = new string[ValidPartitionCount];
|
||||
|
||||
public Result SetFileSystem(IFileSystem fileSystem, BisPartitionId partitionId)
|
||||
{
|
||||
if (fileSystem == null) return ResultFs.NullArgument;
|
||||
if (!IsValidPartitionId(partitionId)) return ResultFs.InvalidArgument;
|
||||
|
||||
PartitionFileSystems[GetArrayIndex(partitionId)] = fileSystem;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result SetPath(string path, BisPartitionId partitionId)
|
||||
{
|
||||
if (path == null) return ResultFs.NullArgument;
|
||||
if (!IsValidPartitionId(partitionId)) return ResultFs.InvalidArgument;
|
||||
|
||||
PartitionPaths[GetArrayIndex(partitionId)] = path;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public bool TryGetFileSystem(out IFileSystem fileSystem, BisPartitionId partitionId)
|
||||
{
|
||||
if (!IsValidPartitionId(partitionId))
|
||||
{
|
||||
fileSystem = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
fileSystem = PartitionFileSystems[GetArrayIndex(partitionId)];
|
||||
|
||||
return fileSystem != null;
|
||||
}
|
||||
|
||||
public bool TryGetPartitionPath(out string path, BisPartitionId partitionId)
|
||||
{
|
||||
if (!IsValidPartitionId(partitionId))
|
||||
{
|
||||
path = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
path = PartitionPaths[GetArrayIndex(partitionId)];
|
||||
|
||||
return path != null;
|
||||
}
|
||||
|
||||
private int GetArrayIndex(BisPartitionId id)
|
||||
{
|
||||
Debug.Assert(IsValidPartitionId(id));
|
||||
|
||||
return id - BisPartitionId.CalibrationFile;
|
||||
}
|
||||
|
||||
private bool IsValidPartitionId(BisPartitionId id)
|
||||
{
|
||||
return id >= BisPartitionId.CalibrationFile && id <= BisPartitionId.System;
|
||||
}
|
||||
}
|
||||
}
|
46
src/LibHac/FsService/Creators/EmulatedSdFileSystemCreator.cs
Normal file
46
src/LibHac/FsService/Creators/EmulatedSdFileSystemCreator.cs
Normal file
|
@ -0,0 +1,46 @@
|
|||
using System;
|
||||
using LibHac.Fs;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
{
|
||||
class EmulatedSdFileSystemCreator : ISdFileSystemCreator
|
||||
{
|
||||
private const string DefaultPath = "/sdcard";
|
||||
|
||||
public IFileSystem RootFileSystem { get; set; }
|
||||
public string Path { get; set; }
|
||||
|
||||
public IFileSystem SdCardFileSystem { get; set; }
|
||||
|
||||
public EmulatedSdFileSystemCreator(IFileSystem rootFileSystem)
|
||||
{
|
||||
RootFileSystem = rootFileSystem;
|
||||
}
|
||||
|
||||
public Result Create(out IFileSystem fileSystem)
|
||||
{
|
||||
fileSystem = default;
|
||||
|
||||
if (SdCardFileSystem != null)
|
||||
{
|
||||
fileSystem = SdCardFileSystem;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
if (RootFileSystem == null)
|
||||
{
|
||||
return ResultFs.PreconditionViolation;
|
||||
}
|
||||
|
||||
string path = Path ?? DefaultPath;
|
||||
|
||||
return Util.CreateSubFileSystem(out fileSystem, RootFileSystem, path, true);
|
||||
}
|
||||
|
||||
public Result Format(bool closeOpenEntries)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
33
src/LibHac/FsService/Creators/EncryptedFileSystemCreator.cs
Normal file
33
src/LibHac/FsService/Creators/EncryptedFileSystemCreator.cs
Normal file
|
@ -0,0 +1,33 @@
|
|||
using System;
|
||||
using LibHac.Fs;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
{
|
||||
public class EncryptedFileSystemCreator : IEncryptedFileSystemCreator
|
||||
{
|
||||
private Keyset Keyset { get; }
|
||||
|
||||
public EncryptedFileSystemCreator(Keyset keyset)
|
||||
{
|
||||
Keyset = keyset;
|
||||
}
|
||||
|
||||
public Result Create(out IFileSystem encryptedFileSystem, IFileSystem baseFileSystem, EncryptedFsKeyId keyId,
|
||||
ReadOnlySpan<byte> encryptionSeed)
|
||||
{
|
||||
encryptedFileSystem = default;
|
||||
|
||||
if (keyId < EncryptedFsKeyId.Save || keyId > EncryptedFsKeyId.CustomStorage)
|
||||
{
|
||||
return ResultFs.InvalidArgument;
|
||||
}
|
||||
|
||||
// todo: "proper" key generation instead of a lazy hack
|
||||
Keyset.SetSdSeed(encryptionSeed.ToArray());
|
||||
|
||||
encryptedFileSystem = new AesXtsFileSystem(baseFileSystem, Keyset.SdCardKeys[(int)keyId], 0x4000);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
namespace LibHac.FsService.Creators
|
||||
using LibHac.Fs;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
{
|
||||
public class FileSystemCreators
|
||||
{
|
||||
|
@ -16,5 +18,17 @@
|
|||
public IMemoryStorageCreator MemoryStorageCreator { get; set; }
|
||||
public IBuiltInStorageFileSystemCreator BuiltInStorageFileSystemCreator { get; set; }
|
||||
public ISdFileSystemCreator SdFileSystemCreator { get; set; }
|
||||
|
||||
public static FileSystemCreators GetDefaultEmulatedCreators(IFileSystem rootFileSystem, Keyset keyset)
|
||||
{
|
||||
var creators = new FileSystemCreators();
|
||||
|
||||
creators.SubDirectoryFileSystemCreator = new SubDirectoryFileSystemCreator();
|
||||
creators.EncryptedFileSystemCreator = new EncryptedFileSystemCreator(keyset);
|
||||
creators.BuiltInStorageFileSystemCreator = new EmulatedBisFileSystemCreator(rootFileSystem);
|
||||
creators.SdFileSystemCreator = new EmulatedSdFileSystemCreator(rootFileSystem);
|
||||
|
||||
return creators;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
using LibHac.Fs;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
{
|
||||
public class SubDirectoryFileSystemCreator : ISubDirectoryFileSystemCreator
|
||||
{
|
||||
public Result Create(out IFileSystem subDirFileSystem, IFileSystem baseFileSystem, string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
baseFileSystem.OpenDirectory(path, OpenDirectoryMode.Directories);
|
||||
}
|
||||
catch (HorizonResultException ex)
|
||||
{
|
||||
subDirFileSystem = default;
|
||||
|
||||
return ex.ResultValue;
|
||||
}
|
||||
|
||||
subDirFileSystem = new SubdirectoryFileSystem(baseFileSystem, path);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,6 +13,17 @@ namespace LibHac.FsService
|
|||
public string SaveDataRootPath { get; private set; }
|
||||
public bool AutoCreateSaveData { get; private set; }
|
||||
|
||||
internal FileSystemProxy(FileSystemProxyCore fsProxyCore)
|
||||
{
|
||||
FsProxyCore = fsProxyCore;
|
||||
|
||||
CurrentProcess = -1;
|
||||
SaveDataSize = 0x2000000;
|
||||
SaveDataJournalSize = 0x1000000;
|
||||
SaveDataRootPath = string.Empty;
|
||||
AutoCreateSaveData = true;
|
||||
}
|
||||
|
||||
public Result SetCurrentProcess(long processId)
|
||||
{
|
||||
CurrentProcess = processId;
|
||||
|
|
|
@ -1,6 +1,19 @@
|
|||
namespace LibHac.FsService
|
||||
using LibHac.FsService.Creators;
|
||||
|
||||
namespace LibHac.FsService
|
||||
{
|
||||
public class FileSystemService
|
||||
{
|
||||
private FileSystemProxyCore FsProxyCore { get; }
|
||||
|
||||
public FileSystemService(FileSystemCreators fsCreators)
|
||||
{
|
||||
FsProxyCore = new FileSystemProxyCore(fsCreators);
|
||||
}
|
||||
|
||||
public FileSystemProxy CreateFileSystemProxyService()
|
||||
{
|
||||
return new FileSystemProxy(FsProxyCore);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
47
src/LibHac/FsService/Util.cs
Normal file
47
src/LibHac/FsService/Util.cs
Normal file
|
@ -0,0 +1,47 @@
|
|||
using LibHac.Fs;
|
||||
|
||||
namespace LibHac.FsService
|
||||
{
|
||||
public static class Util
|
||||
{
|
||||
public static Result CreateSubFileSystem(out IFileSystem subFileSystem, IFileSystem baseFileSystem, string path,
|
||||
bool createPathIfMissing)
|
||||
{
|
||||
subFileSystem = default;
|
||||
|
||||
if (!createPathIfMissing)
|
||||
{
|
||||
if (path == null) return ResultFs.NullArgument;
|
||||
|
||||
if (baseFileSystem.GetEntryType(path) != DirectoryEntryType.Directory)
|
||||
{
|
||||
return ResultFs.PathNotFound;
|
||||
}
|
||||
}
|
||||
|
||||
baseFileSystem.EnsureDirectoryExists(path);
|
||||
|
||||
return CreateSubFileSystemImpl(out subFileSystem, baseFileSystem, path);
|
||||
}
|
||||
|
||||
public static Result CreateSubFileSystemImpl(out IFileSystem subFileSystem, IFileSystem baseFileSystem, string path)
|
||||
{
|
||||
subFileSystem = default;
|
||||
|
||||
if (path == null) return ResultFs.NullArgument;
|
||||
|
||||
try
|
||||
{
|
||||
baseFileSystem.OpenDirectory(path, OpenDirectoryMode.Directories);
|
||||
}
|
||||
catch (HorizonResultException ex)
|
||||
{
|
||||
return ex.ResultValue;
|
||||
}
|
||||
|
||||
subFileSystem = new SubdirectoryFileSystem(baseFileSystem, path);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue