ICSharpCode.SharpZipLib.Tar.TarOutputStream - Coverage Report

# Summary

Class: | ICSharpCode.SharpZipLib.Tar.TarOutputStream
Assembly: | ICSharpCode.SharpZipLib
File(s): | C:\Users\Neil\Documents\Visual Studio 2015\Projects\icsharpcode\SZL_master\ICSharpCode.SharpZipLib\Tar\TarOutputStream.cs
Covered lines: | 64
Uncovered lines: | 54
Coverable lines: | 118
Total lines: | 442
Line coverage: | 54.2%
Branch coverage: | 58.3%

# Metrics

Method | Cyclomatic Complexity | Sequence Coverage | Branch Coverage
--- | --- | --- | ---
.ctor(...) | 1 | 100 | 100
.ctor(...) | 2 | 87.5 | 66.67
Seek(...) | 1 | 0 | 0
SetLength(...) | 1 | 0 | 0
ReadByte() | 1 | 0 | 0
Read(...) | 1 | 0 | 0
Flush() | 1 | 100 | 100
Finish() | 2 | 100 | 100
Close() | 2 | 100 | 66.67
GetRecordSize() | 1 | 0 | 0
PutNextEntry(...) | 5 | 26.92 | 44.44
CloseEntry() | 3 | 77.78 | 60
WriteByte(...) | 1 | 100 | 100
Write(...) | 10 | 59.46 | 68.42
WriteEofBlock() | 1 | 100 | 100

# File(s)

## C:\Users\Neil\Documents\Visual Studio 2015\Projects\icsharpcode\SZL_master\ICSharpCode.SharpZipLib\Tar\TarOutputStream.cs

