Example #1
0
        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);
        }
Example #2
0
        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);
        }
Example #5
0
        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);
        }
Example #7
0
        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();
            }
        }