ffi-libarchive 0.2.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -3,10 +3,75 @@ ffi-libarchive
3
3
  A Ruby FFI binding to [libarchive][0].
4
4
 
5
5
  This library provides Ruby FFI bindings to the well-known
6
- [libarchive library][0]. It aims to be interface compatiable
7
- to libarchive-ruby.
6
+ [libarchive library][0].
8
7
 
9
- ## Why this instead of libarchive-ruby?
8
+ ## Installation
9
+
10
+ Ensure that you have libarchive installed. On Debian/Ubuntu:
11
+
12
+ ```sh
13
+ apt install libarchive13
14
+ ```
15
+
16
+ On macOS with Homebrew:
17
+ ```sh
18
+ brew install libarchive
19
+ ```
20
+
21
+ Add this line to your application's Gemfile:
22
+
23
+ ```ruby
24
+ gem 'ffi-libarchive'
25
+ ```
26
+
27
+ And then execute:
28
+
29
+ ```shell
30
+ $ bundle
31
+ ```
32
+
33
+ Or install it yourself as:
34
+
35
+ ```shell
36
+ $ gem install ffi-libarchive
37
+ ```
38
+
39
+ ## Usage
40
+
41
+ To extract an archive into the current directory:
42
+
43
+ ```ruby
44
+ flags = Archive::EXTRACT_PERM
45
+ reader = Archive::Reader.open_filename('/path/to/archive.tgz')
46
+
47
+ reader.each_entry do |entry|
48
+ reader.extract(entry, flags.to_i)
49
+ end
50
+ reader.close
51
+ ```
52
+
53
+ To create a gzipped tar archive:
54
+
55
+ ```ruby
56
+ Archive.write_open_filename('my.tgz', Archive::COMPRESSION_GZIP, Archive::FORMAT_TAR_PAX_RESTRICTED) do |tar|
57
+ content = File.read 'some_path'
58
+ size = content.size
59
+ tar.new_entry do |e|
60
+ e.pathname = 'some_path'
61
+ e.size = size
62
+ e.filetype = Archive::Entry::FILE
63
+ tar.write_header e
64
+ tar.write_data content
65
+ end
66
+ end
67
+ ```
68
+
69
+ ## Contributing
70
+
71
+ Bug reports and pull requests are welcome on GitHub at <https://github.com/chef/ffi-libarchive>. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Community Guidelines](https://docs.chef.io/community_guidelines.html) code of conduct.
72
+
73
+ ## License
74
+
75
+ The gem is available as open source under the terms of the Apache License, v2
10
76
 
11
77
  [0]: https://github.com/libarchive/libarchive
12
- [1]: https://github.com/Hanmac/libarchive-ruby
data/Rakefile CHANGED
@@ -1,11 +1,28 @@
1
- require 'bundler/gem_tasks'
2
-
3
- require 'rspec/core/rake_task'
4
- RSpec::Core::RakeTask.new do |t|
5
- t.rspec_opts = [
6
- '--color',
7
- '--format progress',
8
- ].join(' ')
1
+ #!/usr/bin/env rake
2
+
3
+ require "bundler/setup"
4
+ require "bundler/gem_tasks"
5
+ require "chefstyle"
6
+ require "rubocop/rake_task"
7
+ require "rake/testtask"
8
+
9
+ namespace :style do
10
+ desc "Run Ruby style checks"
11
+ RuboCop::RakeTask.new(:ruby)
12
+ end
13
+
14
+ Rake::TestTask.new(:test) do |t|
15
+ t.libs << "test"
16
+ t.libs << "lib"
17
+ t.test_files = FileList["test/test_ffi-libarchive.rb"]
9
18
  end
10
19
 
11
- task default: :spec
20
+ desc "Run all style checks"
21
+ task style: ["style:ruby"]
22
+
23
+ desc "Run style & unit tests on Travis"
24
+ task travis: %w{style test}
25
+
26
+ # Default
27
+ desc "Run style, unit"
28
+ task default: %w{style test}
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.4.1
@@ -1,25 +1,25 @@
1
1
  # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
