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