xref: /csrg-svn/sbin/fsck/utilities.c (revision 17944)
1 #ifndef lint
2 static char version[] = "@(#)utilities.c	3.3 (Berkeley) 02/11/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 /*
182  * allocate a data block with the specified number of fragments
183  */
184 allocblk(frags)
185 	int frags;
186 {
187 	register int i, j, k;
188 
189 	if (frags <= 0 || frags > sblock.fs_frag)
190 		return (0);
191 	for (i = 0; i < fmax - sblock.fs_frag; i += sblock.fs_frag) {
192 		for (j = 0; j <= sblock.fs_frag - frags; j++) {
193 			if (getbmap(i + j))
194 				continue;
195 			for (k = 1; k < frags; k++)
196 				if (getbmap(i + j + k))
197 					break;
198 			if (k < frags) {
199 				j += k;
200 				continue;
201 			}
202 			for (k = 0; k < frags; k++)
203 				setbmap(i + j + k);
204 			n_blks += frags;
205 			return (i + j);
206 		}
207 	}
208 	return (0);
209 }
210 
211 /*
212  * Free a previously allocated block
213  */
214 freeblk(blkno, frags)
215 	daddr_t blkno;
216 	int frags;
217 {
218 	struct inodesc idesc;
219 
220 	idesc.id_blkno = blkno;
221 	idesc.id_numfrags = frags;
222 	pass4check(&idesc);
223 }
224 
225 catch()
226 {
227 
228 	ckfini();
229 	exit(12);
230 }
231 
232 /*
233  * determine whether an inode should be fixed.
234  */
235 dofix(idesc, msg)
236 	register struct inodesc *idesc;
237 	char *msg;
238 {
239 
240 	switch (idesc->id_fix) {
241 
242 	case DONTKNOW:
243 		if (idesc->id_type == DATA)
244 			direrr(idesc->id_number, msg);
245 		else
246 			pwarn(msg);
247 		if (preen) {
248 			printf(" (SALVAGED)\n");
249 			idesc->id_fix = FIX;
250 			return (ALTERED);
251 		}
252 		if (reply("SALVAGE") == 0) {
253 			idesc->id_fix = NOFIX;
254 			return (0);
255 		}
256 		idesc->id_fix = FIX;
257 		return (ALTERED);
258 
259 	case FIX:
260 		return (ALTERED);
261 
262 	case NOFIX:
263 		return (0);
264 
265 	default:
266 		errexit("UNKNOWN INODESC FIX MODE %d\n", idesc->id_fix);
267 	}
268 	/* NOTREACHED */
269 }
270 
271 /* VARARGS1 */
272 errexit(s1, s2, s3, s4)
273 	char *s1;
274 {
275 	printf(s1, s2, s3, s4);
276 	exit(8);
277 }
278 
279 /*
280  * An inconsistency occured which shouldn't during normal operations.
281  * Die if preening, otherwise just printf.
282  */
283 /* VARARGS1 */
284 pfatal(s, a1, a2, a3)
285 	char *s;
286 {
287 
288 	if (preen) {
289 		printf("%s: ", devname);
290 		printf(s, a1, a2, a3);
291 		printf("\n");
292 		printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n",
293 			devname);
294 		exit(8);
295 	}
296 	printf(s, a1, a2, a3);
297 }
298 
299 /*
300  * Pwarn is like printf when not preening,
301  * or a warning (preceded by filename) when preening.
302  */
303 /* VARARGS1 */
304 pwarn(s, a1, a2, a3, a4, a5, a6)
305 	char *s;
306 {
307 
308 	if (preen)
309 		printf("%s: ", devname);
310 	printf(s, a1, a2, a3, a4, a5, a6);
311 }
312 
313 #ifndef lint
314 /*
315  * Stub for routines from kernel.
316  */
317 panic(s)
318 	char *s;
319 {
320 
321 	pfatal("INTERNAL INCONSISTENCY:");
322 	errexit(s);
323 }
324 #endif
325