2
+ lib = File.expand_path("../lib", __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'ffi-libarchive/version'
4
+ require "ffi-libarchive/version"
5
5
 
6
6
  Gem::Specification.new do |s|
7
- s.name = 'ffi-libarchive'
7
+ s.name = "ffi-libarchive"
8
8
  s.version = Archive::VERSION
9
- s.authors = ['John Bellone', 'Jamie Winsor', 'Frank Fischer']
9
+ s.authors = ["John Bellone", "Jamie Winsor", "Frank Fischer"]
10
10
  s.email = %w{jbellone@bloomberg.net jamie@vialstudios.com frank-fischer@shadow-soft.de}
11
- s.description = 'A Ruby FFI binding to libarchive.'
11
+ s.description = "A Ruby FFI binding to libarchive."
12
12
  s.summary = s.description
13
- s.homepage = 'https://github.com/johnbellone/ffi-libarchive'
14
- s.license = 'GPL 3.0'
13
+ s.homepage = "https://github.com/chef/ffi-libarchive"
14
+ s.license = "Apache-2.0"
15
15
 
16
- s.files = `git ls-files`.split($/)
17
- s.test_files = s.files.grep(%r{^(test)/})
16
+ s.files = %w{ Gemfile Rakefile README.md LICENSE VERSION } + Dir.glob("{lib,test}/**/*", File::FNM_DOTMATCH).reject { |f| File.directory?(f) } + Dir.glob("*.gemspec")
18
17
  s.require_paths = %w{lib}
19
- s.required_ruby_version = '>= 1.9'
18
+ s.required_ruby_version = ">= 2.4.0"
20
19
 
21
- s.add_dependency 'ffi', '~> 1.0'
20
+ s.add_dependency "ffi", "~> 1.0"
22
21
 
23
- s.add_development_dependency 'bundler'
24
- s.add_development_dependency 'rake'
22
+ s.add_development_dependency "bundler"
23
+ s.add_development_dependency "rake"
24
+ s.add_development_dependency "test-unit"
25
25
  end
@@ -8,8 +8,8 @@ module Archive
8
8
  # they will be joined to the end of the libray path using
9
9
  # <tt>File.join</tt>.
10
10
  #
11
- def self.libpath( *args )
12
- rv = args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
11
+ def self.libpath(*args)
12
+ rv = args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
13
13
  if block_given?
14
14
  begin
15
15
  $LOAD_PATH.unshift LIBPATH
@@ -18,14 +18,14 @@ module Archive
18
18
  $LOAD_PATH.shift
19
19
  end
20
20
  end
21
- return rv
21
+ rv
22
22
  end
23
23
 
24
24
  # Returns the lpath for the module. If any arguments are given,
25
25
  # they will be joined to the end of the path using
26
26
  # <tt>File.join</tt>.
27
27
  #
28
- def self.path( *args )
28
+ def self.path(*args)
29
29
  rv = args.empty? ? PATH : ::File.join(PATH, args.flatten)
30
30
  if block_given?
31
31
  begin
@@ -35,7 +35,7 @@ module Archive
35
35
  $LOAD_PATH.shift
36
36
  end
37
37
  end
38
- return rv
38
+ rv
39
39
  end
40
40
 
41
41
  # Utility method used to require all files ending in .rb that lie in the
@@ -43,15 +43,14 @@ module Archive
43
43
  # in. Optionally, a specific _directory_ name can be passed in such that
44
44
  # the _filename_ does not have to be equivalent to the directory.
45
45
  #
46
- def self.require_all_libs_relative_to( fname, dir = nil )
47
- dir ||= ::File.basename(fname, '.*')
46
+ def self.require_all_libs_relative_to(fname, dir = nil)
47
+ dir ||= ::File.basename(fname, ".*")
48
48
  search_me = ::File.expand_path(
49
- ::File.join(::File.dirname(fname), dir, '**', '*.rb'))
49
+ ::File.join(::File.dirname(fname), dir, "**", "*.rb"))
50
50
 
51
- Dir.glob(search_me).sort.each {|rb| require rb}
51
+ Dir.glob(search_me).sort.each { |rb| require rb }
52
52
  end
53
-
54
- end # module Archive
53
+ end # module Archive
55
54
 
56
55
  require File.join(Archive::LIBPATH, "ffi-libarchive", "archive")
57
56
  require File.join(Archive::LIBPATH, "ffi-libarchive", "reader")
