1 /* 2 * Copyright 1999 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 7 /* All Rights Reserved */ 8 9 /* 10 * Copyright (c) 1980, 1986, 1990 The Regents of the University of California. 11 * All rights reserved. 12 * 13 * Redistribution and use in source and binary forms are permitted 14 * provided that: (1) source distributions retain this entire copyright 15 * notice and comment, and (2) distributions including binaries display 16 * the following acknowledgement: ``This product includes software 17 * developed by the University of California, Berkeley and its contributors'' 18 * in the documentation or other materials provided with the distribution 19 * and in all advertising materials mentioning features or use of this 20 * software. Neither the name of the University nor the names of its 21 * contributors may be used to endorse or promote products derived 22 * from this software without specific prior written permission. 23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 26 */ 27 28 #pragma ident "%Z%%M% %I% %E% SMI" 29 30 #define DKTYPENAMES 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <unistd.h> 34 #include <fcntl.h> 35 #include <ustat.h> 36 #include <errno.h> 37 #include <sys/param.h> 38 #include <sys/types.h> 39 #include <sys/sysmacros.h> 40 #include <sys/mntent.h> 41 #include <sys/mnttab.h> 42 #include <sys/dkio.h> 43 #include <sys/filio.h> 44 #include <sys/isa_defs.h> /* for ENDIAN defines */ 45 #include <sys/int_const.h> 46 #include <sys/vnode.h> 47 #include <sys/stat.h> 48 #include <sys/file.h> 49 #include <sys/fcntl.h> 50 #include <string.h> 51 #include <sys/vfstab.h> 52 #include <sys/fs/udf_volume.h> 53 #include <sys/vtoc.h> 54 #include <locale.h> 55 56 #include "fsck.h" 57 58 extern void errexit(char *, ...); 59 extern int32_t mounted(char *); 60 extern void pwarn(char *, ...); 61 extern void pfatal(char *, ...); 62 extern void printclean(); 63 extern void bufinit(); 64 extern void ckfini(); 65 extern int32_t bread(int32_t, char *, daddr_t, long); 66 extern int32_t reply(char *); 67 68 static int32_t readvolseq(int32_t); 69 static uint32_t get_last_block(); 70 extern int32_t verifytag(struct tag *, uint32_t, struct tag *, int); 71 extern char *tagerrs[]; 72 73 #define POWEROF2(num) (((num) & ((num) - 1)) == 0) 74 75 extern int mflag; 76 extern char hotroot; 77 78 char avdbuf[MAXBSIZE]; /* buffer for anchor volume descriptor */ 79 char *main_vdbuf; /* buffer for entire main volume sequence */ 80 char *res_vdbuf; /* buffer for reserved volume sequence */ 81 int serialnum = -1; /* set from primary volume descriptor */ 82 83 char * 84 setup(dev) 85 char *dev; 86 { 87 dev_t rootdev; 88 struct stat statb; 89 static char devstr[MAXPATHLEN]; 90 char *raw, *rawname(), *unrawname(); 91 struct ustat ustatb; 92 93 havesb = 0; 94 if (stat("/", &statb) < 0) 95 errexit(gettext("Can't stat root\n")); 96 rootdev = statb.st_dev; 97 98 devname = devstr; 99 (void) strncpy(devstr, dev, sizeof (devstr)); 100 restat: 101 if (stat(devstr, &statb) < 0) { 102 (void) printf(gettext("Can't stat %s\n"), devstr); 103 exitstat = 34; 104 return (0); 105 } 106 /* 107 * A mount point is specified. But the mount point doesn't 108 * match entries in the /etc/vfstab. 109 * Search mnttab, because if the fs is error locked, it is 110 * allowed to be fsck'd while mounted. 111 */ 112 if ((statb.st_mode & S_IFMT) == S_IFDIR) { 113 (void) printf(gettext("%s is not a block or " 114 "character device\n"), dev); 115 return (0); 116 } 117 118 if ((statb.st_mode & S_IFMT) == S_IFBLK) { 119 if (rootdev == statb.st_rdev) 120 hotroot++; 121 else if (ustat(statb.st_rdev, &ustatb) == 0) { 122 (void) printf(gettext("%s is a mounted file system, " 123 "ignored\n"), dev); 124 exitstat = 33; 125 return (0); 126 } 127 } 128 if ((statb.st_mode & S_IFMT) == S_IFDIR) { 129 FILE *vfstab; 130 struct vfstab vfsbuf; 131 /* 132 * Check vfstab for a mount point with this name 133 */ 134 if ((vfstab = fopen(VFSTAB, "r")) == NULL) { 135 errexit(gettext("Can't open checklist file: %s\n"), 136 VFSTAB); 137 } 138 while (getvfsent(vfstab, &vfsbuf) == NULL) { 139 if (strcmp(devstr, vfsbuf.vfs_mountp) == 0) { 140 if (strcmp(vfsbuf.vfs_fstype, 141 MNTTYPE_UDFS) != 0) { 142 /* 143 * found the entry but it is not a 144 * udfs filesystem, don't check it 145 */ 146 (void) fclose(vfstab); 147 return (0); 148 } 149 (void) strcpy(devstr, vfsbuf.vfs_special); 150 if (rflag) { 151 raw = rawname( 152 unrawname(vfsbuf.vfs_special)); 153 (void) strcpy(devstr, raw); 154 } 155 goto restat; 156 } 157 } 158 (void) fclose(vfstab); 159 160 } else if (((statb.st_mode & S_IFMT) != S_IFBLK) && 161 ((statb.st_mode & S_IFMT) != S_IFCHR)) { 162 if (preen) 163 pwarn(gettext("file is not a block or " 164 "character device.\n")); 165 else if (reply(gettext("file is not a block or " 166 "character device; OK")) 167 == 0) 168 return (0); 169 /* 170 * To fsck regular files (fs images) 171 * we need to clear the rflag since 172 * regular files don't have raw names. --CW 173 */ 174 rflag = 0; 175 } 176 177 if (mounted(devstr)) { 178 if (rflag) 179 mountedfs++; 180 else { 181 (void) printf(gettext("%s is mounted, fsck on BLOCK " 182 "device ignored\n"), devstr); 183 exit(33); 184 } 185 sync(); /* call sync, only when devstr's mounted */ 186 } 187 if (rflag) { 188 char blockname[MAXPATHLEN]; 189 /* 190 * For root device check, must check 191 * block devices. 192 */ 193 (void) strcpy(blockname, devstr); 194 if (stat(unrawname(blockname), &statb) < 0) { 195 (void) printf(gettext("Can't stat %s\n"), blockname); 196 exitstat = 34; 197 return (0); 198 } 199 } 200 if (rootdev == statb.st_rdev) 201 hotroot++; 202 if ((fsreadfd = open(devstr, O_RDONLY)) < 0) { 203 (void) printf(gettext("Can't open %s\n"), devstr); 204 exitstat = 34; 205 return (0); 206 } 207 if (preen == 0 || debug != 0) 208 (void) printf("** %s", devstr); 209 210 if (nflag || (fswritefd = open(devstr, O_WRONLY)) < 0) { 211 fswritefd = -1; 212 if (preen && !debug) 213 pfatal(gettext("(NO WRITE ACCESS)\n")); 214 (void) printf(gettext(" (NO WRITE)")); 215 } 216 if (preen == 0) 217 (void) printf("\n"); 218 if (debug && (hotroot || mountedfs)) { 219 (void) printf("** %s", devstr); 220 if (hotroot) 221 (void) printf(" is root fs%s", 222 mountedfs? " and": ""); 223 if (mountedfs) 224 (void) printf(" is mounted"); 225 226 (void) printf(".\n"); 227 } 228 fsmodified = 0; 229 if (readvolseq(1) == 0) 230 return (0); 231 if (fflag == 0 && preen && 232 lvintp->lvid_int_type == LVI_CLOSE) { 233 iscorrupt = 0; 234 printclean(); 235 return (0); 236 } 237 listmax = FEGROW; 238 inphash = (struct fileinfo **)calloc(FEGROW, 239 sizeof (struct fileinfo *)); 240 inphead = (struct fileinfo *)calloc(FEGROW + 1, 241 sizeof (struct fileinfo)); 242 if (inphead == NULL || inphash == NULL) { 243 (void) printf(gettext("cannot alloc %ld bytes for inphead\n"), 244 listmax * sizeof (struct fileinfo)); 245 goto badsb; 246 } 247 inpnext = inphead; 248 inplast = &inphead[listmax]; 249 250 bufinit(); 251 return (devstr); 252 253 badsb: 254 ckfini(); 255 exitstat = 39; 256 return (0); 257 } 258 259 static 260 check_pri_vol_desc(struct tag *tp) 261 { 262 pvolp = (struct pri_vol_desc *)tp; 263 return (0); 264 } 265 266 static 267 check_avdp(struct tag *tp) 268 { 269 avdp = (struct anch_vol_desc_ptr *)tp; 270 return (0); 271 } 272 273 static 274 check_vdp(struct tag *tp) 275 { 276 volp = (struct vdp_desc *)tp; 277 return (0); 278 } 279 280 static 281 check_iuvd(struct tag *tp) 282 { 283 iudp = (struct iuvd_desc *)tp; 284 return (0); 285 } 286 287 static 288 check_part_desc(struct tag *tp) 289 { 290 partp = (struct part_desc *)tp; 291 /* LINTED */ 292 pheadp = (struct phdr_desc *)&partp->pd_pc_use; 293 part_start = partp->pd_part_start; 294 part_len = partp->pd_part_length; 295 if (debug) 296 (void) printf("partition start %x len %x\n", part_start, 297 part_len); 298 return (0); 299 } 300 301 static 302 check_log_desc(struct tag *tp) 303 { 304 logvp = (struct log_vol_desc *)tp; 305 return (0); 306 } 307 308 static 309 check_unall_desc(struct tag *tp) 310 { 311 unallp = (struct unall_desc *)tp; 312 return (0); 313 } 314 315 /* ARGSUSED */ 316 static 317 check_term_desc(struct tag *tp) 318 { 319 return (0); 320 } 321 322 static 323 check_lvint(struct tag *tp) 324 { 325 /* LINTED */ 326 lvintp = (struct log_vol_int_desc *)tp; 327 return (0); 328 } 329 330 void 331 dump16(char *cp, char *nl) 332 { 333 int i; 334 long *ptr; 335 336 337 for (i = 0; i < 16; i += 4) { 338 /* LINTED */ 339 ptr = (long *)(cp + i); 340 (void) printf("%08lx ", *ptr); 341 } 342 (void) printf(nl); 343 } 344 345 /* 346 * Read in the super block and its summary info. 347 */ 348 /* ARGSUSED */ 349 static 350 readvolseq(int32_t listerr) 351 { 352 struct tag *tp; 353 long_ad_t *lap; 354 struct anch_vol_desc_ptr *avp; 355 uint8_t *cp, *end; 356 daddr_t nextblock; 357 int err; 358 long freelen; 359 daddr_t avdp; 360 361 disk_size = get_last_block(); 362 if (debug) 363 (void) printf("Disk partition size: %x\n", disk_size); 364 365 /* LINTED */ 366 avp = (struct anch_vol_desc_ptr *)avdbuf; 367 tp = &avp->avd_tag; 368 for (fsbsize = 512; fsbsize <= MAXBSIZE; fsbsize <<= 1) { 369 avdp = FIRSTAVDP * fsbsize / DEV_BSIZE; 370 if (bread(fsreadfd, avdbuf, avdp, fsbsize) != 0) 371 return (0); 372 err = verifytag(tp, FIRSTAVDP, tp, UD_ANCH_VOL_DESC); 373 if (debug) 374 (void) printf("bsize %ld tp->tag %d, %s\n", fsbsize, 375 tp->tag_id, tagerrs[err]); 376 if (err == 0) 377 break; 378 } 379 if (fsbsize > MAXBSIZE) 380 errexit(gettext("Can't find anchor volume descriptor\n")); 381 secsize = fsbsize; 382 if (debug) 383 (void) printf("fsbsize = %ld\n", fsbsize); 384 main_vdbuf = malloc(avp->avd_main_vdse.ext_len); 385 res_vdbuf = malloc(avp->avd_res_vdse.ext_len); 386 if (main_vdbuf == NULL || res_vdbuf == NULL) 387 errexit("cannot allocate space for volume sequences\n"); 388 if (debug) 389 (void) printf("reading volume sequences " 390 "(%d bytes at %x and %x)\n", 391 avp->avd_main_vdse.ext_len, avp->avd_main_vdse.ext_loc, 392 avp->avd_res_vdse.ext_loc); 393 if (bread(fsreadfd, main_vdbuf, fsbtodb(avp->avd_main_vdse.ext_loc), 394 avp->avd_main_vdse.ext_len) != 0) 395 return (0); 396 if (bread(fsreadfd, res_vdbuf, fsbtodb(avp->avd_res_vdse.ext_loc), 397 avp->avd_res_vdse.ext_len) != 0) 398 return (0); 399 end = (uint8_t *)main_vdbuf + avp->avd_main_vdse.ext_len; 400 nextblock = avp->avd_main_vdse.ext_loc; 401 for (cp = (uint8_t *)main_vdbuf; cp < end; cp += fsbsize, nextblock++) { 402 /* LINTED */ 403 tp = (struct tag *)cp; 404 err = verifytag(tp, nextblock, tp, 0); 405 if (debug) { 406 dump16((char *)cp, ""); 407 (void) printf("blk %lx err %s tag %d\n", nextblock, 408 tagerrs[err], tp->tag_id); 409 } 410 if (err == 0) { 411 if (serialnum >= 0 && tp->tag_sno != serialnum) { 412 (void) printf(gettext("serial number mismatch " 413 "tag type %d, block %lx\n"), tp->tag_id, 414 nextblock); 415 continue; 416 } 417 switch (tp->tag_id) { 418 case UD_PRI_VOL_DESC: 419 serialnum = tp->tag_sno; 420 if (debug) { 421 (void) printf("serial number = %d\n", 422 serialnum); 423 } 424 err = check_pri_vol_desc(tp); 425 break; 426 case UD_ANCH_VOL_DESC: 427 err = check_avdp(tp); 428 break; 429 case UD_VOL_DESC_PTR: 430 err = check_vdp(tp); 431 break; 432 case UD_IMPL_USE_DESC: 433 err = check_iuvd(tp); 434 break; 435 case UD_PART_DESC: 436 err = check_part_desc(tp); 437 break; 438 case UD_LOG_VOL_DESC: 439 err = check_log_desc(tp); 440 break; 441 case UD_UNALL_SPA_DESC: 442 err = check_unall_desc(tp); 443 break; 444 case UD_TERM_DESC: 445 err = check_term_desc(tp); 446 goto done; 447 break; 448 case UD_LOG_VOL_INT: 449 err = check_lvint(tp); 450 break; 451 default: 452 (void) printf(gettext("Invalid volume " 453 "sequence tag %d\n"), tp->tag_id); 454 } 455 } else { 456 (void) printf(gettext("Volume sequence tag error %s\n"), 457 tagerrs[err]); 458 } 459 } 460 done: 461 if (!partp || !logvp) { 462 (void) printf(gettext("Missing partition header or" 463 " logical volume descriptor\n")); 464 return (0); 465 } 466 467 /* Get the logical volume integrity descriptor */ 468 lvintblock = logvp->lvd_int_seq_ext.ext_loc; 469 lvintlen = logvp->lvd_int_seq_ext.ext_len; 470 lvintp = (struct log_vol_int_desc *)malloc(lvintlen); 471 if (debug) 472 (void) printf("Logvolint at %x for %d bytes\n", lvintblock, 473 lvintlen); 474 if (lvintp == NULL) { 475 (void) printf(gettext("Can't allocate space for logical" 476 " volume integrity sequence\n")); 477 return (0); 478 } 479 if (bread(fsreadfd, (char *)lvintp, 480 fsbtodb(lvintblock), lvintlen) != 0) { 481 return (0); 482 } 483 err = verifytag(&lvintp->lvid_tag, lvintblock, &lvintp->lvid_tag, 484 UD_LOG_VOL_INT); 485 if (debug) { 486 dump16((char *)lvintp, "\n"); 487 } 488 if (err) { 489 (void) printf(gettext("Log_vol_int tag error: %s, tag = %d\n"), 490 tagerrs[err], lvintp->lvid_tag.tag_id); 491 return (0); 492 } 493 494 /* Get pointer to implementation use area */ 495 lviup = (struct lvid_iu *)&lvintp->lvid_fst[lvintp->lvid_npart*2]; 496 if (debug) { 497 (void) printf("free space %d total %d ", lvintp->lvid_fst[0], 498 lvintp->lvid_fst[1]); 499 (void) printf(gettext("nfiles %d ndirs %d\n"), lviup->lvidiu_nfiles, 500 lviup->lvidiu_ndirs); 501 } 502 503 /* Set up free block map and read in the existing free space map */ 504 freelen = pheadp->phdr_usb.sad_ext_len; 505 if (freelen == 0) { 506 (void) printf(gettext("No partition free map\n")); 507 } 508 part_bmp_bytes = (part_len + NBBY - 1) / NBBY; 509 busymap = calloc((unsigned)part_bmp_bytes, sizeof (char)); 510 if (busymap == NULL) { 511 (void) printf(gettext("Can't allocate free block bitmap\n")); 512 return (0); 513 } 514 if (freelen) { 515 part_bmp_sectors = 516 (part_bmp_bytes + SPACEMAP_OFF + secsize - 1) / 517 secsize; 518 part_bmp_loc = pheadp->phdr_usb.sad_ext_loc + part_start; 519 520 /* Mark the partition map blocks busy */ 521 markbusy(pheadp->phdr_usb.sad_ext_loc, 522 part_bmp_sectors * secsize); 523 524 spacep = (struct space_bmap_desc *) 525 malloc(secsize*part_bmp_sectors); 526 if (spacep == NULL) { 527 (void) printf(gettext("Can't allocate partition " 528 "map\n")); 529 return (0); 530 } 531 if (bread(fsreadfd, (char *)spacep, fsbtodb(part_bmp_loc), 532 part_bmp_sectors * secsize) != 0) 533 return (0); 534 cp = (uint8_t *)spacep; 535 err = verifytag(&spacep->sbd_tag, pheadp->phdr_usb.sad_ext_loc, 536 &spacep->sbd_tag, UD_SPA_BMAP_DESC); 537 if (debug) { 538 dump16((char *)cp, ""); 539 (void) printf("blk %x err %s tag %d\n", part_bmp_loc, 540 tagerrs[err], spacep->sbd_tag.tag_id); 541 } 542 freemap = (char *)cp + SPACEMAP_OFF; 543 if (debug) 544 (void) printf("err %s tag %x space bitmap at %x" 545 " length %d nbits %d nbytes %d\n", 546 tagerrs[err], spacep->sbd_tag.tag_id, 547 part_bmp_loc, part_bmp_sectors, 548 spacep->sbd_nbits, spacep->sbd_nbytes); 549 if (err) { 550 (void) printf(gettext("Space bitmap tag error, %s, " 551 "tag = %d\n"), 552 tagerrs[err], spacep->sbd_tag.tag_id); 553 return (0); 554 } 555 } 556 557 /* Get the fileset descriptor */ 558 lap = (long_ad_t *)&logvp->lvd_lvcu; 559 filesetblock = lap->lad_ext_loc; 560 filesetlen = lap->lad_ext_len; 561 markbusy(filesetblock, filesetlen); 562 if (debug) 563 (void) printf("Fileset descriptor at %x for %d bytes\n", 564 filesetblock, filesetlen); 565 if (!filesetlen) { 566 (void) printf(gettext("No file set descriptor found\n")); 567 return (0); 568 } 569 fileset = (struct file_set_desc *)malloc(filesetlen); 570 if (fileset == NULL) { 571 (void) printf(gettext("Unable to allocate fileset\n")); 572 return (0); 573 } 574 if (bread(fsreadfd, (char *)fileset, fsbtodb(filesetblock + part_start), 575 filesetlen) != 0) { 576 return (0); 577 } 578 err = verifytag(&fileset->fsd_tag, filesetblock, &fileset->fsd_tag, 579 UD_FILE_SET_DESC); 580 if (err) { 581 (void) printf(gettext("Fileset tag error, tag = %d, %s\n"), 582 fileset->fsd_tag.tag_id, tagerrs[err]); 583 return (0); 584 } 585 586 /* Get the address of the root file entry */ 587 lap = (long_ad_t *)&fileset->fsd_root_icb; 588 rootblock = lap->lad_ext_loc; 589 rootlen = lap->lad_ext_len; 590 if (debug) 591 (void) printf("Root at %x for %d bytes\n", rootblock, rootlen); 592 593 havesb = 1; 594 return (1); 595 } 596 597 uint32_t 598 get_last_block() 599 { 600 struct vtoc vtoc; 601 struct dk_cinfo dki_info; 602 603 if (ioctl(fsreadfd, DKIOCGVTOC, (intptr_t)&vtoc) != 0) { 604 (void) fprintf(stderr, gettext("Unable to read VTOC\n")); 605 return (0); 606 } 607 608 if (vtoc.v_sanity != VTOC_SANE) { 609 (void) fprintf(stderr, gettext("Vtoc.v_sanity != VTOC_SANE\n")); 610 return (0); 611 } 612 613 if (ioctl(fsreadfd, DKIOCINFO, (intptr_t)&dki_info) != 0) { 614 (void) fprintf(stderr, 615 gettext("Could not get the slice information\n")); 616 return (0); 617 } 618 619 if (dki_info.dki_partition > V_NUMPAR) { 620 (void) fprintf(stderr, 621 gettext("dki_info.dki_partition > V_NUMPAR\n")); 622 return (0); 623 } 624 625 return ((uint32_t)vtoc.v_part[dki_info.dki_partition].p_size); 626 } 627