// 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); }