xref: /csrg-svn/sbin/fsck/utilities.c (revision 16269)
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