mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Messing around
This commit is contained in:
parent
bb6c73014b
commit
2bf6613165
11 changed files with 417 additions and 0 deletions
22
src/LibHac/IO/DirectoryEntry.cs
Normal file
22
src/LibHac/IO/DirectoryEntry.cs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
namespace LibHac.IO
|
||||||
|
{
|
||||||
|
public class DirectoryEntry
|
||||||
|
{
|
||||||
|
public string Name { get; }
|
||||||
|
public DirectoryEntryType Type { get; }
|
||||||
|
public long Size { get; }
|
||||||
|
|
||||||
|
public DirectoryEntry(string name, DirectoryEntryType type, long size)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Type = type;
|
||||||
|
Size = size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum DirectoryEntryType
|
||||||
|
{
|
||||||
|
Directory,
|
||||||
|
File
|
||||||
|
}
|
||||||
|
}
|
7
src/LibHac/IO/HierarchicalRomFileTable.cs
Normal file
7
src/LibHac/IO/HierarchicalRomFileTable.cs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
namespace LibHac.IO
|
||||||
|
{
|
||||||
|
public class HierarchicalRomFileTable
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
10
src/LibHac/IO/IDirectory.cs
Normal file
10
src/LibHac/IO/IDirectory.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
namespace LibHac.IO
|
||||||
|
{
|
||||||
|
public interface IDirectory
|
||||||
|
{
|
||||||
|
IFileSystem ParentFileSystem { get; }
|
||||||
|
|
||||||
|
DirectoryEntry[] Read();
|
||||||
|
int GetEntryCount();
|
||||||
|
}
|
||||||
|
}
|
13
src/LibHac/IO/IFile.cs
Normal file
13
src/LibHac/IO/IFile.cs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace LibHac.IO
|
||||||
|
{
|
||||||
|
public interface IFile
|
||||||
|
{
|
||||||
|
void Read(Span<byte> destination, long offset);
|
||||||
|
void Write(ReadOnlySpan<byte> source, long offset);
|
||||||
|
void Flush();
|
||||||
|
long GetSize();
|
||||||
|
long SetSize();
|
||||||
|
}
|
||||||
|
}
|
17
src/LibHac/IO/IFileSystem.cs
Normal file
17
src/LibHac/IO/IFileSystem.cs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
namespace LibHac.IO
|
||||||
|
{
|
||||||
|
public interface IFileSystem
|
||||||
|
{
|
||||||
|
void Commit();
|
||||||
|
void CreateDirectory(string path);
|
||||||
|
void CreateFile(string path, long size);
|
||||||
|
void DeleteDirectory(string path);
|
||||||
|
void DeleteFile(string path);
|
||||||
|
IDirectory OpenDirectory(string path);
|
||||||
|
IFile OpenFile(string path);
|
||||||
|
void RenameDirectory(string srcPath, string dstPath);
|
||||||
|
void RenameFile(string srcPath, string dstPath);
|
||||||
|
bool DirectoryExists(string path);
|
||||||
|
bool FileExists(string path);
|
||||||
|
}
|
||||||
|
}
|
67
src/LibHac/IO/IFileSystemExtensions.cs
Normal file
67
src/LibHac/IO/IFileSystemExtensions.cs
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace LibHac.IO
|
||||||
|
{
|
||||||
|
public static class IFileSystemExtensions
|
||||||
|
{
|
||||||
|
public static void Extract(this IFileSystem fs, string outDir)
|
||||||
|
{
|
||||||
|
var root = fs.OpenDirectory("/");
|
||||||
|
|
||||||
|
foreach (var filename in root.EnumerateFiles())
|
||||||
|
{
|
||||||
|
//Console.WriteLine(filename);
|
||||||
|
IFile file = fs.OpenFile(filename);
|
||||||
|
string outPath = Path.Combine(outDir, filename.TrimStart('/'));
|
||||||
|
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(outPath));
|
||||||
|
|
||||||
|
using (var outFile = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
|
||||||
|
{
|
||||||
|
file.CopyTo(outFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<string> EnumerateFiles(this IDirectory directory)
|
||||||
|
{
|
||||||
|
var entries = directory.Read();
|
||||||
|
|
||||||
|
foreach (var entry in entries)
|
||||||
|
{
|
||||||
|
if (entry.Type == DirectoryEntryType.Directory)
|
||||||
|
{
|
||||||
|
foreach(string a in EnumerateFiles(directory.ParentFileSystem.OpenDirectory(entry.Name)))
|
||||||
|
{
|
||||||
|
yield return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry.Type == DirectoryEntryType.File)
|
||||||
|
{
|
||||||
|
yield return entry.Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CopyTo(this IFile file, Stream output)
|
||||||
|
{
|
||||||
|
const int bufferSize = 0x8000;
|
||||||
|
long remaining = file.GetSize();
|
||||||
|
long inOffset = 0;
|
||||||
|
var buffer = new byte[bufferSize];
|
||||||
|
|
||||||
|
while (remaining > 0)
|
||||||
|
{
|
||||||
|
int toWrite = (int)Math.Min(buffer.Length, remaining);
|
||||||
|
file.Read(buffer.AsSpan(0, toWrite), inOffset);
|
||||||
|
|
||||||
|
output.Write(buffer, 0, toWrite);
|
||||||
|
remaining -= toWrite;
|
||||||
|
inOffset += toWrite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
72
src/LibHac/IO/RomFsDirectory.cs
Normal file
72
src/LibHac/IO/RomFsDirectory.cs
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace LibHac.IO
|
||||||
|
{
|
||||||
|
public class RomFsDirectory : IDirectory
|
||||||
|
{
|
||||||
|
public IFileSystem ParentFileSystem { get; }
|
||||||
|
|
||||||
|
private RomfsDir Directory { get; }
|
||||||
|
|
||||||
|
public RomFsDirectory(RomFsFileSystem fs, string path)
|
||||||
|
{
|
||||||
|
if (!fs.DirectoryDict.TryGetValue(path, out RomfsDir dir))
|
||||||
|
{
|
||||||
|
throw new DirectoryNotFoundException(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
ParentFileSystem = fs;
|
||||||
|
Directory = dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DirectoryEntry[] Read()
|
||||||
|
{
|
||||||
|
int count = GetEntryCount();
|
||||||
|
|
||||||
|
var entries = new DirectoryEntry[count];
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
var dirEntry = Directory.FirstChild;
|
||||||
|
|
||||||
|
while (dirEntry != null)
|
||||||
|
{
|
||||||
|
entries[index] = new DirectoryEntry(dirEntry.FullPath, DirectoryEntryType.Directory, 0);
|
||||||
|
dirEntry = dirEntry.NextSibling;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
RomfsFile fileEntry = Directory.FirstFile;
|
||||||
|
|
||||||
|
while (fileEntry != null)
|
||||||
|
{
|
||||||
|
entries[index] = new DirectoryEntry(fileEntry.FullPath, DirectoryEntryType.File, fileEntry.DataLength);
|
||||||
|
fileEntry = fileEntry.NextSibling;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetEntryCount()
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
RomfsDir dirEntry = Directory.FirstChild;
|
||||||
|
|
||||||
|
while (dirEntry != null)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
dirEntry = dirEntry.NextSibling;
|
||||||
|
}
|
||||||
|
|
||||||
|
RomfsFile fileEntry = Directory.FirstFile;
|
||||||
|
|
||||||
|
while (fileEntry != null)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
fileEntry = fileEntry.NextSibling;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
45
src/LibHac/IO/RomFsFile.cs
Normal file
45
src/LibHac/IO/RomFsFile.cs
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace LibHac.IO
|
||||||
|
{
|
||||||
|
public class RomFsFile : IFile
|
||||||
|
{
|
||||||
|
private IStorage BaseStorage { get; }
|
||||||
|
private long Offset { get; }
|
||||||
|
private long Size { get; }
|
||||||
|
|
||||||
|
public RomFsFile(IStorage baseStorage, long offset, long size)
|
||||||
|
{
|
||||||
|
BaseStorage = baseStorage;
|
||||||
|
Offset = offset;
|
||||||
|
Size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Read(Span<byte> destination, long offset)
|
||||||
|
{
|
||||||
|
long storageOffset = Offset + offset;
|
||||||
|
|
||||||
|
BaseStorage.Read(destination, storageOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(ReadOnlySpan<byte> source, long offset)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Flush()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long GetSize()
|
||||||
|
{
|
||||||
|
return Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long SetSize()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
152
src/LibHac/IO/RomFsFileSystem.cs
Normal file
152
src/LibHac/IO/RomFsFileSystem.cs
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace LibHac.IO
|
||||||
|
{
|
||||||
|
public class RomFsFileSystem : IFileSystem
|
||||||
|
{
|
||||||
|
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; }
|
||||||
|
public Dictionary<string, RomfsDir> DirectoryDict { get; }
|
||||||
|
private IStorage BaseStorage { get; }
|
||||||
|
|
||||||
|
public RomFsFileSystem(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);
|
||||||
|
DirectoryDict = Directories.ToDictionary(x => x.FullPath, x => x);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 void Commit()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateDirectory(string path)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateFile(string path, long size)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteDirectory(string path)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteFile(string path)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IDirectory OpenDirectory(string path)
|
||||||
|
{
|
||||||
|
return new RomFsDirectory(this, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IFile OpenFile(string path)
|
||||||
|
{
|
||||||
|
if (!FileDict.TryGetValue(path, out RomfsFile file))
|
||||||
|
{
|
||||||
|
throw new FileNotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return OpenFile(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IFile OpenFile(RomfsFile file)
|
||||||
|
{
|
||||||
|
return new RomFsFile(BaseStorage, Header.DataOffset + file.DataOffset, file.DataLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RenameDirectory(string srcPath, string dstPath)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RenameFile(string srcPath, string dstPath)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DirectoryExists(string path)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool FileExists(string path)
|
||||||
|
{
|
||||||
|
return FileDict.ContainsKey(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -255,6 +255,15 @@ namespace LibHac
|
||||||
return new HierarchicalIntegrityVerificationStorage(initInfo, integrityCheckLevel, leaveOpen);
|
return new HierarchicalIntegrityVerificationStorage(initInfo, integrityCheckLevel, leaveOpen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IFileSystem OpenSectionFileSystem(int index)
|
||||||
|
{
|
||||||
|
IStorage storage = OpenSection(index, false, IntegrityCheckLevel.ErrorOnInvalid, true);
|
||||||
|
|
||||||
|
var fs = new RomFsFileSystem(storage);
|
||||||
|
|
||||||
|
return fs;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets a base <see cref="Nca"/> to use when reading patches.
|
/// Sets a base <see cref="Nca"/> to use when reading patches.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -31,6 +31,9 @@ namespace LibHac
|
||||||
dir = dir.ParentDir;
|
dir = dir.ParentDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//todo
|
||||||
|
if (list.Count == 1) list.Add("/");
|
||||||
|
|
||||||
for (int i = list.Count - 1; i >= 0; i--)
|
for (int i = list.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
sb.Append(list[i]);
|
sb.Append(list[i]);
|
||||||
|
|
Loading…
Reference in a new issue