Update ISaveDataFileSystemCreator.Create

Update method parameters and rewrite the method to use SaveDataSharedFileStorage.

SaveDataFileSystemCreator now requires a FileSystemServer at construction time, so DefaultFsServerObjects must be created after FileSystemServer construction but before FileSystemServer initialization.
This commit is contained in:
Alex Barney 2021-05-16 22:52:27 -07:00
parent d1a49b989a
commit 7294206116
9 changed files with 156 additions and 123 deletions

View File

@ -12,7 +12,8 @@ namespace LibHac.FsSrv
public EmulatedGameCard GameCard { get; set; } public EmulatedGameCard GameCard { get; set; }
public EmulatedSdCard SdCard { get; set; } public EmulatedSdCard SdCard { get; set; }
public static DefaultFsServerObjects GetDefaultEmulatedCreators(IFileSystem rootFileSystem, KeySet keySet) public static DefaultFsServerObjects GetDefaultEmulatedCreators(IFileSystem rootFileSystem, KeySet keySet,
FileSystemServer fsServer)
{ {
var creators = new FileSystemCreatorInterfaces(); var creators = new FileSystemCreatorInterfaces();
var gameCard = new EmulatedGameCard(keySet); var gameCard = new EmulatedGameCard(keySet);
@ -25,7 +26,7 @@ namespace LibHac.FsSrv
creators.StorageOnNcaCreator = new StorageOnNcaCreator(keySet); creators.StorageOnNcaCreator = new StorageOnNcaCreator(keySet);
creators.TargetManagerFileSystemCreator = new TargetManagerFileSystemCreator(); creators.TargetManagerFileSystemCreator = new TargetManagerFileSystemCreator();
creators.SubDirectoryFileSystemCreator = new SubDirectoryFileSystemCreator(); creators.SubDirectoryFileSystemCreator = new SubDirectoryFileSystemCreator();
creators.SaveDataFileSystemCreator = new SaveDataFileSystemCreator(keySet, null, null); creators.SaveDataFileSystemCreator = new SaveDataFileSystemCreator(fsServer, keySet, null, null);
creators.GameCardStorageCreator = gcStorageCreator; creators.GameCardStorageCreator = gcStorageCreator;
creators.GameCardFileSystemCreator = new EmulatedGameCardFsCreator(gcStorageCreator, gameCard); creators.GameCardFileSystemCreator = new EmulatedGameCardFsCreator(gcStorageCreator, gameCard);
creators.EncryptedFileSystemCreator = new EncryptedFileSystemCreator(keySet); creators.EncryptedFileSystemCreator = new EncryptedFileSystemCreator(keySet);

View File

@ -74,10 +74,6 @@ namespace LibHac.FsSrv
Memory<byte> heapBuffer = GC.AllocateArray<byte>(BufferManagerHeapSize, true); Memory<byte> heapBuffer = GC.AllocateArray<byte>(BufferManagerHeapSize, true);
bufferManager.Initialize(BufferManagerCacheSize, heapBuffer, BufferManagerBlockSize); bufferManager.Initialize(BufferManagerCacheSize, heapBuffer, BufferManagerBlockSize);
// Todo: A non-hacky way of initializing the save data creator
config.FsCreators.SaveDataFileSystemCreator =
new SaveDataFileSystemCreator(config.KeySet, bufferManager, randomGenerator);
var saveDataIndexerManager = new SaveDataIndexerManager(server.Hos.Fs, Fs.SaveData.SaveIndexerId, var saveDataIndexerManager = new SaveDataIndexerManager(server.Hos.Fs, Fs.SaveData.SaveIndexerId,
new ArrayPoolMemoryResource(), new SdHandleManager(), false); new ArrayPoolMemoryResource(), new SdHandleManager(), false);
@ -264,10 +260,5 @@ namespace LibHac.FsSrv
/// If null, an empty set will be created. /// If null, an empty set will be created.
/// </summary> /// </summary>
public ExternalKeySet ExternalKeySet { get; set; } public ExternalKeySet ExternalKeySet { get; set; }
/// <summary>
/// A keyset used for decrypting content.
/// </summary>
public KeySet KeySet { get; set; }
} }
} }

