Пример #1
0
static gboolean
asb_utils_write_archive (const gchar *filename,
			 const gchar *path_orig,
			 GPtrArray *files,
			 GError **error)
{
	const gchar *tmp;
	gboolean ret = TRUE;
	gsize len;
	guint i;
	struct archive *a;
	struct archive_entry *entry;
	struct stat st;

	a = archive_write_new ();
	if (g_str_has_suffix (filename, ".gz")) {
		archive_write_add_filter_gzip (a);
		archive_write_set_filter_option (a, "gzip", "timestamp", NULL);
	}
	if (g_str_has_suffix (filename, ".bz2"))
		archive_write_add_filter_bzip2 (a);
	if (g_str_has_suffix (filename, ".xz"))
		archive_write_add_filter_xz (a);
	archive_write_set_format_pax_restricted (a);
	archive_write_open_filename (a, filename);
	for (i = 0; i < files->len; i++) {
		g_autofree gchar *data = NULL;
		g_autofree gchar *filename_full = NULL;

		tmp = g_ptr_array_index (files, i);
		filename_full = g_build_filename (path_orig, tmp, NULL);
		if (stat (filename_full, &st) != 0)
			continue;
		entry = archive_entry_new ();
		archive_entry_set_pathname (entry, tmp);
		archive_entry_set_size (entry, st.st_size);
		archive_entry_set_filetype (entry, AE_IFREG);
		archive_entry_set_perm (entry, 0644);
		archive_write_header (a, entry);
		ret = g_file_get_contents (filename_full, &data, &len, error);
		if (!ret) {
			archive_entry_free (entry);
			break;
		}
		archive_write_data (a, data, len);
		archive_entry_free (entry);
	}
	archive_write_close (a);
	archive_write_free (a);
	return ret;
}
Пример #2
0
int
packing_init(struct packing **pack, const char *path, pkg_formats format)
{
	char archive_path[MAXPATHLEN];
	const char *ext;

	assert(pack != NULL);

	if ((*pack = calloc(1, sizeof(struct packing))) == NULL) {
		pkg_emit_errno("malloc", "packing");
		return (EPKG_FATAL);
	}

	(*pack)->aread = archive_read_disk_new();
	archive_read_disk_set_standard_lookup((*pack)->aread);
	archive_read_disk_set_symlink_physical((*pack)->aread);

	if (!is_dir(path)) {
		(*pack)->awrite = archive_write_new();
		archive_write_set_format_pax_restricted((*pack)->awrite);
		ext = packing_set_format((*pack)->awrite, format);
		if (ext == NULL) {
			archive_read_finish((*pack)->aread);
			archive_write_finish((*pack)->awrite);
			*pack = NULL;
			return EPKG_FATAL; /* error set by _set_format() */
		}
		snprintf(archive_path, sizeof(archive_path), "%s.%s", path,
		    ext);

		if (archive_write_open_filename(
		    (*pack)->awrite, archive_path) != ARCHIVE_OK) {
			pkg_emit_errno("archive_write_open_filename",
			    archive_path);
			archive_read_finish((*pack)->aread);
			archive_write_finish((*pack)->awrite);
			*pack = NULL;
			return EPKG_FATAL;
		}
	} else { /* pass mode directly write to the disk */
		(*pack)->awrite = archive_write_disk_new();
		archive_write_disk_set_options((*pack)->awrite,
		    EXTRACT_ARCHIVE_FLAGS);
	}

	(*pack)->resolver = archive_entry_linkresolver_new();
	archive_entry_linkresolver_set_strategy((*pack)->resolver,
	    ARCHIVE_FORMAT_TAR_PAX_RESTRICTED);
	return (EPKG_OK);
}
Пример #3
0
void write_archive(const char *outname, const char **filename) {
  struct archive *a;
  
  a = archive_write_new();
  archive_write_set_format_zip(a);
  archive_write_open_filename(a, outname);

  while(*filename) {
    file_to_archive(a, *filename);
    filename++;
  }

  archive_write_close(a);
  archive_write_free(a);
}
Пример #4
0
static int archive_conv_open(struct archive_conv *conv,
                             const struct repo_t *repo) {
  int r;

  /* generally, repo files are gzip compressed, but there's no guarantee of
   * this. in order to be compression-agnostic, use libarchive's reader/writer
   * methods. this also gives us an opportunity to rewrite the archive as CPIO,
   * which is marginally faster given our staunch sequential access. */

  conv->reponame = repo->name;
  stpcpy(stpcpy(conv->tmpfile, repo->diskfile), "~");

  conv->in = archive_read_new();
  conv->out = archive_write_new();

  if (conv->in == NULL || conv->out == NULL) {
    fputs("error: failed to allocate memory for archive objects\n", stderr);
    return -ENOMEM;
  }

  archive_read_support_format_tar(conv->in);
  archive_read_support_filter_all(conv->in);
  r = archive_read_open_fd(conv->in, repo->tmpfile.fd, BUFSIZ);
  if (r != ARCHIVE_OK) {
    fprintf(stderr, "error: failed to create archive reader for %s: %s\n",
            repo->name, strerror(archive_errno(conv->in)));
    r = archive_errno(conv->in);
    goto open_error;
  }

  archive_write_set_format_cpio_newc(conv->out);
  archive_write_add_filter(conv->out, repo->config->compress);
  r = archive_write_open_filename(conv->out, conv->tmpfile);
  if (r != ARCHIVE_OK) {
    fprintf(stderr, "error: failed to open file for writing: %s: %s\n",
            conv->tmpfile, strerror(archive_errno(conv->out)));
    r = archive_errno(conv->out);
    goto open_error;
  }

  return 0;

open_error:
  archive_write_free(conv->out);
  archive_read_free(conv->in);

  return -r;
}
Пример #5
0
void
tar_mode_c(struct bsdtar *bsdtar)
{
    struct archive *a;
    const void *filter_name;
    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 (cset_get_format(bsdtar->cset) == NULL) {
        r = archive_write_set_format_pax_restricted(a);
        cset_set_format(bsdtar->cset, "pax restricted");
    } else {
        r = archive_write_set_format_by_name(a,
                                             cset_get_format(bsdtar->cset));
    }
    if (r != ARCHIVE_OK) {
        fprintf(stderr, "Can't use format %s: %s\n",
                cset_get_format(bsdtar->cset),
                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);

    r = cset_write_add_filters(bsdtar->cset, a, &filter_name);
    if (r < ARCHIVE_WARN) {
        lafe_errc(1, 0, "Unsupported compression option --%s",
                  (const char *)filter_name);
    }

    set_writer_options(bsdtar, a);
    if (bsdtar->passphrase != NULL)
        r = archive_write_set_passphrase(a, bsdtar->passphrase);
    else
        r = archive_write_set_passphrase_callback(a, bsdtar,
                &passphrase_callback);
    if (r != ARCHIVE_OK)
        lafe_errc(1, 0, "%s", archive_error_string(a));
    if (ARCHIVE_OK != archive_write_open_filename(a, bsdtar->filename))
        lafe_errc(1, 0, "%s", archive_error_string(a));
    write_archive(a, bsdtar);
}
Пример #6
0
int
packing_init(struct packing **pack, const char *path, pkg_formats format)
{
	char archive_path[MAXPATHLEN];
	const char *ext;

	assert(pack != NULL);

	*pack = xcalloc(1, sizeof(struct packing));

	(*pack)->aread = archive_read_disk_new();
	archive_read_disk_set_standard_lookup((*pack)->aread);
	archive_read_disk_set_symlink_physical((*pack)->aread);

	(*pack)->awrite = archive_write_new();
	archive_write_set_format_pax_restricted((*pack)->awrite);
	ext = packing_set_format((*pack)->awrite, format);
	if (ext == NULL) {
		archive_read_close((*pack)->aread);
		archive_read_free((*pack)->aread);
		archive_write_close((*pack)->awrite);
		archive_write_free((*pack)->awrite);
		*pack = NULL;
		return EPKG_FATAL; /* error set by _set_format() */
	}
	snprintf(archive_path, sizeof(archive_path), "%s.%s", path,
	    ext);

	pkg_debug(1, "Packing to file '%s'", archive_path);
	if (archive_write_open_filename(
	    (*pack)->awrite, archive_path) != ARCHIVE_OK) {
		pkg_emit_errno("archive_write_open_filename",
		    archive_path);
		archive_read_close((*pack)->aread);
		archive_read_free((*pack)->aread);
		archive_write_close((*pack)->awrite);
		archive_write_free((*pack)->awrite);
		*pack = NULL;
		return EPKG_FATAL;
	}

	(*pack)->resolver = archive_entry_linkresolver_new();
	archive_entry_linkresolver_set_strategy((*pack)->resolver,
	    archive_format((*pack)->awrite));

	return (EPKG_OK);
}
Пример #7
0
Writer *Writer::write_open_filename(const char *filename,
    int compression, int format)
{
    std::string error_msg;
    struct archive *ar = archive_write_new();

    try {

        switch(compression) {
            case Archive::COMPRESSION_BZIP2:
                archive_write_add_filter_bzip2(ar);
                break;
            case Archive::COMPRESSION_COMPRESS:
                archive_write_add_filter_compress(ar);
                break;
            case Archive::COMPRESSION_GZIP:
                archive_write_add_filter_gzip(ar);
                break;
            case Archive::COMPRESSION_LZMA:
                archive_write_add_filter_lzma(ar);
                break;
            case Archive::COMPRESSION_NONE:
                archive_write_add_filter_none(ar);
                break;
            case Archive::COMPRESSION_XZ:
                archive_write_add_filter_xz(ar);
                break;
            default:
                error_msg = "unknown or unsupported compression scheme";
                throw Error(error_msg);
        }

        set_format_helper(ar, format);

        if(archive_write_open_filename(ar, filename) != ARCHIVE_OK) {
            error_msg = archive_error_string(ar);
            throw Error(error_msg);
        }

    } catch(...) {
        archive_write_free(ar);
        throw;
    }

    return new Writer(ar);
}
Пример #8
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));
}
Пример #9
0
Status Carver::compress(const std::set<boost::filesystem::path>& paths) {
  auto arch = archive_write_new();
  if (arch == nullptr) {
    return Status(1, "Failed to create tar archive");
  }
  // Zipping doesn't seem to be working currently
  // archive_write_set_format_zip(arch);
  archive_write_set_format_pax_restricted(arch);
  auto ret = archive_write_open_filename(arch, archivePath_.string().c_str());
  if (ret == ARCHIVE_FATAL) {
    archive_write_free(arch);
    return Status(1, "Failed to open tar archive for writing");
  }
  for (const auto& f : paths) {
    PlatformFile pFile(f.string(), PF_OPEN_EXISTING | PF_READ);

    auto entry = archive_entry_new();
    archive_entry_set_pathname(entry, f.leaf().string().c_str());
    archive_entry_set_size(entry, pFile.size());
    archive_entry_set_filetype(entry, AE_IFREG);
    archive_entry_set_perm(entry, 0644);
    // archive_entry_set_atime();
    // archive_entry_set_ctime();
    // archive_entry_set_mtime();
    archive_write_header(arch, entry);

    // TODO: Chunking or a max file size.
    std::ifstream in(f.string(), std::ios::binary);
    std::stringstream buffer;
    buffer << in.rdbuf();
    archive_write_data(arch, buffer.str().c_str(), buffer.str().size());
    in.close();
    archive_entry_free(entry);
  }
  archive_write_free(arch);

  PlatformFile archFile(archivePath_.string(), PF_OPEN_EXISTING | PF_READ);
  updateCarveValue(carveGuid_, "size", std::to_string(archFile.size()));
  updateCarveValue(
      carveGuid_,
      "sha256",
      hashFromFile(HashType::HASH_TYPE_SHA256, archivePath_.string()));

  return Status(0, "Ok");
};
Пример #10
0
void errorReporterClose(ErrorReporter self) {
#if HAVE_LIBARCHIVE
  struct archive* outArchive;
  CharString outputFilename = newCharString();
  LinkedList reportContents = newLinkedList();
#endif

  // Always do this, just in case
  flushErrorLog();

#if HAVE_LIBARCHIVE
  // In case any part of the error report causes a segfault, this function will
  // be called recursively. A mutex would really be a better solution here, but
  // this will also work just fine.
  if(!self->completed) {
    self->completed = true;
    buildAbsolutePath(self->desktopPath, self->reportName, "tar.gz", outputFilename);
    listDirectory(self->reportDirPath->data, reportContents);
    if(self != NULL) {
      outArchive = archive_write_new();
      archive_write_set_compression_gzip(outArchive);
      archive_write_set_format_pax_restricted(outArchive);
      archive_write_open_filename(outArchive, outputFilename->data);

      linkedListForeach(reportContents, _remapFileToErrorReportRelativePath, self);
      chdir(self->desktopPath->data);
      linkedListForeach(reportContents, _addFileToArchive, outArchive);

      archive_write_close(outArchive);
      archive_write_free(outArchive);
    }
    // Remove original error report
    removeDirectory(self->reportDirPath);
  }
#endif

  printf("\n=== Error report complete ===\n");
  printf("Created error report at %s\n", self->reportDirPath->data);
#if HAVE_LIBARCHIVE
  printf("Please email the report to: %s\n", SUPPORT_EMAIL);
#else
  printf("Please compress and email the report to: %s\n", SUPPORT_EMAIL);
#endif
  printf("Thanks!\n");
}
static void
test(int pristine)
{
	struct archive* a = archive_write_new();

	if (!pristine)
		archive_write_set_compression_gzip(a);

	should(a, ARCHIVE_OK, NULL, NULL, NULL);
	should(a, ARCHIVE_OK, "", "", "");

	should(a, ARCHIVE_FAILED, NULL, "fubar", NULL);
	should(a, ARCHIVE_FAILED, NULL, "fubar", "snafu");
	should(a, ARCHIVE_FAILED, "fubar", "snafu", NULL);
	should(a, ARCHIVE_FAILED, "fubar", "snafu", "betcha");

	archive_write_finish(a);
}
Пример #12
0
int archive_create_tar_bzip2(const char **pathnames) {
	int error = 0;
	
	struct archive *a = archive_write_new();
	archive_write_set_compression_bzip2(a);
	archive_write_set_format_ustar(a);
	archive_write_open_file(a, NULL);
	
	while (*pathnames) {
		append_path_recursively(*pathnames, a);
		pathnames++;
	}
	
	archive_write_close(a);
	archive_write_finish(a);
	
	return error;
}
Пример #13
0
void DTAR_write_header(struct archive *ar, uint64_t idx, uint64_t offset)
{

    const char * fname = mfu_flist_file_get_name(DTAR_flist, idx);

    /* fill up entry, FIXME: the uglyness of removing leading slash */
    struct archive_entry *entry = archive_entry_new();
    archive_entry_copy_pathname(entry, &fname[1]);

    if (DTAR_user_opts.preserve) {
        struct archive * source = archive_read_disk_new();
        archive_read_disk_set_standard_lookup(source);
        int fd = open(fname, O_RDONLY);
        if (archive_read_disk_entry_from_file(source, entry, fd, NULL) != ARCHIVE_OK) {
            MFU_LOG(MFU_LOG_ERR, "archive_read_disk_entry_from_file(): %s", archive_error_string(ar));
        }
        archive_read_free(source);
    } else {
        /* read stat info from mfu_flist */
        struct stat stbuf;
        mfu_lstat(fname, &stbuf);
        archive_entry_copy_stat(entry, &stbuf);
        const char* uname = mfu_flist_file_get_username(DTAR_flist, idx);
        archive_entry_set_uname(entry, uname);
        const char* gname = mfu_flist_file_get_groupname(DTAR_flist, idx);
        archive_entry_set_gname(entry, gname);
    }
    /* write entry info to archive */
    struct archive* dest = archive_write_new();
    archive_write_set_format_pax(dest);

    if (archive_write_open_fd(dest, DTAR_writer.fd_tar) != ARCHIVE_OK) {
        MFU_LOG(MFU_LOG_ERR, "archive_write_open_fd(): %s", archive_error_string(ar));
    }

    lseek64(DTAR_writer.fd_tar, offset, SEEK_SET);

    if (archive_write_header(dest, entry) != ARCHIVE_OK) {
        MFU_LOG(MFU_LOG_ERR, "archive_write_header(): %s", archive_error_string(ar));
    }
    archive_entry_free(entry);
    archive_write_free(dest);

}
Пример #14
0
static void create_archive(const char *filepath, const char *tarfile)
{
    struct archive *a;
    struct archive_entry *entry;
    struct stat st;
    char buff[8192];
    int len;
    int fd;
    char **filenames, **filename;

    filenames = list_filenames(filepath);
    filename = filenames;

    a = archive_write_new();
    archive_write_set_compression_bzip2(a);
    archive_write_set_format_ustar(a);
    archive_write_open_filename(a, tarfile);
    while (*filename) {
	stat(*filename, &st);
	entry = archive_entry_new();
	archive_entry_set_pathname(entry, *filename);
	archive_entry_set_size(entry, st.st_size);
	archive_entry_set_filetype(entry, AE_IFREG);
	archive_entry_set_perm(entry, 0644);
	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));
	}
	close(fd);
	archive_entry_free(entry);
	filename++;
    }

    free_str_array(filenames);
    archive_write_close(a);
