xref: /openbsd-src/sbin/fdisk/fdisk.c (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
1 /*	$OpenBSD: fdisk.c,v 1.63 2014/03/20 13:18:21 krw Exp $	*/
2 
3 /*
4  * Copyright (c) 1997 Tobias Weingartner
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  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <sys/types.h>
29 #include <sys/fcntl.h>
30 #include <sys/disklabel.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35 #include <paths.h>
36 #include <stdint.h>
37 #include <err.h>
38 
39 #include "disk.h"
40 #include "part.h"
41 #include "mbr.h"
42 #include "misc.h"
43 #include "user.h"
44 
45 #define _PATH_MBR _PATH_BOOTDIR "mbr"
46 static unsigned char builtin_mbr[] = {
47 #include "mbrcode.h"
48 };
49 
50 int	y_flag;
51 
52 static void
53 usage(void)
54 {
55 	extern char * __progname;
56 
57 	fprintf(stderr, "usage: %s "
58 	    "[-eiuy] [-c cylinders -h heads -s sectors] [-f mbrfile] [-l blocks] disk\n"
59 	    "\t-i: initialize disk with virgin MBR\n"
60 	    "\t-u: update MBR code, preserve partition table\n"
61 	    "\t-e: edit MBRs on disk interactively\n"
62 	    "\t-f: specify non-standard MBR template\n"
63 	    "\t-chs: specify disk geometry\n"
64 	    "\t-l: specify LBA block count\n"
65 	    "\t-y: do not ask questions\n"
66 	    "`disk' may be of the forms: sd0 or /dev/rsd0c.\n",
67 	    __progname);
68 	exit(1);
69 }
70 
71 
72 int
73 main(int argc, char *argv[])
74 {
75 	int ch, fd, error;
76 	int i_flag = 0, m_flag = 0, u_flag = 0;
77 	int c_arg = 0, h_arg = 0, s_arg = 0;
78 	struct disk disk;
79 	u_int32_t l_arg = 0;
80 #ifdef HAS_MBR
81 	char *mbrfile = _PATH_MBR;
82 #else
83 	char *mbrfile = NULL;
84 #endif
85 	struct mbr mbr;
86 	struct dos_mbr dos_mbr;
87 
88 	while ((ch = getopt(argc, argv, "ieuf:c:h:s:l: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 			m_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 			break;
110 		case 'h':
111 			h_arg = strtonum(optarg, 1, 256, &errstr);
112 			if (errstr)
113 				errx(1, "Head argument %s [1..256].", errstr);
114 			break;
115 		case 's':
116 			s_arg = strtonum(optarg, 1, 63, &errstr);
117 			if (errstr)
118 				errx(1, "Sector argument %s [1..63].", errstr);
119 			break;
120 		case 'l':
121 			l_arg = strtonum(optarg, 64, UINT32_MAX, &errstr);
122 			if (errstr)
123 				errx(1, "Block argument %s [64..%u].", errstr,
124 				    UINT32_MAX);
125 			break;
126 		case 'y':
127 			y_flag = 1;
128 			break;
129 		default:
130 			usage();
131 		}
132 	}
133 	argc -= optind;
134 	argv += optind;
135 
136 	memset(&disk, 0, sizeof(disk));
137 
138 	/* Argument checking */
139 	if (argc != 1)
140 		usage();
141 	else
142 		disk.name = argv[0];
143 
144 	/* Start with the disklabel geometry and get the sector size. */
145 	DISK_getlabelgeometry(&disk);
146 
147 	if (c_arg | h_arg | s_arg) {
148 		/* Use supplied geometry if it is completely specified. */
149 		if (c_arg && h_arg && s_arg) {
150 			disk.cylinders = c_arg;
151 			disk.heads = h_arg;
152 			disk.sectors = s_arg;
153 			disk.size = c_arg * h_arg * s_arg;
154 		} else
155 			errx(1, "Please specify a full geometry with [-chs].");
156 	} else if (l_arg) {
157 		/* Use supplied size to calculate a geometry. */
158 		disk.cylinders = l_arg / 64;
159 		disk.heads = 1;
160 		disk.sectors = 64;
161 		disk.size = l_arg;
162 	}
163 
164 	if (disk.size == 0 || disk.cylinders == 0 || disk.heads == 0 ||
165 	    disk.sectors == 0 || unit_types[SECTORS].conversion == 0)
166 		errx(1, "Can't get disk geometry, please use [-chs] "
167 		    "to specify.");
168 
169 	/* Print out current MBRs on disk */
170 	if ((i_flag + u_flag + m_flag) == 0)
171 		exit(USER_print_disk(&disk));
172 
173 	/* Parse mbr template, to pass on later */
174 	if (mbrfile != NULL && (fd = open(mbrfile, O_RDONLY)) == -1) {
175 		warn("%s", mbrfile);
176 		warnx("using builtin MBR");
177 		mbrfile = NULL;
178 	}
179 	if (mbrfile == NULL) {
180 		memcpy(&dos_mbr, builtin_mbr, sizeof(dos_mbr));
181 	} else {
182 		error = MBR_read(fd, 0, &dos_mbr);
183 		if (error == -1)
184 			err(1, "Unable to read MBR");
185 		close(fd);
186 	}
187 	MBR_parse(&disk, &dos_mbr, 0, 0, &mbr);
188 
189 	/* Now do what we are supposed to */
190 	if (i_flag || u_flag)
191 		if (USER_init(&disk, &mbr, u_flag) == -1)
192 			err(1, "error initializing MBR");
193 
194 	if (m_flag)
195 		USER_modify(&disk, &mbr, 0, 0);
196 
197 	return (0);
198 }
199