# 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 103
    def self.from(stream)
      header = stream.read 512
      empty = (header == EMPTY_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 149
    def initialize(vals)
      unless vals[:name] && vals[:size] && vals[:prefix] && vals[:mode]
        raise ArgumentError, ":name, :size, :prefix and :mode required"
      end

      @checksum = vals[:checksum] || ""
      @devmajor = vals[:devmajor] || 0
      @devminor = vals[:devminor] || 0
      @gid = vals[:gid] || 0
      @gname = vals[:gname] || "wheel"
      @linkname = vals[:linkname]
      @magic = vals[:magic] || "ustar"
      @mode = vals[:mode]
      @mtime = vals[:mtime] || 0
      @name = vals[:name]
      @prefix = vals[:prefix]
      @size = vals[:size]
      @typeflag = vals[:typeflag]
      @typeflag = "0" if @typeflag.nil? || @typeflag.empty?
      @uid = vals[:uid] || 0
      @uname = vals[:uname] || "wheel"
      @version = vals[:version] || "00"

      @empty = vals[:empty]
    end

oct_or_256based(str) click to toggle source

    # File lib/rubygems/package/tar_header.rb, line 136
    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.unpack1("@4N") if /\A[\x80\xff]/n.match?(str)
      strict_oct(str)
    end

strict_oct(str) click to toggle source

    # File lib/rubygems/package/tar_header.rb, line 129
    def self.strict_oct(str)
      str.strip!
      return str.oct if /\A[0-7]*\z/.match?(str)

      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 178
    def empty?
      @empty
    end

update_checksum() click to toggle source

Updates the TarHeader’s checksum

    # File lib/rubygems/package/tar_header.rb, line 210
    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 217
    def calculate_checksum(header)
      header.sum(0)
    end

header(checksum = @checksum) click to toggle source

    # File lib/rubygems/package/tar_header.rb, line 221
    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 247
    def oct(num, len)
      format("%0#{len}o", num)
    end