1 /* $NetBSD: main.c,v 1.15 2025/02/23 20:47:19 christos 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.15 2025/02/23 20:47:19 christos 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 53 static const struct gpt_cmd c_null = { 0 }; 54 55 static const struct gpt_cmd *cmdsw[] = { 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 &c_null, 79 }; 80 81 __dead static void 82 usage(void) 83 { 84 const char *p = getprogname(); 85 const char *f = 86 "[-nrqv] [-m mediasize] [-s sectorsize] [-T timestamp]"; 87 size_t i; 88 89 if (strcmp(p, "gpt") == 0) 90 fprintf(stderr, 91 "Usage: %s %s command device\n", p, f); 92 else 93 fprintf(stderr, 94 "Usage: %s %s device command\n", p, f); 95 fprintf(stderr, "Commands:\n"); 96 for (i = 0; i < __arraycount(cmdsw); i++) 97 gpt_usage("\t", cmdsw[i]); 98 exit(EXIT_FAILURE); 99 } 100 101 static void 102 prefix(const char *cmd) 103 { 104 char *pfx; 105 106 if (asprintf(&pfx, "%s %s", getprogname(), cmd) < 0) 107 pfx = NULL; 108 else 109 setprogname(pfx); 110 } 111 112 static time_t 113 get_tstamp(const char *b) 114 { 115 struct stat st; 116 char *eb; 117 long long l; 118 #ifndef HAVE_NBTOOL_CONFIG_H 119 time_t when; 120 #endif 121 122 if (stat(b, &st) != -1) 123 return (time_t)st.st_mtime; 124 125 #ifndef HAVE_NBTOOL_CONFIG_H 126 errno = 0; 127 if ((when = parsedate(b, NULL, NULL)) != -1 || errno == 0) 128 return when; 129 #endif 130 errno = 0; 131 l = strtoll(b, &eb, 0); 132 if (b == eb || *eb || errno) 133 errx(EXIT_FAILURE, "Can't parse timestamp `%s'", b); 134 return (time_t)l; 135 } 136 137 int 138 main(int argc, char *argv[]) 139 { 140 char *cmd, *p, *dev = NULL; 141 int ch, i; 142 u_int secsz = 0; 143 off_t mediasz = 0; 144 int flags = 0; 145 int verbose = 0; 146 time_t timestamp = 0; 147 gpt_t gpt; 148 149 setprogname(argv[0]); 150 151 if (strcmp(getprogname(), "gpt") == 0) { 152 if (argc < 3) 153 usage(); 154 dev = argv[--argc]; 155 } 156 157 #ifdef __GLIBC__ 158 #define GETOPT_BE_POSIX "+" 159 #else 160 #define GETOPT_BE_POSIX "" 161 #endif 162 163 /* Get the generic options */ 164 while ((ch = getopt(argc, argv, GETOPT_BE_POSIX "Hm:nqrs:T:v")) != -1) { 165 switch(ch) { 166 case 'H': 167 flags |= GPT_HYBRID; 168 break; 169 case 'm': 170 if (mediasz > 0) 171 usage(); 172 mediasz = strtol(optarg, &p, 10); 173 if (*p != 0 || mediasz < 1) 174 usage(); 175 break; 176 case 'n': 177 flags |= GPT_NOSYNC; 178 break; 179 case 'r': 180 flags |= GPT_READONLY; 181 break; 182 case 'q': 183 flags |= GPT_QUIET; 184 break; 185 case 's': 186 if (gpt_uint_get(NULL, &secsz) == -1) 187 usage(); 188 break; 189 case 'T': 190 flags |= GPT_TIMESTAMP; 191 timestamp = get_tstamp(optarg); 192 break; 193 case 'v': 194 verbose++; 195 break; 196 default: 197 usage(); 198 } 199 } 200 201 if (argc == optind) 202 usage(); 203 204 if (dev == NULL) 205 dev = argv[optind++]; 206 207 if (argc == optind) 208 usage(); 209 210 cmd = argv[optind++]; 211 for (i = 0; cmdsw[i]->name != NULL && strcmp(cmd, cmdsw[i]->name); i++) 212 continue; 213 214 if (cmdsw[i]->fptr == NULL) 215 errx(EXIT_FAILURE, "Unknown command: %s", cmd); 216 217 prefix(cmd); 218 219 if (*dev != '-') { 220 gpt = gpt_open(dev, flags | cmdsw[i]->flags, 221 verbose, mediasz, secsz, timestamp); 222 if (gpt == NULL) 223 return EXIT_FAILURE; 224 } else { 225 if ((cmdsw[i]->flags & GPT_OPTDEV) == 0) 226 errx(EXIT_FAILURE, 227 "Command %s needs a device parameter", cmd); 228 argc++; 229 gpt = NULL; 230 } 231 232 if ((*cmdsw[i]->fptr)(gpt, argc, argv) == -1) 233 return EXIT_FAILURE; 234 235 if (gpt) 236 gpt_close(gpt); 237 return EXIT_SUCCESS; 238 } 239