xref: /openbsd-src/sbin/fdisk/cmd.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: cmd.c,v 1.28 2001/01/28 00:56:07 weingart 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  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *    This product includes software developed by Tobias Weingartner.
18  * 4. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <stdio.h>
34 #include <ctype.h>
35 #include <memory.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <signal.h>
39 #include <sys/fcntl.h>
40 #include <sys/disklabel.h>
41 #include "disk.h"
42 #include "misc.h"
43 #include "user.h"
44 #include "part.h"
45 #include "cmd.h"
46 #define MAX(a, b) ((a) >= (b) ? (a) : (b))
47 
48 int
49 Xreinit(cmd, disk, mbr, tt, offset)
50 	cmd_t *cmd;
51 	disk_t *disk;
52 	mbr_t *mbr;
53 	mbr_t *tt;
54 	int offset;
55 {
56 	char buf[DEV_BSIZE];
57 
58 	/* Copy template MBR */
59 	MBR_make(tt, buf);
60 	MBR_parse(disk, buf, 0, 0, mbr);
61 
62 	MBR_init(disk, mbr);
63 
64 	/* Tell em we did something */
65 	printf("In memory copy is initialized to:\n");
66 	printf("Offset: %d\t", offset);
67 	MBR_print(mbr);
68 	printf("Use 'write' to update disk.\n");
69 
70 	return (CMD_DIRTY);
71 }
72 
73 int
74 Xdisk(cmd, disk, mbr, tt, offset)
75 	cmd_t *cmd;
76 	disk_t *disk;
77 	mbr_t *mbr;
78 	mbr_t *tt;
79 	int offset;
80 {
81 	int maxcyl  = 1024;
82 	int maxhead = 256;
83 	int maxsec  = 63;
84 
85 	/* Print out disk info */
86 	DISK_printmetrics(disk);
87 
88 #if defined (__powerpc__) || defined (__mips__)
89 	maxcyl  = 9999999;
90 	maxhead = 9999999;
91 	maxsec  = 9999999;
92 #endif
93 
94 	/* Ask for new info */
95 	if (ask_yn("Change disk geometry?")) {
96 		disk->real->cylinders = ask_num("BIOS Cylinders", ASK_DEC,
97 		    disk->real->cylinders, 1, maxcyl, NULL);
98 		disk->real->heads = ask_num("BIOS Heads", ASK_DEC,
99 		    disk->real->heads, 1, maxhead, NULL);
100 		disk->real->sectors = ask_num("BIOS Sectors", ASK_DEC,
101 		    disk->real->sectors, 1, maxsec, NULL);
102 
103 		disk->real->size = disk->real->cylinders * disk->real->heads
104 			* disk->real->sectors;
105 	}
106 
107 	return (CMD_CONT);
108 }
109 
110 int
111 Xedit(cmd, disk, mbr, tt, offset)
112 	cmd_t *cmd;
113 	disk_t *disk;
114 	mbr_t *mbr;
115 	mbr_t *tt;
116 	int offset;
117 {
118 	int pn, num, ret;
119 	prt_t *pp;
120 
121 	ret = CMD_CONT;
122 
123 	if (!isdigit(cmd->args[0])) {
124 		printf("Invalid argument: %s <partition number>\n", cmd->cmd);
125 		return (ret);
126 	}
127 	pn = atoi(cmd->args);
128 
129 	if (pn < 0 || pn > 3) {
130 		printf("Invalid partition number.\n");
131 		return (ret);
132 	}
133 
134 	/* Print out current table entry */
135 	pp = &mbr->part[pn];
136 	PRT_print(0, NULL);
137 	PRT_print(pn, pp);
138 
139 #define	EDIT(p, f, v, n, m, h)				\
140 	if ((num = ask_num(p, f, v, n, m, h)) != v)	\
141 		ret = CMD_DIRTY;			\
142 	v = num;
143 
144 	/* Ask for partition type */
145 	EDIT("Partition id ('0' to disable) ", ASK_HEX, pp->id, 0, 0xFF, PRT_printall);
146 
147 	/* Unused, so just zero out */
148 	if (pp->id == DOSPTYP_UNUSED) {
149 		memset(pp, 0, sizeof(*pp));
150 		printf("Partition %d is disabled.\n", pn);
151 		return (ret);
152 	}
153 
154 	/* Change table entry */
155 	if (ask_yn("Do you wish to edit in CHS mode?")) {
156 		int maxcyl, maxhead, maxsect;
157 
158 		/* Shorter */
159 		maxcyl = disk->real->cylinders - 1;
160 		maxhead = disk->real->heads - 1;
161 		maxsect = disk->real->sectors;
162 
163 		/* Get data */
164 		EDIT("BIOS Starting cylinder", ASK_DEC, pp->scyl,  0, maxcyl, NULL);
165 		EDIT("BIOS Starting head",     ASK_DEC, pp->shead, 0, maxhead, NULL);
166 		EDIT("BIOS Starting sector",   ASK_DEC, pp->ssect, 1, maxsect, NULL);
167 		EDIT("BIOS Ending cylinder",   ASK_DEC, pp->ecyl,  0, maxcyl, NULL);
168 		EDIT("BIOS Ending head",       ASK_DEC, pp->ehead, 0, maxhead, NULL);
169 		EDIT("BIOS Ending sector",     ASK_DEC, pp->esect, 1, maxsect, NULL);
170 		/* Fix up off/size values */
171 		PRT_fix_BN(disk, pp, pn);
172 		/* Fix up CHS values for LBA */
173 		PRT_fix_CHS(disk, pp, pn);
174 	} else {
175 		u_int m;
176 
177 		/* Get data */
178 		EDIT("Partition offset", ASK_DEC, pp->bs, 0,
179 		    disk->real->size, NULL);
180 		m = MAX(pp->ns, disk->real->size - pp->bs);
181 		if ( m > disk->real->size - pp->bs) {
182 			/* dont have default value extend beyond end of disk */
183 			m = disk->real->size - pp->bs;
184 		}
185 		EDIT("Partition size", ASK_DEC, pp->ns, 1,
186 		    m, NULL);
187 
188 		/* Fix up CHS values */
189 		PRT_fix_CHS(disk, pp, pn);
190 	}
191 #undef EDIT
192 	return (ret);
193 }
194 
195 int
196 Xsetpid(cmd, disk, mbr, tt, offset)
197 	cmd_t *cmd;
198 	disk_t *disk;
199 	mbr_t *mbr;
200 	mbr_t *tt;
201 	int offset;
202 {
203 	int pn, num, ret;
204 	prt_t *pp;
205 
206 	ret = CMD_CONT;
207 
208 	if (!isdigit(cmd->args[0])) {
209 		printf("Invalid argument: %s <partition number>\n", cmd->cmd);
210 		return (ret);
211 	}
212 	pn = atoi(cmd->args);
213 
214 	if (pn < 0 || pn > 3) {
215 		printf("Invalid partition number.\n");
216 		return (ret);
217 	}
218 
219 	/* Print out current table entry */
220 	pp = &mbr->part[pn];
221 	PRT_print(0, NULL);
222 	PRT_print(pn, pp);
223 
224 #define	EDIT(p, f, v, n, m, h)				\
225 	if ((num = ask_num(p, f, v, n, m, h)) != v)	\
226 		ret = CMD_DIRTY;			\
227 	v = num;
228 
229 	/* Ask for partition type */
230 	EDIT("Partition id ('0' to disable) ", ASK_HEX, pp->id, 0, 0xFF, PRT_printall);
231 
232 #undef EDIT
233 	return (ret);
234 }
235 int
236 Xselect(cmd, disk, mbr, tt, offset)
237 	cmd_t *cmd;
238 	disk_t *disk;
239 	mbr_t *mbr;
240 	mbr_t *tt;
241 	int offset;
242 {
243 	static int firstoff = 0;
244 	int off;
245 	int pn;
246 
247 	if (!isdigit(cmd->args[0])) {
248 		printf("Invalid argument: %s <partition number>\n", cmd->cmd);
249 		return (CMD_CONT);
250 	}
251 
252 	pn = atoi(cmd->args);
253 	off = mbr->part[pn].bs;
254 
255 	/* Sanity checks */
256 	if ((mbr->part[pn].id != DOSPTYP_EXTEND) &&
257 	    (mbr->part[pn].id != DOSPTYP_EXTENDL)) {
258 		printf("Partition %d is not an extended partition.\n", pn);
259 		return (CMD_CONT);
260 	}
261 
262 	if (firstoff == 0)
263 		firstoff = off;
264 
265 	if (!off) {
266 		printf("Loop to offset 0!  Not selected.\n");
267 		return (CMD_CONT);
268 	} else {
269 		printf("Selected extended partition %d\n", pn);
270 		printf("New MBR at offset %d.\n", off);
271 	}
272 
273 	/* Recursion is beautifull! */
274 	USER_modify(disk, tt, off, firstoff);
275 	return (CMD_CONT);
276 }
277 
278 int
279 Xprint(cmd, disk, mbr, tt, offset)
280 	cmd_t *cmd;
281 	disk_t *disk;
282 	mbr_t *mbr;
283 	mbr_t *tt;
284 	int offset;
285 {
286 
287 	DISK_printmetrics(disk);
288 	printf("Offset: %d\t", offset);
289 	MBR_print(mbr);
290 
291 	return (CMD_CONT);
292 }
293 
294 int
295 Xwrite(cmd, disk, mbr, tt, offset)
296 	cmd_t *cmd;
297 	disk_t *disk;
298 	mbr_t *mbr;
299 	mbr_t *tt;
300 	int offset;
301 {
302 	char mbr_buf[DEV_BSIZE];
303 	int fd;
304 
305 	printf("Writing MBR at offset %d.\n", offset);
306 
307 	fd = DISK_open(disk->name, O_RDWR);
308 	MBR_make(mbr, mbr_buf);
309 	MBR_write(fd, offset, mbr_buf);
310 	close(fd);
311 	return (CMD_CLEAN);
312 }
313 
314 int
315 Xquit(cmd, disk, r, tt, offset)
316 	cmd_t *cmd;
317 	disk_t *disk;
318 	mbr_t *r;
319 	mbr_t *tt;
320 	int offset;
321 {
322 
323 	/* Nothing to do here */
324 	return (CMD_SAVE);
325 }
326 
327 int
328 Xabort(cmd, disk, mbr, tt, offset)
329 	cmd_t *cmd;
330 	disk_t *disk;
331 	mbr_t *mbr;
332 	mbr_t *tt;
333 	int offset;
334 {
335 	exit(0);
336 
337 	/* NOTREACHED */
338 	return (CMD_CONT);
339 }
340 
341 
342 int
343 Xexit(cmd, disk, mbr, tt, offset)
344 	cmd_t *cmd;
345 	disk_t *disk;
346 	mbr_t *mbr;
347 	mbr_t *tt;
348 	int offset;
349 {
350 
351 	/* Nothing to do here */
352 	return (CMD_EXIT);
353 }
354 
355 int
356 Xhelp(cmd, disk, mbr, tt, offset)
357 	cmd_t *cmd;
358 	disk_t *disk;
359 	mbr_t *mbr;
360 	mbr_t *tt;
361 	int offset;
362 {
363 	cmd_table_t *cmd_table = cmd->table;
364 	int i;
365 
366 	/* Hmm, print out cmd_table here... */
367 	for (i = 0; cmd_table[i].cmd != NULL; i++)
368 		printf("\t%s\t\t%s\n", cmd_table[i].cmd, cmd_table[i].help);
369 	return (CMD_CONT);
370 }
371 
372 int
373 Xupdate(cmd, disk, mbr, tt, offset)
374 	cmd_t *cmd;
375 	disk_t *disk;
376 	mbr_t *mbr;
377 	mbr_t *tt;
378 	int offset;
379 {
380 
381 	/* Update code */
382 	memcpy(mbr->code, tt->code, MBR_CODE_SIZE);
383 	printf("Machine code updated.\n");
384 	return (CMD_DIRTY);
385 }
386 
387 int
388 Xflag(cmd, disk, mbr, tt, offset)
389 	cmd_t *cmd;
390 	disk_t *disk;
391 	mbr_t *mbr;
392 	mbr_t *tt;
393 	int offset;
394 {
395 	int i, pn = -1;
396 
397 	/* Parse partition table entry number */
398 	if (!isdigit(cmd->args[0])) {
399 		printf("Invalid argument: %s <partition number>\n", cmd->cmd);
400 		return (CMD_CONT);
401 	}
402 	pn = atoi(cmd->args);
403 
404 	if (pn < 0 || pn > 3) {
405 		printf("Invalid partition number.\n");
406 		return (CMD_CONT);
407 	}
408 
409 	/* Set active flag */
410 	for (i = 0; i < 4; i++) {
411 		if (i == pn)
412 			mbr->part[i].flag = DOSACTIVE;
413 		else
414 			mbr->part[i].flag = 0x00;
415 	}
416 
417 	printf("Partition %d marked active.\n", pn);
418 	return (CMD_DIRTY);
419 }
420 
421 int
422 Xmanual(cmd, disk, mbr, tt, offset)
423 	cmd_t *cmd;
424 	disk_t *disk;
425 	mbr_t *mbr;
426 	mbr_t *tt;
427 	int offset;
428 {
429 	char *pager = "/usr/bin/less";
430 	char *p;
431 	sig_t opipe;
432 	extern char manpage[];
433 	FILE *f;
434 
435 	opipe = signal(SIGPIPE, SIG_IGN);
436 	if ((p = getenv("PAGER")) != NULL && (*p != '\0'))
437 		pager = p;
438 	f = popen(pager, "w");
439 	if (f) {
440 		(void) fwrite(manpage, strlen(manpage), 1, f);
441 		pclose(f);
442 	}
443 
444 	(void)signal(SIGPIPE, opipe);
445 	return (CMD_CONT);
446 }
447 
448