#if ARCHIVE_VERSION_NUMBER < 4000000
    archive_write_finish(a);
#else
    archive_write_free(a);
#endif
}
Пример #15
0
/*
 * Initialize archive structure and create a shar archive.
 */
static struct archive *
shar_create(void)
{
	struct archive *a;

	if ((a = archive_write_new()) == NULL)
		errx(EXIT_FAILURE, "%s", archive_error_string(a));

	if (b_opt)
		archive_write_set_format_shar_dump(a);
	else
		archive_write_set_format_shar(a);
	archive_write_set_compression_none(a);

	if (archive_write_open_filename(a, o_arg) != ARCHIVE_OK)
		errx(EX_CANTCREAT, "%s", archive_error_string(a));

	return (a);
}
Пример #16
0
void Package::pack()
{
    struct archive *a;
    char buf[8192];

    std::string package_base_filename(mManifest.packageName() + "-"
        + std::to_string(mManifest.packageVersion()) + "-"
        + mManifest.targetArch());

    std::string tbz2_path = mWorkDir.string() + "/"
        + package_base_filename + ".rps";

    a = archive_write_new();
    archive_write_add_filter_bzip2(a);
    archive_write_set_format_pax_restricted(a);
    archive_write_open_filename(a, tbz2_path.c_str());

    struct stat st;
    struct archive_entry *entry;

    for (auto &f: mManifest.files()) {
        std::string source = mUnpackedDir.string() + std::string("/data/") + f.name();
        std::string dest = std::string("data/") + f.name();
        stat(source.c_str(), &st);
        entry = archive_entry_new();
        archive_entry_set_pathname(entry, dest.c_str());
        archive_entry_set_size(entry, st.st_size);
        archive_entry_set_filetype(entry, AE_IFREG);
        archive_entry_set_perm(entry, 0644);
        archive_write_header(a, entry);
        int fd = open(source.c_str(), O_RDONLY);
        int len = read(fd, buf, sizeof(buf));
        while (len > 0) {
            archive_write_data(a, buf, len);
            len = read(fd, buf, sizeof(buf));
        }
        close(fd);
        archive_entry_free(entry);
    }

    archive_write_close(a);
    archive_write_free(a);
}
Пример #17
0
int createArchiveofFiles(char** files, unsigned long * size,
		unsigned int fileCount, const char* filename) {
	unsigned int ctr = 0;
	struct timespec ts;
	struct archive_entry* entry;
	struct archive* archive = archive_write_new();
	if ((archive_write_set_compression_gzip(archive) != ARCHIVE_OK)
			|| (archive_write_set_format_ustar(archive) != ARCHIVE_OK)
			|| (archive_write_open_filename(archive, filename) != ARCHIVE_OK)) {
		printf("%s\n", archive_error_string(archive));
		return -1;
	}
	for (ctr = 0; ctr < fileCount; ctr++) {
		entry = archive_entry_new();
		clock_gettime(CLOCK_REALTIME, &ts);

		archive_entry_set_pathname(entry, files[ctr]);
		archive_entry_set_size(entry, size[ctr]);
		archive_entry_set_filetype(entry, AE_IFREG);
		archive_entry_set_perm(entry, 0444);
		archive_entry_set_atime(entry, ts.tv_sec, ts.tv_nsec);
		archive_entry_set_birthtime(entry, ts.tv_sec, ts.tv_nsec);
		archive_entry_set_ctime(entry, ts.tv_sec, ts.tv_nsec);
		archive_entry_set_mtime(entry, ts.tv_sec, ts.tv_nsec);

		int rc = archive_write_header(archive, entry);
		char *contents = new char[size[ctr]+1];
		FILE* fp = fopen(files[ctr],"rb");
		fread((void *)contents, size[ctr], 1, fp);
		fclose(fp);
		archive_write_data(archive, contents, size[ctr]);
		archive_entry_free(entry);
		entry = NULL;
		delete[] contents;
		if (ARCHIVE_OK != rc) {
			printf("%s\n", archive_error_string(archive));
			return -1;
		}
	}
	archive_write_finish(archive);
}
Пример #18
0
int test1()
{
	struct archive *a = archive_write_new();
	int ret = archive_write_set_format_zip(a);

	unsigned char buffer[100];
	int size;
	ret = archive_write_open_memory(a, buffer, 100, &size);

	// add a file
	struct archive_entry  *entry = archive_entry_new();

	archive_entry_set_pathname(entry, "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);
	printf("archive_write_header: ret=%d\n", ret);
	la_ssize_t n = archive_write_data(a, "world", 5);
	printf("archive_write_data: n=%d, error=%s\n", n, archive_error_string(a));


	// ad another file
	//
	archive_entry_clear(entry);
	archive_entry_set_pathname(entry, "somedir/yo.txt");
	archive_entry_set_size(entry, 5);
	archive_entry_set_filetype(entry, AE_IFREG);
	archive_entry_set_perm(entry, 0644);
	archive_write_header(a, entry);
	n = archive_write_data(a, "12345", 5);
	printf("archive_write_data: n=%d, error=%s\n", n, archive_error_string(a));

	archive_entry_free(entry);

	ret = archive_write_free(a);
	printf("archive_write_free: ret=%d, error=%s\n", ret, archive_error_string(a));

	printf("size=%d\n", size);
	write(1, buffer, size);
}
Пример #19
0
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");
    }
}
Пример #20
0
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));
}
Пример #21
0
/*
 * Do not translate CP1251 into CP866 if non Windows platform.
 */
