mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Add OpenSaveDataFileSystemBySystemSaveDataId
This commit is contained in:
parent
d610d2262b
commit
d6165d1097
10 changed files with 248 additions and 2 deletions
|
@ -33,6 +33,7 @@ namespace LibHac.Fs
|
|||
}
|
||||
else
|
||||
{
|
||||
// todo: FS returns invalid file entries with a size of 0
|
||||
long size = GetAesXtsFileSize(entry.FullPath);
|
||||
if (size == -1) continue;
|
||||
|
||||
|
|
|
@ -42,4 +42,15 @@
|
|||
Secure = 1,
|
||||
Writable = 2
|
||||
}
|
||||
|
||||
public enum SaveDataSpaceId
|
||||
{
|
||||
System = 0,
|
||||
User = 1,
|
||||
SdSystem = 2,
|
||||
TemporaryStorage = 3,
|
||||
SdCache = 4,
|
||||
ProperSystem = 100,
|
||||
Safe = 101
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
public static Result InsufficientFreeSpace => new Result(ModuleFs, 30);
|
||||
public static Result MountNameAlreadyExists => new Result(ModuleFs, 60);
|
||||
|
||||
public static Result ResultPartitionNotFound => new Result(ModuleFs, 1002);
|
||||
public static Result TargetNotFound => new Result(ModuleFs, 1002);
|
||||
|
||||
public static Result NotImplemented => new Result(ModuleFs, 3001);
|
||||
public static Result Result3002 => new Result(ModuleFs, 3002);
|
||||
public static Result SaveDataPathAlreadyExists => new Result(ModuleFs, 3003);
|
||||
|
|
|
@ -8,6 +8,8 @@ namespace LibHac.FsService.Creators
|
|||
public IPartitionFileSystemCreator PartitionFileSystemCreator { get; set; }
|
||||
public IStorageOnNcaCreator StorageOnNcaCreator { get; set; }
|
||||
public IFatFileSystemCreator FatFileSystemCreator { get; set; }
|
||||
public IHostFileSystemCreator HostFileSystemCreator { get; set; }
|
||||
public ITargetManagerFileSystemCreator TargetManagerFileSystemCreator { get; set; }
|
||||
public ISubDirectoryFileSystemCreator SubDirectoryFileSystemCreator { get; set; }
|
||||
public IBuiltInStorageCreator BuiltInStorageCreator { get; set; }
|
||||
public ISdStorageCreator SdStorageCreator { get; set; }
|
||||
|
|
10
src/LibHac/FsService/Creators/IHostFileSystemCreator.cs
Normal file
10
src/LibHac/FsService/Creators/IHostFileSystemCreator.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
using LibHac.Fs;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
{
|
||||
public interface IHostFileSystemCreator
|
||||
{
|
||||
Result Create(out IFileSystem fileSystem, bool someBool);
|
||||
Result Create(out IFileSystem fileSystem, string path, bool someBool);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
using LibHac.Fs;
|
||||
|
||||
namespace LibHac.FsService.Creators
|
||||
{
|
||||
public interface ITargetManagerFileSystemCreator
|
||||
{
|
||||
Result Create(out IFileSystem fileSystem, bool someBool);
|
||||
Result GetCaseSensitivePath(out bool isSuccess, ref string path);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
|
||||
namespace LibHac.FsService
|
||||
|
@ -13,6 +14,8 @@ namespace LibHac.FsService
|
|||
public string SaveDataRootPath { get; private set; }
|
||||
public bool AutoCreateSaveData { get; private set; }
|
||||
|
||||
private const ulong SaveIndexerId = 0x8000000000000000;
|
||||
|
||||
internal FileSystemProxy(FileSystemProxyCore fsProxyCore)
|
||||
{
|
||||
FsProxyCore = fsProxyCore;
|
||||
|
@ -86,10 +89,29 @@ namespace LibHac.FsService
|
|||
return FsProxyCore.OpenContentStorageFileSystem(out fileSystem, storageId);
|
||||
}
|
||||
|
||||
public Result OpenSaveDataFileSystemBySystemSaveDataId(out IFileSystem fileSystem, SaveDataSpaceId spaceId,
|
||||
SaveDataAttribute attribute)
|
||||
{
|
||||
// Missing permission check, speed emulation storage type wrapper, and FileSystemInterfaceAdapter
|
||||
fileSystem = default;
|
||||
|
||||
if (!IsSystemSaveDataId(attribute.SaveId)) return ResultFs.InvalidArgument.Log();
|
||||
|
||||
Result saveFsResult = OpenSaveDataFileSystemImpl(out IFileSystem saveFs, out ulong saveDataId, spaceId,
|
||||
attribute, false, true);
|
||||
if (saveFsResult.IsFailure()) return saveFsResult.Log();
|
||||
|
||||
// Missing check if the current title owns the save data or can open it
|
||||
|
||||
fileSystem = saveFs;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result SetSdCardEncryptionSeed(ReadOnlySpan<byte> seed)
|
||||
{
|
||||
// todo: use struct instead of byte span
|
||||
if (seed.Length != 0x16) return ResultFs.InvalidSize;
|
||||
if (seed.Length != 0x10) return ResultFs.InvalidSize;
|
||||
|
||||
// Missing permission check
|
||||
|
||||
|
@ -100,5 +122,42 @@ namespace LibHac.FsService
|
|||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private Result OpenSaveDataFileSystemImpl(out IFileSystem fileSystem, out ulong saveDataId,
|
||||
SaveDataSpaceId spaceId, SaveDataAttribute attribute, bool openReadOnly, bool cacheExtraData)
|
||||
{
|
||||
bool hasFixedId = attribute.SaveId != 0 && attribute.UserId.Id == Id128.InvalidId;
|
||||
|
||||
if (hasFixedId)
|
||||
{
|
||||
saveDataId = attribute.SaveId;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
Result saveFsResult = FsProxyCore.OpenSaveDataFileSystem(out fileSystem, spaceId, saveDataId,
|
||||
SaveDataRootPath, openReadOnly, attribute.Type, cacheExtraData);
|
||||
|
||||
if (saveFsResult.IsSuccess()) return Result.Success;
|
||||
|
||||
if (saveFsResult == ResultFs.PathNotFound || saveFsResult == ResultFs.TargetNotFound) return saveFsResult;
|
||||
|
||||
if (saveDataId != SaveIndexerId)
|
||||
{
|
||||
if(hasFixedId)
|
||||
{
|
||||
// todo: remove save indexer entry
|
||||
}
|
||||
}
|
||||
|
||||
return ResultFs.TargetNotFound;
|
||||
}
|
||||
|
||||
private bool IsSystemSaveDataId(ulong id)
|
||||
{
|
||||
return (long)id < 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Save;
|
||||
using LibHac.FsService.Creators;
|
||||
|
||||
namespace LibHac.FsService
|
||||
|
@ -77,9 +78,129 @@ namespace LibHac.FsService
|
|||
public Result SetSdCardEncryptionSeed(ReadOnlySpan<byte> seed)
|
||||
{
|
||||
seed.CopyTo(SdEncryptionSeed);
|
||||
FsCreators.SaveDataFileSystemCreator.SetSdCardEncryptionSeed(seed);
|
||||
//FsCreators.SaveDataFileSystemCreator.SetSdCardEncryptionSeed(seed);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public bool AllowDirectorySaveData(SaveDataSpaceId spaceId, string saveDataRootPath)
|
||||
{
|
||||
return spaceId == SaveDataSpaceId.User && !string.IsNullOrWhiteSpace(saveDataRootPath);
|
||||
}
|
||||
|
||||
public Result OpenSaveDataFileSystem(out IFileSystem fileSystem, SaveDataSpaceId spaceId, ulong saveDataId,
|
||||
string saveDataRootPath, bool openReadOnly, SaveDataType type, bool cacheExtraData)
|
||||
{
|
||||
fileSystem = default;
|
||||
|
||||
Result openSaveDirResult = OpenSaveDataDirectory(out IFileSystem saveDirFs, spaceId, saveDataRootPath, true);
|
||||
if (openSaveDirResult.IsFailure()) return openSaveDirResult.Log();
|
||||
|
||||
bool allowDirectorySaveData = AllowDirectorySaveData(spaceId, saveDataRootPath);
|
||||
bool useDeviceUniqueMac = Util.UseDeviceUniqueSaveMac(spaceId);
|
||||
|
||||
if (allowDirectorySaveData)
|
||||
{
|
||||
try
|
||||
{
|
||||
saveDirFs.EnsureDirectoryExists(GetSaveDataIdPath(saveDataId));
|
||||
}
|
||||
catch (HorizonResultException ex)
|
||||
{
|
||||
return ex.ResultValue;
|
||||
}
|
||||
}
|
||||
|
||||
// Missing save FS cache lookup
|
||||
|
||||
Result saveFsResult = FsCreators.SaveDataFileSystemCreator.Create(out IFileSystem saveFs,
|
||||
out ISaveDataExtraDataAccessor extraDataAccessor, saveDirFs, saveDataId, allowDirectorySaveData,
|
||||
useDeviceUniqueMac, type, null);
|
||||
|
||||
if (saveFsResult.IsFailure()) return saveFsResult.Log();
|
||||
|
||||
if (cacheExtraData)
|
||||
{
|
||||
// Missing extra data caching
|
||||
}
|
||||
|
||||
fileSystem = openReadOnly ? new ReadOnlyFileSystem(saveFs) : saveFs;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenSaveDataDirectory(out IFileSystem fileSystem, SaveDataSpaceId spaceId, string saveDataRootPath, bool openOnHostFs)
|
||||
{
|
||||
if (openOnHostFs && AllowDirectorySaveData(spaceId, saveDataRootPath))
|
||||
{
|
||||
Result hostFsResult = FsCreators.TargetManagerFileSystemCreator.Create(out IFileSystem hostFs, false);
|
||||
|
||||
if (hostFsResult.IsFailure())
|
||||
{
|
||||
fileSystem = default;
|
||||
return hostFsResult.Log();
|
||||
}
|
||||
|
||||
return Util.CreateSubFileSystem(out fileSystem, hostFs, saveDataRootPath, true);
|
||||
}
|
||||
|
||||
string dirName = spaceId == SaveDataSpaceId.TemporaryStorage ? "/temp" : "/save";
|
||||
|
||||
return OpenSaveDataDirectoryImpl(out fileSystem, spaceId, dirName, true);
|
||||
}
|
||||
|
||||
public Result OpenSaveDataDirectoryImpl(out IFileSystem fileSystem, SaveDataSpaceId spaceId, string saveDirName, bool createIfMissing)
|
||||
{
|
||||
fileSystem = default;
|
||||
|
||||
switch (spaceId)
|
||||
{
|
||||
case SaveDataSpaceId.System:
|
||||
Result sysFsResult = OpenBisFileSystem(out IFileSystem sysFs, string.Empty, BisPartitionId.System);
|
||||
if (sysFsResult.IsFailure()) return sysFsResult.Log();
|
||||
|
||||
return Util.CreateSubFileSystem(out fileSystem, sysFs, saveDirName, createIfMissing);
|
||||
|
||||
case SaveDataSpaceId.User:
|
||||
case SaveDataSpaceId.TemporaryStorage:
|
||||
Result userFsResult = OpenBisFileSystem(out IFileSystem userFs, string.Empty, BisPartitionId.System);
|
||||
if (userFsResult.IsFailure()) return userFsResult.Log();
|
||||
|
||||
return Util.CreateSubFileSystem(out fileSystem, userFs, saveDirName, createIfMissing);
|
||||
|
||||
case SaveDataSpaceId.SdSystem:
|
||||
case SaveDataSpaceId.SdCache:
|
||||
Result sdFsResult = OpenSdCardFileSystem(out IFileSystem sdFs);
|
||||
if (sdFsResult.IsFailure()) return sdFsResult.Log();
|
||||
|
||||
string sdSaveDirPath = $"/{NintendoDirectoryName}{saveDirName}";
|
||||
|
||||
Result sdSubResult = Util.CreateSubFileSystem(out IFileSystem sdSubFs, sdFs, sdSaveDirPath, createIfMissing);
|
||||
if (sdSubResult.IsFailure()) return sdSubResult.Log();
|
||||
|
||||
return FsCreators.EncryptedFileSystemCreator.Create(out fileSystem, sdSubFs,
|
||||
EncryptedFsKeyId.Save, SdEncryptionSeed);
|
||||
|
||||
case SaveDataSpaceId.ProperSystem:
|
||||
Result sysProperFsResult = OpenBisFileSystem(out IFileSystem sysProperFs, string.Empty, BisPartitionId.SystemProperPartition);
|
||||
if (sysProperFsResult.IsFailure()) return sysProperFsResult.Log();
|
||||
|
||||
return Util.CreateSubFileSystem(out fileSystem, sysProperFs, saveDirName, createIfMissing);
|
||||
|
||||
case SaveDataSpaceId.Safe:
|
||||
Result safeFsResult = OpenBisFileSystem(out IFileSystem safeFs, string.Empty, BisPartitionId.SafeMode);
|
||||
if (safeFsResult.IsFailure()) return safeFsResult.Log();
|
||||
|
||||
return Util.CreateSubFileSystem(out fileSystem, safeFs, saveDirName, createIfMissing);
|
||||
|
||||
default:
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
}
|
||||
|
||||
private string GetSaveDataIdPath(ulong saveDataId)
|
||||
{
|
||||
return $"/{saveDataId:x16}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
20
src/LibHac/FsService/IFileSystemProxy.cs
Normal file
20
src/LibHac/FsService/IFileSystemProxy.cs
Normal file
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using LibHac.Fs;
|
||||
|
||||
namespace LibHac.FsService
|
||||
{
|
||||
public interface IFileSystemProxy
|
||||
{
|
||||
Result SetCurrentProcess(long processId);
|
||||
Result OpenBisFileSystem(out IFileSystem fileSystem, string rootPath, BisPartitionId partitionId);
|
||||
Result OpenSdCardFileSystem(out IFileSystem fileSystem);
|
||||
Result OpenGameCardStorage(out IStorage storage, GameCardHandle handle, GameCardPartitionRaw partitionId);
|
||||
Result OpenSaveDataFileSystem(out IFileSystem fileSystem, SaveDataSpaceId spaceId, SaveDataAttribute attribute);
|
||||
Result OpenSaveDataFileSystemBySystemSaveDataId(out IFileSystem fileSystem, SaveDataSpaceId spaceId, SaveDataAttribute attribute);
|
||||
Result OpenContentStorageFileSystem(out IFileSystem fileSystem, ContentStorageId storageId);
|
||||
Result SetSdCardEncryptionSeed(ReadOnlySpan<byte> seed);
|
||||
Result SetSaveDataSize(long saveDataSize, long saveDataJournalSize);
|
||||
Result SetSaveDataRootPath(string path);
|
||||
Result DisableAutoSaveDataCreation();
|
||||
}
|
||||
}
|
|
@ -43,5 +43,14 @@ namespace LibHac.FsService
|
|||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static bool UseDeviceUniqueSaveMac(SaveDataSpaceId spaceId)
|
||||
{
|
||||
return spaceId == SaveDataSpaceId.System ||
|
||||
spaceId == SaveDataSpaceId.User ||
|
||||
spaceId == SaveDataSpaceId.TemporaryStorage ||
|
||||
spaceId == SaveDataSpaceId.ProperSystem ||
|
||||
spaceId == SaveDataSpaceId.Safe;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue