| @@ -1,563 +1,564 @@ | | | @@ -1,563 +1,564 @@ |
1 | /* $NetBSD: pass1.c,v 1.57 2017/02/08 16:11:40 rin Exp $ */ | | 1 | /* $NetBSD: pass1.c,v 1.58 2018/02/13 11:20:08 hannken Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1980, 1986, 1993 | | 4 | * Copyright (c) 1980, 1986, 1993 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
15 | * 3. Neither the name of the University nor the names of its contributors | | 15 | * 3. Neither the name of the University nor the names of its contributors |
16 | * may be used to endorse or promote products derived from this software | | 16 | * may be used to endorse or promote products derived from this software |
17 | * without specific prior written permission. | | 17 | * without specific prior written permission. |
18 | * | | 18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
29 | * SUCH DAMAGE. | | 29 | * SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #include <sys/cdefs.h> | | 32 | #include <sys/cdefs.h> |
33 | #ifndef lint | | 33 | #ifndef lint |
34 | #if 0 | | 34 | #if 0 |
35 | static char sccsid[] = "@(#)pass1.c 8.6 (Berkeley) 4/28/95"; | | 35 | static char sccsid[] = "@(#)pass1.c 8.6 (Berkeley) 4/28/95"; |
36 | #else | | 36 | #else |
37 | __RCSID("$NetBSD: pass1.c,v 1.57 2017/02/08 16:11:40 rin Exp $"); | | 37 | __RCSID("$NetBSD: pass1.c,v 1.58 2018/02/13 11:20:08 hannken Exp $"); |
38 | #endif | | 38 | #endif |
39 | #endif /* not lint */ | | 39 | #endif /* not lint */ |
40 | | | 40 | |
41 | #include <sys/param.h> | | 41 | #include <sys/param.h> |
42 | #include <sys/stat.h> | | 42 | #include <sys/stat.h> |
43 | #include <sys/time.h> | | 43 | #include <sys/time.h> |
44 | | | 44 | |
45 | #include <ufs/ufs/dinode.h> | | 45 | #include <ufs/ufs/dinode.h> |
46 | #include <ufs/ufs/dir.h> | | 46 | #include <ufs/ufs/dir.h> |
47 | #include <ufs/ffs/fs.h> | | 47 | #include <ufs/ffs/fs.h> |
48 | #include <ufs/ufs/ufs_bswap.h> | | 48 | #include <ufs/ufs/ufs_bswap.h> |
49 | #include <ufs/ffs/ffs_extern.h> | | 49 | #include <ufs/ffs/ffs_extern.h> |
50 | | | 50 | |
51 | #include <err.h> | | 51 | #include <err.h> |
52 | #include <stdio.h> | | 52 | #include <stdio.h> |
53 | #include <stdlib.h> | | 53 | #include <stdlib.h> |
54 | #include <string.h> | | 54 | #include <string.h> |
55 | | | 55 | |
56 | #include "fsck.h" | | 56 | #include "fsck.h" |
57 | #include "extern.h" | | 57 | #include "extern.h" |
58 | #include "fsutil.h" | | 58 | #include "fsutil.h" |
59 | #include "exitvalues.h" | | 59 | #include "exitvalues.h" |
60 | | | 60 | |
61 | static daddr_t badblk; | | 61 | static daddr_t badblk; |
62 | static daddr_t dupblk; | | 62 | static daddr_t dupblk; |
63 | static void checkinode(ino_t, struct inodesc *); | | 63 | static void checkinode(ino_t, struct inodesc *); |
64 | static ino_t lastino; | | 64 | static ino_t lastino; |
65 | | | 65 | |
66 | void | | 66 | void |
67 | pass1(void) | | 67 | pass1(void) |
68 | { | | 68 | { |
69 | ino_t inumber, inosused, ninosused, ii; | | 69 | ino_t inumber, inosused, ninosused, ii; |
70 | size_t inospace; | | 70 | size_t inospace; |
71 | int c; | | 71 | int c; |
72 | daddr_t i, cgd; | | 72 | daddr_t i, cgd; |
73 | struct inodesc idesc; | | 73 | struct inodesc idesc; |
74 | struct cg *cgp = cgrp; | | 74 | struct cg *cgp = cgrp; |
75 | struct inostat *info; | | 75 | struct inostat *info; |
76 | uint8_t *cp; | | 76 | uint8_t *cp; |
77 | | | 77 | |
78 | /* | | 78 | /* |
79 | * Set file system reserved blocks in used block map. | | 79 | * Set file system reserved blocks in used block map. |
80 | */ | | 80 | */ |
81 | for (c = 0; c < sblock->fs_ncg; c++) { | | 81 | for (c = 0; c < sblock->fs_ncg; c++) { |
82 | cgd = cgdmin(sblock, c); | | 82 | cgd = cgdmin(sblock, c); |
83 | if (c == 0) | | 83 | if (c == 0) |
84 | i = cgbase(sblock, c); | | 84 | i = cgbase(sblock, c); |
85 | else | | 85 | else |
86 | i = cgsblock(sblock, c); | | 86 | i = cgsblock(sblock, c); |
87 | for (; i < cgd; i++) | | 87 | for (; i < cgd; i++) |
88 | setbmap(i); | | 88 | setbmap(i); |
89 | } | | 89 | } |
90 | i = sblock->fs_csaddr; | | 90 | i = sblock->fs_csaddr; |
91 | cgd = i + howmany(sblock->fs_cssize, sblock->fs_fsize); | | 91 | cgd = i + howmany(sblock->fs_cssize, sblock->fs_fsize); |
92 | for (; i < cgd; i++) | | 92 | for (; i < cgd; i++) |
93 | setbmap(i); | | 93 | setbmap(i); |
94 | /* | | 94 | /* |
95 | * Find all allocated blocks. | | 95 | * Find all allocated blocks. |
96 | */ | | 96 | */ |
97 | memset(&idesc, 0, sizeof(struct inodesc)); | | 97 | memset(&idesc, 0, sizeof(struct inodesc)); |
98 | idesc.id_func = pass1check; | | 98 | idesc.id_func = pass1check; |
99 | n_files = n_blks = 0; | | 99 | n_files = n_blks = 0; |
100 | for (c = 0; c < sblock->fs_ncg; c++) { | | 100 | for (c = 0; c < sblock->fs_ncg; c++) { |
101 | inumber = c * sblock->fs_ipg; | | 101 | inumber = c * sblock->fs_ipg; |
102 | setinodebuf(inumber); | | 102 | setinodebuf(inumber); |
103 | getblk(&cgblk, cgtod(sblock, c), sblock->fs_cgsize); | | 103 | getblk(&cgblk, cgtod(sblock, c), sblock->fs_cgsize); |
104 | memcpy(cgp, cgblk.b_un.b_cg, sblock->fs_cgsize); | | 104 | memcpy(cgp, cgblk.b_un.b_cg, sblock->fs_cgsize); |
105 | if((doswap && !needswap) || (!doswap && needswap)) | | 105 | if((doswap && !needswap) || (!doswap && needswap)) |
106 | ffs_cg_swap(cgblk.b_un.b_cg, cgp, sblock); | | 106 | ffs_cg_swap(cgblk.b_un.b_cg, cgp, sblock); |
107 | if (is_ufs2) | | 107 | if (is_ufs2) |
108 | inosused = cgp->cg_initediblk; | | 108 | inosused = cgp->cg_initediblk; |
109 | else | | 109 | else |
110 | inosused = sblock->fs_ipg; | | 110 | inosused = sblock->fs_ipg; |
111 | if (got_siginfo) { | | 111 | if (got_siginfo) { |
112 | fprintf(stderr, | | 112 | fprintf(stderr, |
113 | "%s: phase 1: cyl group %d of %d (%d%%)\n", | | 113 | "%s: phase 1: cyl group %d of %d (%d%%)\n", |
114 | cdevname(), c, sblock->fs_ncg, | | 114 | cdevname(), c, sblock->fs_ncg, |
115 | c * 100 / sblock->fs_ncg); | | 115 | c * 100 / sblock->fs_ncg); |
116 | got_siginfo = 0; | | 116 | got_siginfo = 0; |
117 | } | | 117 | } |
118 | #ifdef PROGRESS | | 118 | #ifdef PROGRESS |
119 | progress_bar(cdevname(), preen ? NULL : "phase 1", | | 119 | progress_bar(cdevname(), preen ? NULL : "phase 1", |
120 | c, sblock->fs_ncg); | | 120 | c, sblock->fs_ncg); |
121 | #endif /* PROGRESS */ | | 121 | #endif /* PROGRESS */ |
122 | /* | | 122 | /* |
123 | * If we are using soft updates, then we can trust the | | 123 | * If we are using soft updates, then we can trust the |
124 | * cylinder group inode allocation maps to tell us which | | 124 | * cylinder group inode allocation maps to tell us which |
125 | * inodes are allocated. We will scan the used inode map | | 125 | * inodes are allocated. We will scan the used inode map |
126 | * to find the inodes that are really in use, and then | | 126 | * to find the inodes that are really in use, and then |
127 | * read only those inodes in from disk. | | 127 | * read only those inodes in from disk. |
128 | */ | | 128 | */ |
129 | if (preen && usedsoftdep) { | | 129 | if (preen && usedsoftdep) { |
130 | if (!cg_chkmagic(cgp, 0)) | | 130 | if (!cg_chkmagic(cgp, 0)) |
131 | pfatal("CG %d: BAD MAGIC NUMBER\n", c); | | 131 | pfatal("CG %d: BAD MAGIC NUMBER\n", c); |
132 | cp = &cg_inosused(cgp, 0)[(inosused - 1) / CHAR_BIT]; | | 132 | cp = &cg_inosused(cgp, 0)[(inosused - 1) / CHAR_BIT]; |
133 | for ( ; inosused > 0; inosused -= CHAR_BIT, cp--) { | | 133 | for ( ; inosused > 0; inosused -= CHAR_BIT, cp--) { |
134 | if (*cp == 0) | | 134 | if (*cp == 0) |
135 | continue; | | 135 | continue; |
136 | for (i = 1 << (CHAR_BIT - 1); i > 0; i >>= 1) { | | 136 | for (i = 1 << (CHAR_BIT - 1); i > 0; i >>= 1) { |
137 | if (*cp & i) | | 137 | if (*cp & i) |
138 | break; | | 138 | break; |
139 | inosused--; | | 139 | inosused--; |
140 | } | | 140 | } |
141 | break; | | 141 | break; |
142 | } | | 142 | } |
143 | #ifdef notdef | | 143 | #ifdef notdef |
144 | if (inosused < 0) | | 144 | if (inosused < 0) |
145 | inosused = 0; | | 145 | inosused = 0; |
146 | #endif | | 146 | #endif |
147 | } | | 147 | } |
148 | /* | | 148 | /* |
149 | * Allocate inoinfo structures for the allocated inodes. | | 149 | * Allocate inoinfo structures for the allocated inodes. |
150 | */ | | 150 | */ |
151 | inostathead[c].il_numalloced = inosused; | | 151 | inostathead[c].il_numalloced = inosused; |
152 | if (inosused == 0) { | | 152 | if (inosused == 0) { |
153 | inostathead[c].il_stat = 0; | | 153 | inostathead[c].il_stat = 0; |
154 | continue; | | 154 | continue; |
155 | } | | 155 | } |
156 | inospace = inosused * sizeof(*info); | | 156 | inospace = inosused * sizeof(*info); |
157 | if (inospace / sizeof(*info) != inosused) { | | 157 | if (inospace / sizeof(*info) != inosused) { |
158 | pfatal("too many inodes %llu\n", (unsigned long long) | | 158 | pfatal("too many inodes %llu\n", (unsigned long long) |
159 | inosused); | | 159 | inosused); |
160 | exit(FSCK_EXIT_CHECK_FAILED); | | 160 | exit(FSCK_EXIT_CHECK_FAILED); |
161 | } | | 161 | } |
162 | info = malloc(inospace); | | 162 | info = malloc(inospace); |
163 | if (info == NULL) { | | 163 | if (info == NULL) { |
164 | pfatal("cannot alloc %zu bytes for inoinfo\n", | | 164 | pfatal("cannot alloc %zu bytes for inoinfo\n", |
165 | inospace); | | 165 | inospace); |
166 | exit(FSCK_EXIT_CHECK_FAILED); | | 166 | exit(FSCK_EXIT_CHECK_FAILED); |
167 | } | | 167 | } |
168 | (void)memset(info, 0, inospace); | | 168 | (void)memset(info, 0, inospace); |
169 | inostathead[c].il_stat = info; | | 169 | inostathead[c].il_stat = info; |
170 | /* | | 170 | /* |
171 | * Scan the allocated inodes. | | 171 | * Scan the allocated inodes. |
172 | */ | | 172 | */ |
173 | for (ii = 0; ii < inosused; ii++, inumber++) { | | 173 | for (ii = 0; ii < inosused; ii++, inumber++) { |
174 | if (inumber < UFS_ROOTINO) { | | 174 | if (inumber < UFS_ROOTINO) { |
175 | (void)getnextinode(inumber); | | 175 | (void)getnextinode(inumber); |
176 | continue; | | 176 | continue; |
177 | } | | 177 | } |
178 | checkinode(inumber, &idesc); | | 178 | checkinode(inumber, &idesc); |
179 | } | | 179 | } |
180 | lastino += 1; | | 180 | lastino += 1; |
181 | if (inosused < (ino_t)sblock->fs_ipg || inumber == lastino) | | 181 | if (inosused < (ino_t)sblock->fs_ipg || inumber == lastino) |
182 | continue; | | 182 | continue; |
183 | /* | | 183 | /* |
184 | * If we were not able to determine in advance which inodes | | 184 | * If we were not able to determine in advance which inodes |
185 | * were in use, then reduce the size of the inoinfo structure | | 185 | * were in use, then reduce the size of the inoinfo structure |
186 | * to the size necessary to describe the inodes that we | | 186 | * to the size necessary to describe the inodes that we |
187 | * really found. | | 187 | * really found. |
188 | */ | | 188 | */ |
189 | if (lastino < (c * (ino_t)sblock->fs_ipg)) | | 189 | if (lastino < (c * (ino_t)sblock->fs_ipg)) |
190 | ninosused = 0; | | 190 | ninosused = 0; |
191 | else | | 191 | else |
192 | ninosused = lastino - (c * sblock->fs_ipg); | | 192 | ninosused = lastino - (c * sblock->fs_ipg); |
193 | inostathead[c].il_numalloced = ninosused; | | 193 | inostathead[c].il_numalloced = ninosused; |
194 | if (ninosused == 0) { | | 194 | if (ninosused == 0) { |
195 | free(inostathead[c].il_stat); | | 195 | free(inostathead[c].il_stat); |
196 | inostathead[c].il_stat = 0; | | 196 | inostathead[c].il_stat = 0; |
197 | continue; | | 197 | continue; |
198 | } | | 198 | } |
199 | if (ninosused != inosused) { | | 199 | if (ninosused != inosused) { |
200 | struct inostat *ninfo; | | 200 | struct inostat *ninfo; |
201 | size_t ninospace = ninosused * sizeof(*ninfo); | | 201 | size_t ninospace = ninosused * sizeof(*ninfo); |
202 | if (ninospace / sizeof(*info) != ninosused) { | | 202 | if (ninospace / sizeof(*info) != ninosused) { |
203 | pfatal("too many inodes %llu\n", | | 203 | pfatal("too many inodes %llu\n", |
204 | (unsigned long long)ninosused); | | 204 | (unsigned long long)ninosused); |
205 | exit(FSCK_EXIT_CHECK_FAILED); | | 205 | exit(FSCK_EXIT_CHECK_FAILED); |
206 | } | | 206 | } |
207 | ninfo = realloc(info, ninospace); | | 207 | ninfo = realloc(info, ninospace); |
208 | if (ninfo == NULL) { | | 208 | if (ninfo == NULL) { |
209 | pfatal("cannot realloc %zu bytes to %zu " | | 209 | pfatal("cannot realloc %zu bytes to %zu " |
210 | "for inoinfo\n", inospace, ninospace); | | 210 | "for inoinfo\n", inospace, ninospace); |
211 | exit(FSCK_EXIT_CHECK_FAILED); | | 211 | exit(FSCK_EXIT_CHECK_FAILED); |
212 | } | | 212 | } |
213 | if (ninosused > inosused) | | 213 | if (ninosused > inosused) |
214 | (void)memset(&ninfo[inosused], 0, ninospace - inospace); | | 214 | (void)memset(&ninfo[inosused], 0, ninospace - inospace); |
215 | inostathead[c].il_stat = ninfo; | | 215 | inostathead[c].il_stat = ninfo; |
216 | } | | 216 | } |
217 | } | | 217 | } |
218 | #ifdef PROGRESS | | 218 | #ifdef PROGRESS |
219 | if (!preen) | | 219 | if (!preen) |
220 | progress_done(); | | 220 | progress_done(); |
221 | #endif /* PROGRESS */ | | 221 | #endif /* PROGRESS */ |
222 | freeinodebuf(); | | 222 | freeinodebuf(); |
223 | #ifndef NO_FFS_EI | | 223 | #ifndef NO_FFS_EI |
224 | do_blkswap = 0; /* has been done */ | | 224 | do_blkswap = 0; /* has been done */ |
225 | #endif | | 225 | #endif |
226 | } | | 226 | } |
227 | | | 227 | |
228 | static void | | 228 | static void |
229 | checkinode(ino_t inumber, struct inodesc *idesc) | | 229 | checkinode(ino_t inumber, struct inodesc *idesc) |
230 | { | | 230 | { |
231 | union dinode *dp; | | 231 | union dinode *dp; |
232 | struct zlncnt *zlnp; | | 232 | struct zlncnt *zlnp; |
233 | daddr_t ndb; | | 233 | daddr_t ndb; |
234 | int j; | | 234 | int j; |
235 | mode_t mode; | | 235 | mode_t mode; |
236 | u_int64_t size, kernmaxfilesize; | | 236 | u_int64_t size, kernmaxfilesize; |
237 | int64_t blocks; | | 237 | int64_t blocks; |
238 | char symbuf[MAXBSIZE]; | | 238 | char symbuf[MAXBSIZE]; |
239 | struct inostat *info; | | 239 | struct inostat *info; |
240 | | | 240 | |
241 | dp = getnextinode(inumber); | | 241 | dp = getnextinode(inumber); |
242 | info = inoinfo(inumber); | | 242 | info = inoinfo(inumber); |
243 | mode = iswap16(DIP(dp, mode)) & IFMT; | | 243 | mode = iswap16(DIP(dp, mode)) & IFMT; |
244 | size = iswap64(DIP(dp, size)); | | 244 | size = iswap64(DIP(dp, size)); |
245 | if (mode == 0) { | | 245 | if (mode == 0) { |
246 | if ((is_ufs2 && | | 246 | if ((is_ufs2 && |
247 | (memcmp(dp->dp2.di_db, ufs2_zino.di_db, | | 247 | (memcmp(dp->dp2.di_db, ufs2_zino.di_db, |
248 | UFS_NDADDR * sizeof(int64_t)) || | | 248 | UFS_NDADDR * sizeof(int64_t)) || |
249 | memcmp(dp->dp2.di_ib, ufs2_zino.di_ib, | | 249 | memcmp(dp->dp2.di_ib, ufs2_zino.di_ib, |
250 | UFS_NIADDR * sizeof(int64_t)))) | | 250 | UFS_NIADDR * sizeof(int64_t)))) |
251 | || | | 251 | || |
252 | (!is_ufs2 && | | 252 | (!is_ufs2 && |
253 | (memcmp(dp->dp1.di_db, ufs1_zino.di_db, | | 253 | (memcmp(dp->dp1.di_db, ufs1_zino.di_db, |
254 | UFS_NDADDR * sizeof(int32_t)) || | | 254 | UFS_NDADDR * sizeof(int32_t)) || |
255 | memcmp(dp->dp1.di_ib, ufs1_zino.di_ib, | | 255 | memcmp(dp->dp1.di_ib, ufs1_zino.di_ib, |
256 | UFS_NIADDR * sizeof(int32_t)))) || | | 256 | UFS_NIADDR * sizeof(int32_t)))) |
257 | mode || size) { | | 257 | || |
| | | 258 | mode || size || DIP(dp, blocks)) { |
258 | pfatal("PARTIALLY ALLOCATED INODE I=%llu", | | 259 | pfatal("PARTIALLY ALLOCATED INODE I=%llu", |
259 | (unsigned long long)inumber); | | 260 | (unsigned long long)inumber); |
260 | if (reply("CLEAR") == 1) { | | 261 | if (reply("CLEAR") == 1) { |
261 | dp = ginode(inumber); | | 262 | dp = ginode(inumber); |
262 | clearinode(dp); | | 263 | clearinode(dp); |
263 | inodirty(); | | 264 | inodirty(); |
264 | } else | | 265 | } else |
265 | markclean = 0; | | 266 | markclean = 0; |
266 | } | | 267 | } |
267 | info->ino_state = USTATE; | | 268 | info->ino_state = USTATE; |
268 | return; | | 269 | return; |
269 | } | | 270 | } |
270 | lastino = inumber; | | 271 | lastino = inumber; |
271 | /* This should match the file size limit in ffs_mountfs(). */ | | 272 | /* This should match the file size limit in ffs_mountfs(). */ |
272 | if (is_ufs2) | | 273 | if (is_ufs2) |
273 | kernmaxfilesize = sblock->fs_maxfilesize; | | 274 | kernmaxfilesize = sblock->fs_maxfilesize; |
274 | else | | 275 | else |
275 | kernmaxfilesize = (u_int64_t)0x80000000 * sblock->fs_bsize - 1; | | 276 | kernmaxfilesize = (u_int64_t)0x80000000 * sblock->fs_bsize - 1; |
276 | if (size > kernmaxfilesize || size + sblock->fs_bsize - 1 < size || | | 277 | if (size > kernmaxfilesize || size + sblock->fs_bsize - 1 < size || |
277 | (mode == IFDIR && size > UFS_MAXDIRSIZE)) { | | 278 | (mode == IFDIR && size > UFS_MAXDIRSIZE)) { |
278 | if (debug) | | 279 | if (debug) |
279 | printf("bad size %llu:",(unsigned long long)size); | | 280 | printf("bad size %llu:",(unsigned long long)size); |
280 | goto unknown; | | 281 | goto unknown; |
281 | } | | 282 | } |
282 | if (!preen && mode == IFMT && reply("HOLD BAD BLOCK") == 1) { | | 283 | if (!preen && mode == IFMT && reply("HOLD BAD BLOCK") == 1) { |
283 | dp = ginode(inumber); | | 284 | dp = ginode(inumber); |
284 | DIP_SET(dp, size, iswap64(sblock->fs_fsize)); | | 285 | DIP_SET(dp, size, iswap64(sblock->fs_fsize)); |
285 | size = sblock->fs_fsize; | | 286 | size = sblock->fs_fsize; |
286 | DIP_SET(dp, mode, iswap16(IFREG|0600)); | | 287 | DIP_SET(dp, mode, iswap16(IFREG|0600)); |
287 | inodirty(); | | 288 | inodirty(); |
288 | } | | 289 | } |
289 | ndb = howmany(size, sblock->fs_bsize); | | 290 | ndb = howmany(size, sblock->fs_bsize); |
290 | if (ndb < 0) { | | 291 | if (ndb < 0) { |
291 | if (debug) | | 292 | if (debug) |
292 | printf("bad size %llu ndb %lld:", | | 293 | printf("bad size %llu ndb %lld:", |
293 | (unsigned long long)size, (long long)ndb); | | 294 | (unsigned long long)size, (long long)ndb); |
294 | goto unknown; | | 295 | goto unknown; |
295 | } | | 296 | } |
296 | if (mode == IFBLK || mode == IFCHR) | | 297 | if (mode == IFBLK || mode == IFCHR) |
297 | ndb++; | | 298 | ndb++; |
298 | if (mode == IFLNK) { | | 299 | if (mode == IFLNK) { |
299 | /* | | 300 | /* |
300 | * Note that the old fastlink format always had di_blocks set | | 301 | * Note that the old fastlink format always had di_blocks set |
301 | * to 0. Other than that we no longer use the `spare' field | | 302 | * to 0. Other than that we no longer use the `spare' field |
302 | * (which is now the extended uid) for sanity checking, the | | 303 | * (which is now the extended uid) for sanity checking, the |
303 | * new format is the same as the old. We simply ignore the | | 304 | * new format is the same as the old. We simply ignore the |
304 | * conversion altogether. - mycroft, 19MAY1994 | | 305 | * conversion altogether. - mycroft, 19MAY1994 |
305 | */ | | 306 | */ |
306 | if (!is_ufs2 && doinglevel2 && | | 307 | if (!is_ufs2 && doinglevel2 && |
307 | size > 0 && size < UFS1_MAXSYMLINKLEN && | | 308 | size > 0 && size < UFS1_MAXSYMLINKLEN && |
308 | DIP(dp, blocks) != 0) { | | 309 | DIP(dp, blocks) != 0) { |
309 | if (bread(fsreadfd, symbuf, | | 310 | if (bread(fsreadfd, symbuf, |
310 | FFS_FSBTODB(sblock, iswap32(DIP(dp, db[0]))), | | 311 | FFS_FSBTODB(sblock, iswap32(DIP(dp, db[0]))), |
311 | (long)secsize) != 0) | | 312 | (long)secsize) != 0) |
312 | errexit("cannot read symlink"); | | 313 | errexit("cannot read symlink"); |
313 | if (debug) { | | 314 | if (debug) { |
314 | symbuf[size] = 0; | | 315 | symbuf[size] = 0; |
315 | printf("convert symlink %llu(%s) " | | 316 | printf("convert symlink %llu(%s) " |
316 | "of size %lld\n", | | 317 | "of size %lld\n", |
317 | (unsigned long long)inumber, symbuf, | | 318 | (unsigned long long)inumber, symbuf, |
318 | (unsigned long long)size); | | 319 | (unsigned long long)size); |
319 | } | | 320 | } |
320 | dp = ginode(inumber); | | 321 | dp = ginode(inumber); |
321 | memmove(dp->dp1.di_db, symbuf, (long)size); | | 322 | memmove(dp->dp1.di_db, symbuf, (long)size); |
322 | DIP_SET(dp, blocks, 0); | | 323 | DIP_SET(dp, blocks, 0); |
323 | inodirty(); | | 324 | inodirty(); |
324 | } | | 325 | } |
325 | /* | | 326 | /* |
326 | * Fake ndb value so direct/indirect block checks below | | 327 | * Fake ndb value so direct/indirect block checks below |
327 | * will detect any garbage after symlink string. | | 328 | * will detect any garbage after symlink string. |
328 | */ | | 329 | */ |
329 | if ((sblock->fs_maxsymlinklen < 0) || | | 330 | if ((sblock->fs_maxsymlinklen < 0) || |
330 | (size < (uint64_t)sblock->fs_maxsymlinklen) || | | 331 | (size < (uint64_t)sblock->fs_maxsymlinklen) || |
331 | (isappleufs && (size < APPLEUFS_MAXSYMLINKLEN)) || | | 332 | (isappleufs && (size < APPLEUFS_MAXSYMLINKLEN)) || |
332 | (sblock->fs_maxsymlinklen == 0 && DIP(dp, blocks) == 0)) { | | 333 | (sblock->fs_maxsymlinklen == 0 && DIP(dp, blocks) == 0)) { |
333 | if (is_ufs2) | | 334 | if (is_ufs2) |
334 | ndb = howmany(size, sizeof(int64_t)); | | 335 | ndb = howmany(size, sizeof(int64_t)); |
335 | else | | 336 | else |
336 | ndb = howmany(size, sizeof(int32_t)); | | 337 | ndb = howmany(size, sizeof(int32_t)); |
337 | if (ndb > UFS_NDADDR) { | | 338 | if (ndb > UFS_NDADDR) { |
338 | j = ndb - UFS_NDADDR; | | 339 | j = ndb - UFS_NDADDR; |
339 | for (ndb = 1; j > 1; j--) | | 340 | for (ndb = 1; j > 1; j--) |
340 | ndb *= FFS_NINDIR(sblock); | | 341 | ndb *= FFS_NINDIR(sblock); |
341 | ndb += UFS_NDADDR; | | 342 | ndb += UFS_NDADDR; |
342 | } | | 343 | } |
343 | } | | 344 | } |
344 | } | | 345 | } |
345 | if (ndb < UFS_NDADDR) { | | 346 | if (ndb < UFS_NDADDR) { |
346 | for (j = ndb; j < UFS_NDADDR; j++) | | 347 | for (j = ndb; j < UFS_NDADDR; j++) |
347 | if (DIP(dp, db[j]) != 0) { | | 348 | if (DIP(dp, db[j]) != 0) { |
348 | if (debug) { | | 349 | if (debug) { |
349 | if (!is_ufs2) | | 350 | if (!is_ufs2) |
350 | printf("bad direct addr ix %d: %d [ndb %lld]\n", | | 351 | printf("bad direct addr ix %d: %d [ndb %lld]\n", |
351 | j, iswap32(dp->dp1.di_db[j]), | | 352 | j, iswap32(dp->dp1.di_db[j]), |
352 | (long long)ndb); | | 353 | (long long)ndb); |
353 | else | | 354 | else |
354 | printf("bad direct addr ix %d: %lld [ndb %lld]\n", | | 355 | printf("bad direct addr ix %d: %lld [ndb %lld]\n", |
355 | j, (long long)iswap64(dp->dp2.di_db[j]), | | 356 | j, (long long)iswap64(dp->dp2.di_db[j]), |
356 | (long long)ndb); | | 357 | (long long)ndb); |
357 | } | | 358 | } |
358 | goto unknown; | | 359 | goto unknown; |
359 | } | | 360 | } |
360 | } | | 361 | } |
361 | | | 362 | |
362 | for (j = 0, ndb -= UFS_NDADDR; ndb > 0; j++) | | 363 | for (j = 0, ndb -= UFS_NDADDR; ndb > 0; j++) |
363 | ndb /= FFS_NINDIR(sblock); | | 364 | ndb /= FFS_NINDIR(sblock); |
364 | | | 365 | |
365 | for (; j < UFS_NIADDR; j++) | | 366 | for (; j < UFS_NIADDR; j++) |
366 | if (DIP(dp, ib[j]) != 0) { | | 367 | if (DIP(dp, ib[j]) != 0) { |
367 | if (debug) { | | 368 | if (debug) { |
368 | if (!is_ufs2) | | 369 | if (!is_ufs2) |
369 | printf("bad indirect addr: %d\n", | | 370 | printf("bad indirect addr: %d\n", |
370 | iswap32(dp->dp1.di_ib[j])); | | 371 | iswap32(dp->dp1.di_ib[j])); |
371 | else | | 372 | else |
372 | printf("bad indirect addr: %lld\n", | | 373 | printf("bad indirect addr: %lld\n", |
373 | (long long)iswap64(dp->dp2.di_ib[j])); | | 374 | (long long)iswap64(dp->dp2.di_ib[j])); |
374 | } | | 375 | } |
375 | goto unknown; | | 376 | goto unknown; |
376 | } | | 377 | } |
377 | if (ftypeok(dp) == 0) | | 378 | if (ftypeok(dp) == 0) |
378 | goto unknown; | | 379 | goto unknown; |
379 | n_files++; | | 380 | n_files++; |
380 | info->ino_linkcnt = iswap16(DIP(dp, nlink)); | | 381 | info->ino_linkcnt = iswap16(DIP(dp, nlink)); |
381 | if (info->ino_linkcnt <= 0) { | | 382 | if (info->ino_linkcnt <= 0) { |
382 | zlnp = (struct zlncnt *)malloc(sizeof *zlnp); | | 383 | zlnp = (struct zlncnt *)malloc(sizeof *zlnp); |
383 | if (zlnp == NULL) { | | 384 | if (zlnp == NULL) { |
384 | markclean = 0; | | 385 | markclean = 0; |
385 | pfatal("LINK COUNT TABLE OVERFLOW"); | | 386 | pfatal("LINK COUNT TABLE OVERFLOW"); |
386 | if (reply("CONTINUE") == 0) { | | 387 | if (reply("CONTINUE") == 0) { |
387 | ckfini(1); | | 388 | ckfini(1); |
388 | exit(FSCK_EXIT_CHECK_FAILED); | | 389 | exit(FSCK_EXIT_CHECK_FAILED); |
389 | } | | 390 | } |
390 | } else { | | 391 | } else { |
391 | zlnp->zlncnt = inumber; | | 392 | zlnp->zlncnt = inumber; |
392 | zlnp->next = zlnhead; | | 393 | zlnp->next = zlnhead; |
393 | zlnhead = zlnp; | | 394 | zlnhead = zlnp; |
394 | } | | 395 | } |
395 | } | | 396 | } |
396 | if (mode == IFDIR) { | | 397 | if (mode == IFDIR) { |
397 | if (size == 0) | | 398 | if (size == 0) |
398 | info->ino_state = DCLEAR; | | 399 | info->ino_state = DCLEAR; |
399 | else | | 400 | else |
400 | info->ino_state = DSTATE; | | 401 | info->ino_state = DSTATE; |
401 | cacheino(dp, inumber); | | 402 | cacheino(dp, inumber); |
402 | countdirs++; | | 403 | countdirs++; |
403 | } else | | 404 | } else |
404 | info->ino_state = FSTATE; | | 405 | info->ino_state = FSTATE; |
405 | info->ino_type = IFTODT(mode); | | 406 | info->ino_type = IFTODT(mode); |
406 | if (!is_ufs2 && doinglevel2 && | | 407 | if (!is_ufs2 && doinglevel2 && |
407 | (iswap16(dp->dp1.di_ouid) != (u_short)-1 || | | 408 | (iswap16(dp->dp1.di_ouid) != (u_short)-1 || |
408 | iswap16(dp->dp1.di_ogid) != (u_short)-1)) { | | 409 | iswap16(dp->dp1.di_ogid) != (u_short)-1)) { |
409 | dp = ginode(inumber); | | 410 | dp = ginode(inumber); |
410 | dp->dp1.di_uid = iswap32(iswap16(dp->dp1.di_ouid)); | | 411 | dp->dp1.di_uid = iswap32(iswap16(dp->dp1.di_ouid)); |
411 | dp->dp1.di_ouid = iswap16(-1); | | 412 | dp->dp1.di_ouid = iswap16(-1); |
412 | dp->dp1.di_gid = iswap32(iswap16(dp->dp1.di_ogid)); | | 413 | dp->dp1.di_gid = iswap32(iswap16(dp->dp1.di_ogid)); |
413 | dp->dp1.di_ogid = iswap16(-1); | | 414 | dp->dp1.di_ogid = iswap16(-1); |
414 | inodirty(); | | 415 | inodirty(); |
415 | } | | 416 | } |
416 | badblk = dupblk = 0; | | 417 | badblk = dupblk = 0; |
417 | idesc->id_number = inumber; | | 418 | idesc->id_number = inumber; |
418 | idesc->id_uid = iswap32(DIP(dp, uid)); | | 419 | idesc->id_uid = iswap32(DIP(dp, uid)); |
419 | idesc->id_gid = iswap32(DIP(dp, gid)); | | 420 | idesc->id_gid = iswap32(DIP(dp, gid)); |
420 | if (iswap32(DIP(dp, flags)) & SF_SNAPSHOT) | | 421 | if (iswap32(DIP(dp, flags)) & SF_SNAPSHOT) |
421 | idesc->id_type = SNAP; | | 422 | idesc->id_type = SNAP; |
422 | else | | 423 | else |
423 | idesc->id_type = ADDR; | | 424 | idesc->id_type = ADDR; |
424 | (void)ckinode(dp, idesc); | | 425 | (void)ckinode(dp, idesc); |
425 | #ifdef notyet | | 426 | #ifdef notyet |
426 | if (is_ufs2 && iswap32(dp->dp2.di_extsize) > 0) { | | 427 | if (is_ufs2 && iswap32(dp->dp2.di_extsize) > 0) { |
427 | int ret, offset; | | 428 | int ret, offset; |
428 | idesc->id_type = ADDR; | | 429 | idesc->id_type = ADDR; |
429 | ndb = howmany(iswap32(dp->dp2.di_extsize), sblock->fs_bsize); | | 430 | ndb = howmany(iswap32(dp->dp2.di_extsize), sblock->fs_bsize); |
430 | for (j = 0; j < UFS_NXADDR; j++) { | | 431 | for (j = 0; j < UFS_NXADDR; j++) { |
431 | if (--ndb == 0 && | | 432 | if (--ndb == 0 && |
432 | (offset = ffs_blkoff(sblock, iswap32(dp->dp2.di_extsize))) != 0) | | 433 | (offset = ffs_blkoff(sblock, iswap32(dp->dp2.di_extsize))) != 0) |
433 | idesc->id_numfrags = ffs_numfrags(sblock, | | 434 | idesc->id_numfrags = ffs_numfrags(sblock, |
434 | ffs_fragroundup(sblock, offset)); | | 435 | ffs_fragroundup(sblock, offset)); |
435 | else | | 436 | else |
436 | idesc->id_numfrags = sblock->fs_frag; | | 437 | idesc->id_numfrags = sblock->fs_frag; |
437 | if (dp->dp2.di_extb[j] == 0) | | 438 | if (dp->dp2.di_extb[j] == 0) |
438 | continue; | | 439 | continue; |
439 | idesc->id_blkno = iswap64(dp->dp2.di_extb[j]); | | 440 | idesc->id_blkno = iswap64(dp->dp2.di_extb[j]); |
440 | ret = (*idesc->id_func)(idesc); | | 441 | ret = (*idesc->id_func)(idesc); |
441 | if (ret & STOP) | | 442 | if (ret & STOP) |
442 | break; | | 443 | break; |
443 | } | | 444 | } |
444 | } | | 445 | } |
445 | #endif | | 446 | #endif |
446 | idesc->id_entryno *= btodb(sblock->fs_fsize); | | 447 | idesc->id_entryno *= btodb(sblock->fs_fsize); |
447 | if (is_ufs2) | | 448 | if (is_ufs2) |
448 | blocks = iswap64(dp->dp2.di_blocks); | | 449 | blocks = iswap64(dp->dp2.di_blocks); |
449 | else | | 450 | else |
450 | blocks = iswap32(dp->dp1.di_blocks); | | 451 | blocks = iswap32(dp->dp1.di_blocks); |
451 | if (blocks != idesc->id_entryno) { | | 452 | if (blocks != idesc->id_entryno) { |
452 | pwarn("INCORRECT BLOCK COUNT I=%llu (%lld should be %lld)", | | 453 | pwarn("INCORRECT BLOCK COUNT I=%llu (%lld should be %lld)", |
453 | (unsigned long long)inumber, (long long)blocks, | | 454 | (unsigned long long)inumber, (long long)blocks, |
454 | (long long)idesc->id_entryno); | | 455 | (long long)idesc->id_entryno); |
455 | if (preen) | | 456 | if (preen) |
456 | printf(" (CORRECTED)\n"); | | 457 | printf(" (CORRECTED)\n"); |
457 | else if (reply("CORRECT") == 0) { | | 458 | else if (reply("CORRECT") == 0) { |
458 | markclean = 0; | | 459 | markclean = 0; |
459 | return; | | 460 | return; |
460 | } | | 461 | } |
461 | dp = ginode(inumber); | | 462 | dp = ginode(inumber); |
462 | if (is_ufs2) | | 463 | if (is_ufs2) |
463 | dp->dp2.di_blocks = iswap64(idesc->id_entryno); | | 464 | dp->dp2.di_blocks = iswap64(idesc->id_entryno); |
464 | else | | 465 | else |
465 | dp->dp1.di_blocks = iswap32((int32_t)idesc->id_entryno); | | 466 | dp->dp1.di_blocks = iswap32((int32_t)idesc->id_entryno); |
466 | inodirty(); | | 467 | inodirty(); |
467 | } | | 468 | } |
468 | if (idesc->id_type != SNAP) | | 469 | if (idesc->id_type != SNAP) |
469 | update_uquot(inumber, idesc->id_uid, idesc->id_gid, | | 470 | update_uquot(inumber, idesc->id_uid, idesc->id_gid, |
470 | idesc->id_entryno, 1); | | 471 | idesc->id_entryno, 1); |
471 | return; | | 472 | return; |
472 | unknown: | | 473 | unknown: |
473 | pfatal("UNKNOWN FILE TYPE I=%llu", (unsigned long long)inumber); | | 474 | pfatal("UNKNOWN FILE TYPE I=%llu", (unsigned long long)inumber); |
474 | info->ino_state = FCLEAR; | | 475 | info->ino_state = FCLEAR; |
475 | if (reply("CLEAR") == 1) { | | 476 | if (reply("CLEAR") == 1) { |
476 | info->ino_state = USTATE; | | 477 | info->ino_state = USTATE; |
477 | dp = ginode(inumber); | | 478 | dp = ginode(inumber); |
478 | clearinode(dp); | | 479 | clearinode(dp); |
479 | inodirty(); | | 480 | inodirty(); |
480 | } else | | 481 | } else |
481 | markclean = 0; | | 482 | markclean = 0; |
482 | } | | 483 | } |
483 | | | 484 | |
484 | int | | 485 | int |
485 | pass1check(struct inodesc *idesc) | | 486 | pass1check(struct inodesc *idesc) |
486 | { | | 487 | { |
487 | int res = KEEPON; | | 488 | int res = KEEPON; |
488 | int anyout, nfrags; | | 489 | int anyout, nfrags; |
489 | daddr_t blkno = idesc->id_blkno; | | 490 | daddr_t blkno = idesc->id_blkno; |
490 | struct dups *dlp; | | 491 | struct dups *dlp; |
491 | struct dups *new; | | 492 | struct dups *new; |
492 | | | 493 | |
493 | if (idesc->id_type == SNAP) { | | 494 | if (idesc->id_type == SNAP) { |
494 | if (blkno == BLK_NOCOPY || blkno == BLK_SNAP) | | 495 | if (blkno == BLK_NOCOPY || blkno == BLK_SNAP) |
495 | return (KEEPON); | | 496 | return (KEEPON); |
496 | } | | 497 | } |
497 | if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) { | | 498 | if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) { |
498 | blkerror(idesc->id_number, "BAD", blkno); | | 499 | blkerror(idesc->id_number, "BAD", blkno); |
499 | if (badblk++ >= MAXBAD) { | | 500 | if (badblk++ >= MAXBAD) { |
500 | pwarn("EXCESSIVE BAD BLKS I=%llu", | | 501 | pwarn("EXCESSIVE BAD BLKS I=%llu", |
501 | (unsigned long long)idesc->id_number); | | 502 | (unsigned long long)idesc->id_number); |
502 | if (preen) | | 503 | if (preen) |
503 | printf(" (SKIPPING)\n"); | | 504 | printf(" (SKIPPING)\n"); |
504 | else if (reply("CONTINUE") == 0) { | | 505 | else if (reply("CONTINUE") == 0) { |
505 | markclean = 0; | | 506 | markclean = 0; |
506 | ckfini(1); | | 507 | ckfini(1); |
507 | exit(FSCK_EXIT_CHECK_FAILED); | | 508 | exit(FSCK_EXIT_CHECK_FAILED); |
508 | } | | 509 | } |
509 | return (STOP); | | 510 | return (STOP); |
510 | } | | 511 | } |
511 | } | | 512 | } |
512 | for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) { | | 513 | for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) { |
513 | if (anyout && chkrange(blkno, 1)) { | | 514 | if (anyout && chkrange(blkno, 1)) { |
514 | res = SKIP; | | 515 | res = SKIP; |
515 | } else if (!testbmap(blkno)) { | | 516 | } else if (!testbmap(blkno)) { |
516 | n_blks++; | | 517 | n_blks++; |
517 | setbmap(blkno); | | 518 | setbmap(blkno); |
518 | } else { | | 519 | } else { |
519 | blkerror(idesc->id_number, "DUP", blkno); | | 520 | blkerror(idesc->id_number, "DUP", blkno); |
520 | if (dupblk++ >= MAXDUP) { | | 521 | if (dupblk++ >= MAXDUP) { |
521 | pwarn("EXCESSIVE DUP BLKS I=%llu", | | 522 | pwarn("EXCESSIVE DUP BLKS I=%llu", |
522 | (unsigned long long)idesc->id_number); | | 523 | (unsigned long long)idesc->id_number); |
523 | if (preen) | | 524 | if (preen) |
524 | printf(" (SKIPPING)\n"); | | 525 | printf(" (SKIPPING)\n"); |
525 | else if (reply("CONTINUE") == 0) { | | 526 | else if (reply("CONTINUE") == 0) { |
526 | markclean = 0; | | 527 | markclean = 0; |
527 | ckfini(1); | | 528 | ckfini(1); |
528 | exit(FSCK_EXIT_CHECK_FAILED); | | 529 | exit(FSCK_EXIT_CHECK_FAILED); |
529 | } | | 530 | } |
530 | return (STOP); | | 531 | return (STOP); |
531 | } | | 532 | } |
532 | new = (struct dups *)malloc(sizeof(struct dups)); | | 533 | new = (struct dups *)malloc(sizeof(struct dups)); |
533 | if (new == NULL) { | | 534 | if (new == NULL) { |
534 | markclean = 0; | | 535 | markclean = 0; |
535 | pfatal("DUP TABLE OVERFLOW."); | | 536 | pfatal("DUP TABLE OVERFLOW."); |
536 | if (reply("CONTINUE") == 0) { | | 537 | if (reply("CONTINUE") == 0) { |
537 | markclean = 0; | | 538 | markclean = 0; |
538 | ckfini(1); | | 539 | ckfini(1); |
539 | exit(FSCK_EXIT_CHECK_FAILED); | | 540 | exit(FSCK_EXIT_CHECK_FAILED); |
540 | } | | 541 | } |
541 | return (STOP); | | 542 | return (STOP); |
542 | } | | 543 | } |
543 | new->dup = blkno; | | 544 | new->dup = blkno; |
544 | if (muldup == 0) { | | 545 | if (muldup == 0) { |
545 | duplist = muldup = new; | | 546 | duplist = muldup = new; |
546 | new->next = 0; | | 547 | new->next = 0; |
547 | } else { | | 548 | } else { |
548 | new->next = muldup->next; | | 549 | new->next = muldup->next; |
549 | muldup->next = new; | | 550 | muldup->next = new; |
550 | } | | 551 | } |
551 | for (dlp = duplist; dlp != muldup; dlp = dlp->next) | | 552 | for (dlp = duplist; dlp != muldup; dlp = dlp->next) |
552 | if (dlp->dup == blkno) | | 553 | if (dlp->dup == blkno) |
553 | break; | | 554 | break; |
554 | if (dlp == muldup && dlp->dup != blkno) | | 555 | if (dlp == muldup && dlp->dup != blkno) |
555 | muldup = new; | | 556 | muldup = new; |
556 | } | | 557 | } |
557 | /* | | 558 | /* |
558 | * count the number of blocks found in id_entryno | | 559 | * count the number of blocks found in id_entryno |
559 | */ | | 560 | */ |
560 | idesc->id_entryno++; | | 561 | idesc->id_entryno++; |
561 | } | | 562 | } |
562 | return (res); | | 563 | return (res); |
563 | } | | 564 | } |