public static ResultCode LoadSaveDataFileSystem(ServiceCtx context, bool readOnly, out IFileSystem loadedFileSystem) { loadedFileSystem = null; SaveSpaceId saveSpaceId = (SaveSpaceId)context.RequestData.ReadInt64(); ulong titleId = context.RequestData.ReadUInt64(); UInt128 userId = context.RequestData.ReadStruct <UInt128>(); long saveId = context.RequestData.ReadInt64(); SaveDataType saveDataType = (SaveDataType)context.RequestData.ReadByte(); SaveInfo saveInfo = new SaveInfo(titleId, saveId, saveDataType, saveSpaceId, userId); string savePath = context.Device.FileSystem.GetSavePath(context, saveInfo); try { LocalFileSystem fileSystem = new LocalFileSystem(savePath); LibHac.Fs.IFileSystem saveFileSystem = new DirectorySaveDataFileSystem(fileSystem); if (readOnly) { saveFileSystem = new ReadOnlyFileSystem(saveFileSystem); } loadedFileSystem = new IFileSystem(saveFileSystem); } catch (HorizonResultException ex) { return((ResultCode)ex.ResultValue.Value); } return(ResultCode.Success); }
public long LoadSaveDataFileSystem(ServiceCtx context) { SaveSpaceId saveSpaceId = (SaveSpaceId)context.RequestData.ReadInt64(); long titleId = context.RequestData.ReadInt64(); UInt128 userId = context.RequestData.ReadStruct <UInt128>(); long saveId = context.RequestData.ReadInt64(); SaveDataType saveDataType = (SaveDataType)context.RequestData.ReadByte(); SaveInfo saveInfo = new SaveInfo(titleId, saveId, saveDataType, userId, saveSpaceId); string savePath = context.Device.FileSystem.GetGameSavePath(saveInfo, context); try { LocalFileSystem fileSystem = new LocalFileSystem(savePath); DirectorySaveDataFileSystem saveFileSystem = new DirectorySaveDataFileSystem(fileSystem); MakeObject(context, new IFileSystem(saveFileSystem)); } catch (HorizonResultException ex) { return(ex.ResultValue.Value); } return(0); }
public void Rollback_WriteExtraDataThenCloseFs_ExtraDataIsRolledBack() { var baseFs = new InMemoryFileSystem(); DirectorySaveDataFileSystem.CreateNew(out DirectorySaveDataFileSystem saveFs, baseFs, true, true, true) .ThrowIfFailure(); // Write extra data and close with committing var originalExtraData = new SaveDataExtraData(); originalExtraData.DataSize = 0x12345; saveFs.WriteExtraData(in originalExtraData).ThrowIfFailure(); saveFs.CommitExtraData(false).ThrowIfFailure(); saveFs.Dispose(); DirectorySaveDataFileSystem.CreateNew(out saveFs, baseFs, true, true, true).ThrowIfFailure(); // Write a new extra data and close without committing var newExtraData = new SaveDataExtraData(); newExtraData.DataSize = 0x67890; saveFs.WriteExtraData(in newExtraData).ThrowIfFailure(); saveFs.Dispose(); // Read extra data should match the first one DirectorySaveDataFileSystem.CreateNew(out saveFs, baseFs, true, true, true).ThrowIfFailure(); Assert.Success(saveFs.ReadExtraData(out SaveDataExtraData extraData)); Assert.Equal(originalExtraData, extraData); }
public void Rollback_WriteExtraDataThenRollback_ExtraDataIsRolledBack() { var baseFs = new InMemoryFileSystem(); DirectorySaveDataFileSystem.CreateNew(out DirectorySaveDataFileSystem saveFs, baseFs, true, true, true) .ThrowIfFailure(); var originalExtraData = new SaveDataExtraData(); originalExtraData.DataSize = 0x12345; saveFs.WriteExtraData(in originalExtraData).ThrowIfFailure(); saveFs.CommitExtraData(false).ThrowIfFailure(); saveFs.Dispose(); DirectorySaveDataFileSystem.CreateNew(out saveFs, baseFs, true, true, true).ThrowIfFailure(); var newExtraData = new SaveDataExtraData(); newExtraData.DataSize = 0x67890; saveFs.WriteExtraData(in newExtraData).ThrowIfFailure(); Assert.Success(saveFs.Rollback()); Assert.Success(saveFs.ReadExtraData(out SaveDataExtraData extraData)); Assert.Equal(originalExtraData, extraData); }
public void LoadSaveDataFileSystem(ServiceCtx context) { SaveSpaceId saveSpaceId = (SaveSpaceId)context.RequestData.ReadInt64(); long titleId = context.RequestData.ReadInt64(); UInt128 userId = new UInt128( context.RequestData.ReadInt64(), context.RequestData.ReadInt64()); long saveId = context.RequestData.ReadInt64(); SaveDataType saveDataType = (SaveDataType)context.RequestData.ReadByte(); SaveInfo saveInfo = new SaveInfo(titleId, saveId, saveDataType, userId, saveSpaceId); string savePath = context.Device.FileSystem.GetGameSavePath(saveInfo, context); LocalFileSystem fileSystem = new LocalFileSystem(savePath); DirectorySaveDataFileSystem saveFileSystem = new DirectorySaveDataFileSystem(fileSystem); MakeObject(context, new IFileSystem(saveFileSystem)); }
public void Commit_AfterSuccessfulCommit_CanReadCommittedExtraData() { var baseFs = new InMemoryFileSystem(); DirectorySaveDataFileSystem.CreateNew(out DirectorySaveDataFileSystem saveFs, baseFs, true, true, true) .ThrowIfFailure(); var originalExtraData = new SaveDataExtraData(); originalExtraData.DataSize = 0x12345; saveFs.WriteExtraData(in originalExtraData).ThrowIfFailure(); Assert.Success(saveFs.CommitExtraData(false)); saveFs.Dispose(); DirectorySaveDataFileSystem.CreateNew(out saveFs, baseFs, true, true, true).ThrowIfFailure(); Assert.Success(saveFs.ReadExtraData(out SaveDataExtraData extraData)); Assert.Equal(originalExtraData, extraData); }
public Result Create(out ReferenceCountedDisposable <IFileSystem> fileSystem, out ReferenceCountedDisposable <ISaveDataExtraDataAccessor> extraDataAccessor, ISaveDataFileSystemCacheManager cacheManager, ref ReferenceCountedDisposable <IFileSystem> baseFileSystem, 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); 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)); if (rc.IsFailure()) { return(ResultFs.PathNotFound.Includes(rc) ? ResultFs.TargetNotFound.LogConverted(rc) : rc); } if (type == DirectoryEntryType.Directory) { if (!allowDirectorySaveData) { return(ResultFs.InvalidSaveDataEntryType.Log()); } SubdirectoryFileSystem subDirFs = null; ReferenceCountedDisposable <DirectorySaveDataFileSystem> saveFs = null; try { subDirFs = new SubdirectoryFileSystem(ref baseFileSystem); 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); } finally { subDirFs?.Dispose(); saveFs?.Dispose(); } } ReferenceCountedDisposable <IStorage> fileStorage = null; 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 (!isJournalingSupported) { throw new NotImplementedException(); } // Todo: Properly handle shared storage fileSystem = new ReferenceCountedDisposable <IFileSystem>(new SaveDataFileSystem(_keySet, fileStorage.Target, IntegrityCheckLevel.ErrorOnInvalid, false)); // Todo: ISaveDataExtraDataAccessor return(Result.Success); } finally { fileStorage?.Dispose(); } }