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