Cross package maker. DEB/RPM generation or conversion. Derived from jordansissel/fpm.

⌈⌋ ⎇ branch:  cross package maker


Artifact [610b87b3e0]

Artifact 610b87b3e057f8c5648aea0d70b85dfd5f2a9609:

  • File lib/rpm/rpmfile.rb — part of check-in [35f668b84f] at 2011-05-14 07:49:46 on branch trunk — - factor out the rpm bits into separate class files - include all known rpm 'tag' types (user: jls@semicomplete.com size: 1969)

require "ap"
require File.join(File.dirname(__FILE__), "namespace")
require File.join(File.dirname(__FILE__), "header")
require File.join(File.dirname(__FILE__), "lead")
require File.join(File.dirname(__FILE__), "tag")

# Much of the code here is derived from knowledge gained by reading the rpm
# source code, but mostly it started making more sense after reading this site:
# http://www.rpm.org/max-rpm/s1-rpm-file-format-rpm-file-format.html

class RPMFile 
  attr_reader :file

  def initialize(file)
    if file.is_a?(String)
      file = File.new(file, "r")
    end
    @file = file

    # Make sure we're at the beginning of the file.
    @file.seek(0, IO::SEEK_SET)
  end # def initialize

  public
  def lead
    if @lead.nil?
      @lead = ::RPMFile::Lead.new(self)
      @lead.read
    end
    return @lead
  end # def lead

  public
  def signature
    lead # Make sure we've parsed the lead...

    # If signature_type is not 5 (HEADER_SIGNED_TYPE), no signature.
    if @lead.signature_type != Header::HEADER_SIGNED_TYPE
      @signature = false
      return
    end

    if @signature.nil?
      @signature = ::RPMFile::Header.new(self)
      @signature.read
    end

    return @signature
  end # def signature

  public
  def header
    signature

    # Skip 4 bytes of nulls
    # Why? I have no idea yet.
    if @file.read(4) != "\0\0\0\0"
      raise "Expected 4 nulls."
    end

    if @header.nil?
      @header = ::RPMFile::Header.new(self)
      @header.read
    end
    return @header
  end

  # Returns a file descriptor. On first invocation, it seeks to the start of the payload
  public
  def payload
    header
    if @payload.nil?
      @payload = @file.clone
      # TODO(sissel): Why +20? I have no idea. Needs more digging. Clearly I'm missing a part
      # of the file here.
      @payload.seek(@lead.length + @signature.length + @header.length + 20, IO::SEEK_SET)
    end

    return @payload
  end # def payload
end # class RPMFile