public override ILoadedImage Load(Address?addrLoad) { var rdr = new ByteImageReader(RawImage); ReadHeader(rdr); var archive = new ArArchive(this.ImageLocation); ReadFiles(rdr, archive); return(archive); }
private void ReadFiles(ByteImageReader rdr, ArArchive archive) { for (; ;) { var header = ArFileHeader.Load(rdr); if (header == null) { return; } ReadFile(header, rdr, archive); } }
private void ReadFile(ArFileHeader fileHeader, ByteImageReader rdr, ArArchive archive) { if (!int.TryParse(fileHeader.FileSize, out int dataSize)) { throw new BadImageFormatException("Invalid archive file header."); } if (dataSize + rdr.Offset > rdr.Bytes.Length) { throw new BadImageFormatException("The archive file is corrupt."); } string name = fileHeader.Name; if (name.StartsWith("// ")) { throw new NotImplementedException("Extended file names not implemented yet."); } else if (name.StartsWith("/ ") || name.StartsWith("__.SYMDEF")) { // System V symbol lookup table. var symbolData = rdr.ReadBytes(dataSize); ReadSymbolTable(symbolData); return; } else if (name.StartsWith("#1/ ")) { // File name length follows #1/ as decimal digits. // This variant is used by Mac and some versions of BSD. var fileNameLength = Convert.ToInt32(name + 3); long fileDataOffset = rdr.Offset + fileNameLength; name = Encoding.ASCII.GetString(rdr.ReadBytes(fileNameLength)); if (dataSize > fileNameLength) { // The length of the name is included in the dataSize. dataSize -= fileNameLength; } rdr.Offset = fileDataOffset; } else { // Ordinary short name char[] charsToTrim = { '/', ' ' }; name = name.TrimEnd(charsToTrim); } archive.AddFile(name, (a, p, name) => new ArFile(a, p, name, rdr, rdr.Offset, dataSize)); rdr.Offset += dataSize; AlignReader(rdr); }