Implement the rest of SaveDataInternalStorageFileSystem

This commit is contained in:
Alex Barney 2024-03-09 15:23:26 -07:00
parent 2501cd24d0
commit 2b2b7471ea
12 changed files with 528 additions and 51 deletions

View file

@ -0,0 +1,6 @@
namespace LibHac.Common;
public interface IConstant<T> where T : struct
{
static abstract T Value { get; }
}

View file

@ -179,7 +179,7 @@ public class FileStorageBasedFileSystem : FileStorage
/// <see cref="ResultFs.PathNotFound"/>: The specified path does not exist or is a directory.<br/>
/// <see cref="ResultFs.TargetLocked"/>: When opening as <see cref="OpenMode.Write"/>,
/// the file is already opened as <see cref="OpenMode.Write"/>.</returns>
public Result Initialize(ref SharedRef<IFileSystem> baseFileSystem, ref readonly Path path, OpenMode mode)
public Result Initialize(ref readonly SharedRef<IFileSystem> baseFileSystem, ref readonly Path path, OpenMode mode)
{
using var baseFile = new UniqueRef<IFile>();
@ -187,7 +187,7 @@ public class FileStorageBasedFileSystem : FileStorage
if (res.IsFailure()) return res.Miss();
SetFile(baseFile.Get);
_baseFileSystem.SetByMove(ref baseFileSystem);
_baseFileSystem.SetByCopy(in baseFileSystem);
_baseFile.Set(ref baseFile.Ref);
return Result.Success;

View file

@ -37,7 +37,7 @@ public class DefaultFsServerObjects
creators.StorageOnNcaCreator = new StorageOnNcaCreator(keySet);
creators.TargetManagerFileSystemCreator = new TargetManagerFileSystemCreator();
creators.SubDirectoryFileSystemCreator = new SubDirectoryFileSystemCreator();
creators.SaveDataFileSystemCreator = new SaveDataFileSystemCreator(fsServer, keySet, null, randomGenerator);
creators.SaveDataFileSystemCreator = new SaveDataFileSystemCreator(fsServer, null, randomGenerator);
creators.GameCardStorageCreator = gcStorageCreator;
creators.GameCardFileSystemCreator = new GameCardFileSystemCreator(new ArrayPoolMemoryResource(), gcStorageCreator, fsServer);
creators.EncryptedFileSystemCreator = new EncryptedFileSystemCreator(keySet);

View file

@ -1,8 +1,12 @@
using System;
using LibHac.Common;
using LibHac.FsSrv.FsCreator;
namespace LibHac.FsSrv;
public delegate Result GenerateSeedUniqueMac(Span<byte> outMacBuffer, ReadOnlySpan<byte> data, ReadOnlySpan<byte> seed);
public delegate Result GenerateDeviceUniqueMac(Span<byte> outMacBuffer, ReadOnlySpan<byte> data, DeviceUniqueMacType macType);
public delegate Result SaveTransferAesKeyGenerator(Span<byte> outKeyBuffer,
SaveDataTransferCryptoConfiguration.KeyIndex index, ReadOnlySpan<byte> keySource, int keyGeneration);

View file

@ -8,7 +8,7 @@ using LibHac.FsSystem.Save;
namespace LibHac.FsSrv.FsCreator;
public interface ISaveDataFileSystemCreator
public interface ISaveDataFileSystemCreator : IDisposable
{
Result CreateRaw(ref SharedRef<IFile> outFile, in SharedRef<IFileSystem> fileSystem, ulong saveDataId, OpenMode openMode);

View file

@ -2,74 +2,314 @@
using System.Runtime.CompilerServices;
using LibHac.Common;
using LibHac.Common.FixedArrays;
using LibHac.Common.Keys;
using LibHac.Crypto;
using LibHac.Diag;
using LibHac.Fs;
using LibHac.Fs.Fsa;
using LibHac.Fs.Shim;
using LibHac.FsSrv.Impl;
using LibHac.FsSystem;
using LibHac.FsSystem.Save;
using LibHac.Util;
using OpenType = LibHac.FsSrv.SaveDataOpenTypeSetFileStorage.OpenType;
using ValueSubStorage = LibHac.Fs.ValueSubStorage;
namespace LibHac.FsSrv.FsCreator;
public enum DeviceUniqueMacType
{
Normal,
Temporary
}
/// <summary>
/// Extends <see cref="LibHac.FsSystem.Save.SaveDataInternalStorageFileSystem"/> to allow initializing it with a
/// <see cref="SaveDataFileSystem"/> instead of directly using an <see cref="IInternalStorageFileSystem"/>.
/// </summary>
/// <remarks>Based on nnSdk 17.5.0 (FS 17.0.0)</remarks>
file class SaveDataInternalStorageFileSystem : LibHac.FsSystem.Save.SaveDataInternalStorageFileSystem
{
private SharedRef<SaveDataFileSystem> _saveDataFileSystem;
public SaveDataInternalStorageFileSystem()
{
_saveDataFileSystem = new SharedRef<SaveDataFileSystem>();
}
public override void Dispose()
{
_saveDataFileSystem.Destroy();
base.Dispose();
}
public Result Initialize(ref readonly SharedRef<SaveDataFileSystem> saveDataFileSystem,
IMacGenerator normalMacGenerator, IMacGenerator temporaryMacGenerator,
IHash256GeneratorFactorySelector hashGeneratorFactorySelector)
{
Assert.SdkRequiresNotNull(in saveDataFileSystem);
Assert.SdkRequiresNotNull(normalMacGenerator);
Assert.SdkRequiresNotNull(temporaryMacGenerator);
Assert.SdkRequiresNotNull(hashGeneratorFactorySelector);
_saveDataFileSystem.SetByCopy(in saveDataFileSystem);
Result res = Initialize(_saveDataFileSystem.Get.GetInternalStorageFileSystem(), normalMacGenerator,
temporaryMacGenerator, hashGeneratorFactorySelector);
if (res.IsFailure()) return res.Miss();
return Result.Success;
}
}
file static class Anonymous
{
public static Result GetSaveDataFormatType(out SaveDataFormatType outFormatType, IStorage saveImageStorage,
IBufferManager bufferManager, IMacGenerator macGenerator,
IHash256GeneratorFactorySelector hashGeneratorFactorySelector, uint minimumVersion)
{
UnsafeHelpers.SkipParamInit(out outFormatType);
Result res = saveImageStorage.GetSize(out long storageSize);
if (res.IsFailure()) return res.Miss();
using var saveSubStorage = new ValueSubStorage(saveImageStorage, 0, storageSize);
Result resultJournalIntegrity = JournalIntegritySaveDataFileSystem.VerifyMasterHeader(in saveSubStorage,
bufferManager, macGenerator, hashGeneratorFactorySelector, minimumVersion);
if (resultJournalIntegrity.IsSuccess())
{
outFormatType = SaveDataFormatType.Normal;
return Result.Success;
}
Result resultIntegrity = IntegritySaveDataFileSystem.VerifyMasterHeader(in saveSubStorage, bufferManager,
macGenerator, hashGeneratorFactorySelector);
if (resultIntegrity.IsSuccess())
{
outFormatType = SaveDataFormatType.NoJournal;
return Result.Success;
}
return resultJournalIntegrity.Miss();
}
}
/// <summary>
/// Used by <see cref="SaveDataFileSystemServiceImpl"/> for opening, formatting, and working with save data.
/// This class directly operates on save data <see cref="IStorage"/>s and the directories containing the save data,
/// whereas <see cref="SaveDataFileSystemServiceImpl"/> handles higher level tasks such as opening or creating
/// the save data images on the file system, managing caches, etc.
/// </summary>
/// <remarks>Based on nnSdk 17.5.0 (FS 17.0.0)</remarks>
public class SaveDataFileSystemCreator : ISaveDataFileSystemCreator
{
// Option to disable some restrictions enforced in actual FS.
private static readonly bool EnforceSaveTypeRestrictions = false;
private class MacGenerationSeed
{
public const uint Size = Aes.KeySize128;
public Array16<byte> Value;
}
private struct DeviceUniqueMacTypeNormal : IConstant<DeviceUniqueMacType>
{
public static DeviceUniqueMacType Value => DeviceUniqueMacType.Normal;
}
private struct DeviceUniqueMacTypeTemporary : IConstant<DeviceUniqueMacType>
{
public static DeviceUniqueMacType Value => DeviceUniqueMacType.Temporary;
}
private class DeviceUniqueMacGenerator<TMacType> : IMacGenerator where TMacType : IConstant<DeviceUniqueMacType>
{
private GenerateDeviceUniqueMac _generatorFunction;
public DeviceUniqueMacGenerator(GenerateDeviceUniqueMac generatorFunction)
{
_generatorFunction = generatorFunction;
}
public Result Generate(Span<byte> macDestBuffer, ReadOnlySpan<byte> data)
{
return _generatorFunction(macDestBuffer, data, TMacType.Value).Ret();
}
}
private class SeedUniqueMacGenerator : IMacGenerator
{
private GenerateSeedUniqueMac _generatorFunction;
private MacGenerationSeed _seed;
public SeedUniqueMacGenerator(GenerateSeedUniqueMac generatorFunction, MacGenerationSeed seed)
{
_generatorFunction = generatorFunction;
_seed = seed;
}
public Result Generate(Span<byte> macDestBuffer, ReadOnlySpan<byte> data)
{
return _generatorFunction(macDestBuffer, data, _seed.Value).Ret();
}
}
// ReSharper disable once NotAccessedField.Local
private IBufferManager _bufferManager;
private RandomDataGenerator _randomGenerator;
private DeviceUniqueMacGenerator<DeviceUniqueMacTypeNormal> _deviceUniqueMacGeneratorNormal;
private DeviceUniqueMacGenerator<DeviceUniqueMacTypeTemporary> _deviceUniqueMacGeneratorTemporary;
private SeedUniqueMacGenerator _seedUniqueMacGenerator;
private MacGenerationSeed _macGenerationSeed;
private IHash256GeneratorFactorySelector _hashGeneratorFactorySelector;
private uint _saveDataMinimumVersion;
private RandomDataGenerator _randomDataGenerator;
private Func<DebugOptionKey, long, long> _debugValueGetter;
// LibHac Additions
// ReSharper disable once NotAccessedField.Local
private KeySet _keySet;
private FileSystemServer _fsServer;
public SaveDataFileSystemCreator(FileSystemServer fsServer, KeySet keySet, IBufferManager bufferManager,
RandomDataGenerator randomGenerator)
public SaveDataFileSystemCreator(FileSystemServer fsServer, IBufferManager bufferManager,
GenerateDeviceUniqueMac deviceUniqueMacGenerator, GenerateSeedUniqueMac seedUniqueMacGenerator,
RandomDataGenerator randomDataGenerator, IHash256GeneratorFactorySelector hashGeneratorFactorySelector,
uint minimumVersion, Func<DebugOptionKey, long, long> debugValueGetter)
{
_fsServer = fsServer;
_macGenerationSeed = new MacGenerationSeed();
_bufferManager = bufferManager;
_deviceUniqueMacGeneratorNormal = new DeviceUniqueMacGenerator<DeviceUniqueMacTypeNormal>(deviceUniqueMacGenerator);
_deviceUniqueMacGeneratorTemporary = new DeviceUniqueMacGenerator<DeviceUniqueMacTypeTemporary>(deviceUniqueMacGenerator);
_seedUniqueMacGenerator = new SeedUniqueMacGenerator(seedUniqueMacGenerator, _macGenerationSeed);
_hashGeneratorFactorySelector = hashGeneratorFactorySelector;
_saveDataMinimumVersion = minimumVersion;
_randomDataGenerator = randomDataGenerator;
_debugValueGetter = debugValueGetter;
JournalIntegritySaveDataFileSystem.SetGenerateRandomFunction(fsServer, randomDataGenerator);
}
public SaveDataFileSystemCreator(FileSystemServer fsServer, IBufferManager bufferManager,
RandomDataGenerator randomDataGenerator)
{
_bufferManager = bufferManager;
_randomGenerator = randomGenerator;
_randomDataGenerator = randomDataGenerator;
_fsServer = fsServer;
_keySet = keySet;
}
public void Dispose() { }
private IMacGenerator GetDeviceUniqueMacGenerator(DeviceUniqueMacType macType)
{
switch (macType)
{
case DeviceUniqueMacType.Normal:
return _deviceUniqueMacGeneratorNormal;
case DeviceUniqueMacType.Temporary:
return _deviceUniqueMacGeneratorTemporary;
default:
Abort.UnexpectedDefault();
return default;
}
}
private IMacGenerator GetMacGenerator(bool isDeviceUnique, DeviceUniqueMacType macType)
{
return isDeviceUnique ? GetDeviceUniqueMacGenerator(macType) : _seedUniqueMacGenerator;
}
public Result Format(in ValueSubStorage saveImageStorage, long blockSize, int countExpandMax, uint blockCount,
uint journalBlockCount, IBufferManager bufferManager, bool isDeviceUniqueMac, in HashSalt hashSalt,
RandomDataGenerator encryptionKeyGenerator, bool isReconstructible, uint version)
{
throw new NotImplementedException();
Result res = JournalIntegritySaveDataFileSystemDriver.Format(in saveImageStorage, blockSize, blockCount,
journalBlockCount, countExpandMax, bufferManager,
GetMacGenerator(isDeviceUniqueMac, DeviceUniqueMacType.Normal), _hashGeneratorFactorySelector, hashSalt,
encryptionKeyGenerator, version);
res = SaveDataResultConverter.ConvertSaveDataFsResult(res, isReconstructible);
if (res.IsFailure()) return res.Miss();
return Result.Success;
}
public Result FormatAsIntegritySaveData(in ValueSubStorage saveImageStorage, long blockSize, uint blockCount,
IBufferManager bufferManager, bool isDeviceUniqueMac, RandomDataGenerator encryptionKeyGenerator,
bool isReconstructible, uint version)
{
throw new NotImplementedException();
Result res = IntegritySaveDataFileSystemDriver.Format(in saveImageStorage, blockSize, blockCount, bufferManager,
GetMacGenerator(isDeviceUniqueMac, DeviceUniqueMacType.Normal), _hashGeneratorFactorySelector,
encryptionKeyGenerator, version);
res = SaveDataResultConverter.ConvertSaveDataFsResult(res, isReconstructible);
if (res.IsFailure()) return res.Miss();
return Result.Success;
}
public Result ExtractSaveDataParameters(out JournalIntegritySaveDataParameters outParams, IStorage saveFileStorage,
bool isDeviceUniqueMac, bool isReconstructible)
{
throw new NotImplementedException();
Result res = SaveDataFileSystem.ExtractParameters(out outParams, saveFileStorage, _bufferManager,
GetMacGenerator(isDeviceUniqueMac, DeviceUniqueMacType.Normal), _hashGeneratorFactorySelector,
_saveDataMinimumVersion);
res = SaveDataResultConverter.ConvertSaveDataFsResult(res, isReconstructible);
if (res.IsFailure()) return res.Miss();
return Result.Success;
}
public Result ExtendSaveData(SaveDataExtender extender, in ValueSubStorage baseStorage,
in ValueSubStorage logStorage, bool isDeviceUniqueMac, bool isReconstructible)
{
throw new NotImplementedException();
Assert.SdkRequiresNotNull(extender);
Result res = extender.Extend(in baseStorage, in logStorage, _bufferManager,
GetMacGenerator(isDeviceUniqueMac, DeviceUniqueMacType.Normal), _hashGeneratorFactorySelector,
_saveDataMinimumVersion);
res = SaveDataResultConverter.ConvertSaveDataFsResult(res, isReconstructible);
if (res.IsFailure()) return res.Miss();
return Result.Success;
}
public void SetMacGenerationSeed(ReadOnlySpan<byte> seed)
{
throw new NotImplementedException();
Assert.SdkRequires(seed.Length == MacGenerationSeed.Size);
seed.CopyTo(_macGenerationSeed.Value);
}
public Result CreateRaw(ref SharedRef<IFile> outFile, in SharedRef<IFileSystem> fileSystem, ulong saveDataId, OpenMode openMode)
{
throw new NotImplementedException();
Unsafe.SkipInit(out Array18<byte> saveImageNameBuffer);
using scoped var saveImageName = new Path();
Result res = PathFunctions.SetUpFixedPathSaveId(ref saveImageName.Ref(), saveImageNameBuffer, saveDataId);
if (res.IsFailure()) return res.Miss();
res = fileSystem.Get.GetEntryType(out DirectoryEntryType type, in saveImageName);
if (res.IsFailure())
{
if (ResultFs.PathNotFound.Includes(res))
return ResultFs.TargetNotFound.LogConverted(res);
return res.Miss();
}
if (type == DirectoryEntryType.Directory)
{
return ResultFs.TargetNotFound.Log();
}
using var file = new UniqueRef<IFile>();
res = fileSystem.Get.OpenFile(ref file.Ref, in saveImageName, openMode);
if (res.IsFailure()) return res.Miss();
outFile.Set(ref file.Ref);
return Result.Success;
}
public Result Create(ref SharedRef<ISaveDataFileSystem> outFileSystem, ref SharedRef<IFileSystem> baseFileSystem,
@ -87,7 +327,10 @@ public class SaveDataFileSystemCreator : ISaveDataFileSystemCreator
if (res.IsFailure())
{
return ResultFs.PathNotFound.Includes(res) ? ResultFs.TargetNotFound.LogConverted(res) : res.Miss();
if (ResultFs.PathNotFound.Includes(res))
return ResultFs.TargetNotFound.LogConverted(res);
return res.Miss();
}
using var saveDataFs = new SharedRef<ISaveDataFileSystem>();
@ -118,7 +361,7 @@ public class SaveDataFileSystemCreator : ISaveDataFileSystemCreator
return ResultFs.AllocationMemoryFailedInSaveDataFileSystemCreatorB.Log();
res = saveDirFs.Get.Initialize(isJournalingSupported, isMultiCommitSupported, !openReadOnly,
timeStampGetter, _randomGenerator);
timeStampGetter, _randomDataGenerator);
if (res.IsFailure()) return res.Miss();
saveDataFs.SetByMove(ref saveDirFs.Ref);
@ -134,7 +377,37 @@ public class SaveDataFileSystemCreator : ISaveDataFileSystemCreator
OpenMode.ReadWrite, openType);
if (res.IsFailure()) return res.Miss();
throw new NotImplementedException();
res = Anonymous.GetSaveDataFormatType(out SaveDataFormatType formatType, fileStorage.Get, _bufferManager,
GetMacGenerator(isDeviceUniqueMac, DeviceUniqueMacType.Normal), _hashGeneratorFactorySelector,
_saveDataMinimumVersion);
if (res.IsFailure()) return res.Miss();
if (!SaveDataProperties.IsJournalingSupported(formatType))
{
using var fs = new SharedRef<ApplicationTemporaryFileSystem>(new ApplicationTemporaryFileSystem());
res = fs.Get.Initialize(in fileStorage, _bufferManager,
GetMacGenerator(isDeviceUniqueMac, DeviceUniqueMacType.Normal), _hashGeneratorFactorySelector);
res = SaveDataResultConverter.ConvertSaveDataFsResult(res, isReconstructible);
if (res.IsFailure()) return res.Miss();
saveDataFs.SetByMove(ref fs.Ref);
}
else
{
using var fs = new SharedRef<SaveDataFileSystem>(new SaveDataFileSystem());
if (!fs.HasValue)
return ResultFs.AllocationMemoryFailedInSaveDataFileSystemCreatorD.Log();
res = fs.Get.Initialize(in fileStorage, _bufferManager,
GetMacGenerator(isDeviceUniqueMac, DeviceUniqueMacType.Normal), _hashGeneratorFactorySelector,
timeStampGetter, _randomDataGenerator, _saveDataMinimumVersion, isMultiCommitSupported);
res = SaveDataResultConverter.ConvertSaveDataFsResult(res, isReconstructible);
if (res.IsFailure()) return res.Miss();
saveDataFs.SetByMove(ref fs.Ref);
}
}
// Wrap the save FS in a result convert FS and set it as the output FS
@ -142,44 +415,234 @@ public class SaveDataFileSystemCreator : ISaveDataFileSystemCreator
new SaveDataResultConvertFileSystem(ref saveDataFs.Ref, isReconstructible));
outFileSystem.SetByMove(ref resultConvertFs.Ref);
return Result.Success;
}
public Result CreateExtraDataAccessor(ref SharedRef<ISaveDataExtraDataAccessor> outExtraDataAccessor,
in SharedRef<IStorage> baseStorage, bool isDeviceUniqueMac, bool isIntegritySaveData, bool isReconstructible)
{
throw new NotImplementedException();
using var saveDataFs = new SharedRef<ISaveDataFileSystem>();
if (!isIntegritySaveData)
{
using var fs = new SharedRef<ApplicationTemporaryFileSystem>(new ApplicationTemporaryFileSystem());
Result res = fs.Get.Initialize(in baseStorage, _bufferManager,
GetMacGenerator(isDeviceUniqueMac, DeviceUniqueMacType.Normal), _hashGeneratorFactorySelector);
res = SaveDataResultConverter.ConvertSaveDataFsResult(res, isReconstructible);
if (res.IsFailure()) return res.Miss();
saveDataFs.SetByMove(ref fs.Ref);
}
else
{
using var fs = new SharedRef<SaveDataFileSystem>(new SaveDataFileSystem());
Result res = fs.Get.Initialize(in baseStorage, _bufferManager,
GetMacGenerator(isDeviceUniqueMac, DeviceUniqueMacType.Normal), _hashGeneratorFactorySelector,
_saveDataMinimumVersion, canCommitProvisionally: false);
res = SaveDataResultConverter.ConvertSaveDataFsResult(res, isReconstructible);
if (res.IsFailure()) return res.Miss();
saveDataFs.SetByMove(ref fs.Ref);
}
using var resultConvertFs = new SharedRef<SaveDataResultConvertFileSystem>(
new SaveDataResultConvertFileSystem(ref saveDataFs.Ref, isReconstructible));
outExtraDataAccessor.SetByMove(ref resultConvertFs.Ref);
return Result.Success;
}
public Result CreateInternalStorage(ref SharedRef<IFileSystem> outFileSystem,
in SharedRef<IFileSystem> baseFileSystem, SaveDataSpaceId spaceId, ulong saveDataId, bool isDeviceUniqueMac,
bool useUniqueKey1, ISaveDataCommitTimeStampGetter timeStampGetter, bool isReconstructible)
{
throw new NotImplementedException();
Result res;
Unsafe.SkipInit(out Array18<byte> saveImageNameBuffer);
using (scoped var saveImageName = new Path())
{
res = PathFunctions.SetUpFixedPathSaveId(ref saveImageName.Ref(), saveImageNameBuffer, saveDataId);
if (res.IsFailure()) return res.Miss();
res = baseFileSystem.Get.GetEntryType(out DirectoryEntryType entryType, in saveImageName);
if (res.IsFailure())
{
if (ResultFs.PathNotFound.Includes(res))
return ResultFs.TargetNotFound.LogConverted(res);
return res.Miss();
}
if (entryType == DirectoryEntryType.Directory)
return ResultFs.InvalidSaveDataEntryType.Log();
}
IMacGenerator normalMacGenerator = GetMacGenerator(isDeviceUniqueMac, DeviceUniqueMacType.Normal);
IMacGenerator temporaryMacGenerator = GetMacGenerator(isDeviceUniqueMac, DeviceUniqueMacType.Temporary);
IMacGenerator macGenerator = useUniqueKey1 ? temporaryMacGenerator : normalMacGenerator;
using var fileStorage = new SharedRef<IStorage>();
res = _fsServer.OpenSaveDataStorage(ref fileStorage.Ref, in baseFileSystem, spaceId, saveDataId,
OpenMode.ReadWrite, OpenType.Internal);
if (res.IsFailure()) return res.Miss();
using var saveFs = new SharedRef<SaveDataFileSystem>(new SaveDataFileSystem());
res = saveFs.Get.Initialize(in fileStorage, _bufferManager, macGenerator, _hashGeneratorFactorySelector,
timeStampGetter, _randomDataGenerator, _saveDataMinimumVersion, canCommitProvisionally: false);
res = SaveDataResultConverter.ConvertSaveDataFsResult(res, isReconstructible);
if (res.IsFailure()) return res.Miss();
using var internalStorage = new SharedRef<SaveDataInternalStorageFileSystem>(new SaveDataInternalStorageFileSystem());
res = internalStorage.Get.Initialize(in saveFs, normalMacGenerator, temporaryMacGenerator, _hashGeneratorFactorySelector);
res = SaveDataResultConverter.ConvertSaveDataFsResult(res, isReconstructible);
if (res.IsFailure()) return res.Miss();
using SharedRef<ISaveDataFileSystem> tempSaveFs = SharedRef<ISaveDataFileSystem>.CreateMove(ref saveFs.Ref);
using var resultConvertFs = new SharedRef<SaveDataResultConvertFileSystem>(
new SaveDataResultConvertFileSystem(ref tempSaveFs.Ref, isReconstructible));
outFileSystem.SetByMove(ref resultConvertFs.Ref);
return Result.Success;
}
public Result RecoverMasterHeader(in SharedRef<IFileSystem> baseFileSystem, ulong saveDataId,
IBufferManager bufferManager, bool isDeviceUniqueMac, bool isReconstructible)
{
throw new NotImplementedException();
Unsafe.SkipInit(out Array18<byte> saveImageNameBuffer);
using scoped var saveImageName = new Path();
Result res = PathFunctions.SetUpFixedPathSaveId(ref saveImageName.Ref(), saveImageNameBuffer, saveDataId);
if (res.IsFailure()) return res.Miss();
res = baseFileSystem.Get.GetEntryType(out DirectoryEntryType entryType, in saveImageName);
if (res.IsFailure())
{
if (ResultFs.PathNotFound.Includes(res))
return ResultFs.TargetNotFound.LogConverted(res);
return res.Miss();
}
if (entryType == DirectoryEntryType.Directory)
{
// Directory save data doesn't have a master header
return Result.Success;
}
using var fileStorage = new SharedRef<FileStorageBasedFileSystem>();
res = fileStorage.Get.Initialize(in baseFileSystem, in saveImageName, OpenMode.ReadWrite);
if (res.IsFailure()) return res.Miss();
res = fileStorage.Get.GetSize(out long size);
if (res.IsFailure()) return res.Miss();
using var fileSubStorage = new ValueSubStorage(fileStorage.Get, 0, size);
IMacGenerator macGenerator = GetMacGenerator(isDeviceUniqueMac, DeviceUniqueMacType.Normal);
res = JournalIntegritySaveDataFileSystem.RecoverMasterHeader(in fileSubStorage, bufferManager, macGenerator,
_hashGeneratorFactorySelector, _saveDataMinimumVersion);
res = SaveDataResultConverter.ConvertSaveDataFsResult(res, isReconstructible);
if (res.IsFailure()) return res.Miss();
return Result.Success;
}
public Result UpdateMac(in SharedRef<IFileSystem> baseFileSystem, ulong saveDataId, bool isDeviceUniqueMac,
bool isReconstructible)
{
throw new NotImplementedException();
Unsafe.SkipInit(out Array18<byte> saveImageNameBuffer);
using scoped var saveImageName = new Path();
Result res = PathFunctions.SetUpFixedPathSaveId(ref saveImageName.Ref(), saveImageNameBuffer, saveDataId);
if (res.IsFailure()) return res.Miss();
res = baseFileSystem.Get.GetEntryType(out DirectoryEntryType entryType, in saveImageName);
if (res.IsFailure())
{
if (ResultFs.PathNotFound.Includes(res))
return ResultFs.TargetNotFound.LogConverted(res);
return res.Miss();
}
if (entryType == DirectoryEntryType.Directory)
{
// Directory save data doesn't contain a MAC
return Result.Success;
}
using var fileStorage = new SharedRef<FileStorageBasedFileSystem>();
res = fileStorage.Get.Initialize(in baseFileSystem, in saveImageName, OpenMode.ReadWrite);
if (res.IsFailure()) return res.Miss();
res = fileStorage.Get.GetSize(out long size);
if (res.IsFailure()) return res.Miss();
using var fileSubStorage = new ValueSubStorage(fileStorage.Get, 0, size);
IMacGenerator macGenerator = GetMacGenerator(isDeviceUniqueMac, DeviceUniqueMacType.Normal);
res = JournalIntegritySaveDataFileSystem.UpdateMac(in fileSubStorage, macGenerator,
_hashGeneratorFactorySelector, _saveDataMinimumVersion);
res = SaveDataResultConverter.ConvertSaveDataFsResult(res, isReconstructible);
if (res.IsFailure()) return res.Miss();
return Result.Success;
}
public Result IsProvisionallyCommittedSaveData(out bool outIsProvisionallyCommitted,
in SharedRef<IFileSystem> baseFileSystem, in SaveDataInfo info, bool isDeviceUniqueMac,
ISaveDataCommitTimeStampGetter timeStampGetter, bool isReconstructible)
{
throw new NotImplementedException();
UnsafeHelpers.SkipParamInit(out outIsProvisionallyCommitted);
Unsafe.SkipInit(out Array18<byte> saveImageNameBuffer);
using scoped var saveImageName = new Path();
Result res = PathFunctions.SetUpFixedPathSaveId(ref saveImageName.Ref(), saveImageNameBuffer, info.SaveDataId);
if (res.IsFailure()) return res.Miss();
res = baseFileSystem.Get.GetEntryType(out DirectoryEntryType entryType, in saveImageName);
if (res.IsFailure())
{
if (ResultFs.PathNotFound.Includes(res))
return ResultFs.TargetNotFound.LogConverted(res);
return res.Miss();
}
if (entryType == DirectoryEntryType.Directory)
return ResultFs.InvalidSaveDataEntryType.Log();
using var fileStorage = new SharedRef<IStorage>();
res = _fsServer.OpenSaveDataStorage(ref fileStorage.Ref, in baseFileSystem, info.SpaceId, info.SaveDataId,
OpenMode.ReadWrite, OpenType.Internal);
if (res.IsFailure()) return res.Miss();
using var saveFs = new SharedRef<SaveDataFileSystem>(new SaveDataFileSystem());
res = saveFs.Get.Initialize(in fileStorage, _bufferManager,
GetMacGenerator(isDeviceUniqueMac, DeviceUniqueMacType.Normal), _hashGeneratorFactorySelector,
timeStampGetter, _randomDataGenerator, _saveDataMinimumVersion, canCommitProvisionally: false);
res = SaveDataResultConverter.ConvertSaveDataFsResult(res, isReconstructible);
if (res.IsFailure()) return res.Miss();
outIsProvisionallyCommitted = saveFs.Get.GetCounterForBundledCommit() != 0;
return Result.Success;
}
public IMacGenerator GetMacGenerator(bool isDeviceUniqueMac, bool isTemporaryTransferSave)
{
throw new NotImplementedException();
DeviceUniqueMacType macType = isTemporaryTransferSave ? DeviceUniqueMacType.Temporary : DeviceUniqueMacType.Normal;
return GetMacGenerator(isDeviceUniqueMac, macType);
}
}