static void
test_zip_filename_encoding_ru_RU_CP1251(void)
{
  	struct archive *a;
  	struct archive_entry *entry;
	char buff[4096];
	size_t used;

	if (NULL == setlocale(LC_ALL, "ru_RU.CP1251")) {
		skipping("Russian_Russia locale not available on this system.");
		return;
	}

	/*
	 * Verify that CP1251 filenames are not translated into any
	 * other character-set, in particular, 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 not translate into
	 * any other character-set. */
	assertEqualMem(buff + 30, "\xEF\xF0\xE8", 3);
}
Пример #22
0
static void
test(int pristine)
{
	struct archive* a = archive_write_new();
#ifdef BUILD_ISO_FORMAT
	int known_option_rv = pristine ? ARCHIVE_FAILED : ARCHIVE_OK;
#endif

	if (!pristine) {
		archive_write_add_filter_gzip(a);
#ifdef BUILD_ISO_FORMAT
		archive_write_set_format_iso9660(a);
#endif
        }

	/* NULL and "" denote `no option', so they're ok no matter
	 * what, if any, formats are registered */
	should(a, ARCHIVE_OK, NULL, NULL, NULL);
	should(a, ARCHIVE_OK, "", "", "");

	/* unknown modules and options */
	should(a, ARCHIVE_FAILED, "fubar", "snafu", NULL);
	should(a, ARCHIVE_FAILED, "fubar", "snafu", "betcha");

	/* unknown modules and options */
	should(a, ARCHIVE_FAILED, NULL, "snafu", NULL);
	should(a, ARCHIVE_FAILED, NULL, "snafu", "betcha");

#ifdef BUILD_ISO_FORMAT
	/* ARCHIVE_OK with iso9660 loaded, ARCHIVE_WARN otherwise */
	should(a, known_option_rv, "iso9660", "joliet", NULL);
	should(a, known_option_rv, "iso9660", "joliet", NULL);
	should(a, known_option_rv, NULL, "joliet", NULL);
	should(a, known_option_rv, NULL, "joliet", NULL);
#endif

	archive_write_free(a);
}
Пример #23
0
Writer *Writer::write_open_filename(const char *filename,
    const char *cmd, int format)

