internal void Read() { if (!IsAr(Stream, Diagnostics)) { return; } Span <byte> entryBuffer = stackalloc byte[ArFile.FileEntrySizeInBytes]; _futureHeaders = null; while (TryReadFileEntry(entryBuffer, out var fileEntry)) { if (fileEntry is ArLongNamesTable arGnuFutureHeaders) { if (_futureHeaders != null) { Diagnostics.Error(DiagnosticId.AR_ERR_InvalidDuplicatedFutureHeadersTable, $"Invalid duplicated future headers table found at offset {fileEntry.Offset} while another table was already found at offset {_futureHeaders.Offset}. This file is invalid."); break; } _futureHeaders = arGnuFutureHeaders; } else { ArArchiveFile.AddFile(fileEntry); } } if (Diagnostics.HasErrors) { return; } // Perform a pass after all entries have been read foreach (var arFileEntry in ArArchiveFile.Files) { arFileEntry.AfterReadInternal(this.Diagnostics); } }
/// <inheritdoc /> public override bool TryUpdateLayout(DiagnosticBag diagnostics) { if (diagnostics == null) { throw new ArgumentNullException(nameof(diagnostics)); } // Check first that we have a valid object file var localDiagnostics = new DiagnosticBag(); Verify(localDiagnostics); // If we have any any errors if (localDiagnostics.HasErrors) { localDiagnostics.CopyTo(diagnostics); return(false); } if (Kind == ArArchiveKind.GNU) { if (LongNamesTable == null) { LongNamesTable = new ArLongNamesTable { Parent = this }; } if (SymbolTable != null && SymbolTable.Index == 0) { LongNamesTable.Index = 1; } else { LongNamesTable.Index = 1; } // Reset the calculation of the size of headers LongNamesTable.SizeKind = ValueKind.Auto; } else { // Don't use headers LongNamesTable = null; } ulong size = (ulong)Magic.Length; // Clear the internal names foreach (var entry in Files) { entry.InternalName = null; } for (var i = 0; i < Files.Count; i++) { var entry = Files[i]; // If we have a GNU headers and they are required, add them to the offset and size if (LongNamesTable != null && LongNamesTable.Index == i) { var headerSize = LongNamesTable.Size; if (headerSize > 0) { LongNamesTable.Offset = size; size += ArFile.FileEntrySizeInBytes + LongNamesTable.Size; if ((size & 1) != 0) { size++; } } } entry.Offset = size; size += ArFile.FileEntrySizeInBytes + entry.Size; if ((size & 1) != 0) { size++; } } return(true); }
public void UpdateLayout(DiagnosticBag diagnostics) { if (diagnostics == null) { throw new ArgumentNullException(nameof(diagnostics)); } Size = 0; if (Kind == ArArchiveKind.GNU) { if (LongNamesTable == null) { LongNamesTable = new ArLongNamesTable { Parent = this }; } if (SymbolTable != null && SymbolTable.Index == 0) { LongNamesTable.Index = 1; } else { LongNamesTable.Index = 1; } } else { // Don't use headers LongNamesTable = null; } ulong size = (ulong)Magic.Length; // Clear the internal names foreach (var entry in Files) { entry.InternalName = null; } for (var i = 0; i < Files.Count; i++) { var entry = Files[i]; entry.UpdateLayout(diagnostics); if (diagnostics.HasErrors) { return; } // If we have a GNU headers and they are required, add them to the offset and size if (LongNamesTable != null && LongNamesTable.Index == i) { LongNamesTable.UpdateLayout(diagnostics); if (diagnostics.HasErrors) { return; } var headerSize = LongNamesTable.Size; if (headerSize > 0) { LongNamesTable.Offset = size; size += ArFile.FileEntrySizeInBytes + LongNamesTable.Size; if ((size & 1) != 0) { size++; } } } entry.Offset = size; size += ArFile.FileEntrySizeInBytes + entry.Size; if ((size & 1) != 0) { size++; } } Size = size; }