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