{
    std::string error_msg;
    struct archive *ar = archive_write_new();

    archive_write_add_filter_program(ar, cmd);
    try {
        set_format_helper(ar, format);

        if(archive_write_open_filename(ar, filename) != ARCHIVE_OK) {
            error_msg = archive_error_string(ar);
            throw Error(error_msg);
        }

    } catch(...) {
        archive_write_free(ar);
        throw;
    }

    return new Writer(ar);
}
Пример #24
0
// This function will create a gzipped tar file (outname)
// which contains the files matched by the function pattern_match.
// Pattern_match should return 0 on no match and 1 on match.
int create_archive(char *outname, char *path, 
                   const std::vector<std::string> &filenames)
{
    struct archive *a;
    struct archive_entry *entry;
    struct stat st;
    char buff[BUFFER_SIZE];
    int len;
    int fd;

    a = archive_write_new();
    archive_write_set_compression_gzip(a);
    archive_write_set_format_pax_restricted(a);
    archive_write_open_filename(a, outname);

    for (unsigned int i=0;i<filenames.size();i++) {
        stat(filenames[i].c_str(), &st);
        entry = archive_entry_new();
        archive_entry_set_pathname(entry, filenames[i].c_str());
        archive_entry_set_size(entry, st.st_size);
        archive_entry_set_filetype(entry, AE_IFREG);
        archive_entry_set_perm(entry, 0644);
        archive_write_header(a, entry);
        fd = open(filenames[i].c_str(), O_RDONLY);
        len = read(fd, buff, sizeof(buff));
        while (len > 0) {
            archive_write_data(a, buff, len);
            len = read(fd, buff, sizeof(buff));
        }
        close(fd);
    }

    archive_write_close(a);
    archive_write_finish(a);

    return 0;
}
Пример #25
0
static db_writer_t *db_writer_new(repo_t *repo, file_t *db)
{
    db_writer_t *writer = malloc(sizeof(db_writer_t));
    writer->archive = archive_write_new();
    writer->entry = archive_entry_new();

    switch (repo->compression) {
    case COMPRESS_NONE:
        archive_write_add_filter_none(writer->archive);
        break;
    case COMPRESS_GZIP:
        archive_write_add_filter_gzip(writer->archive);
        break;
    case COMPRESS_BZIP2:
        archive_write_add_filter_bzip2(writer->archive);
        break;
    case COMPRESS_XZ:
        archive_write_add_filter_xz(writer->archive);
        break;
    case COMPRESS_COMPRESS:
        archive_write_add_filter_compress(writer->archive);
        break;
    }

    archive_write_set_format_pax_restricted(writer->archive);

    writer->fd = openat(repo->dirfd, db->file, O_CREAT | O_WRONLY | O_TRUNC, 0644);
    if (writer->fd < 0)
        err(EXIT_FAILURE, "failed to open %s for writing", db->file);
    if (flock(writer->fd, LOCK_EX) < 0)
        err(EXIT_FAILURE, "failed to lock %s", db->file);

    archive_write_open_fd(writer->archive, writer->fd);
    buffer_init(&writer->buf, 1024);

    return writer;
}
Пример #26
0
int
packing_init(struct packing **pack, const char *path, pkg_formats format)
{
	char archive_path[MAXPATHLEN];
	const char *ext;

	if ((*pack = calloc(1, sizeof(struct packing))) == NULL) {
		pkg_emit_event(PKG_EVENT_MALLOC_ERROR, /*argc*/1,
		    strerror(errno));
	}

	(*pack)->aread = archive_read_disk_new();
	archive_read_disk_set_standard_lookup((*pack)->aread);
	archive_read_disk_set_symlink_physical((*pack)->aread);

	(*pack)->entry = archive_entry_new();

	if (!is_dir(path)) {
		(*pack)->awrite = archive_write_new();
		archive_write_set_format_pax_restricted((*pack)->awrite);
		if ((ext = packing_set_format((*pack)->awrite, format)) == NULL) {
			archive_read_finish((*pack)->aread);
			archive_write_finish((*pack)->awrite);
			archive_entry_free((*pack)->entry);
			return EPKG_FATAL; /* error set by _set_format() */
		}
		snprintf(archive_path, sizeof(archive_path), "%s.%s", path, ext);

		archive_write_open_filename((*pack)->awrite, archive_path);
	} else { /* pass mode directly write to the disk */
		(*pack)->awrite = archive_write_disk_new();
		archive_write_disk_set_options((*pack)->awrite, EXTRACT_ARCHIVE_FLAGS);
	}

	return (EPKG_OK);
}
Пример #27
0
static void
test_filename(const char *prefix, int dlen, int flen)
{
	char buff[8192];
	char filename[400];
	char dirname[400];
	struct archive_entry *ae;
	struct archive *a;
	size_t used;
	int separator = 0;
	int i = 0;

	if (prefix != NULL) {
		strcpy(filename, prefix);
		i = (int)strlen(prefix);
	}
	if (dlen > 0) {
		for (; i < dlen; i++)
			filename[i] = 'a';
		filename[i++] = '/';
		separator = 1;
	}
	for (; i < dlen + flen + separator; i++)
		filename[i] = 'b';
	filename[i] = '\0';

	strcpy(dirname, filename);

	/* Create a new archive in memory. */
	assert((a = archive_write_new()) != NULL);
	assertA(0 == archive_write_set_format_ustar(a));
	assertA(0 == archive_write_add_filter_none(a));
	assertA(0 == archive_write_set_bytes_per_block(a,0));
	assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));

	/*
	 * Write a file to it.
	 */
	assert((ae = archive_entry_new()) != NULL);
	archive_entry_copy_pathname(ae, filename);
	archive_entry_set_mode(ae, S_IFREG | 0755);
	failure("dlen=%d, flen=%d", dlen, flen);
	if (flen > 100) {
		assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae));
	} else {
		assertEqualIntA(a, 0, archive_write_header(a, ae));
	}
	archive_entry_free(ae);

	/*
	 * Write a dir to it (without trailing '/').
	 */
	assert((ae = archive_entry_new()) != NULL);
	archive_entry_copy_pathname(ae, dirname);
	archive_entry_set_mode(ae, S_IFDIR | 0755);
	failure("dlen=%d, flen=%d", dlen, flen);
	if (flen >= 100) {
		assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae));
	} else {
		assertEqualIntA(a, 0, archive_write_header(a, ae));
	}
	archive_entry_free(ae);

	/* Tar adds a '/' to directory names. */
	strcat(dirname, "/");

	/*
	 * Write a dir to it (with trailing '/').
	 */
	assert((ae = archive_entry_new()) != NULL);
	archive_entry_copy_pathname(ae, dirname);
	archive_entry_set_mode(ae, S_IFDIR | 0755);
	failure("dlen=%d, flen=%d", dlen, flen);
	if (flen >= 100) {
		assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae));
	} else {
		assertEqualIntA(a, 0, archive_write_header(a, ae));
	}
	archive_entry_free(ae);

	/* 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);
	assertA(0 == archive_read_support_format_all(a));
	assertA(0 == archive_read_support_filter_all(a));
	assertA(0 == archive_read_open_memory(a, buff, used));

	if (flen <= 100) {
		/* Read the file and check the filename. */
		assertA(0 == archive_read_next_header(a, &ae));
		failure("dlen=%d, flen=%d", dlen, flen);
		assertEqualString(filename, archive_entry_pathname(ae));
		assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae));
	}

	/*
	 * Read the two dirs and check the names.
	 *
	 * Both dirs should read back with the same name, since
	 * tar should add a trailing '/' to any dir that doesn't
	 * already have one.
	 */
	if (flen <= 99) {
		assertA(0 == archive_read_next_header(a, &ae));
		assert((S_IFDIR | 0755) == archive_entry_mode(ae));
		failure("dlen=%d, flen=%d", dlen, flen);
		assertEqualString(dirname, archive_entry_pathname(ae));
	}

	if (flen <= 99) {
		assertA(0 == archive_read_next_header(a, &ae));
		assert((S_IFDIR | 0755) == archive_entry_mode(ae));
		assertEqualString(dirname, archive_entry_pathname(ae));
	}

	/* Verify the end of the archive. */
	failure("This fails if entries were written that should not have been written.  dlen=%d, flen=%d", dlen, flen);
	assertEqualInt(1, archive_read_next_header(a, &ae));
	assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
