seven_zip_ruby 1.1.0 → 1.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/.gitignore +1 -0
- data/.travis.yml +9 -0
- data/README.md +11 -4
- data/Rakefile +13 -1
- data/ext/seven_zip_ruby/extconf.rb +46 -5
- data/ext/seven_zip_ruby/seven_zip_archive.cpp +298 -70
- data/ext/seven_zip_ruby/seven_zip_archive.h +82 -55
- data/ext/seven_zip_ruby/util_common.cpp +28 -0
- data/ext/seven_zip_ruby/util_common.h +26 -3
- data/ext/seven_zip_ruby/utils.cpp +0 -1
- data/ext/seven_zip_ruby/win32/mutex.h +1 -1
- data/lib/seven_zip_ruby.rb +21 -10
- data/lib/seven_zip_ruby/entry_info.rb +3 -2
- data/lib/seven_zip_ruby/seven_zip_reader.rb +78 -6
- data/lib/seven_zip_ruby/seven_zip_writer.rb +108 -11
- data/lib/seven_zip_ruby/version.rb +1 -1
- data/seven_zip_ruby.gemspec +8 -0
- data/spec/seven_zip_ruby_spec.rb +138 -63
- data/spec/seven_zip_ruby_spec_helper.rb +11 -4
- metadata +5 -5
- data/ext/seven_zip_ruby/depend +0 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 576e8ef01f360932073896eb2ada1386f998f644
|
|
4
|
+
data.tar.gz: 1ec0d7e51e795d61062c969126c206025e6734d4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d46d87711429c1cdf191efdf8bed3c0077de239fe7934b8d1fa619f9fcadedd11d026b9b38dfd8a3ecf44af27e85e9be563a8df0432a24cc03939d9308e684be
|
|
7
|
+
data.tar.gz: 4164be8cbd6877ee638369385027c5ac232db25d3c784a11d9a4d80413076f8fedef31fdae86fce7ee5933ad7047ec41d853e504e39729b6a324b5aa198a7d83
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# SevenZipRuby 
|
|
2
2
|
|
|
3
|
-
[](https://travis-ci.org/masamitsu-murase/seven_zip_ruby)
|
|
3
|
+
[](https://travis-ci.org/masamitsu-murase/seven_zip_ruby) [](http://badge.fury.io/rb/seven_zip_ruby)
|
|
4
4
|
|
|
5
|
-
This is a Ruby gem library to
|
|
5
|
+
This is a Ruby gem library to extract/compress [7-Zip](http://www.7-zip.org) archives.
|
|
6
6
|
|
|
7
7
|
This extension calls the native library, 7z.dll or 7z.so, internally and it is included in this gem.
|
|
8
8
|
|
|
@@ -86,12 +86,19 @@ File.open("filename.7z", "wb") do |file|
|
|
|
86
86
|
end
|
|
87
87
|
```
|
|
88
88
|
|
|
89
|
-
## Supported
|
|
89
|
+
## Supported environment
|
|
90
|
+
|
|
91
|
+
SevenZipRuby supports the following platforms.
|
|
90
92
|
|
|
91
93
|
* Windows
|
|
92
94
|
* Linux
|
|
93
95
|
* Mac OSX
|
|
94
96
|
|
|
97
|
+
SevenZipRuby supports the following Ruby engines on each platform.
|
|
98
|
+
|
|
99
|
+
* MRI 2.0.0 and later
|
|
100
|
+
* Rubinius 2.2.1 and later
|
|
101
|
+
|
|
95
102
|
## More examples
|
|
96
103
|
|
|
97
104
|
### Extract partially
|
|
@@ -180,7 +187,7 @@ LGPL and unRAR license. Please refer to LICENSE.txt.
|
|
|
180
187
|
|
|
181
188
|
## Releases
|
|
182
189
|
|
|
183
|
-
* 1.1.0
|
|
190
|
+
* 1.1.0
|
|
184
191
|
Raise error when wrong password is specified.
|
|
185
192
|
* 1.0.0
|
|
186
193
|
Initial release.
|
data/Rakefile
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require "fileutils"
|
|
2
|
+
require "tempfile"
|
|
2
3
|
require "bundler/gem_tasks"
|
|
3
4
|
|
|
4
5
|
BINARY_FILES = [ "seven_zip_archive.so", "seven_zip_archive.bundle" ]
|
|
@@ -32,7 +33,18 @@ end
|
|
|
32
33
|
task :build_binary do
|
|
33
34
|
Dir.chdir "ext/seven_zip_ruby" do
|
|
34
35
|
FileUtils.rmtree BINARY_FILES
|
|
35
|
-
|
|
36
|
+
|
|
37
|
+
Tempfile.open([ "site", ".rb" ], Dir.pwd) do |temp|
|
|
38
|
+
temp.puts <<"EOS"
|
|
39
|
+
require('rbconfig')
|
|
40
|
+
RbConfig::CONFIG['sitearchdir'] = "../../lib"
|
|
41
|
+
EOS
|
|
42
|
+
temp.flush
|
|
43
|
+
|
|
44
|
+
sh "ruby -r#{File.expand_path(temp.path)} extconf.rb"
|
|
45
|
+
temp.unlink
|
|
46
|
+
end
|
|
47
|
+
|
|
36
48
|
sh "#{MAKE}"
|
|
37
49
|
end
|
|
38
50
|
end
|
|
@@ -4,6 +4,8 @@ require("mkmf")
|
|
|
4
4
|
require("rbconfig")
|
|
5
5
|
|
|
6
6
|
|
|
7
|
+
SO_TARGET_DIR = File.expand_path(File.join(RbConfig::CONFIG["sitearchdir"], "seven_zip_ruby"))
|
|
8
|
+
|
|
7
9
|
def create_p7zip_makefile(type)
|
|
8
10
|
config = RbConfig::CONFIG
|
|
9
11
|
|
|
@@ -64,7 +66,6 @@ def sample_cpp_source
|
|
|
64
66
|
#include <iostream>
|
|
65
67
|
|
|
66
68
|
#include <ruby.h>
|
|
67
|
-
#include <ruby/thread.h>
|
|
68
69
|
|
|
69
70
|
void test()
|
|
70
71
|
{
|
|
@@ -87,11 +88,49 @@ void test()
|
|
|
87
88
|
EOS
|
|
88
89
|
end
|
|
89
90
|
|
|
91
|
+
def sample_for_rb_thread_call_without_gvl(have_ruby_thread_h)
|
|
92
|
+
header = "#include <ruby.h>\n"
|
|
93
|
+
header += "#include <ruby/thread.h>\n" if (have_ruby_thread_h)
|
|
94
|
+
body = <<'EOS'
|
|
95
|
+
|
|
96
|
+
#include <stdio.h>
|
|
97
|
+
|
|
98
|
+
int main(int argc, char *argv[])
|
|
99
|
+
{
|
|
100
|
+
printf("%p\n", rb_thread_call_without_gvl);
|
|
101
|
+
return 0;
|
|
102
|
+
}
|
|
103
|
+
EOS
|
|
104
|
+
return header + body
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def sample_for_nullptr
|
|
108
|
+
return <<'EOS'
|
|
109
|
+
#include <stdio.h>
|
|
110
|
+
int main(int argc, char *argv[])
|
|
111
|
+
{
|
|
112
|
+
printf("%p\n", nullptr);
|
|
113
|
+
return 0;
|
|
114
|
+
}
|
|
115
|
+
EOS
|
|
116
|
+
end
|
|
117
|
+
|
|
90
118
|
def main
|
|
119
|
+
base_flag = ""
|
|
120
|
+
|
|
121
|
+
th_h = have_header("ruby/thread.h")
|
|
122
|
+
|
|
123
|
+
unless (try_compile(sample_for_rb_thread_call_without_gvl(th_h)))
|
|
124
|
+
base_flag += " -DNO_RB_THREAD_CALL_WITHOUT_GVL"
|
|
125
|
+
end
|
|
126
|
+
unless (try_compile(sample_for_nullptr))
|
|
127
|
+
base_flag += " -DNO_NULLPTR"
|
|
128
|
+
end
|
|
129
|
+
|
|
91
130
|
if (RUBY_PLATFORM.include?("mswin"))
|
|
92
131
|
# mswin32
|
|
93
132
|
$LIBS = "oleaut32.lib"
|
|
94
|
-
$CPPFLAGS = "/I.. /EHsc /DNDEBUG"
|
|
133
|
+
$CPPFLAGS = "/I.. /EHsc /DNDEBUG /DUSE_WIN32_FILE_API #{base_flag} "
|
|
95
134
|
elsif (RUBY_PLATFORM.include?("mingw"))
|
|
96
135
|
# MinGW
|
|
97
136
|
$LIBS = "-loleaut32 -static-libgcc -static-libstdc++"
|
|
@@ -101,14 +140,14 @@ def main
|
|
|
101
140
|
end
|
|
102
141
|
raise "C++11 is not supported by the compiler." unless (cpp0x_flag)
|
|
103
142
|
|
|
104
|
-
$CPPFLAGS = "-I.. #{cpp0x_flag} -DNDEBUG "
|
|
143
|
+
$CPPFLAGS = "-I.. #{cpp0x_flag} -DNDEBUG -DUSE_WIN32_FILE_API #{base_flag} "
|
|
105
144
|
else
|
|
106
145
|
cpp0x_flag = [ "", "-std=c++11", "-std=gnu++11", "-std=c++0x", "-std=gnu++0x" ].find do |opt|
|
|
107
146
|
next (try_compile(sample_cpp_source, "#{opt} -x c++ ") || try_compile(sample_cpp_source, "#{opt} "))
|
|
108
147
|
end
|
|
109
148
|
raise "C++11 is not supported by the compiler." unless (cpp0x_flag)
|
|
110
149
|
|
|
111
|
-
$CPPFLAGS = "-I.. -I../CPP/include_windows -I../CPP #{cpp0x_flag} -DNDEBUG "
|
|
150
|
+
$CPPFLAGS = "-I.. -I../CPP/include_windows -I../CPP #{cpp0x_flag} -DNDEBUG #{base_flag} "
|
|
112
151
|
|
|
113
152
|
|
|
114
153
|
ostype = check_ostype
|
|
@@ -119,7 +158,9 @@ def main
|
|
|
119
158
|
make_success = system("make 7zso")
|
|
120
159
|
raise "Failed to make p7zip" unless (make_success)
|
|
121
160
|
|
|
122
|
-
FileUtils.
|
|
161
|
+
FileUtils.mkpath(SO_TARGET_DIR)
|
|
162
|
+
FileUtils.cp("./bin/7z.so", SO_TARGET_DIR)
|
|
163
|
+
|
|
123
164
|
system("make clean_7zso")
|
|
124
165
|
end
|
|
125
166
|
end
|
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
namespace SevenZip
|
|
19
19
|
{
|
|
20
20
|
|
|
21
|
+
using namespace RubyCppUtil;
|
|
22
|
+
|
|
21
23
|
|
|
22
24
|
typedef UINT32 (WINAPI * CreateObjectFunc)(
|
|
23
25
|
const GUID *clsID,
|
|
@@ -38,7 +40,8 @@ ArchiveBase::RubyAction ArchiveBase::ACTION_END = [](){};
|
|
|
38
40
|
|
|
39
41
|
ArchiveBase::ArchiveBase()
|
|
40
42
|
: m_action_tuple(nullptr),
|
|
41
|
-
m_event_loop_running(false)
|
|
43
|
+
m_event_loop_running(false),
|
|
44
|
+
m_self(Qnil)
|
|
42
45
|
{
|
|
43
46
|
m_action_result.clear();
|
|
44
47
|
}
|
|
@@ -47,6 +50,16 @@ ArchiveBase::~ArchiveBase()
|
|
|
47
50
|
{
|
|
48
51
|
}
|
|
49
52
|
|
|
53
|
+
void ArchiveBase::setSelf(VALUE self)
|
|
54
|
+
{
|
|
55
|
+
m_self = self;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
VALUE ArchiveBase::self()
|
|
59
|
+
{
|
|
60
|
+
return m_self;
|
|
61
|
+
}
|
|
62
|
+
|
|
50
63
|
void ArchiveBase::rubyEventLoop()
|
|
51
64
|
{
|
|
52
65
|
m_action_mutex.lock();
|
|
@@ -54,7 +67,7 @@ void ArchiveBase::rubyEventLoop()
|
|
|
54
67
|
m_action_mutex.unlock();
|
|
55
68
|
|
|
56
69
|
RubyActionTuple end_tuple = std::make_pair(&ACTION_END, false);
|
|
57
|
-
RubyActionTuple *action_tuple = nullptr;
|
|
70
|
+
RubyActionTuple * volatile action_tuple = nullptr;
|
|
58
71
|
|
|
59
72
|
bool success = runNativeFuncProtect([&](){
|
|
60
73
|
MutexLocker locker(&m_action_mutex);
|
|
@@ -95,6 +108,12 @@ void ArchiveBase::rubyEventLoop()
|
|
|
95
108
|
|
|
96
109
|
m_action_mutex.lock();
|
|
97
110
|
m_event_loop_running = event_loop_running;
|
|
111
|
+
// if (m_action_tuple && m_action_tuple != &end_tuple && m_action_tuple != action_tuple){
|
|
112
|
+
// // Someone overrode m_action_tuple.
|
|
113
|
+
// // It might be killEventLoopThread. Otherwise, it might a bug.
|
|
114
|
+
// // Therefore, terminate event loop for safety.
|
|
115
|
+
// m_event_loop_running = false;
|
|
116
|
+
// }
|
|
98
117
|
m_action_tuple = nullptr;
|
|
99
118
|
m_action_cond_var.broadcast();
|
|
100
119
|
}
|
|
@@ -111,6 +130,8 @@ VALUE ArchiveBase::runProtectedRubyAction(VALUE p)
|
|
|
111
130
|
VALUE ArchiveBase::staticRubyEventLoop(void *p)
|
|
112
131
|
{
|
|
113
132
|
ArchiveBase *self = reinterpret_cast<ArchiveBase*>(p);
|
|
133
|
+
VALUE gc_guard = self->self();
|
|
134
|
+
RB_GC_GUARD(gc_guard);
|
|
114
135
|
self->rubyEventLoop();
|
|
115
136
|
return Qnil;
|
|
116
137
|
}
|
|
@@ -125,19 +146,21 @@ void ArchiveBase::startEventLoopThread()
|
|
|
125
146
|
rb_thread_create(RUBY_METHOD_FUNC(staticRubyEventLoop), this);
|
|
126
147
|
}
|
|
127
148
|
|
|
128
|
-
void ArchiveBase::cancelAction(
|
|
149
|
+
void ArchiveBase::cancelAction()
|
|
129
150
|
{
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
ArchiveBase *self = reinterpret_cast<ArchiveBase*>(p);
|
|
135
|
-
self->cancelAction();
|
|
151
|
+
// killEventLoopThread();
|
|
152
|
+
setErrorState();
|
|
136
153
|
}
|
|
137
154
|
|
|
138
|
-
void ArchiveBase::
|
|
155
|
+
void ArchiveBase::killEventLoopThread()
|
|
139
156
|
{
|
|
140
|
-
|
|
157
|
+
MutexLocker locker(&m_action_mutex);
|
|
158
|
+
if (m_event_loop_running){
|
|
159
|
+
static RubyActionTuple end_tuple;
|
|
160
|
+
end_tuple = std::make_pair(&ACTION_END, false);
|
|
161
|
+
m_action_tuple = &end_tuple; // override.
|
|
162
|
+
m_action_cond_var.broadcast();
|
|
163
|
+
}
|
|
141
164
|
}
|
|
142
165
|
|
|
143
166
|
bool ArchiveBase::runRubyActionImpl(RubyAction *action)
|
|
@@ -168,8 +191,10 @@ bool ArchiveBase::runRubyActionImpl(RubyAction *action)
|
|
|
168
191
|
return (tuple.second && m_event_loop_running);
|
|
169
192
|
}
|
|
170
193
|
|
|
171
|
-
|
|
194
|
+
template<typename T>
|
|
195
|
+
bool ArchiveBase::runRubyAction(T t)
|
|
172
196
|
{
|
|
197
|
+
RubyAction action = t;
|
|
173
198
|
return runRubyActionImpl(&action);
|
|
174
199
|
}
|
|
175
200
|
|
|
@@ -180,6 +205,7 @@ void ArchiveBase::finishRubyAction()
|
|
|
180
205
|
|
|
181
206
|
void ArchiveBase::mark()
|
|
182
207
|
{
|
|
208
|
+
rb_gc_mark(m_self);
|
|
183
209
|
m_action_result.mark();
|
|
184
210
|
}
|
|
185
211
|
|
|
@@ -199,8 +225,8 @@ void ArchiveBase::terminateEventLoopThread()
|
|
|
199
225
|
|
|
200
226
|
////////////////////////////////////////////////////////////////
|
|
201
227
|
ArchiveReader::ArchiveReader(const GUID &format_guid)
|
|
202
|
-
: m_rb_callback_proc(Qnil), m_rb_out_stream(Qnil),
|
|
203
|
-
m_processing_index((UInt32)(Int32)-1),
|
|
228
|
+
: m_rb_callback_proc(Qnil), m_rb_out_stream(Qnil),
|
|
229
|
+
m_processing_index((UInt32)(Int32)-1), m_rb_in_stream(Qnil),
|
|
204
230
|
m_format_guid(format_guid),
|
|
205
231
|
m_password_specified(false),
|
|
206
232
|
m_state(STATE_INITIAL)
|
|
@@ -258,7 +284,10 @@ VALUE ArchiveReader::open(VALUE in_stream, VALUE param)
|
|
|
258
284
|
m_rb_out_stream = Qnil;
|
|
259
285
|
m_rb_entry_info_list.clear();
|
|
260
286
|
|
|
261
|
-
VALUE password
|
|
287
|
+
VALUE password;
|
|
288
|
+
runRubyFunction([&](){
|
|
289
|
+
password = rb_hash_aref(param, ID2SYM(INTERN("password")));
|
|
290
|
+
});
|
|
262
291
|
if (NIL_P(password)){
|
|
263
292
|
m_password_specified = false;
|
|
264
293
|
}else{
|
|
@@ -365,13 +394,17 @@ VALUE ArchiveReader::getArchiveProperty()
|
|
|
365
394
|
|
|
366
395
|
checkState(STATE_OPENED, "getArchiveProperty error");
|
|
367
396
|
|
|
368
|
-
VALUE
|
|
369
|
-
ID new_id = INTERN("new");
|
|
397
|
+
VALUE ret;
|
|
370
398
|
VALUE value_list[size];
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
399
|
+
runRubyFunction([&](){
|
|
400
|
+
VALUE archive_info = rb_const_get(gSevenZipModule, INTERN("ArchiveInfo"));
|
|
401
|
+
ID new_id = INTERN("new");
|
|
402
|
+
for (unsigned int i=0; i<size; i++){
|
|
403
|
+
value_list[i] = ConvertPropToValue(variant_list[i]);
|
|
404
|
+
}
|
|
405
|
+
ret = rb_funcall2(archive_info, new_id, size, value_list);
|
|
406
|
+
});
|
|
407
|
+
return ret;
|
|
375
408
|
}
|
|
376
409
|
|
|
377
410
|
VALUE ArchiveReader::getEntryInfo(VALUE index)
|
|
@@ -384,7 +417,10 @@ VALUE ArchiveReader::getEntryInfo(VALUE index)
|
|
|
384
417
|
|
|
385
418
|
checkState(STATE_OPENED, "getEntryInfo error");
|
|
386
419
|
|
|
387
|
-
UInt32 idx
|
|
420
|
+
UInt32 idx;
|
|
421
|
+
runRubyFunction([&](){
|
|
422
|
+
idx = NUM2ULONG(index);
|
|
423
|
+
});
|
|
388
424
|
return entryInfo(idx);
|
|
389
425
|
}
|
|
390
426
|
|
|
@@ -407,7 +443,11 @@ VALUE ArchiveReader::getAllEntryInfo()
|
|
|
407
443
|
|
|
408
444
|
checkState(STATE_OPENED, "getAllEntryInfo error");
|
|
409
445
|
|
|
410
|
-
|
|
446
|
+
VALUE ret;
|
|
447
|
+
runRubyFunction([&](){
|
|
448
|
+
ret = rb_ary_new4(m_rb_entry_info_list.size(), &m_rb_entry_info_list[0]);
|
|
449
|
+
});
|
|
450
|
+
return ret;
|
|
411
451
|
}
|
|
412
452
|
|
|
413
453
|
VALUE ArchiveReader::setFileAttribute(VALUE path, VALUE attrib)
|
|
@@ -433,7 +473,10 @@ VALUE ArchiveReader::extract(VALUE index, VALUE callback_proc)
|
|
|
433
473
|
|
|
434
474
|
fillEntryInfo();
|
|
435
475
|
|
|
436
|
-
UInt32 i
|
|
476
|
+
UInt32 i;
|
|
477
|
+
runRubyFunction([&](){
|
|
478
|
+
i = NUM2ULONG(index);
|
|
479
|
+
});
|
|
437
480
|
HRESULT ret;
|
|
438
481
|
runNativeFunc([&](){
|
|
439
482
|
ArchiveExtractCallback *extract_callback = createArchiveExtractCallback();
|
|
@@ -541,35 +584,37 @@ VALUE ArchiveReader::testAll(VALUE detail)
|
|
|
541
584
|
}
|
|
542
585
|
|
|
543
586
|
if (RTEST(detail)){
|
|
544
|
-
|
|
587
|
+
VALUE ary;
|
|
588
|
+
runRubyFunction([&](){
|
|
589
|
+
using namespace NArchive::NExtract::NOperationResult;
|
|
545
590
|
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
591
|
+
VALUE unsupportedMethod = ID2SYM(INTERN("UnsupportedMethod"));
|
|
592
|
+
VALUE dataError = ID2SYM(INTERN("DataError"));
|
|
593
|
+
VALUE crcError = ID2SYM(INTERN("CrcError"));
|
|
594
|
+
|
|
595
|
+
ary = rb_ary_new2(num);
|
|
596
|
+
for (unsigned int i=0; i<m_test_result.size(); i++){
|
|
597
|
+
VALUE v;
|
|
598
|
+
switch(m_test_result[i]){
|
|
599
|
+
case kOK:
|
|
600
|
+
v = Qtrue;
|
|
601
|
+
break;
|
|
602
|
+
case kUnSupportedMethod:
|
|
603
|
+
v = unsupportedMethod;
|
|
604
|
+
break;
|
|
605
|
+
case kDataError:
|
|
606
|
+
v = dataError;
|
|
607
|
+
break;
|
|
608
|
+
case kCRCError:
|
|
609
|
+
v = crcError;
|
|
610
|
+
break;
|
|
611
|
+
default:
|
|
612
|
+
v = Qnil;
|
|
613
|
+
break;
|
|
614
|
+
}
|
|
615
|
+
rb_ary_store(ary, (long)i, v);
|
|
570
616
|
}
|
|
571
|
-
|
|
572
|
-
}
|
|
617
|
+
});
|
|
573
618
|
return ary;
|
|
574
619
|
}else{
|
|
575
620
|
using namespace NArchive::NExtract::NOperationResult;
|
|
@@ -643,17 +688,19 @@ void ArchiveReader::fillEntryInfo()
|
|
|
643
688
|
throw RubyCppUtil::RubyException("Cannot get property of items");
|
|
644
689
|
}
|
|
645
690
|
|
|
646
|
-
VALUE entry_info = rb_const_get(gSevenZipModule, INTERN("EntryInfo"));
|
|
647
|
-
ID new_id = INTERN("new");
|
|
648
691
|
m_rb_entry_info_list.resize(variant_list.size(), Qnil);
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
692
|
+
VALUE value_list[size + 1];
|
|
693
|
+
runRubyFunction([&](){
|
|
694
|
+
VALUE entry_info = rb_const_get(gSevenZipModule, INTERN("EntryInfo"));
|
|
695
|
+
ID new_id = INTERN("new");
|
|
696
|
+
for (UInt32 i=0; i<m_rb_entry_info_list.size(); i++){
|
|
697
|
+
value_list[0] = ULONG2NUM(i);
|
|
698
|
+
for (unsigned int j=0; j<size; j++){
|
|
699
|
+
value_list[j+1] = ConvertPropToValue(variant_list[i][j]);
|
|
700
|
+
}
|
|
701
|
+
m_rb_entry_info_list[i] = rb_funcall2(entry_info, new_id, size + 1, value_list);
|
|
654
702
|
}
|
|
655
|
-
|
|
656
|
-
}
|
|
703
|
+
});
|
|
657
704
|
}
|
|
658
705
|
|
|
659
706
|
void ArchiveReader::mark()
|
|
@@ -728,7 +775,10 @@ VALUE ArchiveWriter::open(VALUE out_stream, VALUE param)
|
|
|
728
775
|
m_rb_in_stream = Qnil;
|
|
729
776
|
std::vector<VALUE>().swap(m_rb_update_list);
|
|
730
777
|
|
|
731
|
-
VALUE password
|
|
778
|
+
VALUE password;
|
|
779
|
+
runRubyFunction([&](){
|
|
780
|
+
password = rb_hash_aref(param, ID2SYM(INTERN("password")));
|
|
781
|
+
});
|
|
732
782
|
if (NIL_P(password)){
|
|
733
783
|
m_password_specified = false;
|
|
734
784
|
}else{
|
|
@@ -999,7 +1049,7 @@ VALUE SevenZipWriter::method()
|
|
|
999
1049
|
|
|
1000
1050
|
VALUE SevenZipWriter::setLevel(VALUE level)
|
|
1001
1051
|
{
|
|
1002
|
-
level =
|
|
1052
|
+
level = rb_check_to_integer(level, "to_int");
|
|
1003
1053
|
if (NIL_P(level)){
|
|
1004
1054
|
throw RubyCppUtil::RubyException(rb_exc_new2(rb_eArgError, "level should be Integer"));
|
|
1005
1055
|
}
|
|
@@ -1094,11 +1144,19 @@ ArchiveOpenCallback::ArchiveOpenCallback(ArchiveReader *archive, const std::stri
|
|
|
1094
1144
|
|
|
1095
1145
|
STDMETHODIMP ArchiveOpenCallback::SetTotal(const UInt64 *files, const UInt64 *bytes)
|
|
1096
1146
|
{
|
|
1147
|
+
// This function is called periodically, so use this function as a check function of interrupt.
|
|
1148
|
+
if (m_archive->isErrorState()){
|
|
1149
|
+
return E_ABORT;
|
|
1150
|
+
}
|
|
1097
1151
|
return S_OK;
|
|
1098
1152
|
}
|
|
1099
1153
|
|
|
1100
1154
|
STDMETHODIMP ArchiveOpenCallback::SetCompleted(const UInt64 *files, const UInt64 *bytes)
|
|
1101
1155
|
{
|
|
1156
|
+
// This function is called periodically, so use this function as a check function of interrupt.
|
|
1157
|
+
if (m_archive->isErrorState()){
|
|
1158
|
+
return E_ABORT;
|
|
1159
|
+
}
|
|
1102
1160
|
return S_OK;
|
|
1103
1161
|
}
|
|
1104
1162
|
|
|
@@ -1128,6 +1186,10 @@ ArchiveExtractCallback::ArchiveExtractCallback(ArchiveReader *archive, const std
|
|
|
1128
1186
|
|
|
1129
1187
|
STDMETHODIMP ArchiveExtractCallback::SetTotal(UInt64 size)
|
|
1130
1188
|
{
|
|
1189
|
+
// This function is called periodically, so use this function as a check function of interrupt.
|
|
1190
|
+
if (m_archive->isErrorState()){
|
|
1191
|
+
return E_ABORT;
|
|
1192
|
+
}
|
|
1131
1193
|
return S_OK;
|
|
1132
1194
|
}
|
|
1133
1195
|
|
|
@@ -1135,7 +1197,7 @@ STDMETHODIMP ArchiveExtractCallback::SetCompleted(const UInt64 *completeValue)
|
|
|
1135
1197
|
{
|
|
1136
1198
|
// This function is called periodically, so use this function as a check function of interrupt.
|
|
1137
1199
|
if (m_archive->isErrorState()){
|
|
1138
|
-
return
|
|
1200
|
+
return E_ABORT;
|
|
1139
1201
|
}
|
|
1140
1202
|
return S_OK;
|
|
1141
1203
|
}
|
|
@@ -1243,13 +1305,18 @@ ArchiveUpdateCallback::ArchiveUpdateCallback(ArchiveWriter *archive, const std::
|
|
|
1243
1305
|
|
|
1244
1306
|
STDMETHODIMP ArchiveUpdateCallback::SetTotal(UInt64 size)
|
|
1245
1307
|
{
|
|
1308
|
+
// This function is called periodically, so use this function as a check function of interrupt.
|
|
1309
|
+
if (m_archive->isErrorState()){
|
|
1310
|
+
return E_ABORT;
|
|
1311
|
+
}
|
|
1246
1312
|
return S_OK;
|
|
1247
1313
|
}
|
|
1248
1314
|
|
|
1249
1315
|
STDMETHODIMP ArchiveUpdateCallback::SetCompleted(const UInt64 *completeValue)
|
|
1250
1316
|
{
|
|
1317
|
+
// This function is called periodically, so use this function as a check function of interrupt.
|
|
1251
1318
|
if (m_archive->isErrorState()){
|
|
1252
|
-
return
|
|
1319
|
+
return E_ABORT;
|
|
1253
1320
|
}
|
|
1254
1321
|
return S_OK;
|
|
1255
1322
|
}
|
|
@@ -1338,6 +1405,9 @@ STDMETHODIMP ArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PRO
|
|
|
1338
1405
|
break;
|
|
1339
1406
|
}
|
|
1340
1407
|
});
|
|
1408
|
+
if (!ret){
|
|
1409
|
+
return E_FAIL;
|
|
1410
|
+
}
|
|
1341
1411
|
|
|
1342
1412
|
return S_OK;
|
|
1343
1413
|
}
|
|
@@ -1345,10 +1415,25 @@ STDMETHODIMP ArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PRO
|
|
|
1345
1415
|
STDMETHODIMP ArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream)
|
|
1346
1416
|
{
|
|
1347
1417
|
VALUE rb_stream;
|
|
1418
|
+
std::string filepath;
|
|
1348
1419
|
VALUE proc = m_archive->callbackProc();
|
|
1349
1420
|
bool ret = m_archive->runRubyAction([&](){
|
|
1350
1421
|
VALUE info = m_archive->itemInfo(index);
|
|
1351
|
-
|
|
1422
|
+
VALUE ret_array = rb_funcall(proc, INTERN("call"), 2, ID2SYM(INTERN("stream")), info);
|
|
1423
|
+
if (NIL_P(ret_array)){
|
|
1424
|
+
rb_stream = Qnil;
|
|
1425
|
+
return;
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1428
|
+
// ret_array[0]: true: filepath
|
|
1429
|
+
// false: io
|
|
1430
|
+
if (RTEST(rb_ary_entry(ret_array, 0))){
|
|
1431
|
+
rb_stream = Qnil;
|
|
1432
|
+
VALUE path = rb_ary_entry(ret_array, 1);
|
|
1433
|
+
filepath = std::string(RSTRING_PTR(path), RSTRING_LEN(path));
|
|
1434
|
+
}else{
|
|
1435
|
+
rb_stream = rb_ary_entry(ret_array, 1);
|
|
1436
|
+
}
|
|
1352
1437
|
});
|
|
1353
1438
|
if (!ret){
|
|
1354
1439
|
m_archive->clearProcessingStream();
|
|
@@ -1357,9 +1442,15 @@ STDMETHODIMP ArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream
|
|
|
1357
1442
|
|
|
1358
1443
|
m_archive->setProcessingStream(rb_stream, index);
|
|
1359
1444
|
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1445
|
+
if (NIL_P(rb_stream) && !(filepath.empty())){
|
|
1446
|
+
FileInStream *stream = new FileInStream(filepath, m_archive);
|
|
1447
|
+
CMyComPtr<FileInStream> ptr(stream);
|
|
1448
|
+
*inStream = ptr.Detach();
|
|
1449
|
+
}else{
|
|
1450
|
+
InStream *stream = new InStream(rb_stream, m_archive);
|
|
1451
|
+
CMyComPtr<InStream> ptr(stream);
|
|
1452
|
+
*inStream = ptr.Detach();
|
|
1453
|
+
}
|
|
1363
1454
|
|
|
1364
1455
|
return S_OK;
|
|
1365
1456
|
}
|
|
@@ -1449,11 +1540,138 @@ STDMETHODIMP InStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
|
|
1449
1540
|
*processedSize = (NIL_P(str) ? 0 : RSTRING_LEN(str));
|
|
1450
1541
|
}
|
|
1451
1542
|
});
|
|
1543
|
+
if (!ret){
|
|
1544
|
+
if (processedSize){
|
|
1545
|
+
*processedSize = 0;
|
|
1546
|
+
}
|
|
1547
|
+
return E_FAIL;
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
return S_OK;
|
|
1551
|
+
}
|
|
1552
|
+
|
|
1553
|
+
////////////////////////////////////////////////////////////////
|
|
1554
|
+
FileInStream::FileInStream(const std::string &filename, ArchiveBase *archive)
|
|
1555
|
+
: m_archive(archive)
|
|
1556
|
+
#ifdef USE_WIN32_FILE_API
|
|
1557
|
+
, m_file_handle(INVALID_HANDLE_VALUE)
|
|
1558
|
+
#else
|
|
1559
|
+
, m_file(filename.c_str(), std::ios::binary)
|
|
1560
|
+
#endif
|
|
1561
|
+
{
|
|
1562
|
+
#ifdef USE_WIN32_FILE_API
|
|
1563
|
+
BSTR name = ConvertStringToBstr(filename);
|
|
1564
|
+
m_file_handle = CreateFileW(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
|
1565
|
+
FILE_ATTRIBUTE_NORMAL, NULL);
|
|
1566
|
+
SysFreeString(name);
|
|
1567
|
+
#else
|
|
1568
|
+
// Nothing to do
|
|
1569
|
+
#endif
|
|
1570
|
+
}
|
|
1571
|
+
|
|
1572
|
+
FileInStream::~FileInStream()
|
|
1573
|
+
{
|
|
1574
|
+
#ifdef USE_WIN32_FILE_API
|
|
1575
|
+
if (m_file_handle == INVALID_HANDLE_VALUE){
|
|
1576
|
+
return;
|
|
1577
|
+
}
|
|
1578
|
+
|
|
1579
|
+
CloseHandle(m_file_handle);
|
|
1580
|
+
m_file_handle = INVALID_HANDLE_VALUE;
|
|
1581
|
+
#else
|
|
1582
|
+
// Nothing to do
|
|
1583
|
+
#endif
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
STDMETHODIMP FileInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
|
1587
|
+
{
|
|
1588
|
+
#ifdef USE_WIN32_FILE_API
|
|
1589
|
+
if (m_file_handle == INVALID_HANDLE_VALUE){
|
|
1590
|
+
return E_FAIL;
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1593
|
+
DWORD method;
|
|
1594
|
+
switch(seekOrigin){
|
|
1595
|
+
case 0:
|
|
1596
|
+
method = FILE_BEGIN;
|
|
1597
|
+
break;
|
|
1598
|
+
case 1:
|
|
1599
|
+
method = FILE_CURRENT;
|
|
1600
|
+
break;
|
|
1601
|
+
case 2:
|
|
1602
|
+
method = FILE_END;
|
|
1603
|
+
break;
|
|
1604
|
+
default:
|
|
1605
|
+
return E_FAIL;
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1608
|
+
DWORD low, high;
|
|
1609
|
+
low = (DWORD)(offset & 0xFFFFFFFFUL);
|
|
1610
|
+
high = (DWORD)((offset >> 32) & 0xFFFFFFFFUL);
|
|
1611
|
+
DWORD new_low = SetFilePointer(m_file_handle, (LONG)low, (PLONG)&high, method);
|
|
1612
|
+
|
|
1613
|
+
if (newPosition){
|
|
1614
|
+
*newPosition = (((UInt64)high) << 32) + ((UInt64)new_low);
|
|
1615
|
+
}
|
|
1616
|
+
return S_OK;
|
|
1617
|
+
#else
|
|
1618
|
+
if (!m_file.is_open()){
|
|
1619
|
+
return E_FAIL;
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
std::ios::seekdir method;
|
|
1623
|
+
switch(seekOrigin){
|
|
1624
|
+
case 0:
|
|
1625
|
+
method = std::ios::beg;
|
|
1626
|
+
break;
|
|
1627
|
+
case 1:
|
|
1628
|
+
method = std::ios::cur;
|
|
1629
|
+
break;
|
|
1630
|
+
case 2:
|
|
1631
|
+
method = std::ios::end;
|
|
1632
|
+
break;
|
|
1633
|
+
default:
|
|
1634
|
+
return E_FAIL;
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1637
|
+
std::streamoff sto = offset;
|
|
1638
|
+
m_file.seekg(sto, method);
|
|
1639
|
+
if (newPosition){
|
|
1640
|
+
*newPosition = m_file.tellg();
|
|
1641
|
+
}
|
|
1642
|
+
return S_OK;
|
|
1643
|
+
#endif
|
|
1644
|
+
}
|
|
1645
|
+
|
|
1646
|
+
STDMETHODIMP FileInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
|
1647
|
+
{
|
|
1648
|
+
#ifdef USE_WIN32_FILE_API
|
|
1649
|
+
if (m_file_handle == INVALID_HANDLE_VALUE){
|
|
1650
|
+
return E_FAIL;
|
|
1651
|
+
}
|
|
1652
|
+
|
|
1653
|
+
DWORD processed_size;
|
|
1654
|
+
BOOL ret = ReadFile(m_file_handle, data, size, &processed_size, NULL);
|
|
1452
1655
|
if (!ret){
|
|
1453
1656
|
return E_FAIL;
|
|
1454
1657
|
}
|
|
1455
1658
|
|
|
1659
|
+
if (processedSize){
|
|
1660
|
+
*processedSize = processed_size;
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1456
1663
|
return S_OK;
|
|
1664
|
+
#else
|
|
1665
|
+
if (!m_file.is_open()){
|
|
1666
|
+
return E_FAIL;
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1669
|
+
m_file.read(reinterpret_cast<char*>(data), size);
|
|
1670
|
+
if (processedSize){
|
|
1671
|
+
*processedSize = m_file.gcount();
|
|
1672
|
+
}
|
|
1673
|
+
return S_OK;
|
|
1674
|
+
#endif
|
|
1457
1675
|
}
|
|
1458
1676
|
|
|
1459
1677
|
////////////////////////////////////////////////////////////////
|
|
@@ -1476,6 +1694,16 @@ STDMETHODIMP OutStream::Write(const void *data, UInt32 size, UInt32 *processedSi
|
|
|
1476
1694
|
}
|
|
1477
1695
|
});
|
|
1478
1696
|
if (!ret){
|
|
1697
|
+
if (processedSize){
|
|
1698
|
+
*processedSize = 0;
|
|
1699
|
+
}
|
|
1700
|
+
// When killEventLoopThread is called in cancelAction
|
|
1701
|
+
// return S_OK even if error occurs.
|
|
1702
|
+
//
|
|
1703
|
+
// Detail:
|
|
1704
|
+
// It seems that BZip2Encoder has a bug.
|
|
1705
|
+
// If Write method returns E_FAIL, some Events are not set in that file
|
|
1706
|
+
// because OutBuffer throws an exception in Encoder->WriteBytes.
|
|
1479
1707
|
return E_FAIL;
|
|
1480
1708
|
}
|
|
1481
1709
|
|
|
@@ -1570,7 +1798,7 @@ extern "C" void Init_seven_zip_archive(void)
|
|
|
1570
1798
|
|
|
1571
1799
|
cls = rb_define_wrapped_cpp_class_under<SevenZipReader>(mod, "SevenZipReader", rb_cObject);
|
|
1572
1800
|
rb_define_method_ext(cls, "open_impl", READER_FUNC(open, 2));
|
|
1573
|
-
rb_define_method_ext(cls, "
|
|
1801
|
+
rb_define_method_ext(cls, "close_impl", READER_FUNC(close, 0));
|
|
1574
1802
|
rb_define_method_ext(cls, "entry_num", READER_FUNC(entryNum, 0));
|
|
1575
1803
|
rb_define_method_ext(cls, "extract_impl", READER_FUNC(extract, 2));
|
|
1576
1804
|
rb_define_method_ext(cls, "extract_files_impl", READER_FUNC(extractFiles, 2));
|
|
@@ -1593,7 +1821,7 @@ extern "C" void Init_seven_zip_archive(void)
|
|
|
1593
1821
|
rb_define_method_ext(cls, "open_impl", WRITER_FUNC(open, 2));
|
|
1594
1822
|
rb_define_method_ext(cls, "add_item", WRITER_FUNC(addItem, 1));
|
|
1595
1823
|
rb_define_method_ext(cls, "compress_impl", WRITER_FUNC(compress, 1));
|
|
1596
|
-
rb_define_method_ext(cls, "
|
|
1824
|
+
rb_define_method_ext(cls, "close_impl", WRITER_FUNC(close, 0));
|
|
1597
1825
|
rb_define_method_ext(cls, "get_file_attribute", WRITER_FUNC(getFileAttribute, 1));
|
|
1598
1826
|
|
|
1599
1827
|
rb_define_method_ext(cls, "method=", WRITER_FUNC2(setMethod, 1));
|