mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Add save data extra data functions to SaveDataFileSystemServiceImpl
Adds ReadSaveDataFileSystemExtraData and WriteSaveDataFileSystemExtraData Auto-format SaveDataFileSystemServiceImpl Use SdkRecursiveMutexType instead of SdkRecursiveMutex in SaveDataExtraDataAccessorCacheManager
This commit is contained in:
parent
7aae39c358
commit
f67d51cb37
3 changed files with 134 additions and 25 deletions
|
@ -37,12 +37,12 @@ namespace LibHac.FsSrv.Impl
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly LinkedList<Cache> _accessorList;
|
private readonly LinkedList<Cache> _accessorList;
|
||||||
private SdkRecursiveMutex _mutex;
|
private SdkRecursiveMutexType _mutex;
|
||||||
|
|
||||||
public SaveDataExtraDataAccessorCacheManager()
|
public SaveDataExtraDataAccessorCacheManager()
|
||||||
{
|
{
|
||||||
_accessorList = new LinkedList<Cache>();
|
_accessorList = new LinkedList<Cache>();
|
||||||
_mutex = new SdkRecursiveMutex();
|
_mutex.Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
@ -55,7 +55,7 @@ namespace LibHac.FsSrv.Impl
|
||||||
{
|
{
|
||||||
var cache = new Cache(accessor, spaceId, saveDataId);
|
var cache = new Cache(accessor, spaceId, saveDataId);
|
||||||
|
|
||||||
using ScopedLock<SdkRecursiveMutex> scopedLock = ScopedLock.Lock(ref _mutex);
|
using ScopedLock<SdkRecursiveMutexType> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||||
|
|
||||||
_accessorList.AddLast(cache);
|
_accessorList.AddLast(cache);
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
|
@ -63,7 +63,7 @@ namespace LibHac.FsSrv.Impl
|
||||||
|
|
||||||
public void Unregister(SaveDataSpaceId spaceId, ulong saveDataId)
|
public void Unregister(SaveDataSpaceId spaceId, ulong saveDataId)
|
||||||
{
|
{
|
||||||
using ScopedLock<SdkRecursiveMutex> scopedLock = ScopedLock.Lock(ref _mutex);
|
using ScopedLock<SdkRecursiveMutexType> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||||
|
|
||||||
UnregisterImpl(spaceId, saveDataId);
|
UnregisterImpl(spaceId, saveDataId);
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ namespace LibHac.FsSrv.Impl
|
||||||
{
|
{
|
||||||
UnsafeHelpers.SkipParamInit(out accessor);
|
UnsafeHelpers.SkipParamInit(out accessor);
|
||||||
|
|
||||||
using ScopedLock<SdkRecursiveMutex> scopedLock = ScopedLock.Lock(ref _mutex);
|
using ScopedLock<SdkRecursiveMutexType> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||||
|
|
||||||
LinkedListNode<Cache> currentNode = _accessorList.First;
|
LinkedListNode<Cache> currentNode = _accessorList.First;
|
||||||
|
|
||||||
|
@ -126,9 +126,9 @@ namespace LibHac.FsSrv.Impl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScopedLock<SdkRecursiveMutex> GetScopedLock()
|
public ScopedLock<SdkRecursiveMutexType> GetScopedLock()
|
||||||
{
|
{
|
||||||
return new ScopedLock<SdkRecursiveMutex>(ref _mutex);
|
return new ScopedLock<SdkRecursiveMutexType>(ref _mutex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -165,7 +165,7 @@ namespace LibHac.FsSrv
|
||||||
ReferenceCountedDisposable<ISaveDataExtraDataAccessor> extraDataAccessor = null;
|
ReferenceCountedDisposable<ISaveDataExtraDataAccessor> extraDataAccessor = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using ScopedLock<SdkRecursiveMutex> scopedLock = _extraDataCacheManager.GetScopedLock();
|
using ScopedLock<SdkRecursiveMutexType> scopedLock = _extraDataCacheManager.GetScopedLock();
|
||||||
|
|
||||||
// Todo: Update ISaveDataFileSystemCreator
|
// Todo: Update ISaveDataFileSystemCreator
|
||||||
bool useDeviceUniqueMac = IsDeviceUniqueMac(spaceId);
|
bool useDeviceUniqueMac = IsDeviceUniqueMac(spaceId);
|
||||||
|
@ -217,8 +217,8 @@ namespace LibHac.FsSrv
|
||||||
var metaDirPath = // /saveMeta/
|
var metaDirPath = // /saveMeta/
|
||||||
new U8Span(new[]
|
new U8Span(new[]
|
||||||
{
|
{
|
||||||
(byte) '/', (byte) 's', (byte) 'a', (byte) 'v', (byte) 'e', (byte) 'M', (byte) 'e', (byte) 't',
|
(byte)'/', (byte)'s', (byte)'a', (byte)'v', (byte)'e', (byte)'M', (byte)'e', (byte)'t',
|
||||||
(byte) 'a', (byte) '/'
|
(byte)'a', (byte)'/'
|
||||||
});
|
});
|
||||||
|
|
||||||
Span<byte> directoryName = stackalloc byte[0x1B];
|
Span<byte> directoryName = stackalloc byte[0x1B];
|
||||||
|
@ -287,8 +287,8 @@ namespace LibHac.FsSrv
|
||||||
var metaDirPath = // /saveMeta
|
var metaDirPath = // /saveMeta
|
||||||
new U8Span(new[]
|
new U8Span(new[]
|
||||||
{
|
{
|
||||||
(byte) '/', (byte) 's', (byte) 'a', (byte) 'v', (byte) 'e', (byte) 'M', (byte) 'e', (byte) 't',
|
(byte)'/', (byte)'s', (byte)'a', (byte)'v', (byte)'e', (byte)'M', (byte)'e', (byte)'t',
|
||||||
(byte) 'a'
|
(byte)'a'
|
||||||
});
|
});
|
||||||
|
|
||||||
ReferenceCountedDisposable<IFileSystem> fileSystem = null;
|
ReferenceCountedDisposable<IFileSystem> fileSystem = null;
|
||||||
|
@ -427,15 +427,115 @@ namespace LibHac.FsSrv
|
||||||
public Result ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, SaveDataSpaceId spaceId,
|
public Result ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, SaveDataSpaceId spaceId,
|
||||||
ulong saveDataId, SaveDataType type, U8Span saveDataRootPath)
|
ulong saveDataId, SaveDataType type, U8Span saveDataRootPath)
|
||||||
{
|
{
|
||||||
// Todo: Find a way to store extra data for directory save data
|
UnsafeHelpers.SkipParamInit(out extraData);
|
||||||
extraData = new SaveDataExtraData();
|
|
||||||
return Result.Success;
|
// 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 ScopedLock<SdkRecursiveMutexType> scopedLockFsCache = _saveDataFsCacheManager.GetScopedLock();
|
||||||
|
using ScopedLock<SdkRecursiveMutexType> scopedLockExtraDataCache = _extraDataCacheManager.GetScopedLock();
|
||||||
|
|
||||||
|
ReferenceCountedDisposable<ISaveDataExtraDataAccessor> extraDataAccessor = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Try to grab an extra data accessor for the requested save from the cache.
|
||||||
|
Result rc = _extraDataCacheManager.GetCache(out extraDataAccessor, spaceId, saveDataId);
|
||||||
|
|
||||||
|
if (rc.IsSuccess())
|
||||||
|
{
|
||||||
|
// An extra data accessor was found in the cache. Read the extra data from it.
|
||||||
|
return extraDataAccessor.Target.ReadExtraData(out extraData);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReferenceCountedDisposable<IFileSystem> unusedSaveDataFs = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// We won't actually use the returned save data FS.
|
||||||
|
// Opening the FS should cache an extra data accessor for it.
|
||||||
|
rc = OpenSaveDataFileSystem(out unusedSaveDataFs, spaceId, saveDataId, saveDataRootPath,
|
||||||
|
openReadOnly: true, type, cacheExtraData: true);
|
||||||
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
|
// Try to grab an accessor from the cache again.
|
||||||
|
rc = _extraDataCacheManager.GetCache(out extraDataAccessor, spaceId, saveDataId);
|
||||||
|
|
||||||
|
if (rc.IsFailure())
|
||||||
|
{
|
||||||
|
// No extra data accessor was registered for the requested save data.
|
||||||
|
// Return a blank extra data struct.
|
||||||
|
extraData = new SaveDataExtraData();
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return extraDataAccessor.Target.ReadExtraData(out extraData);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
unusedSaveDataFs?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
extraDataAccessor?.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Result WriteSaveDataFileSystemExtraData(SaveDataSpaceId spaceId, ulong saveDataId,
|
public Result WriteSaveDataFileSystemExtraData(SaveDataSpaceId spaceId, ulong saveDataId,
|
||||||
in SaveDataExtraData extraData, U8Span saveDataRootPath, SaveDataType type, bool updateTimeStamp)
|
in SaveDataExtraData extraData, U8Span saveDataRootPath, SaveDataType type, bool updateTimeStamp)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
// 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 ScopedLock<SdkRecursiveMutexType> scopedLockFsCache = _saveDataFsCacheManager.GetScopedLock();
|
||||||
|
using ScopedLock<SdkRecursiveMutexType> scopedLockExtraDataCache = _extraDataCacheManager.GetScopedLock();
|
||||||
|
|
||||||
|
ReferenceCountedDisposable<ISaveDataExtraDataAccessor> extraDataAccessor = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Try to grab an extra data accessor for the requested save from the cache.
|
||||||
|
Result rc = _extraDataCacheManager.GetCache(out extraDataAccessor, spaceId, saveDataId);
|
||||||
|
|
||||||
|
if (rc.IsFailure())
|
||||||
|
{
|
||||||
|
// No accessor was found in the cache. Try to open one.
|
||||||
|
ReferenceCountedDisposable<IFileSystem> unusedSaveDataFs = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// We won't actually use the returned save data FS.
|
||||||
|
// Opening the FS should cache an extra data accessor for it.
|
||||||
|
rc = OpenSaveDataFileSystem(out unusedSaveDataFs, spaceId, saveDataId, saveDataRootPath,
|
||||||
|
openReadOnly: false, type, cacheExtraData: true);
|
||||||
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
|
// Try to grab an accessor from the cache again.
|
||||||
|
rc = _extraDataCacheManager.GetCache(out extraDataAccessor, spaceId, saveDataId);
|
||||||
|
|
||||||
|
if (rc.IsFailure())
|
||||||
|
{
|
||||||
|
// No extra data accessor was registered for the requested save data, so don't do anything.
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
unusedSaveDataFs?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We should have a valid accessor if we've reached this point.
|
||||||
|
// Write and commit the extra data.
|
||||||
|
rc = extraDataAccessor.Target.WriteExtraData(in extraData);
|
||||||
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
|
rc = extraDataAccessor.Target.CommitExtraData(updateTimeStamp);
|
||||||
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
extraDataAccessor?.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Result CorruptSaveDataFileSystem(SaveDataSpaceId spaceId, ulong saveDataId, long offset,
|
public Result CorruptSaveDataFileSystem(SaveDataSpaceId spaceId, ulong saveDataId, long offset,
|
||||||
|
@ -527,14 +627,16 @@ namespace LibHac.FsSrv
|
||||||
switch (spaceId)
|
switch (spaceId)
|
||||||
{
|
{
|
||||||
case SaveDataSpaceId.System:
|
case SaveDataSpaceId.System:
|
||||||
rc = _config.BaseFsService.OpenBisFileSystem(out tempFs, U8Span.Empty, BisPartitionId.System, true);
|
rc = _config.BaseFsService.OpenBisFileSystem(out tempFs, U8Span.Empty, BisPartitionId.System,
|
||||||
|
true);
|
||||||
if (rc.IsFailure()) return rc;
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
return Utility.WrapSubDirectory(out fileSystem, ref tempFs, basePath, createIfMissing);
|
return Utility.WrapSubDirectory(out fileSystem, ref tempFs, basePath, createIfMissing);
|
||||||
|
|
||||||
case SaveDataSpaceId.User:
|
case SaveDataSpaceId.User:
|
||||||
case SaveDataSpaceId.Temporary:
|
case SaveDataSpaceId.Temporary:
|
||||||
rc = _config.BaseFsService.OpenBisFileSystem(out tempFs, U8Span.Empty, BisPartitionId.User, true);
|
rc = _config.BaseFsService.OpenBisFileSystem(out tempFs, U8Span.Empty, BisPartitionId.User,
|
||||||
|
true);
|
||||||
if (rc.IsFailure()) return rc;
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
return Utility.WrapSubDirectory(out fileSystem, ref tempFs, basePath, createIfMissing);
|
return Utility.WrapSubDirectory(out fileSystem, ref tempFs, basePath, createIfMissing);
|
||||||
|
@ -558,13 +660,15 @@ namespace LibHac.FsSrv
|
||||||
in _encryptionSeed);
|
in _encryptionSeed);
|
||||||
|
|
||||||
case SaveDataSpaceId.ProperSystem:
|
case SaveDataSpaceId.ProperSystem:
|
||||||
rc = _config.BaseFsService.OpenBisFileSystem(out tempFs, U8Span.Empty, BisPartitionId.SystemProperPartition, true);
|
rc = _config.BaseFsService.OpenBisFileSystem(out tempFs, U8Span.Empty,
|
||||||
|
BisPartitionId.SystemProperPartition, true);
|
||||||
if (rc.IsFailure()) return rc;
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
return Utility.WrapSubDirectory(out fileSystem, ref tempFs, basePath, createIfMissing);
|
return Utility.WrapSubDirectory(out fileSystem, ref tempFs, basePath, createIfMissing);
|
||||||
|
|
||||||
case SaveDataSpaceId.SafeMode:
|
case SaveDataSpaceId.SafeMode:
|
||||||
rc = _config.BaseFsService.OpenBisFileSystem(out tempFs, U8Span.Empty, BisPartitionId.SafeMode, true);
|
rc = _config.BaseFsService.OpenBisFileSystem(out tempFs, U8Span.Empty, BisPartitionId.SafeMode,
|
||||||
|
true);
|
||||||
if (rc.IsFailure()) return rc;
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
return Utility.WrapSubDirectory(out fileSystem, ref tempFs, basePath, createIfMissing);
|
return Utility.WrapSubDirectory(out fileSystem, ref tempFs, basePath, createIfMissing);
|
||||||
|
|
|
@ -155,5 +155,10 @@ namespace LibHac.FsSystem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ScopedLock<SdkRecursiveMutexType> GetScopedLock()
|
||||||
|
{
|
||||||
|
return new ScopedLock<SdkRecursiveMutexType>(ref _mutex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue