From f1b660b95f20e8596560ae14d820ae083714424d Mon Sep 17 00:00:00 2001 From: Alex Barney Date: Wed, 11 Jul 2018 20:03:09 -0500 Subject: [PATCH] Add IFileSystem interface I don't know about this. It seems really easy to screw something up. Allows using the same code for reading the raw nand and reading a normal file system --- NandReader/Program.cs | 26 +++++++++++++++++- hactoolnet/Program.cs | 2 +- libhac.Nand/Nand.cs | 16 +++++------ libhac.Nand/NandPartition.cs | 53 ++++++++++++++++++++++++++++++++++++ libhac/FileSystem.cs | 49 +++++++++++++++++++++++++++++++++ libhac/IFileSystem.cs | 15 ++++++++++ libhac/Nca.cs | 1 - libhac/SdFs.cs | 30 ++++++++++---------- 8 files changed, 166 insertions(+), 26 deletions(-) create mode 100644 libhac.Nand/NandPartition.cs create mode 100644 libhac/FileSystem.cs create mode 100644 libhac/IFileSystem.cs diff --git a/NandReader/Program.cs b/NandReader/Program.cs index 2187a18e..298c198e 100644 --- a/NandReader/Program.cs +++ b/NandReader/Program.cs @@ -15,7 +15,31 @@ namespace NandReader Console.WriteLine("Usage: NandReader raw_nand_dump_file"); return; } - DumpTickets(args[0]); + ReadSwitchFs(args[0]); + } + + private static void ReadSwitchFs(string nandFile) + { + using (var logger = new ProgressBar()) + using (var stream = new FileStream(nandFile, FileMode.Open, FileAccess.Read)) + { + var keyset = OpenKeyset(); + var nand = new Nand(stream, keyset); + var user = nand.OpenSystemPartition(); + var sdfs = new SdFs(keyset, user); + } + } + + private static void ReadCalibration(string nandFile) + { + using (var logger = new ProgressBar()) + using (var stream = new FileStream(nandFile, FileMode.Open, FileAccess.Read)) + { + var keyset = OpenKeyset(); + var nand = new Nand(stream, keyset); + var prodinfo = nand.OpenProdInfo(); + var calibration = new Calibration(prodinfo); + } } private static void DumpTickets(string nandFile) diff --git a/hactoolnet/Program.cs b/hactoolnet/Program.cs index 5fc4de3d..1383fe8f 100644 --- a/hactoolnet/Program.cs +++ b/hactoolnet/Program.cs @@ -123,7 +123,7 @@ namespace hactoolnet private static void ProcessSwitchFs(Context ctx) { - var switchFs = new SdFs(ctx.Keyset, ctx.Options.InFile); + var switchFs = new SdFs(ctx.Keyset, new FileSystem(ctx.Options.InFile)); if (ctx.Options.ListTitles) { diff --git a/libhac.Nand/Nand.cs b/libhac.Nand/Nand.cs index bcb8b8e0..d51341ce 100644 --- a/libhac.Nand/Nand.cs +++ b/libhac.Nand/Nand.cs @@ -37,40 +37,40 @@ namespace libhac.Nand return decStream; } - public FatFileSystem OpenProdInfoF() + public NandPartition OpenProdInfoF() { var encStream = ProdInfoF.Open(); var xts = XtsAes128.Create(Keyset.bis_keys[0]); var decStream = new RandomAccessSectorStream(new XtsSectorStream(encStream, xts, 0x4000, 0), true); FatFileSystem fat = new FatFileSystem(decStream, Ownership.None); - return fat; + return new NandPartition(fat); } - public FatFileSystem OpenSafePartition() + public NandPartition OpenSafePartition() { var encStream = Safe.Open(); var xts = XtsAes128.Create(Keyset.bis_keys[1]); var decStream = new RandomAccessSectorStream(new XtsSectorStream(encStream, xts, 0x4000, 0), true); FatFileSystem fat = new FatFileSystem(decStream, Ownership.None); - return fat; + return new NandPartition(fat); } - public FatFileSystem OpenSystemPartition() + public NandPartition OpenSystemPartition() { var encStream = System.Open(); var xts = XtsAes128.Create(Keyset.bis_keys[2]); var decStream = new RandomAccessSectorStream(new XtsSectorStream(encStream, xts, 0x4000, 0), true); FatFileSystem fat = new FatFileSystem(decStream, Ownership.None); - return fat; + return new NandPartition(fat); } - public FatFileSystem OpenUserPartition() + public NandPartition OpenUserPartition() { var encStream = User.Open(); var xts = XtsAes128.Create(Keyset.bis_keys[3]); var decStream = new RandomAccessSectorStream(new XtsSectorStream(encStream, xts, 0x4000, 0), true); FatFileSystem fat = new FatFileSystem(decStream, Ownership.None); - return fat; + return new NandPartition(fat); } } } diff --git a/libhac.Nand/NandPartition.cs b/libhac.Nand/NandPartition.cs new file mode 100644 index 00000000..f1551e06 --- /dev/null +++ b/libhac.Nand/NandPartition.cs @@ -0,0 +1,53 @@ +using System.IO; +using System.Linq; +using DiscUtils.Fat; + +namespace libhac.Nand +{ + public class NandPartition : IFileSystem + { + public FatFileSystem Fs { get; } + + public NandPartition(FatFileSystem fileSystem) + { + Fs = fileSystem; + } + + public bool FileExists(string path) + { + return Fs.FileExists(path); + } + + public bool DirectoryExists(string path) + { + return Fs.DirectoryExists(path); + } + + public Stream OpenFile(string path, FileMode mode) + { + return Fs.OpenFile(path, mode); + } + + public Stream OpenFile(string path, FileMode mode, FileAccess access) + { + return Fs.OpenFile(path, mode, access); + } + + public string[] GetFileSystemEntries(string path, string searchPattern) + { + return Fs.GetFileSystemEntries(path, searchPattern); + } + + public string[] GetFileSystemEntries(string path, string searchPattern, SearchOption searchOption) + { + var files = Fs.GetFiles(path, searchPattern, searchOption); + var dirs = Fs.GetDirectories(path, searchPattern, searchOption); + return files.Concat(dirs).ToArray(); + } + + public string GetFullPath(string path) + { + return path; + } + } +} diff --git a/libhac/FileSystem.cs b/libhac/FileSystem.cs new file mode 100644 index 00000000..211d7321 --- /dev/null +++ b/libhac/FileSystem.cs @@ -0,0 +1,49 @@ +using System.IO; + +namespace libhac +{ + public class FileSystem : IFileSystem + { + public string Root { get; } + + public FileSystem(string rootDir) + { + Root = Path.GetFullPath(rootDir); + } + + public bool FileExists(string path) + { + return File.Exists(Path.Combine(Root, path)); + } + + public bool DirectoryExists(string path) + { + return Directory.Exists(Path.Combine(Root, path)); + } + + public Stream OpenFile(string path, FileMode mode) + { + return new FileStream(path, mode); + } + + public Stream OpenFile(string path, FileMode mode, FileAccess access) + { + return new FileStream(path, mode, access); + } + + public string[] GetFileSystemEntries(string path, string searchPattern) + { + return Directory.GetFileSystemEntries(Path.Combine(Root, path), searchPattern); + } + + public string[] GetFileSystemEntries(string path, string searchPattern, SearchOption searchOption) + { + return Directory.GetFileSystemEntries(Path.Combine(Root, path), searchPattern, searchOption); + } + + public string GetFullPath(string path) + { + return Path.Combine(Root, path); + } + } +} diff --git a/libhac/IFileSystem.cs b/libhac/IFileSystem.cs new file mode 100644 index 00000000..33d9097b --- /dev/null +++ b/libhac/IFileSystem.cs @@ -0,0 +1,15 @@ +using System.IO; + +namespace libhac +{ + public interface IFileSystem + { + bool FileExists(string path); + bool DirectoryExists(string path); + Stream OpenFile(string path, FileMode mode); + Stream OpenFile(string path, FileMode mode, FileAccess access); + string[] GetFileSystemEntries(string path, string searchPattern); + string[] GetFileSystemEntries(string path, string searchPattern, SearchOption searchOption); + string GetFullPath(string path); + } +} diff --git a/libhac/Nca.cs b/libhac/Nca.cs index e70fb134..0e621446 100644 --- a/libhac/Nca.cs +++ b/libhac/Nca.cs @@ -1,7 +1,6 @@ using System; using System.IO; using System.Linq; -using System.Runtime.Serialization.Json; using System.Security.Cryptography; using System.Text; using libhac.XTSSharp; diff --git a/libhac/SdFs.cs b/libhac/SdFs.cs index 8dc43728..89bbf69c 100644 --- a/libhac/SdFs.cs +++ b/libhac/SdFs.cs @@ -10,25 +10,25 @@ namespace libhac public class SdFs : IDisposable { public Keyset Keyset { get; } - public string RootDir { get; } + public IFileSystem Fs { get; } public string ContentsDir { get; } public Dictionary Ncas { get; } = new Dictionary(StringComparer.OrdinalIgnoreCase); public Dictionary Titles { get; } = new Dictionary(); public Dictionary Applications { get; } = new Dictionary(); - public SdFs(Keyset keyset, string rootDir) + public SdFs(Keyset keyset, IFileSystem fs) { - RootDir = rootDir; + Fs = fs; Keyset = keyset; - if (Directory.Exists(Path.Combine(rootDir, "Nintendo"))) + if (fs.DirectoryExists("Nintendo")) { - ContentsDir = Path.Combine(rootDir, "Nintendo", "Contents"); + ContentsDir = fs.GetFullPath(Path.Combine("Nintendo", "Contents")); } - else if (Directory.Exists(Path.Combine(rootDir, "Contents"))) + else if (fs.DirectoryExists("Contents")) { - ContentsDir = Path.Combine(rootDir, "Contents"); + ContentsDir = fs.GetFullPath("Contents"); } if (ContentsDir == null) @@ -44,7 +44,7 @@ namespace libhac private void OpenAllNcas() { - string[] files = Directory.GetFileSystemEntries(ContentsDir, "*.nca", SearchOption.AllDirectories).ToArray(); + string[] files = Fs.GetFileSystemEntries(ContentsDir, "*.nca", SearchOption.AllDirectories); foreach (var file in files) { @@ -52,7 +52,7 @@ namespace libhac try { bool isNax0; - Stream stream = OpenSplitNcaStream(file); + Stream stream = OpenSplitNcaStream(Fs, file); if (stream == null) continue; using (var reader = new BinaryReader(stream, Encoding.Default, true)) @@ -178,26 +178,26 @@ namespace libhac } } - internal static Stream OpenSplitNcaStream(string path) + internal static Stream OpenSplitNcaStream(IFileSystem fs, string path) { List files = new List(); List streams = new List(); - if (Directory.Exists(path)) + if (fs.DirectoryExists(path)) { while (true) { var partName = Path.Combine(path, $"{files.Count:D2}"); - if (!File.Exists(partName)) break; + if (!fs.FileExists(partName)) break; files.Add(partName); } } - else if (File.Exists(path)) + else if (fs.FileExists(path)) { if (Path.GetFileName(path) != "00") { - return new FileStream(path, FileMode.Open, FileAccess.Read); + return fs.OpenFile(path, FileMode.Open, FileAccess.Read); } files.Add(path); } @@ -208,7 +208,7 @@ namespace libhac foreach (var file in files) { - streams.Add(new FileStream(file, FileMode.Open, FileAccess.Read)); + streams.Add(fs.OpenFile(file, FileMode.Open, FileAccess.Read)); } if (streams.Count == 0) return null;