File Coverage

lib/Archive/Ar/Libarchive.xs
Criterion Covered Total %
statement 341 403 84.6
branch 160 402 39.8
condition n/a
subroutine n/a
pod n/a
total 501 805 62.2


line stmt bran cond sub pod time code
1             #include "EXTERN.h"
2             #include "perl.h"
3             #include "XSUB.h"
4             #include "ppport.h"
5              
6             #include "perl_math_int64_types.h"
7             #define MATH_INT64_NATIVE_IF_AVAILABLE
8             #include "perl_math_int64.h"
9              
10             #include
11             #include
12              
13             #if ARCHIVE_VERSION_NUMBER < 3000000
14             # if !defined(__LA_INT64_T)
15             # if defined(_WIN32) && !defined(__CYGWIN__)
16             # define __LA_INT64_T __int64
17             # else
18             # if defined(_SCO_DS)
19             # define __LA_INT64_T long long
20             # else
21             # define __LA_INT64_T int64_t
22             # endif
23             # endif
24             # endif
25             #endif
26              
27             #define ARCHIVE_AR_UNDEF 0
28             #define ARCHIVE_AR_COMMON 1
29             #define ARCHIVE_AR_BSD 2
30             #define ARCHIVE_AR_GNU 3
31              
32             #if ARCHIVE_VERSION_NUMBER < 3000000
33             #define archive_write_free(archive) archive_write_finish(archive)
34             #endif
35              
36             #define _error(ar, message) { \
37             if(ar->opt_warn) \
38             warn("%s", message); \
39             if(ar->error != NULL) \
40             SvREFCNT_dec(ar->error); \
41             if(ar->longmess != NULL) \
42             SvREFCNT_dec(ar->longmess); \
43             ar->error = ar->longmess = SvREFCNT_inc(newSVpv(message,0)); \
44             }
45              
46             struct ar_entry;
47              
48             struct ar {
49             struct ar_entry *first;
50             SV *callback;
51              
52             unsigned int opt_warn : 2;
53             unsigned int opt_chmod : 1;
54             unsigned int opt_same_perms : 1;
55             unsigned int opt_chown : 1;
56             unsigned int opt_type : 2;
57              
58             SV *error;
59             SV *longmess;
60             SV *opt_symbols;
61             };
62              
63             struct ar_entry {
64             struct archive_entry *entry;
65             const char *data;
66             size_t data_size;
67             struct ar_entry *next;
68              
69             unsigned int is_symbol_table : 1;
70             };
71              
72 2           static int ar_disk_options(struct ar *ar)
73             {
74 2           int flags = ARCHIVE_EXTRACT_TIME;
75 2 50         if(ar->opt_chown)
76 2           flags |= ARCHIVE_EXTRACT_OWNER;
77 2 50         if(ar->opt_same_perms)
78 2           flags |= ARCHIVE_EXTRACT_PERM;
79 2           return flags;
80             }
81              
82             static void
83 80           ar_free_entry(struct ar_entry *entry)
84             {
85 80           archive_entry_free(entry->entry);
86 80 50         if(entry->data != NULL)
87 80           Safefree(entry->data);
88 80           }
89              
90             static void
91 110           ar_reset(struct ar *ar)
92             {
93             struct ar_entry *entry, *old;
94              
95 110 100         if(ar->error != NULL)
96 4           SvREFCNT_dec(ar->error);
97 110 100         if(ar->longmess != NULL)
98 4           SvREFCNT_dec(ar->longmess);
99              
100 110           ar->error = NULL;
101 110           ar->longmess = NULL;
102              
103 110           entry = ar->first;
104 186 100         while(entry != NULL)
105             {
106 76           ar_free_entry(entry);
107 76           old = entry;
108 76           entry = entry->next;
109 76           Safefree(old);
110             }
111              
112 110           ar->first = NULL;
113              
114 110           ar->opt_type = ARCHIVE_AR_UNDEF;
115 110           }
116              
117             static struct ar_entry*
118 50           ar_find_by_name(struct ar *ar, const char *filename)
119             {
120             struct ar_entry *entry;
121              
122 50           entry = ar->first;
123              
124 90 100         while(entry != NULL)
125             {
126 87 100         if(!strcmp(archive_entry_pathname(entry->entry), filename))
127 47           return entry;
128 40           entry = entry->next;
129             }
130              
131 3           return NULL;
132             }
133              
134             static int
135 3           ar_entry_extract(struct ar *ar, struct ar_entry *entry, struct archive *disk)
136             {
137             int r;
138              
139 3           r = archive_write_header(disk, entry->entry);
140 3 50         if(r != ARCHIVE_OK)
141             {
142 0 0         _error(ar,archive_error_string(disk));
    0          
    0          
143             }
144 3 50         else if(archive_entry_size(entry->entry) > 0)
145             {
146 3           r = archive_write_data_block(disk, entry->data, entry->data_size, 0);
147 3 50         if(r != ARCHIVE_OK)
148 0 0         _error(ar, archive_error_string(disk));
    0          
    0          
149 3 50         if(r < ARCHIVE_WARN)
150 0           return 0;
151             }
152              
153 3           r = archive_write_finish_entry(disk);
154 3 50         if(r != ARCHIVE_OK)
155 0 0         _error(ar, archive_error_string(disk));
    0          
    0          
156              
157 3 50         if(r < ARCHIVE_WARN)
158 0           return 0;
159             else
160 3           return 1;
161             }
162              
163             static __LA_SSIZE_T
164 30           ar_read_callback(struct archive *archive, void *cd, const void **buffer)
165             {
166 30           struct ar *ar = (struct ar *)cd;
167             int count;
168             __LA_INT64_T status;
169             STRLEN len;
170             SV *sv_buffer;
171              
172 30           dSP;
173 30           ENTER;
174 30           SAVETMPS;
175 30 50         PUSHMARK(SP);
176 30 50         XPUSHs(sv_2mortal(newSViv(PTR2IV((void*)archive))));
177 30           PUTBACK;
178              
179 30           count = call_sv(ar->callback, G_ARRAY);
180              
181 30           SPAGAIN;
182              
183 30           sv_buffer = SvRV(POPs);
184 30           status = SvI64(POPs);
185 30 50         if(status == ARCHIVE_OK)
186             {
187 30 50         *buffer = (void*) SvPV(sv_buffer, len);
188             }
189              
190 30           PUTBACK;
191 30 50         FREETMPS;
192 30           LEAVE;
193              
194 30 50         if(status == ARCHIVE_OK)
195 30 50         return len == 1 ? 0 : len;
196             else
197 30           return status;
198             }
199              
200             static __LA_INT64_T
201 9           ar_write_callback(struct archive *archive, void *cd, const void *buffer, size_t length)
202             {
203 9           struct ar *ar = (struct ar *)cd;
204             int count;
205             __LA_INT64_T status;
206              
207 9           dSP;
208 9           ENTER;
209 9           SAVETMPS;
210 9 50         PUSHMARK(SP);
211 9 50         XPUSHs(sv_2mortal(newSViv(PTR2IV((void*)archive))));
212 9 50         XPUSHs(sv_2mortal(newSVpvn(buffer, length)));
213 9           PUTBACK;
214              
215 9           call_sv(ar->callback, G_SCALAR);
216              
217 9           SPAGAIN;
218              
219 9           status = SvI64(POPs);
220              
221 9           PUTBACK;
222 9 50         FREETMPS;
223 9           LEAVE;
224              
225 9           return status;
226             }
227              
228             static int
229 24           ar_close_callback(struct archive *archive, void *client_data)
230             {
231 24           return ARCHIVE_OK;
232             }
233              
234             static __LA_INT64_T
235 12           ar_write_archive(struct archive *archive, struct ar *ar)
236             {
237             int r;
238             struct ar_entry *entry;
239             int count;
240              
241 12 100         if(ar->opt_type == ARCHIVE_AR_GNU)
242             {
243 3           int size=0;
244              
245             /* calculate the size of the string table */
246 10 100         for(entry = ar->first; entry != NULL; entry = entry->next)
247             {
248 7 100         if(entry->is_symbol_table)
249 1           continue;
250 6           int len = strlen(archive_entry_pathname(entry->entry));
251 6 100         if(len > 15)
252 3           size += len + 2;
253             }
254              
255             /* if string table size is zero then we don't need *
256             * one. Otherwise create the string table since *
257             * libarchive does not do that for us. */
258 3 50         if(size > 0)
259 3           {
260 3           struct archive_entry *table = archive_entry_new();
261 3           archive_entry_set_pathname(table, "//");
262 3           archive_entry_set_size(table, size);
263 3           char buffer[size];
264 3           int offset = 0;
265              
266             /* write the string table header */
267 3           r = archive_write_header(archive, table);
268 3 50         if(r < ARCHIVE_OK)
269             {
270 0 0         _error(ar, archive_error_string(archive));
    0          
    0          
271 0 0         if(r != ARCHIVE_WARN)
272             {
273 0           archive_entry_free(table);
274 0           return 0;
275             }
276             }
277              
278             /* construct the data section of the string table */
279 10 100         for(entry = ar->first; entry != NULL; entry = entry->next)
280             {
281             const char *name;
282             int len;
283 7           name = archive_entry_pathname(entry->entry);
284 7           len = strlen(name);
285              
286 7 100         if(len > 15)
287             {
288 3           memcpy(&buffer[offset], name, len);
289 3           memcpy(&buffer[offset+len], "/\n", 2);
290 3           offset += len+2;
291             }
292             }
293              
294             /* write the string table to the archive */
295 3           r = archive_write_data(archive, buffer, size);
296 3           archive_entry_free(table);
297              
298 3 50         if(r < ARCHIVE_OK)
299             {
300 0 0         _error(ar, archive_error_string(archive));
    0          
    0          
301 0 0         if(r != ARCHIVE_WARN)
302 3 50         return 0;
303             }
304             }
305             }
306              
307             /* write each entry out one at a time */
308 35 100         for(entry = ar->first; entry != NULL; entry = entry->next)
309             {
310 23           struct archive_entry *short_entry = NULL;
311              
312 23 100         if(entry->is_symbol_table)
313             {
314 1           short_entry = archive_entry_clone(entry->entry);
315 1           archive_entry_copy_pathname(short_entry, "/");
316             }
317              
318 23 100         if(ar->opt_type == ARCHIVE_AR_COMMON)
319             {
320 6           const char *name = archive_entry_pathname(entry->entry);
321 6           int len = strlen(name);
322 6 100         if(len > 15)
323             {
324             char buffer[16];
325 1           short_entry = archive_entry_clone(entry->entry);
326 1           strncpy(buffer, name, 15);
327 1           buffer[15] = '\0';
328 1           archive_entry_copy_pathname(short_entry, buffer);
329             }
330             }
331              
332 23 100         r = archive_write_header(archive, short_entry != NULL ? short_entry : entry->entry);
333 23 50         if(r < ARCHIVE_OK)
334             {
335 0 0         _error(ar,archive_error_string(archive));
    0          
    0          
336 0 0         if(r != ARCHIVE_WARN)
337 0           return 0;
338             }
339 23           r = archive_write_data(archive, entry->data, entry->data_size);
340 23 50         if(r < ARCHIVE_OK)
341             {
342 0 0         _error(ar,archive_error_string(archive));
    0          
    0          
343 0 0         if(r != ARCHIVE_WARN)
344 0           return 0;
345             }
346              
347 23 100         if(short_entry != NULL)
348 2           archive_entry_free(short_entry);
349             }
350              
351             #if ARCHIVE_VERSION_NUMBER < 3000000
352             return archive_position_uncompressed(archive);
353             #else
354 12           return archive_filter_bytes(archive, 0);
355             #endif
356             }
357              
358             static __LA_INT64_T
359 25           ar_read_archive(struct archive *archive, struct ar *ar)
360             {
361             struct archive_entry *entry;
362 25           struct ar_entry *e=NULL, *next;
363             int r;
364             size_t size;
365             off_t offset;
366             const char *name;
367             int is_symbol_table;
368              
369 25           ar->opt_type = ARCHIVE_AR_COMMON;
370              
371             while(1)
372             {
373             #if HAS_has_archive_read_next_header2
374             entry = archive_entry_new();
375             r = archive_read_next_header2(archive, entry);
376             #else
377             struct archive_entry *tmp;
378 88           r = archive_read_next_header(archive, &tmp);
379 88           entry = archive_entry_clone(tmp);
380             #endif
381 88           is_symbol_table = 0;
382              
383              
384 88 100         if(r == ARCHIVE_OK || r == ARCHIVE_WARN)
    50          
385             {
386 63           name = archive_entry_pathname(entry);
387             /* Filename of // means it has a GNU style string *
388             * table */
389 63 100         if(!strcmp(name, "//"))
390             {
391 4           ar->opt_type = ARCHIVE_AR_GNU;
392 5           continue;
393             }
394              
395 59 100         if(!strcmp(name, "/"))
396             {
397 2 100         if(ar->opt_symbols == NULL)
398 1           continue;
399 1 50         archive_entry_copy_pathname(entry, SvPV_nolen(ar->opt_symbols));
400 1           is_symbol_table = 1;
401             }
402              
403             /* Otherwise rely on libarchive to determine *
404             * archive type */
405 58 100         if(ar->opt_type == ARCHIVE_AR_COMMON)
406             {
407 49 100         switch(archive_format(archive))
408             {
409             case ARCHIVE_FORMAT_AR_BSD:
410 1           ar->opt_type = ARCHIVE_AR_BSD;
411 1           break;
412             }
413             }
414 58 50         if(r == ARCHIVE_WARN)
415             {
416 0 0         _error(ar,archive_error_string(archive));
    0          
    0          
417             }
418             }
419 25 50         else if(r == ARCHIVE_EOF)
420             {
421             #if ARCHIVE_VERSION_NUMBER < 3000000
422             return archive_position_uncompressed(archive);
423             #else
424 25           return archive_filter_bytes(archive, 0);
425             #endif
426             }
427             else
428             {
429 0           archive_entry_free(entry);
430 0 0         _error(ar,archive_error_string(archive));
    0          
    0          
431 0           ar_reset(ar);
432 0           return 0;
433             }
434              
435 58           Newx(next, 1, struct ar_entry);
436 58           next->data_size = archive_entry_size(entry);
437 58           Newx(next->data, next->data_size, char);
438              
439 58           r = archive_read_data(archive, (void*)next->data, next->data_size);
440 58           next->is_symbol_table = is_symbol_table;
441              
442 58 50         if(r == ARCHIVE_WARN)
443             {
444 0 0         _error(ar,archive_error_string(archive));
    0          
    0          
445             }
446 58 50         else if(r < ARCHIVE_OK && r != ARCHIVE_EOF)
    0          
447             {
448 0           archive_entry_free(entry);
449 0 0         _error(ar,archive_error_string(archive));
    0          
    0          
450 0           Safefree(next->data);
451 0           Safefree(next);
452 0           return 0;
453             }
454              
455 58           next->entry = entry;
456 58           next->next = NULL;
457              
458 58 100         if(ar->first == NULL)
459 25           ar->first = next;
460             else
461 33           e->next = next;
462 58           e = next;
463 63           }
464             }
465              
466             MODULE = Archive::Ar::Libarchive PACKAGE = Archive::Ar::Libarchive
467              
468             BOOT:
469 25 50         PERL_MATH_INT64_LOAD_OR_CROAK;
470              
471             struct ar*
472             _new()
473             CODE:
474             struct ar *self;
475 42           Newx(self, 1, struct ar);
476 42           self->first = NULL;
477 42           self->callback = NULL;
478 42           self->error = NULL;
479 42           self->longmess = NULL;
480 42           self->opt_symbols = NULL;
481 42           self->opt_warn = 0;
482 42           self->opt_chmod = 1; /* ignored */
483 42           self->opt_same_perms = 1; /* different: pp version this is true for root only */
484 42           self->opt_chown = 1;
485 42           ar_reset(self);
486 42           RETVAL = self;
487             OUTPUT:
488             RETVAL
489              
490             int
491             set_opt(self, name, value)
492             struct ar *self
493             const char *name
494             SV *value
495             CODE:
496 6 100         if(!strcmp(name, "warn"))
497 3 50         RETVAL = self->opt_warn = SvIV(value);
498 3 50         else if(!strcmp(name, "chmod"))
499 0 0         RETVAL = self->opt_chmod = SvIV(value);
500 3 50         else if(!strcmp(name, "same_perms"))
501 0 0         RETVAL = self->opt_same_perms = SvIV(value);
502 3 50         else if(!strcmp(name, "chown"))
503 0 0         RETVAL = self->opt_chown = SvIV(value);
504 3 100         else if(!strcmp(name, "type"))
505 2 50         RETVAL = self->opt_type = SvIV(value);
506 1 50         else if(!strcmp(name, "symbols"))
507 1           self->opt_symbols = SvREFCNT_inc(value); /* TODO: make set_opt return void; maybe */
508             else
509 0           warn("unknown or unsupported option %s", name);
510             OUTPUT:
511             RETVAL
512              
513             int
514             get_opt(self, name)
515             struct ar *self
516             const char *name
517             CODE:
518 8 100         if(!strcmp(name, "warn"))
519 7           RETVAL = self->opt_warn;
520 1 50         else if(!strcmp(name, "chmod"))
521 0           RETVAL = self->opt_chmod;
522 1 50         else if(!strcmp(name, "same_perms"))
523 0           RETVAL = self->opt_same_perms;
524 1 50         else if(!strcmp(name, "chown"))
525 0           RETVAL = self->opt_chown;
526 1 50         else if(!strcmp(name, "type"))
527             {
528 1 50         if(self->opt_type == ARCHIVE_AR_UNDEF)
529 1           XSRETURN_EMPTY;
530             else
531 0           RETVAL = self->opt_type;
532             }
533             else
534 0           warn("unknown or unsupported option %s", name);
535             OUTPUT:
536             RETVAL
537              
538             void
539             _set_error(self, message, longmess)
540             struct ar *self
541             SV *message
542             SV *longmess
543             CODE:
544 4 50         if(self->error != NULL)
545 0           SvREFCNT_dec(self->error);
546 4 50         if(self->longmess != NULL)
547 0           SvREFCNT_dec(self->longmess);
548 4           self->error = SvREFCNT_inc(message);
549 4           self->longmess = SvREFCNT_inc(longmess);
550              
551             SV *
552             error(self, ...)
553             struct ar *self
554             CODE:
555 5 100         if(self->error == NULL)
556 1           XSRETURN_EMPTY;
557 4 100         if(items >= 2 && SvTRUE(ST(1)))
    50          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
