예제 #1
0
파일: SaveData.cs 프로젝트: garoxas/LibHac
        public void MountCacheStorage_SdCardIsPreferredOverBis()
        {
            var applicationId   = new Ncm.ApplicationId(1);
            FileSystemClient fs = FileSystemServerFactory.CreateClient(true);

            fs.CreateCacheStorage(applicationId, SaveDataSpaceId.SdCache, applicationId.Value, 0, 0, SaveDataFlags.None);
            fs.MountCacheStorage("cache".ToU8Span(), applicationId);
            fs.CreateFile("cache:/sd".ToU8Span(), 0);
            fs.Commit("cache".ToU8Span());
            fs.Unmount("cache".ToU8Span());

            // Turn off the SD card so the User save is mounted
            fs.SetSdCardAccessibility(false);

            fs.CreateCacheStorage(applicationId, SaveDataSpaceId.User, applicationId.Value, 0, 0, SaveDataFlags.None);
            fs.MountCacheStorage("cache".ToU8Span(), applicationId);
            fs.CreateFile("cache:/bis".ToU8Span(), 0);
            fs.Commit("cache".ToU8Span());
            fs.Unmount("cache".ToU8Span());

            fs.SetSdCardAccessibility(true);

            Assert.Success(fs.MountCacheStorage("cache".ToU8String(), applicationId));
            Assert.Success(fs.GetEntryType(out _, "cache:/sd".ToU8Span()));
            Assert.Failure(fs.GetEntryType(out _, "cache:/bis".ToU8Span()));
        }
예제 #2
0
        public ResultCode DeleteFile()
        {
            ResultCode result = (ResultCode)_filesystemClient.DeleteFile(DatabasePath).Value;

            _filesystemClient.Commit(MountName);

            return(result);
        }
예제 #3
0
        private static Result ImportSave(FileSystemClient fs, SaveToImport save)
        {
            SaveDataAttribute key = save.Attribute;

            Result result = fs.CreateSaveData(key.TitleId, key.UserId, key.TitleId, 0, 0, 0);

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

            bool isOldMounted = false;
            bool isNewMounted = false;

            try
            {
                result = fs.Register("OldSave".ToU8Span(), new LocalFileSystem(save.Path));
                if (result.IsFailure())
                {
                    return(result);
                }

                isOldMounted = true;

                result = fs.MountSaveData("NewSave".ToU8Span(), key.TitleId, key.UserId);
                if (result.IsFailure())
                {
                    return(result);
                }

                isNewMounted = true;

                result = fs.CopyDirectory("OldSave:/", "NewSave:/");
                if (result.IsFailure())
                {
                    return(result);
                }

                result = fs.Commit("NewSave");
            }
            finally
            {
                if (isOldMounted)
                {
                    fs.Unmount("OldSave");
                }

                if (isNewMounted)
                {
                    fs.Unmount("NewSave");
                }
            }

            return(result);
        }
예제 #4
0
        public void Commit_MultipleFileSystems_AllFileSystemsAreCommitted()
        {
            FileSystemClient fs = FileSystemServerFactory.CreateClient(true);

            var saveInfo = new List <(int id, string name)>
            {
                (1, "Save1"),
                (3, "Save2"),
                (2, "Save3")
            };

            foreach ((int id, string name)info in saveInfo)
            {
                var applicationId = new Ncm.ApplicationId((uint)info.id);
                fs.CreateSaveData(applicationId, UserId.InvalidId, 0, 0x4000, 0x4000, SaveDataFlags.None);
                fs.MountSaveData(info.name.ToU8Span(), applicationId, UserId.InvalidId);
            }

            foreach ((int id, string name)info in saveInfo)
            {
                fs.CreateFile($"{info.name}:/file{info.id}".ToU8Span(), 0);
            }

            var names = new List <U8String>();

            foreach ((int id, string name)info in saveInfo)
            {
                names.Add(info.name.ToU8String());
            }

            Assert.Success(fs.Commit(names.ToArray()));

            foreach ((int id, string name)info in saveInfo)
            {
                fs.Unmount(info.name.ToU8Span());
            }

            foreach ((int id, string name)info in saveInfo)
            {
                var applicationId = new Ncm.ApplicationId((uint)info.id);
                fs.MountSaveData(info.name.ToU8Span(), applicationId, UserId.InvalidId);
            }

            foreach ((int id, string name)info in saveInfo)
            {
                Assert.Success(fs.GetEntryType(out _, $"{info.name}:/file{info.id}".ToU8Span()));
            }
        }
예제 #5
0
파일: SaveData.cs 프로젝트: garoxas/LibHac
        public void MountCacheStorage_WrittenDataPersists()
        {
            var applicationId   = new Ncm.ApplicationId(1);
            FileSystemClient fs = FileSystemServerFactory.CreateClient(true);

            fs.CreateCacheStorage(applicationId, SaveDataSpaceId.SdCache, applicationId.Value, 0, 0, SaveDataFlags.None);
            fs.MountCacheStorage("cache".ToU8Span(), applicationId);

            fs.CreateFile("cache:/file".ToU8Span(), 0);
            fs.Commit("cache".ToU8Span());
            fs.Unmount("cache".ToU8Span());

            Assert.Success(fs.MountCacheStorage("cache".ToU8Span(), applicationId));
            Assert.Success(fs.GetEntryType(out DirectoryEntryType type, "cache:/file".ToU8Span()));
            Assert.Equal(DirectoryEntryType.File, type);
        }