View File

@ -11,8 +11,13 @@ namespace LibHac.FsSrv.FsCreator
Result Create(out ReferenceCountedDisposable<IFileSystem> fileSystem, Result Create(out ReferenceCountedDisposable<IFileSystem> fileSystem,
out ReferenceCountedDisposable<ISaveDataExtraDataAccessor> extraDataAccessor, out ReferenceCountedDisposable<ISaveDataExtraDataAccessor> extraDataAccessor,
ReferenceCountedDisposable<IFileSystem> sourceFileSystem, ulong saveDataId, bool allowDirectorySaveData, ISaveDataFileSystemCacheManager cacheManager, ref ReferenceCountedDisposable<IFileSystem> baseFileSystem,
bool useDeviceUniqueMac, SaveDataType type, ISaveDataCommitTimeStampGetter timeStampGetter); SaveDataSpaceId spaceId, ulong saveDataId, bool allowDirectorySaveData, bool useDeviceUniqueMac,
bool isJournalingSupported, bool isMultiCommitSupported, bool openReadOnly, bool openShared,
ISaveDataCommitTimeStampGetter timeStampGetter);
Result CreateExtraDataAccessor(out ReferenceCountedDisposable<ISaveDataExtraDataAccessor> extraDataAccessor,
ReferenceCountedDisposable<IFileSystem> sourceFileSystem);
void SetSdCardEncryptionSeed(ReadOnlySpan<byte> seed); void SetSdCardEncryptionSeed(ReadOnlySpan<byte> seed);
} }

View File

