1 #ifndef lint 2 static char version[] = "@(#)utilities.c 3.2 (Berkeley) 02/07/85"; 3 #endif 4 5 #include <stdio.h> 6 #include <ctype.h> 7 #include <sys/param.h> 8 #include <sys/inode.h> 9 #include <sys/fs.h> 10 #include "fsck.h" 11 12 long lseek(); 13 14 ftypeok(dp) 15 DINODE *dp; 16 { 17 switch (dp->di_mode & IFMT) { 18 19 case IFDIR: 20 case IFREG: 21 case IFBLK: 22 case IFCHR: 23 case IFLNK: 24 case IFSOCK: 25 return (1); 26 27 default: 28 if (debug) 29 printf("bad file type 0%o\n", dp->di_mode); 30 return (0); 31 } 32 } 33 34 reply(s) 35 char *s; 36 { 37 char line[80]; 38 39 if (preen) 40 pfatal("INTERNAL ERROR: GOT TO reply()"); 41 printf("\n%s? ", s); 42 if (nflag || dfile.wfdes < 0) { 43 printf(" no\n\n"); 44 return (0); 45 } 46 if (yflag) { 47 printf(" yes\n\n"); 48 return (1); 49 } 50 if (getline(stdin, line, sizeof(line)) == EOF) 51 errexit("\n"); 52 printf("\n"); 53 if (line[0] == 'y' || line[0] == 'Y') 54 return (1); 55 else 56 return (0); 57 } 58 59 getline(fp, loc, maxlen) 60 FILE *fp; 61 char *loc; 62 { 63 register n; 64 register char *p, *lastloc; 65 66 p = loc; 67 lastloc = &p[maxlen-1]; 68 while ((n = getc(fp)) != '\n') { 69 if (n == EOF) 70 return (EOF); 71 if (!isspace(n) && p < lastloc) 72 *p++ = n; 73 } 74 *p = 0; 75 return (p - loc); 76 } 77 78 BUFAREA * 79 getblk(bp, blk, size) 80 register BUFAREA *bp; 81 daddr_t blk; 82 long size; 83 { 84 register struct filecntl *fcp; 85 daddr_t dblk; 86 87 fcp = &dfile; 88 dblk = fsbtodb(&sblock, blk); 89 if (bp->b_bno == dblk) 90 return (bp); 91 flush(fcp, bp); 92 if (bread(fcp, bp->b_un.b_buf, dblk, size) != 0) { 93 bp->b_bno = dblk; 94 bp->b_size = size; 95 return (bp); 96 } 97 bp->b_bno = (daddr_t)-1; 98 return (NULL); 99 } 100 101 flush(fcp, bp) 102 struct filecntl *fcp; 103 register BUFAREA *bp; 104 { 105 register int i, j; 106 107 if (!bp->b_dirty) 108 return; 109 bp->b_dirty = 0; 110 (void)bwrite(fcp, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size); 111 if (bp != &sblk) 112 return; 113 for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { 114 (void)bwrite(&dfile, (char *)sblock.fs_csp[j], 115 fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), 116 sblock.fs_cssize - i < sblock.fs_bsize ? 117 sblock.fs_cssize - i : sblock.fs_bsize); 118 } 119 } 120 121 rwerr(s, blk) 122 char *s; 123 daddr_t blk; 124 { 125 126 if (preen == 0) 127 printf("\n"); 128 pfatal("CANNOT %s: BLK %ld", s, blk); 129 if (reply("CONTINUE") == 0) 130 errexit("Program terminated\n"); 131 } 132 133 ckfini() 134 { 135 136 flush(&dfile, &fileblk); 137 flush(&dfile, &sblk); 138 if (sblk.b_bno != SBLOCK) { 139 sblk.b_bno = SBLOCK; 140 sbdirty(); 141 flush(&dfile, &sblk); 142 } 143 flush(&dfile, &inoblk); 144 (void)close(dfile.rfdes); 145 (void)close(dfile.wfdes); 146 } 147 148 bread(fcp, buf, blk, size) 149 register struct filecntl *fcp; 150 char *buf; 151 daddr_t blk; 152 long size; 153 { 154 if (lseek(fcp->rfdes, (long)dbtob(blk), 0) < 0) 155 rwerr("SEEK", blk); 156 else if (read(fcp->rfdes, buf, (int)size) == size) 157 return (1); 158 rwerr("READ", blk); 159 return (0); 160 } 161 162 bwrite(fcp, buf, blk, size) 163 register struct filecntl *fcp; 164 char *buf; 165 daddr_t blk; 166 long size; 167 { 168 169 if (fcp->wfdes < 0) 170 return (0); 171 if (lseek(fcp->wfdes, (long)dbtob(blk), 0) < 0) 172 rwerr("SEEK", blk); 173 else if (write(fcp->wfdes, buf, (int)size) == size) { 174 fcp->mod = 1; 175 return (1); 176 } 177 rwerr("WRITE", blk); 178 return (0); 179 } 180 181 catch() 182 { 183 184 ckfini(); 185 exit(12); 186 } 187 188 /* 189 * determine whether an inode should be fixed. 190 */ 191 dofix(idesc, msg) 192 register struct inodesc *idesc; 193 char *msg; 194 { 195 196 switch (idesc->id_fix) { 197 198 case DONTKNOW: 199 if (idesc->id_type == DATA) 200 direrr(idesc->id_number, msg); 201 else 202 pwarn(msg); 203 if (preen) { 204 printf(" (SALVAGED)\n"); 205 idesc->id_fix = FIX; 206 return (ALTERED); 207 } 208 if (reply("SALVAGE") == 0) { 209 idesc->id_fix = NOFIX; 210 return (0); 211 } 212 idesc->id_fix = FIX; 213 return (ALTERED); 214 215 case FIX: 216 return (ALTERED); 217 218 case NOFIX: 219 return (0); 220 221 default: 222 errexit("UNKNOWN INODESC FIX MODE %d\n", idesc->id_fix); 223 } 224 /* NOTREACHED */ 225 } 226 227 /* VARARGS1 */ 228 errexit(s1, s2, s3, s4) 229 char *s1; 230 { 231 printf(s1, s2, s3, s4); 232 exit(8); 233 } 234 235 /* 236 * An inconsistency occured which shouldn't during normal operations. 237 * Die if preening, otherwise just printf. 238 */ 239 /* VARARGS1 */ 240 pfatal(s, a1, a2, a3) 241 char *s; 242 { 243 244 if (preen) { 245 printf("%s: ", devname); 246 printf(s, a1, a2, a3); 247 printf("\n"); 248 printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", 249 devname); 250 exit(8); 251 } 252 printf(s, a1, a2, a3); 253 } 254 255 /* 256 * Pwarn is like printf when not preening, 257 * or a warning (preceded by filename) when preening. 258 */ 259 /* VARARGS1 */ 260 pwarn(s, a1, a2, a3, a4, a5, a6) 261 char *s; 262 { 263 264 if (preen) 265 printf("%s: ", devname); 266 printf(s, a1, a2, a3, a4, a5, a6); 267 } 268 269 #ifndef lint 270 /* 271 * Stub for routines from kernel. 272 */ 273 panic(s) 274 char *s; 275 { 276 277 pfatal("INTERNAL INCONSISTENCY:"); 278 errexit(s); 279 } 280 #endif 281