xref: /csrg-svn/sbin/fsck/utilities.c (revision 17931)
1 #ifndef lint
2 static char version[] = "@(#)utilities.c	3.2 (Berkeley) 02/07/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 catch()
182 {
183 
184 	ckfini();
185 	exit(12);
186 }
187 
188 /*
189  * determine whether an inode should be fixed.
190  */
191 dofix(idesc, msg)
192 	register struct inodesc *idesc;
193 	char *msg;
194 {
195 
196 	switch (idesc->id_fix) {
197 
198 	case DONTKNOW:
199 		if (idesc->id_type == DATA)
200 			direrr(idesc->id_number, msg);
201 		else
202 			pwarn(msg);
203 		if (preen) {
204 			printf(" (SALVAGED)\n");
205 			idesc->id_fix = FIX;
206 			return (ALTERED);
207 		}
208 		if (reply("SALVAGE") == 0) {
209 			idesc->id_fix = NOFIX;
210 			return (0);
211 		}
212 		idesc->id_fix = FIX;
213 		return (ALTERED);
214 
215 	case FIX:
216 		return (ALTERED);
217 
218 	case NOFIX:
219 		return (0);
220 
221 	default:
222 		errexit("UNKNOWN INODESC FIX MODE %d\n", idesc->id_fix);
223 	}
224 	/* NOTREACHED */
225 }
226 
227 /* VARARGS1 */
228 errexit(s1, s2, s3, s4)
229 	char *s1;
230 {
231 	printf(s1, s2, s3, s4);
232 	exit(8);
233 }
234 
235 /*
236  * An inconsistency occured which shouldn't during normal operations.
237  * Die if preening, otherwise just printf.
238  */
239 /* VARARGS1 */
240 pfatal(s, a1, a2, a3)
241 	char *s;
242 {
243 
244 	if (preen) {
245 		printf("%s: ", devname);
246 		printf(s, a1, a2, a3);
247 		printf("\n");
248 		printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n",
249 			devname);
250 		exit(8);
251 	}
252 	printf(s, a1, a2, a3);
253 }
254 
255 /*
256  * Pwarn is like printf when not preening,
257  * or a warning (preceded by filename) when preening.
258  */
259 /* VARARGS1 */
260 pwarn(s, a1, a2, a3, a4, a5, a6)
261 	char *s;
262 {
263 
264 	if (preen)
265 		printf("%s: ", devname);
266 	printf(s, a1, a2, a3, a4, a5, a6);
267 }
268 
269 #ifndef lint
270 /*
271  * Stub for routines from kernel.
272  */
273 panic(s)
274 	char *s;
275 {
276 
277 	pfatal("INTERNAL INCONSISTENCY:");
278 	errexit(s);
279 }
280 #endif
281