struct mp_archive *mp_archive_new(struct mp_log *log, struct stream *src, int flags) { struct mp_archive *mpa = talloc_zero(NULL, struct mp_archive); mpa->log = log; mpa->locale = newlocale(LC_ALL_MASK, "C.UTF-8", (locale_t)0); if (!mpa->locale) goto err; mpa->arch = archive_read_new(); mpa->primary_src = src; if (!mpa->arch) goto err; // first volume is the primary streame if (!add_volume(log ,mpa, src, src->url)) goto err; // try to open other volumes char** volumes = find_volumes(src); for (int i = 0; volumes[i]; i++) { if (!add_volume(log, mpa, NULL, volumes[i])) { talloc_free(volumes); goto err; } } talloc_free(volumes); locale_t oldlocale = uselocale(mpa->locale); archive_read_support_format_7zip(mpa->arch); archive_read_support_format_iso9660(mpa->arch); archive_read_support_format_rar(mpa->arch); archive_read_support_format_zip(mpa->arch); archive_read_support_filter_bzip2(mpa->arch); archive_read_support_filter_gzip(mpa->arch); archive_read_support_filter_xz(mpa->arch); if (flags & MP_ARCHIVE_FLAG_UNSAFE) { archive_read_support_format_gnutar(mpa->arch); archive_read_support_format_tar(mpa->arch); } archive_read_set_read_callback(mpa->arch, read_cb); archive_read_set_skip_callback(mpa->arch, skip_cb); archive_read_set_switch_callback(mpa->arch, switch_cb); archive_read_set_open_callback(mpa->arch, open_cb); archive_read_set_close_callback(mpa->arch, close_cb); if (mpa->primary_src->seekable) archive_read_set_seek_callback(mpa->arch, seek_cb); bool fail = archive_read_open1(mpa->arch) < ARCHIVE_OK; uselocale(oldlocale); if (fail) goto err; return mpa; err: mp_archive_free(mpa); return NULL; }
static int read_open_memory_internal(struct archive *a, const void *buff, size_t size, size_t read_size, int level) { struct read_memory_data *mine = NULL; switch (level) { case 3: archive_read_set_seek_callback(a, memory_read_seek); __LA_FALLTHROUGH; case 2: archive_read_set_open_callback(a, memory_read_open); archive_read_set_skip_callback(a, memory_read_skip); __LA_FALLTHROUGH; case 1: mine = malloc(sizeof(*mine)); if (mine == NULL) { archive_set_error(a, ENOMEM, "No memory"); return (ARCHIVE_FATAL); } memset(mine, 0, sizeof(*mine)); mine->start = mine->p = (const unsigned char *)buff; mine->end = mine->start + size; mine->read_size = read_size; mine->copy_buff_offset = 32; mine->copy_buff_size = read_size + mine->copy_buff_offset * 2; mine->copy_buff = malloc(mine->copy_buff_size); memset(mine->copy_buff, 0xA5, mine->copy_buff_size); archive_read_set_read_callback(a, memory_read); archive_read_set_close_callback(a, memory_read_close); archive_read_set_callback_data(a, mine); } return archive_read_open1(a); }
int archive_read_open_filename_w(struct archive *a, const wchar_t *wfilename, size_t block_size) { struct read_file_data *mine = (struct read_file_data *)calloc(1, sizeof(*mine) + wcslen(wfilename) * sizeof(wchar_t)); if (!mine) { archive_set_error(a, ENOMEM, "No memory"); return (ARCHIVE_FATAL); } mine->fd = -1; mine->block_size = block_size; if (wfilename == NULL || wfilename[0] == L'\0') { mine->filename_type = FNT_STDIN; } else { #if defined(_WIN32) && !defined(__CYGWIN__) mine->filename_type = FNT_WCS; wcscpy(mine->filename.w, wfilename); #else /* * POSIX system does not support a wchar_t interface for * open() system call, so we have to translate a whcar_t * filename to multi-byte one and use it. */ struct archive_string fn; archive_string_init(&fn); if (archive_string_append_from_wcs(&fn, wfilename, wcslen(wfilename)) != 0) { if (errno == ENOMEM) archive_set_error(a, errno, "Can't allocate memory"); else archive_set_error(a, EINVAL, "Failed to convert a wide-character" " filename to a multi-byte filename"); archive_string_free(&fn); free(mine); return (ARCHIVE_FATAL); } mine->filename_type = FNT_MBS; strcpy(mine->filename.m, fn.s); archive_string_free(&fn); #endif } if (archive_read_append_callback_data(a, mine) != (ARCHIVE_OK)) return (ARCHIVE_FATAL); archive_read_set_open_callback(a, file_open); archive_read_set_read_callback(a, file_read); archive_read_set_skip_callback(a, file_skip); archive_read_set_close_callback(a, file_close); archive_read_set_switch_callback(a, file_switch); archive_read_set_seek_callback(a, file_seek); return (archive_read_open1(a)); }
/* * Open the archive */ int archive_read_open(struct archive *a, void *client_data, archive_open_callback *client_opener, archive_read_callback *client_reader, archive_close_callback *client_closer) { /* Old archive_read_open() is just a thin shell around * archive_read_open1. */ archive_read_set_open_callback(a, client_opener); archive_read_set_read_callback(a, client_reader); archive_read_set_close_callback(a, client_closer); archive_read_set_callback_data(a, client_data); return archive_read_open1(a); }
int archive_read_open_filenames(struct archive *a, const char **filenames, size_t block_size) { struct read_file_data *mine; const char *filename = NULL; if (filenames) filename = *(filenames++); archive_clear_error(a); do { if (filename == NULL) filename = ""; mine = (struct read_file_data *)calloc(1, sizeof(*mine) + strlen(filename)); if (mine == NULL) goto no_memory; strcpy(mine->filename.m, filename); mine->block_size = block_size; mine->fd = -1; mine->buffer = NULL; mine->st_mode = mine->use_lseek = 0; if (filename == NULL || filename[0] == '\0') { mine->filename_type = FNT_STDIN; } else mine->filename_type = FNT_MBS; if (archive_read_append_callback_data(a, mine) != (ARCHIVE_OK)) return (ARCHIVE_FATAL); if (filenames == NULL) break; filename = *(filenames++); } while (filename != NULL && filename[0] != '\0'); archive_read_set_open_callback(a, file_open); archive_read_set_read_callback(a, file_read); archive_read_set_skip_callback(a, file_skip); archive_read_set_close_callback(a, file_close); archive_read_set_switch_callback(a, file_switch); archive_read_set_seek_callback(a, file_seek); return (archive_read_open1(a)); no_memory: archive_set_error(a, ENOMEM, "No memory"); return (ARCHIVE_FATAL); }
/* * Don't use _open_memory2() in production code; the archive_read_open_memory() * version is the one you really want. This is just here so that * test harnesses can exercise block operations inside the library. */ int archive_read_open_memory2(struct archive *a, void *buff, size_t size, size_t read_size) { struct read_memory_data *mine; mine = (struct read_memory_data *)malloc(sizeof(*mine)); if (mine == NULL) { archive_set_error(a, ENOMEM, "No memory"); return (ARCHIVE_FATAL); } memset(mine, 0, sizeof(*mine)); mine->buffer = (unsigned char *)buff; mine->end = mine->buffer + size; mine->read_size = read_size; archive_read_set_open_callback(a, memory_read_open); archive_read_set_read_callback(a, memory_read); archive_read_set_skip_callback(a, memory_read_skip); archive_read_set_close_callback(a, memory_read_close); archive_read_set_callback_data(a, mine); return (archive_read_open1(a)); }
/* * Don't use _open_memory2() in production code; the archive_read_open_memory() * version is the one you really want. This is just here so that * test harnesses can exercise block operations inside the library. */ int archive_read_open_memory2(struct archive *a, const void *buff, size_t size, size_t read_size) { struct read_memory_data *mine; mine = (struct read_memory_data *)calloc(1, sizeof(*mine)); if (mine == NULL) { archive_set_error(a, ENOMEM, "No memory"); return (ARCHIVE_FATAL); } mine->start = mine->p = (const unsigned char *)buff; mine->end = mine->start + size; mine->read_size = read_size; archive_read_set_open_callback(a, memory_read_open); archive_read_set_read_callback(a, memory_read); archive_read_set_seek_callback(a, memory_read_seek); archive_read_set_skip_callback(a, memory_read_skip); archive_read_set_close_callback(a, memory_read_close); archive_read_set_callback_data(a, mine); return (archive_read_open1(a)); }
static void test_customized_multiple_data_objects(void) { char buff[64]; static const char *reffiles[] = { "test_read_splitted_rar_aa", "test_read_splitted_rar_ab", "test_read_splitted_rar_ac", "test_read_splitted_rar_ad", NULL }; const char test_txt[] = "test text document\r\n"; int size = sizeof(test_txt)-1; struct archive_entry *ae; struct archive *a; struct mydata *mydata; const char *filename = *reffiles; int i; extract_reference_files(reffiles); assert((a = archive_read_new()) != NULL); assertA(0 == archive_read_support_filter_all(a)); assertA(0 == archive_read_support_format_all(a)); for (i = 0; filename != NULL;) { assert((mydata = (struct mydata *)calloc(1, sizeof(*mydata))) != NULL); assert((mydata->filename = (char *)calloc(1, strlen(filename) + 1)) != NULL); strcpy(mydata->filename, filename); mydata->fd = -1; filename = reffiles[++i]; assertA(0 == archive_read_append_callback_data(a, mydata)); } assertA(0 == archive_read_set_open_callback(a, file_open)); assertA(0 == archive_read_set_read_callback(a, file_read)); assertA(0 == archive_read_set_skip_callback(a, file_skip)); assertA(0 == archive_read_set_close_callback(a, file_close)); assertA(0 == archive_read_set_switch_callback(a, file_switch)); assertA(0 == archive_read_set_seek_callback(a, file_seek)); assertA(0 == archive_read_open1(a)); /* First header. */ assertA(0 == archive_read_next_header(a, &ae)); assertEqualString("test.txt", archive_entry_pathname(ae)); assertA((int)archive_entry_mtime(ae)); assertA((int)archive_entry_ctime(ae)); assertA((int)archive_entry_atime(ae)); assertEqualInt(20, archive_entry_size(ae)); assertEqualInt(33188, archive_entry_mode(ae)); assertA(size == archive_read_data(a, buff, size)); assertEqualMem(buff, test_txt, size); /* Second header. */ assertA(0 == archive_read_next_header(a, &ae)); assertEqualString("testlink", archive_entry_pathname(ae)); assertA((int)archive_entry_mtime(ae)); assertA((int)archive_entry_ctime(ae)); assertA((int)archive_entry_atime(ae)); assertEqualInt(0, archive_entry_size(ae)); assertEqualInt(41471, archive_entry_mode(ae)); assertEqualString("test.txt", archive_entry_symlink(ae)); assertEqualIntA(a, 0, archive_read_data(a, buff, sizeof(buff))); /* Third header. */ assertA(0 == archive_read_next_header(a, &ae)); assertEqualString("testdir/test.txt", archive_entry_pathname(ae)); assertA((int)archive_entry_mtime(ae)); assertA((int)archive_entry_ctime(ae)); assertA((int)archive_entry_atime(ae)); assertEqualInt(20, archive_entry_size(ae)); assertEqualInt(33188, archive_entry_mode(ae)); assertA(size == archive_read_data(a, buff, size)); assertEqualMem(buff, test_txt, size); /* Fourth header. */ assertA(0 == archive_read_next_header(a, &ae)); assertEqualString("testdir", archive_entry_pathname(ae)); assertA((int)archive_entry_mtime(ae)); assertA((int)archive_entry_ctime(ae)); assertA((int)archive_entry_atime(ae)); assertEqualInt(0, archive_entry_size(ae)); assertEqualInt(16877, archive_entry_mode(ae)); /* Fifth header. */ assertA(0 == archive_read_next_header(a, &ae)); assertEqualString("testemptydir", archive_entry_pathname(ae)); assertA((int)archive_entry_mtime(ae)); assertA((int)archive_entry_ctime(ae)); assertA((int)archive_entry_atime(ae)); assertEqualInt(0, archive_entry_size(ae)); assertEqualInt(16877, archive_entry_mode(ae)); /* Test EOF */ assertA(1 == archive_read_next_header(a, &ae)); assertEqualInt(5, archive_file_count(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); }
static foreign_t archive_open_stream(term_t data, term_t handle, term_t options) { IOSTREAM *datas; archive_wrapper *ar; term_t tail = PL_copy_term_ref(options); term_t head = PL_new_term_ref(); term_t arg = PL_new_term_ref(); if ( !PL_get_stream_handle(data, &datas) ) return FALSE; if ( !(datas->flags & SIO_INPUT) ) { PL_release_stream(datas); return PL_domain_error("input_stream", data); } ar = PL_malloc(sizeof(*ar)); memset(ar, 0, sizeof(*ar)); ar->data = datas; ar->magic = ARCHIVE_MAGIC; if ( !PL_unify_blob(handle, ar, sizeof(*ar), &archive_blob) ) return FALSE; while( PL_get_list_ex(tail, head, tail) ) { atom_t name; int arity; if ( !PL_get_name_arity(head, &name, &arity) || !PL_get_arg(1, head, arg) ) return PL_type_error("option", head); if ( name == ATOM_compression || name == ATOM_filter ) { atom_t c; if ( !PL_get_atom_ex(arg, &c) ) return FALSE; if ( c == ATOM_all ) ar->type |= FILTER_ALL; #ifdef FILTER_BZIP2 else if ( c == ATOM_bzip2 ) ar->type |= FILTER_BZIP2; #endif #ifdef FILTER_COMPRESS else if ( c == ATOM_compress ) ar->type |= FILTER_COMPRESS; #endif #ifdef FILTER_GZIP else if ( c == ATOM_gzip ) ar->type |= FILTER_GZIP; #endif #ifdef FILTER_GRZIP else if ( c == ATOM_grzip ) ar->type |= FILTER_GRZIP; #endif #ifdef FILTER_LRZIP else if ( c == ATOM_lrzip ) ar->type |= FILTER_LRZIP; #endif #ifdef FILTER_LZIP else if ( c == ATOM_lzip ) ar->type |= FILTER_LZIP; #endif #ifdef FILTER_LZMA else if ( c == ATOM_lzma ) ar->type |= FILTER_LZMA; #endif #ifdef FILTER_LZOP else if ( c == ATOM_lzop ) ar->type |= FILTER_LZOP; #endif #ifdef FILTER_NONE else if ( c == ATOM_none ) ar->type |= FILTER_NONE; #endif #ifdef FILTER_RPM else if ( c == ATOM_rpm ) ar->type |= FILTER_RPM; #endif #ifdef FILTER_UU else if ( c == ATOM_uu ) ar->type |= FILTER_UU; #endif #ifdef FILTER_XZ else if ( c == ATOM_xz ) ar->type |= FILTER_XZ; #endif else return PL_domain_error("filter", arg); } else if ( name == ATOM_format ) { atom_t f; if ( !PL_get_atom_ex(arg, &f) ) return FALSE; if ( f == ATOM_all ) ar->type |= FORMAT_ALL; #ifdef FORMAT_7ZIP else if ( f == ATOM_7zip ) ar->type |= FORMAT_7ZIP; #endif #ifdef FORMAT_AR else if ( f == ATOM_ar ) ar->type |= FORMAT_AR; #endif #ifdef FORMAT_CAB else if ( f == ATOM_cab ) ar->type |= FORMAT_CAB; #endif #ifdef FORMAT_CPIO else if ( f == ATOM_cpio ) ar->type |= FORMAT_CPIO; #endif #ifdef FORMAT_EMPTY else if ( f == ATOM_empty ) ar->type |= FORMAT_EMPTY; #endif #ifdef FORMAT_GNUTAR else if ( f == ATOM_gnutar ) ar->type |= FORMAT_GNUTAR; #endif #ifdef FORMAT_ISO9960 else if ( f == ATOM_iso9960 ) ar->type |= FORMAT_ISO9960; #endif #ifdef FORMAT_LHA else if ( f == ATOM_lha ) ar->type |= FORMAT_LHA; #endif #ifdef FORMAT_MTREE else if ( f == ATOM_mtree ) ar->type |= FORMAT_MTREE; #endif #ifdef FORMAT_RAR else if ( f == ATOM_rar ) ar->type |= FORMAT_RAR; #endif #ifdef FORMAT_RAW else if ( f == ATOM_raw ) ar->type |= FORMAT_RAW; #endif #ifdef FORMAT_TAR else if ( f == ATOM_tar ) ar->type |= FORMAT_TAR; #endif #ifdef FORMAT_XAR else if ( f == ATOM_xar ) ar->type |= FORMAT_XAR; #endif #ifdef FORMAT_ZIP else if ( f == ATOM_zip ) ar->type |= FORMAT_ZIP; #endif else return PL_domain_error("format", arg); } else if ( name == ATOM_close_parent ) { if ( !PL_get_bool_ex(arg, &ar->close_parent) ) return FALSE; } } if ( !PL_get_nil_ex(tail) ) return FALSE; if ( !(ar->type & FILTER_ALL) ) ar->type |= FILTER_ALL; if ( !(ar->type & FORMAT_MASK) ) ar->type |= FORMAT_ALL; if ( !(ar->archive = archive_read_new()) ) return PL_resource_error("memory"); if ( (ar->type & FILTER_ALL) == FILTER_ALL ) { archive_read_support_filter_all(ar->archive); } else { #ifdef FILTER_BZIP2 enable_type(ar, FILTER_BZIP2, archive_read_support_filter_bzip2); #endif #ifdef FILTER_COMPRESS enable_type(ar, FILTER_COMPRESS, archive_read_support_filter_compress); #endif #ifdef FILTER_GZIP enable_type(ar, FILTER_GZIP, archive_read_support_filter_gzip); #endif #ifdef FILTER_GRZIP enable_type(ar, FILTER_GRZIP, archive_read_support_filter_grzip); #endif #ifdef FILTER_LRZIP enable_type(ar, FILTER_LRZIP, archive_read_support_filter_lrzip); #endif #ifdef FILTER_LZIP enable_type(ar, FILTER_LZIP, archive_read_support_filter_lzip); #endif #ifdef FILTER_LZMA enable_type(ar, FILTER_LZMA, archive_read_support_filter_lzma); #endif #ifdef FILTER_LZOP enable_type(ar, FILTER_LZOP, archive_read_support_filter_lzop); #endif #ifdef FILTER_NONE enable_type(ar, FILTER_NONE, archive_read_support_filter_none); #endif #ifdef FILTER_RPM enable_type(ar, FILTER_RPM, archive_read_support_filter_rpm); #endif #ifdef FILTER_UU enable_type(ar, FILTER_UU, archive_read_support_filter_uu); #endif #ifdef FILTER_XZ enable_type(ar, FILTER_XZ, archive_read_support_filter_xz); #endif } if ( (ar->type & FORMAT_ALL) == FORMAT_ALL ) { archive_read_support_format_all(ar->archive); #ifdef FORMAT_RAW enable_type(ar, FORMAT_RAW, archive_read_support_format_raw); #endif } else { #ifdef FORMAT_7ZIP enable_type(ar, FORMAT_7ZIP, archive_read_support_format_7zip); #endif #ifdef FORMAT_AR enable_type(ar, FORMAT_AR, archive_read_support_format_ar); #endif #ifdef FORMAT_CAB enable_type(ar, FORMAT_CAB, archive_read_support_format_cab); #endif #ifdef FORMAT_CPIO enable_type(ar, FORMAT_CPIO, archive_read_support_format_cpio); #endif #ifdef FORMAT_EMPTY enable_type(ar, FORMAT_EMPTY, archive_read_support_format_empty); #endif #ifdef FORMAT_GNUTAR enable_type(ar, FORMAT_GNUTAR, archive_read_support_format_gnutar); #endif #ifdef FORMAT_ISO9960 enable_type(ar, FORMAT_ISO9960, archive_read_support_format_iso9660); #endif #ifdef FORMAT_LHA enable_type(ar, FORMAT_LHA, archive_read_support_format_lha); #endif #ifdef FORMAT_MTREE enable_type(ar, FORMAT_MTREE, archive_read_support_format_mtree); #endif #ifdef FORMAT_RAR enable_type(ar, FORMAT_RAR, archive_read_support_format_rar); #endif #ifdef FORMAT_RAW enable_type(ar, FORMAT_RAW, archive_read_support_format_raw); #endif #ifdef FORMAT_TAR enable_type(ar, FORMAT_TAR, archive_read_support_format_tar); #endif #ifdef FORMAT_XAR enable_type(ar, FORMAT_XAR, archive_read_support_format_xar); #endif #ifdef FORMAT_ZIP enable_type(ar, FORMAT_ZIP, archive_read_support_format_zip); #endif } #ifdef HAVE_ARCHIVE_READ_OPEN1 archive_read_set_callback_data(ar->archive, ar); archive_read_set_open_callback(ar->archive, ar_open); archive_read_set_read_callback(ar->archive, ar_read); archive_read_set_skip_callback(ar->archive, ar_skip); archive_read_set_seek_callback(ar->archive, ar_seek); archive_read_set_close_callback(ar->archive, ar_close); if ( archive_read_open1(ar->archive) == ARCHIVE_OK ) { ar->status = AR_OPENED; return TRUE; } #else if ( archive_read_open2(ar->archive, ar, ar_open, ar_read, ar_skip, ar_close) == ARCHIVE_OK ) { ar->status = AR_OPENED; return TRUE; } #endif return archive_error(ar); }