View file

@ -18,12 +18,12 @@ namespace LibHac.FsSrv;
public static class SaveDataSharedFileStorageGlobalMethods
{
public static Result OpenSaveDataStorage(this FileSystemServer fsSrv,
ref SharedRef<IStorage> outSaveDataStorage, ref SharedRef<IFileSystem> baseFileSystem,
ref SharedRef<IStorage> outSaveDataStorage, ref readonly SharedRef<IFileSystem> baseFileSystem,
SaveDataSpaceId spaceId, ulong saveDataId, OpenMode mode,
Optional<SaveDataOpenTypeSetFileStorage.OpenType> type)
{
return fsSrv.Globals.SaveDataSharedFileStorage.SaveDataFileStorageHolder.OpenSaveDataStorage(
ref outSaveDataStorage, ref baseFileSystem, spaceId, saveDataId, mode, type);
ref outSaveDataStorage, in baseFileSystem, spaceId, saveDataId, mode, type);
}
}
@ -74,9 +74,9 @@ public class SaveDataOpenTypeSetFileStorage : FileStorageBasedFileSystem
_mutex = new SdkMutexType();
}
public Result Initialize(ref SharedRef<IFileSystem> baseFileSystem, ref readonly Path path, OpenMode mode, OpenType type)
public Result Initialize(ref readonly SharedRef<IFileSystem> baseFileSystem, ref readonly Path path, OpenMode mode, OpenType type)
{
Result res = Initialize(ref baseFileSystem, in path, mode);
Result res = Initialize(in baseFileSystem, in path, mode);
if (res.IsFailure()) return res.Miss();
return SetOpenType(type);
@ -331,7 +331,7 @@ public class SaveDataFileStorageHolder
}
public Result OpenSaveDataStorage(ref SharedRef<IStorage> outSaveDataStorage,
ref SharedRef<IFileSystem> baseFileSystem, SaveDataSpaceId spaceId, ulong saveDataId, OpenMode mode,
ref readonly SharedRef<IFileSystem> baseFileSystem, SaveDataSpaceId spaceId, ulong saveDataId, OpenMode mode,
Optional<SaveDataOpenTypeSetFileStorage.OpenType> type)
{
Unsafe.SkipInit(out Array18<byte> saveImageNameBuffer);
@ -344,7 +344,7 @@ public class SaveDataFileStorageHolder
if (!type.HasValue)
{
using var fileStorage = new SharedRef<FileStorageBasedFileSystem>(new FileStorageBasedFileSystem());
res = fileStorage.Get.Initialize(ref baseFileSystem, in saveImageName, mode);
res = fileStorage.Get.Initialize(in baseFileSystem, in saveImageName, mode);
if (res.IsFailure()) return res.Miss();
outSaveDataStorage.SetByMove(ref fileStorage.Ref);
@ -363,7 +363,7 @@ public class SaveDataFileStorageHolder
else
{
baseFileStorage.Reset(new SaveDataOpenTypeSetFileStorage(_fsServer, spaceId, saveDataId));
res = baseFileStorage.Get.Initialize(ref baseFileSystem, in saveImageName, mode, type.ValueRo);
res = baseFileStorage.Get.Initialize(in baseFileSystem, in saveImageName, mode, type.ValueRo);
if (res.IsFailure()) return res.Miss();
using SharedRef<SaveDataOpenTypeSetFileStorage> baseFileStorageCopy =

View file

@ -54,7 +54,7 @@ file class ApplicationTemporaryFile : IFile
}
}
public class ApplicationTemporaryFileSystem : IFileSystem, ICacheableSaveDataFileSystem, ISaveDataExtraDataAccessor
public class ApplicationTemporaryFileSystem : ISaveDataFileSystem, ISaveDataExtraDataAccessor
{
private SharedRef<IStorage> _baseStorage;
private IntegritySaveDataFileSystemDriver _saveFsDriver;
@ -166,12 +166,12 @@ public class ApplicationTemporaryFileSystem : IFileSystem, ICacheableSaveDataFil
throw new NotImplementedException();
}
public bool IsSaveDataFileSystemCacheEnabled()
public override bool IsSaveDataFileSystemCacheEnabled()
{
throw new NotImplementedException();
}
public Result RollbackOnlyModified()
public override Result RollbackOnlyModified()
{
throw new NotImplementedException();
}
@ -181,22 +181,22 @@ public class ApplicationTemporaryFileSystem : IFileSystem, ICacheableSaveDataFil
throw new NotImplementedException();
}
public Result WriteExtraData(in SaveDataExtraData extraData)
public override Result WriteExtraData(in SaveDataExtraData extraData)
{
throw new NotImplementedException();
}
public Result CommitExtraData(bool updateTimeStamp)
public override Result CommitExtraData(bool updateTimeStamp)
{
throw new NotImplementedException();
}
public Result ReadExtraData(out SaveDataExtraData extraData)
public override Result ReadExtraData(out SaveDataExtraData extraData)
{
throw new NotImplementedException();
}
public void RegisterExtraDataAccessorObserver(ISaveDataExtraDataAccessorObserver observer, SaveDataSpaceId spaceId,
public override void RegisterExtraDataAccessorObserver(ISaveDataExtraDataAccessorObserver observer, SaveDataSpaceId spaceId,
ulong saveDataId)
{
throw new NotImplementedException();

View file

@ -322,7 +322,7 @@ public class JournalIntegritySaveDataFileSystem : IFileSystem
throw new NotImplementedException();
}
public static void SetGenerateRandomFunction(RandomDataGenerator func)
public static void SetGenerateRandomFunction(FileSystemServer fsServer, RandomDataGenerator func)
{
throw new NotImplementedException();
}
@ -479,7 +479,7 @@ public class JournalIntegritySaveDataFileSystem : IFileSystem
throw new NotImplementedException();
}
private Result MountSaveData(in FileSystemLayoutHeader layoutHeader, in SubStorage saveImageStorage, long blockSize,
private Result MountSaveData(in FileSystemLayoutHeader layoutHeader, in ValueSubStorage saveImageStorage, long blockSize,
FileSystemBufferManagerSet integrityCacheBufferSet, IBufferManager bufferManager, SdkRecursiveMutex mutex)
{
throw new NotImplementedException();
@ -497,7 +497,7 @@ public class JournalIntegritySaveDataFileSystem : IFileSystem
}
public Result Initialize(
in SubStorage saveImageStorage,
in ValueSubStorage saveImageStorage,
FileSystemBufferManagerSet integrityCacheBufferSet,
IBufferManager duplicateCacheBuffer,
SdkRecursiveMutex mutex,
@ -518,13 +518,13 @@ public class JournalIntegritySaveDataFileSystem : IFileSystem
throw new NotImplementedException();
}
public static Result UpdateMac(in SubStorage saveImageStorage, IMacGenerator macGenerator,
public static Result UpdateMac(in ValueSubStorage saveImageStorage, IMacGenerator macGenerator,
IHash256GeneratorFactorySelector hashGeneratorFactorySelector, uint minimumVersion)
{
throw new NotImplementedException();
}
public static Result RecoverMasterHeader(in SubStorage saveImageStorage, IBufferManager bufferManager,
public static Result RecoverMasterHeader(in ValueSubStorage saveImageStorage, IBufferManager bufferManager,
IMacGenerator macGenerator, IHash256GeneratorFactorySelector hashGeneratorFactorySelector, uint minimumVersion)
{
throw new NotImplementedException();

View file

@ -177,6 +177,11 @@ public class SaveDataFileSystem : ISaveDataFileSystem, InternalStorageFileSystem
throw new NotImplementedException();
}
public long GetCounterForBundledCommit()
{
throw new NotImplementedException();
}
protected override Result DoCommitProvisionally(long counter)
{
throw new NotImplementedException();

View file

@ -1,10 +1,9 @@
using LibHac.Common;
using LibHac.Fs;
using LibHac.Fs.Fsa;
using LibHac.FsSystem;
using static LibHac.FsSrv.FsCreator.SaveDataResultConverter;
using static LibHac.FsSystem.SaveDataResultConverter;
namespace LibHac.FsSrv.FsCreator;
namespace LibHac.FsSystem;
/// <summary>
/// Wraps an <see cref="IFile"/>, converting its returned <see cref="Result"/>s

View file

@ -1,7 +1,7 @@
using LibHac.Diag;
using LibHac.Fs;
namespace LibHac.FsSrv.FsCreator;
namespace LibHac.FsSystem;
/// <summary>
/// Contains functions for converting internal save data <see cref="Result"/>s to external <see cref="Result"/>s.