Пример #1
0
bool LibarchivePlugin::list()
{
    qCDebug(ARK) << "Listing archive contents";

    if (!initializeReader()) {
        return false;
    }

    qDebug(ARK) << "Detected compression filter:" << archive_filter_name(m_archiveReader.data(), 0);
    QString compMethod = convertCompressionName(QString::fromUtf8(archive_filter_name(m_archiveReader.data(), 0)));
    if (!compMethod.isEmpty()) {
        emit compressionMethodFound(compMethod);
    }

    m_cachedArchiveEntryCount = 0;
    m_extractedFilesSize = 0;
    m_numberOfEntries = 0;
    auto compressedArchiveSize = QFileInfo(filename()).size();

    struct archive_entry *aentry;
    int result = ARCHIVE_RETRY;

    bool firstEntry = true;
    while (!QThread::currentThread()->isInterruptionRequested() && (result = archive_read_next_header(m_archiveReader.data(), &aentry)) == ARCHIVE_OK) {

        if (firstEntry) {
            qDebug(ARK) << "Detected format for first entry:" << archive_format_name(m_archiveReader.data());
            firstEntry = false;
        }

        if (!m_emitNoEntries) {
            emitEntryFromArchiveEntry(aentry);
        }

        m_extractedFilesSize += (qlonglong)archive_entry_size(aentry);

        emit progress(float(archive_filter_bytes(m_archiveReader.data(), -1))/float(compressedArchiveSize));

        m_cachedArchiveEntryCount++;
        archive_read_data_skip(m_archiveReader.data());
    }

    if (result != ARCHIVE_EOF) {
        qCWarning(ARK) << "Could not read until the end of the archive:" << QLatin1String(archive_error_string(m_archiveReader.data()));
        return false;
    }

    return archive_read_close(m_archiveReader.data()) == ARCHIVE_OK;
}
Пример #2
0
size_t LIBARCHIVEgetEntry(char *name, char *contentFile, char **ptr) {
  struct mydata *mydata;
  struct archive *a;
  struct archive_entry *entry;
  char *buf;
  size_t size = 0;

  mydata = (struct mydata*)malloc(sizeof(struct mydata));
  a = archive_read_new();
  mydata->name = name;
  archive_read_support_format_all(a);
  archive_read_support_compression_all(a);
  if (archive_read_open(a, mydata, myopen, myread, myclose) == ARCHIVE_FATAL) {
    fprintf(stderr, "failed to open %s\n", mydata->name);
    free(mydata->name);
    free(mydata);
    return 0;
  }

  while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
    if( 0 == strcmp(archive_entry_pathname(entry), contentFile)) {
      o_log(DEBUGM, "%s", (char *)archive_compression_name(a));
      o_log(DEBUGM, "%s", (char *)archive_format_name(a));
      o_log(DEBUGM, "%s", (char *)archive_entry_pathname(entry));
      size = archive_entry_size(entry);
      if(size <= 0)
        o_log(DEBUGM, "zero size");
      if ((buf = (char *)malloc(size+1)) == NULL)
        o_log(ERROR, "cannot allocate memory");
      if ((size_t)archive_read_data(a, buf, size) != size)
        o_log(DEBUGM, "cannot read data");
      buf[size] = '\0';
      *ptr = buf;
    }
    else
      archive_read_data_skip(a);
  }

  archive_read_close(a);
  archive_read_finish(a);
  free(mydata);
  return size;
}
Пример #3
0
static void
test_read_uu_sub(const char *uudata, size_t uusize, int no_nl)
{
	struct archive_entry *ae;
	struct archive *a;
	char *buff;
	char extradata_no_nl[sizeof(extradata)];
	const char *extradata_ptr;
	int extra;
	size_t size;

	if (no_nl) {
		/* Remove '\n' from extra data to make a very long line. */
		char *p;
		memcpy(extradata_no_nl, extradata, sizeof(extradata));
		extradata_ptr = extradata_no_nl;
		for (p = extradata_no_nl;
		    *p && (p = strchr(p, '\n')) != NULL; p++)
			*p = ' ';/* Replace '\n' with ' ' a space character. */
	} else
		extradata_ptr = extradata;

	assert(NULL != (buff = malloc(uusize + 1024 * 1024)));
	if (buff == NULL)
		return;
	for (extra = 0; extra <= 64; extra = extra==0?1:extra*2) {
		char *p = buff;

		size = extra * 1024;
		/* Add extra text size of which is from 1K bytes to
		 * 64Kbytes before uuencoded data. */
		while (size) {
			if (size > sizeof(extradata)-1) {
				memcpy(p, extradata_ptr, sizeof(extradata)-1);
				p += sizeof(extradata)-1;
				size -= sizeof(extradata)-1;
			} else {
				memcpy(p, extradata_ptr, size-1);
				p += size-1;
				*p++ = '\n';/* the last of extra text must have
					     * '\n' character. */
				break;
			}
		}
		memcpy(p, uudata, uusize);
		size = extra * 1024 + uusize;

		assert((a = archive_read_new()) != NULL);
		assertEqualIntA(a, ARCHIVE_OK,
		    archive_read_support_filter_all(a));
		assertEqualIntA(a, ARCHIVE_OK,
		    archive_read_support_format_all(a));
		assertEqualIntA(a, ARCHIVE_OK,
		    read_open_memory(a, buff, size, 2));
		assertEqualIntA(a, ARCHIVE_OK,
		    archive_read_next_header(a, &ae));
		failure("archive_compression_name(a)=\"%s\""
		    "extra %d, NL %d",
		    archive_compression_name(a), extra, !no_nl);
		assertEqualInt(archive_compression(a),
		    ARCHIVE_COMPRESSION_COMPRESS);
		failure("archive_format_name(a)=\"%s\""
		    "extra %d, NL %d",
		    archive_format_name(a), extra, !no_nl);
		assertEqualInt(archive_format(a),
		    ARCHIVE_FORMAT_TAR_USTAR);
		assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
		assertEqualInt(ARCHIVE_OK, archive_read_free(a));
	}

	/* UUdecode bidder shouldn't scan too much data; make sure it
	 * fails if we put 512k of data before the start. */
	size = 512 * 1024;
	for (extra = 0; (size_t)extra < size; ++extra)
		buff[extra + 1024] = buff[extra];
	buff[size - 1] = '\n';
	memcpy(buff + size, uudata, uusize);
	size += uusize;
	assert((a = archive_read_new()) != NULL);
	assertEqualIntA(a, ARCHIVE_OK,
	    archive_read_support_filter_all(a));
	assertEqualIntA(a, ARCHIVE_OK,
	    archive_read_support_format_all(a));
	assertEqualIntA(a, ARCHIVE_FATAL,
	    read_open_memory(a, buff, size, 2));
	assertEqualInt(ARCHIVE_OK, archive_read_free(a));

	free(buff);
}
Пример #4
0
/*
 * The reference file for this has been manually tweaked so that:
 *   * file2 has length-at-end but file1 does not
 *   * file2 has an invalid CRC
 */
