libarchive-ruby-gvalmon 0.0.1

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/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
+ }