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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ceb08ab00b24c659ee4f0fd42d8f5c8ad77416ffff3f89e8ee18ec46ddc58383
|
4
|
+
data.tar.gz: b53d4d64c24362fb2cf27606842d8352e9f7d184f9ba3b76eb1e33b3e13b2775
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 441b7c7a0d0851c3c4cadaf7e2e0f20d32388ba4df722ee3f76bfb3a34bb072739daf63739cf19e9d8f221a40a80f999ca47b2825043ded493d1f3363dec3e54
|
7
|
+
data.tar.gz: 815d8fff66bc8672b7e212f6c138795a9029b5e78032d26051ac114e306084f97d01519060427aeb50e9bca29dd49af5d5567370904d8881fc99179184811cd3
|
data/.rubocop.yml
ADDED
@@ -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
data/Guardfile
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
## Uncomment and set this to only include directories you want to watch
|
5
|
+
# directories %w(app lib config test spec features)
|
6
|
+
|
7
|
+
## Uncomment to clear the screen before every task
|
8
|
+
# clearing :on
|
9
|
+
|
10
|
+
## Guard internally checks for changes in the Guardfile and exits.
|
11
|
+
## If you want Guard to automatically start up again, run guard in a
|
12
|
+
## shell loop, e.g.:
|
13
|
+
##
|
14
|
+
## $ while bundle exec guard; do echo "Restarting Guard..."; done
|
15
|
+
##
|
16
|
+
## Note: if you are using the `directories` clause above and you are not
|
17
|
+
## watching the project directory ('.'), then you will want to move
|
18
|
+
## the Guardfile to a watched dir and symlink it back, e.g.
|
19
|
+
#
|
20
|
+
# $ mkdir config
|
21
|
+
# $ mv Guardfile config/
|
22
|
+
# $ ln -s config/Guardfile .
|
23
|
+
#
|
24
|
+
# and, you'll have to watch "config/Guardfile" instead of "Guardfile"
|
25
|
+
|
26
|
+
# Note: The cmd option is now required due to the increasing number of ways
|
27
|
+
# rspec may be run, below are examples of the most common uses.
|
28
|
+
# * bundler: 'bundle exec rspec'
|
29
|
+
# * bundler binstubs: 'bin/rspec'
|
30
|
+
# * spring: 'bin/rspec' (This will use spring if running and you have
|
31
|
+
# installed the spring binstubs per the docs)
|
32
|
+
# * zeus: 'zeus rspec' (requires the server to be started separately)
|
33
|
+
# * 'just' rspec: 'rspec'
|
34
|
+
|
35
|
+
guard :rspec, cmd: "bundle exec rspec" do
|
36
|
+
require "guard/rspec/dsl"
|
37
|
+
dsl = Guard::RSpec::Dsl.new(self)
|
38
|
+
|
39
|
+
# Feel free to open issues for suggestions and improvements
|
40
|
+
|
41
|
+
# RSpec files
|
42
|
+
rspec = dsl.rspec
|
43
|
+
watch(rspec.spec_helper) { rspec.spec_dir }
|
44
|
+
watch(rspec.spec_support) { rspec.spec_dir }
|
45
|
+
watch(rspec.spec_files)
|
46
|
+
|
47
|
+
# Ruby files
|
48
|
+
ruby = dsl.ruby
|
49
|
+
dsl.watch_spec_files_for(ruby.lib_files)
|
50
|
+
|
51
|
+
# Rails files
|
52
|
+
rails = dsl.rails(view_extensions: %w(erb haml slim))
|
53
|
+
dsl.watch_spec_files_for(rails.app_files)
|
54
|
+
dsl.watch_spec_files_for(rails.views)
|
55
|
+
|
56
|
+
watch(rails.controllers) do |m|
|
57
|
+
[
|
58
|
+
rspec.spec.("routing/#{m[1]}_routing"),
|
59
|
+
rspec.spec.("controllers/#{m[1]}_controller"),
|
60
|
+
rspec.spec.("acceptance/#{m[1]}")
|
61
|
+
]
|
62
|
+
end
|
63
|
+
|
64
|
+
# Rails config changes
|
65
|
+
watch(rails.spec_helper) { rspec.spec_dir }
|
66
|
+
watch(rails.routes) { "#{rspec.spec_dir}/routing" }
|
67
|
+
watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" }
|
68
|
+
|
69
|
+
# Capybara features specs
|
70
|
+
watch(rails.view_dirs) { |m| rspec.spec.("features/#{m[1]}") }
|
71
|
+
|
72
|
+
# Turnip features and steps
|
73
|
+
watch(%r{^spec/acceptance/(.+)\.feature$})
|
74
|
+
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) do |m|
|
75
|
+
Dir[File.join("**/#{m[1]}.feature")][0] || "spec/acceptance"
|
76
|
+
end
|
77
|
+
end
|
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
|
|
data/arr-pm.gemspec
CHANGED
@@ -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.
|
5
|
+
spec.version = "0.0.11"
|
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
|
data/lib/arr-pm/file.rb
CHANGED
@@ -2,6 +2,7 @@ require File.join(File.dirname(__FILE__), "namespace")
|
|
2
2
|
require File.join(File.dirname(__FILE__), "file", "header")
|
3
3
|
require File.join(File.dirname(__FILE__), "file", "lead")
|
4
4
|
require File.join(File.dirname(__FILE__), "file", "tag")
|
5
|
+
require "fcntl"
|
5
6
|
|
6
7
|
# Much of the code here is derived from knowledge gained by reading the rpm
|
7
8
|
# source code, but mostly it started making more sense after reading this site:
|
@@ -99,7 +100,11 @@ class RPM::File
|
|
99
100
|
|
100
101
|
extractor = IO.popen("#{tags[:payloadcompressor]} -d | (cd #{target}; cpio -i --quiet --make-directories)", "w")
|
101
102
|
buffer = ""
|
102
|
-
|
103
|
+
begin
|
104
|
+
buffer.force_encoding("BINARY")
|
105
|
+
rescue NoMethodError
|
106
|
+
# Do Nothing
|
107
|
+
end
|
103
108
|
payload_fd = payload.clone
|
104
109
|
loop do
|
105
110
|
data = payload_fd.read(16384, buffer)
|
@@ -158,24 +163,28 @@ class RPM::File
|
|
158
163
|
#
|
159
164
|
# @return Array of [ [name, operator, version], ... ]
|
160
165
|
def conflicts
|
161
|
-
return relation(:
|
166
|
+
return relation(:conflict)
|
162
167
|
end # def conflicts
|
163
168
|
|
164
169
|
# Get an array of provides defined in this package.
|
165
170
|
#
|
166
171
|
# @return Array of [ [name, operator, version], ... ]
|
167
172
|
def provides
|
168
|
-
return relation(:
|
173
|
+
return relation(:provide)
|
169
174
|
end # def provides
|
170
175
|
|
171
176
|
# Get an array of config files
|
172
177
|
def config_files
|
173
178
|
# this stuff seems to be in the 'enum rpmfileAttrs_e' from rpm/rpmfi.h
|
174
179
|
results = []
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
180
|
+
# short-circuit if there's no :fileflags tag
|
181
|
+
return results unless tags.include?(:fileflags)
|
182
|
+
if !tags[:fileflags].nil?
|
183
|
+
tags[:fileflags].each_with_index do |flag, i|
|
184
|
+
# The :fileflags (and other :file... tags) are an array, in order of
|
185
|
+
# files in the rpm payload, we want a list of paths of config files.
|
186
|
+
results << files[i] if mask?(flag, FLAG_CONFIG_FILE)
|
187
|
+
end
|
179
188
|
end
|
180
189
|
return results
|
181
190
|
end # def config_files
|
@@ -190,7 +199,11 @@ class RPM::File
|
|
190
199
|
|
191
200
|
lister = IO.popen("#{tags[:payloadcompressor]} -d | cpio -it --quiet", "r+")
|
192
201
|
buffer = ""
|
193
|
-
|
202
|
+
begin
|
203
|
+
buffer.force_encoding("BINARY")
|
204
|
+
rescue NoMethodError
|
205
|
+
# Do Nothing
|
206
|
+
end
|
194
207
|
payload_fd = payload.clone
|
195
208
|
output = ""
|
196
209
|
loop do
|
@@ -202,12 +215,23 @@ class RPM::File
|
|
202
215
|
begin
|
203
216
|
output << lister.read_nonblock(16384)
|
204
217
|
rescue Errno::EAGAIN
|
205
|
-
#
|
218
|
+
# Nothing to read, move on!
|
206
219
|
end
|
207
220
|
end
|
208
221
|
lister.close_write
|
222
|
+
|
209
223
|
# Read remaining output
|
210
|
-
|
224
|
+
begin
|
225
|
+
output << lister.read
|
226
|
+
rescue Errno::EAGAIN
|
227
|
+
# Because read_nonblock enables NONBLOCK the 'lister' fd,
|
228
|
+
# and we may have invoked a read *before* cpio has started
|
229
|
+
# writing, let's keep retrying this read until we get an EOF
|
230
|
+
retry
|
231
|
+
rescue EOFError
|
232
|
+
# At EOF, hurray! We're done reading.
|
233
|
+
end
|
234
|
+
|
211
235
|
# Split output by newline and strip leading "."
|
212
236
|
@files = output.split("\n").collect { |s| s.gsub(/^\./, "") }
|
213
237
|
return @files
|