// Extract a file from our archive
 public void ExtractFile(TARMetaData entry, string output)
 {
     // Check we're extracting a normal file
     if (entry.GetTypeFlags() == TARMetaData.TypeFlags.NormalFile)
     {
         //Create any directories as required
         string directory = Path.GetDirectoryName(output);
         if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
         {
             Directory.CreateDirectory(directory);
         }
         {
             // Open relevant streams and extract
             using (var stream = File.OpenRead(Filename))
                 if (isCompressed)
                 {
                     using (var gzip = new GZipStream(stream, CompressionMode.Decompress))
                         ExtractFile(entry, gzip, output);
                 }
                 else
                 {
                     ExtractFile(entry, stream, output);
                 }
         }
     }
 }
    // Load a TAR archive from a Stream
    private void LoadFromStream(Stream stream)
    {
        // TAR Entry MetaData is stored in 512 byte buffers
        var  metaDataBuffer = new byte[512];
        int  readCount      = 0;
        long bufferPosition = 0;

        do
        {
            // Read 512 bytes
            readCount = stream.Read(metaDataBuffer, 0, 512);

            // If we were successful
            if (readCount >= 512)
            {
                // Unpack the MetaData and update the buffer positions
                TARMetaData fileMetaData = new TARMetaData(metaDataBuffer);
                fileMetaData.MetaDataBufferPositionStart = bufferPosition;
                bufferPosition += readCount;
                fileMetaData.FileBufferPositionStart = bufferPosition;

                // If the entry has file data following it
                if (fileMetaData.GetTypeFlags() == TARMetaData.TypeFlags.NormalFile ||
                    fileMetaData.GetTypeFlags() == TARMetaData.TypeFlags.ExtendedHeaderWithMetaDataForNextFileInArchive)
                {
                    // Seek past the data
                    StreamSeek(stream, fileMetaData.fileSize);
                    bufferPosition += fileMetaData.fileSize;

                    // Make sure we seek past by a multiple of 512
                    if (fileMetaData.fileSize % 512 > 0)
                    {
                        long offset = 512 - (fileMetaData.fileSize % 512);
                        StreamSeek(stream, offset);
                        bufferPosition += offset;
                    }
                }

                // Store the meta data
                Entries.Add(fileMetaData);
            }

            //Loop until we've run out of entries
        } while (readCount >= 512);
    }