1/* 2 * This file is in the public domain. 3 * 4 * Feel free to use it as you wish. 5 */ 6 7/* 8 * This example program reads an archive from stdin (which can be in 9 * any format recognized by libarchive) and writes certain entries to 10 * an uncompressed ustar archive on stdout. This is a template for 11 * many kinds of archive manipulation: converting formats, resetting 12 * ownership, inserting entries, removing entries, etc. 13 * 14 * To compile: 15 * gcc -Wall -o tarfilter tarfilter.c -larchive -lz -lbz2 16 */ 17 18#include <sys/stat.h> 19#include <archive.h> 20#include <archive_entry.h> 21#include <stdarg.h> 22#include <stdio.h> 23#include <stdlib.h> 24 25static void 26die(char *fmt, ...) 27{ 28 va_list ap; 29 30 va_start(ap, fmt); 31 vfprintf(stderr, fmt, ap); 32 va_end(ap); 33 fprintf(stderr, "\n"); 34 exit(1); 35} 36 37int 38main(int argc, char **argv) 39{ 40 char buff[8192]; 41 ssize_t len; 42 int r; 43 mode_t m; 44 struct archive *ina; 45 struct archive *outa; 46 struct archive_entry *entry; 47 48 /* Read an archive from stdin, with automatic format detection. */ 49 ina = archive_read_new(); 50 if (ina == NULL) 51 die("Couldn't create archive reader."); 52 if (archive_read_support_compression_all(ina) != ARCHIVE_OK) 53 die("Couldn't enable decompression"); 54 if (archive_read_support_format_all(ina) != ARCHIVE_OK) 55 die("Couldn't enable read formats"); 56 if (archive_read_open_fd(ina, 0, 10240) != ARCHIVE_OK) 57 die("Couldn't open input archive"); 58 59 /* Write an uncompressed ustar archive to stdout. */ 60 outa = archive_write_new(); 61 if (outa == NULL) 62 die("Couldn't create archive writer."); 63 if (archive_write_set_compression_none(outa) != ARCHIVE_OK) 64 die("Couldn't enable compression"); 65 if (archive_write_set_format_ustar(outa) != ARCHIVE_OK) 66 die("Couldn't set output format"); 67 if (archive_write_open_fd(outa, 1) != ARCHIVE_OK) 68 die("Couldn't open output archive"); 69 70 /* Examine each entry in the input archive. */ 71 while ((r = archive_read_next_header(ina, &entry)) == ARCHIVE_OK) { 72 fprintf(stderr, "%s: ", archive_entry_pathname(entry)); 73 74 /* Skip anything that isn't a regular file. */ 75 if (!S_ISREG(archive_entry_mode(entry))) { 76 fprintf(stderr, "skipped\n"); 77 continue; 78 } 79 80 /* Make everything owned by root/wheel. */ 81 archive_entry_set_uid(entry, 0); 82 archive_entry_set_uname(entry, "root"); 83 archive_entry_set_gid(entry, 0); 84 archive_entry_set_gname(entry, "wheel"); 85 86 /* Make everything permission 0744, strip SUID, etc. */ 87 m = archive_entry_mode(entry); 88 archive_entry_set_mode(entry, (m & ~07777) | 0744); 89 90 /* Copy input entries to output archive. */ 91 if (archive_write_header(outa, entry) != ARCHIVE_OK) 92 die("Error writing output archive"); 93 if (archive_entry_size(entry) > 0) { 94 len = archive_read_data(ina, buff, sizeof(buff)); 95 while (len > 0) { 96 if (archive_write_data(outa, buff, len) != len) 97 die("Error writing output archive"); 98 len = archive_read_data(ina, buff, sizeof(buff)); 99 } 100 if (len < 0) 101 die("Error reading input archive"); 102 } 103 fprintf(stderr, "copied\n"); 104 } 105 if (r != ARCHIVE_EOF) 106 die("Error reading archive"); 107 /* Close the archives. */ 108 if (archive_read_finish(ina) != ARCHIVE_OK) 109 die("Error closing input archive"); 110 if (archive_write_finish(outa) != ARCHIVE_OK) 111 die("Error closing output archive"); 112 return (0); 113} 114