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