1 #ifndef lint 2 static char version[] = "@(#)utilities.c 3.3 (Berkeley) 02/11/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 /* 182 * allocate a data block with the specified number of fragments 183 */ 184 allocblk(frags) 185 int frags; 186 { 187 register int i, j, k; 188 189 if (frags <= 0 || frags > sblock.fs_frag) 190 return (0); 191 for (i = 0; i < fmax - sblock.fs_frag; i += sblock.fs_frag) { 192 for (j = 0; j <= sblock.fs_frag - frags; j++) { 193 if (getbmap(i + j)) 194 continue; 195 for (k = 1; k < frags; k++) 196 if (getbmap(i + j + k)) 197 break; 198 if (k < frags) { 199 j += k; 200 continue; 201 } 202 for (k = 0; k < frags; k++) 203 setbmap(i + j + k); 204 n_blks += frags; 205 return (i + j); 206 } 207 } 208 return (0); 209 } 210 211 /* 212 * Free a previously allocated block 213 */ 214 freeblk(blkno, frags) 215 daddr_t blkno; 216 int frags; 217 { 218 struct inodesc idesc; 219 220 idesc.id_blkno = blkno; 221 idesc.id_numfrags = frags; 222 pass4check(&idesc); 223 } 224 225 catch() 226 { 227 228 ckfini(); 229 exit(12); 230 } 231 232 /* 233 * determine whether an inode should be fixed. 234 */ 235 dofix(idesc, msg) 236 register struct inodesc *idesc; 237 char *msg; 238 { 239 240 switch (idesc->id_fix) { 241 242 case DONTKNOW: 243 if (idesc->id_type == DATA) 244 direrr(idesc->id_number, msg); 245 else 246 pwarn(msg); 247 if (preen) { 248 printf(" (SALVAGED)\n"); 249 idesc->id_fix = FIX; 250 return (ALTERED); 251 } 252 if (reply("SALVAGE") == 0) { 253 idesc->id_fix = NOFIX; 254 return (0); 255 } 256 idesc->id_fix = FIX; 257 return (ALTERED); 258 259 case FIX: 260 return (ALTERED); 261 262 case NOFIX: 263 return (0); 264 265 default: 266 errexit("UNKNOWN INODESC FIX MODE %d\n", idesc->id_fix); 267 } 268 /* NOTREACHED */ 269 } 270 271 /* VARARGS1 */ 272 errexit(s1, s2, s3, s4) 273 char *s1; 274 { 275 printf(s1, s2, s3, s4); 276 exit(8); 277 } 278 279 /* 280 * An inconsistency occured which shouldn't during normal operations. 281 * Die if preening, otherwise just printf. 282 */ 283 /* VARARGS1 */ 284 pfatal(s, a1, a2, a3) 285 char *s; 286 { 287 288 if (preen) { 289 printf("%s: ", devname); 290 printf(s, a1, a2, a3); 291 printf("\n"); 292 printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", 293 devname); 294 exit(8); 295 } 296 printf(s, a1, a2, a3); 297 } 298 299 /* 300 * Pwarn is like printf when not preening, 301 * or a warning (preceded by filename) when preening. 302 */ 303 /* VARARGS1 */ 304 pwarn(s, a1, a2, a3, a4, a5, a6) 305 char *s; 306 { 307 308 if (preen) 309 printf("%s: ", devname); 310 printf(s, a1, a2, a3, a4, a5, a6); 311 } 312 313 #ifndef lint 314 /* 315 * Stub for routines from kernel. 316 */ 317 panic(s) 318 char *s; 319 { 320 321 pfatal("INTERNAL INCONSISTENCY:"); 322 errexit(s); 323 } 324 #endif 325