1# -*- coding: utf-8 -*- 2#++ 3# Copyright (C) 2004 Mauricio Julio Fernández Pradier 4# See LICENSE.txt for additional licensing information. 5#-- 6 7## 8# Class for reading entries out of a tar file 9 10class Gem::Package::TarReader::Entry 11 12 ## 13 # Header for this tar entry 14 15 attr_reader :header 16 17 ## 18 # Creates a new tar entry for +header+ that will be read from +io+ 19 20 def initialize(header, io) 21 @closed = false 22 @header = header 23 @io = io 24 @orig_pos = @io.pos 25 @read = 0 26 end 27 28 def check_closed # :nodoc: 29 raise IOError, "closed #{self.class}" if closed? 30 end 31 32 ## 33 # Number of bytes read out of the tar entry 34 35 def bytes_read 36 @read 37 end 38 39 ## 40 # Closes the tar entry 41 42 def close 43 @closed = true 44 end 45 46 ## 47 # Is the tar entry closed? 48 49 def closed? 50 @closed 51 end 52 53 ## 54 # Are we at the end of the tar entry? 55 56 def eof? 57 check_closed 58 59 @read >= @header.size 60 end 61 62 ## 63 # Full name of the tar entry 64 65 def full_name 66 if @header.prefix != "" then 67 File.join @header.prefix, @header.name 68 else 69 @header.name 70 end 71 rescue ArgumentError => e 72 raise unless e.message == 'string contains null byte' 73 raise Gem::Package::TarInvalidError, 74 'tar is corrupt, name contains null byte' 75 end 76 77 ## 78 # Read one byte from the tar entry 79 80 def getc 81 check_closed 82 83 return nil if @read >= @header.size 84 85 ret = @io.getc 86 @read += 1 if ret 87 88 ret 89 end 90 91 ## 92 # Is this tar entry a directory? 93 94 def directory? 95 @header.typeflag == "5" 96 end 97 98 ## 99 # Is this tar entry a file? 100 101 def file? 102 @header.typeflag == "0" 103 end 104 105 ## 106 # The position in the tar entry 107 108 def pos 109 check_closed 110 111 bytes_read 112 end 113 114 ## 115 # Reads +len+ bytes from the tar file entry, or the rest of the entry if 116 # nil 117 118 def read(len = nil) 119 check_closed 120 121 return nil if @read >= @header.size 122 123 len ||= @header.size - @read 124 max_read = [len, @header.size - @read].min 125 126 ret = @io.read max_read 127 @read += ret.size 128 129 ret 130 end 131 132 ## 133 # Rewinds to the beginning of the tar file entry 134 135 def rewind 136 check_closed 137 138 raise Gem::Package::NonSeekableIO unless @io.respond_to? :pos= 139 140 @io.pos = @orig_pos 141 @read = 0 142 end 143 144end 145 146