Commit | Line | Data |
---|---|---|
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 | 8 | static 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 |
20 | BUFAREA *pbp = 0; |
21 | ||
7026cd3f KM |
22 | ckinode(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 | ||
66 | iblock(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 | ||
125 | outrange(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 | ||
158 | DINODE * | |
159 | ginode(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 | ||
178 | inodirty() | |
179 | { | |
180 | ||
181 | dirty(pbp); | |
7026cd3f KM |
182 | } |
183 | ||
184 | clri(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 |
207 | findname(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 |
218 | findino(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 | ||
233 | pinode(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 | ||
258 | blkerr(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 | */ | |
289 | ino_t | |
290 | allocino(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 | */ | |
336 | freeino(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 | } |