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