1 /* $NetBSD: setup.c,v 1.9 2001/07/13 20:30:19 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; 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 daddr += btofsb(osb, LFS_SBPAD); 116 goto oncemore; 117 } 118 return 0x0; 119 } 120 bc = check_summary(osb, sp, daddr); 121 if (bc == 0) 122 break; 123 daddr += btofsb(osb, osb->lfs_sumsize + bc); 124 if (dtosn(osb, daddr) != dtosn(osb, daddr + 125 btofsb(osb, osb->lfs_sumsize + osb->lfs_bsize))) 126 daddr = ((SEGSUM *)summary)->ss_next; 127 } 128 return daddr; 129 } 130 131 u_quad_t maxtable[] = { 132 /* 1 */ -1, 133 /* 2 */ -1, 134 /* 4 */ -1, 135 /* 8 */ -1, 136 /* 16 */ -1, 137 /* 32 */ -1, 138 /* 64 */ -1, 139 /* 128 */ -1, 140 /* 256 */ -1, 141 /* 512 */ NDADDR + 128 + 128 * 128 + 128 * 128 * 128, 142 /* 1024 */ NDADDR + 256 + 256 * 256 + 256 * 256 * 256, 143 /* 2048 */ NDADDR + 512 + 512 * 512 + 512 * 512 * 512, 144 /* 4096 */ NDADDR + 1024 + 1024 * 1024 + 1024 * 1024 * 1024, 145 /* 8192 */ 1 << 31, 146 /* 16 K */ 1 << 31, 147 /* 32 K */ 1 << 31, 148 }; 149 150 int 151 setup(const char *dev) 152 { 153 long bmapsize; 154 struct disklabel *lp; 155 #if 0 156 long i; 157 off_t sizepb; 158 #endif 159 struct stat statb; 160 daddr_t daddr; 161 struct lfs proto; 162 int doskipclean; 163 u_int64_t maxfilesize; 164 struct lfs *sb0, *sb1, *osb, *nsb; 165 struct dinode *idinode; 166 167 havesb = 0; 168 fswritefd = -1; 169 doskipclean = skipclean; 170 if (stat(dev, &statb) < 0) { 171 printf("Can't stat %s: %s\n", dev, strerror(errno)); 172 return (0); 173 } 174 if (!S_ISCHR(statb.st_mode)) { 175 pfatal("%s is not a character device", dev); 176 if (reply("CONTINUE") == 0) 177 return (0); 178 } 179 if ((fsreadfd = open(dev, O_RDONLY)) < 0) { 180 printf("Can't open %s: %s\n", dev, strerror(errno)); 181 return (0); 182 } 183 if (preen == 0) 184 printf("** %s", dev); 185 if (nflag || (fswritefd = open(dev, O_WRONLY)) < 0) { 186 fswritefd = -1; 187 if (preen) 188 pfatal("NO WRITE ACCESS"); 189 printf(" (NO WRITE)"); 190 } 191 if (preen == 0) 192 printf("\n"); 193 fsmodified = 0; 194 lfdir = 0; 195 initbarea(&sblk); 196 initbarea(&asblk); 197 sblk.b_un.b_buf = malloc(LFS_SBPAD); 198 asblk.b_un.b_buf = malloc(LFS_SBPAD); 199 if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL) 200 errexit("cannot allocate space for superblock\n"); 201 if ((lp = getdisklabel((char *) NULL, fsreadfd)) != NULL) 202 dev_bsize = secsize = lp->d_secsize; 203 else 204 dev_bsize = secsize = DEV_BSIZE; 205 206 /* 207 * Read in the superblock, looking for alternates if necessary 208 */ 209 if (readsb(1) == 0) { 210 if (bflag || preen || calcsb(dev, fsreadfd, &proto) == 0) 211 return (0); 212 if (reply("LOOK FOR ALTERNATE SUPERBLOCKS") == 0) 213 return (0); 214 #if 0 /* XXX find the LFS way to do this */ 215 for (cg = 0; cg < proto.lfs_ncg; cg++) { 216 bflag = fsbtodb(&proto, cgsblock(&proto, cg)); 217 if (readsb(0) != 0) 218 break; 219 } 220 if (cg >= proto.lfs_ncg) { 221 printf("%s %s\n%s %s\n%s %s\n", 222 "SEARCH FOR ALTERNATE SUPER-BLOCK", 223 "FAILED. YOU MUST USE THE", 224 "-b OPTION TO FSCK_FFS TO SPECIFY THE", 225 "LOCATION OF AN ALTERNATE", 226 "SUPER-BLOCK TO SUPPLY NEEDED", 227 "INFORMATION; SEE fsck_ffs(8)."); 228 return (0); 229 } 230 #else 231 pwarn("XXX Can't look for alternate superblocks yet\n"); 232 return (0); 233 #endif 234 doskipclean = 0; 235 pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag); 236 } 237 bufinit(); 238 239 if (bflag == 0x0 && idaddr == 0x0) { 240 /* 241 * If we read a proper superblock, but its address was not 242 * lfs_sboffs[0], we're holding a fake primary superblock, 243 * and need to read the real one. 244 */ 245 if (sblock.lfs_sboffs[0] != dbtofsb(&sblock, 246 LFS_LABELPAD / dev_bsize)) 247 { 248 if (debug) 249 pwarn("Getting 'real' prinary superblock from 0x%x\n", 250 fsbtodb(&sblock, sblock.lfs_sboffs[0])); 251 bflag = fsbtodb(&sblock, sblock.lfs_sboffs[0]); 252 readsb(1); 253 bflag = 0; 254 } 255 256 /* 257 * Even if that superblock read in properly, it may not 258 * be guaranteed to point to a complete checkpoint. 259 * Read in the second superblock too, and take whichever 260 * of the two is *less* recent. --ks 261 */ 262 sb0 = malloc(sizeof(*sb0)); 263 sb1 = malloc(sizeof(*sb1)); 264 memcpy(sb0, &sblock, sizeof(*sb0)); 265 bflag = fsbtodb(&sblock, sblock.lfs_sboffs[1]); 266 if (readsb(1) == 0) { 267 pwarn("COULDN'T READ ALT SUPERBLOCK AT BLK %d", bflag); 268 if (reply("ASSUME PRIMARY SUPERBLOCK IS GOOD") == 0) { 269 return (0); 270 } else {/* use primary as good */ 271 memcpy(&sblock, sb0, sizeof(*sb0)); /* XXX cheating? */ 272 } 273 } else { 274 memcpy(sb1, &sblock, sizeof(*sb1)); 275 if (debug) { 276 if (sb0->lfs_version > 1) { 277 pwarn("sb0 sn=%lld, sb1 sn=%lld\n", 278 (long long)sb0->lfs_serial, 279 (long long)sblock.lfs_serial); 280 } else { 281 pwarn("sb0 %lld, sb1 %lld\n", 282 (long long)sb0->lfs_otstamp, 283 (long long)sblock.lfs_otstamp); 284 } 285 } 286 /* 287 * Verify the checkpoint of the newer superblock, 288 * if the timestamp of the two superblocks is 289 * different. XXX use lfs_offset instead, discover 290 * how to quickly discover "newness" based on that. 291 */ 292 if ((sb0->lfs_version == 1 && 293 sb0->lfs_otstamp != sb1->lfs_otstamp) || 294 (sb0->lfs_version > 1 && 295 sb0->lfs_serial != sb1->lfs_serial)) { 296 if (sb0->lfs_version == 1) { 297 if (sb0->lfs_otstamp > sb1->lfs_otstamp) { 298 osb = sb1; 299 nsb = sb0; 300 } else { 301 osb = sb0; 302 nsb = sb1; 303 } 304 } else { 305 if (sb0->lfs_serial > sb1->lfs_serial) { 306 osb = sb1; 307 nsb = sb0; 308 } else { 309 osb = sb0; 310 nsb = sb1; 311 } 312 } 313 daddr = try_verify(osb, nsb); 314 315 if (debug) 316 printf("done.\n"); 317 if (daddr == nsb->lfs_offset) { 318 pwarn("Checkpoint verified, recovered %lld seconds of data\n", 319 (long long)nsb->lfs_tstamp - (long long)osb->lfs_tstamp); 320 memcpy(&sblock, nsb, sizeof(*nsb)); 321 sbdirty(); 322 } else { 323 pwarn("Checkpoint invalid, lost %lld seconds of data\n", (long long)nsb->lfs_tstamp - (long long)osb->lfs_tstamp); 324 memcpy(&sblock, osb, sizeof(*osb)); 325 } 326 } 327 } 328 free(sb0); 329 free(sb1); 330 } 331 if (idaddr == 0x0) 332 idaddr = sblock.lfs_idaddr; 333 if (debug) { 334 printf("dev_bsize = %lu\n", dev_bsize); 335 printf("lfs_bsize = %lu\n", (unsigned long)sblock.lfs_bsize); 336 printf("lfs_fsize = %lu\n", (unsigned long)sblock.lfs_fsize); 337 printf("lfs_frag = %lu\n", (unsigned long)sblock.lfs_frag); 338 printf("INOPB(fs) = %lu\n", (unsigned long)INOPB(&sblock)); 339 if (sblock.lfs_version > 1) 340 printf("INOPF(fs) = %lu\n", 341 (unsigned long)INOPF(&sblock)); 342 /* printf("fsbtodb(fs,1) = %lu\n",fsbtodb(&sblock,1)); */ 343 } 344 /* Compatibility */ 345 if (sblock.lfs_version == 1) { 346 sblock.lfs_sumsize = LFS_V1_SUMMARY_SIZE; 347 sblock.lfs_ibsize = sblock.lfs_bsize; 348 sblock.lfs_start = sblock.lfs_sboffs[0]; 349 sblock.lfs_fsbtodb = 0; 350 } 351 initbarea(&iblk); 352 iblk.b_un.b_buf = malloc(sblock.lfs_ibsize); 353 if (bread(fsreadfd, (char *)iblk.b_un.b_buf, fsbtodb(&sblock, idaddr), 354 (long)sblock.lfs_ibsize) != 0) { 355 printf("Couldn't read disk block %d\n", idaddr); 356 exit(1); 357 } 358 idinode = lfs_difind(&sblock, sblock.lfs_ifile, &ifblock); 359 if (idinode == NULL) { 360 printf("Ifile inode not found at daddr 0x%x\n", idaddr); 361 exit(1); 362 /* XXX find it in the segment summaries */ 363 } 364 365 maxino = ((idinode->di_size 366 - (sblock.lfs_cleansz + sblock.lfs_segtabsz) * sblock.lfs_bsize) 367 / sblock.lfs_bsize) * sblock.lfs_ifpb; 368 if (debug) 369 printf("maxino = %d\n", maxino); 370 din_table = (daddr_t *)malloc(maxino * sizeof(*din_table)); 371 memset(din_table, 0, maxino * sizeof(*din_table)); 372 seg_table = (SEGUSE *)malloc(sblock.lfs_nseg * sizeof(SEGUSE)); 373 memset(seg_table, 0, sblock.lfs_nseg * sizeof(SEGUSE)); 374 if (sblock.lfs_version == 1) 375 maxfsblock = sblock.lfs_size * (sblock.lfs_bsize / dev_bsize); 376 else 377 maxfsblock = sblock.lfs_size; 378 maxfilesize = maxtable[sblock.lfs_bshift] << sblock.lfs_bshift; 379 if ((sblock.lfs_minfree < 0 || sblock.lfs_minfree > 99)) { 380 pfatal("IMPOSSIBLE MINFREE=%d IN SUPERBLOCK", 381 sblock.lfs_minfree); 382 if (reply("SET TO DEFAULT") == 1) { 383 sblock.lfs_minfree = 10; 384 sbdirty(); 385 } 386 } 387 if (sblock.lfs_bmask != sblock.lfs_bsize - 1) { 388 pwarn("INCORRECT BMASK=%x IN SUPERBLOCK (should be %x)", 389 (unsigned int)sblock.lfs_bmask, 390 (unsigned int)sblock.lfs_bsize - 1); 391 sblock.lfs_bmask = sblock.lfs_bsize - 1; 392 if (preen) 393 printf(" (FIXED)\n"); 394 if (preen || reply("FIX") == 1) { 395 sbdirty(); 396 dirty(&asblk); 397 } 398 } 399 #if 0 /* FFS-specific checks */ 400 if (sblock.lfs_fmask != ~(sblock.lfs_fsize - 1)) { 401 pwarn("INCORRECT FMASK=%x IN SUPERBLOCK", 402 sblock.lfs_fmask); 403 sblock.lfs_fmask = ~(sblock.lfs_fsize - 1); 404 if (preen) 405 printf(" (FIXED)\n"); 406 if (preen || reply("FIX") == 1) { 407 sbdirty(); 408 dirty(&asblk); 409 } 410 } 411 #endif 412 if (sblock.lfs_maxfilesize != maxfilesize) { 413 pwarn( 414 "INCORRECT MAXFILESIZE=%llu IN SUPERBLOCK (should be %llu)", 415 (unsigned long long)sblock.lfs_maxfilesize, 416 (unsigned long long)maxfilesize); 417 sblock.lfs_maxfilesize = maxfilesize; 418 if (preen) 419 printf(" (FIXED)\n"); 420 if (preen || reply("FIX") == 1) { 421 sbdirty(); 422 dirty(&asblk); 423 } 424 } 425 if (sblock.lfs_maxsymlinklen != MAXSYMLINKLEN) { 426 pwarn("INCORRECT MAXSYMLINKLEN=%d IN SUPERBLOCK", 427 sblock.lfs_maxsymlinklen); 428 sblock.lfs_maxsymlinklen = MAXSYMLINKLEN; 429 if (preen) 430 printf(" (FIXED)\n"); 431 if (preen || reply("FIX") == 1) { 432 sbdirty(); 433 dirty(&asblk); 434 } 435 } 436 newinofmt = 1; 437 /* 438 * allocate and initialize the necessary maps 439 */ 440 #ifndef VERBOSE_BLOCKMAP 441 bmapsize = roundup(howmany(maxfsblock, NBBY), sizeof(int16_t)); 442 blockmap = calloc((unsigned)bmapsize, sizeof(char)); 443 #else 444 bmapsize = maxfsblock * sizeof(ino_t); 445 blockmap = (ino_t *)calloc(maxfsblock, sizeof(ino_t)); 446 #endif 447 if (blockmap == NULL) { 448 printf("cannot alloc %u bytes for blockmap\n", 449 (unsigned)bmapsize); 450 goto badsblabel; 451 } 452 453 statemap = calloc((unsigned)maxino, sizeof(char)); 454 if (statemap == NULL) { 455 printf("cannot alloc %u bytes for statemap\n", 456 (unsigned)maxino); 457 goto badsblabel; 458 } 459 typemap = calloc((unsigned)maxino, sizeof(char)); 460 if (typemap == NULL) { 461 printf("cannot alloc %u bytes for typemap\n", 462 (unsigned)maxino); 463 goto badsblabel; 464 } 465 lncntp = (int16_t *)calloc((unsigned)maxino, sizeof(int16_t)); 466 if (lncntp == NULL) { 467 printf("cannot alloc %lu bytes for lncntp\n", 468 (unsigned long)maxino * sizeof(int16_t)); 469 goto badsblabel; 470 } 471 return (1); 472 473 badsblabel: 474 ckfini(0); 475 return (0); 476 } 477 478 /* 479 * Read in the LFS super block and its summary info. 480 */ 481 static int 482 readsb(int listerr) 483 { 484 daddr_t super = bflag ? bflag : LFS_LABELPAD / dev_bsize; 485 u_int32_t checksum; 486 487 if (bread(fsreadfd, (char *) &sblock, super, (long) LFS_SBPAD) != 0) 488 return (0); 489 490 sblk.b_bno = super; 491 sblk.b_size = LFS_SBPAD; 492 /* 493 * run a few consistency checks of the super block 494 */ 495 if (sblock.lfs_magic != LFS_MAGIC) { 496 badsb(listerr, "MAGIC NUMBER WRONG"); 497 return (0); 498 } 499 /* checksum */ 500 checksum = lfs_sb_cksum(&(sblock.lfs_dlfs)); 501 if (sblock.lfs_cksum != checksum) { 502 printf("Superblock checksum (%lu)does not match computed checksum %lu\n", 503 (unsigned long)sblock.lfs_cksum, (unsigned long) checksum); 504 } 505 #if 0 /* XXX - replace these checks with 506 * appropriate LFS sanity checks */ 507 if (sblock.lfs_ncg < 1) { 508 badsb(listerr, "NCG OUT OF RANGE"); 509 return (0); 510 } 511 if (sblock.lfs_cpg < 1) { 512 badsb(listerr, "CPG OUT OF RANGE"); 513 return (0); 514 } 515 if (sblock.lfs_ncg * sblock.lfs_cpg < sblock.lfs_ncyl || 516 (sblock.lfs_ncg - 1) * sblock.lfs_cpg >= sblock.lfs_ncyl) { 517 badsb(listerr, "NCYL LESS THAN NCG*CPG"); 518 return (0); 519 } 520 if (sblock.lfs_sbsize > SBSIZE) { 521 badsb(listerr, "SIZE PREPOSTEROUSLY LARGE"); 522 return (0); 523 } 524 #endif 525 /* 526 * Compute block size that the filesystem is based on, 527 * according to fsbtodb, and adjust superblock block number 528 * so we can tell if this is an alternate later. 529 */ 530 super *= dev_bsize; 531 #if 0 532 dev_bsize = sblock.lfs_bsize / fsbtodb(&sblock, 1); 533 #endif 534 sblk.b_bno = super / dev_bsize; 535 if (bflag) { 536 havesb = 1; 537 return (1); 538 } 539 #if 0 /* XXX - for now skip the alt. superblock 540 * test as well */ 541 /* 542 * Set all possible fields that could differ, then do check 543 * of whole super block against an alternate super block. 544 * When an alternate super-block is specified this check is skipped. 545 */ 546 getblk(&asblk, cgsblock(&sblock, sblock.lfs_ncg - 1), sblock.lfs_sbsize); 547 if (asblk.b_errs) 548 return (0); 549 altsblock.lfs_firstfield = sblock.lfs_firstfield; 550 altsblock.lfs_fscktime = sblock.lfs_fscktime; 551 altsblock.lfs_time = sblock.lfs_time; 552 altsblock.lfs_cstotal = sblock.lfs_cstotal; 553 altsblock.lfs_cgrotor = sblock.lfs_cgrotor; 554 altsblock.lfs_fmod = sblock.lfs_fmod; 555 altsblock.lfs_clean = sblock.lfs_clean; 556 altsblock.lfs_ronly = sblock.lfs_ronly; 557 altsblock.lfs_flags = sblock.lfs_flags; 558 altsblock.lfs_maxcontig = sblock.lfs_maxcontig; 559 altsblock.lfs_minfree = sblock.lfs_minfree; 560 altsblock.lfs_optim = sblock.lfs_optim; 561 altsblock.lfs_rotdelay = sblock.lfs_rotdelay; 562 altsblock.lfs_maxbpg = sblock.lfs_maxbpg; 563 memcpy(altsblock.lfs_csp, sblock.lfs_csp, 564 sizeof sblock.lfs_csp); 565 altsblock.lfs_maxcluster = sblock.lfs_maxcluster; 566 memcpy(altsblock.lfs_fsmnt, sblock.lfs_fsmnt, 567 sizeof sblock.lfs_fsmnt); 568 memcpy(altsblock.lfs_sparecon, sblock.lfs_sparecon, 569 sizeof sblock.lfs_sparecon); 570 /* 571 * The following should not have to be copied. 572 */ 573 altsblock.lfs_fsbtodb = sblock.lfs_fsbtodb; 574 altsblock.lfs_interleave = sblock.lfs_interleave; 575 altsblock.lfs_npsect = sblock.lfs_npsect; 576 altsblock.lfs_nrpos = sblock.lfs_nrpos; 577 altsblock.lfs_state = sblock.lfs_state; 578 altsblock.lfs_qbmask = sblock.lfs_qbmask; 579 altsblock.lfs_qfmask = sblock.lfs_qfmask; 580 altsblock.lfs_state = sblock.lfs_state; 581 altsblock.lfs_maxfilesize = sblock.lfs_maxfilesize; 582 if (memcmp(&sblock, &altsblock, (int)sblock.lfs_sbsize)) { 583 if (debug) { 584 long *nlp, *olp, *endlp; 585 586 printf("superblock mismatches\n"); 587 nlp = (long *) &altsblock; 588 olp = (long *) &sblock; 589 endlp = olp + (sblock.lfs_sbsize / sizeof *olp); 590 for (; olp < endlp; olp++, nlp++) { 591 if (*olp == *nlp) 592 continue; 593 printf("offset %d, original %ld, alternate %ld\n", 594 olp - (long *) &sblock, *olp, *nlp); 595 } 596 } 597 badsb(listerr, 598 "VALUES IN SUPER BLOCK DISAGREE WITH THOSE IN FIRST ALTERNATE"); 599 return (0); 600 } 601 #endif 602 havesb = 1; 603 return (1); 604 } 605 606 void 607 badsb(int listerr, char *s) 608 { 609 610 if (!listerr) 611 return; 612 if (preen) 613 printf("%s: ", cdevname()); 614 pfatal("BAD SUPER BLOCK: %s\n", s); 615 } 616 617 /* 618 * Calculate a prototype superblock based on information in the disk label. 619 * When done the cgsblock macro can be calculated and the fs_ncg field 620 * can be used. Do NOT attempt to use other macros without verifying that 621 * their needed information is available! 622 */ 623 int 624 calcsb(const char *dev, int devfd, struct lfs * fs) 625 { 626 register struct disklabel *lp; 627 register struct partition *pp; 628 register char *cp; 629 int i; 630 631 cp = strchr(dev, '\0') - 1; 632 if ((cp == (char *) -1 || (*cp < 'a' || *cp > 'h')) && !isdigit(*cp)) { 633 pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev); 634 return (0); 635 } 636 lp = getdisklabel(dev, devfd); 637 if (lp == NULL) { 638 dev_bsize = DEV_BSIZE; 639 } else { 640 if (isdigit(*cp)) 641 pp = &lp->d_partitions[0]; 642 else 643 pp = &lp->d_partitions[*cp - 'a']; 644 if (pp->p_fstype != FS_BSDLFS) { 645 pfatal("%s: NOT LABELED AS AN LFS FILE SYSTEM (%s)\n", 646 dev, pp->p_fstype < FSMAXTYPES ? 647 fstypenames[pp->p_fstype] : "unknown"); 648 return (0); 649 } 650 memset(fs, 0, sizeof(struct lfs)); 651 fs->lfs_fsize = pp->p_fsize; 652 fs->lfs_frag = pp->p_frag; 653 fs->lfs_size = pp->p_size; 654 fs->lfs_nspf = fs->lfs_fsize / lp->d_secsize; 655 dev_bsize = lp->d_secsize; 656 for (fs->lfs_fsbtodb = 0, i = fs->lfs_nspf; i > 1; i >>= 1) 657 fs->lfs_fsbtodb++; 658 } 659 return (1); 660 } 661 662 static struct disklabel * 663 getdisklabel(const char *s, int fd) 664 { 665 static struct disklabel lab; 666 667 if (ioctl(fd, DIOCGDINFO, (char *) &lab) < 0) { 668 if (s == NULL) 669 return ((struct disklabel *) NULL); 670 pwarn("ioctl (GCINFO): %s\n", strerror(errno)); 671 #if 0 672 errexit("%s: can't read disk label\n", s); 673 #else 674 return NULL; 675 #endif 676 } 677 return (&lab); 678 } 679