1 #ifndef lint 2 static char version[] = "@(#)utilities.c 3.1 (Berkeley) 03/31/84"; 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 rplyflag = 1; 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 107 if (bp->b_dirty) 108 (void)bwrite(fcp, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size); 109 bp->b_dirty = 0; 110 } 111 112 rwerr(s, blk) 113 char *s; 114 daddr_t blk; 115 { 116 117 if (preen == 0) 118 printf("\n"); 119 pfatal("CANNOT %s: BLK %ld", s, blk); 120 if (reply("CONTINUE") == 0) 121 errexit("Program terminated\n"); 122 } 123 124 ckfini() 125 { 126 127 flush(&dfile, &fileblk); 128 flush(&dfile, &sblk); 129 if (sblk.b_bno != SBLOCK) { 130 sblk.b_bno = SBLOCK; 131 sbdirty(); 132 flush(&dfile, &sblk); 133 } 134 flush(&dfile, &inoblk); 135 (void)close(dfile.rfdes); 136 (void)close(dfile.wfdes); 137 } 138 139 bread(fcp, buf, blk, size) 140 register struct filecntl *fcp; 141 char *buf; 142 daddr_t blk; 143 long size; 144 { 145 if (lseek(fcp->rfdes, (long)dbtob(blk), 0) < 0) 146 rwerr("SEEK", blk); 147 else if (read(fcp->rfdes, buf, (int)size) == size) 148 return (1); 149 rwerr("READ", blk); 150 return (0); 151 } 152 153 bwrite(fcp, buf, blk, size) 154 register struct filecntl *fcp; 155 char *buf; 156 daddr_t blk; 157 long size; 158 { 159 160 if (fcp->wfdes < 0) 161 return (0); 162 if (lseek(fcp->wfdes, (long)dbtob(blk), 0) < 0) 163 rwerr("SEEK", blk); 164 else if (write(fcp->wfdes, buf, (int)size) == size) { 165 fcp->mod = 1; 166 return (1); 167 } 168 rwerr("WRITE", blk); 169 return (0); 170 } 171 172 catch() 173 { 174 175 ckfini(); 176 exit(12); 177 } 178 179 /* 180 * determine whether an inode should be fixed. 181 */ 182 dofix(idesc) 183 register struct inodesc *idesc; 184 { 185 186 switch (idesc->id_fix) { 187 188 case DONTKNOW: 189 direrr(idesc->id_number, "DIRECTORY CORRUPTED"); 190 if (reply("SALVAGE") == 0) { 191 idesc->id_fix = NOFIX; 192 return (0); 193 } 194 idesc->id_fix = FIX; 195 return (ALTERED); 196 197 case FIX: 198 return (ALTERED); 199 200 case NOFIX: 201 return (0); 202 203 default: 204 errexit("UNKNOWN INODESC FIX MODE %d\n", idesc->id_fix); 205 } 206 /* NOTREACHED */ 207 } 208 209 /* VARARGS1 */ 210 error(s1, s2, s3, s4) 211 char *s1; 212 { 213 214 printf(s1, s2, s3, s4); 215 } 216 217 /* VARARGS1 */ 218 errexit(s1, s2, s3, s4) 219 char *s1; 220 { 221 error(s1, s2, s3, s4); 222 exit(8); 223 } 224 225 /* 226 * An inconsistency occured which shouldn't during normal operations. 227 * Die if preening, otherwise just printf. 228 */ 229 /* VARARGS1 */ 230 pfatal(s, a1, a2, a3) 231 char *s; 232 { 233 234 if (preen) { 235 printf("%s: ", devname); 236 printf(s, a1, a2, a3); 237 printf("\n"); 238 preendie(); 239 } 240 printf(s, a1, a2, a3); 241 } 242 243 preendie() 244 { 245 246 printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", devname); 247 exit(8); 248 } 249 250 /* 251 * Pwarn is like printf when not preening, 252 * or a warning (preceded by filename) when preening. 253 */ 254 /* VARARGS1 */ 255 pwarn(s, a1, a2, a3, a4, a5, a6) 256 char *s; 257 { 258 259 if (preen) 260 printf("%s: ", devname); 261 printf(s, a1, a2, a3, a4, a5, a6); 262 } 263 264 #ifndef lint 265 /* 266 * Stub for routines from kernel. 267 */ 268 panic(s) 269 char *s; 270 { 271 272 pfatal("INTERNAL INCONSISTENCY: %s\n", s); 273 exit(12); 274 } 275 #endif 276