Esempio n. 1
0
        private Result OpenSaveDataFileSystem2(out IFileSystem fileSystem, SaveDataSpaceId spaceId,
                                               ref SaveDataAttribute attribute, bool openReadOnly)
        {
            fileSystem = default;

            // Missing permission checks

            SaveDataAttribute attributeCopy;

            if (attribute.TitleId == TitleId.Zero)
            {
                throw new NotImplementedException();
            }
            else
            {
                attributeCopy = attribute;
            }

            SaveDataSpaceId actualSpaceId;

            if (attributeCopy.Type == SaveDataType.CacheStorage)
            {
                // Check whether the save is on the SD card or the BIS
                throw new NotImplementedException();
            }
            else
            {
                actualSpaceId = spaceId;
            }

            return(OpenSaveDataFileSystem3(out fileSystem, actualSpaceId, ref attributeCopy, openReadOnly));
        }
Esempio n. 2
0
        private static Result FixExtraDataInSpaceId(HorizonClient hos, SaveDataSpaceId spaceId)
        {
            Span <SaveDataInfo> info = stackalloc SaveDataInfo[8];

            using var iterator = new UniqueRef <SaveDataIterator>();

            Result rc = hos.Fs.OpenSaveDataIterator(ref iterator.Ref(), spaceId);

            if (rc.IsFailure())
            {
                return(rc);
            }

            while (true)
            {
                rc = iterator.Get.ReadSaveDataInfo(out long count, info);
                if (rc.IsFailure())
                {
                    return(rc);
                }

                if (count == 0)
                {
                    return(Result.Success);
                }

                for (int i = 0; i < count; i++)
                {
                    rc = FixExtraData(out bool wasFixNeeded, hos, in info[i]);
Esempio n. 3
0
        public Result DoesSaveDataExist(out bool exists, SaveDataSpaceId spaceId, ulong saveDataId)
        {
            exists = false;

            Result rc = OpenSaveDataDirectory(out IFileSystem fileSystem, spaceId, string.Empty, true);

            if (rc.IsFailure())
            {
                return(rc);
            }

            string saveDataPath = $"/{saveDataId:x16}";

            rc = fileSystem.GetEntryType(out _, saveDataPath.ToU8Span());

            if (rc.IsFailure())
            {
                if (ResultFs.PathNotFound.Includes(rc))
                {
                    return(Result.Success);
                }

                return(rc);
            }

            exists = true;
            return(Result.Success);
        }
Esempio n. 4
0
        public static Result MountSystemSaveData(this FileSystemClient fs, U8Span mountName,
                                                 SaveDataSpaceId spaceId, ulong saveDataId, UserId userId)
        {
            Result rc = MountHelpers.CheckMountName(mountName);

            if (rc.IsFailure())
            {
                return(rc);
            }

            IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject();

            SaveDataAttribute attribute = default;

            attribute.UserId     = userId;
            attribute.SaveDataId = saveDataId;

            rc = fsProxy.OpenSaveDataFileSystemBySystemSaveDataId(out IFileSystem fileSystem, spaceId, ref attribute);
            if (rc.IsFailure())
            {
                return(rc);
            }

            return(fs.Register(mountName, fileSystem));
        }
        public static Result CreateCacheStorage(this FileSystemClient fs, TitleId applicationId,
                                                SaveDataSpaceId spaceId, TitleId ownerId, short index, long size, long journalSize, SaveDataFlags flags)
        {
            return(fs.RunOperationWithAccessLog(AccessLogTarget.System,
                                                () =>
            {
                IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject();

                var attribute = new SaveDataAttribute
                {
                    TitleId = applicationId,
                    Type = SaveDataType.Cache,
                    Index = index
                };

                var creationInfo = new SaveDataCreationInfo
                {
                    Size = size,
                    JournalSize = journalSize,
                    BlockSize = 0x4000,
                    OwnerId = ownerId,
                    Flags = flags,
                    SpaceId = spaceId
                };

                var metaInfo = new SaveMetaCreateInfo();

                return fsProxy.CreateSaveDataFileSystem(ref attribute, ref creationInfo, ref metaInfo);
            },
                                                () => $", applicationid: 0x{applicationId.Value:X}, savedataspaceid: {spaceId}, save_data_owner_id: 0x{ownerId.Value:X}, save_data_size: {size}, save_data_journal_size: {journalSize}, save_data_flags: 0x{(int)flags:X8}"));
        }
Esempio n. 6
0
        private Result GetSaveDataInfo(out SaveDataInfo info, SaveDataSpaceId spaceId, ref SaveDataAttribute attribute)
        {
            info = default;

            SaveDataIndexerReader reader = default;

            try
            {
                Result rc = FsServer.SaveDataIndexerManager.GetSaveDataIndexer(out reader, spaceId);
                if (rc.IsFailure())
                {
                    return(rc);
                }

                rc = reader.Indexer.Get(out SaveDataIndexerValue value, ref attribute);
                if (rc.IsFailure())
                {
                    return(rc);
                }

                SaveDataIndexer.GetSaveDataInfo(out info, ref attribute, ref value);
                return(Result.Success);
            }
            finally
            {
                reader.Dispose();
            }
        }
Esempio n. 7
0
        public static Result MountSystemSaveData(this FileSystemClient fs, U8Span mountName,
                                                 SaveDataSpaceId spaceId, ulong saveDataId, UserId userId)
        {
            Result      rc;
            Span <byte> logBuffer = stackalloc byte[0x90];

            if (fs.Impl.IsEnabledAccessLog(AccessLogTarget.System))
            {
                Tick start = fs.Hos.Os.GetSystemTick();
                rc = Mount(fs, mountName, spaceId, saveDataId, userId);
                Tick end = fs.Hos.Os.GetSystemTick();

                var idString = new IdString();
                var sb       = new U8StringBuilder(logBuffer, true);
                sb.Append(LogName).Append(mountName)
                .Append(LogSaveDataSpaceId).Append(idString.ToString(spaceId))
                .Append(LogSaveDataId).AppendFormat(saveDataId, 'X')
                .Append(LogUserId).AppendFormat(userId.Id.High, 'X', 16).AppendFormat(userId.Id.Low, 'X', 16);

                fs.Impl.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer));
            }
            else
            {
                rc = Mount(fs, mountName, spaceId, saveDataId, userId);
            }

            fs.Impl.AbortIfNeeded(rc);
            return(rc);
Esempio n. 8
0
        public Result GetSaveDataIndexer(out SaveDataIndexerReader reader, SaveDataSpaceId spaceId)
        {
            switch (spaceId)
            {
            case SaveDataSpaceId.System:
            case SaveDataSpaceId.User:
                Monitor.Enter(_bisIndexer.Locker);

                if (!_bisIndexer.IsInitialized)
                {
                    _bisIndexer.Indexer = new SaveDataIndexer(FsClient, "saveDataIxrDb", SaveDataSpaceId.System, SaveDataId);
                }

                reader = new SaveDataIndexerReader(_bisIndexer.Indexer, _bisIndexer.Locker);
                return(Result.Success);

            case SaveDataSpaceId.SdSystem:
            case SaveDataSpaceId.SdCache:
                Monitor.Enter(_sdCardIndexer.Locker);

                // Missing reinitialize if SD handle is old

                if (!_sdCardIndexer.IsInitialized)
                {
                    _sdCardIndexer.Indexer = new SaveDataIndexer(FsClient, "saveDataIxrDbSd", SaveDataSpaceId.SdSystem, SaveDataId);
                }

                reader = new SaveDataIndexerReader(_sdCardIndexer.Indexer, _sdCardIndexer.Locker);
                return(Result.Success);

            case SaveDataSpaceId.TemporaryStorage:
                throw new NotImplementedException();

            case SaveDataSpaceId.ProperSystem:
                Monitor.Enter(_safeIndexer.Locker);

                if (!_safeIndexer.IsInitialized)
                {
                    _safeIndexer.Indexer = new SaveDataIndexer(FsClient, "saveDataIxrDbPr", SaveDataSpaceId.ProperSystem, SaveDataId);
                }

                reader = new SaveDataIndexerReader(_safeIndexer.Indexer, _safeIndexer.Locker);
                return(Result.Success);

            case SaveDataSpaceId.Safe:
                Monitor.Enter(_properSystemIndexer.Locker);

                if (!_properSystemIndexer.IsInitialized)
                {
                    _properSystemIndexer.Indexer = new SaveDataIndexer(FsClient, "saveDataIxrDbSf", SaveDataSpaceId.Safe, SaveDataId);
                }

                reader = new SaveDataIndexerReader(_properSystemIndexer.Indexer, _properSystemIndexer.Locker);
                return(Result.Success);

            default:
                reader = default;
                return(ResultFs.InvalidArgument.Log());
            }
        }
 public SaveDataOpenTypeSetFileStorage(FileSystemServer fsServer, SaveDataSpaceId spaceId, ulong saveDataId)
 {
     _fsServer   = fsServer;
     _spaceId    = spaceId;
     _saveDataId = saveDataId;
     _mutex.Initialize();
 }
Esempio n. 10
0
 public Entry(ref ReferenceCountedDisposable <SaveDataOpenTypeSetFileStorage> storage,
              SaveDataSpaceId spaceId, ulong saveDataId)
 {
     _storage    = Shared.Move(ref storage);
     _spaceId    = spaceId;
     _saveDataId = saveDataId;
 }
Esempio n. 11
0
        public static Result CreateSystemSaveData(this FileSystemClient fs, SaveDataSpaceId spaceId,
                                                  ulong saveDataId, UserId userId, TitleId ownerId, long size, long journalSize, uint flags)
        {
            return(fs.RunOperationWithAccessLog(LocalAccessLogMode.System,
                                                () =>
            {
                IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject();

                var attribute = new SaveDataAttribute
                {
                    UserId = userId,
                    SaveDataId = saveDataId
                };

                var createInfo = new SaveDataCreateInfo
                {
                    Size = size,
                    JournalSize = journalSize,
                    BlockSize = 0x4000,
                    OwnerId = ownerId,
                    Flags = flags,
                    SpaceId = spaceId
                };

                return fsProxy.CreateSaveDataFileSystemBySystemSaveDataId(ref attribute, ref createInfo);
            },
                                                () => $", savedataspaceid: {spaceId}, savedataid: 0x{saveDataId:X}, userid: 0x{userId.Id.High:X16}{userId.Id.Low:X16}, save_data_owner_id: 0x{ownerId.Value:X}, save_data_size: {size}, save_data_journal_size: {journalSize}, save_data_flags: 0x{flags:X8}"));
        }
Esempio n. 12
0
        private Result DeleteSaveDataFileSystemBySaveDataSpaceIdImpl(SaveDataSpaceId spaceId, ulong saveDataId)
        {
            if (saveDataId != FileSystemServer.SaveIndexerId)
            {
                SaveDataIndexerReader reader = default;

                try
                {
                    Result rc = FsServer.SaveDataIndexerManager.GetSaveDataIndexer(out reader, spaceId);
                    if (rc.IsFailure())
                    {
                        return(rc);
                    }

                    rc = reader.Indexer.GetBySaveDataId(out SaveDataIndexerValue value, saveDataId);
                    if (rc.IsFailure())
                    {
                        return(rc);
                    }

                    if (value.SpaceId != GetSpaceIdForIndexer(spaceId))
                    {
                        return(ResultFs.TargetNotFound.Log());
                    }
                }
                finally
                {
                    reader.Dispose();
                }
            }

            return(DeleteSaveDataFileSystemImpl(spaceId, saveDataId));
        }
            public Cache(ReferenceCountedDisposable <ISaveDataExtraDataAccessor> accessor, SaveDataSpaceId spaceId,
                         ulong saveDataId)
            {
                _accessor = new ReferenceCountedDisposable <ISaveDataExtraDataAccessor> .WeakReference(accessor);

                _spaceId    = spaceId;
                _saveDataId = saveDataId;
            }
Esempio n. 14
0
 public SaveDataIndexer(FileSystemClient fsClient, string mountName, SaveDataSpaceId spaceId, ulong saveDataId)
 {
     FsClient   = fsClient;
     MountName  = mountName;
     SaveDataId = saveDataId;
     SpaceId    = spaceId;
     Version    = 1;
 }
Esempio n. 15
0
 public static bool UseDeviceUniqueSaveMac(SaveDataSpaceId spaceId)
 {
     return(spaceId == SaveDataSpaceId.System ||
            spaceId == SaveDataSpaceId.User ||
            spaceId == SaveDataSpaceId.Temporary ||
            spaceId == SaveDataSpaceId.ProperSystem ||
            spaceId == SaveDataSpaceId.SafeMode);
 }
Esempio n. 16
0
        public ResultCode DeleteSaveDataFileSystemBySaveDataAttribute(ServiceCtx context)
        {
            SaveDataSpaceId   spaceId   = (SaveDataSpaceId)context.RequestData.ReadInt64();
            SaveDataAttribute attribute = context.RequestData.ReadStruct <SaveDataAttribute>();

            Result result = _baseFileSystemProxy.DeleteSaveDataFileSystemBySaveDataAttribute(spaceId, ref attribute);

            return((ResultCode)result.Value);
        }
            // Note: Nintendo only supports caching SaveDataFileSystem. We support DirectorySaveDataFileSystem too,
            // so instead of calling methods on SaveDataFileSystem to get the save data info,
            // we pass them in as parameters.
            // Todo: Create a new interface for those methods?
            public void Register(ReferenceCountedDisposable <IFileSystem> fileSystem, SaveDataSpaceId spaceId,
                                 ulong saveDataId)
            {
                _spaceId    = spaceId;
                _saveDataId = saveDataId;

                _fileSystem?.Dispose();
                _fileSystem = fileSystem;
            }
Esempio n. 18
0
        public ResultCode DeleteSaveDataFileSystemBySaveDataSpaceId(ServiceCtx context)
        {
            SaveDataSpaceId spaceId    = (SaveDataSpaceId)context.RequestData.ReadInt64();
            ulong           saveDataId = context.RequestData.ReadUInt64();

            Result result = _baseFileSystemProxy.DeleteSaveDataFileSystemBySaveDataSpaceId(spaceId, saveDataId);

            return((ResultCode)result.Value);
        }
Esempio n. 19
0
        private static Result ExtendSaveDataIfNeeded(FileSystemClient fs, out long requiredSize,
                                                     SaveDataSpaceId spaceId, ulong saveDataId, long requiredDataSize, long requiredJournalSize)
        {
            // Checks the current save data size and extends it if needed.
            // If there is not enough space to do the extension, the amount of space
            // the extension requires will be written to requiredSize.

            requiredSize = 0;
            return(Result.Success);
        }
Esempio n. 20
0
 public static Result DeleteSaveData(this FileSystemClient fs, SaveDataSpaceId spaceId, ulong saveDataId)
 {
     return(fs.RunOperationWithAccessLog(LocalAccessLogMode.System,
                                         () =>
     {
         IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject();
         return fsProxy.DeleteSaveDataFileSystemBySaveDataSpaceId(spaceId, saveDataId);
     },
                                         () => $", savedataspaceid: {spaceId}, savedataid: 0x{saveDataId:X}"));
 }
        public Result Register(ReferenceCountedDisposable <ISaveDataExtraDataAccessor> accessor,
                               SaveDataSpaceId spaceId, ulong saveDataId)
        {
            var cache = new Cache(accessor, spaceId, saveDataId);

            using ScopedLock <SdkRecursiveMutexType> scopedLock = ScopedLock.Lock(ref _mutex);

            _accessorList.AddLast(cache);
            return(Result.Success);
        }
Esempio n. 22
0
        public static Result TryCreateCacheStorage(this FileSystemClient fs, out long requiredSize,
                                                   SaveDataSpaceId spaceId, Ncm.ApplicationId applicationId, ulong saveDataOwnerId, short index,
                                                   long dataSize, long journalSize, bool allowExisting)
        {
            requiredSize = default;
            long requiredSizeLocal = 0;

            var filter = new SaveDataFilter();

            filter.SetProgramId(applicationId);
            filter.SetIndex(index);
            filter.SetSaveDataType(SaveDataType.Cache);

            Result rc = fs.FindSaveDataWithFilter(out SaveDataInfo info, spaceId, ref filter);

            if (rc.IsFailure())
            {
                if (!ResultFs.TargetNotFound.Includes(rc))
                {
                    return(rc);
                }

                Result CreateCacheFunc() => fs.CreateCacheStorage(applicationId, spaceId, saveDataOwnerId, index,
                                                                  dataSize, journalSize, SaveDataFlags.None);

                rc = CreateSaveData(fs, CreateCacheFunc, ref requiredSizeLocal, 0x4000, dataSize, journalSize);
                if (rc.IsFailure())
                {
                    return(rc);
                }

                requiredSize = requiredSizeLocal;
                return(Result.Success);
            }

            if (!allowExisting)
            {
                return(ResultFs.SaveDataPathAlreadyExists.Log());
            }

            rc = ExtendSaveDataIfNeeded(fs, out requiredSizeLocal, spaceId, info.SaveDataId, dataSize, journalSize);

            if (rc.IsSuccess() || ResultFs.InsufficientFreeSpace.Includes(rc))
            {
                requiredSize = requiredSizeLocal;
                return(Result.Success);
            }

            if (ResultFs.SaveDataIsExtending.Includes(rc))
            {
                return(ResultFs.SaveDataCorrupted.LogConverted(rc));
            }

            return(rc);
        }
Esempio n. 23
0
        public Result DeleteSaveDataFileSystemBySaveDataAttribute(SaveDataSpaceId spaceId, ref SaveDataAttribute attribute)
        {
            Result rs = GetSaveDataInfo(out SaveDataInfo info, spaceId, ref attribute);

            if (rs.IsFailure())
            {
                return(rs);
            }

            return(DeleteSaveDataFileSystemBySaveDataSpaceIdImpl(spaceId, info.SaveDataId));
        }
Esempio n. 24
0
        private Result OpenSaveDataFileSystem3(out IFileSystem fileSystem, SaveDataSpaceId spaceId,
                                               ref SaveDataAttribute attribute, bool openReadOnly)
        {
            // Missing check if the open limit has been hit

            Result rc = OpenSaveDataFileSystemImpl(out fileSystem, out _, spaceId, ref attribute, openReadOnly, true);

            // Missing permission check based on the save's owner ID,
            // speed emulation storage type wrapper, and FileSystemInterfaceAdapter

            return(rc);
        }
Esempio n. 25
0
        public void ResetIndexer(SaveDataSpaceId spaceId)
        {
            if (spaceId != SaveDataSpaceId.Temporary)
            {
                Abort.UnexpectedDefault();
            }

            // ReSharper disable once RedundantAssignment
            Result rc = _tempIndexer.Indexer.Reset();

            Assert.SdkAssert(rc.IsSuccess());
        }
Esempio n. 26
0
        public Result SetSpaceId(ulong saveDataId, SaveDataSpaceId spaceId)
        {
            lock (Locker)
            {
                if (IsKeyValueSet && _value.SaveDataId == saveDataId)
                {
                    _value.SpaceId = spaceId;
                    return(Result.Success);
                }

                return(ResultFs.TargetNotFound.Log());
            }
        }
Esempio n. 27
0
        public ResultCode OpenSaveDataInfoReaderBySaveDataSpaceId(ServiceCtx context)
        {
            SaveDataSpaceId spaceId = (SaveDataSpaceId)context.RequestData.ReadByte();

            Result result = _baseFileSystemProxy.OpenSaveDataInfoReaderBySaveDataSpaceId(out ReferenceCountedDisposable <LibHac.FsSrv.ISaveDataInfoReader> infoReader, spaceId);

            if (result.IsSuccess())
            {
                MakeObject(context, new ISaveDataInfoReader(infoReader));
            }

            return((ResultCode)result.Value);
        }
Esempio n. 28
0
        public ResultCode OpenSaveDataInfoReaderWithFilter(ServiceCtx context)
        {
            SaveDataSpaceId spaceId = (SaveDataSpaceId)context.RequestData.ReadInt64();
            SaveDataFilter  filter  = context.RequestData.ReadStruct <SaveDataFilter>();

            Result result = _baseFileSystemProxy.OpenSaveDataInfoReaderWithFilter(out LibHac.FsService.ISaveDataInfoReader infoReader, spaceId, ref filter);

            if (result.IsSuccess())
            {
                MakeObject(context, new ISaveDataInfoReader(infoReader));
            }

            return((ResultCode)result.Value);
        }
Esempio n. 29
0
        // OpenSaveDataFileSystemBySystemSaveDataId(u8 save_data_space_id, nn::fssrv::sf::SaveStruct saveStruct) -> object<nn::fssrv::sf::IFileSystem> systemSaveDataFs
        public ResultCode OpenSaveDataFileSystemBySystemSaveDataId(ServiceCtx context)
        {
            SaveDataSpaceId   spaceId   = (SaveDataSpaceId)context.RequestData.ReadInt64();
            SaveDataAttribute attribute = context.RequestData.ReadStruct <SaveDataAttribute>();

            Result result = _baseFileSystemProxy.OpenSaveDataFileSystemBySystemSaveDataId(out LibHac.Fs.Fsa.IFileSystem fileSystem, spaceId, ref attribute);

            if (result.IsSuccess())
            {
                MakeObject(context, new FileSystemProxy.IFileSystem(fileSystem));
            }

            return((ResultCode)result.Value);
        }
        public void Unregister(SaveDataSpaceId spaceId, ulong saveDataId)
        {
            Assert.SdkRequiresGreaterEqual(_maxCachedFileSystemCount, 0);

            using ScopedLock <SdkRecursiveMutexType> scopedLock = ScopedLock.Lock(ref _mutex);

            for (int i = 0; i < _maxCachedFileSystemCount; i++)
            {
                if (_cachedFileSystems[i].IsCached(spaceId, saveDataId))
                {
                    _cachedFileSystems[i].Unregister();
                }
            }
        }