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