| # | Line |  | Line coverage
--- | --- | --- | --- | ---
|  | `1` |  | `using System;`
|  | `2` |  | `using System.IO;`
|  | `3` |  | ``
|  | `4` |  | `namespace ICSharpCode.SharpZipLib.Tar`
|  | `5` |  | `{`
|  | `6` |  | `/// <summary>`
|  | `7` |  | `/// The TarOutputStream writes a UNIX tar archive as an OutputStream.`
|  | `8` |  | `/// Methods are provided to put entries, and then write their contents`
|  | `9` |  | `/// by writing to this stream using write().`
|  | `10` |  | `/// </summary>`
|  | `11` |  | `/// public`
|  | `12` |  | `public class TarOutputStream : Stream`
|  | `13` |  | `{`
|  | `14` |  | `#region Constructors`
|  | `15` |  | `/// <summary>`
|  | `16` |  | `/// Construct TarOutputStream using default block factor`
|  | `17` |  | `/// </summary>`
|  | `18` |  | `/// <param name="outputStream">stream to write to</param>`
|  | `19` |  | `public TarOutputStream(Stream outputStream)`
| 3 | `20` |  | `: this(outputStream, TarBuffer.DefaultBlockFactor)`
|  | `21` |  | `{`
| 3 | `22` |  | `}`
|  | `23` |  | ``
|  | `24` |  | `/// <summary>`
|  | `25` |  | `/// Construct TarOutputStream with user specified block factor`
|  | `26` |  | `/// </summary>`
|  | `27` |  | `/// <param name="outputStream">stream to write to</param>`
|  | `28` |  | `/// <param name="blockFactor">blocking factor</param>`
| 73 | `29` |  | `public TarOutputStream(Stream outputStream, int blockFactor)`
|  | `30` |  | `{`
| 73 | `31` |  | `if (outputStream == null) {`
| 0 | `32` |  | `throw new ArgumentNullException(nameof(outputStream));`
|  | `33` |  | `}`
|  | `34` |  | ``
| 73 | `35` |  | `this.outputStream = outputStream;`
| 73 | `36` |  | `buffer = TarBuffer.CreateOutputTarBuffer(outputStream, blockFactor);`
|  | `37` |  | ``
| 73 | `38` |  | `assemblyBuffer = new byte[TarBuffer.BlockSize];`
| 73 | `39` |  | `blockBuffer = new byte[TarBuffer.BlockSize];`
| 73 | `40` |  | `}`
|  | `41` |  | `#endregion`
|  | `42` |  | ``
|  | `43` |  | `/// <summary>`
|  | `44` |  | `/// Get/set flag indicating ownership of the underlying stream.`
|  | `45` |  | `/// When the flag is true <see cref="Close"></see> will close the underlying stream also.`
|  | `46` |  | `/// </summary>`
|  | `47` |  | `public bool IsStreamOwner {`
| 0 | `48` |  | `get { return buffer.IsStreamOwner; }`
| 2 | `49` |  | `set { buffer.IsStreamOwner = value; }`
|  | `50` |  | `}`
|  | `51` |  | ``
|  | `52` |  | `/// <summary>`
|  | `53` |  | `/// true if the stream supports reading; otherwise, false.`
|  | `54` |  | `/// </summary>`
|  | `55` |  | `public override bool CanRead {`
|  | `56` |  | `get {`
| 0 | `57` |  | `return outputStream.CanRead;`
|  | `58` |  | `}`
|  | `59` |  | `}`
|  | `60` |  | ``
|  | `61` |  | `/// <summary>`
|  | `62` |  | `/// true if the stream supports seeking; otherwise, false.`
|  | `63` |  | `/// </summary>`
|  | `64` |  | `public override bool CanSeek {`
|  | `65` |  | `get {`
| 0 | `66` |  | `return outputStream.CanSeek;`
|  | `67` |  | `}`
|  | `68` |  | `}`
|  | `69` |  | ``
|  | `70` |  | `/// <summary>`
|  | `71` |  | `/// true if stream supports writing; otherwise, false.`
|  | `72` |  | `/// </summary>`
|  | `73` |  | `public override bool CanWrite {`
|  | `74` |  | `get {`
| 0 | `75` |  | `return outputStream.CanWrite;`
|  | `76` |  | `}`
|  | `77` |  | `}`
|  | `78` |  | ``
|  | `79` |  | `/// <summary>`
|  | `80` |  | `/// length of stream in bytes`
|  | `81` |  | `/// </summary>`
|  | `82` |  | `public override long Length {`
|  | `83` |  | `get {`
| 0 | `84` |  | `return outputStream.Length;`
|  | `85` |  | `}`
|  | `86` |  | `}`
|  | `87` |  | ``
|  | `88` |  | `/// <summary>`
|  | `89` |  | `/// gets or sets the position within the current stream.`
|  | `90` |  | `/// </summary>`
|  | `91` |  | `public override long Position {`
|  | `92` |  | `get {`
| 0 | `93` |  | `return outputStream.Position;`
|  | `94` |  | `}`
|  | `95` |  | `set {`
| 0 | `96` |  | `outputStream.Position = value;`
| 0 | `97` |  | `}`
|  | `98` |  | `}`
|  | `99` |  | ``
|  | `100` |  | `/// <summary>`
|  | `101` |  | `/// set the position within the current stream`
|  | `102` |  | `/// </summary>`
|  | `103` |  | `/// <param name="offset">The offset relative to the <paramref name="origin"/> to seek to</param>`
|  | `104` |  | `/// <param name="origin">The <see cref="SeekOrigin"/> to seek from.</param>`
|  | `105` |  | `/// <returns>The new position in the stream.</returns>`
|  | `106` |  | `public override long Seek(long offset, SeekOrigin origin)`
|  | `107` |  | `{`
| 0 | `108` |  | `return outputStream.Seek(offset, origin);`
|  | `109` |  | `}`
|  | `110` |  | ``
|  | `111` |  | `/// <summary>`
|  | `112` |  | `/// Set the length of the current stream`
|  | `113` |  | `/// </summary>`
|  | `114` |  | `/// <param name="value">The new stream length.</param>`
|  | `115` |  | `public override void SetLength(long value)`
|  | `116` |  | `{`
| 0 | `117` |  | `outputStream.SetLength(value);`
| 0 | `118` |  | `}`
|  | `119` |  | ``
|  | `120` |  | `/// <summary>`
|  | `121` |  | `/// Read a byte from the stream and advance the position within the stream`
|  | `122` |  | `/// by one byte or returns -1 if at the end of the stream.`
|  | `123` |  | `/// </summary>`
|  | `124` |  | `/// <returns>The byte value or -1 if at end of stream</returns>`
|  | `125` |  | `public override int ReadByte()`
|  | `126` |  | `{`
| 0 | `127` |  | `return outputStream.ReadByte();`
|  | `128` |  | `}`
|  | `129` |  | ``
|  | `130` |  | `/// <summary>`
|  | `131` |  | `/// read bytes from the current stream and advance the position within the`
|  | `132` |  | `/// stream by the number of bytes read.`
|  | `133` |  | `/// </summary>`
|  | `134` |  | `/// <param name="buffer">The buffer to store read bytes in.</param>`
|  | `135` |  | `/// <param name="offset">The index into the buffer to being storing bytes at.</param>`
|  | `136` |  | `/// <param name="count">The desired number of bytes to read.</param>`
|  | `137` |  | `/// <returns>The total number of bytes read, or zero if at the end of the stream.`
|  | `138` |  | `/// The number of bytes may be less than the <paramref name="count">count</paramref>`
|  | `139` |  | `/// requested if data is not avialable.</returns>`
|  | `140` |  | `public override int Read(byte[] buffer, int offset, int count)`
|  | `141` |  | `{`
| 0 | `142` |  | `return outputStream.Read(buffer, offset, count);`
|  | `143` |  | `}`
|  | `144` |  | ``
|  | `145` |  | `/// <summary>`
|  | `146` |  | `/// All buffered data is written to destination`
|  | `147` |  | `/// </summary>`
|  | `148` |  | `public override void Flush()`
|  | `149` |  | `{`
| 1 | `150` |  | `outputStream.Flush();`
| 1 | `151` |  | `}`
|  | `152` |  | ``
|  | `153` |  | `/// <summary>`
|  | `154` |  | `/// Ends the TAR archive without closing the underlying OutputStream.`
|  | `155` |  | `/// The result is that the EOF block of nulls is written.`
|  | `156` |  | `/// </summary>`
|  | `157` |  | `public void Finish()`
|  | `158` |  | `{`
| 73 | `159` |  | `if (IsEntryOpen) {`
| 5 | `160` |  | `CloseEntry();`
|  | `161` |  | `}`
| 73 | `162` |  | `WriteEofBlock();`
| 73 | `163` |  | `}`
|  | `164` |  | ``
|  | `165` |  | `/// <summary>`
|  | `166` |  | `/// Ends the TAR archive and closes the underlying OutputStream.`
|  | `167` |  | `/// </summary>`
|  | `168` |  | `/// <remarks>This means that Finish() is called followed by calling the`
|  | `169` |  | `/// TarBuffer's Close().</remarks>`
|  | `170` |  | `public override void Close()`
|  | `171` |  | `{`
| 73 | `172` |  | `if (!isClosed) {`
| 73 | `173` |  | `isClosed = true;`
| 73 | `174` |  | `Finish();`
| 73 | `175` |  | `buffer.Close();`
|  | `176` |  | `}`
| 73 | `177` |  | `}`
|  | `178` |  | ``
|  | `179` |  | `/// <summary>`
|  | `180` |  | `/// Get the record size being used by this stream's TarBuffer.`
|  | `181` |  | `/// </summary>`
|  | `182` |  | `public int RecordSize {`
| 1 | `183` |  | `get { return buffer.RecordSize; }`
|  | `184` |  | `}`
|  | `185` |  | ``
|  | `186` |  | `/// <summary>`
|  | `187` |  | `/// Get the record size being used by this stream's TarBuffer.`
|  | `188` |  | `/// </summary>`
|  | `189` |  | `/// <returns>`
|  | `190` |  | `/// The TarBuffer record size.`
|  | `191` |  | `/// </returns>`
|  | `192` |  | `[Obsolete("Use RecordSize property instead")]`
|  | `193` |  | `public int GetRecordSize()`
|  | `194` |  | `{`
| 0 | `195` |  | `return buffer.RecordSize;`
|  | `196` |  | `}`
|  | `197` |  | ``
|  | `198` |  | `/// <summary>`
|  | `199` |  | `/// Get a value indicating wether an entry is open, requiring more data to be written.`
|  | `200` |  | `/// </summary>`
|  | `201` |  | `bool IsEntryOpen {`
| 73 | `202` |  | `get { return (currBytes < currSize); }`
|  | `203` |  | ``
|  | `204` |  | `}`
|  | `205` |  | ``
|  | `206` |  | `/// <summary>`
|  | `207` |  | `/// Put an entry on the output stream. This writes the entry's`
|  | `208` |  | `/// header and positions the output stream for writing`
|  | `209` |  | `/// the contents of the entry. Once this method is called, the`
|  | `210` |  | `/// stream is ready for calls to write() to write the entry's`
|  | `211` |  | `/// contents. Once the contents are written, closeEntry()`
|  | `212` |  | `/// <B>MUST</B> be called to ensure that all buffered data`
|  | `213` |  | `/// is completely written to the output stream.`
|  | `214` |  | `/// </summary>`
|  | `215` |  | `/// <param name="entry">`
|  | `216` |  | `/// The TarEntry to be written to the archive.`
|  | `217` |  | `/// </param>`
|  | `218` |  | `public void PutNextEntry(TarEntry entry)`
|  | `219` |  | `{`
| 70 | `220` |  | `if (entry == null) {`
| 0 | `221` |  | `throw new ArgumentNullException(nameof(entry));`
|  | `222` |  | `}`
|  | `223` |  | ``
| 70 | `224` |  | `if (entry.TarHeader.Name.Length > TarHeader.NAMELEN) {`
| 0 | `225` |  | `var longHeader = new TarHeader();`
| 0 | `226` |  | `longHeader.TypeFlag = TarHeader.LF_GNU_LONGNAME;`
| 0 | `227` |  | `longHeader.Name = longHeader.Name + "././@LongLink";`
| 0 | `228` |  | `longHeader.Mode = 420;//644 by default`
| 0 | `229` |  | `longHeader.UserId = entry.UserId;`
| 0 | `230` |  | `longHeader.GroupId = entry.GroupId;`
| 0 | `231` |  | `longHeader.GroupName = entry.GroupName;`
| 0 | `232` |  | `longHeader.UserName = entry.UserName;`
| 0 | `233` |  | `longHeader.LinkName = "";`
| 0 | `234` |  | `longHeader.Size = entry.TarHeader.Name.Length + 1; // Plus one to avoid dropping last char`
|  | `235` |  | ``
| 0 | `236` |  | `longHeader.WriteHeader(blockBuffer);`
| 0 | `237` |  | `buffer.WriteBlock(blockBuffer); // Add special long filename header block`
|  | `238` |  | ``
| 0 | `239` |  | `int nameCharIndex = 0;`
|  | `240` |  | ``
| 0 | `241` |  | `while (nameCharIndex < entry.TarHeader.Name.Length) {`
| 0 | `242` |  | `Array.Clear(blockBuffer, 0, blockBuffer.Length);`
| 0 | `243` |  | `TarHeader.GetAsciiBytes(entry.TarHeader.Name, nameCharIndex, this.blockBuffer, 0, TarBuffer.BlockSize);`
| 0 | `244` |  | `nameCharIndex += TarBuffer.BlockSize;`
| 0 | `245` |  | `buffer.WriteBlock(blockBuffer);`
|  | `246` |  | `}`
|  | `247` |  | `}`
|  | `248` |  | ``
| 70 | `249` |  | `entry.WriteEntryHeader(blockBuffer);`
| 70 | `250` |  | `buffer.WriteBlock(blockBuffer);`
|  | `251` |  | ``
| 70 | `252` |  | `currBytes = 0;`
|  | `253` |  | ``
| 70 | `254` |  | `currSize = entry.IsDirectory ? 0 : entry.Size;`
| 70 | `255` |  | `}`
|  | `256` |  | ``
|  | `257` |  | `/// <summary>`
|  | `258` |  | `/// Close an entry. This method MUST be called for all file`
|  | `259` |  | `/// entries that contain data. The reason is that we must`
|  | `260` |  | `/// buffer data written to the stream in order to satisfy`
|  | `261` |  | `/// the buffer's block based writes. Thus, there may be`
|  | `262` |  | `/// data fragments still being assembled that must be written`
|  | `263` |  | `/// to the output stream before this entry is closed and the`
|  | `264` |  | `/// next entry written.`
|  | `265` |  | `/// </summary>`
|  | `266` |  | `public void CloseEntry()`
|  | `267` |  | `{`
| 5 | `268` |  | `if (assemblyBufferLength > 0) {`
| 5 | `269` |  | `Array.Clear(assemblyBuffer, assemblyBufferLength, assemblyBuffer.Length - assemblyBufferLength);`
|  | `270` |  | ``
| 5 | `271` |  | `buffer.WriteBlock(assemblyBuffer);`
|  | `272` |  | ``
| 5 | `273` |  | `currBytes += assemblyBufferLength;`
| 5 | `274` |  | `assemblyBufferLength = 0;`
|  | `275` |  | `}`
|  | `276` |  | ``
| 5 | `277` |  | `if (currBytes < currSize) {`
| 0 | `278` |  | `string errorText = string.Format(`
| 0 | `279` |  | `"Entry closed at '{0}' before the '{1}' bytes specified in the header were written",`
| 0 | `280` |  | `currBytes, currSize);`
| 0 | `281` |  | `throw new TarException(errorText);`
|  | `282` |  | `}`
| 5 | `283` |  | `}`
|  | `284` |  | ``
|  | `285` |  | `/// <summary>`
|  | `286` |  | `/// Writes a byte to the current tar archive entry.`
|  | `287` |  | `/// This method simply calls Write(byte[], int, int).`
|  | `288` |  | `/// </summary>`
|  | `289` |  | `/// <param name="value">`
|  | `290` |  | `/// The byte to be written.`
|  | `291` |  | `/// </param>`
|  | `292` |  | `public override void WriteByte(byte value)`
|  | `293` |  | `{`
| 45 | `294` |  | `Write(new byte[] { value }, 0, 1);`
| 45 | `295` |  | `}`
|  | `296` |  | ``
|  | `297` |  | `/// <summary>`
|  | `298` |  | `/// Writes bytes to the current tar archive entry. This method`
|  | `299` |  | `/// is aware of the current entry and will throw an exception if`
|  | `300` |  | `/// you attempt to write bytes past the length specified for the`
|  | `301` |  | `/// current entry. The method is also (painfully) aware of the`
|  | `302` |  | `/// record buffering required by TarBuffer, and manages buffers`
|  | `303` |  | `/// that are not a multiple of recordsize in length, including`
|  | `304` |  | `/// assembling records from small buffers.`
|  | `305` |  | `/// </summary>`
|  | `306` |  | `/// <param name = "buffer">`
|  | `307` |  | `/// The buffer to write to the archive.`
|  | `308` |  | `/// </param>`
|  | `309` |  | `/// <param name = "offset">`
|  | `310` |  | `/// The offset in the buffer from which to get bytes.`
|  | `311` |  | `/// </param>`
|  | `312` |  | `/// <param name = "count">`
|  | `313` |  | `/// The number of bytes to write.`
|  | `314` |  | `/// </param>`
|  | `315` |  | `public override void Write(byte[] buffer, int offset, int count)`
|  | `316` |  | `{`
| 4087 | `317` |  | `if (buffer == null) {`
| 0 | `318` |  | `throw new ArgumentNullException(nameof(buffer));`
|  | `319` |  | `}`
|  | `320` |  | ``
| 4087 | `321` |  | `if (offset < 0) {`
| 0 | `322` |  | `throw new ArgumentOutOfRangeException(nameof(offset), "Cannot be negative");`
|  | `323` |  | `}`
|  | `324` |  | ``
| 4087 | `325` |  | `if (buffer.Length - offset < count) {`
| 0 | `326` |  | `throw new ArgumentException("offset and count combination is invalid");`
|  | `327` |  | `}`
|  | `328` |  | ``
| 4087 | `329` |  | `if (count < 0) {`
| 0 | `330` |  | `throw new ArgumentOutOfRangeException(nameof(count), "Cannot be negative");`
|  | `331` |  | `}`
|  | `332` |  | ``
| 4087 | `333` |  | `if ((currBytes + count) > currSize) {`
| 0 | `334` |  | `string errorText = string.Format("request to write '{0}' bytes exceeds size in header of '{1}' bytes",`
| 0 | `335` |  | `count, this.currSize);`
| 0 | `336` |  | `throw new ArgumentOutOfRangeException(nameof(count), errorText);`
|  | `337` |  | `}`
|  | `338` |  | ``
|  | `339` |  | `//`
|  | `340` |  | `// We have to deal with assembly!!!`
|  | `341` |  | `// The programmer can be writing little 32 byte chunks for all`
|  | `342` |  | `// we know, and we must assemble complete blocks for writing.`
|  | `343` |  | `// TODO REVIEW Maybe this should be in TarBuffer? Could that help to`
|  | `344` |  | `// eliminate some of the buffer copying.`
|  | `345` |  | `//`
| 4087 | `346` |  | `if (assemblyBufferLength > 0) {`
| 40 | `347` |  | `if ((assemblyBufferLength + count) >= blockBuffer.Length) {`
| 0 | `348` |  | `int aLen = blockBuffer.Length - assemblyBufferLength;`
|  | `349` |  | ``
| 0 | `350` |  | `Array.Copy(assemblyBuffer, 0, blockBuffer, 0, assemblyBufferLength);`
| 0 | `351` |  | `Array.Copy(buffer, offset, blockBuffer, assemblyBufferLength, aLen);`
|  | `352` |  | ``
| 0 | `353` |  | `this.buffer.WriteBlock(blockBuffer);`
|  | `354` |  | ``
| 0 | `355` |  | `currBytes += blockBuffer.Length;`
|  | `356` |  | ``
| 0 | `357` |  | `offset += aLen;`
| 0 | `358` |  | `count -= aLen;`
|  | `359` |  | ``
| 0 | `360` |  | `assemblyBufferLength = 0;`
| 0 | `361` |  | `} else {`
| 40 | `362` |  | `Array.Copy(buffer, offset, assemblyBuffer, assemblyBufferLength, count);`
| 40 | `363` |  | `offset += count;`
| 40 | `364` |  | `assemblyBufferLength += count;`
| 40 | `365` |  | `count -= count;`
|  | `366` |  | `}`
|  | `367` |  | `}`
|  | `368` |  | ``
|  | `369` |  | `//`
|  | `370` |  | `// When we get here we have EITHER:`
|  | `371` |  | `// o An empty "assembly" buffer.`
|  | `372` |  | `// o No bytes to write (count == 0)`
|  | `373` |  | `//`
| 8129 | `374` |  | `while (count > 0) {`
| 4047 | `375` |  | `if (count < blockBuffer.Length) {`
| 5 | `376` |  | `Array.Copy(buffer, offset, assemblyBuffer, assemblyBufferLength, count);`
| 5 | `377` |  | `assemblyBufferLength += count;`
| 5 | `378` |  | `break;`
|  | `379` |  | `}`
|  | `380` |  | ``
| 4042 | `381` |  | `this.buffer.WriteBlock(buffer, offset);`
|  | `382` |  | ``
| 4042 | `383` |  | `int bufferLength = blockBuffer.Length;`
| 4042 | `384` |  | `currBytes += bufferLength;`
| 4042 | `385` |  | `count -= bufferLength;`
| 4042 | `386` |  | `offset += bufferLength;`
|  | `387` |  | `}`
| 4082 | `388` |  | `}`
|  | `389` |  | ``
|  | `390` |  | `/// <summary>`
|  | `391` |  | `/// Write an EOF (end of archive) block to the tar archive.`
|  | `392` |  | `/// An EOF block consists of all zeros.`
|  | `393` |  | `/// </summary>`
|  | `394` |  | `void WriteEofBlock()`
|  | `395` |  | `{`
| 73 | `396` |  | `Array.Clear(blockBuffer, 0, blockBuffer.Length);`
| 73 | `397` |  | `buffer.WriteBlock(blockBuffer);`
| 73 | `398` |  | `}`
|  | `399` |  | ``
|  | `400` |  | `#region Instance Fields`
|  | `401` |  | `/// <summary>`
|  | `402` |  | `/// bytes written for this entry so far`
|  | `403` |  | `/// </summary>`
|  | `404` |  | `long currBytes;`
|  | `405` |  | ``
|  | `406` |  | `/// <summary>`
|  | `407` |  | `/// current 'Assembly' buffer length`
|  | `408` |  | `/// </summary>`
|  | `409` |  | `int assemblyBufferLength;`
|  | `410` |  | ``
|  | `411` |  | `/// <summary>`
|  | `412` |  | `/// Flag indicating wether this instance has been closed or not.`
|  | `413` |  | `/// </summary>`
|  | `414` |  | `bool isClosed;`
|  | `415` |  | ``
|  | `416` |  | `/// <summary>`
|  | `417` |  | `/// Size for the current entry`
|  | `418` |  | `/// </summary>`
|  | `419` |  | `protected long currSize;`
|  | `420` |  | ``
|  | `421` |  | `/// <summary>`
|  | `422` |  | `/// single block working buffer`
|  | `423` |  | `/// </summary>`
|  | `424` |  | `protected byte[] blockBuffer;`
|  | `425` |  | ``
|  | `426` |  | `/// <summary>`
|  | `427` |  | `/// 'Assembly' buffer used to assemble data before writing`
|  | `428` |  | `/// </summary>`
|  | `429` |  | `protected byte[] assemblyBuffer;`
|  | `430` |  | ``
|  | `431` |  | `/// <summary>`
|  | `432` |  | `/// TarBuffer used to provide correct blocking factor`
|  | `433` |  | `/// </summary>`
|  | `434` |  | `protected TarBuffer buffer;`
|  | `435` |  | ``
|  | `436` |  | `/// <summary>`
|  | `437` |  | `/// the destination stream for the archive contents`
|  | `438` |  | `/// </summary>`
|  | `439` |  | `protected Stream outputStream;`
|  | `440` |  | `#endregion`
|  | `441` |  | `}`
|  | `442` |  | `}`