GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/fdisk/fdisk.c Lines: 0 108 0.0 %
Date: 2016-12-06 Branches: 0 75 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: fdisk.c,v 1.101 2016/06/25 17:03:22 tb Exp $	*/
2
3
/*
4
 * Copyright (c) 1997 Tobias Weingartner
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <sys/fcntl.h>
21
#include <sys/disklabel.h>
22
23
#include <err.h>
24
#include <paths.h>
25
#include <stdint.h>
26
#include <stdio.h>
27
#include <stdlib.h>
28
#include <string.h>
29
#include <unistd.h>
30
31
#include "disk.h"
32
#include "part.h"
33
#include "mbr.h"
34
#include "misc.h"
35
#include "cmd.h"
36
#include "user.h"
37
#include "gpt.h"
38
39
#define _PATH_MBR _PATH_BOOTDIR "mbr"
40
static unsigned char builtin_mbr[] = {
41
#include "mbrcode.h"
42
};
43
44
u_int32_t b_arg;
45
int	y_flag;
46
47
static void
48
usage(void)
49
{
50
	extern char * __progname;
51
52
	fprintf(stderr, "usage: %s "
53
	    "[-egvy] [-i|-u] [-b #] [-c # -h # -s #] "
54
	    "[-f mbrfile] [-l # ] disk\n"
55
	    "\t-b: specify special boot partition block count; requires -i\n"
56
	    "\t-chs: specify disk geometry; all three must be specified\n"
57
	    "\t-e: interactively edit MBR or GPT\n"
58
	    "\t-f: specify non-standard MBR template\n"
59
	    "\t-g: initialize disk with GPT; requires -i\n"
60
	    "\t-i: initialize disk with MBR unless -g is also specified\n"
61
	    "\t-l: specify LBA block count; cannot be used with -chs\n"
62
	    "\t-u: update MBR code; preserve partition table\n"
63
	    "\t-v: print the MBR, the Primary GPT and the Secondary GPT\n"
64
	    "\t-y: do not ask questions\n"
65
	    "`disk' may be of the forms: sd0 or /dev/rsd0c.\n",
66
	    __progname);
67
	exit(1);
68
}
69
70
int
71
main(int argc, char *argv[])
72
{
73
	ssize_t len;
74
	int ch, fd, error;
75
	int e_flag = 0, g_flag = 0, i_flag = 0, u_flag = 0;
76
	int verbosity = 0;
77
	int c_arg = 0, h_arg = 0, s_arg = 0;
78
	u_int32_t l_arg = 0;
79
	char *query;
80
#ifdef HAS_MBR
81
	char *mbrfile = _PATH_MBR;
82
#else
83
	char *mbrfile = NULL;
84
#endif
85
	struct dos_mbr dos_mbr;
86
	struct mbr mbr;
87
88
	while ((ch = getopt(argc, argv, "iegpuvf:c:h:s:l:b:y")) != -1) {
89
		const char *errstr;
90
91
		switch(ch) {
92
		case 'i':
93
			i_flag = 1;
94
			break;
95
		case 'u':
96
			u_flag = 1;
97
			break;
98
		case 'e':
99
			e_flag = 1;
100
			break;
101
		case 'f':
102
			mbrfile = optarg;
103
			break;
104
		case 'c':
105
			c_arg = strtonum(optarg, 1, 262144, &errstr);
106
			if (errstr)
107
				errx(1, "Cylinder argument %s [1..262144].",
108
				    errstr);
109
			disk.cylinders = c_arg;
110
			disk.size = c_arg * h_arg * s_arg;
111
			break;
112
		case 'h':
113
			h_arg = strtonum(optarg, 1, 256, &errstr);
114
			if (errstr)
115
				errx(1, "Head argument %s [1..256].", errstr);
116
			disk.heads = h_arg;
117
			disk.size = c_arg * h_arg * s_arg;
118
			break;
119
		case 's':
120
			s_arg = strtonum(optarg, 1, 63, &errstr);
121
			if (errstr)
122
				errx(1, "Sector argument %s [1..63].", errstr);
123
			disk.sectors = s_arg;
124
			disk.size = c_arg * h_arg * s_arg;
125
			break;
126
		case 'g':
127
			g_flag = 1;
128
			break;
129
		case 'b':
130
			b_arg = strtonum(optarg, 64, UINT32_MAX, &errstr);
131
			if (errstr)
132
				errx(1, "Block argument %s [64..%u].", errstr,
133
				    UINT32_MAX);
134
			break;
135
		case 'l':
136
			l_arg = strtonum(optarg, 64, UINT32_MAX, &errstr);
137
			if (errstr)
138
				errx(1, "Block argument %s [64..%u].", errstr,
139
				    UINT32_MAX);
140
			disk.cylinders = l_arg / 64;
141
			disk.heads = 1;
142
			disk.sectors = 64;
143
			disk.size = l_arg;
144
			break;
145
		case 'y':
146
			y_flag = 1;
147
			break;
148
		case 'v':
149
			verbosity++;
150
			break;
151
		default:
152
			usage();
153
		}
154
	}
155
	argc -= optind;
156
	argv += optind;
157
158
	/* Argument checking */
