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);
            }
        }
Esempio n. 2
0
        /// <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);
        }
Esempio n. 3
0
        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;
        }