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