xref: /netbsd-src/sbin/gpt/main.c (revision 53b02e147d4ed531c0d2a5ca9b3e8026ba3e99b5)
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 
53 static const struct gpt_cmd c_null;
54 
55 extern 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 
79 static 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
106 usage(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 
125 static void
126 prefix(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 
136 static time_t
137 get_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 
161 int
162 main(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