class Minitar::Reader

streams.
sequential or random access, but certain features only work with random access data
The class that reads a tar format archive from a data stream. The data stream may be

def self.each_entry(io)

Minitar::Reader.each_entry(io) { |entry| block } -> obj
Minitar::Reader.each_entry(io) -> enumerator
:call-seq:

If a block is not provided, an enumerator will be created with the same behaviour.

end
end
# ...
inp.each do |entry|
Minitar::Input.open(io) do |i|

Iterates over each entry in the provided input. This wraps the common pattern of:
def self.each_entry(io)
  return to_enum(__method__, io) unless block_given?
  Input.open(io) do |reader|
    reader.each_entry do |entry|
      yield entry
    end
  end
end

def self.open(io)

instance, +Reader::open+ returns the value of the block.
the Reader object will automatically be closed when the block terminates. In this
optional code block is given, it will be passed the new _writer_ as an argument and
With no associated block, +Reader::open+ is a synonym for +Reader::new+. If the
def self.open(io)
  reader = new(io)
  return reader unless block_given?
  # This exception context must remain, otherwise the stream closes on open even if
  # a block is not given.
  begin
    yield reader
  ensure
    reader.close
  end
end

def close

def close
end

def closed? = false

Returns false if the reader is open (it never closes).
def closed? = false

def each_entry

Iterates through each entry in the data stream.
def each_entry
  return to_enum unless block_given?
  loop do
    return if @io.eof?
    header = Minitar::PosixHeader.from_stream(@io)
    raise Minitar::InvalidTarStream unless header.valid?
    return if header.empty?
    raise Minitar::InvalidTarStream if header.size < 0
    if header.long_name?
      name_block = (header.size / 512.0).ceil * 512
      long_name = @io.read(name_block).rstrip
      header = PosixHeader.from_stream(@io)
      return if header.empty?
      header.long_name = long_name
    elsif header.pax_header?
      pax_header = PaxHeader.from_stream(@io, header)
      header = PosixHeader.from_stream(@io)
      return if header.empty?
      header.size = pax_header.size if pax_header.size
    end
    entry = EntryStream.new(header, @io)
    size = entry.size
    yield entry
    skip = (512 - (size % 512)) % 512
    if Minitar.seekable?(@io, :seek)
      # avoid reading...
      try_seek(size - entry.bytes_read)
    else
      pending = size - entry.bytes_read
      while pending > 0
        bread = @io.read([pending, 4096].min).bytesize
        raise UnexpectedEOF if @io.eof?
        pending -= bread
      end
    end
    @io.read(skip) # discard trailing zeros
    # make sure nobody can use #read, #getc or #rewind anymore
    entry.close
  end
end

def initialize(io)

Creates and returns a new Reader object.
def initialize(io)
  @io = io
  @init_pos = begin
    io.pos
  rescue
    nil
  end
end

def rewind

that respond to #rewind and #pos.
a #each or #each_entry iteration. This only works with random access data streams
Resets the read pointer to the beginning of data stream. Do not call this during
def rewind
  if @init_pos.zero?
    raise Minitar::NonSeekableStream unless Minitar.seekable?(@io, :rewind)
    @io.rewind
  else
    raise Minitar::NonSeekableStream unless Minitar.seekable?(@io, :pos=)
    @io.pos = @init_pos
  end
end

def try_seek(bytes)

def try_seek(bytes)
  @io.seek(bytes, IO::SEEK_CUR)
rescue RangeError
  # This happens when skipping the large entry and the skipping entry size exceeds
  # maximum allowed size (varies by platform and underlying IO object).
  max = RbConfig::LIMITS.fetch("INT_MAX", 2147483647)
  skipped = 0
  while skipped < bytes
    to_skip = [bytes - skipped, max].min
    @io.seek(to_skip, IO::SEEK_CUR)
    skipped += to_skip
  end
end