/// <summary> /// Commit changes /// </summary> private void Commit(IIMGArchiveEntryStream stream) { if (archive.AccessMode != EIMGArchiveAccessMode.Read) { archive.CommitEntry(this, stream); } }
/// <summary> /// Open IMG archive entry /// </summary> /// <returns>Stream to archive entry if successful, otherwise "null"</returns> public IIMGArchiveEntryStream Open() { IIMGArchiveEntryStream ret = null; try { if (available && archive.Stream.CanRead) { byte[] data = new byte[Length]; archive.Stream.Seek(Offset, SeekOrigin.Begin); archive.Stream.Read(data, 0, Length); ret = new IMGArchiveEntryStream(this); ret.Stream.Write(data, 0, data.Length); ret.Stream.Seek(0L, SeekOrigin.Begin); ret.OnIMGArchiveEntryClosed += (entry, stream) => (entry as IMGArchiveEntry)?.Commit(stream); } } catch (Exception e) { if (ret != null) { ret.Dispose(); ret = null; } Console.Error.WriteLine(e); } return(ret); }
public void CommitToIMGFile() { InitializeIMGArchives(); if (File.Exists(testDotThreeDotIMGFilePath)) { File.Delete(testDotThreeDotIMGFilePath); } File.Copy(testDotOneDotIMGFilePath, testDotThreeDotIMGFilePath); using (IIMGArchive archive = IMGFile.Open(testDotThreeDotIMGFilePath, EIMGArchiveAccessMode.Update)) { string entry_name = string.Empty; long entry_size = 0; Assert.IsNotNull(archive); IReadOnlyDictionary <string, IIMGArchiveEntry> entries = archive.Entries; int entry_count = entries.Count; Assert.Less(0, entry_count); foreach (IIMGArchiveEntry entry in entries.Values) { entry_name = entry.FullName; Debug.WriteLine($"Unpacking file \"{ entry.FullName }\""); if (!(Directory.Exists("test"))) { Directory.CreateDirectory("test"); } using (IIMGArchiveEntryStream img_archive_entry_stream = entry.Open()) { Assert.IsNotNull(img_archive_entry_stream); entry_size = img_archive_entry_stream.Stream.Length; Assert.AreEqual(entry_size, (long)(entry.Length)); img_archive_entry_stream.Stream.Seek(0L, SeekOrigin.End); using (BinaryWriter img_archive_entry_stream_binary_writer = new BinaryWriter(img_archive_entry_stream.Stream, archive.EntryNameEncoding, true)) { byte[] zero_bytes = new byte[2048]; img_archive_entry_stream_binary_writer.Write(zero_bytes); img_archive_entry_stream_binary_writer.Flush(); entry_size += zero_bytes.Length; } } break; } if (entry_count > 0) { entries = archive.Entries; Assert.AreEqual(entry_count, entries.Count); IIMGArchiveEntry another_entry = archive.GetEntry(entry_name); Assert.IsNotNull(another_entry); using (IIMGArchiveEntryStream img_archive_entry_stream = another_entry.Open()) { Assert.AreEqual(entry_size, img_archive_entry_stream.Stream.Length); Assert.AreEqual(entry_size, another_entry.Length); if (entry_size >= 2048) { entry_size -= 2048; img_archive_entry_stream.Stream.SetLength(entry_size); } } } } }
/// <summary> /// Write IMG archive entry /// </summary> /// <param name="tempArchive">Temporary IMG archive</param> /// <param name="newEntry">New IMG archive entry</param> /// <param name="stream">Stream</param> private void WriteEntry(IMGArchive tempArchive, IIMGArchiveEntry newEntry, Stream stream) { using (IIMGArchiveEntryStream temporary_img_archive_entry_stream = tempArchive.InternalEntries[newEntry.FullName.ToLower()].Open()) { byte[] temp_data = new byte[temporary_img_archive_entry_stream.Stream.Length]; temporary_img_archive_entry_stream.Stream.Read(temp_data, 0, temp_data.Length); stream.Write(temp_data, 0, temp_data.Length); } }
/// <summary> /// Extract IMG archive to directory /// </summary> /// <param name="sourceIMGArchiveFilePath">Source IMG archive file path</param> /// <param name="destinationDirectoryPath">Destination directory path</param> /// <param name="entryNameEncoding">Entry name encoding</param> public static void ExtractToDirectory(string sourceIMGArchiveFilePath, string destinationDirectoryPath, Encoding entryNameEncoding) { if (sourceIMGArchiveFilePath == null) { throw new ArgumentNullException(nameof(sourceIMGArchiveFilePath)); } if (destinationDirectoryPath == null) { throw new ArgumentNullException(nameof(destinationDirectoryPath)); } if (entryNameEncoding == null) { throw new ArgumentNullException(nameof(entryNameEncoding)); } IMGArchive img_archive = Open(sourceIMGArchiveFilePath, EIMGArchiveAccessMode.Read, entryNameEncoding) as IMGArchive; if (img_archive != null) { if (!(Directory.Exists(destinationDirectoryPath))) { Directory.CreateDirectory(destinationDirectoryPath); } foreach (IMGArchiveEntry img_archive_entry in img_archive.InternalEntries.Values) { string file_path = Path.Combine(destinationDirectoryPath, img_archive_entry.FullName); string directory_path = Path.GetDirectoryName(file_path); if (!(Directory.Exists(directory_path))) { Directory.CreateDirectory(directory_path); } using (FileStream img_archive_entry_file_stream = File.Open(file_path, FileMode.Create)) { using (IIMGArchiveEntryStream img_archive_entry_stream = img_archive_entry.Open()) { img_archive_entry_file_stream.Position = 0L; img_archive_entry_stream.Stream.Position = 0L; img_archive_entry_file_stream.CopyTo(img_archive_entry_stream.Stream); } } } } }
/// <summary> /// Commit IMG archive entry /// </summary> /// <param name="entry">IMG archive entry</param> /// <param name="entryStream">IMG archive entry stream</param> internal void CommitEntry(IIMGArchiveEntry entry, IIMGArchiveEntryStream entryStream) { try { if (AccessMode != EIMGArchiveAccessMode.Read) { string temporary_img_archive_path = Path.Combine(Path.GetTempPath(), $"{ Guid.NewGuid() }.img"); if (File.Exists(temporary_img_archive_path)) { File.Delete(temporary_img_archive_path); } using (FileStream temporary_img_archive_file_stream = File.Open(temporary_img_archive_path, FileMode.Create)) { Stream.Seek(0L, SeekOrigin.Begin); Stream.CopyTo(temporary_img_archive_file_stream); } using (IMGArchive temporary_img_archive = IMGFile.OpenRead(temporary_img_archive_path) as IMGArchive) { if (temporary_img_archive != null) { InternalEntries.Clear(); Stream.SetLength(0L); using (BinaryWriter stream_binary_writer = new BinaryWriter(Stream, EntryNameEncoding, true)) { int entry_count = temporary_img_archive.InternalEntries.Values.Count + ((entry == null) ? 0 : (entry.IsNewEntry ? 1 : 0)); int first_entry_offset = ((((entry_count * 32) % 2048) == 0) ? ((entry_count * 32) / 2048) : (((entry_count * 32) / 2048) + 1)); int current_entry_offset = first_entry_offset; List <IMGArchiveEntry> new_entries = new List <IMGArchiveEntry>(); Dictionary <string, IIMGArchiveEntry> temporary_entries = new Dictionary <string, IIMGArchiveEntry>(temporary_img_archive.InternalEntries); long missing_byte_count; stream_binary_writer.Write(IMGFile.SupportedIMGArchiveVersion); stream_binary_writer.Write((short)entry_count); if ((entry != null) && entry.IsNewEntry) { temporary_entries.Add(entry.FullName.ToLower(), new IMGArchiveEntry(temporary_img_archive, 0L, (int)(entryStream.Stream.Length), entry.FullName)); } foreach (KeyValuePair <string, IIMGArchiveEntry> temporary_entry in temporary_entries) { int entry_length = (int)((entry == null) ? (((temporary_entry.Value.Length % 2048L) == 0L) ? (temporary_entry.Value.Length / 2048L) : ((temporary_entry.Value.Length / 2048L) + 1L)) : ((entry.FullName.ToLower() == temporary_entry.Key) ? (((entryStream.Stream.Length % 2048L) == 0L) ? (entryStream.Stream.Length / 2048L) : ((entryStream.Stream.Length / 2048L) + 1)) : (((temporary_entry.Value.Length % 2048L) == 0L) ? (temporary_entry.Value.Length / 2048L) : ((temporary_entry.Value.Length / 2048L) + 1L)))); byte[] name_bytes_raw = EntryNameEncoding.GetBytes(temporary_entry.Value.FullName); byte[] name_bytes = new byte[24]; Array.Copy(name_bytes_raw, name_bytes, Math.Min(name_bytes_raw.Length, name_bytes.Length)); stream_binary_writer.Write(current_entry_offset); stream_binary_writer.Write((short)entry_length); stream_binary_writer.Write(name_bytes); IMGArchiveEntry new_entry = new IMGArchiveEntry(this, current_entry_offset * 2048, entry_length * 2048, temporary_entry.Value.FullName); new_entries.Add(new_entry); InternalEntries.Add(new_entry.FullName.ToLower(), new_entry); current_entry_offset += entry_length; } foreach (IMGArchiveEntry new_entry in new_entries) { stream_binary_writer.Flush(); missing_byte_count = new_entry.Offset - Stream.Length; if (missing_byte_count > 0L) { stream_binary_writer.Write(new byte[missing_byte_count]); } if (entry != null) { if (entry.FullName == new_entry.FullName) { byte[] data = new byte[entryStream.Stream.Length]; entryStream.Stream.Seek(0L, SeekOrigin.Begin); entryStream.Stream.Read(data, 0, data.Length); Stream.Write(data, 0, data.Length); } else { WriteEntry(temporary_img_archive, new_entry, Stream); } } else { WriteEntry(temporary_img_archive, new_entry, Stream); } } stream_binary_writer.Flush(); missing_byte_count = current_entry_offset - (Stream.Length / 2048); if (missing_byte_count > 0) { stream_binary_writer.Write(new byte[missing_byte_count]); } stream_binary_writer.Flush(); } } } if (File.Exists(temporary_img_archive_path)) { File.Delete(temporary_img_archive_path); } } } catch (Exception e) { Console.Error.WriteLine(e); } }