static void set_writer_options(struct bsdtar *bsdtar, struct archive *a) { const char *writer_options; int r; writer_options = getenv(ENV_WRITER_OPTIONS); if (writer_options != NULL) { char *p; /* Set default write options. */ p = malloc(sizeof(IGNORE_WRONG_MODULE_NAME) + strlen(writer_options) + 1); if (p == NULL) lafe_errc(1, errno, "Out of memory"); /* Prepend magic code to ignore options for * a format or filters which are not added to * the archive write object. */ strncpy(p, IGNORE_WRONG_MODULE_NAME, sizeof(IGNORE_WRONG_MODULE_NAME) -1); strcpy(p + sizeof(IGNORE_WRONG_MODULE_NAME) -1, writer_options); r = archive_write_set_options(a, p); free(p); if (r < ARCHIVE_WARN) lafe_errc(1, 0, "%s", archive_error_string(a)); else archive_clear_error(a); } if (ARCHIVE_OK != archive_write_set_options(a, bsdtar->option_options)) lafe_errc(1, 0, "%s", archive_error_string(a)); }
/* * Verify that KOI8-R filenames are not translated to Unicode and UTF-8 * when using hdrcharset=BINARY option. */ static void test_pax_filename_encoding_KOI8R_BINARY(void) { struct archive *a; struct archive_entry *entry; char buff[4096]; size_t used; if (NULL == setlocale(LC_ALL, "ru_RU.KOI8-R")) { skipping("KOI8-R locale not available on this system."); return; } a = archive_write_new(); assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a)); /* BINARY mode should be accepted. */ assertEqualInt(ARCHIVE_OK, archive_write_set_options(a, "hdrcharset=BINARY")); assertEqualInt(ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff), &used)); entry = archive_entry_new2(a); archive_entry_set_pathname(entry, "\xD0\xD2\xC9"); archive_entry_set_filetype(entry, AE_IFREG); archive_entry_set_size(entry, 0); assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* "hdrcharset=BINARY" pax attribute should be written. */ assertEqualMem(buff + 512, "21 hdrcharset=BINARY\x0A", 21); /* Above three characters in KOI8-R should not translate to any * character-set. */ assertEqualMem(buff + 512+21, "12 path=\xD0\xD2\xC9\x0A", 12); }
int repodata_flush(struct xbps_handle *xhp, const char *repodir, xbps_dictionary_t idx, xbps_dictionary_t idxfiles) { struct archive *ar; mode_t myumask; char *repofile, *tname, *xml; int repofd; /* Create a tempfile for our repository archive */ repofile = xbps_repo_path(xhp, repodir); tname = xbps_xasprintf("%s.XXXXXXXXXX", repofile); if ((repofd = mkstemp(tname)) == -1) return errno; /* Create and write our repository archive */ ar = archive_write_new(); assert(ar); archive_write_set_compression_gzip(ar); archive_write_set_format_pax_restricted(ar); archive_write_set_options(ar, "compression-level=9"); archive_write_open_fd(ar, repofd); xml = xbps_dictionary_externalize(idx); assert(xml); if (xbps_archive_append_buf(ar, xml, strlen(xml), XBPS_PKGINDEX, 0644, "root", "root") != 0) { free(xml); return -1; } free(xml); xml = xbps_dictionary_externalize(idxfiles); assert(xml); if (xbps_archive_append_buf(ar, xml, strlen(xml), XBPS_PKGINDEX_FILES, 0644, "root", "root") != 0) { free(xml); return -1; } free(xml); archive_write_finish(ar); /* Write data to tempfile and rename */ fdatasync(repofd); myumask = umask(0); (void)umask(myumask); assert(fchmod(repofd, 0666 & ~myumask) != -1); close(repofd); rename(tname, repofile); free(repofile); free(tname); return 0; }
/* * Pax format writer only accepts both BINARY and UTF-8. * If other character-set name is specified, you will get ARCHIVE_FAILED. */ static void test_pax_filename_encoding_KOI8R_CP1251(void) { struct archive *a; if (NULL == setlocale(LC_ALL, "ru_RU.KOI8-R")) { skipping("KOI8-R locale not available on this system."); return; } a = archive_write_new(); assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a)); /* pax format writer only accepts both BINARY and UTF-8. */ assertEqualInt(ARCHIVE_FAILED, archive_write_set_options(a, "hdrcharset=CP1251")); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); }
/* * Verify that CP932/SJIS filenames are correctly translated to Unicode and UTF-8. */ static void test_pax_filename_encoding_CP932(void) { struct archive *a; struct archive_entry *entry; char buff[4096]; size_t used; if (NULL == setlocale(LC_ALL, "Japanese_Japan") && NULL == setlocale(LC_ALL, "ja_JP.SJIS")) { skipping("eucJP locale not available on this system."); return; } /* Check if the paltform completely supports the string conversion. */ a = archive_write_new(); assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a)); if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { skipping("This system cannot convert character-set" " from CP932/SJIS to UTF-8."); archive_write_free(a); return; } archive_write_free(a); /* Re-create a write archive object since filenames should be written * in UTF-8 by default. */ a = archive_write_new(); assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a)); assertEqualInt(ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff), &used)); entry = archive_entry_new2(a); archive_entry_set_pathname(entry, "\x95\x5C.txt"); /* Check the Unicode version. */ archive_entry_set_filetype(entry, AE_IFREG); archive_entry_set_size(entry, 0); assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* Check UTF-8 version. */ assertEqualMem(buff + 512, "16 path=\xE8\xA1\xA8.txt\x0A", 16); }
/* * Verify that CP1251 filenames are correctly translated to Unicode and UTF-8. */ static void test_pax_filename_encoding_CP1251(void) { struct archive *a; struct archive_entry *entry; char buff[4096]; size_t used; if (NULL == setlocale(LC_ALL, "Russian_Russia") && NULL == setlocale(LC_ALL, "ru_RU.CP1251")) { skipping("KOI8-R locale not available on this system."); return; } /* Check if the paltform completely supports the string conversion. */ a = archive_write_new(); assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a)); if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { skipping("This system cannot convert character-set" " from KOI8-R to UTF-8."); archive_write_free(a); return; } archive_write_free(a); /* Re-create a write archive object since filenames should be written * in UTF-8 by default. */ a = archive_write_new(); assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a)); assertEqualInt(ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff), &used)); entry = archive_entry_new2(a); archive_entry_set_pathname(entry, "\xef\xf0\xe8"); archive_entry_set_filetype(entry, AE_IFREG); archive_entry_set_size(entry, 0); assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* Above three characters in KOI8-R should translate to the following * three characters (two bytes each) in UTF-8. */ assertEqualMem(buff + 512, "15 path=\xD0\xBF\xD1\x80\xD0\xB8\x0A", 15); }
static void test_filter_by_name(const char *filter_name, int filter_code, int (*can_filter_prog)(void)) { struct archive_entry *ae; struct archive *a; size_t used; size_t buffsize = 1024 * 128; char *buff; int r; assert((buff = calloc(1, buffsize)) != NULL); if (buff == NULL) return; /* Create a new archive in memory. */ assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); r = archive_write_add_filter_by_name(a, filter_name); if (r == ARCHIVE_WARN) { if (!can_filter_prog()) { skipping("%s filter not suported on this platform", filter_name); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); free(buff); return; } } else if (r == ARCHIVE_FATAL && (strcmp(archive_error_string(a), "lzma compression not supported on this platform") == 0 || strcmp(archive_error_string(a), "xz compression not supported on this platform") == 0)) { skipping("%s filter not suported on this platform", filter_name); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); free(buff); return; } else { if (!assertEqualIntA(a, ARCHIVE_OK, r)) { assertEqualInt(ARCHIVE_OK, archive_write_free(a)); free(buff); return; } } if (filter_code == ARCHIVE_FILTER_LRZIP) { /* * There's a bug in lrzip (as of release 0.612) where 2nd stage * compression can't be performed on smaller files. Set lrzip to * use no 2nd stage compression. */ assertEqualIntA(a, ARCHIVE_OK, archive_write_set_options(a, "lrzip:compression=none")); } assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_per_block(a, 10)); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used)); /* * Write a file to it. */ assert((ae = archive_entry_new()) != NULL); archive_entry_set_mtime(ae, 1, 0); assertEqualInt(1, archive_entry_mtime(ae)); archive_entry_set_ctime(ae, 1, 0); assertEqualInt(1, archive_entry_ctime(ae)); archive_entry_set_atime(ae, 1, 0); assertEqualInt(1, archive_entry_atime(ae)); archive_entry_copy_pathname(ae, "file"); assertEqualString("file", archive_entry_pathname(ae)); archive_entry_set_mode(ae, AE_IFREG | 0755); assertEqualInt((AE_IFREG | 0755), archive_entry_mode(ae)); archive_entry_set_size(ae, 8); assertEqualInt(0, archive_write_header(a, ae)); archive_entry_free(ae); assertEqualInt(8, archive_write_data(a, "12345678", 8)); /* Close out the archive. */ assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* * Now, read the data back. */ assert((a = archive_read_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); /* * Read and verify the file. */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualInt(1, archive_entry_mtime(ae)); assertEqualString("file", archive_entry_pathname(ae)); assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); assertEqualInt(8, archive_entry_size(ae)); /* Verify the end of the archive. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); /* Verify archive format. */ assertEqualIntA(a, filter_code, archive_filter_code(a, 0)); assertEqualIntA(a, ARCHIVE_FORMAT_TAR_USTAR, archive_format(a)); assertEqualInt(ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); }
static void test_write_format_mtree_sub(int use_set) { struct archive_entry *ae; struct archive* a; size_t used; int i; /* Create a mtree format archive. */ assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_mtree(a)); if (use_set) assertEqualIntA(a, ARCHIVE_OK, archive_write_set_options(a, "use-set,!all,flags,type")); else assertEqualIntA(a, ARCHIVE_OK, archive_write_set_options(a, "!all,flags,type")); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff)-1, &used)); /* Write entries */ for (i = 0; entries[i].path != NULL; i++) { assert((ae = archive_entry_new()) != NULL); archive_entry_set_fflags(ae, entries[i].fflags, 0); archive_entry_copy_pathname(ae, entries[i].path); archive_entry_set_size(ae, 0); assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); archive_entry_free(ae); } assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); if (use_set) { const char *p; buff[used] = '\0'; assert(NULL != (p = strstr(buff, "\n/set "))); if (p != NULL) { char *r; const char *o; p++; r = strchr(p, '\n'); if (r != NULL) *r = '\0'; o = "/set type=file flags=uchg,nodump"; assertEqualString(o, p); if (r != NULL) *r = '\n'; } } /* * Read the data and check it. */ assert((a = archive_read_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); /* Read entries */ for (i = 0; entries[i].path != NULL; i++) { unsigned long fset, fclr; assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); archive_entry_fflags(ae, &fset, &fclr); assertEqualInt((int)entries[i].fflags, (int)fset); assertEqualInt(0, (int)fclr); assertEqualString(entries[i].path, archive_entry_pathname(ae)); } assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); }
static void test_options(const char *options) { struct archive_entry *ae; struct archive* a; char *buff, *data; size_t buffsize, datasize; char path[16]; size_t used1; int i, r, use_prog = 0, filecount; assert((a = archive_write_new()) != NULL); r = archive_write_add_filter_lz4(a); if (archive_liblz4_version() == NULL) { if (!canLz4()) { skipping("lz4 writing not supported on this platform"); assertEqualInt(ARCHIVE_WARN, r); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); return; } else { assertEqualInt(ARCHIVE_WARN, r); use_prog = 1; } } else { assertEqualInt(ARCHIVE_OK, r); } buffsize = 2000000; assert(NULL != (buff = (char *)malloc(buffsize))); datasize = 10000; assert(NULL != (data = (char *)calloc(1, datasize))); filecount = 10; /* * Write a filecount files and read them all back. */ assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, archive_write_add_filter_lz4(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_options(a, options)); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_per_block(a, 1024)); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_in_last_block(a, 1024)); assertEqualInt(ARCHIVE_FILTER_LZ4, archive_filter_code(a, 0)); assertEqualString("lz4", archive_filter_name(a, 0)); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used1)); assert((ae = archive_entry_new()) != NULL); archive_entry_set_filetype(ae, AE_IFREG); archive_entry_set_size(ae, datasize); for (i = 0; i < filecount; i++) { sprintf(path, "file%03d", i); archive_entry_copy_pathname(ae, path); assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); assertA(datasize == (size_t)archive_write_data(a, data, datasize)); } archive_entry_free(ae); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); r = archive_read_support_filter_lz4(a); if (r == ARCHIVE_WARN) { skipping("Can't verify lz4 writing by reading back;" " lz4 reading not fully supported on this platform"); } else { assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used1)); for (i = 0; i < filecount; i++) { sprintf(path, "file%03d", i); if (!assertEqualInt(ARCHIVE_OK, archive_read_next_header(a, &ae))) break; assertEqualString(path, archive_entry_pathname(ae)); assertEqualInt((int)datasize, archive_entry_size(ae)); } assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); } assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* * Clean up. */ free(data); free(buff); }
static void test_zip_filename_encoding_CP932(void) { struct archive *a; struct archive_entry *entry; char buff[4096]; size_t used; if (NULL == setlocale(LC_ALL, "Japanese_Japan") && NULL == setlocale(LC_ALL, "ja_JP.SJIS")) { skipping("CP932/SJIS locale not available on this system."); return; } /* * Verify that EUC-JP filenames are correctly translated to UTF-8. */ a = archive_write_new(); assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { skipping("This system cannot convert character-set" " from CP932/SJIS to UTF-8."); archive_write_free(a); return; } assertEqualInt(ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff), &used)); entry = archive_entry_new2(a); /* Set a CP932/SJIS filename. */ archive_entry_set_pathname(entry, "\x95\x5C.txt"); /* Check the Unicode version. */ archive_entry_set_filetype(entry, AE_IFREG); archive_entry_set_size(entry, 0); assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* A bit 11 of general purpose flag should be 0x08, * which indicates the filename charset is UTF-8. */ assertEqualInt(0x08, buff[7]); /* Check UTF-8 version. */ assertEqualMem(buff + 30, "\xE8\xA1\xA8.txt", 7); /* * Verify that CP932/SJIS filenames are not translated to UTF-8. */ a = archive_write_new(); assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); assertEqualInt(ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff), &used)); entry = archive_entry_new2(a); /* Set a CP932/SJIS filename. */ archive_entry_set_pathname(entry, "\x95\x5C.txt"); /* Check the Unicode version. */ archive_entry_set_filetype(entry, AE_IFREG); archive_entry_set_size(entry, 0); assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* A bit 11 of general purpose flag should be 0, * which indicates the filename charset is unknown. */ assertEqualInt(0, buff[7]); /* Above three characters in CP932/SJIS should not translate to * any character-set. */ assertEqualMem(buff + 30, "\x95\x5C.txt", 6); /* * Verify that A bit 11 of general purpose flag is not set * when ASCII filenames are stored even if hdrcharset=UTF-8 * is specified. */ a = archive_write_new(); assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { skipping("This system cannot convert character-set" " from CP932/SJIS to UTF-8."); archive_write_free(a); return; } assertEqualInt(ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff), &used)); entry = archive_entry_new2(a); /* Set an ASCII filename. */ archive_entry_set_pathname(entry, "abcABC"); /* Check the Unicode version. */ archive_entry_set_filetype(entry, AE_IFREG); archive_entry_set_size(entry, 0); assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* A bit 11 of general purpose flag should be 0, * which indicates the filename charset is unknown. */ assertEqualInt(0, buff[7]); assertEqualMem(buff + 30, "abcABC", 6); }
////////////////////////////////////////////////////////////////////// // 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; }
void tar_mode_u(struct bsdtar *bsdtar) { int64_t end_offset; struct archive *a; struct archive_entry *entry; int format; struct archive_dir_entry *p; struct archive_dir archive_dir; bsdtar->archive_dir = &archive_dir; memset(&archive_dir, 0, sizeof(archive_dir)); format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED; /* Sanity-test some arguments and the file. */ test_for_append(bsdtar); bsdtar->fd = open(bsdtar->filename, O_RDWR | O_BINARY); if (bsdtar->fd < 0) lafe_errc(1, errno, "Cannot open %s", bsdtar->filename); a = archive_read_new(); archive_read_support_filter_all(a); archive_read_support_format_tar(a); archive_read_support_format_gnutar(a); if (archive_read_open_fd(a, bsdtar->fd, bsdtar->bytes_per_block) != ARCHIVE_OK) { lafe_errc(1, 0, "Can't open %s: %s", bsdtar->filename, archive_error_string(a)); } /* Build a list of all entries and their recorded mod times. */ while (0 == archive_read_next_header(a, &entry)) { if (archive_compression(a) != ARCHIVE_COMPRESSION_NONE) { archive_read_free(a); close(bsdtar->fd); lafe_errc(1, 0, "Cannot append to compressed archive."); } add_dir_list(bsdtar, archive_entry_pathname(entry), archive_entry_mtime(entry), archive_entry_mtime_nsec(entry)); /* Record the last format determination we see */ format = archive_format(a); /* Keep going until we hit end-of-archive */ } end_offset = archive_read_header_position(a); archive_read_free(a); /* Re-open archive for writing. */ a = archive_write_new(); /* * Set format to same one auto-detected above. */ archive_write_set_format(a, format); archive_write_set_bytes_per_block(a, bsdtar->bytes_per_block); archive_write_set_bytes_in_last_block(a, bsdtar->bytes_in_last_block); if (lseek(bsdtar->fd, end_offset, SEEK_SET) < 0) lafe_errc(1, errno, "Could not seek to archive end"); if (ARCHIVE_OK != archive_write_set_options(a, bsdtar->option_options)) lafe_errc(1, 0, "%s", archive_error_string(a)); if (ARCHIVE_OK != archive_write_open_fd(a, bsdtar->fd)) lafe_errc(1, 0, "%s", archive_error_string(a)); write_archive(a, bsdtar); close(bsdtar->fd); bsdtar->fd = -1; while (bsdtar->archive_dir->head != NULL) { p = bsdtar->archive_dir->head->next; free(bsdtar->archive_dir->head->name); free(bsdtar->archive_dir->head); bsdtar->archive_dir->head = p; } bsdtar->archive_dir->tail = NULL; }
static void test_zip_filename_encoding_KOI8R(void) { struct archive *a; struct archive_entry *entry; char buff[4096]; size_t used; if (NULL == setlocale(LC_ALL, "ru_RU.KOI8-R")) { skipping("KOI8-R locale not available on this system."); return; } /* * Verify that KOI8-R filenames are correctly translated to UTF-8. */ a = archive_write_new(); assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { skipping("This system cannot convert character-set" " from KOI8-R to UTF-8."); archive_write_free(a); return; } assertEqualInt(ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff), &used)); entry = archive_entry_new2(a); /* Set a KOI8-R filename. */ archive_entry_set_pathname(entry, "\xD0\xD2\xC9"); archive_entry_set_filetype(entry, AE_IFREG); archive_entry_set_size(entry, 0); assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* A bit 11 of general purpose flag should be 0x08, * which indicates the filename charset is UTF-8. */ assertEqualInt(0x08, buff[7]); /* Above three characters in KOI8-R should translate to the following * three characters (two bytes each) in UTF-8. */ assertEqualMem(buff + 30, "\xD0\xBF\xD1\x80\xD0\xB8", 6); /* * Verify that KOI8-R filenames are not translated to UTF-8. */ a = archive_write_new(); assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); assertEqualInt(ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff), &used)); entry = archive_entry_new2(a); /* Set a KOI8-R filename. */ archive_entry_set_pathname(entry, "\xD0\xD2\xC9"); archive_entry_set_filetype(entry, AE_IFREG); archive_entry_set_size(entry, 0); assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* A bit 11 of general purpose flag should be 0, * which indicates the filename charset is unknown. */ assertEqualInt(0, buff[7]); /* Above three characters in KOI8-R should not translate to * any character-set. */ assertEqualMem(buff + 30, "\xD0\xD2\xC9", 3); /* * Verify that A bit 11 of general purpose flag is not set * when ASCII filenames are stored even if hdrcharset=UTF-8 * is specified. */ a = archive_write_new(); assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { skipping("This system cannot convert character-set" " from KOI8-R to UTF-8."); archive_write_free(a); return; } assertEqualInt(ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff), &used)); entry = archive_entry_new2(a); /* Set an ASCII filename. */ archive_entry_set_pathname(entry, "abcABC"); archive_entry_set_filetype(entry, AE_IFREG); archive_entry_set_size(entry, 0); assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* A bit 11 of general purpose flag should be 0, * which indicates the filename charset is unknown. */ assertEqualInt(0, buff[7]); assertEqualMem(buff + 30, "abcABC", 6); }
void tar_mode_u(struct bsdtar *bsdtar) { off_t end_offset; struct archive *a; struct archive_entry *entry; int format; struct archive_dir_entry *p; struct archive_dir archive_dir; bsdtar->archive_dir = &archive_dir; memset(&archive_dir, 0, sizeof(archive_dir)); format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED; /* Sanity-test some arguments and the file. */ test_for_append(bsdtar); bsdtar->fd = open(bsdtar->filename, O_RDWR); if (bsdtar->fd < 0) bsdtar_errc(bsdtar, 1, errno, "Cannot open %s", bsdtar->filename); a = archive_read_new(); archive_read_support_compression_all(a); archive_read_support_format_tar(a); archive_read_support_format_gnutar(a); if (archive_read_open_fd(a, bsdtar->fd, bsdtar->bytes_per_block != 0 ? bsdtar->bytes_per_block : DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) { bsdtar_errc(bsdtar, 1, 0, "Can't open %s: %s", bsdtar->filename, archive_error_string(a)); } /* Build a list of all entries and their recorded mod times. */ while (0 == archive_read_next_header(a, &entry)) { if (archive_compression(a) != ARCHIVE_COMPRESSION_NONE) { archive_read_finish(a); close(bsdtar->fd); bsdtar_errc(bsdtar, 1, 0, "Cannot append to compressed archive."); } add_dir_list(bsdtar, archive_entry_pathname(entry), archive_entry_mtime(entry), archive_entry_mtime_nsec(entry)); /* Record the last format determination we see */ format = archive_format(a); /* Keep going until we hit end-of-archive */ } end_offset = archive_read_header_position(a); archive_read_finish(a); /* Re-open archive for writing. */ a = archive_write_new(); archive_write_set_compression_none(a); /* * Set format to same one auto-detected above, except that * we don't write GNU tar format, so use ustar instead. */ if (format == ARCHIVE_FORMAT_TAR_GNUTAR) format = ARCHIVE_FORMAT_TAR_USTAR; archive_write_set_format(a, format); if (bsdtar->bytes_per_block != 0) { archive_write_set_bytes_per_block(a, bsdtar->bytes_per_block); archive_write_set_bytes_in_last_block(a, bsdtar->bytes_per_block); } else archive_write_set_bytes_per_block(a, DEFAULT_BYTES_PER_BLOCK); lseek(bsdtar->fd, end_offset, SEEK_SET); ftruncate(bsdtar->fd, end_offset); if (ARCHIVE_OK != archive_write_set_options(a, bsdtar->option_options)) bsdtar_errc(bsdtar, 1, 0, archive_error_string(a)); if (ARCHIVE_OK != archive_write_open_fd(a, bsdtar->fd)) bsdtar_errc(bsdtar, 1, 0, archive_error_string(a)); write_archive(a, bsdtar); close(bsdtar->fd); bsdtar->fd = -1; while (bsdtar->archive_dir->head != NULL) { p = bsdtar->archive_dir->head->next; free(bsdtar->archive_dir->head->name); free(bsdtar->archive_dir->head); bsdtar->archive_dir->head = p; } bsdtar->archive_dir->tail = NULL; }
void tar_mode_c(struct bsdtar *bsdtar) { struct archive *a; int r; if (*bsdtar->argv == NULL && bsdtar->names_from_file == NULL) bsdtar_errc(bsdtar, 1, 0, "no files or directories specified"); a = archive_write_new(); /* Support any format that the library supports. */ if (bsdtar->create_format == NULL) { r = archive_write_set_format_pax_restricted(a); bsdtar->create_format = "pax restricted"; } else { r = archive_write_set_format_by_name(a, bsdtar->create_format); } if (r != ARCHIVE_OK) { fprintf(stderr, "Can't use format %s: %s\n", bsdtar->create_format, archive_error_string(a)); usage(bsdtar); } /* * If user explicitly set the block size, then assume they * want the last block padded as well. Otherwise, use the * default block size and accept archive_write_open_file()'s * default padding decisions. */ if (bsdtar->bytes_per_block != 0) { archive_write_set_bytes_per_block(a, bsdtar->bytes_per_block); archive_write_set_bytes_in_last_block(a, bsdtar->bytes_per_block); } else archive_write_set_bytes_per_block(a, DEFAULT_BYTES_PER_BLOCK); if (bsdtar->compress_program) { archive_write_set_compression_program(a, bsdtar->compress_program); } else { switch (bsdtar->create_compression) { case 0: archive_write_set_compression_none(a); break; #ifdef HAVE_LIBBZ2 case 'j': case 'y': archive_write_set_compression_bzip2(a); break; #endif #ifdef HAVE_LIBLZMA case 'J': archive_write_set_compression_xz(a); break; case OPTION_LZMA: archive_write_set_compression_lzma(a); break; #endif #ifdef HAVE_LIBZ case 'z': archive_write_set_compression_gzip(a); break; #endif case 'Z': archive_write_set_compression_compress(a); break; default: bsdtar_errc(bsdtar, 1, 0, "Unrecognized compression option -%c", bsdtar->create_compression); } } if (ARCHIVE_OK != archive_write_set_options(a, bsdtar->option_options)) bsdtar_errc(bsdtar, 1, 0, archive_error_string(a)); if (ARCHIVE_OK != archive_write_open_file(a, bsdtar->filename)) bsdtar_errc(bsdtar, 1, 0, archive_error_string(a)); write_archive(a, bsdtar); }
void tar_mode_c(struct bsdtar *bsdtar) { struct archive *a; int r; if (*bsdtar->argv == NULL && bsdtar->names_from_file == NULL) lafe_errc(1, 0, "no files or directories specified"); a = archive_write_new(); /* Support any format that the library supports. */ if (bsdtar->create_format == NULL) { r = archive_write_set_format_pax_restricted(a); bsdtar->create_format = "pax restricted"; } else { r = archive_write_set_format_by_name(a, bsdtar->create_format); } if (r != ARCHIVE_OK) { fprintf(stderr, "Can't use format %s: %s\n", bsdtar->create_format, archive_error_string(a)); usage(); } archive_write_set_bytes_per_block(a, bsdtar->bytes_per_block); archive_write_set_bytes_in_last_block(a, bsdtar->bytes_in_last_block); if (bsdtar->compress_program) { archive_write_set_compression_program(a, bsdtar->compress_program); } else { switch (bsdtar->create_compression) { case 0: r = ARCHIVE_OK; break; case 'j': case 'y': r = archive_write_set_compression_bzip2(a); break; case 'J': r = archive_write_set_compression_xz(a); break; case OPTION_LZIP: r = archive_write_set_compression_lzip(a); break; case OPTION_LZMA: r = archive_write_set_compression_lzma(a); break; case 'z': r = archive_write_set_compression_gzip(a); break; case 'Z': r = archive_write_set_compression_compress(a); break; default: lafe_errc(1, 0, "Unrecognized compression option -%c", bsdtar->create_compression); } if (r != ARCHIVE_OK) { lafe_errc(1, 0, "Unsupported compression option -%c", bsdtar->create_compression); } } if (ARCHIVE_OK != archive_write_set_options(a, bsdtar->option_options)) lafe_errc(1, 0, "%s", archive_error_string(a)); if (ARCHIVE_OK != archive_write_open_file(a, bsdtar->filename)) lafe_errc(1, 0, "%s", archive_error_string(a)); write_archive(a, bsdtar); }
/* * Same as 'c', except we only support tar or empty formats in * uncompressed files on disk. */ void tar_mode_r(struct bsdtar *bsdtar) { int64_t end_offset; int format; struct archive *a; struct archive_entry *entry; int r; /* Sanity-test some arguments and the file. */ test_for_append(bsdtar); format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED; #if defined(__BORLANDC__) bsdtar->fd = open(bsdtar->filename, O_RDWR | O_CREAT | O_BINARY); #else bsdtar->fd = open(bsdtar->filename, O_RDWR | O_CREAT | O_BINARY, 0666); #endif if (bsdtar->fd < 0) lafe_errc(1, errno, "Cannot open %s", bsdtar->filename); a = archive_read_new(); archive_read_support_filter_all(a); archive_read_support_format_tar(a); archive_read_support_format_gnutar(a); r = archive_read_open_fd(a, bsdtar->fd, 10240); if (r != ARCHIVE_OK) lafe_errc(1, archive_errno(a), "Can't read archive %s: %s", bsdtar->filename, archive_error_string(a)); while (0 == archive_read_next_header(a, &entry)) { if (archive_compression(a) != ARCHIVE_COMPRESSION_NONE) { archive_read_free(a); close(bsdtar->fd); lafe_errc(1, 0, "Cannot append to compressed archive."); } /* Keep going until we hit end-of-archive */ format = archive_format(a); } end_offset = archive_read_header_position(a); archive_read_free(a); /* Re-open archive for writing */ a = archive_write_new(); /* * Set the format to be used for writing. To allow people to * extend empty files, we need to allow them to specify the format, * which opens the possibility that they will specify a format that * doesn't match the existing format. Hence, the following bit * of arcane ugliness. */ if (bsdtar->create_format != NULL) { /* If the user requested a format, use that, but ... */ archive_write_set_format_by_name(a, bsdtar->create_format); /* ... complain if it's not compatible. */ format &= ARCHIVE_FORMAT_BASE_MASK; if (format != (int)(archive_format(a) & ARCHIVE_FORMAT_BASE_MASK) && format != ARCHIVE_FORMAT_EMPTY) { lafe_errc(1, 0, "Format %s is incompatible with the archive %s.", bsdtar->create_format, bsdtar->filename); } } else { /* * Just preserve the current format, with a little care * for formats that libarchive can't write. */ if (format == ARCHIVE_FORMAT_EMPTY) format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED; archive_write_set_format(a, format); } if (lseek(bsdtar->fd, end_offset, SEEK_SET) < 0) lafe_errc(1, errno, "Could not seek to archive end"); if (ARCHIVE_OK != archive_write_set_options(a, bsdtar->option_options)) lafe_errc(1, 0, "%s", archive_error_string(a)); if (ARCHIVE_OK != archive_write_open_fd(a, bsdtar->fd)) lafe_errc(1, 0, "%s", archive_error_string(a)); write_archive(a, bsdtar); /* XXX check return val XXX */ close(bsdtar->fd); bsdtar->fd = -1; }
static void test_zip_filename_encoding_UTF8(void) { struct archive *a; struct archive_entry *entry; char buff[4096]; size_t used; if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) { skipping("en_US.UTF-8 locale not available on this system."); return; } /* * Verify that UTF-8 filenames are correctly stored with * hdrcharset=UTF-8 option. */ a = archive_write_new(); assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { skipping("This system cannot convert character-set" " for UTF-8."); archive_write_free(a); return; } assertEqualInt(ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff), &used)); entry = archive_entry_new2(a); /* Set a UTF-8 filename. */ archive_entry_set_pathname(entry, "\xD0\xBF\xD1\x80\xD0\xB8"); archive_entry_set_filetype(entry, AE_IFREG); archive_entry_set_size(entry, 0); assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* A bit 11 of general purpose flag should be 0x08, * which indicates the filename charset is UTF-8. */ assertEqualInt(0x08, buff[7]); assertEqualMem(buff + 30, "\xD0\xBF\xD1\x80\xD0\xB8", 6); /* * Verify that UTF-8 filenames are correctly stored without * hdrcharset=UTF-8 option. */ a = archive_write_new(); assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); assertEqualInt(ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff), &used)); entry = archive_entry_new2(a); /* Set a UTF-8 filename. */ archive_entry_set_pathname(entry, "\xD0\xBF\xD1\x80\xD0\xB8"); archive_entry_set_filetype(entry, AE_IFREG); archive_entry_set_size(entry, 0); assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* A bit 11 of general purpose flag should be 0x08, * which indicates the filename charset is UTF-8. */ assertEqualInt(0x08, buff[7]); assertEqualMem(buff + 30, "\xD0\xBF\xD1\x80\xD0\xB8", 6); /* * Verify that A bit 11 of general purpose flag is not set * when ASCII filenames are stored. */ a = archive_write_new(); assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); assertEqualInt(ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff), &used)); entry = archive_entry_new2(a); /* Set an ASCII filename. */ archive_entry_set_pathname(entry, "abcABC"); archive_entry_set_filetype(entry, AE_IFREG); archive_entry_set_size(entry, 0); assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* A bit 11 of general purpose flag should be 0, * which indicates the filename charset is unknown. */ assertEqualInt(0, buff[7]); assertEqualMem(buff + 30, "abcABC", 6); }
/* * Other archiver applications on Windows translate CP1251 filenames * into CP866 filenames and store it in the zip file. * Test above behavior works well. */ static void test_zip_filename_encoding_Russian_Russia(void) { struct archive *a; struct archive_entry *entry; char buff[4096]; size_t used; if (NULL == setlocale(LC_ALL, "Russian_Russia")) { skipping("Russian_Russia locale not available on this system."); return; } /* * Verify that Russian_Russia(CP1251) filenames are correctly translated * to UTF-8. */ a = archive_write_new(); assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { skipping("This system cannot convert character-set" " from Russian_Russia.CP1251 to UTF-8."); archive_write_free(a); return; } assertEqualInt(ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff), &used)); entry = archive_entry_new2(a); /* Set a CP1251 filename. */ archive_entry_set_pathname(entry, "\xEF\xF0\xE8"); archive_entry_set_filetype(entry, AE_IFREG); archive_entry_set_size(entry, 0); assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* A bit 11 of general purpose flag should be 0x08, * which indicates the filename charset is UTF-8. */ assertEqualInt(0x08, buff[7]); /* Above three characters in CP1251 should translate to the following * three characters (two bytes each) in UTF-8. */ assertEqualMem(buff + 30, "\xD0\xBF\xD1\x80\xD0\xB8", 6); /* * Verify that Russian_Russia(CP1251) filenames are correctly translated * to CP866. */ a = archive_write_new(); assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); assertEqualInt(ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff), &used)); entry = archive_entry_new2(a); /* Set a CP1251 filename. */ archive_entry_set_pathname(entry, "\xEF\xF0\xE8"); archive_entry_set_filetype(entry, AE_IFREG); archive_entry_set_size(entry, 0); assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* A bit 11 of general purpose flag should be 0, * which indicates the filename charset is unknown. */ assertEqualInt(0, buff[7]); /* Above three characters in CP1251 should translate to the following * three characters in CP866. */ assertEqualMem(buff + 30, "\xAF\xE0\xA8", 3); }
static int create_iso_image(unsigned char *buff, size_t buffsize, size_t *used, const char *opt) { struct archive *a; int i, l, fcnt; const int lens[] = { 0, 1, 3, 5, 7, 8, 9, 29, 30, 31, 32, 62, 63, 64, 65, 101, 102, 103, 104, 191, 192, 193, 194, 204, 205, 206, 207, 208, 252, 253, 254, 255, -1 }; char fname1[256]; char fname2[256]; char sym1[2]; char sym128[129]; char sym255[256]; /* ISO9660 format: Create a new archive in memory. */ assert((a = archive_write_new()) != NULL); assertA(0 == archive_write_set_format_iso9660(a)); assertA(0 == archive_write_add_filter_none(a)); assertA(0 == archive_write_set_option(a, NULL, "pad", NULL)); if (opt) assertA(0 == archive_write_set_options(a, opt)); assertA(0 == archive_write_set_bytes_per_block(a, 1)); assertA(0 == archive_write_set_bytes_in_last_block(a, 1)); assertA(0 == archive_write_open_memory(a, buff, buffsize, used)); sym1[0] = 'x'; sym1[1] = '\0'; for (i = 0; i < (int)sizeof(sym128)-2; i++) sym128[i] = 'a'; sym128[sizeof(sym128)-2] = 'x'; sym128[sizeof(sym128)-1] = '\0'; for (i = 0; i < (int)sizeof(sym255)-2; i++) sym255[i] = 'a'; sym255[sizeof(sym255)-2] = 'x'; sym255[sizeof(sym255)-1] = '\0'; fcnt = 0; for (i = 0; lens[i] >= 0; i++) { for (l = 0; l < lens[i]; l++) { fname1[l] = 'a'; fname2[l] = 'A'; } if (l > 0) { fname1[l] = '\0'; fname2[l] = '\0'; add_entry(a, fname1, NULL); add_entry(a, fname2, sym1); fcnt += 2; } if (l < 254) { fname1[l] = '.'; fname1[l+1] = 'c'; fname1[l+2] = '\0'; fname2[l] = '.'; fname2[l+1] = 'C'; fname2[l+2] = '\0'; add_entry(a, fname1, sym128); add_entry(a, fname2, sym255); fcnt += 2; } if (l < 252) { fname1[l] = '.'; fname1[l+1] = 'p'; fname1[l+2] = 'n'; fname1[l+3] = 'g'; fname1[l+4] = '\0'; fname2[l] = '.'; fname2[l+1] = 'P'; fname2[l+2] = 'N'; fname2[l+3] = 'G'; fname2[l+4] = '\0'; add_entry(a, fname1, NULL); add_entry(a, fname2, sym1); fcnt += 2; } if (l < 251) { fname1[l] = '.'; fname1[l+1] = 'j'; fname1[l+2] = 'p'; fname1[l+3] = 'e'; fname1[l+4] = 'g'; fname1[l+5] = '\0'; fname2[l] = '.'; fname2[l+1] = 'J'; fname2[l+2] = 'P'; fname2[l+3] = 'E'; fname2[l+4] = 'G'; fname2[l+5] = '\0'; add_entry(a, fname1, sym128); add_entry(a, fname2, sym255); fcnt += 2; } } /* Close out the archive. */ assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); return (fcnt); }