arr-pm 0.0.6 → 0.0.11
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of arr-pm might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/.rubocop.yml +73 -0
- data/Gemfile +3 -1
- data/Guardfile +77 -0
- data/Makefile +0 -19
- data/arr-pm.gemspec +3 -1
- data/cpio.rb +202 -0
- data/lib/arr-pm/file.rb +34 -10
- data/lib/arr-pm/file/header.rb +3 -2
- data/lib/arr-pm/file/lead.rb +1 -1
- data/lib/arr-pm/file/tag.rb +1 -1
- data/lib/arr-pm/namespace.rb +6 -0
- data/lib/arr-pm/v2/architecture.rb +32 -0
- data/lib/arr-pm/v2/error.rb +32 -0
- data/lib/arr-pm/v2/format.rb +16 -0
- data/lib/arr-pm/v2/header.rb +35 -0
- data/lib/arr-pm/v2/header_header.rb +36 -0
- data/lib/arr-pm/v2/lead.rb +121 -0
- data/lib/arr-pm/v2/package.rb +18 -0
- data/lib/arr-pm/v2/tag.rb +295 -0
- data/lib/arr-pm/v2/type.rb +15 -0
- data/spec/arr-pm/v2/header_spec.rb +34 -0
- data/spec/arr-pm/v2/lead_spec.rb +125 -0
- data/spec/fixtures/example-1.0-1.x86_64.rpm +0 -0
- data/spec/fixtures/example.json +55 -0
- metadata +45 -27
- data/header-verify.rb +0 -71
- data/notify-failure.sh +0 -15
- data/printrpm.rb +0 -22
- data/test/all.rb +0 -24
- data/test/docs.rb +0 -42
- data/test/testing.rb +0 -14
@@ -0,0 +1,15 @@
|
|
1
|
+
require "arr-pm/namespace"
|
2
|
+
|
3
|
+
module ArrPM::V2::Type
|
4
|
+
BINARY = 0
|
5
|
+
SOURCE = 1
|
6
|
+
|
7
|
+
module_function
|
8
|
+
|
9
|
+
# Is a given rpm type value valid?
|
10
|
+
#
|
11
|
+
# The only valid types are BINARY (0) or SOURCE (1)
|
12
|
+
def valid?(value)
|
13
|
+
return (value == BINARY || value == SOURCE)
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "flores/random"
|
4
|
+
|
5
|
+
require "arr-pm/v2/header"
|
6
|
+
require "arr-pm/v2/type"
|
7
|
+
require "arr-pm/v2/architecture"
|
8
|
+
require "json"
|
9
|
+
|
10
|
+
describe ArrPM::V2::Header do
|
11
|
+
context "with a known good rpm" do
|
12
|
+
let(:path) { File.join(File.dirname(__FILE__), "../../fixtures/example-1.0-1.x86_64.rpm") }
|
13
|
+
let(:file) { File.new(path) }
|
14
|
+
|
15
|
+
before do
|
16
|
+
lead = ArrPM::V2::Lead.new
|
17
|
+
lead.load(file)
|
18
|
+
|
19
|
+
# Throw away the signature if we have one
|
20
|
+
described_class.new.load(file) if lead.signature?
|
21
|
+
|
22
|
+
subject.load(file)
|
23
|
+
end
|
24
|
+
|
25
|
+
expectations = JSON.parse(File.read(File.join(File.dirname(__FILE__), "../../fixtures/example.json")))
|
26
|
+
|
27
|
+
expectations.each do |name, expected_value|
|
28
|
+
it "should have expected value for the #{name} tag" do
|
29
|
+
tag = subject.tags.find { |t| t.tag.to_s == name }
|
30
|
+
expect(tag.value).to be == expected_value
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "flores/random"
|
4
|
+
|
5
|
+
require "arr-pm/v2/lead"
|
6
|
+
require "arr-pm/v2/type"
|
7
|
+
require "arr-pm/v2/architecture"
|
8
|
+
|
9
|
+
describe ArrPM::V2::Lead do
|
10
|
+
let(:major) { Flores::Random.integer(0..255) }
|
11
|
+
let(:minor) { Flores::Random.integer(0..255) }
|
12
|
+
let(:magic) { described_class::MAGIC }
|
13
|
+
let(:type) { ArrPM::V2::Type::BINARY }
|
14
|
+
let(:architecture) { ArrPM::V2::Architecture::I386 }
|
15
|
+
let(:os) { 0 }
|
16
|
+
let(:os_bytes) { [os].pack("n").unpack("C2") }
|
17
|
+
let(:signature_type) { 0 }
|
18
|
+
let(:signature_type_bytes) { [signature_type].pack("n").unpack("C2") }
|
19
|
+
let(:longname) { "test-1.0-1" }
|
20
|
+
let(:longnamebytes) { longname.bytes + (66-longname.bytesize).times.collect { 0 } }
|
21
|
+
let(:leadbytes) { magic + [major, minor] + [0, type, 0, architecture] + longnamebytes + os_bytes + signature_type_bytes + 16.times.collect { 0 } }
|
22
|
+
let(:lead) { leadbytes.pack("C*") }
|
23
|
+
|
24
|
+
describe ".parse_magic" do
|
25
|
+
context "when given an invalid magic value" do
|
26
|
+
# Generate random bytes for the magic value, should be bad.
|
27
|
+
let(:magic) { Flores::Random.iterations(0..10).collect { Flores::Random.integer(0..255) } }
|
28
|
+
|
29
|
+
it "should fail" do
|
30
|
+
expect { described_class.parse_magic(leadbytes) }.to raise_error(ArrPM::V2::Error::InvalidMagicValue)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "when given a valid magic value" do
|
35
|
+
it "should succeed" do
|
36
|
+
expect { described_class.parse_magic(leadbytes) }.not_to raise_error
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe ".parse_version" do
|
42
|
+
context "when given an invalid version value" do
|
43
|
+
let(:data) { magic + [major, minor] }
|
44
|
+
|
45
|
+
it "should return an array of two values " do
|
46
|
+
expect(described_class.parse_version(leadbytes)).to be == [major, minor]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe ".parse_type" do
|
52
|
+
context "when given an invalid type" do
|
53
|
+
let(:type) { Flores::Random.integer(2..1000) }
|
54
|
+
it "should fail" do
|
55
|
+
expect { described_class.parse_type(leadbytes) }.to raise_error(ArrPM::V2::Error::InvalidType)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
context "with a valid type" do
|
59
|
+
it "should return the type" do
|
60
|
+
expect(described_class.parse_type(leadbytes)).to be == type
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe ".parse_name" do
|
66
|
+
context "with a valid name" do
|
67
|
+
it "should return the name" do
|
68
|
+
expect(described_class.parse_name(leadbytes)).to be == longname
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe ".parse_signature_type" do
|
74
|
+
it "should return the signature type" do
|
75
|
+
expect(described_class.parse_signature_type(leadbytes)).to be == signature_type
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe ".parse_reserved" do
|
80
|
+
it "should return exactly 16 bytes" do
|
81
|
+
expect(described_class.parse_reserved(leadbytes).count).to be == 16
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "#parse" do
|
86
|
+
before do
|
87
|
+
subject.parse(lead)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should have a correct parsed values" do
|
91
|
+
expect(subject.name).to be == longname
|
92
|
+
expect(subject.major).to be == major
|
93
|
+
expect(subject.minor).to be == minor
|
94
|
+
expect(subject.type).to be == type
|
95
|
+
expect(subject.architecture).to be == architecture
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe "#dump" do
|
100
|
+
before do
|
101
|
+
subject.parse(lead)
|
102
|
+
end
|
103
|
+
|
104
|
+
let(:blob) { subject.serialize }
|
105
|
+
|
106
|
+
it "should parse successfully" do
|
107
|
+
subject.parse(blob)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context "with a known good rpm" do
|
112
|
+
let(:path) { File.join(File.dirname(__FILE__), "../../fixtures/example-1.0-1.x86_64.rpm") }
|
113
|
+
|
114
|
+
before do
|
115
|
+
subject.load(File.new(path))
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should have expected values" do
|
119
|
+
expect(subject.name).to be == "example-1.0-1"
|
120
|
+
expect(subject.major).to be == 3
|
121
|
+
expect(subject.minor).to be == 0
|
122
|
+
expect(subject.architecture).to be == architecture
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
Binary file
|
@@ -0,0 +1,55 @@
|
|
1
|
+
{
|
2
|
+
"NAME": "example",
|
3
|
+
"VERSION": "1.0",
|
4
|
+
"RELEASE": "1",
|
5
|
+
"SUMMARY": "no description given",
|
6
|
+
"DESCRIPTION": "no description given",
|
7
|
+
"BUILDTIME": [
|
8
|
+
1466326707
|
9
|
+
],
|
10
|
+
"BUILDHOST": "localhost",
|
11
|
+
"SIZE": [
|
12
|
+
0
|
13
|
+
],
|
14
|
+
"VENDOR": "none",
|
15
|
+
"LICENSE": "unknown",
|
16
|
+
"PACKAGER": "<jls@localhost.localdomain>",
|
17
|
+
"GROUP": "default",
|
18
|
+
"URL": "http://example.com/no-uri-given",
|
19
|
+
"OS": "linux",
|
20
|
+
"ARCH": "x86_64",
|
21
|
+
"SOURCERPM": "example-1.0-1.src.rpm",
|
22
|
+
"PROVIDENAME": [
|
23
|
+
"example",
|
24
|
+
"example(x86-64)"
|
25
|
+
],
|
26
|
+
"REQUIREFLAGS": [
|
27
|
+
16777226,
|
28
|
+
16777226
|
29
|
+
],
|
30
|
+
"REQUIRENAME": [
|
31
|
+
"rpmlib(CompressedFileNames)",
|
32
|
+
"rpmlib(PayloadFilesHavePrefix)"
|
33
|
+
],
|
34
|
+
"REQUIREVERSION": [
|
35
|
+
"3.0.4-1",
|
36
|
+
"4.0-1"
|
37
|
+
],
|
38
|
+
"RPMVERSION": "4.13.0-rc1",
|
39
|
+
"PREFIXES": [
|
40
|
+
"/"
|
41
|
+
],
|
42
|
+
"PROVIDEFLAGS": [
|
43
|
+
8,
|
44
|
+
8
|
45
|
+
],
|
46
|
+
"PROVIDEVERSION": [
|
47
|
+
"1.0-1",
|
48
|
+
"1.0-1"
|
49
|
+
],
|
50
|
+
"PAYLOADFORMAT": "cpio",
|
51
|
+
"PAYLOADCOMPRESSOR": "gzip",
|
52
|
+
"PAYLOADFLAGS": "9",
|
53
|
+
"PLATFORM": "x86_64-redhat-linux-gnu",
|
54
|
+
"ENCODING": "utf-8"
|
55
|
+
}
|
metadata
CHANGED
@@ -1,30 +1,41 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: arr-pm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.0.11
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Jordan Sissel
|
9
|
-
autorequire:
|
8
|
+
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2021-06-15 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: cabin
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - ">"
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - ">"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: flores
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">"
|
28
39
|
- !ruby/object:Gem::Version
|
29
40
|
version: '0'
|
30
41
|
description: This library allows to you to read and write rpm packages. Written in
|
@@ -35,14 +46,16 @@ executables: []
|
|
35
46
|
extensions: []
|
36
47
|
extra_rdoc_files: []
|
37
48
|
files:
|
38
|
-
- .batcave/manifest
|
39
|
-
- .gitignore
|
49
|
+
- ".batcave/manifest"
|
50
|
+
- ".gitignore"
|
51
|
+
- ".rubocop.yml"
|
40
52
|
- Gemfile
|
53
|
+
- Guardfile
|
41
54
|
- LICENSE
|
42
55
|
- Makefile
|
43
56
|
- README.md
|
44
57
|
- arr-pm.gemspec
|
45
|
-
-
|
58
|
+
- cpio.rb
|
46
59
|
- lib/arr-pm.rb
|
47
60
|
- lib/arr-pm/conflicts.rb
|
48
61
|
- lib/arr-pm/file.rb
|
@@ -51,36 +64,41 @@ files:
|
|
51
64
|
- lib/arr-pm/file/tag.rb
|
52
65
|
- lib/arr-pm/namespace.rb
|
53
66
|
- lib/arr-pm/requires.rb
|
54
|
-
-
|
55
|
-
-
|
56
|
-
-
|
57
|
-
-
|
58
|
-
-
|
59
|
-
|
67
|
+
- lib/arr-pm/v2/architecture.rb
|
68
|
+
- lib/arr-pm/v2/error.rb
|
69
|
+
- lib/arr-pm/v2/format.rb
|
70
|
+
- lib/arr-pm/v2/header.rb
|
71
|
+
- lib/arr-pm/v2/header_header.rb
|
72
|
+
- lib/arr-pm/v2/lead.rb
|
73
|
+
- lib/arr-pm/v2/package.rb
|
74
|
+
- lib/arr-pm/v2/tag.rb
|
75
|
+
- lib/arr-pm/v2/type.rb
|
76
|
+
- spec/arr-pm/v2/header_spec.rb
|
77
|
+
- spec/arr-pm/v2/lead_spec.rb
|
78
|
+
- spec/fixtures/example-1.0-1.x86_64.rpm
|
79
|
+
- spec/fixtures/example.json
|
80
|
+
homepage:
|
60
81
|
licenses:
|
61
82
|
- Apache 2
|
62
|
-
|
83
|
+
metadata: {}
|
84
|
+
post_install_message:
|
63
85
|
rdoc_options: []
|
64
86
|
require_paths:
|
65
87
|
- lib
|
66
88
|
- lib
|
67
89
|
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
-
none: false
|
69
90
|
requirements:
|
70
|
-
- -
|
91
|
+
- - ">="
|
71
92
|
- !ruby/object:Gem::Version
|
72
93
|
version: '0'
|
73
94
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
-
none: false
|
75
95
|
requirements:
|
76
|
-
- -
|
96
|
+
- - ">="
|
77
97
|
- !ruby/object:Gem::Version
|
78
98
|
version: '0'
|
79
99
|
requirements: []
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
specification_version: 3
|
100
|
+
rubygems_version: 3.2.15
|
101
|
+
signing_key:
|
102
|
+
specification_version: 4
|
84
103
|
summary: RPM reader and writer library
|
85
104
|
test_files: []
|
86
|
-
has_rdoc:
|
data/header-verify.rb
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
HEADER_MAGIC = "\x8e\xad\xe8\x01\x00\x00\x00\x00"
|
2
|
-
TAG_ENTRY_SIZE = 16 # tag id, type, offset, count == 16 bytes
|
3
|
-
|
4
|
-
def read_header(io)
|
5
|
-
# RPM 'header' section looks like:
|
6
|
-
#
|
7
|
-
# MAGIC (8 bytes) index_count (4 bytes), data_length (4 bytes )
|
8
|
-
#
|
9
|
-
# * index_count is the number of 'tags' in this header.
|
10
|
-
# * data_length is a blob containing all the values for the tags
|
11
|
-
#
|
12
|
-
# Header has a header of 'magic' + index_count (4 bytes) + data_length (4 bytes)
|
13
|
-
#p "start of header" => io.pos
|
14
|
-
data = io.read(16).unpack("a8NN")
|
15
|
-
|
16
|
-
# TODO(sissel): @index_count is really a count, rename?
|
17
|
-
@magic, @index_count, @data_length = data
|
18
|
-
if @magic != HEADER_MAGIC
|
19
|
-
puts "Magic value in header was wrong. Expected #{HEADER_MAGIC.inspect}, but got #{@magic.inspect}"
|
20
|
-
exit 1
|
21
|
-
end
|
22
|
-
|
23
|
-
@index_size = @index_count * TAG_ENTRY_SIZE
|
24
|
-
tag_data = io.read(@index_size)
|
25
|
-
data = io.read(@data_length)
|
26
|
-
#p "end of header" => io.pos
|
27
|
-
|
28
|
-
(0 ... @index_count).each do |i|
|
29
|
-
offset = i * TAG_ENTRY_SIZE
|
30
|
-
entry_data = tag_data[i * TAG_ENTRY_SIZE, TAG_ENTRY_SIZE]
|
31
|
-
tag, tag_type, offset, count = entry_data.unpack("NNNN")
|
32
|
-
if block_given?
|
33
|
-
yield :tag => tag, :type => tag_type, :offset => offset, :count => count
|
34
|
-
end
|
35
|
-
#entry << data
|
36
|
-
end # each index
|
37
|
-
return 16 + @index_size + @data_length
|
38
|
-
end
|
39
|
-
|
40
|
-
if ARGV.length != 1
|
41
|
-
puts "Usage: #{$0} blah.rpm"
|
42
|
-
exit 1
|
43
|
-
end
|
44
|
-
|
45
|
-
rpm = File.new(ARGV[0])
|
46
|
-
|
47
|
-
# Read the 'lead' - it's mostly an ignored part of the rpm file.
|
48
|
-
lead = rpm.read(96)
|
49
|
-
magic, major, minor, type, archnum, name, osnum, signature_type, reserved = lead.unpack("A4CCnnA66nnA16")
|
50
|
-
|
51
|
-
puts "RPM file version #{major}.#{minor} (#{signature_type == 5 ? "signed" : "unsigned"})"
|
52
|
-
|
53
|
-
if signature_type == 5
|
54
|
-
# Read a header for the rpm signature. This has the same format as a normal
|
55
|
-
# rpm header
|
56
|
-
puts "Checking signature"
|
57
|
-
length = read_header(rpm) do |tag|
|
58
|
-
# print each tag in this header
|
59
|
-
p tag
|
60
|
-
end
|
61
|
-
|
62
|
-
# signature headers are padded up to an 8-byte boundar, details here:
|
63
|
-
# http://rpm.org/gitweb?p=rpm.git;a=blob;f=lib/signature.c;h=63e59c00f255a538e48cbc8b0cf3b9bd4a4dbd56;hb=HEAD#l204
|
64
|
-
# Throw away the pad.
|
65
|
-
rpm.read((length % 8))
|
66
|
-
end
|
67
|
-
|
68
|
-
# Read the rpm header
|
69
|
-
puts "Checking header"
|
70
|
-
read_header(rpm)
|
71
|
-
p rpm.read(4)
|