|
|
1.1 root 1: /*
2: * general utility functions for phases of fsck
3: */
4:
5: #include "fsck.h"
6:
7: struct stat stats; /* Used by statit() */
8:
9: statit(name, probfun)
10: char *name;
11: int (*probfun)();
12: {
13:
14: if ( stat(name, &stats) == -1 ) {
15: bclear(&stats, sizeof(struct stat));
16: (*probfun)("Can not stat %s", name);
17: }
18: }
19:
20:
21: query(x)
22: {
23: while(1) {
24: printf("%r [yes/no]: ", &x);
25:
26: switch (daction) {
27: case YES:
28: printf("[default - YES]\n");
29: return(YES);
30: break;
31: case NO:
32: printf("[default - NO]\n");
33: return(NO);
34: break;
35: case ASK:
36: switch( nextchar() ) {
37: case 'Y':
38: return(YES);
39: case 'N':
40: return(NO);
41: }
42: }
43: }
44: }
45:
46: action(msg)
47: char *msg;
48: {
49: switch( query(msg) ) {
50: case YES:
51: return(TRUE);
52: case NO:
53: return(FALSE);
54: }
55: }
56:
57: char
58: nextchar()
59: {
60: char buff[8];
61: int i, n, ch;
62:
63: if ( ((n=read(0,buff,8)) <= 0) || (n == 8) )
64: fatal("Invalid Response");
65:
66: for(i=0; i<n; i++)
67: if ( ((ch=buff[i])!=' ') && (ch!='\t') )
68: break;
69:
70: if ( (ch>='a') && (ch<='z') )
71: ch += 'A' - 'a';
72:
73: return(ch);
74: }
75:
76: char *nfile = "FILE";
77: char *ndir = "DIR";
78: char *nchr = "Character Special";
79: char *nblk = "Block Special";
80: char *npipe = "PIPE";
81: char *nunkwn = "Unknown I-node type";
82:
83: char *
84: typename(ino)
85: ino_t ino;
86: {
87: switch( flags(ino)&MODEMASK ) {
88: case IREG:
89: return(nfile);
90: case IDIR:
91: return(ndir);
92: case ICHR:
93: return(nchr);
94: case IBLK:
95: return(nblk);
96: case IPIPE:
97: return(npipe);
98: default:
99: return(nunkwn);
100: }
101: }
102:
103: abort()
104: {
105: fatal("abort.");
106: }
107:
108: fatal(x)
109: {
110: printf("fsck: %r\n", &x);
111: _exit(1);
112: }
113:
114: nonfatal(x)
115: {
116: printf("fsck: %r\n", &x);
117: errflag = TRUE;
118: }
119:
120: /*
121: * Inode Manipulation Routines
122: * ptrino: returns a pointer to the wanted inode using the given
123: * buffer to read in the block performing canonicalization.
124: * writeino: writes the block containing the given inode to the
125: * disk performing the necessary canonicalization
126: * candino: canonicalize an inode
127: *
128: */
129:
130: struct dinode *
131: ptrino(ino, buf)
132: register ino_t ino;
133: register char *buf;
134: {
135: register daddr_t bn;
136: register struct dinode *dip;
137:
138: bn = iblockn(ino);
139: if ( (testblock(bn)) && (bn!=INODEI) ) /* bad inode block */
140: return(NULL);
141: bread(bn, buf);
142: dip = ((struct dinode *) buf) + iblocko(ino);
143: candino(dip);
144: return(dip);
145: }
146:
147: writeino(ino, buf)
148: ino_t ino;
149: char *buf;
150: {
151: struct dinode *dip;
152:
153: dip = ((struct dinode *) buf) + iblocko(ino);
154: candino(dip);
155: bwrite((daddr_t) iblockn(ino), buf);
156: }
157:
158: candino(dip)
159: register struct dinode *dip;
160: {
161: canshort(dip->di_mode);
162: canshort(dip->di_nlink);
163: canshort(dip->di_uid);
164: canshort(dip->di_gid);
165: cansize(dip->di_size);
166: cantime(dip->di_atime);
167: cantime(dip->di_mtime);
168: cantime(dip->di_ctime);
169: }
170:
171: /*
172: * Transfer a logical block number for an inode to a
173: * physical block number, chasing indirects as necessary.
174: * The inefficiency of this method is put up with since
175: * this is only used for directory inodes, and they tend
176: * not to use indirects. Pass in 'addrs' which is a pointer
177: * to the 13 daddr_s in the inode, and the logical block
178: * number you would like. (Stolen from dcheck.c)
179: */
180:
181: static daddr_t ranges[] = {
182: ND,
183: ND + (daddr_t)NI*NBN,
184: ND + (daddr_t)NI*NBN + (daddr_t)NII*NBN*NBN,
185: ND + (daddr_t)NI*NBN + (daddr_t)NII*NBN*NBN + (daddr_t)NIII*NBN*NBN*NBN
186: };
187:
188: static char index[] = {
189: 0,
190: ND,
191: ND+NI,
192: ND+NI+NII
193: };
194:
195: static daddr_t coeff[] = {
196: 1, (daddr_t)NBN, (daddr_t)NBN*NBN, (daddr_t)NBN*NBN*NBN
197: };
198:
199: daddr_t
200: imap(addrs, block)
201: daddr_t *addrs;
202: register daddr_t block;
203: {
204: int i;
205: register daddr_t bpos;
206: register daddr_t *bp;
207: register daddr_t bn;
208:
209: for (i=0; i<4; i++)
210: if (block < ranges[i]) {
211: if (i != 0)
212: block -= ranges[i-1];
213: bpos = block/coeff[i];
214: block %= coeff[i];
215: bp = &addrs[(int)bpos + index[i]];
216: if ( (bn=*bp) != 0 ) {
217: /*
218: * Map through indirects here
219: */
220: while (i-- > 0) {
221: bread(bn, databuf);
222: bpos = block/coeff[i];
223: block %= coeff[i];
224: bp = (daddr_t *)databuf + bpos;
225: if ( (bn=*bp) == 0 )
226: break;
227: bn = *bp;
228: candaddr(bn);
229: }
230: }
231: return(bn);
232: }
233: return(0);
234: }
235:
236: /*
237: * Read the specified block number into the given buffer
238: */
239:
240: char *rgblkerr = "Out of Range Block number: %U (CONTINUE)";
241: char *skblkerr = "Can not Seek: Blk num: %U (CONTINUE)";
242: char *rdblkerr = "Can not Read: Blk num: %U (CONTINUE)";
243: char *wtblkerr = "Can not Write: Blk num: %U (CONTINUE)";
244:
245: bread(bn, buf)
246: register daddr_t bn;
247: register char *buf;
248: {
249: #ifdef DEBUG
250: printf("Reading block number: %ld\n", bn);
251: #endif
252: if (bn<0 || bn >= fsize )
253: switch( query(rgblkerr, bn) ) {
254: case YES:
255: bclear(buf, BSIZE);
256: return;
257: case NO:
258: abort();
259: }
260:
261: if ( (bn<isize) && getcache(bn, buf) ) {
262: #if DEBUG
263: bdump(buf);
264: #endif
265: return;
266: }
267:
268: if ( lseek(fsfd, (unsigned long)bn*BSIZE, 0) == (-1L) )
269: switch( query(skblkerr, bn) ) {
270: case YES:
271: bclear(buf, BSIZE);
272: return;
273: case NO:
274: abort();
275: }
276:
277: if ( read(fsfd, buf, BSIZE) != BSIZE )
278: switch( query(rdblkerr, bn) ) {
279: case YES:
280: bclear(buf, BSIZE);
281: return;
282: case NO:
283: abort();
284: }
285: #if DEBUG
286: bdump(buf);
287: #endif
288: }
289:
290: /*
291: * Write block number bn with data in buf
292: */
293:
294: bwrite(bn, buf)
295: daddr_t bn;
296: char *buf;
297: {
298: #ifdef DEBUG
299: printf("Writing block number: %ld\n", bn);
300: #endif
301: if (!writeflg)
302: return;
303:
304: if (bn<0 || bn>=fsize)
305: switch( query(rgblkerr, bn) ) {
306: case YES:
307: return;
308: case NO:
309: abort();
310: }
311:
312: if ( lseek(fsfd, (fsize_t)BSIZE*bn, 0) == (-1L) )
313: switch( query(skblkerr, bn) ) {
314: case YES:
315: return;
316: case NO:
317: abort();
318: }
319:
320: if ( write(fsfd, buf, BSIZE) != BSIZE )
321: switch( query(wtblkerr, bn) ) {
322: case YES:
323: return;
324: case NO:
325: abort();
326: }
327:
328: if ( bn <= isize )
329: chgcache(bn, buf);
330: changeflg = TRUE;
331: }
332:
333: /*
334: * i-node block area caching routines
335: */
336:
337: static char cache[NBLK * BSIZE];
338: static int low = 0; high = -1;
339:
340: getcache(bn, buf)
341: register daddr_t bn;
342: register char *buf;
343: {
344: int totsize;
345:
346: if ( bn > isize )
347: return(0);
348:
349: if ( (bn>=low) && (bn<=high) ) {
350: blkmove(buf, &cache[BSIZE * (bn-low)]);
351: return(1);
352: }
353:
354: low = bn;
355: if ( (high=bn+NBLK-1) > isize )
356: high = isize;
357: totsize = BSIZE * (high-low+1);
358:
359: if ( (lseek(fsfd, (unsigned long)bn*BSIZE, 0) == (-1L)) ||
360: (read(fsfd, cache, totsize) != totsize) ) {
361: low = 0; high = -1;
362: return(0);
363: }
364:
365: return( getcache(bn, buf) );
366: }
367:
368: chgcache(bn, buf)
369: register daddr_t bn;
370: register char *buf;
371: {
372: if ( (bn>=low) && (bn<=high) )
373: blkmove(&cache[BSIZE * (bn-low)], buf);
374: }
375:
376: blkmove(to, from)
377: register char *to, *from;
378: {
379: register int num=BSIZE;
380:
381: while ( num-- )
382: *to++= *from++;
383: }
384:
385: /*
386: * Clear the given block of memory
387: */
388:
389: bclear(bp, nb)
390: register char *bp;
391: register unsigned nb;
392: {
393: if (nb)
394: do {
395: *bp++ = 0;
396: } while (--nb);
397: }
398:
399:
400: /*
401: * Determine if the given block is bad
402: */
403:
404: bad(bn)
405: daddr_t bn;
406: {
407: if ( (bn >= isize) && (bn < fsize) )
408: return(GOOD);
409: else
410: return(BAD);
411: }
412:
413:
414: #if DEBUG
415:
416: /*
417: * Debug dump a block of data.
418: */
419:
420: #define NUMPLIN 16
421:
422: bdump(buf)
423: register unsigned char *buf;
424: {
425: register int i;
426:
427: for (i=0; i<BSIZE; i++) {
428: if ( (i % NUMPLIN) == 0 )
429: printf("\n0x%04x: ", i);
430: printf(" %02x", *buf++);
431: }
432: printf("\n\n");
433: }
434:
435: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.