コード例 #1
0
ファイル: stream_libarchive.c プロジェクト: atomnuker/mpv
struct mp_archive *mp_archive_new(struct mp_log *log, struct stream *src,
                                  int flags)
{
    struct mp_archive *mpa = talloc_zero(NULL, struct mp_archive);
    mpa->log = log;
    mpa->locale = newlocale(LC_ALL_MASK, "C.UTF-8", (locale_t)0);
    if (!mpa->locale)
        goto err;
    mpa->arch = archive_read_new();
    mpa->primary_src = src;
    if (!mpa->arch)
        goto err;

    // first volume is the primary streame
    if (!add_volume(log ,mpa, src, src->url))
        goto err;

    // try to open other volumes
    char** volumes = find_volumes(src);
    for (int i = 0; volumes[i]; i++) {
        if (!add_volume(log, mpa, NULL, volumes[i])) {
            talloc_free(volumes);
            goto err;
        }
    }
    talloc_free(volumes);

    locale_t oldlocale = uselocale(mpa->locale);

    archive_read_support_format_7zip(mpa->arch);
    archive_read_support_format_iso9660(mpa->arch);
    archive_read_support_format_rar(mpa->arch);
    archive_read_support_format_zip(mpa->arch);
    archive_read_support_filter_bzip2(mpa->arch);
    archive_read_support_filter_gzip(mpa->arch);
    archive_read_support_filter_xz(mpa->arch);
    if (flags & MP_ARCHIVE_FLAG_UNSAFE) {
        archive_read_support_format_gnutar(mpa->arch);
        archive_read_support_format_tar(mpa->arch);
    }

    archive_read_set_read_callback(mpa->arch, read_cb);
    archive_read_set_skip_callback(mpa->arch, skip_cb);
    archive_read_set_switch_callback(mpa->arch, switch_cb);
    archive_read_set_open_callback(mpa->arch, open_cb);
    archive_read_set_close_callback(mpa->arch, close_cb);
    if (mpa->primary_src->seekable)
        archive_read_set_seek_callback(mpa->arch, seek_cb);
    bool fail = archive_read_open1(mpa->arch) < ARCHIVE_OK;

    uselocale(oldlocale);

    if (fail)
        goto err;
    return mpa;

err:
    mp_archive_free(mpa);
    return NULL;
}
コード例 #2
0
ファイル: archive.c プロジェクト: BossKing/vlc
void EnableArchiveFormats(struct archive *p_archive)
{
    //    archive_read_support_filter_bzip2(p_archive);
    //    archive_read_support_filter_compress(p_archive);
    //    archive_read_support_filter_gzip(p_archive);
    //    archive_read_support_filter_grzip(p_archive);
    //    archive_read_support_filter_lrzip(p_archive);
    //    archive_read_support_filter_lzip(p_archive);
    archive_read_support_filter_lzma(p_archive);
    archive_read_support_filter_lzop(p_archive);
    archive_read_support_filter_none(p_archive);
    archive_read_support_filter_rpm(p_archive);
    archive_read_support_filter_uu(p_archive);
    archive_read_support_filter_xz(p_archive);

    //    archive_read_support_format_7zip(p_archive);
    archive_read_support_format_ar(p_archive);
    archive_read_support_format_cab(p_archive);
    archive_read_support_format_cpio(p_archive);
    archive_read_support_format_gnutar(p_archive);
    //    archive_read_support_format_iso9660(p_archive);
    archive_read_support_format_lha(p_archive);
    archive_read_support_format_mtree(p_archive);
    archive_read_support_format_rar(p_archive);
    archive_read_support_format_raw(p_archive);
    archive_read_support_format_tar(p_archive);
    archive_read_support_format_xar(p_archive);
    //    archive_read_support_format_zip(p_archive);
}
コード例 #3
0
ファイル: archive.cpp プロジェクト: striezel/libstriezel
void archive::applyFormats()
{
    int r2 = archive_read_support_format_tar(m_archive);
    if (r2 != ARCHIVE_OK)
    {
        archive_read_free(m_archive);
        m_archive = nullptr;
        throw std::runtime_error("libstriezel::tar::archive::applyFormats(): Format not supported!");
    }
    r2 = archive_read_support_format_gnutar(m_archive);
    if (r2 != ARCHIVE_OK)
    {
        archive_read_free(m_archive);
        m_archive = nullptr;
        throw std::runtime_error("libstriezel::tar::archive::applyFormats(): Format not supported!");
    }
}
コード例 #4
0
/*! \brief Extracts the selected .tar.gz archive to the selected folder, will try to create the target folder if it does not exist.
* @param filePath Full path to selected archive.
* @param targetFolderPath Full path to target folder.
* @return Returns full path to the extracted archive, or empty QString if failed.
*/
QString ArchiveExtractor::extractFileToTargetFolder(QString filePath, QString targetFolderPath){
  //check if the selected archive file exist
  QFile *selectedFile = new QFile(filePath);
  if(!selectedFile->exists()){
    qDebug()<<"ERROR: File marked for decompression does not exist!";
    delete selectedFile;
    return QString("");
  }
  delete selectedFile;
  struct archive *a;
  struct archive *ext;
  struct archive_entry *entry;
  int r;
  //  /* The "flags" argument selects optional behavior, 'OR' the flags you want. */
  //  /* Default: Do not try to set owner/group. */
  //#define	ARCHIVE_EXTRACT_OWNER			(0x0001)
  //  /* Default: Do obey umask, do not restore SUID/SGID/SVTX bits. */
  //#define	ARCHIVE_EXTRACT_PERM			(0x0002)
  //  /* Default: Do not restore mtime/atime. */
  //#define	ARCHIVE_EXTRACT_TIME			(0x0004)
  //  /* Default: Replace existing files. */
  //#define	ARCHIVE_EXTRACT_NO_OVERWRITE 		(0x0008)
  //  /* Default: Try create first, unlink only if create fails with EEXIST. */
  //#define	ARCHIVE_EXTRACT_UNLINK			(0x0010)
  //  /* Default: Do not restore ACLs. */
  //#define	ARCHIVE_EXTRACT_ACL			(0x0020)
  //  /* Default: Do not restore fflags. */
  //#define	ARCHIVE_EXTRACT_FFLAGS			(0x0040)
  //  /* Default: Do not restore xattrs. */
  //#define	ARCHIVE_EXTRACT_XATTR 			(0x0080)
  //  /* Default: Do not try to guard against extracts redirected by symlinks. */
  //  /* Note: With ARCHIVE_EXTRACT_UNLINK, will remove any intermediate symlink. */
  //#define	ARCHIVE_EXTRACT_SECURE_SYMLINKS		(0x0100)
  //  /* Default: Do not reject entries with '..' as path elements. */
  //#define	ARCHIVE_EXTRACT_SECURE_NODOTDOT		(0x0200)
  //  /* Default: Create parent directories as needed. */
  //#define	ARCHIVE_EXTRACT_NO_AUTODIR		(0x0400)
  //  /* Default: Overwrite files, even if one on disk is newer. */
  //#define	ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER	(0x0800)
  //  /* Detect blocks of 0 and write holes instead. */
  //#define	ARCHIVE_EXTRACT_SPARSE			(0x1000)
  //  /* Default: Do not restore Mac extended metadata. */
  //  /* This has no effect except on Mac OS. */
  //#define	ARCHIVE_EXTRACT_MAC_METADATA		(0x2000)
  int flags = 0;
  //      flags |= ARCHIVE_EXTRACT_TIME;
  //      flags |= ARCHIVE_EXTRACT_NO_AUTODIR;
  //      flags |= ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER;

  QFileInfo *fileInfo = new QFileInfo(filePath);
//  qDebug()<<"resolved filename: "<<fileInfo->fileName();
  delete fileInfo;

  //MEMORY LEAK!!! (Pointers be dangerous, man. :)
  //  const char *filename = fileInfo->fileName().toUtf8().constData();
  //AVOID IT BY CONVERTING TO A QBYTEARRAY FIRST!
  QByteArray byteArray = filePath.toUtf8();
  const char *filename = byteArray.constData();
  //That's better :D

  //toggle extraction
  bool do_extract = true;

  a = archive_read_new();
  ext = archive_write_disk_new();
  archive_write_disk_set_options(ext, flags);

  //tuned for .tar.gz
  archive_read_support_filter_gzip(a);
  archive_read_support_format_gnutar(a);

  if((r = archive_read_open_filename(a, filename, 10240)) ){
    errmsg(archive_error_string(a));
  }
  for(;;){
    r = archive_read_next_header(a, &entry);
    if(r == ARCHIVE_EOF) break;
    if(r != ARCHIVE_OK){
      errmsg(archive_error_string(a));
    }
    if (verbose || !do_extract){
      qDebug()<<"Detected files in archive: ";
      msg(archive_entry_pathname(entry));
    }
    QString currentPath(archive_entry_pathname( entry ));
    qDebug()<<currentPath;

    QDir targetFolder(targetFolderPath);
    if(!targetFolder.exists()){//target folder does not exist
      //attempt to create it
      if(!targetFolder.mkpath(targetFolderPath)){//failed to create target folder
        //break procedure
        qDebug()<<"ERROR: Target folder does not exist and cannot be created";
        return QString("");
      }
    }

    QString newPath = targetFolderPath + currentPath;
    qDebug()<<"newPath: " << newPath;

    archive_entry_set_pathname( entry, newPath.toUtf8().constData() );
    if (verbose && do_extract){
//      msg("About to start extracting\n");
    }
    if (do_extract){
      qDebug()<<"Extracting...";
      r = archive_write_header(ext, entry);
      if (r != ARCHIVE_OK) errmsg(archive_error_string(a));
      else copy_data(a, ext);
      std::string returnPath;
      returnPath = archive_entry_pathname(entry);
      qDebug()<<"File extracted: " << QString::fromStdString(returnPath);
      archive_read_close(a);
      archive_read_free(a);
      archive_write_close(ext);
      archive_write_free(ext);
      return QString::fromStdString( returnPath );
    }
  }
  archive_read_close(a);
  archive_read_free(a);
  archive_write_close(ext);
  archive_write_free(ext);
  return QString("");
}
コード例 #5
0
ファイル: write.c プロジェクト: AAZemlyanukhin/freebsd
void
tar_mode_u(struct bsdtar *bsdtar)
{
	int64_t			 end_offset;
	struct archive		*a;
	struct archive_entry	*entry;
	int			 format;
	struct archive_dir_entry	*p;
	struct archive_dir	 archive_dir;

	bsdtar->archive_dir = &archive_dir;
	memset(&archive_dir, 0, sizeof(archive_dir));

	format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED;

	/* Sanity-test some arguments and the file. */
	test_for_append(bsdtar);

	bsdtar->fd = open(bsdtar->filename, O_RDWR | O_BINARY);
	if (bsdtar->fd < 0)
		lafe_errc(1, errno,
		    "Cannot open %s", bsdtar->filename);

	a = archive_read_new();
	archive_read_support_filter_all(a);
	archive_read_support_format_tar(a);
	archive_read_support_format_gnutar(a);
	set_reader_options(bsdtar, a);
	if (archive_read_open_fd(a, bsdtar->fd, bsdtar->bytes_per_block)
	    != ARCHIVE_OK) {
		lafe_errc(1, 0,
		    "Can't open %s: %s", bsdtar->filename,
		    archive_error_string(a));
	}

	/* Build a list of all entries and their recorded mod times. */
	while (0 == archive_read_next_header(a, &entry)) {
		if (archive_filter_code(a, 0) != ARCHIVE_FILTER_NONE) {
			archive_read_free(a);
			close(bsdtar->fd);
			lafe_errc(1, 0,
			    "Cannot append to compressed archive.");
		}
		if (archive_match_exclude_entry(bsdtar->matching,
		    ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER |
		    ARCHIVE_MATCH_EQUAL, entry) != ARCHIVE_OK)
			lafe_errc(1, 0, "Error : %s",
			    archive_error_string(bsdtar->matching));
		/* Record the last format determination we see */
		format = archive_format(a);
		/* Keep going until we hit end-of-archive */
	}

	end_offset = archive_read_header_position(a);
	archive_read_free(a);

	/* Re-open archive for writing. */
	a = archive_write_new();
	/*
	 * Set format to same one auto-detected above.
	 */
	archive_write_set_format(a, format);
	archive_write_set_bytes_per_block(a, bsdtar->bytes_per_block);
	archive_write_set_bytes_in_last_block(a, bsdtar->bytes_in_last_block);

	if (lseek(bsdtar->fd, end_offset, SEEK_SET) < 0)
		lafe_errc(1, errno, "Could not seek to archive end");
	set_writer_options(bsdtar, a);
	if (ARCHIVE_OK != archive_write_open_fd(a, bsdtar->fd))
		lafe_errc(1, 0, "%s", archive_error_string(a));

	write_archive(a, bsdtar);

	close(bsdtar->fd);
	bsdtar->fd = -1;

	while (bsdtar->archive_dir->head != NULL) {
		p = bsdtar->archive_dir->head->next;
		free(bsdtar->archive_dir->head->name);
		free(bsdtar->archive_dir->head);
		bsdtar->archive_dir->head = p;
	}
	bsdtar->archive_dir->tail = NULL;
}
コード例 #6
0
ファイル: write.c プロジェクト: AAZemlyanukhin/freebsd
/*
 * Same as 'c', except we only support tar or empty formats in
 * uncompressed files on disk.
 */
