Beispiel #1
0
        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);
        }
Beispiel #2
0
        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));
        }
Beispiel #3
0
        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);
        }