mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2025-02-09 13:14:46 +01:00
Remove old Pfs and Romfs classes
This commit is contained in:
parent
9a234575ac
commit
585c351917
31
src/LibHac/IO/FileStorage.cs
Normal file
31
src/LibHac/IO/FileStorage.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using System;
|
||||
|
||||
namespace LibHac.IO
|
||||
{
|
||||
public class FileStorage : Storage
|
||||
{
|
||||
private IFile BaseFile { get; }
|
||||
|
||||
public FileStorage(IFile baseFile)
|
||||
{
|
||||
BaseFile = baseFile;
|
||||
}
|
||||
|
||||
protected override void ReadImpl(Span<byte> destination, long offset)
|
||||
{
|
||||
BaseFile.Read(destination, offset);
|
||||
}
|
||||
|
||||
protected override void WriteImpl(ReadOnlySpan<byte> source, long offset)
|
||||
{
|
||||
BaseFile.Write(source, offset);
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
BaseFile.Flush();
|
||||
}
|
||||
|
||||
public override long Length => BaseFile.GetSize();
|
||||
}
|
||||
}
|
@ -101,8 +101,8 @@ namespace LibHac.IO
|
||||
|
||||
public enum PartitionFileSystemType
|
||||
{
|
||||
Pfs0,
|
||||
Hfs0
|
||||
Standard,
|
||||
Hashed
|
||||
}
|
||||
|
||||
public class PartitionFileSystemHeader
|
||||
@ -125,10 +125,10 @@ namespace LibHac.IO
|
||||
switch (Magic)
|
||||
{
|
||||
case "PFS0":
|
||||
Type = PartitionFileSystemType.Pfs0;
|
||||
Type = PartitionFileSystemType.Standard;
|
||||
break;
|
||||
case "HFS0":
|
||||
Type = PartitionFileSystemType.Hfs0;
|
||||
Type = PartitionFileSystemType.Hashed;
|
||||
break;
|
||||
default:
|
||||
throw new InvalidDataException($"Invalid Partition FS type \"{Magic}\"");
|
||||
@ -151,7 +151,7 @@ namespace LibHac.IO
|
||||
}
|
||||
|
||||
|
||||
if (Type == PartitionFileSystemType.Hfs0)
|
||||
if (Type == PartitionFileSystemType.Hashed)
|
||||
{
|
||||
for (int i = 0; i < NumFiles; i++)
|
||||
{
|
||||
@ -166,9 +166,9 @@ namespace LibHac.IO
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case PartitionFileSystemType.Pfs0:
|
||||
case PartitionFileSystemType.Standard:
|
||||
return 24;
|
||||
case PartitionFileSystemType.Hfs0:
|
||||
case PartitionFileSystemType.Hashed:
|
||||
return 0x40;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(type), type, null);
|
||||
@ -193,7 +193,7 @@ namespace LibHac.IO
|
||||
Offset = reader.ReadInt64();
|
||||
Size = reader.ReadInt64();
|
||||
StringTableOffset = reader.ReadUInt32();
|
||||
if (type == PartitionFileSystemType.Hfs0)
|
||||
if (type == PartitionFileSystemType.Hashed)
|
||||
{
|
||||
HashedRegionSize = reader.ReadInt32();
|
||||
Reserved = reader.ReadInt64();
|
||||
|
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace LibHac.IO
|
||||
@ -13,15 +12,14 @@ namespace LibHac.IO
|
||||
// See the LICENSE file in the project root for more information.
|
||||
public static string Normalize(string inPath)
|
||||
{
|
||||
// Relative paths aren't a thing for IFileSystem, so assume all paths are absolute
|
||||
// and add a '/' to the beginning of the path if it doesn't already begin with one
|
||||
if (inPath.Length == 0 || !IsDirectorySeparator(inPath[0])) inPath = DirectorySeparator + inPath;
|
||||
|
||||
ReadOnlySpan<char> path = inPath.AsSpan();
|
||||
|
||||
if (path.Length == 0) return DirectorySeparator.ToString();
|
||||
|
||||
if (path[0] != DirectorySeparator)
|
||||
{
|
||||
throw new InvalidDataException($"{nameof(path)} must begin with '{DirectorySeparator}'");
|
||||
}
|
||||
|
||||
Span<char> initialBuffer = stackalloc char[0x200];
|
||||
var sb = new ValueStringBuilder(initialBuffer);
|
||||
|
||||
|
@ -161,5 +161,38 @@ namespace LibHac.IO
|
||||
|
||||
return FileDict.ContainsKey(path);
|
||||
}
|
||||
|
||||
public IStorage GetBaseStorage()
|
||||
{
|
||||
return BaseStorage;
|
||||
}
|
||||
}
|
||||
|
||||
public class RomfsHeader
|
||||
{
|
||||
public long HeaderSize { get; }
|
||||
public long DirHashTableOffset { get; }
|
||||
public long DirHashTableSize { get; }
|
||||
public long DirMetaTableOffset { get; }
|
||||
public long DirMetaTableSize { get; }
|
||||
public long FileHashTableOffset { get; }
|
||||
public long FileHashTableSize { get; }
|
||||
public long FileMetaTableOffset { get; }
|
||||
public long FileMetaTableSize { get; }
|
||||
public long DataOffset { get; }
|
||||
|
||||
public RomfsHeader(BinaryReader reader)
|
||||
{
|
||||
HeaderSize = reader.ReadInt64();
|
||||
DirHashTableOffset = reader.ReadInt64();
|
||||
DirHashTableSize = reader.ReadInt64();
|
||||
DirMetaTableOffset = reader.ReadInt64();
|
||||
DirMetaTableSize = reader.ReadInt64();
|
||||
FileHashTableOffset = reader.ReadInt64();
|
||||
FileHashTableSize = reader.ReadInt64();
|
||||
FileMetaTableOffset = reader.ReadInt64();
|
||||
FileMetaTableSize = reader.ReadInt64();
|
||||
DataOffset = reader.ReadInt64();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -297,9 +297,11 @@ namespace LibHac
|
||||
{
|
||||
if (Header.ContentType != ContentType.Program) return;
|
||||
|
||||
var pfs = new Pfs(OpenSection(ProgramPartitionType.Code, false, IntegrityCheckLevel.ErrorOnInvalid, true));
|
||||
var pfs = new PartitionFileSystem(OpenSection(ProgramPartitionType.Code, false, IntegrityCheckLevel.ErrorOnInvalid, true));
|
||||
|
||||
if (!pfs.TryOpenFile("main.npdm", out IStorage npdmStorage)) return;
|
||||
if (!pfs.FileExists("main.npdm")) return;
|
||||
|
||||
var npdmStorage = new FileStorage(pfs.OpenFile("main.npdm", OpenMode.Read));
|
||||
|
||||
Npdm = new Npdm.NpdmBinary(npdmStorage.AsStream(), Keyset);
|
||||
|
||||
@ -523,11 +525,11 @@ namespace LibHac
|
||||
case SectionType.Invalid:
|
||||
break;
|
||||
case SectionType.Pfs0:
|
||||
var pfs0 = new Pfs(storage);
|
||||
var pfs0 = new PartitionFileSystem(storage);
|
||||
pfs0.Extract(outputDir, logger);
|
||||
break;
|
||||
case SectionType.Romfs:
|
||||
var romfs = new Romfs(storage);
|
||||
var romfs = new RomFsFileSystem(storage);
|
||||
romfs.Extract(outputDir, logger);
|
||||
break;
|
||||
case SectionType.Bktr:
|
||||
|
@ -1,191 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using LibHac.IO;
|
||||
|
||||
namespace LibHac
|
||||
{
|
||||
public class Pfs
|
||||
{
|
||||
public PfsHeader Header { get; }
|
||||
public int HeaderSize { get; }
|
||||
public PfsFileEntry[] Files { get; }
|
||||
|
||||
private Dictionary<string, PfsFileEntry> FileDict { get; }
|
||||
private IStorage BaseStorage { get; }
|
||||
|
||||
public Pfs(IStorage storage)
|
||||
{
|
||||
using (var reader = new BinaryReader(storage.AsStream(), Encoding.Default, true))
|
||||
{
|
||||
Header = new PfsHeader(reader);
|
||||
}
|
||||
|
||||
HeaderSize = Header.HeaderSize;
|
||||
Files = Header.Files;
|
||||
FileDict = Header.Files.ToDictionary(x => x.Name, x => x);
|
||||
BaseStorage = storage;
|
||||
}
|
||||
|
||||
public IStorage OpenFile(string filename)
|
||||
{
|
||||
if (!FileDict.TryGetValue(filename, out PfsFileEntry file))
|
||||
{
|
||||
throw new FileNotFoundException();
|
||||
}
|
||||
|
||||
return OpenFile(file);
|
||||
}
|
||||
|
||||
public bool TryOpenFile(string filename, out IStorage storage)
|
||||
{
|
||||
if (!FileDict.TryGetValue(filename, out PfsFileEntry file))
|
||||
{
|
||||
storage = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
storage = OpenFile(file);
|
||||
return true;
|
||||
}
|
||||
|
||||
public IStorage OpenFile(PfsFileEntry file)
|
||||
{
|
||||
return BaseStorage.Slice(HeaderSize + file.Offset, file.Size);
|
||||
}
|
||||
|
||||
public bool FileExists(string filename)
|
||||
{
|
||||
return FileDict.ContainsKey(filename);
|
||||
}
|
||||
}
|
||||
|
||||
public enum PfsType
|
||||
{
|
||||
Pfs0,
|
||||
Hfs0
|
||||
}
|
||||
|
||||
public class PfsHeader
|
||||
{
|
||||
public string Magic;
|
||||
public int NumFiles;
|
||||
public int StringTableSize;
|
||||
public long Reserved;
|
||||
public PfsType Type;
|
||||
public int HeaderSize;
|
||||
public PfsFileEntry[] Files;
|
||||
|
||||
public PfsHeader(BinaryReader reader)
|
||||
{
|
||||
Magic = reader.ReadAscii(4);
|
||||
NumFiles = reader.ReadInt32();
|
||||
StringTableSize = reader.ReadInt32();
|
||||
Reserved = reader.ReadInt32();
|
||||
|
||||
switch (Magic)
|
||||
{
|
||||
case "PFS0":
|
||||
Type = PfsType.Pfs0;
|
||||
break;
|
||||
case "HFS0":
|
||||
Type = PfsType.Hfs0;
|
||||
break;
|
||||
default:
|
||||
throw new InvalidDataException($"Invalid Partition FS type \"{Magic}\"");
|
||||
}
|
||||
|
||||
int entrysize = GetFileEntrySize(Type);
|
||||
int stringTableOffset = 16 + entrysize * NumFiles;
|
||||
HeaderSize = stringTableOffset + StringTableSize;
|
||||
|
||||
Files = new PfsFileEntry[NumFiles];
|
||||
for (int i = 0; i < NumFiles; i++)
|
||||
{
|
||||
Files[i] = new PfsFileEntry(reader, Type) { Index = i };
|
||||
}
|
||||
|
||||
for (int i = 0; i < NumFiles; i++)
|
||||
{
|
||||
reader.BaseStream.Position = stringTableOffset + Files[i].StringTableOffset;
|
||||
Files[i].Name = reader.ReadAsciiZ();
|
||||
}
|
||||
|
||||
|
||||
if (Type == PfsType.Hfs0)
|
||||
{
|
||||
for (int i = 0; i < NumFiles; i++)
|
||||
{
|
||||
reader.BaseStream.Position = HeaderSize + Files[i].Offset;
|
||||
Files[i].HashValidity = Crypto.CheckMemoryHashTable(reader.ReadBytes(Files[i].HashedRegionSize), Files[i].Hash, 0, Files[i].HashedRegionSize);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static int GetFileEntrySize(PfsType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case PfsType.Pfs0:
|
||||
return 24;
|
||||
case PfsType.Hfs0:
|
||||
return 0x40;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(type), type, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class PfsFileEntry
|
||||
{
|
||||
public int Index;
|
||||
public long Offset;
|
||||
public long Size;
|
||||
public uint StringTableOffset;
|
||||
public long Reserved;
|
||||
public int HashedRegionSize;
|
||||
public byte[] Hash;
|
||||
public string Name;
|
||||
public Validity HashValidity = Validity.Unchecked;
|
||||
|
||||
public PfsFileEntry(BinaryReader reader, PfsType type)
|
||||
{
|
||||
Offset = reader.ReadInt64();
|
||||
Size = reader.ReadInt64();
|
||||
StringTableOffset = reader.ReadUInt32();
|
||||
if (type == PfsType.Hfs0)
|
||||
{
|
||||
HashedRegionSize = reader.ReadInt32();
|
||||
Reserved = reader.ReadInt64();
|
||||
Hash = reader.ReadBytes(Crypto.Sha256DigestSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
Reserved = reader.ReadUInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class PfsExtensions
|
||||
{
|
||||
public static void Extract(this Pfs pfs, string outDir, IProgressReport logger = null)
|
||||
{
|
||||
foreach (PfsFileEntry file in pfs.Header.Files)
|
||||
{
|
||||
IStorage storage = pfs.OpenFile(file);
|
||||
string outName = Path.Combine(outDir, file.Name);
|
||||
string dir = Path.GetDirectoryName(outName);
|
||||
if (!string.IsNullOrWhiteSpace(dir)) Directory.CreateDirectory(dir);
|
||||
|
||||
using (var outFile = new FileStream(outName, FileMode.Create, FileAccess.ReadWrite))
|
||||
{
|
||||
logger?.LogMessage(file.Name);
|
||||
storage.CopyToStream(outFile, storage.Length, logger);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,163 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using LibHac.IO;
|
||||
|
||||
namespace LibHac
|
||||
{
|
||||
public class Romfs
|
||||
{
|
||||
public const int IvfcMaxLevel = 6;
|
||||
public RomfsHeader Header { get; }
|
||||
public List<RomfsDir> Directories { get; } = new List<RomfsDir>();
|
||||
public List<RomfsFile> Files { get; } = new List<RomfsFile>();
|
||||
public RomfsDir RootDir { get; }
|
||||
|
||||
public Dictionary<string, RomfsFile> FileDict { get; }
|
||||
private IStorage BaseStorage { get; }
|
||||
|
||||
public Romfs(IStorage storage)
|
||||
{
|
||||
BaseStorage = storage;
|
||||
|
||||
byte[] dirMetaTable;
|
||||
byte[] fileMetaTable;
|
||||
using (var reader = new BinaryReader(BaseStorage.AsStream(), Encoding.Default, true))
|
||||
{
|
||||
Header = new RomfsHeader(reader);
|
||||
reader.BaseStream.Position = Header.DirMetaTableOffset;
|
||||
dirMetaTable = reader.ReadBytes((int)Header.DirMetaTableSize);
|
||||
reader.BaseStream.Position = Header.FileMetaTableOffset;
|
||||
fileMetaTable = reader.ReadBytes((int)Header.FileMetaTableSize);
|
||||
}
|
||||
|
||||
using (var reader = new BinaryReader(new MemoryStream(dirMetaTable)))
|
||||
{
|
||||
int position = 0;
|
||||
while (position + 20 < Header.DirMetaTableSize)
|
||||
{
|
||||
var dir = new RomfsDir(reader) { Offset = position };
|
||||
Directories.Add(dir);
|
||||
if (dir.ParentDirOffset == position) RootDir = dir;
|
||||
position = (int)reader.BaseStream.Position;
|
||||
}
|
||||
}
|
||||
|
||||
using (var reader = new BinaryReader(new MemoryStream(fileMetaTable)))
|
||||
{
|
||||
int position = 0;
|
||||
while (position + 20 < Header.FileMetaTableSize)
|
||||
{
|
||||
var file = new RomfsFile(reader) { Offset = position };
|
||||
Files.Add(file);
|
||||
position = (int)reader.BaseStream.Position;
|
||||
}
|
||||
}
|
||||
|
||||
SetReferences();
|
||||
RomfsEntry.ResolveFilenames(Files);
|
||||
RomfsEntry.ResolveFilenames(Directories);
|
||||
FileDict = Files.ToDictionary(x => x.FullPath, x => x);
|
||||
}
|
||||
|
||||
public IStorage OpenFile(string filename)
|
||||
{
|
||||
if (!FileDict.TryGetValue(filename, out RomfsFile file))
|
||||
{
|
||||
throw new FileNotFoundException();
|
||||
}
|
||||
|
||||
return OpenFile(file);
|
||||
}
|
||||
|
||||
public IStorage OpenFile(RomfsFile file)
|
||||
{
|
||||
return BaseStorage.Slice(Header.DataOffset + file.DataOffset, file.DataLength);
|
||||
}
|
||||
|
||||
public byte[] GetFile(string filename)
|
||||
{
|
||||
IStorage storage = OpenFile(filename);
|
||||
var file = new byte[storage.Length];
|
||||
|
||||
storage.Read(file, 0);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
public bool FileExists(string filename) => FileDict.ContainsKey(filename);
|
||||
|
||||
public IStorage OpenRawStream() => BaseStorage.Slice(0);
|
||||
|
||||
private void SetReferences()
|
||||
{
|
||||
Dictionary<int, RomfsDir> dirDict = Directories.ToDictionary(x => x.Offset, x => x);
|
||||
Dictionary<int, RomfsFile> fileDict = Files.ToDictionary(x => x.Offset, x => x);
|
||||
|
||||
foreach (RomfsDir dir in Directories)
|
||||
{
|
||||
if (dir.ParentDirOffset >= 0 && dir.ParentDirOffset != dir.Offset) dir.ParentDir = dirDict[dir.ParentDirOffset];
|
||||
if (dir.NextSiblingOffset >= 0) dir.NextSibling = dirDict[dir.NextSiblingOffset];
|
||||
if (dir.FirstChildOffset >= 0) dir.FirstChild = dirDict[dir.FirstChildOffset];
|
||||
if (dir.FirstFileOffset >= 0) dir.FirstFile = fileDict[dir.FirstFileOffset];
|
||||
if (dir.NextDirHashOffset >= 0) dir.NextDirHash = dirDict[dir.NextDirHashOffset];
|
||||
}
|
||||
|
||||
foreach (RomfsFile file in Files)
|
||||
{
|
||||
if (file.ParentDirOffset >= 0) file.ParentDir = dirDict[file.ParentDirOffset];
|
||||
if (file.NextSiblingOffset >= 0) file.NextSibling = fileDict[file.NextSiblingOffset];
|
||||
if (file.NextFileHashOffset >= 0) file.NextFileHash = fileDict[file.NextFileHashOffset];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class RomfsHeader
|
||||
{
|
||||
public long HeaderSize { get; }
|
||||
public long DirHashTableOffset { get; }
|
||||
public long DirHashTableSize { get; }
|
||||
public long DirMetaTableOffset { get; }
|
||||
public long DirMetaTableSize { get; }
|
||||
public long FileHashTableOffset { get; }
|
||||
public long FileHashTableSize { get; }
|
||||
public long FileMetaTableOffset { get; }
|
||||
public long FileMetaTableSize { get; }
|
||||
public long DataOffset { get; }
|
||||
|
||||
public RomfsHeader(BinaryReader reader)
|
||||
{
|
||||
HeaderSize = reader.ReadInt64();
|
||||
DirHashTableOffset = reader.ReadInt64();
|
||||
DirHashTableSize = reader.ReadInt64();
|
||||
DirMetaTableOffset = reader.ReadInt64();
|
||||
DirMetaTableSize = reader.ReadInt64();
|
||||
FileHashTableOffset = reader.ReadInt64();
|
||||
FileHashTableSize = reader.ReadInt64();
|
||||
FileMetaTableOffset = reader.ReadInt64();
|
||||
FileMetaTableSize = reader.ReadInt64();
|
||||
DataOffset = reader.ReadInt64();
|
||||
}
|
||||
}
|
||||
|
||||
public static class RomfsExtensions
|
||||
{
|
||||
public static void Extract(this Romfs romfs, string outDir, IProgressReport logger = null)
|
||||
{
|
||||
foreach (RomfsFile file in romfs.Files)
|
||||
{
|
||||
IStorage storage = romfs.OpenFile(file);
|
||||
string outName = outDir + file.FullPath;
|
||||
string dir = Path.GetDirectoryName(outName);
|
||||
if (!string.IsNullOrWhiteSpace(dir)) Directory.CreateDirectory(dir);
|
||||
|
||||
using (var outFile = new FileStream(outName, FileMode.Create, FileAccess.ReadWrite))
|
||||
{
|
||||
logger?.LogMessage(file.FullPath);
|
||||
storage.CopyToStream(outFile, storage.Length, logger);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -149,10 +149,10 @@ namespace LibHac
|
||||
|
||||
// Meta contents always have 1 Partition FS section with 1 file in it
|
||||
IStorage sect = nca.OpenSection(0, false, IntegrityCheckLevel.ErrorOnInvalid, true);
|
||||
var pfs0 = new Pfs(sect);
|
||||
IStorage file = pfs0.OpenFile(pfs0.Files[0]);
|
||||
var pfs0 = new PartitionFileSystem(sect);
|
||||
IFile file = pfs0.OpenFile(pfs0.Files[0], OpenMode.Read);
|
||||
|
||||
var metadata = new Cnmt(file.AsStream());
|
||||
var metadata = new Cnmt(new FileStorage(file).AsStream());
|
||||
title.Id = metadata.TitleId;
|
||||
title.Version = metadata.TitleVersion;
|
||||
title.Metadata = metadata;
|
||||
@ -188,8 +188,8 @@ namespace LibHac
|
||||
{
|
||||
foreach (Title title in Titles.Values.Where(x => x.ControlNca != null))
|
||||
{
|
||||
var romfs = new Romfs(title.ControlNca.OpenSection(0, false, IntegrityCheckLevel.ErrorOnInvalid, true));
|
||||
IStorage control = romfs.OpenFile("/control.nacp");
|
||||
var romfs = new RomFsFileSystem(title.ControlNca.OpenSection(0, false, IntegrityCheckLevel.ErrorOnInvalid, true));
|
||||
IStorage control = new FileStorage(romfs.OpenFile("control.nacp", OpenMode.Read));
|
||||
|
||||
title.Control = new Nacp(control.AsStream());
|
||||
|
||||
|
@ -25,9 +25,9 @@ namespace LibHac
|
||||
public Xci(Keyset keyset, IStorage storage)
|
||||
{
|
||||
Header = new XciHeader(keyset, storage.AsStream());
|
||||
IStorage hfs0Stream = storage.Slice(Header.PartitionFsHeaderAddress);
|
||||
IStorage hfs0Storage = storage.Slice(Header.PartitionFsHeaderAddress);
|
||||
|
||||
RootPartition = new XciPartition(hfs0Stream)
|
||||
RootPartition = new XciPartition(hfs0Storage)
|
||||
{
|
||||
Name = RootPartitionName,
|
||||
Offset = Header.PartitionFsHeaderAddress,
|
||||
@ -36,11 +36,11 @@ namespace LibHac
|
||||
|
||||
Partitions.Add(RootPartition);
|
||||
|
||||
foreach (PfsFileEntry file in RootPartition.Files)
|
||||
foreach (PartitionFileEntry file in RootPartition.Files)
|
||||
{
|
||||
IStorage partitionStorage = RootPartition.OpenFile(file);
|
||||
IFile partitionFile = RootPartition.OpenFile(file, OpenMode.Read);
|
||||
|
||||
var partition = new XciPartition(partitionStorage)
|
||||
var partition = new XciPartition(new FileStorage(partitionFile))
|
||||
{
|
||||
Name = file.Name,
|
||||
Offset = Header.PartitionFsHeaderAddress + RootPartition.HeaderSize + file.Offset,
|
||||
@ -57,7 +57,7 @@ namespace LibHac
|
||||
}
|
||||
}
|
||||
|
||||
public class XciPartition : Pfs
|
||||
public class XciPartition : PartitionFileSystem
|
||||
{
|
||||
public string Name { get; internal set; }
|
||||
public long Offset { get; internal set; }
|
||||
|
@ -44,7 +44,7 @@ namespace hactoolnet
|
||||
|
||||
if (ctx.Options.ListRomFs && nca.Sections[1] != null)
|
||||
{
|
||||
var romfs = new Romfs(nca.OpenSection(1, false, ctx.Options.IntegrityLevel, true));
|
||||
var romfs = new RomFsFileSystem(nca.OpenSection(1, false, ctx.Options.IntegrityLevel, true));
|
||||
|
||||
foreach (RomfsFile romfsFile in romfs.Files)
|
||||
{
|
||||
|
@ -10,12 +10,12 @@ namespace hactoolnet
|
||||
{
|
||||
using (var file = new FileStream(ctx.Options.InFile, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
var romfs = new Romfs(file.AsStorage());
|
||||
var romfs = new RomFsFileSystem(file.AsStorage());
|
||||
Process(ctx, romfs);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Process(Context ctx, Romfs romfs)
|
||||
public static void Process(Context ctx, RomFsFileSystem romfs)
|
||||
{
|
||||
if (ctx.Options.ListRomFs)
|
||||
{
|
||||
@ -29,7 +29,7 @@ namespace hactoolnet
|
||||
{
|
||||
using (var outFile = new FileStream(ctx.Options.RomfsOut, FileMode.Create, FileAccess.ReadWrite))
|
||||
{
|
||||
IStorage romfsStorage = romfs.OpenRawStream();
|
||||
IStorage romfsStorage = romfs.GetBaseStorage();
|
||||
romfsStorage.CopyToStream(outFile, romfsStorage.Length, ctx.Logger);
|
||||
}
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ namespace hactoolnet
|
||||
|
||||
if (ctx.Options.RomfsOutDir != null)
|
||||
{
|
||||
var romfs = new Romfs(title.MainNca.OpenSection(section.SectionNum, false, ctx.Options.IntegrityLevel, true));
|
||||
var romfs = new RomFsFileSystem(title.MainNca.OpenSection(section.SectionNum, false, ctx.Options.IntegrityLevel, true));
|
||||
romfs.Extract(ctx.Options.RomfsOutDir, ctx.Logger);
|
||||
}
|
||||
|
||||
|
@ -51,9 +51,9 @@ namespace hactoolnet
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (PfsFileEntry sub in root.Files)
|
||||
foreach (PartitionFileEntry sub in root.Files)
|
||||
{
|
||||
var subPfs = new Pfs(root.OpenFile(sub));
|
||||
var subPfs = new PartitionFileSystem(new FileStorage(root.OpenFile(sub, OpenMode.Read)));
|
||||
string subDir = Path.Combine(ctx.Options.OutDir, sub.Name);
|
||||
|
||||
subPfs.Extract(subDir, ctx.Logger);
|
||||
@ -109,7 +109,7 @@ namespace hactoolnet
|
||||
|
||||
if (ctx.Options.RomfsOutDir != null)
|
||||
{
|
||||
var romfs = new Romfs(mainNca.OpenSection(romfsSection.SectionNum, false, ctx.Options.IntegrityLevel, true));
|
||||
var romfs = new RomFsFileSystem(mainNca.OpenSection(romfsSection.SectionNum, false, ctx.Options.IntegrityLevel, true));
|
||||
romfs.Extract(ctx.Options.RomfsOutDir, ctx.Logger);
|
||||
}
|
||||
|
||||
@ -131,9 +131,9 @@ namespace hactoolnet
|
||||
|
||||
Nca mainNca = null;
|
||||
|
||||
foreach (PfsFileEntry fileEntry in xci.SecurePartition.Files.Where(x => x.Name.EndsWith(".nca")))
|
||||
foreach (PartitionFileEntry fileEntry in xci.SecurePartition.Files.Where(x => x.Name.EndsWith(".nca")))
|
||||
{
|
||||
IStorage ncaStorage = xci.SecurePartition.OpenFile(fileEntry);
|
||||
IStorage ncaStorage = new FileStorage(xci.SecurePartition.OpenFile(fileEntry, OpenMode.Read));
|
||||
var nca = new Nca(ctx.Keyset, ncaStorage, true);
|
||||
|
||||
if (nca.Header.ContentType == ContentType.Program)
|
||||
@ -182,7 +182,7 @@ namespace hactoolnet
|
||||
{
|
||||
for (int i = 0; i < partition.Files.Length; i++)
|
||||
{
|
||||
PfsFileEntry file = partition.Files[i];
|
||||
PartitionFileEntry file = partition.Files[i];
|
||||
|
||||
string label = i == 0 ? " Files:" : "";
|
||||
string offsets = $"{file.Offset:x12}-{file.Offset + file.Size:x12}{file.HashValidity.GetValidityString()}";
|
||||
|
@ -1,5 +1,4 @@
|
||||
using System.IO;
|
||||
using LibHac.IO;
|
||||
using LibHac.IO;
|
||||
using Xunit;
|
||||
|
||||
namespace LibHac.Tests
|
||||
@ -18,13 +17,24 @@ namespace LibHac.Tests
|
||||
new object[] {"/a/../../..", "/"},
|
||||
new object[] {"/a/../../../a/b/c", "/a/b/c"},
|
||||
new object[] {"//a/b//.//c", "/a/b/c"},
|
||||
new object[] {"/../a/b/c/.", "/a/b/c"},
|
||||
new object[] {"/./a/b/c/.", "/a/b/c"},
|
||||
|
||||
|
||||
new object[] {"/a/b/c/", "/a/b/c/"},
|
||||
new object[] {"/a/./b/../c/", "/a/c/"},
|
||||
new object[] {"/./b/../c/", "/c/"},
|
||||
new object[] {"/a/../../../", "/"},
|
||||
new object[] {"//a/b//.//c/", "/a/b/c/"},
|
||||
new object[] {@"/tmp/../", @"/"},
|
||||
new object[] {"/tmp/../", "/"},
|
||||
|
||||
new object[] {"a", "/a"},
|
||||
new object[] {"a/../../../a/b/c", "/a/b/c"},
|
||||
new object[] {"./b/../c/", "/c/"},
|
||||
new object[] {".", "/"},
|
||||
new object[] {"..", "/"},
|
||||
new object[] {"../a/b/c/.", "/a/b/c"},
|
||||
new object[] {"./a/b/c/.", "/a/b/c"},
|
||||
};
|
||||
|
||||
[Theory]
|
||||
@ -35,11 +45,5 @@ namespace LibHac.Tests
|
||||
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void NormalizeThrowsOnInvalidStartChar()
|
||||
{
|
||||
Assert.Throws<InvalidDataException>(() => PathTools.Normalize(@"c:\a\b\c"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user