ffi-libarchive 1.0.0 → 1.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e9b6e6ed6fbbaf0e493767d47541307f64cfcffd32e23d33f0f47ab3efd6a35a
4
- data.tar.gz: c85cb44e37fdbe3bec65f7408fc7e0eb821393bec658c929f6252d2ca01c6ecf
3
+ metadata.gz: ad607029b63e0c23ad8bf7ab667c246ec99d122ae09a60430657b1fa6ddd8126
4
+ data.tar.gz: 57c455b2d4e159da7ccee28faa0f4c347d98e6b92a8ffe70b5c00e6b02a60414
5
5
  SHA512:
6
- metadata.gz: f3bf10cbcfa75efc763348bce05f35f4891717a5c8aed5ab38e5ab2cd6c0d162b179fb2c3defb9af7c6e039e12f385590e66c8534b0eafd394706afc20b7ea55
7
- data.tar.gz: 07cba89aa39ec4be250d187cb75113ae1b1f2c21b20b3854926fed0bc2f7ff413ba24c526fa5a2d2c7a3e27b2a8bc6ec2b27dfab54a6b7370c3ce8aea3c4dfc9
6
+ metadata.gz: 35b3c1c4737846dedf71efa6925f6c594ff997156cd793a2df39e001d7d874fc74f20a36f38aa0c593718c28ef9bbd64029ec28aadf6e8d2317469e002aaf330
7
+ data.tar.gz: 5d054df7e653dd6e14f1897cddd0859cdf90e3f26970f2d09701ee0a2ae8c2a89496fe1035850426f7634e01d7fad91cb5ab7b5c7392849d03c8eceace2fe15c
@@ -1,4 +1,4 @@
1
- require "ffi"
1
+ require "ffi" unless defined?(FFI)
2
2
 
3
3
  module Archive
4
4
  module C
@@ -123,6 +123,7 @@ module Archive
123
123
  attach_function :archive_write_set_bytes_in_last_block, %i{pointer int}, :int
124
124
 
125
125
  attach_function :archive_entry_new, [], :pointer
126
+ attach_function :archive_entry_clone, [:pointer], :pointer
126
127
  attach_function :archive_entry_free, [:pointer], :void
127
128
  attach_function :archive_entry_atime, [:pointer], :time_t
128
129
  attach_function :archive_entry_atime_nsec, %i{pointer time_t long}, :void
@@ -155,8 +156,8 @@ module Archive
155
156
  attach_function :archive_entry_fflags, %i{pointer pointer pointer}, :void
156
157
  attach_function :archive_entry_set_fflags, %i{pointer ulong ulong}, :void
157
158
  attach_function :archive_entry_fflags_text, [:pointer], :string
158
- attach_function :archive_entry_gid, [:pointer], :gid_t
159
- attach_function :archive_entry_set_gid, %i{pointer gid_t}, :void
159
+ attach_function :archive_entry_gid, [:pointer], :uint
160
+ attach_function :archive_entry_set_gid, %i{pointer uint}, :void
160
161
  attach_function :archive_entry_gname, [:pointer], :string
161
162
  attach_function :archive_entry_set_gname, %i{pointer string}, :void
162
163
  attach_function :archive_entry_hardlink, [:pointer], :string
@@ -185,8 +186,8 @@ module Archive
185
186
  attach_function :archive_entry_strmode, [:pointer], :string
186
187
  attach_function :archive_entry_symlink, [:pointer], :string
187
188
  attach_function :archive_entry_set_symlink, %i{pointer string}, :void
188
- attach_function :archive_entry_uid, [:pointer], :uid_t
189
- attach_function :archive_entry_set_uid, %i{pointer uid_t}, :void
189
+ attach_function :archive_entry_uid, [:pointer], :uint
190
+ attach_function :archive_entry_set_uid, %i{pointer uint}, :void
190
191
  attach_function :archive_entry_uname, [:pointer], :string
191
192
  attach_function :archive_entry_set_uname, %i{pointer string}, :void
192
193
  attach_function :archive_entry_copy_stat, %i{pointer pointer}, :void
@@ -17,14 +17,14 @@ module Archive
17
17
  CHARACTER_SPECIAL = 0020000 # character device
18
18
  FIFO = 0010000 # FIFO
19
19
 
20
- def self.from_pointer(entry)
21
- new entry
20
+ def self.from_pointer(entry, clone: false)
21
+ new entry, clone: clone
22
22
  end
23
23
 
24
- def initialize(entry = nil)
24
+ def initialize(entry = nil, clone: false)
25
25
  @entry_free = [true]
