xref: /openbsd-src/sbin/fdisk/fdisk.c (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1 /*	$OpenBSD: fdisk.c,v 1.52 2011/02/21 19:26:12 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 <err.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <paths.h>
34 #include <sys/types.h>
35 #include <sys/fcntl.h>
36 #include <sys/disklabel.h>
37 #include "disk.h"
38 #include "user.h"
39 
40 #define _PATH_MBR _PATH_BOOTDIR "mbr"
41 static unsigned char builtin_mbr[] = {
42 #include "mbrcode.h"
43 };
44 
45 int	y_flag;
46 
47 static void
48 usage(void)
49 {
50 	extern char * __progname;
51 
52 	fprintf(stderr, "usage: %s "
53 	    "[-eiuy] [-c cylinders -h heads -s sectors] [-f mbrfile] disk\n"
54 	    "\t-i: initialize disk with virgin MBR\n"
55 	    "\t-u: update MBR code, preserve partition table\n"
56 	    "\t-e: edit MBRs on disk interactively\n"
57 	    "\t-f: specify non-standard MBR template\n"
58 	    "\t-chs: specify disk geometry\n"
59 	    "\t-y: do not ask questions\n"
60 	    "`disk' may be of the forms: sd0 or /dev/rsd0c.\n",
61 	    __progname);
62 	exit(1);
63 }
64 
65 
66 int
67 main(int argc, char *argv[])
68 {
69 	int ch, fd, error;
70 	int i_flag = 0, m_flag = 0, u_flag = 0;
71 	int c_arg = 0, h_arg = 0, s_arg = 0;
72 	disk_t disk;
73 	DISK_metrics *usermetrics;
74 #ifdef HAS_MBR
75 	char *mbrfile = _PATH_MBR;
76 #else
77 	char *mbrfile = NULL;
78 #endif
79 	mbr_t mbr;
80 	char mbr_buf[DEV_BSIZE];
81 
82 	while ((ch = getopt(argc, argv, "ieuf:c:h:s:y")) != -1) {
83 		const char *errstr;
84 
85 		switch(ch) {
86 		case 'i':
87 			i_flag = 1;
88 			break;
89 		case 'u':
90 			u_flag = 1;
91 			break;
92 		case 'e':
93 			m_flag = 1;
94 			break;
95 		case 'f':
96 			mbrfile = optarg;
97 			break;
98 		case 'c':
99 			c_arg = strtonum(optarg, 1, 262144, &errstr);
100 			if (errstr)
101 				errx(1, "Cylinder argument %s [1..262144].",
102 				    errstr);
103 			break;
104 		case 'h':
105 			h_arg = strtonum(optarg, 1, 256, &errstr);
106 			if (errstr)
107 				errx(1, "Head argument %s [1..256].", errstr);
108 			break;
109 		case 's':
110 			s_arg = strtonum(optarg, 1, 63, &errstr);
111 			if (errstr)
112 				errx(1, "Sector argument %s [1..63].", errstr);
113 			break;
114 		case 'y':
115 			y_flag = 1;
116 			break;
117 		default:
118 			usage();
119 		}
120 	}
121 	argc -= optind;
122 	argv += optind;
123 
124 	/* Argument checking */
125 	if (argc != 1)
126 		usage();
127 	else
128 		disk.name = argv[0];
129 
130 	/* Put in supplied geometry if there */
131 	if (c_arg | h_arg | s_arg) {
132 		usermetrics = malloc(sizeof(DISK_metrics));
133 		if (usermetrics != NULL) {
134 			if (c_arg && h_arg && s_arg) {
135 				usermetrics->cylinders = c_arg;
136 				usermetrics->heads = h_arg;
137 				usermetrics->sectors = s_arg;
138 				usermetrics->size = c_arg * h_arg * s_arg;
139 			} else
140 				errx(1, "Please specify a full geometry with [-chs].");
141 		}
142 	} else
143 		usermetrics = NULL;
144 
145 	/* Get the geometry */
146 	disk.real = NULL;
147 	if (DISK_getmetrics(&disk, usermetrics))
148 		errx(1, "Can't get disk geometry, please use [-chs] to specify.");
149 
150 
151 	/* Print out current MBRs on disk */
152 	if ((i_flag + u_flag + m_flag) == 0)
153 		exit(USER_print_disk(&disk));
154 
155 	/* Parse mbr template, to pass on later */
156 	if (mbrfile != NULL && (fd = open(mbrfile, O_RDONLY)) == -1) {
157 		warn("%s", mbrfile);
158 		warnx("using builtin MBR");
159 		mbrfile = NULL;
160 	}
161 	if (mbrfile == NULL) {
162 		memcpy(mbr_buf, builtin_mbr, sizeof(mbr_buf));
163 	} else {
164 		error = MBR_read(fd, 0, mbr_buf);
165 		close(fd);
166 		if (error == -1) {
167 			printf("Unable to read MBR\n");
168 			return (1);
169 		}
170 	}
171 	MBR_parse(&disk, mbr_buf, 0, 0, &mbr);
172 
173 	/* Now do what we are supposed to */
174 	if (i_flag || u_flag)
175 		if (USER_init(&disk, &mbr, u_flag) == -1)
176 			err(1, "error initializing MBR");
177 
178 	if (m_flag)
179 		USER_modify(&disk, &mbr, 0, 0);
180 
181 	return (0);
182 }
183 
184