Пример #28
0
static void
test_filename(const char *prefix, int dlen, int flen)
{
	char buff[8192];
	char filename[400];
	char dirname[400];
	struct archive_entry *ae;
	struct archive *a;
	size_t used;
	char *p;
	int i;

	p = filename;
	if (prefix) {
		strcpy(filename, prefix);
		p += strlen(p);
	}
	if (dlen > 0) {
		for (i = 0; i < dlen; i++)
			*p++ = 'a';
		*p++ = '/';
	}
	for (i = 0; i < flen; i++)
		*p++ = 'b';
	*p = '\0';

	strcpy(dirname, filename);

	/* Create a new archive in memory. */
	assert((a = archive_write_new()) != NULL);
	assertA(0 == archive_write_set_format_pax_restricted(a));
	assertA(0 == archive_write_set_compression_none(a));
	assertA(0 == archive_write_set_bytes_per_block(a,0));
	assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));

	/*
	 * Write a file to it.
	 */
	assert((ae = archive_entry_new()) != NULL);
	archive_entry_copy_pathname(ae, filename);
	archive_entry_set_mode(ae, S_IFREG | 0755);
	failure("Pathname %d/%d", dlen, flen);
	assertA(0 == archive_write_header(a, ae));
	archive_entry_free(ae);

	/*
	 * Write a dir to it (without trailing '/').
	 */
	assert((ae = archive_entry_new()) != NULL);
	archive_entry_copy_pathname(ae, dirname);
	archive_entry_set_mode(ae, S_IFDIR | 0755);
	failure("Dirname %d/%d", dlen, flen);
	assertA(0 == archive_write_header(a, ae));
	archive_entry_free(ae);

	/* Tar adds a '/' to directory names. */
	strcat(dirname, "/");

	/*
	 * Write a dir to it (with trailing '/').
	 */
	assert((ae = archive_entry_new()) != NULL);
	archive_entry_copy_pathname(ae, dirname);
	archive_entry_set_mode(ae, S_IFDIR | 0755);
	failure("Dirname %d/%d", dlen, flen);
	assertA(0 == archive_write_header(a, ae));
	archive_entry_free(ae);

	/* Close out the archive. */
	assertA(0 == archive_write_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
	archive_write_finish(a);
#else
	assertA(0 == archive_write_finish(a));
#endif

	/*
	 * Now, read the data back.
	 */
	assert((a = archive_read_new()) != NULL);
	assertA(0 == archive_read_support_format_all(a));
	assertA(0 == archive_read_support_compression_all(a));
	assertA(0 == archive_read_open_memory(a, buff, used));

	/* Read the file and check the filename. */
	assertA(0 == archive_read_next_header(a, &ae));
#if ARCHIVE_VERSION_NUMBER < 1009000
	skipping("Leading '/' preserved on long filenames");
#else
	assertEqualString(filename, archive_entry_pathname(ae));
#endif
	assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae));

	/*
	 * Read the two dirs and check the names.
	 *
	 * Both dirs should read back with the same name, since
	 * tar should add a trailing '/' to any dir that doesn't
	 * already have one.  We only report the first such failure
	 * here.
	 */
	assertA(0 == archive_read_next_header(a, &ae));