static void
verify_basic(struct archive *a, int seek_checks)
{
	struct archive_entry *ae;
	char *buff[128];
	const void *pv;
	size_t s;
	int64_t o;

	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
        assertEqualString("ZIP 1.0 (uncompressed)", archive_format_name(a));
	assertEqualString("dir/", archive_entry_pathname(ae));
	assertEqualInt(1179604249, archive_entry_mtime(ae));
	assertEqualInt(0, archive_entry_size(ae));
	if (seek_checks)
		assertEqualInt(AE_IFDIR | 0755, archive_entry_mode(ae));
	assertEqualInt(archive_entry_is_encrypted(ae), 0);
	assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0);
	assertEqualIntA(a, ARCHIVE_EOF,
	    archive_read_data_block(a, &pv, &s, &o));
	assertEqualInt((int)s, 0);

	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
        assertEqualString("ZIP 2.0 (deflation)", archive_format_name(a));
	assertEqualString("file1", archive_entry_pathname(ae));
	assertEqualInt(1179604289, archive_entry_mtime(ae));
	if (seek_checks)
		assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae));
	assertEqualInt(18, archive_entry_size(ae));
	assertEqualInt(archive_entry_is_encrypted(ae), 0);
	assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0);
	failure("archive_read_data() returns number of bytes read");
	if (archive_zlib_version() != NULL) {
		assertEqualInt(18, archive_read_data(a, buff, 19));
		assertEqualMem(buff, "hello\nhello\nhello\n", 18);
	} else {
		assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, 19));
		assertEqualString(archive_error_string(a),
		    "Unsupported ZIP compression method (deflation)");
		assert(archive_errno(a) != 0);
	}

	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
        assertEqualString("ZIP 2.0 (deflation)", archive_format_name(a));
	assertEqualString("file2", archive_entry_pathname(ae));
	assertEqualInt(1179605932, archive_entry_mtime(ae));
	assertEqualInt(archive_entry_is_encrypted(ae), 0);
	assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0);
	if (seek_checks) {
		assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae));
	}
	assert(archive_entry_size_is_set(ae));
	assertEqualInt(18, archive_entry_size(ae));
	if (archive_zlib_version() != NULL) {
		failure("file2 has a bad CRC, so read should fail and not change buff");
		memset(buff, 'a', 19);
		assertEqualInt(ARCHIVE_WARN, archive_read_data(a, buff, 19));
		assertEqualMem(buff, "aaaaaaaaaaaaaaaaaaa", 19);
	} else {
		assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, 19));
		assertEqualString(archive_error_string(a),
		    "Unsupported ZIP compression method (deflation)");
		assert(archive_errno(a) != 0);
	}
	assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &ae));
        assertEqualString("ZIP 2.0 (deflation)", archive_format_name(a));
	/* Verify the number of files read. */
	failure("the archive file has three files");
	assertEqualInt(3, archive_file_count(a));
	assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0));
	assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a));
	assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
Пример #5
0
/*
 * Handle 'x' and 't' modes.
 */
