예제 #1
0
        private const string UstarPrefixFormat = "{0}/{1}"; // "prefix/name"

        // Attempts to read all the fields of the next header.
        // Throws if end of stream is reached or if any data type conversion fails.
        // Returns true if all the attributes were read successfully, false otherwise.
        internal bool TryGetNextHeader(Stream archiveStream, bool copyData)
        {
            // The four supported formats have a header that fits in the default record size
            byte[] rented = ArrayPool <byte> .Shared.Rent(minimumLength : TarHelpers.RecordSize);

            Span <byte> buffer = rented.AsSpan(0, TarHelpers.RecordSize); // minimumLength means the array could've been larger

            buffer.Clear();                                               // Rented arrays aren't clean

            TarHelpers.ReadOrThrow(archiveStream, buffer);

            try
            {
                // Confirms if v7 or pax, or tentatively selects ustar
                if (!TryReadCommonAttributes(buffer))
                {
                    return(false);
                }

                // Confirms if gnu, or tentatively selects ustar
                ReadMagicAttribute(buffer);

                if (_format != TarFormat.V7)
                {
                    // Confirms if gnu
                    ReadVersionAttribute(buffer);

                    // Fields that ustar, pax and gnu share identically
                    ReadPosixAndGnuSharedAttributes(buffer);

                    Debug.Assert(_format is TarFormat.Ustar or TarFormat.Pax or TarFormat.Gnu);
                    if (_format == TarFormat.Ustar)
                    {
                        ReadUstarAttributes(buffer);
                    }
                    else if (_format == TarFormat.Gnu)
                    {
                        ReadGnuAttributes(buffer);
                    }
                    // In PAX, there is nothing to read in this section (empty space)
                }

                ProcessDataBlock(archiveStream, copyData);

                return(true);
            }
            finally
            {
                ArrayPool <byte> .Shared.Return(rented);
            }
        }