116269Smckusick #ifndef lint 2*21758Smckusick static char version[] = "@(#)utilities.c 3.7 (Berkeley) 06/02/85"; 316269Smckusick #endif 416269Smckusick 516269Smckusick #include <stdio.h> 616269Smckusick #include <ctype.h> 716269Smckusick #include <sys/param.h> 816269Smckusick #include <sys/inode.h> 916269Smckusick #include <sys/fs.h> 1017991Smckusick #include <sys/dir.h> 1116269Smckusick #include "fsck.h" 1216269Smckusick 1316269Smckusick long lseek(); 1416269Smckusick 1516269Smckusick ftypeok(dp) 1616269Smckusick DINODE *dp; 1716269Smckusick { 1816269Smckusick switch (dp->di_mode & IFMT) { 1916269Smckusick 2016269Smckusick case IFDIR: 2116269Smckusick case IFREG: 2216269Smckusick case IFBLK: 2316269Smckusick case IFCHR: 2416269Smckusick case IFLNK: 2516269Smckusick case IFSOCK: 2616269Smckusick return (1); 2716269Smckusick 2816269Smckusick default: 2916269Smckusick if (debug) 3016269Smckusick printf("bad file type 0%o\n", dp->di_mode); 3116269Smckusick return (0); 3216269Smckusick } 3316269Smckusick } 3416269Smckusick 3516269Smckusick reply(s) 3616269Smckusick char *s; 3716269Smckusick { 3816269Smckusick char line[80]; 3916269Smckusick 4016269Smckusick if (preen) 4116269Smckusick pfatal("INTERNAL ERROR: GOT TO reply()"); 4216269Smckusick printf("\n%s? ", s); 4316269Smckusick if (nflag || dfile.wfdes < 0) { 4416269Smckusick printf(" no\n\n"); 4516269Smckusick return (0); 4616269Smckusick } 4716269Smckusick if (yflag) { 4816269Smckusick printf(" yes\n\n"); 4916269Smckusick return (1); 5016269Smckusick } 5116269Smckusick if (getline(stdin, line, sizeof(line)) == EOF) 5216269Smckusick errexit("\n"); 5316269Smckusick printf("\n"); 5416269Smckusick if (line[0] == 'y' || line[0] == 'Y') 5516269Smckusick return (1); 5616269Smckusick else 5716269Smckusick return (0); 5816269Smckusick } 5916269Smckusick 6016269Smckusick getline(fp, loc, maxlen) 6116269Smckusick FILE *fp; 6216269Smckusick char *loc; 6316269Smckusick { 6416269Smckusick register n; 6516269Smckusick register char *p, *lastloc; 6616269Smckusick 6716269Smckusick p = loc; 6816269Smckusick lastloc = &p[maxlen-1]; 6916269Smckusick while ((n = getc(fp)) != '\n') { 7016269Smckusick if (n == EOF) 7116269Smckusick return (EOF); 7216269Smckusick if (!isspace(n) && p < lastloc) 7316269Smckusick *p++ = n; 7416269Smckusick } 7516269Smckusick *p = 0; 7616269Smckusick return (p - loc); 7716269Smckusick } 7816269Smckusick 7916269Smckusick BUFAREA * 8016269Smckusick getblk(bp, blk, size) 8116269Smckusick register BUFAREA *bp; 8216269Smckusick daddr_t blk; 8316269Smckusick long size; 8416269Smckusick { 8516269Smckusick register struct filecntl *fcp; 8616269Smckusick daddr_t dblk; 8716269Smckusick 8816269Smckusick fcp = &dfile; 8916269Smckusick dblk = fsbtodb(&sblock, blk); 9016269Smckusick if (bp->b_bno == dblk) 9116269Smckusick return (bp); 9216269Smckusick flush(fcp, bp); 9321540Smckusick bp->b_errs = bread(fcp, bp->b_un.b_buf, dblk, size); 9421540Smckusick bp->b_bno = dblk; 9521540Smckusick bp->b_size = size; 9621540Smckusick return (bp); 9716269Smckusick } 9816269Smckusick 9916269Smckusick flush(fcp, bp) 10016269Smckusick struct filecntl *fcp; 10116269Smckusick register BUFAREA *bp; 10216269Smckusick { 10317931Smckusick register int i, j; 10416269Smckusick 10517931Smckusick if (!bp->b_dirty) 10617931Smckusick return; 10721540Smckusick if (bp->b_errs != 0) 10821540Smckusick pfatal("WRITING ZERO'ED BLOCK %d TO DISK\n", bp->b_bno); 10916269Smckusick bp->b_dirty = 0; 11021540Smckusick bp->b_errs = 0; 111*21758Smckusick bwrite(fcp, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size); 11217931Smckusick if (bp != &sblk) 11317931Smckusick return; 11417931Smckusick for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { 115*21758Smckusick bwrite(&dfile, (char *)sblock.fs_csp[j], 11617931Smckusick fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), 11717931Smckusick sblock.fs_cssize - i < sblock.fs_bsize ? 11817931Smckusick sblock.fs_cssize - i : sblock.fs_bsize); 11917931Smckusick } 12016269Smckusick } 12116269Smckusick 12216269Smckusick rwerr(s, blk) 12316269Smckusick char *s; 12416269Smckusick daddr_t blk; 12516269Smckusick { 12616269Smckusick 12716269Smckusick if (preen == 0) 12816269Smckusick printf("\n"); 12916269Smckusick pfatal("CANNOT %s: BLK %ld", s, blk); 13016269Smckusick if (reply("CONTINUE") == 0) 13116269Smckusick errexit("Program terminated\n"); 13216269Smckusick } 13316269Smckusick 13416269Smckusick ckfini() 13516269Smckusick { 13616269Smckusick 13716269Smckusick flush(&dfile, &fileblk); 13816269Smckusick flush(&dfile, &sblk); 13916269Smckusick if (sblk.b_bno != SBLOCK) { 14016269Smckusick sblk.b_bno = SBLOCK; 14116269Smckusick sbdirty(); 14216269Smckusick flush(&dfile, &sblk); 14316269Smckusick } 14416269Smckusick flush(&dfile, &inoblk); 14518002Smckusick flush(&dfile, &cgblk); 14616269Smckusick (void)close(dfile.rfdes); 14716269Smckusick (void)close(dfile.wfdes); 14816269Smckusick } 14916269Smckusick 15016269Smckusick bread(fcp, buf, blk, size) 15116269Smckusick register struct filecntl *fcp; 15216269Smckusick char *buf; 15316269Smckusick daddr_t blk; 15416269Smckusick long size; 15516269Smckusick { 15621540Smckusick char *cp; 15721540Smckusick int i, errs; 15821540Smckusick 15916269Smckusick if (lseek(fcp->rfdes, (long)dbtob(blk), 0) < 0) 16016269Smckusick rwerr("SEEK", blk); 16116269Smckusick else if (read(fcp->rfdes, buf, (int)size) == size) 16221540Smckusick return (0); 16316269Smckusick rwerr("READ", blk); 16421540Smckusick if (lseek(fcp->rfdes, (long)dbtob(blk), 0) < 0) 16521540Smckusick rwerr("SEEK", blk); 16621540Smckusick errs = 0; 167*21758Smckusick pfatal("THE FOLLOWING SECTORS COULD NOT BE READ:"); 16821540Smckusick for (cp = buf, i = 0; i < size; i += DEV_BSIZE, cp += DEV_BSIZE) { 16921540Smckusick if (read(fcp->rfdes, cp, DEV_BSIZE) < 0) { 170*21758Smckusick printf(" %d,", blk + i / DEV_BSIZE); 17121540Smckusick bzero(cp, DEV_BSIZE); 17221540Smckusick errs++; 17321540Smckusick } 17421540Smckusick } 175*21758Smckusick printf("\n"); 17621540Smckusick return (errs); 17716269Smckusick } 17816269Smckusick 17916269Smckusick bwrite(fcp, buf, blk, size) 18016269Smckusick register struct filecntl *fcp; 18116269Smckusick char *buf; 18216269Smckusick daddr_t blk; 18316269Smckusick long size; 18416269Smckusick { 185*21758Smckusick int i; 186*21758Smckusick char *cp; 18716269Smckusick 18816269Smckusick if (fcp->wfdes < 0) 189*21758Smckusick return; 19016269Smckusick if (lseek(fcp->wfdes, (long)dbtob(blk), 0) < 0) 19116269Smckusick rwerr("SEEK", blk); 19216269Smckusick else if (write(fcp->wfdes, buf, (int)size) == size) { 19316269Smckusick fcp->mod = 1; 194*21758Smckusick return; 19516269Smckusick } 19616269Smckusick rwerr("WRITE", blk); 197*21758Smckusick if (lseek(fcp->wfdes, (long)dbtob(blk), 0) < 0) 198*21758Smckusick rwerr("SEEK", blk); 199*21758Smckusick pfatal("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:"); 200*21758Smckusick for (cp = buf, i = 0; i < size; i += DEV_BSIZE, cp += DEV_BSIZE) 201*21758Smckusick if (write(fcp->wfdes, cp, DEV_BSIZE) < 0) 202*21758Smckusick printf(" %d,", blk + i / DEV_BSIZE); 203*21758Smckusick printf("\n"); 204*21758Smckusick return; 20516269Smckusick } 20616269Smckusick 20717944Smckusick /* 20817944Smckusick * allocate a data block with the specified number of fragments 20917944Smckusick */ 21017944Smckusick allocblk(frags) 21117944Smckusick int frags; 21217944Smckusick { 21317944Smckusick register int i, j, k; 21417944Smckusick 21517944Smckusick if (frags <= 0 || frags > sblock.fs_frag) 21617944Smckusick return (0); 21717944Smckusick for (i = 0; i < fmax - sblock.fs_frag; i += sblock.fs_frag) { 21817944Smckusick for (j = 0; j <= sblock.fs_frag - frags; j++) { 21917944Smckusick if (getbmap(i + j)) 22017944Smckusick continue; 22117944Smckusick for (k = 1; k < frags; k++) 22217944Smckusick if (getbmap(i + j + k)) 22317944Smckusick break; 22417944Smckusick if (k < frags) { 22517944Smckusick j += k; 22617944Smckusick continue; 22717944Smckusick } 22817944Smckusick for (k = 0; k < frags; k++) 22917944Smckusick setbmap(i + j + k); 23017944Smckusick n_blks += frags; 23117944Smckusick return (i + j); 23217944Smckusick } 23317944Smckusick } 23417944Smckusick return (0); 23517944Smckusick } 23617944Smckusick 23717944Smckusick /* 23817944Smckusick * Free a previously allocated block 23917944Smckusick */ 24017944Smckusick freeblk(blkno, frags) 24117944Smckusick daddr_t blkno; 24217944Smckusick int frags; 24317944Smckusick { 24417944Smckusick struct inodesc idesc; 24517944Smckusick 24617944Smckusick idesc.id_blkno = blkno; 24717944Smckusick idesc.id_numfrags = frags; 24817944Smckusick pass4check(&idesc); 24917944Smckusick } 25017944Smckusick 25117991Smckusick /* 25217991Smckusick * Find a pathname 25317991Smckusick */ 25417991Smckusick getpathname(namebuf, curdir, ino) 25517991Smckusick char *namebuf; 25617991Smckusick ino_t curdir, ino; 25717991Smckusick { 25817991Smckusick int len; 25917991Smckusick register char *cp; 26017991Smckusick struct inodesc idesc; 26117991Smckusick extern int findname(); 26217991Smckusick 26317991Smckusick if (statemap[ino] != DSTATE && statemap[ino] != DFOUND) { 26417991Smckusick strcpy(namebuf, "?"); 26517991Smckusick return; 26617991Smckusick } 26717991Smckusick bzero(&idesc, sizeof(struct inodesc)); 26817991Smckusick idesc.id_type = DATA; 26917991Smckusick cp = &namebuf[BUFSIZ - 1]; 27017991Smckusick *cp-- = '\0'; 27117991Smckusick if (curdir != ino) { 27217991Smckusick idesc.id_parent = curdir; 27317991Smckusick goto namelookup; 27417991Smckusick } 27517991Smckusick while (ino != ROOTINO) { 27617991Smckusick idesc.id_number = ino; 27717991Smckusick idesc.id_func = findino; 27817991Smckusick idesc.id_name = ".."; 27917991Smckusick if ((ckinode(ginode(ino), &idesc) & STOP) == 0) 28017991Smckusick break; 28117991Smckusick namelookup: 28217991Smckusick idesc.id_number = idesc.id_parent; 28317991Smckusick idesc.id_parent = ino; 28417991Smckusick idesc.id_func = findname; 28517991Smckusick idesc.id_name = namebuf; 28617991Smckusick if ((ckinode(ginode(idesc.id_number), &idesc) & STOP) == 0) 28717991Smckusick break; 28817991Smckusick len = strlen(namebuf); 28917991Smckusick cp -= len; 29017991Smckusick if (cp < &namebuf[MAXNAMLEN]) 29117991Smckusick break; 29217991Smckusick bcopy(namebuf, cp, len); 29317991Smckusick *--cp = '/'; 29417991Smckusick ino = idesc.id_number; 29517991Smckusick } 29617991Smckusick if (ino != ROOTINO) { 29717991Smckusick strcpy(namebuf, "?"); 29817991Smckusick return; 29917991Smckusick } 30017991Smckusick bcopy(cp, namebuf, &namebuf[BUFSIZ] - cp); 30117991Smckusick } 30217991Smckusick 30316269Smckusick catch() 30416269Smckusick { 30516269Smckusick 30616269Smckusick ckfini(); 30716269Smckusick exit(12); 30816269Smckusick } 30916269Smckusick 31016269Smckusick /* 31116269Smckusick * determine whether an inode should be fixed. 31216269Smckusick */ 31317931Smckusick dofix(idesc, msg) 31416269Smckusick register struct inodesc *idesc; 31517931Smckusick char *msg; 31616269Smckusick { 31716269Smckusick 31816269Smckusick switch (idesc->id_fix) { 31916269Smckusick 32016269Smckusick case DONTKNOW: 32117931Smckusick if (idesc->id_type == DATA) 32217931Smckusick direrr(idesc->id_number, msg); 32317931Smckusick else 32417931Smckusick pwarn(msg); 32517931Smckusick if (preen) { 32617931Smckusick printf(" (SALVAGED)\n"); 32717931Smckusick idesc->id_fix = FIX; 32817931Smckusick return (ALTERED); 32917931Smckusick } 33016269Smckusick if (reply("SALVAGE") == 0) { 33116269Smckusick idesc->id_fix = NOFIX; 33216269Smckusick return (0); 33316269Smckusick } 33416269Smckusick idesc->id_fix = FIX; 33516269Smckusick return (ALTERED); 33616269Smckusick 33716269Smckusick case FIX: 33816269Smckusick return (ALTERED); 33916269Smckusick 34016269Smckusick case NOFIX: 34116269Smckusick return (0); 34216269Smckusick 34316269Smckusick default: 34416269Smckusick errexit("UNKNOWN INODESC FIX MODE %d\n", idesc->id_fix); 34516269Smckusick } 34616269Smckusick /* NOTREACHED */ 34716269Smckusick } 34816269Smckusick 34916269Smckusick /* VARARGS1 */ 35017931Smckusick errexit(s1, s2, s3, s4) 35116269Smckusick char *s1; 35216269Smckusick { 35316269Smckusick printf(s1, s2, s3, s4); 35416269Smckusick exit(8); 35516269Smckusick } 35616269Smckusick 35716269Smckusick /* 35816269Smckusick * An inconsistency occured which shouldn't during normal operations. 35916269Smckusick * Die if preening, otherwise just printf. 36016269Smckusick */ 36116269Smckusick /* VARARGS1 */ 36216269Smckusick pfatal(s, a1, a2, a3) 36316269Smckusick char *s; 36416269Smckusick { 36516269Smckusick 36616269Smckusick if (preen) { 36716269Smckusick printf("%s: ", devname); 36816269Smckusick printf(s, a1, a2, a3); 36916269Smckusick printf("\n"); 37017931Smckusick printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", 37117931Smckusick devname); 37217931Smckusick exit(8); 37316269Smckusick } 37416269Smckusick printf(s, a1, a2, a3); 37516269Smckusick } 37616269Smckusick 37716269Smckusick /* 37816269Smckusick * Pwarn is like printf when not preening, 37916269Smckusick * or a warning (preceded by filename) when preening. 38016269Smckusick */ 38116269Smckusick /* VARARGS1 */ 38216269Smckusick pwarn(s, a1, a2, a3, a4, a5, a6) 38316269Smckusick char *s; 38416269Smckusick { 38516269Smckusick 38616269Smckusick if (preen) 38716269Smckusick printf("%s: ", devname); 38816269Smckusick printf(s, a1, a2, a3, a4, a5, a6); 38916269Smckusick } 39016269Smckusick 39116269Smckusick #ifndef lint 39216269Smckusick /* 39316269Smckusick * Stub for routines from kernel. 39416269Smckusick */ 39516269Smckusick panic(s) 39616269Smckusick char *s; 39716269Smckusick { 39816269Smckusick 39917931Smckusick pfatal("INTERNAL INCONSISTENCY:"); 40017931Smckusick errexit(s); 40116269Smckusick } 40216269Smckusick #endif 403