Add an IFileSystem provider for DiscUtils

This commit is contained in:
Alex Barney 2019-01-11 15:26:27 -06:00
parent 828c1f5b54
commit 3e4dcd9466
7 changed files with 179 additions and 23 deletions

View file

@ -0,0 +1,63 @@
using System.Collections.Generic;
using DiscUtils;
using LibHac.IO;
using DirectoryEntry = LibHac.IO.DirectoryEntry;
using IFileSystem = LibHac.IO.IFileSystem;
namespace LibHac.Nand
{
public class FatFileSystemDirectory : IDirectory
{
public IFileSystem ParentFileSystem { get; }
public string FullPath { get; }
public OpenDirectoryMode Mode { get; }
private DiscDirectoryInfo DirInfo { get; }
public FatFileSystemDirectory(FatFileSystemProvider fs, string path, OpenDirectoryMode mode)
{
ParentFileSystem = fs;
FullPath = path;
Mode = mode;
path = FatFileSystemProvider.ToDiscUtilsPath(PathTools.Normalize(path));
DirInfo = fs.Fs.GetDirectoryInfo(path);
}
public IEnumerable<DirectoryEntry> Read()
{
if (Mode.HasFlag(OpenDirectoryMode.Directories))
{
foreach (DiscDirectoryInfo dir in DirInfo.GetDirectories())
{
yield return new DirectoryEntry(dir.Name, FullPath + '/' + dir.Name, DirectoryEntryType.Directory, 0);
}
}
if (Mode.HasFlag(OpenDirectoryMode.Files))
{
foreach (DiscFileInfo file in DirInfo.GetFiles())
{
yield return new DirectoryEntry(file.Name, FullPath + '/' + file.Name, DirectoryEntryType.File, file.Length);
}
}
}
public int GetEntryCount()
{
int count = 0;
if (Mode.HasFlag(OpenDirectoryMode.Directories))
{
count += DirInfo.GetDirectories().Length;
}
if (Mode.HasFlag(OpenDirectoryMode.Files))
{
count += DirInfo.GetFiles().Length;
}
return count;
}
}
}

View file

@ -0,0 +1,92 @@
using System;
using System.IO;
using DiscUtils.Fat;
using LibHac.IO;
namespace LibHac.Nand
{
public class FatFileSystemProvider : IAttributeFileSystem
{
public FatFileSystem Fs { get; }
public FatFileSystemProvider(FatFileSystem fileSystem)
{
Fs = fileSystem;
}
public void DeleteDirectory(string path)
{
path = ToDiscUtilsPath(PathTools.Normalize(path));
Fs.DeleteDirectory(path);
}
public void DeleteFile(string path)
{
path = ToDiscUtilsPath(PathTools.Normalize(path));
Fs.DeleteFile(path);
}
public IDirectory OpenDirectory(string path, OpenDirectoryMode mode)
{
path = PathTools.Normalize(path);
return new FatFileSystemDirectory(this, path, mode);
}
public IFile OpenFile(string path, OpenMode mode)
{
path = ToDiscUtilsPath(PathTools.Normalize(path));
Stream stream = Fs.OpenFile(path, FileMode.Open, GetFileAccess(mode));
return stream.AsIFile(mode);
}
public bool DirectoryExists(string path)
{
path = ToDiscUtilsPath(PathTools.Normalize(path));
if (path == @"\\") return true;
return Fs.DirectoryExists(path);
}
public bool FileExists(string path)
{
path = ToDiscUtilsPath(PathTools.Normalize(path));
return Fs.FileExists(path);
}
public FileAttributes GetFileAttributes(string path)
{
path = ToDiscUtilsPath(PathTools.Normalize(path));
return Fs.GetAttributes(path);
}
public long GetFileSize(string path)
{
path = ToDiscUtilsPath(PathTools.Normalize(path));
return Fs.GetFileInfo(path).Length;
}
public void Commit() { }
public void CreateDirectory(string path) => throw new NotSupportedException();
public void CreateFile(string path, long size) => throw new NotSupportedException();
public void RenameDirectory(string srcPath, string dstPath) => throw new NotSupportedException();
public void RenameFile(string srcPath, string dstPath) => throw new NotSupportedException();
private static FileAccess GetFileAccess(OpenMode mode)
{
// FileAccess and OpenMode have the same flags
return (FileAccess)(mode & OpenMode.ReadWrite);
}
internal static string ToDiscUtilsPath(string path)
{
return path.Replace("/", @"\\");
}
}
}

