arr-pm 0.0.9 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- ZTNjMjFhNWE2MmQ0MDhhOWZlNjBhZDYwNzI3MzI5NTM4MTMyZTJlYQ==
5
- data.tar.gz: !binary |-
6
- NDllNDRiN2NhODY3ZmRhNDYxNTk5MmU4OTA4Y2FmZTA3NDhkYWZkOQ==
2
+ SHA1:
3
+ metadata.gz: 60fcb2287ddbb0f718255da5beb0033d9459be16
4
+ data.tar.gz: 1586517c23d99e2c5dead4a45128cfd49c9ff87c
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- ZTAwZWViMjNkZWI4MmJmMjFhNjI2MGNiYmIyZmFjNjhkNGI4ZmQwMjU1NDY5
10
- YWY4YjY5MmE2MGNmMTNkYWI0MDRiMTdmZTg0ODE4YmM5MzU3YWY0M2JjYmNl
11
- NGM0ZGUzYWIwZmIzODE4ODI4MzVjMzY1NDhhYTJiNjI2NjcyN2U=
12
- data.tar.gz: !binary |-
13
- MWNkZWU2ODFlMmMxNzEzOTYzYzllMTIwN2Y3YjBmYTc0ZjE2M2I1YjljYWFk
14
- NjFhM2VkZmVhYjNmYzIxNzE1YTZjNzFkZjExMmMzMDRjYjA2MzA2MDc3MjI3
15
- N2VmYWU0YjBhZTlhM2FkZGUxMGYzMmFhMWIwZmM0MWNiMmI1NjE=
6
+ metadata.gz: e44130d06daa88d4b84b0c800fb54dd8ca8cb4f0b75185c98e450e6b241d30fe666e4a491c6a8113c837d162b95783dcd805c293b1af5fc0d99b2e74ad86eb30
7
+ data.tar.gz: 1c7b02c83d66bcc5964faeeab66b3cc179acda31225039ba60ef0e05311ab9824887830e2ee568ef7946e18d594b274e11141fde2b92eb4a3418c3b85123abd0
@@ -0,0 +1,73 @@
1
+ # Let's not argue over this...
2
+ StringLiterals:
3
+ Enabled: false
4
+
5
+ # I can't find a reason for raise vs fail.
6
+ SignalException:
7
+ Enabled: false
8
+
9
+ # I can't find a reason to prefer 'map' when 'collect' is what I mean.
10
+ # I'm collecting things from a list. Maybe someone can help me understand the
11
+ # semantics here.
12
+ CollectionMethods:
13
+ Enabled: false
14
+
15
+ # Why do you even *SEE* trailing whitespace? Because your editor was
16
+ # misconfigured to highlight trailing whitespace, right? Maybe turn that off?
17
+ # ;)
18
+ TrailingWhitespace:
19
+ Enabled: false
20
+
21
+ # Line length is another weird problem that somehow in the past 40 years of
22
+ # computing we don't seem to have solved. It's a display problem :(
23
+ LineLength:
24
+ Max: 9000
25
+
26
+ # %w() vs [ "x", "y", ... ]
27
+ # The complaint is on lib/pleaserun/detector.rb's map of OS=>Runner,
28
+ # i'll ignore it.
29
+ WordArray:
30
+ MinSize: 5
31
+
32
+ # A 20-line method isn't too bad.
33
+ MethodLength:
34
+ Max: 20
35
+
36
+ # Hash rockets (=>) forever. Why? Not all of my hash keys are static symbols.
37
+ HashSyntax:
38
+ EnforcedStyle: hash_rockets
39
+
40
+ # I prefer explicit return. It makes it clear in the code that the
41
+ # code author intended to return a value from a method.
42
+ RedundantReturn:
43
+ Enabled: false
44
+
45
+ # My view on a readable case statement seems to disagree with
46
+ # what rubocop wants and it doesn't let me configure it other than
47
+ # enable/disable.
48
+ CaseIndentation:
49
+ Enabled: false
50
+
51
+ # module This::Module::Definition is good.
52
+ Style/ClassAndModuleChildren:
53
+ Enabled: true
54
+ EnforcedStyle: compact
55
+
56
+ # "in interpolation #{use.some("double quotes is ok")}"
57
+ Style/StringLiteralsInInterpolation:
58
+ Enabled: true
59
+ EnforcedStyle: double_quotes
60
+
61
+ # Long-block `if !something ... end` are more readable to me than `unless something ... end`
62
+ Style/NegatedIf:
63
+ Enabled: false
64
+
65
+ Style/NumericLiterals:
66
+ MinDigits: 6
67
+
68
+ # This kind of style "useless use of %x" assumes code is write-once.
69
+ Style/UnneededPercentX:
70
+ Enabled: false
71
+
72
+ Style/FileName:
73
+ Enabled: false
data/Gemfile CHANGED
@@ -1 +1,3 @@
1
- source :rubygems
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/Makefile CHANGED
@@ -3,25 +3,6 @@ VERSION=$(shell awk -F\" '/spec.version/ { print $$2 }' $(GEMSPEC))
3
3
  NAME=$(shell awk -F\" '/spec.name/ { print $$2 }' $(GEMSPEC))
4
4
  GEM=$(NAME)-$(VERSION).gem
5
5
 
6
- .PHONY: test
7
- test:
8
- sh notify-failure.sh ruby test/all.rb
9
-
10
- .PHONY: testloop
11
- testloop:
12
- while true; do \
13
- $(MAKE) test; \
14
- $(MAKE) wait-for-changes; \
15
- done
16
-
17
- .PHONY: serve-coverage
18
- serve-coverage:
19
- cd coverage; python -mSimpleHTTPServer
20
-
21
- .PHONY: wait-for-changes
22
- wait-for-changes:
23
- -inotifywait --exclude '\.swp' -e modify $$(find $(DIRS) -name '*.rb'; find $(DIRS) -type d)
24
-
25
6
  .PHONY: package
26
7
  package: | $(GEM)
27
8
 
@@ -2,7 +2,7 @@ Gem::Specification.new do |spec|
2
2
  files = %x{git ls-files}.split("\n")
3
3
 
4
4
  spec.name = "arr-pm"
5
- spec.version = "0.0.9"
5
+ spec.version = "0.0.10"
6
6
  spec.summary = "RPM reader and writer library"
7
7
  spec.description = "This library allows to you to read and write rpm " \
8
8
  "packages. Written in pure ruby because librpm is not available " \
@@ -16,6 +16,8 @@ Gem::Specification.new do |spec|
16
16
 
17
17
  spec.authors = ["Jordan Sissel"]
18
18
  spec.email = ["jls@semicomplete.com"]
19
+
20
+ spec.add_development_dependency "flores", ">0"
19
21
  #spec.homepage = "..."
20
22
  end
21
23
 
data/cpio.rb ADDED
@@ -0,0 +1,202 @@
1
+ class BoundedIO
2
+ attr_reader :length
3
+ attr_reader :remaining
4
+
5
+ def initialize(io, length, &eof_callback)
6
+ @io = io
7
+ @length = length
8
+ @remaining = length
9
+
10
+ @eof_callback = eof_callback
11
+ @eof = false
12
+ end
13
+
14
+ def read(size=nil)
15
+ return nil if eof?
16
+ size = @remaining if size.nil?
17
+ data = @io.read(size)
18
+ @remaining -= data.bytesize
19
+ eof?
20
+ data
21
+ end
22
+
23
+ def sysread(size)
24
+ raise EOFError, "end of file reached" if eof?
25
+ read(size)
26
+ end
27
+
28
+ def eof?
29
+ return false if @remaining > 0
30
+ return @eof if @eof
31
+
32
+ @eof_callback.call
33
+ @eof = true
34
+ end
35
+ end
36
+
37
+ module CPIO
38
+ FIELDS = [
39
+ :magic, :ino, :mode, :uid, :gid, :nlink, :mtime, :filesize, :devmajor,
40
+ :devminor, :rdevmajor, :rdevminor, :namesize, :check
41
+ ]
42
+ end
43
+
44
+ class CPIO::ASCIIReader
45
+ FIELD_SIZES = {
46
+ :magic => 6,
47
+ :ino => 8,
48
+ :mode => 8,
49
+ :uid => 8,
50
+ :gid => 8,
51
+ :nlink => 8,
52
+ :mtime => 8,
53
+ :filesize => 8,
54
+ :devmajor => 8,
55
+ :devminor => 8,
56
+ :rdevmajor => 8,
57
+ :rdevminor => 8,
58
+ :namesize => 8,
59
+ :check => 8
60
+ }
61
+ HEADER_LENGTH = FIELD_SIZES.reduce(0) { |m, (_, v)| m + v }
62
+ HEADER_PACK = FIELD_SIZES.collect { |_, v| "A#{v}" }.join
63
+
64
+ FIELD_ORDER = [
65
+ :magic, :ino, :mode, :uid, :gid, :nlink, :mtime, :filesize, :devmajor,
66
+ :devminor, :rdevmajor, :rdevminor, :namesize, :check
67
+ ]
68
+
69
+ def initialize(io)
70
+ @io = io
71
+ end
72
+
73
+ private
74
+
75
+ def io
76
+ @io
77
+ end
78
+
79
+ def each(&block)
80
+ while true
81
+ entry = read
82
+ break if entry.nil?
83
+ # The CPIO format has the end-of-stream marker as a file called "TRAILER!!!"
84
+ break if entry.name == "TRAILER!!!"
85
+ block.call(entry, entry.file)
86
+ verify_correct_read(entry) unless entry.directory?
87
+ end
88
+ end
89
+
90
+ def verify_correct_read(entry)
91
+ # Read and throw away the whole file if not read at all.
92
+ entry.file.tap do |file|
93
+ if file.nil? || file.remaining == 0
94
+ # All OK! :)
95
+ elsif file.remaining == file.length
96
+ file.read(16384) while !file.eof?
97
+ else
98
+ # The file was only partially read? This should be an error by the
99
+ # user.
100
+ consumed = file.length - file.remaining
101
+ raise BadState, "Only #{consumed} bytes were read of the #{file.length} byte file: #{entry.name}"
102
+ end
103
+ end
104
+ end
105
+
106
+ def read
107
+ entry = CPIOEntry.new
108
+ header = io.read(HEADER_LENGTH)
109
+ return nil if header.nil?
110
+ FIELD_ORDER.zip(header.unpack(HEADER_PACK)).each do |field, value|
111
+ entry.send("#{field}=", value.to_i(16))
112
+ end
113
+
114
+ entry.validate
115
+ entry.mtime = Time.at(entry.mtime)
116
+ read_name(entry, @io)
117
+ read_file(entry, @io)
118
+ entry
119
+ end
120
+
121
+ def read_name(entry, io)
122
+ entry.name = io.read(entry.namesize - 1) # - 1 for null terminator
123
+ nul = io.read(1)
124
+ raise ArgumentError, "Corrupt CPIO or bug? Name null terminator was not null: #{nul.inspect}" if nul != "\0"
125
+ padding_data = io.read(padding_name(entry))
126
+ # Padding should be all null bytes
127
+ if padding_data != ("\0" * padding_data.bytesize)
128
+ raise ArgumentError, "Corrupt CPIO or bug? Name null padding was #{padding_name(entry)} bytes: #{padding_data.inspect}"
129
+ end
130
+ end
131
+
132
+ def read_file(entry, io)
133
+ if entry.directory?
134
+ entry.file = nil
135
+ #read_file_padding(entry, io)
136
+ nil
137
+ else
138
+ entry.file = BoundedIO.new(io, entry.filesize) do
139
+ read_file_padding(entry, io)
140
+ end
141
+ end
142
+ end
143
+
144
+ def read_file_padding(entry, io)
145
+ padding_data = io.read(padding_file(entry))
146
+ if padding_data != ("\0" * padding_data.bytesize)
147
+ raise ArgumentError, "Corrupt CPIO or bug? File null padding was #{padding_file(entry)} bytes: #{padding_data.inspect}"
148
+ end
149
+ end
150
+
151
+ def padding_name(entry)
152
+ # name padding is padding up to a multiple of 4 after header+namesize
153
+ -(HEADER_LENGTH + entry.namesize) % 4
154
+ end
155
+
156
+ def padding_file(entry)
157
+ (-(HEADER_LENGTH + entry.filesize + 2) % 4)
158
+ end
159
+ public(:each)
160
+ end
161
+
162
+ class CPIOEntry
163
+ CPIO::FIELDS.each do |field|
164
+ attr_accessor field
165
+ end
166
+
167
+ attr_accessor :name
168
+ attr_accessor :file
169
+
170
+ DIRECTORY_FLAG = 0040000
171
+
172
+ def validate
173
+ raise "Invalid magic #{magic.inspect}" if magic != 0x070701
174
+ raise "Invalid ino #{ino.inspect}" if ino < 0
175
+ raise "Invalid mode #{mode.inspect}" if mode < 0
176
+ raise "Invalid uid #{uid.inspect}" if uid < 0
177
+ raise "Invalid gid #{gid.inspect}" if gid < 0
178
+ raise "Invalid nlink #{nlink.inspect}" if nlink < 0
179
+ raise "Invalid mtime #{mtime.inspect}" if mtime < 0
180
+ raise "Invalid filesize #{filesize.inspect}" if filesize < 0
181
+ raise "Invalid devmajor #{devmajor.inspect}" if devmajor < 0
182
+ raise "Invalid devminor #{devminor.inspect}" if devminor < 0
183
+ raise "Invalid rdevmajor #{rdevmajor.inspect}" if rdevmajor < 0
184
+ raise "Invalid rdevminor #{rdevminor.inspect}" if rdevminor < 0
185
+ raise "Invalid namesize #{namesize.inspect}" if namesize < 0
186
+ raise "Invalid check #{check.inspect}" if check < 0
187
+ end # def validate
188
+
189
+ def read(*args)
190
+ return nil if directory?
191
+ file.read(*args)
192
+ end
193
+
194
+ def directory?
195
+ mode & DIRECTORY_FLAG > 0
196
+ end
197
+ end
198
+
199
+ CPIO::ASCIIReader.new(STDIN).each do |entry, file|
200
+ puts entry.name
201
+ file.read unless entry.directory?
202
+ end
@@ -177,6 +177,8 @@ class RPM::File
177
177
  def config_files
178
178
  # this stuff seems to be in the 'enum rpmfileAttrs_e' from rpm/rpmfi.h
179
179
  results = []
180
+ # short-circuit if there's no :fileflags tag
181
+ return results unless tags.include?(:fileflags)
180
182
  tags[:fileflags].each_with_index do |flag, i|
181
183
  # The :fileflags (and other :file... tags) are an array, in order of
182
184
  # files in the rpm payload, we want a list of paths of config files.
metadata CHANGED
@@ -1,27 +1,41 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arr-pm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jordan Sissel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-05 00:00:00.000000000 Z
11
+ date: 2015-04-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cabin
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ! '>'
17
+ - - ">"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ! '>'
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
+ - - ">"
25
39
  - !ruby/object:Gem::Version
26
40
  version: '0'
27
41
  description: This library allows to you to read and write rpm packages. Written in
@@ -32,14 +46,15 @@ executables: []
32
46
  extensions: []
33
47
  extra_rdoc_files: []
34
48
  files:
35
- - .batcave/manifest
36
- - .gitignore
49
+ - ".batcave/manifest"
50
+ - ".gitignore"
51
+ - ".rubocop.yml"
37
52
  - Gemfile
38
53
  - LICENSE
39
54
  - Makefile
40
55
  - README.md
41
56
  - arr-pm.gemspec
42
- - header-verify.rb
57
+ - cpio.rb
43
58
  - lib/arr-pm.rb
44
59
  - lib/arr-pm/conflicts.rb
45
60
  - lib/arr-pm/file.rb
@@ -48,8 +63,6 @@ files:
48
63
  - lib/arr-pm/file/tag.rb
49
64
  - lib/arr-pm/namespace.rb
50
65
  - lib/arr-pm/requires.rb
51
- - notify-failure.sh
52
- - printrpm.rb
53
66
  homepage:
54
67
  licenses:
55
68
  - Apache 2
@@ -61,19 +74,18 @@ require_paths:
61
74
  - lib
62
75
  required_ruby_version: !ruby/object:Gem::Requirement
63
76
  requirements:
64
- - - ! '>='
77
+ - - ">="
65
78
  - !ruby/object:Gem::Version
66
79
  version: '0'
67
80
  required_rubygems_version: !ruby/object:Gem::Requirement
68
81
  requirements:
69
- - - ! '>='
82
+ - - ">="
70
83
  - !ruby/object:Gem::Version
71
84
  version: '0'
72
85
  requirements: []
73
86
  rubyforge_project:
74
- rubygems_version: 2.1.11
87
+ rubygems_version: 2.4.3
75
88
  signing_key:
76
89
  specification_version: 4
77
90
  summary: RPM reader and writer library
78
91
  test_files: []
79
- has_rdoc:
@@ -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)
@@ -1,15 +0,0 @@
1
- #!/bin/sh
2
-
3
- "$@"
4
- status=$?
5
-
6
- if [ ! -z "$TMUX" ] ; then
7
- if [ "$status" -ne 0 ] ; then
8
- tmux display-message "Tests Fail"
9
- else
10
- tmux display-message "Tests OK"
11
- fi
12
- fi
13
-
14
- exit $status
15
-
@@ -1,22 +0,0 @@
1
- $: << "lib"
2
-
3
- require "rpm/file"
4
-
5
- rpm = RPM::File.new(ARGV[0])
6
-
7
- #p rpm.lead
8
- rpm.signature.tags.each do |tag|
9
- #p :tag => [tag.tag, tag.type, tag.count, tag.value]
10
- end
11
-
12
- rpm.header.tags.each do |tag|
13
- #next unless tag.tag.to_s =~ /(payload|sig)/
14
- # p :tag => [tag.tag, tag.type, tag.count, tag.value]
15
- end
16
-
17
- require "awesome_print"
18
- ap rpm.requires
19
-
20
- #payload = rpm.payload
21
- #fd = File.new("/tmp/rpm.payload", "w")
22
- #fd.write(rpm.payload.read)