558 2           RETVAL = SvREFCNT_inc(self->longmess);
559             else
560 2           RETVAL = SvREFCNT_inc(self->error);
561             OUTPUT:
562             RETVAL
563              
564             int
565             _read_from_filename(self, filename)
566             struct ar *self
567             const char *filename
568             CODE:
569             struct archive *archive;
570             int r;
571              
572 10           ar_reset(self);
573 10           archive = archive_read_new();
574 10           archive_read_support_format_ar(archive);
575              
576 10           r = archive_read_open_filename(archive, filename, 1024);
577 10 50         if(r == ARCHIVE_OK || r == ARCHIVE_WARN)
    0          
578             {
579 10 50         if(r == ARCHIVE_WARN)
580 0 0         _error(self, archive_error_string(archive));
    0          
    0          
581 10           RETVAL = ar_read_archive(archive, self);
582             }
583             else
584             {
585 0 0         _error(self,archive_error_string(archive));
    0          
    0          
586 0           RETVAL = 0;
587             }
588             #if ARCHIVE_VERSION_NUMBER < 3000000
589             archive_read_finish(archive);
590             #else
591 10           archive_read_free(archive);
592             #endif
593             OUTPUT:
594             RETVAL
595              
596             int
597             _read_from_callback(self, callback)
598             struct ar *self
599             SV *callback
600             CODE:
601             struct archive *archive;
602             int r;
603              
604 15           ar_reset(self);
605 15           archive = archive_read_new();
606 15           archive_read_support_format_ar(archive);
607              
608 15           self->callback = SvREFCNT_inc(callback);
609 15           r = archive_read_open(archive, (void*)self, NULL, ar_read_callback, ar_close_callback);
610              
611 15 50         if(r == ARCHIVE_OK || r == ARCHIVE_WARN)
    0          