26
26
  if entry
27
- @entry = entry
27
+ @entry = clone ? C.archive_entry_clone(entry) : entry
28
28
  yield self if block_given?
29
29
  else
30
30
  @entry = C.archive_entry_new
@@ -34,7 +34,7 @@ module Archive
34
34
  result = yield self
35
35
  C.archive_entry_free(@entry)
36
36
  @entry = nil
37
- return result
37
+ result
38
38
  else
39
39
  @entry_free[0] = false
40
40
  ObjectSpace.define_finalizer(self, Entry.finalizer(@entry, @entry_free))
@@ -462,10 +462,10 @@ module Archive
462
462
  value = FFI::MemoryPointer.new :pointer
463
463
  size = FFI::MemoryPointer.new :size_t
464
464
  if C.archive_entry_xattr_next(entry, name, value, size) != C::OK
465
- return nil
465
+ nil
466
466
  else
467
467
  # TODO: someday size.read_size_t could work
468
- return [name.null? ? nil : name.read_string,
468
+ [name.null? ? nil : name.read_string,
469
469
  value.null? ? nil : value.get_string(0, size.read_ulong)]
470
470
  end
471
471
  end
@@ -2,16 +2,16 @@ module Archive
2
2
  class Reader < BaseArchive
3
3
  private_class_method :new
4
4
 
5
- def self.open_filename(file_name, command = nil)
5
+ def self.open_filename(file_name, command = nil, strip_components: 0)
6
6
  if block_given?
7
- reader = open_filename file_name, command
7
+ reader = open_filename file_name, command, strip_components: strip_components
8
8
  begin
9
9
  yield reader
10
10
  ensure
11
11
  reader.close
12
12
  end
13
13
  else
14
- new file_name: file_name, command: command
14
+ new file_name: file_name, command: command, strip_components: strip_components
15
15
  end
16
16
  end
17
17
 
@@ -41,9 +41,19 @@ module Archive
41
41
  end
42
42
  end
43
43
 
44
+ attr_reader :strip_components
45
+
44
46
  def initialize(params = {})
45
47
  super C.method(:archive_read_new), C.method(:archive_read_finish)
46
48
 
49
+ if params[:strip_components]
50
+ raise ArgumentError, "Expected Integer as strip_components" unless params[:strip_components].is_a?(Integer)
51
+
52
+ @strip_components = params[:strip_components]
53
+ else
54
+ @strip_components = 0
55
+ end
56
+
47
57
  if params[:command]
48
58
  cmd = params[:command]
49
59
  raise Error, @archive if C.archive_read_support_compression_program(archive, cmd) != C::OK
@@ -97,9 +107,16 @@ module Archive
97
107
  raise
98
108
  end
99
109
 
100
- def extract(entry, flags = 0)
110
+ def extract(entry, flags = 0, destination: nil)
101
111
  raise ArgumentError, "Expected Archive::Entry as first argument" unless entry.is_a? Entry
102
112
  raise ArgumentError, "Expected Integer as second argument" unless flags.is_a? Integer
113
+ raise ArgumentError, "Expected String as destination" if destination && !destination.is_a?(String)
114
+
115
+ if destination
116
+ # We update the pathname here so this will change for the caller as a side effect, but this seems convenient and accurate?
117
+ pathname = C.archive_entry_pathname(entry.entry)
118
+ C.archive_entry_set_pathname(entry.entry, "#{destination}/#{pathname}")
119
+ end
103
120
 
104
121
  flags |= EXTRACT_FFLAGS
105
122
  raise Error, @archive if C.archive_read_extract(archive, entry.entry, flags) != C::OK
@@ -109,11 +126,11 @@ module Archive
109
126
  raise Error, @archive if C.archive_read_header_position archive
110
127
  end
111
128
 
112
- def next_header
129
+ def next_header(clone_entry: false)
113
130
  entry_ptr = FFI::MemoryPointer.new(:pointer)
114
131
  case C.archive_read_next_header(archive, entry_ptr)
115
132
  when C::OK
116
- Entry.from_pointer entry_ptr.read_pointer
133
+ Entry.from_pointer entry_ptr.read_pointer, clone: clone_entry
117
134
  when C::EOF
118
135
  @eof = true
119
136
  nil
@@ -124,12 +141,16 @@ module Archive
124
141
 
125
142
  def each_entry
126
143
  while (entry = next_header)
144
+ next if strip_entry_components!(entry).nil?
145
+
127
146
  yield entry
128
147
  end
129
148
  end
130
149
 
131
150
  def each_entry_with_data(_size = C::DATA_BUFFER_SIZE)
132
151
  while (entry = next_header)
152
+ next if strip_entry_components!(entry).nil?
153
+
133
154
  yield entry, read_data
134
155
  end
135
156
  end
@@ -164,5 +185,57 @@ module Archive
164
185
  raise Error, @archive if C.archive_read_data_into_fd(archive, fd) != C::OK
165
186
  end
166
187
  end
188
+
189
+ private
190
+
191
+ #
192
+ # See:
193
+ # 1. https://github.com/libarchive/libarchive/blob/6a9dcf9fc429e2dc9fb08e669bf7b0bed4d5edf9/tar/read.c#L346
194
+ # 2. https://github.com/libarchive/libarchive/blob/a11f15860ae39ecdc8173243a211cdafc8ac893c/tar/util.c#L523-L535
195
+ # 3. https://github.com/libarchive/libarchive/blob/a11f15860ae39ecdc8173243a211cdafc8ac893c/tar/util.c#L554-L560
196
+ #
197
+ # @param entry [Archive::Entry]
198
+ #
199
+ # @return [Archive::Entry, nil] entry stripped or nil if entry is no longer relevant due to stripping
200
+ #
201
+ def strip_entry_components!(entry)
202
+ if strip_components > 0
203
+ name = entry.pathname
204
+ original_name = name.dup
205
+ hardlink_name = entry.hardlink
206
+ original_hardlink_name = hardlink_name.dup
207
+
208
+ strip_path_components!(name)
209
+ return if name.empty?
210
+
211
+ unless hardlink_name.nil?
212
+ strip_path_components!(hardlink_name)
213
+ return if hardlink_name.empty?
214
+ end
215
+
216
+ if name != original_name
217
+ entry.copy_pathname(name)
218
+ end
219
+ entry.copy_hardlink(hardlink_name) if hardlink_name != original_hardlink_name
220
+ end
221
+
222
+ entry
223
+ end
224
+
225
+ #
226
+ # @param path [String]
227
+ #
228
+ # @return [String]
229
+ #
230
+ def strip_path_components!(path)
231
+ if strip_components > 0
232
+ is_dir = path.end_with?("/")
233
+ updated_path = path.split("/").drop(strip_components).join("/")
234
+ updated_path = is_dir && updated_path != "" ? updated_path + "/" : updated_path
235
+ path.gsub!(path, updated_path)
236
+ else
237
+ path
238
+ end
239
+ end
167
240
  end
168
241
  end
@@ -1,3 +1,3 @@
1
1
  module Archive
2
- VERSION = "1.0.0".freeze
2
+ VERSION = "1.1.3".freeze
3
3
  end
@@ -1,6 +1,6 @@
1
1
  module Archive
2
2
  # :stopdoc:
3
- LIBPATH ||= ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
3
+ LIBPATH ||= __dir__ + ::File::SEPARATOR
4
4
  PATH ||= ::File.dirname(LIBPATH) + ::File::SEPARATOR
5
5
  # :startdoc:
6
6
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ffi-libarchive
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Bellone
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2019-12-28 00:00:00.000000000 Z
13
+ date: 2021-09-16 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: ffi
@@ -26,20 +26,6 @@ dependencies:
26
26
  - - "~>"
27
27
  - !ruby/object:Gem::Version
28
28
  version: '1.0'
29
- - !ruby/object:Gem::Dependency
30
- name: bundler
31
- requirement: !ruby/object:Gem::Requirement
32
- requirements:
33
- - - ">="
34
- - !ruby/object:Gem::Version
35
- version: '0'
36
- type: :development
37
- prerelease: false
38
- version_requirements: !ruby/object:Gem::Requirement
39
- requirements:
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- version: '0'
43
29
  description: A Ruby FFI binding to libarchive.
44
30
  email:
45
31
  - jbellone@bloomberg.net
@@ -69,14 +55,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
69
55
  requirements:
70
56
  - - ">="
71
57
  - !ruby/object:Gem::Version
72
- version: 2.4.0
58
+ version: '2.5'
73
59
  required_rubygems_version: !ruby/object:Gem::Requirement
74
60
  requirements:
75
61
  - - ">="
76
62
  - !ruby/object:Gem::Version
77
63
  version: '0'
78
64
  requirements: []
79
- rubygems_version: 3.0.3
65
+ rubygems_version: 3.1.4
80
66
  signing_key:
81
67
  specification_version: 4
82
68
  summary: A Ruby FFI binding to libarchive.