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