View file

@ -37,40 +37,40 @@ namespace LibHac.Nand
return decStorage.AsStream(); return decStorage.AsStream();
} }
public NandPartition OpenProdInfoF() public FatFileSystemProvider OpenProdInfoF()
{ {
IStorage encStorage = ProdInfoF.Open().AsStorage(); IStorage encStorage = ProdInfoF.Open().AsStorage();
var decStorage = new CachedStorage(new Aes128XtsStorage(encStorage, Keyset.BisKeys[0], 0x4000, true), 0x4000, 4, true); var decStorage = new CachedStorage(new Aes128XtsStorage(encStorage, Keyset.BisKeys[0], 0x4000, true), 0x4000, 4, true);
decStorage.SetReadOnly(); decStorage.SetReadOnly();
var fat = new FatFileSystem(decStorage.AsStream(), Ownership.None); var fat = new FatFileSystem(decStorage.AsStream(), Ownership.None);
return new NandPartition(fat); return new FatFileSystemProvider(fat);
} }
public NandPartition OpenSafePartition() public FatFileSystemProvider OpenSafePartition()
{ {
IStorage encStorage = Safe.Open().AsStorage(); IStorage encStorage = Safe.Open().AsStorage();
var decStorage = new CachedStorage(new Aes128XtsStorage(encStorage, Keyset.BisKeys[1], 0x4000, true), 0x4000, 4, true); var decStorage = new CachedStorage(new Aes128XtsStorage(encStorage, Keyset.BisKeys[1], 0x4000, true), 0x4000, 4, true);
decStorage.SetReadOnly(); decStorage.SetReadOnly();
var fat = new FatFileSystem(decStorage.AsStream(), Ownership.None); var fat = new FatFileSystem(decStorage.AsStream(), Ownership.None);
return new NandPartition(fat); return new FatFileSystemProvider(fat);
} }
public NandPartition OpenSystemPartition() public FatFileSystemProvider OpenSystemPartition()
{ {
IStorage encStorage = System.Open().AsStorage(); IStorage encStorage = System.Open().AsStorage();
var decStorage = new CachedStorage(new Aes128XtsStorage(encStorage, Keyset.BisKeys[2], 0x4000, true), 0x4000, 4, true); var decStorage = new CachedStorage(new Aes128XtsStorage(encStorage, Keyset.BisKeys[2], 0x4000, true), 0x4000, 4, true);
decStorage.SetReadOnly(); decStorage.SetReadOnly();
var fat = new FatFileSystem(decStorage.AsStream(), Ownership.None); var fat = new FatFileSystem(decStorage.AsStream(), Ownership.None);
return new NandPartition(fat); return new FatFileSystemProvider(fat);
} }
public NandPartition OpenUserPartition() public FatFileSystemProvider OpenUserPartition()
{ {
IStorage encStorage = User.Open().AsStorage(); IStorage encStorage = User.Open().AsStorage();
var decStorage = new CachedStorage(new Aes128XtsStorage(encStorage, Keyset.BisKeys[3], 0x4000, true), 0x4000, 4, true); var decStorage = new CachedStorage(new Aes128XtsStorage(encStorage, Keyset.BisKeys[3], 0x4000, true), 0x4000, 4, true);
decStorage.SetReadOnly(); decStorage.SetReadOnly();
var fat = new FatFileSystem(decStorage.AsStream(), Ownership.None); var fat = new FatFileSystem(decStorage.AsStream(), Ownership.None);
return new NandPartition(fat); return new FatFileSystemProvider(fat);
} }
} }
} }

View file

