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