mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Update SaveDataFileSystemService for 14.0.0
- Creating save data file systems now uses a new SaveDataCreationInfo2 struct. - Ensure all implemented functions in the class are accurate to 14.0.0
This commit is contained in:
parent
3725c21928
commit
7b44441ff2
14 changed files with 1256 additions and 589 deletions
|
@ -43,4 +43,7 @@ public static class Log
|
|||
|
||||
diag.LogImpl(in metaData, message);
|
||||
}
|
||||
|
||||
/// <summary>"<c>$</c>"</summary>
|
||||
public static ReadOnlySpan<byte> EmptyModuleName => new[] { (byte)'$' }; // "$"
|
||||
}
|
||||
|
|
|
@ -94,9 +94,17 @@ public ref struct Path
|
|||
[DebuggerDisplay("{" + nameof(ToString) + "(),nq}")]
|
||||
public struct Stored : IDisposable
|
||||
{
|
||||
private static readonly byte[] EmptyBuffer = { 0 };
|
||||
|
||||
private byte[] _buffer;
|
||||
private int _length;
|
||||
|
||||
public Stored()
|
||||
{
|
||||
_buffer = EmptyBuffer;
|
||||
_length = 0;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
byte[] buffer = Shared.Move(ref _buffer);
|
||||
|
@ -160,7 +168,8 @@ public ref struct Path
|
|||
byte[] oldBuffer = _buffer;
|
||||
_buffer = buffer;
|
||||
|
||||
if (oldBuffer is not null)
|
||||
// Check if the buffer is longer than 1 so we don't try to return EmptyBuffer to the pool.
|
||||
if (oldBuffer?.Length > 1)
|
||||
ArrayPool<byte>.Shared.Return(oldBuffer);
|
||||
|
||||
return Result.Success;
|
||||
|
|
|
@ -16,8 +16,7 @@ public enum SaveDataSpaceId : byte
|
|||
Temporary = 3,
|
||||
SdUser = 4,
|
||||
ProperSystem = 100,
|
||||
SafeMode = 101,
|
||||
BisAuto = 127
|
||||
SafeMode = 101
|
||||
}
|
||||
|
||||
public enum SaveDataType : byte
|
||||
|
@ -99,6 +98,7 @@ public struct SaveDataExtraData
|
|||
public ulong OwnerId;
|
||||
public long TimeStamp;
|
||||
public SaveDataFlags Flags;
|
||||
public SaveDataFormatType FormatType;
|
||||
public long DataSize;
|
||||
public long JournalSize;
|
||||
public long CommitId;
|
||||
|
|
|
@ -4,8 +4,9 @@ namespace LibHac.Fs.Impl;
|
|||
|
||||
internal readonly struct SaveDataMetaPolicy
|
||||
{
|
||||
internal const int ThumbnailFileSize = 0x40060;
|
||||
|
||||
private readonly SaveDataType _type;
|
||||
private const int ThumbnailFileSize = 0x40060;
|
||||
|
||||
public SaveDataMetaPolicy(SaveDataType saveType)
|
||||
{
|
||||
|
|
|
@ -352,6 +352,14 @@ public class FileSystemProxyImpl : IFileSystemProxy, IFileSystemProxyForLoader
|
|||
return saveFsService.CreateSaveDataFileSystemBySystemSaveDataId(in attribute, in creationInfo);
|
||||
}
|
||||
|
||||
public Result CreateSaveDataFileSystemWithCreationInfo2(in SaveDataCreationInfo2 creationInfo)
|
||||
{
|
||||
Result rc = GetSaveDataFileSystemService(out SaveDataFileSystemService saveFsService);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return saveFsService.CreateSaveDataFileSystemWithCreationInfo2(in creationInfo);
|
||||
}
|
||||
|
||||
public Result ExtendSaveDataFileSystem(SaveDataSpaceId spaceId, ulong saveDataId, long dataSize,
|
||||
long journalSize)
|
||||
{
|
||||
|
|
|
@ -136,7 +136,7 @@ public static class FileSystemServerInitializer
|
|||
saveFsServiceConfig.BufferManager = bufferManager;
|
||||
saveFsServiceConfig.GenerateRandomData = config.RandomGenerator;
|
||||
saveFsServiceConfig.IsPseudoSaveData = () => true;
|
||||
saveFsServiceConfig.MaxSaveFsCacheCount = 1;
|
||||
saveFsServiceConfig.SaveDataFileSystemCacheCount = 1;
|
||||
saveFsServiceConfig.SaveIndexerManager = saveDataIndexerManager;
|
||||
saveFsServiceConfig.FsServer = server;
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ namespace LibHac.FsSrv;
|
|||
|
||||
public interface ISaveDataIndexerManager
|
||||
{
|
||||
Result OpenSaveDataIndexerAccessor(ref UniqueRef<SaveDataIndexerAccessor> outAccessor, out bool neededInit, SaveDataSpaceId spaceId);
|
||||
Result OpenSaveDataIndexerAccessor(ref UniqueRef<SaveDataIndexerAccessor> outAccessor, out bool isInitialOpen, SaveDataSpaceId spaceId);
|
||||
void ResetIndexer(SaveDataSpaceId spaceId);
|
||||
void InvalidateIndexer(SaveDataSpaceId spaceId);
|
||||
}
|
||||
|
|
|
@ -2,15 +2,15 @@
|
|||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.Os;
|
||||
using LibHac.Util;
|
||||
using IFileSf = LibHac.FsSrv.Sf.IFile;
|
||||
|
||||
namespace LibHac.FsSrv.Impl;
|
||||
|
||||
public interface ISaveDataTransferCoreInterface : IDisposable
|
||||
{
|
||||
Result GetFreeSpaceSizeForSaveData(out long freeSpaceSize, SaveDataSpaceId spaceId);
|
||||
Result QuerySaveDataTotalSize(out long totalSize, long dataSize, long journalSize);
|
||||
Result GetFreeSpaceSizeForSaveData(out long outFreeSpaceSize, SaveDataSpaceId spaceId);
|
||||
Result QuerySaveDataTotalSize(out long outTotalSize, long dataSize, long journalSize);
|
||||
Result CheckSaveDataFile(long saveDataId, SaveDataSpaceId spaceId);
|
||||
Result CreateSaveDataFileSystemCore(in SaveDataAttribute attribute, in SaveDataCreationInfo creationInfo, in SaveDataMetaInfo metaInfo, in Optional<HashSalt> hashSalt, bool leaveUnfinalized);
|
||||
Result GetSaveDataInfo(out SaveDataInfo saveInfo, SaveDataSpaceId spaceId, in SaveDataAttribute attribute);
|
||||
|
@ -18,13 +18,15 @@ public interface ISaveDataTransferCoreInterface : IDisposable
|
|||
Result WriteSaveDataFileSystemExtraDataCore(SaveDataSpaceId spaceId, ulong saveDataId, in SaveDataExtraData extraData, SaveDataType type, bool updateTimeStamp);
|
||||
Result FinalizeSaveDataCreation(ulong saveDataId, SaveDataSpaceId spaceId);
|
||||
Result CancelSaveDataCreation(ulong saveDataId, SaveDataSpaceId spaceId);
|
||||
Result OpenSaveDataFile(ref SharedRef<IFileSf> file, SaveDataSpaceId spaceId, in SaveDataAttribute attribute, SaveDataMetaType metaType);
|
||||
Result OpenSaveDataMetaFileRaw(ref SharedRef<IFile> file, SaveDataSpaceId spaceId, ulong saveDataId, SaveDataMetaType metaType, OpenMode mode);
|
||||
Result OpenSaveDataFile(ref SharedRef<IFile> oufFile, SaveDataSpaceId spaceId, ulong saveDataId, OpenMode mode);
|
||||
Result OpenSaveDataMetaFileRaw(ref SharedRef<IFile> outFile, SaveDataSpaceId spaceId, ulong saveDataId, SaveDataMetaType metaType, OpenMode mode);
|
||||
Result OpenSaveDataInternalStorageFileSystemCore(ref SharedRef<IFileSystem> fileSystem, SaveDataSpaceId spaceId, ulong saveDataId, bool useSecondMacKey);
|
||||
Result OpenSaveDataFileSystemCore(ref SharedRef<IFileSystem> outFileSystem, out ulong outSaveDataId, SaveDataSpaceId spaceId, in SaveDataAttribute attribute, bool openReadOnly, bool cacheExtraData);
|
||||
Result ExtendSaveDataFileSystem(SaveDataSpaceId spaceId, ulong saveDataId, long dataSize, long journalSize);
|
||||
Result DeleteSaveDataFileSystemBySaveDataSpaceId(SaveDataSpaceId spaceId, ulong saveDataId);
|
||||
Result SwapSaveDataKeyAndState(SaveDataSpaceId spaceId, ulong saveDataId1, ulong saveDataId2);
|
||||
Result SetSaveDataState(SaveDataSpaceId spaceId, ulong saveDataId, SaveDataState state);
|
||||
Result SetSaveDataRank(SaveDataSpaceId spaceId, ulong saveDataId, SaveDataRank rank);
|
||||
Result OpenSaveDataIndexerAccessor(ref UniqueRef<SaveDataIndexerAccessor> outAccessor, SaveDataSpaceId spaceId);
|
||||
bool IsProhibited(ref UniqueLock<SdkMutex> outLock, ApplicationId applicationId);
|
||||
}
|
|
@ -46,7 +46,7 @@ internal class MultiCommitManager : IMultiCommitManager
|
|||
{
|
||||
private const int MaxFileSystemCount = 10;
|
||||
|
||||
public const ulong ProgramId = 0x0100000000000000;
|
||||
public const ulong ProgramId = 0;
|
||||
public const ulong SaveDataId = 0x8000000000000001;
|
||||
private const long SaveDataSize = 0xC000;
|
||||
private const long SaveJournalSize = 0xC000;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -15,13 +15,13 @@ using Utility = LibHac.FsSrv.Impl.Utility;
|
|||
|
||||
namespace LibHac.FsSrv;
|
||||
|
||||
public class SaveDataFileSystemServiceImpl
|
||||
public class SaveDataFileSystemServiceImpl : IDisposable
|
||||
{
|
||||
private Configuration _config;
|
||||
private EncryptionSeed _encryptionSeed;
|
||||
|
||||
private SaveDataFileSystemCacheManager _saveDataFsCacheManager;
|
||||
private SaveDataExtraDataAccessorCacheManager _extraDataCacheManager;
|
||||
private SaveDataFileSystemCacheManager _saveFileSystemCacheManager;
|
||||
private SaveDataExtraDataAccessorCacheManager _saveExtraDataCacheManager;
|
||||
// Save data porter manager
|
||||
private bool _isSdCardAccessible;
|
||||
private TimeStampGetter _timeStampGetter;
|
||||
|
@ -40,22 +40,10 @@ public class SaveDataFileSystemServiceImpl
|
|||
|
||||
public Result Get(out long timeStamp)
|
||||
{
|
||||
return _saveService.GetSaveDataCommitTimeStamp(out timeStamp);
|
||||
return _saveService.GetSaveDataCommitTimeStamp(out timeStamp).Ret();
|
||||
}
|
||||
}
|
||||
|
||||
public SaveDataFileSystemServiceImpl(in Configuration configuration)
|
||||
{
|
||||
_config = configuration;
|
||||
_saveDataFsCacheManager = new SaveDataFileSystemCacheManager();
|
||||
_extraDataCacheManager = new SaveDataExtraDataAccessorCacheManager();
|
||||
|
||||
_timeStampGetter = new TimeStampGetter(this);
|
||||
|
||||
Result rc = _saveDataFsCacheManager.Initialize(_config.MaxSaveFsCacheCount);
|
||||
Abort.DoAbortUnless(rc.IsSuccess());
|
||||
}
|
||||
|
||||
public struct Configuration
|
||||
{
|
||||
public BaseFileSystemServiceImpl BaseFsService;
|
||||
|
@ -68,7 +56,7 @@ public class SaveDataFileSystemServiceImpl
|
|||
public IBufferManager BufferManager;
|
||||
public RandomDataGenerator GenerateRandomData;
|
||||
public SaveDataTransferCryptoConfiguration SaveTransferCryptoConfig;
|
||||
public int MaxSaveFsCacheCount;
|
||||
public int SaveDataFileSystemCacheCount;
|
||||
public Func<bool> IsPseudoSaveData;
|
||||
public ISaveDataIndexerManager SaveIndexerManager;
|
||||
|
||||
|
@ -76,10 +64,36 @@ public class SaveDataFileSystemServiceImpl
|
|||
public FileSystemServer FsServer;
|
||||
}
|
||||
|
||||
internal Result GetProgramInfo(out ProgramInfo programInfo, ulong processId)
|
||||
private static bool IsDeviceUniqueMac(SaveDataSpaceId spaceId)
|
||||
{
|
||||
var registry = new ProgramRegistryImpl(_config.FsServer);
|
||||
return registry.GetProgramInfo(out programInfo, processId);
|
||||
return spaceId == SaveDataSpaceId.System ||
|
||||
spaceId == SaveDataSpaceId.User ||
|
||||
spaceId == SaveDataSpaceId.Temporary ||
|
||||
spaceId == SaveDataSpaceId.ProperSystem ||
|
||||
spaceId == SaveDataSpaceId.SafeMode;
|
||||
}
|
||||
|
||||
private static Result WipeData(IFileSystem fileSystem, in Path filePath, RandomDataGenerator random)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public SaveDataFileSystemServiceImpl(in Configuration configuration)
|
||||
{
|
||||
_config = configuration;
|
||||
_saveFileSystemCacheManager = new SaveDataFileSystemCacheManager();
|
||||
_saveExtraDataCacheManager = new SaveDataExtraDataAccessorCacheManager();
|
||||
|
||||
_timeStampGetter = new TimeStampGetter(this);
|
||||
|
||||
Result rc = _saveFileSystemCacheManager.Initialize(_config.SaveDataFileSystemCacheCount);
|
||||
Abort.DoAbortUnless(rc.IsSuccess());
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_saveFileSystemCacheManager.Dispose();
|
||||
_saveExtraDataCacheManager.Dispose();
|
||||
}
|
||||
|
||||
public Result DoesSaveDataEntityExist(out bool exists, SaveDataSpaceId spaceId, ulong saveDataId)
|
||||
|
@ -116,7 +130,12 @@ public class SaveDataFileSystemServiceImpl
|
|||
}
|
||||
}
|
||||
|
||||
// 14.3.0
|
||||
public Result OpenSaveDataFile(ref SharedRef<IFile> outFile, SaveDataSpaceId spaceId, ulong saveDataId,
|
||||
OpenMode openMode)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result OpenSaveDataFileSystem(ref SharedRef<IFileSystem> outFileSystem, SaveDataSpaceId spaceId,
|
||||
ulong saveDataId, in Path saveDataRootPath, bool openReadOnly, SaveDataType type, bool cacheExtraData)
|
||||
{
|
||||
|
@ -141,10 +160,10 @@ public class SaveDataFileSystemServiceImpl
|
|||
|
||||
using var saveDataFs = new SharedRef<ISaveDataFileSystem>();
|
||||
|
||||
using (_saveDataFsCacheManager.GetScopedLock())
|
||||
using (_extraDataCacheManager.GetScopedLock())
|
||||
using (_saveFileSystemCacheManager.GetScopedLock())
|
||||
using (_saveExtraDataCacheManager.GetScopedLock())
|
||||
{
|
||||
if (isEmulatedOnHost || !_saveDataFsCacheManager.GetCache(ref saveDataFs.Ref(), spaceId, saveDataId))
|
||||
if (isEmulatedOnHost || !_saveFileSystemCacheManager.GetCache(ref saveDataFs.Ref(), spaceId, saveDataId))
|
||||
{
|
||||
bool isDeviceUniqueMac = IsDeviceUniqueMac(spaceId);
|
||||
bool isJournalingSupported = SaveDataProperties.IsJournalingSupported(type);
|
||||
|
@ -163,13 +182,13 @@ public class SaveDataFileSystemServiceImpl
|
|||
using SharedRef<ISaveDataExtraDataAccessor> extraDataAccessor =
|
||||
SharedRef<ISaveDataExtraDataAccessor>.CreateCopy(in saveDataFs);
|
||||
|
||||
rc = _extraDataCacheManager.Register(in extraDataAccessor, spaceId, saveDataId);
|
||||
rc = _saveExtraDataCacheManager.Register(in extraDataAccessor, spaceId, saveDataId);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
}
|
||||
}
|
||||
|
||||
using var registerFs = new SharedRef<SaveDataFileSystemCacheRegister>(
|
||||
new SaveDataFileSystemCacheRegister(ref saveDataFs.Ref(), _saveDataFsCacheManager, spaceId, saveDataId));
|
||||
new SaveDataFileSystemCacheRegister(ref saveDataFs.Ref(), _saveFileSystemCacheManager, spaceId, saveDataId));
|
||||
|
||||
if (openReadOnly)
|
||||
{
|
||||
|
@ -203,11 +222,61 @@ public class SaveDataFileSystemServiceImpl
|
|||
}
|
||||
|
||||
public Result OpenSaveDataInternalStorageFileSystem(ref SharedRef<IFileSystem> outFileSystem,
|
||||
SaveDataSpaceId spaceId, ulong saveDataId, in Path saveDataRootPath, bool useSecondMacKey)
|
||||
SaveDataSpaceId spaceId, ulong saveDataId, in Path saveDataRootPath, bool useSecondMacKey,
|
||||
bool isReconstructible)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result ExtendSaveDataFileSystemCore(out long extendedTotalSize, ulong saveDataId, SaveDataSpaceId spaceId,
|
||||
SaveDataType type, long dataSize, long journalSize, in Path saveDataRootPath, bool isExtensionStart)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private Result OpenSaveDataImageFile(ref UniqueRef<IFile> outFile, SaveDataSpaceId spaceId, ulong saveDataId,
|
||||
in Path saveDataRootPath)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result StartExtendSaveDataFileSystem(out long extendedTotalSize, ulong saveDataId, SaveDataSpaceId spaceId,
|
||||
SaveDataType type, long dataSize, long journalSize, in Path saveDataRootPath)
|
||||
{
|
||||
return ExtendSaveDataFileSystemCore(out extendedTotalSize, saveDataId, spaceId, type, dataSize, journalSize,
|
||||
in saveDataRootPath, isExtensionStart: true);
|
||||
}
|
||||
|
||||
public Result ResumeExtendSaveDataFileSystem(out long extendedTotalSize, ulong saveDataId, SaveDataSpaceId spaceId,
|
||||
SaveDataType type, in Path saveDataRootPath)
|
||||
{
|
||||
return ExtendSaveDataFileSystemCore(out extendedTotalSize, saveDataId, spaceId, type, dataSize: 0,
|
||||
journalSize: 0, in saveDataRootPath, isExtensionStart: false);
|
||||
}
|
||||
|
||||
public Result FinishExtendSaveDataFileSystem(ulong saveDataId, SaveDataSpaceId spaceId)
|
||||
{
|
||||
Result rc = DeleteSaveDataMeta(saveDataId, spaceId, SaveDataMetaType.ExtensionContext);
|
||||
if (rc.IsFailure() && !ResultFs.PathNotFound.Includes(rc))
|
||||
return rc.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public void RevertExtendSaveDataFileSystem(ulong saveDataId, SaveDataSpaceId spaceId, long originalSize,
|
||||
in Path saveDataRootPath)
|
||||
{
|
||||
using var saveDataFile = new UniqueRef<IFile>();
|
||||
Result rc = OpenSaveDataImageFile(ref saveDataFile.Ref(), spaceId, saveDataId, in saveDataRootPath);
|
||||
|
||||
if (rc.IsSuccess())
|
||||
{
|
||||
saveDataFile.Get.SetSize(originalSize).IgnoreResult();
|
||||
}
|
||||
|
||||
FinishExtendSaveDataFileSystem(saveDataId, spaceId).IgnoreResult();
|
||||
}
|
||||
|
||||
public Result QuerySaveDataTotalSize(out long totalSize, int blockSize, long dataSize, long journalSize)
|
||||
{
|
||||
// Todo: Implement
|
||||
|
@ -316,6 +385,82 @@ public class SaveDataFileSystemServiceImpl
|
|||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result CreateSaveDataFileSystem(ulong saveDataId, in SaveDataCreationInfo2 creationInfo,
|
||||
in Path saveDataRootPath, bool skipFormat)
|
||||
{
|
||||
Unsafe.SkipInit(out Array18<byte> saveImageNameBuffer);
|
||||
|
||||
long dataSize = creationInfo.Size;
|
||||
long journalSize = creationInfo.JournalSize;
|
||||
ulong ownerId = creationInfo.OwnerId;
|
||||
SaveDataSpaceId spaceId = creationInfo.SpaceId;
|
||||
SaveDataFlags flags = creationInfo.Flags;
|
||||
|
||||
using var fileSystem = new SharedRef<IFileSystem>();
|
||||
|
||||
Result rc = OpenSaveDataDirectoryFileSystem(ref fileSystem.Ref(), creationInfo.SpaceId, in saveDataRootPath,
|
||||
allowEmulatedSave: false);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
using var saveImageName = new Path();
|
||||
rc = PathFunctions.SetUpFixedPathSaveId(ref saveImageName.Ref(), saveImageNameBuffer.Items, saveDataId);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
bool isPseudoSaveFs = _config.IsPseudoSaveData();
|
||||
bool isCreationSuccessful = false;
|
||||
|
||||
try
|
||||
{
|
||||
if (isPseudoSaveFs)
|
||||
{
|
||||
rc = FsSystem.Utility.EnsureDirectory(fileSystem.Get, in saveImageName);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
SaveDataExtraData extraData = default;
|
||||
extraData.Attribute = creationInfo.Attribute;
|
||||
extraData.OwnerId = ownerId;
|
||||
|
||||
rc = GetSaveDataCommitTimeStamp(out extraData.TimeStamp);
|
||||
if (rc.IsFailure())
|
||||
extraData.TimeStamp = 0;
|
||||
|
||||
extraData.CommitId = 0;
|
||||
_config.GenerateRandomData(SpanHelpers.AsByteSpan(ref extraData.CommitId));
|
||||
|
||||
extraData.Flags = flags;
|
||||
extraData.DataSize = dataSize;
|
||||
extraData.JournalSize = journalSize;
|
||||
extraData.FormatType = creationInfo.FormatType;
|
||||
|
||||
rc = WriteSaveDataFileSystemExtraData(spaceId, saveDataId, in extraData, in saveDataRootPath,
|
||||
creationInfo.Attribute.Type, updateTimeStamp: true);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
isCreationSuccessful = true;
|
||||
return Result.Success;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Delete any created save if something goes wrong.
|
||||
if (!isCreationSuccessful)
|
||||
{
|
||||
if (isPseudoSaveFs)
|
||||
{
|
||||
fileSystem.Get.DeleteDirectoryRecursively(in saveImageName).IgnoreResult();
|
||||
}
|
||||
else
|
||||
{
|
||||
fileSystem.Get.DeleteFile(in saveImageName).IgnoreResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Result CreateSaveDataFileSystem(ulong saveDataId, in SaveDataAttribute attribute,
|
||||
in SaveDataCreationInfo creationInfo, in Path saveDataRootPath, in Optional<HashSalt> hashSalt,
|
||||
bool skipFormat)
|
||||
|
@ -379,11 +524,6 @@ public class SaveDataFileSystemServiceImpl
|
|||
return Result.Success;
|
||||
}
|
||||
|
||||
private Result WipeData(IFileSystem fileSystem, in Path filePath, RandomDataGenerator random)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result DeleteSaveDataFileSystem(SaveDataSpaceId spaceId, ulong saveDataId, bool wipeSaveFile,
|
||||
in Path saveDataRootPath)
|
||||
{
|
||||
|
@ -391,7 +531,7 @@ public class SaveDataFileSystemServiceImpl
|
|||
|
||||
using var fileSystem = new SharedRef<IFileSystem>();
|
||||
|
||||
_saveDataFsCacheManager.Unregister(spaceId, saveDataId);
|
||||
_saveFileSystemCacheManager.Unregister(spaceId, saveDataId);
|
||||
|
||||
// Open the directory containing the save data
|
||||
Result rc = OpenSaveDataDirectoryFileSystem(ref fileSystem.Ref(), spaceId, in saveDataRootPath, false);
|
||||
|
@ -433,13 +573,13 @@ public class SaveDataFileSystemServiceImpl
|
|||
// Nintendo returns blank extra data for directory save data.
|
||||
// We've extended directory save data to store extra data so we don't need to do that.
|
||||
|
||||
using UniqueLockRef<SdkRecursiveMutexType> scopedLockFsCache = _saveDataFsCacheManager.GetScopedLock();
|
||||
using UniqueLockRef<SdkRecursiveMutexType> scopedLockExtraDataCache = _extraDataCacheManager.GetScopedLock();
|
||||
using UniqueLockRef<SdkRecursiveMutexType> scopedLockFsCache = _saveFileSystemCacheManager.GetScopedLock();
|
||||
using UniqueLockRef<SdkRecursiveMutexType> scopedLockExtraDataCache = _saveExtraDataCacheManager.GetScopedLock();
|
||||
|
||||
using var extraDataAccessor = new SharedRef<ISaveDataExtraDataAccessor>();
|
||||
|
||||
// Try to grab an extra data accessor for the requested save from the cache.
|
||||
Result rc = _extraDataCacheManager.GetCache(ref extraDataAccessor.Ref(), spaceId, saveDataId);
|
||||
Result rc = _saveExtraDataCacheManager.GetCache(ref extraDataAccessor.Ref(), spaceId, saveDataId);
|
||||
|
||||
if (rc.IsSuccess())
|
||||
{
|
||||
|
@ -456,7 +596,7 @@ public class SaveDataFileSystemServiceImpl
|
|||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
// Try to grab an accessor from the cache again.
|
||||
rc = _extraDataCacheManager.GetCache(ref extraDataAccessor.Ref(), spaceId, saveDataId);
|
||||
rc = _saveExtraDataCacheManager.GetCache(ref extraDataAccessor.Ref(), spaceId, saveDataId);
|
||||
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
|
@ -478,13 +618,13 @@ public class SaveDataFileSystemServiceImpl
|
|||
// Nintendo does nothing when writing directory save data extra data.
|
||||
// We've extended directory save data to store extra data so we don't return early.
|
||||
|
||||
using UniqueLockRef<SdkRecursiveMutexType> scopedLockFsCache = _saveDataFsCacheManager.GetScopedLock();
|
||||
using UniqueLockRef<SdkRecursiveMutexType> scopedLockExtraDataCache = _extraDataCacheManager.GetScopedLock();
|
||||
using UniqueLockRef<SdkRecursiveMutexType> scopedLockFsCache = _saveFileSystemCacheManager.GetScopedLock();
|
||||
using UniqueLockRef<SdkRecursiveMutexType> scopedLockExtraDataCache = _saveExtraDataCacheManager.GetScopedLock();
|
||||
|
||||
using var extraDataAccessor = new SharedRef<ISaveDataExtraDataAccessor>();
|
||||
|
||||
// Try to grab an extra data accessor for the requested save from the cache.
|
||||
Result rc = _extraDataCacheManager.GetCache(ref extraDataAccessor.Ref(), spaceId, saveDataId);
|
||||
Result rc = _saveExtraDataCacheManager.GetCache(ref extraDataAccessor.Ref(), spaceId, saveDataId);
|
||||
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
|
@ -498,7 +638,7 @@ public class SaveDataFileSystemServiceImpl
|
|||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
// Try to grab an accessor from the cache again.
|
||||
rc = _extraDataCacheManager.GetCache(ref extraDataAccessor.Ref(), spaceId, saveDataId);
|
||||
rc = _saveExtraDataCacheManager.GetCache(ref extraDataAccessor.Ref(), spaceId, saveDataId);
|
||||
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
|
@ -592,12 +732,6 @@ public class SaveDataFileSystemServiceImpl
|
|||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenSaveDataDirectoryFileSystemImpl(ref SharedRef<IFileSystem> outFileSystem,
|
||||
SaveDataSpaceId spaceId, in Path basePath)
|
||||
{
|
||||
return OpenSaveDataDirectoryFileSystemImpl(ref outFileSystem, spaceId, in basePath, true);
|
||||
}
|
||||
|
||||
public Result OpenSaveDataDirectoryFileSystemImpl(ref SharedRef<IFileSystem> outFileSystem,
|
||||
SaveDataSpaceId spaceId, in Path basePath, bool createIfMissing)
|
||||
{
|
||||
|
@ -680,15 +814,10 @@ public class SaveDataFileSystemServiceImpl
|
|||
}
|
||||
}
|
||||
|
||||
public Result SetSdCardEncryptionSeed(in EncryptionSeed seed)
|
||||
public Result OpenSaveDataDirectoryFileSystemImpl(ref SharedRef<IFileSystem> outFileSystem,
|
||||
SaveDataSpaceId spaceId, in Path basePath)
|
||||
{
|
||||
_encryptionSeed = seed;
|
||||
|
||||
_config.SaveFsCreator.SetSdCardEncryptionSeed(seed.Value);
|
||||
_config.SaveIndexerManager.InvalidateIndexer(SaveDataSpaceId.SdSystem);
|
||||
_config.SaveIndexerManager.InvalidateIndexer(SaveDataSpaceId.SdUser);
|
||||
|
||||
return Result.Success;
|
||||
return OpenSaveDataDirectoryFileSystemImpl(ref outFileSystem, spaceId, in basePath, true);
|
||||
}
|
||||
|
||||
public Result IsProvisionallyCommittedSaveData(out bool isProvisionallyCommitted, in SaveDataInfo saveInfo)
|
||||
|
@ -704,13 +833,15 @@ public class SaveDataFileSystemServiceImpl
|
|||
return spaceId == SaveDataSpaceId.User && IsSaveEmulated(in saveDataRootPath);
|
||||
}
|
||||
|
||||
public bool IsDeviceUniqueMac(SaveDataSpaceId spaceId)
|
||||
public Result SetSdCardEncryptionSeed(in EncryptionSeed seed)
|
||||
{
|
||||
return spaceId == SaveDataSpaceId.System ||
|
||||
spaceId == SaveDataSpaceId.User ||
|
||||
spaceId == SaveDataSpaceId.Temporary ||
|
||||
spaceId == SaveDataSpaceId.ProperSystem ||
|
||||
spaceId == SaveDataSpaceId.SafeMode;
|
||||
_encryptionSeed = seed;
|
||||
|
||||
_config.SaveFsCreator.SetSdCardEncryptionSeed(seed.Value);
|
||||
_config.SaveIndexerManager.InvalidateIndexer(SaveDataSpaceId.SdSystem);
|
||||
_config.SaveIndexerManager.InvalidateIndexer(SaveDataSpaceId.SdUser);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public void SetSdCardAccessibility(bool isAccessible)
|
||||
|
@ -753,6 +884,11 @@ public class SaveDataFileSystemServiceImpl
|
|||
return programId;
|
||||
}
|
||||
|
||||
public SaveDataTransferCryptoConfiguration GetSaveDataTransferCryptoConfiguration()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result GetSaveDataIndexCount(out int count)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out count);
|
||||
|
@ -766,10 +902,10 @@ public class SaveDataFileSystemServiceImpl
|
|||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenSaveDataIndexerAccessor(ref UniqueRef<SaveDataIndexerAccessor> outAccessor, out bool neededInit,
|
||||
SaveDataSpaceId spaceId)
|
||||
public Result OpenSaveDataIndexerAccessor(ref UniqueRef<SaveDataIndexerAccessor> outAccessor,
|
||||
out bool isInitialOpen, SaveDataSpaceId spaceId)
|
||||
{
|
||||
return _config.SaveIndexerManager.OpenSaveDataIndexerAccessor(ref outAccessor, out neededInit, spaceId);
|
||||
return _config.SaveIndexerManager.OpenSaveDataIndexerAccessor(ref outAccessor, out isInitialOpen, spaceId);
|
||||
}
|
||||
|
||||
public void ResetTemporaryStorageIndexer()
|
||||
|
|
|
@ -122,14 +122,14 @@ internal class SaveDataIndexerManager : ISaveDataIndexerManager, IDisposable
|
|||
/// The accessor must be disposed after use.
|
||||
/// </remarks>
|
||||
/// <param name="outAccessor">If the method returns successfully, contains the created accessor.</param>
|
||||
/// <param name="neededInit">If the method returns successfully, contains <see langword="true"/>
|
||||
/// if the indexer needed to be initialized.</param>
|
||||
/// <param name="isInitialOpen">If the method returns successfully, contains <see langword="true"/>
|
||||
/// if the indexer needed to be initialized because this was the first time it was opened.</param>
|
||||
/// <param name="spaceId">The <see cref="SaveDataSpaceId"/> of the indexer to open.</param>
|
||||
/// <returns>The <see cref="Result"/> of the operation.</returns>
|
||||
public Result OpenSaveDataIndexerAccessor(ref UniqueRef<SaveDataIndexerAccessor> outAccessor,
|
||||
out bool neededInit, SaveDataSpaceId spaceId)
|
||||
out bool isInitialOpen, SaveDataSpaceId spaceId)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out neededInit);
|
||||
UnsafeHelpers.SkipParamInit(out isInitialOpen);
|
||||
|
||||
if (_isBisUserRedirectionEnabled && spaceId == SaveDataSpaceId.User)
|
||||
{
|
||||
|
@ -226,7 +226,7 @@ internal class SaveDataIndexerManager : ISaveDataIndexerManager, IDisposable
|
|||
}
|
||||
|
||||
outAccessor.Reset(new SaveDataIndexerAccessor(indexer, ref indexerLock.Ref()));
|
||||
neededInit = wasIndexerInitialized;
|
||||
isInitialOpen = wasIndexerInitialized;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace LibHac.FsSrv.Sf;
|
|||
/// <summary>
|
||||
/// The interface most programs use to interact with the FS service.
|
||||
/// </summary>
|
||||
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
|
||||
/// <remarks>Based on FS 14.1.0 (nnSdk 14.3.0)</remarks>
|
||||
public interface IFileSystemProxy : IDisposable
|
||||
{
|
||||
Result SetCurrentProcess(ulong processId);
|
||||
|
@ -42,6 +42,7 @@ public interface IFileSystemProxy : IDisposable
|
|||
Result GetCacheStorageSize(out long dataSize, out long journalSize, ushort index);
|
||||
Result CreateSaveDataFileSystemWithHashSalt(in SaveDataAttribute attribute, in SaveDataCreationInfo creationInfo, in SaveDataMetaInfo metaInfo, in HashSalt hashSalt);
|
||||
Result OpenHostFileSystemWithOption(ref SharedRef<IFileSystemSf> outFileSystem, in FspPath path, MountHostOption option);
|
||||
Result CreateSaveDataFileSystemWithCreationInfo2(in SaveDataCreationInfo2 creationInfo);
|
||||
Result OpenSaveDataFileSystem(ref SharedRef<IFileSystemSf> outFileSystem, SaveDataSpaceId spaceId, in SaveDataAttribute attribute);
|
||||
Result OpenSaveDataFileSystemBySystemSaveDataId(ref SharedRef<IFileSystemSf> outFileSystem, SaveDataSpaceId spaceId, in SaveDataAttribute attribute);
|
||||
Result OpenReadOnlySaveDataFileSystem(ref SharedRef<IFileSystemSf> outFileSystem, SaveDataSpaceId spaceId, in SaveDataAttribute attribute);
|
||||
|
|
|
@ -136,6 +136,7 @@ public class TypeLayoutTests
|
|||
Assert.Equal(0x40, GetOffset(in s, in s.OwnerId));
|
||||
Assert.Equal(0x48, GetOffset(in s, in s.TimeStamp));
|
||||
Assert.Equal(0x50, GetOffset(in s, in s.Flags));
|
||||
Assert.Equal(0x54, GetOffset(in s, in s.FormatType));
|
||||
Assert.Equal(0x58, GetOffset(in s, in s.DataSize));
|
||||
Assert.Equal(0x60, GetOffset(in s, in s.JournalSize));
|
||||
Assert.Equal(0x68, GetOffset(in s, in s.CommitId));
|
||||
|
|
Loading…
Reference in a new issue