more fixes: write boot block if writing, not editing;
[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
88b9be0b 8static char sccsid[] = "@(#)disklabel.c 5.8 (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
ee5681fe 55char *dkname;
12c6e49c 56#ifdef BOOT
ee5681fe
MK
57char *xxboot;
58char *bootxx;
12c6e49c 59#endif
ee5681fe 60char *specname;
12c6e49c 61char tmpfil[] = "/tmp/EdDk.aXXXXXX";
ee5681fe 62char *sprintf();
ee5681fe
MK
63
64extern int errno;
65char namebuf[BBSIZE], *np = namebuf;
66char bootarea[BBSIZE];
67struct disklabel lab;
68struct disklabel *readlabel(), *getbootarea();
69
12c6e49c 70enum { READ, WRITE, EDIT, RESTORE } op = READ;
ee5681fe 71
452bf484
MK
72int rflag;
73
ee5681fe
MK
74main(argc, argv)
75 int argc;
76 char *argv[];
77{
12c6e49c 78 extern int optind;
ee5681fe 79 register struct disklabel *lp;
12c6e49c
KB
80 FILE *t;
81 int ch, f;
82 char *name = 0, *type;
83
84 while ((ch = getopt(argc, argv, "Rerw")) != EOF)
85 switch((char)ch) {
86 case 'R':
87 op = RESTORE;
88 break;
89 case 'e':
90 op = EDIT;
91 break;
92 case 'r':
93 ++rflag;
94 break;
95 case 'w':
96 op = WRITE;
97 break;
98 case '?':
99 default:
100 usage();
101 }
102 argc -= optind;
103 argv += optind;
104 if (argc < 1)
105 usage();
106
107 dkname = argv[0];
ee5681fe 108 if (dkname[0] != '/') {
452bf484 109 sprintf(np, "/dev/r%s%c", dkname, RAWPARTITION);
ee5681fe
MK
110 specname = np;
111 np += strlen(specname) + 1;
112 } else
113 specname = dkname;
114 f = open(specname, op == READ ? O_RDONLY : O_RDWR);
115 if (f < 0 && errno == ENOENT && dkname[0] != '/') {
116 sprintf(specname, "/dev/r%s", dkname);
117 np = namebuf + strlen(specname) + 1;
118 f = open(specname, op == READ ? O_RDONLY : O_RDWR);
119 }
120 if (f < 0)
121 Perror(specname);
122
12c6e49c 123 switch(op) {
ee5681fe 124 case EDIT:
12c6e49c
KB
125 if (argc != 1)
126 usage();
ee5681fe 127 lp = readlabel(f, bootarea);
12c6e49c
KB
128 if (edit(lp))
129 writelabel(f, bootarea, lp);
ee5681fe 130 break;
12c6e49c
KB
131 case READ:
132 if (argc != 1)
133 usage();
134 lp = readlabel(f, (char *)0);
135 display(stdout, lp);
136 (void) checklabel(lp);
ee5681fe 137 break;
ee5681fe 138 case RESTORE:
12c6e49c
KB
139#ifdef BOOT
140 if (argc == 4) {
141 xxboot = argv[2];
142 bootxx = argv[3];
143 }
144 else
145#else
146 if (argc != 2)
147 usage();
148#endif
ee5681fe
MK
149 lab.d_secsize = DEV_BSIZE; /* XXX */
150 lab.d_bbsize = BBSIZE; /* XXX */
151 lp = getbootarea(bootarea, &lab);
12c6e49c
KB
152 if (!(t = fopen(argv[1],"r")))
153 Perror(argv[1]);
88b9be0b
MK
154#ifdef BOOT
155 rflag = 1; /* force bootstrap to be written */
156#endif
12c6e49c
KB
157 if (getasciilabel(t, lp))
158 writelabel(f, bootarea, lp);
159 break;
160 case WRITE:
161 type = argv[1];
162#ifdef BOOT
163 if (argc > 5 || argc < 2)
164 usage();
165 if (argc > 3) {
166 bootxx = argv[--argc];
167 xxboot = argv[--argc];
168 }
169#else
12c6e49c 170 if (argc > 3 || argc < 2)
12c6e49c
KB
171 usage();
172#endif
173 if (argc > 2)
174 name = argv[--argc];
175 makelabel(type, name, &lab);
176 lp = getbootarea(bootarea, &lab);
177 *lp = lab;
88b9be0b
MK
178#ifdef BOOT
179 rflag = 1; /* force bootstrap to be written */
180#endif
12c6e49c
KB
181 if (checklabel(lp) == 0)
182 writelabel(f, bootarea, lp);
ee5681fe
MK
183 break;
184 }
185 exit(0);
186}
187
188makelabel(type, name, lp)
189 char *type, *name;
190 register struct disklabel *lp;
191{
192 register struct disklabel *dp;
ee5681fe
MK
193
194 dp = getdiskbyname(type);
195 if (dp == NULL) {
196 fprintf(stderr, "%s: unknown disk type\n", type);
197 exit(1);
198 }
199 *lp = *dp;
200 if (name)
12c6e49c 201 (void)strncpy(lp->d_name, name, sizeof(lp->d_name));
ee5681fe
MK
202}
203
204writelabel(f, boot, lp)
205 int f;
206 char *boot;
207 register struct disklabel *lp;
208{
12c6e49c
KB
209 register int i;
210 long lseek();
ee5681fe
MK
211
212 lp->d_magic = DISKMAGIC;
213 lp->d_magic2 = DISKMAGIC;
ee5681fe
MK
214 lp->d_checksum = 0;
215 lp->d_checksum = dkcksum(lp);
12c6e49c 216 (void)lseek(f, (off_t)0, L_SET);
452bf484
MK
217 if (rflag) {
218 if (write(f, boot, lp->d_bbsize) < lp->d_bbsize)
219 Perror("write");
220 if (ioctl(f, DIOCSDINFO, lp) < 0)
221 Perror("ioctl DIOCSDINFO");
222 } else if (ioctl(f, DIOCWDINFO, lp) < 0)
223 Perror("ioctl DIOCWDINFO");
1268bb93 224#if vax
452bf484
MK
225 if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) {
226 daddr_t alt;
227
228 alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
229 for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
12c6e49c 230 (void)lseek(f, (off_t)((alt + i) * lp->d_secsize), L_SET);
452bf484
MK
231 if (write(f, boot, lp->d_secsize) < lp->d_secsize) {
232 int oerrno = errno;
233 fprintf(stderr, "alternate label %d ", i/2);
234 errno = oerrno;
235 perror("write");
236 }
ee5681fe
MK
237 }
238 }
1268bb93 239#endif
ee5681fe
MK
240}
241
242/*
243 * Read disklabel from disk.
244 * If boot is given, need bootstrap too.
452bf484
MK
245 * If boot not needed, use ioctl to get label
246 * unless -r flag is given.
ee5681fe
MK
247 */
248struct disklabel *
249readlabel(f, boot)
250 int f;
251 char *boot;
252{
253 register struct disklabel *lp;
452bf484 254 register char *buf;
ee5681fe 255
452bf484
MK
256 if (boot)
257 buf = boot;
258 else
259 buf = bootarea;
260 lp = (struct disklabel *)(buf + LABELOFFSET);
88b9be0b
MK
261 if (boot || rflag)
262 if (read(f, buf, BBSIZE) < BBSIZE)
263 Perror(specname);
264 if (rflag == 0) {
452bf484
MK
265 if (ioctl(f, DIOCGDINFO, lp) < 0)
266 Perror("ioctl DIOCGDINFO");
267 } else {
452bf484
MK
268 for (lp = (struct disklabel *)buf;
269 lp <= (struct disklabel *)(buf + BBSIZE - sizeof(*lp));
270 lp = (struct disklabel *)((char *)lp + 16))
271 if (lp->d_magic == DISKMAGIC &&
272 lp->d_magic2 == DISKMAGIC)
273 break;
274 if (lp > (struct disklabel *)(buf + BBSIZE - sizeof(*lp)) ||
275 lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC ||
276 dkcksum(lp) != 0) {
277 fprintf(stderr,
ee5681fe 278 "Bad pack magic number (label is damaged, or pack is unlabeled)\n");
452bf484
MK
279 exit(1);
280 }
ee5681fe 281 }
ee5681fe
MK
282 return (lp);
283}
284
285struct disklabel *
286getbootarea(boot, dp)
287 char *boot;
288 register struct disklabel *dp;
289{
290 struct disklabel *lp;
291 register char *p;
292 int b;
293
294#ifdef BOOT
12c6e49c
KB
295 char *dkbasename;
296
ee5681fe
MK
297 if (xxboot == NULL) {
298 dkbasename = np;
299 if ((p = rindex(dkname, '/')) == NULL)
300 p = dkname;
301 else
302 p++;
303 while (*p && !isdigit(*p))
304 *np++ = *p++;
305 *np++ = '\0';
306
307 sprintf(np, "%s/%sboot", BOOTDIR, dkbasename);
308 if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
309 dkbasename++;
310 xxboot = np;
311 sprintf(xxboot, "%s/%sboot", BOOTDIR, dkbasename);
312 np += strlen(xxboot) + 1;
313
314 bootxx = np;
315 sprintf(bootxx, "%s/boot%s", BOOTDIR, dkbasename);
316 np += strlen(bootxx) + 1;
317 }
318
319 b = open(xxboot, O_RDONLY);
320 if (b < 0)
321 Perror(xxboot);
12c6e49c 322 if (read(b, boot, (int)dp->d_secsize) < 0)
ee5681fe
MK
323 Perror(xxboot);
324 close(b);
325 b = open(bootxx, O_RDONLY);
326 if (b < 0)
327 Perror(bootxx);
12c6e49c 328 if (read(b, &boot[dp->d_secsize], (int)(dp->d_bbsize-dp->d_secsize)) < 0)
ee5681fe 329 Perror(bootxx);
12c6e49c 330 (void)close(b);
ee5681fe
MK
331#endif
332
333 lp = (struct disklabel *)(boot + (LABELSECTOR * dp->d_secsize) +
334 LABELOFFSET);
335 for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++)
336 if (*p) {
337 fprintf(stderr,
338 "Bootstrap doesn't leave room for disk label\n");
339 exit(2);
340 }
341 return (lp);
342}
343
344display(f, lp)
345 FILE *f;
346 register struct disklabel *lp;
347{
12c6e49c 348 register int i, j;
ee5681fe
MK
349 register struct partition *pp;
350
351 fprintf(f, "# %s:\n", specname);
352 if ((unsigned) lp->d_type < DKMAXTYPES)
353 fprintf(f, "type: %s\n", dktypenames[lp->d_type]);
354 else
355 fprintf(f, "type: %d\n", lp->d_type);
356 fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename);
357 fprintf(f, "label: %.*s\n", sizeof(lp->d_name), lp->d_name);
88b9be0b 358 fprintf(f, "flags:");
ee5681fe 359 if (lp->d_flags & D_REMOVABLE)
88b9be0b 360 fprintf(f, " removeable");
ee5681fe 361 if (lp->d_flags & D_ECC)
88b9be0b 362 fprintf(f, " ecc");
ee5681fe 363 if (lp->d_flags & D_BADSECT)
88b9be0b 364 fprintf(f, " badsect");
ee5681fe
MK
365 fprintf(f, "\n");
366 fprintf(f, "bytes/sector: %d\n", lp->d_secsize);
367 fprintf(f, "sectors/track: %d\n", lp->d_nsectors);
368 fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks);
c6e761b2 369 fprintf(f, "sectors/cylinder: %d\n", lp->d_secpercyl);
ee5681fe 370 fprintf(f, "cylinders: %d\n", lp->d_ncylinders);
12c6e49c 371 fprintf(f, "rpm: %d\n", lp->d_rpm);
ee5681fe
MK
372 fprintf(f, "interleave: %d\n", lp->d_interleave);
373 fprintf(f, "trackskew: %d\n", lp->d_trackskew);
374 fprintf(f, "cylinderskew: %d\n", lp->d_cylskew);
375 fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch);
376 fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek);
377 fprintf(f, "drivedata: ");
378 for (i = NDDATA - 1; i >= 0; i--)
379 if (lp->d_drivedata[i])
380 break;
381 if (i < 0)
382 i = 0;
383 for (j = 0; j <= i; j++)
384 fprintf(f, "%d ", lp->d_drivedata[j]);
385 fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions);
9e0e871b
MK
386 fprintf(f,
387 "# size offset fstype [fsize bsize cpg]\n");
ee5681fe
MK
388 pp = lp->d_partitions;
389 for (i = 0; i < lp->d_npartitions; i++, pp++) {
ee5681fe 390 if (pp->p_size) {
9e0e871b
MK
391 fprintf(f, " %c: %8d %8d ", 'a' + i,
392 pp->p_size, pp->p_offset);
ee5681fe
MK
393 if ((unsigned) pp->p_fstype < FSMAXTYPES)
394 fprintf(f, "%8.8s", fstypenames[pp->p_fstype]);
395 else
396 fprintf(f, "%8d", pp->p_fstype);
9e0e871b
MK
397 switch (pp->p_fstype) {
398
399 case FS_UNUSED: /* XXX */
400 fprintf(f, " %5d %5d %5.5s ",
401 pp->p_fsize, pp->p_fsize * pp->p_frag, "");
402 break;
403
404 case FS_BSDFFS:
405 fprintf(f, " %5d %5d %5d ",
406 pp->p_fsize, pp->p_fsize * pp->p_frag,
407 pp->p_cpg);
408 break;
409
410 default:
411 fprintf(f, "%20.20s", "");
412 break;
413 }
ee5681fe
MK
414 fprintf(f, "\t# (Cyl. %4d",
415 pp->p_offset / lp->d_secpercyl);
416 if (pp->p_offset % lp->d_secpercyl)
417 putc('*', f);
418 else
419 putc(' ', f);
420 fprintf(f, "- %d",
421 (pp->p_offset +
422 pp->p_size + lp->d_secpercyl - 1) /
423 lp->d_secpercyl - 1);
424 if (pp->p_size % lp->d_secpercyl)
425 putc('*', f);
9e0e871b 426 fprintf(f, ")\n");
ee5681fe 427 }
ee5681fe
MK
428 }
429}
430
12c6e49c
KB
431edit(lp)
432 struct disklabel *lp;
ee5681fe 433{
12c6e49c
KB
434 register int c;
435 struct disklabel label;
436 FILE *fd;
437 char *mktemp();
438
439 (void) mktemp(tmpfil);
440 fd = fopen(tmpfil, "w");
441 if (fd == NULL) {
442 fprintf(stderr, "%s: Can't create\n", tmpfil);
443 return (0);
444 }
445 (void)fchmod(fd, 0600);
446 display(fd, lp);
447 fclose(fd);
448 for (;;) {
449 if (!editit())
450 break;
451 fd = fopen(tmpfil, "r");
452 if (fd == NULL) {
453 fprintf(stderr, "%s: Can't reopen for reading\n");
454 break;
455 }
9e0e871b 456 bzero((char *)&label, sizeof(label));
12c6e49c
KB
457 if (getasciilabel(fd, &label)) {
458 *lp = label;
459 (void) unlink(tmpfil);
460 return (1);
461 }
462 printf("re-edit the label? [y]: "); fflush(stdout);
463 c = getchar();
464 if (c != EOF && c != (int)'\n')
465 while (getchar() != (int)'\n')
466 ;
467 if (c == (int)'n')
468 break;
469 }
470 (void) unlink(tmpfil);
471 return (0);
ee5681fe
MK
472}
473
12c6e49c
KB
474editit()
475{
476 register int pid, xpid;
477 int stat, omask;
478 extern char *getenv();
479
480 omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
481 while ((pid = fork()) < 0) {
482 extern int errno;
483
484 if (errno == EPROCLIM) {
485 fprintf(stderr, "You have too many processes\n");
486 return(0);
487 }
488 if (errno != EAGAIN) {
489 perror("fork");
490 return(0);
491 }
492 sleep(1);
493 }
494 if (pid == 0) {
495 register char *ed;
496
497 sigsetmask(omask);
498 setgid(getgid());
499 setuid(getuid());
500 if ((ed = getenv("EDITOR")) == (char *)0)
501 ed = DEFEDITOR;
502 execlp(ed, ed, tmpfil, 0);
503 perror(ed);
504 exit(1);
505 }
506 while ((xpid = wait(&stat)) >= 0)
507 if (xpid == pid)
508 break;
509 sigsetmask(omask);
510 return(!stat);
511}
512
513char *
514skip(cp)
515 register char *cp;
516{
517
518 while (*cp != '\0' && isspace(*cp))
519 cp++;
520 if (*cp == '\0' || *cp == '#')
521 return ((char *)NULL);
522 return (cp);
523}
524
525char *
526word(cp)
527 register char *cp;
528{
529 register char c;
530
88b9be0b
MK
531 while (*cp != '\0' && !isspace(*cp) && *cp != '#')
532 cp++;
12c6e49c
KB
533 if ((c = *cp) != '\0') {
534 *cp++ = '\0';
535 if (c != '#')
536 return (skip(cp));
537 }
538 return ((char *)NULL);
539}
ee5681fe
MK
540
541/*
542 * Read an ascii label in from fd f,
543 * in the same format as that put out by display(),
544 * and fill in lp.
545 */
546getasciilabel(f, lp)
12c6e49c 547 FILE *f;
ee5681fe
MK
548 register struct disklabel *lp;
549{
12c6e49c 550 register char **cpp, *cp;
9e0e871b 551 register struct partition *pp;
12c6e49c
KB
552 char *tp, *s, line[BUFSIZ];
553 int v, lineno = 0, errors = 0;
554
555 lp->d_bbsize = BBSIZE; /* XXX */
556 lp->d_sbsize = SBSIZE; /* XXX */
557 while (fgets(line, sizeof(line) - 1, f)) {
558 lineno++;
559 if (cp = index(line,'\n'))
560 *cp = '\0';
561 cp = skip(line);
562 if (cp == NULL)
563 continue;
564 tp = index(cp, ':');
565 if (tp == NULL) {
566 fprintf(stderr, "line %d: syntax error\n", lineno);
567 errors++;
568 continue;
569 }
570 *tp++ = '\0', tp = skip(tp);
571 if (streq(cp, "type")) {
572 if (tp == NULL)
573 tp = "unknown";
574 cpp = dktypenames;
575 for (; cpp < &dktypenames[DKMAXTYPES]; cpp++)
576 if ((s = *cpp) && streq(s, tp)) {
577 lp->d_type = cpp - dktypenames;
578 goto next;
579 }
580 v = atoi(tp);
581 if ((unsigned)v >= DKMAXTYPES)
582 fprintf(stderr, "line %d:%s %d\n", lineno,
583 "Warning, unknown disk type", v);
584 lp->d_type = v;
585 continue;
586 }
587 if (streq(cp, "flags")) {
c6e761b2 588 for (v = 0; (cp = tp) && *cp != '\0'; tp = word(cp)) {
12c6e49c
KB
589 if (streq(cp, "removeable"))
590 v |= D_REMOVABLE;
591 else if (streq(cp, "ecc"))
592 v |= D_ECC;
593 else if (streq(cp, "badsect"))
594 v |= D_BADSECT;
595 else {
596 fprintf(stderr,
597 "line %d: %s: bad flag\n",
598 lineno, cp);
599 errors++;
600 }
601 }
602 lp->d_flags = v;
603 continue;
604 }
605 if (streq(cp, "drivedata")) {
606 register int i;
607
c6e761b2 608 for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) {
12c6e49c 609 lp->d_drivedata[i++] = atoi(cp);
c6e761b2 610 tp = word(cp);
12c6e49c
KB
611 }
612 continue;
613 }
614 if (sscanf(cp, "%d partitions", &v) == 1) {
9e0e871b 615 if (v == 0 || (unsigned)v > MAXPARTITIONS) {
12c6e49c
KB
616 fprintf(stderr,
617 "line %d: bad # of partitions\n", lineno);
9e0e871b
MK
618 lp->d_npartitions = MAXPARTITIONS;
619 errors++;
620 } else
12c6e49c
KB
621 lp->d_npartitions = v;
622 continue;
623 }
624 if (tp == NULL)
625 tp = "";
626 if (streq(cp, "disk")) {
627 strncpy(lp->d_typename, tp, sizeof (lp->d_typename));
628 continue;
629 }
630 if (streq(cp, "label")) {
631 strncpy(lp->d_name, tp, sizeof (lp->d_name));
632 continue;
633 }
634 if (streq(cp, "bytes/sector")) {
635 v = atoi(tp);
636 if (v <= 0 || (v % 512) != 0) {
637 fprintf(stderr,
638 "line %d: %s: bad sector size\n",
639 lineno, tp);
640 errors++;
641 } else
642 lp->d_secsize = v;
643 continue;
644 }
645 if (streq(cp, "sectors/track")) {
646 v = atoi(tp);
647 if (v <= 0) {
648 fprintf(stderr, "line %d: %s: bad %s\n",
649 lineno, tp, cp);
650 errors++;
651 } else
652 lp->d_nsectors = v;
653 continue;
654 }
c6e761b2
MK
655 if (streq(cp, "sectors/cylinder")) {
656 v = atoi(tp);
657 if (v <= 0) {
658 fprintf(stderr, "line %d: %s: bad %s\n",
659 lineno, tp, cp);
660 errors++;
661 } else
662 lp->d_secpercyl = v;
663 continue;
664 }
12c6e49c
KB
665 if (streq(cp, "tracks/cylinder")) {
666 v = atoi(tp);
667 if (v <= 0) {
668 fprintf(stderr, "line %d: %s: bad %s\n",
669 lineno, tp, cp);
670 errors++;
671 } else
672 lp->d_ntracks = v;
673 continue;
674 }
675 if (streq(cp, "cylinders")) {
676 v = atoi(tp);
677 if (v <= 0) {
678 fprintf(stderr, "line %d: %s: bad %s\n",
679 lineno, tp, cp);
680 errors++;
681 } else
682 lp->d_ncylinders = v;
683 continue;
684 }
685 if (streq(cp, "rpm")) {
686 v = atoi(tp);
687 if (v <= 0) {
688 fprintf(stderr, "line %d: %s: bad %s\n",
689 lineno, tp, cp);
690 errors++;
691 } else
692 lp->d_rpm = v;
693 continue;
694 }
695 if (streq(cp, "interleave")) {
696 v = atoi(tp);
697 if (v <= 0) {
698 fprintf(stderr, "line %d: %s: bad %s\n",
699 lineno, tp, cp);
700 errors++;
701 } else
702 lp->d_interleave = v;
703 continue;
704 }
705 if (streq(cp, "trackskew")) {
706 v = atoi(tp);
707 if (v < 0) {
708 fprintf(stderr, "line %d: %s: bad %s\n",
709 lineno, tp, cp);
710 errors++;
711 } else
712 lp->d_trackskew = v;
713 continue;
714 }
715 if (streq(cp, "cylinderskew")) {
716 v = atoi(tp);
717 if (v < 0) {
718 fprintf(stderr, "line %d: %s: bad %s\n",
719 lineno, tp, cp);
720 errors++;
721 } else
722 lp->d_cylskew = v;
723 continue;
724 }
725 if (streq(cp, "headswitch")) {
726 v = atoi(tp);
727 if (v < 0) {
728 fprintf(stderr, "line %d: %s: bad %s\n",
729 lineno, tp, cp);
730 errors++;
731 } else
732 lp->d_headswitch = v;
733 continue;
734 }
735 if (streq(cp, "track-to-track seek")) {
736 v = atoi(tp);
737 if (v < 0) {
738 fprintf(stderr, "line %d: %s: bad %s\n",
739 lineno, tp, cp);
740 errors++;
741 } else
742 lp->d_trkseek = v;
743 continue;
744 }
745 if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') {
9e0e871b 746 unsigned part = *cp - 'a';
12c6e49c 747
9e0e871b 748 if (part > lp->d_npartitions) {
12c6e49c
KB
749 fprintf(stderr,
750 "line %d: bad partition name\n", lineno);
751 errors++;
752 continue;
753 }
9e0e871b
MK
754 pp = &lp->d_partitions[part];
755#define NXTNUM(n) { \
756 cp = tp, tp = word(cp); \
757 if (tp == NULL) \
758 tp = cp; \
759 (n) = atoi(cp); \
760 }
761
762 NXTNUM(v);
12c6e49c
KB
763 if (v < 0) {
764 fprintf(stderr,
765 "line %d: %s: bad partition size\n",
766 lineno, cp);
767 errors++;
768 } else
9e0e871b
MK
769 pp->p_size = v;
770 NXTNUM(v);
12c6e49c
KB
771 if (v < 0) {
772 fprintf(stderr,
773 "line %d: %s: bad partition offset\n",
774 lineno, cp);
775 errors++;
776 } else
9e0e871b 777 pp->p_offset = v;
12c6e49c
KB
778 cp = tp, tp = word(cp);
779 cpp = fstypenames;
780 for (; cpp < &fstypenames[FSMAXTYPES]; cpp++)
781 if ((s = *cpp) && streq(s, cp)) {
9e0e871b
MK
782 pp->p_fstype = cpp - fstypenames;
783 goto gottype;
12c6e49c
KB
784 }
785 v = atoi(cp);
786 if ((unsigned)v >= FSMAXTYPES)
787 fprintf(stderr, "line %d: %s %s\n", lineno,
788 "Warning, unknown filesystem type", cp);
9e0e871b
MK
789 pp->p_fstype = v;
790 gottype:
791
792 switch (pp->p_fstype) {
793
794 case FS_UNUSED: /* XXX */
795 NXTNUM(pp->p_fsize);
796 if (pp->p_fsize == 0)
797 break;
798 NXTNUM(v);
799 pp->p_frag = v / pp->p_fsize;
800 break;
801
802 case FS_BSDFFS:
803 NXTNUM(pp->p_fsize);
804 if (pp->p_fsize == 0)
805 break;
806 NXTNUM(v);
807 pp->p_frag = v / pp->p_fsize;
808 NXTNUM(pp->p_cpg);
809 break;
810
811 default:
812 break;
813 }
12c6e49c
KB
814 continue;
815 }
816 fprintf(stderr, "line %d: %s: Unknown disklabel field\n",
817 lineno, cp);
818 errors++;
819 next:
820 ;
821 }
822 errors += checklabel(lp);
823 return (errors == 0);
824}
825
826/*
827 * Check disklabel for errors and fill in
828 * derived fields according to supplied values.
829 */
830checklabel(lp)
831 register struct disklabel *lp;
832{
833 register struct partition *pp;
834 int i, errors = 0;
835 char part;
836
837 if (lp->d_secsize == 0) {
838 fprintf(stderr, "sector size %d\n", lp->d_secsize);
839 return (1);
840 }
841 if (lp->d_nsectors == 0) {
842 fprintf(stderr, "sectors/track %d\n", lp->d_nsectors);
843 return (1);
844 }
845 if (lp->d_ntracks == 0) {
846 fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks);
847 return (1);
848 }
849 if (lp->d_ncylinders == 0) {
850 fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders);
851 errors++;
852 }
853 if (lp->d_rpm == 0)
854 Warning("revolutions/minute %d\n", lp->d_rpm);
855 if (lp->d_secpercyl == 0)
856 lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
857 if (lp->d_secperunit == 0)
858 lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders;
859 if (lp->d_bbsize == 0) {
860 fprintf(stderr, "boot block size %d\n", lp->d_bbsize);
861 errors++;
862 } else if (lp->d_bbsize % lp->d_secsize)
863 Warning("boot block size %% sector-size != 0\n");
864 if (lp->d_sbsize == 0) {
865 fprintf(stderr, "super block size %d\n", lp->d_sbsize);
866 errors++;
867 } else if (lp->d_sbsize % lp->d_secsize)
868 Warning("super block size %% sector-size != 0\n");
869 if (lp->d_npartitions > MAXPARTITIONS)
870 Warning("number of partitions (%d) > MAXPARTITIONS (%d)\n",
871 lp->d_npartitions, MAXPARTITIONS);
872 for (i = 0; i < lp->d_npartitions; i++) {
873 part = 'a' + i;
874 pp = &lp->d_partitions[i];
875 if (pp->p_size == 0 && pp->p_offset != 0)
876 Warning("partition %c: size 0, but offset %d\n",
877 part, pp->p_offset);
878#ifdef notdef
879 if (pp->p_size % lp->d_secpercyl)
880 Warning("partition %c: size %% cylinder-size != 0\n",
881 part);
882 if (pp->p_offset % lp->d_secpercyl)
883 Warning("partition %c: offset %% cylinder-size != 0\n",
884 part);
885#endif
886 if (pp->p_offset > lp->d_secperunit) {
887 fprintf(stderr,
888 "partition %c: offset past end of unit\n", part);
889 errors++;
890 }
891 if (pp->p_offset + pp->p_size > lp->d_secperunit) {
892 fprintf(stderr,
893 "partition %c: partition extends past end of unit\n",
894 part);
895 errors++;
896 }
897 }
898 for (; i < MAXPARTITIONS; i++) {
899 part = 'a' + i;
900 pp = &lp->d_partitions[i];
901 if (pp->p_size || pp->p_offset)
902 Warning("unused partition %c: size %d offset %d\n",
903 pp->p_size, pp->p_offset);
904 }
905 return (errors);
ee5681fe
MK
906}
907
12c6e49c
KB
908/*VARARGS1*/
909Warning(fmt, a1, a2, a3, a4, a5)
910 char *fmt;
ee5681fe
MK
911{
912
12c6e49c
KB
913 fprintf(stderr, "Warning, ");
914 fprintf(stderr, fmt, a1, a2, a3, a4, a5);
915 fprintf(stderr, "\n");
916}
917
918Perror(str)
919 char *str;
920{
921 fputs("disklabel: ", stderr); perror(str);
ee5681fe
MK
922 exit(4);
923}
12c6e49c
KB
924
925usage()
926{
927#ifdef BOOT
928 fprintf(stderr, "%-64s%s\n%-64s%s\n%-64s%s\n%-64s%s\n",
929"usage: disklabel [-r] disk", "(to read label)",
930"or disklabel -w [-r] disk type [ packid ] [ xxboot bootxx ]", "(to write label)",
931"or disklabel -e [-r] disk", "(to edit label)",
932"or disklabel -R [-r] disk protofile [ xxboot bootxx ]", "(to restore label)");
933#else
934 fprintf(stderr, "%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n",
935"usage: disklabel [-r] disk", "(to read label)",
936"or disklabel -w [-r] disk type [ packid ]", "(to write label)",
937"or disklabel -e [-r] disk", "(to edit label)",
938"or disklabel -R [-r] disk protofile", "(to restore label)");
939#endif
940 exit(1);
941}