#if ARCHIVE_VERSION_NUMBER < 1009000
	skipping("Trailing '/' preserved on dirnames");
#else
	assertEqualString(dirname, archive_entry_pathname(ae));
#endif
	assert((S_IFDIR | 0755) == archive_entry_mode(ae));

	assertA(0 == archive_read_next_header(a, &ae));
#if ARCHIVE_VERSION_NUMBER < 1009000
	skipping("Trailing '/' added to dir names");
#else
	assertEqualString(dirname, archive_entry_pathname(ae));
#endif
	assert((S_IFDIR | 0755) == archive_entry_mode(ae));

	/* Verify the end of the archive. */
	assert(1 == archive_read_next_header(a, &ae));
	assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
	archive_read_finish(a);
#else
	assert(0 == archive_read_finish(a));
#endif
}
/* 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;
}
Пример #30
0
static void
make_dist(const char *pkg, const char *suffix, const package_t *plist)
{
	char *archive_name;
	const char *owner, *group;
	const plist_t *p;
	struct archive *archive;
	struct archive_entry *entry, *sparse_entry;
	struct archive_entry_linkresolver *resolver;
	char *initial_cwd;
	
	archive = archive_write_new();
	archive_write_set_format_pax_restricted(archive);
	if ((resolver = archive_entry_linkresolver_new()) == NULL)
		errx(2, "cannot create link resolver");
	archive_entry_linkresolver_set_strategy(resolver,
	    archive_format(archive));

	if (CompressionType == NULL) {
		if (strcmp(suffix, "tbz") == 0 ||
		    strcmp(suffix, "tar.bz2") == 0)
			CompressionType = "bzip2";
		else if (strcmp(suffix, "tgz") == 0 ||
		    strcmp(suffix, "tar.gz") == 0)
			CompressionType = "gzip";
		else
			CompressionType = "none";
	}

	if (strcmp(CompressionType, "bzip2") == 0)
		archive_write_set_compression_bzip2(archive);
	else if (strcmp(CompressionType, "gzip") == 0)
		archive_write_set_compression_gzip(archive);
	else if (strcmp(CompressionType, "xz") == 0)
		archive_write_set_compression_xz(archive);
	else if (strcmp(CompressionType, "none") == 0)
		archive_write_set_compression_none(archive);
	else
		errx(1, "Unspported compression type for -F: %s",
		    CompressionType);

	archive_name = xasprintf("%s.%s", pkg, suffix);

	if (archive_write_open_file(archive, archive_name))
		errx(2, "cannot create archive: %s", archive_error_string(archive));

	free(archive_name);

	owner = DefaultOwner;
	group = DefaultGroup;

	write_meta_file(contents_file, archive);
	write_meta_file(comment_file, archive);
	write_meta_file(desc_file, archive);

	if (Install)
		write_meta_file(install_file, archive);
	if (DeInstall)
		write_meta_file(deinstall_file, archive);
	if (Display)
		write_meta_file(display_file, archive);
	if (BuildVersion)
		write_meta_file(build_version_file, archive);
	if (BuildInfo)
		write_meta_file(build_info_file, archive);
	if (SizePkg)
		write_meta_file(size_pkg_file, archive);
	if (SizeAll)
		write_meta_file(size_all_file, archive);
	if (Preserve)
		write_meta_file(preserve_file, archive);
	if (create_views)
		write_meta_file(views_file, archive);

	initial_cwd = getcwd(NULL, 0);

	for (p = plist->head; p; p = p->next) {
		if (p->type == PLIST_FILE) {
			write_normal_file(p->name, archive, resolver, owner, group);
		} else if (p->type == PLIST_CWD) {
			chdir(p->name);
		} else if (p->type == PLIST_IGNORE) {
			p = p->next;
		} else if (p->type == PLIST_CHOWN) {
			if (p->name != NULL)
				owner = p->name;
			else
				owner = DefaultOwner;
		} else if (p->type == PLIST_CHGRP) {
			if (p->name != NULL)
				group = p->name;
			else
				group = DefaultGroup;
		}
	}

	entry = NULL;
	archive_entry_linkify(resolver, &entry, &sparse_entry);
	while (entry != NULL) {
		write_entry(archive, entry);
		entry = NULL;
		archive_entry_linkify(resolver, &entry, &sparse_entry);
	}

	archive_entry_linkresolver_free(resolver);

	if (archive_write_close(archive))
		errx(2, "cannot finish archive: %s", archive_error_string(archive));
	archive_write_finish(archive);

	free(initial_cwd);
}