libarchive-ruby 0.0.1.dev
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.
- data/COPYING.txt +339 -0
- data/README.rdoc +135 -0
- data/ext/archive.cpp +1547 -0
- data/ext/entry.cpp +592 -0
- data/ext/extconf.rb +38 -0
- data/ext/main.hpp +86 -0
- metadata +80 -0
data/ext/archive.cpp
ADDED
@@ -0,0 +1,1547 @@
|
|
1
|
+
/****************************************************************************
|
2
|
+
This file is part of libarchive-ruby.
|
3
|
+
|
4
|
+
libarchive-ruby is a Ruby binding for the C library libarchive.
|
5
|
+
|
6
|
+
Copyright (C) 2011 Hans Mackowiak
|
7
|
+
|
8
|
+
libarchive-ruby is free software; you can redistribute it and/or modify
|
9
|
+
it under the terms of the GNU General Public License as published by
|
10
|
+
the Free Software Foundation; either version 2 of the License, or
|
11
|
+
(at your option) any later version.
|
12
|
+
|
13
|
+
libarchive-ruby is distributed in the hope that it will be useful,
|
14
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
GNU General Public License for more details.
|
17
|
+
|
18
|
+
You should have received a copy of the GNU General Public License along
|
19
|
+
with libarchive-ruby; if not, write to the Free Software Foundation, Inc.,
|
20
|
+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
21
|
+
****************************************************************************/
|
22
|
+
|
23
|
+
#include "main.hpp"
|
24
|
+
#include <vector>
|
25
|
+
#include <exception>
|
26
|
+
#include <stdexcept>
|
27
|
+
#define _self wrap<rarchive*>(self)
|
28
|
+
#define RB_ENSURE(func1,obj1,func2,obj2)\
|
29
|
+
rb_ensure(RUBY_METHOD_FUNC(func1),(VALUE)obj1,RUBY_METHOD_FUNC(func2),(VALUE)obj2)
|
30
|
+
|
31
|
+
//TODO: handle string IO as archive Archive.new(stringio)
|
32
|
+
|
33
|
+
|
34
|
+
VALUE rb_cArchive,rb_eArchiveError,rb_eArchiveErrorFormat,rb_eArchiveErrorCompression;
|
35
|
+
|
36
|
+
VALUE Archive_alloc(VALUE self)
|
37
|
+
{
|
38
|
+
rarchive *result = new rarchive;
|
39
|
+
return wrap(result);
|
40
|
+
}
|
41
|
+
|
42
|
+
VALUE Archive_initialize_copy(VALUE self, VALUE other)
|
43
|
+
{
|
44
|
+
VALUE result = rb_call_super(1,&other);
|
45
|
+
_self->path = std::string(wrap<rarchive*>(other)->path.c_str());
|
46
|
+
_self->type = wrap<rarchive*>(other)->type;
|
47
|
+
return result;
|
48
|
+
}
|
49
|
+
|
50
|
+
struct extract_obj {
|
51
|
+
struct archive* archive;
|
52
|
+
int extract_opt;
|
53
|
+
};
|
54
|
+
|
55
|
+
struct write_obj {
|
56
|
+
struct archive* archive;
|
57
|
+
std::vector<struct archive_entry *> *entries;
|
58
|
+
std::vector<std::string> *allbuff;
|
59
|
+
};
|
60
|
+
|
61
|
+
|
62
|
+
VALUE Archive_read_block_ensure(struct archive * data)
|
63
|
+
{
|
64
|
+
archive_read_finish(data);
|
65
|
+
return Qnil;
|
66
|
+
}
|
67
|
+
|
68
|
+
VALUE Archive_write_block_ensure(struct archive * data)
|
69
|
+
{
|
70
|
+
archive_write_finish(data);
|
71
|
+
return Qnil;
|
72
|
+
}
|
73
|
+
|
74
|
+
int rubymyopen(struct archive *a, void *client_data)
|
75
|
+
{
|
76
|
+
rb_funcall((VALUE)client_data,rb_intern("rewind"),0);
|
77
|
+
return ARCHIVE_OK;
|
78
|
+
}
|
79
|
+
ssize_t
|
80
|
+
rubymyread(struct archive *a, void *client_data, const void **buff)
|
81
|
+
{
|
82
|
+
VALUE result = rb_funcall((VALUE)client_data,rb_intern("read"),0);
|
83
|
+
if(result == Qnil){
|
84
|
+
*buff = NULL;
|
85
|
+
return 0;
|
86
|
+
}else{
|
87
|
+
if (RSTRING_LEN(result))
|
88
|
+
*buff = RSTRING_PTR(result);
|
89
|
+
else
|
90
|
+
*buff = NULL;
|
91
|
+
return RSTRING_LEN(result);
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
95
|
+
ssize_t rubymywrite(struct archive *a,void *client_data,const void *buffer, size_t length){
|
96
|
+
VALUE string = rb_str_new((char*)buffer,length);
|
97
|
+
// rb_funcall(string,rb_intern("rstrip!"),0);
|
98
|
+
return NUM2INT(rb_funcall((VALUE)client_data,rb_intern("write"),1,string));
|
99
|
+
}
|
100
|
+
|
101
|
+
int rubymyclose(struct archive *a, void *client_data)
|
102
|
+
{
|
103
|
+
rb_funcall((VALUE)client_data,rb_intern("rewind"),0);
|
104
|
+
return ARCHIVE_OK;
|
105
|
+
}
|
106
|
+
|
107
|
+
|
108
|
+
void Archive_format_from_path(VALUE self,int &format,int &compression)
|
109
|
+
{
|
110
|
+
if(format == ARCHIVE_FORMAT_EMPTY){
|
111
|
+
if(_self->type == archive_path){
|
112
|
+
std::string selfpath = _self->path;
|
113
|
+
if(selfpath.substr(selfpath.length()-7).compare(".tar.xz")==0 || selfpath.substr(selfpath.length()-4).compare(".txz")==0 ){
|
114
|
+
format=ARCHIVE_FORMAT_TAR_USTAR;
|
115
|
+
compression=ARCHIVE_COMPRESSION_XZ;
|
116
|
+
}else if(selfpath.substr(selfpath.length()-9).compare(".tar.lzma")==0 ){
|
117
|
+
format=ARCHIVE_FORMAT_TAR_USTAR;
|
118
|
+
compression=ARCHIVE_COMPRESSION_LZMA;
|
119
|
+
}else if(selfpath.substr(selfpath.length()-7).compare(".tar.gz")==0 || selfpath.substr(selfpath.length()-4).compare(".tgz")==0){
|
120
|
+
format=ARCHIVE_FORMAT_TAR_USTAR;
|
121
|
+
compression=ARCHIVE_COMPRESSION_GZIP;
|
122
|
+
}else if(selfpath.substr(selfpath.length()-8).compare(".tar.bz2")==0 || selfpath.substr(selfpath.length()-4).compare(".tbz")==0 || selfpath.substr(selfpath.length()-4).compare(".tb2")==0){
|
123
|
+
format=ARCHIVE_FORMAT_TAR_USTAR;
|
124
|
+
compression=ARCHIVE_COMPRESSION_BZIP2;
|
125
|
+
}else if(selfpath.substr(selfpath.length()-4).compare(".tar")==0)
|
126
|
+
format=ARCHIVE_FORMAT_TAR_USTAR;
|
127
|
+
}
|
128
|
+
}
|
129
|
+
if(format==ARCHIVE_FORMAT_TAR_GNUTAR)
|
130
|
+
format=ARCHIVE_FORMAT_TAR_USTAR;
|
131
|
+
}
|
132
|
+
|
133
|
+
int Archive_read_ruby(VALUE self,struct archive *data)
|
134
|
+
{
|
135
|
+
int error =0;
|
136
|
+
switch(_self->type){
|
137
|
+
case archive_path:
|
138
|
+
error = archive_read_open_filename(data,_self->path.c_str(),10240);
|
139
|
+
break;
|
140
|
+
case archive_fd:
|
141
|
+
error = archive_read_open_fd(data,_self->fd,10240);
|
142
|
+
break;
|
143
|
+
case archive_buffer:
|
144
|
+
break;
|
145
|
+
case archive_ruby:
|
146
|
+
error = archive_read_open(data, (void*)_self->ruby,rubymyopen,rubymyread,rubymyclose);
|
147
|
+
break;
|
148
|
+
}
|
149
|
+
return error;
|
150
|
+
}
|
151
|
+
|
152
|
+
|
153
|
+
|
154
|
+
int Archive_write_ruby(VALUE self,struct archive *data)
|
155
|
+
{
|
156
|
+
int error =0;
|
157
|
+
switch(_self->type){
|
158
|
+
case archive_path:
|
159
|
+
error = archive_write_open_filename(data,_self->path.c_str());
|
160
|
+
break;
|
161
|
+
case archive_fd:
|
162
|
+
error = archive_write_open_fd(data,_self->fd);
|
163
|
+
break;
|
164
|
+
case archive_buffer:
|
165
|
+
break;
|
166
|
+
case archive_ruby:
|
167
|
+
error = archive_write_open(data,(void*)_self->ruby,rubymyopen,rubymywrite,rubymyclose);
|
168
|
+
break;
|
169
|
+
}
|
170
|
+
return error;
|
171
|
+
}
|
172
|
+
|
173
|
+
int Archive_write_set_compression(struct archive *data,int compression)
|
174
|
+
{
|
175
|
+
int error = 0;
|
176
|
+
switch(compression){
|
177
|
+
case ARCHIVE_COMPRESSION_NONE:
|
178
|
+
error = archive_write_set_compression_none(data);
|
179
|
+
break;
|
180
|
+
case ARCHIVE_COMPRESSION_GZIP:
|
181
|
+
error = archive_write_set_compression_gzip(data);
|
182
|
+
break;
|
183
|
+
case ARCHIVE_COMPRESSION_BZIP2:
|
184
|
+
error = archive_write_set_compression_bzip2(data);
|
185
|
+
break;
|
186
|
+
case ARCHIVE_COMPRESSION_COMPRESS:
|
187
|
+
error = archive_write_set_compression_compress(data);
|
188
|
+
break;
|
189
|
+
case ARCHIVE_COMPRESSION_LZMA:
|
190
|
+
error = archive_write_set_compression_lzma(data);
|
191
|
+
break;
|
192
|
+
case ARCHIVE_COMPRESSION_XZ:
|
193
|
+
error = archive_write_set_compression_xz(data);
|
194
|
+
break;
|
195
|
+
default:
|
196
|
+
rb_raise(rb_eArchiveErrorCompression,"unsupported compresstype");
|
197
|
+
break;
|
198
|
+
}
|
199
|
+
return error;
|
200
|
+
}
|
201
|
+
/*
|
202
|
+
*call-seq:
|
203
|
+
* new( path [, format [, compression ] ] ) → an_archive
|
204
|
+
*
|
205
|
+
* Makes a new Archive object. If format is given, a new archive is created or
|
206
|
+
* an existing archive will be converted into the given format.
|
207
|
+
* ===Parameters
|
208
|
+
* [path] The path to the archive. May or may not exist.
|
209
|
+
* [format] The archive's format as a symbol. If you ommit this, the format will
|
210
|
+
* be guessed from the file extension. Possible formats are:
|
211
|
+
* * :ar
|
212
|
+
* * :tar
|
213
|
+
* * :xar
|
214
|
+
* * :zip
|
215
|
+
* [compression] Symbol inidicating the compression you want to use. If
|
216
|
+
* ommited, it will be guessed from the file extension.
|
217
|
+
* Possible formats are:
|
218
|
+
* * :bzip2
|
219
|
+
* * :compress
|
220
|
+
* * :gzip
|
221
|
+
* * :lzma
|
222
|
+
* * :xz
|
223
|
+
* ===Raises
|
224
|
+
* [FormatError] Unknown archive format or writing not supported.
|
225
|
+
* [CompressionError] Unknown compression format.
|
226
|
+
* ===Examples
|
227
|
+
* See the README for some examples.
|
228
|
+
*/
|
229
|
+
|
230
|
+
VALUE Archive_initialize(int argc, VALUE *argv,VALUE self)
|
231
|
+
{
|
232
|
+
VALUE path,r_format,r_compression;
|
233
|
+
rb_scan_args(argc, argv, "12", &path,&r_format,&r_compression);
|
234
|
+
if(rb_obj_is_kind_of(path,rb_cIO)){
|
235
|
+
_self->fd = NUM2INT(rb_funcall(path,rb_intern("fileno"),0));
|
236
|
+
_self->type = archive_fd;
|
237
|
+
rb_scan_args(argc, argv, "21", &path,&r_format,&r_compression);
|
238
|
+
}else if(rb_respond_to(path,rb_intern("read"))){
|
239
|
+
_self->ruby = path;
|
240
|
+
_self->type = archive_ruby;
|
241
|
+
rb_scan_args(argc, argv, "21", &path,&r_format,&r_compression);
|
242
|
+
}else{
|
243
|
+
path = rb_file_s_expand_path(1,&path);
|
244
|
+
_self->path = std::string(rb_string_value_cstr(&path));
|
245
|
+
_self->type =archive_path;
|
246
|
+
}
|
247
|
+
|
248
|
+
//to set the format the file must convert
|
249
|
+
if(!NIL_P(r_format)){
|
250
|
+
|
251
|
+
char buff[8192];
|
252
|
+
//std::string selfpath =_self->path;
|
253
|
+
size_t bytes_read;
|
254
|
+
struct archive *a = archive_read_new(),*b=archive_write_new();
|
255
|
+
struct archive_entry *entry;
|
256
|
+
int format,compression,error=0;
|
257
|
+
std::vector<struct archive_entry *> entries;
|
258
|
+
std::vector<std::string> allbuff;
|
259
|
+
if(rb_obj_is_kind_of(r_format,rb_cSymbol)!=Qtrue)
|
260
|
+
rb_raise(rb_eTypeError,"exepted Symbol");
|
261
|
+
if(SYM2ID(r_format) == rb_intern("tar"))
|
262
|
+
format = ARCHIVE_FORMAT_TAR_GNUTAR;
|
263
|
+
else if(SYM2ID(r_format) == rb_intern("zip"))
|
264
|
+
format = ARCHIVE_FORMAT_ZIP;
|
265
|
+
else if(SYM2ID(r_format) == rb_intern("ar"))
|
266
|
+
format = ARCHIVE_FORMAT_AR_GNU;
|
267
|
+
else if(SYM2ID(r_format) == rb_intern("xar"))
|
268
|
+
format = ARCHIVE_FORMAT_XAR;
|
269
|
+
else
|
270
|
+
rb_raise(rb_eTypeError,"wrong format");
|
271
|
+
|
272
|
+
if(NIL_P(r_compression)){
|
273
|
+
compression = ARCHIVE_COMPRESSION_NONE;
|
274
|
+
error = archive_write_set_compression_none(b);
|
275
|
+
}else if(SYM2ID(r_compression) == rb_intern("gzip")){
|
276
|
+
compression =ARCHIVE_COMPRESSION_GZIP;
|
277
|
+
error = archive_write_set_compression_gzip(b);
|
278
|
+
}else if(SYM2ID(r_compression) == rb_intern("bzip2")){
|
279
|
+
compression =ARCHIVE_COMPRESSION_BZIP2;
|
280
|
+
error = archive_write_set_compression_bzip2(b);
|
281
|
+
}else if(SYM2ID(r_compression) == rb_intern("compress")){
|
282
|
+
compression =ARCHIVE_COMPRESSION_BZIP2;
|
283
|
+
error = archive_write_set_compression_compress(b);
|
284
|
+
}else if(SYM2ID(r_compression) == rb_intern("lzma")){
|
285
|
+
compression =ARCHIVE_COMPRESSION_LZMA;
|
286
|
+
error = archive_write_set_compression_lzma(b);
|
287
|
+
}else if(SYM2ID(r_compression) == rb_intern("xz")){
|
288
|
+
compression =ARCHIVE_COMPRESSION_XZ;
|
289
|
+
error = archive_write_set_compression_xz(b);
|
290
|
+
}else
|
291
|
+
rb_raise(rb_eTypeError,"unsupported compression");
|
292
|
+
|
293
|
+
if(error)
|
294
|
+
rb_raise(rb_eArchiveError,"error (%d): %s ",archive_errno(b),archive_error_string(b));
|
295
|
+
|
296
|
+
archive_read_support_compression_all(a);
|
297
|
+
archive_read_support_format_all(a);
|
298
|
+
archive_read_support_format_raw(a);
|
299
|
+
//autodetect format and compression
|
300
|
+
error=Archive_read_ruby(self,a);
|
301
|
+
_self->format = format;
|
302
|
+
_self->compression = compression;
|
303
|
+
if(error==ARCHIVE_OK){
|
304
|
+
while(archive_read_next_header(a, &entry)==ARCHIVE_OK){
|
305
|
+
if(format==archive_format(a) && compression==archive_compression(a)){
|
306
|
+
archive_read_finish(a);
|
307
|
+
return self;
|
308
|
+
}
|
309
|
+
entries.push_back(archive_entry_clone(entry));
|
310
|
+
allbuff.push_back(std::string(""));
|
311
|
+
while ((bytes_read=archive_read_data(a,&buff,sizeof(buff)))>0)
|
312
|
+
allbuff.back().append(buff,bytes_read);
|
313
|
+
}
|
314
|
+
archive_read_finish(a);
|
315
|
+
}
|
316
|
+
//format fix
|
317
|
+
if(format==ARCHIVE_FORMAT_TAR_GNUTAR)
|
318
|
+
format=ARCHIVE_FORMAT_TAR_USTAR;
|
319
|
+
|
320
|
+
if((error = archive_write_set_format(b,format)) != ARCHIVE_OK)
|
321
|
+
rb_raise(rb_eArchiveErrorFormat,"error (%d): %s ",error,archive_error_string(b));
|
322
|
+
error=Archive_write_ruby(self,b);
|
323
|
+
if(error==ARCHIVE_OK){
|
324
|
+
//write old data back
|
325
|
+
for(unsigned int i=0; i<entries.size(); i++){
|
326
|
+
archive_write_header(b,entries[i]);
|
327
|
+
archive_write_data(b,allbuff[i].c_str(),allbuff[i].length());
|
328
|
+
archive_write_finish_entry(b);
|
329
|
+
}
|
330
|
+
archive_write_finish(b);
|
331
|
+
}
|
332
|
+
}
|
333
|
+
return self;
|
334
|
+
}
|
335
|
+
|
336
|
+
/*
|
337
|
+
* call-seq:
|
338
|
+
* path() → a_string
|
339
|
+
*
|
340
|
+
* Returns the path (filename) of the archive.
|
341
|
+
* ===Return value
|
342
|
+
* Returns path of the archive. May or may not exist.
|
343
|
+
* ===Example
|
344
|
+
* a.path #=> /home/freak/myarchive.tar.gz
|
345
|
+
*/
|
346
|
+
|
347
|
+
VALUE Archive_path(VALUE self)
|
348
|
+
{
|
349
|
+
return (_self->type == archive_path) ? rb_str_new2(_self->path.c_str()) : Qnil;
|
350
|
+
}
|
351
|
+
|
352
|
+
VALUE Archive_each_block(struct archive *data)
|
353
|
+
{
|
354
|
+
VALUE result = rb_ary_new();
|
355
|
+
struct archive_entry *entry;
|
356
|
+
while (archive_read_next_header(data, &entry) == ARCHIVE_OK) {
|
357
|
+
VALUE temp = wrap(entry);
|
358
|
+
if(rb_proc_arity(rb_block_proc())==1){
|
359
|
+
rb_yield(temp);
|
360
|
+
archive_read_data_skip(data);
|
361
|
+
}else{
|
362
|
+
char buff[8192];
|
363
|
+
std::string str;
|
364
|
+
size_t bytes_read;
|
365
|
+
try {
|
366
|
+
while ((bytes_read=archive_read_data(data,&buff,sizeof(buff)))>0)
|
367
|
+
str.append(buff,bytes_read);
|
368
|
+
}catch(...){
|
369
|
+
rb_raise(rb_eArchiveError,"error:%d:%s",archive_errno(data),archive_error_string(data));
|
370
|
+
}
|
371
|
+
rb_yield_values(2,temp,rb_str_new2(str.c_str()));
|
372
|
+
}
|
373
|
+
rb_ary_push(result,temp);
|
374
|
+
}
|
375
|
+
return result;
|
376
|
+
}
|
377
|
+
|
378
|
+
/*
|
379
|
+
* call-seq:
|
380
|
+
* each(){|entry [, data]| ... } → an_array
|
381
|
+
* each() → an_enumerator
|
382
|
+
*
|
383
|
+
* Iterates through the archive and yields each entry as an Archive::Entry object. The second parameter
|
384
|
+
* contains the data of that entry, so you don't have to extract it only to read what's in it.
|
385
|
+
* ===Return value
|
386
|
+
* If a block is given, returns an array of Archive::Entry objects, otherwise an enumerator.
|
387
|
+
* ===Example
|
388
|
+
* a.each{|entry| p entry.path}
|
389
|
+
* a.each{|entry, data| puts "'#{entry.path}' contains '#{data}'"}
|
390
|
+
* Output:
|
391
|
+
* "file1.txt"
|
392
|
+
* "file2.txt"
|
393
|
+
* 'file1.txt' contains 'I am file1!'
|
394
|
+
* 'file2.txt' contains 'I am file2!'
|
395
|
+
*/
|
396
|
+
|
397
|
+
VALUE Archive_each(VALUE self)
|
398
|
+
{
|
399
|
+
RETURN_ENUMERATOR(self,0,NULL);
|
400
|
+
struct archive *a = archive_read_new();
|
401
|
+
|
402
|
+
archive_read_support_compression_all(a);
|
403
|
+
archive_read_support_format_all(a);
|
404
|
+
archive_read_support_format_raw(a);
|
405
|
+
int error=Archive_read_ruby(self,a);
|
406
|
+
if(error==ARCHIVE_OK)
|
407
|
+
return RB_ENSURE(Archive_each_block,a,Archive_read_block_ensure,a);
|
408
|
+
return Qnil;
|
409
|
+
}
|
410
|
+
|
411
|
+
|
412
|
+
VALUE Archive_each_entry_block(struct archive *data)
|
413
|
+
{
|
414
|
+
VALUE result = rb_ary_new();
|
415
|
+
struct archive_entry *entry;
|
416
|
+
while (archive_read_next_header(data, &entry) == ARCHIVE_OK) {
|
417
|
+
VALUE temp = wrap(entry);
|
418
|
+
rb_yield(temp);
|
419
|
+
archive_read_data_skip(data);
|
420
|
+
rb_ary_push(result,temp);
|
421
|
+
}
|
422
|
+
return result;
|
423
|
+
}
|
424
|
+
|
425
|
+
/*
|
426
|
+
* call-seq:
|
427
|
+
* each_entry() {|entry| ... } → an_array
|
428
|
+
* each_entry() → an_enumerator
|
429
|
+
*
|
430
|
+
* Iterates through the archive and yields each entry as an Archive::Entry object.
|
431
|
+
* This is the same as #each, but doesn't allow for the second block parameter.
|
432
|
+
* ===Return value
|
433
|
+
* If a block is given, returns an array of Archive::Entry objects, otherwise an enumerator.
|
434
|
+
* ===Example
|
435
|
+
* a.each_entry{|entry| p entry.path}
|
436
|
+
* Output:
|
437
|
+
* "file1.txt"
|
438
|
+
* "file2.txt"
|
439
|
+
*/
|
440
|
+
|
441
|
+
VALUE Archive_each_entry(VALUE self)
|
442
|
+
{
|
443
|
+
RETURN_ENUMERATOR(self,0,NULL);
|
444
|
+
struct archive *a = archive_read_new();
|
445
|
+
|
446
|
+
archive_read_support_compression_all(a);
|
447
|
+
archive_read_support_format_all(a);
|
448
|
+
archive_read_support_format_raw(a);
|
449
|
+
int error=Archive_read_ruby(self,a);
|
450
|
+
if(error==ARCHIVE_OK)
|
451
|
+
return RB_ENSURE(Archive_each_entry_block,a,Archive_read_block_ensure,a);
|
452
|
+
return Qnil;
|
453
|
+
}
|
454
|
+
|
455
|
+
|
456
|
+
VALUE Archive_each_data_block(struct archive *data)
|
457
|
+
{
|
458
|
+
VALUE result = rb_ary_new();
|
459
|
+
struct archive_entry *entry;
|
460
|
+
while (archive_read_next_header(data, &entry) == ARCHIVE_OK) {
|
461
|
+
char buff[8192];
|
462
|
+
std::string str;
|
463
|
+
size_t bytes_read;
|
464
|
+
try{
|
465
|
+
while ((bytes_read=archive_read_data(data,&buff,sizeof(buff)))>0)
|
466
|
+
str.append(buff,bytes_read);
|
467
|
+
} catch (...){
|
468
|
+
rb_raise(rb_eArchiveError,"error:%d:%s",archive_errno(data),archive_error_string(data));
|
469
|
+
}
|
470
|
+
rb_yield(rb_str_new2(str.c_str()));
|
471
|
+
rb_ary_push(result,rb_str_new2(str.c_str()));
|
472
|
+
}
|
473
|
+
return result;
|
474
|
+
}
|
475
|
+
|
476
|
+
|
477
|
+
/*
|
478
|
+
* call-seq:
|
479
|
+
* each_data() {|data| } → an_array
|
480
|
+
* each_data() → an_enumerator
|
481
|
+
*
|
482
|
+
* Iterates through the archive and yields each entry's data as a string.
|
483
|
+
* This is the same as #each, but doesn't allow for the first block parameter.
|
484
|
+
* ===Return value
|
485
|
+
* If a block is given, returns an array of String objects, otherwise an enumerator.
|
486
|
+
* ===Example
|
487
|
+
* a.each{|data| puts "This is: '#{data}'"}
|
488
|
+
* Output:
|
489
|
+
* This is: 'I am file1!'
|
490
|
+
* This is: 'I am file2!'
|
491
|
+
*/
|
492
|
+
|
493
|
+
VALUE Archive_each_data(VALUE self)
|
494
|
+
{
|
495
|
+
RETURN_ENUMERATOR(self,0,NULL);
|
496
|
+
struct archive *a = archive_read_new();
|
497
|
+
|
498
|
+
archive_read_support_compression_all(a);
|
499
|
+
archive_read_support_format_all(a);
|
500
|
+
archive_read_support_format_raw(a);
|
501
|
+
int error=Archive_read_ruby(self,a);
|
502
|
+
if(error==ARCHIVE_OK)
|
503
|
+
return RB_ENSURE(Archive_each_data_block,a,Archive_read_block_ensure,a);
|
504
|
+
return Qnil;
|
505
|
+
}
|
506
|
+
|
507
|
+
|
508
|
+
/*
|
509
|
+
* call-seq:
|
510
|
+
* archive.to_hash → Hash
|
511
|
+
*
|
512
|
+
* Iterates through the archive and yields each data of an entry as a string object.
|
513
|
+
* ===Return value
|
514
|
+
* returns Hash of Archive::Entry => Sring
|
515
|
+
*/
|
516
|
+
|
517
|
+
VALUE Archive_to_hash(VALUE self)
|
518
|
+
{
|
519
|
+
VALUE result = rb_hash_new();
|
520
|
+
struct archive *a = archive_read_new();
|
521
|
+
struct archive_entry *entry;
|
522
|
+
archive_read_support_compression_all(a);
|
523
|
+
archive_read_support_format_all(a);
|
524
|
+
archive_read_support_format_raw(a);
|
525
|
+
int error=Archive_read_ruby(self,a);
|
526
|
+
if(error==ARCHIVE_OK){
|
527
|
+
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
|
528
|
+
char buff[8192];
|
529
|
+
std::string str;
|
530
|
+
size_t bytes_read;
|
531
|
+
try{
|
532
|
+
while ((bytes_read=archive_read_data(a,&buff,sizeof(buff)))>0)
|
533
|
+
str.append(buff,bytes_read);
|
534
|
+
} catch (...){
|
535
|
+
rb_raise(rb_eArchiveError,"error:%d:%s",archive_errno(a),archive_error_string(a));
|
536
|
+
}
|
537
|
+
rb_hash_aset(result,wrap(entry),rb_str_new2(str.c_str()));
|
538
|
+
}
|
539
|
+
archive_read_finish(a);
|
540
|
+
}
|
541
|
+
return result;
|
542
|
+
}
|
543
|
+
|
544
|
+
VALUE Archive_map_block(struct write_obj * data){
|
545
|
+
for(unsigned int i=0; i< data->entries->size(); i++){
|
546
|
+
VALUE temp = wrap(data->entries->at(i));
|
547
|
+
VALUE val;
|
548
|
+
if(rb_proc_arity(rb_block_proc())<2){
|
549
|
+
val = rb_yield(temp);
|
550
|
+
}else{
|
551
|
+
val = rb_yield_values(2,temp,rb_str_new2(data->allbuff->at(i).c_str()));
|
552
|
+
}
|
553
|
+
VALUE entry,rdata= Qnil;
|
554
|
+
if(rb_obj_is_kind_of(val,rb_cArray)==Qtrue){
|
555
|
+
entry=rb_ary_entry(val,0);
|
556
|
+
rdata=rb_ary_entry(val,1);
|
557
|
+
}else
|
558
|
+
entry = val;
|
559
|
+
if(rb_obj_is_kind_of(entry,rb_cArchiveEntry)==Qtrue){
|
560
|
+
archive_write_header(data->archive,wrap<struct archive_entry *>(val));
|
561
|
+
|
562
|
+
if(rdata == Qnil)
|
563
|
+
archive_write_data(data->archive,data->allbuff->at(i).c_str(),data->allbuff->at(i).length());
|
564
|
+
else{
|
565
|
+
char* buff = StringValueCStr(rdata);
|
566
|
+
archive_write_data(data->archive,buff,strlen(buff));
|
567
|
+
}
|
568
|
+
archive_write_finish_entry(data->archive);
|
569
|
+
}else if(entry==Qnil){
|
570
|
+
}else
|
571
|
+
rb_raise(rb_eTypeError,"exepted %s!",rb_class2name(rb_cArchiveEntry));
|
572
|
+
}
|
573
|
+
return Qnil;
|
574
|
+
}
|
575
|
+
|
576
|
+
/*
|
577
|
+
* call-seq:
|
578
|
+
* map!() {| entry [,data] | ... } → Array
|
579
|
+
* archive.map!() → Enumerator
|
580
|
+
*
|
581
|
+
* Iterates through the archive and changes it's data "on the fly", i.e.
|
582
|
+
* the value your block returns for each iteration is put for the data
|
583
|
+
* in the yielded entry. Your block is expected to return a 2-element
|
584
|
+
* array of form
|
585
|
+
* [archive_entry, "data"]
|
586
|
+
* where +archive_enty+ is the +entry+ yielded to the block (which you
|
587
|
+
* may modify via the Archive::Entry methods) and <tt>"data"</tt> is a
|
588
|
+
* string containing the data you want to set for this entry.
|
589
|
+
*
|
590
|
+
* The block parameters are the same as for #each.
|
591
|
+
* ===Return value
|
592
|
+
* The archive itself.
|
593
|
+
* ===Example
|
594
|
+
* #Double the contents in each file of the archive
|
595
|
+
* a.map!{|entry, data| [entry, data * 2]}
|
596
|
+
* #Clear all files in the archive
|
597
|
+
* a.map!{|entry| [entry, ""]}
|
598
|
+
*/
|
599
|
+
VALUE Archive_map_self(VALUE self)
|
600
|
+
{
|
601
|
+
RETURN_ENUMERATOR(self,0,NULL);
|
602
|
+
char buff[8192];
|
603
|
+
std::string selfpath =_self->path;
|
604
|
+
size_t bytes_read;
|
605
|
+
struct archive *a = archive_read_new(),*b=archive_write_new();
|
606
|
+
struct archive_entry *entry;
|
607
|
+
int format = ARCHIVE_FORMAT_EMPTY,compression = ARCHIVE_COMPRESSION_NONE,error=0;
|
608
|
+
std::vector<struct archive_entry *> entries;
|
609
|
+
std::vector<std::string> allbuff;
|
610
|
+
|
611
|
+
archive_read_support_compression_all(a);
|
612
|
+
archive_read_support_format_all(a);
|
613
|
+
archive_read_support_format_raw(a);
|
614
|
+
//autodetect format and compression
|
615
|
+
error=Archive_read_ruby(self,a);
|
616
|
+
if(error==ARCHIVE_OK){
|
617
|
+
while(archive_read_next_header(a, &entry)==ARCHIVE_OK){
|
618
|
+
format = archive_format(a);
|
619
|
+
compression = archive_compression(a);
|
620
|
+
entries.push_back(archive_entry_clone(entry));
|
621
|
+
allbuff.push_back(std::string(""));
|
622
|
+
try{
|
623
|
+
while ((bytes_read=archive_read_data(a,&buff,sizeof(buff)))>0)
|
624
|
+
allbuff.back().append(buff,bytes_read);
|
625
|
+
} catch (...){
|
626
|
+
rb_raise(rb_eArchiveError,"error:%d:%s",archive_errno(a),archive_error_string(a));
|
627
|
+
}
|
628
|
+
}
|
629
|
+
archive_read_finish(a);
|
630
|
+
//format fix
|
631
|
+
if(format==ARCHIVE_FORMAT_TAR_GNUTAR)
|
632
|
+
format=ARCHIVE_FORMAT_TAR_USTAR;
|
633
|
+
if((error = archive_write_set_format(b,format)) != ARCHIVE_OK)
|
634
|
+
rb_raise(rb_eArchiveErrorFormat,"error (%d): %s ",error,archive_error_string(b));
|
635
|
+
Archive_write_set_compression(b,compression);
|
636
|
+
|
637
|
+
error=Archive_write_ruby(self,b);
|
638
|
+
if(error==ARCHIVE_OK){
|
639
|
+
write_obj obj;
|
640
|
+
obj.archive = b;
|
641
|
+
obj.entries = &entries;
|
642
|
+
obj.allbuff = &allbuff;
|
643
|
+
RB_ENSURE(Archive_map_block,&obj,Archive_write_block_ensure,b);
|
644
|
+
}
|
645
|
+
}
|
646
|
+
return self;
|
647
|
+
}
|
648
|
+
|
649
|
+
/*
|
650
|
+
* call-seq:
|
651
|
+
* [](name) → Archive::Entry or nil
|
652
|
+
*
|
653
|
+
* Returns an archive entry for the given name.
|
654
|
+
* ===Parameters
|
655
|
+
* [name] could be a String or a Regex.
|
656
|
+
* ===Return value
|
657
|
+
* If a matching entry is found, it's returned as an Archive::Entry object. If not,
|
658
|
+
* nil is returned.
|
659
|
+
* ===Example
|
660
|
+
* #Assuming your archive contains file.txt and ruby.txt
|
661
|
+
*
|
662
|
+
* a["file.txt"] #=> Archive::Entry
|
663
|
+
* a[/txt/] #=> Archive::Entry
|
664
|
+
*/
|
665
|
+
|
666
|
+
VALUE Archive_get(VALUE self,VALUE val)
|
667
|
+
{
|
668
|
+
struct archive *a = archive_read_new();
|
669
|
+
struct archive_entry *entry;
|
670
|
+
archive_read_support_compression_all(a);
|
671
|
+
archive_read_support_format_all(a);
|
672
|
+
archive_read_support_format_raw(a);
|
673
|
+
int error=Archive_read_ruby(self,a);
|
674
|
+
if(error==ARCHIVE_OK){
|
675
|
+
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
|
676
|
+
bool find = false;
|
677
|
+
if(rb_obj_is_kind_of(val,rb_cRegexp)==Qtrue){
|
678
|
+
find = rb_reg_match(val,rb_str_new2(archive_entry_pathname(entry)))!=Qnil;
|
679
|
+
}else{
|
680
|
+
val = rb_funcall(val,rb_intern("to_s"),0);
|
681
|
+
std::string str1(rb_string_value_cstr(&val)),str2(str1);
|
682
|
+
str2 += '/'; // dir ends of '/'
|
683
|
+
const char *cstr = archive_entry_pathname(entry);
|
684
|
+
find = (str1.compare(cstr)==0 || str2.compare(cstr)==0);
|
685
|
+
}
|
686
|
+
if(find){
|
687
|
+
VALUE result = wrap(entry);
|
688
|
+
archive_read_finish(a);
|
689
|
+
return result;
|
690
|
+
}
|
691
|
+
}
|
692
|
+
archive_read_finish(a);
|
693
|
+
}
|
694
|
+
return Qnil;
|
695
|
+
}
|
696
|
+
/*
|
697
|
+
* call-seq:
|
698
|
+
* extract( [name = nil [, io [ ,opt ] ] ] ) → an_array
|
699
|
+
*
|
700
|
+
* Extract files to current directory.
|
701
|
+
* ===Parameters
|
702
|
+
* [name] (nil) could be an Archive::Entry, a String or an Regex. If given,
|
703
|
+
* only this entry is extracted. Otherwise extracts the whole
|
704
|
+
* archive.
|
705
|
+
* [io] an instance of IO or something with a +write+ method like
|
706
|
+
* StringIO. If given, the entry specified via +name+ will be
|
707
|
+
* extracted into +io+ instead of a file.
|
708
|
+
* [opt] is an option hash. See below for possible options.
|
709
|
+
* ===Parameters for the option hash
|
710
|
+
* [:extract] flag, Integer combined of the Archive::Extract_* constants.
|
711
|
+
* This tells libarchive-ruby to only extract the file attributes
|
712
|
+
* you specify here. Exceptions is Archive::EXTRACT_NO_OVERWRITE
|
713
|
+
* which prevents this method from overwrtiting existing files.
|
714
|
+
* ===Return value
|
715
|
+
* The paths of the extracted entries as an array.
|
716
|
+
* ===Example
|
717
|
+
* #Simply extract everything into the current directory.
|
718
|
+
* a.extract
|
719
|
+
* #Extract only file1.txt
|
720
|
+
* a.extract("file1.txt")
|
721
|
+
* #Same as above, but extract it to a StringIO
|
722
|
+
* s = StringIO.new
|
723
|
+
* a.extract("file1.txt", s)
|
724
|
+
* #Same as the first example, but only extract information about the
|
725
|
+
* #modification time.
|
726
|
+
* a.extract(nil, nil, extract: Archive::EXTRACT_TIME)
|
727
|
+
*/
|
728
|
+
|
729
|
+
VALUE Archive_extract(int argc, VALUE *argv, VALUE self)
|
730
|
+
{
|
731
|
+
char buff[8192];
|
732
|
+
size_t bytes_read;
|
733
|
+
|
734
|
+
VALUE result = rb_ary_new(),name,io,opts,temp;
|
735
|
+
struct archive *a = archive_read_new();
|
736
|
+
struct archive_entry *entry;
|
737
|
+
archive_read_support_compression_all(a);
|
738
|
+
archive_read_support_format_all(a);
|
739
|
+
archive_read_support_format_raw(a);//add raw, this is not by all
|
740
|
+
int extract_opt = 0,fd=-1,error=0;
|
741
|
+
rb_scan_args(argc, argv, "03", &name,&io,&opts);
|
742
|
+
if(rb_obj_is_kind_of(name,rb_cHash)){
|
743
|
+
opts = name;name = Qnil;
|
744
|
+
}
|
745
|
+
if(rb_obj_is_kind_of(io,rb_cHash)){
|
746
|
+
opts = io;io = Qnil;
|
747
|
+
}
|
748
|
+
if(rb_obj_is_kind_of(io,rb_cIO))
|
749
|
+
fd = NUM2INT(rb_funcall(io,rb_intern("fileno"),0));
|
750
|
+
|
751
|
+
|
752
|
+
if(rb_obj_is_kind_of(opts,rb_cHash))
|
753
|
+
if(RTEST(temp=rb_hash_aref(opts,ID2SYM(rb_intern("extract")))))
|
754
|
+
extract_opt = NUM2INT(temp);
|
755
|
+
|
756
|
+
error=Archive_read_ruby(self,a);
|
757
|
+
if(error==ARCHIVE_OK){
|
758
|
+
try{
|
759
|
+
if(NIL_P(name)){
|
760
|
+
if(!NIL_P(io)){
|
761
|
+
rb_raise(rb_eArgError,"You can't extract more than 1 entry into an IO-like object!");
|
762
|
+
}
|
763
|
+
while(archive_read_next_header(a, &entry) == ARCHIVE_OK){
|
764
|
+
archive_read_extract(a,entry,extract_opt);
|
765
|
+
rb_ary_push(result,rb_str_new2(archive_entry_pathname(entry)));
|
766
|
+
}
|
767
|
+
}else{
|
768
|
+
if(rb_obj_is_kind_of(name,rb_cArchiveEntry)==Qtrue){
|
769
|
+
if(rb_obj_is_kind_of(io,rb_cIO)==Qtrue){
|
770
|
+
while(archive_read_next_header(a, &entry) == ARCHIVE_OK){
|
771
|
+
if(std::string(archive_entry_pathname(entry)).compare(archive_entry_pathname(wrap<archive_entry*>(name)))==0)
|
772
|
+
archive_read_data_into_fd(a,fd);
|
773
|
+
}
|
774
|
+
}else if(rb_respond_to(io,rb_intern("write"))){
|
775
|
+
while(archive_read_next_header(a, &entry) == ARCHIVE_OK){
|
776
|
+
if(std::string(archive_entry_pathname(entry)).compare(archive_entry_pathname(wrap<archive_entry*>(name)))==0)
|
777
|
+
while ((bytes_read=archive_read_data(a,&buff,sizeof(buff)))>0)
|
778
|
+
rb_funcall(io,rb_intern("write"),1,rb_str_new(buff,bytes_read));
|
779
|
+
|
780
|
+
}
|
781
|
+
}else
|
782
|
+
archive_read_extract(a,wrap<archive_entry*>(name),extract_opt);
|
783
|
+
rb_ary_push(result,rb_str_new2(archive_entry_pathname(wrap<archive_entry*>(name))));
|
784
|
+
}else if(rb_obj_is_kind_of(name,rb_cRegexp)==Qtrue){
|
785
|
+
while(archive_read_next_header(a, &entry) == ARCHIVE_OK){
|
786
|
+
VALUE str = rb_str_new2(archive_entry_pathname(entry));
|
787
|
+
if(rb_reg_match(name,str)!=Qnil){
|
788
|
+
if(rb_obj_is_kind_of(io,rb_cIO)==Qtrue){
|
789
|
+
archive_read_data_into_fd(a,fd);
|
790
|
+
}else if(rb_respond_to(io,rb_intern("write"))){
|
791
|
+
while ((bytes_read=archive_read_data(a,&buff,sizeof(buff)))>0)
|
792
|
+
rb_funcall(io,rb_intern("write"),1,rb_str_new(buff,bytes_read));
|
793
|
+
}else
|
794
|
+
archive_read_extract(a,entry,extract_opt);
|
795
|
+
rb_ary_push(result,str);
|
796
|
+
}
|
797
|
+
}
|
798
|
+
}else{
|
799
|
+
name = rb_funcall(name,rb_intern("to_s"),0);
|
800
|
+
std::string str1(rb_string_value_cstr(&name)),str2(str1);
|
801
|
+
str2 += '/'; // dir ends of '/'
|
802
|
+
while(archive_read_next_header(a, &entry) == ARCHIVE_OK){
|
803
|
+
const char *cstr = archive_entry_pathname(entry);
|
804
|
+
if(str1.compare(cstr)==0 || str2.compare(cstr)==0){
|
805
|
+
if(rb_obj_is_kind_of(io,rb_cIO)==Qtrue){
|
806
|
+
archive_read_data_into_fd(a,fd);
|
807
|
+
}else if(rb_respond_to(io,rb_intern("write"))){
|
808
|
+
while ((bytes_read=archive_read_data(a,&buff,sizeof(buff)))>0)
|
809
|
+
rb_funcall(io,rb_intern("write"),1,rb_str_new(buff,bytes_read));
|
810
|
+
}else
|
811
|
+
archive_read_extract(a,entry,extract_opt);
|
812
|
+
rb_ary_push(result,rb_str_new2(cstr));
|
813
|
+
}
|
814
|
+
}
|
815
|
+
}
|
816
|
+
}
|
817
|
+
}catch (...){
|
818
|
+
rb_raise(rb_eArchiveError,"error:%d:%s",archive_errno(a),archive_error_string(a));
|
819
|
+
}
|
820
|
+
archive_read_finish(a);
|
821
|
+
}
|
822
|
+
return result;
|
823
|
+
}
|
824
|
+
|
825
|
+
VALUE Archive_extract_if_block(struct extract_obj * data)
|
826
|
+
{
|
827
|
+
VALUE result = rb_ary_new();
|
828
|
+
struct archive_entry *entry;
|
829
|
+
while(archive_read_next_header(data->archive, &entry) == ARCHIVE_OK){
|
830
|
+
VALUE str = rb_str_new2(archive_entry_pathname(entry));
|
831
|
+
if(RTEST(rb_yield(wrap(entry)))){
|
832
|
+
archive_read_extract(data->archive,entry,data->extract_opt);
|
833
|
+
rb_ary_push(result,str);
|
834
|
+
}
|
835
|
+
}
|
836
|
+
return result;
|
837
|
+
}
|
838
|
+
/*
|
839
|
+
* call-seq:
|
840
|
+
* extract_if( [ opt ] ) {|entry| } → an_array
|
841
|
+
* extract_if( [ opt ] ) → an_enumerator
|
842
|
+
*
|
843
|
+
* Yields each entry in the archive to the block and extracts only those
|
844
|
+
* entries (to the current directory) for which the block evaluates to a
|
845
|
+
* truth value.
|
846
|
+
* ===Parameters
|
847
|
+
* [opt] is the same option hash that you can pass to #extract.
|
848
|
+
* ====Parameters for the option hash
|
849
|
+
* See the #extract method for explanation.
|
850
|
+
* ===Return value
|
851
|
+
* The paths of all extracted entries if a block was given, an Enumerator
|
852
|
+
* otherwise.
|
853
|
+
*/
|
854
|
+
|
855
|
+
VALUE Archive_extract_if(int argc, VALUE *argv, VALUE self)
|
856
|
+
{
|
857
|
+
RETURN_ENUMERATOR(self,argc,argv);
|
858
|
+
VALUE opts,temp;
|
859
|
+
struct archive *a = archive_read_new();
|
860
|
+
archive_read_support_compression_all(a);
|
861
|
+
archive_read_support_format_all(a);
|
862
|
+
archive_read_support_format_raw(a);
|
863
|
+
int extract_opt=0,error=0;
|
864
|
+
|
865
|
+
rb_scan_args(argc, argv, "01", &opts);
|
866
|
+
if(rb_obj_is_kind_of(opts,rb_cHash))
|
867
|
+
if(RTEST(temp=rb_hash_aref(opts,ID2SYM(rb_intern("extract")))))
|
868
|
+
extract_opt = NUM2INT(temp);
|
869
|
+
error=Archive_read_ruby(self,a);
|
870
|
+
if(error==ARCHIVE_OK){
|
871
|
+
extract_obj obj;
|
872
|
+
obj.archive = a;
|
873
|
+
obj.extract_opt = extract_opt;
|
874
|
+
return RB_ENSURE(Archive_extract_if_block,&obj,Archive_read_block_ensure,a);
|
875
|
+
}
|
876
|
+
return Qnil;
|
877
|
+
}
|
878
|
+
|
879
|
+
/*
|
880
|
+
* call-seq:
|
881
|
+
* format() → an_integer or nil
|
882
|
+
*
|
883
|
+
* Returns the archive format as an integer. You should use #format_name
|
884
|
+
* instead.
|
885
|
+
* ===Return value
|
886
|
+
* An integer or nil if the format wasn't detectable.
|
887
|
+
*/
|
888
|
+
|
889
|
+
VALUE Archive_format(VALUE self)
|
890
|
+
{
|
891
|
+
struct archive *a = archive_read_new();
|
892
|
+
struct archive_entry *entry;
|
893
|
+
VALUE result = Qnil;
|
894
|
+
archive_read_support_compression_all(a);
|
895
|
+
archive_read_support_format_all(a);
|
896
|
+
archive_read_support_format_raw(a);
|
897
|
+
int error=Archive_read_ruby(self,a);
|
898
|
+
if(error==ARCHIVE_OK){
|
899
|
+
archive_read_next_header(a, &entry);
|
900
|
+
result = INT2NUM(archive_format(a));
|
901
|
+
archive_read_finish(a);
|
902
|
+
}
|
903
|
+
return result;
|
904
|
+
}
|
905
|
+
|
906
|
+
/*
|
907
|
+
* call-seq:
|
908
|
+
* compression() → an_integer or nil
|
909
|
+
*
|
910
|
+
* Returns the archive compression as an integer. You should use
|
911
|
+
* #compression_name instead.
|
912
|
+
* ===Return value
|
913
|
+
* An integer or nil if the compression wasn't detectable. 0 means
|
914
|
+
* no compression.
|
915
|
+
*/
|
916
|
+
|
917
|
+
VALUE Archive_compression(VALUE self)
|
918
|
+
{
|
919
|
+
struct archive *a = archive_read_new();
|
920
|
+
struct archive_entry *entry;
|
921
|
+
VALUE result = Qnil;
|
922
|
+
archive_read_support_compression_all(a);
|
923
|
+
archive_read_support_format_all(a);
|
924
|
+
archive_read_support_format_raw(a);
|
925
|
+
int error=Archive_read_ruby(self,a);
|
926
|
+
if(error==ARCHIVE_OK){
|
927
|
+
archive_read_next_header(a, &entry);
|
928
|
+
result = INT2NUM(archive_compression(a));
|
929
|
+
archive_read_finish(a);
|
930
|
+
}
|
931
|
+
return result;
|
932
|
+
}
|
933
|
+
|
934
|
+
/*
|
935
|
+
* call-seq:
|
936
|
+
* format_name() → a_string or nil
|
937
|
+
*
|
938
|
+
* Returns the archive format's name as a string.
|
939
|
+
* ===Return value
|
940
|
+
* A string or nil if the format wasn't detectable.
|
941
|
+
* ===Example
|
942
|
+
* a.format_name #=> "GNU tar format"
|
943
|
+
*/
|
944
|
+
|
945
|
+
VALUE Archive_format_name(VALUE self)
|
946
|
+
{
|
947
|
+
struct archive *a = archive_read_new();
|
948
|
+
struct archive_entry *entry;
|
949
|
+
const char* name = NULL;
|
950
|
+
archive_read_support_compression_all(a);
|
951
|
+
archive_read_support_format_all(a);
|
952
|
+
archive_read_support_format_raw(a);
|
953
|
+
int error=Archive_read_ruby(self,a);
|
954
|
+
if(error==ARCHIVE_OK){
|
955
|
+
if(archive_read_next_header(a, &entry)==ARCHIVE_OK){
|
956
|
+
name = archive_format_name(a);
|
957
|
+
archive_read_finish(a);
|
958
|
+
}
|
959
|
+
}
|
960
|
+
return name ? rb_str_new2(name) : Qnil ;
|
961
|
+
}
|
962
|
+
|
963
|
+
/*
|
964
|
+
* call-seq:
|
965
|
+
* compression_name() → a_string or nil
|
966
|
+
*
|
967
|
+
* Returns the archive compression's name as a string.
|
968
|
+
* ===Return value
|
969
|
+
* A string or nil if the compression format wasn't detectable. If there
|
970
|
+
* is no compression, <tt>"none"</tt> is returned.
|
971
|
+
* ===Example
|
972
|
+
* a.compression_name #=> "gzip"
|
973
|
+
*
|
974
|
+
* a.compression_name #=> "none"
|
975
|
+
*/
|
976
|
+
|
977
|
+
VALUE Archive_compression_name(VALUE self)
|
978
|
+
{
|
979
|
+
struct archive *a = archive_read_new();
|
980
|
+
struct archive_entry *entry;
|
981
|
+
const char* name = NULL;
|
982
|
+
archive_read_support_compression_all(a);
|
983
|
+
archive_read_support_format_all(a);
|
984
|
+
archive_read_support_format_raw(a);
|
985
|
+
int error=Archive_read_ruby(self,a);
|
986
|
+
if(error==ARCHIVE_OK){
|
987
|
+
archive_read_next_header(a, &entry);
|
988
|
+
name = archive_compression_name(a);
|
989
|
+
archive_read_finish(a);
|
990
|
+
}
|
991
|
+
return name ? rb_str_new2(name) : Qnil ;
|
992
|
+
}
|
993
|
+
|
994
|
+
/*
|
995
|
+
* call-seq:
|
996
|
+
* add( obj , path ) → self
|
997
|
+
*
|
998
|
+
* Adds a file to an archive.
|
999
|
+
* ===Parameters
|
1000
|
+
* [obj] String, IO, File or an object which responds to +read+.
|
1001
|
+
* [path] Sets the file name inside the archive.
|
1002
|
+
* ===Return value
|
1003
|
+
* self
|
1004
|
+
* ===Raises
|
1005
|
+
* [FormatError] Raised if the archive format is not supported for writing.
|
1006
|
+
*/
|
1007
|
+
|
1008
|
+
VALUE Archive_add(VALUE self,VALUE obj,VALUE name)
|
1009
|
+
{
|
1010
|
+
char buff[8192];
|
1011
|
+
char *path = NULL;
|
1012
|
+
|
1013
|
+
size_t bytes_read;
|
1014
|
+
struct archive *a = archive_read_new(),*b=archive_write_new(),*c=archive_read_disk_new();
|
1015
|
+
struct archive_entry *entry;
|
1016
|
+
std::vector<struct archive_entry *> entries;
|
1017
|
+
std::vector<std::string> allbuff;
|
1018
|
+
int format= ARCHIVE_FORMAT_EMPTY,compression=ARCHIVE_COMPRESSION_NONE,fd=-1,error=0;
|
1019
|
+
archive_read_support_compression_all(a);
|
1020
|
+
archive_read_support_format_all(a);
|
1021
|
+
archive_read_support_format_raw(a);
|
1022
|
+
//autodetect format and compression
|
1023
|
+
error=Archive_read_ruby(self,a);
|
1024
|
+
if(error==ARCHIVE_OK){
|
1025
|
+
while(archive_read_next_header(a, &entry)==ARCHIVE_OK){
|
1026
|
+
entries.push_back(archive_entry_clone(entry));
|
1027
|
+
allbuff.push_back(std::string(""));
|
1028
|
+
try{
|
1029
|
+
while ((bytes_read=archive_read_data(a,&buff,sizeof(buff)))>0)
|
1030
|
+
allbuff.back().append(buff,bytes_read);
|
1031
|
+
}catch(...){
|
1032
|
+
rb_raise(rb_eArchiveError,"error:%d:%s",archive_errno(a),archive_error_string(a));
|
1033
|
+
}
|
1034
|
+
}
|
1035
|
+
format = archive_format(a);
|
1036
|
+
compression = archive_compression(a);
|
1037
|
+
archive_read_finish(a);
|
1038
|
+
}
|
1039
|
+
if(rb_obj_is_kind_of(obj,rb_cIO)){
|
1040
|
+
fd = NUM2INT(rb_funcall(obj,rb_intern("fileno"),0));
|
1041
|
+
}else if(rb_obj_is_kind_of(obj,rb_cFile)){
|
1042
|
+
VALUE pathname = rb_funcall(obj,rb_intern("path"),0); //source path
|
1043
|
+
VALUE obj2 = rb_file_s_expand_path(1,&pathname);
|
1044
|
+
path = rb_string_value_cstr(&obj2);
|
1045
|
+
fd = NUM2INT(rb_funcall(obj,rb_intern("fileno"),0));
|
1046
|
+
}else if(rb_respond_to(obj,rb_intern("read"))){
|
1047
|
+
//stringio has neigther path or fileno, so do nothing
|
1048
|
+
}else {
|
1049
|
+
VALUE obj2 = rb_file_s_expand_path(1,&obj);
|
1050
|
+
path = rb_string_value_cstr(&obj2);
|
1051
|
+
fd = open(path, O_RDONLY);
|
1052
|
+
if (fd < 0) //TODO: add error
|
1053
|
+
return self;
|
1054
|
+
}
|
1055
|
+
Archive_format_from_path(self,format,compression);
|
1056
|
+
if((error = archive_write_set_format(b,format)) != ARCHIVE_OK)
|
1057
|
+
rb_raise(rb_eArchiveErrorFormat,"error:%d:%s",archive_errno(b),archive_error_string(b));
|
1058
|
+
Archive_write_set_compression(b,compression);
|
1059
|
+
|
1060
|
+
error=Archive_write_ruby(self,b);
|
1061
|
+
if(error==ARCHIVE_OK){
|
1062
|
+
for(unsigned int i=0; i<entries.size(); i++){
|
1063
|
+
if(std::string(rb_string_value_cstr(&name)).compare(archive_entry_pathname(entries[i]))!=0){
|
1064
|
+
archive_write_header(b,entries[i]);
|
1065
|
+
archive_write_data(b,allbuff[i].c_str(),allbuff[i].length());
|
1066
|
+
archive_write_finish_entry(b);
|
1067
|
+
}
|
1068
|
+
}
|
1069
|
+
archive_read_disk_set_standard_lookup(c);
|
1070
|
+
entry = archive_entry_new();
|
1071
|
+
if (path)
|
1072
|
+
archive_entry_copy_sourcepath(entry, path);
|
1073
|
+
archive_entry_copy_pathname(entry, rb_string_value_cstr(&name));
|
1074
|
+
if(fd < 0 and rb_respond_to(obj,rb_intern("read"))){
|
1075
|
+
archive_write_header(b, entry);
|
1076
|
+
VALUE result;
|
1077
|
+
result = rb_funcall(obj,rb_intern("read"),0);
|
1078
|
+
archive_write_data(b, rb_string_value_cstr(&result), RSTRING_LEN(result));
|
1079
|
+
}else{
|
1080
|
+
archive_read_disk_entry_from_file(c, entry, fd, NULL);
|
1081
|
+
archive_write_header(b, entry);
|
1082
|
+
while ((bytes_read = read(fd, buff, sizeof(buff))) > 0)
|
1083
|
+
archive_write_data(b, buff, bytes_read);
|
1084
|
+
}
|
1085
|
+
archive_write_finish_entry(b);
|
1086
|
+
archive_read_finish(c);
|
1087
|
+
archive_write_finish(b);
|
1088
|
+
}
|
1089
|
+
|
1090
|
+
if(fd >= 0 and !rb_obj_is_kind_of(name,rb_cIO))
|
1091
|
+
close(fd);
|
1092
|
+
return self;
|
1093
|
+
}
|
1094
|
+
|
1095
|
+
/*
|
1096
|
+
* call-seq:
|
1097
|
+
* << obj → self
|
1098
|
+
*
|
1099
|
+
* Adds a file to an archive. Basicly the same as #add, but you can't
|
1100
|
+
* set the path inside the archive.
|
1101
|
+
* ===Parameters
|
1102
|
+
* [obj] String or File
|
1103
|
+
* ===Return value
|
1104
|
+
* self
|
1105
|
+
* ===Raises
|
1106
|
+
* [FormatError] The archive format is not supported for writing.
|
1107
|
+
*/
|
1108
|
+
VALUE Archive_add_shift(VALUE self,VALUE name)
|
1109
|
+
{
|
1110
|
+
if(rb_obj_is_kind_of(name,rb_cFile))
|
1111
|
+
return Archive_add(self,name,rb_funcall(name,rb_intern("path"),0));
|
1112
|
+
else
|
1113
|
+
return Archive_add(self,name,name);
|
1114
|
+
}
|
1115
|
+
|
1116
|
+
/*
|
1117
|
+
* call-seq:
|
1118
|
+
* delete( name ) → an_array
|
1119
|
+
*
|
1120
|
+
* Delete files from an archive.
|
1121
|
+
* ===Parameters
|
1122
|
+
* [name] An Archive::Entry, a String or a Regex.
|
1123
|
+
* ===Return value
|
1124
|
+
* A list of paths removed from the archive.
|
1125
|
+
* ===Raises
|
1126
|
+
* raise TypeError if the parameter is neigther String or File.
|
1127
|
+
* raise Error if the format has no write support
|
1128
|
+
*/
|
1129
|
+
|
1130
|
+
VALUE Archive_delete(VALUE self,VALUE val)
|
1131
|
+
{
|
1132
|
+
char buff[8192];
|
1133
|
+
size_t bytes_read;
|
1134
|
+
struct archive *a = archive_read_new(),*b=archive_write_new();
|
1135
|
+
struct archive_entry *entry;
|
1136
|
+
int format = ARCHIVE_FORMAT_EMPTY,compression = ARCHIVE_COMPRESSION_NONE,error=0;
|
1137
|
+
std::vector<struct archive_entry *> entries;
|
1138
|
+
std::vector<std::string> allbuff;
|
1139
|
+
VALUE result = rb_ary_new();
|
1140
|
+
archive_read_support_compression_all(a);
|
1141
|
+
archive_read_support_format_all(a);
|
1142
|
+
archive_read_support_format_raw(a);
|
1143
|
+
//autodetect format and compression
|
1144
|
+
error=Archive_read_ruby(self,a);
|
1145
|
+
if(error==ARCHIVE_OK){
|
1146
|
+
while(archive_read_next_header(a, &entry)==ARCHIVE_OK){
|
1147
|
+
format = archive_format(a);
|
1148
|
+
compression = archive_compression(a);
|
1149
|
+
bool del = false;
|
1150
|
+
if(rb_obj_is_kind_of(val,rb_cArchiveEntry)==Qtrue){
|
1151
|
+
del = std::string(archive_entry_pathname(wrap<archive_entry*>(val))).compare(archive_entry_pathname(entry)) == 0;
|
1152
|
+
}else if(rb_obj_is_kind_of(val,rb_cRegexp)==Qtrue){
|
1153
|
+
VALUE str = rb_str_new2(archive_entry_pathname(entry));
|
1154
|
+
del = rb_reg_match(val,str)!=Qnil;
|
1155
|
+
}else {
|
1156
|
+
std::string str1(rb_string_value_cstr(&val)),str2(str1);
|
1157
|
+
str2 += '/'; // dir ends of '/'
|
1158
|
+
const char *cstr = archive_entry_pathname(entry);
|
1159
|
+
del = (str1.compare(cstr)==0 || str2.compare(cstr)==0);
|
1160
|
+
}
|
1161
|
+
if(!del){
|
1162
|
+
entries.push_back(archive_entry_clone(entry));
|
1163
|
+
allbuff.push_back(std::string(""));
|
1164
|
+
try{
|
1165
|
+
while ((bytes_read=archive_read_data(a,&buff,sizeof(buff)))>0)
|
1166
|
+
allbuff.back().append(buff,bytes_read);
|
1167
|
+
}catch(...){
|
1168
|
+
rb_raise(rb_eArchiveError,"error:%d:%s",archive_errno(a),archive_error_string(a));
|
1169
|
+
}
|
1170
|
+
}else
|
1171
|
+
rb_ary_push(result,wrap(archive_entry_clone(entry)));
|
1172
|
+
}
|
1173
|
+
archive_read_finish(a);
|
1174
|
+
|
1175
|
+
//format fix
|
1176
|
+
if(format==ARCHIVE_FORMAT_TAR_GNUTAR)
|
1177
|
+
format=ARCHIVE_FORMAT_TAR_USTAR;
|
1178
|
+
|
1179
|
+
//TODO add archive-error
|
1180
|
+
if((error = archive_write_set_format(b,format)) != ARCHIVE_OK)
|
1181
|
+
rb_raise(rb_eArchiveErrorFormat,"error (%d): %s ",error,archive_error_string(b));
|
1182
|
+
Archive_write_set_compression(b,compression);
|
1183
|
+
error=Archive_write_ruby(self,b);
|
1184
|
+
if(error==ARCHIVE_OK){
|
1185
|
+
//write old data back
|
1186
|
+
for(unsigned int i=0; i<entries.size(); i++){
|
1187
|
+
archive_write_header(b,entries[i]);
|
1188
|
+
archive_write_data(b,allbuff[i].c_str(),allbuff[i].length());
|
1189
|
+
archive_write_finish_entry(b);
|
1190
|
+
}
|
1191
|
+
archive_write_finish(b);
|
1192
|
+
}
|
1193
|
+
|
1194
|
+
}
|
1195
|
+
return result;
|
1196
|
+
}
|
1197
|
+
|
1198
|
+
VALUE Archive_delete_if_block(struct write_obj * data)
|
1199
|
+
{
|
1200
|
+
VALUE result= rb_ary_new();
|
1201
|
+
for(unsigned int i=0; i< data->entries->size(); i++){
|
1202
|
+
if(!RTEST(rb_yield(wrap(data->entries->at(i))))){
|
1203
|
+
archive_write_header(data->archive,data->entries->at(i));
|
1204
|
+
archive_write_data(data->archive,data->allbuff->at(i).c_str(),data->allbuff->at(i).length());
|
1205
|
+
archive_write_finish_entry(data->archive);
|
1206
|
+
}else
|
1207
|
+
rb_ary_push(result,wrap(data->entries->at(i)));
|
1208
|
+
}
|
1209
|
+
return result;
|
1210
|
+
}
|
1211
|
+
|
1212
|
+
/*
|
1213
|
+
* call-seq:
|
1214
|
+
* archive.delete_if {|entry| } -> self
|
1215
|
+
* archive.delete_if -> Enumerator
|
1216
|
+
*
|
1217
|
+
* Yields each entry in the archive to the block and deletes those for which
|
1218
|
+
* the block evaluates to a truth value.
|
1219
|
+
* ===Parameters
|
1220
|
+
* [name] An Archive::Entry, a String or a Regex.
|
1221
|
+
* ===Return value
|
1222
|
+
* If a block was given, returns self, otherwise an Enumerator.
|
1223
|
+
* ===Raises
|
1224
|
+
* raise Error if the format has no write support
|
1225
|
+
*/
|
1226
|
+
|
1227
|
+
VALUE Archive_delete_if(VALUE self)
|
1228
|
+
{
|
1229
|
+
RETURN_ENUMERATOR(self,0,NULL);
|
1230
|
+
char buff[8192];
|
1231
|
+
std::string selfpath =_self->path;
|
1232
|
+
size_t bytes_read;
|
1233
|
+
struct archive *a = archive_read_new(),*b=archive_write_new();
|
1234
|
+
struct archive_entry *entry;
|
1235
|
+
int format = ARCHIVE_FORMAT_EMPTY,compression = ARCHIVE_COMPRESSION_NONE,error=0;
|
1236
|
+
std::vector<struct archive_entry *> entries;
|
1237
|
+
std::vector<std::string> allbuff;
|
1238
|
+
|
1239
|
+
archive_read_support_compression_all(a);
|
1240
|
+
archive_read_support_format_all(a);
|
1241
|
+
archive_read_support_format_raw(a);
|
1242
|
+
error=Archive_read_ruby(self,a);
|
1243
|
+
if(error==ARCHIVE_OK){
|
1244
|
+
while(archive_read_next_header(a, &entry)==ARCHIVE_OK){
|
1245
|
+
format = archive_format(a);
|
1246
|
+
compression = archive_compression(a);
|
1247
|
+
entries.push_back(archive_entry_clone(entry));
|
1248
|
+
allbuff.push_back(std::string(""));
|
1249
|
+
try{
|
1250
|
+
while ((bytes_read=archive_read_data(a,&buff,sizeof(buff)))>0)
|
1251
|
+
allbuff.back().append(buff,bytes_read);
|
1252
|
+
}catch(...){
|
1253
|
+
rb_raise(rb_eArchiveError,"error:%d:%s",archive_errno(a),archive_error_string(a));
|
1254
|
+
}
|
1255
|
+
}
|
1256
|
+
archive_read_finish(a);
|
1257
|
+
//format fix
|
1258
|
+
if(format==ARCHIVE_FORMAT_TAR_GNUTAR)
|
1259
|
+
format=ARCHIVE_FORMAT_TAR_USTAR;
|
1260
|
+
if((error = archive_write_set_format(b,format)) != ARCHIVE_OK)
|
1261
|
+
rb_raise(rb_eArchiveErrorFormat,"error (%d): %s ",error,archive_error_string(b));
|
1262
|
+
Archive_write_set_compression(b,compression);
|
1263
|
+
error=Archive_write_ruby(self,b);
|
1264
|
+
if(error==ARCHIVE_OK){
|
1265
|
+
write_obj obj;
|
1266
|
+
obj.archive = b;
|
1267
|
+
obj.entries = &entries;
|
1268
|
+
obj.allbuff = &allbuff;
|
1269
|
+
return RB_ENSURE(Archive_delete_if_block,&obj,Archive_write_block_ensure,b);
|
1270
|
+
}
|
1271
|
+
}
|
1272
|
+
return Qnil;
|
1273
|
+
}
|
1274
|
+
|
1275
|
+
/*
|
1276
|
+
* call-seq:
|
1277
|
+
* archive.clear -> self
|
1278
|
+
*
|
1279
|
+
* Deletes all files from an archive.
|
1280
|
+
* ===Return value
|
1281
|
+
* returns self.
|
1282
|
+
* ===Raises
|
1283
|
+
* raise Error if the format has no write support
|
1284
|
+
*/
|
1285
|
+
|
1286
|
+
VALUE Archive_clear(VALUE self)
|
1287
|
+
{
|
1288
|
+
|
1289
|
+
std::string selfpath =_self->path;
|
1290
|
+
|
1291
|
+
struct archive *a = archive_read_new(),*b=archive_write_new();
|
1292
|
+
struct archive_entry *entry;
|
1293
|
+
int format = ARCHIVE_FORMAT_EMPTY,compression = ARCHIVE_COMPRESSION_NONE,error=0;
|
1294
|
+
|
1295
|
+
archive_read_support_compression_all(a);
|
1296
|
+
archive_read_support_format_all(a);
|
1297
|
+
archive_read_support_format_raw(a);
|
1298
|
+
error=Archive_read_ruby(self,a);
|
1299
|
+
if(error==ARCHIVE_OK){
|
1300
|
+
archive_read_next_header(a, &entry);
|
1301
|
+
format = archive_format(a);
|
1302
|
+
compression = archive_compression(a);
|
1303
|
+
archive_read_finish(a);
|
1304
|
+
|
1305
|
+
//format fix
|
1306
|
+
if(format==ARCHIVE_FORMAT_TAR_GNUTAR)
|
1307
|
+
format=ARCHIVE_FORMAT_TAR_USTAR;
|
1308
|
+
|
1309
|
+
if((error = archive_write_set_format(b,format)) != ARCHIVE_OK)
|
1310
|
+
rb_raise(rb_eArchiveErrorFormat,"error (%d): %s ",error,archive_error_string(b));
|
1311
|
+
Archive_write_set_compression(b,compression);
|
1312
|
+
error=Archive_write_ruby(self,b);
|
1313
|
+
if(error==ARCHIVE_OK)
|
1314
|
+
archive_write_finish(b);
|
1315
|
+
}
|
1316
|
+
|
1317
|
+
return self;
|
1318
|
+
}
|
1319
|
+
|
1320
|
+
/*:nodoc:
|
1321
|
+
* call-seq:
|
1322
|
+
* archive.exist? -> true or false
|
1323
|
+
*
|
1324
|
+
* Same as
|
1325
|
+
* File.exist?(archive.path)
|
1326
|
+
* . Checks wheather or not the archive file is existant.
|
1327
|
+
* ===Return value
|
1328
|
+
* True or false.
|
1329
|
+
*/
|
1330
|
+
|
1331
|
+
VALUE Archive_exist(VALUE self)
|
1332
|
+
{
|
1333
|
+
return rb_funcall(rb_cFile,rb_intern("exist?"),1,Archive_path(self));
|
1334
|
+
}
|
1335
|
+
|
1336
|
+
/*:nodoc:
|
1337
|
+
* call-seq:
|
1338
|
+
* archive.unlink -> self
|
1339
|
+
*
|
1340
|
+
* call the File.unlink(path)
|
1341
|
+
*/
|
1342
|
+
|
1343
|
+
VALUE Archive_unlink(VALUE self)
|
1344
|
+
{
|
1345
|
+
return rb_funcall(rb_cFile,rb_intern("unlink"),1,Archive_path(self));
|
1346
|
+
return self;
|
1347
|
+
}
|
1348
|
+
|
1349
|
+
/*:nodoc:
|
1350
|
+
* call-seq:
|
1351
|
+
* archive.mtime -> Time
|
1352
|
+
*
|
1353
|
+
* call the File.mtime(path)
|
1354
|
+
*/
|
1355
|
+
|
1356
|
+
VALUE Archive_mtime(VALUE self)
|
1357
|
+
{
|
1358
|
+
return rb_funcall(rb_cFile,rb_intern("mtime"),1,Archive_path(self));
|
1359
|
+
}
|
1360
|
+
|
1361
|
+
/*:nodoc:
|
1362
|
+
* call-seq:
|
1363
|
+
* archive.atime -> Time
|
1364
|
+
*
|
1365
|
+
* call the File.atime(path)
|
1366
|
+
*/
|
1367
|
+
|
1368
|
+
VALUE Archive_atime(VALUE self)
|
1369
|
+
{
|
1370
|
+
return rb_funcall(rb_cFile,rb_intern("atime"),1,Archive_path(self));
|
1371
|
+
}
|
1372
|
+
|
1373
|
+
/*:nodoc:
|
1374
|
+
* call-seq:
|
1375
|
+
* archive.ctime -> Time
|
1376
|
+
*
|
1377
|
+
* call the File.ctime(path)
|
1378
|
+
*/
|
1379
|
+
|
1380
|
+
|
1381
|
+
VALUE Archive_ctime(VALUE self)
|
1382
|
+
{
|
1383
|
+
return rb_funcall(rb_cFile,rb_intern("ctime"),1,Archive_path(self));
|
1384
|
+
}
|
1385
|
+
|
1386
|
+
/*:nodoc:
|
1387
|
+
* call-seq:
|
1388
|
+
* archive.stat -> File::Stat
|
1389
|
+
*
|
1390
|
+
* call the File.stat(path)
|
1391
|
+
*/
|
1392
|
+
|
1393
|
+
VALUE Archive_stat(VALUE self)
|
1394
|
+
{
|
1395
|
+
return rb_funcall(rb_cFile,rb_intern("stat"),1,Archive_path(self));
|
1396
|
+
}
|
1397
|
+
|
1398
|
+
/*
|
1399
|
+
* call-seq:
|
1400
|
+
* archive.inspect -> String
|
1401
|
+
*
|
1402
|
+
* Human-readable description.
|
1403
|
+
* ===Return value
|
1404
|
+
* String
|
1405
|
+
*/
|
1406
|
+
|
1407
|
+
VALUE Archive_inspect(VALUE self)
|
1408
|
+
{
|
1409
|
+
VALUE array[3];
|
1410
|
+
switch(_self->type){
|
1411
|
+
case archive_path:
|
1412
|
+
array[0]=rb_str_new2("#<%s:%s>");
|
1413
|
+
array[1]=rb_class_of(self);
|
1414
|
+
array[2]=Archive_path(self);
|
1415
|
+
break;
|
1416
|
+
case archive_fd:
|
1417
|
+
array[0]=rb_str_new2("#<%s:%d>");
|
1418
|
+
array[1]=rb_class_of(self);
|
1419
|
+
array[2]=INT2NUM(_self->fd);
|
1420
|
+
break;
|
1421
|
+
case archive_buffer:
|
1422
|
+
break;
|
1423
|
+
case archive_ruby:
|
1424
|
+
array[0]=rb_str_new2("#<%s:%s>");
|
1425
|
+
array[1]=rb_class_of(self);
|
1426
|
+
array[2]=_self->ruby;
|
1427
|
+
break;
|
1428
|
+
}
|
1429
|
+
return rb_f_sprintf(3,array);
|
1430
|
+
}
|
1431
|
+
|
1432
|
+
/*
|
1433
|
+
* Document-class: Archive::Error
|
1434
|
+
* This is the superclass of all errors specific to this library.
|
1435
|
+
*/
|
1436
|
+
|
1437
|
+
/*
|
1438
|
+
* Document-class: Archive::Error::Compression
|
1439
|
+
* This exception is thrown if you try to use an unknown compression format.
|
1440
|
+
*/
|
1441
|
+
|
1442
|
+
/*
|
1443
|
+
* Document-class: Archive::Error::Format
|
1444
|
+
* This exception is thrown if you try to use an unknown archive format or libarchive doesn't
|
1445
|
+
* have write support for the format you wanted to write.
|
1446
|
+
*/
|
1447
|
+
|
1448
|
+
/*
|
1449
|
+
* Document-class: Archive
|
1450
|
+
*
|
1451
|
+
* This class represents an archive file. The file may or may not exist,
|
1452
|
+
* depending on wheather you want to create a new archive or read from
|
1453
|
+
* an existing one. When instanciating this class, libarchive-ruby will
|
1454
|
+
* automatically detect the correct file format for you using libarchive's
|
1455
|
+
* own detection mechanism if the archive file is already present, otherwise
|
1456
|
+
* by looking at the archive file's file extension.
|
1457
|
+
*/
|
1458
|
+
/*
|
1459
|
+
* Document-const: EXTRACT_TIME
|
1460
|
+
*
|
1461
|
+
* extract the atime and mtime
|
1462
|
+
*/
|
1463
|
+
/*
|
1464
|
+
* Document-const: EXTRACT_PERM
|
1465
|
+
*
|
1466
|
+
* extract the permission
|
1467
|
+
*/
|
1468
|
+
/*
|
1469
|
+
* Document-const: EXTRACT_OWNER
|
1470
|
+
*
|
1471
|
+
* extract the owner
|
1472
|
+
*/
|
1473
|
+
|
1474
|
+
/*
|
1475
|
+
* Document-const: EXTRACT_ACL
|
1476
|
+
*
|
1477
|
+
* extract the access control list
|
1478
|
+
*/
|
1479
|
+
/*
|
1480
|
+
* Document-const: EXTRACT_FFLAGS
|
1481
|
+
*
|
1482
|
+
* extract the fflags
|
1483
|
+
*/
|
1484
|
+
/*
|
1485
|
+
* Document-const: EXTRACT_XATTR
|
1486
|
+
*
|
1487
|
+
* extract the extended information
|
1488
|
+
*/
|
1489
|
+
extern "C" void Init_archive(void){
|
1490
|
+
rb_cArchive = rb_define_class("Archive",rb_cObject);
|
1491
|
+
rb_define_alloc_func(rb_cArchive,Archive_alloc);
|
1492
|
+
rb_define_method(rb_cArchive,"initialize",RUBY_METHOD_FUNC(Archive_initialize),-1);
|
1493
|
+
rb_define_private_method(rb_cArchive,"initialize_copy",RUBY_METHOD_FUNC(Archive_initialize_copy),1);
|
1494
|
+
rb_define_method(rb_cArchive,"path",RUBY_METHOD_FUNC(Archive_path),0);
|
1495
|
+
|
1496
|
+
rb_define_method(rb_cArchive,"each",RUBY_METHOD_FUNC(Archive_each),0);
|
1497
|
+
rb_define_method(rb_cArchive,"each_entry",RUBY_METHOD_FUNC(Archive_each_entry),0);
|
1498
|
+
rb_define_method(rb_cArchive,"each_data",RUBY_METHOD_FUNC(Archive_each_data),0);
|
1499
|
+
rb_define_method(rb_cArchive,"map!",RUBY_METHOD_FUNC(Archive_map_self),0);
|
1500
|
+
rb_define_alias(rb_cArchive,"collect!","map!");
|
1501
|
+
rb_define_method(rb_cArchive,"[]",RUBY_METHOD_FUNC(Archive_get),1);
|
1502
|
+
|
1503
|
+
rb_define_method(rb_cArchive,"to_hash",RUBY_METHOD_FUNC(Archive_to_hash),0);
|
1504
|
+
|
1505
|
+
rb_define_method(rb_cArchive,"extract",RUBY_METHOD_FUNC(Archive_extract),-1);
|
1506
|
+
rb_define_method(rb_cArchive,"extract_if",RUBY_METHOD_FUNC(Archive_extract_if),-1);
|
1507
|
+
|
1508
|
+
rb_define_method(rb_cArchive,"delete",RUBY_METHOD_FUNC(Archive_delete),1);
|
1509
|
+
rb_define_method(rb_cArchive,"delete_if",RUBY_METHOD_FUNC(Archive_delete_if),0);
|
1510
|
+
rb_define_method(rb_cArchive,"clear",RUBY_METHOD_FUNC(Archive_clear),0);
|
1511
|
+
|
1512
|
+
//rb_define_method(rb_cArchive,"move_to",RUBY_METHOD_FUNC(Archive_move_to),1);
|
1513
|
+
|
1514
|
+
rb_define_method(rb_cArchive,"add",RUBY_METHOD_FUNC(Archive_add),2);
|
1515
|
+
rb_define_method(rb_cArchive,"<<",RUBY_METHOD_FUNC(Archive_add_shift),1);
|
1516
|
+
|
1517
|
+
rb_define_method(rb_cArchive,"inspect",RUBY_METHOD_FUNC(Archive_inspect),0);
|
1518
|
+
|
1519
|
+
rb_define_method(rb_cArchive,"format",RUBY_METHOD_FUNC(Archive_format),0);
|
1520
|
+
rb_define_method(rb_cArchive,"compression",RUBY_METHOD_FUNC(Archive_compression),0);
|
1521
|
+
rb_define_method(rb_cArchive,"format_name",RUBY_METHOD_FUNC(Archive_format_name),0);
|
1522
|
+
rb_define_method(rb_cArchive,"compression_name",RUBY_METHOD_FUNC(Archive_compression_name),0);
|
1523
|
+
|
1524
|
+
rb_define_method(rb_cArchive,"unlink",RUBY_METHOD_FUNC(Archive_unlink),0);
|
1525
|
+
rb_define_method(rb_cArchive,"exist?",RUBY_METHOD_FUNC(Archive_exist),0);
|
1526
|
+
rb_define_method(rb_cArchive,"mtime",RUBY_METHOD_FUNC(Archive_mtime),0);
|
1527
|
+
rb_define_method(rb_cArchive,"atime",RUBY_METHOD_FUNC(Archive_atime),0);
|
1528
|
+
rb_define_method(rb_cArchive,"ctime",RUBY_METHOD_FUNC(Archive_ctime),0);
|
1529
|
+
rb_define_method(rb_cArchive,"stat",RUBY_METHOD_FUNC(Archive_stat),0);
|
1530
|
+
|
1531
|
+
rb_include_module(rb_cArchive,rb_mEnumerable);
|
1532
|
+
//rb_define_method(rb_cArchive,"size",RUBY_METHOD_FUNC(Archive_size),0);
|
1533
|
+
|
1534
|
+
Init_archive_entry(rb_cArchive);
|
1535
|
+
|
1536
|
+
rb_define_const(rb_cArchive,"EXTRACT_TIME",INT2NUM(ARCHIVE_EXTRACT_TIME));
|
1537
|
+
rb_define_const(rb_cArchive,"EXTRACT_OWNER",INT2NUM(ARCHIVE_EXTRACT_OWNER));
|
1538
|
+
rb_define_const(rb_cArchive,"EXTRACT_PERM",INT2NUM(ARCHIVE_EXTRACT_PERM));
|
1539
|
+
rb_define_const(rb_cArchive,"EXTRACT_NO_OVERWRITE",INT2NUM(ARCHIVE_EXTRACT_NO_OVERWRITE));
|
1540
|
+
rb_define_const(rb_cArchive,"EXTRACT_ACL",INT2NUM(ARCHIVE_EXTRACT_ACL));
|
1541
|
+
rb_define_const(rb_cArchive,"EXTRACT_FFLAGS",INT2NUM(ARCHIVE_EXTRACT_FFLAGS));
|
1542
|
+
rb_define_const(rb_cArchive,"EXTRACT_XATTR",INT2NUM(ARCHIVE_EXTRACT_XATTR));
|
1543
|
+
|
1544
|
+
rb_eArchiveError = rb_define_class_under(rb_cArchive,"Error",rb_eStandardError);
|
1545
|
+
rb_eArchiveErrorFormat = rb_define_class_under(rb_eArchiveError,"Format",rb_eArchiveError);
|
1546
|
+
rb_eArchiveErrorCompression = rb_define_class_under(rb_eArchiveError,"Compression",rb_eArchiveError);
|
1547
|
+
}
|