+ pfatal("BAD SUPER BLOCK: %s\n", s);
+}
+
+/*
+ * Calculate a prototype superblock based on information in the disk label.
+ * When done the cgsblock macro can be calculated and the fs_ncg field
+ * can be used. Do NOT attempt to use other macros without verifying that
+ * their needed information is available!
+ */
+calcsb(dev, devfd, fs)
+ char *dev;
+ int devfd;
+ register struct fs *fs;
+{
+ register struct disklabel *lp;
+ register struct partition *pp;
+ register char *cp;
+ struct disklabel *getdisklabel();
+ int i;
+
+ cp = index(dev, '\0') - 1;
+ if (cp == (char *)-1 || (*cp < 'a' || *cp > 'h') && !isdigit(*cp)) {
+ pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev);
+ return (0);
+ }
+ lp = getdisklabel(dev, devfd);
+ if (isdigit(*cp))
+ pp = &lp->d_partitions[0];
+ else
+ pp = &lp->d_partitions[*cp - 'a'];
+ if (pp->p_fstype != FS_BSDFFS) {
+ pfatal("%s: NOT FORMATTED AS A BSD FILE SYSTEM (%s)\n",
+ dev, pp->p_fstype < FSMAXTYPES ?
+ fstypenames[pp->p_fstype] : "unknown");
+ return (0);
+ }
+ bzero(fs, sizeof(struct fs));
+ fs->fs_fsize = pp->p_fsize;
+ fs->fs_frag = pp->p_frag;
+ fs->fs_cpg = pp->p_cpg;
+ fs->fs_size = pp->p_size;
+ fs->fs_ntrak = lp->d_ntracks;
+ fs->fs_nsect = lp->d_nsectors;
+ fs->fs_spc = lp->d_secpercyl;
+ fs->fs_nspf = fs->fs_fsize / lp->d_secsize;
+ fs->fs_sblkno = roundup(
+ howmany(lp->d_bbsize + lp->d_sbsize, fs->fs_fsize),
+ fs->fs_frag);
+ fs->fs_cgmask = 0xffffffff;
+ for (i = fs->fs_ntrak; i > 1; i >>= 1)
+ fs->fs_cgmask <<= 1;
+ if (!POWEROF2(fs->fs_ntrak))
+ fs->fs_cgmask <<= 1;
+ fs->fs_cgoffset = roundup(
+ howmany(fs->fs_nsect, NSPF(fs)), fs->fs_frag);
+ fs->fs_fpg = (fs->fs_cpg * fs->fs_spc) / NSPF(fs);
+ fs->fs_ncg = howmany(fs->fs_size / fs->fs_spc, fs->fs_cpg);
+ for (fs->fs_fsbtodb = 0, i = NSPF(fs); i > 1; i >>= 1)
+ fs->fs_fsbtodb++;
+ return (1);
+}
+
+#ifdef byioctl
+struct disklabel *
+getdisklabel(s, fd)
+ char *s;
+ int fd;
+{
+ static struct disklabel lab;
+
+ if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) {
+ perror("ioctl (GDINFO)");
+ fatal("%s: can't read disk label", s);
+ }
+ return (&lab);
+}
+#else byioctl
+char specname[64];
+char boot[BBSIZE];
+
+struct disklabel *
+getdisklabel(s, fd)
+ char *s;
+ int fd;
+{
+ char *cp;
+ u_long magic = htonl(DISKMAGIC);
+ register struct disklabel *lp;
+ int cfd;
+
+ /*
+ * Make name for 'c' partition.
+ */
+ strcpy(specname, s);
+ cp = specname + strlen(specname) - 1;
+ if (!isdigit(*cp))
+ *cp = 'c';
+ cfd = open(specname, O_RDONLY);
+ if (cfd < 0) {
+ perror(specname);
+ exit(2);
+ }
+
+ if (read(cfd, boot, BBSIZE) < BBSIZE) {
+ perror(specname);
+ exit(2);
+ }
+ close(cfd);
+ for (lp = (struct disklabel *)(boot + LABELOFFSET);
+ lp <= (struct disklabel *)(boot + BBSIZE -
+ sizeof(struct disklabel));
+ lp = (struct disklabel *)((char *)lp + 128))
+ if (lp->d_magic == magic && lp->d_magic2 == magic)
+ break;
+ if (lp > (struct disklabel *)(boot + BBSIZE -
+ sizeof(struct disklabel)) ||
+ lp->d_magic != magic || lp->d_magic2 != magic ||
+ dkcksum(lp) != 0) {
+ printf("Bad pack magic number %s\n",
+ "(label is damaged, or pack is unlabeled)");
+ exit(1);
+ }
+#if ENDIAN != BIG
+ swablabel(lp);
+#endif
+ return (lp);