ffi-libarchive 1.0.0 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/ffi-libarchive/archive.rb +6 -5
- data/lib/ffi-libarchive/entry.rb +7 -7
- data/lib/ffi-libarchive/reader.rb +79 -6
- data/lib/ffi-libarchive/version.rb +1 -1
- data/lib/ffi-libarchive.rb +1 -1
- metadata +4 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ad607029b63e0c23ad8bf7ab667c246ec99d122ae09a60430657b1fa6ddd8126
|
4
|
+
data.tar.gz: 57c455b2d4e159da7ccee28faa0f4c347d98e6b92a8ffe70b5c00e6b02a60414
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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], :
|
159
|
-
attach_function :archive_entry_set_gid, %i{pointer
|
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], :
|
189
|
-
attach_function :archive_entry_set_uid, %i{pointer
|
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
|
data/lib/ffi-libarchive/entry.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
465
|
+
nil
|
466
466
|
else
|
467
467
|
# TODO: someday size.read_size_t could work
|
468
|
-
|
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
|
data/lib/ffi-libarchive.rb
CHANGED
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.
|
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:
|
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.
|
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.
|
65
|
+
rubygems_version: 3.1.4
|
80
66
|
signing_key:
|
81
67
|
specification_version: 4
|
82
68
|
summary: A Ruby FFI binding to libarchive.
|