1/* $NetBSD$ */ 2 3/*- 4 * Copyright (c) 2013 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Taylor R. Campbell. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33__RCSID("$NetBSD$"); 34 35#include <assert.h> 36#include <err.h> 37#include <getopt.h> 38#include <stdio.h> 39#include <stdlib.h> 40#include <string.h> 41 42#include "common.h" 43 44static int (*operation)(int, char **, const struct options *) = &vndcompress; 45 46int 47main(int argc, char **argv) 48{ 49 static const struct options zero_options; 50 struct options options = zero_options, *O = &options; 51 int ch; 52 53 setprogname(argv[0]); 54 55 if (strcmp(getprogname(), "vndcompress") == 0) 56 operation = &vndcompress; 57 else if (strcmp(getprogname(), "vnduncompress") == 0) 58 operation = &vnduncompress; 59 else 60 warnx("unknown program name, defaulting to vndcompress: %s", 61 getprogname()); 62 63 while ((ch = getopt(argc, argv, "b:cdk:l:p:rRw:")) != -1) { 64 switch (ch) { 65 case 'b': 66 if (ISSET(O->flags, FLAG_b)) { 67 warnx("-b may be supplied only once"); 68 usage(); 69 } 70 O->flags |= FLAG_b; 71 __CTASSERT(MIN_BLOCKSIZE <= MAX_BLOCKSIZE); 72 __CTASSERT(MAX_BLOCKSIZE <= LLONG_MAX); 73 O->blocksize = strsuftoll("block size", optarg, 74 MIN_BLOCKSIZE, MAX_BLOCKSIZE); 75 break; 76 77 case 'c': 78 if (ISSET(O->flags, FLAG_d)) { 79 warnx("-c and -d are mutually exclusive"); 80 usage(); 81 } 82 O->flags |= FLAG_c; 83 operation = &vndcompress; 84 break; 85 86 case 'd': 87 if (ISSET(O->flags, FLAG_c)) { 88 warnx("-c and -d are mutually exclusive"); 89 usage(); 90 } 91 O->flags |= FLAG_d; 92 operation = &vnduncompress; 93 break; 94 95 case 'k': 96 if (ISSET(O->flags, FLAG_k)) { 97 warnx("-k may be supplied only once"); 98 usage(); 99 } 100 O->flags |= FLAG_k; 101 O->checkpoint_blocks = strsuftoll("checkpoint blocks", 102 optarg, 103 0, MIN(UINT32_MAX, (OFF_MAX / MIN_BLOCKSIZE))); 104 break; 105 106 case 'l': 107 if (ISSET(O->flags, FLAG_l)) { 108 warnx("-l may be supplied only once"); 109 usage(); 110 } 111 O->flags |= FLAG_l; 112 O->length = strsuftoll("length", optarg, 113 0, MIN(OFF_MAX, UINT64_MAX)); 114 break; 115 116 case 'p': 117 O->flags |= FLAG_p; 118 __CTASSERT(OFF_MAX <= LLONG_MAX); 119 O->end_block = strsuftoll("end block", optarg, 120 0, MIN(UINT32_MAX, (OFF_MAX / MIN_BLOCKSIZE))); 121 break; 122 123 case 'r': 124 O->flags |= FLAG_r; 125 break; 126 127 case 'R': 128 O->flags |= FLAG_R; 129 break; 130 131 case 'w': 132 if (ISSET(O->flags, FLAG_w)) { 133 warnx("-w may be supplied only once"); 134 usage(); 135 } 136 O->flags |= FLAG_w; 137 O->window_size = strsuftoll("window size", optarg, 138 0, MAX_WINDOW_SIZE); 139 break; 140 141 case '?': 142 default: 143 usage(); 144 } 145 } 146 147 argc -= optind; 148 argv += optind; 149 150 if (operation == &vnduncompress) { 151 if (ISSET(O->flags, ~(FLAG_d | FLAG_w))) 152 usage(); 153 } else { 154 assert(operation == &vndcompress); 155 if (ISSET(O->flags, ~(FLAG_b | FLAG_c | FLAG_k | FLAG_l | 156 FLAG_p | FLAG_r | FLAG_R | FLAG_w))) 157 usage(); 158 if (ISSET(O->flags, FLAG_R) && !ISSET(O->flags, FLAG_r)) { 159 warnx("-R makes no sense without -r"); 160 usage(); 161 } 162 } 163 164 return (*operation)(argc, argv, O); 165} 166 167void __dead 168usage(void) 169{ 170 171 (void)fprintf(stderr, 172 "Usage: %s -c [-rR] [-b <blocksize>] [-k <checkpoint-blocks>]\n" 173 " [-l <length>] [-p <partial-offset>] [-w <winsize>]\n" 174 " <image> <compressed-image> [<blocksize>]\n" 175 " %s -d <compressed-image> <image>\n", 176 getprogname(), getprogname()); 177 exit(1); 178} 179