void
tar_mode_r(struct bsdtar *bsdtar)
{
	int64_t	end_offset;
	int	format;
	struct archive *a;
	struct archive_entry *entry;
	int	r;

	/* Sanity-test some arguments and the file. */
	test_for_append(bsdtar);

	format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED;

#if defined(__BORLANDC__)
	bsdtar->fd = open(bsdtar->filename, O_RDWR | O_CREAT | O_BINARY);
#else
	bsdtar->fd = open(bsdtar->filename, O_RDWR | O_CREAT | O_BINARY, 0666);
#endif
	if (bsdtar->fd < 0)
		lafe_errc(1, errno,
		    "Cannot open %s", bsdtar->filename);

	a = archive_read_new();
	archive_read_support_filter_all(a);
	archive_read_support_format_empty(a);
	archive_read_support_format_tar(a);
	archive_read_support_format_gnutar(a);
	set_reader_options(bsdtar, a);
	r = archive_read_open_fd(a, bsdtar->fd, 10240);
	if (r != ARCHIVE_OK)
		lafe_errc(1, archive_errno(a),
		    "Can't read archive %s: %s", bsdtar->filename,
		    archive_error_string(a));
	while (0 == archive_read_next_header(a, &entry)) {
		if (archive_filter_code(a, 0) != ARCHIVE_FILTER_NONE) {
			archive_read_free(a);
			close(bsdtar->fd);
			lafe_errc(1, 0,
			    "Cannot append to compressed archive.");
		}
		/* Keep going until we hit end-of-archive */
		format = archive_format(a);
	}

	end_offset = archive_read_header_position(a);
	archive_read_free(a);

	/* Re-open archive for writing */
	a = archive_write_new();
	/*
	 * Set the format to be used for writing.  To allow people to
	 * extend empty files, we need to allow them to specify the format,
	 * which opens the possibility that they will specify a format that
	 * doesn't match the existing format.  Hence, the following bit
	 * of arcane ugliness.
	 */

	if (cset_get_format(bsdtar->cset) != NULL) {
		/* If the user requested a format, use that, but ... */
		archive_write_set_format_by_name(a,
		    cset_get_format(bsdtar->cset));
		/* ... complain if it's not compatible. */
		format &= ARCHIVE_FORMAT_BASE_MASK;
		if (format != (int)(archive_format(a) & ARCHIVE_FORMAT_BASE_MASK)
		    && format != ARCHIVE_FORMAT_EMPTY) {
			lafe_errc(1, 0,
			    "Format %s is incompatible with the archive %s.",
			    cset_get_format(bsdtar->cset), bsdtar->filename);
		}
	} else {
		/*
		 * Just preserve the current format, with a little care
		 * for formats that libarchive can't write.
		 */
		if (format == ARCHIVE_FORMAT_EMPTY)
			format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED;
		archive_write_set_format(a, format);
	}
	if (lseek(bsdtar->fd, end_offset, SEEK_SET) < 0)
		lafe_errc(1, errno, "Could not seek to archive end");
	set_writer_options(bsdtar, a);
	if (ARCHIVE_OK != archive_write_open_fd(a, bsdtar->fd))
		lafe_errc(1, 0, "%s", archive_error_string(a));

	write_archive(a, bsdtar); /* XXX check return val XXX */

	close(bsdtar->fd);
	bsdtar->fd = -1;
}
コード例 #7
0
ファイル: extract.c プロジェクト: liloman/PRoot
/**
 * Extract the archive stored at the given @path.  This function
 * returns -1 if an error occurred, otherwise 0.
 */
