Class: Archive::Reader

Inherits:
BaseArchive show all
Defined in:
lib/ffi_libarchive/reader.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from BaseArchive

#errno, #error_string

Constructor Details

#initialize(params = {}) ⇒ Reader

Returns a new instance of Reader.

Parameters:

  • params (Hash) (defaults to: {})

Options Hash (params):

  • :command (Object)
  • :file_name (String)
  • :memory (String)
  • :reader (#call)


60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/ffi_libarchive/reader.rb', line 60

def initialize(params = {})
  super C.method(:archive_read_new), C.method(:archive_read_free)

  begin
    init_compression params[:command]
    init_format

    if params[:file_name]
      init_for_filename params[:file_name]
    elsif params[:memory]
      init_for_memory params[:memory]
    elsif params[:reader]
      init_for_stream params[:reader]
    end
  rescue StandardError
    close
    raise
  end
end

Class Method Details

.open_filename(file_name, command = nil) {|| ... } ⇒ Reader

Parameters:

  • file_name (String)

Yield Parameters:

Returns:



10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/ffi_libarchive/reader.rb', line 10

def self.open_filename(file_name, command = nil)
  if block_given?
    reader = open_filename file_name, command
    begin
      yield reader
    ensure
      reader.close if reader.respond_to?(:close)
    end
  else
    new file_name: file_name, command: command
  end
end

.open_memory(string, command = nil) {|| ... } ⇒ Reader

Parameters:

  • string (String)

Yield Parameters:

Returns:



26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/ffi_libarchive/reader.rb', line 26

def self.open_memory(string, command = nil)
  if block_given?
    reader = open_memory string, command
    begin
      yield reader
    ensure
      reader.close if reader.respond_to?(:close)
    end
  else
    new memory: string, command: command
  end
end

.open_stream(stream, command = nil) {|| ... } ⇒ Reader

Parameters:

  • stream (#call)

Yield Parameters:

Returns:



42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/ffi_libarchive/reader.rb', line 42

def self.open_stream(stream, command = nil)
  if block_given?
    reader = open_stream stream, command
    begin
      yield reader
    ensure
      reader.close if reader.respond_to?(:close)
    end
  else
    new reader: stream, command: command
  end
end

Instance Method Details

#closeObject



171
172
173
174
175
176
# File 'lib/ffi_libarchive/reader.rb', line 171

def close
  super
  @read_callback = nil
  @skip_callback = nil
  @seek_callback = nil
end

#each_entry {|| ... } ⇒ Object

Yield Parameters:



111
112
113
114
115
# File 'lib/ffi_libarchive/reader.rb', line 111

def each_entry
  while (entry = next_header)
    yield entry
  end
end

#each_entry_skip_data {|entry| ... } ⇒ Object

Yield Parameters:



126
127
128
129
130
131
132
133
134
# File 'lib/ffi_libarchive/reader.rb', line 126

def each_entry_skip_data
  while (entry = next_header)
    begin
      yield entry
    ensure
      C.archive_read_data_skip archive
    end
  end
end

#each_entry_with_data(size = C::DATA_BUFFER_SIZE) {|entry, data| ... } ⇒ Object

Yield Parameters:

  • entry (Entry)
  • data (String)


119
120
121
122
123
# File 'lib/ffi_libarchive/reader.rb', line 119

def each_entry_with_data(size = C::DATA_BUFFER_SIZE)
  while (entry = next_header)
    yield entry, read_data(size)
  end
end

#extract(entry, flags = 0) ⇒ Object

Parameters:

  • entry (Entry)
  • flags (Integer) (defaults to: 0)

    see ::EXTRACT_*

Raises:

  • (ArgumentError)


82
83
84
85
86
87
88
# File 'lib/ffi_libarchive/reader.rb', line 82

def extract(entry, flags = 0)
  raise ArgumentError, 'Expected Archive::Entry as first argument' unless entry.is_a? Entry
  raise ArgumentError, 'Expected Integer as second argument' unless flags.is_a? Integer

  flags |= EXTRACT_FFLAGS
  raise Error, self if C.archive_read_extract(archive, entry.entry, flags) != C::OK
end

#header_positionInteger

Retrieve the byte offset in UNCOMPRESSED data where last-read header started.

Returns:

  • (Integer)


92
93
94
# File 'lib/ffi_libarchive/reader.rb', line 92

def header_position
  C.archive_read_header_position archive
end

#next_headerEntry

Returns:



97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/ffi_libarchive/reader.rb', line 97

def next_header
  entry_ptr = FFI::MemoryPointer.new(:pointer)

  case C.archive_read_next_header(archive, entry_ptr)
  when C::OK
    Entry.from_pointer entry_ptr.get_pointer(0)
  when C::EOF
    nil
  else
    raise Error, self
  end
end

#read_data(size = C::DATA_BUFFER_SIZE) {|chunk| ... } ⇒ String, Integer

Yield Parameters:

  • chunk (String)

Returns:

  • (String, Integer)

Raises:

  • (ArgumentError)


138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/ffi_libarchive/reader.rb', line 138

def read_data(size = C::DATA_BUFFER_SIZE)
  raise ArgumentError, "Buffer size must be > 0 (was: #{size})" if !size.is_a?(Integer) || size <= 0

  data   = nil
  buffer = FFI::MemoryPointer.new(:char, size)
  len    = 0

  while (n = C.archive_read_data(archive, buffer, size)) != 0
    # TODO: C::FATAL, C::WARN, C::RETRY
    raise Error, self if n < 0

    chunk = buffer.get_bytes(0, n)
    if block_given?
      yield chunk
    elsif data
      data << chunk
    else
      data = chunk.dup
    end

    len += n
  end

  data || len
end

#save_data(file_name) ⇒ Object

Parameters:

  • file_name (String)


165
166
167
168
169
# File 'lib/ffi_libarchive/reader.rb', line 165

def save_data(file_name)
  File.open(file_name, 'wb') do |f|
    raise Error, self if C.archive_read_data_into_fd(archive, f.fileno) != C::OK
  end
end