zipruby1.9 0.3.3-mswin32

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ 2010-01-23 winebarrel
2
+
3
+ * fixes bug: [ruby-dev:40120] SEGV on zipruby with irb
4
+
5
+ 2009-06-11 winebarrel
6
+
7
+ * fixes bug: C macro mistake (reported by SHITAMORI Akira)
8
+
9
+ 2009-05-16 winebarrel
10
+
11
+ * improve Zip::Archive#add_io, replace_io, add, replace
12
+
13
+ * fixes bug: Zip::Archive#add_io, <<
14
+
15
+ * add method: Zip::Archive#add_dir
16
+
17
+ * zipruby/README.txt: fixes example code.
18
+
@@ -0,0 +1,27 @@
1
+ Copyright (C) 1999-2008 Dieter Baron and Thomas Klausner
2
+ The authors can be contacted at <libzip@nih.at>
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions
6
+ are met:
7
+ 1. Redistributions of source code must retain the above copyright
8
+ notice, this list of conditions and the following disclaimer.
9
+ 2. Redistributions in binary form must reproduce the above copyright
10
+ notice, this list of conditions and the following disclaimer in
11
+ the documentation and/or other materials provided with the
12
+ distribution.
13
+ 3. The names of the authors may not be used to endorse or promote
14
+ products derived from this software without specific prior
15
+ written permission.
16
+
17
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
18
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
21
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25
+ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,288 @@
1
+ = Zip/Ruby
2
+
3
+ Copyright (c) 2008-2010 SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
4
+
5
+ == Description
6
+
7
+ Ruby bindings for libzip.
8
+
9
+ libzip is a C library for reading, creating, and modifying zip archives.
10
+
11
+ == Project Page
12
+
13
+ http://rubyforge.org/projects/zipruby
14
+
15
+ == Install
16
+
17
+ gem install zipruby
18
+
19
+ == Download
20
+
21
+ https://rubyforge.org/frs/?group_id=6124
22
+
23
+ == Example
24
+ === reading zip archive
25
+
26
+ require 'zipruby'
27
+
28
+ Zip::Archive.open('filename.zip') do |ar|
29
+ n = ar.num_files # number of entries
30
+
31
+ n.times do |i|
32
+ entry_name = ar.get_name(i) # get entry name from archive
33
+
34
+ # open entry
35
+ ar.fopen(entry_name) do |f| # or ar.fopen(i) do |f|
36
+ name = f.name # name of the file
37
+ size = f.size # size of file (uncompressed)
38
+ comp_size = f.comp_size # size of file (compressed)
39
+
40
+ content = f.read # read entry content
41
+ end
42
+ end
43
+
44
+ # Zip::Archive includes Enumerable
45
+ entry_names = ar.map do |f|
46
+ f.name
47
+ end
48
+ end
49
+
50
+ # read huge entry
51
+ BUFSIZE = 8192
52
+
53
+ Zip::Archive.open('filename.zip') do |ar|
54
+ ar.each do |f|
55
+ buf = ''
56
+
57
+ while chunk = f.read(BUFSIZE)
58
+ buf << chunk
59
+ end
60
+ # or
61
+ # f.read do |chunk|
62
+ # buf << chunk
63
+ # end
64
+ end
65
+ end
66
+
67
+ === creating zip archive
68
+
69
+ require 'zipruby'
70
+
71
+ bar_txt = open('bar.txt')
72
+
73
+ Zip::Archive.open('filename.zip', Zip::CREATE) do |ar|
74
+ # if overwrite: ..., Zip::CREATE | Zip::TRUNC) do |ar|
75
+
76
+ ar.add_file('foo.txt') # add file to zip archive
77
+
78
+ # add file to zip archive from File object
79
+ ar << bar_txt # or ar.add_io(bar_txt)
80
+
81
+ # add file to zip archive from buffer
82
+ ar.add_buffer('zoo.txt', 'Hello, world!')
83
+ end
84
+
85
+ bar_txt.rewind
86
+
87
+ # include directory in zip archive
88
+ Zip::Archive.open('filename.zip') do |ar|
89
+ ar.add_dir('dirname')
90
+ ar.add_file('dirname/foo.txt', 'foo.txt')
91
+ # args: <entry name> , <source>
92
+
93
+ ar.add_io('dirname/bar.txt', bar_txt)
94
+ # args: <entry name> , <source>
95
+
96
+ ar.add_buffer('dirname/zoo.txt', 'Hello, world!')
97
+ # args: <entry name> , <source>
98
+ end
99
+
100
+ bar_txt.close # close file after archive closed
101
+
102
+ # add huge file
103
+ source = %w(London Bridge is falling down)
104
+
105
+ Zip::Archive.open('filename.zip') do |ar|
106
+ # lb.txt => 'LondonBridgeisfallingdown'
107
+ ar.add('lb.txt') do # add(<filename>, <mtime>)
108
+ source.shift # end of stream is nil
109
+ end
110
+ end
111
+
112
+ === modifying zip archive
113
+
114
+ require 'zipruby'
115
+
116
+ bar_txt = open('bar.txt')
117
+
118
+ Zip::Archive.open('filename.zip') do |ar|
119
+ # replace file in zip archive
120
+ ar.replace_file(0, 'foo.txt')
121
+
122
+ # replace file in zip archive with File object
123
+ ar.replace_io(1, bar_txt)
124
+
125
+ # if commit changes
126
+ # ar.commit
127
+
128
+ # replace file in zip archive with buffer
129
+ ar.replace_buffer(2, 'Hello, world!')
130
+ # or
131
+ # ar.replace_buffer('entry name', 'Hello, world!')
132
+ # if ignore case distinctions
133
+ # ar.replace_buffer('entry name', 'Hello, world!', Zip::FL_NOCASE)
134
+
135
+ # add or replace file in zip archive
136
+ ar.add_or_replace_file('zoo.txt', 'foo.txt')
137
+ end
138
+
139
+ # append comment
140
+ Zip::Archive.open('filename.zip') do |ar|
141
+ ar.comment = <<-EOS
142
+ jugem jugem gokou no surikere
143
+ kaijari suigyo no
144
+ suigyoumatsu unraimatsu furaimatsu
145
+ EOS
146
+ end
147
+
148
+ bar_txt.close # close file after archive closed
149
+
150
+ # ar1 import ar2 entries
151
+ Zip::Archive.open('ar1.zip') do |ar1|
152
+ Zip::Archive.open('ar2.zip') do |ar2|
153
+ ar1.update(ar2)
154
+ end
155
+ end
156
+
157
+ === encrypt/decrypt zip archive
158
+
159
+ require 'zipruby'
160
+
161
+ # encrypt
162
+ Zip::Archive.encrypt('filename.zip', 'password') # return true if encrypted
163
+ # or
164
+ # Zip::Archive.open('filename.zip') do |ar|
165
+ # ar.encrypt('password')
166
+ # end
167
+
168
+ # decrypt
169
+ Zip::Archive.decrypt('filename.zip', 'password') # return true if decrypted
170
+ # or
171
+ # Zip::Archive.open('filename.zip') do |ar|
172
+ # ar.decrypt('password')
173
+ # end
174
+
175
+ === modifying zip data in memory
176
+
177
+ require 'zipruby'
178
+
179
+ $stdout.binmode
180
+
181
+ buf = ''
182
+
183
+ Zip::Archive.open_buffer(buf, Zip::CREATE) do |ar|
184
+ ar.add_buffer('bar.txt', 'zoo');
185
+ end
186
+
187
+ Zip::Archive.open_buffer(buf) do |ar|
188
+ ar.each do |f|
189
+ puts f.name
190
+ end
191
+ end
192
+
193
+ # read from stream
194
+ zip_data = open('foo.zip') do |f|
195
+ f.binmode
196
+ f.read
197
+ end
198
+
199
+ stream = lambda { return zip_data.slice!(0, 256) }
200
+
201
+ Zip::Archive.open_buffer(stream) do |ar|
202
+ puts ar.num_files
203
+ end
204
+
205
+ # output huge zip data to stdout
206
+ Zip::Archive.open_buffer(zip_data) do |ar|
207
+ ar.read do |chunk|
208
+ print chunk
209
+ end
210
+ end
211
+
212
+ === adding directory recursively
213
+
214
+ require 'zipruby'
215
+
216
+ Zip::Archive.open('filename.zip', Zip::CREATE) do |ar|
217
+ ar.add_dir('dir')
218
+
219
+ Dir.glob('dir/**/*').each do |path|
220
+ if File.directory?(path)
221
+ ar.add_dir(path)
222
+ else
223
+ ar.add_file(path, path) # add_file(<entry name>, <source path>)
224
+ end
225
+ end
226
+ end
227
+
228
+ === extract all files
229
+
230
+ require 'zipruby'
231
+ require 'fileutils'
232
+
233
+ Zip::Archive.open('filename.zip') do |ar|
234
+ ar.each do |zf|
235
+ if zf.directory?
236
+ FileUtils.mkdir_p(zf.name)
237
+ else
238
+ dirname = File.dirname(zf.name)
239
+ FileUtils.mkdir_p(dirname) unless File.exist?(dirname)
240
+
241
+ open(zf.name, 'wb') do |f|
242
+ f << zf.read
243
+ end
244
+ end
245
+ end
246
+ end
247
+
248
+ == License
249
+
250
+ Copyright (c) 2008,2009 SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
251
+ All rights reserved.
252
+
253
+ Redistribution and use in source and binary forms, with or without modification,
254
+ are permitted provided that the following conditions are met:
255
+
256
+ * Redistributions of source code must retain the above copyright notice,
257
+ this list of conditions and the following disclaimer.
258
+ * Redistributions in binary form must reproduce the above copyright notice,
259
+ this list of conditions and the following disclaimer in the documentation
260
+ and/or other materials provided with the distribution.
261
+ * The names of its contributors may not be used to endorse or promote products
262
+ derived from this software without specific prior written permission.
263
+
264
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
265
+ ANY EXPRESS OR IMPLIED WARRANTIES,
266
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
267
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
268
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
269
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
270
+ OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
271
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
272
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
273
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
274
+ DAMAGE.
275
+
276
+ === libzip
277
+
278
+ Zip/Ruby contains libzip.
279
+
280
+ libzip is a C library for reading, creating, and modifying zip archives.
281
+
282
+ * distribution site:
283
+ * http://www.nih.at/libzip/
284
+ * ftp.nih.at /pub/nih/libzip
285
+
286
+ * authors:
287
+ * Dieter Baron <dillo@giga.or.at>
288
+ * Thomas Klausner <tk@giga.or.at>
@@ -0,0 +1,2471 @@
1
+ /* rdoc source */
2
+ #include <stdio.h>
3
+ #include <stdlib.h>
4
+ #include <string.h>
5
+ #include <sys/types.h>
6
+ #include <sys/stat.h>
7
+
8
+ #ifdef _WIN32
9
+ #if RUBY_VERSION_MAJOR == 1 && RUBY_VERSION_MINOR == 8
10
+ #include <windows.h>
11
+ #endif
12
+ #include <io.h>
13
+ #include <fcntl.h>
14
+ #include <share.h>
15
+ #endif
16
+
17
+ #include "tmpfile.h"
18
+ #include "ruby.h"
19
+
20
+ #ifndef _WIN32
21
+ #ifndef HAVE_MKSTEMP
22
+ int _zip_mkstemp(char *);
23
+ #define mkstemp _zip_mkstemp
24
+ #endif
25
+ #endif
26
+
27
+ static int write_from_proc(VALUE proc, int fd);
28
+ static VALUE proc_call(VALUE proc);
29
+
30
+ char *zipruby_tmpnam(void *data, int len) {
31
+ char *filnam;
32
+
33
+ #ifdef _WIN32
34
+ int fd;
35
+ char tmpdirnam[_MAX_PATH];
36
+ char tmpfilnam[_MAX_PATH];
37
+ int namlen;
38
+
39
+ memset(tmpdirnam, 0, _MAX_PATH);
40
+
41
+ if (GetTempPathA(_MAX_PATH, tmpdirnam) == 0) {
42
+ return NULL;
43
+ }
44
+
45
+ memset(tmpfilnam, 0, _MAX_PATH);
46
+
47
+ if (GetTempFileNameA(tmpdirnam, "zrb", 0, tmpfilnam) == 0) {
48
+ return NULL;
49
+ }
50
+
51
+ namlen = strlen(tmpfilnam) + 1;
52
+
53
+ if ((filnam = calloc(namlen, sizeof(char))) == NULL) {
54
+ return NULL;
55
+ }
56
+
57
+ if (strcpy_s(filnam, namlen, tmpfilnam) != 0) {
58
+ free(filnam);
59
+ return NULL;
60
+ }
61
+
62
+ if (data) {
63
+ if ((_sopen_s(&fd, filnam, _O_WRONLY | _O_BINARY, _SH_DENYRD, _S_IWRITE)) != 0) {
64
+ free(filnam);
65
+ return NULL;
66
+ }
67
+
68
+ if (len < 0) {
69
+ if (write_from_proc((VALUE) data, fd) == -1) {
70
+ free(filnam);
71
+ return NULL;
72
+ }
73
+ } else {
74
+ if (_write(fd, data, len) == -1) {
75
+ free(filnam);
76
+ return NULL;
77
+ }
78
+ }
79
+
80
+ if (_close(fd) == -1) {
81
+ free(filnam);
82
+ return NULL;
83
+ }
84
+ }
85
+ #else
86
+ int fd;
87
+ #ifdef P_tmpdir
88
+ int namlen = 16 + strlen(P_tmpdir);
89
+ char *dirnam = P_tmpdir;
90
+ #else
91
+ int namlen = 20;
92
+ char *dirnam = "/tmp";
93
+ #endif
94
+
95
+ if ((filnam = calloc(namlen, sizeof(char))) == NULL) {
96
+ return NULL;
97
+ }
98
+
99
+ strcpy(filnam, dirnam);
100
+ strcat(filnam, "/zipruby.XXXXXX");
101
+
102
+ if ((fd = mkstemp(filnam)) == -1) {
103
+ free(filnam);
104
+ return NULL;
105
+ }
106
+
107
+ if (data) {
108
+ if (len < 0) {
109
+ if (write_from_proc((VALUE) data, fd) == -1) {
110
+ free(filnam);
111
+ return NULL;
112
+ }
113
+ } else {
114
+ if (write(fd, data, len) == -1) {
115
+ free(filnam);
116
+ return NULL;
117
+ }
118
+ }
119
+ }
120
+
121
+ if (close(fd) == -1) {
122
+ free(filnam);
123
+ return NULL;
124
+ }
125
+ #endif
126
+
127
+ return filnam;
128
+ }
129
+
130
+ void zipruby_rmtmp(const char *tmpfilnam) {
131
+ struct stat st;
132
+
133
+ if (!tmpfilnam) {
134
+ return;
135
+ }
136
+
137
+ if (stat(tmpfilnam, &st) != 0) {
138
+ return;
139
+ }
140
+
141
+ #ifdef _WIN32
142
+ _unlink(tmpfilnam);
143
+ #else
144
+ unlink(tmpfilnam);
145
+ #endif
146
+ }
147
+
148
+ static int write_from_proc(VALUE proc, int fd) {
149
+ while (1) {
150
+ VALUE src = rb_protect(proc_call, proc, NULL);
151
+
152
+ if (TYPE(src) != T_STRING) {
153
+ break;
154
+ }
155
+
156
+ if (RSTRING_LEN(src) < 1) {
157
+ break;
158
+ }
159
+
160
+ #ifdef _WIN32
161
+ if (_write(fd, RSTRING_PTR(src), RSTRING_LEN(src)) == -1) {
162
+ return -1;
163
+ }
164
+ #else
165
+ if (write(fd, RSTRING_PTR(src), RSTRING_LEN(src)) == -1) {
166
+ return -1;
167
+ }
168
+ #endif
169
+ }
170
+
171
+ return 0;
172
+ }
173
+
174
+ static VALUE proc_call(VALUE proc) {
175
+ return rb_funcall(proc, rb_intern("call"), 0);
176
+ }
177
+ #ifdef _WIN32
178
+ __declspec(dllexport) void Init_zipruby(void);
179
+ #endif
180
+
181
+ #include "zipruby.h"
182
+ #include "zipruby_zip.h"
183
+ #include "zipruby_archive.h"
184
+ #include "zipruby_file.h"
185
+ #include "zipruby_stat.h"
186
+ #include "zipruby_error.h"
187
+
188
+ void Init_zipruby() {
189
+ Init_zipruby_zip();
190
+ Init_zipruby_archive();
191
+ Init_zipruby_file();
192
+ Init_zipruby_stat();
193
+ Init_zipruby_error();
194
+ }
195
+ #include <errno.h>
196
+
197
+ #include "zip.h"
198
+ #include "zipruby.h"
199
+ #include "zipruby_archive.h"
200
+ #include "zipruby_zip_source_proc.h"
201
+ #include "zipruby_zip_source_io.h"
202
+ #include "tmpfile.h"
203
+ #include "ruby.h"
204
+ #ifndef RUBY_VM
205
+ #include "rubyio.h"
206
+ #endif
207
+
208
+ static VALUE zipruby_archive_alloc(VALUE klass);
209
+ static void zipruby_archive_mark(struct zipruby_archive *p);
210
+ static void zipruby_archive_free(struct zipruby_archive *p);
211
+ static VALUE zipruby_archive_s_open(int argc, VALUE *argv, VALUE self);
212
+ static VALUE zipruby_archive_s_open_buffer(int argc, VALUE *argv, VALUE self);
213
+ static VALUE zipruby_archive_s_decrypt(VALUE self, VALUE path, VALUE password);
214
+ static VALUE zipruby_archive_s_encrypt(VALUE self, VALUE path, VALUE password);
215
+ static VALUE zipruby_archive_close(VALUE self);
216
+ static VALUE zipruby_archive_num_files(VALUE self);
217
+ static VALUE zipruby_archive_get_name(int argc, VALUE *argv, VALUE self);
218
+ static VALUE zipruby_archive_fopen(int argc, VALUE *argv, VALUE self);
219
+ static VALUE zipruby_archive_get_stat(int argc, VALUE *argv, VALUE self);
220
+ static VALUE zipruby_archive_add_buffer(VALUE self, VALUE name, VALUE source);
221
+ static VALUE zipruby_archive_add_file(int argc, VALUE *argv, VALUE self);
222
+ static VALUE zipruby_archive_add_io(int argc, VALUE *argv, VALUE self);
223
+ static VALUE zipruby_archive_add_function(int argc, VALUE *argv, VALUE self);
224
+ static VALUE zipruby_archive_replace_buffer(int argc, VALUE *argv, VALUE self);
225
+ static VALUE zipruby_archive_replace_file(int argc, VALUE* argv, VALUE self);
226
+ static VALUE zipruby_archive_replace_io(int argc, VALUE* argv, VALUE self);
227
+ static VALUE zipruby_archive_replace_function(int argc, VALUE *argv, VALUE self);
228
+ static VALUE zipruby_archive_add_or_replace_buffer(int argc, VALUE *argv, VALUE self);
229
+ static VALUE zipruby_archive_add_or_replace_file(int argc, VALUE *argv, VALUE self);
230
+ static VALUE zipruby_archive_add_or_replace_io(int argc, VALUE *argv, VALUE self);
231
+ static VALUE zipruby_archive_add_or_replace_function(int argc, VALUE *argv, VALUE self);
232
+ static VALUE zipruby_archive_update(int argc, VALUE *argv, VALUE self);
233
+ static VALUE zipruby_archive_get_comment(int argc, VALUE *argv, VALUE self);
234
+ static VALUE zipruby_archive_set_comment(VALUE self, VALUE comment);
235
+ static VALUE zipruby_archive_locate_name(int argc, VALUE *argv, VALUE self);
236
+ static VALUE zipruby_archive_get_fcomment(int argc, VALUE *argv, VALUE self);
237
+ static VALUE zipruby_archive_set_fcomment(VALUE self, VALUE index, VALUE comment);
238
+ static VALUE zipruby_archive_fdelete(VALUE self, VALUE index);
239
+ static VALUE zipruby_archive_frename(VALUE self, VALUE index, VALUE name);
240
+ static VALUE zipruby_archive_funchange(VALUE self, VALUE index);
241
+ static VALUE zipruby_archive_funchange_all(VALUE self);
242
+ static VALUE zipruby_archive_unchange(VALUE self);
243
+ static VALUE zipruby_archive_revert(VALUE self);
244
+ static VALUE zipruby_archive_each(VALUE self);
245
+ static VALUE zipruby_archive_commit(VALUE self);
246
+ static VALUE zipruby_archive_is_open(VALUE self);
247
+ static VALUE zipruby_archive_decrypt(VALUE self, VALUE password);
248
+ static VALUE zipruby_archive_encrypt(VALUE self, VALUE password);
249
+ static VALUE zipruby_archive_read(VALUE self);
250
+ static VALUE zipruby_archive_add_dir(VALUE self, VALUE name);
251
+
252
+ extern VALUE Zip;
253
+ VALUE Archive;
254
+ extern VALUE File;
255
+ extern VALUE Stat;
256
+ extern VALUE Error;
257
+
258
+ void Init_zipruby_archive() {
259
+ Archive = rb_define_class_under(Zip, "Archive", rb_cObject);
260
+ rb_define_alloc_func(Archive, zipruby_archive_alloc);
261
+ rb_include_module(Archive, rb_mEnumerable);
262
+ rb_define_singleton_method(Archive, "open", zipruby_archive_s_open, -1);
263
+ rb_define_singleton_method(Archive, "open_buffer", zipruby_archive_s_open_buffer, -1);
264
+ rb_define_singleton_method(Archive, "decrypt", zipruby_archive_s_decrypt, 2);
265
+ rb_define_singleton_method(Archive, "encrypt", zipruby_archive_s_encrypt, 2);
266
+ rb_define_method(Archive, "close", zipruby_archive_close, 0);
267
+ rb_define_method(Archive, "num_files", zipruby_archive_num_files, 0);
268
+ rb_define_method(Archive, "get_name", zipruby_archive_get_name, -1);
269
+ rb_define_method(Archive, "fopen", zipruby_archive_fopen, -1);
270
+ rb_define_method(Archive, "get_stat", zipruby_archive_get_stat, -1);
271
+ rb_define_method(Archive, "add_buffer", zipruby_archive_add_buffer, 2);
272
+ rb_define_method(Archive, "add_file", zipruby_archive_add_file, -1);
273
+ rb_define_method(Archive, "add_io", zipruby_archive_add_io, -1);
274
+ rb_define_method(Archive, "add", zipruby_archive_add_function, -1);
275
+ rb_define_method(Archive, "replace_buffer", zipruby_archive_replace_buffer, -1);
276
+ rb_define_method(Archive, "replace_file", zipruby_archive_replace_file, -1);
277
+ rb_define_method(Archive, "replace_io", zipruby_archive_replace_io, -1);
278
+ rb_define_method(Archive, "replace", zipruby_archive_replace_function, -1);
279
+ rb_define_method(Archive, "add_or_replace_buffer", zipruby_archive_add_or_replace_buffer, -1);
280
+ rb_define_method(Archive, "add_or_replace_file", zipruby_archive_add_or_replace_file, -1);
281
+ rb_define_method(Archive, "add_or_replace_io", zipruby_archive_add_or_replace_io, -1);
282
+ rb_define_method(Archive, "add_or_replace", zipruby_archive_add_or_replace_function, -1);
283
+ rb_define_method(Archive, "update", zipruby_archive_update, -1);
284
+ rb_define_method(Archive, "<<", zipruby_archive_add_io, -1);
285
+ rb_define_method(Archive, "get_comment", zipruby_archive_get_comment, -1);
286
+ rb_define_method(Archive, "comment", zipruby_archive_get_comment, -1);
287
+ rb_define_method(Archive, "comment=", zipruby_archive_set_comment, 1);
288
+ rb_define_method(Archive, "locate_name", zipruby_archive_locate_name, -1);
289
+ rb_define_method(Archive, "get_fcomment", zipruby_archive_get_fcomment, -1);
290
+ rb_define_method(Archive, "set_fcomment", zipruby_archive_set_fcomment, 2);
291
+ rb_define_method(Archive, "fdelete", zipruby_archive_fdelete, 1);
292
+ rb_define_method(Archive, "frename", zipruby_archive_frename, 2);
293
+ rb_define_method(Archive, "funchange", zipruby_archive_funchange, 1);
294
+ rb_define_method(Archive, "funchange_all", zipruby_archive_funchange_all, 0);
295
+ rb_define_method(Archive, "unchange", zipruby_archive_unchange, 0);
296
+ rb_define_method(Archive, "frevert", zipruby_archive_unchange, 1);
297
+ rb_define_method(Archive, "revert", zipruby_archive_revert, 0);
298
+ rb_define_method(Archive, "each", zipruby_archive_each, 0);
299
+ rb_define_method(Archive, "commit", zipruby_archive_commit, 0);
300
+ rb_define_method(Archive, "open?", zipruby_archive_is_open, 0);
301
+ rb_define_method(Archive, "decrypt", zipruby_archive_decrypt, 1);
302
+ rb_define_method(Archive, "encrypt", zipruby_archive_encrypt, 1);
303
+ rb_define_method(Archive, "read", zipruby_archive_read, 0);
304
+ rb_define_method(Archive, "add_dir", zipruby_archive_add_dir, 1);
305
+ }
306
+
307
+ static VALUE zipruby_archive_alloc(VALUE klass) {
308
+ struct zipruby_archive *p = ALLOC(struct zipruby_archive);
309
+
310
+ p->archive = NULL;
311
+ p->path = Qnil;
312
+ p->flags = 0;
313
+ p->tmpfilnam = NULL;
314
+ p->buffer = Qnil;
315
+ p->sources = Qnil;
316
+
317
+ return Data_Wrap_Struct(klass, zipruby_archive_mark, zipruby_archive_free, p);
318
+ }
319
+
320
+ static void zipruby_archive_mark(struct zipruby_archive *p) {
321
+ rb_gc_mark(p->path);
322
+ rb_gc_mark(p->buffer);
323
+ rb_gc_mark(p->sources);
324
+ }
325
+
326
+ static void zipruby_archive_free(struct zipruby_archive *p) {
327
+ if (p->tmpfilnam) {
328
+ zipruby_rmtmp(p->tmpfilnam);
329
+ free(p->tmpfilnam);
330
+ }
331
+
332
+ xfree(p);
333
+ }
334
+
335
+ /* */
336
+ static VALUE zipruby_archive_s_open(int argc, VALUE *argv, VALUE self) {
337
+ VALUE path, flags;
338
+ VALUE archive;
339
+ struct zipruby_archive *p_archive;
340
+ int i_flags = 0;
341
+ int errorp;
342
+
343
+ rb_scan_args(argc, argv, "11", &path, &flags);
344
+ Check_Type(path, T_STRING);
345
+
346
+ if (!NIL_P(flags)) {
347
+ i_flags = NUM2INT(flags);
348
+ }
349
+
350
+ archive = rb_funcall(Archive, rb_intern("new"), 0);
351
+ Data_Get_Struct(archive, struct zipruby_archive, p_archive);
352
+
353
+ if ((p_archive->archive = zip_open(RSTRING_PTR(path), i_flags, &errorp)) == NULL) {
354
+ char errstr[ERRSTR_BUFSIZE];
355
+ zip_error_to_str(errstr, ERRSTR_BUFSIZE, errorp, errno);
356
+ rb_raise(Error, "Open archive failed - %s: %s", RSTRING_PTR(path), errstr);
357
+ }
358
+
359
+ p_archive->path = path;
360
+ p_archive->flags = i_flags;
361
+ p_archive->sources = rb_ary_new();
362
+
363
+ if (rb_block_given_p()) {
364
+ VALUE retval;
365
+ int status;
366
+
367
+ retval = rb_protect(rb_yield, archive, &status);
368
+ zipruby_archive_close(archive);
369
+
370
+ if (status != 0) {
371
+ rb_jump_tag(status);
372
+ }
373
+
374
+ return retval;
375
+ } else {
376
+ return archive;
377
+ }
378
+ }
379
+
380
+ /* */
381
+ static VALUE zipruby_archive_s_open_buffer(int argc, VALUE *argv, VALUE self) {
382
+ VALUE buffer, flags;
383
+ VALUE archive;
384
+ struct zipruby_archive *p_archive;
385
+ void *data = NULL;
386
+ int len = 0, i_flags = 0;
387
+ int errorp;
388
+
389
+ rb_scan_args(argc, argv, "02", &buffer, &flags);
390
+
391
+ if (FIXNUM_P(buffer) && NIL_P(flags)) {
392
+ flags = buffer;
393
+ buffer = Qnil;
394
+ }
395
+
396
+ if (!NIL_P(flags)) {
397
+ i_flags = NUM2INT(flags);
398
+ }
399
+
400
+ if (i_flags & ZIP_CREATE) {
401
+ if (!NIL_P(buffer)) {
402
+ Check_Type(buffer, T_STRING);
403
+ }
404
+
405
+ i_flags = (i_flags | ZIP_TRUNC);
406
+ } else if (TYPE(buffer) == T_STRING) {
407
+ data = RSTRING_PTR(buffer);
408
+ len = RSTRING_LEN(buffer);
409
+ } else if (rb_obj_is_instance_of(buffer, rb_cProc)) {
410
+ data = (void *) buffer;
411
+ len = -1;
412
+ } else {
413
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected String or Proc)", rb_class2name(CLASS_OF(buffer)));
414
+ }
415
+
416
+ archive = rb_funcall(Archive, rb_intern("new"), 0);
417
+ Data_Get_Struct(archive, struct zipruby_archive, p_archive);
418
+
419
+ if ((p_archive->tmpfilnam = zipruby_tmpnam(data, len)) == NULL) {
420
+ rb_raise(Error, "Open archive failed: Failed to create temporary file");
421
+ }
422
+
423
+ if ((p_archive->archive = zip_open(p_archive->tmpfilnam, i_flags, &errorp)) == NULL) {
424
+ char errstr[ERRSTR_BUFSIZE];
425
+ zip_error_to_str(errstr, ERRSTR_BUFSIZE, errorp, errno);
426
+ rb_raise(Error, "Open archive failed: %s", errstr);
427
+ }
428
+
429
+ p_archive->path = rb_str_new2(p_archive->tmpfilnam);
430
+ p_archive->flags = i_flags;
431
+ p_archive->buffer = buffer;
432
+ p_archive->sources = rb_ary_new();
433
+
434
+ if (rb_block_given_p()) {
435
+ VALUE retval;
436
+ int status;
437
+
438
+ retval = rb_protect(rb_yield, archive, &status);
439
+ zipruby_archive_close(archive);
440
+
441
+ if (status != 0) {
442
+ rb_jump_tag(status);
443
+ }
444
+
445
+ return retval;
446
+ } else {
447
+ return archive;
448
+ }
449
+ }
450
+
451
+ /* */
452
+ static VALUE zipruby_archive_s_decrypt(VALUE self, VALUE path, VALUE password) {
453
+ int res;
454
+ int errorp, wrongpwd;
455
+ long pwdlen;
456
+
457
+ Check_Type(path, T_STRING);
458
+ Check_Type(password, T_STRING);
459
+ pwdlen = RSTRING_LEN(password);
460
+
461
+ if (pwdlen < 1) {
462
+ rb_raise(Error, "Decrypt archive failed - %s: Password is empty", RSTRING_PTR(path));
463
+ } else if (pwdlen > 0xff) {
464
+ rb_raise(Error, "Decrypt archive failed - %s: Password is too long", RSTRING_PTR(path));
465
+ }
466
+
467
+ res = zip_decrypt(RSTRING_PTR(path), RSTRING_PTR(password), pwdlen, &errorp, &wrongpwd);
468
+
469
+ if (res == -1) {
470
+ if (wrongpwd) {
471
+ rb_raise(Error, "Decrypt archive failed - %s: Wrong password", RSTRING_PTR(path));
472
+ } else {
473
+ char errstr[ERRSTR_BUFSIZE];
474
+ zip_error_to_str(errstr, ERRSTR_BUFSIZE, errorp, errno);
475
+ rb_raise(Error, "Decrypt archive failed - %s: %s", RSTRING_PTR(path), errstr);
476
+ }
477
+ }
478
+
479
+ return (res > 0) ? Qtrue : Qfalse;
480
+ }
481
+
482
+ /* */
483
+ static VALUE zipruby_archive_s_encrypt(VALUE self, VALUE path, VALUE password) {
484
+ int res;
485
+ int errorp;
486
+ long pwdlen;
487
+
488
+ Check_Type(path, T_STRING);
489
+ Check_Type(password, T_STRING);
490
+ pwdlen = RSTRING_LEN(password);
491
+
492
+ if (pwdlen < 1) {
493
+ rb_raise(Error, "Encrypt archive failed - %s: Password is empty", RSTRING_PTR(path));
494
+ } else if (pwdlen > 0xff) {
495
+ rb_raise(Error, "Encrypt archive failed - %s: Password is too long", RSTRING_PTR(path));
496
+ }
497
+
498
+ res = zip_encrypt(RSTRING_PTR(path), RSTRING_PTR(password), pwdlen, &errorp);
499
+
500
+ if (res == -1) {
501
+ char errstr[ERRSTR_BUFSIZE];
502
+ zip_error_to_str(errstr, ERRSTR_BUFSIZE, errorp, errno);
503
+ rb_raise(Error, "Encrypt archive failed - %s: %s", RSTRING_PTR(path), errstr);
504
+ }
505
+
506
+ return (res > 0) ? Qtrue : Qfalse;
507
+ }
508
+
509
+ /* */
510
+ static VALUE zipruby_archive_close(VALUE self) {
511
+ struct zipruby_archive *p_archive;
512
+ int changed, survivors;
513
+
514
+ if (!zipruby_archive_is_open(self)) {
515
+ return Qfalse;
516
+ }
517
+
518
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
519
+ Check_Archive(p_archive);
520
+
521
+ changed = _zip_changed(p_archive->archive, &survivors);
522
+
523
+ if (zip_close(p_archive->archive) == -1) {
524
+ zip_unchange_all(p_archive->archive);
525
+ zip_unchange_archive(p_archive->archive);
526
+ rb_raise(Error, "Close archive failed: %s", zip_strerror(p_archive->archive));
527
+ }
528
+
529
+ if (!NIL_P(p_archive->buffer) && changed) {
530
+ rb_funcall(p_archive->buffer, rb_intern("replace"), 1, rb_funcall(self, rb_intern("read"), 0));
531
+ }
532
+
533
+ zipruby_rmtmp(p_archive->tmpfilnam);
534
+ p_archive->archive = NULL;
535
+ p_archive->flags = 0;
536
+
537
+ return Qtrue;
538
+ }
539
+
540
+ /* */
541
+ static VALUE zipruby_archive_num_files(VALUE self) {
542
+ struct zipruby_archive *p_archive;
543
+ int num_files;
544
+
545
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
546
+ Check_Archive(p_archive);
547
+ num_files = zip_get_num_files(p_archive->archive);
548
+
549
+ return INT2NUM(num_files);
550
+ }
551
+
552
+ /* */
553
+ static VALUE zipruby_archive_get_name(int argc, VALUE *argv, VALUE self) {
554
+ VALUE index, flags;
555
+ struct zipruby_archive *p_archive;
556
+ int i_flags = 0;
557
+ const char *name;
558
+
559
+ rb_scan_args(argc, argv, "11", &index, &flags);
560
+ Check_Type(index, T_FIXNUM);
561
+
562
+ if (!NIL_P(flags)) {
563
+ i_flags = NUM2INT(flags);
564
+ }
565
+
566
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
567
+ Check_Archive(p_archive);
568
+
569
+ if ((name = zip_get_name(p_archive->archive, NUM2INT(index), i_flags)) == NULL) {
570
+ rb_raise(Error, "Get name failed at %d: %s", index, zip_strerror(p_archive->archive));
571
+ }
572
+
573
+ return (name != NULL) ? rb_str_new2(name) : Qnil;
574
+ }
575
+
576
+ /* */
577
+ static VALUE zipruby_archive_fopen(int argc, VALUE *argv, VALUE self) {
578
+ VALUE index, flags, stat_flags, file;
579
+
580
+ rb_scan_args(argc, argv, "12", &index, &flags, &stat_flags);
581
+ file = rb_funcall(File, rb_intern("new"), 4, self, index, flags, stat_flags);
582
+
583
+ if (rb_block_given_p()) {
584
+ VALUE retval;
585
+ int status;
586
+
587
+ retval = rb_protect(rb_yield, file, &status);
588
+ rb_funcall(file, rb_intern("close"), 0);
589
+
590
+ if (status != 0) {
591
+ rb_jump_tag(status);
592
+ }
593
+
594
+ return retval;
595
+ } else {
596
+ return file;
597
+ }
598
+ }
599
+
600
+ /* */
601
+ static VALUE zipruby_archive_get_stat(int argc, VALUE *argv, VALUE self) {
602
+ VALUE index, flags;
603
+
604
+ rb_scan_args(argc, argv, "11", &index, &flags);
605
+
606
+ return rb_funcall(Stat, rb_intern("new"), 3, self, index, flags);
607
+ }
608
+
609
+ /* */
610
+ static VALUE zipruby_archive_add_buffer(VALUE self, VALUE name, VALUE source) {
611
+ struct zipruby_archive *p_archive;
612
+ struct zip_source *zsource;
613
+ char *data;
614
+ size_t len;
615
+
616
+ Check_Type(name, T_STRING);
617
+ Check_Type(source, T_STRING);
618
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
619
+ Check_Archive(p_archive);
620
+
621
+ len = RSTRING_LEN(source);
622
+
623
+ if ((data = malloc(len)) == NULL) {
624
+ rb_raise(rb_eRuntimeError, "Add file failed: Cannot allocate memory");
625
+ }
626
+
627
+ memset(data, 0, len);
628
+ memcpy(data, RSTRING_PTR(source), len);
629
+
630
+ if ((zsource = zip_source_buffer(p_archive->archive, data, len, 1)) == NULL) {
631
+ free(data);
632
+ rb_raise(Error, "Add file failed - %s: %s", RSTRING_PTR(name), zip_strerror(p_archive->archive));
633
+ }
634
+
635
+ if (zip_add(p_archive->archive, RSTRING_PTR(name), zsource) == -1) {
636
+ zip_source_free(zsource);
637
+ zip_unchange_all(p_archive->archive);
638
+ zip_unchange_archive(p_archive->archive);
639
+ rb_raise(Error, "Add file failed - %s: %s", RSTRING_PTR(name), zip_strerror(p_archive->archive));
640
+ }
641
+
642
+ return Qnil;
643
+ }
644
+
645
+ /* */
646
+ static VALUE zipruby_archive_replace_buffer(int argc, VALUE *argv, VALUE self) {
647
+ struct zipruby_archive *p_archive;
648
+ struct zip_source *zsource;
649
+ VALUE index, source, flags;
650
+ int i_index, i_flags = 0;
651
+ char *data;
652
+ size_t len;
653
+
654
+ rb_scan_args(argc, argv, "21", &index, &source, &flags);
655
+
656
+ if (TYPE(index) != T_STRING && !FIXNUM_P(index)) {
657
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Fixnum or String)", rb_class2name(CLASS_OF(index)));
658
+ }
659
+
660
+ if (!NIL_P(flags)) {
661
+ i_flags = NUM2INT(flags);
662
+ }
663
+
664
+ Check_Type(source, T_STRING);
665
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
666
+ Check_Archive(p_archive);
667
+
668
+ if (FIXNUM_P(index)) {
669
+ i_index = NUM2INT(index);
670
+ } else if ((i_index = zip_name_locate(p_archive->archive, RSTRING_PTR(index), i_flags)) == -1) {
671
+ rb_raise(Error, "Replace file failed - %s: Archive does not contain a file", RSTRING_PTR(index));
672
+ }
673
+
674
+ len = RSTRING_LEN(source);
675
+
676
+ if ((data = malloc(len)) == NULL) {
677
+ rb_raise(rb_eRuntimeError, "Replace file failed: Cannot allocate memory");
678
+ }
679
+
680
+ memcpy(data, RSTRING_PTR(source), len);
681
+
682
+ if ((zsource = zip_source_buffer(p_archive->archive, data, len, 1)) == NULL) {
683
+ free(data);
684
+ rb_raise(Error, "Replace file failed at %d: %s", i_index, zip_strerror(p_archive->archive));
685
+ }
686
+
687
+ if (zip_replace(p_archive->archive, i_index, zsource) == -1) {
688
+ zip_source_free(zsource);
689
+ zip_unchange_all(p_archive->archive);
690
+ zip_unchange_archive(p_archive->archive);
691
+ rb_raise(Error, "Replace file failed at %d: %s", i_index, zip_strerror(p_archive->archive));
692
+ }
693
+
694
+ return Qnil;
695
+ }
696
+
697
+ /* */
698
+ static VALUE zipruby_archive_add_or_replace_buffer(int argc, VALUE *argv, VALUE self) {
699
+ struct zipruby_archive *p_archive;
700
+ VALUE name, source, flags;
701
+ int index, i_flags = 0;
702
+
703
+ rb_scan_args(argc, argv, "21", &name, &source, &flags);
704
+
705
+ if (!NIL_P(flags)) {
706
+ i_flags = NUM2INT(flags);
707
+ }
708
+
709
+ Check_Type(name, T_STRING);
710
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
711
+ Check_Archive(p_archive);
712
+
713
+ index = zip_name_locate(p_archive->archive, RSTRING_PTR(name), i_flags);
714
+
715
+ if (index >= 0) {
716
+ VALUE _args[] = { INT2NUM(index), source };
717
+ return zipruby_archive_replace_buffer(2, _args, self);
718
+ } else {
719
+ return zipruby_archive_add_buffer(self, name, source);
720
+ }
721
+ }
722
+
723
+ /* */
724
+ static VALUE zipruby_archive_add_file(int argc, VALUE *argv, VALUE self) {
725
+ VALUE name, fname;
726
+ struct zipruby_archive *p_archive;
727
+ struct zip_source *zsource;
728
+
729
+ rb_scan_args(argc, argv, "11", &name, &fname);
730
+
731
+ if (NIL_P(fname)) {
732
+ fname = name;
733
+ name = Qnil;
734
+ }
735
+
736
+ Check_Type(fname, T_STRING);
737
+
738
+ if (NIL_P(name)) {
739
+ name = rb_funcall(rb_cFile, rb_intern("basename"), 1, fname);
740
+ }
741
+
742
+ Check_Type(name, T_STRING);
743
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
744
+ Check_Archive(p_archive);
745
+
746
+ if ((zsource = zip_source_file(p_archive->archive, RSTRING_PTR(fname), 0, -1)) == NULL) {
747
+ rb_raise(Error, "Add file failed - %s: %s", RSTRING_PTR(name), zip_strerror(p_archive->archive));
748
+ }
749
+
750
+ if (zip_add(p_archive->archive, RSTRING_PTR(name), zsource) == -1) {
751
+ zip_source_free(zsource);
752
+ zip_unchange_all(p_archive->archive);
753
+ zip_unchange_archive(p_archive->archive);
754
+ rb_raise(Error, "Add file failed - %s: %s", RSTRING_PTR(name), zip_strerror(p_archive->archive));
755
+ }
756
+
757
+ return Qnil;
758
+ }
759
+
760
+ /* */
761
+ static VALUE zipruby_archive_replace_file(int argc, VALUE* argv, VALUE self) {
762
+ struct zipruby_archive *p_archive;
763
+ struct zip_source *zsource;
764
+ VALUE index, fname, flags;
765
+ int i_index, i_flags = 0;
766
+
767
+ rb_scan_args(argc, argv, "21", &index, &fname, &flags);
768
+
769
+ if (TYPE(index) != T_STRING && !FIXNUM_P(index)) {
770
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Fixnum or String)", rb_class2name(CLASS_OF(index)));
771
+ }
772
+
773
+ if (!NIL_P(flags)) {
774
+ i_flags = NUM2INT(flags);
775
+ }
776
+
777
+ Check_Type(fname, T_STRING);
778
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
779
+ Check_Archive(p_archive);
780
+
781
+ if (FIXNUM_P(index)) {
782
+ i_index = NUM2INT(index);
783
+ } else if ((i_index = zip_name_locate(p_archive->archive, RSTRING_PTR(index), i_flags)) == -1) {
784
+ rb_raise(Error, "Replace file failed - %s: Archive does not contain a file", RSTRING_PTR(index));
785
+ }
786
+
787
+ if ((zsource = zip_source_file(p_archive->archive, RSTRING_PTR(fname), 0, -1)) == NULL) {
788
+ rb_raise(Error, "Replace file failed at %d: %s", i_index, zip_strerror(p_archive->archive));
789
+ }
790
+
791
+ if (zip_replace(p_archive->archive, i_index, zsource) == -1) {
792
+ zip_source_free(zsource);
793
+ zip_unchange_all(p_archive->archive);
794
+ zip_unchange_archive(p_archive->archive);
795
+ rb_raise(Error, "Replace file failed at %d: %s", i_index, zip_strerror(p_archive->archive));
796
+ }
797
+
798
+ return Qnil;
799
+ }
800
+
801
+ /* */
802
+ static VALUE zipruby_archive_add_or_replace_file(int argc, VALUE *argv, VALUE self) {
803
+ VALUE name, fname, flags;
804
+ struct zipruby_archive *p_archive;
805
+ int index, i_flags = 0;
806
+
807
+ rb_scan_args(argc, argv, "12", &name, &fname, &flags);
808
+
809
+ if (NIL_P(flags) && FIXNUM_P(fname)) {
810
+ flags = fname;
811
+ fname = Qnil;
812
+ }
813
+
814
+ if (NIL_P(fname)) {
815
+ fname = name;
816
+ name = Qnil;
817
+ }
818
+
819
+ Check_Type(fname, T_STRING);
820
+
821
+ if (NIL_P(name)) {
822
+ name = rb_funcall(rb_cFile, rb_intern("basename"), 1, fname);
823
+ }
824
+
825
+ if (!NIL_P(flags)) {
826
+ i_flags = NUM2INT(flags);
827
+ }
828
+
829
+ Check_Type(name, T_STRING);
830
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
831
+ Check_Archive(p_archive);
832
+
833
+ index = zip_name_locate(p_archive->archive, RSTRING_PTR(name), i_flags);
834
+
835
+ if (index >= 0) {
836
+ VALUE _args[] = { INT2NUM(index), fname };
837
+ return zipruby_archive_replace_file(2, _args, self);
838
+ } else {
839
+ VALUE _args[] = { name, fname };
840
+ return zipruby_archive_add_file(2, _args, self);
841
+ }
842
+ }
843
+
844
+ /* */
845
+ static VALUE zipruby_archive_add_io(int argc, VALUE *argv, VALUE self) {
846
+ VALUE name, file, mtime;
847
+ struct zipruby_archive *p_archive;
848
+ struct zip_source *zsource;
849
+ struct read_io *z;
850
+
851
+ rb_scan_args(argc, argv, "11", &name, &file);
852
+
853
+ if (NIL_P(file)) {
854
+ file = name;
855
+ name = Qnil;
856
+ }
857
+
858
+ Check_IO(file);
859
+
860
+ if (NIL_P(name)) {
861
+ if (rb_obj_is_kind_of(file, rb_cFile)) {
862
+ name = rb_funcall(rb_cFile, rb_intern("basename"), 1, rb_funcall(file, rb_intern("path"), 0));
863
+ } else {
864
+ rb_raise(rb_eRuntimeError, "Add io failed - %s: Entry name is not given", RSTRING(rb_inspect(file)));
865
+ }
866
+ }
867
+
868
+ if (rb_obj_is_kind_of(file, rb_cFile)) {
869
+ mtime = rb_funcall(file, rb_intern("mtime"), 0);
870
+ } else {
871
+ mtime = rb_funcall(rb_cTime, rb_intern("now"), 0);
872
+ }
873
+
874
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
875
+ Check_Archive(p_archive);
876
+
877
+ if ((z = malloc(sizeof(struct read_io))) == NULL) {
878
+ zip_unchange_all(p_archive->archive);
879
+ zip_unchange_archive(p_archive->archive);
880
+ rb_raise(rb_eRuntimeError, "Add io failed - %s: Cannot allocate memory", RSTRING(rb_inspect(file)));
881
+ }
882
+
883
+ z->io = file;
884
+ rb_ary_push(p_archive->sources, file);
885
+ z->mtime = TIME2LONG(mtime);
886
+
887
+ if ((zsource = zip_source_io(p_archive->archive, z)) == NULL) {
888
+ free(z);
889
+ rb_raise(Error, "Add io failed - %s: %s", RSTRING(rb_inspect(file)), zip_strerror(p_archive->archive));
890
+ }
891
+
892
+ if (zip_add(p_archive->archive, RSTRING_PTR(name), zsource) == -1) {
893
+ zip_source_free(zsource);
894
+ zip_unchange_all(p_archive->archive);
895
+ zip_unchange_archive(p_archive->archive);
896
+ rb_raise(Error, "Add io failed - %s: %s", RSTRING_PTR(name), zip_strerror(p_archive->archive));
897
+ }
898
+
899
+ return Qnil;
900
+ }
901
+
902
+ /* */
903
+ static VALUE zipruby_archive_replace_io(int argc, VALUE *argv, VALUE self) {
904
+ VALUE file, index, flags, mtime;
905
+ struct zipruby_archive *p_archive;
906
+ struct zip_source *zsource;
907
+ struct read_io *z;
908
+ int i_index, i_flags = 0;
909
+
910
+ rb_scan_args(argc, argv, "21", &index, &file, &flags);
911
+
912
+ if (TYPE(index) != T_STRING && !FIXNUM_P(index)) {
913
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Fixnum or String)", rb_class2name(CLASS_OF(index)));
914
+ }
915
+
916
+ Check_IO(file);
917
+
918
+ if (!NIL_P(flags)) {
919
+ i_flags = NUM2INT(flags);
920
+ }
921
+
922
+ if (rb_obj_is_kind_of(file, rb_cFile)) {
923
+ mtime = rb_funcall(file, rb_intern("mtime"), 0);
924
+ } else {
925
+ mtime = rb_funcall(rb_cTime, rb_intern("now"), 0);
926
+ }
927
+
928
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
929
+ Check_Archive(p_archive);
930
+
931
+ if (FIXNUM_P(index)) {
932
+ i_index = NUM2INT(index);
933
+ } else if ((i_index = zip_name_locate(p_archive->archive, RSTRING_PTR(index), i_flags)) == -1) {
934
+ rb_raise(Error, "Replace io failed - %s: Archive does not contain a file", RSTRING_PTR(index));
935
+ }
936
+
937
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
938
+ Check_Archive(p_archive);
939
+
940
+ if ((z = malloc(sizeof(struct read_io))) == NULL) {
941
+ zip_unchange_all(p_archive->archive);
942
+ zip_unchange_archive(p_archive->archive);
943
+ rb_raise(rb_eRuntimeError, "Replace io failed at %d - %s: Cannot allocate memory", i_index, RSTRING(rb_inspect(file)));
944
+ }
945
+
946
+ z->io = file;
947
+ rb_ary_push(p_archive->sources, file);
948
+ z->mtime = TIME2LONG(mtime);
949
+
950
+ if ((zsource = zip_source_io(p_archive->archive, z)) == NULL) {
951
+ free(z);
952
+ rb_raise(Error, "Replace io failed at %d - %s: %s", i_index, RSTRING(rb_inspect(file)), zip_strerror(p_archive->archive));
953
+ }
954
+
955
+ if (zip_replace(p_archive->archive, i_index, zsource) == -1) {
956
+ zip_source_free(zsource);
957
+ zip_unchange_all(p_archive->archive);
958
+ zip_unchange_archive(p_archive->archive);
959
+ rb_raise(Error, "Replace io failed at %d - %s: %s", i_index, RSTRING(rb_inspect(file)), zip_strerror(p_archive->archive));
960
+ }
961
+
962
+ return Qnil;
963
+ }
964
+
965
+ /* */
966
+ static VALUE zipruby_archive_add_or_replace_io(int argc, VALUE *argv, VALUE self) {
967
+ VALUE name, io, flags;
968
+ struct zipruby_archive *p_archive;
969
+ int index, i_flags = 0;
970
+
971
+ rb_scan_args(argc, argv, "21", &name, &io, &flags);
972
+ Check_IO(io);
973
+
974
+ if (!NIL_P(flags)) {
975
+ i_flags = NUM2INT(flags);
976
+ }
977
+
978
+ Check_Type(name, T_STRING);
979
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
980
+ Check_Archive(p_archive);
981
+
982
+ index = zip_name_locate(p_archive->archive, RSTRING_PTR(name), i_flags);
983
+
984
+ if (index >= 0) {
985
+ VALUE _args[] = {INT2NUM(index), io, flags};
986
+ return zipruby_archive_replace_io(2, _args, self);
987
+ } else {
988
+ VALUE _args[2] = { name, io };
989
+ return zipruby_archive_add_io(2, _args, self);
990
+ }
991
+ }
992
+
993
+ /* */
994
+ static VALUE zipruby_archive_add_function(int argc, VALUE *argv, VALUE self) {
995
+ VALUE name, mtime;
996
+ struct zipruby_archive *p_archive;
997
+ struct zip_source *zsource;
998
+ struct read_proc *z;
999
+
1000
+ rb_scan_args(argc, argv, "11", &name, &mtime);
1001
+ rb_need_block();
1002
+ Check_Type(name, T_STRING);
1003
+
1004
+ if (NIL_P(mtime)) {
1005
+ mtime = rb_funcall(rb_cTime, rb_intern("now"), 0);
1006
+ } else if (!rb_obj_is_instance_of(mtime, rb_cTime)) {
1007
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Time)", rb_class2name(CLASS_OF(mtime)));
1008
+ }
1009
+
1010
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
1011
+ Check_Archive(p_archive);
1012
+
1013
+ if ((z = malloc(sizeof(struct read_proc))) == NULL) {
1014
+ zip_unchange_all(p_archive->archive);
1015
+ zip_unchange_archive(p_archive->archive);
1016
+ rb_raise(rb_eRuntimeError, "Add failed - %s: Cannot allocate memory", RSTRING_PTR(name));
1017
+ }
1018
+
1019
+ z->proc = rb_block_proc();
1020
+ rb_ary_push(p_archive->sources, z->proc);
1021
+ z->mtime = TIME2LONG(mtime);
1022
+
1023
+ if ((zsource = zip_source_proc(p_archive->archive, z)) == NULL) {
1024
+ free(z);
1025
+ rb_raise(Error, "Add failed - %s: %s", RSTRING_PTR(name), zip_strerror(p_archive->archive));
1026
+ }
1027
+
1028
+ if (zip_add(p_archive->archive, RSTRING_PTR(name), zsource) == -1) {
1029
+ zip_source_free(zsource);
1030
+ zip_unchange_all(p_archive->archive);
1031
+ zip_unchange_archive(p_archive->archive);
1032
+ rb_raise(Error, "Add file failed - %s: %s", RSTRING_PTR(name), zip_strerror(p_archive->archive));
1033
+ }
1034
+
1035
+ return Qnil;
1036
+ }
1037
+
1038
+ /* */
1039
+ static VALUE zipruby_archive_replace_function(int argc, VALUE *argv, VALUE self) {
1040
+ VALUE index, flags, mtime;
1041
+ struct zipruby_archive *p_archive;
1042
+ struct zip_source *zsource;
1043
+ struct read_proc *z;
1044
+ int i_index, i_flags = 0;
1045
+
1046
+ rb_scan_args(argc, argv, "12", &index, &mtime, &flags);
1047
+ rb_need_block();
1048
+
1049
+ if (TYPE(index) != T_STRING && !FIXNUM_P(index)) {
1050
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Fixnum or String)", rb_class2name(CLASS_OF(index)));
1051
+ }
1052
+
1053
+ if (NIL_P(mtime)) {
1054
+ mtime = rb_funcall(rb_cTime, rb_intern("now"), 0);
1055
+ } else if (!rb_obj_is_instance_of(mtime, rb_cTime)) {
1056
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Time)", rb_class2name(CLASS_OF(mtime)));
1057
+ }
1058
+
1059
+ if (!NIL_P(flags)) {
1060
+ i_flags = NUM2INT(flags);
1061
+ }
1062
+
1063
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
1064
+ Check_Archive(p_archive);
1065
+
1066
+ if (FIXNUM_P(index)) {
1067
+ i_index = NUM2INT(index);
1068
+ } else if ((i_index = zip_name_locate(p_archive->archive, RSTRING_PTR(index), i_flags)) == -1) {
1069
+ rb_raise(Error, "Replace file failed - %s: Archive does not contain a file", RSTRING_PTR(index));
1070
+ }
1071
+
1072
+ if ((z = malloc(sizeof(struct read_proc))) == NULL) {
1073
+ zip_unchange_all(p_archive->archive);
1074
+ zip_unchange_archive(p_archive->archive);
1075
+ rb_raise(rb_eRuntimeError, "Replace failed at %d: Cannot allocate memory", i_index);
1076
+ }
1077
+
1078
+ z->proc = rb_block_proc();
1079
+ rb_ary_push(p_archive->sources, z->proc);
1080
+ z->mtime = TIME2LONG(mtime);
1081
+
1082
+ if ((zsource = zip_source_proc(p_archive->archive, z)) == NULL) {
1083
+ free(z);
1084
+ rb_raise(Error, "Replace failed at %d: %s", i_index, zip_strerror(p_archive->archive));
1085
+ }
1086
+
1087
+ if (zip_replace(p_archive->archive, i_index, zsource) == -1) {
1088
+ zip_source_free(zsource);
1089
+ zip_unchange_all(p_archive->archive);
1090
+ zip_unchange_archive(p_archive->archive);
1091
+ rb_raise(Error, "Replace failed at %d: %s", i_index, zip_strerror(p_archive->archive));
1092
+ }
1093
+
1094
+ return Qnil;
1095
+ }
1096
+
1097
+ /* */
1098
+ static VALUE zipruby_archive_add_or_replace_function(int argc, VALUE *argv, VALUE self) {
1099
+ VALUE name, mtime, flags;
1100
+ struct zipruby_archive *p_archive;
1101
+ int index, i_flags = 0;
1102
+
1103
+ rb_scan_args(argc, argv, "12", &name, &mtime, &flags);
1104
+
1105
+ if (NIL_P(flags) && FIXNUM_P(mtime)) {
1106
+ flags = mtime;
1107
+ mtime = Qnil;
1108
+ }
1109
+
1110
+ if (!NIL_P(flags)) {
1111
+ i_flags = NUM2INT(flags);
1112
+ }
1113
+
1114
+ Check_Type(name, T_STRING);
1115
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
1116
+ Check_Archive(p_archive);
1117
+
1118
+ index = zip_name_locate(p_archive->archive, RSTRING_PTR(name), i_flags);
1119
+
1120
+ if (index >= 0) {
1121
+ VALUE _args[] = { INT2NUM(index), mtime };
1122
+ return zipruby_archive_replace_function(2, _args, self);
1123
+ } else {
1124
+ VALUE _args[] = { name, mtime };
1125
+ return zipruby_archive_add_function(2, _args, self);
1126
+ }
1127
+ }
1128
+
1129
+ /* */
1130
+ static VALUE zipruby_archive_update(int argc, VALUE *argv, VALUE self) {
1131
+ struct zipruby_archive *p_archive, *p_srcarchive;
1132
+ VALUE srcarchive, flags;
1133
+ int i, num_files, i_flags = 0;
1134
+
1135
+ rb_scan_args(argc, argv, "11", &srcarchive, &flags);
1136
+
1137
+ if (!rb_obj_is_instance_of(srcarchive, Archive)) {
1138
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Zip::Archive)", rb_class2name(CLASS_OF(srcarchive)));
1139
+ }
1140
+
1141
+ if (!NIL_P(flags)) {
1142
+ i_flags = NUM2INT(flags);
1143
+ }
1144
+
1145
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
1146
+ Check_Archive(p_archive);
1147
+ Data_Get_Struct(srcarchive, struct zipruby_archive, p_srcarchive);
1148
+ Check_Archive(p_srcarchive);
1149
+
1150
+ num_files = zip_get_num_files(p_srcarchive->archive);
1151
+
1152
+ for (i = 0; i < num_files; i++) {
1153
+ struct zip_source *zsource;
1154
+ struct zip_file *fzip;
1155
+ struct zip_stat sb;
1156
+ char *buf;
1157
+ const char *name;
1158
+ int index, error;
1159
+
1160
+ zip_stat_init(&sb);
1161
+
1162
+ if (zip_stat_index(p_srcarchive->archive, i, 0, &sb)) {
1163
+ zip_unchange_all(p_archive->archive);
1164
+ zip_unchange_archive(p_archive->archive);
1165
+ rb_raise(Error, "Update archive failed: %s", zip_strerror(p_srcarchive->archive));
1166
+ }
1167
+
1168
+ if ((buf = malloc(sb.size)) == NULL) {
1169
+ zip_unchange_all(p_archive->archive);
1170
+ zip_unchange_archive(p_archive->archive);
1171
+ rb_raise(rb_eRuntimeError, "Update archive failed: Cannot allocate memory");
1172
+ }
1173
+
1174
+ fzip = zip_fopen_index(p_srcarchive->archive, i, 0);
1175
+
1176
+ if (fzip == NULL) {
1177
+ free(buf);
1178
+ zip_unchange_all(p_archive->archive);
1179
+ zip_unchange_archive(p_archive->archive);
1180
+ rb_raise(Error, "Update archive failed: %s", zip_strerror(p_srcarchive->archive));
1181
+ }
1182
+
1183
+ if (zip_fread(fzip, buf, sb.size) == -1) {
1184
+ free(buf);
1185
+ zip_fclose(fzip);
1186
+ zip_unchange_all(p_archive->archive);
1187
+ zip_unchange_archive(p_archive->archive);
1188
+ rb_raise(Error, "Update archive failed: %s", zip_file_strerror(fzip));
1189
+ }
1190
+
1191
+ if ((error = zip_fclose(fzip)) != 0) {
1192
+ char errstr[ERRSTR_BUFSIZE];
1193
+ free(buf);
1194
+ zip_unchange_all(p_archive->archive);
1195
+ zip_unchange_archive(p_archive->archive);
1196
+ zip_error_to_str(errstr, ERRSTR_BUFSIZE, error, errno);
1197
+ rb_raise(Error, "Update archive failed: %s", errstr);
1198
+ }
1199
+
1200
+ if ((zsource = zip_source_buffer(p_archive->archive, buf, sb.size, 1)) == NULL) {
1201
+ free(buf);
1202
+ zip_unchange_all(p_archive->archive);
1203
+ zip_unchange_archive(p_archive->archive);
1204
+ rb_raise(Error, "Update archive failed: %s", zip_strerror(p_archive->archive));
1205
+ }
1206
+
1207
+ if ((name = zip_get_name(p_srcarchive->archive, i, 0)) == NULL) {
1208
+ zip_source_free(zsource);
1209
+ zip_unchange_all(p_archive->archive);
1210
+ zip_unchange_archive(p_archive->archive);
1211
+ rb_raise(Error, "Update archive failed: %s", zip_strerror(p_srcarchive->archive));
1212
+ }
1213
+
1214
+ index = zip_name_locate(p_archive->archive, name, i_flags);
1215
+
1216
+ if (index >= 0) {
1217
+ if (zip_replace(p_archive->archive, i, zsource) == -1) {
1218
+ zip_source_free(zsource);
1219
+ zip_unchange_all(p_archive->archive);
1220
+ zip_unchange_archive(p_archive->archive);
1221
+ rb_raise(Error, "Update archive failed: %s", zip_strerror(p_archive->archive));
1222
+ }
1223
+ } else {
1224
+ if (zip_add(p_archive->archive, name, zsource) == -1) {
1225
+ zip_source_free(zsource);
1226
+ zip_unchange_all(p_archive->archive);
1227
+ zip_unchange_archive(p_archive->archive);
1228
+ rb_raise(Error, "Update archive failed: %s", zip_strerror(p_archive->archive));
1229
+ }
1230
+ }
1231
+ }
1232
+
1233
+ return Qnil;
1234
+ }
1235
+
1236
+ /* */
1237
+ static VALUE zipruby_archive_get_comment(int argc, VALUE *argv, VALUE self) {
1238
+ VALUE flags;
1239
+ struct zipruby_archive *p_archive;
1240
+ const char *comment;
1241
+ int lenp, i_flags = 0;
1242
+
1243
+ rb_scan_args(argc, argv, "01", &flags);
1244
+
1245
+ if (!NIL_P(flags)) {
1246
+ i_flags = NUM2INT(flags);
1247
+ }
1248
+
1249
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
1250
+ Check_Archive(p_archive);
1251
+
1252
+ // XXX: How is the error checked?
1253
+ comment = zip_get_archive_comment(p_archive->archive, &lenp, i_flags);
1254
+
1255
+ return comment ? rb_str_new(comment, lenp) : Qnil;
1256
+ }
1257
+
1258
+ /* */
1259
+ static VALUE zipruby_archive_set_comment(VALUE self, VALUE comment) {
1260
+ struct zipruby_archive *p_archive;
1261
+ const char *s_comment = NULL;
1262
+ int len = 0;
1263
+
1264
+ if (!NIL_P(comment)) {
1265
+ Check_Type(comment, T_STRING);
1266
+ s_comment = RSTRING_PTR(comment);
1267
+ len = RSTRING_LEN(comment);
1268
+ }
1269
+
1270
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
1271
+ Check_Archive(p_archive);
1272
+
1273
+ if (zip_set_archive_comment(p_archive->archive, s_comment, len) == -1) {
1274
+ zip_unchange_all(p_archive->archive);
1275
+ zip_unchange_archive(p_archive->archive);
1276
+ rb_raise(Error, "Comment archived failed: %s", zip_strerror(p_archive->archive));
1277
+ }
1278
+
1279
+ return Qnil;
1280
+ }
1281
+
1282
+ /* */
1283
+ static VALUE zipruby_archive_locate_name(int argc, VALUE *argv, VALUE self) {
1284
+ VALUE fname, flags;
1285
+ struct zipruby_archive *p_archive;
1286
+ int i_flags = 0;
1287
+
1288
+ rb_scan_args(argc, argv, "11", &fname, &flags);
1289
+ Check_Type(fname, T_STRING);
1290
+
1291
+ if (!NIL_P(flags)) {
1292
+ i_flags = NUM2INT(flags);
1293
+ }
1294
+
1295
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
1296
+ Check_Archive(p_archive);
1297
+
1298
+ return INT2NUM(zip_name_locate(p_archive->archive, RSTRING_PTR(fname), i_flags));
1299
+ }
1300
+
1301
+ /* */
1302
+ static VALUE zipruby_archive_get_fcomment(int argc, VALUE *argv, VALUE self) {
1303
+ VALUE index, flags;
1304
+ struct zipruby_archive *p_archive;
1305
+ const char *comment;
1306
+ int lenp, i_flags = 0;
1307
+
1308
+ rb_scan_args(argc, argv, "11", &index, &flags);
1309
+
1310
+ if (!NIL_P(flags)) {
1311
+ i_flags = NUM2INT(flags);
1312
+ }
1313
+
1314
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
1315
+ Check_Archive(p_archive);
1316
+
1317
+ // XXX: How is the error checked?
1318
+ comment = zip_get_file_comment(p_archive->archive, NUM2INT(index), &lenp, i_flags);
1319
+
1320
+ return comment ? rb_str_new(comment, lenp) : Qnil;
1321
+ }
1322
+
1323
+ /* */
1324
+ static VALUE zipruby_archive_set_fcomment(VALUE self, VALUE index, VALUE comment) {
1325
+ struct zipruby_archive *p_archive;
1326
+ char *s_comment = NULL;
1327
+ int len = 0;
1328
+
1329
+ if (!NIL_P(comment)) {
1330
+ Check_Type(comment, T_STRING);
1331
+ s_comment = RSTRING_PTR(comment);
1332
+ len = RSTRING_LEN(comment);
1333
+ }
1334
+
1335
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
1336
+ Check_Archive(p_archive);
1337
+
1338
+ if (zip_set_file_comment(p_archive->archive, NUM2INT(index), s_comment, len) == -1) {
1339
+ zip_unchange_all(p_archive->archive);
1340
+ zip_unchange_archive(p_archive->archive);
1341
+ rb_raise(Error, "Comment file failed at %d: %s", NUM2INT(index), zip_strerror(p_archive->archive));
1342
+ }
1343
+
1344
+ return Qnil;
1345
+ }
1346
+
1347
+ /* */
1348
+ static VALUE zipruby_archive_fdelete(VALUE self, VALUE index) {
1349
+ struct zipruby_archive *p_archive;
1350
+
1351
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
1352
+ Check_Archive(p_archive);
1353
+
1354
+ if (zip_delete(p_archive->archive, NUM2INT(index)) == -1) {
1355
+ zip_unchange_all(p_archive->archive);
1356
+ zip_unchange_archive(p_archive->archive);
1357
+ rb_raise(Error, "Delete file failed at %d: %s", NUM2INT(index), zip_strerror(p_archive->archive));
1358
+ }
1359
+
1360
+ return Qnil;
1361
+ }
1362
+
1363
+ /* */
1364
+ static VALUE zipruby_archive_frename(VALUE self, VALUE index, VALUE name) {
1365
+ struct zipruby_archive *p_archive;
1366
+
1367
+ Check_Type(name, T_STRING);
1368
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
1369
+ Check_Archive(p_archive);
1370
+
1371
+ if (zip_rename(p_archive->archive, NUM2INT(index), RSTRING_PTR(name)) == -1) {
1372
+ zip_unchange_all(p_archive->archive);
1373
+ zip_unchange_archive(p_archive->archive);
1374
+ rb_raise(Error, "Rename file failed at %d: %s", NUM2INT(index), zip_strerror(p_archive->archive));
1375
+ }
1376
+
1377
+ return Qnil;
1378
+ }
1379
+
1380
+ /* */
1381
+ static VALUE zipruby_archive_funchange(VALUE self, VALUE index) {
1382
+ struct zipruby_archive *p_archive;
1383
+
1384
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
1385
+ Check_Archive(p_archive);
1386
+
1387
+ if (zip_unchange(p_archive->archive, NUM2INT(index)) == -1) {
1388
+ zip_unchange_all(p_archive->archive);
1389
+ zip_unchange_archive(p_archive->archive);
1390
+ rb_raise(Error, "Unchange file failed at %d: %s", NUM2INT(index), zip_strerror(p_archive->archive));
1391
+ }
1392
+
1393
+ return Qnil;
1394
+ }
1395
+
1396
+ /* */
1397
+ static VALUE zipruby_archive_funchange_all(VALUE self) {
1398
+ struct zipruby_archive *p_archive;
1399
+
1400
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
1401
+ Check_Archive(p_archive);
1402
+
1403
+ if (zip_unchange_all(p_archive->archive) == -1) {
1404
+ rb_raise(Error, "Unchange all file failed: %s", zip_strerror(p_archive->archive));
1405
+ }
1406
+
1407
+ return Qnil;
1408
+ }
1409
+
1410
+ /* */
1411
+ static VALUE zipruby_archive_unchange(VALUE self) {
1412
+ struct zipruby_archive *p_archive;
1413
+
1414
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
1415
+ Check_Archive(p_archive);
1416
+
1417
+ if (zip_unchange_archive(p_archive->archive) == -1) {
1418
+ rb_raise(Error, "Unchange archive failed: %s", zip_strerror(p_archive->archive));
1419
+ }
1420
+
1421
+ return Qnil;
1422
+ }
1423
+
1424
+ /* */
1425
+ static VALUE zipruby_archive_revert(VALUE self) {
1426
+ zipruby_archive_funchange_all(self);
1427
+ zipruby_archive_unchange(self);
1428
+
1429
+ return Qnil;
1430
+ }
1431
+
1432
+ /* */
1433
+ static VALUE zipruby_archive_each(VALUE self) {
1434
+ struct zipruby_archive *p_archive;
1435
+ int i, num_files;
1436
+
1437
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
1438
+ Check_Archive(p_archive);
1439
+ num_files = zip_get_num_files(p_archive->archive);
1440
+
1441
+ for (i = 0; i < num_files; i++) {
1442
+ VALUE file;
1443
+ int status;
1444
+
1445
+ file = rb_funcall(File, rb_intern("new"), 2, self, INT2NUM(i));
1446
+ rb_protect(rb_yield, file, &status);
1447
+ rb_funcall(file, rb_intern("close"), 0);
1448
+
1449
+ if (status != 0) {
1450
+ rb_jump_tag(status);
1451
+ }
1452
+ }
1453
+
1454
+ return Qnil;
1455
+ }
1456
+
1457
+ /* */
1458
+ static VALUE zipruby_archive_commit(VALUE self) {
1459
+ struct zipruby_archive *p_archive;
1460
+ int changed, survivors;
1461
+ int errorp;
1462
+
1463
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
1464
+ Check_Archive(p_archive);
1465
+
1466
+ changed = _zip_changed(p_archive->archive, &survivors);
1467
+
1468
+ if (zip_close(p_archive->archive) == -1) {
1469
+ zip_unchange_all(p_archive->archive);
1470
+ zip_unchange_archive(p_archive->archive);
1471
+ rb_raise(Error, "Commit archive failed: %s", zip_strerror(p_archive->archive));
1472
+ }
1473
+
1474
+ if (!NIL_P(p_archive->buffer) && changed) {
1475
+ rb_funcall(p_archive->buffer, rb_intern("replace"), 1, rb_funcall(self, rb_intern("read"), 0));
1476
+ }
1477
+
1478
+ p_archive->archive = NULL;
1479
+ p_archive->flags = (p_archive->flags & ~(ZIP_CREATE | ZIP_EXCL));
1480
+
1481
+ if ((p_archive->archive = zip_open(RSTRING_PTR(p_archive->path), p_archive->flags, &errorp)) == NULL) {
1482
+ char errstr[ERRSTR_BUFSIZE];
1483
+ zip_error_to_str(errstr, ERRSTR_BUFSIZE, errorp, errno);
1484
+ rb_raise(Error, "Commit archive failed: %s", errstr);
1485
+ }
1486
+
1487
+ return Qnil;
1488
+ }
1489
+
1490
+ /* */
1491
+ static VALUE zipruby_archive_is_open(VALUE self) {
1492
+ struct zipruby_archive *p_archive;
1493
+
1494
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
1495
+ return (p_archive->archive != NULL) ? Qtrue : Qfalse;
1496
+ }
1497
+
1498
+ /* */
1499
+ static VALUE zipruby_archive_decrypt(VALUE self, VALUE password) {
1500
+ VALUE retval;
1501
+ struct zipruby_archive *p_archive;
1502
+ long pwdlen;
1503
+ int changed, survivors;
1504
+ int errorp;
1505
+
1506
+ Check_Type(password, T_STRING);
1507
+ pwdlen = RSTRING_LEN(password);
1508
+
1509
+ if (pwdlen < 1) {
1510
+ rb_raise(Error, "Decrypt archive failed: Password is empty");
1511
+ } else if (pwdlen > 0xff) {
1512
+ rb_raise(Error, "Decrypt archive failed: Password is too long");
1513
+ }
1514
+
1515
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
1516
+ Check_Archive(p_archive);
1517
+
1518
+ changed = _zip_changed(p_archive->archive, &survivors);
1519
+
1520
+ if (zip_close(p_archive->archive) == -1) {
1521
+ zip_unchange_all(p_archive->archive);
1522
+ zip_unchange_archive(p_archive->archive);
1523
+ rb_raise(Error, "Decrypt archive failed: %s", zip_strerror(p_archive->archive));
1524
+ }
1525
+
1526
+ if (!NIL_P(p_archive->buffer) && changed) {
1527
+ rb_funcall(p_archive->buffer, rb_intern("replace"), 1, rb_funcall(self, rb_intern("read"), 0));
1528
+ }
1529
+
1530
+ p_archive->archive = NULL;
1531
+ p_archive->flags = (p_archive->flags & ~(ZIP_CREATE | ZIP_EXCL));
1532
+
1533
+ retval = zipruby_archive_s_decrypt(Archive, p_archive->path, password);
1534
+
1535
+ if ((p_archive->archive = zip_open(RSTRING_PTR(p_archive->path), p_archive->flags, &errorp)) == NULL) {
1536
+ char errstr[ERRSTR_BUFSIZE];
1537
+ zip_error_to_str(errstr, ERRSTR_BUFSIZE, errorp, errno);
1538
+ rb_raise(Error, "Decrypt archive failed: %s", errstr);
1539
+ }
1540
+
1541
+ return retval;
1542
+ }
1543
+
1544
+ /* */
1545
+ static VALUE zipruby_archive_encrypt(VALUE self, VALUE password) {
1546
+ VALUE retval;
1547
+ struct zipruby_archive *p_archive;
1548
+ long pwdlen;
1549
+ int changed, survivors;
1550
+ int errorp;
1551
+
1552
+ Check_Type(password, T_STRING);
1553
+ pwdlen = RSTRING_LEN(password);
1554
+
1555
+ if (pwdlen < 1) {
1556
+ rb_raise(Error, "Encrypt archive failed: Password is empty");
1557
+ } else if (pwdlen > 0xff) {
1558
+ rb_raise(Error, "Encrypt archive failed: Password is too long");
1559
+ }
1560
+
1561
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
1562
+ Check_Archive(p_archive);
1563
+
1564
+ changed = _zip_changed(p_archive->archive, &survivors);
1565
+
1566
+ if (zip_close(p_archive->archive) == -1) {
1567
+ zip_unchange_all(p_archive->archive);
1568
+ zip_unchange_archive(p_archive->archive);
1569
+ rb_raise(Error, "Encrypt archive failed: %s", zip_strerror(p_archive->archive));
1570
+ }
1571
+
1572
+ if (!NIL_P(p_archive->buffer) && changed) {
1573
+ rb_funcall(p_archive->buffer, rb_intern("replace"), 1, rb_funcall(self, rb_intern("read"), 0));
1574
+ }
1575
+
1576
+ p_archive->archive = NULL;
1577
+ p_archive->flags = (p_archive->flags & ~(ZIP_CREATE | ZIP_EXCL));
1578
+
1579
+ retval = zipruby_archive_s_encrypt(Archive, p_archive->path, password);
1580
+
1581
+ if ((p_archive->archive = zip_open(RSTRING_PTR(p_archive->path), p_archive->flags, &errorp)) == NULL) {
1582
+ char errstr[ERRSTR_BUFSIZE];
1583
+ zip_error_to_str(errstr, ERRSTR_BUFSIZE, errorp, errno);
1584
+ rb_raise(Error, "Encrypt archive failed: %s", errstr);
1585
+ }
1586
+
1587
+ return retval;
1588
+ }
1589
+
1590
+ /* */
1591
+ static VALUE zipruby_archive_read(VALUE self) {
1592
+ VALUE retval = Qnil;
1593
+ struct zipruby_archive *p_archive;
1594
+ FILE *fzip;
1595
+ char buf[DATA_BUFSIZE];
1596
+ ssize_t n;
1597
+ int block_given;
1598
+
1599
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
1600
+
1601
+ if (NIL_P(p_archive->path)) {
1602
+ rb_raise(rb_eRuntimeError, "invalid Zip::Archive");
1603
+ }
1604
+
1605
+ #ifdef _WIN32
1606
+ if (fopen_s(&fzip, RSTRING_PTR(p_archive->path), "rb") != 0) {
1607
+ rb_raise(Error, "Read archive failed: Cannot open archive");
1608
+ }
1609
+ #else
1610
+ if ((fzip = fopen(RSTRING_PTR(p_archive->path), "rb")) == NULL) {
1611
+ rb_raise(Error, "Read archive failed: Cannot open archive");
1612
+ }
1613
+ #endif
1614
+
1615
+ block_given = rb_block_given_p();
1616
+
1617
+ while ((n = fread(buf, 1, sizeof(buf), fzip)) > 0) {
1618
+ if (block_given) {
1619
+ rb_yield(rb_str_new(buf, n));
1620
+ } else {
1621
+ if (NIL_P(retval)) {
1622
+ retval = rb_str_new(buf, n);
1623
+ } else {
1624
+ rb_str_buf_cat(retval, buf, n);
1625
+ }
1626
+ }
1627
+ }
1628
+
1629
+ #if defined(RUBY_VM) && defined(_WIN32)
1630
+ _fclose_nolock(fzip);
1631
+ #elif defined(RUBY_WIN32_H)
1632
+ #undef fclose
1633
+ fclose(fzip);
1634
+ #define fclose(f) rb_w32_fclose(f)
1635
+ #else
1636
+ fclose(fzip);
1637
+ #endif
1638
+
1639
+ if (n == -1) {
1640
+ rb_raise(Error, "Read archive failed");
1641
+ }
1642
+
1643
+ return retval;
1644
+ }
1645
+
1646
+ /* */
1647
+ static VALUE zipruby_archive_add_dir(VALUE self, VALUE name) {
1648
+ struct zipruby_archive *p_archive;
1649
+
1650
+ Check_Type(name, T_STRING);
1651
+ Data_Get_Struct(self, struct zipruby_archive, p_archive);
1652
+ Check_Archive(p_archive);
1653
+
1654
+ if (zip_add_dir(p_archive->archive, RSTRING_PTR(name)) == -1) {
1655
+ zip_unchange_all(p_archive->archive);
1656
+ zip_unchange_archive(p_archive->archive);
1657
+ rb_raise(Error, "Add dir failed - %s: %s", RSTRING_PTR(name), zip_strerror(p_archive->archive));
1658
+ }
1659
+
1660
+ return Qnil;
1661
+ }
1662
+ #include "zipruby.h"
1663
+ #include "zipruby_error.h"
1664
+ #include "ruby.h"
1665
+
1666
+ extern VALUE Zip;
1667
+ VALUE Error;
1668
+
1669
+ void Init_zipruby_error() {
1670
+ Error = rb_define_class_under(Zip, "Error", rb_eStandardError);
1671
+ }
1672
+ #include <errno.h>
1673
+
1674
+ #include "zip.h"
1675
+ #include "zipint.h"
1676
+ #include "zipruby.h"
1677
+ #include "zipruby_archive.h"
1678
+ #include "zipruby_file.h"
1679
+ #include "zipruby_stat.h"
1680
+ #include "ruby.h"
1681
+
1682
+ #define MIN(a, b) ((a) < (b) ? (a) : (b))
1683
+
1684
+ static VALUE zipruby_file(VALUE klass);
1685
+ static VALUE zipruby_file_alloc(VALUE klass);
1686
+ static void zipruby_file_mark(struct zipruby_file *p);
1687
+ static void zipruby_file_free(struct zipruby_file *p);
1688
+ static VALUE zipruby_file_initialize(int argc, VALUE *argv, VALUE self);
1689
+ static VALUE zipruby_file_close(VALUE self);
1690
+ static VALUE zipruby_file_read(int argc, VALUE *argv, VALUE self);
1691
+ static VALUE zipruby_file_stat(VALUE self);
1692
+ static VALUE zipruby_file_get_comment(int argc, VALUE *argv, VALUE self);
1693
+ static VALUE zipruby_file_set_comment(VALUE self, VALUE comment);
1694
+ static VALUE zipruby_file_delete(VALUE self);
1695
+ static VALUE zipruby_file_rename(VALUE self, VALUE name);
1696
+ static VALUE zipruby_file_unchange(VALUE self);
1697
+ static VALUE zipruby_file_name(VALUE self);
1698
+ static VALUE zipruby_file_index(VALUE self);
1699
+ static VALUE zipruby_file_crc(VALUE self);
1700
+ static VALUE zipruby_file_size(VALUE self);
1701
+ static VALUE zipruby_file_mtime(VALUE self);
1702
+ static VALUE zipruby_file_comp_size(VALUE self);
1703
+ static VALUE zipruby_file_comp_method(VALUE self);
1704
+ static VALUE zipruby_file_encryption_method(VALUE self);
1705
+ static VALUE zipruby_file_is_directory(VALUE self);
1706
+
1707
+ extern VALUE Zip;
1708
+ extern VALUE Archive;
1709
+ VALUE File;
1710
+ extern VALUE Stat;
1711
+ extern VALUE Error;
1712
+
1713
+ void Init_zipruby_file() {
1714
+ File = rb_define_class_under(Zip, "File", rb_cObject);
1715
+ rb_define_alloc_func(File, zipruby_file_alloc);
1716
+ rb_define_method(File, "initialize", zipruby_file_initialize, -1);
1717
+ rb_define_method(File, "close", zipruby_file_close, 0);
1718
+ rb_define_method(File, "read", zipruby_file_read, -1);
1719
+ rb_define_method(File, "stat", zipruby_file_stat, 0);
1720
+ rb_define_method(File, "get_comment", zipruby_file_get_comment, -1);
1721
+ rb_define_method(File, "comment", zipruby_file_get_comment, -1);
1722
+ rb_define_method(File, "comment=", zipruby_file_set_comment, 1);
1723
+ rb_define_method(File, "delete", zipruby_file_delete, 0);
1724
+ rb_define_method(File, "rename", zipruby_file_rename, 1);
1725
+ rb_define_method(File, "unchange", zipruby_file_unchange, 1);
1726
+ rb_define_method(File, "revert", zipruby_file_unchange, 1);
1727
+ rb_define_method(File, "name", zipruby_file_name, 0);
1728
+ rb_define_method(File, "index", zipruby_file_index, 0);
1729
+ rb_define_method(File, "crc", zipruby_file_crc, 0);
1730
+ rb_define_method(File, "size", zipruby_file_size, 0);
1731
+ rb_define_method(File, "mtime", zipruby_file_mtime, 0);
1732
+ rb_define_method(File, "comp_size", zipruby_file_comp_size, 0);
1733
+ rb_define_method(File, "comp_method", zipruby_file_comp_method, 0);
1734
+ rb_define_method(File, "encryption_method", zipruby_file_encryption_method, 0);
1735
+ rb_define_method(File, "directory?", zipruby_file_is_directory, 0);
1736
+ }
1737
+
1738
+ static VALUE zipruby_file_alloc(VALUE klass) {
1739
+ struct zipruby_file *p = ALLOC(struct zipruby_file);
1740
+
1741
+ p->archive = NULL;
1742
+ p->file = NULL;
1743
+ p->sb = NULL;
1744
+
1745
+ return Data_Wrap_Struct(klass, zipruby_file_mark, zipruby_file_free, p);
1746
+ }
1747
+
1748
+ static void zipruby_file_mark(struct zipruby_file *p) {
1749
+ if (p->archive) { rb_gc_mark(p->v_archive); }
1750
+ if (p->sb) { rb_gc_mark(p->v_sb); }
1751
+ }
1752
+
1753
+ static void zipruby_file_free(struct zipruby_file *p) {
1754
+ xfree(p);
1755
+ }
1756
+
1757
+ /* */
1758
+ static VALUE zipruby_file_initialize(int argc, VALUE *argv, VALUE self) {
1759
+ VALUE archive, index, flags, stat_flags;
1760
+ struct zipruby_archive *p_archive;
1761
+ struct zipruby_file *p_file;
1762
+ struct zipruby_stat *p_stat;
1763
+ struct zip_file *fzip;
1764
+ char *fname = NULL;
1765
+ int i_index = -1, i_flags = 0;
1766
+
1767
+ rb_scan_args(argc, argv, "22", &archive, &index, &flags, &stat_flags);
1768
+
1769
+ if (!rb_obj_is_instance_of(archive, Archive)) {
1770
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Zip::Archive)", rb_class2name(CLASS_OF(archive)));
1771
+ }
1772
+
1773
+ switch (TYPE(index)) {
1774
+ case T_STRING: fname = RSTRING_PTR(index); break;
1775
+ case T_FIXNUM: i_index = NUM2INT(index); break;
1776
+ default:
1777
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected String or Fixnum)", rb_class2name(CLASS_OF(index)));
1778
+ }
1779
+
1780
+ if (!NIL_P(flags)) {
1781
+ i_flags = NUM2INT(flags);
1782
+ }
1783
+
1784
+ Data_Get_Struct(archive, struct zipruby_archive, p_archive);
1785
+ Check_Archive(p_archive);
1786
+
1787
+ if (fname) {
1788
+ fzip = zip_fopen(p_archive->archive, fname, i_flags);
1789
+
1790
+ if (fzip == NULL) {
1791
+ rb_raise(Error, "Open file failed - %s: %s", fname, zip_strerror(p_archive->archive));
1792
+ }
1793
+ } else {
1794
+ fzip = zip_fopen_index(p_archive->archive, i_index, i_flags);
1795
+
1796
+ if (fzip == NULL) {
1797
+ rb_raise(Error, "Open file failed at %d: %s", i_index, zip_strerror(p_archive->archive));
1798
+ }
1799
+ }
1800
+
1801
+ Data_Get_Struct(self, struct zipruby_file, p_file);
1802
+ p_file->v_archive = archive;
1803
+ p_file->archive = p_archive->archive;
1804
+ p_file->file = fzip;
1805
+ p_file->v_sb = rb_funcall(Stat, rb_intern("new"), 3, archive, index, stat_flags);
1806
+ Data_Get_Struct(p_file->v_sb, struct zipruby_stat, p_stat);
1807
+ p_file->sb = p_stat->sb;
1808
+
1809
+ return Qnil;
1810
+ }
1811
+
1812
+ /* */
1813
+ static VALUE zipruby_file_close(VALUE self) {
1814
+ struct zipruby_file *p_file;
1815
+ int error;
1816
+
1817
+ Data_Get_Struct(self, struct zipruby_file, p_file);
1818
+ Check_File(p_file);
1819
+
1820
+ if ((error = zip_fclose(p_file->file)) != 0) {
1821
+ char errstr[ERRSTR_BUFSIZE];
1822
+ zip_unchange(p_file->archive, p_file->sb->index);
1823
+ zip_error_to_str(errstr, ERRSTR_BUFSIZE, error, errno);
1824
+ rb_raise(Error, "Close file failed: %s", errstr);
1825
+ }
1826
+
1827
+ p_file->archive = NULL;
1828
+ p_file->file = NULL;
1829
+ p_file->sb = NULL;
1830
+
1831
+ return Qnil;
1832
+ }
1833
+
1834
+ /* */
1835
+ static VALUE zipruby_file_read(int argc, VALUE *argv, VALUE self) {
1836
+ VALUE size, retval = Qnil;
1837
+ struct zipruby_file *p_file;
1838
+ struct zip_stat sb;
1839
+ int block_given;
1840
+ size_t bytes_left;
1841
+ char buf[DATA_BUFSIZE];
1842
+ ssize_t n;
1843
+
1844
+ rb_scan_args(argc, argv, "01", &size);
1845
+ Data_Get_Struct(self, struct zipruby_file, p_file);
1846
+ Check_File(p_file);
1847
+ zip_stat_init(&sb);
1848
+
1849
+ if (p_file->archive->cdir->entry[0].bitflags & ZIP_GPBF_ENCRYPTED) {
1850
+ rb_raise(Error, "Read file failed: File encrypted");
1851
+ }
1852
+
1853
+ if (zip_stat_index(p_file->archive, p_file->sb->index, 0, &sb)) {
1854
+ rb_raise(Error, "Read file failed: %s", zip_strerror(p_file->archive));
1855
+ }
1856
+
1857
+ if (NIL_P(size)) {
1858
+ bytes_left = sb.size;
1859
+ } else {
1860
+ bytes_left = NUM2LONG(size);
1861
+ }
1862
+
1863
+ if (bytes_left <= 0) {
1864
+ return Qnil;
1865
+ }
1866
+
1867
+ block_given = rb_block_given_p();
1868
+
1869
+ while ((n = zip_fread(p_file->file, buf, MIN(bytes_left, sizeof(buf)))) > 0) {
1870
+ if (block_given) {
1871
+ rb_yield(rb_str_new(buf, n));
1872
+ } else {
1873
+ if (NIL_P(retval)) {
1874
+ retval = rb_str_new(buf, n);
1875
+ } else {
1876
+ rb_str_buf_cat(retval, buf, n);
1877
+ }
1878
+ }
1879
+
1880
+ bytes_left -= n;
1881
+ }
1882
+
1883
+ if (n == -1) {
1884
+ rb_raise(Error, "Read file failed: %s", zip_file_strerror(p_file->file));
1885
+ }
1886
+
1887
+ return retval;
1888
+ }
1889
+
1890
+ /* */
1891
+ static VALUE zipruby_file_stat(VALUE self) {
1892
+ struct zipruby_file *p_file;
1893
+
1894
+ Data_Get_Struct(self, struct zipruby_file, p_file);
1895
+ Check_File(p_file);
1896
+
1897
+ return p_file->v_sb;
1898
+ }
1899
+
1900
+ /* */
1901
+ static VALUE zipruby_file_get_comment(int argc, VALUE *argv, VALUE self) {
1902
+ VALUE flags;
1903
+ struct zipruby_file *p_file;
1904
+ const char *comment;
1905
+ int lenp, i_flags = 0;
1906
+
1907
+ rb_scan_args(argc, argv, "01", &flags);
1908
+
1909
+ if (!NIL_P(flags)) {
1910
+ i_flags = NUM2INT(flags);
1911
+ }
1912
+
1913
+ Data_Get_Struct(self, struct zipruby_file, p_file);
1914
+ Check_File(p_file);
1915
+
1916
+ // XXX: How is the error checked?
1917
+ comment = zip_get_file_comment(p_file->archive, p_file->sb->index, &lenp, i_flags);
1918
+
1919
+ return comment ? rb_str_new(comment, lenp) : Qnil;
1920
+ }
1921
+
1922
+ /* */
1923
+ static VALUE zipruby_file_set_comment(VALUE self, VALUE comment) {
1924
+ struct zipruby_file *p_file;
1925
+ char *s_comment = NULL;
1926
+ int len = 0;
1927
+
1928
+ if (!NIL_P(comment)) {
1929
+ Check_Type(comment, T_STRING);
1930
+ s_comment = RSTRING_PTR(comment);
1931
+ len = RSTRING_LEN(comment);
1932
+ }
1933
+
1934
+ Data_Get_Struct(self, struct zipruby_file, p_file);
1935
+ Check_File(p_file);
1936
+
1937
+ if (zip_set_file_comment(p_file->archive, p_file->sb->index, s_comment, len) == -1) {
1938
+ zip_unchange_all(p_file->archive);
1939
+ zip_unchange_archive(p_file->archive);
1940
+ rb_raise(Error, "Comment file failed - %s: %s", p_file->sb->name, zip_strerror(p_file->archive));
1941
+ }
1942
+
1943
+ return Qnil;
1944
+ }
1945
+
1946
+ /* */
1947
+ static VALUE zipruby_file_delete(VALUE self) {
1948
+ struct zipruby_file *p_file;
1949
+
1950
+ Data_Get_Struct(self, struct zipruby_file, p_file);
1951
+ Check_File(p_file);
1952
+
1953
+ if (zip_delete(p_file->archive, p_file->sb->index) == -1) {
1954
+ zip_unchange_all(p_file->archive);
1955
+ zip_unchange_archive(p_file->archive);
1956
+ rb_raise(Error, "Delete file failed - %s: %s", p_file->sb->name, zip_strerror(p_file->archive));
1957
+ }
1958
+
1959
+ return Qnil;
1960
+ }
1961
+
1962
+ /* */
1963
+ static VALUE zipruby_file_rename(VALUE self, VALUE name) {
1964
+ struct zipruby_file *p_file;
1965
+
1966
+ Check_Type(name, T_STRING);
1967
+ Data_Get_Struct(self, struct zipruby_file, p_file);
1968
+ Check_File(p_file);
1969
+
1970
+ if (zip_rename(p_file->archive, p_file->sb->index, RSTRING_PTR(name)) == -1) {
1971
+ zip_unchange_all(p_file->archive);
1972
+ zip_unchange_archive(p_file->archive);
1973
+ rb_raise(Error, "Rename file failed - %s: %s", p_file->sb->name, zip_strerror(p_file->archive));
1974
+ }
1975
+
1976
+ return Qnil;
1977
+ }
1978
+
1979
+ /* */
1980
+ static VALUE zipruby_file_unchange(VALUE self) {
1981
+ struct zipruby_file *p_file;
1982
+
1983
+ Data_Get_Struct(self, struct zipruby_file, p_file);
1984
+ Check_File(p_file);
1985
+
1986
+ if (zip_unchange(p_file->archive, p_file->sb->index) == -1) {
1987
+ rb_raise(Error, "Unchange file failed - %s: %s", p_file->sb->name, zip_strerror(p_file->archive));
1988
+ }
1989
+
1990
+ return Qnil;
1991
+ }
1992
+
1993
+ /* */
1994
+ static VALUE zipruby_file_name(VALUE self) {
1995
+ struct zipruby_file *p_file;
1996
+
1997
+ Data_Get_Struct(self, struct zipruby_file, p_file);
1998
+ Check_File(p_file);
1999
+
2000
+ return zipruby_stat_name(p_file->v_sb);
2001
+ }
2002
+
2003
+ /* */
2004
+ static VALUE zipruby_file_index(VALUE self) {
2005
+ struct zipruby_file *p_file;
2006
+
2007
+ Data_Get_Struct(self, struct zipruby_file, p_file);
2008
+ Check_File(p_file);
2009
+
2010
+ return zipruby_stat_index(p_file->v_sb);
2011
+ }
2012
+
2013
+ /* */
2014
+ static VALUE zipruby_file_crc(VALUE self) {
2015
+ struct zipruby_file *p_file;
2016
+
2017
+ Data_Get_Struct(self, struct zipruby_file, p_file);
2018
+ Check_File(p_file);
2019
+
2020
+ return zipruby_stat_crc(p_file->v_sb);
2021
+ }
2022
+
2023
+ /* */
2024
+ static VALUE zipruby_file_size(VALUE self) {
2025
+ struct zipruby_file *p_file;
2026
+
2027
+ Data_Get_Struct(self, struct zipruby_file, p_file);
2028
+ Check_File(p_file);
2029
+
2030
+ return zipruby_stat_size(p_file->v_sb);
2031
+ }
2032
+
2033
+ /* */
2034
+ static VALUE zipruby_file_mtime(VALUE self) {
2035
+ struct zipruby_file *p_file;
2036
+
2037
+ Data_Get_Struct(self, struct zipruby_file, p_file);
2038
+ Check_File(p_file);
2039
+
2040
+ return zipruby_stat_mtime(p_file->v_sb);
2041
+ }
2042
+
2043
+ /* */
2044
+ static VALUE zipruby_file_comp_size(VALUE self) {
2045
+ struct zipruby_file *p_file;
2046
+
2047
+ Data_Get_Struct(self, struct zipruby_file, p_file);
2048
+ Check_File(p_file);
2049
+
2050
+ return zipruby_stat_comp_size(p_file->v_sb);
2051
+ }
2052
+
2053
+ /* */
2054
+ static VALUE zipruby_file_comp_method(VALUE self) {
2055
+ struct zipruby_file *p_file;
2056
+
2057
+ Data_Get_Struct(self, struct zipruby_file, p_file);
2058
+ Check_File(p_file);
2059
+
2060
+ return zipruby_stat_comp_method(p_file->v_sb);
2061
+ }
2062
+
2063
+ /* */
2064
+ static VALUE zipruby_file_encryption_method(VALUE self) {
2065
+ struct zipruby_file *p_file;
2066
+
2067
+ Data_Get_Struct(self, struct zipruby_file, p_file);
2068
+ Check_File(p_file);
2069
+
2070
+ return zipruby_stat_encryption_method(p_file->v_sb);
2071
+ }
2072
+
2073
+ /* */
2074
+ static VALUE zipruby_file_is_directory(VALUE self) {
2075
+ struct zipruby_file *p_file;
2076
+
2077
+ Data_Get_Struct(self, struct zipruby_file, p_file);
2078
+ Check_File(p_file);
2079
+
2080
+ return zipruby_stat_is_directory(p_file->v_sb);
2081
+ }
2082
+ #include <string.h>
2083
+
2084
+ #include "zip.h"
2085
+ #include "zipruby.h"
2086
+ #include "zipruby_archive.h"
2087
+ #include "zipruby_stat.h"
2088
+ #include "ruby.h"
2089
+
2090
+ static VALUE zipruby_stat_alloc(VALUE klass);
2091
+ static void zipruby_stat_free(struct zipruby_stat *p);
2092
+ static VALUE zipruby_stat_initialize(int argc, VALUE *argv, VALUE self);
2093
+
2094
+ extern VALUE Zip;
2095
+ extern VALUE Archive;
2096
+ VALUE Stat;
2097
+ extern VALUE Error;
2098
+
2099
+ void Init_zipruby_stat() {
2100
+ Stat = rb_define_class_under(Zip, "Stat", rb_cObject);
2101
+ rb_define_alloc_func(Stat, zipruby_stat_alloc);
2102
+ rb_define_method(Stat, "initialize", zipruby_stat_initialize, -1);
2103
+ rb_define_method(Stat, "name", zipruby_stat_name, 0);
2104
+ rb_define_method(Stat, "index", zipruby_stat_index, 0);
2105
+ rb_define_method(Stat, "crc", zipruby_stat_crc, 0);
2106
+ rb_define_method(Stat, "size", zipruby_stat_size, 0);
2107
+ rb_define_method(Stat, "mtime", zipruby_stat_mtime, 0);
2108
+ rb_define_method(Stat, "comp_size", zipruby_stat_comp_size, 0);
2109
+ rb_define_method(Stat, "comp_method", zipruby_stat_comp_method, 0);
2110
+ rb_define_method(Stat, "encryption_method", zipruby_stat_encryption_method, 0);
2111
+ rb_define_method(Stat, "directory?", zipruby_stat_is_directory, 0);
2112
+ }
2113
+
2114
+ static VALUE zipruby_stat_alloc(VALUE klass) {
2115
+ struct zipruby_stat *p = ALLOC(struct zipruby_stat);
2116
+
2117
+ p->sb = ALLOC(struct zip_stat);
2118
+ zip_stat_init(p->sb);
2119
+
2120
+ return Data_Wrap_Struct(klass, 0, zipruby_stat_free, p);
2121
+ }
2122
+
2123
+ static void zipruby_stat_free(struct zipruby_stat *p) {
2124
+ xfree(p->sb);
2125
+ xfree(p);
2126
+ }
2127
+
2128
+ /* */
2129
+ static VALUE zipruby_stat_initialize(int argc, VALUE *argv, VALUE self) {
2130
+ VALUE archive, index, flags;
2131
+ struct zipruby_archive *p_archive;
2132
+ struct zipruby_stat *p_stat;
2133
+ char *fname = NULL;
2134
+ int i_index = -1, i_flags = 0;
2135
+
2136
+ rb_scan_args(argc, argv, "21", &archive, &index, &flags);
2137
+
2138
+ if (!rb_obj_is_instance_of(archive, Archive)) {
2139
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Zip::Archive)", rb_class2name(CLASS_OF(archive)));
2140
+ }
2141
+
2142
+ switch (TYPE(index)) {
2143
+ case T_STRING: fname = RSTRING_PTR(index); break;
2144
+ case T_FIXNUM: i_index = NUM2INT(index); break;
2145
+ default:
2146
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected String or Fixnum)", rb_class2name(CLASS_OF(index)));
2147
+ }
2148
+
2149
+ if (!NIL_P(flags)) {
2150
+ i_flags = NUM2INT(flags);
2151
+ }
2152
+
2153
+ Data_Get_Struct(archive, struct zipruby_archive, p_archive);
2154
+ Check_Archive(p_archive);
2155
+ Data_Get_Struct(self, struct zipruby_stat, p_stat);
2156
+
2157
+ if (fname) {
2158
+ if (zip_stat(p_archive->archive, fname, i_flags, p_stat->sb) != 0) {
2159
+ rb_raise(Error, "Obtain file status failed - %s: %s", fname, zip_strerror(p_archive->archive));
2160
+ }
2161
+ } else {
2162
+ if (zip_stat_index(p_archive->archive, i_index, i_flags, p_stat->sb) != 0) {
2163
+ rb_raise(Error, "Obtain file status failed at %d: %s", i_index, zip_strerror(p_archive->archive));
2164
+ }
2165
+ }
2166
+
2167
+ return Qnil;
2168
+ }
2169
+
2170
+ /* */
2171
+ VALUE zipruby_stat_name(VALUE self) {
2172
+ struct zipruby_stat *p_stat;
2173
+
2174
+ Data_Get_Struct(self, struct zipruby_stat, p_stat);
2175
+
2176
+ return p_stat->sb->name ? rb_str_new2(p_stat->sb->name) : Qnil;
2177
+ }
2178
+
2179
+ /* */
2180
+ VALUE zipruby_stat_index(VALUE self) {
2181
+ struct zipruby_stat *p_stat;
2182
+
2183
+ Data_Get_Struct(self, struct zipruby_stat, p_stat);
2184
+
2185
+ return INT2NUM(p_stat->sb->index);
2186
+ }
2187
+
2188
+ /* */
2189
+ VALUE zipruby_stat_crc(VALUE self) {
2190
+ struct zipruby_stat *p_stat;
2191
+
2192
+ Data_Get_Struct(self, struct zipruby_stat, p_stat);
2193
+
2194
+ return UINT2NUM(p_stat->sb->crc);
2195
+ }
2196
+
2197
+ /* */
2198
+ VALUE zipruby_stat_size(VALUE self) {
2199
+ struct zipruby_stat *p_stat;
2200
+
2201
+ Data_Get_Struct(self, struct zipruby_stat, p_stat);
2202
+
2203
+ return LONG2NUM(p_stat->sb->size);
2204
+ }
2205
+
2206
+ /* */
2207
+ VALUE zipruby_stat_mtime(VALUE self) {
2208
+ struct zipruby_stat *p_stat;
2209
+
2210
+ Data_Get_Struct(self, struct zipruby_stat, p_stat);
2211
+
2212
+ return rb_funcall(rb_cTime, rb_intern("at"), 1, LONG2NUM((long) p_stat->sb->mtime));
2213
+ }
2214
+
2215
+ /* */
2216
+ VALUE zipruby_stat_comp_size(VALUE self) {
2217
+ struct zipruby_stat *p_stat;
2218
+
2219
+ Data_Get_Struct(self, struct zipruby_stat, p_stat);
2220
+
2221
+ return LONG2NUM(p_stat->sb->comp_size);
2222
+ }
2223
+
2224
+ /* */
2225
+ VALUE zipruby_stat_comp_method(VALUE self) {
2226
+ struct zipruby_stat *p_stat;
2227
+
2228
+ Data_Get_Struct(self, struct zipruby_stat, p_stat);
2229
+
2230
+ return INT2NUM(p_stat->sb->comp_method);
2231
+ }
2232
+
2233
+ /* */
2234
+ VALUE zipruby_stat_encryption_method(VALUE self) {
2235
+ struct zipruby_stat *p_stat;
2236
+
2237
+ Data_Get_Struct(self, struct zipruby_stat, p_stat);
2238
+
2239
+ return INT2NUM(p_stat->sb->encryption_method);
2240
+ }
2241
+
2242
+ /* */
2243
+ VALUE zipruby_stat_is_directory(VALUE self) {
2244
+ struct zipruby_stat *p_stat;
2245
+ const char *name;
2246
+ size_t name_len;
2247
+ off_t size;
2248
+
2249
+ Data_Get_Struct(self, struct zipruby_stat, p_stat);
2250
+ name = p_stat->sb->name;
2251
+ size = p_stat->sb->size;
2252
+
2253
+ if (!name || size != 0) {
2254
+ return Qfalse;
2255
+ }
2256
+
2257
+ name_len = strlen(name);
2258
+
2259
+ if (name_len > 0 && name[name_len - 1] == '/') {
2260
+ return Qtrue;
2261
+ } else {
2262
+ return Qfalse;
2263
+ }
2264
+ }
2265
+ #include "ruby.h"
2266
+ #include "zip.h"
2267
+ #include "zipruby.h"
2268
+ #include "zipruby_zip.h"
2269
+
2270
+ VALUE Zip;
2271
+
2272
+ void Init_zipruby_zip() {
2273
+ Zip = rb_define_module("Zip");
2274
+ rb_define_const(Zip, "VERSION", rb_str_new2(VERSION));
2275
+
2276
+ rb_define_const(Zip, "CREATE", INT2NUM(ZIP_CREATE));
2277
+ rb_define_const(Zip, "EXCL", INT2NUM(ZIP_EXCL));
2278
+ rb_define_const(Zip, "CHECKCONS", INT2NUM(ZIP_CHECKCONS));
2279
+ rb_define_const(Zip, "TRUNC", INT2NUM(ZIP_TRUNC));
2280
+
2281
+ rb_define_const(Zip, "FL_NOCASE", INT2NUM(ZIP_FL_NOCASE));
2282
+ rb_define_const(Zip, "FL_NODIR", INT2NUM(ZIP_FL_NODIR));
2283
+ rb_define_const(Zip, "FL_COMPRESSED", INT2NUM(ZIP_FL_COMPRESSED));
2284
+ rb_define_const(Zip, "FL_UNCHANGED", INT2NUM(ZIP_FL_UNCHANGED));
2285
+
2286
+ rb_define_const(Zip, "CM_DEFAULT" , INT2NUM(ZIP_CM_DEFAULT));
2287
+ rb_define_const(Zip, "CM_STORE", INT2NUM(ZIP_CM_STORE));
2288
+ rb_define_const(Zip, "CM_SHRINK", INT2NUM(ZIP_CM_SHRINK));
2289
+ rb_define_const(Zip, "CM_REDUCE_1", INT2NUM(ZIP_CM_REDUCE_1));
2290
+ rb_define_const(Zip, "CM_REDUCE_2", INT2NUM(ZIP_CM_REDUCE_2));
2291
+ rb_define_const(Zip, "CM_REDUCE_3", INT2NUM(ZIP_CM_REDUCE_3));
2292
+ rb_define_const(Zip, "CM_REDUCE_4", INT2NUM(ZIP_CM_REDUCE_4));
2293
+ rb_define_const(Zip, "CM_IMPLODE", INT2NUM(ZIP_CM_IMPLODE));
2294
+ rb_define_const(Zip, "CM_DEFLATE", INT2NUM(ZIP_CM_DEFLATE));
2295
+ rb_define_const(Zip, "CM_DEFLATE64", INT2NUM(ZIP_CM_DEFLATE64));
2296
+ rb_define_const(Zip, "CM_PKWARE_IMPLODE", INT2NUM(ZIP_CM_PKWARE_IMPLODE));
2297
+ rb_define_const(Zip, "CM_BZIP2", INT2NUM(ZIP_CM_BZIP2));
2298
+
2299
+ rb_define_const(Zip, "EM_NONE", INT2NUM(ZIP_EM_NONE));
2300
+ rb_define_const(Zip, "EM_TRAD_PKWARE", INT2NUM(ZIP_EM_TRAD_PKWARE));
2301
+ // XXX: Strong Encryption Header not parsed yet
2302
+ }
2303
+ #include <string.h>
2304
+
2305
+ #include "zip.h"
2306
+ #include "zipint.h"
2307
+ #include "zipruby_zip_source_io.h"
2308
+ #include "ruby.h"
2309
+
2310
+ #define IO_READ_BUFSIZE 8192
2311
+
2312
+ static VALUE io_read(VALUE io) {
2313
+ return rb_funcall(io, rb_intern("read"), 1, INT2FIX(IO_READ_BUFSIZE));
2314
+ }
2315
+
2316
+ static ssize_t read_io(void *state, void *data, size_t len, enum zip_source_cmd cmd) {
2317
+ struct read_io *z;
2318
+ VALUE src;
2319
+ char *buf;
2320
+ size_t n;
2321
+ int status = 0;
2322
+
2323
+ z = (struct read_io *) state;
2324
+ buf = (char *) data;
2325
+
2326
+ switch (cmd) {
2327
+ case ZIP_SOURCE_OPEN:
2328
+ return 0;
2329
+
2330
+ case ZIP_SOURCE_READ:
2331
+ src = rb_protect(io_read, z->io, NULL);
2332
+
2333
+ if (status != 0) {
2334
+ VALUE message, clazz;
2335
+
2336
+ #if defined(RUBY_VM)
2337
+ message = rb_funcall(rb_errinfo(), rb_intern("message"), 0);
2338
+ clazz = CLASS_OF(rb_errinfo());
2339
+ #else
2340
+ message = rb_funcall(ruby_errinfo, rb_intern("message"), 0);
2341
+ clazz = CLASS_OF(ruby_errinfo);
2342
+ #endif
2343
+
2344
+ rb_warn("Error in IO: %s (%s)", RSTRING_PTR(message), rb_class2name(clazz));
2345
+ return -1;
2346
+ }
2347
+
2348
+ if (TYPE(src) != T_STRING) {
2349
+ return 0;
2350
+ }
2351
+
2352
+ n = RSTRING_LEN(src);
2353
+
2354
+ if (n > 0) {
2355
+ n = (n > len) ? len : n;
2356
+ memcpy(buf, RSTRING_PTR(src), n);
2357
+ }
2358
+
2359
+ return n;
2360
+
2361
+ case ZIP_SOURCE_CLOSE:
2362
+ return 0;
2363
+
2364
+ case ZIP_SOURCE_STAT:
2365
+ {
2366
+ struct zip_stat *st = (struct zip_stat *)data;
2367
+ zip_stat_init(st);
2368
+ st->mtime = z->mtime;
2369
+ return sizeof(*st);
2370
+ }
2371
+
2372
+ case ZIP_SOURCE_ERROR:
2373
+ return 0;
2374
+
2375
+ case ZIP_SOURCE_FREE:
2376
+ free(z);
2377
+ return 0;
2378
+ }
2379
+
2380
+ return -1;
2381
+ }
2382
+
2383
+ struct zip_source *zip_source_io(struct zip *za, struct read_io *z) {
2384
+ struct zip_source *zs;
2385
+ zs = zip_source_function(za, read_io, z);
2386
+ return zs;
2387
+ }
2388
+ #include <string.h>
2389
+
2390
+ #include "zip.h"
2391
+ #include "zipint.h"
2392
+ #include "zipruby_zip_source_proc.h"
2393
+ #include "ruby.h"
2394
+
2395
+ static VALUE proc_call(VALUE proc) {
2396
+ return rb_funcall(proc, rb_intern("call"), 0);
2397
+ }
2398
+
2399
+ static ssize_t read_proc(void *state, void *data, size_t len, enum zip_source_cmd cmd) {
2400
+ struct read_proc *z;
2401
+ VALUE src;
2402
+ char *buf;
2403
+ size_t n;
2404
+ int status = 0;
2405
+
2406
+ z = (struct read_proc *) state;
2407
+ buf = (char *) data;
2408
+
2409
+ switch (cmd) {
2410
+ case ZIP_SOURCE_OPEN:
2411
+ return 0;
2412
+
2413
+ case ZIP_SOURCE_READ:
2414
+ src = rb_protect(proc_call, z->proc, &status);
2415
+
2416
+ if (status != 0) {
2417
+ VALUE message, clazz;
2418
+
2419
+ #if defined(RUBY_VM)
2420
+ message = rb_funcall(rb_errinfo(), rb_intern("message"), 0);
2421
+ clazz = CLASS_OF(rb_errinfo());
2422
+ #else
2423
+ message = rb_funcall(ruby_errinfo, rb_intern("message"), 0);
2424
+ clazz = CLASS_OF(ruby_errinfo);
2425
+ #endif
2426
+
2427
+ rb_warn("Error in Proc: %s (%s)", RSTRING_PTR(message), rb_class2name(clazz));
2428
+ return -1;
2429
+ }
2430
+
2431
+
2432
+ if (TYPE(src) != T_STRING) {
2433
+ src = rb_funcall(src, rb_intern("to_s"), 0);
2434
+ }
2435
+
2436
+ n = RSTRING_LEN(src);
2437
+
2438
+ if (n > 0) {
2439
+ n = (n > len) ? len : n;
2440
+ memcpy(buf, RSTRING_PTR(src), n);
2441
+ }
2442
+
2443
+ return n;
2444
+
2445
+ case ZIP_SOURCE_CLOSE:
2446
+ return 0;
2447
+
2448
+ case ZIP_SOURCE_STAT:
2449
+ {
2450
+ struct zip_stat *st = (struct zip_stat *)data;
2451
+ zip_stat_init(st);
2452
+ st->mtime = z->mtime;
2453
+ return sizeof(*st);
2454
+ }
2455
+
2456
+ case ZIP_SOURCE_ERROR:
2457
+ return 0;
2458
+
2459
+ case ZIP_SOURCE_FREE:
2460
+ free(z);
2461
+ return 0;
2462
+ }
2463
+
2464
+ return -1;
2465
+ }
2466
+
2467
+ struct zip_source *zip_source_proc(struct zip *za, struct read_proc *z) {
2468
+ struct zip_source *zs;
2469
+ zs = zip_source_function(za, read_proc, z);
2470
+ return zs;
2471
+ }