159
	if (argc != 1 || (i_flag && u_flag) ||
160
	    (i_flag == 0 && (b_arg || g_flag)) ||
161
	    ((c_arg | h_arg | s_arg) && !(c_arg && h_arg && s_arg)) ||
162
	    ((c_arg | h_arg | s_arg) && l_arg))
163
		usage();
164
165
	disk.name = argv[0];
166
	DISK_open(i_flag || u_flag || e_flag);
167
168
	/* "proc exec" for man page display */
169
	if (pledge("stdio rpath wpath disklabel proc exec cpath", NULL) == -1)
170
		err(1, "pledge");
171
172
	error = MBR_read(0, &dos_mbr);
173
	if (error)
174
		errx(1, "Can't read sector 0!");
175
	MBR_parse(&dos_mbr, 0, 0, &mbr);
176
177
	/* Get the GPT if present. Either primary or secondary is ok. */
178
	if (MBR_protective_mbr(&mbr) == 0)
179
		GPT_get_gpt(0);
180
181
	if (letoh64(gh.gh_sig) != GPTSIGNATURE) {
182
		if (DL_GETDSIZE(&dl) > disk.size)
183
			warnx("disk too large (%llu sectors). size truncated.",
184
			    (unsigned long long)DL_GETDSIZE(&dl));
185
	}
186
187
	if (!(i_flag || u_flag || e_flag)) {
188
		if (pledge("stdio rpath cpath wpath", NULL) == -1)
189
			err(1, "pledge");
190
		USER_print_disk(verbosity);
191
		goto done;
192
	}
193
194
	/* Create initial/default MBR. */
195
	if (mbrfile == NULL) {
196
		memcpy(&dos_mbr, builtin_mbr, sizeof(dos_mbr));
197
	} else {
198
		fd = open(mbrfile, O_RDONLY);
199
		if (fd == -1) {
200
			warn("%s", mbrfile);
201
			warnx("using builtin MBR");
202
			memcpy(&dos_mbr, builtin_mbr, sizeof(dos_mbr));
203
		} else {
204
			len = read(fd, &dos_mbr, sizeof(dos_mbr));
205
			close(fd);
206
			if (len == -1)
207
				err(1, "Unable to read MBR from '%s'", mbrfile);
208
			else if (len != sizeof(dos_mbr))
209
				errx(1, "Unable to read complete MBR from '%s'",
210
				    mbrfile);
211
		}
212
	}
213
	MBR_parse(&dos_mbr, 0, 0, &initial_mbr);
214
215
	query = NULL;
216
	if (i_flag) {
217
		reinited = 1;
218
		if (g_flag) {
219
			MBR_init_GPT(&initial_mbr);
220
			GPT_init();
221
			query = "Do you wish to write new GPT?";
222
		} else {
223
			MBR_init(&initial_mbr);
224
			query = "Do you wish to write new MBR and "
225
			    "partition table?";
226
		}
227
	} else if (u_flag) {
228
		memcpy(initial_mbr.part, mbr.part, sizeof(initial_mbr.part));
229
		query = "Do you wish to write new MBR?";
230
	}
231
	if (query && ask_yn(query))
232
		Xwrite(NULL, &initial_mbr);
233
234
	if (e_flag)
235
		USER_edit(0, 0);
236
237
done:
238
	close(disk.fd);
239
240
	return (0);
241
}