Fix up Rubinius specific library specs.
[rbx.git] / lib / rubygems / package / tar_reader.rb
blob8359399207e4d9c19cf696d8f7dec08bbc1e5b66
1 #++
2 # Copyright (C) 2004 Mauricio Julio Fernández Pradier
3 # See LICENSE.txt for additional licensing information.
4 #--
6 require 'rubygems/package'
8 class Gem::Package::TarReader
10   include Gem::Package
12   class UnexpectedEOF < StandardError; end
14   def self.new(io)
15     reader = super
17     return reader unless block_given?
19     begin
20       yield reader
21     ensure
22       reader.close
23     end
25     nil
26   end
28   def initialize(io)
29     @io = io
30     @init_pos = io.pos
31   end
33   def close
34   end
36   def each
37     loop do
38       return if @io.eof?
40       header = Gem::Package::TarHeader.from @io
41       return if header.empty?
43       entry = Gem::Package::TarReader::Entry.new header, @io
44       size = entry.header.size
46       yield entry
48       skip = (512 - (size % 512)) % 512
50       if @io.respond_to? :seek then
51         # avoid reading...
52         @io.seek(size - entry.bytes_read, IO::SEEK_CUR)
53       else
54         pending = size - entry.bytes_read
56         while pending > 0 do
57           bread = @io.read([pending, 4096].min).size
58           raise UnexpectedEOF if @io.eof?
59           pending -= bread
60         end
61       end
63       @io.read skip # discard trailing zeros
65       # make sure nobody can use #read, #getc or #rewind anymore
66       entry.close
67     end
68   end
70   alias each_entry each
72   ##
73   # NOTE: Do not call #rewind during #each
75   def rewind
76     if @init_pos == 0 then
77       raise Gem::Package::NonSeekableIO unless @io.respond_to? :rewind
78       @io.rewind
79     else
80       raise Gem::Package::NonSeekableIO unless @io.respond_to? :pos=
81       @io.pos = @init_pos
82     end
83   end
85 end