1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <stdio.h> 27 #include <unistd.h> 28 #include <stdlib.h> 29 #include <string.h> 30 #include <strings.h> 31 #include <fcntl.h> 32 #include <signal.h> 33 #include <setjmp.h> 34 #include <errno.h> 35 #include <inttypes.h> 36 #include <libgen.h> 37 #include <locale.h> 38 39 #include <sys/param.h> 40 #include <sys/signal.h> 41 #include <sys/file.h> 42 #include <sys/sysmacros.h> 43 #include <sys/types.h> 44 #include <sys/vnode.h> 45 #include <sys/mntent.h> 46 #include <sys/wait.h> 47 #include <sys/vtoc.h> 48 #include <sys/dkio.h> 49 50 #include <sys/fs/udf_volume.h> 51 #include "ud_lib.h" 52 #include "y.tab.h" 53 54 typedef unsigned short unicode_t; 55 #define MAXNAMLEN 0x200 56 57 extern uint32_t i_number; 58 59 extern int32_t run_fsdb(); 60 61 void usage(); 62 void init_buffers(); 63 char *getblk(u_offset_t); 64 int32_t parse_udfs(uint32_t); 65 int32_t parse_vds(uint32_t, uint32_t); 66 int32_t parse_part(struct part_desc *); 67 int32_t parse_lvd(struct log_vol_desc *); 68 int32_t parse_fsds(); 69 int32_t get_vat_loc(); 70 int32_t get_fid(uint32_t, uint8_t *, uint64_t); 71 72 73 char *progname; 74 char prompt[256] = "fsdb>"; 75 76 #define ARG_OVERRIDE 0 77 #define ARG_NEW_PROMPT 1 78 #define ARG_WR_ENABLED 2 79 #define ARG_USAGE 3 80 81 char *subopt_v[] = { 82 "o", 83 "p", 84 "w", 85 "?", 86 NULL 87 }; 88 int32_t override = 0; 89 int32_t openflg = O_RDONLY; 90 91 #define MAX_PARTS 10 92 93 /* 94 * udp_flags 95 */ 96 #define UDP_BITMAPS 0x00 97 #define UDP_SPACETBLS 0x01 98 99 ud_handle_t udh; 100 int32_t fd, nparts, nmaps; 101 int32_t bmask, l2d, l2b; 102 103 104 uint16_t ricb_prn; 105 uint32_t ricb_loc, ricb_len; 106 extern int value; 107 108 109 int32_t 110 main(int argc, char *argv[]) 111 { 112 int opt, ret; 113 uint32_t bsize; 114 char *subopts, *optval; 115 116 #if !defined(TEXT_DOMAIN) 117 #define TEXT_DOMAIN "SYS_TEST" 118 #endif 119 (void) textdomain(TEXT_DOMAIN); 120 121 progname = argv[0]; 122 123 while ((opt = getopt(argc, argv, "o:")) != EOF) { 124 switch (opt) { 125 case 'o' : 126 subopts = optarg; 127 while (*subopts != '\0') { 128 switch (getsubopt(&subopts, 129 subopt_v, &optval)) { 130 case ARG_OVERRIDE : 131 override = 1; 132 (void) fprintf(stdout, 133 gettext("error checking off\n")); 134 break; 135 case ARG_NEW_PROMPT : 136 if (optval == NULL) { 137 usage(); 138 } 139 if (strlen(optval) > 255) { 140 (void) fprintf(stdout, 141 gettext("prompt should be less" 142 "than 255 bytes\n")); 143 exit(1); 144 } 145 (void) strcpy(prompt, optval); 146 break; 147 case ARG_WR_ENABLED : 148 openflg = O_RDWR; 149 break; 150 case ARG_USAGE : 151 default : 152 usage(); 153 } 154 } 155 break; 156 default : 157 usage(); 158 } 159 } 160 161 if ((argc - optind) != 1) { /* Should just have "special" left */ 162 usage(); 163 } 164 165 if (ud_init(-1, &udh) != 0) { 166 (void) fprintf(stderr, 167 gettext("udfs labelit: cannot initialize ud_lib\n")); 168 exit(1); 169 } 170 171 if ((fd = ud_open_dev(udh, argv[optind], openflg)) < 0) { 172 perror("open"); 173 exit(1); 174 } 175 176 if ((ret = ud_fill_udfs_info(udh)) != 0) { 177 return (ret); 178 } 179 180 if ((udh->udfs.flags & VALID_UDFS) == 0) { 181 return (1); 182 } 183 184 bsize = udh->udfs.lbsize; 185 bmask = bsize - 1; 186 l2d = 0; 187 while ((bsize >> l2d) > DEV_BSIZE) { 188 l2d++; 189 } 190 l2b = l2d + 9; 191 192 ricb_prn = udh->udfs.ricb_prn; 193 ricb_loc = udh->udfs.ricb_loc; 194 ricb_len = udh->udfs.ricb_len; 195 196 value = i_number = ud_xlate_to_daddr(udh, ricb_prn, ricb_loc); 197 198 init_buffers(); 199 200 run_fsdb(); 201 202 ud_fini(udh); 203 (void) close(fd); 204 205 return (0); 206 } 207 208 /* 209 * usage - print usage and exit 210 */ 211 void 212 usage() 213 { 214 (void) fprintf(stdout, 215 gettext("usage: %s [options] special\n"), progname); 216 (void) fprintf(stdout, 217 gettext("options:\n")); 218 (void) fprintf(stdout, 219 gettext("\t-o\tSpecify udfs filesystem sepcific options\n")); 220 (void) fprintf(stdout, 221 gettext("\t\tAvailable suboptions are:\n")); 222 (void) fprintf(stdout, 223 gettext("\t\t?\tdisplay usage\n")); 224 (void) fprintf(stdout, 225 gettext("\t\to\toverride some error conditions\n")); 226 (void) fprintf(stdout, 227 gettext("\t\tp\t\"string\" set prompt to string\n")); 228 (void) fprintf(stdout, 229 gettext("\t\tw\topen for write\n")); 230 exit(1); 231 } 232 233 #define NBUF 10 234 static struct lbuf { 235 struct lbuf *fwd; 236 struct lbuf *back; 237 int32_t valid; 238 char *blkaddr; 239 u_offset_t blkno; 240 } lbuf[NBUF], bhdr; 241 242 #define INSERT(bp) \ 243 { \ 244 bp->back = &bhdr; \ 245 bp->fwd = bhdr.fwd; \ 246 bhdr.fwd->back = bp; \ 247 bhdr.fwd = bp; \ 248 } 249 250 void 251 init_buffers() 252 { 253 int32_t i; 254 char *addr; 255 struct lbuf *bp; 256 257 addr = malloc(NBUF * udh->udfs.lbsize); 258 bhdr.fwd = bhdr.back = &bhdr; 259 for (i = 0; i < NBUF; i++) { 260 bp = &lbuf[i]; 261 bp->blkaddr = addr + i * udh->udfs.lbsize; 262 bp->valid = 0; 263 INSERT(bp); 264 } 265 } 266 267 char * 268 getblk(u_offset_t address) 269 { 270 u_offset_t off, block; 271 struct lbuf *bp; 272 273 off = address & ~bmask; 274 block = address >> l2b; 275 for (bp = bhdr.fwd; bp != &bhdr; bp = bp->fwd) { 276 if (bp->valid && bp->blkno == block) { 277 goto found; 278 } 279 } 280 bp = bhdr.back; 281 bp->blkno = block; 282 bp->valid = 0; 283 errno = 0; 284 if (llseek(fd, off, SEEK_SET) != off) { 285 (void) fprintf(stdout, 286 gettext("Seek failed fd %x off %llx errno %x\n"), 287 fd, off, errno); 288 return (NULL); 289 } 290 errno = 0; 291 if (read(fd, bp->blkaddr, udh->udfs.lbsize) != udh->udfs.lbsize) { 292 (void) fprintf(stdout, 293 gettext("Read failed fd %x off %llx errno %x\n"), 294 fd, off, errno); 295 return (NULL); 296 } 297 bp->valid = 1; 298 found: 299 bp->back->fwd = bp->fwd; 300 bp->fwd->back = bp->back; 301 INSERT(bp); 302 return (bp->blkaddr); 303 } 304 305 306 int32_t 307 putblk(caddr_t address) 308 { 309 u_offset_t off; 310 struct lbuf *bp; 311 312 if (openflg == O_RDONLY) { 313 (void) fprintf(stdout, 314 gettext("Not run with -w flag\n")); 315 return (1); 316 } 317 318 for (bp = bhdr.fwd; bp != &bhdr; bp = bp->fwd) { 319 if (bp->valid && bp->blkaddr == address) { 320 goto found; 321 } 322 } 323 (void) fprintf(stdout, 324 gettext("Could not find the buffer\n")); 325 return (1); 326 327 found: 328 off = bp->blkno << l2b; 329 if (llseek(fd, off, SEEK_SET) == off) { 330 if (write(fd, bp->blkaddr, udh->udfs.lbsize) == 331 udh->udfs.lbsize) { 332 return (0); 333 } 334 (void) fprintf(stdout, 335 gettext("Write failed fd %x off %llx errno %x\n"), 336 fd, off, errno); 337 } else { 338 (void) fprintf(stdout, 339 gettext("Seek failed fd %x off %llx errno %x\n"), 340 fd, off, errno); 341 } 342 return (1); 343 } 344 345 void 346 inval_bufs() 347 { 348 struct lbuf *bp; 349 350 for (bp = bhdr.fwd; bp != &bhdr; bp = bp->fwd) { 351 bp->valid = 0; 352 } 353 } 354 355 /* 356 * If addr == NULL then use id to print the desc 357 * other wise use addr to self identify the type of desc 358 */ 359 void 360 print_desc(uint32_t addr, int32_t id) 361 { 362 struct tag *tag; 363 caddr_t baddr; 364 365 /* 366 * Read the block at addr 367 * find out the type of tag 368 * and print the descriptor 369 */ 370 if (addr != 0) { 371 if ((baddr = getblk(addr & (~bmask))) == NULL) { 372 (void) fprintf(stdout, 373 gettext("Could not read block %x\n"), 374 addr >> l2b); 375 } 376 /* LINTED */ 377 tag = (struct tag *)(baddr + (addr & bmask)); 378 } else { 379 switch (id) { 380 case AVD : 381 /* LINTED */ 382 if ((tag = (struct tag *)getblk( 383 udh->udfs.avdp_loc << l2b)) == NULL) { 384 (void) fprintf(stdout, 385 gettext("Could not read AVDP\n")); 386 } 387 break; 388 case MVDS : 389 case RVDS : 390 case INTS : 391 { 392 uint32_t i, end; 393 394 if (id == MVDS) { 395 i = udh->udfs.mvds_loc; 396 end = i + 397 (udh->udfs.mvds_len >> l2b); 398 } else if (id == RVDS) { 399 i = udh->udfs.rvds_loc; 400 end = i + 401 (udh->udfs.rvds_len >> l2b); 402 } else { 403 i = udh->udfs.lvid_loc; 404 end = i + 405 (udh->udfs.lvid_len >> l2b); 406 } 407 408 for (; i < end; i++) { 409 print_desc(i << l2b, 0); 410 } 411 } 412 return; 413 case FSDS : 414 case ROOT : 415 { 416 uint16_t prn; 417 uint32_t i, end, block; 418 419 if (id == FSDS) { 420 prn = udh->udfs.fsds_prn; 421 i = udh->udfs.fsds_loc; 422 end = i + 423 (udh->udfs.fsds_len >> l2b); 424 } else { 425 prn = ricb_prn; 426 i = ricb_loc; 427 end = i + (ricb_len >> l2b); 428 } 429 430 for (; i < end; i++) { 431 if ((block = ud_xlate_to_daddr( 432 udh, prn, i)) == 0) { 433 (void) fprintf(stdout, 434 gettext("Cannot xlate " 435 "prn %x loc %x\n"), 436 prn, i); 437 continue; 438 } 439 print_desc(block << l2b, 0); 440 } 441 } 442 /* FALLTHROUGH */ 443 default : 444 return; 445 } 446 } 447 448 switch (SWAP_16(tag->tag_id)) { 449 case UD_PRI_VOL_DESC : 450 print_pvd(stdout, (struct pri_vol_desc *)tag); 451 break; 452 case UD_ANCH_VOL_DESC : 453 print_avd(stdout, (struct anch_vol_desc_ptr *)tag); 454 break; 455 case UD_VOL_DESC_PTR : 456 print_vdp(stdout, (struct vol_desc_ptr *)tag); 457 break; 458 case UD_IMPL_USE_DESC : 459 print_iuvd(stdout, (struct iuvd_desc *)tag); 460 break; 461 case UD_PART_DESC : 462 print_part(stdout, (struct part_desc *)tag); 463 break; 464 case UD_LOG_VOL_DESC : 465 print_lvd(stdout, (struct log_vol_desc *)tag); 466 break; 467 case UD_UNALL_SPA_DESC : 468 print_usd(stdout, (struct unall_spc_desc *)tag); 469 break; 470 case UD_TERM_DESC : 471 (void) fprintf(stdout, "TERM DESC\n"); 472 print_tag(stdout, tag); 473 break; 474 case UD_LOG_VOL_INT : 475 print_lvid(stdout, (struct log_vol_int_desc *)tag); 476 break; 477 case UD_FILE_SET_DESC : 478 print_fsd(stdout, udh, (struct file_set_desc *)tag); 479 break; 480 case UD_FILE_ID_DESC : 481 print_fid(stdout, (struct file_id *)tag); 482 break; 483 case UD_ALLOC_EXT_DESC : 484 print_aed(stdout, (struct alloc_ext_desc *)tag); 485 break; 486 case UD_INDIRECT_ENT : 487 print_ie(stdout, (struct indirect_entry *)tag); 488 break; 489 case UD_TERMINAL_ENT : 490 print_td(stdout, (struct term_desc *)tag); 491 break; 492 case UD_FILE_ENTRY : 493 print_fe(stdout, (struct file_entry *)tag); 494 break; 495 case UD_EXT_ATTR_HDR : 496 case UD_UNALL_SPA_ENT : 497 case UD_SPA_BMAP_DESC : 498 case UD_PART_INT_DESC : 499 case UD_EXT_FILE_ENT : 500 break; 501 default : 502 (void) fprintf(stdout, 503 gettext("unknown descriptor\n")); 504 print_tag(stdout, tag); 505 break; 506 } 507 } 508 509 void 510 set_file(int32_t id, uint32_t iloc, uint64_t value) 511 { 512 uint8_t i8; 513 uint16_t i16; 514 uint32_t i32, block, ea_len, ea_off; 515 uint64_t i64; 516 struct file_entry *fe; 517 struct dev_spec_ear *ds; 518 struct attr_hdr *ah; 519 struct ext_attr_hdr *eah; 520 521 /* LINTED */ 522 if ((fe = (struct file_entry *)getblk(iloc)) == NULL) { 523 return; 524 } 525 if (ud_verify_tag(udh, &fe->fe_tag, UD_FILE_ENTRY, 526 SWAP_32(fe->fe_tag.tag_loc), 1, 1) != 0) { 527 return; 528 } 529 i8 = (uint8_t)value; 530 i16 = SWAP_16(((uint16_t)value)); 531 i32 = SWAP_32(((uint32_t)value)); 532 i64 = SWAP_64(value); 533 switch (id) { 534 case ATTZ : 535 fe->fe_acc_time.ts_tzone = i16; 536 break; 537 case ATYE : 538 fe->fe_acc_time.ts_year = i16; 539 break; 540 case ATMO : 541 fe->fe_acc_time.ts_month = i8; 542 break; 543 case ATDA : 544 fe->fe_acc_time.ts_day = i8; 545 break; 546 case ATHO : 547 fe->fe_acc_time.ts_hour = i8; 548 break; 549 case ATMI : 550 fe->fe_acc_time.ts_min = i8; 551 break; 552 case ATSE : 553 fe->fe_acc_time.ts_sec = i8; 554 break; 555 case ATCE : 556 fe->fe_acc_time.ts_csec = i8; 557 break; 558 case ATHU : 559 fe->fe_acc_time.ts_husec = i8; 560 break; 561 case ATMIC : 562 fe->fe_acc_time.ts_usec = i8; 563 break; 564 case CTTZ : 565 fe->fe_attr_time.ts_tzone = i16; 566 break; 567 case CTYE : 568 fe->fe_attr_time.ts_year = i16; 569 break; 570 case CTMO : 571 fe->fe_attr_time.ts_month = i8; 572 break; 573 case CTDA : 574 fe->fe_attr_time.ts_day = i8; 575 break; 576 case CTHO : 577 fe->fe_attr_time.ts_hour = i8; 578 break; 579 case CTMI : 580 fe->fe_attr_time.ts_min = i8; 581 break; 582 case CTSE : 583 fe->fe_attr_time.ts_sec = i8; 584 break; 585 case CTCE : 586 fe->fe_attr_time.ts_csec = i8; 587 break; 588 case CTHU : 589 fe->fe_attr_time.ts_husec = i8; 590 break; 591 case CTMIC : 592 fe->fe_attr_time.ts_usec = i8; 593 break; 594 case MTTZ : 595 fe->fe_mod_time.ts_tzone = i16; 596 break; 597 case MTYE : 598 fe->fe_mod_time.ts_year = i16; 599 break; 600 case MTMO : 601 fe->fe_mod_time.ts_month = i8; 602 break; 603 case MTDA : 604 fe->fe_mod_time.ts_day = i8; 605 break; 606 case MTHO : 607 fe->fe_mod_time.ts_hour = i8; 608 break; 609 case MTMI : 610 fe->fe_mod_time.ts_min = i8; 611 break; 612 case MTSE : 613 fe->fe_mod_time.ts_sec = i8; 614 break; 615 case MTCE : 616 fe->fe_mod_time.ts_csec = i8; 617 break; 618 case MTHU : 619 fe->fe_mod_time.ts_husec = i8; 620 break; 621 case MTMIC : 622 fe->fe_mod_time.ts_usec = i8; 623 break; 624 case GID : 625 fe->fe_gid = i32; 626 break; 627 case LN : 628 fe->fe_lcount = i16; 629 break; 630 case MD : 631 fe->fe_perms = i32; 632 break; 633 case MAJ : 634 case MIO : 635 if ((fe->fe_icb_tag.itag_ftype != VBLK) && 636 (fe->fe_icb_tag.itag_ftype != VCHR)) { 637 (void) fprintf(stdout, 638 gettext("Not a device\n")); 639 break; 640 } 641 /* LINTED */ 642 eah = (struct ext_attr_hdr *)fe->fe_spec; 643 ea_off = SWAP_32(eah->eah_ial); 644 ea_len = SWAP_32(fe->fe_len_ear); 645 block = SWAP_32(eah->eah_tag.tag_loc); 646 if (ea_len && (ud_verify_tag(udh, &eah->eah_tag, 647 UD_EXT_ATTR_HDR, block, 1, 1) == 0)) { 648 while (ea_off < ea_len) { 649 /* LINTED */ 650 ah = (struct attr_hdr *) 651 &fe->fe_spec[ea_off]; 652 if ((ah->ahdr_atype == SWAP_32(12)) && 653 (ah->ahdr_astype == 1)) { 654 655 ds = (struct dev_spec_ear *)ah; 656 if (id == MAJ) { 657 ds->ds_major_id = i32; 658 } else { 659 ds->ds_minor_id = i32; 660 } 661 ud_make_tag(udh, &eah->eah_tag, 662 UD_EXT_ATTR_HDR, block, 663 eah->eah_tag.tag_crc_len); 664 break; 665 } 666 } 667 } 668 (void) fprintf(stdout, 669 gettext("does not have a Device Specification EA\n")); 670 break; 671 case NM : 672 break; 673 case SZ : 674 fe->fe_info_len = i64; 675 break; 676 case UID : 677 fe->fe_uid = i32; 678 break; 679 case UNIQ : 680 fe->fe_uniq_id = i32; 681 break; 682 default : 683 (void) fprintf(stdout, 684 gettext("Unknown set\n")); 685 } 686 ud_make_tag(udh, &fe->fe_tag, UD_FILE_ENTRY, 687 SWAP_32(fe->fe_tag.tag_loc), fe->fe_tag.tag_crc_len); 688 (void) putblk((caddr_t)fe); 689 } 690 691 caddr_t 692 verify_inode(uint32_t addr, uint32_t type) 693 { 694 struct file_entry *fe; 695 struct tag *tag; 696 697 /* LINTED */ 698 if ((tag = (struct tag *)getblk(addr & (~bmask))) == NULL) { 699 (void) fprintf(stdout, 700 gettext("Could not read block %x\n"), 701 addr >> l2b); 702 } else { 703 if (ud_verify_tag(udh, tag, UD_FILE_ENTRY, 704 addr >> l2b, 0, 1) != 0) { 705 (void) fprintf(stdout, 706 gettext("Not a file entry(inode) at %x\n"), 707 addr >> l2b); 708 } else { 709 if (ud_verify_tag(udh, tag, UD_FILE_ENTRY, 710 SWAP_32(tag->tag_loc), 1, 1) != 0) { 711 (void) fprintf(stdout, 712 gettext("CRC failed\n")); 713 } else { 714 fe = (struct file_entry *)tag; 715 if ((type == 0) || 716 (type == fe->fe_icb_tag.itag_ftype)) { 717 return ((caddr_t)tag); 718 } 719 } 720 } 721 } 722 return (0); 723 } 724 725 void 726 print_inode(uint32_t addr) 727 { 728 if (verify_inode(addr, 0) != NULL) { 729 print_desc(addr, 0); 730 } 731 } 732 733 int32_t 734 verify_dent(uint32_t i_addr, uint32_t nent) 735 { 736 uint32_t ent = 0; 737 uint64_t off = 0; 738 uint8_t buf[1024]; 739 struct file_id *fid; 740 741 /* LINTED */ 742 fid = (struct file_id *)buf; 743 744 if (verify_inode(i_addr, 4) == 0) { 745 (void) fprintf(stdout, 746 gettext("Inode is not a directory\n")); 747 return (1); 748 } 749 750 while (get_fid(i_addr >> l2b, buf, off) == 0) { 751 off += FID_LEN(fid); 752 if (ent == nent) { 753 return (0); 754 } 755 ent++; 756 } 757 (void) fprintf(stdout, 758 gettext("Reached EOF\n")); 759 return (1); 760 } 761 762 void 763 print_dent(uint32_t i_addr, uint32_t nent) 764 { 765 uint32_t ent = 0; 766 uint64_t off = 0; 767 uint8_t buf[1024]; 768 struct file_id *fid; 769 770 /* LINTED */ 771 fid = (struct file_id *)buf; 772 773 if (verify_dent(i_addr, nent) == 0) { 774 while (get_fid(i_addr >> l2b, buf, off) == 0) { 775 off += FID_LEN(fid); 776 if (ent == nent) { 777 print_fid(stdout, fid); 778 return; 779 } 780 ent++; 781 } 782 } 783 } 784 785 uint32_t in; 786 uint32_t de_count, ie_count; 787 struct ext { 788 uint16_t prn; 789 uint16_t flags; 790 uint32_t blkno; 791 uint32_t len; 792 } *de, *ie; 793 794 int32_t 795 get_blkno(uint32_t inode, uint32_t *blkno, uint64_t off) 796 { 797 struct file_entry *fe; 798 int32_t i, d, nent; 799 uint16_t prn, flags, elen; 800 uint32_t desc_type, bno, len; 801 struct short_ad *sad; 802 struct long_ad *lad; 803 uint64_t b_off, e_off; 804 805 if (inode != in) { 806 /* LINTED */ 807 if ((fe = (struct file_entry *) 808 getblk(inode << l2b)) == NULL) { 809 (void) fprintf(stdout, 810 gettext("Could not read block %x\n"), 811 off & (~bmask)); 812 return (1); 813 } 814 desc_type = SWAP_16(fe->fe_icb_tag.itag_flags) & 0x7; 815 sad = NULL; 816 lad = NULL; 817 if (desc_type == ICB_FLAG_SHORT_AD) { 818 elen = sizeof (struct short_ad); 819 /* LINTED */ 820 sad = (struct short_ad *) 821 (fe->fe_spec + SWAP_32(fe->fe_len_ear)); 822 } else if (desc_type == ICB_FLAG_LONG_AD) { 823 elen = sizeof (struct long_ad); 824 /* LINTED */ 825 lad = (struct long_ad *) 826 (fe->fe_spec + SWAP_32(fe->fe_len_ear)); 827 } else if (desc_type == ICB_FLAG_ONE_AD) { 828 *blkno = inode; 829 return (0); 830 } else { 831 /* This cannot happen return */ 832 return (EINVAL); 833 } 834 835 nent = SWAP_32(fe->fe_len_adesc) / elen; 836 de = malloc(nent * sizeof (struct ext)); 837 if (de == NULL) { 838 (void) fprintf(stdout, 839 gettext("could not allocate memeory\n")); 840 return (1); 841 } 842 in = inode; 843 de_count = nent; 844 for (d = 0, i = 0; i < nent; i++) { 845 switch (desc_type) { 846 case ICB_FLAG_SHORT_AD: 847 prn = 0; 848 bno = SWAP_32(sad->sad_ext_loc); 849 len = SWAP_32(sad->sad_ext_len); 850 break; 851 case ICB_FLAG_LONG_AD: 852 prn = SWAP_16(lad->lad_ext_prn); 853 bno = SWAP_32(lad->lad_ext_loc); 854 len = SWAP_32(lad->lad_ext_len); 855 break; 856 default: 857 prn = 0; 858 bno = 0; 859 len = 0; 860 } 861 flags = len >> 30; 862 if (flags == 0x3) { 863 (void) fprintf(stdout, 864 gettext("Handle IE\n")); 865 } else { 866 de[d].prn = prn; 867 de[d].flags = flags; 868 de[d].blkno = bno; 869 de[d].len = len & 0x3FFFFFFF; 870 d++; 871 } 872 } 873 } 874 875 b_off = 0; 876 for (i = 0; i < de_count; i++) { 877 e_off = b_off + de[i].len; 878 if (off < e_off) { 879 bno = de[i].blkno + ((off - b_off) >> l2b); 880 if ((*blkno = ud_xlate_to_daddr( 881 udh, de[i].prn, bno)) == 0) { 882 return (1); 883 } 884 return (0); 885 } 886 b_off = e_off; 887 } 888 return (1); 889 } 890 891 /* 892 * assume the buffer is big enough 893 * for the entire request 894 */ 895 int32_t 896 read_file(uint32_t inode, uint8_t *buf, uint32_t count, uint64_t off) 897 { 898 caddr_t addr; 899 uint32_t bno, tcount; 900 901 902 while (count) { 903 if (get_blkno(inode, &bno, off) != 0) { 904 return (1); 905 } 906 if ((addr = getblk(bno << l2b)) == NULL) { 907 return (1); 908 } 909 if (bno == inode) { 910 struct file_entry *fe; 911 /* 912 * embedded file 913 */ 914 /* LINTED */ 915 fe = (struct file_entry *)addr; 916 addr += 0xB0 + SWAP_32(fe->fe_len_ear); 917 if (off >= SWAP_64(fe->fe_info_len)) { 918 return (1); 919 } 920 } 921 tcount = udh->udfs.lbsize - (off & bmask); 922 if (tcount > count) { 923 tcount = count; 924 } 925 addr += off & bmask; 926 (void) memcpy(buf, addr, tcount); 927 count -= tcount; 928 buf += tcount; 929 off += tcount; 930 } 931 return (0); 932 } 933 934 int32_t 935 get_fid(uint32_t inode, uint8_t *buf, uint64_t off) 936 { 937 struct file_id *fid; 938 939 /* LINTED */ 940 fid = (struct file_id *)buf; 941 if ((read_file(inode, buf, sizeof (struct file_id), off)) != 0) { 942 return (1); 943 } 944 945 if (ud_verify_tag(udh, &fid->fid_tag, UD_FILE_ID_DESC, 0, 0, 1) != 0) { 946 (void) fprintf(stdout, 947 gettext("file_id tag does not verify off %llx\n"), 948 off); 949 return (1); 950 } 951 952 if ((read_file(inode, buf, FID_LEN(fid), off)) != 0) { 953 return (1); 954 } 955 956 return (0); 957 } 958 959 /* 960 * Path is absolute path 961 */ 962 int32_t 963 inode_from_path(char *path, uint32_t *in, uint8_t *fl) 964 { 965 char dname[1024]; 966 char fname[256]; 967 int32_t err; 968 uint32_t dinode; 969 struct tag *tag; 970 uint8_t flags; 971 972 uint8_t buf[1024]; 973 uint64_t off; 974 struct file_id *fid; 975 uint8_t *addr; 976 977 if (strcmp(path, "/") == 0) { 978 *fl = FID_DIR; 979 if ((*in = ud_xlate_to_daddr(udh, ricb_prn, ricb_loc)) == 0) { 980 return (1); 981 } 982 return (0); 983 } 984 985 (void) strcpy(dname, path); 986 (void) strcpy(fname, basename(dname)); 987 (void) dirname(dname); 988 989 if ((err = inode_from_path(dname, &dinode, &flags)) != 0) { 990 return (1); 991 } 992 993 994 /* 995 * Check if dname is a directory 996 */ 997 if ((flags & FID_DIR) == 0) { 998 (void) fprintf(stdout, 999 gettext("Path %s is not a directory\n"), path); 1000 } 1001 1002 /* 1003 * Search for the fname in the directory now 1004 */ 1005 1006 1007 off = 0; 1008 /* LINTED */ 1009 fid = (struct file_id *)buf; 1010 while (get_fid(dinode, buf, off) == 0) { 1011 off += FID_LEN(fid); 1012 if (fid->fid_flags & FID_DELETED) { 1013 continue; 1014 } 1015 addr = &fid->fid_spec[SWAP_16((fid)->fid_iulen) + 1]; 1016 if (fid->fid_flags & FID_PARENT) { 1017 addr[0] = '.'; 1018 addr[1] = '.'; 1019 addr[2] = '\0'; 1020 } else { 1021 addr[fid->fid_idlen] = '\0'; 1022 } 1023 if (strcmp((caddr_t)addr, fname) == 0) { 1024 *fl = fid->fid_flags; 1025 if ((*in = ud_xlate_to_daddr(udh, 1026 SWAP_16(fid->fid_icb.lad_ext_prn), 1027 SWAP_32(fid->fid_icb.lad_ext_loc))) == 0) { 1028 return (1); 1029 } 1030 /* LINTED */ 1031 if ((tag = (struct tag *)getblk(*in << l2b)) == NULL) { 1032 (void) fprintf(stdout, 1033 gettext("Could not read block %x\n"), 1034 *in); 1035 return (1); 1036 } 1037 if (ud_verify_tag(udh, tag, UD_FILE_ENTRY, 1038 0, 0, 1) != 0) { 1039 (void) fprintf(stdout, 1040 gettext("Not a file entry(inode)" 1041 " at %x\n"), *in); 1042 return (1); 1043 } 1044 if (ud_verify_tag(udh, tag, UD_FILE_ENTRY, 1045 SWAP_32(tag->tag_loc), 1, 1) != 0) { 1046 (void) fprintf(stdout, 1047 gettext("CRC failed\n")); 1048 return (1); 1049 } 1050 1051 return (0); 1052 } 1053 } 1054 return (err); 1055 } 1056 1057 struct recu_dir { 1058 struct recu_dir *next; 1059 uint32_t inode; 1060 char *nm; 1061 }; 1062 1063 void 1064 list(char *nm, uint32_t in, uint32_t fl) 1065 { 1066 uint8_t buf[1024]; 1067 uint64_t off; 1068 struct file_id *fid; 1069 struct recu_dir *rd, *erd, *temp; 1070 uint32_t iloc; 1071 1072 rd = erd = temp = NULL; 1073 if (verify_inode(in << l2b, 4) == 0) { 1074 (void) fprintf(stdout, 1075 gettext("Inode is not a directory\n")); 1076 return; 1077 } 1078 1079 if (fl & 2) { 1080 (void) printf("\n"); 1081 if (fl & 1) { 1082 (void) fprintf(stdout, 1083 gettext("i#: %x\t"), in); 1084 } 1085 (void) printf("%s\n", nm); 1086 } 1087 1088 off = 0; 1089 /* LINTED */ 1090 fid = (struct file_id *)buf; 1091 while (get_fid(in, buf, off) == 0) { 1092 off += FID_LEN(fid); 1093 if (fid->fid_flags & FID_DELETED) { 1094 continue; 1095 } 1096 iloc = ud_xlate_to_daddr(udh, SWAP_16(fid->fid_icb.lad_ext_prn), 1097 SWAP_32(fid->fid_icb.lad_ext_loc)); 1098 if (fl & 1) { 1099 (void) fprintf(stdout, 1100 gettext("i#: %x\t"), iloc); 1101 } 1102 if (fid->fid_flags & FID_PARENT) { 1103 (void) fprintf(stdout, 1104 gettext("..\n")); 1105 } else { 1106 int32_t i; 1107 uint8_t *addr; 1108 1109 addr = &fid->fid_spec[SWAP_16((fid)->fid_iulen) + 1]; 1110 for (i = 0; i < fid->fid_idlen - 1; i++) 1111 (void) fprintf(stdout, "%c", addr[i]); 1112 (void) fprintf(stdout, "\n"); 1113 if ((fid->fid_flags & FID_DIR) && 1114 (fl & 2)) { 1115 temp = (struct recu_dir *) 1116 malloc(sizeof (struct recu_dir)); 1117 if (temp == NULL) { 1118 (void) fprintf(stdout, 1119 gettext("Could not allocate memory\n")); 1120 } else { 1121 temp->next = NULL; 1122 temp->inode = iloc; 1123 temp->nm = malloc(strlen(nm) + 1 + 1124 fid->fid_idlen + 1); 1125 if (temp->nm != NULL) { 1126 (void) strcpy(temp->nm, nm); 1127 (void) strcat(temp->nm, "/"); 1128 (void) strncat(temp->nm, 1129 (char *)addr, 1130 fid->fid_idlen); 1131 } 1132 if (rd == NULL) { 1133 erd = rd = temp; 1134 } else { 1135 erd->next = temp; 1136 erd = temp; 1137 } 1138 } 1139 } 1140 } 1141 } 1142 1143 while (rd != NULL) { 1144 if (rd->nm != NULL) { 1145 list(rd->nm, rd->inode, fl); 1146 } else { 1147 list(".", rd->inode, fl); 1148 } 1149 temp = rd; 1150 rd = rd->next; 1151 if (temp->nm) { 1152 free(temp->nm); 1153 } 1154 free(temp); 1155 } 1156 } 1157 1158 void 1159 fill_pattern(uint32_t addr, uint32_t count, char *pattern) 1160 { 1161 uint32_t beg, end, soff, lcount; 1162 int32_t len = strlen(pattern); 1163 caddr_t buf, p; 1164 1165 if (openflg == O_RDONLY) { 1166 (void) fprintf(stdout, 1167 gettext("Not run with -w flag\n")); 1168 return; 1169 } 1170 1171 if (count == 0) { 1172 count = 1; 1173 } 1174 beg = addr; 1175 end = addr + count * len; 1176 soff = beg & (~bmask); 1177 lcount = ((end + bmask) & (~bmask)) - soff; 1178 1179 inval_bufs(); 1180 1181 buf = malloc(lcount); 1182 1183 if (llseek(fd, soff, SEEK_SET) != soff) { 1184 (void) fprintf(stdout, 1185 gettext("Seek failed fd %x off %llx errno %x\n"), 1186 fd, soff, errno); 1187 goto end; 1188 } 1189 1190 if (read(fd, buf, lcount) != lcount) { 1191 (void) fprintf(stdout, 1192 gettext("Read failed fd %x off %llx errno %x\n"), 1193 fd, soff, errno); 1194 goto end; 1195 } 1196 1197 p = buf + (addr & bmask); 1198 while (count--) { 1199 (void) strncpy(p, pattern, len); 1200 p += len; 1201 } 1202 1203 if (write(fd, buf, lcount) != lcount) { 1204 (void) fprintf(stdout, 1205 gettext("Write failed fd %x off %llx errno %x\n"), 1206 fd, soff, errno); 1207 goto end; 1208 } 1209 end: 1210 free(buf); 1211 } 1212 1213 void 1214 dump_disk(uint32_t addr, uint32_t count, char *format) 1215 { 1216 uint32_t beg, end, soff, lcount; 1217 int32_t len, prperline, n; 1218 uint8_t *buf, *p; 1219 uint16_t *p_16; 1220 uint32_t *p_32; 1221 1222 if (strlen(format) != 1) { 1223 (void) fprintf(stdout, 1224 gettext("Invalid command\n")); 1225 return; 1226 } 1227 if (count == 0) { 1228 count = 1; 1229 } 1230 switch (*format) { 1231 case 'b' : 1232 /* FALLTHROUGH */ 1233 case 'c' : 1234 /* FALLTHROUGH */ 1235 case 'd' : 1236 /* FALLTHROUGH */ 1237 case 'o' : 1238 len = 1; 1239 prperline = 16; 1240 break; 1241 case 'x' : 1242 len = 2; 1243 prperline = 8; 1244 break; 1245 case 'D' : 1246 /* FALLTHROUGH */ 1247 case 'O' : 1248 /* FALLTHROUGH */ 1249 case 'X' : 1250 len = 4; 1251 prperline = 4; 1252 break; 1253 default : 1254 (void) fprintf(stdout, 1255 gettext("Invalid format\n")); 1256 return; 1257 } 1258 1259 beg = addr; 1260 end = addr + count * len; 1261 soff = beg & (~bmask); 1262 lcount = ((end + bmask) & (~bmask)) - soff; 1263 1264 inval_bufs(); 1265 1266 buf = malloc(lcount); 1267 if (llseek(fd, soff, SEEK_SET) != soff) { 1268 (void) fprintf(stdout, 1269 gettext("Seek failed fd %x off %llx errno %x\n"), 1270 fd, soff, errno); 1271 goto end; 1272 } 1273 1274 if (read(fd, buf, lcount) != lcount) { 1275 (void) fprintf(stdout, 1276 gettext("Read failed fd %x off %llx errno %x\n"), 1277 fd, soff, errno); 1278 goto end; 1279 } 1280 p = buf + (addr & bmask); 1281 /* LINTED */ 1282 p_16 = (uint16_t *)p; 1283 /* LINTED */ 1284 p_32 = (uint32_t *)p; 1285 n = 0; 1286 while (n < count) { 1287 switch (*format) { 1288 case 'b' : 1289 (void) fprintf(stdout, 1290 "%4x ", *((uint8_t *)p)); 1291 break; 1292 case 'c' : 1293 (void) fprintf(stdout, 1294 "%4c ", *((uint8_t *)p)); 1295 break; 1296 case 'd' : 1297 (void) fprintf(stdout, 1298 "%4d ", *((uint8_t *)p)); 1299 break; 1300 case 'o' : 1301 (void) fprintf(stdout, 1302 "%4o ", *((uint8_t *)p)); 1303 break; 1304 case 'x' : 1305 (void) fprintf(stdout, 1306 "%8x ", *p_16); 1307 break; 1308 case 'D' : 1309 (void) fprintf(stdout, 1310 "%16d ", *p_32); 1311 break; 1312 case 'O' : 1313 (void) fprintf(stdout, 1314 "%16o ", *p_32); 1315 break; 1316 case 'X' : 1317 (void) fprintf(stdout, 1318 "%16x ", *p_32); 1319 break; 1320 } 1321 p += len; 1322 n++; 1323 if ((n % prperline) == 0) { 1324 (void) fprintf(stdout, "\n"); 1325 } 1326 } 1327 if (n % prperline) { 1328 (void) fprintf(stdout, "\n"); 1329 } 1330 end: 1331 free(buf); 1332 } 1333 1334 void 1335 find_it(char *dir, char *name, uint32_t in, uint32_t fl) 1336 { 1337 uint8_t buf[1024], *addr; 1338 uint64_t off; 1339 struct file_id *fid; 1340 uint32_t iloc, d_in; 1341 uint8_t d_fl; 1342 struct recu_dir *rd, *erd, *temp; 1343 1344 rd = erd = temp = NULL; 1345 1346 if (inode_from_path(dir, &d_in, &d_fl) != 0) { 1347 (void) fprintf(stdout, 1348 gettext("Could not find directory %s"), dir); 1349 return; 1350 } 1351 1352 if ((d_fl & FID_DIR) == 0) { 1353 (void) fprintf(stdout, 1354 gettext("Path %s is not a directory\n"), dir); 1355 return; 1356 } 1357 1358 if (verify_inode(d_in << l2b, 4) == 0) { 1359 (void) fprintf(stdout, 1360 gettext("Inode is not a directory\n")); 1361 return; 1362 } 1363 1364 off = 0; 1365 /* LINTED */ 1366 fid = (struct file_id *)buf; 1367 while (get_fid(d_in, buf, off) == 0) { 1368 off += FID_LEN(fid); 1369 if ((fid->fid_flags & FID_DELETED) || 1370 (fid->fid_flags & FID_PARENT)) { 1371 continue; 1372 } 1373 1374 iloc = ud_xlate_to_daddr(udh, SWAP_16(fid->fid_icb.lad_ext_prn), 1375 SWAP_32(fid->fid_icb.lad_ext_loc)); 1376 addr = &fid->fid_spec[SWAP_16((fid)->fid_iulen) + 1]; 1377 if (((fl & 4) && (in == iloc)) || 1378 ((fl & 2) && (strcmp(name, (char *)addr) == 0))) { 1379 (void) printf("%s %x %s\n", dir, iloc, addr); 1380 } 1381 1382 if (fid->fid_flags & FID_DIR) { 1383 temp = (struct recu_dir *) 1384 malloc(sizeof (struct recu_dir)); 1385 if (temp == NULL) { 1386 (void) fprintf(stdout, 1387 gettext("Could not allocate memory\n")); 1388 } else { 1389 temp->next = NULL; 1390 temp->inode = iloc; 1391 temp->nm = malloc(strlen(dir) + 1 + 1392 fid->fid_idlen + 1); 1393 if (temp->nm != NULL) { 1394 (void) strcpy(temp->nm, dir); 1395 (void) strcat(temp->nm, "/"); 1396 (void) strncat(temp->nm, (char *)addr, 1397 fid->fid_idlen); 1398 } else { 1399 (void) fprintf(stdout, gettext( 1400 "Could not allocate memory\n")); 1401 } 1402 if (rd == NULL) { 1403 erd = rd = temp; 1404 } else { 1405 erd->next = temp; 1406 erd = temp; 1407 } 1408 } 1409 } 1410 } 1411 1412 while (rd != NULL) { 1413 if (rd->nm != NULL) { 1414 find_it(rd->nm, name, in, fl); 1415 } 1416 temp = rd; 1417 rd = rd->next; 1418 if (temp->nm) { 1419 free(temp->nm); 1420 } 1421 free(temp); 1422 } 1423 } 1424