1 #ifndef lint 2 static char version[] = "@(#)utilities.c 3.4 (Berkeley) 02/15/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 <sys/dir.h> 11 #include "fsck.h" 12 13 long lseek(); 14 15 ftypeok(dp) 16 DINODE *dp; 17 { 18 switch (dp->di_mode & IFMT) { 19 20 case IFDIR: 21 case IFREG: 22 case IFBLK: 23 case IFCHR: 24 case IFLNK: 25 case IFSOCK: 26 return (1); 27 28 default: 29 if (debug) 30 printf("bad file type 0%o\n", dp->di_mode); 31 return (0); 32 } 33 } 34 35 reply(s) 36 char *s; 37 { 38 char line[80]; 39 40 if (preen) 41 pfatal("INTERNAL ERROR: GOT TO reply()"); 42 printf("\n%s? ", s); 43 if (nflag || dfile.wfdes < 0) { 44 printf(" no\n\n"); 45 return (0); 46 } 47 if (yflag) { 48 printf(" yes\n\n"); 49 return (1); 50 } 51 if (getline(stdin, line, sizeof(line)) == EOF) 52 errexit("\n"); 53 printf("\n"); 54 if (line[0] == 'y' || line[0] == 'Y') 55 return (1); 56 else 57 return (0); 58 } 59 60 getline(fp, loc, maxlen) 61 FILE *fp; 62 char *loc; 63 { 64 register n; 65 register char *p, *lastloc; 66 67 p = loc; 68 lastloc = &p[maxlen-1]; 69 while ((n = getc(fp)) != '\n') { 70 if (n == EOF) 71 return (EOF); 72 if (!isspace(n) && p < lastloc) 73 *p++ = n; 74 } 75 *p = 0; 76 return (p - loc); 77 } 78 79 BUFAREA * 80 getblk(bp, blk, size) 81 register BUFAREA *bp; 82 daddr_t blk; 83 long size; 84 { 85 register struct filecntl *fcp; 86 daddr_t dblk; 87 88 fcp = &dfile; 89 dblk = fsbtodb(&sblock, blk); 90 if (bp->b_bno == dblk) 91 return (bp); 92 flush(fcp, bp); 93 if (bread(fcp, bp->b_un.b_buf, dblk, size) != 0) { 94 bp->b_bno = dblk; 95 bp->b_size = size; 96 return (bp); 97 } 98 bp->b_bno = (daddr_t)-1; 99 return (NULL); 100 } 101 102 flush(fcp, bp) 103 struct filecntl *fcp; 104 register BUFAREA *bp; 105 { 106 register int i, j; 107 108 if (!bp->b_dirty) 109 return; 110 bp->b_dirty = 0; 111 (void)bwrite(fcp, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size); 112 if (bp != &sblk) 113 return; 114 for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { 115 (void)bwrite(&dfile, (char *)sblock.fs_csp[j], 116 fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), 117 sblock.fs_cssize - i < sblock.fs_bsize ? 118 sblock.fs_cssize - i : sblock.fs_bsize); 119 } 120 } 121 122 rwerr(s, blk) 123 char *s; 124 daddr_t blk; 125 { 126 127 if (preen == 0) 128 printf("\n"); 129 pfatal("CANNOT %s: BLK %ld", s, blk); 130 if (reply("CONTINUE") == 0) 131 errexit("Program terminated\n"); 132 } 133 134 ckfini() 135 { 136 137 flush(&dfile, &fileblk); 138 flush(&dfile, &sblk); 139 if (sblk.b_bno != SBLOCK) { 140 sblk.b_bno = SBLOCK; 141 sbdirty(); 142 flush(&dfile, &sblk); 143 } 144 flush(&dfile, &inoblk); 145 (void)close(dfile.rfdes); 146 (void)close(dfile.wfdes); 147 } 148 149 bread(fcp, buf, blk, size) 150 register struct filecntl *fcp; 151 char *buf; 152 daddr_t blk; 153 long size; 154 { 155 if (lseek(fcp->rfdes, (long)dbtob(blk), 0) < 0) 156 rwerr("SEEK", blk); 157 else if (read(fcp->rfdes, buf, (int)size) == size) 158 return (1); 159 rwerr("READ", blk); 160 return (0); 161 } 162 163 bwrite(fcp, buf, blk, size) 164 register struct filecntl *fcp; 165 char *buf; 166 daddr_t blk; 167 long size; 168 { 169 170 if (fcp->wfdes < 0) 171 return (0); 172 if (lseek(fcp->wfdes, (long)dbtob(blk), 0) < 0) 173 rwerr("SEEK", blk); 174 else if (write(fcp->wfdes, buf, (int)size) == size) { 175 fcp->mod = 1; 176 return (1); 177 } 178 rwerr("WRITE", blk); 179 return (0); 180 } 181 182 /* 183 * allocate a data block with the specified number of fragments 184 */ 185 allocblk(frags) 186 int frags; 187 { 188 register int i, j, k; 189 190 if (frags <= 0 || frags > sblock.fs_frag) 191 return (0); 192 for (i = 0; i < fmax - sblock.fs_frag; i += sblock.fs_frag) { 193 for (j = 0; j <= sblock.fs_frag - frags; j++) { 194 if (getbmap(i + j)) 195 continue; 196 for (k = 1; k < frags; k++) 197 if (getbmap(i + j + k)) 198 break; 199 if (k < frags) { 200 j += k; 201 continue; 202 } 203 for (k = 0; k < frags; k++) 204 setbmap(i + j + k); 205 n_blks += frags; 206 return (i + j); 207 } 208 } 209 return (0); 210 } 211 212 /* 213 * Free a previously allocated block 214 */ 215 freeblk(blkno, frags) 216 daddr_t blkno; 217 int frags; 218 { 219 struct inodesc idesc; 220 221 idesc.id_blkno = blkno; 222 idesc.id_numfrags = frags; 223 pass4check(&idesc); 224 } 225 226 /* 227 * Find a pathname 228 */ 229 getpathname(namebuf, curdir, ino) 230 char *namebuf; 231 ino_t curdir, ino; 232 { 233 int len; 234 register char *cp; 235 struct inodesc idesc; 236 extern int findname(); 237 238 if (statemap[ino] != DSTATE && statemap[ino] != DFOUND) { 239 strcpy(namebuf, "?"); 240 return; 241 } 242 bzero(&idesc, sizeof(struct inodesc)); 243 idesc.id_type = DATA; 244 cp = &namebuf[BUFSIZ - 1]; 245 *cp-- = '\0'; 246 if (curdir != ino) { 247 idesc.id_parent = curdir; 248 goto namelookup; 249 } 250 while (ino != ROOTINO) { 251 idesc.id_number = ino; 252 idesc.id_func = findino; 253 idesc.id_name = ".."; 254 if ((ckinode(ginode(ino), &idesc) & STOP) == 0) 255 break; 256 namelookup: 257 idesc.id_number = idesc.id_parent; 258 idesc.id_parent = ino; 259 idesc.id_func = findname; 260 idesc.id_name = namebuf; 261 if ((ckinode(ginode(idesc.id_number), &idesc) & STOP) == 0) 262 break; 263 len = strlen(namebuf); 264 cp -= len; 265 if (cp < &namebuf[MAXNAMLEN]) 266 break; 267 bcopy(namebuf, cp, len); 268 *--cp = '/'; 269 ino = idesc.id_number; 270 } 271 if (ino != ROOTINO) { 272 strcpy(namebuf, "?"); 273 return; 274 } 275 bcopy(cp, namebuf, &namebuf[BUFSIZ] - cp); 276 } 277 278 catch() 279 { 280 281 ckfini(); 282 exit(12); 283 } 284 285 /* 286 * determine whether an inode should be fixed. 287 */ 288 dofix(idesc, msg) 289 register struct inodesc *idesc; 290 char *msg; 291 { 292 293 switch (idesc->id_fix) { 294 295 case DONTKNOW: 296 if (idesc->id_type == DATA) 297 direrr(idesc->id_number, msg); 298 else 299 pwarn(msg); 300 if (preen) { 301 printf(" (SALVAGED)\n"); 302 idesc->id_fix = FIX; 303 return (ALTERED); 304 } 305 if (reply("SALVAGE") == 0) { 306 idesc->id_fix = NOFIX; 307 return (0); 308 } 309 idesc->id_fix = FIX; 310 return (ALTERED); 311 312 case FIX: 313 return (ALTERED); 314 315 case NOFIX: 316 return (0); 317 318 default: 319 errexit("UNKNOWN INODESC FIX MODE %d\n", idesc->id_fix); 320 } 321 /* NOTREACHED */ 322 } 323 324 /* VARARGS1 */ 325 errexit(s1, s2, s3, s4) 326 char *s1; 327 { 328 printf(s1, s2, s3, s4); 329 exit(8); 330 } 331 332 /* 333 * An inconsistency occured which shouldn't during normal operations. 334 * Die if preening, otherwise just printf. 335 */ 336 /* VARARGS1 */ 337 pfatal(s, a1, a2, a3) 338 char *s; 339 { 340 341 if (preen) { 342 printf("%s: ", devname); 343 printf(s, a1, a2, a3); 344 printf("\n"); 345 printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", 346 devname); 347 exit(8); 348 } 349 printf(s, a1, a2, a3); 350 } 351 352 /* 353 * Pwarn is like printf when not preening, 354 * or a warning (preceded by filename) when preening. 355 */ 356 /* VARARGS1 */ 357 pwarn(s, a1, a2, a3, a4, a5, a6) 358 char *s; 359 { 360 361 if (preen) 362 printf("%s: ", devname); 363 printf(s, a1, a2, a3, a4, a5, a6); 364 } 365 366 #ifndef lint 367 /* 368 * Stub for routines from kernel. 369 */ 370 panic(s) 371 char *s; 372 { 373 374 pfatal("INTERNAL INCONSISTENCY:"); 375 errexit(s); 376 } 377 #endif 378