Class: Minitar::Input
- Inherits:
-
Object
- Object
- Minitar::Input
- Includes:
- Enumerable
- Defined in:
- lib/minitar/input.rb
Overview
Wraps a Minitar::Reader with convenience methods and wrapped stream management; Input only works with data streams that can be rewound.
Instance Attribute Summary collapse
-
#tar ⇒ Object
readonly
Returns the Reader object for direct access.
Class Method Summary collapse
-
.each_entry(input) ⇒ Object
Iterates over each entry in the provided input.
-
.open(input) ⇒ Object
With no associated block,
Input.open
is a synonym forInput.new
.
Instance Method Summary collapse
-
#close ⇒ Object
Closes both the Reader object and the wrapped data stream.
-
#closed? ⇒ Boolean
Returns false if the wrapped data stream is open.
-
#each_entry ⇒ Object
(also: #each)
When provided a block, iterates through each entry in the archive.
-
#extract_entry(destdir, entry, options = {}) ⇒ Object
Extracts the current
entry
todestdir
. -
#initialize(input) ⇒ Input
constructor
Creates a new Input object.
Constructor Details
#initialize(input) ⇒ Input
Creates a new Input object. If input
is a stream object that responds to #read, then it will simply be wrapped. Otherwise, one will be created and opened using Kernel#open. When Input#close is called, the stream object wrapped will be closed.
An exception will be raised if the stream that is wrapped does not support rewinding.
call-seq:
Minitar::Input.new(io) -> input
Minitar::Input.new(path) -> input
70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/minitar/input.rb', line 70 def initialize(input) @io = if input.respond_to?(:read) input else ::Kernel.open(input, "rb") end unless Minitar.seekable?(@io, :rewind) raise Minitar::NonSeekableStream end @tar = Reader.new(@io) end |
Instance Attribute Details
#tar ⇒ Object (readonly)
Returns the Reader object for direct access.
153 154 155 |
# File 'lib/minitar/input.rb', line 153 def tar @tar end |
Class Method Details
.each_entry(input) ⇒ Object
Iterates over each entry in the provided input. This wraps the common pattern of:
Minitar::Input.open(io) do |i|
inp.each do |entry|
# ...
end
end
If a block is not provided, an enumerator will be created with the same behaviour.
call-seq:
Minitar::Input.each_entry(io) -> enumerator
Minitar::Input.each_entry(io) { |entry| block } -> obj
49 50 51 52 53 54 55 56 57 |
# File 'lib/minitar/input.rb', line 49 def self.each_entry(input) return to_enum(__method__, input) unless block_given? Input.open(input) do |stream| stream.each do |entry| yield entry end end end |
.open(input) ⇒ Object
With no associated block, Input.open
is a synonym for Input.new
. If the optional code block is given, it will be given the new Input as an argument and the Input object will automatically be closed when the block terminates (this also closes the wrapped stream object). In this instance, Input.open
returns the value of the block.
call-seq:
Minitar::Input.open(io) -> input
Minitar::Input.open(io) { |input| block } -> obj
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/minitar/input.rb', line 18 def self.open(input) stream = new(input) if block_given? # This exception context must remain, otherwise the stream closes on # open even if a block is not given. begin yield stream ensure stream.close end else stream end end |
Instance Method Details
#close ⇒ Object
Closes both the Reader object and the wrapped data stream.
156 157 158 159 |
# File 'lib/minitar/input.rb', line 156 def close @io.close @tar.close end |
#closed? ⇒ Boolean
Returns false if the wrapped data stream is open.
148 149 150 |
# File 'lib/minitar/input.rb', line 148 def closed? @io.closed? end |
#each_entry ⇒ Object Also known as: each
When provided a block, iterates through each entry in the archive. When finished, rewinds to the beginning of the stream.
If not provided a block, creates an enumerator with the same semantics.
88 89 90 91 92 93 94 95 96 |
# File 'lib/minitar/input.rb', line 88 def each_entry return to_enum unless block_given? @tar.each do |entry| yield entry end ensure @tar.rewind end |
#extract_entry(destdir, entry, options = {}) ⇒ Object
Extracts the current entry
to destdir
. If a block is provided, it yields an action
Symbol, the full name of the file being extracted (name
), and a Hash of statistical information (stats
).
The action
will be one of:
:dir
-
The
entry
is a directory. :file_start
-
The
entry
is a file; the extract of the file is just beginning. :file_progress
-
Yielded every 4096 bytes during the extract of the
entry
. :file_done
-
Yielded when the
entry
is completed.
The stats
hash contains the following keys:
:current
-
The current total number of bytes read in the
entry
. :currinc
-
The current number of bytes read in this read cycle.
:entry
-
The entry being extracted; this is a Reader::EntryStream, with all methods thereof.
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/minitar/input.rb', line 118 def extract_entry(destdir, entry, = {}, &) # :yields action, name, stats: stats = { current: 0, currinc: 0, entry: entry } # extract_entry is not vulnerable to prefix '/' vulnerabilities, but it # is vulnerable to relative path directories. This code will break this # vulnerability. For this version, we are breaking relative paths HARD by # throwing an exception. # # Future versions may permit relative paths as long as the file does not # leave +destdir+. # # However, squeeze consecutive '/' characters together. full_name = entry.full_name.squeeze("/") if /\.{2}(?:\/|\z)/.match?(full_name) raise SecureRelativePathError, "Path contains '..'" end if entry.directory? extract_directory(destdir, full_name, entry, stats, , &) else # it's a file extract_file(destdir, full_name, entry, stats, , &) end end |