示例#1
0
void write_archive(const char *outname, const char **filename)
{
	struct archive *a;
	struct archive_entry *entry;
	struct stat st;
	char buff[8192];
	int len;
	int fd;

	a = archive_write_new();
	archive_write_set_compression_gzip(a);
	archive_write_set_format_pax_restricted(a); // Note 1
	archive_write_open_filename(a, outname, 10240);
	while (*filename) {
		stat(*filename, &st);
		entry = archive_entry_new(); // Note 2
		archive_entry_set_pathname(entry, *filename);
		archive_entry_set_size(entry, st.st_size); // Note 3
		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++;
	}
	archive_write_close(a); // Note 4
	archive_write_free(a); // Note 5
}
示例#2
0
文件: archive.c 项目: nishidy/cpee
void archive_create(){
	struct stat st;

	g_archive = archive_write_new();
	archive_write_add_filter_gzip(g_archive);
	archive_write_set_format_pax_restricted(g_archive); // Note 1
}
示例#3
0
void Writer::set_format_helper(struct archive *ar, int format)
{
    std::string error_msg;

    switch(format) {
        case Archive::FORMAT_AR_BSD:
            archive_write_set_format_ar_bsd(ar);
            break;
        case Archive::FORMAT_AR_SVR4:
            archive_write_set_format_ar_svr4(ar);
            break;
        case Archive::FORMAT_CPIO:
            archive_write_set_format_cpio(ar);
            break;
        case Archive::FORMAT_CPIO_NEWC:
            archive_write_set_format_cpio_newc(ar);
            break;
        case Archive::FORMAT_MTREE:
            archive_write_set_format_mtree(ar);
            break;
        case Archive::FORMAT_TAR:
        case Archive::FORMAT_TAR_PAX_RESTRICTED:
            archive_write_set_format_pax_restricted(ar);
            break;
        case Archive::FORMAT_TAR_PAX_INTERCHANGE:
            archive_write_set_format_pax(ar);
            break;
        case Archive::FORMAT_TAR_USTAR:
            archive_write_set_format_ustar(ar);
            break;
        default:
            error_msg = "unknown or unsupported archive format";
            throw Error(error_msg);
    }
}
示例#4
0
// Based on libarchive's public example code.
// https://github.com/libarchive/libarchive/wiki/Examples#wiki-A_Basic_Write_Example
void GuiZipper::packageFiles(const char *outputFile, const char *baseDir,
    char **filenames, int numFiles, bool binary, const char *absMetaFilename,
    const char *metaFilename) throw (ZipperException*) {
  int r;
  struct archive *a = archive_write_new();
  r = archive_write_add_filter_gzip(a);
  checkForErrors("Error adding filter gzip", a, r);
  r = archive_write_set_format_pax_restricted(a);
  checkForErrors("Error setting format pax restricted", a, r);
  r = archive_write_open_filename(a, outputFile);
  checkForErrors("Error opening file", a, r);
  packageSingleFile(absMetaFilename, metaFilename, a, false);
  for (int x = 0; x < numFiles; x++) {
    char *filename = filenames[x];
    char *filePath = fileManager_->getFilePath(baseDir, filename);
    try {
      packageSingleFile(filePath, filename, a, binary);
    } catch (ZipperException *ze) {
      delete filePath;
      throw ze;
    }
    delete filePath;
  }
  r = archive_write_close(a);
  checkForErrors("Error writing close", a, r);
  r = archive_write_free(a);
  checkForErrors("Error writing free", a, r);
}
示例#5
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("calloc", "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)->pass = false;
		(*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;
		}
	} else { /* pass mode directly write to the disk */
		pkg_debug(1, "Packing to directory '%s' (pass mode)", path);
		(*pack)->pass = true;
		(*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);
}
示例#6
0
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;
}
示例#7
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;
}
示例#8
0
文件: write.c 项目: nanakom/freebsd
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);
}
示例#9
0
文件: packing.c 项目: Absolight/pkg
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);
}
示例#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");
}
示例#11
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");
};
示例#12
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);
}
示例#13
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;
}
示例#14
0
文件: database.c 项目: buhman/repose
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;
}
示例#15
0
文件: packing.c 项目: philpep/pkgng
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);
}
示例#16
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;
}
示例#18
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);
}
示例#19
0
static int process_package(rpmts ts, char * filename)
{
    FD_t fdi;
    FD_t gzdi;
    Header h;
    int rc = 0;
    char * rpmio_flags = NULL;
    struct archive *a;
    struct archive_entry *entry;

    if (!strcmp(filename, "-")) {
	fdi = fdDup(STDIN_FILENO);
    } else {
	fdi = Fopen(filename, "r.ufdio");
    }

    if (Ferror(fdi)) {
	fprintf(stderr, "rpm2archive: %s: %s\n",
		filename, Fstrerror(fdi));
	exit(EXIT_FAILURE);
    }

    rc = rpmReadPackageFile(ts, fdi, "rpm2cpio", &h);

    switch (rc) {
    case RPMRC_OK:
    case RPMRC_NOKEY:
    case RPMRC_NOTTRUSTED:
	break;
    case RPMRC_NOTFOUND:
	fprintf(stderr, _("argument is not an RPM package\n"));
	exit(EXIT_FAILURE);
	break;
    case RPMRC_FAIL:
    default:
	fprintf(stderr, _("error reading header from package\n"));
	exit(EXIT_FAILURE);
	break;
    }


    /* Retrieve payload size and compression type. */
    {	const char *compr = headerGetString(h, RPMTAG_PAYLOADCOMPRESSOR);
	rpmio_flags = rstrscat(NULL, "r.", compr ? compr : "gzip", NULL);
    }

    gzdi = Fdopen(fdi, rpmio_flags);	/* XXX gzdi == fdi */
    free(rpmio_flags);

    if (gzdi == NULL) {
	fprintf(stderr, _("cannot re-open payload: %s\n"), Fstrerror(gzdi));
	exit(EXIT_FAILURE);
    }

    rpmfiles files = rpmfilesNew(NULL, h, 0, RPMFI_KEEPHEADER);
    rpmfi fi = rpmfiNewArchiveReader(gzdi, files, RPMFI_ITER_READ_ARCHIVE_CONTENT_FIRST);

    /* create archive */
    a = archive_write_new();
    archive_write_add_filter_gzip(a);
    archive_write_set_format_pax_restricted(a);

    if (!strcmp(filename, "-")) {
	if (isatty(STDOUT_FILENO)) {
	    fprintf(stderr, "Error: refusing to output archive data to a terminal.\n");
	    exit(EXIT_FAILURE);
	}
	archive_write_open_fd(a, STDOUT_FILENO);
    } else {
	char * outname = rstrscat(NULL, filename, ".tgz", NULL);
	archive_write_open_filename(a, outname);
	_free(outname);
	// XXX error handling
    }

    entry = archive_entry_new();

    char * buf = xmalloc(BUFSIZE);
    char * hardlink = NULL;

    rc = 0;
    while (rc >= 0) {
	rc = rpmfiNext(fi);
	if (rc == RPMERR_ITER_END) {
	    break;
	}

	rpm_mode_t mode = rpmfiFMode(fi);
	int nlink = rpmfiFNlink(fi);

	fill_archive_entry(a, entry, fi);

	if (nlink > 1) {
	    if (rpmfiArchiveHasContent(fi)) {
		_free(hardlink);
		hardlink = rstrscat(NULL, ".", rpmfiFN(fi), NULL);
	    } else {
		archive_entry_set_hardlink(entry, hardlink);
	    }
	}

	archive_write_header(a, entry);

	if (S_ISREG(mode) && (nlink == 1 || rpmfiArchiveHasContent(fi))) {
	    write_file_content(a, buf, fi);
	}
    }
    /* End of iteration is not an error */
    if (rc == RPMERR_ITER_END) {
	rc = 0;
    }

    _free(hardlink);

    Fclose(gzdi);	/* XXX gzdi == fdi */
    archive_entry_free(entry);
    archive_write_close(a);
    archive_write_free(a);
    buf = _free(buf);
    rpmfilesFree(files);
    rpmfiFree(fi);
    headerFree(h);
    return rc;
}
示例#20
0
	RESULTCODE ArchiveProcessorImpl::Compress()
	{
		const char* tpath = GetArchivePath();
		if(tpath==NULL)
		{
			return AG_FAILURE;
		}

		struct archive *a;
		struct archive_entry *entry;
		struct stat st;
		char buff[AUGE_BUFFER_MAX];
		int len;
		int fd;

		a = archive_write_new();
		if(a==NULL)
		{
			return AG_FAILURE;
		}
		//archive_write_add_filter_gzip(a);
		archive_write_set_format_zip(a);
		archive_write_set_format_pax_restricted(a);
		archive_write_open_filename(a,tpath);

		const char* fpath = NULL;
		char name[AUGE_NAME_MAX];
		char ext[AUGE_EXT_MAX];
		char fname[AUGE_NAME_MAX];
		std::vector<std::string>::iterator iter;
		for(iter=m_paths.begin(); iter!=m_paths.end();iter++)
		{
			fpath = (*iter).c_str();
			memset(fname,0,AUGE_NAME_MAX);
			memset(name,0,AUGE_NAME_MAX);
			memset(name,0,AUGE_EXT_MAX);
			auge_split_path(fpath, NULL, NULL, name, ext);
			auge_make_path(fname, NULL, NULL, name, ext);
			if(strlen(fname)==0)
			{
				continue;
			}

			stat(fpath,&st);

			entry = archive_entry_new();
			archive_entry_set_pathname(entry,fname);
			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(fpath,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);
		}

		archive_write_close(a);	
		archive_write_free(a);	

		return AG_SUCCESS;
	}
