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