void PopulateDirectory(FileStream stream, CustomBinaryReader reader, CentralDirectoryLocator central_directory_locator) { long central_directory_base_offset = central_directory_locator.ContentDirectoryOffset; stream.Position = central_directory_base_offset; byte[] central_directory_data = reader.ReadBytes(central_directory_locator.ContentDictionarySize); using (MemoryStream central_directory_stream = new MemoryStream(central_directory_data)) using (CustomBinaryReader central_directory_reader = new CustomBinaryReader(central_directory_stream)) { // rebase current offset to 0 because we've copied data to a relative stream long central_directory_current_offset = 0; content_dictionary_count = central_directory_locator.DontentDictionaryCount; for (int i = 0; i < central_directory_locator.DontentDictionaryCount; i++) { var central_directory = ReadPK(central_directory_stream, central_directory_reader, central_directory_current_offset) as CentralDirectory; central_directory_current_offset = central_directory_stream.Position; //TODO async query //var file_structure = ReadPK(stream, reader, central_directory.extra.data_offset) as FileStructure; Files[central_directory.Filename] = new P4KFile(this, central_directory); //var file_data = ReadDataFromFileSection(stream, reader, file_offset.extra.file_data_offset, file_offset.extra.file_data_length); /*if(PopulateDirectoryCallbackFunc != null) * { * PopulateDirectoryCallbackFunc(i, central_directory_locator.content_dictionary_count); * }*/ current_index = i; } } }
public void Initialize(string filename, bool readOnly, bool logging = false) { Filename = filename; Logging = logging; mutex = new Mutex(); if (readOnly) { ReadOnly = true; fileStream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read); } else { try { ReadOnly = false; fileStream = File.Open(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None); } catch (IOException) { ReadOnly = true; fileStream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read); } } try { mutex.WaitOne(); customBinaryReader = new CustomBinaryReader(fileStream); customBinaryWriter = ReadOnly ? null : new CustomBinaryWriter(fileStream); var offset_central_directory_end = FindEndCentralDirectoryOffset(fileStream, customBinaryReader); central_directory_end = ReadPK(fileStream, customBinaryReader, offset_central_directory_end) as CentralDirectoryEnd; var offset_central_directory_locator_offset = offset_central_directory_end - 0x14; central_directory_locator_offset = ReadPK(fileStream, customBinaryReader, offset_central_directory_locator_offset) as CentralDirectoryLocatorOffset; var offset_central_directory_locator = central_directory_locator_offset.DirectoryLocatorOffset; central_directory_locator = ReadPK(fileStream, customBinaryReader, offset_central_directory_locator) as CentralDirectoryLocator; PopulateDirectory(fileStream, customBinaryReader, central_directory_locator); } finally { mutex.ReleaseMutex(); } if (Logging) { Console.WriteLine($"Finished loading {filename}"); } }
public object ReadPK(Stream stream, CustomBinaryReader reader, Int64 offset) { stream.Seek(offset, SeekOrigin.Begin); var magic = reader.ReadInt16(); if (magic != 0x4B50) { throw new Exception("Invalid PK offset"); } Signature signature = (Signature)reader.ReadInt16(); switch (signature) { case Signature.CentralDirectory: CentralDirectory centralDirectory = new CentralDirectory(stream, reader); if (Logging) { Console.WriteLine($"Found CentralDirectory {centralDirectory.Filename}"); } if (Logging) { Console.WriteLine($"Searching for FileStructure @{centralDirectory.Extra.data_offset.ToString("X")}"); } return(centralDirectory); case Signature.FileStructure: FileStructure fileStructure = new FileStructure(stream, reader); if (Logging) { Console.WriteLine($"Found FileStructure {fileStructure.Filename}"); } return(fileStructure); case Signature.CentralDirectoryLocator: CentralDirectoryLocator centralDirectoryLocator = new CentralDirectoryLocator(stream, reader); if (Logging) { Console.WriteLine($"Found CentralDirectoryLocator @{offset}"); } return(centralDirectoryLocator); case Signature.CentralDirectoryLocatorOffset: CentralDirectoryLocatorOffset centralDirectoryLocatorOffset = new CentralDirectoryLocatorOffset(stream, reader); if (Logging) { Console.WriteLine($"Found CentralDirectoryLocatorOffset @{offset}"); } return(centralDirectoryLocatorOffset); case Signature.CentralDirectoryEnd: CentralDirectoryEnd centralDirectoryEnd = new CentralDirectoryEnd(stream, reader); if (Logging) { Console.WriteLine($"Found CentralDirectoryEnd @{offset}"); } return(centralDirectoryEnd); default: throw new NotImplementedException(); } }