612             {
613 15 50         if(r == ARCHIVE_WARN)
614 0 0         _error(self,archive_error_string(archive));
    0          
    0          
615 15           RETVAL = ar_read_archive(archive, self);
616             }
617             else
618             {
619 0 0         _error(self,archive_error_string(archive));
    0          
    0          
620 0           RETVAL = 0;
621             }
622             #if ARCHIVE_VERSION_NUMBER < 3000000
623             archive_read_finish(archive);
624             #else
625 15           archive_read_free(archive);
626             #endif
627 15           SvREFCNT_dec(callback);
628 15           self->callback = NULL;
629             OUTPUT:
630             RETVAL
631              
632             int
633             _write_to_filename(self, filename)
634             struct ar *self
635             const char *filename
636             CODE:
637             struct archive *archive;
638             int r;
639              
640 3           archive = archive_write_new();
641 3 100         if(self->opt_type == ARCHIVE_AR_BSD)
642 1           r = archive_write_set_format_ar_bsd(archive);
643             else
644 2           r = archive_write_set_format_ar_svr4(archive);
645 3 50         if(r != ARCHIVE_OK)
646 0 0         _error(self,archive_error_string(archive));
    0          
    0          
647 3           r = archive_write_open_filename(archive, filename);
648 3 50         if(r != ARCHIVE_OK)
649 0 0         _error(self,archive_error_string(archive));
    0          
    0          
