+ }
+ sync(); /* ??? */
+}
+
+setup(dev)
+ char *dev;
+{
+ dev_t rootdev;
+ struct stat statb;
+ int super = bflag ? bflag : SBLOCK;
+ int i, j, size;
+ int c, d, cgd;
+
+ bflag = 0;
+ if (stat("/", &statb) < 0)
+ errexit("Can't stat root\n");
+ rootdev = statb.st_dev;
+ if (stat(dev, &statb) < 0) {
+ error("Can't stat %s\n", dev);
+ return (0);
+ }
+ rawflg = 0;
+ if ((statb.st_mode & S_IFMT) == S_IFBLK)
+ ;
+ else if ((statb.st_mode & S_IFMT) == S_IFCHR)
+ rawflg++;
+ else {
+ if (reply("file is not a block or character device; OK") == 0)
+ return (0);
+ }
+ if (rootdev == statb.st_rdev)
+ hotroot++;
+ if ((dfile.rfdes = open(dev, 0)) < 0) {
+ error("Can't open %s\n", dev);
+ return (0);
+ }
+ if (preen == 0)
+ printf("** %s", dev);
+ if (nflag || (dfile.wfdes = open(dev, 1)) < 0) {
+ dfile.wfdes = -1;
+ if (preen)
+ pfatal("NO WRITE ACCESS");
+ printf(" (NO WRITE)");
+ }
+ if (preen == 0)
+ printf("\n");
+ fixcg = 0; inosumbad = 0; offsumbad = 0; frsumbad = 0; sbsumbad = 0;
+ dfile.mod = 0;
+ n_files = n_blks = n_ffree = n_bfree = 0;
+ muldup = enddup = &duplist[0];
+ badlnp = &badlncnt[0];
+ lfdir = 0;
+ rplyflag = 0;
+ initbarea(&sblk);
+ initbarea(&fileblk);
+ initbarea(&inoblk);
+ initbarea(&cgblk);
+ /*
+ * Read in the super block and its summary info.
+ */
+ if (bread(&dfile, &sblock, super, SBSIZE) == 0)
+ return (0);
+ sblk.b_bno = super;
+ sblk.b_size = SBSIZE;
+ /*
+ * run a few consistency checks of the super block
+ */
+ if (sblock.fs_magic != FS_MAGIC)
+ { badsb("MAGIC NUMBER WRONG"); return (0); }
+ if (sblock.fs_ncg < 1)
+ { badsb("NCG OUT OF RANGE"); return (0); }
+ if (sblock.fs_cpg < 1 || sblock.fs_cpg > MAXCPG)
+ { badsb("CPG OUT OF RANGE"); return (0); }
+ if (sblock.fs_nsect < 1)
+ { badsb("NSECT < 1"); return (0); }
+ if (sblock.fs_ntrak < 1)
+ { badsb("NTRAK < 1"); return (0); }
+ if (sblock.fs_spc != sblock.fs_nsect * sblock.fs_ntrak)
+ { badsb("SPC DOES NOT JIVE w/NTRAK*NSECT"); return (0); }
+ if (sblock.fs_ipg % INOPB(&sblock))
+ { badsb("INODES NOT MULTIPLE OF A BLOCK"); return (0); }
+ if (cgdmin(&sblock, 0) >= sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock))
+ { badsb("IMPLIES MORE INODE THAN DATA BLOCKS"); return (0); }
+ if (sblock.fs_ncg * sblock.fs_cpg < sblock.fs_ncyl ||
+ (sblock.fs_ncg - 1) * sblock.fs_cpg >= sblock.fs_ncyl)
+ { badsb("NCYL DOES NOT JIVE WITH NCG*CPG"); return (0); }
+ if (sblock.fs_fpg != sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock))
+ { badsb("FPG DOES NOT JIVE WITH CPG & SPC"); return (0); }
+ if (sblock.fs_size * NSPF(&sblock) <=
+ (sblock.fs_ncyl - 1) * sblock.fs_spc)
+ { badsb("SIZE PREPOSTEROUSLY SMALL"); return (0); }
+ if (sblock.fs_size * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc)
+ { badsb("SIZE PREPOSTEROUSLY LARGE"); return (0); }
+ /* rest we COULD repair... */
+ if (sblock.fs_cgsize != fragroundup(&sblock,
+ sizeof(struct cg) + howmany(sblock.fs_fpg, NBBY)))
+ { badsb("CGSIZE INCORRECT"); return (0); }
+ if (sblock.fs_cssize !=
+ fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum)))
+ { badsb("CSSIZE INCORRECT"); return (0); }
+ fmax = sblock.fs_size;
+ imax = sblock.fs_ncg * sblock.fs_ipg;
+ n_bad = cgsblock(&sblock, 0); /* boot block plus dedicated sblock */
+ /*
+ * read in the summary info.
+ */
+ for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
+ size = sblock.fs_cssize - i < sblock.fs_bsize ?
+ sblock.fs_cssize - i : sblock.fs_bsize;
+ sblock.fs_csp[j] = (struct csum *)calloc(1, size);
+ bread(&dfile, (char *)sblock.fs_csp[j],
+ fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
+ size);
+ }
+ /*
+ * allocate and initialize the necessary maps
+ */
+ bmapsz = roundup(howmany(fmax, NBBY), sizeof(short));
+ blockmap = (char *)calloc(bmapsz, sizeof (char));
+ if (blockmap == NULL) {
+ printf("cannot alloc %d bytes for blockmap\n", bmapsz);
+ exit(1);
+ }
+ freemap = (char *)calloc(bmapsz, sizeof (char));
+ if (freemap == NULL) {
+ printf("cannot alloc %d bytes for freemap\n", bmapsz);
+ exit(1);
+ }
+ statemap = (char *)calloc(imax+1, sizeof(char));
+ if (statemap == NULL) {
+ printf("cannot alloc %d bytes for statemap\n", imax + 1);
+ exit(1);
+ }
+ lncntp = (short *)calloc(imax+1, sizeof(short));
+ if (lncntp == NULL) {
+ printf("cannot alloc %d bytes for lncntp\n",
+ (imax + 1) * sizeof(short));
+ exit(1);
+ }
+ for (c = 0; c < sblock.fs_ncg; c++) {
+ cgd = cgdmin(&sblock, c);
+ if (c == 0) {
+ d = cgbase(&sblock, c);
+ cgd += howmany(sblock.fs_cssize, sblock.fs_fsize);
+ } else
+ d = cgsblock(&sblock, c);
+ for (; d < cgd; d++)
+ setbmap(d);
+ }
+
+ startinum = imax + 1;
+ return (1);
+
+badsb:
+ ckfini();
+ return (0);