@@ -1,15 +1,14 @@
1
- require 'ffi'
1
+ require "ffi"
2
2
 
3
3
  module Archive
4
-
5
4
  module C
6
- def self.attach_function_maybe *args
5
+ def self.attach_function_maybe(*args)
7
6
  attach_function(*args)
8
- rescue FFI::NotFoundError
7
+ rescue FFI::NotFoundError # rubocop:disable Lint/HandleExceptions
9
8
  end
10
9
 
11
10
  extend FFI::Library
12
- ffi_lib ["archive", "libarchive.so.2"]
11
+ ffi_lib %w{libarchive.so.13 libarchive.13 libarchive.so libarchive archive}
13
12
 
14
13
  attach_function :archive_version_number, [], :int
15
14
  attach_function :archive_version_string, [], :string
@@ -21,8 +20,49 @@ module Archive
21
20
  attach_function :archive_read_open_memory, [:pointer, :pointer, :size_t], :int
22
21
  attach_function :archive_read_support_compression_program, [:pointer, :string], :int
23
22
  attach_function :archive_read_support_compression_all, [:pointer], :int
24
- attach_function :archive_read_support_format_all, [:pointer], :int
25
- # TODO: this function has been renamed to :archive_read_free in libarchive 3.0
23
+
24
+ attach_function_maybe :archive_read_set_format, [:pointer, :int], :int
25
+ attach_function_maybe :archive_read_append_filter, [:pointer, :int], :int
26
+ attach_function_maybe :archive_read_append_filter_program, [:pointer, :pointer], :int
27
+ attach_function_maybe :archive_read_append_filter_program_signature, [:pointer, :string, :pointer, :size_t], :int
28
+
29
+ attach_function_maybe :archive_read_support_filter_all, [:pointer], :int
30
+ attach_function_maybe :archive_read_support_filter_bzip2, [:pointer], :int
31
+ attach_function_maybe :archive_read_support_filter_compress, [:pointer], :int
32
+ attach_function_maybe :archive_read_support_filter_gzip, [:pointer], :int
33
+ attach_function_maybe :archive_read_support_filter_grzip, [:pointer], :int
34
+ attach_function_maybe :archive_read_support_filter_lrzip, [:pointer], :int
35
+ attach_function_maybe :archive_read_support_filter_lz4, [:pointer], :int
36
+ attach_function_maybe :archive_read_support_filter_lzip, [:pointer], :int
37
+ attach_function_maybe :archive_read_support_filter_lzma, [:pointer], :int
38
+ attach_function_maybe :archive_read_support_filter_lzop, [:pointer], :int
39
+ attach_function_maybe :archive_read_support_filter_none, [:pointer], :int
40
+ attach_function_maybe :archive_read_support_filter_program, [:pointer], :int
41
+ attach_function_maybe :archive_read_support_filter_program_signature, [:pointer], :int
42
+ attach_function_maybe :archive_read_support_filter_rpm, [:pointer], :int
43
+ attach_function_maybe :archive_read_support_filter_uu, [:pointer], :int
44
+ attach_function_maybe :archive_read_support_filter_xz, [:pointer], :int
45
+
46
+ attach_function_maybe :archive_read_support_format_all, [:pointer], :int
47
+ attach_function_maybe :archive_read_support_format_7zip, [:pointer], :int
48
+ attach_function_maybe :archive_read_support_format_ar, [:pointer], :int
49
+ attach_function_maybe :archive_read_support_format_by_code, [:pointer], :int
50
+ attach_function_maybe :archive_read_support_format_cab, [:pointer], :int
51
+ attach_function_maybe :archive_read_support_format_cpio, [:pointer], :int
52
+ attach_function_maybe :archive_read_support_format_empty, [:pointer], :int
53
+ attach_function_maybe :archive_read_support_format_gnutar, [:pointer], :int
54
+ attach_function_maybe :archive_read_support_format_iso9660, [:pointer], :int
55
+ attach_function_maybe :archive_read_support_format_lha, [:pointer], :int
56
+ attach_function_maybe :archive_read_support_format_mtree, [:pointer], :int
57
+ attach_function_maybe :archive_read_support_format_rar, [:pointer], :int
58
+ attach_function_maybe :archive_read_support_format_raw, [:pointer], :int
59
+ attach_function_maybe :archive_read_support_format_tar, [:pointer], :int
60
+ attach_function_maybe :archive_read_support_format_warc, [:pointer], :int
61
+ attach_function_maybe :archive_read_support_format_xar, [:pointer], :int
62
+ attach_function_maybe :archive_read_support_format_zip, [:pointer], :int
63
+ attach_function_maybe :archive_read_support_format_zip_streamable, [:pointer], :int
64
+ attach_function_maybe :archive_read_support_format_zip_seekable, [:pointer], :int
65
+
26
66
  attach_function :archive_read_finish, [:pointer], :int
