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