public async Task CreateEntryAsync(TarEntry entry) { ValidateWroteAll(); var paxAttributes = new Dictionary <string, string>(); // Clear padding. for (int i = 0; i < TarCommon.BlockSize; i++) { _buffer[i] = 0; } var state = new TarHeaderView(_buffer, TarCommon.BlockSize, paxAttributes); var padding = _remainingPadding; _remainingPadding = 0; GenerateHeader(ref state, entry, default(ArraySegment <byte>)); if (paxAttributes.Count > 0) { padding = await WritePaxEntry(entry, paxAttributes, padding); } await _stream.WriteAsync(_buffer, TarCommon.BlockSize - padding, TarCommon.BlockSize + padding); _remaining = entry.Length; _remainingPadding = TarCommon.Padding(_remaining); }
private async Task <int> WritePaxEntry(TarEntry entry, Dictionary <string, string> paxAttributes, int padding) { var paxStream = new MemoryStream(); // Skip the tar header, then go back and write it later. var paxDataOffset = padding + TarCommon.BlockSize; paxStream.SetLength(paxDataOffset); paxStream.Position = paxDataOffset; foreach (var attribute in paxAttributes) { WritePaxAttribute(paxStream, attribute.Key, attribute.Value); } var paxEntry = new TarEntry { Type = TarCommon.PaxHeaderType, Length = paxStream.Length - paxDataOffset, }; ArraySegment <byte> buffer; paxStream.TryGetBuffer(out buffer); var paxHeader = new TarHeaderView(buffer.Array, buffer.Offset + padding, null); GenerateHeader(ref paxHeader, paxEntry, GetPaxName(entry.Name)); paxStream.Position = 0; await paxStream.CopyToAsync(_stream); return(TarCommon.Padding(paxEntry.Length)); }
private async Task <TarEntry> ReadHeader(Dictionary <string, string> paxAttributes) { if (_remaining > 0) { await Skip(_remaining); _remaining = 0; } var read = await _stream.ReadAsync(_buffer, 0, TarCommon.BlockSize + _remainingPadding); var padding = _remainingPadding; _remainingPadding = 0; if (read <= _remainingPadding) { // No more entries. return(null); } else if (read - _remainingPadding < TarCommon.BlockSize) { throw new EndOfStreamException(); } if (IsArrayZero(padding, TarCommon.BlockSize)) { // Verify that the next block is also zero. read = await _stream.ReadAsync(_buffer, 0, TarCommon.BlockSize); if (read == 0) { return(null); } else if (read < TarCommon.BlockSize) { throw new EndOfStreamException(); } else if (IsArrayZero(0, TarCommon.BlockSize)) { return(null); } else { throw new TarParseException("non-zero header after zero header"); } } var header = new TarHeaderView(_buffer, padding, paxAttributes); var entry = ParseHeader(ref header); _remaining = entry.Length; _remainingPadding = TarCommon.Padding(_remaining); return(entry); }