116269Smckusick #ifndef lint 2*17944Smckusick static char version[] = "@(#)utilities.c 3.3 (Berkeley) 02/11/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> 1016269Smckusick #include "fsck.h" 1116269Smckusick 1216269Smckusick long lseek(); 1316269Smckusick 1416269Smckusick ftypeok(dp) 1516269Smckusick DINODE *dp; 1616269Smckusick { 1716269Smckusick switch (dp->di_mode & IFMT) { 1816269Smckusick 1916269Smckusick case IFDIR: 2016269Smckusick case IFREG: 2116269Smckusick case IFBLK: 2216269Smckusick case IFCHR: 2316269Smckusick case IFLNK: 2416269Smckusick case IFSOCK: 2516269Smckusick return (1); 2616269Smckusick 2716269Smckusick default: 2816269Smckusick if (debug) 2916269Smckusick printf("bad file type 0%o\n", dp->di_mode); 3016269Smckusick return (0); 3116269Smckusick } 3216269Smckusick } 3316269Smckusick 3416269Smckusick reply(s) 3516269Smckusick char *s; 3616269Smckusick { 3716269Smckusick char line[80]; 3816269Smckusick 3916269Smckusick if (preen) 4016269Smckusick pfatal("INTERNAL ERROR: GOT TO reply()"); 4116269Smckusick printf("\n%s? ", s); 4216269Smckusick if (nflag || dfile.wfdes < 0) { 4316269Smckusick printf(" no\n\n"); 4416269Smckusick return (0); 4516269Smckusick } 4616269Smckusick if (yflag) { 4716269Smckusick printf(" yes\n\n"); 4816269Smckusick return (1); 4916269Smckusick } 5016269Smckusick if (getline(stdin, line, sizeof(line)) == EOF) 5116269Smckusick errexit("\n"); 5216269Smckusick printf("\n"); 5316269Smckusick if (line[0] == 'y' || line[0] == 'Y') 5416269Smckusick return (1); 5516269Smckusick else 5616269Smckusick return (0); 5716269Smckusick } 5816269Smckusick 5916269Smckusick getline(fp, loc, maxlen) 6016269Smckusick FILE *fp; 6116269Smckusick char *loc; 6216269Smckusick { 6316269Smckusick register n; 6416269Smckusick register char *p, *lastloc; 6516269Smckusick 6616269Smckusick p = loc; 6716269Smckusick lastloc = &p[maxlen-1]; 6816269Smckusick while ((n = getc(fp)) != '\n') { 6916269Smckusick if (n == EOF) 7016269Smckusick return (EOF); 7116269Smckusick if (!isspace(n) && p < lastloc) 7216269Smckusick *p++ = n; 7316269Smckusick } 7416269Smckusick *p = 0; 7516269Smckusick return (p - loc); 7616269Smckusick } 7716269Smckusick 7816269Smckusick BUFAREA * 7916269Smckusick getblk(bp, blk, size) 8016269Smckusick register BUFAREA *bp; 8116269Smckusick daddr_t blk; 8216269Smckusick long size; 8316269Smckusick { 8416269Smckusick register struct filecntl *fcp; 8516269Smckusick daddr_t dblk; 8616269Smckusick 8716269Smckusick fcp = &dfile; 8816269Smckusick dblk = fsbtodb(&sblock, blk); 8916269Smckusick if (bp->b_bno == dblk) 9016269Smckusick return (bp); 9116269Smckusick flush(fcp, bp); 9216269Smckusick if (bread(fcp, bp->b_un.b_buf, dblk, size) != 0) { 9316269Smckusick bp->b_bno = dblk; 9416269Smckusick bp->b_size = size; 9516269Smckusick return (bp); 9616269Smckusick } 9716269Smckusick bp->b_bno = (daddr_t)-1; 9816269Smckusick return (NULL); 9916269Smckusick } 10016269Smckusick 10116269Smckusick flush(fcp, bp) 10216269Smckusick struct filecntl *fcp; 10316269Smckusick register BUFAREA *bp; 10416269Smckusick { 10517931Smckusick register int i, j; 10616269Smckusick 10717931Smckusick if (!bp->b_dirty) 10817931Smckusick return; 10916269Smckusick bp->b_dirty = 0; 11017931Smckusick (void)bwrite(fcp, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size); 11117931Smckusick if (bp != &sblk) 11217931Smckusick return; 11317931Smckusick for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { 11417931Smckusick (void)bwrite(&dfile, (char *)sblock.fs_csp[j], 11517931Smckusick fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), 11617931Smckusick sblock.fs_cssize - i < sblock.fs_bsize ? 11717931Smckusick sblock.fs_cssize - i : sblock.fs_bsize); 11817931Smckusick } 11916269Smckusick } 12016269Smckusick 12116269Smckusick rwerr(s, blk) 12216269Smckusick char *s; 12316269Smckusick daddr_t blk; 12416269Smckusick { 12516269Smckusick 12616269Smckusick if (preen == 0) 12716269Smckusick printf("\n"); 12816269Smckusick pfatal("CANNOT %s: BLK %ld", s, blk); 12916269Smckusick if (reply("CONTINUE") == 0) 13016269Smckusick errexit("Program terminated\n"); 13116269Smckusick } 13216269Smckusick 13316269Smckusick ckfini() 13416269Smckusick { 13516269Smckusick 13616269Smckusick flush(&dfile, &fileblk); 13716269Smckusick flush(&dfile, &sblk); 13816269Smckusick if (sblk.b_bno != SBLOCK) { 13916269Smckusick sblk.b_bno = SBLOCK; 14016269Smckusick sbdirty(); 14116269Smckusick flush(&dfile, &sblk); 14216269Smckusick } 14316269Smckusick flush(&dfile, &inoblk); 14416269Smckusick (void)close(dfile.rfdes); 14516269Smckusick (void)close(dfile.wfdes); 14616269Smckusick } 14716269Smckusick 14816269Smckusick bread(fcp, buf, blk, size) 14916269Smckusick register struct filecntl *fcp; 15016269Smckusick char *buf; 15116269Smckusick daddr_t blk; 15216269Smckusick long size; 15316269Smckusick { 15416269Smckusick if (lseek(fcp->rfdes, (long)dbtob(blk), 0) < 0) 15516269Smckusick rwerr("SEEK", blk); 15616269Smckusick else if (read(fcp->rfdes, buf, (int)size) == size) 15716269Smckusick return (1); 15816269Smckusick rwerr("READ", blk); 15916269Smckusick return (0); 16016269Smckusick } 16116269Smckusick 16216269Smckusick bwrite(fcp, buf, blk, size) 16316269Smckusick register struct filecntl *fcp; 16416269Smckusick char *buf; 16516269Smckusick daddr_t blk; 16616269Smckusick long size; 16716269Smckusick { 16816269Smckusick 16916269Smckusick if (fcp->wfdes < 0) 17016269Smckusick return (0); 17116269Smckusick if (lseek(fcp->wfdes, (long)dbtob(blk), 0) < 0) 17216269Smckusick rwerr("SEEK", blk); 17316269Smckusick else if (write(fcp->wfdes, buf, (int)size) == size) { 17416269Smckusick fcp->mod = 1; 17516269Smckusick return (1); 17616269Smckusick } 17716269Smckusick rwerr("WRITE", blk); 17816269Smckusick return (0); 17916269Smckusick } 18016269Smckusick 181*17944Smckusick /* 182*17944Smckusick * allocate a data block with the specified number of fragments 183*17944Smckusick */ 184*17944Smckusick allocblk(frags) 185*17944Smckusick int frags; 186*17944Smckusick { 187*17944Smckusick register int i, j, k; 188*17944Smckusick 189*17944Smckusick if (frags <= 0 || frags > sblock.fs_frag) 190*17944Smckusick return (0); 191*17944Smckusick for (i = 0; i < fmax - sblock.fs_frag; i += sblock.fs_frag) { 192*17944Smckusick for (j = 0; j <= sblock.fs_frag - frags; j++) { 193*17944Smckusick if (getbmap(i + j)) 194*17944Smckusick continue; 195*17944Smckusick for (k = 1; k < frags; k++) 196*17944Smckusick if (getbmap(i + j + k)) 197*17944Smckusick break; 198*17944Smckusick if (k < frags) { 199*17944Smckusick j += k; 200*17944Smckusick continue; 201*17944Smckusick } 202*17944Smckusick for (k = 0; k < frags; k++) 203*17944Smckusick setbmap(i + j + k); 204*17944Smckusick n_blks += frags; 205*17944Smckusick return (i + j); 206*17944Smckusick } 207*17944Smckusick } 208*17944Smckusick return (0); 209*17944Smckusick } 210*17944Smckusick 211*17944Smckusick /* 212*17944Smckusick * Free a previously allocated block 213*17944Smckusick */ 214*17944Smckusick freeblk(blkno, frags) 215*17944Smckusick daddr_t blkno; 216*17944Smckusick int frags; 217*17944Smckusick { 218*17944Smckusick struct inodesc idesc; 219*17944Smckusick 220*17944Smckusick idesc.id_blkno = blkno; 221*17944Smckusick idesc.id_numfrags = frags; 222*17944Smckusick pass4check(&idesc); 223*17944Smckusick } 224*17944Smckusick 22516269Smckusick catch() 22616269Smckusick { 22716269Smckusick 22816269Smckusick ckfini(); 22916269Smckusick exit(12); 23016269Smckusick } 23116269Smckusick 23216269Smckusick /* 23316269Smckusick * determine whether an inode should be fixed. 23416269Smckusick */ 23517931Smckusick dofix(idesc, msg) 23616269Smckusick register struct inodesc *idesc; 23717931Smckusick char *msg; 23816269Smckusick { 23916269Smckusick 24016269Smckusick switch (idesc->id_fix) { 24116269Smckusick 24216269Smckusick case DONTKNOW: 24317931Smckusick if (idesc->id_type == DATA) 24417931Smckusick direrr(idesc->id_number, msg); 24517931Smckusick else 24617931Smckusick pwarn(msg); 24717931Smckusick if (preen) { 24817931Smckusick printf(" (SALVAGED)\n"); 24917931Smckusick idesc->id_fix = FIX; 25017931Smckusick return (ALTERED); 25117931Smckusick } 25216269Smckusick if (reply("SALVAGE") == 0) { 25316269Smckusick idesc->id_fix = NOFIX; 25416269Smckusick return (0); 25516269Smckusick } 25616269Smckusick idesc->id_fix = FIX; 25716269Smckusick return (ALTERED); 25816269Smckusick 25916269Smckusick case FIX: 26016269Smckusick return (ALTERED); 26116269Smckusick 26216269Smckusick case NOFIX: 26316269Smckusick return (0); 26416269Smckusick 26516269Smckusick default: 26616269Smckusick errexit("UNKNOWN INODESC FIX MODE %d\n", idesc->id_fix); 26716269Smckusick } 26816269Smckusick /* NOTREACHED */ 26916269Smckusick } 27016269Smckusick 27116269Smckusick /* VARARGS1 */ 27217931Smckusick errexit(s1, s2, s3, s4) 27316269Smckusick char *s1; 27416269Smckusick { 27516269Smckusick printf(s1, s2, s3, s4); 27616269Smckusick exit(8); 27716269Smckusick } 27816269Smckusick 27916269Smckusick /* 28016269Smckusick * An inconsistency occured which shouldn't during normal operations. 28116269Smckusick * Die if preening, otherwise just printf. 28216269Smckusick */ 28316269Smckusick /* VARARGS1 */ 28416269Smckusick pfatal(s, a1, a2, a3) 28516269Smckusick char *s; 28616269Smckusick { 28716269Smckusick 28816269Smckusick if (preen) { 28916269Smckusick printf("%s: ", devname); 29016269Smckusick printf(s, a1, a2, a3); 29116269Smckusick printf("\n"); 29217931Smckusick printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", 29317931Smckusick devname); 29417931Smckusick exit(8); 29516269Smckusick } 29616269Smckusick printf(s, a1, a2, a3); 29716269Smckusick } 29816269Smckusick 29916269Smckusick /* 30016269Smckusick * Pwarn is like printf when not preening, 30116269Smckusick * or a warning (preceded by filename) when preening. 30216269Smckusick */ 30316269Smckusick /* VARARGS1 */ 30416269Smckusick pwarn(s, a1, a2, a3, a4, a5, a6) 30516269Smckusick char *s; 30616269Smckusick { 30716269Smckusick 30816269Smckusick if (preen) 30916269Smckusick printf("%s: ", devname); 31016269Smckusick printf(s, a1, a2, a3, a4, a5, a6); 31116269Smckusick } 31216269Smckusick 31316269Smckusick #ifndef lint 31416269Smckusick /* 31516269Smckusick * Stub for routines from kernel. 31616269Smckusick */ 31716269Smckusick panic(s) 31816269Smckusick char *s; 31916269Smckusick { 32016269Smckusick 32117931Smckusick pfatal("INTERNAL INCONSISTENCY:"); 32217931Smckusick errexit(s); 32316269Smckusick } 32416269Smckusick #endif 325