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); }
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; }
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); }
int archive_read_open_fd(struct archive *a, int fd, size_t block_size) { struct stat st; struct read_fd_data *mine; void *b; archive_clear_error(a); if (fstat(fd, &st) != 0) { archive_set_error(a, errno, "Can't stat fd %d", fd); return (ARCHIVE_FATAL); } mine = (struct read_fd_data *)calloc(1, sizeof(*mine)); b = malloc(block_size); if (mine == NULL || b == NULL) { archive_set_error(a, ENOMEM, "No memory"); free(mine); free(b); return (ARCHIVE_FATAL); } mine->block_size = block_size; mine->buffer = b; mine->fd = fd; /* * Skip support is a performance optimization for anything * that supports lseek(). On FreeBSD, only regular files and * raw disk devices support lseek() and there's no portable * way to determine if a device is a raw disk device, so we * only enable this optimization for regular files. */ if (S_ISREG(st.st_mode)) { archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino); mine->use_lseek = 1; } #if defined(__CYGWIN__) || defined(_WIN32) setmode(mine->fd, O_BINARY); #endif 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_callback_data(a, mine); return (archive_read_open1(a)); }
int archive_read_open_FILE(struct archive *a, FILE *f) { struct stat st; struct read_FILE_data *mine; size_t block_size = 128 * 1024; void *b; archive_clear_error(a); mine = (struct read_FILE_data *)malloc(sizeof(*mine)); b = malloc(block_size); if (mine == NULL || b == NULL) { archive_set_error(a, ENOMEM, "No memory"); free(mine); free(b); return (ARCHIVE_FATAL); } mine->block_size = block_size; mine->buffer = b; mine->f = f; /* * If we can't fstat() the file, it may just be that it's not * a file. (On some platforms, FILE * objects can wrap I/O * streams that don't support fileno()). As a result, fileno() * should be used cautiously.) */ if (fstat(fileno(mine->f), &st) == 0 && S_ISREG(st.st_mode)) { archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino); /* Enable the seek optimization only for regular files. */ mine->can_skip = 1; } else mine->can_skip = 0; #if defined(__CYGWIN__) || defined(_WIN32) setmode(fileno(mine->f), O_BINARY); #endif 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_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, 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 int file_open_filename(struct archive *a, enum fnt_e filename_type, const void *_filename, size_t block_size) { struct stat st; struct read_file_data *mine; void *buffer; const char *filename = NULL; const wchar_t *wfilename = NULL; int fd; int is_disk_like = 0; #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) off_t mediasize = 0; /* FreeBSD-specific, so off_t okay here. */ #elif defined(__NetBSD__) || defined(__OpenBSD__) struct disklabel dl; #elif defined(__DragonFly__) struct partinfo pi; #endif archive_clear_error(a); if (filename_type == FNT_STDIN) { /* We used to delegate stdin support by * directly calling archive_read_open_fd(a,0,block_size) * here, but that doesn't (and shouldn't) handle the * end-of-file flush when reading stdout from a pipe. * Basically, read_open_fd() is intended for folks who * are willing to handle such details themselves. This * API is intended to be a little smarter for folks who * want easy handling of the common case. */ fd = 0; #if defined(__CYGWIN__) || defined(_WIN32) setmode(0, O_BINARY); #endif filename = ""; } else if (filename_type == FNT_MBS) { filename = (const char *)_filename; fd = open(filename, O_RDONLY | O_BINARY); if (fd < 0) { archive_set_error(a, errno, "Failed to open '%s'", filename); return (ARCHIVE_FATAL); } } else { #if defined(_WIN32) && !defined(__CYGWIN__) wfilename = (const wchar_t *)_filename; fd = _wopen(wfilename, O_RDONLY | O_BINARY); if (fd < 0 && errno == ENOENT) { wchar_t *fullpath; fullpath = __la_win_permissive_name_w(wfilename); if (fullpath != NULL) { fd = _wopen(fullpath, O_RDONLY | O_BINARY); free(fullpath); } } if (fd < 0) { archive_set_error(a, errno, "Failed to open '%S'", wfilename); return (ARCHIVE_FATAL); } #else archive_set_error(a, ARCHIVE_ERRNO_MISC, "Unexpedted operation in archive_read_open_filename"); return (ARCHIVE_FATAL); #endif } if (fstat(fd, &st) != 0) { if (filename_type == FNT_WCS) archive_set_error(a, errno, "Can't stat '%S'", wfilename); else archive_set_error(a, errno, "Can't stat '%s'", filename); return (ARCHIVE_FATAL); } /* * Determine whether the input looks like a disk device or a * tape device. The results are used below to select an I/O * strategy: * = "disk-like" devices support arbitrary lseek() and will * support I/O requests of any size. So we get easy skipping * and can cheat on block sizes to get better performance. * = "tape-like" devices require strict blocking and use * specialized ioctls for seeking. * = "socket-like" devices cannot seek at all but can improve * performance by using nonblocking I/O to read "whatever is * available right now". * * Right now, we only specially recognize disk-like devices, * but it should be straightforward to add probes and strategy * here for tape-like and socket-like devices. */ if (S_ISREG(st.st_mode)) { /* Safety: Tell the extractor not to overwrite the input. */ archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino); /* Regular files act like disks. */ is_disk_like = 1; } #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) /* FreeBSD: if it supports DIOCGMEDIASIZE ioctl, it's disk-like. */ else if (S_ISCHR(st.st_mode) && ioctl(fd, DIOCGMEDIASIZE, &mediasize) == 0 && mediasize > 0) { is_disk_like = 1; } #elif defined(__NetBSD__) || defined(__OpenBSD__) /* Net/OpenBSD: if it supports DIOCGDINFO ioctl, it's disk-like. */ else if ((S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) && ioctl(fd, DIOCGDINFO, &dl) == 0 && dl.d_partitions[DISKPART(st.st_rdev)].p_size > 0) { is_disk_like = 1; } #elif defined(__DragonFly__) /* DragonFly BSD: if it supports DIOCGPART ioctl, it's disk-like. */ else if (S_ISCHR(st.st_mode) && ioctl(fd, DIOCGPART, &pi) == 0 && pi.media_size > 0) { is_disk_like = 1; } #elif defined(__linux__) /* Linux: All block devices are disk-like. */ else if (S_ISBLK(st.st_mode) && lseek(fd, 0, SEEK_CUR) == 0 && lseek(fd, 0, SEEK_SET) == 0 && lseek(fd, 0, SEEK_END) > 0 && lseek(fd, 0, SEEK_SET) == 0) { is_disk_like = 1; } #endif /* TODO: Add an "is_tape_like" variable and appropriate tests. */ if (filename_type == FNT_WCS) mine = (struct read_file_data *)calloc(1, sizeof(*mine) + wcslen(wfilename) * sizeof(wchar_t)); else mine = (struct read_file_data *)calloc(1, sizeof(*mine) + strlen(filename)); /* Disk-like devices prefer power-of-two block sizes. */ /* Use provided block_size as a guide so users have some control. */ if (is_disk_like) { size_t new_block_size = 64 * 1024; while (new_block_size < block_size && new_block_size < 64 * 1024 * 1024) new_block_size *= 2; block_size = new_block_size; } buffer = malloc(block_size); if (mine == NULL || buffer == NULL) { archive_set_error(a, ENOMEM, "No memory"); free(mine); free(buffer); return (ARCHIVE_FATAL); } if (filename_type == FNT_WCS) wcscpy(mine->filename.w, wfilename); else strcpy(mine->filename.m, filename); mine->filename_type = filename_type; mine->block_size = block_size; mine->buffer = buffer; mine->fd = fd; /* Remember mode so close can decide whether to flush. */ mine->st_mode = st.st_mode; /* Disk-like inputs can use lseek(). */ if (is_disk_like) { archive_read_set_seek_callback(a, file_seek); mine->use_lseek = 1; } 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_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); }