Class: Archive::Tar::Minitar::Input
- Inherits:
-
Object
- Object
- Archive::Tar::Minitar::Input
- Includes:
- Enumerable
- Defined in:
- lib/archive/tar/minitar/input.rb
Overview
Wraps a Archive::Tar::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 = {}, &block) ⇒ 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:
Archive::Tar::Minitar::Input.new(io) -> input
Archive::Tar::Minitar::Input.new(path) -> input
72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/archive/tar/minitar/input.rb', line 72 def initialize(input) @io = if input.respond_to?(:read) input else ::Kernel.open(input, 'rb') end unless Archive::Tar::Minitar.seekable?(@io, :rewind) raise Archive::Tar::Minitar::NonSeekableStream end @tar = Reader.new(@io) end |
Instance Attribute Details
#tar ⇒ Object (readonly)
Returns the Reader object for direct access.
155 156 157 |
# File 'lib/archive/tar/minitar/input.rb', line 155 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:
Archive::Tar::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:
Archive::Tar::Minitar::Input.each_entry(io) -> enumerator
Archive::Tar::Minitar::Input.each_entry(io) { |entry| block } -> obj
51 52 53 54 55 56 57 58 59 |
# File 'lib/archive/tar/minitar/input.rb', line 51 def self.each_entry(input) return to_enum(__method__, input) unless block_given? 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:
Archive::Tar::Minitar::Input.open(io) -> input
Archive::Tar::Minitar::Input.open(io) { |input| block } -> obj
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/archive/tar/minitar/input.rb', line 20 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.
158 159 160 161 |
# File 'lib/archive/tar/minitar/input.rb', line 158 def close @io.close @tar.close end |
#closed? ⇒ Boolean
Returns false if the wrapped data stream is open.
150 151 152 |
# File 'lib/archive/tar/minitar/input.rb', line 150 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.
90 91 92 93 94 95 96 97 98 |
# File 'lib/archive/tar/minitar/input.rb', line 90 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 = {}, &block) ⇒ 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.
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 146 147 |
# File 'lib/archive/tar/minitar/input.rb', line 120 def extract_entry(destdir, entry, = {}, &block) # :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 full_name =~ /\.{2}(?:\/|\z)/ raise SecureRelativePathError, %q(Path contains '..') end if entry.directory? extract_directory(destdir, full_name, entry, stats, , &block) else # it's a file extract_file(destdir, full_name, entry, stats, , &block) end end |