Moved to 'ruby-arr-pm' project
This commit is contained in:
parent
eaa4e1d1bd
commit
df5ae16470
|
|
@ -1,89 +0,0 @@
|
|||
require File.join(File.dirname(__FILE__), "namespace")
|
||||
require File.join(File.dirname(__FILE__), "tag")
|
||||
|
||||
class RPMFile::Header
|
||||
attr_reader :tags
|
||||
attr_reader :length
|
||||
|
||||
attr_accessor :magic # 8-byte string magic
|
||||
attr_accessor :index_count # rpmlib calls this field 'il' unhelpfully
|
||||
attr_accessor :data_length # rpmlib calls this field 'dl' unhelpfully
|
||||
|
||||
HEADER_SIGNED_TYPE = 5
|
||||
HEADER_MAGIC = "\x8e\xad\xe8\x01\x00\x00\x00\x00"
|
||||
|
||||
def initialize(rpm)
|
||||
@rpm = rpm
|
||||
@tags = []
|
||||
end
|
||||
|
||||
def read
|
||||
# TODO(sissel): update the comments here to reflect learnings about rpm
|
||||
# internals
|
||||
# At this point assume we've read and consumed the lead and signature.
|
||||
#len = @rpm.signature.index_length + @rpm.signature
|
||||
#
|
||||
# header size is
|
||||
# ( @rpm.signature.index_length * size of a header entry )
|
||||
# + @rpm.signature.data_length
|
||||
#
|
||||
# header 'entries' are an
|
||||
# int32 (tag id), int32 (tag type), int32 (offset), uint32 (count)
|
||||
#
|
||||
# See rpm's header.c, the headerLoad method function for reference.
|
||||
|
||||
# Header always starts with HEADER_MAGIC + index_count(2bytes) +
|
||||
# data_length(2bytes)
|
||||
data = @rpm.file.read(16).unpack("a8NN")
|
||||
# TODO(sissel): @index_count is really a count, rename?
|
||||
@magic, @index_count, @data_length = data
|
||||
validate
|
||||
|
||||
entry_size = 16 # tag id, type, offset, count == 16 bytes
|
||||
@index_size = @index_count * entry_size
|
||||
tag_data = @rpm.file.read(@index_size)
|
||||
data = @rpm.file.read(@data_length)
|
||||
|
||||
#ap :data => data
|
||||
|
||||
(0 ... @index_count).each do |i|
|
||||
offset = i * entry_size
|
||||
entry_data = tag_data[i * entry_size, entry_size]
|
||||
entry = entry_data.unpack("NNNN")
|
||||
entry << data
|
||||
tag = ::RPMFile::Tag.new(*entry)
|
||||
@tags << tag
|
||||
|
||||
#ap tag.tag => {
|
||||
#:type => tag.type,
|
||||
#:offset => tag.offset,
|
||||
#:count => tag.count,
|
||||
#:value => (tag.value rescue "???"),
|
||||
#}
|
||||
end # each index
|
||||
@length = @magic.size + @index_size + @data_length
|
||||
end # def read
|
||||
|
||||
def write
|
||||
raise "not implemented yet"
|
||||
# Sort tags by type (integer value)
|
||||
# emit all tags in order
|
||||
# then emit all data segments in same order
|
||||
end # def write
|
||||
|
||||
def validate
|
||||
# TODO(sissel): raise real exceptions
|
||||
if @magic != ::RPMFile::Header::HEADER_MAGIC
|
||||
raise "Header magic did not match; got #{@magic.inspect}, " \
|
||||
"expected #{::RPMFile::Header::HEADER_MAGIC.inspect}"
|
||||
end
|
||||
|
||||
#if !(0..32).include?(@index_count)
|
||||
#raise "Invalid 'index_count' value #{@index_count}, expected to be in range [0..32]"
|
||||
#end
|
||||
|
||||
#if !(0..8192).include?(@data_length)
|
||||
#raise "Invalid 'data_length' value #{@data_length}, expected to be in range [0..8192]"
|
||||
#end
|
||||
end # def validate
|
||||
end # class RPMFile::Header
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
require File.join(File.dirname(__FILE__), "namespace")
|
||||
|
||||
class RPMFile::Lead
|
||||
#struct rpmlead {
|
||||
attr_accessor :magic #unsigned char magic[4];
|
||||
attr_accessor :major #unsigned char major;
|
||||
attr_accessor :minor #unsigned char minor;
|
||||
attr_accessor :type #short type;
|
||||
attr_accessor :archnum #short archnum;
|
||||
attr_accessor :name #char name[66];
|
||||
attr_accessor :osnum #short osnum;
|
||||
attr_accessor :signature_type #short signature_type;
|
||||
attr_accessor :reserved #char reserved[16];
|
||||
#}
|
||||
|
||||
attr_accessor :length
|
||||
|
||||
def initialize(rpm)
|
||||
@rpm = rpm
|
||||
end
|
||||
|
||||
def type
|
||||
case @type
|
||||
when 0
|
||||
return :binary
|
||||
when 1
|
||||
return :source
|
||||
else
|
||||
raise "Unknown package 'type' value #{@type}"
|
||||
end
|
||||
end # def type
|
||||
|
||||
def read
|
||||
# Use 'A' here instead of 'a' to trim nulls.
|
||||
@length = 96
|
||||
data = @rpm.file.read(@length).unpack("A4CCnnA66nnA16")
|
||||
@magic, @major, @minor, @type, @archnum, @name, \
|
||||
@osnum, @signature_type, @reserved = data
|
||||
|
||||
return nil
|
||||
end # def read
|
||||
|
||||
def write(file)
|
||||
data = [ @magic, @major, @minor, @type, @archnum, @name, \
|
||||
@osnum, @signature_type, @reserved ].pack("a4CCnna66nna16")
|
||||
file.write(data)
|
||||
end # def write
|
||||
end # class RPMFile::Lead
|
||||
|
|
@ -1 +0,0 @@
|
|||
class RPMFile; end
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
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
|
||||
304
lib/rpm/tag.rb
304
lib/rpm/tag.rb
|
|
@ -1,304 +0,0 @@
|
|||
require File.join(File.dirname(__FILE__), "namespace")
|
||||
|
||||
class RPMFile::Tag
|
||||
attr_accessor :tag
|
||||
attr_accessor :type
|
||||
attr_accessor :offset
|
||||
attr_accessor :count
|
||||
attr_accessor :value
|
||||
|
||||
# This data can be found mostly in rpmtag.h
|
||||
TAG = {
|
||||
61 => :headerimage,
|
||||
62 => :headersignatures,
|
||||
63 => :headerimmutable,
|
||||
64 => :headerregions,
|
||||
100 => :headeri18ntable,
|
||||
256 => :sig_base,
|
||||
|
||||
257 => :sigsize,
|
||||
258 => :siglemd5_1,
|
||||
259 => :sigpgp,
|
||||
260 => :siglemd5_2,
|
||||
261 => :sigmd5,
|
||||
262 => :siggpg,
|
||||
263 => :sigpgp5,
|
||||
264 => :badsha1_1,
|
||||
265 => :badsha1_2,
|
||||
266 => :pubkeys,
|
||||
267 => :dsaheader,
|
||||
268 => :rsaheader,
|
||||
269 => :sha1header,
|
||||
270 => :longsigsize,
|
||||
271 => :longarchivesize,
|
||||
|
||||
1000 => :name,
|
||||
1001 => :version,
|
||||
1002 => :release,
|
||||
1003 => :epoch,
|
||||
1004 => :summary,
|
||||
1005 => :description,
|
||||
1006 => :buildtime,
|
||||
1007 => :buildhost,
|
||||
1008 => :installtime,
|
||||
1009 => :size,
|
||||
1010 => :distribution,
|
||||
1011 => :vendor,
|
||||
1012 => :gif,
|
||||
1013 => :xpm,
|
||||
1014 => :license,
|
||||
1015 => :packager,
|
||||
1016 => :group,
|
||||
1017 => :changelog,
|
||||
1018 => :source,
|
||||
1019 => :patch,
|
||||
1020 => :url,
|
||||
1021 => :os,
|
||||
1022 => :arch,
|
||||
1023 => :prein,
|
||||
1024 => :postin,
|
||||
1025 => :preun,
|
||||
1026 => :postun,
|
||||
1027 => :oldfilenames,
|
||||
1028 => :filesizes,
|
||||
1029 => :filestates,
|
||||
1030 => :filemodes,
|
||||
1031 => :fileuids,
|
||||
1032 => :filegids,
|
||||
1033 => :filerdevs,
|
||||
1034 => :filemtimes,
|
||||
1035 => :filedigests,
|
||||
1036 => :filelinktos,
|
||||
1037 => :fileflags,
|
||||
1038 => :root,
|
||||
1039 => :fileusername,
|
||||
1040 => :filegroupname,
|
||||
1041 => :exclude,
|
||||
1042 => :exclusive,
|
||||
1043 => :icon,
|
||||
1044 => :sourcerpm,
|
||||
1045 => :fileverifyflags,
|
||||
1046 => :archivesize,
|
||||
1047 => :providename,
|
||||
1048 => :requireflags,
|
||||
1049 => :requirename,
|
||||
1050 => :requireversion,
|
||||
1051 => :nosource,
|
||||
1052 => :nopatch,
|
||||
1053 => :conflictflags,
|
||||
1054 => :conflictname,
|
||||
1055 => :conflictversion,
|
||||
1056 => :defaultprefix,
|
||||
1057 => :buildroot,
|
||||
1058 => :installprefix,
|
||||
1059 => :excludearch,
|
||||
1060 => :excludeos,
|
||||
1061 => :exclusivearch,
|
||||
1062 => :exclusiveos,
|
||||
1063 => :autoreqprov,
|
||||
1064 => :rpmversion,
|
||||
1065 => :triggerscripts,
|
||||
1066 => :triggername,
|
||||
1067 => :triggerversion,
|
||||
1068 => :triggerflags,
|
||||
1069 => :triggerindex,
|
||||
1079 => :verifyscript,
|
||||
1080 => :changelogtime,
|
||||
1081 => :changelogname,
|
||||
1082 => :changelogtext,
|
||||
1083 => :brokenmd5,
|
||||
1084 => :prereq,
|
||||
1085 => :preinprog,
|
||||
1086 => :postinprog,
|
||||
1087 => :preunprog,
|
||||
1088 => :postunprog,
|
||||
1089 => :buildarchs,
|
||||
1090 => :obsoletename,
|
||||
1091 => :verifyscriptprog,
|
||||
1092 => :triggerscriptprog,
|
||||
1093 => :docdir,
|
||||
1094 => :cookie,
|
||||
1095 => :filedevices,
|
||||
1096 => :fileinodes,
|
||||
1097 => :filelangs,
|
||||
1098 => :prefixes,
|
||||
1099 => :instprefixes,
|
||||
1100 => :triggerin,
|
||||
1101 => :triggerun,
|
||||
1102 => :triggerpostun,
|
||||
1103 => :autoreq,
|
||||
1104 => :autoprov,
|
||||
1105 => :capability,
|
||||
1106 => :sourcepackage,
|
||||
1107 => :oldorigfilenames,
|
||||
1108 => :buildprereq,
|
||||
1109 => :buildrequires,
|
||||
1110 => :buildconflicts,
|
||||
1111 => :buildmacros,
|
||||
1112 => :provideflags,
|
||||
1113 => :provideversion,
|
||||
1114 => :obsoleteflags,
|
||||
1115 => :obsoleteversion,
|
||||
1116 => :dirindexes,
|
||||
1117 => :basenames,
|
||||
1118 => :dirnames,
|
||||
1119 => :origdirindexes,
|
||||
1120 => :origbasenames,
|
||||
1121 => :origdirnames,
|
||||
1122 => :optflags,
|
||||
1123 => :disturl,
|
||||
1124 => :payloadformat,
|
||||
1125 => :payloadcompressor,
|
||||
1126 => :payloadflags,
|
||||
1127 => :installcolor,
|
||||
1128 => :installtid,
|
||||
1129 => :removetid,
|
||||
1130 => :sha1rhn,
|
||||
1131 => :rhnplatform,
|
||||
1132 => :platform,
|
||||
1133 => :patchesname,
|
||||
1134 => :patchesflags,
|
||||
1135 => :patchesversion,
|
||||
1136 => :cachectime,
|
||||
1137 => :cachepkgpath,
|
||||
1138 => :cachepkgsize,
|
||||
1139 => :cachepkgmtime,
|
||||
1140 => :filecolors,
|
||||
1141 => :fileclass,
|
||||
1142 => :classdict,
|
||||
1143 => :filedependsx,
|
||||
1144 => :filedependsn,
|
||||
1145 => :dependsdict,
|
||||
1146 => :sourcepkgid,
|
||||
1147 => :filecontexts,
|
||||
1148 => :fscontexts,
|
||||
1149 => :recontexts,
|
||||
1150 => :policies,
|
||||
1151 => :pretrans,
|
||||
1152 => :posttrans,
|
||||
1153 => :pretransprog,
|
||||
1154 => :posttransprog,
|
||||
1155 => :disttag,
|
||||
1156 => :suggestsname,
|
||||
1157 => :suggestsversion,
|
||||
1158 => :suggestsflags,
|
||||
1159 => :enhancesname,
|
||||
1160 => :enhancesversion,
|
||||
1161 => :enhancesflags,
|
||||
1162 => :priority,
|
||||
1163 => :cvsid,
|
||||
1164 => :blinkpkgid,
|
||||
1165 => :blinkhdrid,
|
||||
1166 => :blinknevra,
|
||||
1167 => :flinkpkgid,
|
||||
1168 => :flinkhdrid,
|
||||
1169 => :flinknevra,
|
||||
1170 => :packageorigin,
|
||||
1171 => :triggerprein,
|
||||
1172 => :buildsuggests,
|
||||
1173 => :buildenhances,
|
||||
1174 => :scriptstates,
|
||||
1175 => :scriptmetrics,
|
||||
1176 => :buildcpuclock,
|
||||
1177 => :filedigestalgos,
|
||||
1178 => :variants,
|
||||
1179 => :xmajor,
|
||||
1180 => :xminor,
|
||||
1181 => :repotag,
|
||||
1182 => :keywords,
|
||||
1183 => :buildplatforms,
|
||||
1184 => :packagecolor,
|
||||
1185 => :packageprefcolor,
|
||||
1186 => :xattrsdict,
|
||||
1187 => :filexattrsx,
|
||||
1188 => :depattrsdict,
|
||||
1189 => :conflictattrsx,
|
||||
1190 => :obsoleteattrsx,
|
||||
1191 => :provideattrsx,
|
||||
1192 => :requireattrsx,
|
||||
1193 => :buildprovides,
|
||||
1194 => :buildobsoletes,
|
||||
1195 => :dbinstance,
|
||||
1196 => :nvra,
|
||||
5000 => :filenames,
|
||||
5001 => :fileprovide,
|
||||
5002 => :filerequire,
|
||||
5003 => :fsnames,
|
||||
5004 => :fssizes,
|
||||
5005 => :triggerconds,
|
||||
5006 => :triggertype,
|
||||
5007 => :origfilenames,
|
||||
5008 => :longfilesizes,
|
||||
5009 => :longsize,
|
||||
5010 => :filecaps,
|
||||
5011 => :filedigestalgo,
|
||||
5012 => :bugurl,
|
||||
5013 => :evr,
|
||||
5014 => :nvr,
|
||||
5015 => :nevr,
|
||||
5016 => :nevra,
|
||||
5017 => :headercolor,
|
||||
5018 => :verbose,
|
||||
5019 => :epochnum,
|
||||
}
|
||||
|
||||
# See 'rpmTagType' enum in rpmtag.h
|
||||
TYPE = {
|
||||
0 => :null,
|
||||
1 => :char,
|
||||
2 => :int8,
|
||||
3 => :int16,
|
||||
4 => :int32,
|
||||
5 => :int64,
|
||||
6 => :string,
|
||||
7 => :binary,
|
||||
8 => :string_array,
|
||||
9 => :i18nstring,
|
||||
}
|
||||
|
||||
def initialize(tag_id, type, offset, count, data)
|
||||
@tag = tag_id
|
||||
@type = type
|
||||
@offset = offset
|
||||
@count = count
|
||||
|
||||
@data = data
|
||||
end # def initialize
|
||||
|
||||
def tag
|
||||
TAG[@tag] or @tag
|
||||
end # def tag
|
||||
|
||||
def tag_as_int
|
||||
@tag
|
||||
end
|
||||
|
||||
def type
|
||||
TYPE[@type] or @type
|
||||
end # def type
|
||||
|
||||
def value
|
||||
if !@value
|
||||
# TODO(sissel): Handle @count of string_array, int32, etc?
|
||||
case type
|
||||
when :string
|
||||
# string at offset up to first null
|
||||
@value = @data[@offset .. -1][/^[^\0]+/]
|
||||
when :i18nstring
|
||||
# string at offset up to first null
|
||||
@value = @data[@offset .. -1][/^[^\0]+/]
|
||||
when :string_array
|
||||
@value = @data[@offset .. -1].split("\0")[0 ... @count]
|
||||
when :binary
|
||||
@value = @data[@offset, @count]
|
||||
when :int32
|
||||
@value = @data[@offset, 4 * count].unpack("N" * count)
|
||||
when :int16
|
||||
@value = @data[@offset, 2 * count].unpack("n" * count)
|
||||
end # case type
|
||||
end # if !@value
|
||||
|
||||
return @value
|
||||
end # def value
|
||||
end # class RPMFile::Tag
|
||||
|
||||
Loading…
Reference in New Issue