]> git.cameronkatri.com Git - apple_cmds.git/blob - diskdev_cmds/fdisk.tproj/fdisk.c
setup.sh: Use iOS ~12 XNU version
[apple_cmds.git] / diskdev_cmds / fdisk.tproj / fdisk.c
1 /*
2 * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 /*
26 * Copyright (c) 1997 Tobias Weingartner
27 * All rights reserved.
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 * 1. Redistributions of source code must retain the above copyright
33 * notice, this list of conditions and the following disclaimer.
34 * 2. Redistributions in binary form must reproduce the above copyright
35 * notice, this list of conditions and the following disclaimer in the
36 * documentation and/or other materials provided with the distribution.
37 * 3. All advertising materials mentioning features or use of this software
38 * must display the following acknowledgement:
39 * This product includes software developed by Tobias Weingartner.
40 * 4. The name of the author may not be used to endorse or promote products
41 * derived from this software without specific prior written permission.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
44 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
45 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
46 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
47 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
48 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
49 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
50 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
51 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
52 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53 */
54
55 #include <err.h>
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <string.h>
59 #include <unistd.h>
60 #include <paths.h>
61 #include <sys/types.h>
62 #include <sys/fcntl.h>
63 #include "disk.h"
64 #include "user.h"
65 #include "auto.h"
66
67 #define _PATH_MBR "/usr/standalone/i386/boot0"
68
69 void
70 usage()
71 {
72 extern char * __progname;
73 fprintf(stderr, "usage: %s "
74 "[-ieu] [-f mbrboot] [-c cyl -h head -s sect] [-S size] [-r] [-a style] disk\n"
75 "\t-i: initialize disk with new MBR\n"
76 "\t-u: update MBR code, preserve partition table\n"
77 "\t-e: edit MBRs on disk interactively\n"
78 "\t-f: specify non-standard MBR template\n"
79 "\t-chs: specify disk geometry\n"
80 "\t-S: specify disk size\n"
81 "\t-r: read partition specs from stdin (implies -i)\n"
82 "\t-a: auto-partition with the given style\n"
83 "\t-d: dump partition table\n"
84 "\t-y: don't ask any questions\n"
85 "\t-t: test if disk is partitioned\n"
86 "`disk' is of the form /dev/rdisk0.\n",
87 __progname);
88 fprintf(stderr, "auto-partition styles:\n");
89 AUTO_print_styles(stderr);
90 exit(1);
91 }
92
93 char *mbr_binary = NULL;
94 int
95 main(argc, argv)
96 int argc;
97 char **argv;
98 {
99 int ch, fd;
100 int i_flag = 0, m_flag = 0, u_flag = 0, r_flag = 0, d_flag = 0, y_flag = 0, t_flag = 0;
101 int c_arg = 0, h_arg = 0, s_arg = 0;
102 int size_arg = 0;
103 int block_size_arg = 0;
104 disk_t disk;
105 DISK_metrics *usermetrics;
106 char *mbrfile = _PATH_MBR;
107 mbr_t *mp;
108 char *auto_style = NULL;
109
110 while ((ch = getopt(argc, argv, "ieuf:c:h:s:b:S:ra:dyt")) != -1) {
111 switch(ch) {
112 case 'i':
113 i_flag = 1;
114 break;
115 case 'u':
116 u_flag = 1;
117 break;
118 case 'e':
119 m_flag = 1;
120 break;
121 case 'f':
122 mbrfile = optarg;
123 break;
124 case 'c':
125 c_arg = atoi(optarg);
126 if (c_arg < 1 || c_arg > 262144)
127 errx(1, "Cylinder argument out of range.");
128 break;
129 case 'h':
130 h_arg = atoi(optarg);
131 if (h_arg < 1 || h_arg > 256)
132 errx(1, "Head argument out of range.");
133 break;
134 case 's':
135 s_arg = atoi(optarg);
136 if (s_arg < 1 || s_arg > 63)
137 errx(1, "Sector argument out of range.");
138 break;
139 case 'b':
140 block_size_arg = atoi(optarg);
141 if (block_size_arg & (block_size_arg - 1))
142 errx(1, "Block size argument not a power of two.");
143 if (block_size_arg < 512 || block_size_arg > 4096)
144 errx(1, "Block size argument out of range 512..4096.");
145 break;
146 case 'S':
147 size_arg = atoi(optarg);
148 break;
149 case 'r':
150 r_flag = 1;
151 break;
152 case 'a':
153 auto_style = optarg;
154 break;
155 case 'd':
156 d_flag = 1;
157 break;
158 case 'y':
159 y_flag = 1;
160 break;
161 case 't':
162 t_flag = 1;
163 break;
164 default:
165 usage();
166 }
167 }
168 argc -= optind;
169 argv += optind;
170
171 /* Argument checking */
172 if (argc != 1)
173 usage();
174 else
175 disk.name = argv[0];
176
177 if (i_flag && u_flag) errx(1, "-i and -u cannot be specified simultaneously");
178
179 /* Put in supplied geometry if there */
180 if (c_arg | h_arg | s_arg | size_arg | block_size_arg) {
181 usermetrics = malloc(sizeof(DISK_metrics));
182 if (usermetrics != NULL) {
183 if (c_arg && h_arg && s_arg) {
184 usermetrics->cylinders = c_arg;
185 usermetrics->heads = h_arg;
186 usermetrics->sectors = s_arg;
187 if (size_arg) {
188 usermetrics->size = size_arg;
189 } else {
190 usermetrics->size = c_arg * h_arg * s_arg;
191 }
192 } else {
193 if (size_arg) {
194 usermetrics->size = size_arg;
195 DISK_fake_CHS(usermetrics);
196 } else {
197 errx(1, "Please specify a full geometry with [-chs].");
198 }
199 }
200 if (block_size_arg) {
201 usermetrics->sector_size = block_size_arg;
202 } else {
203 DISK_get_sector_size(&disk, usermetrics);
204 }
205 }
206 } else {
207 usermetrics = NULL;
208 }
209
210 /* Get the geometry */
211 disk.real = NULL;
212 if (DISK_getmetrics(&disk, usermetrics))
213 errx(1, "Can't get disk geometry, please use [-chs] to specify.");
214
215 /* If only testing, read MBR and silently exit */
216 if (t_flag) {
217 mbr_t *mbr;
218
219 mp = mbr = MBR_read_all(&disk);
220 while (mp) {
221 if (mp->signature != MBR_SIGNATURE) {
222 MBR_free(mbr);
223 exit(1);
224 }
225 mp = mp->next;
226 }
227 MBR_free(mbr);
228 exit(0);
229 }
230
231 /* If not editing the disk, print out current MBRs on disk */
232 if ((i_flag + r_flag + u_flag + m_flag) == 0) {
233 exit(USER_print_disk(&disk, d_flag));
234 }
235
236 /* Parse mbr template or read partition specs, to pass on later */
237 if (auto_style && r_flag) {
238 errx(1, "Can't specify both -r and -a");
239 }
240
241 mbr_binary = (char *)malloc(MBR_CODE_SIZE);
242 if ((fd = open(mbrfile, O_RDONLY)) == -1) {
243 warn("could not open MBR file %s", mbrfile);
244 bzero(mbr_binary, MBR_CODE_SIZE);
245 } else {
246 int cc;
247 cc = read(fd, mbr_binary, MBR_CODE_SIZE);
248 if (cc < MBR_CODE_SIZE) {
249 err(1, "could not read MBR code");
250 }
251 close(fd);
252 }
253
254 if (u_flag) {
255 /* Don't hose the partition table; just write the boot code */
256 mp = MBR_read_all(&disk);
257 bcopy(mbr_binary, mp->code, MBR_CODE_SIZE);
258 MBR_make(mp);
259 } else if (i_flag) {
260 /* If they didn't specify -a, they'll get the default auto style */
261 mp = MBR_alloc(NULL);
262 if (AUTO_init(&disk, auto_style, mp) != AUTO_OK) {
263 errx(1, "error initializing disk");
264 }
265 bcopy(mbr_binary, mp->code, MBR_CODE_SIZE);
266 MBR_make(mp);
267 } else if (r_flag) {
268 mp = MBR_parse_spec(stdin, &disk);
269 bcopy(mbr_binary, mp->code, MBR_CODE_SIZE);
270 MBR_make(mp);
271 } else {
272 /* Use what's on the disk. */
273 mp = MBR_read_all(&disk);
274 }
275
276 /* Now do what we are supposed to */
277 if (i_flag || r_flag || u_flag) {
278 USER_write(&disk, mp, u_flag, y_flag);
279 }
280
281 if (m_flag) {
282 USER_modify(&disk, mp, 0, 0);
283 }
284
285 if (mbr_binary)
286 free(mbr_binary);
287
288 return (0);
289 }