1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2011-2014, Mike Kazantsev 5 * All rights reserved. 6 */ 7 8 #include "bsdcat_platform.h" 9 10 #include <stdio.h> 11 #ifdef HAVE_STDLIB_H 12 #include <stdlib.h> 13 #endif 14 #ifdef HAVE_UNISTD_H 15 #include <unistd.h> 16 #endif 17 #ifdef HAVE_STRING_H 18 #include <string.h> 19 #endif 20 21 #include <archive.h> 22 #include <archive_entry.h> 23 24 #include "bsdcat.h" 25 #include "err.h" 26 27 #define BYTES_PER_BLOCK (20*512) 28 29 static struct archive *a; 30 static struct archive_entry *ae; 31 static const char *bsdcat_current_path; 32 static int exit_status = 0; 33 34 35 static __LA_NORETURN void 36 usage(FILE *stream, int eval) 37 { 38 const char *p; 39 p = lafe_getprogname(); 40 fprintf(stream, 41 "Usage: %s [-h] [--help] [--version] [--] [filenames...]\n", p); 42 exit(eval); 43 } 44 45 static __LA_NORETURN void 46 version(void) 47 { 48 printf("bsdcat %s - %s \n", 49 BSDCAT_VERSION_STRING, 50 archive_version_details()); 51 exit(0); 52 } 53 54 static void 55 bsdcat_print_error(void) 56 { 57 lafe_warnc(0, "%s: %s", 58 bsdcat_current_path, archive_error_string(a)); 59 exit_status = 1; 60 } 61 62 static void 63 bsdcat_next(void) 64 { 65 if (a != NULL) { 66 if (archive_read_close(a) != ARCHIVE_OK) 67 bsdcat_print_error(); 68 archive_read_free(a); 69 } 70 71 a = archive_read_new(); 72 archive_read_support_filter_all(a); 73 archive_read_support_format_empty(a); 74 archive_read_support_format_raw(a); 75 } 76 77 static void 78 bsdcat_read_to_stdout(const char* filename) 79 { 80 int r; 81 82 if (archive_read_open_filename(a, filename, BYTES_PER_BLOCK) 83 != ARCHIVE_OK) 84 bsdcat_print_error(); 85 else if (r = archive_read_next_header(a, &ae), 86 r != ARCHIVE_OK && r != ARCHIVE_EOF) 87 bsdcat_print_error(); 88 else if (r == ARCHIVE_EOF) 89 /* for empty payloads don't try and read data */ 90 ; 91 else if (archive_read_data_into_fd(a, 1) != ARCHIVE_OK) 92 bsdcat_print_error(); 93 if (archive_read_close(a) != ARCHIVE_OK) 94 bsdcat_print_error(); 95 archive_read_free(a); 96 a = NULL; 97 } 98 99 int 100 main(int argc, char **argv) 101 { 102 struct bsdcat *bsdcat, bsdcat_storage; 103 int c; 104 105 bsdcat = &bsdcat_storage; 106 memset(bsdcat, 0, sizeof(*bsdcat)); 107 108 lafe_setprogname(*argv, "bsdcat"); 109 110 bsdcat->argv = argv; 111 bsdcat->argc = argc; 112 113 while ((c = bsdcat_getopt(bsdcat)) != -1) { 114 switch (c) { 115 case 'h': 116 usage(stdout, 0); 117 /* NOTREACHED */ 118 /* Fallthrough */ 119 case OPTION_VERSION: 120 version(); 121 /* NOTREACHED */ 122 /* Fallthrough */ 123 default: 124 usage(stderr, 1); 125 /* Fallthrough */ 126 /* NOTREACHED */ 127 } 128 } 129 130 bsdcat_next(); 131 if (*bsdcat->argv == NULL) { 132 bsdcat_current_path = "<stdin>"; 133 bsdcat_read_to_stdout(NULL); 134 } else { 135 while (*bsdcat->argv) { 136 bsdcat_current_path = *bsdcat->argv++; 137 bsdcat_read_to_stdout(bsdcat_current_path); 138 bsdcat_next(); 139 } 140 archive_read_free(a); /* Help valgrind & friends */ 141 } 142 143 exit(exit_status); 144 } 145