-
-setup(dev)
- char *dev;
-{
- dev_t rootdev;
- struct stat statb;
- daddr_t super = bflag ? bflag : SBLOCK;
- int i, j, c, d, cgd;
- long size;
- BUFAREA asblk;
-# define altsblock asblk.b_un.b_fs
-
- 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);
- initbarea(&asblk);
- /*
- * Read in the super block and its summary info.
- */
- if (bread(&dfile, (char *)&sblock, super, (long)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_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_sbsize > SBSIZE)
- { badsb("SIZE PREPOSTEROUSLY LARGE"); return (0); }
- /*
- * Set all possible fields that could differ, then do check
- * of whole super block against an alternate super block.
- * When an alternate super-block is specified this check is skipped.
- */
- if (bflag)
- goto sbok;
- if (getblk(&asblk, cgsblock(&sblock, sblock.fs_ncg - 1),
- sblock.fs_sbsize) == 0)
- return (0);
- altsblock.fs_link = sblock.fs_link;
- altsblock.fs_rlink = sblock.fs_rlink;
- altsblock.fs_time = sblock.fs_time;
- altsblock.fs_cstotal = sblock.fs_cstotal;
- altsblock.fs_cgrotor = sblock.fs_cgrotor;
- altsblock.fs_fmod = sblock.fs_fmod;
- altsblock.fs_clean = sblock.fs_clean;
- altsblock.fs_ronly = sblock.fs_ronly;
- altsblock.fs_flags = sblock.fs_flags;
- altsblock.fs_maxcontig = sblock.fs_maxcontig;
- altsblock.fs_minfree = sblock.fs_minfree;
- altsblock.fs_rotdelay = sblock.fs_rotdelay;
- altsblock.fs_maxbpg = sblock.fs_maxbpg;
- bcopy((char *)sblock.fs_csp, (char *)altsblock.fs_csp,
- sizeof sblock.fs_csp);
- bcopy((char *)sblock.fs_fsmnt, (char *)altsblock.fs_fsmnt,
- sizeof sblock.fs_fsmnt);
- if (bcmp((char *)&sblock, (char *)&altsblock, (int)sblock.fs_sbsize))
- { badsb("TRASHED VALUES IN SUPER BLOCK"); return (0); }
-sbok:
- 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, (unsigned)size);
- if (bread(&dfile, (char *)sblock.fs_csp[j],
- fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
- size) == 0)
- return (0);
- }
- /*
- * allocate and initialize the necessary maps
- */
- bmapsz = roundup(howmany(fmax, NBBY), sizeof(short));
- blockmap = calloc((unsigned)bmapsz, sizeof (char));
- if (blockmap == NULL) {
- printf("cannot alloc %d bytes for blockmap\n", bmapsz);
- goto badsb;
- }
- freemap = calloc((unsigned)bmapsz, sizeof (char));
- if (freemap == NULL) {
- printf("cannot alloc %d bytes for freemap\n", bmapsz);
- goto badsb;
- }
- statemap = calloc((unsigned)(imax + 1), sizeof(char));
- if (statemap == NULL) {
- printf("cannot alloc %d bytes for statemap\n", imax + 1);
- goto badsb;
- }
- lncntp = (short *)calloc((unsigned)(imax + 1), sizeof(short));
- if (lncntp == NULL) {
- printf("cannot alloc %d bytes for lncntp\n",
- (imax + 1) * sizeof(short));
- goto badsb;
- }
- 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);
- }
-
- return (1);
-
-badsb:
- ckfini();
- return (0);
-# undef altsblock
-}
-
-pass1()
-{
- register int c, i, n, j;
- register DINODE *dp;
- int ndb, partial;
- struct inodesc idesc;
- ino_t inumber;
-
- bzero((char *)&idesc, sizeof(struct inodesc));
- idesc.id_type = ADDR;
- idesc.id_func = pass1check;
- inumber = 0;
- n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
- for (c = 0; c < sblock.fs_ncg; c++) {
- if (getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize) == 0)
- continue;
- if (cgrp.cg_magic != CG_MAGIC) {
- pfatal("CG %d: BAD MAGIC NUMBER\n", c);
- bzero((char *)&cgrp, (int)sblock.fs_cgsize);
- }
- n = 0;
- for (i = 0; i < sblock.fs_ipg; i++, inumber++) {
- dp = ginode(inumber);
- if (dp == NULL)
- continue;
- n++;
- if (ALLOC) {
- if (!isset(cgrp.cg_iused, i)) {
- if (debug)
- printf("%d bad, not used\n",
- inumber);
- inosumbad++;
- }
- n--;
- lastino = inumber;
- if (!preen && BADBLK &&
- reply("HOLD BAD BLOCK") == 1) {
- dp->di_size = sblock.fs_fsize;
- dp->di_mode = IFREG|0600;
- inodirty();
- } else if (ftypeok(dp) == 0)
- goto unknown;
- if (dp->di_size < 0) {
- if (debug)
- printf("bad size %d:",
- dp->di_size);
- goto unknown;
- }
- ndb = howmany(dp->di_size, sblock.fs_bsize);
- if (SPECIAL)
- ndb++;
- for (j = ndb; j < NDADDR; j++)
- if (dp->di_db[j] != 0) {
- if (debug)
- printf("bad direct addr: %d\n",
- dp->di_db[j]);
- goto unknown;
- }
- for (j = 0, ndb -= NDADDR; ndb > 0; j++)
- ndb /= NINDIR(&sblock);
- for (; j < NIADDR; j++)
- if (dp->di_ib[j] != 0) {
- if (debug)
- printf("bad indirect addr: %d\n",
- dp->di_ib[j]);
- goto unknown;
- }
- n_files++;
- lncntp[inumber] = dp->di_nlink;
- if (dp->di_nlink <= 0) {
- if (badlnp < &badlncnt[MAXLNCNT])
- *badlnp++ = inumber;
- else {
- pfatal("LINK COUNT TABLE OVERFLOW");
- if (reply("CONTINUE") == 0)
- errexit("");
- }
- }
- statemap[inumber] = DIRCT ? DSTATE : FSTATE;
- badblk = dupblk = 0; maxblk = 0;
- idesc.id_number = inumber;
- idesc.id_filesize = 0;
- (void)ckinode(dp, &idesc);
- idesc.id_filesize *= btodb(sblock.fs_fsize);
- if (dp->di_blocks != idesc.id_filesize) {
- pwarn("INCORRECT BLOCK COUNT I=%u (%ld should be %ld)",
- inumber, dp->di_blocks,
- idesc.id_filesize);
- if (preen)
- printf(" (CORRECTED)\n");
- else if (reply("CORRECT") == 0)
- continue;
- dp->di_blocks = idesc.id_filesize;
- inodirty();
- }
- continue;
- unknown:
- pfatal("UNKNOWN FILE TYPE I=%u", inumber);
- if (reply("CLEAR") == 1) {
- zapino(dp);
- inodirty();
- inosumbad++;
- }
- } else {
- if (isset(cgrp.cg_iused, i)) {
- if (debug)
- printf("%d bad, marked used\n",
- inumber);
- inosumbad++;
- n--;
- }
- partial = 0;
- for (j = 0; j < NDADDR; j++)
- if (dp->di_db[j] != 0)
- partial++;
- for (j = 0; j < NIADDR; j++)
- if (dp->di_ib[j] != 0)
- partial++;
- if (partial || dp->di_mode != 0 ||
- dp->di_size != 0) {
- pfatal("PARTIALLY ALLOCATED INODE I=%u",
- inumber);
- if (reply("CLEAR") == 1) {
- zapino(dp);
- inodirty();
- inosumbad++;
- }
- }
- }
- }
- if (n != cgrp.cg_cs.cs_nifree) {
- if (debug)
- printf("cg[%d].cg_cs.cs_nifree is %d; calc %d\n",
- c, cgrp.cg_cs.cs_nifree, n);
- inosumbad++;
- }
- if (cgrp.cg_cs.cs_nbfree != sblock.fs_cs(&sblock, c).cs_nbfree
- || cgrp.cg_cs.cs_nffree != sblock.fs_cs(&sblock, c).cs_nffree
- || cgrp.cg_cs.cs_nifree != sblock.fs_cs(&sblock, c).cs_nifree
- || cgrp.cg_cs.cs_ndir != sblock.fs_cs(&sblock, c).cs_ndir)
- sbsumbad++;
- }
-}
-
-pass1check(idesc)
- register struct inodesc *idesc;
-{
- register daddr_t *dlp;
- int res = KEEPON;
- int anyout, nfrags;
- daddr_t blkno = idesc->id_blkno;
-
- anyout = outrange(blkno, idesc->id_numfrags);
- for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
- if (anyout && outrange(blkno, 1)) {
- blkerr(idesc->id_number, "BAD", blkno);
- if (++badblk >= MAXBAD) {
- pwarn("EXCESSIVE BAD BLKS I=%u",
- idesc->id_number);
- if (preen)
- printf(" (SKIPPING)\n");
- else if (reply("CONTINUE") == 0)
- errexit("");
- return (STOP);
- }
- res = SKIP;
- } else if (getbmap(blkno)) {
- blkerr(idesc->id_number, "DUP", blkno);
- if (++dupblk >= MAXDUP) {
- pwarn("EXCESSIVE DUP BLKS I=%u",
- idesc->id_number);
- if (preen)
- printf(" (SKIPPING)\n");
- else if (reply("CONTINUE") == 0)
- errexit("");
- return (STOP);
- }
- if (enddup >= &duplist[DUPTBLSIZE]) {
- pfatal("DUP TABLE OVERFLOW.");
- if (reply("CONTINUE") == 0)
- errexit("");
- return (STOP);
- }
- for (dlp = duplist; dlp < muldup; dlp++)
- if (*dlp == blkno) {
- *enddup++ = blkno;
- break;
- }
- if (dlp >= muldup) {
- *enddup++ = *muldup;
- *muldup++ = blkno;
- }
- } else {
- n_blks++;
- setbmap(blkno);
- }
- idesc->id_filesize++;
- }
- return (res);
-}
-
-pass1b()
-{
- register int c, i;
- register DINODE *dp;
- struct inodesc idesc;
- ino_t inumber;
-
- bzero((char *)&idesc, sizeof(struct inodesc));
- idesc.id_type = ADDR;
- idesc.id_func = pass1bcheck;
- inumber = 0;
- for (c = 0; c < sblock.fs_ncg; c++) {
- for (i = 0; i < sblock.fs_ipg; i++, inumber++) {
- dp = ginode(inumber);
- if (dp == NULL)
- continue;
- idesc.id_number = inumber;
- if (statemap[inumber] != USTATE &&
- (ckinode(dp, &idesc) & STOP))
- goto out1b;
- }
- }
-out1b:
- flush(&dfile, &inoblk);
-}
-
-pass1bcheck(idesc)
- register struct inodesc *idesc;
-{
- register daddr_t *dlp;
- int nfrags, res = KEEPON;
- daddr_t blkno = idesc->id_blkno;
-
- for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
- if (outrange(blkno, 1))
- res = SKIP;
- for (dlp = duplist; dlp < muldup; dlp++)
- if (*dlp == blkno) {
- blkerr(idesc->id_number, "DUP", blkno);
- *dlp = *--muldup;
- *muldup = blkno;
- if (muldup == duplist)
- return (STOP);
- }
- }
- return (res);
-}
-
-pass2()
-{
- register DINODE *dp;
- struct inodesc rootdesc;
-
- bzero((char *)&rootdesc, sizeof(struct inodesc));
- rootdesc.id_type = ADDR;
- rootdesc.id_func = pass2check;
- rootdesc.id_number = ROOTINO;
- pathp = pathname;
- switch (statemap[ROOTINO]) {
-
- case USTATE:
- errexit("ROOT INODE UNALLOCATED. TERMINATING.\n");
-
- case FSTATE:
- pfatal("ROOT INODE NOT DIRECTORY");
- if (reply("FIX") == 0 || (dp = ginode(ROOTINO)) == NULL)
- errexit("");
- dp->di_mode &= ~IFMT;
- dp->di_mode |= IFDIR;
- inodirty();
- inosumbad++;
- statemap[ROOTINO] = DSTATE;
- /* fall into ... */
-
- case DSTATE:
- descend(&rootdesc, ROOTINO);
- break;
-
- case CLEAR:
- pfatal("DUPS/BAD IN ROOT INODE");
- printf("\n");
- if (reply("CONTINUE") == 0)
- errexit("");
- statemap[ROOTINO] = DSTATE;
- descend(&rootdesc, ROOTINO);
- }
-}
-
-pass2check(idesc)
- struct inodesc *idesc;
-{
- register DIRECT *dirp = idesc->id_dirp;
- char *curpathloc;
- int n, entrysize, ret = 0;
- DINODE *dp;
- DIRECT proto;
-
- /*
- * check for "."
- */
- if (idesc->id_entryno != 0)
- goto chk1;
- if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") == 0) {
- if (dirp->d_ino != idesc->id_number) {
- direrr(idesc->id_number, "BAD INODE NUMBER FOR '.'");
- dirp->d_ino = idesc->id_number;
- if (reply("FIX") == 1)
- ret |= ALTERED;
- }
- goto chk1;
- }
- direrr(idesc->id_number, "MISSING '.'");
- proto.d_ino = idesc->id_number;
- proto.d_namlen = 1;
- (void)strcpy(proto.d_name, ".");
- entrysize = DIRSIZ(&proto);
- if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") != 0) {
- pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n",
- dirp->d_name);
- } else if (dirp->d_reclen < entrysize) {
- pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '.'\n");
- } else if (dirp->d_reclen < 2 * entrysize) {
- proto.d_reclen = dirp->d_reclen;
- bcopy((char *)&proto, (char *)dirp, entrysize);
- if (reply("FIX") == 1)
- ret |= ALTERED;
- } else {
- n = dirp->d_reclen - entrysize;
- proto.d_reclen = entrysize;
- bcopy((char *)&proto, (char *)dirp, entrysize);
- idesc->id_entryno++;
- lncntp[dirp->d_ino]--;
- dirp = (DIRECT *)((char *)(dirp) + entrysize);
- bzero((char *)dirp, n);
- dirp->d_reclen = n;
- if (reply("FIX") == 1)
- ret |= ALTERED;
- }
-chk1:
- if (idesc->id_entryno > 1)
- goto chk2;
- proto.d_ino = idesc->id_parent;
- proto.d_namlen = 2;
- (void)strcpy(proto.d_name, "..");
- entrysize = DIRSIZ(&proto);
- if (idesc->id_entryno == 0) {
- n = DIRSIZ(dirp);
- if (dirp->d_reclen < n + entrysize)
- goto chk2;
- proto.d_reclen = dirp->d_reclen - n;
- dirp->d_reclen = n;
- idesc->id_entryno++;
- lncntp[dirp->d_ino]--;
- dirp = (DIRECT *)((char *)(dirp) + n);
- bzero((char *)dirp, n);
- dirp->d_reclen = n;
- }
- if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") == 0) {
- if (dirp->d_ino != idesc->id_parent) {
- direrr(idesc->id_number, "BAD INODE NUMBER FOR '..'");
- dirp->d_ino = idesc->id_parent;
- if (reply("FIX") == 1)
- ret |= ALTERED;
- }
- goto chk2;
- }
- direrr(idesc->id_number, "MISSING '..'");
- if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") != 0) {
- pfatal("CANNOT FIX, SECOND ENTRY IN DIRECTORY CONTAINS %s\n",
- dirp->d_name);
- } else if (dirp->d_reclen < entrysize) {
- pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '..'\n");
- } else {
- proto.d_reclen = dirp->d_reclen;
- bcopy((char *)&proto, (char *)dirp, entrysize);
- if (reply("FIX") == 1)
- ret |= ALTERED;
- }
-chk2:
- if (dirp->d_ino == 0)
- return (ret|KEEPON);
- if (dirp->d_namlen <= 2 &&
- dirp->d_name[0] == '.' &&
- idesc->id_entryno >= 2) {
- if (dirp->d_namlen == 1) {
- direrr(idesc->id_number, "EXTRA '.' ENTRY");
- dirp->d_ino = 0;
- if (reply("FIX") == 1)
- ret |= ALTERED;
- return (KEEPON | ret);
- }
- if (dirp->d_name[1] == '.') {
- direrr(idesc->id_number, "EXTRA '..' ENTRY");
- dirp->d_ino = 0;
- if (reply("FIX") == 1)
- ret |= ALTERED;
- return (KEEPON | ret);
- }
- }
- curpathloc = pathp;
- *pathp++ = '/';
- if (pathp + dirp->d_namlen >= endpathname) {
- *pathp = '\0';
- errexit("NAME TOO LONG %s%s\n", pathname, dirp->d_name);
- }
- bcopy(dirp->d_name, pathp, dirp->d_namlen + 1);
- pathp += dirp->d_namlen;
- idesc->id_entryno++;
- n = 0;
- if (dirp->d_ino > imax || dirp->d_ino <= 0) {
- direrr(dirp->d_ino, "I OUT OF RANGE");
- n = reply("REMOVE");
- } else {
-again:
- switch (statemap[dirp->d_ino]) {
- case USTATE:
- direrr(dirp->d_ino, "UNALLOCATED");
- n = reply("REMOVE");
- break;
-
- case CLEAR:
- direrr(dirp->d_ino, "DUP/BAD");
- if ((n = reply("REMOVE")) == 1)
- break;
- if ((dp = ginode(dirp->d_ino)) == NULL)
- break;
- statemap[dirp->d_ino] = DIRCT ? DSTATE : FSTATE;
- goto again;
-
- case FSTATE:
- lncntp[dirp->d_ino]--;
- break;
-
- case DSTATE:
- descend(idesc, dirp->d_ino);
- if (statemap[dirp->d_ino] != CLEAR) {
- lncntp[dirp->d_ino]--;
- } else {
- dirp->d_ino = 0;
- ret |= ALTERED;
- }
- break;
- }
- }
- pathp = curpathloc;
- *pathp = '\0';
- if (n == 0)
- return (ret|KEEPON);
- dirp->d_ino = 0;
- return (ret|KEEPON|ALTERED);
-}
-
-pass3()
-{
- register DINODE *dp;
- struct inodesc idesc;
- ino_t inumber, orphan;
- int loopcnt;
-
- bzero((char *)&idesc, sizeof(struct inodesc));
- idesc.id_type = DATA;
- for (inumber = ROOTINO; inumber <= lastino; inumber++) {
- if (statemap[inumber] == DSTATE) {
- pathp = pathname;
- *pathp++ = '?';
- *pathp = '\0';
- idesc.id_func = findino;
- srchname = "..";
- idesc.id_parent = inumber;
- loopcnt = 0;
- do {
- orphan = idesc.id_parent;
- if ((dp = ginode(orphan)) == NULL)
- break;
- idesc.id_parent = 0;
- idesc.id_filesize = dp->di_size;
- idesc.id_number = orphan;
- (void)ckinode(dp, &idesc);
- if (idesc.id_parent == 0)
- break;
- if (loopcnt >= sblock.fs_cstotal.cs_ndir)
- break;
- loopcnt++;
- } while (statemap[idesc.id_parent] == DSTATE);
- if (linkup(orphan, idesc.id_parent) == 1) {
- idesc.id_func = pass2check;
- idesc.id_number = lfdir;
- descend(&idesc, orphan);
- }
- }
- }
-}
-
-pass4()
-{
- register ino_t inumber, *blp;
- int n;
- struct inodesc idesc;
-
- bzero((char *)&idesc, sizeof(struct inodesc));
- idesc.id_type = ADDR;
- idesc.id_func = pass4check;
- for (inumber = ROOTINO; inumber <= lastino; inumber++) {
- idesc.id_number = inumber;
- switch (statemap[inumber]) {
-
- case FSTATE:
- n = lncntp[inumber];
- if (n)
- adjust(&idesc, (short)n);
- else {
- for (blp = badlncnt;blp < badlnp; blp++)
- if (*blp == inumber) {
- clri(&idesc, "UNREF", 1);
- break;
- }
- }
- break;
-
- case DSTATE:
- clri(&idesc, "UNREF", 1);
- break;
-
- case CLEAR:
- clri(&idesc, "BAD/DUP", 1);
- break;
- }
- }
- if (imax - ROOTINO - n_files != sblock.fs_cstotal.cs_nifree) {
- pwarn("FREE INODE COUNT WRONG IN SUPERBLK");
- if (preen)
- printf(" (FIXED)\n");
- if (preen || reply("FIX") == 1) {
- sblock.fs_cstotal.cs_nifree = imax - ROOTINO - n_files;
- sbdirty();
- }
- }
- flush(&dfile, &fileblk);
-}
-
-pass4check(idesc)
- register struct inodesc *idesc;
-{
- register daddr_t *dlp;
- int nfrags, res = KEEPON;
- daddr_t blkno = idesc->id_blkno;
-
- for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
- if (outrange(blkno, 1))
- res = SKIP;
- else if (getbmap(blkno)) {
- for (dlp = duplist; dlp < enddup; dlp++)
- if (*dlp == blkno) {
- *dlp = *--enddup;
- return (KEEPON);
- }
- clrbmap(blkno);
- n_blks--;
- }
- }
- return (res);
-}
-
-pass5()
-{
- register int c, n, i, b, d;
- short bo[MAXCPG][NRPOS];
- long botot[MAXCPG];
- long frsum[MAXFRAG];
- int blk;
- daddr_t cbase;
- int blockbits = (1<<sblock.fs_frag)-1;
-
- bcopy(blockmap, freemap, (unsigned)bmapsz);
- dupblk = 0;
- n_index = sblock.fs_ncg * (cgdmin(&sblock, 0) - cgtod(&sblock, 0));
- for (c = 0; c < sblock.fs_ncg; c++) {
- cbase = cgbase(&sblock, c);
- bzero((char *)botot, sizeof (botot));
- bzero((char *)bo, sizeof (bo));
- bzero((char *)frsum, sizeof (frsum));
- /*
- * need to account for the super blocks
- * which appear (inaccurately) bad
- */
- n_bad += cgtod(&sblock, c) - cgsblock(&sblock, c);
- if (getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize) == 0)
- continue;
- if (cgrp.cg_magic != CG_MAGIC) {
- pfatal("CG %d: BAD MAGIC NUMBER\n", c);
- bzero((char *)&cgrp, (int)sblock.fs_cgsize);
- }
- for (b = 0; b < sblock.fs_fpg; b += sblock.fs_frag) {
- blk = blkmap(&sblock, cgrp.cg_free, b);
- if (blk == 0)
- continue;
- if (blk == blockbits) {
- if (pass5check(cbase+b, sblock.fs_frag) == STOP)
- goto out5;
- /* this is clumsy ... */
- n_ffree -= sblock.fs_frag;
- n_bfree++;
- botot[cbtocylno(&sblock, b)]++;
- bo[cbtocylno(&sblock, b)]
- [cbtorpos(&sblock, b)]++;
- continue;
- }
- for (d = 0; d < sblock.fs_frag; d++)
- if ((blk & (1<<d)) &&
- pass5check(cbase + b + d, (long)1) == STOP)
- goto out5;
- fragacct(&sblock, blk, frsum, 1);
- }
- if (bcmp((char *)cgrp.cg_frsum, (char *)frsum, sizeof(frsum))) {
- if (debug)
- for (i = 0; i < sblock.fs_frag; i++)
- if (cgrp.cg_frsum[i] != frsum[i])
- printf("cg[%d].cg_frsum[%d] have %d calc %d\n",
- c, i, cgrp.cg_frsum[i], frsum[i]);
- frsumbad++;
- }
- if (bcmp((char *)cgrp.cg_btot, (char *)botot, sizeof (botot))) {
- if (debug)
- for (n = 0; n < sblock.fs_cpg; n++)
- if (botot[n] != cgrp.cg_btot[n])
- printf("cg[%d].cg_btot[%d] have %d calc %d\n",
- c, n, cgrp.cg_btot[n], botot[n]);
- offsumbad++;
- }
- if (bcmp((char *)cgrp.cg_b, (char *)bo, sizeof (bo))) {
- if (debug)
- for (i = 0; i < NRPOS; i++)
- if (bo[n][i] != cgrp.cg_b[n][i])
- printf("cg[%d].cg_b[%d][%d] have %d calc %d\n",
- c, n, i, cgrp.cg_b[n][i], bo[n][i]);
- offsumbad++;
- }
- }
-out5:
- if (dupblk)
- pwarn("%d DUP BLKS IN BIT MAPS\n", dupblk);
- if (fixcg == 0) {
- if ((b = n_blks+n_ffree+sblock.fs_frag*n_bfree+n_index+n_bad) != fmax) {
- pwarn("%ld BLK(S) MISSING\n", fmax - b);
- fixcg = 1;
- } else if (inosumbad + offsumbad + frsumbad + sbsumbad) {
- pwarn("SUMMARY INFORMATION %s%s%s%sBAD\n",
- inosumbad ? "(INODE FREE) " : "",
- offsumbad ? "(BLOCK OFFSETS) " : "",
- frsumbad ? "(FRAG SUMMARIES) " : "",
- sbsumbad ? "(SUPER BLOCK SUMMARIES) " : "");
- fixcg = 1;
- } else if (n_ffree != sblock.fs_cstotal.cs_nffree ||
- n_bfree != sblock.fs_cstotal.cs_nbfree) {
- pwarn("FREE BLK COUNT(S) WRONG IN SUPERBLK");
- if (preen)
- printf(" (FIXED)\n");
- if (preen || reply("FIX") == 1) {
- sblock.fs_cstotal.cs_nffree = n_ffree;
- sblock.fs_cstotal.cs_nbfree = n_bfree;
- sbdirty();
- }
- }
- }
- if (fixcg) {
- pwarn("BAD CYLINDER GROUPS");
- if (preen)
- printf(" (SALVAGED)\n");
- else if (reply("SALVAGE") == 0)
- fixcg = 0;
- }
-}
-
-pass5check(blk, size)
- daddr_t blk;
- long size;
-{
-
- if (outrange(blk, (int)size)) {
- fixcg = 1;
- if (preen)
- pfatal("BAD BLOCKS IN BIT MAPS.");
- if (++badblk >= MAXBAD) {
- printf("EXCESSIVE BAD BLKS IN BIT MAPS.");
- if (reply("CONTINUE") == 0)
- errexit("");
- return (STOP);
- }
- }
- for (; size > 0; blk++, size--)
- if (getfmap(blk)) {
- fixcg = 1;
- ++dupblk;
- } else {
- n_ffree++;
- setfmap(blk);
- }
- return (KEEPON);
-}
-
-ckinode(dp, idesc)
- DINODE *dp;
- register struct inodesc *idesc;
-{
- register daddr_t *ap;
- int ret, n, ndb, offset;
- DINODE dino;
-
- if (SPECIAL)
- return (KEEPON);
- dino = *dp;
- idesc->id_fix = DONTKNOW;
- idesc->id_entryno = 0;
- ndb = howmany(dino.di_size, sblock.fs_bsize);
- for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) {
- if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0)
- idesc->id_numfrags =
- numfrags(&sblock, fragroundup(&sblock, offset));
- else
- idesc->id_numfrags = sblock.fs_frag;
- if (*ap == 0)
- continue;
- idesc->id_blkno = *ap;
- if (idesc->id_type == ADDR)
- ret = (*idesc->id_func)(idesc);
- else
- ret = dirscan(idesc);
- if (ret & STOP)
- return (ret);
- }
- idesc->id_numfrags = sblock.fs_frag;
- for (ap = &dino.di_ib[0], n = 1; n <= 2; ap++, n++) {
- if (*ap) {
- idesc->id_blkno = *ap;
- ret = iblock(idesc, n,
- dino.di_size - sblock.fs_bsize * NDADDR);
- if (ret & STOP)
- return (ret);
- }
- }
- return (KEEPON);
-}
-
-iblock(idesc, ilevel, isize)
- struct inodesc *idesc;
- register ilevel;
- long isize;
-{
- register daddr_t *ap;
- register daddr_t *aplim;
- int i, n, (*func)(), nif;
- BUFAREA ib;
-
- if (idesc->id_type == ADDR) {
- func = idesc->id_func;
- if (((n = (*func)(idesc)) & KEEPON) == 0)
- return (n);
- } else
- func = dirscan;
- if (outrange(idesc->id_blkno, idesc->id_numfrags)) /* protect thyself */
- return (SKIP);
- initbarea(&ib);
- if (getblk(&ib, idesc->id_blkno, sblock.fs_bsize) == NULL)
- return (SKIP);
- ilevel--;
- if (ilevel == 0) {
- nif = lblkno(&sblock, isize) + 1;
- } else /* ilevel == 1 */ {
- nif = isize / (sblock.fs_bsize * NINDIR(&sblock)) + 1;
- }
- if (nif > NINDIR(&sblock))
- nif = NINDIR(&sblock);
- aplim = &ib.b_un.b_indir[nif];
- for (ap = ib.b_un.b_indir, i = 1; ap < aplim; ap++, i++)
- if (*ap) {
- idesc->id_blkno = *ap;
- if (ilevel > 0)
- n = iblock(idesc, ilevel,
- isize - i*NINDIR(&sblock)*sblock.fs_bsize);
- else
- n = (*func)(idesc);
- if (n & STOP)
- return (n);
- }
- return (KEEPON);
-}
-
-outrange(blk, cnt)
- daddr_t blk;
- int cnt;
-{
- register int c;
-
- if ((unsigned)(blk+cnt) > fmax)
- return (1);
- c = dtog(&sblock, blk);
- if (blk < cgdmin(&sblock, c)) {
- if ((blk+cnt) > cgsblock(&sblock, c)) {
- if (debug) {
- printf("blk %d < cgdmin %d;",
- blk, cgdmin(&sblock, c));
- printf(" blk+cnt %d > cgsbase %d\n",
- blk+cnt, cgsblock(&sblock, c));
- }
- return (1);
- }
- } else {
- if ((blk+cnt) > cgbase(&sblock, c+1)) {
- if (debug) {
- printf("blk %d >= cgdmin %d;",
- blk, cgdmin(&sblock, c));
- printf(" blk+cnt %d > sblock.fs_fpg %d\n",
- blk+cnt, sblock.fs_fpg);
- }
- return (1);
- }
- }
- return (0);
-}
-
-blkerr(ino, s, blk)
- ino_t ino;
- char *s;
- daddr_t blk;
-{
-
- pfatal("%ld %s I=%u", blk, s, ino);
- printf("\n");
- statemap[ino] = CLEAR;
-}
-
-descend(parentino, inumber)
- struct inodesc *parentino;
- ino_t inumber;
-{
- register DINODE *dp;
- struct inodesc curino;
-
- bzero((char *)&curino, sizeof(struct inodesc));
- statemap[inumber] = FSTATE;
- if ((dp = ginode(inumber)) == NULL)
- return;
- if (dp->di_size == 0) {
- direrr(inumber, "ZERO LENGTH DIRECTORY");
- if (reply("REMOVE") == 1)
- statemap[inumber] = CLEAR;
- return;
- }
- if (dp->di_size < MINDIRSIZE) {
- direrr(inumber, "DIRECTORY TOO SHORT");
- dp->di_size = MINDIRSIZE;
- if (reply("FIX") == 1)
- inodirty();
- }
- curino.id_type = DATA;
- curino.id_func = parentino->id_func;
- curino.id_parent = parentino->id_number;
- curino.id_number = inumber;
- curino.id_filesize = dp->di_size;
- (void)ckinode(dp, &curino);
-}
-
-dirscan(idesc)
- register struct inodesc *idesc;
-{
- register DIRECT *dp;
- int dsize, n;
- long blksiz;
- char dbuf[DIRBLKSIZ];
-
- if (idesc->id_type != DATA)
- errexit("wrong type to dirscan %d\n", idesc->id_type);
- blksiz = idesc->id_numfrags * sblock.fs_fsize;
- if (outrange(idesc->id_blkno, idesc->id_numfrags)) {
- idesc->id_filesize -= blksiz;
- return (SKIP);
- }
- idesc->id_loc = 0;
- for (dp = fsck_readdir(idesc); dp != NULL; dp = fsck_readdir(idesc)) {
- dsize = dp->d_reclen;
- bcopy((char *)dp, dbuf, dsize);
- idesc->id_dirp = (DIRECT *)dbuf;
- if ((n = (*idesc->id_func)(idesc)) & ALTERED) {
- if (getblk(&fileblk, idesc->id_blkno, blksiz) != NULL) {
- bcopy(dbuf, (char *)dp, dsize);
- dirty(&fileblk);
- sbdirty();
- } else
- n &= ~ALTERED;
- }
- if (n & STOP)
- return (n);
- }
- return (idesc->id_filesize > 0 ? KEEPON : STOP);
-}
-
-/*
- * get next entry in a directory.
- */
-DIRECT *
-fsck_readdir(idesc)
- register struct inodesc *idesc;
-{
- register DIRECT *dp, *ndp;
- long size, blksiz;
-
- blksiz = idesc->id_numfrags * sblock.fs_fsize;
- if (getblk(&fileblk, idesc->id_blkno, blksiz) == NULL) {
- idesc->id_filesize -= blksiz - idesc->id_loc;
- return NULL;
- }
- if (idesc->id_loc % DIRBLKSIZ == 0 && idesc->id_filesize > 0 &&
- idesc->id_loc < blksiz) {
- dp = (DIRECT *)(dirblk.b_buf + idesc->id_loc);
- if (dircheck(idesc, dp))
- goto dpok;
- idesc->id_loc += DIRBLKSIZ;
- idesc->id_filesize -= DIRBLKSIZ;
- dp->d_reclen = DIRBLKSIZ;
- dp->d_ino = 0;
- dp->d_namlen = 0;
- dp->d_name[0] = '\0';
- if (dofix(idesc))
- dirty(&fileblk);
- return (dp);
- }
-dpok:
- if (idesc->id_filesize <= 0 || idesc->id_loc >= blksiz)
- return NULL;
- dp = (DIRECT *)(dirblk.b_buf + idesc->id_loc);
- idesc->id_loc += dp->d_reclen;
- idesc->id_filesize -= dp->d_reclen;
- if ((idesc->id_loc % DIRBLKSIZ) == 0)
- return (dp);
- ndp = (DIRECT *)(dirblk.b_buf + idesc->id_loc);
- if (idesc->id_loc < blksiz && idesc->id_filesize > 0 &&
- dircheck(idesc, ndp) == 0) {
- size = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ);
- dp->d_reclen += size;
- idesc->id_loc += size;
- idesc->id_filesize -= size;
- if (dofix(idesc))
- dirty(&fileblk);
- }
- return (dp);
-}
-
-/*
- * Verify that a directory entry is valid.
- * This is a superset of the checks made in the kernel.
- */
-dircheck(idesc, dp)
- struct inodesc *idesc;
- register DIRECT *dp;
-{
- register int size;
- register char *cp;
- int spaceleft;
-
- size = DIRSIZ(dp);
- spaceleft = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ);
- if (dp->d_ino < imax &&
- dp->d_reclen != 0 &&
- dp->d_reclen <= spaceleft &&
- (dp->d_reclen & 0x3) == 0 &&
- dp->d_reclen >= size &&
- idesc->id_filesize >= size &&
- dp->d_namlen <= MAXNAMLEN) {
- if (dp->d_ino == 0)
- return (1);
- for (cp = dp->d_name, size = 0; size < dp->d_namlen; size++)
- if (*cp == 0 || (*cp++ & 0200))
- return (0);
- if (*cp == 0)
- return (1);
- }
- return (0);
-}
-
-direrr(ino, s)
- ino_t ino;
- char *s;
-{
- register DINODE *dp;
-
- pwarn("%s ", s);
- pinode(ino);
- printf("\n");
- if ((dp = ginode(ino)) != NULL && ftypeok(dp))
- pfatal("%s=%s\n", DIRCT?"DIR":"FILE", pathname);
- else
- pfatal("NAME=%s\n", pathname);
-}
-
-adjust(idesc, lcnt)
- register struct inodesc *idesc;
- short lcnt;
-{
- register DINODE *dp;
-
- if ((dp = ginode(idesc->id_number)) == NULL)
- return;
- if (dp->di_nlink == lcnt) {
- if (linkup(idesc->id_number, (ino_t)0) == 0)
- clri(idesc, "UNREF", 0);
- }
- else {
- pwarn("LINK COUNT %s",
- (lfdir==idesc->id_number)?lfname:(DIRCT?"DIR":"FILE"));
- pinode(idesc->id_number);
- printf(" COUNT %d SHOULD BE %d",
- dp->di_nlink, dp->di_nlink-lcnt);
- if (preen) {
- if (lcnt < 0) {
- printf("\n");
- preendie();
- }
- printf(" (ADJUSTED)\n");
- }
- if (preen || reply("ADJUST") == 1) {
- dp->di_nlink -= lcnt;
- inodirty();
- }
- }
-}
-
-clri(idesc, s, flg)
- register struct inodesc *idesc;
- char *s;
- int flg;
-{
- register DINODE *dp;
-
- if ((dp = ginode(idesc->id_number)) == NULL)
- return;
- if (flg == 1) {
- pwarn("%s %s", s, DIRCT?"DIR":"FILE");
- pinode(idesc->id_number);
- }
- if (preen || reply("CLEAR") == 1) {
- if (preen)
- printf(" (CLEARED)\n");
- n_files--;
- (void)ckinode(dp, idesc);
- zapino(dp);
- statemap[idesc->id_number] = USTATE;
- inodirty();
- inosumbad++;
- }
-}
-
-badsb(s)
- char *s;
-{
-
- if (preen)
- printf("%s: ", devname);
- printf("BAD SUPER BLOCK: %s\n", s);
- pwarn("USE -b OPTION TO FSCK TO SPECIFY LOCATION OF AN ALTERNATE\n");
- pfatal("SUPER-BLOCK TO SUPPLY NEEDED INFORMATION; SEE fsck(8).\n");
-}
-
-DINODE *
-ginode(inumber)
- ino_t inumber;
-{
- daddr_t iblk;
- static ino_t startinum = 0; /* blk num of first in raw area */
-
-
- if (inumber < ROOTINO || inumber > imax) {
- if (debug && inumber > imax)
- printf("inumber out of range (%d)\n", inumber);
- return (NULL);
- }
- if (startinum == 0 ||
- inumber < startinum || inumber >= startinum + INOPB(&sblock)) {
- iblk = itod(&sblock, inumber);
- if (getblk(&inoblk, iblk, sblock.fs_bsize) == NULL) {
- return (NULL);
- }
- startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock);
- }
- return (&inoblk.b_un.b_dinode[inumber % INOPB(&sblock)]);
-}
-
-ftypeok(dp)
- DINODE *dp;
-{
- switch (dp->di_mode & IFMT) {
-
- case IFDIR:
- case IFREG:
- case IFBLK:
- case IFCHR:
- case IFLNK:
- case IFSOCK:
- return (1);
-
- default:
- if (debug)
- printf("bad file type 0%o\n", dp->di_mode);
- return (0);
- }
-}
-
-reply(s)
- char *s;
-{
- char line[80];
-
- if (preen)
- pfatal("INTERNAL ERROR: GOT TO reply()");
- rplyflag = 1;
- printf("\n%s? ", s);
- if (nflag || dfile.wfdes < 0) {
- printf(" no\n\n");
- return (0);
- }
- if (yflag) {
- printf(" yes\n\n");
- return (1);
- }
- if (getline(stdin, line, sizeof(line)) == EOF)
- errexit("\n");
- printf("\n");
- if (line[0] == 'y' || line[0] == 'Y')
- return (1);
- else
- return (0);
-}
-
-getline(fp, loc, maxlen)
- FILE *fp;
- char *loc;
-{
- register n;
- register char *p, *lastloc;
-
- p = loc;
- lastloc = &p[maxlen-1];
- while ((n = getc(fp)) != '\n') {
- if (n == EOF)
- return (EOF);
- if (!isspace(n) && p < lastloc)
- *p++ = n;
- }
- *p = 0;
- return (p - loc);
-}
-
-BUFAREA *
-getblk(bp, blk, size)
- register BUFAREA *bp;
- daddr_t blk;
- long size;
-{
- register struct filecntl *fcp;
- daddr_t dblk;
-
- fcp = &dfile;
- dblk = fsbtodb(&sblock, blk);
- if (bp->b_bno == dblk)
- return (bp);
- flush(fcp, bp);
- if (bread(fcp, bp->b_un.b_buf, dblk, size) != 0) {
- bp->b_bno = dblk;
- bp->b_size = size;
- return (bp);
- }
- bp->b_bno = (daddr_t)-1;
- return (NULL);
-}
-
-flush(fcp, bp)
- struct filecntl *fcp;
- register BUFAREA *bp;
-{
-
- if (bp->b_dirty)
- (void)bwrite(fcp, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size);
- bp->b_dirty = 0;
-}
-
-rwerr(s, blk)
- char *s;
- daddr_t blk;
-{
-
- if (preen == 0)
- printf("\n");
- pfatal("CANNOT %s: BLK %ld", s, blk);
- if (reply("CONTINUE") == 0)
- errexit("Program terminated\n");
-}
-
-ckfini()
-{
-
- flush(&dfile, &fileblk);
- flush(&dfile, &sblk);
- if (sblk.b_bno != SBLOCK) {
- sblk.b_bno = SBLOCK;
- sbdirty();
- flush(&dfile, &sblk);
- }
- flush(&dfile, &inoblk);
- (void)close(dfile.rfdes);
- (void)close(dfile.wfdes);
-}
-
-pinode(ino)
- ino_t ino;
-{
- register DINODE *dp;
- register char *p;
- char uidbuf[BUFSIZ];
- char *ctime();
-
- printf(" I=%u ", ino);
- if ((dp = ginode(ino)) == NULL)
- return;
- printf(" OWNER=");
- if (getpw((int)dp->di_uid, uidbuf) == 0) {
- for (p = uidbuf; *p != ':'; p++);
- *p = 0;
- printf("%s ", uidbuf);
- }
- else {
- printf("%d ", dp->di_uid);
- }
- printf("MODE=%o\n", dp->di_mode);
- if (preen)
- printf("%s: ", devname);
- printf("SIZE=%ld ", dp->di_size);
- p = ctime(&dp->di_mtime);
- printf("MTIME=%12.12s %4.4s ", p+4, p+20);
-}
-
-makecg()
-{
- int c, blk;
- daddr_t dbase, d, dlower, dupper, dmax;
- long i, j, s;
- ino_t inumber;
- register struct csum *cs;
- register DINODE *dp;
-
- sblock.fs_cstotal.cs_nbfree = 0;
- sblock.fs_cstotal.cs_nffree = 0;
- sblock.fs_cstotal.cs_nifree = 0;
- sblock.fs_cstotal.cs_ndir = 0;
- for (c = 0; c < sblock.fs_ncg; c++) {
- dbase = cgbase(&sblock, c);
- dmax = dbase + sblock.fs_fpg;
- if (dmax > sblock.fs_size) {
- for ( ; dmax >= sblock.fs_size; dmax--)
- clrbit(cgrp.cg_free, dmax - dbase);
- dmax++;
- }
- dlower = cgsblock(&sblock, c) - dbase;
- dupper = cgdmin(&sblock, c) - dbase;
- cs = &sblock.fs_cs(&sblock, c);
- (void)time(&cgrp.cg_time);
- cgrp.cg_magic = CG_MAGIC;
- cgrp.cg_cgx = c;
- if (c == sblock.fs_ncg - 1)
- cgrp.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg;
- else
- cgrp.cg_ncyl = sblock.fs_cpg;
- cgrp.cg_niblk = sblock.fs_ipg;
- cgrp.cg_ndblk = dmax - dbase;
- cgrp.cg_cs.cs_ndir = 0;
- cgrp.cg_cs.cs_nffree = 0;
- cgrp.cg_cs.cs_nbfree = 0;
- cgrp.cg_cs.cs_nifree = 0;
- cgrp.cg_rotor = 0;
- cgrp.cg_frotor = 0;
- cgrp.cg_irotor = 0;
- for (i = 0; i < sblock.fs_frag; i++)
- cgrp.cg_frsum[i] = 0;
- inumber = sblock.fs_ipg * c;
- for (i = 0; i < sblock.fs_ipg; inumber++, i++) {
- cgrp.cg_cs.cs_nifree++;
- clrbit(cgrp.cg_iused, i);
- dp = ginode(inumber);
- if (dp == NULL)
- continue;
- if (ALLOC) {
- if (DIRCT)
- cgrp.cg_cs.cs_ndir++;
- cgrp.cg_cs.cs_nifree--;
- setbit(cgrp.cg_iused, i);
- continue;
- }
- }
- while (i < MAXIPG) {
- clrbit(cgrp.cg_iused, i);
- i++;
- }
- if (c == 0)
- for (i = 0; i < ROOTINO; i++) {
- setbit(cgrp.cg_iused, i);
- cgrp.cg_cs.cs_nifree--;
- }
- for (s = 0; s < MAXCPG; s++) {
- cgrp.cg_btot[s] = 0;
- for (i = 0; i < NRPOS; i++)
- cgrp.cg_b[s][i] = 0;
- }
- if (c == 0) {
- dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
- }
- for (d = dlower; d < dupper; d++)
- clrbit(cgrp.cg_free, d);
- for (d = 0; (d + sblock.fs_frag) <= dmax - dbase;
- d += sblock.fs_frag) {
- j = 0;
- for (i = 0; i < sblock.fs_frag; i++) {
- if (!getbmap(dbase + d + i)) {
- setbit(cgrp.cg_free, d + i);
- j++;
- } else
- clrbit(cgrp.cg_free, d+i);
- }
- if (j == sblock.fs_frag) {
- cgrp.cg_cs.cs_nbfree++;
- cgrp.cg_btot[cbtocylno(&sblock, d)]++;
- cgrp.cg_b[cbtocylno(&sblock, d)]
- [cbtorpos(&sblock, d)]++;
- } else if (j > 0) {
- cgrp.cg_cs.cs_nffree += j;
- blk = blkmap(&sblock, cgrp.cg_free, d);
- fragacct(&sblock, blk, cgrp.cg_frsum, 1);
- }
- }
- for (j = d; d < dmax - dbase; d++) {
- if (!getbmap(dbase + d)) {
- setbit(cgrp.cg_free, d);
- cgrp.cg_cs.cs_nffree++;
- } else
- clrbit(cgrp.cg_free, d);
- }
- for (; d % sblock.fs_frag != 0; d++)
- clrbit(cgrp.cg_free, d);
- if (j != d) {
- blk = blkmap(&sblock, cgrp.cg_free, j);
- fragacct(&sblock, blk, cgrp.cg_frsum, 1);
- }
- for (d /= sblock.fs_frag; d < MAXBPG(&sblock); d ++)
- clrblock(&sblock, cgrp.cg_free, d);
- sblock.fs_cstotal.cs_nffree += cgrp.cg_cs.cs_nffree;
- sblock.fs_cstotal.cs_nbfree += cgrp.cg_cs.cs_nbfree;
- sblock.fs_cstotal.cs_nifree += cgrp.cg_cs.cs_nifree;
- sblock.fs_cstotal.cs_ndir += cgrp.cg_cs.cs_ndir;
- *cs = cgrp.cg_cs;
- (void)bwrite(&dfile, (char *)&cgrp,
- fsbtodb(&sblock, cgtod(&sblock, c)), sblock.fs_cgsize);
- }
- for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
- (void)bwrite(&dfile, (char *)sblock.fs_csp[j],
- fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
- sblock.fs_cssize - i < sblock.fs_bsize ?
- sblock.fs_cssize - i : sblock.fs_bsize);
- }
- sblock.fs_ronly = 0;
- sblock.fs_fmod = 0;
- sbdirty();
-}
-
-findino(idesc)
- struct inodesc *idesc;
-{
- register DIRECT *dirp = idesc->id_dirp;
-
- if (dirp->d_ino == 0)
- return (KEEPON);
- if (!strcmp(dirp->d_name, srchname)) {
- if (dirp->d_ino >= ROOTINO && dirp->d_ino <= imax)
- idesc->id_parent = dirp->d_ino;
- return (STOP);
- }
- return (KEEPON);
-}
-
-mkentry(idesc)
- struct inodesc *idesc;
-{
- register DIRECT *dirp = idesc->id_dirp;
- DIRECT newent;
- int newlen, oldlen;
-
- newent.d_namlen = 11;
- newlen = DIRSIZ(&newent);
- if (dirp->d_ino != 0)
- oldlen = DIRSIZ(dirp);
- else
- oldlen = 0;
- if (dirp->d_reclen - oldlen < newlen)
- return (KEEPON);
- newent.d_reclen = dirp->d_reclen - oldlen;
- dirp->d_reclen = oldlen;
- dirp = (struct direct *)(((char *)dirp) + oldlen);
- dirp->d_ino = idesc->id_parent; /* ino to be entered is in id_parent */
- dirp->d_reclen = newent.d_reclen;
- dirp->d_namlen = lftempname(dirp->d_name, idesc->id_parent);
- return (ALTERED|STOP);
-}
-
-chgdd(idesc)
- struct inodesc *idesc;
-{
- register DIRECT *dirp = idesc->id_dirp;
-
- if (dirp->d_name[0] == '.' && dirp->d_name[1] == '.' &&
- dirp->d_name[2] == 0) {
- dirp->d_ino = lfdir;
- return (ALTERED|STOP);
- }
- return (KEEPON);
-}
-
-linkup(orphan, pdir)
- ino_t orphan;
- ino_t pdir;
-{
- register DINODE *dp;
- int lostdir, len;
- struct inodesc idesc;
-
- bzero((char *)&idesc, sizeof(struct inodesc));
- if ((dp = ginode(orphan)) == NULL)
- return (0);
- lostdir = DIRCT;
- pwarn("UNREF %s ", lostdir ? "DIR" : "FILE");
- pinode(orphan);
- if (preen && dp->di_size == 0)
- return (0);
- if (preen)
- printf(" (RECONNECTED)\n");
- else
- if (reply("RECONNECT") == 0)
- return (0);
- pathp = pathname;
- *pathp++ = '/';
- *pathp = '\0';
- if (lfdir == 0) {
- if ((dp = ginode(ROOTINO)) == NULL)
- return (0);
- srchname = lfname;
- idesc.id_type = DATA;
- idesc.id_func = findino;
- idesc.id_number = ROOTINO;
- idesc.id_filesize = dp->di_size;
- (void)ckinode(dp, &idesc);
- if ((lfdir = idesc.id_parent) == 0) {
- pfatal("SORRY. NO lost+found DIRECTORY");
- printf("\n\n");
- return (0);
- }
- }
- if ((dp = ginode(lfdir)) == NULL ||
- !DIRCT || statemap[lfdir] != FSTATE) {
- pfatal("SORRY. NO lost+found DIRECTORY");
- printf("\n\n");
- return (0);
- }
- if (fragoff(&sblock, dp->di_size)) {
- dp->di_size = fragroundup(&sblock, dp->di_size);
- inodirty();
- }
- len = strlen(lfname);
- bcopy(lfname, pathp, len + 1);
- pathp += len;
- idesc.id_type = DATA;
- idesc.id_func = mkentry;
- idesc.id_number = lfdir;
- idesc.id_filesize = dp->di_size;
- idesc.id_parent = orphan; /* this is the inode to enter */
- idesc.id_fix = DONTKNOW;
- if ((ckinode(dp, &idesc) & ALTERED) == 0) {
- pfatal("SORRY. NO SPACE IN lost+found DIRECTORY");
- printf("\n\n");
- return (0);
- }
- lncntp[orphan]--;
- *pathp++ = '/';
- pathp += lftempname(pathp, orphan);
- if (lostdir) {
- dp = ginode(orphan);
- idesc.id_type = DATA;
- idesc.id_func = chgdd;
- idesc.id_number = orphan;
- idesc.id_filesize = dp->di_size;
- idesc.id_fix = DONTKNOW;
- (void)ckinode(dp, &idesc);
- if ((dp = ginode(lfdir)) != NULL) {
- dp->di_nlink++;
- inodirty();
- lncntp[lfdir]++;
- }
- pwarn("DIR I=%u CONNECTED. ", orphan);
- printf("PARENT WAS I=%u\n", pdir);
- if (preen == 0)
- printf("\n");
- }
- return (1);
-}
-
-/*
- * generate a temporary name for the lost+found directory.
- */
-lftempname(bufp, ino)
- char *bufp;
- ino_t ino;
-{
- register ino_t in;
- register char *cp;
- int namlen;
-
- cp = bufp + 2;
- for (in = imax; in > 0; in /= 10)
- cp++;
- *--cp = 0;
- namlen = cp - bufp;
- in = ino;
- while (cp > bufp) {
- *--cp = (in % 10) + '0';
- in /= 10;
- }
- *cp = '#';
- return (namlen);
-}
-
-bread(fcp, buf, blk, size)
- register struct filecntl *fcp;
- char *buf;
- daddr_t blk;
- long size;
-{
- if (lseek(fcp->rfdes, (long)dbtob(blk), 0) < 0)
- rwerr("SEEK", blk);
- else if (read(fcp->rfdes, buf, (int)size) == size)
- return (1);
- rwerr("READ", blk);
- return (0);
-}
-
-bwrite(fcp, buf, blk, size)
- register struct filecntl *fcp;
- char *buf;
- daddr_t blk;
- long size;
-{
-
- if (fcp->wfdes < 0)
- return (0);
- if (lseek(fcp->wfdes, (long)dbtob(blk), 0) < 0)
- rwerr("SEEK", blk);
- else if (write(fcp->wfdes, buf, (int)size) == size) {
- fcp->mod = 1;
- return (1);
- }
- rwerr("WRITE", blk);
- return (0);
-}
-
-catch()
-{
-
- ckfini();
- exit(12);
-}
-
-char *
-unrawname(cp)
- char *cp;
-{
- char *dp = rindex(cp, '/');
- struct stat stb;
-
- if (dp == 0)
- return (cp);
- if (stat(cp, &stb) < 0)
- return (cp);
- if ((stb.st_mode&S_IFMT) != S_IFCHR)
- return (cp);
- if (*(dp+1) != 'r')
- return (cp);
- (void)strcpy(dp+1, dp+2);
- return (cp);
-}
-
-char *
-rawname(cp)
- char *cp;
-{
- static char rawbuf[32];
- char *dp = rindex(cp, '/');
-
- if (dp == 0)
- return (0);
- *dp = 0;
- (void)strcpy(rawbuf, cp);
- *dp = '/';
- (void)strcat(rawbuf, "/r");
- (void)strcat(rawbuf, dp+1);
- return (rawbuf);
-}
-
-/*
- * determine whether an inode should be fixed.
- */
-dofix(idesc)
- register struct inodesc *idesc;
-{
-
- switch (idesc->id_fix) {
-
- case DONTKNOW:
- direrr(idesc->id_number, "DIRECTORY CORRUPTED");
- if (reply("SALVAGE") == 0) {
- idesc->id_fix = NOFIX;
- return (0);
- }
- idesc->id_fix = FIX;
- return (ALTERED);
-
- case FIX:
- return (ALTERED);
-
- case NOFIX:
- return (0);
-
- default:
- errexit("UNKNOWN INODESC FIX MODE %d\n", idesc->id_fix);
- }
- /* NOTREACHED */
-}
-
-/* VARARGS1 */
-error(s1, s2, s3, s4)
- char *s1;
-{
-
- printf(s1, s2, s3, s4);
-}
-
-/* VARARGS1 */
-errexit(s1, s2, s3, s4)
- char *s1;
-{
- error(s1, s2, s3, s4);
- exit(8);
-}
-
-/*
- * An inconsistency occured which shouldn't during normal operations.
- * Die if preening, otherwise just printf.
- */
-/* VARARGS1 */
-pfatal(s, a1, a2, a3)
- char *s;
-{
-
- if (preen) {
- printf("%s: ", devname);
- printf(s, a1, a2, a3);
- printf("\n");
- preendie();
- }
- printf(s, a1, a2, a3);
-}
-
-preendie()
-{
-
- printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", devname);
- exit(8);
-}
-
-/*
- * Pwarn is like printf when not preening,
- * or a warning (preceded by filename) when preening.
- */
-/* VARARGS1 */
-pwarn(s, a1, a2, a3, a4, a5, a6)
- char *s;
-{
-
- if (preen)
- printf("%s: ", devname);
- printf(s, a1, a2, a3, a4, a5, a6);
-}
-
-#ifndef lint
-/*
- * Stub for routines from kernel.
- */
-panic(s)
- char *s;
-{
-
- pfatal("INTERNAL INCONSISTENCY: %s\n", s);
- exit(12);
-}
-#endif