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)); }
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]);
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); }
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}")); }
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(); } }
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);
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(); }
public Entry(ref ReferenceCountedDisposable <SaveDataOpenTypeSetFileStorage> storage, SaveDataSpaceId spaceId, ulong saveDataId) { _storage = Shared.Move(ref storage); _spaceId = spaceId; _saveDataId = saveDataId; }
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}")); }
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; }
public SaveDataIndexer(FileSystemClient fsClient, string mountName, SaveDataSpaceId spaceId, ulong saveDataId) { FsClient = fsClient; MountName = mountName; SaveDataId = saveDataId; SpaceId = spaceId; Version = 1; }
public static bool UseDeviceUniqueSaveMac(SaveDataSpaceId spaceId) { return(spaceId == SaveDataSpaceId.System || spaceId == SaveDataSpaceId.User || spaceId == SaveDataSpaceId.Temporary || spaceId == SaveDataSpaceId.ProperSystem || spaceId == SaveDataSpaceId.SafeMode); }
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; }
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); }
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); }
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); }
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); }
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)); }
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); }
public void ResetIndexer(SaveDataSpaceId spaceId) { if (spaceId != SaveDataSpaceId.Temporary) { Abort.UnexpectedDefault(); } // ReSharper disable once RedundantAssignment Result rc = _tempIndexer.Indexer.Reset(); Assert.SdkAssert(rc.IsSuccess()); }
public Result SetSpaceId(ulong saveDataId, SaveDataSpaceId spaceId) { lock (Locker) { if (IsKeyValueSet && _value.SaveDataId == saveDataId) { _value.SpaceId = spaceId; return(Result.Success); } return(ResultFs.TargetNotFound.Log()); } }
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); }
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); }
// 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(); } } }