SD card content listing example

This commit is contained in:
Alex Barney 2018-06-21 11:16:51 -05:00
parent a6e72b0ee7
commit 8054d38f5a
5 changed files with 81 additions and 2 deletions

View file

@ -1,4 +1,5 @@
using System.IO;
using System;
using System.IO;
using libhac;
namespace hactoolnet
@ -6,6 +7,11 @@ namespace hactoolnet
public static class Program
{
static void Main(string[] args)
{
ListSdContents(args);
}
static void DecryptNax0(string[] args)
{
var keyset = ExternalKeys.ReadKeyFile(args[0]);
keyset.SetSdSeed(args[1].ToBytes());
@ -21,5 +27,18 @@ namespace hactoolnet
nax0.Stream.CopyStream(output, nax0.Stream.Length, progress);
}
}
static void ListSdContents(string[] args)
{
var keyset = ExternalKeys.ReadKeyFile(args[0]);
keyset.SetSdSeed(args[1].ToBytes());
var sdfs = new SdFs(keyset, args[2]);
var ncas = sdfs.ReadAllNca();
foreach (var nca in ncas)
{
Console.WriteLine($"{nca.TitleId:X8} {nca.ContentType} {nca.Name}");
}
}
}
}

View file

@ -17,6 +17,7 @@ namespace libhac
public uint SdkVersion { get; set; } // What SDK was this built with?
public byte CryptoType2 { get; set; } // Which keyblob (field 2)
public byte[] RightsId { get; set; }
public string Name { get; set; }
public Nca(Keyset keyset, Stream stream)
{

41
libhac/SdFs.cs Normal file
View file

@ -0,0 +1,41 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace libhac
{
public class SdFs
{
public Keyset Keyset { get; }
public string RootDir { get; }
public string ContentsDir { get; }
public string[] Files { get; }
public SdFs(Keyset keyset, string sdPath)
{
if (Directory.Exists(Path.Combine(sdPath, "Nintendo")))
{
RootDir = sdPath;
Keyset = keyset;
ContentsDir = Path.Combine(sdPath, "Nintendo", "Contents");
}
Files = Directory.GetFiles(ContentsDir, "00", SearchOption.AllDirectories).Select(Path.GetDirectoryName).ToArray();
}
public List<Nca> ReadAllNca()
{
List<Nca> ncas = new List<Nca>();
foreach (var file in Files)
{
var sdPath = "/" + Util.GetRelativePath(file, ContentsDir).Replace('\\', '/');
var nax0 = new Nax0(Keyset, file, sdPath);
var nca = new Nca(Keyset, nax0.Stream);
ncas.Add(nca);
nca.Name = Path.GetFileName(file);
}
return ncas;
}
}
}

View file

@ -79,6 +79,22 @@ namespace libhac
return Encoding.ASCII.GetString(reader.ReadBytes(size), 0, size);
}
// todo Maybe make less naive
public static string GetRelativePath(string path, string basePath)
{
var directory = new DirectoryInfo(basePath);
var file = new FileInfo(path);
string fullDirectory = directory.FullName;
string fullFile = file.FullName;
if (!fullFile.StartsWith(fullDirectory))
{
throw new ArgumentException($"{nameof(path)} is not a subpath of {nameof(basePath)}");
}
return fullFile.Substring(fullDirectory.Length + 1);
}
private static int HexToInt(char c)
{

View file

@ -41,6 +41,7 @@ namespace libhac.XTSSharp
private bool _bufferDirty;
private bool _bufferLoaded;
private int _bufferPos;
private int _currentBufferSize;
/// <summary>
/// Creates a new stream
@ -106,7 +107,7 @@ namespace libhac.XTSSharp
/// <returns>The current position within the stream.</returns>
public override long Position
{
get { return _bufferLoaded ? (_s.Position - _bufferSize + _bufferPos) : _s.Position + _bufferPos; }
get { return _bufferLoaded ? (_s.Position - _currentBufferSize + _bufferPos) : _s.Position + _bufferPos; }
set
{
if (value < 0L)
@ -299,6 +300,7 @@ namespace libhac.XTSSharp
_bufferLoaded = true;
_bufferPos = 0;
_bufferDirty = false;
_currentBufferSize = bytesRead;
}
/// <summary>