650 3 50         if(r == ARCHIVE_OK || r == ARCHIVE_WARN)
    0          
651 3           RETVAL = ar_write_archive(archive, self);
652             else
653 0           RETVAL = 0;
654 3           archive_write_free(archive);
655             OUTPUT:
656             RETVAL
657              
658             int
659             _write_to_callback(self, callback)
660             struct ar *self
661             SV *callback
662             CODE:
663             struct archive *archive;
664             int r;
665              
666 9           self->callback = SvREFCNT_inc(callback);
667              
668 9           archive = archive_write_new();
669 9 100         if(self->opt_type == ARCHIVE_AR_BSD)
670 1           r = archive_write_set_format_ar_bsd(archive);
671             else
672 8           r = archive_write_set_format_ar_svr4(archive);
673 9 50         if(r != ARCHIVE_OK)
674 0 0         _error(self,archive_error_string(archive));
    0          
    0          
675 9           archive_write_set_bytes_in_last_block(archive, 1);
676 9           r = archive_write_open(archive, (void*)self, NULL, ar_write_callback, ar_close_callback);
677 9 50         if(r != ARCHIVE_OK)
678 0 0         _error(self,archive_error_string(archive));
    0          
    0          
679 9 50         if(r == ARCHIVE_OK || r == ARCHIVE_WARN)
    0          
