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");
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)

View file

@ -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)
{

View file

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

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.IO;
using System.Linq;
using System.Runtime.Serialization.Json;
using System.Security.Cryptography;
using System.Text;
using libhac.XTSSharp;

View file

@ -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<string, Nca> Ncas { get; } = new Dictionary<string, Nca>(StringComparer.OrdinalIgnoreCase);
public Dictionary<ulong, Title> Titles { get; } = new Dictionary<ulong, Title>();
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;
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<string> files = new List<string>();
List<Stream> streams = new List<Stream>();
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;