@ -1,10 +1,14 @@
using System; using System;
using LibHac.Common; using LibHac.Common;
using LibHac.Common.Keys; using LibHac.Common.Keys;
using LibHac.Diag;
using LibHac.Fs; using LibHac.Fs;
using LibHac.Fs.Fsa; using LibHac.Fs.Fsa;
using LibHac.FsSystem; using LibHac.FsSystem;
using LibHac.FsSystem.Save; using LibHac.FsSystem.Save;
using LibHac.Util;
using OpenType = LibHac.FsSrv.SaveDataOpenTypeSetFileStorage.OpenType;
namespace LibHac.FsSrv.FsCreator namespace LibHac.FsSrv.FsCreator
{ {
@ -13,13 +17,16 @@ namespace LibHac.FsSrv.FsCreator
private IBufferManager _bufferManager; private IBufferManager _bufferManager;
private RandomDataGenerator _randomGenerator; private RandomDataGenerator _randomGenerator;
// LibHac Additions
private KeySet _keySet; private KeySet _keySet;
private FileSystemServer _fsServer;
public SaveDataFileSystemCreator(KeySet keySet, IBufferManager bufferManager, public SaveDataFileSystemCreator(FileSystemServer fsServer, KeySet keySet, IBufferManager bufferManager,
RandomDataGenerator randomGenerator) RandomDataGenerator randomGenerator)
{ {
_bufferManager = bufferManager; _bufferManager = bufferManager;
_randomGenerator = randomGenerator; _randomGenerator = randomGenerator;
_fsServer = fsServer;
_keySet = keySet; _keySet = keySet;
} }
@ -30,68 +37,92 @@ namespace LibHac.FsSrv.FsCreator
public Result Create(out ReferenceCountedDisposable<IFileSystem> fileSystem, public Result Create(out ReferenceCountedDisposable<IFileSystem> fileSystem,
out ReferenceCountedDisposable<ISaveDataExtraDataAccessor> extraDataAccessor, out ReferenceCountedDisposable<ISaveDataExtraDataAccessor> extraDataAccessor,
ReferenceCountedDisposable<IFileSystem> sourceFileSystem, ulong saveDataId, bool allowDirectorySaveData, ISaveDataFileSystemCacheManager cacheManager, ref ReferenceCountedDisposable<IFileSystem> baseFileSystem,
bool useDeviceUniqueMac, SaveDataType type, ISaveDataCommitTimeStampGetter timeStampGetter) SaveDataSpaceId spaceId, ulong saveDataId, bool allowDirectorySaveData, bool useDeviceUniqueMac,
bool isJournalingSupported, bool isMultiCommitSupported, bool openReadOnly, bool openShared,
ISaveDataCommitTimeStampGetter timeStampGetter)
{ {
Span<byte> saveImageName = stackalloc byte[0x12];
UnsafeHelpers.SkipParamInit(out fileSystem, out extraDataAccessor); UnsafeHelpers.SkipParamInit(out fileSystem, out extraDataAccessor);
var saveDataPath = $"/{saveDataId:x16}".ToU8String(); Assert.SdkRequiresNotNull(cacheManager);
var sb = new U8StringBuilder(saveImageName);
sb.Append((byte)'/').AppendFormat(saveDataId, 'x', 16);
Result rc = baseFileSystem.Target.GetEntryType(out DirectoryEntryType type, new U8Span(saveImageName));
Result rc = sourceFileSystem.Target.GetEntryType(out DirectoryEntryType entryType, saveDataPath);
if (rc.IsFailure()) if (rc.IsFailure())
{ {
return ResultFs.PathNotFound.Includes(rc) ? ResultFs.TargetNotFound.LogConverted(rc) : rc; return ResultFs.PathNotFound.Includes(rc) ? ResultFs.TargetNotFound.LogConverted(rc) : rc;
} }
switch (entryType) if (type == DirectoryEntryType.Directory)
{ {
case DirectoryEntryType.Directory: if (!allowDirectorySaveData)
if (!allowDirectorySaveData) return ResultFs.InvalidSaveDataEntryType.Log(); return ResultFs.InvalidSaveDataEntryType.Log();
var subDirFs = new SubdirectoryFileSystem(ref sourceFileSystem); SubdirectoryFileSystem subDirFs = null;
ReferenceCountedDisposable<DirectorySaveDataFileSystem> saveFs = null;
rc = subDirFs.Initialize(saveDataPath);
if (rc.IsFailure())
{
subDirFs.Dispose();
return rc;
}
bool isPersistentSaveData = type != SaveDataType.Temporary;
bool isUserSaveData = type == SaveDataType.Account || type == SaveDataType.Device;
rc = DirectorySaveDataFileSystem.CreateNew(out DirectorySaveDataFileSystem saveFs, subDirFs,
timeStampGetter, _randomGenerator, isPersistentSaveData, isUserSaveData, true, null);
if (rc.IsFailure()) return rc;
ReferenceCountedDisposable<DirectorySaveDataFileSystem> sharedSaveFs = null;
try try
{ {
sharedSaveFs = new ReferenceCountedDisposable<DirectorySaveDataFileSystem>(saveFs); subDirFs = new SubdirectoryFileSystem(ref baseFileSystem);
fileSystem = sharedSaveFs.AddReference<IFileSystem>();
extraDataAccessor = sharedSaveFs.AddReference<ISaveDataExtraDataAccessor>(); rc = subDirFs.Initialize(new U8Span(saveImageName));
if (rc.IsFailure()) return rc;
saveFs = DirectorySaveDataFileSystem.CreateShared(Shared.Move(ref subDirFs), _fsServer.Hos.Fs);
rc = saveFs.Target.Initialize(timeStampGetter, _randomGenerator, isJournalingSupported,
isMultiCommitSupported, !openReadOnly);
if (rc.IsFailure()) return rc;
fileSystem = saveFs.AddReference<IFileSystem>();
extraDataAccessor = saveFs.AddReference<ISaveDataExtraDataAccessor>();
return Result.Success; return Result.Success;
} }
finally finally
{ {
sharedSaveFs?.Dispose(); subDirFs?.Dispose();
saveFs?.Dispose();
}
} }
case DirectoryEntryType.File: ReferenceCountedDisposable<IStorage> fileStorage = null;
rc = sourceFileSystem.Target.OpenFile(out IFile saveDataFile, saveDataPath, OpenMode.ReadWrite); try
{
Optional<OpenType> openType =
openShared ? new Optional<OpenType>(OpenType.Normal) : new Optional<OpenType>();
rc = _fsServer.OpenSaveDataStorage(out fileStorage, ref baseFileSystem, spaceId, saveDataId,
OpenMode.ReadWrite, openType);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
var saveDataStorage = new DisposingFileStorage(saveDataFile); if (!isJournalingSupported)
{
throw new NotImplementedException();
}
// Todo: Properly handle shared storage
fileSystem = new ReferenceCountedDisposable<IFileSystem>(new SaveDataFileSystem(_keySet, fileSystem = new ReferenceCountedDisposable<IFileSystem>(new SaveDataFileSystem(_keySet,
saveDataStorage, IntegrityCheckLevel.ErrorOnInvalid, false)); fileStorage.Target, IntegrityCheckLevel.ErrorOnInvalid, false));
// Todo: ISaveDataExtraDataAccessor // Todo: ISaveDataExtraDataAccessor
return Result.Success; return Result.Success;
default:
throw new ArgumentOutOfRangeException();
} }
finally
{
fileStorage?.Dispose();
}
}
public Result CreateExtraDataAccessor(
out ReferenceCountedDisposable<ISaveDataExtraDataAccessor> extraDataAccessor,
ReferenceCountedDisposable<IFileSystem> sourceFileSystem)
{
throw new NotImplementedException();
} }
public void SetSdCardEncryptionSeed(ReadOnlySpan<byte> seed) public void SetSdCardEncryptionSeed(ReadOnlySpan<byte> seed)

View File

@ -167,11 +167,14 @@ namespace LibHac.FsSrv
{ {
using ScopedLock<SdkRecursiveMutexType> scopedLock = _extraDataCacheManager.GetScopedLock(); using ScopedLock<SdkRecursiveMutexType> scopedLock = _extraDataCacheManager.GetScopedLock();
// Todo: Update ISaveDataFileSystemCreator bool openShared = SaveDataProperties.IsSharedOpenNeeded(type);
bool isMultiCommitSupported = SaveDataProperties.IsMultiCommitSupported(type);
bool isJournalingSupported = SaveDataProperties.IsJournalingSupported(type);
bool useDeviceUniqueMac = IsDeviceUniqueMac(spaceId); bool useDeviceUniqueMac = IsDeviceUniqueMac(spaceId);
rc = _config.SaveFsCreator.Create(out saveFs, out extraDataAccessor, saveDirectoryFs, rc = _config.SaveFsCreator.Create(out saveFs, out extraDataAccessor, _saveDataFsCacheManager,
saveDataId, allowDirectorySaveData, useDeviceUniqueMac, type, _timeStampGetter); ref saveDirectoryFs, spaceId, saveDataId, allowDirectorySaveData, useDeviceUniqueMac,
isJournalingSupported, isMultiCommitSupported, openReadOnly, openShared, _timeStampGetter);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
saveDataFs = Shared.Move(ref saveFs); saveDataFs = Shared.Move(ref saveFs);
@ -188,7 +191,6 @@ namespace LibHac.FsSrv
finally finally
{ {
saveFs?.Dispose(); saveFs?.Dispose();
cachedSaveDataFs?.Dispose();
extraDataAccessor?.Dispose(); extraDataAccessor?.Dispose();
} }
} }
@ -204,8 +206,6 @@ namespace LibHac.FsSrv
finally finally
{ {
saveDirectoryFs?.Dispose(); saveDirectoryFs?.Dispose();
// ReSharper disable once ExpressionIsAlwaysNull
// ReSharper disable once ConstantConditionalAccessQualifier
cachedSaveDataFs?.Dispose(); cachedSaveDataFs?.Dispose();
saveDataFs?.Dispose(); saveDataFs?.Dispose();
} }

View File

@ -47,9 +47,9 @@ namespace LibHac.FsSystem
// Todo: Unique file system for disposal // Todo: Unique file system for disposal
private int _openWritableFileCount; private int _openWritableFileCount;
private bool _isPersistentSaveData; private bool _isJournalingSupported;
private bool _canCommitProvisionally; private bool _isMultiCommitSupported;
private bool _useTransactions; private bool _isJournalingEnabled;
// Additions to support extra data // Additions to support extra data
private ISaveDataCommitTimeStampGetter _timeStampGetter; private ISaveDataCommitTimeStampGetter _timeStampGetter;
@ -124,12 +124,12 @@ namespace LibHac.FsSystem
public static Result CreateNew(out DirectorySaveDataFileSystem created, IFileSystem baseFileSystem, public static Result CreateNew(out DirectorySaveDataFileSystem created, IFileSystem baseFileSystem,
ISaveDataCommitTimeStampGetter timeStampGetter, RandomDataGenerator randomGenerator, ISaveDataCommitTimeStampGetter timeStampGetter, RandomDataGenerator randomGenerator,
bool isPersistentSaveData, bool canCommitProvisionally, bool useTransactions, bool isJournalingSupported, bool isMultiCommitSupported, bool isJournalingEnabled,
FileSystemClient fsClient) FileSystemClient fsClient)
{ {
var obj = new DirectorySaveDataFileSystem(baseFileSystem, fsClient); var obj = new DirectorySaveDataFileSystem(baseFileSystem, fsClient);
Result rc = obj.Initialize(timeStampGetter, randomGenerator, isPersistentSaveData, canCommitProvisionally, Result rc = obj.Initialize(timeStampGetter, randomGenerator, isJournalingSupported, isMultiCommitSupported,
useTransactions); isJournalingEnabled);
if (rc.IsSuccess()) if (rc.IsSuccess())
{ {
@ -143,10 +143,17 @@ namespace LibHac.FsSystem
} }
public static Result CreateNew(out DirectorySaveDataFileSystem created, IFileSystem baseFileSystem, public static Result CreateNew(out DirectorySaveDataFileSystem created, IFileSystem baseFileSystem,
bool isPersistentSaveData, bool canCommitProvisionally, bool useTransactions) bool isJournalingSupported, bool isMultiCommitSupported, bool isJournalingEnabled)
{ {
return CreateNew(out created, baseFileSystem, null, null, isPersistentSaveData, canCommitProvisionally, return CreateNew(out created, baseFileSystem, null, null, isJournalingSupported, isMultiCommitSupported,
useTransactions, null); isJournalingEnabled, null);
}
public static ReferenceCountedDisposable<DirectorySaveDataFileSystem> CreateShared(IFileSystem baseFileSystem,
FileSystemClient fsClient)
{
var fileSystem = new DirectorySaveDataFileSystem(baseFileSystem, fsClient);
return new ReferenceCountedDisposable<DirectorySaveDataFileSystem>(fileSystem);
} }
/// <summary> /// <summary>
@ -181,17 +188,17 @@ namespace LibHac.FsSystem
base.Dispose(disposing); base.Dispose(disposing);
} }
private Result Initialize(bool isPersistentSaveData, bool canCommitProvisionally, bool useTransactions) public Result Initialize(bool isJournalingSupported, bool isMultiCommitSupported, bool isJournalingEnabled)
{ {
return Initialize(null, null, isPersistentSaveData, canCommitProvisionally, useTransactions); return Initialize(null, null, isJournalingSupported, isMultiCommitSupported, isJournalingEnabled);
} }
private Result Initialize(ISaveDataCommitTimeStampGetter timeStampGetter, RandomDataGenerator randomGenerator, public Result Initialize(ISaveDataCommitTimeStampGetter timeStampGetter, RandomDataGenerator randomGenerator,
bool isPersistentSaveData, bool canCommitProvisionally, bool useTransactions) bool isJournalingSupported, bool isMultiCommitSupported, bool isJournalingEnabled)
{ {
_isPersistentSaveData = isPersistentSaveData; _isJournalingSupported = isJournalingSupported;
_canCommitProvisionally = canCommitProvisionally; _isMultiCommitSupported = isMultiCommitSupported;
_useTransactions = useTransactions; _isJournalingEnabled = isJournalingEnabled;
_timeStampGetter = timeStampGetter ?? _timeStampGetter; _timeStampGetter = timeStampGetter ?? _timeStampGetter;
_randomGenerator = randomGenerator ?? _randomGenerator; _randomGenerator = randomGenerator ?? _randomGenerator;
@ -205,7 +212,7 @@ namespace LibHac.FsSystem
rc = _baseFs.CreateDirectory(WorkingDirectoryPath); rc = _baseFs.CreateDirectory(WorkingDirectoryPath);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
if (_isPersistentSaveData) if (_isJournalingSupported)
{ {
rc = _baseFs.CreateDirectory(CommittedDirectoryPath); rc = _baseFs.CreateDirectory(CommittedDirectoryPath);
@ -215,15 +222,15 @@ namespace LibHac.FsSystem
} }
} }
// Only the working directory is needed for temporary savedata // Only the working directory is needed for non-journaling savedata
if (!_isPersistentSaveData) if (!_isJournalingSupported)
return Result.Success; return Result.Success;
rc = _baseFs.GetEntryType(out _, CommittedDirectoryPath); rc = _baseFs.GetEntryType(out _, CommittedDirectoryPath);
if (rc.IsSuccess()) if (rc.IsSuccess())
{ {
if (!_useTransactions) if (!_isJournalingEnabled)
return Result.Success; return Result.Success;
rc = SynchronizeDirectory(WorkingDirectoryPath, CommittedDirectoryPath); rc = SynchronizeDirectory(WorkingDirectoryPath, CommittedDirectoryPath);
@ -254,7 +261,8 @@ namespace LibHac.FsSystem
if (StringUtils.GetLength(relativePath, PathTools.MaxPathLength + 1) > PathTools.MaxPathLength) if (StringUtils.GetLength(relativePath, PathTools.MaxPathLength + 1) > PathTools.MaxPathLength)
return ResultFs.TooLongPath.Log(); return ResultFs.TooLongPath.Log();
U8Span workingPath = !_useTransactions && _isPersistentSaveData // Use the committed directory directly if journaling is supported but not enabled
U8Span workingPath = _isJournalingSupported && !_isJournalingEnabled
? CommittedDirectoryPath ? CommittedDirectoryPath
: WorkingDirectoryPath; : WorkingDirectoryPath;
@ -466,7 +474,7 @@ namespace LibHac.FsSystem
{ {
using ScopedLock<SdkMutexType> lk = ScopedLock.Lock(ref _mutex); using ScopedLock<SdkMutexType> lk = ScopedLock.Lock(ref _mutex);
if (!_useTransactions || !_isPersistentSaveData) if (!_isJournalingEnabled || !_isJournalingSupported)
return Result.Success; return Result.Success;
if (_openWritableFileCount > 0) if (_openWritableFileCount > 0)
@ -499,7 +507,7 @@ namespace LibHac.FsSystem
protected override Result DoCommitProvisionally(long counter) protected override Result DoCommitProvisionally(long counter)
{ {
if (!_canCommitProvisionally) if (!_isMultiCommitSupported)
return ResultFs.UnsupportedCommitProvisionallyForDirectorySaveDataFileSystem.Log(); return ResultFs.UnsupportedCommitProvisionallyForDirectorySaveDataFileSystem.Log();
return Result.Success; return Result.Success;
@ -507,11 +515,11 @@ namespace LibHac.FsSystem
protected override Result DoRollback() protected override Result DoRollback()
{ {
// No old data is kept for temporary save data, so there's nothing to rollback to // No old data is kept for non-journaling save data, so there's nothing to rollback to
if (!_isPersistentSaveData) if (!_isJournalingSupported)
return Result.Success; return Result.Success;
return Initialize(_isPersistentSaveData, _canCommitProvisionally, _useTransactions); return Initialize(_isJournalingSupported, _isMultiCommitSupported, _isJournalingEnabled);
} }
protected override Result DoGetFreeSpaceSize(out long freeSpace, U8Span path) protected override Result DoGetFreeSpaceSize(out long freeSpace, U8Span path)
@ -589,7 +597,7 @@ namespace LibHac.FsSystem
rc = _baseFs.CreateFile(WorkingExtraDataPath, Unsafe.SizeOf<SaveDataExtraData>()); rc = _baseFs.CreateFile(WorkingExtraDataPath, Unsafe.SizeOf<SaveDataExtraData>());
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
if (_isPersistentSaveData) if (_isJournalingSupported)
{ {
rc = _baseFs.CreateFile(CommittedExtraDataPath, Unsafe.SizeOf<SaveDataExtraData>()); rc = _baseFs.CreateFile(CommittedExtraDataPath, Unsafe.SizeOf<SaveDataExtraData>());
if (rc.IsFailure() && !ResultFs.PathAlreadyExists.Includes(rc)) return rc; if (rc.IsFailure() && !ResultFs.PathAlreadyExists.Includes(rc)) return rc;
@ -602,8 +610,8 @@ namespace LibHac.FsSystem
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
} }
// Only the working extra data is needed for temporary savedata // Only the working extra data is needed for non-journaling savedata
if (!_isPersistentSaveData) if (!_isJournalingSupported)
return Result.Success; return Result.Success;
rc = _baseFs.GetEntryType(out _, CommittedExtraDataPath); rc = _baseFs.GetEntryType(out _, CommittedExtraDataPath);
@ -613,7 +621,7 @@ namespace LibHac.FsSystem
rc = EnsureExtraDataSize(CommittedExtraDataPath); rc = EnsureExtraDataSize(CommittedExtraDataPath);
if (rc.IsFailure()) return rc; if (rc.IsFailure()) return rc;
if (!_useTransactions) if (!_isJournalingEnabled)
return Result.Success; return Result.Success;
return SynchronizeExtraData(WorkingExtraDataPath, CommittedExtraDataPath); return SynchronizeExtraData(WorkingExtraDataPath, CommittedExtraDataPath);
@ -684,7 +692,7 @@ namespace LibHac.FsSystem
private U8Span GetExtraDataPath() private U8Span GetExtraDataPath()
{ {
return !_useTransactions && _isPersistentSaveData return _isJournalingSupported && !_isJournalingEnabled
? CommittedExtraDataPath ? CommittedExtraDataPath
: WorkingExtraDataPath; : WorkingExtraDataPath;
} }
@ -757,7 +765,7 @@ namespace LibHac.FsSystem
{ {
Assert.SdkRequires(_mutex.IsLockedByCurrentThread()); Assert.SdkRequires(_mutex.IsLockedByCurrentThread());
if (!_useTransactions || !_isPersistentSaveData) if (!_isJournalingSupported || !_isJournalingEnabled)
return Result.Success; return Result.Success;
Result RenameCommittedFile() => _baseFs.RenameFile(CommittedExtraDataPath, SynchronizingExtraDataPath); Result RenameCommittedFile() => _baseFs.RenameFile(CommittedExtraDataPath, SynchronizingExtraDataPath);

View File

@ -7,36 +7,21 @@ namespace LibHac
{ {
public static class HorizonFactory public static class HorizonFactory
{ {
public static Horizon CreateWithFsConfig(HorizonConfiguration config, FileSystemServerConfig fsServerConfig) public static Horizon CreateWithDefaultFsConfig(HorizonConfiguration config, IFileSystem rootFileSystem,
KeySet keySet)
{ {
var horizon = new Horizon(config); var horizon = new Horizon(config);
HorizonClient fsServerClient = horizon.CreatePrivilegedHorizonClient(); HorizonClient fsServerClient = horizon.CreatePrivilegedHorizonClient();
var fsServer = new FileSystemServer(fsServerClient); var fsServer = new FileSystemServer(fsServerClient);
FileSystemServerInitializer.InitializeWithConfig(fsServerClient, fsServer, fsServerConfig); var defaultObjects = DefaultFsServerObjects.GetDefaultEmulatedCreators(rootFileSystem, keySet, fsServer);
HorizonClient bcatServerClient = horizon.CreateHorizonClient();
_ = new BcatServer(bcatServerClient);
return horizon;
}
public static Horizon CreateWithDefaultFsConfig(HorizonConfiguration config, IFileSystem rootFileSystem, KeySet keySet)
{
var horizon = new Horizon(config);
var defaultObjects = DefaultFsServerObjects.GetDefaultEmulatedCreators(rootFileSystem, keySet);
HorizonClient fsServerClient = horizon.CreatePrivilegedHorizonClient();
var fsServer = new FileSystemServer(fsServerClient);
var fsServerConfig = new FileSystemServerConfig var fsServerConfig = new FileSystemServerConfig
{ {
DeviceOperator = defaultObjects.DeviceOperator, DeviceOperator = defaultObjects.DeviceOperator,
ExternalKeySet = keySet.ExternalKeySet, ExternalKeySet = keySet.ExternalKeySet,
FsCreators = defaultObjects.FsCreators, FsCreators = defaultObjects.FsCreators,
KeySet = keySet
}; };
FileSystemServerInitializer.InitializeWithConfig(fsServerClient, fsServer, fsServerConfig); FileSystemServerInitializer.InitializeWithConfig(fsServerClient, fsServer, fsServerConfig);

View File

@ -12,7 +12,12 @@ namespace LibHac.Tests.Fs.FileSystemClientTests
rootFs = new InMemoryFileSystem(); rootFs = new InMemoryFileSystem();
var keySet = new KeySet(); var keySet = new KeySet();
var defaultObjects = DefaultFsServerObjects.GetDefaultEmulatedCreators(rootFs, keySet); var horizon = new Horizon(new HorizonConfiguration());
HorizonClient fsServerClient = horizon.CreatePrivilegedHorizonClient();
var fsServer = new FileSystemServer(fsServerClient);
var defaultObjects = DefaultFsServerObjects.GetDefaultEmulatedCreators(rootFs, keySet, fsServer);
defaultObjects.SdCard.SetSdCardInsertionStatus(sdCardInserted); defaultObjects.SdCard.SetSdCardInsertionStatus(sdCardInserted);
@ -20,9 +25,8 @@ namespace LibHac.Tests.Fs.FileSystemClientTests
config.FsCreators = defaultObjects.FsCreators; config.FsCreators = defaultObjects.FsCreators;
config.DeviceOperator = defaultObjects.DeviceOperator; config.DeviceOperator = defaultObjects.DeviceOperator;
config.ExternalKeySet = new ExternalKeySet(); config.ExternalKeySet = new ExternalKeySet();
config.KeySet = keySet;
Horizon horizon = LibHac.HorizonFactory.CreateWithFsConfig(new HorizonConfiguration(), config); FileSystemServerInitializer.InitializeWithConfig(fsServerClient, fsServer, config);
HorizonClient horizonClient = horizon.CreatePrivilegedHorizonClient(); HorizonClient horizonClient = horizon.CreatePrivilegedHorizonClient();

View File

@ -1,4 +1,5 @@
using LibHac.Common.Keys; using LibHac.Bcat;
using LibHac.Common.Keys;
using LibHac.Fs; using LibHac.Fs;
using LibHac.Fs.Fsa; using LibHac.Fs.Fsa;
using LibHac.FsSrv; using LibHac.FsSrv;
@ -12,15 +13,22 @@ namespace LibHac.Tests
IFileSystem rootFs = new InMemoryFileSystem(); IFileSystem rootFs = new InMemoryFileSystem();
var keySet = new KeySet(); var keySet = new KeySet();
var defaultObjects = DefaultFsServerObjects.GetDefaultEmulatedCreators(rootFs, keySet); var horizon = new Horizon(new HorizonConfiguration());
HorizonClient fsServerClient = horizon.CreatePrivilegedHorizonClient();
var fsServer = new FileSystemServer(fsServerClient);
var defaultObjects = DefaultFsServerObjects.GetDefaultEmulatedCreators(rootFs, keySet, fsServer);
var config = new FileSystemServerConfig(); var config = new FileSystemServerConfig();
config.FsCreators = defaultObjects.FsCreators; config.FsCreators = defaultObjects.FsCreators;
config.DeviceOperator = defaultObjects.DeviceOperator; config.DeviceOperator = defaultObjects.DeviceOperator;
config.ExternalKeySet = new ExternalKeySet(); config.ExternalKeySet = new ExternalKeySet();
config.KeySet = keySet;
Horizon horizon = LibHac.HorizonFactory.CreateWithFsConfig(new HorizonConfiguration(), config); FileSystemServerInitializer.InitializeWithConfig(fsServerClient, fsServer, config);
HorizonClient bcatServerClient = horizon.CreateHorizonClient();
_ = new BcatServer(bcatServerClient);
return horizon; return horizon;
} }