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