seven_zip_ruby 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 ![Logo](https://raw.github.com/masamitsu-murase/seven_zip_ruby/master/resources/seven_zip_ruby_logo.png)
|
2
2
|
|
3
|
-
[![Build Status](https://travis-ci.org/masamitsu-murase/seven_zip_ruby.png?branch=master)](https://travis-ci.org/masamitsu-murase/seven_zip_ruby)
|
3
|
+
[![Build Status](https://travis-ci.org/masamitsu-murase/seven_zip_ruby.png?branch=master)](https://travis-ci.org/masamitsu-murase/seven_zip_ruby) [![Gem Version](https://badge.fury.io/rb/seven_zip_ruby.png)](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));
|