date and time created 87/10/22 10:11:57 by bostic
[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
315f1422 8static char sccsid[] = "@(#)inode.c 5.3 (Berkeley) %G%";
76797561 9#endif not lint
7026cd3f 10
1ccd95ec 11#include <pwd.h>
7026cd3f
KM
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
18ckinode(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
7026cd3f
KM
26 idesc->id_fix = DONTKNOW;
27 idesc->id_entryno = 0;
f0ed004a 28 idesc->id_filesize = dp->di_size;
f8a97eea
KM
29 if (SPECIAL(dp))
30 return (KEEPON);
31 dino = *dp;
7026cd3f
KM
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;
7718c0e6 50 for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) {
7026cd3f
KM
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
62iblock(idesc, ilevel, isize)
63 struct inodesc *idesc;
64 register ilevel;
65 long isize;
66{
67 register daddr_t *ap;
68 register daddr_t *aplim;
7718c0e6 69 int i, n, (*func)(), nif, sizepb;
7026cd3f 70 BUFAREA ib;
8f7c3c7e 71 char buf[BUFSIZ];
48a66bfb 72 extern int pass1check();
7026cd3f
KM
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);
49505034 83 getblk(&ib, idesc->id_blkno, sblock.fs_bsize);
7026cd3f 84 ilevel--;
7718c0e6
KM
85 for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++)
86 sizepb *= NINDIR(&sblock);
87 nif = isize / sizepb + 1;
7026cd3f
KM
88 if (nif > NINDIR(&sblock))
89 nif = NINDIR(&sblock);
48a66bfb
KM
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;
8f7c3c7e
KM
95 sprintf(buf, "PARTIALLY TRUNCATED INODE I=%d",
96 idesc->id_number);
97 if (dofix(idesc, buf)) {
48a66bfb
KM
98 *ap = 0;
99 dirty(&ib);
100 }
101 }
102 flush(&dfile, &ib);
103 }
7026cd3f
KM
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)
7718c0e6 109 n = iblock(idesc, ilevel, isize - i * sizepb);
7026cd3f
KM
110 else
111 n = (*func)(idesc);
112 if (n & STOP)
113 return (n);
114 }
115 return (KEEPON);
116}
117
118outrange(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
151DINODE *
152ginode(inumber)
153 ino_t inumber;
154{
155 daddr_t iblk;
156 static ino_t startinum = 0; /* blk num of first in raw area */
157
39c18287
KM
158 if (inumber < ROOTINO || inumber > imax)
159 errexit("bad inode number %d to ginode\n", inumber);
7026cd3f
KM
160 if (startinum == 0 ||
161 inumber < startinum || inumber >= startinum + INOPB(&sblock)) {
162 iblk = itod(&sblock, inumber);
49505034 163 getblk(&inoblk, iblk, sblock.fs_bsize);
7026cd3f
KM
164 startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock);
165 }
166 return (&inoblk.b_un.b_dinode[inumber % INOPB(&sblock)]);
167}
168
169clri(idesc, s, flg)
170 register struct inodesc *idesc;
171 char *s;
172 int flg;
173{
174 register DINODE *dp;
175
39c18287 176 dp = ginode(idesc->id_number);
7026cd3f 177 if (flg == 1) {
7718c0e6 178 pwarn("%s %s", s, DIRCT(dp) ? "DIR" : "FILE");
7026cd3f
KM
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();
7026cd3f
KM
189 }
190}
191
3ad2f081
KM
192findname(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);
315f1422 200 return (STOP|FOUND);
3ad2f081
KM
201}
202
7026cd3f
KM
203findino(idesc)
204 struct inodesc *idesc;
205{
206 register DIRECT *dirp = idesc->id_dirp;
207
208 if (dirp->d_ino == 0)
209 return (KEEPON);
3ad2f081
KM
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;
315f1422 213 return (STOP|FOUND);
7026cd3f
KM
214 }
215 return (KEEPON);
216}
217
218pinode(ino)
219 ino_t ino;
220{
221 register DINODE *dp;
222 register char *p;
1ccd95ec 223 struct passwd *pw;
7026cd3f
KM
224 char *ctime();
225
226 printf(" I=%u ", ino);
39c18287 227 if (ino < ROOTINO || ino > imax)
7026cd3f 228 return;
39c18287 229 dp = ginode(ino);
7026cd3f 230 printf(" OWNER=");
1ccd95ec
KM
231 if ((pw = getpwuid((int)dp->di_uid)) != 0)
232 printf("%s ", pw->pw_name);
233 else
7026cd3f 234 printf("%d ", dp->di_uid);
7026cd3f
KM
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
243blkerr(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");
993a756c
KM
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 }
7026cd3f 269}
ebd05fde
KM
270
271/*
272 * allocate an unused inode
273 */
274ino_t
275allocino(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 */
321freeino(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}