Class: RPM::File
- Inherits:
-
Object
- Object
- RPM::File
- Defined in:
- lib/arr-pm/file.rb,
lib/arr-pm/namespace.rb
Overview
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: www.rpm.org/max-rpm/s1-rpm-file-format-rpm-file-format.html
Defined Under Namespace
Constant Summary collapse
- FLAG_LESS =
RPMSENSE_LESS = (1 << 1),
(1 << 1)
- FLAG_GREATER =
RPMSENSE_GREATER = (1 << 2),
(1 << 2)
- FLAG_EQUAL =
RPMSENSE_EQUAL = (1 << 3),
(1 << 3)
Instance Attribute Summary collapse
-
#file ⇒ Object
readonly
Returns the value of attribute file.
Instance Method Summary collapse
-
#extract(target) ⇒ Object
Extract this RPM to a target directory.
-
#header ⇒ Object
Return the header for this rpm.
-
#initialize(file) ⇒ File
constructor
A new instance of File.
-
#lead ⇒ Object
Return the lead for this rpm.
-
#operator(flag) ⇒ Object
def requires.
-
#payload ⇒ Object
Returns a file descriptor for the payload.
-
#requires ⇒ Object
def extract.
-
#signature ⇒ Object
Return the signature header for this rpm.
Constructor Details
Instance Attribute Details
#file ⇒ Object (readonly)
Returns the value of attribute file.
11 12 13 |
# File 'lib/arr-pm/file.rb', line 11 def file @file end |
Instance Method Details
#extract(target) ⇒ Object
Extract this RPM to a target directory.
This should have roughly the same effect as:
% rpm2cpio blah.rpm | (cd {target}; cpio -i --make-directories)
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/arr-pm/file.rb', line 93 def extract(target) if !File.directory?(target) raise Errno::ENOENT.new(target) end = {} header..each do |tag| [tag.tag] = tag.value end # Extract to the 'target' path #tags[:payloadcompressor] # "xz" or "gzip" or ..? #tags[:payloadformat] # "cpio" extractor = IO.popen("#{[:payloadcompressor]} -d | (cd #{target}; cpio -i --make-directories)", "w") buffer = "" buffer.force_encoding("BINARY") payload_fd = payload loop do data = payload.read(16384, buffer) break if data.nil? # eof extractor.write(data) end extractor.close end |
#header ⇒ Object
Return the header for this rpm.
64 65 66 67 68 69 70 71 72 |
# File 'lib/arr-pm/file.rb', line 64 def header signature if @header.nil? @header = ::RPM::File::Header.new(@file) @header.read end return @header end |
#lead ⇒ Object
Return the lead for this rpm
This ‘lead’ structure is almost entirely deprecated in the RPM file format.
28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/arr-pm/file.rb', line 28 def lead if @lead.nil? # Make sure we're at the beginning of the file. @file.seek(0, IO::SEEK_SET) @lead = ::RPM::File::Lead.new(@file) # TODO(sissel): have 'read' return number of bytes read? @lead.read end return @lead end |
#operator(flag) ⇒ Object
def requires
133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/arr-pm/file.rb', line 133 def operator(flag) have = lambda do |mask| return (flag & mask) == mask end return "<=" if have.call(FLAG_LESS | FLAG_EQUAL) return ">=" if have.call(FLAG_GREATER | FLAG_EQUAL) return "=" if have.call(FLAG_EQUAL) return "<" if have.call(FLAG_LESS) return ">" if have.call(FLAG_GREATER) end |
#payload ⇒ Object
Returns a file descriptor for the payload. On first invocation, it seeks to the start of the payload
76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/arr-pm/file.rb', line 76 def payload header if @payload.nil? @payload = @file.clone # The payload starts after the lead, signature, and header. Remember the signature has an # 8-byte boundary-rounding. @payload.seek(@lead.length + @signature.length + @signature.length % 8 + @header.length, IO::SEEK_SET) end return @payload end |
#requires ⇒ Object
def extract
119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/arr-pm/file.rb', line 119 def requires = {} header..each do |tag| [tag.tag] = tag.value end result = [] reqs = [:requirename].zip([:requireflags], [:requireversion]) reqs.each do |name, flag, version| result << [name, operator(flag), version] end return result end |
#signature ⇒ Object
Return the signature header for this rpm
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/arr-pm/file.rb', line 41 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 = ::RPM::File::Header.new(@file) @signature.read # signature headers are padded up to an 8-byte boundar, details here: # http://rpm.org/gitweb?p=rpm.git;a=blob;f=lib/signature.c;h=63e59c00f255a538e48cbc8b0cf3b9bd4a4dbd56;hb=HEAD#l204 # Throw away the pad. @file.read(@signature.length % 8) end return @signature end |