1/* $NetBSD: main.c,v 1.14 2020/05/24 18:42:20 jmcneill Exp $ */ 2 3/*- 4 * Copyright (c) 2002 Marcel Moolenaar 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * CRC32 code derived from work by Gary S. Brown. 29 */ 30 31#if HAVE_NBTOOL_CONFIG_H 32#include "nbtool_config.h" 33#endif 34 35#include <sys/cdefs.h> 36#ifdef __RCSID 37__RCSID("$NetBSD: main.c,v 1.14 2020/05/24 18:42:20 jmcneill Exp $"); 38#endif 39 40#include <stdio.h> 41#include <stdlib.h> 42#include <unistd.h> 43#include <err.h> 44#include <errno.h> 45#include <sys/stat.h> 46#ifndef NBTOOL_CONFIG_H 47#include <util.h> 48#endif 49 50#include "map.h" 51#include "gpt.h" 52 53static const struct gpt_cmd c_null; 54 55extern const struct gpt_cmd 56 c_add, 57#ifndef HAVE_NBTOOL_CONFIG_H 58 c_backup, 59#endif 60 c_biosboot, 61 c_create, 62 c_destroy, 63 c_header, 64 c_label, 65 c_migrate, 66 c_recover, 67 c_remove, 68 c_resize, 69 c_resizedisk, 70#ifndef HAVE_NBTOOL_CONFIG_H 71 c_restore, 72#endif 73 c_set, 74 c_show, 75 c_type, 76 c_unset, 77 c_uuid; 78 79static const struct gpt_cmd *cmdsw[] = { 80 &c_add, 81#ifndef HAVE_NBTOOL_CONFIG_H 82 &c_backup, 83#endif 84 &c_biosboot, 85 &c_create, 86 &c_destroy, 87 &c_header, 88 &c_label, 89 &c_migrate, 90 &c_recover, 91 &c_remove, 92 &c_resize, 93 &c_resizedisk, 94#ifndef HAVE_NBTOOL_CONFIG_H 95 &c_restore, 96#endif 97 &c_set, 98 &c_show, 99 &c_type, 100 &c_unset, 101 &c_uuid, 102 &c_null, 103}; 104 105__dead static void 106usage(void) 107{ 108 const char *p = getprogname(); 109 const char *f = 110 "[-nrqv] [-m mediasize] [-s sectorsize] [-T timestamp]"; 111 size_t i; 112 113 if (strcmp(p, "gpt") == 0) 114 fprintf(stderr, 115 "Usage: %s %s command device\n", p, f); 116 else 117 fprintf(stderr, 118 "Usage: %s %s device command\n", p, f); 119 fprintf(stderr, "Commands:\n"); 120 for (i = 0; i < __arraycount(cmdsw); i++) 121 gpt_usage("\t", cmdsw[i]); 122 exit(EXIT_FAILURE); 123} 124 125static void 126prefix(const char *cmd) 127{ 128 char *pfx; 129 130 if (asprintf(&pfx, "%s %s", getprogname(), cmd) < 0) 131 pfx = NULL; 132 else 133 setprogname(pfx); 134} 135 136static time_t 137get_tstamp(const char *b) 138{ 139 struct stat st; 140 char *eb; 141 long long l; 142#ifndef HAVE_NBTOOL_CONFIG_H 143 time_t when; 144#endif 145 146 if (stat(b, &st) != -1) 147 return (time_t)st.st_mtime; 148 149#ifndef HAVE_NBTOOL_CONFIG_H 150 errno = 0; 151 if ((when = parsedate(b, NULL, NULL)) != -1 || errno == 0) 152 return when; 153#endif 154 errno = 0; 155 l = strtoll(b, &eb, 0); 156 if (b == eb || *eb || errno) 157 errx(EXIT_FAILURE, "Can't parse timestamp `%s'", b); 158 return (time_t)l; 159} 160 161int 162main(int argc, char *argv[]) 163{ 164 char *cmd, *p, *dev = NULL; 165 int ch, i; 166 u_int secsz = 0; 167 off_t mediasz = 0; 168 int flags = 0; 169 int verbose = 0; 170 time_t timestamp = 0; 171 gpt_t gpt; 172 173 setprogname(argv[0]); 174 175 if (strcmp(getprogname(), "gpt") == 0) { 176 if (argc < 3) 177 usage(); 178 dev = argv[--argc]; 179 } 180 181#ifdef __GLIBC__ 182#define GETOPT_BE_POSIX "+" 183#else 184#define GETOPT_BE_POSIX "" 185#endif 186 187 /* Get the generic options */ 188 while ((ch = getopt(argc, argv, GETOPT_BE_POSIX "Hm:nqrs:T:v")) != -1) { 189 switch(ch) { 190 case 'H': 191 flags |= GPT_HYBRID; 192 break; 193 case 'm': 194 if (mediasz > 0) 195 usage(); 196 mediasz = strtol(optarg, &p, 10); 197 if (*p != 0 || mediasz < 1) 198 usage(); 199 break; 200 case 'n': 201 flags |= GPT_NOSYNC; 202 break; 203 case 'r': 204 flags |= GPT_READONLY; 205 break; 206 case 'q': 207 flags |= GPT_QUIET; 208 break; 209 case 's': 210 if (gpt_uint_get(NULL, &secsz) == -1) 211 usage(); 212 break; 213 case 'T': 214 flags |= GPT_TIMESTAMP; 215 timestamp = get_tstamp(optarg); 216 break; 217 case 'v': 218 verbose++; 219 break; 220 default: 221 usage(); 222 } 223 } 224 225 if (argc == optind) 226 usage(); 227 228 if (dev == NULL) 229 dev = argv[optind++]; 230 231 if (argc == optind) 232 usage(); 233 234 cmd = argv[optind++]; 235 for (i = 0; cmdsw[i]->name != NULL && strcmp(cmd, cmdsw[i]->name); i++) 236 continue; 237 238 if (cmdsw[i]->fptr == NULL) 239 errx(EXIT_FAILURE, "Unknown command: %s", cmd); 240 241 prefix(cmd); 242 243 if (*dev != '-') { 244 gpt = gpt_open(dev, flags | cmdsw[i]->flags, 245 verbose, mediasz, secsz, timestamp); 246 if (gpt == NULL) 247 return EXIT_FAILURE; 248 } else { 249 if ((cmdsw[i]->flags & GPT_OPTDEV) == 0) 250 errx(EXIT_FAILURE, 251 "Command %s needs a device parameter", cmd); 252 argc++; 253 gpt = NULL; 254 } 255 256 if ((*cmdsw[i]->fptr)(gpt, argc, argv) == -1) 257 return EXIT_FAILURE; 258 259 if (gpt) 260 gpt_close(gpt); 261 return EXIT_SUCCESS; 262} 263