示例#21
0
/*
 * 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);
}
示例#22
0
文件: write.c 项目: zeha/tarsnap-deb
void
tarsnap_mode_c(struct bsdtar *bsdtar)
{
	struct archive *a;
	size_t i;

	if (*bsdtar->argv == NULL && bsdtar->names_from_file == NULL)
		bsdtar_errc(bsdtar, 1, 0, "no files or directories specified");

	for (i = 0; bsdtar->argv[i] != NULL; i++) {
		if (bsdtar->argv[i][0] == '-' && bsdtar->argv[i][1] == '-') {
			bsdtar_warnc(bsdtar, 0,
			    "List of objects to archive includes '%s'."
			    "  This might not be what you intended.",
			    bsdtar->argv[i]);
			break;
		}
	}

	a = archive_write_new();

	/* We only support the pax restricted format. */
	archive_write_set_format_pax_restricted(a);

	/* Set the block size to zero -- we don't want buffering. */
	archive_write_set_bytes_per_block(a, 0);

	/* Open the archive, keeping a cookie for talking to the tape layer. */
	bsdtar->write_cookie = archive_write_open_multitape(a,
	    bsdtar->machinenum, bsdtar->cachedir, bsdtar->tapenames[0],
	    bsdtar->argc_orig, bsdtar->argv_orig,
	    bsdtar->option_print_stats, bsdtar->option_dryrun,
	    bsdtar->creationtime);
	if (bsdtar->write_cookie == NULL)
		bsdtar_errc(bsdtar, 1, 0, "%s", archive_error_string(a));

	/*
	 * Remember the device and inode numbers of the cache directory, so
	 * that we can skip is in write_hierarchy().
	 */
	if (getdevino(a, bsdtar->cachedir,
	    &bsdtar->cachedir_dev, &bsdtar->cachedir_ino))
		bsdtar_errc(bsdtar, 1, 0, "%s", archive_error_string(a));

	/* If the chunkification cache is enabled, read it. */
	if ((bsdtar->cachecrunch < 2) && (bsdtar->cachedir != NULL)) {
		bsdtar->chunk_cache = ccache_read(bsdtar->cachedir);
		if (bsdtar->chunk_cache == NULL)
			bsdtar_errc(bsdtar, 1, errno, "Error reading cache");
	}

	write_archive(a, bsdtar);

	/*
	 * If this isn't a dry run and we're running with the chunkification
	 * cache enabled, write the cache back to disk.
	 */
	if ((bsdtar->option_dryrun == 0) && (bsdtar->cachecrunch < 2)) {
		if (ccache_write(bsdtar->chunk_cache, bsdtar->cachedir))
			bsdtar_errc(bsdtar, 1, errno, "Error writing cache");
	}

	/* Free the chunkification cache. */
	if (bsdtar->cachecrunch < 2)
		ccache_free(bsdtar->chunk_cache);
}
示例#23
0
文件: write.c 项目: marccodes/lfl
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);
}
示例#24
0
文件: write.c 项目: kamilWLca/brix
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);
}
示例#25
0
文件: util.c 项目: Berticus/powaur
int powaur_backup(alpm_list_t *targets)
{
	int ret = 0;
	char localdb[PATH_MAX];
	struct archive *a;
	struct archive_entry *entry;
	struct stat st;

	char cwd[PATH_MAX];
	char backup_dest[PATH_MAX];
	char backup[MINI_BUFSZ];

	time_t time_now;
	struct tm tm_st;

	if (targets != NULL && alpm_list_count(targets) != 1) {
		pw_fprintf(PW_LOG_ERROR, stderr, "-B only takes 1 argument.\n");
		return -1;
	}

	a = archive_write_new();
	if (!a) {
		return error(PW_ERR_ARCHIVE_CREATE);
	}

	archive_write_set_compression_bzip2(a);
	archive_write_set_format_pax_restricted(a);

	/* Filename = pacman-YYYY-MM-DD_HHhMM.tar.bz2 */
	time(&time_now);
	localtime_r(&time_now, &tm_st);
	strftime(backup, MINI_BUFSZ, "pacman-%Y-%m-%d_%Hh%M.tar.bz2", &tm_st);

	if (!getcwd(cwd, PATH_MAX)) {
		error(PW_ERR_GETCWD);
		ret = -1;
		goto cleanup;
	}

	/* Get full path */
	if (targets) {
		snprintf(backup_dest, PATH_MAX, "%s/%s", targets->data, backup);
	} else {
		snprintf(backup_dest, PATH_MAX, "%s/%s", cwd, backup);
	}

	if (archive_write_open_filename(a, backup_dest) != ARCHIVE_OK) {
		PW_SETERRNO(PW_ERR_ARCHIVE_OPEN);
		ret = -1;
		goto cleanup;
	}

	if (ret = chdir(pacman_dbpath)) {
		error(PW_ERR_CHDIR, pacman_dbpath);
		goto restore_cwd;
	}

	/* Create entry for the current directory. */
	entry = archive_entry_new();
	if (!entry) {
		error(PW_ERR_ARCHIVE_ENTRY);
		goto restore_cwd;
	}

	snprintf(localdb, PATH_MAX, "%s", "local");
	if (ret = stat(localdb, &st)) {
		error(PW_ERR_STAT, localdb);
		goto free_entry;
	}

	archive_entry_set_pathname(entry, localdb);
	archive_entry_copy_stat(entry, &st);
	archive_write_header(a, entry);

	pw_printf(PW_LOG_INFO, "Saving pacman database in %s\n", backup_dest);

	ret = write_dir_archive(localdb, a);

	if (!ret) {
		pw_printf(PW_LOG_INFO, "Pacman database successfully saved in %s\n",
				  backup_dest);
	} else {
		pw_fprintf(PW_LOG_ERROR, stderr, "Pacman database not saved.\n");
	}

free_entry:
	archive_entry_free(entry);

restore_cwd:
	if (chdir(cwd)) {
		PW_SETERRNO(PW_ERR_RESTORECWD);
		ret = -1;
	}

cleanup:
	archive_write_finish(a);
	return ret;
}
bool LibArchiveInterface::addFiles(const QStringList& files, const CompressionOptions& options)
{
    const bool creatingNewFile = !QFileInfo(filename()).exists();
    const QString tempFilename = filename() + QLatin1String( ".arkWriting" );
    const QString globalWorkDir = options.value(QLatin1String( "GlobalWorkDir" )).toString();

    if (!globalWorkDir.isEmpty()) {
        kDebug() << "GlobalWorkDir is set, changing dir to " << globalWorkDir;
        m_workDir.setPath(globalWorkDir);
        QDir::setCurrent(globalWorkDir);
    }

    m_writtenFiles.clear();

    ArchiveRead arch_reader;
    if (!creatingNewFile) {
        arch_reader.reset(archive_read_new());
        if (!(arch_reader.data())) {
            emit error(i18n("The archive reader could not be initialized."));
            return false;
        }

        if (archive_read_support_compression_all(arch_reader.data()) != ARCHIVE_OK) {
            return false;
        }

        if (archive_read_support_format_all(arch_reader.data()) != ARCHIVE_OK) {
            return false;
        }

        if (archive_read_open_filename(arch_reader.data(), QFile::encodeName(filename()), 10240) != ARCHIVE_OK) {
            emit error(i18n("The source file could not be read."));
            return false;
        }
    }

    ArchiveWrite arch_writer(archive_write_new());
    if (!(arch_writer.data())) {
        emit error(i18n("The archive writer could not be initialized."));
        return false;
    }

    //pax_restricted is the libarchive default, let's go with that.
    archive_write_set_format_pax_restricted(arch_writer.data());

    int ret;
    if (creatingNewFile) {
        if (filename().right(2).toUpper() == QLatin1String( "GZ" )) {
            kDebug() << "Detected gzip compression for new file";
            ret = archive_write_set_compression_gzip(arch_writer.data());
        } else if (filename().right(3).toUpper() == QLatin1String( "BZ2" )) {
            kDebug() << "Detected bzip2 compression for new file";
            ret = archive_write_set_compression_bzip2(arch_writer.data());
#ifdef HAVE_LIBARCHIVE_XZ_SUPPORT
        } else if (filename().right(2).toUpper() == QLatin1String( "XZ" )) {
            kDebug() << "Detected xz compression for new file";
            ret = archive_write_set_compression_xz(arch_writer.data());
#endif
#ifdef HAVE_LIBARCHIVE_LZMA_SUPPORT
        } else if (filename().right(4).toUpper() == QLatin1String( "LZMA" )) {
            kDebug() << "Detected lzma compression for new file";
            ret = archive_write_set_compression_lzma(arch_writer.data());
#endif
        } else if (filename().right(3).toUpper() == QLatin1String( "TAR" )) {
            kDebug() << "Detected no compression for new file (pure tar)";
            ret = archive_write_set_compression_none(arch_writer.data());
        } else {
            kDebug() << "Falling back to gzip";
            ret = archive_write_set_compression_gzip(arch_writer.data());
        }

        if (ret != ARCHIVE_OK) {
            emit error(i18nc("@info", "Setting the compression method failed with the following error: <message>%1</message>",
                       QLatin1String(archive_error_string(arch_writer.data()))));

            return false;
        }
    } else {
        switch (archive_compression(arch_reader.data())) {
        case ARCHIVE_COMPRESSION_GZIP:
            ret = archive_write_set_compression_gzip(arch_writer.data());
            break;
        case ARCHIVE_COMPRESSION_BZIP2:
            ret = archive_write_set_compression_bzip2(arch_writer.data());
            break;
#ifdef HAVE_LIBARCHIVE_XZ_SUPPORT
        case ARCHIVE_COMPRESSION_XZ:
            ret = archive_write_set_compression_xz(arch_writer.data());
            break;
#endif
#ifdef HAVE_LIBARCHIVE_LZMA_SUPPORT
        case ARCHIVE_COMPRESSION_LZMA:
            ret = archive_write_set_compression_lzma(arch_writer.data());
            break;
#endif
        case ARCHIVE_COMPRESSION_NONE:
            ret = archive_write_set_compression_none(arch_writer.data());
            break;
        default:
            emit error(i18n("The compression type '%1' is not supported by Ark.", QLatin1String(archive_compression_name(arch_reader.data()))));
            return false;
        }

        if (ret != ARCHIVE_OK) {
            emit error(i18nc("@info", "Setting the compression method failed with the following error: <message>%1</message>", QLatin1String(archive_error_string(arch_writer.data()))));
            return false;
        }
    }

    ret = archive_write_open_filename(arch_writer.data(), QFile::encodeName(tempFilename));
    if (ret != ARCHIVE_OK) {
        emit error(i18nc("@info", "Opening the archive for writing failed with the following error: <message>%1</message>", QLatin1String(archive_error_string(arch_writer.data()))));
        return false;
    }

    //**************** first write the new files
    foreach(const QString& selectedFile, files) {
        bool success;

        success = writeFile(selectedFile, arch_writer.data());

        if (!success) {
            QFile::remove(tempFilename);
            return false;
        }

        if (QFileInfo(selectedFile).isDir()) {
            QDirIterator it(selectedFile,
                            QDir::AllEntries | QDir::Readable |
                            QDir::Hidden | QDir::NoDotAndDotDot,
                            QDirIterator::Subdirectories);

            while (it.hasNext()) {
                const QString path = it.next();

                if ((it.fileName() == QLatin1String("..")) ||
                    (it.fileName() == QLatin1String("."))) {
                    continue;
                }

                const bool isRealDir = it.fileInfo().isDir() && !it.fileInfo().isSymLink();

                success = writeFile(path +
                                    (isRealDir ? QLatin1String( "/" ) : QLatin1String( "" )),
                                    arch_writer.data());

                if (!success) {
                    QFile::remove(tempFilename);
                    return false;
                }
            }
        }
    }
示例#27
0
/*!
 * \brief Create pax archive with all metadata
 *
 * \param filename Target archive path
 * \param base_dir Base directory for \a paths
 * \param paths List of paths to add to the archive
 *
 * \return Whether the archive creation was successful
 */
bool libarchive_tar_create(const std::string &filename,
                           const std::string &base_dir,
                           const std::vector<std::string> &paths)
{
    if (base_dir.empty() && paths.empty()) {
        LOGE("%s: No base directory or paths specified", filename.c_str());
        return false;
    }

    autoclose::archive in(archive_read_disk_new(), archive_read_free);
    if (!in) {
        LOGE("%s: Out of memory when creating disk reader", __FUNCTION__);
        return false;
    }
    autoclose::archive out(archive_write_new(), archive_write_free);
    if (!out) {
        LOGE("%s: Out of memory when creating archive writer", __FUNCTION__);
        return false;
    }
    autoclose::archive_entry_linkresolver resolver(archive_entry_linkresolver_new(),
                                                   archive_entry_linkresolver_free);
    if (!resolver) {
        LOGE("%s: Out of memory when creating link resolver", __FUNCTION__);
        return false;
    }

    // Set up disk reader parameters
    archive_read_disk_set_symlink_physical(in.get());
    archive_read_disk_set_metadata_filter_callback(
            in.get(), metadata_filter, nullptr);
    archive_read_disk_set_behavior(in.get(), LIBARCHIVE_DISK_READER_FLAGS);
    // We don't want to look up usernames and group names on Android
    //archive_read_disk_set_standard_lookup(in.get());

    // Set up archive writer parameters
    // NOTE: We are creating POSIX pax archives instead of GNU tar archives
    //       because libarchive's GNU tar writer is very limited. In particular,
    //       it does not support storing sparse file information, xattrs, or
    //       ACLs. Since this information is stored as extended attributes in
    //       the pax archive, the GNU tar tool will not be able to extract any
    //       of this additional metadata. In other words, extracting and
    //       repacking a backup on a Linux machine with GNU tar will render the
    //       backup useless.
    //archive_write_set_format_gnutar(out.get());
    archive_write_set_format_pax_restricted(out.get());
    //archive_write_set_compression_bzip2(out.get());
    //archive_write_set_compression_gzip(out.get());
    //archive_write_set_compression_xz(out.get());
    archive_write_set_bytes_per_block(out.get(), 10240);

    // Set up link resolver parameters
    archive_entry_linkresolver_set_strategy(resolver.get(),
                                            archive_format(out.get()));

    // Open output file
    if (archive_write_open_filename(out.get(), filename.c_str()) != ARCHIVE_OK) {
        LOGE("%s: Failed to open file: %s",
             filename.c_str(), archive_error_string(out.get()));
        return false;
    }

    archive_entry *entry = nullptr;
    archive_entry *sparse_entry = nullptr;
    int ret;
    std::string full_path;

    // Add hierarchies
    for (const std::string &path : paths) {
        if (path.empty()) {
            LOGE("%s: Cannot add empty path to the archive", filename.c_str());
            return false;
        }

        // If the path is absolute, don't append it to the base directory
        if (path[0] == '/') {
            full_path = path;
        } else {
            full_path = base_dir;
            if (!full_path.empty() && full_path.back() != '/' && path[0] != '/') {
                full_path += '/';
            }
            full_path += path;
        }

        ret = archive_read_disk_open(in.get(), full_path.c_str());
        if (ret != ARCHIVE_OK) {
            LOGE("%s: %s", full_path.c_str(), archive_error_string(in.get()));
            return false;
        }

        while (true) {
            archive_entry_free(entry);
            entry = archive_entry_new();

            ret = archive_read_next_header2(in.get(), entry);
            if (ret == ARCHIVE_EOF) {
                break;
            } else if (ret != ARCHIVE_OK) {
                LOGE("%s: Failed to read next header: %s", full_path.c_str(),
                     archive_error_string(in.get()));
                archive_entry_free(entry);
                return false;
            }

            if (archive_entry_filetype(entry) != AE_IFREG) {
                archive_entry_set_size(entry, 0);
            }

            // If our current directory tree path is not an absolute path, set
            // the archive path to the relative path starting at base_dir
            const char *curpath = archive_entry_pathname(entry);
            if (curpath && path[0] != '/' && !base_dir.empty()) {
                std::string relpath;
                if (!util::relative_path(curpath, base_dir, &relpath)) {
                    LOGE("Failed to compute relative path of %s starting at %s: %s",
                         curpath, base_dir.c_str(), strerror(errno));
                    archive_entry_free(entry);
                    return false;
                }
                if (relpath.empty()) {
                    // If the relative path is empty, then the current path is
                    // the root of the directory tree. We don't need that, so
                    // skip it.
                    continue;
                }
                archive_entry_set_pathname(entry, relpath.c_str());
            }

            switch (archive_entry_filetype(entry)) {
            case AE_IFSOCK:
                LOGW("%s: Skipping socket", archive_entry_pathname(entry));
                continue;
            default:
                LOGV("%s", archive_entry_pathname(entry));
                break;
            }

            archive_entry_linkify(resolver.get(), &entry, &sparse_entry);

            if (entry) {
                if (!write_file(in.get(), out.get(), entry)) {
                    archive_entry_free(entry);
                    return false;
                }
                archive_entry_free(entry);
                entry = nullptr;
            }
            if (sparse_entry) {
                if (!write_file(in.get(), out.get(), sparse_entry)) {
                    archive_entry_free(sparse_entry);
                    return false;
                }
                archive_entry_free(sparse_entry);
                sparse_entry = nullptr;
            }
        }

        archive_entry_free(entry);
        entry = nullptr;
        archive_read_close(in.get());
    }

    archive_read_disk_set_metadata_filter_callback(in.get(), nullptr, nullptr);

    entry = nullptr;
    archive_entry_linkify(resolver.get(), &entry, &sparse_entry);

    while (entry) {
        // This tricky code here is to correctly read the contents of the entry
        // because the disk reader 'in' is pointing at does not have any
        // information about the entry by this time and using
        // archive_read_data_block() with the disk reader consequently must
        // fail. And we hae to re-open the entry to read the contents.
        ret = archive_read_disk_open(in.get(), archive_entry_sourcepath(entry));
        if (ret != ARCHIVE_OK) {
            LOGE("%s: %s", archive_entry_sourcepath(entry),
                 archive_error_string(in.get()));
            return false;
        }

        // Invoke archive_read_next_header2() to work archive_read_data_block(),
        // which is called via write_file() without failure.
        archive_entry *entry2 = archive_entry_new();
        ret = archive_read_next_header2(in.get(), entry2);
        archive_entry_free(entry2);
        if (ret != ARCHIVE_OK) {
            LOGE("%s: %s", archive_entry_sourcepath(entry),
                 archive_error_string(in.get()));
            archive_entry_free(entry);
            return false;
        }

        if (!write_file(in.get(), out.get(), entry)) {
            archive_entry_free(entry);
            return false;
        }
        archive_entry_free(entry);
        archive_read_close(in.get());
        entry = nullptr;
        archive_entry_linkify(resolver.get(), &entry, &sparse_entry);
    }

    if (archive_write_close(out.get()) != ARCHIVE_OK) {
        LOGE("%s: %s", filename.c_str(), archive_error_string(out.get()));
        return false;
    }

    return true;
}