#include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include #include #include "ppport.h" int DEBUG = 0; typedef struct archive* Archive__Peek__Libarchive; struct archive* _open_file(const char * filename) { struct archive *a; int r; a = archive_read_new(); archive_read_support_compression_all(a); archive_read_support_format_all(a); if ((r = archive_read_open_file(a, filename, 10240))) { croak(archive_error_string(a)); } return a; } void _close_file(struct archive* a) { archive_read_close(a); archive_read_finish(a); } static int _copy_data(struct archive *ar, struct archive *aw) { int r; const void *buff; size_t size; off_t offset; for (;;) { r = archive_read_data_block(ar, &buff, &size, &offset); if (r == ARCHIVE_EOF) return (ARCHIVE_OK); if (r != ARCHIVE_OK) return (r); r = archive_write_data_block(aw, buff, size, offset); if (r != ARCHIVE_OK) { warn("archive_write_data_block()", archive_error_string(aw)); return (r); } } } MODULE = Archive::Extract::Libarchive PACKAGE = Archive::Extract::Libarchive void _extract(const char * filename, const char * path) PPCODE: struct archive *a; struct archive *ext; struct archive_entry *entry; SV *path_sv; int r; int flags; a = _open_file(filename); flags = ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS; ext = archive_write_disk_new(); archive_write_disk_set_options(ext, flags); archive_write_disk_set_standard_lookup(ext); for (;;) { r = archive_read_next_header(a, &entry); if (r == ARCHIVE_EOF) break; if (r != ARCHIVE_OK) croak(archive_error_string(a)); if (archive_entry_filetype(entry) == AE_IFREG) { mXPUSHs(newSVpv(archive_entry_pathname(entry), 0)); } path_sv = newSVpv(path, 0); sv_catpvs(path_sv, "/"); sv_catpv(path_sv, archive_entry_pathname(entry)); archive_entry_set_pathname(entry, SvPV_nolen(path_sv)); sv_free(path_sv); r = archive_write_header(ext, entry); if (r != ARCHIVE_OK) croak(archive_error_string(ext)); _copy_data(a, ext); r = archive_write_finish_entry(ext); if (r != ARCHIVE_OK) croak(archive_error_string(ext)); } _close_file(a); archive_write_close(ext); archive_write_finish(ext);