class Gem::Package::TarReader

def self.new(io)

def self.new(io)
  reader = super
  return reader unless block_given?
  begin
    yield reader
  ensure
    reader.close
  end
  nil
end

def close

def close
end

def each

def each
  return enum_for __method__ unless block_given?
  use_seek = @io.respond_to?(:seek)
  until @io.eof? do
    header = Gem::Package::TarHeader.from @io
    return if header.empty?
    entry = Gem::Package::TarReader::Entry.new header, @io
    size = entry.header.size
    yield entry
    skip = (512 - (size % 512)) % 512
    pending = size - entry.bytes_read
    if use_seek
      begin
        # avoid reading if the @io supports seeking
        @io.seek pending, IO::SEEK_CUR
        pending = 0
      rescue Errno::EINVAL
      end
    end
    # if seeking isn't supported or failed
    while pending > 0 do
      bytes_read = @io.read([pending, 4096].min).size
      raise UnexpectedEOF if @io.eof?
      pending -= bytes_read
    end
    @io.read skip # discard trailing zeros
    # make sure nobody can use #read, #getc or #rewind anymore
    entry.close
  end
end

def initialize(io)

def initialize(io)
  @io = io
  @init_pos = io.pos
end

def rewind

def rewind
  if @init_pos == 0
    @io.rewind
  else
    @io.pos = @init_pos
  end
end

def seek(name) # :yields: entry

:yields: entry
def seek(name) # :yields: entry
  found = find do |entry|
    entry.full_name == name
  end
  return unless found
  return yield found
ensure
  rewind
end