using System.IO; using System.Text; using Aaru.CommonTypes.Enums; using Aaru.CommonTypes.Interfaces; using Aaru.Helpers; namespace Aaru.Archives; public sealed partial class Amg { #region IArchive Members /// public ErrorNumber Open(IFilter filter, Encoding encoding) { encoding ??= Encoding.ASCII; if(filter.DataForkLength < Marshal.SizeOf()) return ErrorNumber.InvalidArgument; _stream = filter.GetDataForkStream(); _stream.Position = 0; var hdr = new byte[Marshal.SizeOf()]; _stream.ReadExactly(hdr, 0, hdr.Length); ArcHeader header = Marshal.ByteArrayToStructureLittleEndian(hdr); // Not a valid magic if(header.magic != ARC_MAGIC) return ErrorNumber.InvalidArgument; // Skip comment _stream.Position += header.commentLength; int fileHeaderLen = Marshal.SizeOf(); _files = []; while(_stream.Position + fileHeaderLen < _stream.Length) { var fileHdr = new byte[fileHeaderLen]; _stream.ReadExactly(fileHdr, 0, fileHdr.Length); FileHeader fh = Marshal.ByteArrayToStructureLittleEndian(fileHdr); // Not a valid file magic if(fh.magic != FILE_MAGIC) break; var entry = new FileEntry { Attributes = (FileAttributes)fh.attr, Compressed = (uint)(fh.compressed - fh.pathLength - fh.commentLength - fileHeaderLen), Crc = fh.crc, Flags = fh.flags, LastWrite = DateHandlers.DosToDateTime(fh.date, fh.time), Uncompressed = fh.uncompressed, Filename = StringHandlers.CToString(fh.filename, encoding) }; string extension = StringHandlers.CToString(fh.extension, encoding); if(!string.IsNullOrEmpty(extension)) entry.Filename += "." + extension; if(fh.pathLength > 0) { var buffer = new byte[fh.pathLength]; _stream.ReadExactly(buffer, 0, buffer.Length); string path = StringHandlers.CToString(buffer, encoding); path = path.Replace('\\', Path.DirectorySeparatorChar); entry.Filename = Path.Combine(path, entry.Filename); } if(fh.commentLength > 0) { var buffer = new byte[fh.commentLength]; _stream.ReadExactly(buffer, 0, buffer.Length); entry.Comment = StringHandlers.CToString(buffer, encoding); } entry.Offset = _stream.Position; _files.Add(entry); // Skip compressed data _stream.Position += entry.Compressed; } Opened = true; return ErrorNumber.NoError; } /// public void Close() { // Already closed if(!Opened) return; _stream?.Close(); _files?.Clear(); _stream = null; Opened = false; } #endregion }