diff --git a/src/LibHac/IO/AesXtsFile.cs b/src/LibHac/IO/AesXtsFile.cs index f2aec314..c211d755 100644 --- a/src/LibHac/IO/AesXtsFile.cs +++ b/src/LibHac/IO/AesXtsFile.cs @@ -31,7 +31,7 @@ namespace LibHac.IO throw new ArgumentException("NAX0 key derivation failed."); } - IStorage encStorage = new FileStorage(BaseFile).Slice(HeaderLength, Header.Size); + IStorage encStorage = BaseFile.AsStorage().Slice(HeaderLength, Header.Size); BaseStorage = new CachedStorage(new Aes128XtsStorage(encStorage, Header.DecryptedKey1, Header.DecryptedKey2, BlockSize, true), 4, true); } diff --git a/src/LibHac/IO/DeltaFragment.cs b/src/LibHac/IO/DeltaFragment.cs index 2c202eac..6dd112e5 100644 --- a/src/LibHac/IO/DeltaFragment.cs +++ b/src/LibHac/IO/DeltaFragment.cs @@ -23,7 +23,7 @@ namespace LibHac.IO if (Delta.Length < 0x40) throw new InvalidDataException("Delta file is too small."); - Header = new DeltaFragmentHeader(new StorageFile(delta, OpenMode.Read)); + Header = new DeltaFragmentHeader(delta.AsFile(OpenMode.Read)); if (Header.Magic != Ndv0Magic) throw new InvalidDataException("NDV0 magic value is missing."); @@ -67,7 +67,7 @@ namespace LibHac.IO private void ParseDeltaStructure() { - var reader = new FileReader(new StorageFile(Delta, OpenMode.Read)); + var reader = new FileReader(Delta.AsFile(OpenMode.Read)); reader.Position = Header.FragmentHeaderSize; diff --git a/src/LibHac/IO/FileSystemExtensions.cs b/src/LibHac/IO/FileSystemExtensions.cs index eb88fa00..1c509f45 100644 --- a/src/LibHac/IO/FileSystemExtensions.cs +++ b/src/LibHac/IO/FileSystemExtensions.cs @@ -119,6 +119,7 @@ namespace LibHac.IO } } + public static IStorage AsStorage(this IFile file) => new FileStorage(file); public static Stream AsStream(this IFile file) => new NxFileStream(file, true); public static Stream AsStream(this IFile file, bool keepOpen) => new NxFileStream(file, keepOpen); diff --git a/src/LibHac/IO/NullFile.cs b/src/LibHac/IO/NullFile.cs new file mode 100644 index 00000000..f3a7946f --- /dev/null +++ b/src/LibHac/IO/NullFile.cs @@ -0,0 +1,34 @@ +using System; + +namespace LibHac.IO +{ + public class NullFile : FileBase + { + public NullFile() { } + public NullFile(long length) => Length = length; + + private long Length { get; } + + public override int Read(Span destination, long offset) + { + int toRead = ValidateReadParamsAndGetSize(destination, offset); + destination.Slice(0, toRead).Clear(); + return toRead; + } + + public override void Write(ReadOnlySpan source, long offset) + { + } + + public override void Flush() + { + } + + public override long GetSize() => Length; + + public override void SetSize(long size) + { + throw new NotSupportedException(); + } + } +} diff --git a/src/LibHac/IO/Save/SaveDataFileSystemCore.cs b/src/LibHac/IO/Save/SaveDataFileSystemCore.cs index 4ddc9b60..cbe38891 100644 --- a/src/LibHac/IO/Save/SaveDataFileSystemCore.cs +++ b/src/LibHac/IO/Save/SaveDataFileSystemCore.cs @@ -104,8 +104,7 @@ namespace LibHac.IO.Save if (file.BlockIndex < 0) { - // todo - return new StorageFile(new MemoryStorage(new byte[0]), OpenMode.ReadWrite); + return new NullFile(); } AllocationTableStorage storage = OpenFatBlock(file.BlockIndex, file.FileSize); diff --git a/src/LibHac/IO/StorageExtensions.cs b/src/LibHac/IO/StorageExtensions.cs index f91b4d07..07ac6fbe 100644 --- a/src/LibHac/IO/StorageExtensions.cs +++ b/src/LibHac/IO/StorageExtensions.cs @@ -40,6 +40,8 @@ namespace LibHac.IO public static Stream AsStream(this IStorage storage, FileAccess access) => new StorageStream(storage, access, true); public static Stream AsStream(this IStorage storage, FileAccess access, bool keepOpen) => new StorageStream(storage, access, keepOpen); + public static IFile AsFile(this IStorage storage, OpenMode mode) => new StorageFile(storage, mode); + public static void CopyTo(this IStorage input, IStorage output, IProgressReport progress = null) { const int bufferSize = 81920; diff --git a/src/LibHac/Nca.cs b/src/LibHac/Nca.cs index 82d8e4b0..655fb68f 100644 --- a/src/LibHac/Nca.cs +++ b/src/LibHac/Nca.cs @@ -232,7 +232,8 @@ namespace LibHac // Set the master hash initInfo[0] = new IntegrityVerificationInfo { - Data = new StreamStorage(new MemoryStream(sb.MasterHash), true), + // todo Get hash directly from header + Data = new MemoryStorage(sb.MasterHash), BlockSize = 0, Type = IntegrityStorageType.PartitionFs @@ -301,7 +302,7 @@ namespace LibHac if (!pfs.FileExists("main.npdm")) return; - var npdmStorage = new FileStorage(pfs.OpenFile("main.npdm", OpenMode.Read)); + IStorage npdmStorage = pfs.OpenFile("main.npdm", OpenMode.Read).AsStorage(); Npdm = new Npdm.NpdmBinary(npdmStorage.AsStream(), Keyset); diff --git a/src/LibHac/SwitchFs.cs b/src/LibHac/SwitchFs.cs index d73d11ac..cb976017 100644 --- a/src/LibHac/SwitchFs.cs +++ b/src/LibHac/SwitchFs.cs @@ -67,7 +67,7 @@ namespace LibHac Nca nca = null; try { - var storage = new FileStorage(ContentFs.OpenFile(fileEntry.FullPath, OpenMode.Read)); + IStorage storage = ContentFs.OpenFile(fileEntry.FullPath, OpenMode.Read).AsStorage(); nca = new Nca(Keyset, storage, false); @@ -106,7 +106,7 @@ namespace LibHac try { IFile file = SaveFs.OpenFile(fileEntry.FullPath, OpenMode.Read); - save = new SaveDataFileSystem(Keyset, new FileStorage(file), IntegrityCheckLevel.None, true); + save = new SaveDataFileSystem(Keyset, file.AsStorage(), IntegrityCheckLevel.None, true); } catch (Exception ex) { @@ -131,7 +131,7 @@ namespace LibHac var pfs0 = new PartitionFileSystem(sect); IFile file = pfs0.OpenFile(pfs0.Files[0], OpenMode.Read); - var metadata = new Cnmt(new FileStorage(file).AsStream()); + var metadata = new Cnmt(file.AsStream()); title.Id = metadata.TitleId; title.Version = metadata.TitleVersion; title.Metadata = metadata; @@ -168,7 +168,7 @@ namespace LibHac foreach (Title title in Titles.Values.Where(x => x.ControlNca != null)) { var romfs = new RomFsFileSystem(title.ControlNca.OpenSection(0, false, IntegrityCheckLevel.ErrorOnInvalid, true)); - IStorage control = new FileStorage(romfs.OpenFile("control.nacp", OpenMode.Read)); + IFile control = romfs.OpenFile("control.nacp", OpenMode.Read); title.Control = new Nacp(control.AsStream()); diff --git a/src/LibHac/Xci.cs b/src/LibHac/Xci.cs index e95b0ff7..5b713e2b 100644 --- a/src/LibHac/Xci.cs +++ b/src/LibHac/Xci.cs @@ -40,7 +40,7 @@ namespace LibHac { IFile partitionFile = RootPartition.OpenFile(file, OpenMode.Read); - var partition = new XciPartition(new FileStorage(partitionFile)) + var partition = new XciPartition(partitionFile.AsStorage()) { Name = file.Name, Offset = Header.PartitionFsHeaderAddress + RootPartition.HeaderSize + file.Offset, diff --git a/src/hactoolnet/ProcessDelta.cs b/src/hactoolnet/ProcessDelta.cs index 56ad4e51..5e102091 100644 --- a/src/hactoolnet/ProcessDelta.cs +++ b/src/hactoolnet/ProcessDelta.cs @@ -15,9 +15,8 @@ namespace hactoolnet public static void Process(Context ctx) { - using (var deltaFile = new StreamStorage(new FileStream(ctx.Options.InFile, FileMode.Open, FileAccess.Read), false)) + using (IStorage deltaFile = new FileStream(ctx.Options.InFile, FileMode.Open, FileAccess.Read).AsStorage(false)) { - IStorage deltaStorage = deltaFile; Span magic = stackalloc byte[4]; deltaFile.Read(magic, 0); @@ -34,7 +33,7 @@ namespace hactoolnet throw new FileNotFoundException("Specified NCA does not contain a delta fragment"); } - deltaStorage = new FileStorage(fs.OpenFile(FragmentFileName, OpenMode.Read)); + deltaStorage = fs.OpenFile(FragmentFileName, OpenMode.Read).AsStorage(); } catch (InvalidDataException) { } // Ignore non-NCA3 files } @@ -43,7 +42,7 @@ namespace hactoolnet if (ctx.Options.BaseFile != null) { - using (var baseFile = new StreamStorage(new FileStream(ctx.Options.BaseFile, FileMode.Open, FileAccess.Read), false)) + using (IStorage baseFile = new FileStream(ctx.Options.BaseFile, FileMode.Open, FileAccess.Read).AsStorage(false)) { delta.SetBaseStorage(baseFile); diff --git a/src/hactoolnet/ProcessNca.cs b/src/hactoolnet/ProcessNca.cs index e538f12e..34178784 100644 --- a/src/hactoolnet/ProcessNca.cs +++ b/src/hactoolnet/ProcessNca.cs @@ -11,7 +11,7 @@ namespace hactoolnet { public static void Process(Context ctx) { - using (var file = new StreamStorage(new FileStream(ctx.Options.InFile, FileMode.Open, FileAccess.Read), false)) + using (IStorage file = new FileStream(ctx.Options.InFile, FileMode.Open, FileAccess.Read).AsStorage(false)) { var nca = new Nca(ctx.Keyset, file, false); nca.ValidateMasterHashes(); @@ -19,7 +19,7 @@ namespace hactoolnet if (ctx.Options.BaseNca != null) { - var baseFile = new StreamStorage(new FileStream(ctx.Options.BaseNca, FileMode.Open, FileAccess.Read), false); + IStorage baseFile = new FileStream(ctx.Options.BaseNca, FileMode.Open, FileAccess.Read).AsStorage(false); var baseNca = new Nca(ctx.Keyset, baseFile, false); nca.SetBaseNca(baseNca); } diff --git a/src/hactoolnet/ProcessSave.cs b/src/hactoolnet/ProcessSave.cs index 7910726a..f394fb8b 100644 --- a/src/hactoolnet/ProcessSave.cs +++ b/src/hactoolnet/ProcessSave.cs @@ -99,7 +99,7 @@ namespace hactoolnet string destFilename = ctx.Options.ReplaceFileDest; if (!destFilename.StartsWith("/")) destFilename = '/' + destFilename; - using (IFile inFile = new StorageFile(new FileStream(ctx.Options.ReplaceFileSource, FileMode.Open, FileAccess.Read).AsStorage(false), OpenMode.ReadWrite)) + using (IFile inFile = new FileStream(ctx.Options.ReplaceFileSource, FileMode.Open, FileAccess.Read).AsIFile(OpenMode.ReadWrite)) { using (IFile outFile = save.OpenFile(destFilename, OpenMode.ReadWrite)) { diff --git a/src/hactoolnet/ProcessXci.cs b/src/hactoolnet/ProcessXci.cs index 5bd4907b..dd4bb8eb 100644 --- a/src/hactoolnet/ProcessXci.cs +++ b/src/hactoolnet/ProcessXci.cs @@ -53,7 +53,7 @@ namespace hactoolnet foreach (PartitionFileEntry sub in root.Files) { - var subPfs = new PartitionFileSystem(new FileStorage(root.OpenFile(sub, OpenMode.Read))); + var subPfs = new PartitionFileSystem(root.OpenFile(sub, OpenMode.Read).AsStorage()); string subDir = Path.Combine(ctx.Options.OutDir, sub.Name); subPfs.Extract(subDir, ctx.Logger); @@ -133,7 +133,7 @@ namespace hactoolnet foreach (PartitionFileEntry fileEntry in xci.SecurePartition.Files.Where(x => x.Name.EndsWith(".nca"))) { - IStorage ncaStorage = new FileStorage(xci.SecurePartition.OpenFile(fileEntry, OpenMode.Read)); + IStorage ncaStorage = xci.SecurePartition.OpenFile(fileEntry, OpenMode.Read).AsStorage(); var nca = new Nca(ctx.Keyset, ncaStorage, true); if (nca.Header.ContentType == ContentType.Program)