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