private static Result EnsureApplicationBcatDeliveryCacheStorageImpl(FileSystemClient fs, out long requiredSize, Ncm.ApplicationId applicationId, ref ApplicationControlProperty nacp) { const long bcatDeliveryCacheJournalSize = 0x200000; long bcatStorageSize = nacp.BcatDeliveryCacheStorageSize; if (bcatStorageSize <= 0) { requiredSize = 0; return(Result.Success); } requiredSize = default; long requiredSizeBcat = 0; var filter = new SaveDataFilter(); filter.SetProgramId(applicationId); filter.SetSaveDataType(SaveDataType.Bcat); Result CreateBcatStorageFunc() => fs.CreateBcatSaveData(applicationId, bcatStorageSize); Result rc = EnsureAndExtendSaveData(fs, CreateBcatStorageFunc, ref requiredSizeBcat, ref filter, 0x4000, bcatStorageSize, bcatDeliveryCacheJournalSize); if (rc.IsFailure()) { return(rc); } requiredSize = requiredSizeBcat; return(requiredSizeBcat > 0 ? ResultFs.InsufficientFreeSpace.Log() : Result.Success); }
public static Result CleanUpTemporaryStorage(FileSystemClient fs) { var filter = new SaveDataFilter(); filter.SetSaveDataType(SaveDataType.Temporary); Result rc; while (true) { rc = fs.FindSaveDataWithFilter(out SaveDataInfo saveInfo, SaveDataSpaceId.Temporary, ref filter); if (rc.IsFailure()) { break; } rc = fs.DeleteSaveData(SaveDataSpaceId.Temporary, saveInfo.SaveDataId); if (rc.IsFailure()) { return(rc); } } if (ResultFs.TargetNotFound.Includes(rc)) { return(Result.Success); } return(rc); }
private static Result EnsureAndExtendSaveData(FileSystemClient fs, Func <Result> createFunc, ref long requiredSize, ref SaveDataFilter filter, long baseSize, long dataSize, long journalSize) { Result rc = fs.FindSaveDataWithFilter(out SaveDataInfo info, SaveDataSpaceId.User, ref filter); if (rc.IsFailure()) { if (ResultFs.TargetNotFound.Includes(rc)) { rc = CreateSaveData(fs, createFunc, ref requiredSize, baseSize, dataSize, journalSize); } return(rc); } rc = ExtendSaveDataIfNeeded(fs, out long requiredSizeExtend, SaveDataSpaceId.User, info.SaveDataId, dataSize, journalSize); if (rc.IsFailure()) { if (!ResultFs.InsufficientFreeSpace.Includes(rc)) { return(rc); } requiredSize += requiredSizeExtend; } 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 static Result Make(out SaveDataFilter filter, Optional <ulong> programId, Optional <SaveDataType> saveType, Optional <UserId> userId, Optional <ulong> saveDataId, Optional <ushort> index, SaveDataRank rank) { UnsafeHelpers.SkipParamInit(out filter); SaveDataFilter tempFilter = Make(programId, saveType, userId, saveDataId, index, rank); if (!SaveDataTypesValidity.IsValid(in tempFilter)) { return(ResultFs.InvalidArgument.Log()); } filter = tempFilter; return(Result.Success); }
private static Result GetCacheStorageTargetMediaImpl(this FileSystemClient fs, out CacheStorageTargetMedia target, Ncm.ApplicationId applicationId) { target = CacheStorageTargetMedia.None; var filter = new SaveDataFilter(); filter.SetProgramId(applicationId); filter.SetSaveDataType(SaveDataType.Cache); if (fs.IsSdCardAccessible()) { Result rc = fs.FindSaveDataWithFilter(out _, SaveDataSpaceId.SdCache, ref filter); if (rc.IsFailure() && !ResultFs.TargetNotFound.Includes(rc)) { return(rc); } if (rc.IsSuccess()) { target = CacheStorageTargetMedia.SdCard; } } // Not on the SD card. Check it it's in NAND if (target == CacheStorageTargetMedia.None) { Result rc = fs.FindSaveDataWithFilter(out _, SaveDataSpaceId.User, ref filter); if (rc.IsFailure() && !ResultFs.TargetNotFound.Includes(rc)) { return(rc); } if (rc.IsSuccess()) { target = CacheStorageTargetMedia.Nand; } } return(Result.Success); }
public static SaveDataFilter Make(Optional <ulong> programId, Optional <SaveDataType> saveType, Optional <UserId> userId, Optional <ulong> saveDataId, Optional <ushort> index, SaveDataRank rank) { var filter = new SaveDataFilter(); if (programId.HasValue) { filter.FilterByProgramId = true; filter.Attribute.ProgramId = new ProgramId(programId.Value); } if (saveType.HasValue) { filter.FilterBySaveDataType = true; filter.Attribute.Type = saveType.Value; } if (userId.HasValue) { filter.FilterByUserId = true; filter.Attribute.UserId = userId.Value; } if (saveDataId.HasValue) { filter.FilterBySaveDataId = true; filter.Attribute.StaticSaveDataId = saveDataId.Value; } if (index.HasValue) { filter.FilterByIndex = true; filter.Attribute.Index = index.Value; } filter.Rank = rank; return(filter); }
public static Result EnsureApplicationSaveData(FileSystemClient fs, out long requiredSize, Ncm.ApplicationId applicationId, ref ApplicationControlProperty nacp, ref Uid uid) { requiredSize = default; long requiredSizeSum = 0; // Create local variable for use in closures ProgramId saveDataOwnerId = nacp.SaveDataOwnerId; // Ensure the user account save exists if (uid != Uid.Zero && nacp.UserAccountSaveDataSize > 0) { // More local variables for use in closures Uid uidLocal = uid; long accountSaveDataSize = nacp.UserAccountSaveDataSize; long accountSaveJournalSize = nacp.UserAccountSaveDataJournalSize; Result CreateAccountSaveFunc() { UserId userId = ConvertAccountUidToFsUserId(uidLocal); return(fs.CreateSaveData(applicationId, userId, saveDataOwnerId.Value, accountSaveDataSize, accountSaveJournalSize, SaveDataFlags.None)); } var filter = new SaveDataFilter(); filter.SetProgramId(applicationId); filter.SetSaveDataType(SaveDataType.Account); filter.SetUserId(new UserId(uid.Id.High, uid.Id.Low)); // The 0x4c000 includes the save meta and other stuff Result rc = EnsureAndExtendSaveData(fs, CreateAccountSaveFunc, ref requiredSizeSum, ref filter, 0x4c000, accountSaveDataSize, accountSaveJournalSize); if (rc.IsFailure()) { return(rc); } } // Ensure the device save exists if (nacp.DeviceSaveDataSize > 0) { long deviceSaveDataSize = nacp.DeviceSaveDataSize; long deviceSaveJournalSize = nacp.DeviceSaveDataJournalSize; Result CreateDeviceSaveFunc() => fs.CreateDeviceSaveData(applicationId, saveDataOwnerId.Value, deviceSaveDataSize, deviceSaveJournalSize, 0); var filter = new SaveDataFilter(); filter.SetProgramId(applicationId); filter.SetSaveDataType(SaveDataType.Device); Result rc = EnsureAndExtendSaveData(fs, CreateDeviceSaveFunc, ref requiredSizeSum, ref filter, 0x4000, deviceSaveDataSize, deviceSaveJournalSize); if (rc.IsFailure()) { return(rc); } } Result bcatRc = EnsureApplicationBcatDeliveryCacheStorageImpl(fs, out long requiredSizeBcat, applicationId, ref nacp); if (bcatRc.IsFailure()) { if (!ResultFs.InsufficientFreeSpace.Includes(bcatRc)) { return(bcatRc); } requiredSizeSum += requiredSizeBcat; } if (nacp.TemporaryStorageSize > 0) { if (requiredSizeSum > 0) { // If there was already insufficient space to create the previous saves, check if the temp // save already exists instead of trying to create a new one. var filter = new SaveDataFilter(); filter.SetProgramId(applicationId); filter.SetSaveDataType(SaveDataType.Temporary); Result rc = fs.FindSaveDataWithFilter(out _, SaveDataSpaceId.Temporary, ref filter); if (rc.IsFailure()) { if (!ResultFs.TargetNotFound.Includes(rc)) { return(rc); } Result queryRc = fs.QuerySaveDataTotalSize(out long tempSaveTotalSize, nacp.TemporaryStorageSize, 0); if (queryRc.IsFailure()) { return(queryRc); } requiredSizeSum += Utilities.AlignUp(tempSaveTotalSize, 0x4000) + 0x4000; } } else { Result createRc = fs.CreateTemporaryStorage(applicationId, nacp.SaveDataOwnerId.Value, nacp.TemporaryStorageSize, 0); if (createRc.IsFailure()) { if (ResultFs.InsufficientFreeSpace.Includes(createRc)) { Result queryRc = fs.QuerySaveDataTotalSize(out long tempSaveTotalSize, nacp.TemporaryStorageSize, 0); if (queryRc.IsFailure()) { return(queryRc); } requiredSizeSum += Utilities.AlignUp(tempSaveTotalSize, 0x4000) + 0x4000; } else if (ResultFs.PathAlreadyExists.Includes(createRc)) { requiredSizeSum += 0; } else { return(createRc); } } } } requiredSize = requiredSizeSum; return(requiredSize == 0 ? Result.Success : ResultFs.InsufficientFreeSpace.Log()); }
private static Result EnsureApplicationBcatDeliveryCacheStorageImpl(FileSystemClient fs, out long requiredSize, TitleId applicationId, ref ApplicationControlProperty nacp) { const long bcatDeliveryCacheJournalSize = 0x200000; requiredSize = default; if (nacp.BcatDeliveryCacheStorageSize <= 0) { requiredSize = 0; return(Result.Success); } var filter = new SaveDataFilter(); filter.SetTitleId(applicationId); filter.SetSaveDataType(SaveDataType.BcatDeliveryCacheStorage); Result rc = fs.FindSaveDataWithFilter(out SaveDataInfo saveDataInfo, SaveDataSpaceId.User, ref filter); if (rc.IsSuccess()) { rc = ExtendSaveDataIfNeeded(fs, out long requiredSizeBcat, SaveDataSpaceId.User, saveDataInfo.SaveDataId, nacp.DeviceSaveDataSize, bcatDeliveryCacheJournalSize); if (rc.IsFailure()) { if (!ResultRangeFs.InsufficientFreeSpace.Contains(rc)) { return(rc); } requiredSize = requiredSizeBcat; } } else if (rc != ResultFs.TargetNotFound) { return(rc); } else { Result createRc = fs.CreateBcatSaveData(applicationId, nacp.BcatDeliveryCacheStorageSize); if (createRc.IsFailure()) { if (ResultRangeFs.InsufficientFreeSpace.Contains(createRc)) { // todo: Call QuerySaveDataTotalSize and assign the value to requiredSize requiredSize = 0; } else if (createRc == ResultFs.PathAlreadyExists) { requiredSize = 0; } else { return(createRc); } } } return(requiredSize > 0 ? ResultFs.InsufficientFreeSpace.Log() : Result.Success); }
public static Result EnsureApplicationSaveData(FileSystemClient fs, out long requiredSize, TitleId applicationId, ref ApplicationControlProperty nacp, ref Uid uid) { requiredSize = default; long requiredSizeSum = 0; if (uid != Uid.Zero && nacp.UserAccountSaveDataSize > 0) { var filter = new SaveDataFilter(); filter.SetTitleId(applicationId); filter.SetSaveDataType(SaveDataType.SaveData); filter.SetUserId(new UserId(uid.Id.High, uid.Id.Low)); Result rc = fs.FindSaveDataWithFilter(out SaveDataInfo saveDataInfo, SaveDataSpaceId.User, ref filter); if (rc.IsSuccess()) { rc = ExtendSaveDataIfNeeded(fs, out long requiredSizeUser, SaveDataSpaceId.User, saveDataInfo.SaveDataId, nacp.UserAccountSaveDataSize, nacp.UserAccountSaveDataJournalSize); if (rc.IsFailure()) { if (!ResultRangeFs.InsufficientFreeSpace.Contains(rc)) { return(rc); } requiredSizeSum = requiredSizeUser; } } else if (rc != ResultFs.TargetNotFound) { return(rc); } else { UserId userId = ConvertAccountUidToFsUserId(uid); Result createRc = fs.CreateSaveData(applicationId, userId, nacp.SaveDataOwnerId, nacp.UserAccountSaveDataSize, nacp.UserAccountSaveDataJournalSize, 0); if (createRc.IsFailure()) { if (ResultRangeFs.InsufficientFreeSpace.Contains(createRc)) { // todo: Call QuerySaveDataTotalSize and assign the value to requiredSizeSum requiredSizeSum = 0; } else if (createRc == ResultFs.PathAlreadyExists) { requiredSizeSum = 0; } else { return(createRc); } } } } if (nacp.DeviceSaveDataSize > 0) { var filter = new SaveDataFilter(); filter.SetTitleId(applicationId); filter.SetSaveDataType(SaveDataType.DeviceSaveData); Result rc = fs.FindSaveDataWithFilter(out SaveDataInfo saveDataInfo, SaveDataSpaceId.User, ref filter); if (rc.IsSuccess()) { rc = ExtendSaveDataIfNeeded(fs, out long requiredSizeDevice, SaveDataSpaceId.User, saveDataInfo.SaveDataId, nacp.DeviceSaveDataSize, nacp.DeviceSaveDataJournalSize); if (rc.IsFailure()) { if (!ResultRangeFs.InsufficientFreeSpace.Contains(rc)) { return(rc); } requiredSizeSum += requiredSizeDevice; } } else if (rc != ResultFs.TargetNotFound) { return(rc); } else { Result createRc = fs.CreateDeviceSaveData(applicationId, nacp.SaveDataOwnerId, nacp.DeviceSaveDataSize, nacp.DeviceSaveDataJournalSize, 0); if (createRc.IsFailure()) { if (ResultRangeFs.InsufficientFreeSpace.Contains(createRc)) { // todo: Call QuerySaveDataTotalSize and add the value to requiredSizeSum requiredSizeSum += 0; } else if (createRc == ResultFs.PathAlreadyExists) { requiredSizeSum += 0; } else { return(createRc); } } } } Result bcatRc = EnsureApplicationBcatDeliveryCacheStorageImpl(fs, out long requiredSizeBcat, applicationId, ref nacp); if (bcatRc.IsFailure()) { if (!ResultRangeFs.InsufficientFreeSpace.Contains(bcatRc)) { return(bcatRc); } requiredSizeSum += requiredSizeBcat; } // Don't actually do this yet because the temp save indexer hasn't been implemented // todo: Flip the operator when it is if (nacp.TemporaryStorageSize < 0) { if (requiredSizeSum > 0) { var filter = new SaveDataFilter(); filter.SetTitleId(applicationId); filter.SetSaveDataType(SaveDataType.TemporaryStorage); Result rc = fs.FindSaveDataWithFilter(out _, SaveDataSpaceId.User, ref filter); if (rc.IsFailure()) { if (rc != ResultFs.TargetNotFound) { return(rc); } // todo: Call QuerySaveDataTotalSize and add the value to requiredSizeSum requiredSizeSum += 0; } } else { Result createRc = fs.CreateTemporaryStorage(applicationId, nacp.SaveDataOwnerId, nacp.TemporaryStorageSize, 0); if (createRc.IsFailure()) { if (ResultRangeFs.InsufficientFreeSpace.Contains(createRc)) { // todo: Call QuerySaveDataTotalSize and assign the value to requiredSizeSum requiredSizeSum += 0; } else if (createRc == ResultFs.PathAlreadyExists) { requiredSizeSum += 0; } else { return(createRc); } } } } requiredSize = requiredSizeSum; return(requiredSize == 0 ? Result.Success : ResultFs.InsufficientFreeSpace.Log()); }
public static Result Make(out SaveDataFilter filter, Optional <ulong> programId, Optional <SaveDataType> saveType, Optional <UserId> userId, Optional <ulong> saveDataId, Optional <ushort> index) { return(Make(out filter, programId, saveType, userId, saveDataId, index, SaveDataRank.Primary)); }