static void
read_archive(struct bsdtar *bsdtar, char mode)
{
	FILE			 *out;
	struct archive		 *a;
	struct archive_entry	 *entry;
	const struct stat	 *st;
	int			  r;

	while (*bsdtar->argv) {
		include(bsdtar, *bsdtar->argv);
		bsdtar->argv++;
	}

	if (bsdtar->names_from_file != NULL)
		include_from_file(bsdtar, bsdtar->names_from_file);

	a = archive_read_new();
	if (bsdtar->compress_program != NULL)
		archive_read_support_compression_program(a, bsdtar->compress_program);
	else
		archive_read_support_compression_all(a);
	archive_read_support_format_all(a);
	if (archive_read_open_file(a, bsdtar->filename,
	    bsdtar->bytes_per_block != 0 ? bsdtar->bytes_per_block :
	    DEFAULT_BYTES_PER_BLOCK))
		bsdtar_errc(bsdtar, 1, 0, "Error opening archive: %s",
		    archive_error_string(a));

	do_chdir(bsdtar);
	for (;;) {
		/* Support --fast-read option */
		if (bsdtar->option_fast_read &&
		    unmatched_inclusions(bsdtar) == 0)
			break;

		r = archive_read_next_header(a, &entry);
		if (r == ARCHIVE_EOF)
			break;
		if (r < ARCHIVE_OK)
			bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(a));
		if (r <= ARCHIVE_WARN)
			bsdtar->return_value = 1;
		if (r == ARCHIVE_RETRY) {
			/* Retryable error: try again */
			bsdtar_warnc(bsdtar, 0, "Retrying...");
			continue;
		}
		if (r == ARCHIVE_FATAL)
			break;

		/*
		 * Exclude entries that are too old.
		 */
		st = archive_entry_stat(entry);
		if (bsdtar->newer_ctime_sec > 0) {
			if (st->st_ctime < bsdtar->newer_ctime_sec)
				continue; /* Too old, skip it. */
			if (st->st_ctime == bsdtar->newer_ctime_sec
			    && ARCHIVE_STAT_CTIME_NANOS(st)
			    <= bsdtar->newer_ctime_nsec)
				continue; /* Too old, skip it. */
		}
		if (bsdtar->newer_mtime_sec > 0) {
			if (st->st_mtime < bsdtar->newer_mtime_sec)
				continue; /* Too old, skip it. */
			if (st->st_mtime == bsdtar->newer_mtime_sec
			    && ARCHIVE_STAT_MTIME_NANOS(st)
			    <= bsdtar->newer_mtime_nsec)
				continue; /* Too old, skip it. */
		}

		/*
		 * Note that pattern exclusions are checked before
		 * pathname rewrites are handled.  This gives more
		 * control over exclusions, since rewrites always lose
		 * information.  (For example, consider a rewrite
		 * s/foo[0-9]/foo/.  If we check exclusions after the
		 * rewrite, there would be no way to exclude foo1/bar
		 * while allowing foo2/bar.)
		 */
		if (excluded(bsdtar, archive_entry_pathname(entry)))
			continue; /* Excluded by a pattern test. */

		/*
		 * Modify the pathname as requested by the user.  We
		 * do this for -t as well to give users a way to
		 * preview the effects of their rewrites.  We also do
		 * this before extraction security checks (including
		 * leading '/' removal).  Note that some rewrite
		 * failures prevent extraction.
		 */
		if (edit_pathname(bsdtar, entry))
			continue; /* Excluded by a rewrite failure. */

		if (mode == 't') {
			/* Perversely, gtar uses -O to mean "send to stderr"
			 * when used with -t. */
			out = bsdtar->option_stdout ? stderr : stdout;

			if (bsdtar->verbose < 2)
				safe_fprintf(out, "%s",
				    archive_entry_pathname(entry));
			else
				list_item_verbose(bsdtar, out, entry);
			fflush(out);
			r = archive_read_data_skip(a);
			if (r == ARCHIVE_WARN) {
				fprintf(out, "\n");
				bsdtar_warnc(bsdtar, 0, "%s",
				    archive_error_string(a));
			}
			if (r == ARCHIVE_RETRY) {
				fprintf(out, "\n");
				bsdtar_warnc(bsdtar, 0, "%s",
				    archive_error_string(a));
			}
			if (r == ARCHIVE_FATAL) {
				fprintf(out, "\n");
				bsdtar_warnc(bsdtar, 0, "%s",
				    archive_error_string(a));
				bsdtar->return_value = 1;
				break;
			}
			fprintf(out, "\n");
		} else {
			if (bsdtar->option_interactive &&
			    !yes("extract '%s'", archive_entry_pathname(entry)))
				continue;

			/*
			 * Format here is from SUSv2, including the
			 * deferred '\n'.
			 */
			if (bsdtar->verbose) {
				safe_fprintf(stderr, "x %s",
				    archive_entry_pathname(entry));
				fflush(stderr);
			}
			if (bsdtar->option_stdout)
				r = archive_read_data_into_fd(a, 1);
			else
				r = archive_read_extract(a, entry,
				    bsdtar->extract_flags);
			if (r != ARCHIVE_OK) {
				if (!bsdtar->verbose)
					safe_fprintf(stderr, "%s",
					    archive_entry_pathname(entry));
				safe_fprintf(stderr, ": %s",
				    archive_error_string(a));
				if (!bsdtar->verbose)
					fprintf(stderr, "\n");
				bsdtar->return_value = 1;
			}
			if (bsdtar->verbose)
				fprintf(stderr, "\n");
			if (r == ARCHIVE_FATAL)
				break;
		}
	}

	if (bsdtar->verbose > 2)
		fprintf(stdout, "Archive Format: %s,  Compression: %s\n",
		    archive_format_name(a), archive_compression_name(a));

	archive_read_finish(a);
}
Пример #6
0
/*
 * Handle 'x' and 't' modes.
 */
