mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Add PartitionFileSystem
This commit is contained in:
parent
f94c6e83e9
commit
9a234575ac
8 changed files with 362 additions and 18 deletions
|
@ -6,16 +6,15 @@ namespace LibHac.IO
|
||||||
{
|
{
|
||||||
public static class FileSystemExtensions
|
public static class FileSystemExtensions
|
||||||
{
|
{
|
||||||
// todo add progress logging
|
public static void CopyDirectory(this IDirectory source, IDirectory dest, IProgressReport logger = null)
|
||||||
public static void CopyDirectory(this IDirectory source, IDirectory dest)
|
|
||||||
{
|
{
|
||||||
IFileSystem sourceFs = source.ParentFileSystem;
|
IFileSystem sourceFs = source.ParentFileSystem;
|
||||||
IFileSystem destFs = dest.ParentFileSystem;
|
IFileSystem destFs = dest.ParentFileSystem;
|
||||||
|
|
||||||
foreach (DirectoryEntry entry in source.Read())
|
foreach (DirectoryEntry entry in source.Read())
|
||||||
{
|
{
|
||||||
string subSrcPath = source.FullPath + '/' + entry.Name;
|
string subSrcPath = PathTools.Normalize(source.FullPath + '/' + entry.Name);
|
||||||
string subDstPath = dest.FullPath + '/' + entry.Name;
|
string subDstPath = PathTools.Normalize(dest.FullPath + '/' + entry.Name);
|
||||||
|
|
||||||
if (entry.Type == DirectoryEntryType.Directory)
|
if (entry.Type == DirectoryEntryType.Directory)
|
||||||
{
|
{
|
||||||
|
@ -23,7 +22,7 @@ namespace LibHac.IO
|
||||||
IDirectory subSrcDir = sourceFs.OpenDirectory(subSrcPath, OpenDirectoryMode.All);
|
IDirectory subSrcDir = sourceFs.OpenDirectory(subSrcPath, OpenDirectoryMode.All);
|
||||||
IDirectory subDstDir = destFs.OpenDirectory(subDstPath, OpenDirectoryMode.All);
|
IDirectory subDstDir = destFs.OpenDirectory(subDstPath, OpenDirectoryMode.All);
|
||||||
|
|
||||||
subSrcDir.CopyDirectory(subDstDir);
|
subSrcDir.CopyDirectory(subDstDir, logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry.Type == DirectoryEntryType.File)
|
if (entry.Type == DirectoryEntryType.File)
|
||||||
|
@ -33,12 +32,28 @@ namespace LibHac.IO
|
||||||
using (IFile srcFile = sourceFs.OpenFile(subSrcPath, OpenMode.Read))
|
using (IFile srcFile = sourceFs.OpenFile(subSrcPath, OpenMode.Read))
|
||||||
using (IFile dstFile = destFs.OpenFile(subDstPath, OpenMode.Write))
|
using (IFile dstFile = destFs.OpenFile(subDstPath, OpenMode.Write))
|
||||||
{
|
{
|
||||||
srcFile.CopyTo(dstFile);
|
logger?.LogMessage(subSrcPath);
|
||||||
|
srcFile.CopyTo(dstFile, logger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void CopyFileSystem(this IFileSystem source, IFileSystem dest, IProgressReport logger = null)
|
||||||
|
{
|
||||||
|
IDirectory sourceRoot = source.OpenDirectory("/", OpenDirectoryMode.All);
|
||||||
|
IDirectory destRoot = dest.OpenDirectory("/", OpenDirectoryMode.All);
|
||||||
|
|
||||||
|
sourceRoot.CopyDirectory(destRoot, logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Extract(this IFileSystem source, string destinationPath, IProgressReport logger = null)
|
||||||
|
{
|
||||||
|
var destFs = new LocalFileSystem(destinationPath);
|
||||||
|
|
||||||
|
source.CopyFileSystem(destFs, logger);
|
||||||
|
}
|
||||||
|
|
||||||
public static IEnumerable<DirectoryEntry> EnumerateEntries(this IDirectory directory)
|
public static IEnumerable<DirectoryEntry> EnumerateEntries(this IDirectory directory)
|
||||||
{
|
{
|
||||||
IFileSystem fs = directory.ParentFileSystem;
|
IFileSystem fs = directory.ParentFileSystem;
|
||||||
|
@ -57,10 +72,10 @@ namespace LibHac.IO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo add progress logging
|
public static void CopyTo(this IFile file, IFile dest, IProgressReport logger = null)
|
||||||
public static void CopyTo(this IFile file, IFile dest)
|
|
||||||
{
|
{
|
||||||
const int bufferSize = 0x8000;
|
const int bufferSize = 0x8000;
|
||||||
|
logger?.SetTotal(file.GetSize());
|
||||||
|
|
||||||
byte[] buffer = ArrayPool<byte>.Shared.Rent(bufferSize);
|
byte[] buffer = ArrayPool<byte>.Shared.Rent(bufferSize);
|
||||||
try
|
try
|
||||||
|
@ -72,9 +87,14 @@ namespace LibHac.IO
|
||||||
{
|
{
|
||||||
dest.Write(buffer.AsSpan(0, bytesRead), inOffset);
|
dest.Write(buffer.AsSpan(0, bytesRead), inOffset);
|
||||||
inOffset += bytesRead;
|
inOffset += bytesRead;
|
||||||
|
logger?.ReportAdd(bytesRead);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally { ArrayPool<byte>.Shared.Return(buffer); }
|
finally
|
||||||
|
{
|
||||||
|
ArrayPool<byte>.Shared.Return(buffer);
|
||||||
|
logger?.SetTotal(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
49
src/LibHac/IO/PartitionDirectory.cs
Normal file
49
src/LibHac/IO/PartitionDirectory.cs
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace LibHac.IO
|
||||||
|
{
|
||||||
|
public class PartitionDirectory : IDirectory
|
||||||
|
{
|
||||||
|
IFileSystem IDirectory.ParentFileSystem => ParentFileSystem;
|
||||||
|
public PartitionFileSystem ParentFileSystem { get; }
|
||||||
|
public string FullPath { get; }
|
||||||
|
|
||||||
|
private OpenDirectoryMode Mode { get; }
|
||||||
|
|
||||||
|
public PartitionDirectory(PartitionFileSystem fs, string path, OpenDirectoryMode mode)
|
||||||
|
{
|
||||||
|
path = PathTools.Normalize(path);
|
||||||
|
|
||||||
|
if (path != "/") throw new DirectoryNotFoundException();
|
||||||
|
|
||||||
|
ParentFileSystem = fs;
|
||||||
|
FullPath = path;
|
||||||
|
Mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public IEnumerable<DirectoryEntry> Read()
|
||||||
|
{
|
||||||
|
if (Mode.HasFlag(OpenDirectoryMode.Files))
|
||||||
|
{
|
||||||
|
foreach (PartitionFileEntry entry in ParentFileSystem.Files)
|
||||||
|
{
|
||||||
|
yield return new DirectoryEntry(entry.Name, '/' + entry.Name, DirectoryEntryType.File, entry.Size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetEntryCount()
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
if (Mode.HasFlag(OpenDirectoryMode.Files))
|
||||||
|
{
|
||||||
|
count += ParentFileSystem.Files.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
48
src/LibHac/IO/PartitionFile.cs
Normal file
48
src/LibHac/IO/PartitionFile.cs
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace LibHac.IO
|
||||||
|
{
|
||||||
|
public class PartitionFile : FileBase
|
||||||
|
{
|
||||||
|
private IStorage BaseStorage { get; }
|
||||||
|
private long Offset { get; }
|
||||||
|
private long Size { get; }
|
||||||
|
|
||||||
|
public PartitionFile(IStorage baseStorage, long offset, long size, OpenMode mode)
|
||||||
|
{
|
||||||
|
Mode = mode;
|
||||||
|
BaseStorage = baseStorage;
|
||||||
|
Offset = offset;
|
||||||
|
Size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Read(Span<byte> destination, long offset)
|
||||||
|
{
|
||||||
|
int toRead = ValidateReadParamsAndGetSize(destination, offset);
|
||||||
|
|
||||||
|
long storageOffset = Offset + offset;
|
||||||
|
BaseStorage.Read(destination.Slice(0, toRead), storageOffset);
|
||||||
|
|
||||||
|
return toRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(ReadOnlySpan<byte> source, long offset)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Flush()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override long GetSize()
|
||||||
|
{
|
||||||
|
return Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetSize(long size)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
208
src/LibHac/IO/PartitionFileSystem.cs
Normal file
208
src/LibHac/IO/PartitionFileSystem.cs
Normal file
|
@ -0,0 +1,208 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace LibHac.IO
|
||||||
|
{
|
||||||
|
public class PartitionFileSystem : IFileSystem
|
||||||
|
{
|
||||||
|
public PartitionFileSystemHeader Header { get; }
|
||||||
|
public int HeaderSize { get; }
|
||||||
|
public PartitionFileEntry[] Files { get; }
|
||||||
|
|
||||||
|
private Dictionary<string, PartitionFileEntry> FileDict { get; }
|
||||||
|
private IStorage BaseStorage { get; }
|
||||||
|
|
||||||
|
public PartitionFileSystem(IStorage storage)
|
||||||
|
{
|
||||||
|
using (var reader = new BinaryReader(storage.AsStream(), Encoding.Default, true))
|
||||||
|
{
|
||||||
|
Header = new PartitionFileSystemHeader(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
HeaderSize = Header.HeaderSize;
|
||||||
|
Files = Header.Files;
|
||||||
|
FileDict = Header.Files.ToDictionary(x => x.Name, x => x);
|
||||||
|
BaseStorage = storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateDirectory(string path)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateFile(string path, long size)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteDirectory(string path)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteFile(string path)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IDirectory OpenDirectory(string path, OpenDirectoryMode mode)
|
||||||
|
{
|
||||||
|
return new PartitionDirectory(this, path, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IFile OpenFile(string path, OpenMode mode)
|
||||||
|
{
|
||||||
|
path = PathTools.Normalize(path).TrimStart('/');
|
||||||
|
|
||||||
|
if (!FileDict.TryGetValue(path, out PartitionFileEntry entry))
|
||||||
|
{
|
||||||
|
throw new FileNotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return OpenFile(entry, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IFile OpenFile(PartitionFileEntry entry, OpenMode mode)
|
||||||
|
{
|
||||||
|
return new PartitionFile(BaseStorage, HeaderSize + entry.Offset, entry.Size, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RenameDirectory(string srcPath, string dstPath)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RenameFile(string srcPath, string dstPath)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DirectoryExists(string path)
|
||||||
|
{
|
||||||
|
path = PathTools.Normalize(path);
|
||||||
|
return path == "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool FileExists(string path)
|
||||||
|
{
|
||||||
|
path = PathTools.Normalize(path).TrimStart('/');
|
||||||
|
|
||||||
|
return FileDict.ContainsKey(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Commit()
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum PartitionFileSystemType
|
||||||
|
{
|
||||||
|
Pfs0,
|
||||||
|
Hfs0
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PartitionFileSystemHeader
|
||||||
|
{
|
||||||
|
public string Magic;
|
||||||
|
public int NumFiles;
|
||||||
|
public int StringTableSize;
|
||||||
|
public long Reserved;
|
||||||
|
public PartitionFileSystemType Type;
|
||||||
|
public int HeaderSize;
|
||||||
|
public PartitionFileEntry[] Files;
|
||||||
|
|
||||||
|
public PartitionFileSystemHeader(BinaryReader reader)
|
||||||
|
{
|
||||||
|
Magic = reader.ReadAscii(4);
|
||||||
|
NumFiles = reader.ReadInt32();
|
||||||
|
StringTableSize = reader.ReadInt32();
|
||||||
|
Reserved = reader.ReadInt32();
|
||||||
|
|
||||||
|
switch (Magic)
|
||||||
|
{
|
||||||
|
case "PFS0":
|
||||||
|
Type = PartitionFileSystemType.Pfs0;
|
||||||
|
break;
|
||||||
|
case "HFS0":
|
||||||
|
Type = PartitionFileSystemType.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 PartitionFileEntry[NumFiles];
|
||||||
|
for (int i = 0; i < NumFiles; i++)
|
||||||
|
{
|
||||||
|
Files[i] = new PartitionFileEntry(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 == PartitionFileSystemType.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(PartitionFileSystemType type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case PartitionFileSystemType.Pfs0:
|
||||||
|
return 24;
|
||||||
|
case PartitionFileSystemType.Hfs0:
|
||||||
|
return 0x40;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(type), type, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PartitionFileEntry
|
||||||
|
{
|
||||||
|
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 PartitionFileEntry(BinaryReader reader, PartitionFileSystemType type)
|
||||||
|
{
|
||||||
|
Offset = reader.ReadInt64();
|
||||||
|
Size = reader.ReadInt64();
|
||||||
|
StringTableOffset = reader.ReadUInt32();
|
||||||
|
if (type == PartitionFileSystemType.Hfs0)
|
||||||
|
{
|
||||||
|
HashedRegionSize = reader.ReadInt32();
|
||||||
|
Reserved = reader.ReadInt64();
|
||||||
|
Hash = reader.ReadBytes(Crypto.Sha256DigestSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Reserved = reader.ReadUInt32();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,6 +24,7 @@ namespace LibHac.IO
|
||||||
|
|
||||||
byte[] dirMetaTable;
|
byte[] dirMetaTable;
|
||||||
byte[] fileMetaTable;
|
byte[] fileMetaTable;
|
||||||
|
|
||||||
using (var reader = new BinaryReader(BaseStorage.AsStream(), Encoding.Default, true))
|
using (var reader = new BinaryReader(BaseStorage.AsStream(), Encoding.Default, true))
|
||||||
{
|
{
|
||||||
Header = new RomfsHeader(reader);
|
Header = new RomfsHeader(reader);
|
||||||
|
@ -117,6 +118,8 @@ namespace LibHac.IO
|
||||||
|
|
||||||
public IFile OpenFile(string path, OpenMode mode)
|
public IFile OpenFile(string path, OpenMode mode)
|
||||||
{
|
{
|
||||||
|
path = PathTools.Normalize(path);
|
||||||
|
|
||||||
if (!FileDict.TryGetValue(path, out RomfsFile file))
|
if (!FileDict.TryGetValue(path, out RomfsFile file))
|
||||||
{
|
{
|
||||||
throw new FileNotFoundException();
|
throw new FileNotFoundException();
|
||||||
|
@ -147,11 +150,15 @@ namespace LibHac.IO
|
||||||
|
|
||||||
public bool DirectoryExists(string path)
|
public bool DirectoryExists(string path)
|
||||||
{
|
{
|
||||||
|
path = PathTools.Normalize(path);
|
||||||
|
|
||||||
return DirectoryDict.ContainsKey(path);
|
return DirectoryDict.ContainsKey(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool FileExists(string path)
|
public bool FileExists(string path)
|
||||||
{
|
{
|
||||||
|
path = PathTools.Normalize(path);
|
||||||
|
|
||||||
return FileDict.ContainsKey(path);
|
return FileDict.ContainsKey(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -255,13 +255,24 @@ namespace LibHac
|
||||||
return new HierarchicalIntegrityVerificationStorage(initInfo, integrityCheckLevel, leaveOpen);
|
return new HierarchicalIntegrityVerificationStorage(initInfo, integrityCheckLevel, leaveOpen);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IFileSystem OpenSectionFileSystem(int index)
|
public IFileSystem OpenSectionFileSystem(int index, IntegrityCheckLevel integrityCheckLevel)
|
||||||
{
|
{
|
||||||
IStorage storage = OpenSection(index, false, IntegrityCheckLevel.ErrorOnInvalid, true);
|
if (Sections[index] == null) throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
|
NcaFsHeader header = Sections[index].Header;
|
||||||
|
|
||||||
var fs = new RomFsFileSystem(storage);
|
IStorage storage = OpenSection(index, false, integrityCheckLevel, true);
|
||||||
|
|
||||||
return fs;
|
switch (header.Type)
|
||||||
|
{
|
||||||
|
case SectionType.Pfs0:
|
||||||
|
return new PartitionFileSystem(storage);
|
||||||
|
case SectionType.Romfs:
|
||||||
|
return new RomFsFileSystem(storage);
|
||||||
|
case SectionType.Bktr:
|
||||||
|
return new RomFsFileSystem(storage);
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -75,7 +75,7 @@ namespace hactoolnet
|
||||||
|
|
||||||
if (ctx.Options.RomfsOutDir != null)
|
if (ctx.Options.RomfsOutDir != null)
|
||||||
{
|
{
|
||||||
var romfs = new Romfs(nca.OpenSection(section.SectionNum, false, ctx.Options.IntegrityLevel, true));
|
IFileSystem romfs = nca.OpenSectionFileSystem(section.SectionNum, ctx.Options.IntegrityLevel);
|
||||||
romfs.Extract(ctx.Options.RomfsOutDir, ctx.Logger);
|
romfs.Extract(ctx.Options.RomfsOutDir, ctx.Logger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,8 @@ namespace hactoolnet
|
||||||
|
|
||||||
if (ctx.Options.ExefsOutDir != null)
|
if (ctx.Options.ExefsOutDir != null)
|
||||||
{
|
{
|
||||||
nca.ExtractSection(section.SectionNum, ctx.Options.ExefsOutDir, ctx.Options.IntegrityLevel, ctx.Logger);
|
IFileSystem pfs = nca.OpenSectionFileSystem(section.SectionNum, ctx.Options.IntegrityLevel);
|
||||||
|
pfs.Extract(ctx.Options.ExefsOutDir, ctx.Logger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace hactoolnet
|
||||||
{
|
{
|
||||||
using (var file = new FileStream(ctx.Options.InFile, FileMode.Open, FileAccess.Read))
|
using (var file = new FileStream(ctx.Options.InFile, FileMode.Open, FileAccess.Read))
|
||||||
{
|
{
|
||||||
var pfs = new Pfs(file.AsStorage());
|
var pfs = new PartitionFileSystem(file.AsStorage());
|
||||||
ctx.Logger.LogMessage(pfs.Print());
|
ctx.Logger.LogMessage(pfs.Print());
|
||||||
|
|
||||||
if (ctx.Options.OutDir != null)
|
if (ctx.Options.OutDir != null)
|
||||||
|
@ -23,7 +23,7 @@ namespace hactoolnet
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string Print(this Pfs pfs)
|
private static string Print(this PartitionFileSystem pfs)
|
||||||
{
|
{
|
||||||
const int colLen = 36;
|
const int colLen = 36;
|
||||||
const int fileNameLen = 39;
|
const int fileNameLen = 39;
|
||||||
|
@ -38,7 +38,7 @@ namespace hactoolnet
|
||||||
|
|
||||||
for (int i = 0; i < pfs.Files.Length; i++)
|
for (int i = 0; i < pfs.Files.Length; i++)
|
||||||
{
|
{
|
||||||
PfsFileEntry file = pfs.Files[i];
|
PartitionFileEntry file = pfs.Files[i];
|
||||||
|
|
||||||
string label = i == 0 ? "Files:" : "";
|
string label = i == 0 ? "Files:" : "";
|
||||||
string offsets = $"{file.Offset:x12}-{file.Offset + file.Size:x12}{file.HashValidity.GetValidityString()}";
|
string offsets = $"{file.Offset:x12}-{file.Offset + file.Size:x12}{file.HashValidity.GetValidityString()}";
|
||||||
|
|
Loading…
Reference in a new issue