680 9           RETVAL = ar_write_archive(archive, self);
681             else
682 0           RETVAL = 0;
683 9           archive_write_free(archive);
684 9           SvREFCNT_dec(callback);
685 9           self->callback = NULL;
686             OUTPUT:
687             RETVAL
688              
689             int
690             _remove(self,pathname)
691             struct ar *self
692             const char *pathname
693             CODE:
694             struct ar_entry **entry;
695 4           entry = &(self->first);
696              
697 4           RETVAL = 0;
698              
699             while(1)
700             {
701 6 100         if(!strcmp(archive_entry_pathname((*entry)->entry),pathname))
702             {
703 4           ar_free_entry(*entry);
704 4           *entry = (*entry)->next;
705 4           RETVAL = 1;
706 4           break;
707             }
708              
709 2 50         if((*entry)->next == NULL)
710 0           break;
711              
712 2           entry = &((*entry)->next);
713 2           }
714              
715             OUTPUT:
716             RETVAL
717              
718             void
719             _add_data(self,filename,data,uid,gid,date,mode)
720             struct ar *self
721             const char *filename
722             SV *data
723             __LA_INT64_T uid
724             __LA_INT64_T gid
725             time_t date
726             int mode
727             CODE:
728             struct ar_entry **entry;
729             char *buffer;
730              
731 22           entry = &(self->first);
732              
733 38 100         while(*entry != NULL)
734             {
735 16           entry = &((*entry)->next);
736             }
737              
738 22           Newx((*entry), 1, struct ar_entry);
739              
740 22           (*entry)->entry = archive_entry_new();
741 22           archive_entry_set_pathname((*entry)->entry, filename);
742 22           archive_entry_set_uid((*entry)->entry, uid);
743 22           archive_entry_set_gid((*entry)->entry, gid);
744 22           archive_entry_set_mtime((*entry)->entry, date, date);
745 22           archive_entry_set_mode((*entry)->entry, mode);
746              
747 22           (*entry)->next = NULL;
748 22           (*entry)->is_symbol_table = 0;
749 22 50         if(self->opt_symbols != NULL && !strcmp(SvPV_nolen(self->opt_symbols), filename))
    0          
    0          