static void
read_archive(struct bsdtar *bsdtar, char mode)
{
	struct progress_data	progress_data;
	FILE			 *out;
	struct archive		 *a;
	struct archive_entry	 *entry;
	const struct stat	 *st;
	int			  r;

	while (*bsdtar->argv) {
		lafe_include(&bsdtar->matching, *bsdtar->argv);
		bsdtar->argv++;
	}

	if (bsdtar->names_from_file != NULL)
		lafe_include_from_file(&bsdtar->matching,
		    bsdtar->names_from_file, bsdtar->option_null);

	a = archive_read_new();
	if (bsdtar->compress_program != NULL)
		archive_read_support_compression_program(a, bsdtar->compress_program);
	else
		archive_read_support_compression_all(a);
	archive_read_support_format_all(a);
	if (ARCHIVE_OK != archive_read_set_options(a, bsdtar->option_options))
		lafe_errc(1, 0, "%s", archive_error_string(a));
	if (archive_read_open_file(a, bsdtar->filename,
	    bsdtar->bytes_per_block != 0 ? bsdtar->bytes_per_block :
	    DEFAULT_BYTES_PER_BLOCK))
		lafe_errc(1, 0, "Error opening archive: %s",
		    archive_error_string(a));

	do_chdir(bsdtar);

	if (mode == 'x') {
		/* Set an extract callback so that we can handle SIGINFO. */
		progress_data.bsdtar = bsdtar;
		progress_data.archive = a;
		archive_read_extract_set_progress_callback(a, progress_func,
		    &progress_data);
	}

	if (mode == 'x' && bsdtar->option_chroot) {
#if HAVE_CHROOT
		if (chroot(".") != 0)
			lafe_errc(1, errno, "Can't chroot to \".\"");
#else
		lafe_errc(1, 0,
		    "chroot isn't supported on this platform");
#endif
	}

	for (;;) {
		/* Support --fast-read option */
		if (bsdtar->option_fast_read &&
		    lafe_unmatched_inclusions(bsdtar->matching) == 0)
			break;

		r = archive_read_next_header(a, &entry);
		progress_data.entry = entry;
		if (r == ARCHIVE_EOF)
			break;
		if (r < ARCHIVE_OK)
			lafe_warnc(0, "%s", archive_error_string(a));
		if (r <= ARCHIVE_WARN)
			bsdtar->return_value = 1;
		if (r == ARCHIVE_RETRY) {
			/* Retryable error: try again */
			lafe_warnc(0, "Retrying...");
			continue;
		}
		if (r == ARCHIVE_FATAL)
			break;

		if (bsdtar->uid >= 0) {
			archive_entry_set_uid(entry, bsdtar->uid);
			archive_entry_set_uname(entry, NULL);
		}
		if (bsdtar->gid >= 0) {
			archive_entry_set_gid(entry, bsdtar->gid);
			archive_entry_set_gname(entry, NULL);
		}
		if (bsdtar->uname)
			archive_entry_set_uname(entry, bsdtar->uname);
		if (bsdtar->gname)
			archive_entry_set_gname(entry, bsdtar->gname);

		/*
		 * Exclude entries that are too old.
		 */
		st = archive_entry_stat(entry);
		if (bsdtar->newer_ctime_sec > 0) {
			if (st->st_ctime < bsdtar->newer_ctime_sec)
				continue; /* Too old, skip it. */
			if (st->st_ctime == bsdtar->newer_ctime_sec
			    && ARCHIVE_STAT_CTIME_NANOS(st)
			    <= bsdtar->newer_ctime_nsec)
				continue; /* Too old, skip it. */
		}
		if (bsdtar->newer_mtime_sec > 0) {
			if (st->st_mtime < bsdtar->newer_mtime_sec)
				continue; /* Too old, skip it. */
			if (st->st_mtime == bsdtar->newer_mtime_sec
			    && ARCHIVE_STAT_MTIME_NANOS(st)
			    <= bsdtar->newer_mtime_nsec)
				continue; /* Too old, skip it. */
		}

		/*
		 * Note that pattern exclusions are checked before
		 * pathname rewrites are handled.  This gives more
		 * control over exclusions, since rewrites always lose
		 * information.  (For example, consider a rewrite
		 * s/foo[0-9]/foo/.  If we check exclusions after the
		 * rewrite, there would be no way to exclude foo1/bar
		 * while allowing foo2/bar.)
		 */
		if (lafe_excluded(bsdtar->matching, archive_entry_pathname(entry)))
			continue; /* Excluded by a pattern test. */

		if (mode == 't') {
			/* Perversely, gtar uses -O to mean "send to stderr"
			 * when used with -t. */
			out = bsdtar->option_stdout ? stderr : stdout;

			/*
			 * TODO: Provide some reasonable way to
			 * preview rewrites.  gtar always displays
			 * the unedited path in -t output, which means
			 * you cannot easily preview rewrites.
			 */
			if (bsdtar->verbose < 2)
				safe_fprintf(out, "%s",
				    archive_entry_pathname(entry));
			else
				list_item_verbose(bsdtar, out, entry);
			fflush(out);
			r = archive_read_data_skip(a);
			if (r == ARCHIVE_WARN) {
				fprintf(out, "\n");
				lafe_warnc(0, "%s",
				    archive_error_string(a));
			}
			if (r == ARCHIVE_RETRY) {
				fprintf(out, "\n");
				lafe_warnc(0, "%s",
				    archive_error_string(a));
			}
			if (r == ARCHIVE_FATAL) {
				fprintf(out, "\n");
				lafe_warnc(0, "%s",
				    archive_error_string(a));
				bsdtar->return_value = 1;
				break;
			}
			fprintf(out, "\n");
		} else {
			/* Note: some rewrite failures prevent extraction. */
			if (edit_pathname(bsdtar, entry))
				continue; /* Excluded by a rewrite failure. */

			if (bsdtar->option_interactive &&
			    !yes("extract '%s'", archive_entry_pathname(entry)))
				continue;

			/*
			 * Format here is from SUSv2, including the
			 * deferred '\n'.
			 */
			if (bsdtar->verbose) {
				safe_fprintf(stderr, "x %s",
				    archive_entry_pathname(entry));
				fflush(stderr);
			}

			// TODO siginfo_printinfo(bsdtar, 0);

			if (bsdtar->option_stdout)
				r = archive_read_data_into_fd(a, 1);
			else
				r = archive_read_extract(a, entry,
				    bsdtar->extract_flags);
			if (r != ARCHIVE_OK) {
				if (!bsdtar->verbose)
					safe_fprintf(stderr, "%s",
					    archive_entry_pathname(entry));
				safe_fprintf(stderr, ": %s",
				    archive_error_string(a));
				if (!bsdtar->verbose)
					fprintf(stderr, "\n");
				bsdtar->return_value = 1;
			}
			if (bsdtar->verbose)
				fprintf(stderr, "\n");
			if (r == ARCHIVE_FATAL)
				break;
		}
	}


	r = archive_read_close(a);
	if (r != ARCHIVE_OK)
		lafe_warnc(0, "%s", archive_error_string(a));
	if (r <= ARCHIVE_WARN)
		bsdtar->return_value = 1;

	if (bsdtar->verbose > 2)
		fprintf(stdout, "Archive Format: %s,  Compression: %s\n",
		    archive_format_name(a), archive_compression_name(a));

	archive_read_finish(a);
}
Пример #7
0
/*
 * Handle 'x' and 't' modes.
 */
