class Gem::Package::TarHeader
A header for a tar file
Constants
- FIELDS
Fields in the tar header
- PACK_FORMAT
Pack format for a tar header
- UNPACK_FORMAT
Unpack format for a tar header
Public Class Methods
from(stream)
click to toggle source
Creates a tar header from IO
stream
# File lib/rubygems/package/tar_header.rb, line 101 def self.from(stream) header = stream.read 512 empty = (EMPTY_HEADER == header) fields = header.unpack UNPACK_FORMAT new :name => fields.shift, :mode => strict_oct(fields.shift), :uid => oct_or_256based(fields.shift), :gid => oct_or_256based(fields.shift), :size => strict_oct(fields.shift), :mtime => strict_oct(fields.shift), :checksum => strict_oct(fields.shift), :typeflag => fields.shift, :linkname => fields.shift, :magic => fields.shift, :version => strict_oct(fields.shift), :uname => fields.shift, :gname => fields.shift, :devmajor => strict_oct(fields.shift), :devminor => strict_oct(fields.shift), :prefix => fields.shift, :empty => empty end
new(vals)
click to toggle source
Creates a new TarHeader
using vals
# File lib/rubygems/package/tar_header.rb, line 144 def initialize(vals) unless vals[:name] && vals[:size] && vals[:prefix] && vals[:mode] raise ArgumentError, ":name, :size, :prefix and :mode required" end vals[:uid] ||= 0 vals[:gid] ||= 0 vals[:mtime] ||= 0 vals[:checksum] ||= "" vals[:typeflag] = "0" if vals[:typeflag].nil? || vals[:typeflag].empty? vals[:magic] ||= "ustar" vals[:version] ||= "00" vals[:uname] ||= "wheel" vals[:gname] ||= "wheel" vals[:devmajor] ||= 0 vals[:devminor] ||= 0 FIELDS.each do |name| instance_variable_set "@#{name}", vals[name] end @empty = vals[:empty] end
oct_or_256based(str)
click to toggle source
# File lib/rubygems/package/tar_header.rb, line 132 def self.oct_or_256based(str) # \x80 flags a positive 256-based number # \ff flags a negative 256-based number # In case we have a match, parse it as a signed binary value # in big-endian order, except that the high-order bit is ignored. return str.unpack('N2').last if str =~ /\A[\x80\xff]/n strict_oct(str) end
strict_oct(str)
click to toggle source
# File lib/rubygems/package/tar_header.rb, line 127 def self.strict_oct(str) return str.oct if str =~ /\A[0-7]*\z/ raise ArgumentError, "#{str.inspect} is not an octal string" end
Public Instance Methods
empty?()
click to toggle source
Is the tar entry empty?
# File lib/rubygems/package/tar_header.rb, line 171 def empty? @empty end
update_checksum()
click to toggle source
Updates the TarHeader's checksum
# File lib/rubygems/package/tar_header.rb, line 203 def update_checksum header = header " " * 8 @checksum = oct calculate_checksum(header), 6 end
Private Instance Methods
calculate_checksum(header)
click to toggle source
# File lib/rubygems/package/tar_header.rb, line 210 def calculate_checksum(header) header.unpack("C*").inject { |a, b| a + b } end
header(checksum = @checksum)
click to toggle source
# File lib/rubygems/package/tar_header.rb, line 214 def header(checksum = @checksum) header = [ name, oct(mode, 7), oct(uid, 7), oct(gid, 7), oct(size, 11), oct(mtime, 11), checksum, " ", typeflag, linkname, magic, oct(version, 2), uname, gname, oct(devmajor, 7), oct(devminor, 7), prefix ] header = header.pack PACK_FORMAT header << ("\0" * ((512 - header.size) % 512)) end
oct(num, len)
click to toggle source
# File lib/rubygems/package/tar_header.rb, line 240 def oct(num, len) "%0#{len}o" % num end