zipruby1.9 0.3.3-mswin32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+ }