27
67
  attach_function :archive_read_extract, [:pointer, :pointer, :int], :int
28
68
  attach_function :archive_read_header_position, [:pointer], :int
@@ -35,13 +75,11 @@ module Archive
35
75
  callback :archive_open_callback, [:pointer, :pointer], :int
36
76
  callback :archive_write_callback, [:pointer, :pointer, :pointer, :size_t], :int
37
77
  callback :archive_close_callback, [:pointer, :pointer], :int
38
- # TODO: the following function is the real definition but uses multiple callbacks. This implies that it will not work with Rubinius (currently), but luckily we only need the write-callback actually.
39
- #attach_function :archive_write_open, [:pointer, :pointer, :archive_open_callback, :archive_write_callback, :archive_close_callback], :int
40
78
  attach_function :archive_write_open, [:pointer, :pointer, :pointer, :archive_write_callback, :pointer], :int
41
- # TODO: catch errors if not defined
42
79
  attach_function :archive_write_set_compression_none, [:pointer], :int
43
80
  attach_function_maybe :archive_write_set_compression_gzip, [:pointer], :int
44
81
  attach_function_maybe :archive_write_set_compression_bzip2, [:pointer], :int
82
+ attach_function_maybe :archive_write_set_compression_deflate, [:pointer], :int
45
83
  attach_function_maybe :archive_write_set_compression_compress, [:pointer], :int
46
84
  attach_function_maybe :archive_write_set_compression_lzma, [:pointer], :int
47
85
  attach_function_maybe :archive_write_set_compression_xz, [:pointer], :int
@@ -159,10 +197,10 @@ module Archive
159
197
 
160
198
  EOF = 1
161
199
  OK = 0
162
- RETRY = (-10)
163
- WARN = (-20)
164
- FAILED = (-25)
165
- FATAL = (-30)
200
+ RETRY = -10
201
+ WARN = -20
202
+ FAILED = -25
203
+ FATAL = -30
166
204
 
167
205
  DATA_BUFFER_SIZE = 2**16
168
206
  end
@@ -176,6 +214,11 @@ module Archive
176
214
  COMPRESSION_XZ = 6
177
215
  COMPRESSION_UU = 7
178
216
  COMPRESSION_RPM = 8
217
+ COMPRESSION_LZIP = 9
218
+ COMPRESSION_LRZIP = 10
219
+ COMPRESSION_LZOP = 11
220
+ COMPRESSION_GRZIP = 12
221
+ COMPRESSION_LZ4 = 13
179
222
 
180
223
  FORMAT_BASE_MASK = 0xff0000
181
224
  FORMAT_CPIO = 0x10000
@@ -202,58 +245,67 @@ module Archive
202
245
  FORMAT_MTREE = 0x80000
203
246
  FORMAT_RAW = 0x90000
204
247
  FORMAT_XAR = 0xA0000
248
+ FORMAT_LHA = 0xB0000
249
+ FORMAT_CAB = 0xC0000
250
+ FORMAT_RAR = 0xD0000
251
+ FORMAT_7ZIP = 0xE0000
252
+ FORMAT_WARC = 0xF0000
205
253
 
