libarchive-ruby-gvalmon 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/ext/archive.cpp ADDED
@@ -0,0 +1,1801 @@
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 <map>
26
+ #include <exception>
27
+ #include <stdexcept>
28
+ #define _self wrap<rarchive*>(self)
29
+ #define RB_ENSURE(func1,obj1,func2,obj2)\
30
+ rb_ensure(RUBY_METHOD_FUNC(func1),(VALUE)obj1,RUBY_METHOD_FUNC(func2),(VALUE)obj2)
31
+
32
+ //TODO: handle string IO as archive Archive.new(stringio)
33
+
34
+ #ifndef rb_proc_arity
35
+ #define rb_proc_arity(obj) 2
36
+ #endif
37
+
38
+
39
+ typedef std::vector<struct archive_entry *> EntryVector;
40
+ typedef std::vector<std::string> BuffVector;
41
+ typedef std::vector<int> IntVector;
42
+
43
+ typedef std::vector<std::pair<struct archive_entry *,std::string> > DataVector;
44
+
45
+ typedef std::map<ID,int> SymToIntType;
46
+ SymToIntType SymToFormat;
47
+ SymToIntType SymToFilter;
48
+
49
+ typedef std::map<std::string,std::pair<int,int> > FileExtType;
50
+
51
+ FileExtType fileExt;
52
+
53
+ VALUE rb_cArchive,rb_eArchiveError,rb_eArchiveErrorFormat,rb_eArchiveErrorCompression;
54
+
55
+ VALUE Archive_alloc(VALUE self)
56
+ {
57
+ rarchive *result = new rarchive;
58
+ return wrap(result);
59
+ }
60
+
61
+ VALUE Archive_initialize_copy(VALUE self, VALUE other)
62
+ {
63
+ VALUE result = rb_call_super(1,&other);
64
+ _self->path = std::string(wrap<rarchive*>(other)->path.c_str());
65
+ _self->type = wrap<rarchive*>(other)->type;
66
+ return result;
67
+ }
68
+
69
+ struct extract_obj {
70
+ struct archive* archive;
71
+ int extract_opt;
72
+ };
73
+
74
+ struct write_obj {
75
+ struct archive* archive;
76
+ DataVector *data;
77
+ };
78
+
79
+ struct add_obj {
80
+ struct archive* archive;
81
+ DataVector *data;
82
+ VALUE obj;
83
+ VALUE name;
84
+ };
85
+
86
+
87
+ VALUE wrap_data(const std::string &str)
88
+ {
89
+ #if HAVE_RUBY_ENCODING_H
90
+ return rb_external_str_new_with_enc(&str[0],str.length(),rb_filesystem_encoding());
91
+ #else
92
+ return rb_str_new(&str[0],str.length());
93
+ #endif
94
+ }
95
+
96
+
97
+
98
+ VALUE Archive_read_block_ensure(struct archive * data)
99
+ {
100
+ archive_read_close(data);
101
+ return Qnil;
102
+ }
103
+
104
+ VALUE Archive_write_block_ensure(struct archive * data)
105
+ {
106
+ archive_write_close(data);
107
+ return Qnil;
108
+ }
109
+
110
+ int rubymyopen(struct archive *a, void *client_data)
111
+ {
112
+ rb_funcall((VALUE)client_data,rb_intern("rewind"),0);
113
+ return ARCHIVE_OK;
114
+ }
115
+ ssize_t rubymyread(struct archive *a, void *client_data, const void **buff)
116
+ {
117
+ VALUE result = rb_funcall((VALUE)client_data,rb_intern("read"),0);
118
+ if(result == Qnil){
119
+ *buff = NULL;
120
+ return 0;
121
+ }else{
122
+ if (RSTRING_LEN(result))
123
+ *buff = RSTRING_PTR(result);
124
+ else
125
+ *buff = NULL;
126
+ return RSTRING_LEN(result);
127
+ }
128
+ }
129
+
130
+ ssize_t rubymywrite(struct archive *a,void *client_data,const void *buffer, size_t length){
131
+ VALUE string = rb_str_new((char*)buffer,length);
132
+ // rb_funcall(string,rb_intern("rstrip!"),0);
133
+ return NUM2INT(rb_funcall((VALUE)client_data,rb_intern("write"),1,string));
134
+ }
135
+
136
+ int rubymyclose(struct archive *a, void *client_data)
137
+ {
138
+ rb_funcall((VALUE)client_data,rb_intern("rewind"),0);
139
+ return ARCHIVE_OK;
140
+ }
141
+
142
+ namespace RubyArchive {
143
+
144
+ void read_get_filters(struct archive *a,IntVector &filters)
145
+ {
146
+ size_t filtercount = archive_filter_count(a);
147
+ for(size_t i = 0; i < filtercount; ++i)
148
+ filters.push_back(archive_filter_code(a,i));
149
+ }
150
+
151
+ void read_data(struct archive *a,std::string &str)
152
+ {
153
+ char buff[8192];
154
+ size_t bytes_read;
155
+ try{
156
+ while ((bytes_read=archive_read_data(a,&buff,sizeof(buff)))>0)
157
+ str.append(buff,bytes_read);
158
+ } catch (...){
159
+ rb_raise(rb_eArchiveError,"error:%d:%s",archive_errno(a),archive_error_string(a));
160
+ }
161
+
162
+ }
163
+
164
+ void read_old_data(struct archive *a,DataVector &entries, int &format, IntVector &filters)
165
+ {
166
+ struct archive_entry *entry;
167
+
168
+ while(archive_read_next_header(a, &entry)==ARCHIVE_OK){
169
+ format = archive_format(a);
170
+ if(filters.empty())
171
+ read_get_filters(a,filters);
172
+ std::string buff;
173
+ read_data(a,buff);
174
+
175
+ entries.push_back(std::make_pair(archive_entry_clone(entry),buff));
176
+
177
+ }
178
+ archive_read_close(a);
179
+ }
180
+
181
+ struct archive* create_match_object(VALUE opts)
182
+ {
183
+ VALUE temp;
184
+ struct archive* result = archive_match_new();
185
+ if(rb_obj_is_kind_of(opts,rb_cHash))
186
+ {
187
+ if(RTEST(temp=rb_hash_aref(opts,ID2SYM(rb_intern("uid")))))
188
+ archive_match_include_uid(result,NUM2INT(temp));
189
+ if(RTEST(temp=rb_hash_aref(opts,ID2SYM(rb_intern("gid")))))
190
+ archive_match_include_gid(result,NUM2INT(temp));
191
+
192
+ }
193
+ return result;
194
+ }
195
+
196
+
197
+ bool match_entry(struct archive_entry *entry,VALUE name)
198
+ {
199
+ const char *cstr = archive_entry_pathname(entry);
200
+ if(rb_obj_is_kind_of(name,rb_cArchiveEntry)){
201
+ return std::string(cstr).compare(archive_entry_pathname(wrap<archive_entry*>(name)))==0;
202
+ }else if(rb_obj_is_kind_of(name,rb_cRegexp)){
203
+ VALUE str = rb_str_new2(cstr);
204
+ return rb_reg_match(name,str)!=Qnil;
205
+ }else
206
+ name = rb_funcall(name,rb_intern("to_s"),0);
207
+ std::string str1(StringValueCStr(name)),str2(str1);
208
+ str2 += '/'; // dir ends of '/'
209
+ return str1.compare(cstr)==0 || str2.compare(cstr)==0;
210
+
211
+ return false;
212
+ }
213
+
214
+
215
+ int write_set_filters(struct archive *data,const IntVector &filter)
216
+ {
217
+ int error = 0;
218
+
219
+ for (IntVector::const_reverse_iterator it = filter.rbegin(); it != filter.rend();++it)
220
+ if(*it != ARCHIVE_FILTER_NONE)
221
+ archive_write_add_filter(data,*it);
222
+
223
+ return error;
224
+ }
225
+
226
+ void read_data_from_fd(struct archive *file,VALUE name,int fd,DataVector &data)
227
+ {
228
+ char buff[8192];
229
+ size_t bytes_read;
230
+ std::string strbuff;
231
+
232
+ struct archive_entry *entry = archive_entry_new();
233
+
234
+ archive_read_disk_entry_from_file(file, entry, fd, NULL);
235
+ archive_entry_copy_pathname(entry, StringValueCStr(name));
236
+
237
+
238
+ while ((bytes_read = read(fd, buff, sizeof(buff))) > 0)
239
+ strbuff.append(buff, bytes_read);
240
+
241
+ data.push_back(std::make_pair(entry,strbuff));
242
+ }
243
+
244
+ void read_data_from_ruby(struct archive *file,VALUE name,VALUE obj,DataVector &data)
245
+ {
246
+ std::string strbuff;
247
+
248
+ struct archive_entry *entry = archive_entry_new();
249
+
250
+ archive_entry_copy_pathname(entry, StringValueCStr(name));
251
+
252
+ //TODO should i read in chunks?
253
+ VALUE result = rb_funcall(obj,rb_intern("read"),0);
254
+ strbuff.append(StringValueCStr(result), RSTRING_LEN(result));
255
+
256
+ data.push_back(std::make_pair(entry,strbuff));
257
+ }
258
+
259
+ struct read_data_path_obj
260
+ {
261
+ struct archive* archive;
262
+ struct archive* match;
263
+ DataVector *data;
264
+ VALUE path;
265
+ };
266
+
267
+
268
+ void read_data_match_callback(struct archive * arch, void *, struct archive_entry *entry)
269
+ {
270
+ // entry = archive_entry_clone(entry);
271
+ // if(AE_IFDIR != archive_entry_filetype(entry))
272
+ // {
273
+ // rb_warn("%i ",);
274
+ //rb_warn("%i inclusions",archive_match_path_unmatched_inclusions(arch));
275
+ rb_warn("%s is excluded",archive_entry_pathname(entry));
276
+ // rb_warn("%d fflags",archive_entry_filetype(entry));
277
+ // rb_warn("%d uid",archive_entry_uid(entry));
278
+
279
+ // }else
280
+ // rb_warn("%s is a DIR!",archive_entry_pathname(entry));
281
+ // archive_read_disk_descend(arch);
282
+
283
+
284
+ }
285
+
286
+ int read_data_meta_callback(struct archive *arch, void *, struct archive_entry *entry)
287
+ {
288
+ if(archive_read_disk_can_descend(arch))
289
+ archive_read_disk_descend(arch);
290
+ return 1;
291
+ }
292
+
293
+ VALUE read_data_from_path_block(struct read_data_path_obj *obj)
294
+ {
295
+ struct archive_entry *entry = archive_entry_new();
296
+
297
+ while(archive_read_next_header2(obj->archive,entry) == ARCHIVE_OK)
298
+ {
299
+ const char *cstr = archive_entry_pathname(entry);
300
+
301
+ //allways add subdirs
302
+ //if(archive_read_disk_can_descend(obj->archive))
303
+ // archive_read_disk_descend(obj->archive);
304
+
305
+ // ignore the "." base dir
306
+ if(strcmp(cstr,".") == 0){
307
+ continue;
308
+ }
309
+ // fist look at the match object
310
+ if(archive_match_excluded(obj->match,entry))
311
+ continue;
312
+
313
+ // then if path is Regexp try to match against it
314
+ if(rb_obj_is_kind_of(obj->path,rb_cRegexp))
315
+ if(!RTEST(rb_reg_match(obj->path,rb_str_new2(cstr))))
316
+ continue;
317
+
318
+ // then use the block if given
319
+ if((!rb_block_given_p()) || RTEST(rb_yield(wrap(entry))))
320
+ {
321
+ //TODO: react to the change of the entry object
322
+ std::string strbuff;
323
+ const void *p;
324
+ size_t size;
325
+ int64_t offset;
326
+
327
+ while(archive_read_data_block(obj->archive, &p, &size, &offset) == ARCHIVE_OK)
328
+ strbuff.append((const char*)p,size);
329
+
330
+ struct archive_entry *entry2 = archive_entry_clone(entry);
331
+
332
+
333
+ //Drop the ./ from a filename when using pattern
334
+ std::string path(archive_entry_pathname(entry2));
335
+ if(path.compare(0,2,"./") == 0) {
336
+ path.erase(0,2);
337
+ archive_entry_copy_pathname(entry2,path.c_str());
338
+ }
339
+
340
+ obj->data->push_back(std::make_pair(entry2,strbuff));
341
+
342
+ }
343
+
344
+ }
345
+ return Qnil;
346
+ }
347
+
348
+ VALUE Archive_read_block_close(struct archive * data)
349
+ {
350
+ archive_read_close(data);
351
+ return Qnil;
352
+ }
353
+
354
+ void read_data_from_path(struct archive * file,struct archive * match,VALUE rpath,const char* path,DataVector &data)
355
+ {
356
+
357
+ archive_read_disk_open(file,path);
358
+ archive_read_disk_set_matching(file,match,read_data_match_callback,NULL);
359
+ archive_read_disk_set_metadata_filter_callback(file, read_data_meta_callback, NULL);
360
+ read_data_path_obj obj;
361
+ obj.archive = file;
362
+ obj.path = rpath;
363
+ obj.match = match;
364
+ obj.data = &data;
365
+
366
+ //struct archive_entry *entry = archive_entry_new();
367
+
368
+ //archive_read_next_header2(file,entry);
369
+ //archive_read_disk_descend(file);
370
+
371
+ RB_ENSURE(read_data_from_path_block,&obj,Archive_read_block_close,file);
372
+ }
373
+
374
+
375
+ void read_data_from_path2(VALUE path,VALUE opts,DataVector &data)
376
+ {
377
+ struct archive * file = archive_read_disk_new();
378
+ struct archive * match = create_match_object(opts);
379
+
380
+ archive_read_disk_set_standard_lookup(file);
381
+ const char * str = ".";
382
+ archive_match_include_pattern(match,".");
383
+ //archive_match_exclude_pattern(match,"*/*/*.cpp");
384
+ //archive_match_exclude_pattern(match,"*.cpp");
385
+ //archive_match_include_pattern(match,"*/");
386
+
387
+ if(!rb_obj_is_kind_of(path,rb_cRegexp))
388
+ {
389
+ path = rb_funcall(path,rb_intern("to_s"),0);
390
+ if(!RTEST(rb_funcall(rb_cFile,rb_intern("exist?"),1,path))){
391
+ archive_match_include_pattern(match,StringValueCStr(path));
392
+ }else
393
+ str = StringValueCStr(path);
394
+ }
395
+ read_data_from_path(file,match,path,str,data);
396
+ }
397
+
398
+ }
399
+
400
+ void Archive_format_from_path(VALUE self,int &format,IntVector &filters)
401
+ {
402
+ if(_self->type == archive_path){
403
+ std::string selfpath = _self->path;
404
+ size_t selfpathlength = selfpath.length();
405
+ for(FileExtType::iterator it = fileExt.begin(); it != fileExt.end(); ++it) {
406
+ if(selfpath.rfind(it->first) + it->first.length() == selfpathlength) {
407
+ format = it->second.first;
408
+ filters.push_back(it->second.second);
409
+ return;
410
+ }
411
+ }
412
+ }
413
+
414
+ format = _self->format;
415
+ filters.push_back(_self->filter);
416
+
417
+ }
418
+
419
+ int Archive_read_ruby(VALUE self,struct archive *data)
420
+ {
421
+
422
+ archive_read_support_filter_all(data);
423
+ archive_read_support_format_all(data);
424
+ #if HAVE_ARCHIVE_READ_SUPPORT_FORMAT_RAW
425
+ archive_read_support_format_raw(data);
426
+ #endif
427
+ int error =0;
428
+ switch(_self->type){
429
+ case archive_path:
430
+ error = archive_read_open_filename(data,_self->path.c_str(),10240);
431
+ break;
432
+ case archive_fd:
433
+ error = archive_read_open_fd(data,_self->fd,10240);
434
+ break;
435
+ case archive_buffer:
436
+ break;
437
+ case archive_ruby:
438
+ error = archive_read_open(data, (void*)_self->ruby,rubymyopen,rubymyread,rubymyclose);
439
+ break;
440
+ }
441
+ return error;
442
+ }
443
+
444
+
445
+
446
+ int Archive_write_ruby(VALUE self,struct archive *data,int format, const IntVector &filters)
447
+ {
448
+ int error =0;
449
+
450
+ if((error = archive_write_set_format(data,format)) != ARCHIVE_OK)
451
+ rb_raise(rb_eArchiveErrorFormat,"error (%d): %s ",error,archive_error_string(data));
452
+
453
+ RubyArchive::write_set_filters(data,filters);
454
+
455
+ switch(_self->type){
456
+ case archive_path:
457
+ error = archive_write_open_filename(data,_self->path.c_str());
458
+ break;
459
+ case archive_fd:
460
+ error = archive_write_open_fd(data,_self->fd);
461
+ break;
462
+ case archive_buffer:
463
+ break;
464
+ case archive_ruby:
465
+ error = archive_write_open(data,(void*)_self->ruby,rubymyopen,rubymywrite,rubymyclose);
466
+ break;
467
+ }
468
+ return error;
469
+ }
470
+
471
+ /*
472
+ *call-seq:
473
+ * new( path [, format [, compression ] ] ) → an_archive
474
+ *
475
+ * Makes a new Archive object. If format is given, a new archive is created or
476
+ * an existing archive will be converted into the given format.
477
+ * ===Parameters
478
+ * [path] The path to the archive. May or may not exist.
479
+ * [format] The archive's format as a symbol. If you ommit this, the format will
480
+ * be guessed from the file extension. Possible formats are:
481
+ * * :ar
482
+ * * :tar
483
+ * * :pax
484
+ * * :xar
485
+ * * :zip
486
+ * [compression] Symbol inidicating the compression you want to use. If
487
+ * ommited, it will be guessed from the file extension.
488
+ * Possible formats are:
489
+ * * :bzip2
490
+ * * :compress
491
+ * * :gzip
492
+ * * :lzma
493
+ * * :xz
494
+ * ===Raises
495
+ * [FormatError] Unknown archive format or writing not supported.
496
+ * [CompressionError] Unknown compression format.
497
+ * ===Examples
498
+ * See the README for some examples.
499
+ */
500
+
501
+ VALUE Archive_initialize(int argc, VALUE *argv,VALUE self)
502
+ {
503
+ VALUE path,r_format,r_filter;
504
+ rb_scan_args(argc, argv, "12", &path,&r_format,&r_filter);
505
+ if(rb_obj_is_kind_of(path,rb_cIO)){
506
+ _self->fd = NUM2INT(rb_funcall(path,rb_intern("fileno"),0));
507
+ _self->type = archive_fd;
508
+ rb_scan_args(argc, argv, "21", &path,&r_format,&r_filter);
509
+ }else if(rb_obj_is_kind_of(path,rb_cInteger)){
510
+ _self->fd = NUM2INT(path);
511
+ _self->type = archive_fd;
512
+ rb_scan_args(argc, argv, "21", &path,&r_format,&r_filter);
513
+ }else if(rb_respond_to(path,rb_intern("read"))){
514
+ _self->type = archive_ruby;
515
+ rb_scan_args(argc, argv, "21", &path,&r_format,&r_filter);
516
+ }else{
517
+ path = rb_file_s_expand_path(1,&path);
518
+ _self->path = std::string(StringValueCStr(path));
519
+ _self->type =archive_path;
520
+ }
521
+ _self->ruby = path;
522
+ //to set the format the file must convert
523
+ if(!NIL_P(r_format)){
524
+
525
+ //struct archive *a = archive_read_new(),*b=archive_write_new();
526
+ //struct archive_entry *entry;
527
+ int format,filter;
528
+
529
+ if(SYMBOL_P(r_format)){
530
+ SymToIntType::iterator it = SymToFormat.find(SYM2ID(r_format));
531
+ if(it != SymToFormat.end()) {
532
+ format = it->second;
533
+ }else
534
+ rb_raise(rb_eTypeError,"wrong format");
535
+ }else
536
+ rb_raise(rb_eTypeError,"exepted Symbol");
537
+
538
+ if(NIL_P(r_filter)){
539
+ filter = ARCHIVE_FILTER_NONE;
540
+ }else if(SYMBOL_P(r_filter)){
541
+ SymToIntType::iterator it = SymToFilter.find(SYM2ID(r_filter));
542
+ if(it != SymToFilter.end()) {
543
+ filter = it->second;
544
+ } else
545
+ rb_raise(rb_eTypeError,"unsupported filter");
546
+ }else
547
+ rb_raise(rb_eTypeError,"exepted Symbol");
548
+
549
+ //autodetect format and compression
550
+
551
+ _self->format = format;
552
+ _self->filter = filter;
553
+
554
+ // if(Archive_read_ruby(self,a)==ARCHIVE_OK){
555
+ // while(archive_read_next_header(a, &entry)==ARCHIVE_OK){
556
+ // if(format==archive_format(a) && filter==archive_filter_code(a,0)){
557
+ // archive_read_close(a);
558
+ // return self;
559
+ // }
560
+ // entries.push_back(archive_entry_clone(entry));
561
+ // allbuff.push_back(std::string(""));
562
+ //
563
+ // RubyArchive::read_data(a,allbuff.back());
564
+ // }
565
+ // archive_read_close(a);
566
+ // if(Archive_write_ruby(self,b,format,IntVector(filter))==ARCHIVE_OK){
567
+ // //write old data back
568
+ // for(unsigned int i=0; i<entries.size(); i++){
569
+ // archive_write_header(b,entries[i]);
570
+ // archive_write_data(b,allbuff[i].c_str(),allbuff[i].length());
571
+ // archive_write_finish_entry(b);
572
+ // }
573
+ // archive_write_close(b);
574
+ // }
575
+ // }
576
+ }
577
+ return self;
578
+ }
579
+
580
+ /*
581
+ * call-seq:
582
+ * path() → a_string
583
+ *
584
+ * Returns the path (filename) of the archive.
585
+ * ===Return value
586
+ * Returns path of the archive. May or may not exist.
587
+ * ===Example
588
+ * a.path #=> /home/freak/myarchive.tar.gz
589
+ */
590
+
591
+ VALUE Archive_path(VALUE self)
592
+ {
593
+ return (_self->type == archive_path) ? rb_str_new2(_self->path.c_str()) : Qnil;
594
+ }
595
+
596
+ VALUE Archive_each_block(struct archive *data)
597
+ {
598
+ struct archive_entry *entry;
599
+ while (archive_read_next_header(data, &entry) == ARCHIVE_OK) {
600
+ VALUE temp = wrap(entry);
601
+ if(rb_proc_arity(rb_block_proc())==1){
602
+ rb_yield(temp);
603
+ archive_read_data_skip(data);
604
+ }else{
605
+ std::string str;
606
+ RubyArchive::read_data(data,str);
607
+ rb_yield_values(2,temp,wrap_data(str));
608
+ }
609
+ }
610
+ return Qnil;
611
+ }
612
+
613
+ /*
614
+ * call-seq:
615
+ * each(){|entry [, data]| ... } → self
616
+ * each() → an_enumerator
617
+ *
618
+ * Iterates through the archive and yields each entry as an Archive::Entry object. The second parameter
619
+ * contains the data of that entry, so you don't have to extract it only to read what's in it.
620
+ * ===Return value
621
+ * If a block is given, returns self, otherwise an enumerator.
622
+ * ===Example
623
+ * a.each{|entry| p entry.path}
624
+ * a.each{|entry, data| puts "'#{entry.path}' contains '#{data}'"}
625
+ * Output:
626
+ * "file1.txt"
627
+ * "file2.txt"
628
+ * 'file1.txt' contains 'I am file1!'
629
+ * 'file2.txt' contains 'I am file2!'
630
+ */
631
+
632
+ VALUE Archive_each(VALUE self)
633
+ {
634
+ RETURN_ENUMERATOR(self,0,NULL);
635
+ struct archive *a = archive_read_new();
636
+
637
+
638
+ int error=Archive_read_ruby(self,a);
639
+ if(error==ARCHIVE_OK){
640
+ RB_ENSURE(Archive_each_block,a,Archive_read_block_ensure,a);
641
+ return self;
642
+ }
643
+ return Qnil;
644
+ }
645
+
646
+
647
+ VALUE Archive_each_entry_block(struct archive *data)
648
+ {
649
+ VALUE result = rb_ary_new();
650
+ struct archive_entry *entry;
651
+ while (archive_read_next_header(data, &entry) == ARCHIVE_OK) {
652
+ VALUE temp = wrap(entry);
653
+ rb_yield(temp);
654
+ archive_read_data_skip(data);
655
+ rb_ary_push(result,temp);
656
+ }
657
+ return result;
658
+ }
659
+
660
+ /*
661
+ * call-seq:
662
+ * each_entry() {|entry| ... } → an_array
663
+ * each_entry() → an_enumerator
664
+ *
665
+ * Iterates through the archive and yields each entry as an Archive::Entry object.
666
+ * This is the same as #each, but doesn't allow for the second block parameter.
667
+ * ===Return value
668
+ * If a block is given, returns an array of Archive::Entry objects, otherwise an enumerator.
669
+ * ===Example
670
+ * a.each_entry{|entry| p entry.path}
671
+ * Output:
672
+ * "file1.txt"
673
+ * "file2.txt"
674
+ */
675
+
676
+ VALUE Archive_each_entry(VALUE self)
677
+ {
678
+ RETURN_ENUMERATOR(self,0,NULL);
679
+ struct archive *a = archive_read_new();
680
+
681
+ if(Archive_read_ruby(self,a)==ARCHIVE_OK)
682
+ return RB_ENSURE(Archive_each_entry_block,a,Archive_read_block_ensure,a);
683
+ return Qnil;
684
+ }
685
+
686
+
687
+ VALUE Archive_each_data_block(struct archive *data)
688
+ {
689
+ struct archive_entry *entry;
690
+ while (archive_read_next_header(data, &entry) == ARCHIVE_OK) {
691
+ std::string str;
692
+ RubyArchive::read_data(data,str);
693
+ rb_yield(wrap_data(str));
694
+ }
695
+ return Qnil;
696
+ }
697
+
698
+
699
+ /*
700
+ * call-seq:
701
+ * each_data() {|data| } → self
702
+ * each_data() → an_enumerator
703
+ *
704
+ * Iterates through the archive and yields each entry's data as a string.
705
+ * This is the same as #each, but doesn't allow for the first block parameter.
706
+ * ===Return value
707
+ * If a block is given, returns self, otherwise an enumerator.
708
+ * ===Example
709
+ * a.each{|data| puts "This is: '#{data}'"}
710
+ * Output:
711
+ * This is: 'I am file1!'
712
+ * This is: 'I am file2!'
713
+ */
714
+
715
+ VALUE Archive_each_data(VALUE self)
716
+ {
717
+ RETURN_ENUMERATOR(self,0,NULL);
718
+ struct archive *a = archive_read_new();
719
+
720
+ if(Archive_read_ruby(self,a)==ARCHIVE_OK)
721
+ RB_ENSURE(Archive_each_data_block,a,Archive_read_block_ensure,a);
722
+ return self;
723
+ }
724
+
725
+ VALUE Archive_each_filter_block(struct archive *data)
726
+ {
727
+ struct archive_entry *entry;
728
+ archive_read_next_header(data, &entry);
729
+ size_t count = archive_filter_count(data);
730
+ for(size_t i = 0; i < count; ++i)
731
+ rb_yield_values(2,INT2NUM(archive_filter_code(data,i)),rb_str_new2(archive_filter_name(data,i)));
732
+
733
+ return Qnil;
734
+ }
735
+
736
+
737
+ VALUE Archive_each_filter(VALUE self)
738
+ {
739
+ RETURN_ENUMERATOR(self,0,NULL);
740
+ struct archive *a = archive_read_new();
741
+
742
+ if(Archive_read_ruby(self,a)==ARCHIVE_OK)
743
+ RB_ENSURE(Archive_each_filter_block,a,Archive_read_block_ensure,a);
744
+ return self;
745
+ }
746
+
747
+ /*
748
+ * call-seq:
749
+ * archive.to_hash → Hash
750
+ *
751
+ * Iterates through the archive and yields each data of an entry as a string object.
752
+ * ===Return value
753
+ * returns Hash of Archive::Entry => String
754
+ */
755
+
756
+ VALUE Archive_to_hash(VALUE self)
757
+ {
758
+ VALUE result = rb_hash_new();
759
+ struct archive *a = archive_read_new();
760
+ struct archive_entry *entry;
761
+
762
+ if(Archive_read_ruby(self,a)==ARCHIVE_OK){
763
+ while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
764
+ std::string str;
765
+ RubyArchive::read_data(a,str);
766
+ rb_hash_aset(result,wrap(entry),wrap_data(str));
767
+ }
768
+ archive_read_close(a);
769
+ }
770
+ return result;
771
+ }
772
+
773
+ VALUE Archive_map_block(struct write_obj * data){
774
+ for(unsigned int i=0; i< data->data->size(); i++){
775
+ VALUE temp = wrap(data->data->at(i).first);
776
+ VALUE val;
777
+ if(rb_proc_arity(rb_block_proc())<2){
778
+ val = rb_yield(temp);
779
+ }else{
780
+ val = rb_yield_values(2,temp,wrap_data(data->data->at(i).second));
781
+ }
782
+ VALUE entry,rdata= Qnil;
783
+ if(rb_obj_is_kind_of(val,rb_cArray)){
784
+ entry=rb_ary_entry(val,0);
785
+ rdata=rb_ary_entry(val,1);
786
+ }else
787
+ entry = val;
788
+ if(rb_obj_is_kind_of(entry,rb_cArchiveEntry)){
789
+ archive_write_header(data->archive,wrap<struct archive_entry *>(val));
790
+
791
+ if(rdata == Qnil){
792
+ std::string &buff = data->data->at(i).second;
793
+ archive_write_data(data->archive,&buff[0],buff.length());
794
+ }else{
795
+ //char* buff = StringValueCStr(rdata);
796
+ archive_write_data(data->archive,RSTRING_PTR(rdata),RSTRING_LEN(rdata));
797
+ }
798
+ archive_write_finish_entry(data->archive);
799
+ }else if(entry==Qnil){
800
+ }else
801
+ rb_raise(rb_eTypeError,"exepted %s!",rb_class2name(rb_cArchiveEntry));
802
+ }
803
+ return Qnil;
804
+ }
805
+
806
+ /*
807
+ * call-seq:
808
+ * map!() {| entry [,data] | ... } → Array
809
+ * archive.map!() → Enumerator
810
+ *
811
+ * Iterates through the archive and changes it's data "on the fly", i.e.
812
+ * the value your block returns for each iteration is put for the data
813
+ * in the yielded entry. Your block is expected to return a 2-element
814
+ * array of form
815
+ * [archive_entry, "data"]
816
+ * where +archive_enty+ is the +entry+ yielded to the block (which you
817
+ * may modify via the Archive::Entry methods) and <tt>"data"</tt> is a
818
+ * string containing the data you want to set for this entry.
819
+ *
820
+ * The block parameters are the same as for #each.
821
+ * ===Return value
822
+ * The archive itself.
823
+ * ===Example
824
+ * #Double the contents in each file of the archive
825
+ * a.map!{|entry, data| [entry, data * 2]}
826
+ * #Clear all files in the archive
827
+ * a.map!{|entry| [entry, ""]}
828
+ */
829
+ VALUE Archive_map_self(VALUE self)
830
+ {
831
+ RETURN_ENUMERATOR(self,0,NULL);
832
+
833
+ struct archive *a = archive_read_new(),*b=archive_write_new();
834
+ int format = ARCHIVE_FORMAT_EMPTY;
835
+
836
+ DataVector entries;
837
+ IntVector filters;
838
+
839
+ //autodetect format and filters
840
+ if(Archive_read_ruby(self,a)==ARCHIVE_OK){
841
+
842
+ RubyArchive::read_old_data(a,entries, format, filters);
843
+
844
+ if(Archive_write_ruby(self,b,format,filters)==ARCHIVE_OK){
845
+ write_obj obj;
846
+ obj.archive = b;
847
+ obj.data = &entries;
848
+ RB_ENSURE(Archive_map_block,&obj,Archive_write_block_ensure,b);
849
+ }
850
+ }
851
+ return self;
852
+ }
853
+
854
+ /*
855
+ * call-seq:
856
+ * [](name) → Archive::Entry or nil
857
+ *
858
+ * Returns an archive entry for the given name.
859
+ * ===Parameters
860
+ * [name] could be a String or a Regex.
861
+ * ===Return value
862
+ * If a matching entry is found, it's returned as an Archive::Entry object. If not,
863
+ * nil is returned.
864
+ * ===Example
865
+ * #Assuming your archive contains file.txt and ruby.txt
866
+ *
867
+ * a["file.txt"] #=> Archive::Entry
868
+ * a[/txt/] #=> Archive::Entry
869
+ */
870
+
871
+ VALUE Archive_get(VALUE self,VALUE val)
872
+ {
873
+ struct archive *a = archive_read_new();
874
+ struct archive_entry *entry;
875
+
876
+ if(Archive_read_ruby(self,a)==ARCHIVE_OK){
877
+ while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
878
+ if(RubyArchive::match_entry(entry,val)){
879
+ VALUE result = wrap(entry);
880
+ archive_read_close(a);
881
+ return result;
882
+ }
883
+ }
884
+ archive_read_close(a);
885
+ }
886
+ return Qnil;
887
+ }
888
+
889
+
890
+ void extract_extract(struct archive *a,struct archive_entry *entry,int extract_opt,VALUE io, int fd)
891
+ {
892
+ if(rb_obj_is_kind_of(io,rb_cIO)){
893
+ archive_read_data_into_fd(a,fd);
894
+ }else if(rb_respond_to(io,rb_intern("write"))){
895
+ char buff[8192];
896
+ size_t bytes_read;
897
+ while ((bytes_read=archive_read_data(a,&buff,sizeof(buff)))>0)
898
+ rb_funcall(io,rb_intern("write"),1,rb_str_new(buff,bytes_read));
899
+ }else
900
+ archive_read_extract(a,entry,extract_opt);
901
+ }
902
+ /*
903
+ * call-seq:
904
+ * extract( [name = nil [, io [ ,opt ] ] ] ) → an_array
905
+ *
906
+ * Extract files to current directory.
907
+ * ===Parameters
908
+ * [name] (nil) could be an Archive::Entry, a String or an Regex. If given,
909
+ * only this entry is extracted. Otherwise extracts the whole
910
+ * archive.
911
+ * [io] an instance of IO or something with a +write+ method like
912
+ * StringIO. If given, the entry specified via +name+ will be
913
+ * extracted into +io+ instead of a file.
914
+ * [opt] is an option hash. See below for possible options.
915
+ * ===Parameters for the option hash
916
+ * [:extract] flag, Integer combined of the Archive::Extract_* constants.
917
+ * This tells libarchive-ruby to only extract the file attributes
918
+ * you specify here. Exceptions is Archive::EXTRACT_NO_OVERWRITE
919
+ * which prevents this method from overwrtiting existing files.
920
+ * ===Return value
921
+ * The paths of the extracted entries as an array.
922
+ * ===Example
923
+ * #Simply extract everything into the current directory.
924
+ * a.extract
925
+ * #Extract only file1.txt
926
+ * a.extract("file1.txt")
927
+ * #Same as above, but extract it to a StringIO
928
+ * s = StringIO.new
929
+ * a.extract("file1.txt", s)
930
+ * #Same as the first example, but only extract information about the
931
+ * #modification time.
932
+ * a.extract(nil, nil, extract: Archive::EXTRACT_TIME)
933
+ */
934
+
935
+ VALUE Archive_extract(int argc, VALUE *argv, VALUE self)
936
+ {
937
+
938
+ VALUE result = rb_ary_new(),name,io,opts,temp;
939
+ struct archive *a = archive_read_new();
940
+ struct archive_entry *entry;
941
+ //add raw, this is not by all
942
+ int extract_opt = 0,fd=-1;
943
+ rb_scan_args(argc, argv, "03", &name,&io,&opts);
944
+ if(rb_obj_is_kind_of(name,rb_cHash)){
945
+ opts = name;name = Qnil;
946
+ }
947
+ if(rb_obj_is_kind_of(io,rb_cHash)){
948
+ opts = io;io = Qnil;
949
+ }
950
+ if(rb_obj_is_kind_of(io,rb_cIO))
951
+ fd = NUM2INT(rb_funcall(io,rb_intern("fileno"),0));
952
+
953
+
954
+ if(rb_obj_is_kind_of(opts,rb_cHash))
955
+ if(RTEST(temp=rb_hash_aref(opts,ID2SYM(rb_intern("extract")))))
956
+ extract_opt = NUM2INT(temp);
957
+
958
+ if(Archive_read_ruby(self,a)==ARCHIVE_OK){
959
+ try{
960
+ if(NIL_P(name)){
961
+ if(!NIL_P(io)){
962
+ rb_raise(rb_eArgError,"You can't extract more than 1 entry into an IO-like object!");
963
+ }
964
+ while(archive_read_next_header(a, &entry) == ARCHIVE_OK){
965
+ archive_read_extract(a,entry,extract_opt);
966
+ rb_ary_push(result,rb_str_new2(archive_entry_pathname(entry)));
967
+ }
968
+ }else{
969
+ while(archive_read_next_header(a, &entry) == ARCHIVE_OK){
970
+ if(RubyArchive::match_entry(entry,name)){
971
+ extract_extract(a,entry,extract_opt,io,fd);
972
+ rb_ary_push(result,rb_str_new2(archive_entry_pathname(entry)));
973
+ }
974
+ }
975
+ }
976
+ }catch (...){
977
+ rb_raise(rb_eArchiveError,"error:%d:%s",archive_errno(a),archive_error_string(a));
978
+ }
979
+ archive_read_close(a);
980
+ }
981
+ return result;
982
+ }
983
+
984
+ VALUE Archive_extract_if_block(struct extract_obj * data)
985
+ {
986
+ VALUE result = rb_ary_new();
987
+ struct archive_entry *entry;
988
+ while(archive_read_next_header(data->archive, &entry) == ARCHIVE_OK){
989
+ VALUE str = rb_str_new2(archive_entry_pathname(entry));
990
+ if(RTEST(rb_yield(wrap(entry)))){
991
+ archive_read_extract(data->archive,entry,data->extract_opt);
992
+ rb_ary_push(result,str);
993
+ }
994
+ }
995
+ return result;
996
+ }
997
+ /*
998
+ * call-seq:
999
+ * extract_if( [ opt ] ) {|entry| } → an_array
1000
+ * extract_if( [ opt ] ) → an_enumerator
1001
+ *
1002
+ * Yields each entry in the archive to the block and extracts only those
1003
+ * entries (to the current directory) for which the block evaluates to a
1004
+ * truth value.
1005
+ * ===Parameters
1006
+ * [opt] is the same option hash that you can pass to #extract.
1007
+ * ====Parameters for the option hash
1008
+ * See the #extract method for explanation.
1009
+ * ===Return value
1010
+ * The paths of all extracted entries if a block was given, an Enumerator
1011
+ * otherwise.
1012
+ */
1013
+
1014
+ VALUE Archive_extract_if(int argc, VALUE *argv, VALUE self)
1015
+ {
1016
+ RETURN_ENUMERATOR(self,argc,argv);
1017
+ VALUE opts,temp;
1018
+ struct archive *a = archive_read_new();
1019
+
1020
+ int extract_opt=0;
1021
+
1022
+ rb_scan_args(argc, argv, "01", &opts);
1023
+ if(rb_obj_is_kind_of(opts,rb_cHash))
1024
+ if(RTEST(temp=rb_hash_aref(opts,ID2SYM(rb_intern("extract")))))
1025
+ extract_opt = NUM2INT(temp);
1026
+
1027
+ if(Archive_read_ruby(self,a)==ARCHIVE_OK){
1028
+ extract_obj obj;
1029
+ obj.archive = a;
1030
+ obj.extract_opt = extract_opt;
1031
+ return RB_ENSURE(Archive_extract_if_block,&obj,Archive_read_block_ensure,a);
1032
+ }
1033
+ return Qnil;
1034
+ }
1035
+
1036
+ /*
1037
+ * call-seq:
1038
+ * format() → an_integer or nil
1039
+ *
1040
+ * Returns the archive format as an integer. You should use #format_name
1041
+ * instead.
1042
+ * ===Return value
1043
+ * An integer or nil if the format wasn't detectable.
1044
+ */
1045
+
1046
+ VALUE Archive_format(VALUE self)
1047
+ {
1048
+ struct archive *a = archive_read_new();
1049
+ struct archive_entry *entry;
1050
+ VALUE result = Qnil;
1051
+
1052
+ if(Archive_read_ruby(self,a)==ARCHIVE_OK){
1053
+ archive_read_next_header(a, &entry);
1054
+ result = INT2NUM(archive_format(a));
1055
+ archive_read_close(a);
1056
+ }
1057
+ return result;
1058
+ }
1059
+
1060
+ /*
1061
+ * call-seq:
1062
+ * format_name() → a_string or nil
1063
+ *
1064
+ * Returns the archive format's name as a string.
1065
+ * ===Return value
1066
+ * A string or nil if the format wasn't detectable.
1067
+ * ===Example
1068
+ * a.format_name #=> "GNU tar format"
1069
+ */
1070
+
1071
+ VALUE Archive_format_name(VALUE self)
1072
+ {
1073
+ struct archive *a = archive_read_new();
1074
+ struct archive_entry *entry;
1075
+ const char* name = NULL;
1076
+
1077
+ if(Archive_read_ruby(self,a)==ARCHIVE_OK){
1078
+ if(archive_read_next_header(a, &entry)==ARCHIVE_OK){
1079
+ name = archive_format_name(a);
1080
+ archive_read_close(a);
1081
+ }
1082
+ }
1083
+ return name ? rb_str_new2(name) : Qnil;
1084
+ }
1085
+
1086
+
1087
+
1088
+
1089
+
1090
+
1091
+
1092
+
1093
+
1094
+
1095
+ ////key is the entry and val is
1096
+
1097
+ ////TODO: hier nochmal ein ensure rein damit es das file wieder zu macht?
1098
+ //int Archive_add_hash_block(VALUE key,VALUE val,struct add_obj *obj){
1099
+ // char buff[8192];
1100
+ // size_t bytes_read;
1101
+ // int fd=-1;
1102
+ // obj->file = archive_read_disk_new();
1103
+ // archive_read_disk_set_standard_lookup(obj->file);
1104
+ // struct archive_entry *entry = archive_entry_new();
1105
+ // archive_entry_copy_pathname(entry, StringValueCStr(key));
1106
+ // if(rb_obj_is_kind_of(val,rb_cFile)){
1107
+ // VALUE pathname = rb_funcall(val,rb_intern("path"),0); //source path
1108
+ // VALUE obj2 = rb_file_s_expand_path(1,&pathname);
1109
+ // archive_entry_copy_sourcepath(entry, StringValueCStr(obj2));
1110
+ // fd = NUM2INT(rb_funcall(val,rb_intern("fileno"),0));
1111
+ // }else if(rb_obj_is_kind_of(val,rb_cIO)){
1112
+ // fd = NUM2INT(rb_funcall(val,rb_intern("fileno"),0));
1113
+ // }else if(rb_respond_to(val,rb_intern("read"))){
1114
+ // //stringio has neigther path or fileno, so do nothing
1115
+ // }else {
1116
+ // VALUE obj2 = rb_file_s_expand_path(1,&val);
1117
+ // archive_entry_copy_sourcepath(entry, StringValueCStr(obj2));
1118
+ // fd = open(StringValueCStr(obj2), O_RDONLY);
1119
+ // if (fd < 0) //TODO: add error
1120
+ // {
1121
+ // return 0;
1122
+ // }
1123
+ // }
1124
+ // if(fd > 0)
1125
+ // archive_read_disk_entry_from_file(obj->file, entry, fd, NULL);
1126
+ // if(rb_block_given_p()){
1127
+ // VALUE temp = wrap(entry);
1128
+ // VALUE result = rb_yield(temp);
1129
+ // if(rb_obj_is_kind_of(result,rb_cArchiveEntry))
1130
+ // entry = wrap<archive_entry*>(result);
1131
+ // else
1132
+ // entry = wrap<archive_entry*>(temp);
1133
+ // }
1134
+ // for(unsigned int i = 0;i < obj->entries->size();)
1135
+ // {
1136
+ // if(std::string(archive_entry_pathname(obj->entries->at(i))).compare(archive_entry_pathname(entry)) == 0){
1137
+ // obj->entries->erase(obj->entries->begin()+i);
1138
+ // obj->allbuff->erase(obj->allbuff->begin()+i);
1139
+ // }else
1140
+ // i++;
1141
+ // }
1142
+ // std::string strbuff;
1143
+ // if(fd < 0 and rb_respond_to(val,rb_intern("read"))){
1144
+ // VALUE result = rb_funcall(val,rb_intern("read"),0);
1145
+ // strbuff.append(StringValueCStr(result), RSTRING_LEN(result));
1146
+ // }else{
1147
+ // while ((bytes_read = read(fd, buff, sizeof(buff))) > 0)
1148
+ // strbuff.append(buff, bytes_read);
1149
+ // }
1150
+ // obj->entries->push_back(entry);
1151
+ // obj->allbuff->push_back(strbuff);
1152
+ // if(fd >= 0 and !rb_obj_is_kind_of(val,rb_cIO))
1153
+ // close(fd);
1154
+ // archive_read_close(obj->file);
1155
+ // return 0;
1156
+ //}
1157
+
1158
+ //VALUE Archive_add_block(struct add_obj *obj )
1159
+ //{
1160
+ // VALUE robj = obj->obj;
1161
+ // char buff[8192];
1162
+ // size_t bytes_read;
1163
+ // archive_read_disk_set_standard_lookup(obj->file);
1164
+ // if(rb_obj_is_kind_of(robj,rb_cArray)){
1165
+ // for(int i=0;i< RARRAY_LEN(robj);i++){
1166
+ // VALUE temp = RARRAY_PTR(robj)[i];
1167
+ // int fd = -1;
1168
+ // char *sourcepath,*pathname;
1169
+ // if(rb_obj_is_kind_of(temp,rb_cFile)){
1170
+ // VALUE rpath = rb_funcall(temp,rb_intern("path"),0); //source path
1171
+ // pathname = StringValueCStr(rpath);
1172
+ // VALUE obj2 = rb_file_s_expand_path(1,&rpath);
1173
+ // sourcepath = StringValueCStr(obj2);
1174
+ // fd = NUM2INT(rb_funcall(temp,rb_intern("fileno"),0));
1175
+ // }else{
1176
+ // VALUE obj2 = rb_file_s_expand_path(1,&temp);
1177
+ // sourcepath = pathname = StringValueCStr(obj2);
1178
+ // fd = open(pathname, O_RDONLY);
1179
+ // if (fd < 0) //TODO: add error
1180
+ // return Qnil;
1181
+ // }
1182
+ // struct archive_entry *entry = archive_entry_new();
1183
+ // archive_entry_copy_sourcepath(entry, sourcepath);
1184
+ // archive_entry_copy_pathname(entry, pathname);
1185
+ // archive_read_disk_entry_from_file(obj->file, entry, fd, NULL);
1186
+ // if(rb_block_given_p()){
1187
+ // VALUE temp = wrap(entry);
1188
+ // VALUE result = rb_yield(temp);
1189
+ // if(rb_obj_is_kind_of(result,rb_cArchiveEntry))
1190
+ // entry = wrap<archive_entry*>(result);
1191
+ // else
1192
+ // entry = wrap<archive_entry*>(temp);
1193
+ // }
1194
+ // std::string strbuff;
1195
+ // while ((bytes_read = read(fd, buff, sizeof(buff))) > 0)
1196
+ // strbuff.append(buff, bytes_read);
1197
+ // if(fd >= 0 and !rb_obj_is_kind_of(robj,rb_cIO))
1198
+ // close(fd);
1199
+ // obj->entries->push_back(entry);
1200
+ // obj->allbuff->push_back(strbuff);
1201
+ // }
1202
+ // }else if(rb_obj_is_kind_of(robj,rb_cHash)){
1203
+ // archive_read_close(obj->file);
1204
+ // rb_hash_foreach(robj,(int (*)(...))Archive_add_hash_block,(VALUE)obj);
1205
+ // }else
1206
+ // {
1207
+ // if(obj->fd > 0)
1208
+ // archive_read_disk_entry_from_file(obj->file, obj->entry, obj->fd, NULL);
1209
+
1210
+ // if(rb_block_given_p()){
1211
+ // VALUE temp = wrap(obj->entry);
1212
+ // VALUE result = rb_yield(temp);
1213
+ // if(rb_obj_is_kind_of(result,rb_cArchiveEntry))
1214
+ // obj->entry = wrap<archive_entry*>(result);
1215
+ // else
1216
+ // obj->entry = wrap<archive_entry*>(temp);
1217
+ // }
1218
+ // for(unsigned int i = 0;i < obj->entries->size();)
1219
+ // {
1220
+ // if(std::string(archive_entry_pathname(obj->entries->at(i))).compare(archive_entry_pathname(obj->entry)) == 0){
1221
+ // obj->entries->erase(obj->entries->begin()+i);
1222
+ // obj->allbuff->erase(obj->allbuff->begin()+i);
1223
+ // }else
1224
+ // i++;
1225
+ // }
1226
+ // std::string strbuff;
1227
+ // if(obj->fd < 0 and rb_respond_to(robj,rb_intern("read"))){
1228
+ // VALUE result = rb_funcall(robj,rb_intern("read"),0);
1229
+ // strbuff.append(StringValueCStr(result), RSTRING_LEN(result));
1230
+ // }else{
1231
+ // while ((bytes_read = read(obj->fd, buff, sizeof(buff))) > 0)
1232
+ // strbuff.append(buff, bytes_read);
1233
+ // }
1234
+ // obj->entries->push_back(obj->entry);
1235
+ // obj->allbuff->push_back(strbuff);
1236
+ // }
1237
+ // return Qnil;
1238
+ //}
1239
+
1240
+ VALUE Archive_add_block(struct add_obj *obj )
1241
+ {
1242
+ RubyArchive::read_data_from_path2(obj->obj,Qnil,*obj->data);
1243
+ return Qnil;
1244
+ }
1245
+
1246
+ VALUE Archive_add_block_ensure(struct add_obj *obj )
1247
+ {
1248
+ // if(!rb_obj_is_kind_of(obj->obj,rb_cHash))
1249
+ // archive_read_close(obj->file);
1250
+
1251
+ size_t size = obj->data->size();
1252
+ for(unsigned int i=0; i<size; i++){
1253
+ archive_write_header(obj->archive,obj->data->at(i).first);
1254
+ archive_write_data(obj->archive,&obj->data->at(i).second[0],obj->data->at(i).second.length());
1255
+ archive_write_finish_entry(obj->archive);
1256
+ }
1257
+ archive_write_close(obj->archive);
1258
+ return Qnil;
1259
+ }
1260
+
1261
+ /*
1262
+ * call-seq:
1263
+ * add( obj [, path] ) → self
1264
+ * add( obj [, path] ) {|entry| } → self
1265
+ * add( [obj, ... ] ) → self
1266
+ * add( [obj, ... ] ) {|entry| } → self
1267
+ * add( { path => obj} ) → self
1268
+ * add( { path => obj} ) {|entry| } → self
1269
+ *
1270
+ * Adds a file to an archive.
1271
+ * ===Parameters
1272
+ * [obj] String, IO, File or an object which responds to +read+.
1273
+ * [path] Sets the file name inside the archive.
1274
+ * ===Return value
1275
+ * self
1276
+ * ===Raises
1277
+ * [FormatError] Raised if the archive format is not supported for writing.
1278
+ */
1279
+
1280
+ VALUE Archive_add(int argc, VALUE *argv, VALUE self)//(VALUE self,VALUE obj,VALUE name)
1281
+ {
1282
+ VALUE obj,name;
1283
+ rb_scan_args(argc, argv, "11", &obj,&name);
1284
+ if(NIL_P(name)){
1285
+ if(rb_obj_is_kind_of(obj,rb_cFile))
1286
+ name = rb_funcall(name,rb_intern("path"),0);
1287
+ else if(rb_obj_is_kind_of(obj,rb_cIO))
1288
+ rb_scan_args(argc, argv, "20", &obj,&name);
1289
+ else if(rb_respond_to(obj,rb_intern("read")))
1290
+ rb_scan_args(argc, argv, "20", &obj,&name);
1291
+ else if(rb_obj_is_kind_of(obj,rb_cArray) or rb_obj_is_kind_of(obj,rb_cHash))
1292
+ rb_scan_args(argc, argv, "10", &obj);
1293
+ else
1294
+ name = obj;
1295
+ }
1296
+
1297
+ struct archive *a = archive_read_new(),*b=archive_write_new();
1298
+
1299
+ DataVector entries;
1300
+ IntVector filters;
1301
+
1302
+
1303
+ int format= ARCHIVE_FORMAT_EMPTY;
1304
+
1305
+
1306
+ //autodetect format and compression
1307
+ if(Archive_read_ruby(self,a)==ARCHIVE_OK){
1308
+ RubyArchive::read_old_data(a, entries, format, filters);
1309
+ }
1310
+
1311
+ // if(rb_obj_is_kind_of(obj,rb_cFile)){
1312
+ // VALUE pathname = rb_funcall(obj,rb_intern("path"),0); //source path
1313
+ // VALUE obj2 = rb_file_s_expand_path(1,&pathname);
1314
+ // path = StringValueCStr(obj2);
1315
+ // fd = NUM2INT(rb_funcall(obj,rb_intern("fileno"),0));
1316
+ // }else if(rb_obj_is_kind_of(obj,rb_cIO)){
1317
+ // fd = NUM2INT(rb_funcall(obj,rb_intern("fileno"),0));
1318
+ // }else if(rb_respond_to(obj,rb_intern("read")) or rb_obj_is_kind_of(obj,rb_cArray) or rb_obj_is_kind_of(obj,rb_cHash)){
1319
+ // //stringio has neigther path or fileno, so do nothing
1320
+ // }else {
1321
+ // if(RTEST(rb_funcall(rb_cFile,rb_intern("directory?"),1,obj)))
1322
+ // obj = rb_funcall(rb_cDir,rb_intern("glob"),1,rb_str_new2("**/**/*"));
1323
+ // else{
1324
+ // VALUE obj2 = rb_file_s_expand_path(1,&obj);
1325
+ // path = StringValueCStr(obj2);
1326
+ // fd = open(path, O_RDONLY);
1327
+ // if (fd < 0) //TODO: add error
1328
+ // return self;
1329
+ // }
1330
+ // }
1331
+ // Archive_format_from_path(self,format,compression);
1332
+
1333
+ if(format == ARCHIVE_FORMAT_EMPTY){
1334
+ Archive_format_from_path(self,format,filters);
1335
+ }
1336
+
1337
+ if(Archive_write_ruby(self,b,format,filters)==ARCHIVE_OK){
1338
+
1339
+ add_obj temp;
1340
+ temp.archive = b;
1341
+ temp.obj = obj;
1342
+ //temp.path = path;
1343
+ temp.name = name;
1344
+ temp.data = &entries;
1345
+ RB_ENSURE(Archive_add_block,&temp,Archive_add_block_ensure,&temp);
1346
+ }
1347
+
1348
+ return self;
1349
+ }
1350
+
1351
+ /*
1352
+ * call-seq:
1353
+ * << obj → self
1354
+ *
1355
+ * Adds a file to an archive. Basicly the same as #add, but you can't
1356
+ * set the path inside the archive.
1357
+ * ===Parameters
1358
+ * [obj] String or File
1359
+ * ===Return value
1360
+ * self
1361
+ * ===Raises
1362
+ * [FormatError] The archive format is not supported for writing.
1363
+ */
1364
+ VALUE Archive_add_shift(VALUE self,VALUE name)
1365
+ {
1366
+ return Archive_add(1,&name,self);
1367
+ }
1368
+
1369
+ /*
1370
+ * call-seq:
1371
+ * delete( name ) → an_array
1372
+ *
1373
+ * Delete files from an archive.
1374
+ * ===Parameters
1375
+ * [name] An Archive::Entry, a String or a Regex.
1376
+ * ===Return value
1377
+ * A list of paths removed from the archive.
1378
+ * ===Raises
1379
+ * raise TypeError if the parameter is neigther String or File.
1380
+ * raise Error if the format has no write support
1381
+ */
1382
+
1383
+ VALUE Archive_delete(VALUE self,VALUE val)
1384
+ {
1385
+ struct archive *a = archive_read_new(),*b=archive_write_new();
1386
+ int format = ARCHIVE_FORMAT_EMPTY;
1387
+
1388
+ DataVector entries;
1389
+ IntVector filters;
1390
+
1391
+ VALUE result = rb_ary_new();
1392
+
1393
+ //autodetect format and compression
1394
+ if(Archive_read_ruby(self,a)==ARCHIVE_OK){
1395
+ RubyArchive::read_old_data(a, entries, format, filters);
1396
+
1397
+ for(unsigned int i=0; i<entries.size();){
1398
+ if(RubyArchive::match_entry(entries[i].first,val)){
1399
+ rb_ary_push(result,rb_str_new2(archive_entry_pathname(entries[i].first)));
1400
+ entries.erase(entries.begin() + i);
1401
+ }else
1402
+ ++i;
1403
+ }
1404
+
1405
+ if(Archive_write_ruby(self,b,format,filters)==ARCHIVE_OK){
1406
+ //write old data back
1407
+ for(unsigned int i=0; i<entries.size(); i++){
1408
+ archive_write_header(b,entries[i].first);
1409
+ archive_write_data(b,&entries[i].second[0],entries[i].second.length());
1410
+ archive_write_finish_entry(b);
1411
+ }
1412
+ archive_write_close(b);
1413
+ }
1414
+
1415
+ }
1416
+ return result;
1417
+ }
1418
+
1419
+ VALUE Archive_delete_if_block(struct write_obj * data)
1420
+ {
1421
+ VALUE result= rb_ary_new();
1422
+ for(unsigned int i=0; i< data->data->size(); i++){
1423
+ if(!RTEST(rb_yield(wrap(data->data->at(i).first)))){
1424
+ archive_write_header(data->archive,data->data->at(i).first);
1425
+ archive_write_data(data->archive,&data->data->at(i).second[0],data->data->at(i).second.length());
1426
+ archive_write_finish_entry(data->archive);
1427
+ }else
1428
+ rb_ary_push(result,wrap(data->data->at(i).first));
1429
+ }
1430
+ return result;
1431
+ }
1432
+
1433
+ /*
1434
+ * call-seq:
1435
+ * archive.delete_if {|entry| } -> self
1436
+ * archive.delete_if -> Enumerator
1437
+ *
1438
+ * Yields each entry in the archive to the block and deletes those for which
1439
+ * the block evaluates to a truth value.
1440
+ * ===Parameters
1441
+ * [name] An Archive::Entry, a String or a Regex.
1442
+ * ===Return value
1443
+ * If a block was given, returns self, otherwise an Enumerator.
1444
+ * ===Raises
1445
+ * raise Error if the format has no write support
1446
+ */
1447
+
1448
+ VALUE Archive_delete_if(VALUE self)
1449
+ {
1450
+ RETURN_ENUMERATOR(self,0,NULL);
1451
+
1452
+ struct archive *a = archive_read_new(),*b=archive_write_new();
1453
+ int format = ARCHIVE_FORMAT_EMPTY;
1454
+
1455
+ DataVector entries;
1456
+ IntVector filters;
1457
+
1458
+ if(Archive_read_ruby(self,a)==ARCHIVE_OK){
1459
+ RubyArchive::read_old_data(a, entries, format, filters);
1460
+
1461
+ if(Archive_write_ruby(self,b,format,filters)==ARCHIVE_OK){
1462
+ write_obj obj;
1463
+ obj.archive = b;
1464
+ obj.data = &entries;
1465
+ return RB_ENSURE(Archive_delete_if_block,&obj,Archive_write_block_ensure,b);
1466
+ }
1467
+ }
1468
+ return Qnil;
1469
+ }
1470
+
1471
+ /*
1472
+ * call-seq:
1473
+ * archive.clear -> self
1474
+ *
1475
+ * Deletes all files from an archive.
1476
+ * ===Return value
1477
+ * returns self.
1478
+ * ===Raises
1479
+ * raise Error if the format has no write support
1480
+ */
1481
+
1482
+ VALUE Archive_clear(VALUE self)
1483
+ {
1484
+
1485
+ struct archive *a = archive_read_new(),*b=archive_write_new();
1486
+ struct archive_entry *entry;
1487
+ int format = ARCHIVE_FORMAT_EMPTY;
1488
+
1489
+ if(Archive_read_ruby(self,a)==ARCHIVE_OK){
1490
+ archive_read_next_header(a, &entry);
1491
+ format = archive_format(a);
1492
+ IntVector filters;
1493
+ RubyArchive::read_get_filters(a,filters);
1494
+ archive_read_close(a);
1495
+
1496
+ if(Archive_write_ruby(self,b,format,filters)==ARCHIVE_OK)
1497
+ archive_write_close(b);
1498
+ }
1499
+
1500
+ return self;
1501
+ }
1502
+
1503
+ /*:nodoc:
1504
+ * call-seq:
1505
+ * archive.exist? -> true or false
1506
+ *
1507
+ * Same as
1508
+ * File.exist?(archive.path)
1509
+ * . Checks wheather or not the archive file is existant.
1510
+ * ===Return value
1511
+ * True or false.
1512
+ */
1513
+
1514
+ VALUE Archive_exist(VALUE self)
1515
+ {
1516
+ return rb_funcall(rb_cFile,rb_intern("exist?"),1,Archive_path(self));
1517
+ }
1518
+
1519
+ /*:nodoc:
1520
+ * call-seq:
1521
+ * archive.unlink -> self
1522
+ *
1523
+ * call the File.unlink(path)
1524
+ */
1525
+
1526
+ VALUE Archive_unlink(VALUE self)
1527
+ {
1528
+ return rb_funcall(rb_cFile,rb_intern("unlink"),1,Archive_path(self));
1529
+ return self;
1530
+ }
1531
+
1532
+ /*:nodoc:
1533
+ * call-seq:
1534
+ * archive.mtime -> Time
1535
+ *
1536
+ * call the File.mtime(path)
1537
+ */
1538
+
1539
+ VALUE Archive_mtime(VALUE self)
1540
+ {
1541
+ return rb_funcall(rb_cFile,rb_intern("mtime"),1,Archive_path(self));
1542
+ }
1543
+
1544
+ /*:nodoc:
1545
+ * call-seq:
1546
+ * archive.atime -> Time
1547
+ *
1548
+ * call the File.atime(path)
1549
+ */
1550
+
1551
+ VALUE Archive_atime(VALUE self)
1552
+ {
1553
+ return rb_funcall(rb_cFile,rb_intern("atime"),1,Archive_path(self));
1554
+ }
1555
+
1556
+ /*:nodoc:
1557
+ * call-seq:
1558
+ * archive.ctime -> Time
1559
+ *
1560
+ * call the File.ctime(path)
1561
+ */
1562
+
1563
+
1564
+ VALUE Archive_ctime(VALUE self)
1565
+ {
1566
+ return rb_funcall(rb_cFile,rb_intern("ctime"),1,Archive_path(self));
1567
+ }
1568
+
1569
+ /*:nodoc:
1570
+ * call-seq:
1571
+ * archive.stat -> File::Stat
1572
+ *
1573
+ * call the File.stat(path)
1574
+ */
1575
+
1576
+ VALUE Archive_stat(VALUE self)
1577
+ {
1578
+ return rb_funcall(rb_cFile,rb_intern("stat"),1,Archive_path(self));
1579
+ }
1580
+
1581
+ /*
1582
+ * call-seq:
1583
+ * archive.inspect -> String
1584
+ *
1585
+ * Human-readable description.
1586
+ * ===Return value
1587
+ * String
1588
+ */
1589
+
1590
+ VALUE Archive_inspect(VALUE self)
1591
+ {
1592
+ VALUE array[3];
1593
+ switch(_self->type){
1594
+ case archive_path:
1595
+ array[0]=rb_str_new2("#<%s:%s>");
1596
+ array[1]=rb_class_of(self);
1597
+ array[2]=Archive_path(self);
1598
+ break;
1599
+ case archive_fd:
1600
+ array[0]=rb_str_new2("#<%s:%d>");
1601
+ array[1]=rb_class_of(self);
1602
+ array[2]=INT2NUM(_self->fd);
1603
+ break;
1604
+ case archive_buffer:
1605
+ break;
1606
+ case archive_ruby:
1607
+ array[0]=rb_str_new2("#<%s:%s>");
1608
+ array[1]=rb_class_of(self);
1609
+ array[2]=_self->ruby;
1610
+ break;
1611
+ }
1612
+ return rb_f_sprintf(3,array);
1613
+ }
1614
+
1615
+ /*
1616
+ * Document-class: Archive::Error
1617
+ * This is the superclass of all errors specific to this library.
1618
+ */
1619
+
1620
+ /*
1621
+ * Document-class: Archive::Error::Compression
1622
+ * This exception is thrown if you try to use an unknown compression format.
1623
+ */
1624
+
1625
+ /*
1626
+ * Document-class: Archive::Error::Format
1627
+ * This exception is thrown if you try to use an unknown archive format or libarchive doesn't
1628
+ * have write support for the format you wanted to write.
1629
+ */
1630
+
1631
+ /*
1632
+ * Document-class: Archive
1633
+ *
1634
+ * This class represents an archive file. The file may or may not exist,
1635
+ * depending on wheather you want to create a new archive or read from
1636
+ * an existing one. When instanciating this class, libarchive-ruby will
1637
+ * automatically detect the correct file format for you using libarchive's
1638
+ * own detection mechanism if the archive file is already present, otherwise
1639
+ * by looking at the archive file's file extension.
1640
+ */
1641
+ /*
1642
+ * Document-const: EXTRACT_TIME
1643
+ *
1644
+ * extract the atime and mtime
1645
+ */
1646
+ /*
1647
+ * Document-const: EXTRACT_PERM
1648
+ *
1649
+ * extract the permission
1650
+ */
1651
+ /*
1652
+ * Document-const: EXTRACT_OWNER
1653
+ *
1654
+ * extract the owner
1655
+ */
1656
+
1657
+ /*
1658
+ * Document-const: EXTRACT_ACL
1659
+ *
1660
+ * extract the access control list
1661
+ */
1662
+ /*
1663
+ * Document-const: EXTRACT_FFLAGS
1664
+ *
1665
+ * extract the fflags
1666
+ */
1667
+ /*
1668
+ * Document-const: EXTRACT_XATTR
1669
+ *
1670
+ * extract the extended information
1671
+ */
1672
+ extern "C" void Init_archive(void){
1673
+ rb_cArchive = rb_define_class("Archive",rb_cObject);
1674
+ rb_define_alloc_func(rb_cArchive,Archive_alloc);
1675
+ rb_define_method(rb_cArchive,"initialize",RUBY_METHOD_FUNC(Archive_initialize),-1);
1676
+ rb_define_private_method(rb_cArchive,"initialize_copy",RUBY_METHOD_FUNC(Archive_initialize_copy),1);
1677
+ rb_define_method(rb_cArchive,"path",RUBY_METHOD_FUNC(Archive_path),0);
1678
+
1679
+ rb_define_method(rb_cArchive,"each",RUBY_METHOD_FUNC(Archive_each),0);
1680
+ rb_define_method(rb_cArchive,"each_entry",RUBY_METHOD_FUNC(Archive_each_entry),0);
1681
+ rb_define_method(rb_cArchive,"each_data",RUBY_METHOD_FUNC(Archive_each_data),0);
1682
+
1683
+ rb_define_method(rb_cArchive,"each_filter",RUBY_METHOD_FUNC(Archive_each_filter),0);
1684
+
1685
+ rb_define_method(rb_cArchive,"map!",RUBY_METHOD_FUNC(Archive_map_self),0);
1686
+ rb_define_alias(rb_cArchive,"collect!","map!");
1687
+ rb_define_method(rb_cArchive,"[]",RUBY_METHOD_FUNC(Archive_get),1);
1688
+
1689
+ rb_define_method(rb_cArchive,"to_hash",RUBY_METHOD_FUNC(Archive_to_hash),0);
1690
+
1691
+ rb_define_method(rb_cArchive,"extract",RUBY_METHOD_FUNC(Archive_extract),-1);
1692
+ rb_define_method(rb_cArchive,"extract_if",RUBY_METHOD_FUNC(Archive_extract_if),-1);
1693
+
1694
+ rb_define_method(rb_cArchive,"delete",RUBY_METHOD_FUNC(Archive_delete),1);
1695
+ rb_define_method(rb_cArchive,"delete_if",RUBY_METHOD_FUNC(Archive_delete_if),0);
1696
+ rb_define_method(rb_cArchive,"clear",RUBY_METHOD_FUNC(Archive_clear),0);
1697
+
1698
+ //rb_define_method(rb_cArchive,"move_to",RUBY_METHOD_FUNC(Archive_move_to),1);
1699
+
1700
+ rb_define_method(rb_cArchive,"add",RUBY_METHOD_FUNC(Archive_add),-1);
1701
+ rb_define_method(rb_cArchive,"<<",RUBY_METHOD_FUNC(Archive_add_shift),1);
1702
+
1703
+ rb_define_method(rb_cArchive,"inspect",RUBY_METHOD_FUNC(Archive_inspect),0);
1704
+
1705
+ rb_define_method(rb_cArchive,"format",RUBY_METHOD_FUNC(Archive_format),0);
1706
+ //rb_define_method(rb_cArchive,"compression",RUBY_METHOD_FUNC(Archive_compression),0);
1707
+ rb_define_method(rb_cArchive,"format_name",RUBY_METHOD_FUNC(Archive_format_name),0);
1708
+ //rb_define_method(rb_cArchive,"compression_name",RUBY_METHOD_FUNC(Archive_compression_name),0);
1709
+
1710
+ rb_define_method(rb_cArchive,"unlink",RUBY_METHOD_FUNC(Archive_unlink),0);
1711
+ rb_define_method(rb_cArchive,"exist?",RUBY_METHOD_FUNC(Archive_exist),0);
1712
+ rb_define_method(rb_cArchive,"mtime",RUBY_METHOD_FUNC(Archive_mtime),0);
1713
+ rb_define_method(rb_cArchive,"atime",RUBY_METHOD_FUNC(Archive_atime),0);
1714
+ rb_define_method(rb_cArchive,"ctime",RUBY_METHOD_FUNC(Archive_ctime),0);
1715
+ rb_define_method(rb_cArchive,"stat",RUBY_METHOD_FUNC(Archive_stat),0);
1716
+
1717
+ rb_include_module(rb_cArchive,rb_mEnumerable);
1718
+ //rb_define_method(rb_cArchive,"size",RUBY_METHOD_FUNC(Archive_size),0);
1719
+
1720
+ Init_archive_entry(rb_cArchive);
1721
+
1722
+ rb_define_const(rb_cArchive,"EXTRACT_OWNER",INT2NUM(ARCHIVE_EXTRACT_OWNER));
1723
+ rb_define_const(rb_cArchive,"EXTRACT_PERM",INT2NUM(ARCHIVE_EXTRACT_PERM));
1724
+ rb_define_const(rb_cArchive,"EXTRACT_TIME",INT2NUM(ARCHIVE_EXTRACT_TIME));
1725
+ rb_define_const(rb_cArchive,"EXTRACT_NO_OVERWRITE",INT2NUM(ARCHIVE_EXTRACT_NO_OVERWRITE));
1726
+ rb_define_const(rb_cArchive,"EXTRACT_UNLINK",INT2NUM(ARCHIVE_EXTRACT_UNLINK));
1727
+ rb_define_const(rb_cArchive,"EXTRACT_ACL",INT2NUM(ARCHIVE_EXTRACT_ACL));
1728
+ rb_define_const(rb_cArchive,"EXTRACT_FFLAGS",INT2NUM(ARCHIVE_EXTRACT_FFLAGS));
1729
+ rb_define_const(rb_cArchive,"EXTRACT_XATTR",INT2NUM(ARCHIVE_EXTRACT_XATTR));
1730
+ rb_define_const(rb_cArchive,"EXTRACT_SECURE_SYMLINKS",INT2NUM(ARCHIVE_EXTRACT_SECURE_SYMLINKS));
1731
+ rb_define_const(rb_cArchive,"EXTRACT_SECURE_NODOTDOT",INT2NUM(ARCHIVE_EXTRACT_SECURE_NODOTDOT));
1732
+ rb_define_const(rb_cArchive,"EXTRACT_NO_AUTODIR",INT2NUM(ARCHIVE_EXTRACT_NO_AUTODIR));
1733
+ rb_define_const(rb_cArchive,"EXTRACT_NO_OVERWRITE_NEWER",INT2NUM(ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER));
1734
+ rb_define_const(rb_cArchive,"EXTRACT_SPARSE",INT2NUM(ARCHIVE_EXTRACT_SPARSE));
1735
+ rb_define_const(rb_cArchive,"EXTRACT_MAC_METADATA",INT2NUM(ARCHIVE_EXTRACT_MAC_METADATA));
1736
+
1737
+
1738
+ rb_eArchiveError = rb_define_class_under(rb_cArchive,"Error",rb_eStandardError);
1739
+ rb_eArchiveErrorFormat = rb_define_class_under(rb_eArchiveError,"Format",rb_eArchiveError);
1740
+ rb_eArchiveErrorCompression = rb_define_class_under(rb_eArchiveError,"Compression",rb_eArchiveError);
1741
+
1742
+
1743
+ SymToFormat[rb_intern("tar")]=ARCHIVE_FORMAT_TAR_GNUTAR;
1744
+ SymToFormat[rb_intern("pax")]=ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE;
1745
+ SymToFormat[rb_intern("zip")]=ARCHIVE_FORMAT_ZIP;
1746
+ SymToFormat[rb_intern("ar")]=ARCHIVE_FORMAT_AR_GNU;
1747
+ SymToFormat[rb_intern("xar")]=ARCHIVE_FORMAT_XAR;
1748
+ SymToFormat[rb_intern("lha")]=ARCHIVE_FORMAT_LHA;
1749
+ SymToFormat[rb_intern("cab")]=ARCHIVE_FORMAT_CAB;
1750
+ SymToFormat[rb_intern("rar")]=ARCHIVE_FORMAT_RAR;
1751
+ SymToFormat[rb_intern("7zip")]=ARCHIVE_FORMAT_7ZIP;
1752
+
1753
+
1754
+ SymToFilter[rb_intern("gzip")]=ARCHIVE_FILTER_GZIP;
1755
+ SymToFilter[rb_intern("bzip2")]=ARCHIVE_FILTER_BZIP2;
1756
+ SymToFilter[rb_intern("compress")]=ARCHIVE_FILTER_BZIP2;
1757
+ SymToFilter[rb_intern("lzma")]=ARCHIVE_FILTER_LZMA;
1758
+ SymToFilter[rb_intern("xz")]=ARCHIVE_FILTER_XZ;
1759
+ SymToFilter[rb_intern("uu")]=ARCHIVE_FILTER_UU;
1760
+ SymToFilter[rb_intern("rpm")]=ARCHIVE_FILTER_RPM;
1761
+ SymToFilter[rb_intern("lzip")]=ARCHIVE_FILTER_LZIP;
1762
+
1763
+ #ifdef ARCHIVE_FILTER_LZOP
1764
+ SymToFilter[rb_intern("lzop")]=ARCHIVE_FILTER_LZOP;
1765
+ #endif
1766
+ #ifdef ARCHIVE_FILTER_GRZIP
1767
+ SymToFilter[rb_intern("grzip")]=ARCHIVE_FILTER_GRZIP;
1768
+ #endif
1769
+
1770
+
1771
+ FileExtType::mapped_type pair;
1772
+
1773
+ pair = std::make_pair(ARCHIVE_FORMAT_TAR,ARCHIVE_FILTER_GZIP);
1774
+ fileExt[".tar.gz"]=pair;
1775
+ fileExt[".tgz"]=pair;
1776
+
1777
+ pair = std::make_pair(ARCHIVE_FORMAT_TAR,ARCHIVE_FILTER_BZIP2);
1778
+ fileExt[".tar.bz2"]=pair;
1779
+ fileExt[".tbz"]=pair;
1780
+ fileExt[".tb2"]=pair;
1781
+
1782
+ pair = std::make_pair(ARCHIVE_FORMAT_TAR,ARCHIVE_FILTER_XZ);
1783
+ fileExt[".tar.xz"]=pair;
1784
+ fileExt[".txz"]=pair;
1785
+
1786
+ fileExt[".tar.lzma"]=std::make_pair(ARCHIVE_FORMAT_TAR,ARCHIVE_FILTER_LZMA);
1787
+
1788
+ fileExt[".tar"]=std::make_pair(ARCHIVE_FORMAT_TAR,ARCHIVE_FILTER_NONE);
1789
+
1790
+
1791
+ DataVector data;
1792
+ // //RubyArchive::read_data_from_path2(rb_reg_new(".",8,0),Qnil,data);
1793
+ RubyArchive::read_data_from_path2(rb_str_new2("*/*.cpp"),Qnil,data);
1794
+ rb_warn("%lu",data.size());
1795
+ ////
1796
+ for(size_t i = 0; i < data.size(); ++i)
1797
+ {
1798
+ rb_warn("%s",archive_entry_pathname(data[i].first));
1799
+ rb_warn("%lu",data[i].second.size());
1800
+ }
1801
+ }