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
This commit is contained in:
Alex Barney 2018-07-11 20:03:09 -05:00
parent 14da035273
commit f1b660b95f
8 changed files with 166 additions and 26 deletions

View file

@ -15,7 +15,31 @@ namespace NandReader
Console.WriteLine("Usage: NandReader raw_nand_dump_file"); Console.WriteLine("Usage: NandReader raw_nand_dump_file");
return; 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) private static void DumpTickets(string nandFile)

View file

@ -123,7 +123,7 @@ namespace hactoolnet
private static void ProcessSwitchFs(Context ctx) 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) if (ctx.Options.ListTitles)
{ {

View file

@ -37,40 +37,40 @@ namespace libhac.Nand
return decStream; return decStream;
} }
public FatFileSystem OpenProdInfoF() public NandPartition OpenProdInfoF()
{ {
var encStream = ProdInfoF.Open(); var encStream = ProdInfoF.Open();
var xts = XtsAes128.Create(Keyset.bis_keys[0]); var xts = XtsAes128.Create(Keyset.bis_keys[0]);
var decStream = new RandomAccessSectorStream(new XtsSectorStream(encStream, xts, 0x4000, 0), true); var decStream = new RandomAccessSectorStream(new XtsSectorStream(encStream, xts, 0x4000, 0), true);
FatFileSystem fat = new FatFileSystem(decStream, Ownership.None); FatFileSystem fat = new FatFileSystem(decStream, Ownership.None);
return fat; return new NandPartition(fat);
} }
public FatFileSystem OpenSafePartition() public NandPartition OpenSafePartition()
{ {
var encStream = Safe.Open(); var encStream = Safe.Open();
var xts = XtsAes128.Create(Keyset.bis_keys[1]); var xts = XtsAes128.Create(Keyset.bis_keys[1]);
var decStream = new RandomAccessSectorStream(new XtsSectorStream(encStream, xts, 0x4000, 0), true); var decStream = new RandomAccessSectorStream(new XtsSectorStream(encStream, xts, 0x4000, 0), true);
FatFileSystem fat = new FatFileSystem(decStream, Ownership.None); FatFileSystem fat = new FatFileSystem(decStream, Ownership.None);
return fat; return new NandPartition(fat);
} }
public FatFileSystem OpenSystemPartition() public NandPartition OpenSystemPartition()
{ {
var encStream = System.Open(); var encStream = System.Open();
var xts = XtsAes128.Create(Keyset.bis_keys[2]); var xts = XtsAes128.Create(Keyset.bis_keys[2]);
var decStream = new RandomAccessSectorStream(new XtsSectorStream(encStream, xts, 0x4000, 0), true); var decStream = new RandomAccessSectorStream(new XtsSectorStream(encStream, xts, 0x4000, 0), true);
FatFileSystem fat = new FatFileSystem(decStream, Ownership.None); FatFileSystem fat = new FatFileSystem(decStream, Ownership.None);
return fat; return new NandPartition(fat);
} }
public FatFileSystem OpenUserPartition() public NandPartition OpenUserPartition()
{ {
var encStream = User.Open(); var encStream = User.Open();
var xts = XtsAes128.Create(Keyset.bis_keys[3]); var xts = XtsAes128.Create(Keyset.bis_keys[3]);
var decStream = new RandomAccessSectorStream(new XtsSectorStream(encStream, xts, 0x4000, 0), true); var decStream = new RandomAccessSectorStream(new XtsSectorStream(encStream, xts, 0x4000, 0), true);
FatFileSystem fat = new FatFileSystem(decStream, Ownership.None); FatFileSystem fat = new FatFileSystem(decStream, Ownership.None);
return fat; return new NandPartition(fat);
} }
} }
} }

View file

@ -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;
}
}
}

49
libhac/FileSystem.cs Normal file
View file

@ -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);
}
}
}

15
libhac/IFileSystem.cs Normal file
View file

@ -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);
}
}

View file

@ -1,7 +1,6 @@
using System; using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.Serialization.Json;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
using libhac.XTSSharp; using libhac.XTSSharp;

View file

@ -10,25 +10,25 @@ namespace libhac
public class SdFs : IDisposable public class SdFs : IDisposable
{ {
public Keyset Keyset { get; } public Keyset Keyset { get; }
public string RootDir { get; } public IFileSystem Fs { get; }
public string ContentsDir { get; } public string ContentsDir { get; }
public Dictionary<string, Nca> Ncas { get; } = new Dictionary<string, Nca>(StringComparer.OrdinalIgnoreCase); public Dictionary<string, Nca> Ncas { get; } = new Dictionary<string, Nca>(StringComparer.OrdinalIgnoreCase);
public Dictionary<ulong, Title> Titles { get; } = new Dictionary<ulong, Title>(); public Dictionary<ulong, Title> Titles { get; } = new Dictionary<ulong, Title>();
public Dictionary<ulong, Application> Applications { get; } = new Dictionary<ulong, Application>(); public Dictionary<ulong, Application> Applications { get; } = new Dictionary<ulong, Application>();
public SdFs(Keyset keyset, string rootDir) public SdFs(Keyset keyset, IFileSystem fs)
{ {
RootDir = rootDir; Fs = fs;
Keyset = keyset; 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) if (ContentsDir == null)
@ -44,7 +44,7 @@ namespace libhac
private void OpenAllNcas() 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) foreach (var file in files)
{ {
@ -52,7 +52,7 @@ namespace libhac
try try
{ {
bool isNax0; bool isNax0;
Stream stream = OpenSplitNcaStream(file); Stream stream = OpenSplitNcaStream(Fs, file);
if (stream == null) continue; if (stream == null) continue;
using (var reader = new BinaryReader(stream, Encoding.Default, true)) 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<string> files = new List<string>(); List<string> files = new List<string>();
List<Stream> streams = new List<Stream>(); List<Stream> streams = new List<Stream>();
if (Directory.Exists(path)) if (fs.DirectoryExists(path))
{ {
while (true) while (true)
{ {
var partName = Path.Combine(path, $"{files.Count:D2}"); var partName = Path.Combine(path, $"{files.Count:D2}");
if (!File.Exists(partName)) break; if (!fs.FileExists(partName)) break;
files.Add(partName); files.Add(partName);
} }
} }
else if (File.Exists(path)) else if (fs.FileExists(path))
{ {
if (Path.GetFileName(path) != "00") if (Path.GetFileName(path) != "00")
{ {
return new FileStream(path, FileMode.Open, FileAccess.Read); return fs.OpenFile(path, FileMode.Open, FileAccess.Read);
} }
files.Add(path); files.Add(path);
} }
@ -208,7 +208,7 @@ namespace libhac
foreach (var file in files) 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; if (streams.Count == 0) return null;