750 0           (*entry)->is_symbol_table = 1;
751              
752 22 50         buffer = SvPV(data, (*entry)->data_size);
753 22           archive_entry_set_size((*entry)->entry, (*entry)->data_size);
754              
755 22           Newx((*entry)->data, (*entry)->data_size, char);
756 22           Copy(buffer, (*entry)->data, (*entry)->data_size, char);
757              
758              
759             SV *
760             _list_files(self)
761             struct ar *self
762             CODE:
763             AV *list;
764             struct ar_entry *entry;
765             const char *pathname;
766              
767 22           list = newAV();
768              
769 73 100         for(entry = self->first; entry != NULL; entry = entry->next)
770             {
771 51           pathname = archive_entry_pathname(entry->entry);
772 51           av_push(list, newSVpv(pathname, strlen(pathname)));
773             }
774              
775 22           RETVAL = newRV_noinc((SV*)list);
776             OUTPUT:
777             RETVAL
778              
779             void
780             DESTROY(self)
781             struct ar *self
782             CODE:
783 42           ar_reset(self);
784 42           Safefree(self);
785              
786             SV *
787             get_content(self, filename)
788             struct ar *self
789             const char *filename
790             CODE:
791             struct ar_entry *entry;
792             HV *hv;
793             int found;
794              
795 33           entry = ar_find_by_name(self, filename);
796              
797 33 100         if(entry != NULL)
798             {
799 31           hv = newHV();
800             #pragma clang diagnostic push
801             #pragma clang diagnostic ignored "-Wunused-value"
802 31           hv_store(hv, "name", 4, newSVpv(filename, strlen(filename)), 0);
803 31           hv_store(hv, "date", 4, newSVi64(archive_entry_mtime(entry->entry)), 0);
804 31           hv_store(hv, "uid", 3, newSVi64(archive_entry_uid(entry->entry)), 0);
805 31           hv_store(hv, "gid", 3, newSVi64(archive_entry_gid(entry->entry)), 0);
806 31           hv_store(hv, "mode", 4, newSViv(archive_entry_mode(entry->entry)), 0);
807 31           hv_store(hv, "size", 4, newSViv(entry->data_size), 0);
808 31           hv_store(hv, "data", 4, newSVpv(entry->data, entry->data_size), 0);
809             #pragma clang diagnostic pop
810 31           RETVAL = newRV_noinc((SV*)hv);
811              
812             }
813             else
814             {
815 2           XSRETURN_EMPTY;
816             }
817             OUTPUT:
818             RETVAL
819              
820             SV *
821             get_data(self, filename)
822             struct ar *self
823             const char *filename
824             CODE:
825             struct ar_entry *entry;
826 6           entry = ar_find_by_name(self, filename);
827 6 50         if(entry == NULL)
828 0           XSRETURN_EMPTY;
829 6           RETVAL = newSVpv(entry->data, entry->data_size);
830             OUTPUT:
831             RETVAL
832              
833              
834             void
835             rename(self, old, new)
836             struct ar *self
837             const char *old
838             const char *new
839             CODE:
840             struct ar_entry *entry;
841 3           entry = ar_find_by_name(self, old);
842 3 50         if(entry != NULL)
843 3           archive_entry_set_pathname(entry->entry, new);
844              
845             int
846             extract(self)
847             struct ar *self
848             CODE:
849             struct ar_entry *entry;
850             struct archive *disk;
851 1           int ok = 1;
852              
853 1           entry = self->first;
854              
855 1           disk = archive_write_disk_new();
856 1           archive_write_disk_set_options(disk, ar_disk_options(self));
857 1           archive_write_disk_set_standard_lookup(disk);
858              
859 3 100         while(entry != NULL)
860             {
861 2 50         if(ar_entry_extract(self, entry, disk) == 0)
862             {
863 0           ok = 0;
864 0           break;
865             }
866 2           entry = entry->next;
867             }
868              
869 1           archive_write_close(disk);
870 1           archive_write_free(disk);
871              
872 1 50         if(ok)
873 1           RETVAL = 1;
874             else
875 0           XSRETURN_EMPTY;
876             OUTPUT:
877             RETVAL
878              
879             int
880             extract_file(self,filename)
881             struct ar *self
882             const char *filename
883             CODE:
884             struct ar_entry *entry;
885             struct archive *disk;
886             int ok;
887              
888 1           entry = ar_find_by_name(self, filename);
889              
890 1 50         if(entry == NULL)
891 0           XSRETURN_EMPTY;
892              
893 1           disk = archive_write_disk_new();
894 1           archive_write_disk_set_options(disk, ar_disk_options(self));
895 1           archive_write_disk_set_standard_lookup(disk);
896              
897 1           ok = ar_entry_extract(self, entry, disk);
898              
899 1           archive_write_close(disk);
900 1           archive_write_free(disk);
901              
902 1 50         if(ok)
903 1           RETVAL = 1;
904             else
905 0           XSRETURN_EMPTY;
906              
907             OUTPUT:
908             RETVAL
909              
910              
911             int
912             type(self)
913             struct ar *self
914             CODE:
915 4           RETVAL = self->opt_type;
916             OUTPUT:
917             RETVAL
918              
919              
920             int
921             contains_file(self, filename)
922             struct ar *self
923             const char *filename
924             CODE:
925 4 100         if(ar_find_by_name(self, filename))
926 3           RETVAL = 1;
927             else
928 1           XSRETURN_EMPTY;
929             OUTPUT:
930             RETVAL
931              
932              
933             void
934             clear(self)
935             struct ar *self
936             CODE:
937 1           ar_reset(self);
938              
939              
940             int
941             _chmod(self, filename, mode)
942             struct ar *self
943             const char *filename
944             int mode
945             CODE:
946             struct ar_entry *entry;
947 1           entry = ar_find_by_name(self, filename);
948 1 50         if(entry != NULL)
949             {
950 1           archive_entry_set_mode(entry->entry, mode);
951 1           RETVAL = 1;
952             }
953             else
954             {
955 0           XSRETURN_EMPTY;
956             }
957             OUTPUT:
958             RETVAL
959              
960              
961             int
962             _chown(self, filename, uid, gid)
963             struct ar *self
964             const char *filename
965             int uid
966             SV *gid
967             CODE:
968             struct ar_entry *entry;
969 2           entry = ar_find_by_name(self, filename);
970 2 50         if(entry != NULL)
971             {
972 2 50         if(uid >= 0)
973 2           archive_entry_set_uid(entry->entry, uid);
974 2 100         if(SvOK(gid) && SvIV(gid) >= 0)
    50          
    50          
    50          
    50          
975             {
976 2 50         archive_entry_set_gid(entry->entry, SvIV(gid));
977             }
978             }
979             else
980             {
981 0           XSRETURN_EMPTY;
982             }
983              
984             const char *
985             _libarchive_version()
986             CODE:
987 0           RETVAL = ARCHIVE_VERSION_STRING;
988             OUTPUT:
989             RETVAL