xref: /csrg-svn/sbin/fsck/inode.c (revision 30354)
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[] = "@(#)inode.c	5.3 (Berkeley) 01/07/87";
9 #endif not lint
10 
11 #include <pwd.h>
12 #include <sys/param.h>
13 #include <sys/inode.h>
14 #include <sys/fs.h>
15 #include <sys/dir.h>
16 #include "fsck.h"
17 
18 ckinode(dp, idesc)
19 	DINODE *dp;
20 	register struct inodesc *idesc;
21 {
22 	register daddr_t *ap;
23 	int ret, n, ndb, offset;
24 	DINODE dino;
25 
26 	idesc->id_fix = DONTKNOW;
27 	idesc->id_entryno = 0;
28 	idesc->id_filesize = dp->di_size;
29 	if (SPECIAL(dp))
30 		return (KEEPON);
31 	dino = *dp;
32 	ndb = howmany(dino.di_size, sblock.fs_bsize);
33 	for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) {
34 		if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0)
35 			idesc->id_numfrags =
36 				numfrags(&sblock, fragroundup(&sblock, offset));
37 		else
38 			idesc->id_numfrags = sblock.fs_frag;
39 		if (*ap == 0)
40 			continue;
41 		idesc->id_blkno = *ap;
42 		if (idesc->id_type == ADDR)
43 			ret = (*idesc->id_func)(idesc);
44 		else
45 			ret = dirscan(idesc);
46 		if (ret & STOP)
47 			return (ret);
48 	}
49 	idesc->id_numfrags = sblock.fs_frag;
50 	for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) {
51 		if (*ap) {
52 			idesc->id_blkno = *ap;
53 			ret = iblock(idesc, n,
54 				dino.di_size - sblock.fs_bsize * NDADDR);
55 			if (ret & STOP)
56 				return (ret);
57 		}
58 	}
59 	return (KEEPON);
60 }
61 
62 iblock(idesc, ilevel, isize)
63 	struct inodesc *idesc;
64 	register ilevel;
65 	long isize;
66 {
67 	register daddr_t *ap;
68 	register daddr_t *aplim;
69 	int i, n, (*func)(), nif, sizepb;
70 	BUFAREA ib;
71 	char buf[BUFSIZ];
72 	extern int pass1check();
73 
74 	if (idesc->id_type == ADDR) {
75 		func = idesc->id_func;
76 		if (((n = (*func)(idesc)) & KEEPON) == 0)
77 			return (n);
78 	} else
79 		func = dirscan;
80 	if (outrange(idesc->id_blkno, idesc->id_numfrags)) /* protect thyself */
81 		return (SKIP);
82 	initbarea(&ib);
83 	getblk(&ib, idesc->id_blkno, sblock.fs_bsize);
84 	ilevel--;
85 	for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++)
86 		sizepb *= NINDIR(&sblock);
87 	nif = isize / sizepb + 1;
88 	if (nif > NINDIR(&sblock))
89 		nif = NINDIR(&sblock);
90 	if (idesc->id_func == pass1check && nif < NINDIR(&sblock)) {
91 		aplim = &ib.b_un.b_indir[NINDIR(&sblock)];
92 		for (ap = &ib.b_un.b_indir[nif]; ap < aplim; ap++) {
93 			if (*ap == 0)
94 				continue;
95 			sprintf(buf, "PARTIALLY TRUNCATED INODE I=%d",
96 				idesc->id_number);
97 			if (dofix(idesc, buf)) {
98 				*ap = 0;
99 				dirty(&ib);
100 			}
101 		}
102 		flush(&dfile, &ib);
103 	}
104 	aplim = &ib.b_un.b_indir[nif];
105 	for (ap = ib.b_un.b_indir, i = 1; ap < aplim; ap++, i++)
106 		if (*ap) {
107 			idesc->id_blkno = *ap;
108 			if (ilevel > 0)
109 				n = iblock(idesc, ilevel, isize - i * sizepb);
110 			else
111 				n = (*func)(idesc);
112 			if (n & STOP)
113 				return (n);
114 		}
115 	return (KEEPON);
116 }
117 
118 outrange(blk, cnt)
119 	daddr_t blk;
120 	int cnt;
121 {
122 	register int c;
123 
124 	if ((unsigned)(blk+cnt) > fmax)
125 		return (1);
126 	c = dtog(&sblock, blk);
127 	if (blk < cgdmin(&sblock, c)) {
128 		if ((blk+cnt) > cgsblock(&sblock, c)) {
129 			if (debug) {
130 				printf("blk %d < cgdmin %d;",
131 				    blk, cgdmin(&sblock, c));
132 				printf(" blk+cnt %d > cgsbase %d\n",
133 				    blk+cnt, cgsblock(&sblock, c));
134 			}
135 			return (1);
136 		}
137 	} else {
138 		if ((blk+cnt) > cgbase(&sblock, c+1)) {
139 			if (debug)  {
140 				printf("blk %d >= cgdmin %d;",
141 				    blk, cgdmin(&sblock, c));
142 				printf(" blk+cnt %d > sblock.fs_fpg %d\n",
143 				    blk+cnt, sblock.fs_fpg);
144 			}
145 			return (1);
146 		}
147 	}
148 	return (0);
149 }
150 
151 DINODE *
152 ginode(inumber)
153 	ino_t inumber;
154 {
155 	daddr_t iblk;
156 	static ino_t startinum = 0;	/* blk num of first in raw area */
157 
158 	if (inumber < ROOTINO || inumber > imax)
159 		errexit("bad inode number %d to ginode\n", inumber);
160 	if (startinum == 0 ||
161 	    inumber < startinum || inumber >= startinum + INOPB(&sblock)) {
162 		iblk = itod(&sblock, inumber);
163 		getblk(&inoblk, iblk, sblock.fs_bsize);
164 		startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock);
165 	}
166 	return (&inoblk.b_un.b_dinode[inumber % INOPB(&sblock)]);
167 }
168 
169 clri(idesc, s, flg)
170 	register struct inodesc *idesc;
171 	char *s;
172 	int flg;
173 {
174 	register DINODE *dp;
175 
176 	dp = ginode(idesc->id_number);
177 	if (flg == 1) {
178 		pwarn("%s %s", s, DIRCT(dp) ? "DIR" : "FILE");
179 		pinode(idesc->id_number);
180 	}
181 	if (preen || reply("CLEAR") == 1) {
182 		if (preen)
183 			printf(" (CLEARED)\n");
184 		n_files--;
185 		(void)ckinode(dp, idesc);
186 		zapino(dp);
187 		statemap[idesc->id_number] = USTATE;
188 		inodirty();
189 	}
190 }
191 
192 findname(idesc)
193 	struct inodesc *idesc;
194 {
195 	register DIRECT *dirp = idesc->id_dirp;
196 
197 	if (dirp->d_ino != idesc->id_parent)
198 		return (KEEPON);
199 	bcopy(dirp->d_name, idesc->id_name, dirp->d_namlen + 1);
200 	return (STOP|FOUND);
201 }
202 
203 findino(idesc)
204 	struct inodesc *idesc;
205 {
206 	register DIRECT *dirp = idesc->id_dirp;
207 
208 	if (dirp->d_ino == 0)
209 		return (KEEPON);
210 	if (strcmp(dirp->d_name, idesc->id_name) == 0 &&
211 	    dirp->d_ino >= ROOTINO && dirp->d_ino <= imax) {
212 		idesc->id_parent = dirp->d_ino;
213 		return (STOP|FOUND);
214 	}
215 	return (KEEPON);
216 }
217 
218 pinode(ino)
219 	ino_t ino;
220 {
221 	register DINODE *dp;
222 	register char *p;
223 	struct passwd *pw;
224 	char *ctime();
225 
226 	printf(" I=%u ", ino);
227 	if (ino < ROOTINO || ino > imax)
228 		return;
229 	dp = ginode(ino);
230 	printf(" OWNER=");
231 	if ((pw = getpwuid((int)dp->di_uid)) != 0)
232 		printf("%s ", pw->pw_name);
233 	else
234 		printf("%d ", dp->di_uid);
235 	printf("MODE=%o\n", dp->di_mode);
236 	if (preen)
237 		printf("%s: ", devname);
238 	printf("SIZE=%ld ", dp->di_size);
239 	p = ctime(&dp->di_mtime);
240 	printf("MTIME=%12.12s %4.4s ", p+4, p+20);
241 }
242 
243 blkerr(ino, s, blk)
244 	ino_t ino;
245 	char *s;
246 	daddr_t blk;
247 {
248 
249 	pfatal("%ld %s I=%u", blk, s, ino);
250 	printf("\n");
251 	switch (statemap[ino]) {
252 
253 	case FSTATE:
254 		statemap[ino] = FCLEAR;
255 		return;
256 
257 	case DSTATE:
258 		statemap[ino] = DCLEAR;
259 		return;
260 
261 	case FCLEAR:
262 	case DCLEAR:
263 		return;
264 
265 	default:
266 		errexit("BAD STATE %d TO BLKERR", statemap[ino]);
267 		/* NOTREACHED */
268 	}
269 }
270 
271 /*
272  * allocate an unused inode
273  */
274 ino_t
275 allocino(request, type)
276 	ino_t request;
277 	int type;
278 {
279 	register ino_t ino;
280 	register DINODE *dp;
281 
282 	if (request == 0)
283 		request = ROOTINO;
284 	else if (statemap[request] != USTATE)
285 		return (0);
286 	for (ino = request; ino < imax; ino++)
287 		if (statemap[ino] == USTATE)
288 			break;
289 	if (ino == imax)
290 		return (0);
291 	switch (type & IFMT) {
292 	case IFDIR:
293 		statemap[ino] = DSTATE;
294 		break;
295 	case IFREG:
296 	case IFLNK:
297 		statemap[ino] = FSTATE;
298 		break;
299 	default:
300 		return (0);
301 	}
302 	dp = ginode(ino);
303 	dp->di_db[0] = allocblk(1);
304 	if (dp->di_db[0] == 0) {
305 		statemap[ino] = USTATE;
306 		return (0);
307 	}
308 	dp->di_mode = type;
309 	time(&dp->di_atime);
310 	dp->di_mtime = dp->di_ctime = dp->di_atime;
311 	dp->di_size = sblock.fs_fsize;
312 	dp->di_blocks = btodb(sblock.fs_fsize);
313 	n_files++;
314 	inodirty();
315 	return (ino);
316 }
317 
318 /*
319  * deallocate an inode
320  */
321 freeino(ino)
322 	ino_t ino;
323 {
324 	struct inodesc idesc;
325 	extern int pass4check();
326 	DINODE *dp;
327 
328 	bzero((char *)&idesc, sizeof(struct inodesc));
329 	idesc.id_type = ADDR;
330 	idesc.id_func = pass4check;
331 	idesc.id_number = ino;
332 	dp = ginode(ino);
333 	(void)ckinode(dp, &idesc);
334 	zapino(dp);
335 	inodirty();
336 	statemap[ino] = USTATE;
337 	n_files--;
338 }
339