int extract_archive_from_file(const char *path)
{
    struct archive *archive = NULL;
    CallbackData *data = NULL;
    int status2;
    int status;

    archive = archive_read_new();
    if (archive == NULL) {
        note(NULL, ERROR, INTERNAL, "can't initialize archive structure");
        status = -1;
        goto end;
    }

    status = archive_read_support_format_cpio(archive);
    if (status != ARCHIVE_OK) {
        note(NULL, ERROR, INTERNAL, "can't set archive format: %s",
             archive_error_string(archive));
        status = -1;
        goto end;
    }

    status = archive_read_support_format_gnutar(archive);
    if (status != ARCHIVE_OK) {
        note(NULL, ERROR, INTERNAL, "can't set archive format: %s",
             archive_error_string(archive));
        status = -1;
        goto end;
    }

    status = archive_read_support_filter_gzip(archive);
    if (status != ARCHIVE_OK) {
        note(NULL, ERROR, INTERNAL, "can't add archive filter: %s",
             archive_error_string(archive));
        status = -1;
        goto end;
    }

    status = archive_read_support_filter_lzop(archive);
    if (status != ARCHIVE_OK) {
        note(NULL, ERROR, INTERNAL, "can't add archive filter: %s",
             archive_error_string(archive));
        status = -1;
        goto end;
    }

    data = talloc_zero(NULL, CallbackData);
    if (data == NULL) {
        note(NULL, ERROR, INTERNAL, "can't allocate callback data");
        status = -1;
        goto end;

    }

    data->path = talloc_strdup(data, path);
    if (data->path == NULL) {
        note(NULL, ERROR, INTERNAL, "can't allocate callback data path");
        status = -1;
        goto end;

    }

    status = archive_read_open(archive, data, open_callback, read_callback, close_callback);
    if (status != ARCHIVE_OK) {
        /* Don't complain if no error message were registered,
         * ie. when testing for a self-extracting archive.  */
        if (archive_error_string(archive) != NULL)
            note(NULL, ERROR, INTERNAL, "can't read archive: %s",
                 archive_error_string(archive));
        status = -1;
        goto end;
    }

    status = extract_archive(archive);
end:
    if (archive != NULL) {
        status2 = archive_read_close(archive);
        if (status2 != ARCHIVE_OK) {
            note(NULL, WARNING, INTERNAL, "can't close archive: %s",
                 archive_error_string(archive));
        }

        status2 = archive_read_free(archive);
        if (status2 != ARCHIVE_OK) {
            note(NULL, WARNING, INTERNAL, "can't free archive: %s",
                 archive_error_string(archive));
        }
    }

    TALLOC_FREE(data);

    return status;
}
コード例 #8
0
ファイル: write.c プロジェクト: marccodes/lfl
void
tar_mode_u(struct bsdtar *bsdtar)
{
	off_t			 end_offset;
	struct archive		*a;
	struct archive_entry	*entry;
	int			 format;
	struct archive_dir_entry	*p;
	struct archive_dir	 archive_dir;

	bsdtar->archive_dir = &archive_dir;
	memset(&archive_dir, 0, sizeof(archive_dir));

	format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED;

	/* Sanity-test some arguments and the file. */
	test_for_append(bsdtar);

	bsdtar->fd = open(bsdtar->filename, O_RDWR);
	if (bsdtar->fd < 0)
		bsdtar_errc(bsdtar, 1, errno,
		    "Cannot open %s", bsdtar->filename);

	a = archive_read_new();
	archive_read_support_compression_all(a);
	archive_read_support_format_tar(a);
	archive_read_support_format_gnutar(a);
	if (archive_read_open_fd(a, bsdtar->fd,
	    bsdtar->bytes_per_block != 0 ? bsdtar->bytes_per_block :
		DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) {
		bsdtar_errc(bsdtar, 1, 0,
		    "Can't open %s: %s", bsdtar->filename,
		    archive_error_string(a));
	}

	/* Build a list of all entries and their recorded mod times. */
	while (0 == archive_read_next_header(a, &entry)) {
		if (archive_compression(a) != ARCHIVE_COMPRESSION_NONE) {
			archive_read_finish(a);
			close(bsdtar->fd);
			bsdtar_errc(bsdtar, 1, 0,
			    "Cannot append to compressed archive.");
		}
		add_dir_list(bsdtar, archive_entry_pathname(entry),
		    archive_entry_mtime(entry),
		    archive_entry_mtime_nsec(entry));
		/* Record the last format determination we see */
		format = archive_format(a);
		/* Keep going until we hit end-of-archive */
	}

	end_offset = archive_read_header_position(a);
	archive_read_finish(a);

	/* Re-open archive for writing. */
	a = archive_write_new();
	archive_write_set_compression_none(a);
	/*
	 * Set format to same one auto-detected above, except that
	 * we don't write GNU tar format, so use ustar instead.
	 */
	if (format == ARCHIVE_FORMAT_TAR_GNUTAR)
		format = ARCHIVE_FORMAT_TAR_USTAR;
	archive_write_set_format(a, format);
	if (bsdtar->bytes_per_block != 0) {
		archive_write_set_bytes_per_block(a, bsdtar->bytes_per_block);
		archive_write_set_bytes_in_last_block(a,
		    bsdtar->bytes_per_block);
	} else
		archive_write_set_bytes_per_block(a, DEFAULT_BYTES_PER_BLOCK);
	lseek(bsdtar->fd, end_offset, SEEK_SET);
	ftruncate(bsdtar->fd, end_offset);
	if (ARCHIVE_OK != archive_write_set_options(a, bsdtar->option_options))
		bsdtar_errc(bsdtar, 1, 0, archive_error_string(a));
	if (ARCHIVE_OK != archive_write_open_fd(a, bsdtar->fd))
		bsdtar_errc(bsdtar, 1, 0, archive_error_string(a));

	write_archive(a, bsdtar);

	close(bsdtar->fd);
	bsdtar->fd = -1;

	while (bsdtar->archive_dir->head != NULL) {
		p = bsdtar->archive_dir->head->next;
		free(bsdtar->archive_dir->head->name);
		free(bsdtar->archive_dir->head);
		bsdtar->archive_dir->head = p;
	}
	bsdtar->archive_dir->tail = NULL;
}
コード例 #9
0
ファイル: write.c プロジェクト: marccodes/lfl
/*
 * Same as 'c', except we only support tar or empty formats in
 * uncompressed files on disk.
 */
void
tar_mode_r(struct bsdtar *bsdtar)
{
	off_t	end_offset;
	int	format;
	struct archive *a;
	struct archive_entry *entry;
	int	r;

	/* Sanity-test some arguments and the file. */
	test_for_append(bsdtar);

	format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED;

	bsdtar->fd = open(bsdtar->filename, O_RDWR | O_CREAT, 0666);
	if (bsdtar->fd < 0)
		bsdtar_errc(bsdtar, 1, errno,
		    "Cannot open %s", bsdtar->filename);

	a = archive_read_new();
	archive_read_support_compression_all(a);
	archive_read_support_format_tar(a);
	archive_read_support_format_gnutar(a);
	r = archive_read_open_fd(a, bsdtar->fd, 10240);
	if (r != ARCHIVE_OK)
		bsdtar_errc(bsdtar, 1, archive_errno(a),
		    "Can't read archive %s: %s", bsdtar->filename,
		    archive_error_string(a));
	while (0 == archive_read_next_header(a, &entry)) {
		if (archive_compression(a) != ARCHIVE_COMPRESSION_NONE) {
			archive_read_finish(a);
			close(bsdtar->fd);
			bsdtar_errc(bsdtar, 1, 0,
			    "Cannot append to compressed archive.");
		}
		/* Keep going until we hit end-of-archive */
		format = archive_format(a);
	}

	end_offset = archive_read_header_position(a);
	archive_read_finish(a);

	/* Re-open archive for writing */
	a = archive_write_new();
	archive_write_set_compression_none(a);
	/*
	 * Set the format to be used for writing.  To allow people to
	 * extend empty files, we need to allow them to specify the format,
	 * which opens the possibility that they will specify a format that
	 * doesn't match the existing format.  Hence, the following bit
	 * of arcane ugliness.
	 */

	if (bsdtar->create_format != NULL) {
		/* If the user requested a format, use that, but ... */
		archive_write_set_format_by_name(a,
		    bsdtar->create_format);
		/* ... complain if it's not compatible. */
		format &= ARCHIVE_FORMAT_BASE_MASK;
		if (format != (int)(archive_format(a) & ARCHIVE_FORMAT_BASE_MASK)
		    && format != ARCHIVE_FORMAT_EMPTY) {
			bsdtar_errc(bsdtar, 1, 0,
			    "Format %s is incompatible with the archive %s.",
			    bsdtar->create_format, bsdtar->filename);
		}
	} else {
		/*
		 * Just preserve the current format, with a little care
		 * for formats that libarchive can't write.
		 */
		if (format == ARCHIVE_FORMAT_TAR_GNUTAR)
			/* TODO: When gtar supports pax, use pax restricted. */
			format = ARCHIVE_FORMAT_TAR_USTAR;
		if (format == ARCHIVE_FORMAT_EMPTY)
			format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED;
		archive_write_set_format(a, format);
	}
	lseek(bsdtar->fd, end_offset, SEEK_SET); /* XXX check return val XXX */
	if (ARCHIVE_OK != archive_write_set_options(a, bsdtar->option_options))
		bsdtar_errc(bsdtar, 1, 0, archive_error_string(a));
	if (ARCHIVE_OK != archive_write_open_fd(a, bsdtar->fd))
		bsdtar_errc(bsdtar, 1, 0, archive_error_string(a));

	write_archive(a, bsdtar); /* XXX check return val XXX */

	close(bsdtar->fd);
	bsdtar->fd = -1;
}
コード例 #10
0
static retvalue read_data_tar(/*@out@*/char **list, /*@out@*/size_t *size, const char *debfile, struct ar_archive *ar, struct archive *tar) {
	struct archive_entry *entry;
	struct filelistcompressor c;
	retvalue r;
	int a, e;

	r = filelistcompressor_setup(&c);
	if (RET_WAS_ERROR(r))
		return r;

	archive_read_support_format_tar(tar);
	archive_read_support_format_gnutar(tar);
	a = archive_read_open(tar, ar,
			ar_archivemember_open,
			ar_archivemember_read,
			ar_archivemember_close);
	if (a != ARCHIVE_OK) {
		filelistcompressor_cancel(&c);
		e = archive_errno(tar);
		if (e == -EINVAL) /* special code to say there is none */
			fprintf(stderr,
"open data.tar within '%s' failed: %s\n",
				debfile, archive_error_string(tar));
		else
			fprintf(stderr,
"open data.tar within '%s' failed: %d:%d:%s\n", debfile, a, e,
				archive_error_string(tar));
		return RET_ERROR;
	}
	while ((a=archive_read_next_header(tar, &entry)) == ARCHIVE_OK) {
		const char *name = archive_entry_pathname(entry);
		mode_t mode;

		if (name[0] == '.')
			name++;
		if (name[0] == '/')
			name++;
		if (name[0] == '\0')
			continue;
		mode = archive_entry_mode(entry);
		if (!S_ISDIR(mode)) {
			r = filelistcompressor_add(&c, name, strlen(name));
			if (RET_WAS_ERROR(r)) {
				filelistcompressor_cancel(&c);
				return r;
			}
		}
		if (interrupted()) {
			filelistcompressor_cancel(&c);
			return RET_ERROR_INTERRUPTED;
		}
		a = archive_read_data_skip(tar);
		if (a != ARCHIVE_OK) {
			e = archive_errno(tar);
			if (e == -EINVAL) {
				r = RET_ERROR;
				fprintf(stderr,
"Error skipping %s within data.tar from %s: %s\n",
					archive_entry_pathname(entry),
					debfile, archive_error_string(tar));
			} else {
				fprintf(stderr,
"Error %d skipping %s within data.tar from %s: %s\n",
					e, archive_entry_pathname(entry),
					debfile, archive_error_string(tar));
				if (e != 0)
					r = RET_ERRNO(e);
				else
					r = RET_ERROR;
			}
			filelistcompressor_cancel(&c);
			return r;
		}
	}
	if (a != ARCHIVE_EOF) {
		e = archive_errno(tar);
		if (e == -EINVAL) {
			r = RET_ERROR;
			fprintf(stderr,
"Error reading data.tar from %s: %s\n", debfile, archive_error_string(tar));
		} else {
			fprintf(stderr,
"Error %d reading data.tar from %s: %s\n",
					e, debfile, archive_error_string(tar));
			if (e != 0)
				r = RET_ERRNO(e);
			else
				r = RET_ERROR;
		}
		filelistcompressor_cancel(&c);
		return r;
	}
	return filelistcompressor_finish(&c, list, size);
}