Blame examples/tarfilter.c

Packit Service 1d0348
/*
Packit Service 1d0348
 * This file is in the public domain.
Packit Service 1d0348
 *
Packit Service 1d0348
 * Feel free to use it as you wish.
Packit Service 1d0348
 */
Packit Service 1d0348
Packit Service 1d0348
/*
Packit Service 1d0348
 * This example program reads an archive from stdin (which can be in
Packit Service 1d0348
 * any format recognized by libarchive) and writes certain entries to
Packit Service 1d0348
 * an uncompressed ustar archive on stdout.  This is a template for
Packit Service 1d0348
 * many kinds of archive manipulation: converting formats, resetting
Packit Service 1d0348
 * ownership, inserting entries, removing entries, etc.
Packit Service 1d0348
 *
Packit Service 1d0348
 * To compile:
Packit Service 1d0348
 * gcc -Wall -o tarfilter tarfilter.c -larchive -lz -lbz2
Packit Service 1d0348
 */
Packit Service 1d0348
Packit Service 1d0348
#include <sys/stat.h>
Packit Service 1d0348
#include <archive.h>
Packit Service 1d0348
#include <archive_entry.h>
Packit Service 1d0348
#include <stdarg.h>
Packit Service 1d0348
#include <stdio.h>
Packit Service 1d0348
#include <stdlib.h>
Packit Service 1d0348
Packit Service 1d0348
static void
Packit Service 1d0348
die(char *fmt, ...)
Packit Service 1d0348
{
Packit Service 1d0348
	va_list ap;
Packit Service 1d0348
Packit Service 1d0348
	va_start(ap, fmt);
Packit Service 1d0348
	vfprintf(stderr, fmt, ap);
Packit Service 1d0348
	va_end(ap);
Packit Service 1d0348
	fprintf(stderr, "\n");
Packit Service 1d0348
	exit(1);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
int
Packit Service 1d0348
main(int argc, char **argv)
Packit Service 1d0348
{
Packit Service 1d0348
	char buff[8192];
Packit Service 1d0348
	ssize_t len;
Packit Service 1d0348
	int r;
Packit Service 1d0348
	mode_t m;
Packit Service 1d0348
	struct archive *ina;
Packit Service 1d0348
	struct archive *outa;
Packit Service 1d0348
	struct archive_entry *entry;
Packit Service 1d0348
Packit Service 1d0348
	/* Read an archive from stdin, with automatic format detection. */
Packit Service 1d0348
	ina = archive_read_new();
Packit Service 1d0348
	if (ina == NULL)
Packit Service 1d0348
		die("Couldn't create archive reader.");
Packit Service 1d0348
	if (archive_read_support_filter_all(ina) != ARCHIVE_OK)
Packit Service 1d0348
		die("Couldn't enable decompression");
Packit Service 1d0348
	if (archive_read_support_format_all(ina) != ARCHIVE_OK)
Packit Service 1d0348
		die("Couldn't enable read formats");
Packit Service 1d0348
	if (archive_read_open_fd(ina, 0, 10240) != ARCHIVE_OK)
Packit Service 1d0348
		die("Couldn't open input archive");
Packit Service 1d0348
Packit Service 1d0348
	/* Write an uncompressed ustar archive to stdout. */
Packit Service 1d0348
	outa = archive_write_new();
Packit Service 1d0348
	if (outa == NULL)
Packit Service 1d0348
		die("Couldn't create archive writer.");
Packit Service 1d0348
	if (archive_write_set_compression_none(outa) != ARCHIVE_OK)
Packit Service 1d0348
		die("Couldn't enable compression");
Packit Service 1d0348
	if (archive_write_set_format_ustar(outa) != ARCHIVE_OK)
Packit Service 1d0348
		die("Couldn't set output format");
Packit Service 1d0348
	if (archive_write_open_fd(outa, 1) != ARCHIVE_OK)
Packit Service 1d0348
		die("Couldn't open output archive");
Packit Service 1d0348
Packit Service 1d0348
	/* Examine each entry in the input archive. */
Packit Service 1d0348
	while ((r = archive_read_next_header(ina, &entry)) == ARCHIVE_OK) {
Packit Service 1d0348
		fprintf(stderr, "%s: ", archive_entry_pathname(entry));
Packit Service 1d0348
Packit Service 1d0348
		/* Skip anything that isn't a regular file. */
Packit Service 1d0348
		if (!S_ISREG(archive_entry_mode(entry))) {
Packit Service 1d0348
			fprintf(stderr, "skipped\n");
Packit Service 1d0348
			continue;
Packit Service 1d0348
		}
Packit Service 1d0348
Packit Service 1d0348
		/* Make everything owned by root/wheel. */
Packit Service 1d0348
		archive_entry_set_uid(entry, 0);
Packit Service 1d0348
		archive_entry_set_uname(entry, "root");
Packit Service 1d0348
		archive_entry_set_gid(entry, 0);
Packit Service 1d0348
		archive_entry_set_gname(entry, "wheel");
Packit Service 1d0348
Packit Service 1d0348
		/* Make everything permission 0744, strip SUID, etc. */
Packit Service 1d0348
		m = archive_entry_mode(entry);
Packit Service 1d0348
		archive_entry_set_mode(entry, (m & ~07777) | 0744);
Packit Service 1d0348
Packit Service 1d0348
		/* Copy input entries to output archive. */
Packit Service 1d0348
		if (archive_write_header(outa, entry) != ARCHIVE_OK)
Packit Service 1d0348
			die("Error writing output archive");
Packit Service 1d0348
		if (archive_entry_size(entry) > 0) {
Packit Service 1d0348
			len = archive_read_data(ina, buff, sizeof(buff));
Packit Service 1d0348
			while (len > 0) {
Packit Service 1d0348
				if (archive_write_data(outa, buff, len) != len)
Packit Service 1d0348
					die("Error writing output archive");
Packit Service 1d0348
				len = archive_read_data(ina, buff, sizeof(buff));
Packit Service 1d0348
			}
Packit Service 1d0348
			if (len < 0)
Packit Service 1d0348
				die("Error reading input archive");
Packit Service 1d0348
		}
Packit Service 1d0348
		fprintf(stderr, "copied\n");
Packit Service 1d0348
	}
Packit Service 1d0348
	if (r != ARCHIVE_EOF)
Packit Service 1d0348
		die("Error reading archive");
Packit Service 1d0348
	/* Close the archives.  */
Packit Service 1d0348
	if (archive_read_free(ina) != ARCHIVE_OK)
Packit Service 1d0348
		die("Error closing input archive");
Packit Service 1d0348
	if (archive_write_free(outa) != ARCHIVE_OK)
Packit Service 1d0348
		die("Error closing output archive");
Packit Service 1d0348
	return (0);
Packit Service 1d0348
}