main.c revision 1.13
1/* $NetBSD: main.c,v 1.13 2019/06/25 04:53:40 jnemeth 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.13 2019/06/25 04:53:40 jnemeth 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 "m:nqrs:T:v")) != -1) { 189 switch(ch) { 190 case 'm': 191 if (mediasz > 0) 192 usage(); 193 mediasz = strtol(optarg, &p, 10); 194 if (*p != 0 || mediasz < 1) 195 usage(); 196 break; 197 case 'n': 198 flags |= GPT_NOSYNC; 199 break; 200 case 'r': 201 flags |= GPT_READONLY; 202 break; 203 case 'q': 204 flags |= GPT_QUIET; 205 break; 206 case 's': 207 if (gpt_uint_get(NULL, &secsz) == -1) 208 usage(); 209 break; 210 case 'T': 211 flags |= GPT_TIMESTAMP; 212 timestamp = get_tstamp(optarg); 213 break; 214 case 'v': 215 verbose++; 216 break; 217 default: 218 usage(); 219 } 220 } 221 222 if (argc == optind) 223 usage(); 224 225 if (dev == NULL) 226 dev = argv[optind++]; 227 228 if (argc == optind) 229 usage(); 230 231 cmd = argv[optind++]; 232 for (i = 0; cmdsw[i]->name != NULL && strcmp(cmd, cmdsw[i]->name); i++) 233 continue; 234 235 if (cmdsw[i]->fptr == NULL) 236 errx(EXIT_FAILURE, "Unknown command: %s", cmd); 237 238 prefix(cmd); 239 240 if (*dev != '-') { 241 gpt = gpt_open(dev, flags | cmdsw[i]->flags, 242 verbose, mediasz, secsz, timestamp); 243 if (gpt == NULL) 244 return EXIT_FAILURE; 245 } else { 246 if ((cmdsw[i]->flags & GPT_OPTDEV) == 0) 247 errx(EXIT_FAILURE, 248 "Command %s needs a device parameter", cmd); 249 argc++; 250 gpt = NULL; 251 } 252 253 if ((*cmdsw[i]->fptr)(gpt, argc, argv) == -1) 254 return EXIT_FAILURE; 255 256 if (gpt) 257 gpt_close(gpt); 258 return EXIT_SUCCESS; 259} 260