206
- EXTRACT_OWNER = (0x0001)
207
- EXTRACT_PERM = (0x0002)
208
- EXTRACT_TIME = (0x0004)
209
- EXTRACT_NO_OVERWRITE = (0x0008)
210
- EXTRACT_UNLINK = (0x0010)
211
- EXTRACT_ACL = (0x0020)
212
- EXTRACT_FFLAGS = (0x0040)
213
- EXTRACT_XATTR = (0x0080)
214
- EXTRACT_SECURE_SYMLINKS = (0x0100)
215
- EXTRACT_SECURE_NODOTDOT = (0x0200)
216
- EXTRACT_NO_AUTODIR = (0x0400)
217
- EXTRACT_NO_OVERWRITE_NEWER = (0x0800)
218
- EXTRACT_SPARSE = (0x1000)
254
+ EXTRACT_OWNER = 0x0001
255
+ EXTRACT_PERM = 0x0002
256
+ EXTRACT_TIME = 0x0004
257
+ EXTRACT_NO_OVERWRITE = 0x0008
258
+ EXTRACT_UNLINK = 0x0010
259
+ EXTRACT_ACL = 0x0020
260
+ EXTRACT_FFLAGS = 0x0040
261
+ EXTRACT_XATTR = 0x0080
262
+ EXTRACT_SECURE_SYMLINKS = 0x0100
263
+ EXTRACT_SECURE_NODOTDOT = 0x0200
264
+ EXTRACT_NO_AUTODIR = 0x0400
265
+ EXTRACT_NO_OVERWRITE_NEWER = 0x0800
266
+ EXTRACT_SPARSE = 0x1000
267
+ EXTRACT_MAC_METADATA = 0x2000
268
+ EXTRACT_NO_HFS_COMPRESSION = 0x4000
269
+ EXTRACT_HFS_COMPRESSION_FORCED = 0x8000
270
+ EXTRACT_SECURE_NOABSOLUTEPATHS = 0x10000
271
+ EXTRACT_CLEAR_NOCHANGE_FFLAGS = 0x20000
219
272
 
220
- def self.read_open_filename file_name, command = nil, &block
273
+ def self.read_open_filename(file_name, command = nil, &block)
221
274
  Reader.open_filename file_name, command, &block
222
275
  end
223
276
 
224
- def self.read_open_memory string, command = nil, &block
277
+ def self.read_open_memory(string, command = nil, &block)
225
278
  Reader.open_memory string, command, &block
226
279
  end
227
280
 
228
- def self.write_open_filename file_name, compression, format, &block
281
+ def self.write_open_filename(file_name, compression, format, &block)
229
282
  Writer.open_filename file_name, compression, format, &block
230
283
  end
231
284
 
232
- def self.write_open_memory string, compression, format, &block
285
+ def self.write_open_memory(string, compression, format, &block)
233
286
  Writer.open_memory string, compression, format, &block
234
287
  end
235
288
 
236
289
  def self.version_number
237
- C::archive_version_number
290
+ C.archive_version_number
238
291
  end
239
292
 
240
293
  def self.version_string
241
- C::archive_version_string
294
+ C.archive_version_string
242
295
  end
243
296
 
244
297
  class Error < StandardError
245
298
  def initialize(archive)
246
- if archive.kind_of? String
299
+ if archive.is_a? String
247
300
  super archive
248
301
  else
249
- super "#{C::archive_error_string(archive)}"
302
+ super C.archive_error_string(archive).to_s
250
303
  end
251
304
  end
252
305
  end
253
306
 
254
307
  class BaseArchive
255
-
256
- def initialize alloc, free
308
+ def initialize(alloc, free)
257
309
  @archive = nil
258
310
  @archive_free = nil
259
311
  @archive = alloc.call
@@ -261,11 +313,11 @@ module Archive
261
313
  raise Error, @archive unless @archive
262
314
 
263
315
  @archive_free[0] = free
264
- ObjectSpace.define_finalizer( self, BaseArchive.finalizer(@archive, @archive_free) )
316
+ ObjectSpace.define_finalizer(self, BaseArchive.finalizer(@archive, @archive_free))
265
317
  end
266
318
 
267
- def self.finalizer archive, archive_free
268
- Proc.new do |*args|
319
+ def self.finalizer(archive, archive_free)
320
+ proc do |*_args|
269
321
  archive_free[0].call(archive) if archive_free[0]
270
322
  end
271
323
  end
@@ -289,12 +341,11 @@ module Archive
289
341
  protected :archive
290
342
 
291
343
  def error_string
292
- C::archive_error_string(@archive)
344
+ C.archive_error_string(@archive)
293
345
  end
294
346
 
295
347
  def errno
296
- C::archive_errno(@archive)
348
+ C.archive_errno(@archive)
297
349
  end
298
350
  end
299
-
300
351
  end