ffi-libarchive 0.1.4 → 0.2.0
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/.gitattributes +6 -0
- data/.gitignore +55 -0
- data/.rubocop.yml +41 -0
- data/.yardopts +5 -0
- data/Gemfile +10 -0
- data/README.md +7 -65
- data/Rakefile +11 -0
- data/ffi-libarchive.gemspec +25 -0
- data/lib/ffi-libarchive.rb +0 -5
- data/lib/ffi-libarchive/archive.rb +265 -265
- data/lib/ffi-libarchive/entry.rb +381 -381
- data/lib/ffi-libarchive/reader.rb +108 -108
- data/lib/ffi-libarchive/stat.rb +17 -17
- data/lib/ffi-libarchive/version.rb +3 -0
- data/lib/ffi-libarchive/writer.rb +122 -122
- metadata +52 -24
- data/History.txt +0 -18
- data/version.txt +0 -1
@@ -1,127 +1,127 @@
|
|
1
1
|
module Archive
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
def self.open_filename file_name, command = nil
|
8
|
-
if block_given?
|
9
|
-
reader = open_filename file_name, command
|
10
|
-
begin
|
11
|
-
yield reader
|
12
|
-
ensure
|
13
|
-
reader.close
|
14
|
-
end
|
15
|
-
else
|
16
|
-
new :file_name => file_name, :command => command
|
17
|
-
end
|
18
|
-
end
|
3
|
+
class Reader < BaseArchive
|
4
|
+
|
5
|
+
private_class_method :new
|
19
6
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
28
|
-
else
|
29
|
-
new :memory => string, :command => command
|
30
|
-
end
|
7
|
+
def self.open_filename file_name, command = nil
|
8
|
+
if block_given?
|
9
|
+
reader = open_filename file_name, command
|
10
|
+
begin
|
11
|
+
yield reader
|
12
|
+
ensure
|
13
|
+
reader.close
|
31
14
|
end
|
15
|
+
else
|
16
|
+
new :file_name => file_name, :command => command
|
17
|
+
end
|
18
|
+
end
|
32
19
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
raise Error, @archive if C::archive_read_support_compression_all(archive) != C::OK
|
41
|
-
end
|
42
|
-
|
43
|
-
raise Error, @archive if C::archive_read_support_format_all(archive) != C::OK
|
44
|
-
|
45
|
-
if params[:file_name]
|
46
|
-
raise Error, @archive if C::archive_read_open_filename(archive, params[:file_name], 1024) != C::OK
|
47
|
-
elsif params[:memory]
|
48
|
-
str = params[:memory]
|
49
|
-
@data = FFI::MemoryPointer.new(str.bytesize + 1)
|
50
|
-
@data.write_string str, str.bytesize
|
51
|
-
raise Error, @archive if C::archive_read_open_memory(archive, @data, str.bytesize) != C::OK
|
52
|
-
end
|
53
|
-
rescue
|
54
|
-
close
|
55
|
-
raise
|
20
|
+
def self.open_memory string, command = nil
|
21
|
+
if block_given?
|
22
|
+
reader = open_memory string, command
|
23
|
+
begin
|
24
|
+
yield reader
|
25
|
+
ensure
|
26
|
+
reader.close
|
56
27
|
end
|
28
|
+
else
|
29
|
+
new :memory => string, :command => command
|
30
|
+
end
|
31
|
+
end
|
57
32
|
|
58
|
-
|
59
|
-
|
60
|
-
|
33
|
+
def initialize params = {}
|
34
|
+
super C::method(:archive_read_new), C::method(:archive_read_finish)
|
35
|
+
|
36
|
+
if params[:command]
|
37
|
+
cmd = params[:command]
|
38
|
+
raise Error, @archive if C::archive_read_support_compression_program(archive, cmd) != C::OK
|
39
|
+
else
|
40
|
+
raise Error, @archive if C::archive_read_support_compression_all(archive) != C::OK
|
41
|
+
end
|
42
|
+
|
43
|
+
raise Error, @archive if C::archive_read_support_format_all(archive) != C::OK
|
44
|
+
|
45
|
+
if params[:file_name]
|
46
|
+
raise Error, @archive if C::archive_read_open_filename(archive, params[:file_name], 1024) != C::OK
|
47
|
+
elsif params[:memory]
|
48
|
+
str = params[:memory]
|
49
|
+
@data = FFI::MemoryPointer.new(str.bytesize + 1)
|
50
|
+
@data.write_string str, str.bytesize
|
51
|
+
raise Error, @archive if C::archive_read_open_memory(archive, @data, str.bytesize) != C::OK
|
52
|
+
end
|
53
|
+
rescue
|
54
|
+
close
|
55
|
+
raise
|
56
|
+
end
|
61
57
|
|
62
|
-
|
63
|
-
|
64
|
-
|
58
|
+
def extract entry, flags = 0
|
59
|
+
raise ArgumentError, "Expected Archive::Entry as first argument" unless entry.kind_of? Entry
|
60
|
+
raise ArgumentError, "Expected Integer as second argument" unless flags.kind_of? Integer
|
65
61
|
|
66
|
-
|
67
|
-
|
68
|
-
|
62
|
+
flags &= EXTRACT_FFLAGS
|
63
|
+
raise Error, @archive if C::archive_read_extract(archive, entry.entry, flags) != C::OK
|
64
|
+
end
|
69
65
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
when C::OK
|
74
|
-
Entry.from_pointer entry_ptr.read_pointer
|
75
|
-
when C::EOF
|
76
|
-
@eof = true
|
77
|
-
nil
|
78
|
-
else
|
79
|
-
raise Error, @archive
|
80
|
-
end
|
81
|
-
end
|
66
|
+
def header_position
|
67
|
+
raise Error, @archive if C::archive_read_header_position archive
|
68
|
+
end
|
82
69
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
70
|
+
def next_header
|
71
|
+
entry_ptr = FFI::MemoryPointer.new(:pointer)
|
72
|
+
case C::archive_read_next_header(archive, entry_ptr)
|
73
|
+
when C::OK
|
74
|
+
Entry.from_pointer entry_ptr.read_pointer
|
75
|
+
when C::EOF
|
76
|
+
@eof = true
|
77
|
+
nil
|
78
|
+
else
|
79
|
+
raise Error, @archive
|
80
|
+
end
|
81
|
+
end
|
88
82
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
83
|
+
def each_entry
|
84
|
+
while entry = next_header
|
85
|
+
yield entry
|
86
|
+
end
|
87
|
+
end
|
94
88
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
data = ""
|
101
|
-
block = data.method :concat
|
102
|
-
end
|
103
|
-
|
104
|
-
buffer = FFI::MemoryPointer.new(size)
|
105
|
-
len = 0
|
106
|
-
while (n = C::archive_read_data(archive, buffer, size)) > 0
|
107
|
-
case n
|
108
|
-
when C::FATAL, C::WARN, C::RETRY
|
109
|
-
raise Error, @archive
|
110
|
-
else
|
111
|
-
block.call buffer.get_bytes(0,n)
|
112
|
-
end
|
113
|
-
len += n
|
114
|
-
end
|
115
|
-
|
116
|
-
data || len
|
117
|
-
end
|
89
|
+
def each_entry_with_data( size = C::DATA_BUFFER_SIZE )
|
90
|
+
while entry = next_header
|
91
|
+
yield entry, read_data
|
92
|
+
end
|
93
|
+
end
|
118
94
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
95
|
+
def read_data size = C::DATA_BUFFER_SIZE, &block
|
96
|
+
raise ArgumentError, "Buffer size must be > 0 (was: #{size})" unless size.kind_of?(Integer) and size > 0
|
97
|
+
|
98
|
+
data = nil
|
99
|
+
unless block
|
100
|
+
data = ""
|
101
|
+
block = data.method :concat
|
102
|
+
end
|
103
|
+
|
104
|
+
buffer = FFI::MemoryPointer.new(size)
|
105
|
+
len = 0
|
106
|
+
while (n = C::archive_read_data(archive, buffer, size)) > 0
|
107
|
+
case n
|
108
|
+
when C::FATAL, C::WARN, C::RETRY
|
109
|
+
raise Error, @archive
|
110
|
+
else
|
111
|
+
block.call buffer.get_bytes(0,n)
|
123
112
|
end
|
113
|
+
len += n
|
114
|
+
end
|
115
|
+
|
116
|
+
data || len
|
117
|
+
end
|
124
118
|
|
119
|
+
def save_data file_name
|
120
|
+
IO.sysopen(file_name, "wb") do |fd|
|
121
|
+
raise Error, @archive if C::archive_read_data_into_fd(archive, fd) != C::OK
|
122
|
+
end
|
125
123
|
end
|
126
124
|
|
125
|
+
end
|
126
|
+
|
127
127
|
end
|
data/lib/ffi-libarchive/stat.rb
CHANGED
@@ -1,38 +1,38 @@
|
|
1
1
|
require 'ffi-inliner'
|
2
2
|
|
3
3
|
module Archive
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
4
|
+
module Stat
|
5
|
+
extend Inliner
|
6
|
+
inline do |builder|
|
7
|
+
builder.include 'stdlib.h'
|
8
|
+
builder.include 'sys/types.h'
|
9
|
+
builder.include 'sys/stat.h'
|
10
|
+
builder.include 'string.h'
|
11
|
+
builder.include 'errno.h'
|
12
|
+
builder.c %q{
|
13
13
|
void* ffi_libarchive_create_stat(const char* filename) {
|
14
14
|
struct stat* s = malloc(sizeof(struct stat));
|
15
15
|
if (stat(filename, s) != 0) return NULL;
|
16
16
|
return s;
|
17
17
|
}
|
18
|
-
|
19
|
-
|
18
|
+
}
|
19
|
+
builder.c %q{
|
20
20
|
void* ffi_libarchive_create_lstat(const char* filename) {
|
21
21
|
struct stat* s = malloc(sizeof(struct stat));
|
22
22
|
lstat(filename, s);
|
23
23
|
return s;
|
24
24
|
}
|
25
|
-
|
26
|
-
|
25
|
+
}
|
26
|
+
builder.c %q{
|
27
27
|
void ffi_libarchive_free_stat(void* s) {
|
28
28
|
free((struct stat*)s);
|
29
29
|
}
|
30
|
-
|
31
|
-
|
30
|
+
}
|
31
|
+
builder.c %q{
|
32
32
|
const char* ffi_error() {
|
33
33
|
return strerror(errno);
|
34
34
|
}
|
35
|
-
|
36
|
-
end
|
35
|
+
}
|
37
36
|
end
|
37
|
+
end
|
38
38
|
end
|
@@ -1,140 +1,140 @@
|
|
1
1
|
module Archive
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
private_class_method :new
|
6
|
-
|
7
|
-
def self.open_filename file_name, compression, format
|
8
|
-
if block_given?
|
9
|
-
writer = open_filename file_name, compression, format
|
10
|
-
begin
|
11
|
-
yield writer
|
12
|
-
ensure
|
13
|
-
writer.close
|
14
|
-
end
|
15
|
-
else
|
16
|
-
new :file_name => file_name, :compression => compression, :format => format
|
17
|
-
end
|
18
|
-
end
|
3
|
+
class Writer < BaseArchive
|
19
4
|
|
20
|
-
|
21
|
-
if block_given?
|
22
|
-
writer = open_memory string, compression, format
|
23
|
-
begin
|
24
|
-
yield writer
|
25
|
-
ensure
|
26
|
-
writer.close
|
27
|
-
end
|
28
|
-
else
|
29
|
-
if compression.kind_of? String
|
30
|
-
command = compression
|
31
|
-
compression = -1
|
32
|
-
else
|
33
|
-
command = nil
|
34
|
-
end
|
35
|
-
new :memory => string, :compression => compression, :format => format
|
36
|
-
end
|
37
|
-
end
|
5
|
+
private_class_method :new
|
38
6
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
end
|
47
|
-
|
48
|
-
format = params[:format]
|
49
|
-
case format
|
50
|
-
when Symbol
|
51
|
-
format = Archive::const_get("FORMAT_#{format.to_s.upcase}".intern)
|
52
|
-
end
|
53
|
-
|
54
|
-
raise Error, @archive if C::archive_write_set_compression(archive, compression) != C::OK
|
55
|
-
|
56
|
-
raise Error, @archive if C::archive_write_set_format(archive, format) != C::OK
|
57
|
-
|
58
|
-
if params[:file_name]
|
59
|
-
raise Error, @archive if C::archive_write_open_filename(archive, params[:file_name]) != C::OK
|
60
|
-
elsif params[:memory]
|
61
|
-
if C::archive_write_get_bytes_in_last_block(@archive) == -1
|
62
|
-
C::archive_write_set_bytes_in_last_block(archive, 1)
|
63
|
-
end
|
64
|
-
@data = write_callback params[:memory]
|
65
|
-
raise Error, @archive if C::archive_write_open(archive, nil,
|
66
|
-
nil,
|
67
|
-
@data,
|
68
|
-
nil) != C::OK
|
69
|
-
end
|
70
|
-
rescue => e
|
71
|
-
close
|
72
|
-
raise
|
7
|
+
def self.open_filename file_name, compression, format
|
8
|
+
if block_given?
|
9
|
+
writer = open_filename file_name, compression, format
|
10
|
+
begin
|
11
|
+
yield writer
|
12
|
+
ensure
|
13
|
+
writer.close
|
73
14
|
end
|
15
|
+
else
|
16
|
+
new :file_name => file_name, :compression => compression, :format => format
|
17
|
+
end
|
18
|
+
end
|
74
19
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
20
|
+
def self.open_memory string, compression, format
|
21
|
+
if block_given?
|
22
|
+
writer = open_memory string, compression, format
|
23
|
+
begin
|
24
|
+
yield writer
|
25
|
+
ensure
|
26
|
+
writer.close
|
80
27
|
end
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
result = yield entry
|
88
|
-
ensure
|
89
|
-
entry.close
|
90
|
-
end
|
91
|
-
result
|
92
|
-
else
|
93
|
-
entry
|
94
|
-
end
|
28
|
+
else
|
29
|
+
if compression.kind_of? String
|
30
|
+
command = compression
|
31
|
+
compression = -1
|
32
|
+
else
|
33
|
+
command = nil
|
95
34
|
end
|
35
|
+
new :memory => string, :compression => compression, :format => format
|
36
|
+
end
|
37
|
+
end
|
96
38
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
39
|
+
def initialize params = {}
|
40
|
+
super C::method(:archive_write_new), C::method(:archive_write_finish)
|
41
|
+
|
42
|
+
compression = params[:compression]
|
43
|
+
case compression
|
44
|
+
when Symbol
|
45
|
+
compression = Archive::const_get("COMPRESSION_#{compression.to_s.upcase}".intern)
|
46
|
+
end
|
47
|
+
|
48
|
+
format = params[:format]
|
49
|
+
case format
|
50
|
+
when Symbol
|
51
|
+
format = Archive::const_get("FORMAT_#{format.to_s.upcase}".intern)
|
52
|
+
end
|
53
|
+
|
54
|
+
raise Error, @archive if C::archive_write_set_compression(archive, compression) != C::OK
|
55
|
+
|
56
|
+
raise Error, @archive if C::archive_write_set_format(archive, format) != C::OK
|
57
|
+
|
58
|
+
if params[:file_name]
|
59
|
+
raise Error, @archive if C::archive_write_open_filename(archive, params[:file_name]) != C::OK
|
60
|
+
elsif params[:memory]
|
61
|
+
if C::archive_write_get_bytes_in_last_block(@archive) == -1
|
62
|
+
C::archive_write_set_bytes_in_last_block(archive, 1)
|
112
63
|
end
|
64
|
+
@data = write_callback params[:memory]
|
65
|
+
raise Error, @archive if C::archive_write_open(archive, nil,
|
66
|
+
nil,
|
67
|
+
@data,
|
68
|
+
nil) != C::OK
|
69
|
+
end
|
70
|
+
rescue => e
|
71
|
+
close
|
72
|
+
raise
|
73
|
+
end
|
113
74
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
str = args[0]
|
130
|
-
C::archive_write_data(archive, str, str.bytesize)
|
131
|
-
end
|
75
|
+
def write_callback data
|
76
|
+
Proc.new { |ar, client, buffer, length|
|
77
|
+
data.concat buffer.get_bytes(0,length)
|
78
|
+
length
|
79
|
+
}
|
80
|
+
end
|
81
|
+
private :write_callback
|
82
|
+
|
83
|
+
def new_entry
|
84
|
+
entry = Entry.new
|
85
|
+
if block_given?
|
86
|
+
begin
|
87
|
+
result = yield entry
|
88
|
+
ensure
|
89
|
+
entry.close
|
132
90
|
end
|
91
|
+
result
|
92
|
+
else
|
93
|
+
entry
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def add_entry &block
|
98
|
+
raise ArgumentError, "No block given" unless block_given?
|
99
|
+
|
100
|
+
entry = Entry.new
|
101
|
+
data = yield entry
|
102
|
+
if data
|
103
|
+
entry.size = data.bytesize
|
104
|
+
write_header entry
|
105
|
+
write_data data
|
106
|
+
else
|
107
|
+
write_header entry
|
108
|
+
end
|
109
|
+
nil
|
110
|
+
ensure
|
111
|
+
entry.close
|
112
|
+
end
|
133
113
|
|
134
|
-
|
135
|
-
|
114
|
+
def write_data *args
|
115
|
+
if block_given?
|
116
|
+
raise ArgumentError, "wrong number of argument (#{args.size} for 0)" if args.size > 0
|
117
|
+
|
118
|
+
ar = archive
|
119
|
+
len = 0
|
120
|
+
while true do
|
121
|
+
str = yield
|
122
|
+
if ((n = C::archive_write_data(ar, str, str.bytesize)) < 1)
|
123
|
+
return len
|
124
|
+
end
|
125
|
+
len += n
|
136
126
|
end
|
127
|
+
else
|
128
|
+
raise ArgumentError, "wrong number of argument (#{args.size}) for 1)" if args.size != 1
|
129
|
+
str = args[0]
|
130
|
+
C::archive_write_data(archive, str, str.bytesize)
|
131
|
+
end
|
132
|
+
end
|
137
133
|
|
134
|
+
def write_header entry
|
135
|
+
raise Error, @archive if C::archive_write_header(archive, entry.entry) != C::OK
|
138
136
|
end
|
139
137
|
|
138
|
+
end
|
139
|
+
|
140
140
|
end
|