fix up tracing info; add default, but disable for now (could cause
[unix-history] / usr / src / sbin / disklabel / disklabel.c
CommitLineData
12c6e49c
KB
1/*
2 * Copyright (c) 1987 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
ee5681fe 7#ifndef lint
40aed5b4 8static char sccsid[] = "@(#)disklabel.c 5.12 (Berkeley) %G%";
ee5681fe
MK
9/* from static char sccsid[] = "@(#)disklabel.c 1.2 (Symmetric) 11/28/85"; */
10#endif
11
12#include <stdio.h>
13#include <ctype.h>
14#include <sys/param.h>
12c6e49c 15#include <sys/signal.h>
ee5681fe
MK
16#include <sys/errno.h>
17#include <sys/file.h>
18#include <sys/ioctl.h>
12c6e49c
KB
19#include <sys/fs.h>
20#include <strings.h>
ee5681fe
MK
21#define DKTYPENAMES
22#include <sys/disklabel.h>
23
24/*
25 * Disklabel: read and write disklabels.
26 * The label is usually placed on one of the first sectors of the disk.
27 * Many machines (VAX 11/750) also place a bootstrap in the same area,
28 * in which case the label is embedded in the bootstrap.
29 * The bootstrap source must leave space at the proper offset
30 * for the label on such machines.
31 */
32
452bf484
MK
33#ifdef vax
34#define RAWPARTITION 'c'
35#else
36#define RAWPARTITION 'a'
37#endif
38
39#ifndef BBSIZE
ee5681fe 40#define BBSIZE 8192 /* size of boot area, with label */
452bf484 41#endif
ee5681fe
MK
42
43#ifdef vax
44#define BOOT /* also have bootstrap in "boot area" */
45#define BOOTDIR "/usr/mdec" /* source of boot binaries */
452bf484
MK
46#else
47#ifdef lint
48#define BOOT
49#endif
ee5681fe
MK
50#endif
51
12c6e49c
KB
52#define DEFEDITOR "/usr/ucb/vi"
53#define streq(a,b) (strcmp(a,b) == 0)
54
12c6e49c 55#ifdef BOOT
ee5681fe
MK
56char *xxboot;
57char *bootxx;
12c6e49c 58#endif
53e3e5d6
MK
59
60char *dkname;
ee5681fe 61char *specname;
12c6e49c 62char tmpfil[] = "/tmp/EdDk.aXXXXXX";
ee5681fe
MK
63
64extern int errno;
65char namebuf[BBSIZE], *np = namebuf;
ee5681fe 66struct disklabel lab;
53e3e5d6
MK
67struct disklabel *readlabel(), *makebootarea();
68char bootarea[BBSIZE];
40aed5b4
MK
69char boot0[MAXPATHLEN];
70char boot1[MAXPATHLEN];
ee5681fe 71
40aed5b4 72enum { UNSPEC, EDIT, NOWRITE, READ, RESTORE, WRITE, WRITEABLE } op = UNSPEC;
ee5681fe 73
452bf484
MK
74int rflag;
75
40aed5b4
MK
76#ifdef DEBUG
77int debug;
78#endif
79
ee5681fe
MK
80main(argc, argv)
81 int argc;
82 char *argv[];
83{
40aed5b4 84 extern int optind;
ee5681fe 85 register struct disklabel *lp;
40aed5b4
MK
86 FILE *t;
87 int ch, f;
12c6e49c
KB
88 char *name = 0, *type;
89
40aed5b4
MK
90 while ((ch = getopt(argc, argv, "NRWerw")) != EOF)
91 switch (ch) {
92 case 'N':
93 if (op != UNSPEC)
94 usage();
95 op = NOWRITE;
96 break;
12c6e49c 97 case 'R':
40aed5b4
MK
98 if (op != UNSPEC)
99 usage();
12c6e49c
KB
100 op = RESTORE;
101 break;
40aed5b4
MK
102 case 'W':
103 if (op != UNSPEC)
104 usage();
105 op = WRITEABLE;
106 break;
12c6e49c 107 case 'e':
40aed5b4
MK
108 if (op != UNSPEC)
109 usage();
12c6e49c
KB
110 op = EDIT;
111 break;
112 case 'r':
113 ++rflag;
114 break;
115 case 'w':
40aed5b4
MK
116 if (op != UNSPEC)
117 usage();
12c6e49c
KB
118 op = WRITE;
119 break;
40aed5b4
MK
120#ifdef DEBUG
121 case 'd':
122 debug++;
123 break;
124#endif
12c6e49c
KB
125 case '?':
126 default:
127 usage();
128 }
129 argc -= optind;
130 argv += optind;
40aed5b4
MK
131 if (op == UNSPEC)
132 op = READ;
12c6e49c
KB
133 if (argc < 1)
134 usage();
135
136 dkname = argv[0];
ee5681fe 137 if (dkname[0] != '/') {
9bd38ba8 138 (void)sprintf(np, "/dev/r%s%c", dkname, RAWPARTITION);
ee5681fe
MK
139 specname = np;
140 np += strlen(specname) + 1;
141 } else
142 specname = dkname;
143 f = open(specname, op == READ ? O_RDONLY : O_RDWR);
144 if (f < 0 && errno == ENOENT && dkname[0] != '/') {
9bd38ba8 145 (void)sprintf(specname, "/dev/r%s", dkname);
ee5681fe
MK
146 np = namebuf + strlen(specname) + 1;
147 f = open(specname, op == READ ? O_RDONLY : O_RDWR);
148 }
149 if (f < 0)
150 Perror(specname);
151
12c6e49c 152 switch(op) {
ee5681fe 153 case EDIT:
12c6e49c
KB
154 if (argc != 1)
155 usage();
40aed5b4 156 lp = readlabel(f);
12c6e49c
KB
157 if (edit(lp))
158 writelabel(f, bootarea, lp);
ee5681fe 159 break;
40aed5b4
MK
160 case NOWRITE: {
161 int flag = 0;
162 if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0)
163 Perror("ioctl DIOCWLABEL");
164 break;
165 }
12c6e49c
KB
166 case READ:
167 if (argc != 1)
168 usage();
40aed5b4 169 lp = readlabel(f);
12c6e49c
KB
170 display(stdout, lp);
171 (void) checklabel(lp);
ee5681fe 172 break;
ee5681fe 173 case RESTORE:
12c6e49c 174#ifdef BOOT
40aed5b4
MK
175 if (rflag) {
176 if (argc == 4) { /* [ priboot secboot ] */
177 xxboot = argv[2];
178 bootxx = argv[3];
179 lab.d_secsize = DEV_BSIZE; /* XXX */
180 lab.d_bbsize = BBSIZE; /* XXX */
181 }
182 else if (argc == 3) /* [ disktype ] */
183 makelabel(argv[2], (char *)NULL, &lab);
184 else {
185 fprintf(stderr,
186"Must specify either disktype or bootfiles with -r flag of RESTORE option\n");
187 exit(1);
188 }
189 }
190 else
53e3e5d6 191#endif
12c6e49c
KB
192 if (argc != 2)
193 usage();
53e3e5d6 194 lp = makebootarea(bootarea, &lab);
12c6e49c
KB
195 if (!(t = fopen(argv[1],"r")))
196 Perror(argv[1]);
197 if (getasciilabel(t, lp))
198 writelabel(f, bootarea, lp);
199 break;
200 case WRITE:
201 type = argv[1];
202#ifdef BOOT
203 if (argc > 5 || argc < 2)
204 usage();
205 if (argc > 3) {
206 bootxx = argv[--argc];
207 xxboot = argv[--argc];
208 }
209#else
12c6e49c 210 if (argc > 3 || argc < 2)
12c6e49c
KB
211 usage();
212#endif
213 if (argc > 2)
214 name = argv[--argc];
215 makelabel(type, name, &lab);
53e3e5d6 216 lp = makebootarea(bootarea, &lab);
12c6e49c
KB
217 *lp = lab;
218 if (checklabel(lp) == 0)
219 writelabel(f, bootarea, lp);
ee5681fe 220 break;
40aed5b4
MK
221 case WRITEABLE: {
222 int flag = 1;
223 if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0)
224 Perror("ioctl DIOCWLABEL");
225 break;
226 }
ee5681fe
MK
227 }
228 exit(0);
229}
230
40aed5b4
MK
231/*
232 * Construct a prototype disklabel from /etc/disktab. As a side
233 * effect, set the names of the primary and secondary boot files
234 * if specified.
235 */
ee5681fe
MK
236makelabel(type, name, lp)
237 char *type, *name;
238 register struct disklabel *lp;
239{
240 register struct disklabel *dp;
40aed5b4 241 char *strcpy();
ee5681fe
MK
242
243 dp = getdiskbyname(type);
244 if (dp == NULL) {
245 fprintf(stderr, "%s: unknown disk type\n", type);
246 exit(1);
247 }
248 *lp = *dp;
40aed5b4
MK
249#ifdef BOOT
250 /*
251 * Check if disktab specifies the bootstraps (b0 or b1).
252 */
253 if (!xxboot && lp->d_boot0) {
254 if (*lp->d_boot0 != '/')
255 (void)sprintf(boot0, "%s/%s", BOOTDIR, lp->d_boot0);
256 else
257 (void)strcpy(boot0, lp->d_boot0);
258 xxboot = boot0;
259 }
260 if (!bootxx && lp->d_boot1) {
261 if (*lp->d_boot1 != '/')
262 (void)sprintf(boot1, "%s/%s", BOOTDIR, lp->d_boot1);
263 else
264 (void)strcpy(boot1, lp->d_boot1);
265 bootxx = boot1;
266 }
267 /*
268 * If bootstraps not specified anywhere, makebootarea()
269 * will choose ones based on the name of the disk special
270 * file. E.g. /dev/ra0 -> raboot, bootra
271 */
272#endif /*BOOT*/
273 /* d_packname is union d_boot[01], so zero */
274 bzero(lp->d_packname, sizeof(lp->d_packname));
ee5681fe 275 if (name)
40aed5b4 276 (void)strncpy(lp->d_packname, name, sizeof(lp->d_packname));
ee5681fe
MK
277}
278
279writelabel(f, boot, lp)
280 int f;
281 char *boot;
282 register struct disklabel *lp;
283{
12c6e49c 284 register int i;
40aed5b4
MK
285 int flag;
286 off_t lseek();
ee5681fe
MK
287
288 lp->d_magic = DISKMAGIC;
289 lp->d_magic2 = DISKMAGIC;
ee5681fe
MK
290 lp->d_checksum = 0;
291 lp->d_checksum = dkcksum(lp);
452bf484 292 if (rflag) {
40aed5b4
MK
293 /*
294 * First set the kernel disk label,
295 * then write a label to the raw disk.
296 * If the SDINFO ioctl fails because it is unimplemented,
297 * keep going; otherwise, the kernel consistency checks
298 * may prevent us from changing the current (in-core)
299 * label.
300 */
301 if (ioctl(f, DIOCSDINFO, lp) < 0 &&
302 errno != ENODEV && errno != ENOTTY)
303 Perror("ioctl DIOCSDINFO");
53e3e5d6 304 (void)lseek(f, (off_t)0, L_SET);
40aed5b4
MK
305 /*
306 * write enable label sector before write (if necessary),
307 * disable after writing.
308 */
309 flag = 1;
310 if (ioctl(f, DIOCWLABEL, &flag) < 0)
311 perror("ioctl DIOCWLABEL");
312 if (write(f, boot, lp->d_bbsize) != lp->d_bbsize)
452bf484 313 Perror("write");
40aed5b4
MK
314 flag = 0;
315 (void) ioctl(f, DIOCWLABEL, &flag);
452bf484
MK
316 } else if (ioctl(f, DIOCWDINFO, lp) < 0)
317 Perror("ioctl DIOCWDINFO");
40aed5b4 318#ifdef vax
452bf484
MK
319 if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) {
320 daddr_t alt;
321
322 alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
323 for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
12c6e49c 324 (void)lseek(f, (off_t)((alt + i) * lp->d_secsize), L_SET);
452bf484
MK
325 if (write(f, boot, lp->d_secsize) < lp->d_secsize) {
326 int oerrno = errno;
327 fprintf(stderr, "alternate label %d ", i/2);
328 errno = oerrno;
329 perror("write");
330 }
ee5681fe
MK
331 }
332 }
1268bb93 333#endif
ee5681fe
MK
334}
335
336/*
53e3e5d6 337 * Fetch disklabel for disk.
53e3e5d6 338 * Use ioctl to get label unless -r flag is given.
ee5681fe
MK
339 */
340struct disklabel *
40aed5b4
MK
341readlabel(f)
342 int f;
ee5681fe
MK
343{
344 register struct disklabel *lp;
ee5681fe 345
40aed5b4 346 if (rflag) {
53e3e5d6 347 if (read(f, bootarea, BBSIZE) < BBSIZE)
88b9be0b 348 Perror(specname);
53e3e5d6
MK
349 for (lp = (struct disklabel *)bootarea;
350 lp <= (struct disklabel *)(bootarea + BBSIZE - sizeof(*lp));
452bf484
MK
351 lp = (struct disklabel *)((char *)lp + 16))
352 if (lp->d_magic == DISKMAGIC &&
353 lp->d_magic2 == DISKMAGIC)
354 break;
53e3e5d6 355 if (lp > (struct disklabel *)(bootarea+BBSIZE-sizeof(*lp)) ||
452bf484
MK
356 lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC ||
357 dkcksum(lp) != 0) {
358 fprintf(stderr,
ee5681fe 359 "Bad pack magic number (label is damaged, or pack is unlabeled)\n");
40aed5b4
MK
360 /* lp = (struct disklabel *)(bootarea + LABELOFFSET); */
361 exit (1);
452bf484 362 }
40aed5b4
MK
363 } else {
364 lp = &lab;
365 if (ioctl(f, DIOCGDINFO, lp) < 0)
366 Perror("ioctl DIOCGDINFO");
ee5681fe 367 }
ee5681fe
MK
368 return (lp);
369}
370
371struct disklabel *
53e3e5d6 372makebootarea(boot, dp)
ee5681fe
MK
373 char *boot;
374 register struct disklabel *dp;
375{
376 struct disklabel *lp;
377 register char *p;
378 int b;
ee5681fe 379#ifdef BOOT
12c6e49c 380 char *dkbasename;
40aed5b4 381#endif /*BOOT*/
12c6e49c 382
40aed5b4
MK
383 lp = (struct disklabel *)(boot + (LABELSECTOR * dp->d_secsize) +
384 LABELOFFSET);
385#ifdef BOOT
386 if (!rflag)
387 return (lp);
388
389 if (xxboot == NULL || bootxx == NULL) {
ee5681fe
MK
390 dkbasename = np;
391 if ((p = rindex(dkname, '/')) == NULL)
392 p = dkname;
393 else
394 p++;
395 while (*p && !isdigit(*p))
396 *np++ = *p++;
397 *np++ = '\0';
398
40aed5b4
MK
399 if (xxboot == NULL) {
400 (void)sprintf(np, "%s/%sboot", BOOTDIR, dkbasename);
401 if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
402 dkbasename++;
403 xxboot = np;
404 (void)sprintf(xxboot, "%s/%sboot", BOOTDIR, dkbasename);
405 np += strlen(xxboot) + 1;
406 }
407 if (bootxx == NULL) {
408 (void)sprintf(np, "%s/boot%s", BOOTDIR, dkbasename);
409 if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
410 dkbasename++;
411 bootxx = np;
412 (void)sprintf(bootxx, "%s/boot%s", BOOTDIR, dkbasename);
413 np += strlen(bootxx) + 1;
414 }
ee5681fe 415 }
40aed5b4
MK
416#ifdef DEBUG
417 if (debug)
418 fprintf(stderr, "bootstraps: xxboot = %s, bootxx = %s\n",
419 xxboot, bootxx);
420#endif
ee5681fe
MK
421
422 b = open(xxboot, O_RDONLY);
423 if (b < 0)
424 Perror(xxboot);
12c6e49c 425 if (read(b, boot, (int)dp->d_secsize) < 0)
ee5681fe
MK
426 Perror(xxboot);
427 close(b);
428 b = open(bootxx, O_RDONLY);
429 if (b < 0)
430 Perror(bootxx);
12c6e49c 431 if (read(b, &boot[dp->d_secsize], (int)(dp->d_bbsize-dp->d_secsize)) < 0)
ee5681fe 432 Perror(bootxx);
12c6e49c 433 (void)close(b);
40aed5b4 434#endif /*BOOT*/
ee5681fe 435
ee5681fe
MK
436 for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++)
437 if (*p) {
438 fprintf(stderr,
439 "Bootstrap doesn't leave room for disk label\n");
440 exit(2);
441 }
442 return (lp);
443}
444
445display(f, lp)
446 FILE *f;
447 register struct disklabel *lp;
448{
12c6e49c 449 register int i, j;
ee5681fe
MK
450 register struct partition *pp;
451
452 fprintf(f, "# %s:\n", specname);
453 if ((unsigned) lp->d_type < DKMAXTYPES)
454 fprintf(f, "type: %s\n", dktypenames[lp->d_type]);
455 else
456 fprintf(f, "type: %d\n", lp->d_type);
457 fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename);
40aed5b4 458 fprintf(f, "label: %.*s\n", sizeof(lp->d_packname), lp->d_packname);
88b9be0b 459 fprintf(f, "flags:");
ee5681fe 460 if (lp->d_flags & D_REMOVABLE)
88b9be0b 461 fprintf(f, " removeable");
ee5681fe 462 if (lp->d_flags & D_ECC)
88b9be0b 463 fprintf(f, " ecc");
ee5681fe 464 if (lp->d_flags & D_BADSECT)
88b9be0b 465 fprintf(f, " badsect");
ee5681fe
MK
466 fprintf(f, "\n");
467 fprintf(f, "bytes/sector: %d\n", lp->d_secsize);
468 fprintf(f, "sectors/track: %d\n", lp->d_nsectors);
469 fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks);
c6e761b2 470 fprintf(f, "sectors/cylinder: %d\n", lp->d_secpercyl);
ee5681fe 471 fprintf(f, "cylinders: %d\n", lp->d_ncylinders);
12c6e49c 472 fprintf(f, "rpm: %d\n", lp->d_rpm);
ee5681fe
MK
473 fprintf(f, "interleave: %d\n", lp->d_interleave);
474 fprintf(f, "trackskew: %d\n", lp->d_trackskew);
475 fprintf(f, "cylinderskew: %d\n", lp->d_cylskew);
476 fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch);
477 fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek);
478 fprintf(f, "drivedata: ");
479 for (i = NDDATA - 1; i >= 0; i--)
480 if (lp->d_drivedata[i])
481 break;
482 if (i < 0)
483 i = 0;
484 for (j = 0; j <= i; j++)
485 fprintf(f, "%d ", lp->d_drivedata[j]);
486 fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions);
9e0e871b
MK
487 fprintf(f,
488 "# size offset fstype [fsize bsize cpg]\n");
ee5681fe
MK
489 pp = lp->d_partitions;
490 for (i = 0; i < lp->d_npartitions; i++, pp++) {
ee5681fe 491 if (pp->p_size) {
9e0e871b
MK
492 fprintf(f, " %c: %8d %8d ", 'a' + i,
493 pp->p_size, pp->p_offset);
ee5681fe
MK
494 if ((unsigned) pp->p_fstype < FSMAXTYPES)
495 fprintf(f, "%8.8s", fstypenames[pp->p_fstype]);
496 else
497 fprintf(f, "%8d", pp->p_fstype);
9e0e871b
MK
498 switch (pp->p_fstype) {
499
500 case FS_UNUSED: /* XXX */
501 fprintf(f, " %5d %5d %5.5s ",
502 pp->p_fsize, pp->p_fsize * pp->p_frag, "");
503 break;
504
505 case FS_BSDFFS:
506 fprintf(f, " %5d %5d %5d ",
507 pp->p_fsize, pp->p_fsize * pp->p_frag,
508 pp->p_cpg);
509 break;
510
511 default:
512 fprintf(f, "%20.20s", "");
513 break;
514 }
ee5681fe
MK
515 fprintf(f, "\t# (Cyl. %4d",
516 pp->p_offset / lp->d_secpercyl);
517 if (pp->p_offset % lp->d_secpercyl)
518 putc('*', f);
519 else
520 putc(' ', f);
521 fprintf(f, "- %d",
522 (pp->p_offset +
523 pp->p_size + lp->d_secpercyl - 1) /
524 lp->d_secpercyl - 1);
525 if (pp->p_size % lp->d_secpercyl)
526 putc('*', f);
9e0e871b 527 fprintf(f, ")\n");
ee5681fe 528 }
ee5681fe 529 }
816cd0ca 530 fflush(f);
ee5681fe
MK
531}
532
12c6e49c
KB
533edit(lp)
534 struct disklabel *lp;
ee5681fe 535{
12c6e49c
KB
536 register int c;
537 struct disklabel label;
538 FILE *fd;
539 char *mktemp();
540
541 (void) mktemp(tmpfil);
542 fd = fopen(tmpfil, "w");
543 if (fd == NULL) {
544 fprintf(stderr, "%s: Can't create\n", tmpfil);
545 return (0);
546 }
547 (void)fchmod(fd, 0600);
548 display(fd, lp);
549 fclose(fd);
550 for (;;) {
551 if (!editit())
552 break;
553 fd = fopen(tmpfil, "r");
554 if (fd == NULL) {
40aed5b4
MK
555 fprintf(stderr, "%s: Can't reopen for reading\n",
556 tmpfil);
12c6e49c
KB
557 break;
558 }
9e0e871b 559 bzero((char *)&label, sizeof(label));
12c6e49c
KB
560 if (getasciilabel(fd, &label)) {
561 *lp = label;
562 (void) unlink(tmpfil);
563 return (1);
564 }
565 printf("re-edit the label? [y]: "); fflush(stdout);
566 c = getchar();
567 if (c != EOF && c != (int)'\n')
568 while (getchar() != (int)'\n')
569 ;
570 if (c == (int)'n')
571 break;
572 }
573 (void) unlink(tmpfil);
574 return (0);
ee5681fe
MK
575}
576
12c6e49c
KB
577editit()
578{
579 register int pid, xpid;
580 int stat, omask;
581 extern char *getenv();
582
583 omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
584 while ((pid = fork()) < 0) {
585 extern int errno;
586
587 if (errno == EPROCLIM) {
588 fprintf(stderr, "You have too many processes\n");
589 return(0);
590 }
591 if (errno != EAGAIN) {
592 perror("fork");
593 return(0);
594 }
595 sleep(1);
596 }
597 if (pid == 0) {
598 register char *ed;
599
600 sigsetmask(omask);
601 setgid(getgid());
602 setuid(getuid());
603 if ((ed = getenv("EDITOR")) == (char *)0)
604 ed = DEFEDITOR;
605 execlp(ed, ed, tmpfil, 0);
606 perror(ed);
607 exit(1);
608 }
609 while ((xpid = wait(&stat)) >= 0)
610 if (xpid == pid)
611 break;
612 sigsetmask(omask);
613 return(!stat);
614}
615
616char *
617skip(cp)
618 register char *cp;
619{
620
621 while (*cp != '\0' && isspace(*cp))
622 cp++;
623 if (*cp == '\0' || *cp == '#')
624 return ((char *)NULL);
625 return (cp);
626}
627
628char *
629word(cp)
630 register char *cp;
631{
632 register char c;
633
88b9be0b
MK
634 while (*cp != '\0' && !isspace(*cp) && *cp != '#')
635 cp++;
12c6e49c
KB
636 if ((c = *cp) != '\0') {
637 *cp++ = '\0';
638 if (c != '#')
639 return (skip(cp));
640 }
641 return ((char *)NULL);
642}
ee5681fe
MK
643
644/*
645 * Read an ascii label in from fd f,
646 * in the same format as that put out by display(),
647 * and fill in lp.
648 */
649getasciilabel(f, lp)
12c6e49c 650 FILE *f;
ee5681fe
MK
651 register struct disklabel *lp;
652{
12c6e49c 653 register char **cpp, *cp;
9e0e871b 654 register struct partition *pp;
12c6e49c
KB
655 char *tp, *s, line[BUFSIZ];
656 int v, lineno = 0, errors = 0;
657
658 lp->d_bbsize = BBSIZE; /* XXX */
659 lp->d_sbsize = SBSIZE; /* XXX */
660 while (fgets(line, sizeof(line) - 1, f)) {
661 lineno++;
662 if (cp = index(line,'\n'))
663 *cp = '\0';
664 cp = skip(line);
665 if (cp == NULL)
666 continue;
667 tp = index(cp, ':');
668 if (tp == NULL) {
669 fprintf(stderr, "line %d: syntax error\n", lineno);
670 errors++;
671 continue;
672 }
673 *tp++ = '\0', tp = skip(tp);
674 if (streq(cp, "type")) {
675 if (tp == NULL)
676 tp = "unknown";
677 cpp = dktypenames;
678 for (; cpp < &dktypenames[DKMAXTYPES]; cpp++)
679 if ((s = *cpp) && streq(s, tp)) {
680 lp->d_type = cpp - dktypenames;
681 goto next;
682 }
683 v = atoi(tp);
684 if ((unsigned)v >= DKMAXTYPES)
685 fprintf(stderr, "line %d:%s %d\n", lineno,
686 "Warning, unknown disk type", v);
687 lp->d_type = v;
688 continue;
689 }
690 if (streq(cp, "flags")) {
40aed5b4
MK
691 for (v = 0; (cp = tp) && *cp != '\0';) {
692 tp = word(cp);
12c6e49c
KB
693 if (streq(cp, "removeable"))
694 v |= D_REMOVABLE;
695 else if (streq(cp, "ecc"))
696 v |= D_ECC;
697 else if (streq(cp, "badsect"))
698 v |= D_BADSECT;
699 else {
700 fprintf(stderr,
701 "line %d: %s: bad flag\n",
702 lineno, cp);
703 errors++;
704 }
705 }
706 lp->d_flags = v;
707 continue;
708 }
709 if (streq(cp, "drivedata")) {
710 register int i;
711
c6e761b2 712 for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) {
12c6e49c 713 lp->d_drivedata[i++] = atoi(cp);
c6e761b2 714 tp = word(cp);
12c6e49c
KB
715 }
716 continue;
717 }
718 if (sscanf(cp, "%d partitions", &v) == 1) {
9e0e871b 719 if (v == 0 || (unsigned)v > MAXPARTITIONS) {
12c6e49c
KB
720 fprintf(stderr,
721 "line %d: bad # of partitions\n", lineno);
9e0e871b
MK
722 lp->d_npartitions = MAXPARTITIONS;
723 errors++;
724 } else
12c6e49c
KB
725 lp->d_npartitions = v;
726 continue;
727 }
728 if (tp == NULL)
729 tp = "";
730 if (streq(cp, "disk")) {
731 strncpy(lp->d_typename, tp, sizeof (lp->d_typename));
732 continue;
733 }
734 if (streq(cp, "label")) {
40aed5b4 735 strncpy(lp->d_packname, tp, sizeof (lp->d_packname));
12c6e49c
KB
736 continue;
737 }
738 if (streq(cp, "bytes/sector")) {
739 v = atoi(tp);
740 if (v <= 0 || (v % 512) != 0) {
741 fprintf(stderr,
742 "line %d: %s: bad sector size\n",
743 lineno, tp);
744 errors++;
745 } else
746 lp->d_secsize = v;
747 continue;
748 }
749 if (streq(cp, "sectors/track")) {
750 v = atoi(tp);
751 if (v <= 0) {
752 fprintf(stderr, "line %d: %s: bad %s\n",
753 lineno, tp, cp);
754 errors++;
755 } else
756 lp->d_nsectors = v;
757 continue;
758 }
c6e761b2
MK
759 if (streq(cp, "sectors/cylinder")) {
760 v = atoi(tp);
761 if (v <= 0) {
762 fprintf(stderr, "line %d: %s: bad %s\n",
763 lineno, tp, cp);
764 errors++;
765 } else
766 lp->d_secpercyl = v;
767 continue;
768 }
12c6e49c
KB
769 if (streq(cp, "tracks/cylinder")) {
770 v = atoi(tp);
771 if (v <= 0) {
772 fprintf(stderr, "line %d: %s: bad %s\n",
773 lineno, tp, cp);
774 errors++;
775 } else
776 lp->d_ntracks = v;
777 continue;
778 }
779 if (streq(cp, "cylinders")) {
780 v = atoi(tp);
781 if (v <= 0) {
782 fprintf(stderr, "line %d: %s: bad %s\n",
783 lineno, tp, cp);
784 errors++;
785 } else
786 lp->d_ncylinders = v;
787 continue;
788 }
789 if (streq(cp, "rpm")) {
790 v = atoi(tp);
791 if (v <= 0) {
792 fprintf(stderr, "line %d: %s: bad %s\n",
793 lineno, tp, cp);
794 errors++;
795 } else
796 lp->d_rpm = v;
797 continue;
798 }
799 if (streq(cp, "interleave")) {
800 v = atoi(tp);
801 if (v <= 0) {
802 fprintf(stderr, "line %d: %s: bad %s\n",
803 lineno, tp, cp);
804 errors++;
805 } else
806 lp->d_interleave = v;
807 continue;
808 }
809 if (streq(cp, "trackskew")) {
810 v = atoi(tp);
811 if (v < 0) {
812 fprintf(stderr, "line %d: %s: bad %s\n",
813 lineno, tp, cp);
814 errors++;
815 } else
816 lp->d_trackskew = v;
817 continue;
818 }
819 if (streq(cp, "cylinderskew")) {
820 v = atoi(tp);
821 if (v < 0) {
822 fprintf(stderr, "line %d: %s: bad %s\n",
823 lineno, tp, cp);
824 errors++;
825 } else
826 lp->d_cylskew = v;
827 continue;
828 }
829 if (streq(cp, "headswitch")) {
830 v = atoi(tp);
831 if (v < 0) {
832 fprintf(stderr, "line %d: %s: bad %s\n",
833 lineno, tp, cp);
834 errors++;
835 } else
836 lp->d_headswitch = v;
837 continue;
838 }
839 if (streq(cp, "track-to-track seek")) {
840 v = atoi(tp);
841 if (v < 0) {
842 fprintf(stderr, "line %d: %s: bad %s\n",
843 lineno, tp, cp);
844 errors++;
845 } else
846 lp->d_trkseek = v;
847 continue;
848 }
849 if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') {
9e0e871b 850 unsigned part = *cp - 'a';
12c6e49c 851
9e0e871b 852 if (part > lp->d_npartitions) {
12c6e49c
KB
853 fprintf(stderr,
854 "line %d: bad partition name\n", lineno);
855 errors++;
856 continue;
857 }
9e0e871b
MK
858 pp = &lp->d_partitions[part];
859#define NXTNUM(n) { \
860 cp = tp, tp = word(cp); \
861 if (tp == NULL) \
862 tp = cp; \
863 (n) = atoi(cp); \
864 }
865
866 NXTNUM(v);
12c6e49c
KB
867 if (v < 0) {
868 fprintf(stderr,
869 "line %d: %s: bad partition size\n",
870 lineno, cp);
871 errors++;
872 } else
9e0e871b
MK
873 pp->p_size = v;
874 NXTNUM(v);
12c6e49c
KB
875 if (v < 0) {
876 fprintf(stderr,
877 "line %d: %s: bad partition offset\n",
878 lineno, cp);
879 errors++;
880 } else
9e0e871b 881 pp->p_offset = v;
12c6e49c
KB
882 cp = tp, tp = word(cp);
883 cpp = fstypenames;
884 for (; cpp < &fstypenames[FSMAXTYPES]; cpp++)
885 if ((s = *cpp) && streq(s, cp)) {
9e0e871b
MK
886 pp->p_fstype = cpp - fstypenames;
887 goto gottype;
12c6e49c 888 }
40aed5b4
MK
889 if (isdigit(*cp))
890 v = atoi(cp);
891 else
892 v = FSMAXTYPES;
893 if ((unsigned)v >= FSMAXTYPES) {
12c6e49c
KB
894 fprintf(stderr, "line %d: %s %s\n", lineno,
895 "Warning, unknown filesystem type", cp);
40aed5b4
MK
896 v = FS_UNUSED;
897 }
9e0e871b
MK
898 pp->p_fstype = v;
899 gottype:
900
901 switch (pp->p_fstype) {
902
903 case FS_UNUSED: /* XXX */
904 NXTNUM(pp->p_fsize);
905 if (pp->p_fsize == 0)
906 break;
907 NXTNUM(v);
908 pp->p_frag = v / pp->p_fsize;
909 break;
910
911 case FS_BSDFFS:
912 NXTNUM(pp->p_fsize);
913 if (pp->p_fsize == 0)
914 break;
915 NXTNUM(v);
916 pp->p_frag = v / pp->p_fsize;
917 NXTNUM(pp->p_cpg);
918 break;
919
920 default:
921 break;
922 }
12c6e49c
KB
923 continue;
924 }
925 fprintf(stderr, "line %d: %s: Unknown disklabel field\n",
926 lineno, cp);
927 errors++;
928 next:
929 ;
930 }
931 errors += checklabel(lp);
932 return (errors == 0);
933}
934
935/*
936 * Check disklabel for errors and fill in
937 * derived fields according to supplied values.
938 */
939checklabel(lp)
940 register struct disklabel *lp;
941{
942 register struct partition *pp;
943 int i, errors = 0;
944 char part;
945
946 if (lp->d_secsize == 0) {
947 fprintf(stderr, "sector size %d\n", lp->d_secsize);
948 return (1);
949 }
950 if (lp->d_nsectors == 0) {
951 fprintf(stderr, "sectors/track %d\n", lp->d_nsectors);
952 return (1);
953 }
954 if (lp->d_ntracks == 0) {
955 fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks);
956 return (1);
957 }
958 if (lp->d_ncylinders == 0) {
959 fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders);
960 errors++;
961 }
962 if (lp->d_rpm == 0)
963 Warning("revolutions/minute %d\n", lp->d_rpm);
964 if (lp->d_secpercyl == 0)
965 lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
966 if (lp->d_secperunit == 0)
967 lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders;
968 if (lp->d_bbsize == 0) {
969 fprintf(stderr, "boot block size %d\n", lp->d_bbsize);
970 errors++;
971 } else if (lp->d_bbsize % lp->d_secsize)
972 Warning("boot block size %% sector-size != 0\n");
973 if (lp->d_sbsize == 0) {
974 fprintf(stderr, "super block size %d\n", lp->d_sbsize);
975 errors++;
976 } else if (lp->d_sbsize % lp->d_secsize)
977 Warning("super block size %% sector-size != 0\n");
978 if (lp->d_npartitions > MAXPARTITIONS)
979 Warning("number of partitions (%d) > MAXPARTITIONS (%d)\n",
980 lp->d_npartitions, MAXPARTITIONS);
981 for (i = 0; i < lp->d_npartitions; i++) {
982 part = 'a' + i;
983 pp = &lp->d_partitions[i];
984 if (pp->p_size == 0 && pp->p_offset != 0)
985 Warning("partition %c: size 0, but offset %d\n",
986 part, pp->p_offset);
987#ifdef notdef
988 if (pp->p_size % lp->d_secpercyl)
989 Warning("partition %c: size %% cylinder-size != 0\n",
990 part);
991 if (pp->p_offset % lp->d_secpercyl)
992 Warning("partition %c: offset %% cylinder-size != 0\n",
993 part);
994#endif
995 if (pp->p_offset > lp->d_secperunit) {
996 fprintf(stderr,
997 "partition %c: offset past end of unit\n", part);
998 errors++;
999 }
1000 if (pp->p_offset + pp->p_size > lp->d_secperunit) {
1001 fprintf(stderr,
1002 "partition %c: partition extends past end of unit\n",
1003 part);
1004 errors++;
1005 }
1006 }
1007 for (; i < MAXPARTITIONS; i++) {
1008 part = 'a' + i;
1009 pp = &lp->d_partitions[i];
1010 if (pp->p_size || pp->p_offset)
1011 Warning("unused partition %c: size %d offset %d\n",
40aed5b4 1012 'a' + i, pp->p_size, pp->p_offset);
12c6e49c
KB
1013 }
1014 return (errors);
ee5681fe
MK
1015}
1016
12c6e49c
KB
1017/*VARARGS1*/
1018Warning(fmt, a1, a2, a3, a4, a5)
1019 char *fmt;
ee5681fe
MK
1020{
1021
12c6e49c
KB
1022 fprintf(stderr, "Warning, ");
1023 fprintf(stderr, fmt, a1, a2, a3, a4, a5);
1024 fprintf(stderr, "\n");
1025}
1026
1027Perror(str)
1028 char *str;
1029{
1030 fputs("disklabel: ", stderr); perror(str);
ee5681fe
MK
1031 exit(4);
1032}
12c6e49c
KB
1033
1034usage()
1035{
1036#ifdef BOOT
40aed5b4 1037 fprintf(stderr, "%-62s%s\n%-62s%s\n%-62s%s\n%-62s%s\n%-62s%s\n",
12c6e49c
KB
1038"usage: disklabel [-r] disk", "(to read label)",
1039"or disklabel -w [-r] disk type [ packid ] [ xxboot bootxx ]", "(to write label)",
1040"or disklabel -e [-r] disk", "(to edit label)",
40aed5b4
MK
1041"or disklabel -R [-r] disk protofile [ type | xxboot bootxx ]", "(to restore label)",
1042"or disklabel [-NW] disk", "(to write disable/enable label)");
12c6e49c 1043#else
40aed5b4 1044 fprintf(stderr, "%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n",
12c6e49c
KB
1045"usage: disklabel [-r] disk", "(to read label)",
1046"or disklabel -w [-r] disk type [ packid ]", "(to write label)",
1047"or disklabel -e [-r] disk", "(to edit label)",
40aed5b4
MK
1048"or disklabel -R [-r] disk protofile", "(to restore label)",
1049"or disklabel [-NW] disk", "(to write disable/enable label)");
12c6e49c
KB
1050#endif
1051 exit(1);
1052}