Moved to 'ruby-arr-pm' project

This commit is contained in:
Jordan Sissel 2012-02-17 22:22:06 -08:00
parent eaa4e1d1bd
commit df5ae16470
5 changed files with 0 additions and 523 deletions

View File

@ -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

View File

@ -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

View File

@ -1 +0,0 @@
class RPMFile; end

View File

@ -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

View File

@ -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