@ -61,7 +61,7 @@ namespace LibHac.IO
public static IEnumerable<DirectoryEntry> EnumerateEntries(this IFileSystem fileSystem) public static IEnumerable<DirectoryEntry> EnumerateEntries(this IFileSystem fileSystem)
{ {
return fileSystem.OpenDirectory("/", OpenDirectoryMode.All).EnumerateEntries(); return fileSystem.OpenDirectory("/", OpenDirectoryMode.All).EnumerateEntries("*", SearchOptions.RecurseSubdirectories);
} }
public static IEnumerable<DirectoryEntry> EnumerateEntries(this IDirectory directory) public static IEnumerable<DirectoryEntry> EnumerateEntries(this IDirectory directory)

View file

@ -48,12 +48,12 @@ namespace LibHac.IO
if (Mode.HasFlag(OpenDirectoryMode.Directories)) if (Mode.HasFlag(OpenDirectoryMode.Directories))
{ {
count += Directory.EnumerateDirectories(LocalPath).Count(); count += DirInfo.EnumerateDirectories().Count();
} }
if (Mode.HasFlag(OpenDirectoryMode.Files)) if (Mode.HasFlag(OpenDirectoryMode.Files))
{ {
count += Directory.EnumerateFiles(LocalPath).Count(); count += DirInfo.EnumerateFiles().Count();
} }
return count; return count;

View file

@ -49,8 +49,9 @@ namespace NandReader
{ {
Keyset keyset = OpenKeyset(); Keyset keyset = OpenKeyset();
var nand = new Nand(stream, keyset); var nand = new Nand(stream, keyset);
NandPartition user = nand.OpenSystemPartition(); FatFileSystemProvider user = nand.OpenSystemPartition();
var sdfs = new SwitchFs(keyset, user); // todo
//var sdfs = new SwitchFs(keyset, user);
} }
} }
@ -87,13 +88,13 @@ namespace NandReader
private static Ticket[] GetTickets(Keyset keyset, Nand nand, IProgressReport logger = null) private static Ticket[] GetTickets(Keyset keyset, Nand nand, IProgressReport logger = null)
{ {
var tickets = new List<Ticket>(); var tickets = new List<Ticket>();
NandPartition system = nand.OpenSystemPartition(); FatFileSystemProvider system = nand.OpenSystemPartition();
Stream saveE1File = system.OpenFile("save\\80000000000000E1", FileMode.Open, FileAccess.Read); IFile saveE1File = system.OpenFile("/save/80000000000000E1", OpenMode.Read);
tickets.AddRange(ReadTickets(keyset, saveE1File)); tickets.AddRange(ReadTickets(keyset, saveE1File.AsStream()));
Stream saveE2 = system.OpenFile("save\\80000000000000E2", FileMode.Open, FileAccess.Read); IFile saveE2 = system.OpenFile("/save/80000000000000E2", OpenMode.Read);
tickets.AddRange(ReadTickets(keyset, saveE2)); tickets.AddRange(ReadTickets(keyset, saveE2.AsStream()));
logger?.LogMessage($"Found {tickets.Count} tickets"); logger?.LogMessage($"Found {tickets.Count} tickets");

View file

@ -71,13 +71,13 @@ namespace NandReaderGui.ViewModel
private static Ticket[] GetTickets(Keyset keyset, Nand nand, IProgressReport logger = null) private static Ticket[] GetTickets(Keyset keyset, Nand nand, IProgressReport logger = null)
{ {
var tickets = new List<Ticket>(); var tickets = new List<Ticket>();
NandPartition system = nand.OpenSystemPartition(); FatFileSystemProvider system = nand.OpenSystemPartition();
Stream saveE1File = system.OpenFile("save\\80000000000000E1", FileMode.Open, FileAccess.Read); IFile saveE1File = system.OpenFile("/save/80000000000000E1", OpenMode.Read);
tickets.AddRange(ReadTickets(keyset, saveE1File)); tickets.AddRange(ReadTickets(keyset, saveE1File.AsStream()));
Stream saveE2 = system.OpenFile("save\\80000000000000E2", FileMode.Open, FileAccess.Read); IFile saveE2 = system.OpenFile("/save/80000000000000E2", OpenMode.Read);
tickets.AddRange(ReadTickets(keyset, saveE2)); tickets.AddRange(ReadTickets(keyset, saveE2.AsStream()));
logger?.LogMessage($"Found {tickets.Count} tickets"); logger?.LogMessage($"Found {tickets.Count} tickets");