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();
}
public NandPartition OpenProdInfoF()
public FatFileSystemProvider OpenProdInfoF()
{
IStorage encStorage = ProdInfoF.Open().AsStorage();
var decStorage = new CachedStorage(new Aes128XtsStorage(encStorage, Keyset.BisKeys[0], 0x4000, true), 0x4000, 4, true);
decStorage.SetReadOnly();
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();
var decStorage = new CachedStorage(new Aes128XtsStorage(encStorage, Keyset.BisKeys[1], 0x4000, true), 0x4000, 4, true);
decStorage.SetReadOnly();
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();
var decStorage = new CachedStorage(new Aes128XtsStorage(encStorage, Keyset.BisKeys[2], 0x4000, true), 0x4000, 4, true);
decStorage.SetReadOnly();
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();
var decStorage = new CachedStorage(new Aes128XtsStorage(encStorage, Keyset.BisKeys[3], 0x4000, true), 0x4000, 4, true);
decStorage.SetReadOnly();
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)
{
return fileSystem.OpenDirectory("/", OpenDirectoryMode.All).EnumerateEntries();
return fileSystem.OpenDirectory("/", OpenDirectoryMode.All).EnumerateEntries("*", SearchOptions.RecurseSubdirectories);
}
public static IEnumerable<DirectoryEntry> EnumerateEntries(this IDirectory directory)

View file

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

View file

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