File: | src/sbin/fsck_ext2fs/inode.c |
Warning: | line 265, column 6 Value stored to 'isize' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: inode.c,v 1.29 2019/07/01 07:13:44 kevlo Exp $ */ |
2 | /* $NetBSD: inode.c,v 1.8 2000/01/28 16:01:46 bouyer Exp $ */ |
3 | |
4 | /* |
5 | * Copyright (c) 1997 Manuel Bouyer. |
6 | * Copyright (c) 1980, 1986, 1993 |
7 | * The Regents of the University of California. All rights reserved. |
8 | * |
9 | * Redistribution and use in source and binary forms, with or without |
10 | * modification, are permitted provided that the following conditions |
11 | * are met: |
12 | * 1. Redistributions of source code must retain the above copyright |
13 | * notice, this list of conditions and the following disclaimer. |
14 | * 2. Redistributions in binary form must reproduce the above copyright |
15 | * notice, this list of conditions and the following disclaimer in the |
16 | * documentation and/or other materials provided with the distribution. |
17 | * 3. Neither the name of the University nor the names of its contributors |
18 | * may be used to endorse or promote products derived from this software |
19 | * without specific prior written permission. |
20 | * |
21 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
31 | * SUCH DAMAGE. |
32 | */ |
33 | |
34 | #include <sys/param.h> /* btodb */ |
35 | #include <sys/time.h> |
36 | #include <ufs/ext2fs/ext2fs_dinode.h> |
37 | #include <ufs/ext2fs/ext2fs_dir.h> |
38 | #include <ufs/ext2fs/ext2fs.h> |
39 | |
40 | #include <ufs/ufs/dinode.h> /* for IFMT & friends */ |
41 | #ifndef SMALL |
42 | #include <pwd.h> |
43 | #endif |
44 | #include <stdio.h> |
45 | #include <stdlib.h> |
46 | #include <string.h> |
47 | #include <time.h> |
48 | #include <limits.h> |
49 | |
50 | #include "fsck.h" |
51 | #include "fsutil.h" |
52 | #include "extern.h" |
53 | |
54 | /* |
55 | * CG is stored in fs byte order in memory, so we can't use ino_to_fsba |
56 | * here. |
57 | */ |
58 | |
59 | #define fsck_ino_to_fsba(fs, x)(((__uint32_t)((fs)->e2fs_gd[(((x) - 1) / (fs)->e2fs.e2fs_ipg )].ext2bgd_i_tables)) + (((x)-1) % (fs)->e2fs.e2fs_ipg)/(fs )->e2fs_ipb) \ |
60 | (letoh32((fs)->e2fs_gd[ino_to_cg(fs, x)].ext2bgd_i_tables)((__uint32_t)((fs)->e2fs_gd[(((x) - 1) / (fs)->e2fs.e2fs_ipg )].ext2bgd_i_tables)) + \ |
61 | (((x)-1) % (fs)->e2fs.e2fs_ipg)/(fs)->e2fs_ipb) |
62 | |
63 | static ino_t startinum; |
64 | |
65 | static int iblock(struct inodesc *, long, u_int64_t); |
66 | static int setlarge(void); |
67 | |
68 | static int |
69 | setlarge(void) |
70 | { |
71 | if (sblock.e2fs.e2fs_rev < E2FS_REV11) { |
72 | pfatal("LARGE FILES UNSUPPORTED ON REVISION 0 FILESYSTEMS"); |
73 | return 0; |
74 | } |
75 | if (!(sblock.e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_LARGE_FILE0x0002)) { |
76 | if (preen) |
77 | pwarn("SETTING LARGE FILE INDICATOR\n"); |
78 | else if (!reply("SET LARGE FILE INDICATOR")) |
79 | return 0; |
80 | sblock.e2fs.e2fs_features_rocompat |= EXT2F_ROCOMPAT_LARGE_FILE0x0002; |
81 | sbdirty()copyback_sb(&sblk); sblk.b_dirty = 1; |
82 | } |
83 | return 1; |
84 | } |
85 | |
86 | u_int64_t |
87 | inosize(struct ext2fs_dinode *dp) |
88 | { |
89 | u_int64_t size = letoh32(dp->e2di_size)((__uint32_t)(dp->e2di_size)); |
90 | |
91 | if ((letoh16(dp->e2di_mode)((__uint16_t)(dp->e2di_mode)) & IFMT0170000) == IFREG0100000) |
92 | size |= (u_int64_t)letoh32(dp->e2di_size_hi)((__uint32_t)(dp->e2di_size_hi)) << 32; |
93 | if (size >= 0x80000000U) |
94 | (void)setlarge(); |
95 | return size; |
96 | } |
97 | |
98 | void |
99 | inossize(struct ext2fs_dinode *dp, u_int64_t size) |
100 | { |
101 | if ((letoh16(dp->e2di_mode)((__uint16_t)(dp->e2di_mode)) & IFMT0170000) == IFREG0100000) { |
102 | dp->e2di_size_hi = htole32(size >> 32)((__uint32_t)(size >> 32)); |
103 | if (size >= 0x80000000U) |
104 | if (!setlarge()) |
105 | return; |
106 | } else if (size >= 0x80000000U) { |
107 | pfatal("TRYING TO SET FILESIZE TO %llu ON MODE %x FILE\n", |
108 | (unsigned long long)size, letoh16(dp->e2di_mode)((__uint16_t)(dp->e2di_mode)) & IFMT0170000); |
109 | return; |
110 | } |
111 | dp->e2di_size = htole32(size)((__uint32_t)(size)); |
112 | } |
113 | |
114 | int |
115 | ckinode(struct ext2fs_dinode *dp, struct inodesc *idesc) |
116 | { |
117 | u_int32_t *ap; |
118 | long ret, n, ndb; |
119 | struct ext2fs_dinode dino; |
120 | u_int64_t remsize, sizepb; |
121 | mode_t mode; |
122 | char pathbuf[PATH_MAX1024 + 1]; |
123 | |
124 | if (idesc->id_fix != IGNORE) |
125 | idesc->id_fix = DONTKNOW; |
126 | idesc->id_entryno = 0; |
127 | idesc->id_filesize = inosize(dp); |
128 | mode = letoh16(dp->e2di_mode)((__uint16_t)(dp->e2di_mode)) & IFMT0170000; |
129 | if (mode == IFBLK0060000 || mode == IFCHR0020000 || mode == IFIFO0010000 || |
130 | (mode == IFLNK0120000 && (inosize(dp) < EXT2_MAXSYMLINKLEN((12 +3) * sizeof (u_int32_t))))) |
131 | return (KEEPON0x04); |
132 | dino = *dp; |
133 | ndb = howmany(inosize(&dino), sblock.e2fs_bsize)(((inosize(&dino)) + ((sblock.e2fs_bsize) - 1)) / (sblock .e2fs_bsize)); |
134 | for (ap = &dino.e2di_blocks[0]; ap < &dino.e2di_blocks[NDADDR12]; |
135 | ap++,ndb--) { |
136 | idesc->id_numfrags = 1; |
137 | if (*ap == 0) { |
138 | if (idesc->id_type == DATA1 && ndb > 0) { |
139 | /* An empty block in a directory XXX */ |
140 | getpathname(pathbuf, sizeof pathbuf, |
141 | idesc->id_number, idesc->id_number); |
142 | pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", |
143 | pathbuf); |
144 | if (reply("ADJUST LENGTH") == 1) { |
145 | dp = ginode(idesc->id_number); |
146 | inossize(dp, |
147 | (ap - &dino.e2di_blocks[0]) * |
148 | sblock.e2fs_bsize); |
149 | printf( |
150 | "YOU MUST RERUN FSCK AFTERWARDS\n"); |
151 | rerun = 1; |
152 | inodirty(); |
153 | } |
154 | } |
155 | continue; |
156 | } |
157 | idesc->id_blkno = letoh32(*ap)((__uint32_t)(*ap)); |
158 | if (idesc->id_type == ADDR2) |
159 | ret = (*idesc->id_func)(idesc); |
160 | else |
161 | ret = dirscan(idesc); |
162 | if (ret & STOP0x01) |
163 | return (ret); |
164 | } |
165 | idesc->id_numfrags = 1; |
166 | remsize = inosize(&dino) - sblock.e2fs_bsize * NDADDR12; |
167 | sizepb = sblock.e2fs_bsize; |
168 | for (ap = &dino.e2di_blocks[NDADDR12], n = 1; n <= NIADDR3; ap++, n++) { |
169 | if (*ap) { |
170 | idesc->id_blkno = letoh32(*ap)((__uint32_t)(*ap)); |
171 | ret = iblock(idesc, n, remsize); |
172 | if (ret & STOP0x01) |
173 | return (ret); |
174 | } else { |
175 | if (idesc->id_type == DATA1 && remsize > 0) { |
176 | /* An empty block in a directory XXX */ |
177 | getpathname(pathbuf, sizeof pathbuf, |
178 | idesc->id_number, idesc->id_number); |
179 | pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", |
180 | pathbuf); |
181 | if (reply("ADJUST LENGTH") == 1) { |
182 | dp = ginode(idesc->id_number); |
183 | inossize(dp, inosize(dp) - remsize); |
184 | remsize = 0; |
185 | printf( |
186 | "YOU MUST RERUN FSCK AFTERWARDS\n"); |
187 | rerun = 1; |
188 | inodirty(); |
189 | break; |
190 | } |
191 | } |
192 | } |
193 | sizepb *= NINDIR(&sblock)((&sblock)->e2fs_bsize / sizeof(u_int32_t)); |
194 | remsize -= sizepb; |
195 | } |
196 | return (KEEPON0x04); |
197 | } |
198 | |
199 | static int |
200 | iblock(struct inodesc *idesc, long ilevel, u_int64_t isize) |
201 | { |
202 | daddr32_t *ap; |
203 | daddr32_t *aplim; |
204 | struct bufarea *bp; |
205 | int i, n, (*func)(struct inodesc *), nif; |
206 | u_int64_t sizepb; |
207 | char buf[BUFSIZ1024]; |
208 | char pathbuf[PATH_MAX1024 + 1]; |
209 | struct ext2fs_dinode *dp; |
210 | |
211 | if (idesc->id_type == ADDR2) { |
212 | func = idesc->id_func; |
213 | if (((n = (*func)(idesc)) & KEEPON0x04) == 0) |
214 | return (n); |
215 | } else |
216 | func = dirscan; |
217 | if (chkrange(idesc->id_blkno, idesc->id_numfrags)) |
218 | return (SKIP0x02); |
219 | bp = getdatablk(idesc->id_blkno, sblock.e2fs_bsize); |
220 | ilevel--; |
221 | for (sizepb = sblock.e2fs_bsize, i = 0; i < ilevel; i++) |
222 | sizepb *= NINDIR(&sblock)((&sblock)->e2fs_bsize / sizeof(u_int32_t)); |
223 | if (isize > sizepb * NINDIR(&sblock)((&sblock)->e2fs_bsize / sizeof(u_int32_t))) |
224 | nif = NINDIR(&sblock)((&sblock)->e2fs_bsize / sizeof(u_int32_t)); |
225 | else |
226 | nif = howmany(isize, sizepb)(((isize) + ((sizepb) - 1)) / (sizepb)); |
227 | if (idesc->id_func == pass1check && |
228 | nif < NINDIR(&sblock)((&sblock)->e2fs_bsize / sizeof(u_int32_t))) { |
229 | aplim = &bp->b_un.b_indir[NINDIR(&sblock)((&sblock)->e2fs_bsize / sizeof(u_int32_t))]; |
230 | for (ap = &bp->b_un.b_indir[nif]; ap < aplim; ap++) { |
231 | if (*ap == 0) |
232 | continue; |
233 | (void)snprintf(buf, sizeof(buf), |
234 | "PARTIALLY TRUNCATED INODE I=%llu", |
235 | (unsigned long long)idesc->id_number); |
236 | if (dofix(idesc, buf)) { |
237 | *ap = 0; |
238 | dirty(bp)(bp)->b_dirty = 1; |
239 | } |
240 | } |
241 | flush(fswritefd, bp); |
242 | } |
243 | aplim = &bp->b_un.b_indir[nif]; |
244 | for (ap = bp->b_un.b_indir; ap < aplim; ap++) { |
245 | if (*ap) { |
246 | idesc->id_blkno = letoh32(*ap)((__uint32_t)(*ap)); |
247 | if (ilevel == 0) |
248 | n = (*func)(idesc); |
249 | else |
250 | n = iblock(idesc, ilevel, isize); |
251 | if (n & STOP0x01) { |
252 | bp->b_flags &= ~B_INUSE1; |
253 | return (n); |
254 | } |
255 | } else { |
256 | if (idesc->id_type == DATA1 && isize > 0) { |
257 | /* An empty block in a directory XXX */ |
258 | getpathname(pathbuf, sizeof pathbuf, |
259 | idesc->id_number, idesc->id_number); |
260 | pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", |
261 | pathbuf); |
262 | if (reply("ADJUST LENGTH") == 1) { |
263 | dp = ginode(idesc->id_number); |
264 | inossize(dp, inosize(dp) - isize); |
265 | isize = 0; |
Value stored to 'isize' is never read | |
266 | printf( |
267 | "YOU MUST RERUN FSCK AFTERWARDS\n"); |
268 | rerun = 1; |
269 | inodirty(); |
270 | bp->b_flags &= ~B_INUSE1; |
271 | return(STOP0x01); |
272 | } |
273 | } |
274 | } |
275 | isize -= sizepb; |
276 | } |
277 | bp->b_flags &= ~B_INUSE1; |
278 | return (KEEPON0x04); |
279 | } |
280 | |
281 | /* |
282 | * Check that a block in a legal block number. |
283 | * Return 0 if in range, 1 if out of range. |
284 | */ |
285 | int |
286 | chkrange(daddr32_t blk, int cnt) |
287 | { |
288 | int c, overh; |
289 | |
290 | if ((unsigned)(blk + cnt) > maxfsblock) |
291 | return (1); |
292 | c = dtog(&sblock, blk)(((blk) - (&sblock)->e2fs.e2fs_first_dblock) / (&sblock )->e2fs.e2fs_fpg); |
293 | overh = cgoverhead(c); |
294 | if (blk < sblock.e2fs.e2fs_bpg * c + overh + |
295 | sblock.e2fs.e2fs_first_dblock) { |
296 | if ((blk + cnt) > sblock.e2fs.e2fs_bpg * c + overh + |
297 | sblock.e2fs.e2fs_first_dblock) { |
298 | if (debug) { |
299 | printf("blk %d < cgdmin %d;", |
300 | blk, sblock.e2fs.e2fs_bpg * c + overh + |
301 | sblock.e2fs.e2fs_first_dblock); |
302 | printf(" blk + cnt %d > cgsbase %d\n", |
303 | blk + cnt, sblock.e2fs.e2fs_bpg * c + |
304 | overh + sblock.e2fs.e2fs_first_dblock); |
305 | } |
306 | return (1); |
307 | } |
308 | } else { |
309 | if ((blk + cnt) > sblock.e2fs.e2fs_bpg * (c + 1) + overh + |
310 | sblock.e2fs.e2fs_first_dblock) { |
311 | if (debug) { |
312 | printf("blk %d >= cgdmin %d;", |
313 | blk, sblock.e2fs.e2fs_bpg * c + overh + |
314 | sblock.e2fs.e2fs_first_dblock); |
315 | printf(" blk + cnt %d > cgdmax %d\n", |
316 | blk+cnt, sblock.e2fs.e2fs_bpg * (c + 1) + |
317 | overh + sblock.e2fs.e2fs_first_dblock); |
318 | } |
319 | return (1); |
320 | } |
321 | } |
322 | return (0); |
323 | } |
324 | |
325 | /* |
326 | * General purpose interface for reading inodes. |
327 | */ |
328 | struct ext2fs_dinode * |
329 | ginode(ino_t inumber) |
330 | { |
331 | daddr32_t iblk; |
332 | |
333 | if ((inumber < EXT2_FIRSTINO((ufsino_t)11) && inumber != EXT2_ROOTINO((ufsino_t)2)) |
334 | || inumber > maxino) |
335 | errexit("bad inode number %llu to ginode\n", |
336 | (unsigned long long)inumber); |
337 | if (startinum == 0 || |
338 | inumber < startinum || inumber >= startinum + sblock.e2fs_ipb) { |
339 | iblk = fsck_ino_to_fsba(&sblock, inumber)(((__uint32_t)((&sblock)->e2fs_gd[(((inumber) - 1) / ( &sblock)->e2fs.e2fs_ipg)].ext2bgd_i_tables)) + (((inumber )-1) % (&sblock)->e2fs.e2fs_ipg)/(&sblock)->e2fs_ipb ); |
340 | if (pbp != 0) |
341 | pbp->b_flags &= ~B_INUSE1; |
342 | pbp = getdatablk(iblk, sblock.e2fs_bsize); |
343 | startinum = ((inumber -1) / sblock.e2fs_ipb) * sblock.e2fs_ipb + 1; |
344 | } |
345 | return (&pbp->b_un.b_dinode[(inumber-1) % sblock.e2fs_ipb]); |
346 | } |
347 | |
348 | /* |
349 | * Special purpose version of ginode used to optimize first pass |
350 | * over all the inodes in numerical order. |
351 | */ |
352 | ino_t nextino, lastinum; |
353 | long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize; |
354 | struct ext2fs_dinode *inodebuf; |
355 | |
356 | struct ext2fs_dinode * |
357 | getnextinode(ino_t inumber) |
358 | { |
359 | long size; |
360 | daddr32_t dblk; |
361 | struct ext2fs_dinode *dp; |
362 | static char *bp; |
363 | |
364 | if (inumber != nextino++ || inumber > maxino) |
365 | errexit("bad inode number %llu to nextinode\n", |
366 | (unsigned long long)inumber); |
367 | if (inumber >= lastinum) { |
368 | readcnt++; |
369 | dblk = fsbtodb(&sblock, fsck_ino_to_fsba(&sblock, lastinum))(((((__uint32_t)((&sblock)->e2fs_gd[(((lastinum) - 1) / (&sblock)->e2fs.e2fs_ipg)].ext2bgd_i_tables)) + (((lastinum )-1) % (&sblock)->e2fs.e2fs_ipg)/(&sblock)->e2fs_ipb )) << (&sblock)->e2fs_fsbtodb); |
370 | if (readcnt % readpercg == 0) { |
371 | size = partialsize; |
372 | lastinum += partialcnt; |
373 | } else { |
374 | size = inobufsize; |
375 | lastinum += fullcnt; |
376 | } |
377 | (void)bread(fsreadfd, (char *)inodebuf, dblk, size); |
378 | bp = (char *)inodebuf; |
379 | } |
380 | |
381 | dp = (struct ext2fs_dinode *)bp; |
382 | bp += EXT2_DINODE_SIZE(&sblock)((&sblock)->e2fs.e2fs_rev > 0 ? (&sblock)->e2fs .e2fs_inode_size : 128); |
383 | |
384 | return (dp); |
385 | } |
386 | |
387 | void |
388 | resetinodebuf(void) |
389 | { |
390 | |
391 | startinum = 0; |
392 | nextino = 1; |
393 | lastinum = 1; |
394 | readcnt = 0; |
395 | inobufsize = blkroundup(&sblock, INOBUFSIZE)(((128*1024) + (&sblock)->e2fs_qbmask) & (&sblock )->e2fs_bmask); |
396 | fullcnt = inobufsize / EXT2_DINODE_SIZE(&sblock)((&sblock)->e2fs.e2fs_rev > 0 ? (&sblock)->e2fs .e2fs_inode_size : 128); |
397 | readpercg = sblock.e2fs.e2fs_ipg / fullcnt; |
398 | partialcnt = sblock.e2fs.e2fs_ipg % fullcnt; |
399 | partialsize = partialcnt * EXT2_DINODE_SIZE(&sblock)((&sblock)->e2fs.e2fs_rev > 0 ? (&sblock)->e2fs .e2fs_inode_size : 128); |
400 | if (partialcnt != 0) { |
401 | readpercg++; |
402 | } else { |
403 | partialcnt = fullcnt; |
404 | partialsize = inobufsize; |
405 | } |
406 | if (inodebuf == NULL((void *)0) && |
407 | (inodebuf = malloc((unsigned)inobufsize)) == NULL((void *)0)) |
408 | errexit("Cannot allocate space for inode buffer\n"); |
409 | while (nextino < EXT2_ROOTINO((ufsino_t)2)) |
410 | (void)getnextinode(nextino); |
411 | } |
412 | |
413 | void |
414 | freeinodebuf(void) |
415 | { |
416 | |
417 | if (inodebuf != NULL((void *)0)) |
418 | free((char *)inodebuf); |
419 | inodebuf = NULL((void *)0); |
420 | } |
421 | |
422 | /* |
423 | * Routines to maintain information about directory inodes. |
424 | * This is built during the first pass and used during the |
425 | * second and third passes. |
426 | * |
427 | * Enter inodes into the cache. |
428 | */ |
429 | void |
430 | cacheino(struct ext2fs_dinode *dp, ino_t inumber) |
431 | { |
432 | struct inoinfo *inp; |
433 | struct inoinfo **inpp; |
434 | unsigned int blks; |
435 | |
436 | blks = howmany(inosize(dp), sblock.e2fs_bsize)(((inosize(dp)) + ((sblock.e2fs_bsize) - 1)) / (sblock.e2fs_bsize )); |
437 | if (blks > NDADDR12) |
438 | blks = NDADDR12 + NIADDR3; |
439 | inp = malloc(sizeof(*inp) + (blks - 1) * sizeof(daddr32_t)); |
440 | if (inp == NULL((void *)0)) |
441 | return; |
442 | inpp = &inphead[inumber % numdirs]; |
443 | inp->i_nexthash = *inpp; |
444 | *inpp = inp; |
445 | inp->i_child = inp->i_sibling = inp->i_parentp = 0; |
446 | if (inumber == EXT2_ROOTINO((ufsino_t)2)) |
447 | inp->i_parent = EXT2_ROOTINO((ufsino_t)2); |
448 | else |
449 | inp->i_parent = (ino_t)0; |
450 | inp->i_dotdot = (ino_t)0; |
451 | inp->i_number = inumber; |
452 | inp->i_isize = inosize(dp); |
453 | inp->i_numblks = blks * sizeof(daddr32_t); |
454 | memcpy(&inp->i_blks[0], &dp->e2di_blocks[0], (size_t)inp->i_numblks); |
455 | if (inplast == listmax) { |
456 | listmax += 100; |
457 | inpsort = reallocarray(inpsort, listmax, |
458 | sizeof(struct inoinfo *)); |
459 | if (inpsort == NULL((void *)0)) |
460 | errexit("cannot increase directory list\n"); |
461 | } |
462 | inpsort[inplast++] = inp; |
463 | } |
464 | |
465 | /* |
466 | * Look up an inode cache structure. |
467 | */ |
468 | struct inoinfo * |
469 | getinoinfo(ino_t inumber) |
470 | { |
471 | struct inoinfo *inp; |
472 | |
473 | for (inp = inphead[inumber % numdirs]; inp; inp = inp->i_nexthash) { |
474 | if (inp->i_number != inumber) |
475 | continue; |
476 | return (inp); |
477 | } |
478 | errexit("cannot find inode %llu\n", (unsigned long long)inumber); |
479 | return (NULL((void *)0)); |
480 | } |
481 | |
482 | /* |
483 | * Clean up all the inode cache structure. |
484 | */ |
485 | void |
486 | inocleanup(void) |
487 | { |
488 | struct inoinfo **inpp; |
489 | |
490 | if (inphead == NULL((void *)0)) |
491 | return; |
492 | for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) |
493 | free((char *)(*inpp)); |
494 | free((char *)inphead); |
495 | free((char *)inpsort); |
496 | inphead = inpsort = NULL((void *)0); |
497 | } |
498 | |
499 | void |
500 | inodirty(void) |
501 | { |
502 | |
503 | dirty(pbp)(pbp)->b_dirty = 1; |
504 | } |
505 | |
506 | void |
507 | clri(struct inodesc *idesc, char *type, int flag) |
508 | { |
509 | struct ext2fs_dinode *dp; |
510 | |
511 | dp = ginode(idesc->id_number); |
512 | if (flag == 1) { |
513 | pwarn("%s %s", type, |
514 | (dp->e2di_mode & IFMT0170000) == IFDIR0040000 ? "DIR" : "FILE"); |
515 | pinode(idesc->id_number); |
516 | } |
517 | if (preen || reply("CLEAR") == 1) { |
518 | if (preen) |
519 | printf(" (CLEARED)\n"); |
520 | n_files--; |
521 | (void)ckinode(dp, idesc); |
522 | clearinode(dp)(*(dp) = zino); |
523 | statemap[idesc->id_number] = USTATE01; |
524 | inodirty(); |
525 | } |
526 | } |
527 | |
528 | int |
529 | findname(struct inodesc *idesc) |
530 | { |
531 | struct ext2fs_direct *dirp = idesc->id_dirp; |
532 | u_int16_t namlen = dirp->e2d_namlen; |
533 | |
534 | if (letoh32(dirp->e2d_ino)((__uint32_t)(dirp->e2d_ino)) != idesc->id_parent) |
535 | return (KEEPON0x04); |
536 | memcpy(idesc->id_name, dirp->e2d_name, (size_t)namlen); |
537 | idesc->id_name[namlen] = '\0'; |
538 | return (STOP0x01|FOUND0x10); |
539 | } |
540 | |
541 | int |
542 | findino(struct inodesc *idesc) |
543 | { |
544 | struct ext2fs_direct *dirp = idesc->id_dirp; |
545 | u_int32_t ino = letoh32(dirp->e2d_ino)((__uint32_t)(dirp->e2d_ino)); |
546 | |
547 | if (ino == 0) |
548 | return (KEEPON0x04); |
549 | if (strcmp(dirp->e2d_name, idesc->id_name) == 0 && |
550 | (ino == EXT2_ROOTINO((ufsino_t)2) || ino >= EXT2_FIRSTINO((ufsino_t)11)) |
551 | && ino <= maxino) { |
552 | idesc->id_parent = ino; |
553 | return (STOP0x01|FOUND0x10); |
554 | } |
555 | return (KEEPON0x04); |
556 | } |
557 | |
558 | void |
559 | pinode(ino_t ino) |
560 | { |
561 | struct ext2fs_dinode *dp; |
562 | const char *p; |
563 | time_t t; |
564 | u_int32_t uid; |
565 | |
566 | printf(" I=%llu ", (unsigned long long)ino); |
567 | if ((ino < EXT2_FIRSTINO((ufsino_t)11) && ino != EXT2_ROOTINO((ufsino_t)2)) || ino > maxino) |
568 | return; |
569 | dp = ginode(ino); |
570 | printf(" OWNER="); |
571 | uid = letoh16(dp->e2di_uid_low)((__uint16_t)(dp->e2di_uid_low)) | (letoh16(dp->e2di_uid_high)((__uint16_t)(dp->e2di_uid_high)) << 16); |
572 | #ifndef SMALL |
573 | if ((p = user_from_uid(uid, 1)) != NULL((void *)0)) |
574 | printf("%s ", p); |
575 | else |
576 | #endif |
577 | printf("%u ", uid); |
578 | printf("MODE=%o\n", letoh16(dp->e2di_mode)((__uint16_t)(dp->e2di_mode))); |
579 | if (preen) |
580 | printf("%s: ", cdevname()); |
581 | printf("SIZE=%llu ", (long long)inosize(dp)); |
582 | t = (time_t) letoh32(dp->e2di_mtime)((__uint32_t)(dp->e2di_mtime)); |
583 | p = ctime(&t); |
584 | printf("MTIME=%12.12s %4.4s ", &p[4], &p[20]); |
585 | } |
586 | |
587 | void |
588 | blkerror(ino_t ino, char *type, daddr32_t blk) |
589 | { |
590 | |
591 | pfatal("%d %s I=%llu", blk, type, (unsigned long long)ino); |
592 | printf("\n"); |
593 | switch (statemap[ino]) { |
594 | |
595 | case FSTATE02: |
596 | statemap[ino] = FCLEAR06; |
597 | return; |
598 | |
599 | case DSTATE03: |
600 | statemap[ino] = DCLEAR05; |
601 | return; |
602 | |
603 | case FCLEAR06: |
604 | case DCLEAR05: |
605 | return; |
606 | |
607 | default: |
608 | errexit("BAD STATE %d TO BLKERR\n", statemap[ino]); |
609 | /* NOTREACHED */ |
610 | } |
611 | } |
612 | |
613 | /* |
614 | * allocate an unused inode |
615 | */ |
616 | ino_t |
617 | allocino(ino_t request, int type) |
618 | { |
619 | ino_t ino; |
620 | struct ext2fs_dinode *dp; |
621 | time_t t; |
622 | |
623 | if (request == 0) |
624 | request = EXT2_ROOTINO((ufsino_t)2); |
625 | else if (statemap[request] != USTATE01) |
626 | return (0); |
627 | for (ino = request; ino < maxino; ino++) { |
628 | if ((ino > EXT2_ROOTINO((ufsino_t)2)) && (ino < EXT2_FIRSTINO((ufsino_t)11))) |
629 | continue; |
630 | if (statemap[ino] == USTATE01) |
631 | break; |
632 | } |
633 | if (ino == maxino) |
634 | return (0); |
635 | switch (type & IFMT0170000) { |
636 | case IFDIR0040000: |
637 | statemap[ino] = DSTATE03; |
638 | break; |
639 | case IFREG0100000: |
640 | case IFLNK0120000: |
641 | statemap[ino] = FSTATE02; |
642 | break; |
643 | default: |
644 | return (0); |
645 | } |
646 | dp = ginode(ino); |
647 | dp->e2di_blocks[0] = htole32(allocblk())((__uint32_t)(allocblk())); |
648 | if (dp->e2di_blocks[0] == 0) { |
649 | statemap[ino] = USTATE01; |
650 | return (0); |
651 | } |
652 | dp->e2di_mode = htole16(type)((__uint16_t)(type)); |
653 | (void)time(&t); |
654 | dp->e2di_atime = (u_int32_t)htole32(t)((__uint32_t)(t)); |
655 | dp->e2di_mtime = dp->e2di_ctime = dp->e2di_atime; |
656 | dp->e2di_dtime = 0; |
657 | inossize(dp, sblock.e2fs_bsize); |
658 | dp->e2di_nblock = htole32(btodb(sblock.e2fs_bsize))((__uint32_t)(((sblock.e2fs_bsize) >> 9))); |
659 | n_files++; |
660 | inodirty(); |
661 | typemap[ino] = E2IFTODT(type)(((type) & 0170000) >> 12); |
662 | return (ino); |
663 | } |
664 | |
665 | /* |
666 | * deallocate an inode |
667 | */ |
668 | void |
669 | freeino(ino_t ino) |
670 | { |
671 | struct inodesc idesc; |
672 | struct ext2fs_dinode *dp; |
673 | |
674 | memset(&idesc, 0, sizeof(struct inodesc)); |
675 | idesc.id_type = ADDR2; |
676 | idesc.id_func = pass4check; |
677 | idesc.id_number = ino; |
678 | dp = ginode(ino); |
679 | (void)ckinode(dp, &idesc); |
680 | clearinode(dp)(*(dp) = zino); |
681 | inodirty(); |
682 | statemap[ino] = USTATE01; |
683 | n_files--; |
684 | } |