xref: /openbsd-src/sbin/fdisk/fdisk.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /*	$OpenBSD: fdisk.c,v 1.48 2007/12/30 13:20:13 sobrado 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] device\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;
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 #if defined(__amd64__) || defined(__i386__) || defined (__powerpc__) || \
75     defined(__sh__)
76 	char *mbrfile = _PATH_MBR;
77 #else
78 	char *mbrfile = NULL;
79 #endif
80 	mbr_t mbr;
81 	char mbr_buf[DEV_BSIZE];
82 
83 	while ((ch = getopt(argc, argv, "ieuf:c:h:s:y")) != -1) {
84 		const char *errstr;
85 
86 		switch(ch) {
87 		case 'i':
88 			i_flag = 1;
89 			break;
90 		case 'u':
91 			u_flag = 1;
92 			break;
93 		case 'e':
94 			m_flag = 1;
95 			break;
96 		case 'f':
97 			mbrfile = optarg;
98 			break;
99 		case 'c':
100 			c_arg = strtonum(optarg, 1, 262144, &errstr);
101 			if (errstr)
102 				errx(1, "Cylinder argument %s [1..262144].",
103 				    errstr);
104 			break;
105 		case 'h':
106 			h_arg = strtonum(optarg, 1, 256, &errstr);
107 			if (errstr)
108 				errx(1, "Head argument %s [1..256].", errstr);
109 			break;
110 		case 's':
111 			s_arg = strtonum(optarg, 1, 63, &errstr);
112 			if (errstr)
113 				errx(1, "Sector argument %s [1..63].", errstr);
114 			break;
115 		case 'y':
116 			y_flag = 1;
117 			break;
118 		default:
119 			usage();
120 		}
121 	}
122 	argc -= optind;
123 	argv += optind;
124 
125 	/* Argument checking */
126 	if (argc != 1)
127 		usage();
128 	else
129 		disk.name = argv[0];
130 
131 	/* Put in supplied geometry if there */
132 	if (c_arg | h_arg | s_arg) {
133 		usermetrics = malloc(sizeof(DISK_metrics));
134 		if (usermetrics != NULL) {
135 			if (c_arg && h_arg && s_arg) {
136 				usermetrics->cylinders = c_arg;
137 				usermetrics->heads = h_arg;
138 				usermetrics->sectors = s_arg;
139 				usermetrics->size = c_arg * h_arg * s_arg;
140 			} else
141 				errx(1, "Please specify a full geometry with [-chs].");
142 		}
143 	} else
144 		usermetrics = NULL;
145 
146 	/* Get the geometry */
147 	disk.real = NULL;
148 	if (DISK_getmetrics(&disk, usermetrics))
149 		errx(1, "Can't get disk geometry, please use [-chs] to specify.");
150 
151 
152 	/* Print out current MBRs on disk */
153 	if ((i_flag + u_flag + m_flag) == 0)
154 		exit(USER_print_disk(&disk));
155 
156 	/* Parse mbr template, to pass on later */
157 	if (mbrfile != NULL && (fd = open(mbrfile, O_RDONLY)) == -1) {
158 		warn("%s", mbrfile);
159 		warnx("using builtin MBR");
160 		mbrfile = NULL;
161 	}
162 	if (mbrfile == NULL) {
163 		memcpy(mbr_buf, builtin_mbr, sizeof(mbr_buf));
164 	} else {
165 		MBR_read(fd, 0, mbr_buf);
166 		close(fd);
167 	}
168 	MBR_parse(&disk, mbr_buf, 0, 0, &mbr);
169 
170 	/* Now do what we are supposed to */
171 	if (i_flag || u_flag)
172 		if (USER_init(&disk, &mbr, u_flag) == -1)
173 			err(1, "error initializing MBR");
174 
175 	if (m_flag)
176 		USER_modify(&disk, &mbr, 0, 0);
177 
178 	return (0);
179 }
180 
181