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