1 /* $NetBSD: setup.c,v 1.11 2002/02/04 23:43:43 perseant Exp $ */ 2 3 /* 4 * Copyright (c) 1980, 1986, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 /* #define DKTYPENAMES */ 37 #define FSTYPENAMES 38 #include <sys/param.h> 39 #include <sys/time.h> 40 #include <sys/stat.h> 41 #include <sys/ioctl.h> 42 #include <sys/disklabel.h> 43 #include <sys/file.h> 44 45 #include <ufs/ufs/dinode.h> 46 #include <sys/mount.h> /* XXX ufs/lfs/lfs.h should include this for 47 * us */ 48 #include <ufs/lfs/lfs.h> 49 #include <ufs/lfs/lfs_extern.h> 50 51 #include <ctype.h> 52 #include <err.h> 53 #include <errno.h> 54 #include <stdio.h> 55 #include <stdlib.h> 56 #include <string.h> 57 58 #include "fsck.h" 59 #include "extern.h" 60 #include "fsutil.h" 61 62 struct bufarea asblk; 63 daddr_t *din_table; 64 SEGUSE *seg_table; 65 #define altsblock (*asblk.b_un.b_fs) 66 #define POWEROF2(num) (((num) & ((num) - 1)) == 0) 67 68 void badsb(int, char *); 69 int calcsb(const char *, int, struct lfs *); 70 static struct disklabel *getdisklabel(const char *, int); 71 static int readsb(int); 72 int lfs_maxino(void); 73 74 static daddr_t try_verify(struct lfs *, struct lfs *); 75 76 #ifdef DKTYPENAMES 77 int useless(void); 78 79 int 80 useless(void) 81 { 82 char **foo = (char **)dktypenames; 83 char **bar = (char **)fscknames; 84 85 return foo - bar; 86 } 87 #endif 88 89 static daddr_t 90 try_verify(struct lfs * osb, struct lfs * nsb) 91 { 92 daddr_t daddr, odaddr; 93 SEGSUM *sp; 94 char *summary; 95 int bc, flag; 96 97 daddr = osb->lfs_offset; 98 summary = malloc(osb->lfs_sumsize); 99 while (daddr != nsb->lfs_offset) { 100 flag = 0; 101 oncemore: 102 /* Read in summary block */ 103 bread(fsreadfd, summary, fsbtodb(osb, daddr), osb->lfs_sumsize); 104 sp = (SEGSUM *)summary; 105 106 /* 107 * Could be a superblock instead of a segment summary. 108 * XXX should use gseguse, but right now we need to do more 109 * setup before we can...fix this 110 */ 111 if (sp->ss_magic != SS_MAGIC || 112 sp->ss_sumsum != cksum(&sp->ss_datasum, osb->lfs_sumsize - 113 sizeof(sp->ss_sumsum))) { 114 if (flag == 0) { 115 flag = 1; 116 daddr += btofsb(osb, LFS_SBPAD); 117 goto oncemore; 118 } 119 return 0x0; 120 } 121 bc = check_summary(osb, sp, daddr); 122 if (bc == 0) 123 break; 124 odaddr = daddr; 125 daddr += btofsb(osb, osb->lfs_sumsize + bc); 126 if (dtosn(osb, odaddr) != dtosn(osb, daddr) || 127 dtosn(osb, daddr) != dtosn(osb, daddr + 128 btofsb(osb, osb->lfs_sumsize + osb->lfs_bsize))) { 129 daddr = ((SEGSUM *)summary)->ss_next; 130 } 131 } 132 return daddr; 133 } 134 135 u_quad_t maxtable[] = { 136 /* 1 */ -1, 137 /* 2 */ -1, 138 /* 4 */ -1, 139 /* 8 */ -1, 140 /* 16 */ -1, 141 /* 32 */ -1, 142 /* 64 */ -1, 143 /* 128 */ -1, 144 /* 256 */ -1, 145 /* 512 */ NDADDR + 128 + 128 * 128 + 128 * 128 * 128, 146 /* 1024 */ NDADDR + 256 + 256 * 256 + 256 * 256 * 256, 147 /* 2048 */ NDADDR + 512 + 512 * 512 + 512 * 512 * 512, 148 /* 4096 */ NDADDR + 1024 + 1024 * 1024 + 1024 * 1024 * 1024, 149 /* 8192 */ 1 << 31, 150 /* 16 K */ 1 << 31, 151 /* 32 K */ 1 << 31, 152 }; 153 154 int 155 setup(const char *dev) 156 { 157 long bmapsize; 158 struct disklabel *lp; 159 #if 0 160 long i; 161 off_t sizepb; 162 #endif 163 struct stat statb; 164 daddr_t daddr; 165 struct lfs proto; 166 int doskipclean; 167 u_int64_t maxfilesize; 168 struct lfs *sb0, *sb1, *osb, *nsb; 169 struct dinode *idinode; 170 171 havesb = 0; 172 fswritefd = -1; 173 doskipclean = skipclean; 174 if (stat(dev, &statb) < 0) { 175 printf("Can't stat %s: %s\n", dev, strerror(errno)); 176 return (0); 177 } 178 if (!S_ISCHR(statb.st_mode)) { 179 pfatal("%s is not a character device", dev); 180 if (reply("CONTINUE") == 0) 181 return (0); 182 } 183 if ((fsreadfd = open(dev, O_RDONLY)) < 0) { 184 printf("Can't open %s: %s\n", dev, strerror(errno)); 185 return (0); 186 } 187 if (preen == 0) 188 printf("** %s", dev); 189 if (nflag || (fswritefd = open(dev, O_WRONLY)) < 0) { 190 fswritefd = -1; 191 if (preen) 192 pfatal("NO WRITE ACCESS"); 193 printf(" (NO WRITE)"); 194 } 195 if (preen == 0) 196 printf("\n"); 197 fsmodified = 0; 198 lfdir = 0; 199 initbarea(&sblk); 200 initbarea(&asblk); 201 sblk.b_un.b_buf = malloc(LFS_SBPAD); 202 asblk.b_un.b_buf = malloc(LFS_SBPAD); 203 if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL) 204 errexit("cannot allocate space for superblock\n"); 205 if ((lp = getdisklabel((char *) NULL, fsreadfd)) != NULL) 206 dev_bsize = secsize = lp->d_secsize; 207 else 208 dev_bsize = secsize = DEV_BSIZE; 209 210 /* 211 * Read in the superblock, looking for alternates if necessary 212 */ 213 if (readsb(1) == 0) { 214 if (bflag || preen || calcsb(dev, fsreadfd, &proto) == 0) 215 return (0); 216 if (reply("LOOK FOR ALTERNATE SUPERBLOCKS") == 0) 217 return (0); 218 #if 0 /* XXX find the LFS way to do this */ 219 for (cg = 0; cg < proto.lfs_ncg; cg++) { 220 bflag = fsbtodb(&proto, cgsblock(&proto, cg)); 221 if (readsb(0) != 0) 222 break; 223 } 224 if (cg >= proto.lfs_ncg) { 225 printf("%s %s\n%s %s\n%s %s\n", 226 "SEARCH FOR ALTERNATE SUPER-BLOCK", 227 "FAILED. YOU MUST USE THE", 228 "-b OPTION TO FSCK_FFS TO SPECIFY THE", 229 "LOCATION OF AN ALTERNATE", 230 "SUPER-BLOCK TO SUPPLY NEEDED", 231 "INFORMATION; SEE fsck_ffs(8)."); 232 return (0); 233 } 234 #else 235 pwarn("XXX Can't look for alternate superblocks yet\n"); 236 return (0); 237 #endif 238 doskipclean = 0; 239 pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag); 240 } 241 bufinit(); 242 243 if (bflag == 0x0 && idaddr == 0x0) { 244 /* 245 * If we read a proper superblock, but its address was not 246 * lfs_sboffs[0], we're holding a fake primary superblock, 247 * and need to read the real one. 248 */ 249 if (sblock.lfs_sboffs[0] != dbtofsb(&sblock, 250 LFS_LABELPAD / dev_bsize)) 251 { 252 if (debug) 253 pwarn("Getting 'real' primary superblock from 0x%x\n", 254 fsbtodb(&sblock, sblock.lfs_sboffs[0])); 255 bflag = fsbtodb(&sblock, sblock.lfs_sboffs[0]); 256 readsb(1); 257 bflag = 0; 258 } 259 260 /* 261 * Even if that superblock read in properly, it may not 262 * be guaranteed to point to a complete checkpoint. 263 * Read in the second superblock too, and take whichever 264 * of the two is *less* recent. --ks 265 */ 266 sb0 = malloc(sizeof(*sb0)); 267 sb1 = malloc(sizeof(*sb1)); 268 memcpy(sb0, &sblock, sizeof(*sb0)); 269 bflag = fsbtodb(&sblock, sblock.lfs_sboffs[1]); 270 if (readsb(1) == 0) { 271 pwarn("COULDN'T READ ALT SUPERBLOCK AT BLK %d", bflag); 272 if (reply("ASSUME PRIMARY SUPERBLOCK IS GOOD") == 0) { 273 return (0); 274 } else {/* use primary as good */ 275 memcpy(&sblock, sb0, sizeof(*sb0)); /* XXX cheating? */ 276 } 277 } else { 278 memcpy(sb1, &sblock, sizeof(*sb1)); 279 if (debug) { 280 if (sb0->lfs_version > 1) { 281 pwarn("sb0 sn=%lld, sb1 sn=%lld\n", 282 (long long)sb0->lfs_serial, 283 (long long)sblock.lfs_serial); 284 } else { 285 pwarn("sb0 %lld, sb1 %lld\n", 286 (long long)sb0->lfs_otstamp, 287 (long long)sblock.lfs_otstamp); 288 } 289 } 290 /* 291 * Verify the checkpoint of the newer superblock, 292 * if the timestamp of the two superblocks is 293 * different. XXX use lfs_offset instead, discover 294 * how to quickly discover "newness" based on that. 295 */ 296 if ((sb0->lfs_version == 1 && 297 sb0->lfs_otstamp != sb1->lfs_otstamp) || 298 (sb0->lfs_version > 1 && 299 sb0->lfs_serial != sb1->lfs_serial)) { 300 if (sb0->lfs_version == 1) { 301 if (sb0->lfs_otstamp > sb1->lfs_otstamp) { 302 osb = sb1; 303 nsb = sb0; 304 } else { 305 osb = sb0; 306 nsb = sb1; 307 } 308 } else { 309 if (sb0->lfs_serial > sb1->lfs_serial) { 310 osb = sb1; 311 nsb = sb0; 312 } else { 313 osb = sb0; 314 nsb = sb1; 315 } 316 } 317 daddr = try_verify(osb, nsb); 318 319 if (debug) 320 printf("done.\n"); 321 if (daddr == nsb->lfs_offset) { 322 pwarn("Checkpoint verified, recovered %lld seconds of data\n", 323 (long long)nsb->lfs_tstamp - (long long)osb->lfs_tstamp); 324 memcpy(&sblock, nsb, sizeof(*nsb)); 325 sbdirty(); 326 } else { 327 pwarn("Checkpoint invalid, lost %lld seconds of data\n", (long long)nsb->lfs_tstamp - (long long)osb->lfs_tstamp); 328 memcpy(&sblock, osb, sizeof(*osb)); 329 } 330 } 331 } 332 free(sb0); 333 free(sb1); 334 } 335 if (idaddr == 0x0) 336 idaddr = sblock.lfs_idaddr; 337 if (debug) { 338 printf("dev_bsize = %lu\n", dev_bsize); 339 printf("lfs_bsize = %lu\n", (unsigned long)sblock.lfs_bsize); 340 printf("lfs_fsize = %lu\n", (unsigned long)sblock.lfs_fsize); 341 printf("lfs_frag = %lu\n", (unsigned long)sblock.lfs_frag); 342 printf("INOPB(fs) = %lu\n", (unsigned long)INOPB(&sblock)); 343 if (sblock.lfs_version > 1) 344 printf("INOPF(fs) = %lu\n", 345 (unsigned long)INOPF(&sblock)); 346 /* printf("fsbtodb(fs,1) = %lu\n",fsbtodb(&sblock,1)); */ 347 } 348 /* Compatibility */ 349 if (sblock.lfs_version == 1) { 350 sblock.lfs_sumsize = LFS_V1_SUMMARY_SIZE; 351 sblock.lfs_ibsize = sblock.lfs_bsize; 352 sblock.lfs_start = sblock.lfs_sboffs[0]; 353 sblock.lfs_fsbtodb = 0; 354 } 355 initbarea(&iblk); 356 iblk.b_un.b_buf = malloc(sblock.lfs_ibsize); 357 if (bread(fsreadfd, (char *)iblk.b_un.b_buf, fsbtodb(&sblock, idaddr), 358 (long)sblock.lfs_ibsize) != 0) { 359 printf("Couldn't read disk block %d\n", idaddr); 360 exit(1); 361 } 362 idinode = lfs_difind(&sblock, sblock.lfs_ifile, &ifblock); 363 if (idinode == NULL) { 364 printf("Ifile inode not found at daddr 0x%x\n", idaddr); 365 exit(1); 366 /* XXX find it in the segment summaries */ 367 } 368 369 maxino = ((idinode->di_size 370 - (sblock.lfs_cleansz + sblock.lfs_segtabsz) * sblock.lfs_bsize) 371 / sblock.lfs_bsize) * sblock.lfs_ifpb; 372 if (debug) 373 printf("maxino = %d\n", maxino); 374 din_table = (daddr_t *)malloc(maxino * sizeof(*din_table)); 375 memset(din_table, 0, maxino * sizeof(*din_table)); 376 seg_table = (SEGUSE *)malloc(sblock.lfs_nseg * sizeof(SEGUSE)); 377 memset(seg_table, 0, sblock.lfs_nseg * sizeof(SEGUSE)); 378 if (sblock.lfs_version == 1) 379 maxfsblock = sblock.lfs_size * (sblock.lfs_bsize / dev_bsize); 380 else 381 maxfsblock = sblock.lfs_size; 382 maxfilesize = maxtable[sblock.lfs_bshift] << sblock.lfs_bshift; 383 if ((sblock.lfs_minfree < 0 || sblock.lfs_minfree > 99)) { 384 pfatal("IMPOSSIBLE MINFREE=%d IN SUPERBLOCK", 385 sblock.lfs_minfree); 386 if (reply("SET TO DEFAULT") == 1) { 387 sblock.lfs_minfree = 10; 388 sbdirty(); 389 } 390 } 391 if (sblock.lfs_bmask != sblock.lfs_bsize - 1) { 392 pwarn("INCORRECT BMASK=%x IN SUPERBLOCK (should be %x)", 393 (unsigned int)sblock.lfs_bmask, 394 (unsigned int)sblock.lfs_bsize - 1); 395 sblock.lfs_bmask = sblock.lfs_bsize - 1; 396 if (preen) 397 printf(" (FIXED)\n"); 398 if (preen || reply("FIX") == 1) { 399 sbdirty(); 400 dirty(&asblk); 401 } 402 } 403 #if 0 /* FFS-specific checks */ 404 if (sblock.lfs_fmask != ~(sblock.lfs_fsize - 1)) { 405 pwarn("INCORRECT FMASK=%x IN SUPERBLOCK", 406 sblock.lfs_fmask); 407 sblock.lfs_fmask = ~(sblock.lfs_fsize - 1); 408 if (preen) 409 printf(" (FIXED)\n"); 410 if (preen || reply("FIX") == 1) { 411 sbdirty(); 412 dirty(&asblk); 413 } 414 } 415 #endif 416 if (sblock.lfs_maxfilesize != maxfilesize) { 417 pwarn( 418 "INCORRECT MAXFILESIZE=%llu IN SUPERBLOCK (should be %llu)", 419 (unsigned long long)sblock.lfs_maxfilesize, 420 (unsigned long long)maxfilesize); 421 sblock.lfs_maxfilesize = maxfilesize; 422 if (preen) 423 printf(" (FIXED)\n"); 424 if (preen || reply("FIX") == 1) { 425 sbdirty(); 426 dirty(&asblk); 427 } 428 } 429 if (sblock.lfs_maxsymlinklen != MAXSYMLINKLEN) { 430 pwarn("INCORRECT MAXSYMLINKLEN=%d IN SUPERBLOCK", 431 sblock.lfs_maxsymlinklen); 432 sblock.lfs_maxsymlinklen = MAXSYMLINKLEN; 433 if (preen) 434 printf(" (FIXED)\n"); 435 if (preen || reply("FIX") == 1) { 436 sbdirty(); 437 dirty(&asblk); 438 } 439 } 440 newinofmt = 1; 441 /* 442 * allocate and initialize the necessary maps 443 */ 444 #ifndef VERBOSE_BLOCKMAP 445 bmapsize = roundup(howmany(maxfsblock, NBBY), sizeof(int16_t)); 446 blockmap = calloc((unsigned)bmapsize, sizeof(char)); 447 #else 448 bmapsize = maxfsblock * sizeof(ino_t); 449 blockmap = (ino_t *)calloc(maxfsblock, sizeof(ino_t)); 450 #endif 451 if (blockmap == NULL) { 452 printf("cannot alloc %u bytes for blockmap\n", 453 (unsigned)bmapsize); 454 goto badsblabel; 455 } 456 457 statemap = calloc((unsigned)maxino, sizeof(char)); 458 if (statemap == NULL) { 459 printf("cannot alloc %u bytes for statemap\n", 460 (unsigned)maxino); 461 goto badsblabel; 462 } 463 typemap = calloc((unsigned)maxino, sizeof(char)); 464 if (typemap == NULL) { 465 printf("cannot alloc %u bytes for typemap\n", 466 (unsigned)maxino); 467 goto badsblabel; 468 } 469 lncntp = (int16_t *)calloc((unsigned)maxino, sizeof(int16_t)); 470 if (lncntp == NULL) { 471 printf("cannot alloc %lu bytes for lncntp\n", 472 (unsigned long)maxino * sizeof(int16_t)); 473 goto badsblabel; 474 } 475 return (1); 476 477 badsblabel: 478 ckfini(0); 479 return (0); 480 } 481 482 /* 483 * Read in the LFS super block and its summary info. 484 */ 485 static int 486 readsb(int listerr) 487 { 488 daddr_t super = bflag ? bflag : LFS_LABELPAD / dev_bsize; 489 u_int32_t checksum; 490 491 if (bread(fsreadfd, (char *) &sblock, super, (long) LFS_SBPAD) != 0) 492 return (0); 493 494 sblk.b_bno = super; 495 sblk.b_size = LFS_SBPAD; 496 /* 497 * run a few consistency checks of the super block 498 */ 499 if (sblock.lfs_magic != LFS_MAGIC) { 500 badsb(listerr, "MAGIC NUMBER WRONG"); 501 return (0); 502 } 503 /* checksum */ 504 checksum = lfs_sb_cksum(&(sblock.lfs_dlfs)); 505 if (sblock.lfs_cksum != checksum) { 506 printf("Superblock checksum (%lu) does not match computed checksum (%lu)\n", 507 (unsigned long)sblock.lfs_cksum, (unsigned long) checksum); 508 } 509 #if 0 /* XXX - replace these checks with 510 * appropriate LFS sanity checks */ 511 if (sblock.lfs_ncg < 1) { 512 badsb(listerr, "NCG OUT OF RANGE"); 513 return (0); 514 } 515 if (sblock.lfs_cpg < 1) { 516 badsb(listerr, "CPG OUT OF RANGE"); 517 return (0); 518 } 519 if (sblock.lfs_ncg * sblock.lfs_cpg < sblock.lfs_ncyl || 520 (sblock.lfs_ncg - 1) * sblock.lfs_cpg >= sblock.lfs_ncyl) { 521 badsb(listerr, "NCYL LESS THAN NCG*CPG"); 522 return (0); 523 } 524 if (sblock.lfs_sbsize > SBSIZE) { 525 badsb(listerr, "SIZE PREPOSTEROUSLY LARGE"); 526 return (0); 527 } 528 #endif 529 /* 530 * Compute block size that the filesystem is based on, 531 * according to fsbtodb, and adjust superblock block number 532 * so we can tell if this is an alternate later. 533 */ 534 super *= dev_bsize; 535 #if 0 536 dev_bsize = sblock.lfs_bsize / fsbtodb(&sblock, 1); 537 #endif 538 sblk.b_bno = super / dev_bsize; 539 if (bflag) { 540 havesb = 1; 541 return (1); 542 } 543 #if 0 /* XXX - for now skip the alt. superblock 544 * test as well */ 545 /* 546 * Set all possible fields that could differ, then do check 547 * of whole super block against an alternate super block. 548 * When an alternate super-block is specified this check is skipped. 549 */ 550 getblk(&asblk, cgsblock(&sblock, sblock.lfs_ncg - 1), sblock.lfs_sbsize); 551 if (asblk.b_errs) 552 return (0); 553 altsblock.lfs_firstfield = sblock.lfs_firstfield; 554 altsblock.lfs_fscktime = sblock.lfs_fscktime; 555 altsblock.lfs_time = sblock.lfs_time; 556 altsblock.lfs_cstotal = sblock.lfs_cstotal; 557 altsblock.lfs_cgrotor = sblock.lfs_cgrotor; 558 altsblock.lfs_fmod = sblock.lfs_fmod; 559 altsblock.lfs_clean = sblock.lfs_clean; 560 altsblock.lfs_ronly = sblock.lfs_ronly; 561 altsblock.lfs_flags = sblock.lfs_flags; 562 altsblock.lfs_maxcontig = sblock.lfs_maxcontig; 563 altsblock.lfs_minfree = sblock.lfs_minfree; 564 altsblock.lfs_optim = sblock.lfs_optim; 565 altsblock.lfs_rotdelay = sblock.lfs_rotdelay; 566 altsblock.lfs_maxbpg = sblock.lfs_maxbpg; 567 memcpy(altsblock.lfs_csp, sblock.lfs_csp, 568 sizeof sblock.lfs_csp); 569 altsblock.lfs_maxcluster = sblock.lfs_maxcluster; 570 memcpy(altsblock.lfs_fsmnt, sblock.lfs_fsmnt, 571 sizeof sblock.lfs_fsmnt); 572 memcpy(altsblock.lfs_sparecon, sblock.lfs_sparecon, 573 sizeof sblock.lfs_sparecon); 574 /* 575 * The following should not have to be copied. 576 */ 577 altsblock.lfs_fsbtodb = sblock.lfs_fsbtodb; 578 altsblock.lfs_interleave = sblock.lfs_interleave; 579 altsblock.lfs_npsect = sblock.lfs_npsect; 580 altsblock.lfs_nrpos = sblock.lfs_nrpos; 581 altsblock.lfs_state = sblock.lfs_state; 582 altsblock.lfs_qbmask = sblock.lfs_qbmask; 583 altsblock.lfs_qfmask = sblock.lfs_qfmask; 584 altsblock.lfs_state = sblock.lfs_state; 585 altsblock.lfs_maxfilesize = sblock.lfs_maxfilesize; 586 if (memcmp(&sblock, &altsblock, (int)sblock.lfs_sbsize)) { 587 if (debug) { 588 long *nlp, *olp, *endlp; 589 590 printf("superblock mismatches\n"); 591 nlp = (long *) &altsblock; 592 olp = (long *) &sblock; 593 endlp = olp + (sblock.lfs_sbsize / sizeof *olp); 594 for (; olp < endlp; olp++, nlp++) { 595 if (*olp == *nlp) 596 continue; 597 printf("offset %d, original %ld, alternate %ld\n", 598 olp - (long *) &sblock, *olp, *nlp); 599 } 600 } 601 badsb(listerr, 602 "VALUES IN SUPER BLOCK DISAGREE WITH THOSE IN FIRST ALTERNATE"); 603 return (0); 604 } 605 #endif 606 havesb = 1; 607 return (1); 608 } 609 610 void 611 badsb(int listerr, char *s) 612 { 613 614 if (!listerr) 615 return; 616 if (preen) 617 printf("%s: ", cdevname()); 618 pfatal("BAD SUPER BLOCK: %s\n", s); 619 } 620 621 /* 622 * Calculate a prototype superblock based on information in the disk label. 623 * When done the cgsblock macro can be calculated and the fs_ncg field 624 * can be used. Do NOT attempt to use other macros without verifying that 625 * their needed information is available! 626 */ 627 int 628 calcsb(const char *dev, int devfd, struct lfs * fs) 629 { 630 register struct disklabel *lp; 631 register struct partition *pp; 632 register char *cp; 633 int i; 634 635 cp = strchr(dev, '\0') - 1; 636 if ((cp == (char *) -1 || (*cp < 'a' || *cp > 'h')) && !isdigit(*cp)) { 637 pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev); 638 return (0); 639 } 640 lp = getdisklabel(dev, devfd); 641 if (lp == NULL) { 642 dev_bsize = DEV_BSIZE; 643 } else { 644 if (isdigit(*cp)) 645 pp = &lp->d_partitions[0]; 646 else 647 pp = &lp->d_partitions[*cp - 'a']; 648 if (pp->p_fstype != FS_BSDLFS) { 649 pfatal("%s: NOT LABELED AS AN LFS FILE SYSTEM (%s)\n", 650 dev, pp->p_fstype < FSMAXTYPES ? 651 fstypenames[pp->p_fstype] : "unknown"); 652 return (0); 653 } 654 memset(fs, 0, sizeof(struct lfs)); 655 fs->lfs_fsize = pp->p_fsize; 656 fs->lfs_frag = pp->p_frag; 657 fs->lfs_size = pp->p_size; 658 fs->lfs_nspf = fs->lfs_fsize / lp->d_secsize; 659 dev_bsize = lp->d_secsize; 660 for (fs->lfs_fsbtodb = 0, i = fs->lfs_nspf; i > 1; i >>= 1) 661 fs->lfs_fsbtodb++; 662 } 663 return (1); 664 } 665 666 static struct disklabel * 667 getdisklabel(const char *s, int fd) 668 { 669 static struct disklabel lab; 670 671 if (ioctl(fd, DIOCGDINFO, (char *) &lab) < 0) { 672 if (s == NULL) 673 return ((struct disklabel *) NULL); 674 pwarn("ioctl (GCINFO): %s\n", strerror(errno)); 675 #if 0 676 errexit("%s: can't read disk label\n", s); 677 #else 678 return NULL; 679 #endif 680 } 681 return (&lab); 682 } 683