예제 #6
0
        public void MountBcatSaveData_WrittenDataPersists()
        {
            var applicationId   = new Ncm.ApplicationId(1);
            FileSystemClient fs = FileSystemServerFactory.CreateClient(true);

            Assert.Success(fs.CreateBcatSaveData(applicationId, 0x400000));
            Assert.Success(fs.MountBcatSaveData("bcat_test".ToU8Span(), applicationId));

            // Check that the path doesn't exist
            Assert.Result(ResultFs.PathNotFound, fs.GetEntryType(out _, "bcat_test:/file".ToU8Span()));

            fs.CreateFile("bcat_test:/file".ToU8Span(), 0);
            fs.Commit("bcat_test".ToU8Span());
            fs.Unmount("bcat_test".ToU8Span());

            Assert.Success(fs.MountBcatSaveData("bcat_test".ToU8Span(), applicationId));
            Assert.Success(fs.GetEntryType(out DirectoryEntryType type, "bcat_test:/file".ToU8Span()));
            Assert.Equal(DirectoryEntryType.File, type);
        }
예제 #7
0
        public static void Process(Context ctx)
        {
            var accessNeeded = FileAccess.Read;

            if (ctx.Options.SignSave || ctx.Options.ReplaceFileDest != null && ctx.Options.ReplaceFileSource != null ||
                ctx.Options.RepackSource != null || ctx.Options.TrimSave)
            {
                accessNeeded = FileAccess.ReadWrite;
            }

            using (var file = new LocalStorage(ctx.Options.InFile, accessNeeded))
            {
                bool signNeeded = ctx.Options.SignSave;

                var save            = new SaveDataFileSystem(ctx.KeySet, file, ctx.Options.IntegrityLevel, true);
                FileSystemClient fs = ctx.FsClient;

                fs.Register("save".ToU8Span(), save);

                if (ctx.Options.Validate)
                {
                    save.Verify(ctx.Logger);
                }

                if (ctx.Options.OutDir != null)
                {
                    fs.Register("output".ToU8Span(), new LocalFileSystem(ctx.Options.OutDir));

                    FsUtils.CopyDirectoryWithProgress(fs, "save:/".ToU8Span(), "output:/".ToU8Span(), logger: ctx.Logger).ThrowIfFailure();

                    fs.Unmount("output".ToU8Span());
                }

                if (ctx.Options.DebugOutDir != null)
                {
                    string dir = ctx.Options.DebugOutDir;

                    ExportSaveDebug(ctx, dir, save);
                }

                try
                {
                    if (ctx.Options.ReplaceFileDest != null && ctx.Options.ReplaceFileSource != null)
                    {
                        string destFilename = ctx.Options.ReplaceFileDest;
                        if (!destFilename.StartsWith("/"))
                        {
                            destFilename = '/' + destFilename;
                        }

                        using (IFile inFile = new LocalFile(ctx.Options.ReplaceFileSource, OpenMode.Read))
                        {
                            save.OpenFile(out IFile outFile, destFilename.ToU8String(), OpenMode.ReadWrite).ThrowIfFailure();

                            using (outFile)
                            {
                                inFile.GetSize(out long inFileSize).ThrowIfFailure();
                                outFile.GetSize(out long outFileSize).ThrowIfFailure();

                                if (inFileSize != outFileSize)
                                {
                                    outFile.SetSize(inFileSize).ThrowIfFailure();
                                }

                                inFile.CopyTo(outFile, ctx.Logger);

                                ctx.Logger.LogMessage($"Replaced file {destFilename}");
                            }
                        }

                        signNeeded = true;
                    }

                    if (ctx.Options.RepackSource != null)
                    {
                        fs.Register("input".ToU8Span(), new LocalFileSystem(ctx.Options.RepackSource));

                        fs.CleanDirectoryRecursively("save:/".ToU8Span());
                        fs.Commit("save".ToU8Span());

                        FsUtils.CopyDirectoryWithProgress(fs, "input:/".ToU8Span(), "save:/".ToU8Span(), logger: ctx.Logger).ThrowIfFailure();

                        fs.Commit("save".ToU8Span());
                        fs.Unmount("input".ToU8Span());

                        signNeeded = true;
                    }
                }
                finally
                {
                    if (signNeeded)
                    {
                        if (save.Commit(ctx.KeySet).IsSuccess())
                        {
                            ctx.Logger.LogMessage(
                                $"Successfully signed save file with key {ctx.KeySet.DeviceUniqueSaveMacKeys[0].ToString()}");
                        }
                        else
                        {
                            ctx.Logger.LogMessage("Unable to sign save file. Do you have all the required keys?");
                        }

                        signNeeded = false;
                    }
                }

                if (ctx.Options.TrimSave)
                {
                    save.FsTrim();
                    signNeeded = true;
                    ctx.Logger.LogMessage("Trimmed save file");
                }

                if (signNeeded)
                {
                    if (save.Commit(ctx.KeySet).IsSuccess())
                    {
                        ctx.Logger.LogMessage(
                            $"Successfully signed save file with key {ctx.KeySet.DeviceUniqueSaveMacKeys[0].ToString()}");
                    }
                    else
                    {
                        ctx.Logger.LogMessage("Unable to sign save file. Do you have all the required keys?");
                    }

                    fs.Unmount("save".ToU8Span());
                    return;
                }

                if (ctx.Options.ListFiles)
                {
                    foreach (DirectoryEntryEx entry in save.EnumerateEntries())
                    {
                        ctx.Logger.LogMessage(entry.FullPath);
                    }
                }

                ctx.Logger.LogMessage(save.Print(ctx.KeySet));
                //ctx.Logger.LogMessage(PrintFatLayout(save.SaveDataFileSystemCore));

                fs.Unmount("save".ToU8Span());
            }
        }