1 /* $NetBSD: main.c,v 1.1 2013/05/03 23:28:15 riastradh Exp $ */ 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: main.c,v 1.1 2013/05/03 23:28:15 riastradh Exp $"); 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 44 static int (*operation)(int, char **, const struct options *) = &vndcompress; 45 46 int 47 main(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, "cdk:l:p:rRs:")) != -1) { 64 switch (ch) { 65 case 'c': 66 if (ISSET(O->flags, FLAG_d)) { 67 warnx("-c and -d are mutually exclusive"); 68 usage(); 69 } 70 O->flags |= FLAG_c; 71 operation = &vndcompress; 72 break; 73 74 case 'd': 75 if (ISSET(O->flags, FLAG_c)) { 76 warnx("-c and -d are mutually exclusive"); 77 usage(); 78 } 79 O->flags |= FLAG_d; 80 operation = &vnduncompress; 81 break; 82 83 case 'k': 84 if (ISSET(O->flags, FLAG_k)) { 85 warnx("-k may be supplied only once"); 86 usage(); 87 } 88 O->flags |= FLAG_k; 89 O->checkpoint_blocks = strsuftoll("checkpoint blocks", 90 optarg, 91 0, MIN(UINT32_MAX, (OFF_MAX / MIN_BLOCKSIZE))); 92 break; 93 94 case 'l': 95 if (ISSET(O->flags, FLAG_l)) { 96 warnx("-l may be supplied only once"); 97 usage(); 98 } 99 O->flags |= FLAG_l; 100 O->length = strsuftoll("length", optarg, 101 0, MIN(OFF_MAX, UINT64_MAX)); 102 break; 103 104 case 'p': 105 O->flags |= FLAG_p; 106 __CTASSERT(OFF_MAX <= LLONG_MAX); 107 O->end_block = strsuftoll("end block", optarg, 108 0, MIN(UINT32_MAX, (OFF_MAX / MIN_BLOCKSIZE))); 109 break; 110 111 case 'r': 112 O->flags |= FLAG_r; 113 break; 114 115 case 'R': 116 O->flags |= FLAG_R; 117 break; 118 119 case 's': 120 if (ISSET(O->flags, FLAG_s)) { 121 warnx("-s may be supplied only once"); 122 usage(); 123 } 124 O->flags |= FLAG_s; 125 __CTASSERT(MIN_BLOCKSIZE <= MAX_BLOCKSIZE); 126 __CTASSERT(MAX_BLOCKSIZE <= LLONG_MAX); 127 O->blocksize = strsuftoll("block size", optarg, 128 MIN_BLOCKSIZE, MAX_BLOCKSIZE); 129 break; 130 131 case '?': 132 default: 133 usage(); 134 } 135 } 136 137 argc -= optind; 138 argv += optind; 139 140 if (operation == &vnduncompress) { 141 if (ISSET(O->flags, ~FLAG_d)) 142 usage(); 143 } else { 144 assert(operation == &vndcompress); 145 if (ISSET(O->flags, ~(FLAG_c | FLAG_k | FLAG_l | FLAG_p | 146 FLAG_r | FLAG_s | FLAG_R))) 147 usage(); 148 if (ISSET(O->flags, FLAG_R) && !ISSET(O->flags, FLAG_r)) { 149 warnx("-R makes no sense without -r"); 150 usage(); 151 } 152 } 153 154 return (*operation)(argc, argv, O); 155 } 156 157 void __dead 158 usage(void) 159 { 160 161 (void)fprintf(stderr, 162 "Usage: %s -c [-rR] [-k <checkpoint-blocks>] [-l <length>]\n" 163 " [-p <partial-offset>] [-s <blocksize>]\n" 164 " <image> <compressed-image> [<blocksize>]\n" 165 " %s -d <compressed-image> <image>\n", 166 getprogname(), getprogname()); 167 exit(1); 168 } 169