static int open_filename(struct archive *a, int mbs_fn, const void *filename) { struct write_file_data *mine; int r; mine = (struct write_file_data *)calloc(1, sizeof(*mine)); if (mine == NULL) { archive_set_error(a, ENOMEM, "No memory"); return (ARCHIVE_FATAL); } if (mbs_fn) r = archive_mstring_copy_mbs(&mine->filename, filename); else r = archive_mstring_copy_wcs(&mine->filename, filename); if (r < 0) { if (errno == ENOMEM) { archive_set_error(a, ENOMEM, "No memory"); return (ARCHIVE_FATAL); } if (mbs_fn) archive_set_error(a, ARCHIVE_ERRNO_MISC, "Can't convert '%s' to WCS", (const char *)filename); else archive_set_error(a, ARCHIVE_ERRNO_MISC, "Can't convert '%S' to MBS", (const wchar_t *)filename); return (ARCHIVE_FAILED); } mine->fd = -1; return (archive_write_open(a, mine, file_open, file_write, file_close)); }
void write_archive(const char *outname, const char **filename) { struct mydata *mydata = malloc(sizeof(struct mydata)); struct archive *a; struct archive_entry *entry; struct stat st; char buff[8192]; int len; int fd; a = archive_write_new(); mydata->name = outname; archive_write_set_compression_gzip(a); archive_write_set_format_ustar(a); archive_write_open(a, mydata, myopen, mywrite, myclose); while (*filename) { stat(*filename, &st); entry = archive_entry_new(); archive_entry_copy_stat(entry, &st); archive_entry_set_pathname(entry, *filename); archive_entry_set_size(entry, st.st_size); archive_clear_error(a); archive_write_header(a, entry); fd = open(*filename, O_RDONLY); len = read(fd, buff, sizeof(buff)); while ( len > 0 ) { archive_write_data(a, buff, len); len = read(fd, buff, sizeof(buff)); } archive_entry_free(entry); filename++; } archive_write_finish(a); }
int archive_write_open_FILE(struct archive *a, FILE *f) { struct write_FILE_data *mine; mine = (struct write_FILE_data *)malloc(sizeof(*mine)); if (mine == NULL) { archive_set_error(a, ENOMEM, "No memory"); return (ARCHIVE_FATAL); } mine->f = f; return (archive_write_open(a, mine, file_open, file_write, file_close)); }
/* * Client provides a pointer to a block of memory to receive * the data. The 'size' param both tells us the size of the * client buffer and lets us tell the client the final size. */ int archive_write_open_memory(struct archive *a, void *buff, size_t buffSize, size_t *used) { struct write_memory_data *mine; mine = (struct write_memory_data *)calloc(1, sizeof(*mine)); if (mine == NULL) { archive_set_error(a, ENOMEM, "No memory"); return (ARCHIVE_FATAL); } mine->buff = buff; mine->size = buffSize; mine->client_size = used; return (archive_write_open(a, mine, memory_write_open, memory_write, memory_write_close)); }
int archive_write_open_fd(struct archive *a, int fd) { struct write_fd_data *mine; mine = (struct write_fd_data *)malloc(sizeof(*mine)); if (mine == NULL) { archive_set_error(a, ENOMEM, "No memory"); return (ARCHIVE_FATAL); } mine->fd = fd; #if defined(__CYGWIN__) || defined(_WIN32) setmode(mine->fd, O_BINARY); #endif return (archive_write_open(a, mine, file_open, file_write, file_close)); }
int ost_write_open_dynamic_memory(struct archive* a, char** location, size_t* written) { struct ost_write_memory_data* mine; mine = (struct ost_write_memory_data*)calloc(1, sizeof (*mine)); if (mine == NULL) { archive_set_error(a, ENOMEM, "No memory"); return (ARCHIVE_FATAL); } mine->current_buffer = location; mine->written = written; mine->current_size = 0; /* "magic" code taken from archive_write_open_memory.c */ /* disable padding */ if (-1 == archive_write_get_bytes_in_last_block(a)) { archive_write_set_bytes_in_last_block(a, 1); } return (archive_write_open(a, mine, ost_mem_open, ost_mem_write, ost_mem_close)); }
MemoryWriteArchive::MemoryWriteArchive(std::vector< char >& buffer) : m_buffer(buffer) { int ret; void* userData; m_archive = archive_write_new(); archive_write_add_filter_none(m_archive); archive_write_set_format_ustar(m_archive); archive_write_set_bytes_in_last_block(m_archive, 1); userData = reinterpret_cast<void*>(&m_buffer); ret = archive_write_open(m_archive, userData, &MemoryWriteArchive::open, &MemoryWriteArchive::write, &MemoryWriteArchive::close); if (ret != ARCHIVE_OK) { throw ::fwZip::exception::Write("Cannot open archive in write mode"); } }
int test2_with_write_callbacks() { struct archive *a = archive_write_new(); archive_write_set_format_zip(a); int ret = archive_write_open(a, NULL, myopen, mywrite, myclose); // add a file struct archive_entry *entry = archive_entry_new(); archive_entry_set_pathname(entry, "123.d/hello.txt"); archive_entry_set_size(entry, 5); archive_entry_set_filetype(entry, AE_IFREG); archive_entry_set_perm(entry, 0644); ret = archive_write_header(a, entry); fprintf(stderr, "archive_write_header: ret=%d\n", ret); la_ssize_t n = archive_write_data(a, "world", 5); fprintf(stderr, "archive_write_data: n=%d, error=%s\n", n, archive_error_string(a)); archive_entry_free(entry); ret = archive_write_free(a); fprintf(stderr, "archive_write_free: ret=%d, error=%s\n", ret, archive_error_string(a)); }
/** * archive_write_open_multitape(a, machinenum, cachedir, tapename, argc, * argv, printstats, dryrun): * Open the multitape tape ${tapename} for writing and associate it with the * archive $a$. If ${printstats} is non-zero, print archive statistics when * the tape is closed. If ${dryrun} is non-zero, perform a dry run. Return * a cookie which can be passed to the multitape layer. */ void * archive_write_open_multitape(struct archive * a, uint64_t machinenum, const char * cachedir, const char * tapename, int argc, char ** argv, int printstats, int dryrun) { struct multitape_write_internal * d; /* Clear any error messages from the archive. */ archive_clear_error(a); if ((d = writetape_open(machinenum, cachedir, tapename, argc, argv, printstats, dryrun)) == NULL) { archive_set_error(a, errno, "Error creating new archive"); return (NULL); } if (archive_write_open(a, d, NULL, write_write, write_close)) { writetape_free(d); return (NULL); } else return (d); }
int archive_write_open_filename(struct archive *a, const char *filename) { struct write_file_data *mine; if (filename == NULL || filename[0] == '\0') { mine = (struct write_file_data *)malloc(sizeof(*mine)); if (mine == NULL) { archive_set_error(a, ENOMEM, "No memory"); return (ARCHIVE_FATAL); } mine->filename[0] = '\0'; /* Record that we're using stdout. */ } else { mine = (struct write_file_data *)malloc(sizeof(*mine) + strlen(filename)); if (mine == NULL) { archive_set_error(a, ENOMEM, "No memory"); return (ARCHIVE_FATAL); } strcpy(mine->filename, filename); } mine->fd = -1; return (archive_write_open(a, mine, file_open, file_write, file_close)); }
/* ArchiveWriter::__construct {{{ * */ ZEND_METHOD(ArchiveWriter, __construct) { archive_file_t *arch = NULL; int resource_id; zval *this = getThis(); const char *error_string = NULL; char *filename; long error_num, filename_len, result, format=0, compression=0; zend_error_handling error_handling; zend_replace_error_handling(EH_THROW, ce_ArchiveException, &error_handling TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &filename, &filename_len, &format, &compression) == FAILURE) { zend_restore_error_handling(&error_handling TSRMLS_CC); return; } #if PHP_API_VERSION < 20100412 if (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) { zend_restore_error_handling(&error_handling TSRMLS_CC); return; } #endif if (php_check_open_basedir(filename TSRMLS_CC)) { zend_restore_error_handling(&error_handling TSRMLS_CC); return; } arch = (archive_file_t *) emalloc(sizeof(archive_file_t)); arch->stream = NULL; ALLOC_HASHTABLE(arch->entries); zend_hash_init(arch->entries, 10, NULL, _archive_entries_hash_dtor, 0); arch->mode = PHP_ARCHIVE_WRITE_MODE; arch->buf = emalloc(PHP_ARCHIVE_BUF_LEN + 1); arch->filename = estrndup(filename, filename_len); arch->arch = archive_write_new(); switch (compression) { case PHP_ARCHIVE_COMPRESSION_GZIP: if (archive_write_add_filter_gzip(arch->arch) != ARCHIVE_OK) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Gzip compression is not supported in this build"); zend_restore_error_handling(&error_handling TSRMLS_CC); return; } break; case PHP_ARCHIVE_COMPRESSION_BZIP2: if (archive_write_add_filter_bzip2(arch->arch) != ARCHIVE_OK) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bzip2 compression is not supported in this build"); zend_restore_error_handling(&error_handling TSRMLS_CC); return; } break; case 0: /* default value */ case PHP_ARCHIVE_COMPRESSION_NONE: /* always supported */ break; default: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported compression type %ld", compression); zend_restore_error_handling(&error_handling TSRMLS_CC); return; break; } switch (format) { case 0: /* default value */ case PHP_ARCHIVE_FORMAT_TAR: case PHP_ARCHIVE_FORMAT_PAX_RESTRICTED: archive_write_set_format_pax_restricted(arch->arch); break; case PHP_ARCHIVE_FORMAT_PAX: archive_write_set_format_pax(arch->arch); break; case PHP_ARCHIVE_FORMAT_CPIO: archive_write_set_format_cpio(arch->arch); break; case PHP_ARCHIVE_FORMAT_SHAR: archive_write_set_format_shar(arch->arch); break; case PHP_ARCHIVE_FORMAT_USTAR: archive_write_set_format_ustar(arch->arch); break; default: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported archive format: %ld", format); zend_restore_error_handling(&error_handling TSRMLS_CC); return; break; } archive_write_set_bytes_per_block(arch->arch, DEFAULT_BYTES_PER_BLOCK); result = archive_write_open(arch->arch, arch, _archive_open_clbk, _archive_write_clbk, _archive_close_clbk); /* do not pad the last block */ archive_write_set_bytes_in_last_block(arch->arch, 1); if (result) { error_num = archive_errno(arch->arch); error_string = archive_error_string(arch->arch); efree(arch->filename); efree(arch->buf); efree(arch); if (error_num && error_string) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to open file %s for writing: error #%ld, %s", filename, error_num, error_string); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to open file %s for writing: unknown error %ld", filename, result); } zend_restore_error_handling(&error_handling TSRMLS_CC); return; } resource_id = zend_list_insert(arch,le_archive); add_property_resource(this, "fd", resource_id); zend_restore_error_handling(&error_handling TSRMLS_CC); return; }
/* * Archiving related functions. * This one creates a list of files to be included into the archive and * sets up the libarchive context. */ int setup_archiver(pc_ctx_t *pctx, struct stat *sbuf) { char *tmpfile, *tmp; int err, fd; uchar_t *pbuf; struct archive *arc; struct fn_list *fn; /* * If sorting is enabled create the initial sort buffer. */ if (pctx->enable_archive_sort) { struct sort_buf *srt; srt = (struct sort_buf *)malloc(sizeof (struct sort_buf)); if (srt == NULL) { log_msg(LOG_ERR, 0, "Out of memory."); return (-1); } srt->next = NULL; srt->pos = 0; pctx->archive_sort_buf = srt; } /* * Create a temporary file to hold the generated list of pathnames to be archived. * Storing in a file saves memory usage and allows scalability. */ tmpfile = pctx->archive_members_file; tmp = get_temp_dir(); strcpy(tmpfile, tmp); free(tmp); strcat(tmpfile, "/.pcompXXXXXX"); if ((fd = mkstemp(tmpfile)) == -1) { log_msg(LOG_ERR, 1, "mkstemp errored."); return (-1); } add_fname(tmpfile); pbuf = malloc(pctx->chunksize); if (pbuf == NULL) { log_msg(LOG_ERR, 0, "Out of memory."); close(fd); unlink(tmpfile); return (-1); } /* * Use nftw() to scan all the directory hierarchies provided on the command * line and generate a consolidated list of pathnames to be archived. By * doing this we can sort the pathnames and estimate the total archive size. * Total archive size is needed by the subsequent compression stages. */ log_msg(LOG_INFO, 0, "Scanning files."); sbuf->st_size = 0; pctx->archive_size = 0; pctx->archive_members_count = 0; /* * nftw requires using global state variable. So we lock to be mt-safe. * This means only one directory tree scan can happen at a time. */ pthread_mutex_lock(&nftw_mutex); fn = pctx->fn; a_state.pbuf = pbuf; a_state.bufsiz = pctx->chunksize; a_state.bufpos = 0; a_state.fd = fd; a_state.srt = pctx->archive_sort_buf; a_state.srt_pos = 0; a_state.head = a_state.srt; a_state.pathlist_size = 0; while (fn) { struct stat sb; if (lstat(fn->filename, &sb) == -1) { log_msg(LOG_ERR, 1, "Ignoring %s.", fn->filename); fn = fn->next; continue; } a_state.arc_size = 0; a_state.fcount = 0; if (S_ISDIR(sb.st_mode)) { /* * Depth-First scan, FTW_DEPTH, is needed to handle restoring * all directory permissions correctly. */ err = nftw(fn->filename, add_pathname, 1024, FTW_PHYS | FTW_DEPTH); } else { int tflag; struct FTW ftwbuf; char *pos; if (S_ISLNK(sb.st_mode)) tflag = FTW_SL; else tflag = FTW_F; /* * Find out basename to mimic FTW. */ pos = strrchr(fn->filename, PATHSEP_CHAR); if (pos) ftwbuf.base = pos - fn->filename + 1; else ftwbuf.base = 0; add_pathname(fn->filename, &sb, tflag, &ftwbuf); a_state.arc_size = sb.st_size; } if (a_state.bufpos > 0) { ssize_t wrtn = Write(a_state.fd, a_state.pbuf, a_state.bufpos); if (wrtn < a_state.bufpos) { log_msg(LOG_ERR, 1, "Write failed."); close(fd); unlink(tmpfile); return (-1); } a_state.bufpos = 0; a_state.pathlist_size += wrtn; } pctx->archive_size += a_state.arc_size; pctx->archive_members_count += a_state.fcount; fn = fn->next; } if (a_state.srt == NULL) { pctx->enable_archive_sort = 0; } else { log_msg(LOG_INFO, 0, "Sorting ..."); a_state.srt->max = a_state.srt_pos - 1; qsort(a_state.srt->members, a_state.srt_pos, sizeof (member_entry_t), compare_members); pctx->archive_temp_size = a_state.pathlist_size; } pthread_mutex_unlock(&nftw_mutex); sbuf->st_size = pctx->archive_size; lseek(fd, 0, SEEK_SET); free(pbuf); sbuf->st_uid = geteuid(); sbuf->st_gid = getegid(); sbuf->st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; arc = archive_write_new(); if (!arc) { log_msg(LOG_ERR, 1, "Unable to create libarchive context.\n"); close(fd); unlink(tmpfile); return (-1); } archive_write_set_format_pax_restricted(arc); archive_write_set_bytes_per_block(arc, 0); archive_write_open(arc, pctx, arc_open_callback, creat_write_callback, creat_close_callback); pctx->archive_ctx = arc; pctx->archive_members_fd = fd; if (pctx->enable_archive_sort) { pctx->temp_mmap_len = TEMP_MMAP_SIZE; pctx->temp_mmap_buf = mmap(NULL, pctx->temp_mmap_len, PROT_READ, MAP_SHARED, pctx->archive_members_fd, 0); if (pctx->temp_mmap_buf == NULL) { log_msg(LOG_WARN, 1, "Unable to mmap pathlist file, switching to read()."); pctx->temp_mmap_len = 0; } } else { pctx->temp_mmap_buf = NULL; pctx->temp_mmap_len = 0; } pctx->temp_mmap_pos = 0; pctx->arc_writing = 0; return (0); }
void TarUtils::write(std::ostream &output, const io::ObservedFile &root, const std::set<ObservedFile> &files_to_send) { bool processed = false; //create new archive, set format to tar, use callbacks (above this method) struct archive *a; a = archive_write_new(); archive_write_set_format_ustar(a); archive_write_open(a, &output, &__tar_utils_open_callback, &__tar_utils_write_callback, &__tar_utils_close_callback); for(std::set<ObservedFile>::const_iterator of_iter = files_to_send.begin(); of_iter != files_to_send.end(); ++of_iter) { const ObservedFile &of = (*of_iter); const ibrcommon::File &file = of.getFile(); struct archive_entry *entry; entry = archive_entry_new(); archive_entry_set_size(entry, file.size()); if(file.isDirectory()) { archive_entry_set_filetype(entry, AE_IFDIR); archive_entry_set_perm(entry, 0755); } else { archive_entry_set_filetype(entry, AE_IFREG); archive_entry_set_perm(entry, 0644); } archive_entry_set_pathname(entry, rel_filename(root, of).c_str()); //set timestamps struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); archive_entry_set_atime(entry, ts.tv_sec, ts.tv_nsec); //accesstime archive_entry_set_birthtime(entry, ts.tv_sec, ts.tv_nsec); //creationtime archive_entry_set_ctime(entry, ts.tv_sec, ts.tv_nsec); //time, inode changed archive_entry_set_mtime(entry, ts.tv_sec, ts.tv_nsec); //modification time archive_write_header(a, entry); try { #ifdef HAVE_LIBTFFS //read file on vfat-image try { const FATFile &ffile = dynamic_cast<const FATFile&>(file); processed = true; // get image reader const FatImageReader &reader = ffile.getReader(); // open fat file io::FatImageReader::FileHandle fh = reader.open(ffile); char buff[BUFF_SIZE]; ssize_t ret = 0; size_t len = 0; // read file len = fh.read((unsigned char*)&buff, BUFF_SIZE); //write buffer to archive while (len > 0) { if( (ret = archive_write_data(a, buff, len)) < 0) { IBRCOMMON_LOGGER_TAG("TarUtils", error) << "archive_write_data failed" << IBRCOMMON_LOGGER_ENDL; break; } // read next chunk len = fh.read((unsigned char*)&buff, BUFF_SIZE); } } catch (const std::bad_cast&) { }; #endif if (!processed) { char buff[BUFF_SIZE]; ssize_t ret = 0; // open file for reading std::ifstream fs(file.getPath().c_str()); // write buffer to archive while (fs.good()) { // read bytes fs.read(buff, BUFF_SIZE); // write bytes to archive if( (ret = archive_write_data(a, buff, fs.gcount())) < 0) { IBRCOMMON_LOGGER_TAG("TarUtils", error) << "archive write failed" << IBRCOMMON_LOGGER_ENDL; break; } } } } catch (const ibrcommon::IOException &e) { // write failed IBRCOMMON_LOGGER_TAG("TarUtils", error) << "archive write failed: " << e.what() << IBRCOMMON_LOGGER_ENDL; archive_entry_free(entry); archive_write_close(a); archive_write_free(a); throw; } archive_entry_free(entry); } archive_write_close(a); archive_write_free(a); }
int archive_write_open_rb_str(struct archive *a, VALUE str) { return archive_write_open(a, (void *) str, rb_str_write_open, rb_str_write, rb_str_write_close); }
////////////////////////////////////////////////////////////////////// // Constructor: static int ar_write(lua_State *L) { struct archive** self_ref; static struct { const char *name; int (*setter)(struct archive *); } names[] = { /* Copied from archive_write_set_format_by_name.c */ { "ar", archive_write_set_format_ar_bsd }, { "arbsd", archive_write_set_format_ar_bsd }, { "argnu", archive_write_set_format_ar_svr4 }, { "arsvr4", archive_write_set_format_ar_svr4 }, { "cpio", archive_write_set_format_cpio }, { "mtree", archive_write_set_format_mtree }, { "newc", archive_write_set_format_cpio_newc }, { "odc", archive_write_set_format_cpio }, { "pax", archive_write_set_format_pax }, { "posix", archive_write_set_format_pax }, { "shar", archive_write_set_format_shar }, { "shardump", archive_write_set_format_shar_dump }, { "ustar", archive_write_set_format_ustar }, /* New ones to more closely match the C API */ { "ar_bsd", archive_write_set_format_ar_bsd }, { "ar_svr4", archive_write_set_format_ar_svr4 }, { "cpio_newc", archive_write_set_format_cpio_newc }, { "pax_restricted", archive_write_set_format_pax_restricted }, { "shar_dump", archive_write_set_format_shar_dump }, { NULL, NULL } }; int idx = 0; const char* name; luaL_checktype(L, 1, LUA_TTABLE); self_ref = (struct archive**) lua_newuserdata(L, sizeof(struct archive*)); // {ud} luaL_getmetatable(L, AR_WRITE); // {ud}, [write] lua_setmetatable(L, -2); // {ud} __ref_count++; *self_ref = archive_write_new(); // Register it in the weak metatable: ar_registry_set(L, *self_ref); // Create an environment to store a reference to the writer: lua_createtable(L, 1, 0); // {ud}, {} lua_pushliteral(L, "writer"); // {ud}, {}, "writer" lua_rawget(L, 1); // {ud}, {}, fn if ( ! lua_isfunction(L, -1) ) { err("MissingArgument: required parameter 'writer' must be a function"); } lua_setfield(L, -2, "writer"); lua_setfenv(L, -2); // {ud} // Extract various fields and prepare the archive: lua_getfield(L, 1, "bytes_per_block"); if ( ! lua_isnil(L, -1) && ARCHIVE_OK != archive_write_set_bytes_per_block(*self_ref, lua_tointeger(L, -1)) ) { err("archive_write_set_bytes_per_block: %s", archive_error_string(*self_ref)); } lua_pop(L, 1); lua_getfield(L, 1, "bytes_in_last_block"); if ( ! lua_isnil(L, -1) && ARCHIVE_OK != archive_write_set_bytes_in_last_block(*self_ref, lua_tointeger(L, -1)) ) { err("archive_write_set_bytes_in_last_block: %s", archive_error_string(*self_ref)); } lua_pop(L, 1); lua_getfield(L, 1, "skip_file"); if ( ! lua_isnil(L, -1) ) { dev_t dev; ino_t ino; if ( LUA_TTABLE != lua_type(L, -1) ) { err("skip_file member must be a table object"); } lua_getfield(L, -1, "dev"); if ( ! lua_isnumber(L, -1) ) { err("skip_file.dev member must be a number"); } dev = (dev_t)lua_tonumber(L, -1); lua_pop(L, 1); lua_getfield(L, -1, "ino"); if ( ! lua_isnumber(L, -1) ) { err("skip_file.ino member must be a number"); } ino = (ino_t)lua_tonumber(L, -1); lua_pop(L, 1); if ( ARCHIVE_OK != archive_write_set_skip_file(*self_ref, dev, ino) ) { err("archive_write_set_skip_file: %s", archive_error_string(*self_ref)); } } lua_pop(L, 1); lua_getfield(L, 1, "format"); if ( lua_isnil(L, -1) ) { lua_pop(L, 1); lua_pushliteral(L, "posix"); } name = lua_tostring(L, -1); for ( ;; idx++ ) { if ( names[idx].name == NULL ) { err("archive_write_set_format_*: No such format '%s'", name); } if ( strcmp(name, names[idx].name) == 0 ) break; } if ( ARCHIVE_OK != (names[idx].setter)(*self_ref) ) { err("archive_write_set_format_%s: %s", name, archive_error_string(*self_ref)); } lua_pop(L, 1); lua_getfield(L, 1, "compression"); if ( ! lua_isnil(L, -1) ) { static struct { const char *name; int (*setter)(struct archive *); } names[] = { { "bzip2", archive_write_add_filter_bzip2 }, { "compress", archive_write_add_filter_compress }, { "gzip", archive_write_add_filter_gzip }, { "lzma", archive_write_add_filter_lzma }, { "xz", archive_write_add_filter_xz }, { NULL, NULL } }; int idx = 0; const char* name = lua_tostring(L, -1); for ( ;; idx++ ) { if ( names[idx].name == NULL ) { err("archive_write_set_compression_*: No such compression '%s'", name); } if ( strcmp(name, names[idx].name) == 0 ) break; } if ( ARCHIVE_OK != (names[idx].setter)(*self_ref) ) { err("archive_write_set_compression_%s: %s", name, archive_error_string(*self_ref)); } } lua_pop(L, 1); lua_getfield(L, 1, "options"); if ( ! lua_isnil(L, -1) && ARCHIVE_OK != archive_write_set_options(*self_ref, lua_tostring(L, -1)) ) { err("archive_write_set_options: %s", archive_error_string(*self_ref)); } lua_pop(L, 1); if ( ARCHIVE_OK != archive_write_open(*self_ref, L, NULL, &ar_write_cb, NULL) ) { err("archive_write_open: %s", archive_error_string(*self_ref)); } return 1; }