static void
read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer)
{
	struct progress_data	progress_data;
	FILE			 *out;
	struct archive		 *a;
	struct archive_entry	 *entry;
	const char		 *reader_options;
	int			  r;

	while (*bsdtar->argv) {
		if (archive_match_include_pattern(bsdtar->matching,
		    *bsdtar->argv) != ARCHIVE_OK)
			lafe_errc(1, 0, "Error inclusion pattern: %s",
			    archive_error_string(bsdtar->matching));
		bsdtar->argv++;
	}

	if (bsdtar->names_from_file != NULL)
		if (archive_match_include_pattern_from_file(
		    bsdtar->matching, bsdtar->names_from_file,
		    bsdtar->option_null) != ARCHIVE_OK)
			lafe_errc(1, 0, "Error inclusion pattern: %s",
			    archive_error_string(bsdtar->matching));

	a = archive_read_new();
	if (cset_read_support_filter_program(bsdtar->cset, a) == 0)
		archive_read_support_filter_all(a);
	archive_read_support_format_all(a);

	reader_options = getenv(ENV_READER_OPTIONS);
	if (reader_options != NULL) {
		char *p;
		/* Set default read options. */
		p = malloc(sizeof(IGNORE_WRONG_MODULE_NAME)
		    + strlen(reader_options) + 1);
		if (p == NULL)
			lafe_errc(1, errno, "Out of memory");
		/* Prepend magic code to ignore options for
		 * a format or  modules which are not added to
		 *  the archive read object. */
		strncpy(p, IGNORE_WRONG_MODULE_NAME,
		    sizeof(IGNORE_WRONG_MODULE_NAME) -1);
		strcpy(p + sizeof(IGNORE_WRONG_MODULE_NAME) -1, reader_options);
		r = archive_read_set_options(a, p);
		free(p);
		if (r == ARCHIVE_FATAL)
			lafe_errc(1, 0, "%s", archive_error_string(a));
		else
			archive_clear_error(a);
	}
	if (ARCHIVE_OK != archive_read_set_options(a, bsdtar->option_options))
		lafe_errc(1, 0, "%s", archive_error_string(a));
	if (archive_read_open_filename(a, bsdtar->filename,
					bsdtar->bytes_per_block))
		lafe_errc(1, 0, "Error opening archive: %s",
		    archive_error_string(a));

	do_chdir(bsdtar);

	if (mode == 'x') {
		/* Set an extract callback so that we can handle SIGINFO. */
		progress_data.bsdtar = bsdtar;
		progress_data.archive = a;
		archive_read_extract_set_progress_callback(a, progress_func,
		    &progress_data);
	}

	if (mode == 'x' && bsdtar->option_chroot) {
#if HAVE_CHROOT
		if (chroot(".") != 0)
			lafe_errc(1, errno, "Can't chroot to \".\"");
#else
		lafe_errc(1, 0,
		    "chroot isn't supported on this platform");
#endif
	}

	for (;;) {
		/* Support --fast-read option */
		if (bsdtar->option_fast_read &&
		    archive_match_path_unmatched_inclusions(bsdtar->matching) == 0)
			break;

		r = archive_read_next_header(a, &entry);
		progress_data.entry = entry;
		if (r == ARCHIVE_EOF)
			break;
		if (r < ARCHIVE_OK)
			lafe_warnc(0, "%s", archive_error_string(a));
		if (r <= ARCHIVE_WARN)
			bsdtar->return_value = 1;
		if (r == ARCHIVE_RETRY) {
			/* Retryable error: try again */
			lafe_warnc(0, "Retrying...");
			continue;
		}
		if (r == ARCHIVE_FATAL)
			break;

		if (bsdtar->uid >= 0) {
			archive_entry_set_uid(entry, bsdtar->uid);
			archive_entry_set_uname(entry, NULL);
		}
		if (bsdtar->gid >= 0) {
			archive_entry_set_gid(entry, bsdtar->gid);
			archive_entry_set_gname(entry, NULL);
		}
		if (bsdtar->uname)
			archive_entry_set_uname(entry, bsdtar->uname);
		if (bsdtar->gname)
			archive_entry_set_gname(entry, bsdtar->gname);

		/*
		 * Note that pattern exclusions are checked before
		 * pathname rewrites are handled.  This gives more
		 * control over exclusions, since rewrites always lose
		 * information.  (For example, consider a rewrite
		 * s/foo[0-9]/foo/.  If we check exclusions after the
		 * rewrite, there would be no way to exclude foo1/bar
		 * while allowing foo2/bar.)
		 */
		if (archive_match_excluded(bsdtar->matching, entry))
			continue; /* Excluded by a pattern test. */

		if (mode == 't') {
			/* Perversely, gtar uses -O to mean "send to stderr"
			 * when used with -t. */
			out = bsdtar->option_stdout ? stderr : stdout;

			/*
			 * TODO: Provide some reasonable way to
			 * preview rewrites.  gtar always displays
			 * the unedited path in -t output, which means
			 * you cannot easily preview rewrites.
			 */
			if (bsdtar->verbose < 2)
				safe_fprintf(out, "%s",
				    archive_entry_pathname(entry));
			else
				list_item_verbose(bsdtar, out, entry);
			fflush(out);
			r = archive_read_data_skip(a);
			if (r == ARCHIVE_WARN) {
				fprintf(out, "\n");
				lafe_warnc(0, "%s",
				    archive_error_string(a));
			}
			if (r == ARCHIVE_RETRY) {
				fprintf(out, "\n");
				lafe_warnc(0, "%s",
				    archive_error_string(a));
			}
			if (r == ARCHIVE_FATAL) {
				fprintf(out, "\n");
				lafe_warnc(0, "%s",
				    archive_error_string(a));
				bsdtar->return_value = 1;
				break;
			}
			fprintf(out, "\n");
		} else {
			/* Note: some rewrite failures prevent extraction. */
			if (edit_pathname(bsdtar, entry))
				continue; /* Excluded by a rewrite failure. */

			if (bsdtar->option_interactive &&
			    !yes("extract '%s'", archive_entry_pathname(entry)))
				continue;

			/*
			 * Format here is from SUSv2, including the
			 * deferred '\n'.
			 */
			if (bsdtar->verbose) {
				safe_fprintf(stderr, "x %s",
				    archive_entry_pathname(entry));
				fflush(stderr);
			}

			/* TODO siginfo_printinfo(bsdtar, 0); */

			if (bsdtar->option_stdout)
				r = archive_read_data_into_fd(a, 1);
			else
				r = archive_read_extract2(a, entry, writer);
			if (r != ARCHIVE_OK) {
				if (!bsdtar->verbose)
					safe_fprintf(stderr, "%s",
					    archive_entry_pathname(entry));
				safe_fprintf(stderr, ": %s",
				    archive_error_string(a));
				if (!bsdtar->verbose)
					fprintf(stderr, "\n");
				bsdtar->return_value = 1;
			}
			if (bsdtar->verbose)
				fprintf(stderr, "\n");
			if (r == ARCHIVE_FATAL)
				break;
		}
	}


	r = archive_read_close(a);
	if (r != ARCHIVE_OK)
		lafe_warnc(0, "%s", archive_error_string(a));
	if (r <= ARCHIVE_WARN)
		bsdtar->return_value = 1;

	if (bsdtar->verbose > 2)
		fprintf(stdout, "Archive Format: %s,  Compression: %s\n",
		    archive_format_name(a), archive_filter_name(a, 0));

	archive_read_free(a);
}
Пример #8
0
BOSNode *file_type_archive_alloc(load_images_state_t state, file_t *file) {/*{{{*/
	GError *error_pointer = NULL;
	GBytes *data = buffered_file_as_bytes(file, NULL, &error_pointer);
	if(!data) {
		g_printerr("Failed to load archive %s: %s\n", file->display_name, error_pointer ? error_pointer->message : "Unknown error");
		g_clear_error(&error_pointer);
		file_free(file);
		return FALSE_POINTER;
	}

	struct archive *archive = file_type_archive_gen_archive(data);
	if(!archive) {
		buffered_file_unref(file);
		file_free(file);
		return FALSE_POINTER;
	}

	GtkFileFilterInfo file_filter_info;
	file_filter_info.contains = GTK_FILE_FILTER_FILENAME | GTK_FILE_FILTER_DISPLAY_NAME;

	BOSNode *first_node = FALSE_POINTER;

	struct archive_entry *entry;
	while(archive_read_next_header(archive, &entry) == ARCHIVE_OK) {
		const gchar *entry_name = archive_entry_pathname(entry);

		#if ARCHIVE_VERSION_NUMBER < 3003002
			// Affected by libarchive bug #869
			if(archive_entry_size(entry) == 0) {
				const char *archive_format = archive_format_name(archive);
				if(strncmp("ZIP", archive_format, 3) == 0) {
					g_printerr("Failed to load archive %s: This ZIP file is affected by libarchive bug #869, which was fixed in v3.3.2. Skipping file.\n", file->display_name);
					archive_read_free(archive);
					buffered_file_unref(file);
					file_free(file);
					return FALSE_POINTER;
				}
			}
		#endif


		// Prepare a new file_t for this entry
		gchar *sub_name = g_strdup_printf("%s#%s", file->display_name, entry_name);
		file_t *new_file = image_loader_duplicate_file(file, g_strdup(sub_name), g_strdup(sub_name), sub_name);
		if(new_file->file_data) {
			g_bytes_unref(new_file->file_data);
			new_file->file_data = NULL;
		}
		size_t delegate_struct_alloc_size = sizeof(file_loader_delegate_archive_t) + strlen(entry_name) + 2;
		file_loader_delegate_archive_t *new_file_data = g_malloc(delegate_struct_alloc_size);
		new_file_data->source_archive = image_loader_duplicate_file(file, NULL, NULL, NULL);
		new_file_data->entry_name     = (char *)(new_file_data) + sizeof(file_loader_delegate_archive_t) + 1;
		memcpy(new_file_data->entry_name, entry_name, strlen(entry_name) + 1);
		new_file->file_data = g_bytes_new_with_free_func(new_file_data, delegate_struct_alloc_size, (GDestroyNotify)file_type_archive_data_free, new_file_data);
		new_file->file_flags |= FILE_FLAGS_MEMORY_IMAGE;
		new_file->file_data_loader = file_type_archive_data_loader;

		// Find an appropriate handler for this file
		gchar *name_lowerc = g_utf8_strdown(entry_name, -1);
		file_filter_info.filename = file_filter_info.display_name = name_lowerc;

		// Check if one of the file type handlers can handle this file
		BOSNode *node = load_images_handle_parameter_find_handler(entry_name, state, new_file, &file_filter_info);
		if(node == NULL) {
			// No handler found. We could fall back to using a default. Free new_file instead.
			file_free(new_file);
		}
		else if(node == FALSE_POINTER) {
			// File type is known, but loading failed; new_file has already been free()d
			node = NULL;
		}
		else if(first_node == FALSE_POINTER) {
			first_node = node;
		}

		g_free(name_lowerc);

		archive_read_data_skip(archive);
	}

	archive_read_free(archive);
	buffered_file_unref(file);
	file_free(file);
	return first_node;
}/*}}}*/
Пример #9
0
int main(int argc, char* argv[]){
	struct archive* ar;
	struct archive_entry* aren;
	int arnum;

	if(argc < 3){
		fprintf(stderr, "Usage: %s infile outfile\n", argv[0]);
		return 255;
	}

#ifdef ENABLE_STAGE_1
	puts("==> Stage 1: Listing");

	ar = archive_read_new();
	archive_read_support_filter_all(ar);
	archive_read_support_format_all(ar);

	arnum = archive_read_open_filename(ar, argv[1], 16384);
	if(arnum != ARCHIVE_OK){
		fprintf(stderr, "%s: %s: %s\n", 
			argv[0], argv[1], archive_error_string(ar));
		return 1;
	}

	while(archive_read_next_header(ar, &aren) == ARCHIVE_OK){
		const char *hardlink, *symlink;
		printf("%s format: %s, pathname: %s, size: %"PRId64", links: %d,"
			   "username: %s, uid: %d", 
			argv[1], archive_format_name(ar), archive_entry_pathname(aren),
			archive_entry_size(aren), archive_entry_nlink(aren),
			archive_entry_uname(aren), archive_entry_uid(aren));
		hardlink = archive_entry_hardlink(aren);
		symlink = archive_entry_symlink(aren);
		if(hardlink != NULL){
			printf(", hardlink: %s", hardlink);
		}
		if(symlink != NULL){
			printf(", symlink: %s", symlink);
		}
		putchar('\n');
	}
	
	archive_read_close(ar);
	archive_read_free(ar);
#endif

#ifdef ENABLE_STAGE_2
	puts("==> Stage 2: Displaying");

	ar = archive_read_new();
	archive_read_support_filter_all(ar);
	archive_read_support_format_all(ar);

	arnum = archive_read_open_filename(ar, argv[1], 16384);
	if(arnum != ARCHIVE_OK){
		fprintf(stderr, "%s: %s: %s\n",
			argv[0], argv[1], archive_error_string(ar));
		return 2;
	}

	while(archive_read_next_header(ar, &aren) == ARCHIVE_OK){
		printf("<<< %s >>>\n", archive_entry_pathname(aren));
		for(;;){
			size_t size;
			off_t  offset;
			const void* buffer;
			switch(archive_read_data_block(ar, &buffer, &size, &offset)){
				case ARCHIVE_OK:
					puts(":: Block reading succeeded");
					fwrite(buffer, size, 1, stdout);
					break;
				case ARCHIVE_WARN:
					puts(":: Block reading succeeded, warning exists");
					fwrite(buffer, size, 1, stdout);
					break;
				case ARCHIVE_EOF:
					goto loop_outside;
				case ARCHIVE_RETRY:
					puts(":: Block reading failed, retrying");
					break;
				case ARCHIVE_FATAL:
					puts(":: Fatal error! STOP!");
					return 2;
			}
		}
loop_outside:
		puts("@@ Extract OK @@");
	}

	archive_read_close(ar);
	archive_read_free(ar);
#endif

#ifdef ENABLE_STAGE_3
	puts("==> Stage 3: Extracting");

	struct archive* arext;

	ar = archive_read_new();
	archive_read_support_format_all(ar);
	archive_read_support_filter_all(ar);

	arext = archive_write_disk_new();
	archive_write_disk_set_options(arext,
		ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_ACL | 
		ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_XATTR );
	archive_write_disk_set_standard_lookup(arext);

	if(archive_read_open_filename(ar, argv[1], 16384)){
		fprintf(stderr, "%s: %s: %s\n",
			argv[0], argv[1], archive_error_string(ar));
		return 3;
	}

	while((arnum = archive_read_next_header(ar, &aren)) == ARCHIVE_OK){
		int filesize, accsize;
		printf("<<< %s >>>\n", archive_entry_pathname(aren));
		if(archive_write_header(arext, aren) != ARCHIVE_OK){
			puts(":: Write header not OK ...");
		}else if((filesize = archive_entry_size(aren)) > 0){
			accsize = 0;
			for(;;){
				size_t size;
				off_t  offset;
				const void* buffer;
				arnum = archive_read_data_block(ar, &buffer, &size, &offset);
				if(arnum != ARCHIVE_OK){
					break;
				}
				arnum = archive_write_data(arext, buffer, size);
				if(arnum >= 0){
					accsize += arnum;
					printf(":: %d of %d bytes written\n", accsize, filesize);
				}
			}
		}
		
		if(archive_write_finish_entry(arext) != ARCHIVE_OK){
			return 3;
		}
	}

	archive_read_close(ar);
	archive_read_free(ar);
	archive_write_close(arext);
	archive_write_free(arext);
#endif


	return 0;
}
Пример #10
0
static foreign_t
archive_header_prop(term_t archive, term_t field)
{ archive_wrapper *ar;
  functor_t prop;

  if ( !get_archive(archive, &ar) )
    return FALSE;

  if ( !PL_get_functor(field, &prop) )
    return PL_type_error("compound", field);
  if ( ar->status != AR_NEW_ENTRY )
    return PL_permission_error("access", "archive_entry", archive);

  if ( prop == FUNCTOR_filetype1 )
  { __LA_MODE_T type = archive_entry_filetype(ar->entry);
    atom_t name;
    term_t arg = PL_new_term_ref();
    _PL_get_arg(1, field, arg);

    switch(type&AE_IFMT)
    { case AE_IFREG:  name = ATOM_file;             break;
      case AE_IFLNK:  name = ATOM_link;             break;
      case AE_IFSOCK: name = ATOM_socket;           break;
      case AE_IFCHR:  name = ATOM_character_device; break;
      case AE_IFBLK:  name = ATOM_block_device;     break;
      case AE_IFDIR:  name = ATOM_directory;        break;
      case AE_IFIFO:  name = ATOM_fifo;             break;
      default:
	return PL_unify_integer(arg, (type&AE_IFMT));
    }
    return PL_unify_atom(arg, name);
  } else if ( prop == FUNCTOR_mtime1 )
  { time_t stamp = archive_entry_mtime(ar->entry);
    term_t arg = PL_new_term_ref();
    _PL_get_arg(1, field, arg);

    return PL_unify_float(arg, (double)stamp);
  } else if ( prop == FUNCTOR_size1 )
  { int64_t size = archive_entry_size(ar->entry);
    term_t arg = PL_new_term_ref();
    _PL_get_arg(1, field, arg);

    return PL_unify_int64(arg, size);
  } else if ( prop == FUNCTOR_link_target1 )
  { __LA_MODE_T type = archive_entry_filetype(ar->entry);
    const wchar_t *target = NULL;

    switch(type&AE_IFMT)
    { case AE_IFLNK:
	target = archive_entry_symlink_w(ar->entry);
        break;
    }

    if ( target )
    { term_t arg = PL_new_term_ref();
      _PL_get_arg(1, field, arg);

      return PL_unify_wchars(arg, PL_ATOM, (size_t)-1, target);
    }

    return FALSE;
  } else if ( prop == FUNCTOR_format1 )
  { const char *s = archive_format_name(ar->archive);

    if ( s )
    { char lwr[50];
      char *o;
      term_t arg = PL_new_term_ref();
      _PL_get_arg(1, field, arg);

      for(o=lwr; *s && o < lwr+sizeof(lwr); )
	*o++ = tolower(*s++);

      *o = '\0';

      return PL_unify_atom_chars(arg, lwr);
    }
  }

  return PL_domain_error("archive_header_property", field);
}