/// <summary> /// Open IMG archive entry /// </summary> /// <returns>Stream to archive entry if successful, otherwise "null"</returns> public Stream Open() { IMGArchiveEntryStream 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.Write(data, 0, data.Length); ret.Seek(0L, SeekOrigin.Begin); ret.OnClose += (entry, stream) => { if (entry != null) { entry.Commit(stream); } }; } } catch (Exception e) { if (ret != null) { ret.Dispose(); ret = null; } Console.Error.WriteLine(e); } return(ret); }
/// <summary> /// Commit IMG archive entry /// </summary> /// <param name="entry">IMG archive entry</param> /// <param name="stream">IMG archive entry stream</param> internal void CommitEntry(IMGArchiveEntry entry, IMGArchiveEntryStream stream) { try { if (mode != EIMGArchiveMode.Read) { string temp_path = Path.GetTempPath() + Guid.NewGuid().ToString() + ".img"; if (File.Exists(temp_path)) { File.Delete(temp_path); } using (FileStream temp_stream = File.Open(temp_path, FileMode.Create)) { this.stream.Seek(0L, SeekOrigin.Begin); byte[] buffer = new byte[2048]; int read_bytes = 0; while ((read_bytes = this.stream.Read(buffer, 0, buffer.Length)) > 0) { temp_stream.Write(buffer, 0, read_bytes); } } using (IMGArchive temp_archive = IMGFile.OpenRead(temp_path)) { entries.Clear(); this.stream.SetLength(0L); int entry_count = temp_archive.entries.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>(); byte[] header_bytes = new byte[] { 0x56, 0x45, 0x52, 0x32, (byte)(entry_count & 0xFF), (byte)((entry_count >> 8) & 0xFF), 0x0, 0x0 }; this.stream.Write(header_bytes, 0, header_bytes.Length); Dictionary <string, IMGArchiveEntry> temp_entries = new Dictionary <string, IMGArchiveEntry>(temp_archive.entries); if (entry != null) { if (entry.IsNewEntry) { temp_entries.Add(entry.FullName.ToLower(), new IMGArchiveEntry(temp_archive, 0L, (int)(stream.Length), entry.FullName)); } } foreach (KeyValuePair <string, IMGArchiveEntry> temp_entry in temp_entries) { int entry_length = (int)((entry == null) ? (((temp_entry.Value.Length % 2048L) == 0L) ? (temp_entry.Value.Length / 2048L) : ((temp_entry.Value.Length / 2048L) + 1L)) : ((entry.FullName.ToLower() == temp_entry.Key) ? (((stream.Length % 2048L) == 0L) ? (stream.Length / 2048L) : ((stream.Length / 2048L) + 1)) : (((temp_entry.Value.Length % 2048L) == 0L) ? (temp_entry.Value.Length / 2048L) : ((temp_entry.Value.Length / 2048L) + 1L)))); byte[] entry_offset_bytes = new byte[] { (byte)(current_entry_offset & 0xFF), (byte)((current_entry_offset >> 8) & 0xFF), (byte)((current_entry_offset >> 16) & 0xFF), (byte)((current_entry_offset >> 24) & 0xFF) }; byte[] entry_length_bytes = new byte[] { (byte)(entry_length & 0xFF), (byte)((entry_length >> 8) & 0xFF), 0x0, 0x0 }; byte[] name_bytes_raw = entryNameEncoding.GetBytes(temp_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)); this.stream.Write(entry_offset_bytes, 0, entry_offset_bytes.Length); this.stream.Write(entry_length_bytes, 0, entry_length_bytes.Length); this.stream.Write(name_bytes, 0, name_bytes.Length); IMGArchiveEntry new_entry = new IMGArchiveEntry(this, current_entry_offset * 2048, entry_length * 2048, temp_entry.Value.FullName); new_entries.Add(new_entry); entries.Add(new_entry.FullName.ToLower(), new_entry); current_entry_offset += entry_length; } foreach (IMGArchiveEntry new_entry in new_entries) { while (this.stream.Length < new_entry.Offset) { this.stream.WriteByte(0); } if (entry != null) { if (entry.FullName == new_entry.FullName) { byte[] data = new byte[stream.Length]; stream.Seek(0L, SeekOrigin.Begin); stream.Read(data, 0, data.Length); this.stream.Write(data, 0, data.Length); } else { WriteEntry(temp_archive, new_entry, this.stream); } } else { WriteEntry(temp_archive, new_entry, this.stream); } } while ((this.stream.Length / 2048) < current_entry_offset) { this.stream.WriteByte(0); } } if (File.Exists(temp_path)) { File.Delete(temp_path); } } } catch (Exception e) { Console.Error.WriteLine(e.Message); } }