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 if (desc_type == ICB_FLAG_SHORT_AD) { 816 elen = sizeof (struct short_ad); 817 /* LINTED */ 818 sad = (struct short_ad *) 819 (fe->fe_spec + SWAP_32(fe->fe_len_ear)); 820 } else if (desc_type == ICB_FLAG_LONG_AD) { 821 elen = sizeof (struct long_ad); 822 /* LINTED */ 823 lad = (struct long_ad *) 824 (fe->fe_spec + SWAP_32(fe->fe_len_ear)); 825 } else if (desc_type == ICB_FLAG_ONE_AD) { 826 *blkno = inode; 827 return (0); 828 } else { 829 /* This cannot happen return */ 830 return (EINVAL); 831 } 832 833 nent = SWAP_32(fe->fe_len_adesc) / elen; 834 de = malloc(nent * sizeof (struct ext)); 835 if (de == NULL) { 836 (void) fprintf(stdout, 837 gettext("could not allocate memeory\n")); 838 return (1); 839 } 840 in = inode; 841 de_count = nent; 842 for (d = 0, i = 0; i < nent; i++) { 843 if (desc_type == ICB_FLAG_SHORT_AD) { 844 prn = 0; 845 bno = SWAP_32(sad->sad_ext_loc); 846 len = SWAP_32(sad->sad_ext_len); 847 } else if (desc_type == ICB_FLAG_LONG_AD) { 848 prn = SWAP_16(lad->lad_ext_prn); 849 bno = SWAP_32(lad->lad_ext_loc); 850 len = SWAP_32(lad->lad_ext_len); 851 } 852 flags = len >> 30; 853 if (flags == 0x3) { 854 (void) fprintf(stdout, 855 gettext("Handle IE\n")); 856 } else { 857 de[d].prn = prn; 858 de[d].flags = flags; 859 de[d].blkno = bno; 860 de[d].len = len & 0x3FFFFFFF; 861 d++; 862 } 863 } 864 } 865 866 b_off = 0; 867 for (i = 0; i < de_count; i++) { 868 e_off = b_off + de[i].len; 869 if (off < e_off) { 870 bno = de[i].blkno + ((off - b_off) >> l2b); 871 if ((*blkno = ud_xlate_to_daddr( 872 udh, de[i].prn, bno)) == 0) { 873 return (1); 874 } 875 return (0); 876 } 877 b_off = e_off; 878 } 879 return (1); 880 } 881 882 /* 883 * assume the buffer is big enough 884 * for the entire request 885 */ 886 int32_t 887 read_file(uint32_t inode, uint8_t *buf, uint32_t count, uint64_t off) 888 { 889 caddr_t addr; 890 uint32_t bno, tcount; 891 892 893 while (count) { 894 if (get_blkno(inode, &bno, off) != 0) { 895 return (1); 896 } 897 if ((addr = getblk(bno << l2b)) == NULL) { 898 return (1); 899 } 900 if (bno == inode) { 901 struct file_entry *fe; 902 /* 903 * embedded file 904 */ 905 /* LINTED */ 906 fe = (struct file_entry *)addr; 907 addr += 0xB0 + SWAP_32(fe->fe_len_ear); 908 if (off >= SWAP_64(fe->fe_info_len)) { 909 return (1); 910 } 911 } 912 tcount = udh->udfs.lbsize - (off & bmask); 913 if (tcount > count) { 914 tcount = count; 915 } 916 addr += off & bmask; 917 (void) memcpy(buf, addr, tcount); 918 count -= tcount; 919 buf += tcount; 920 off += tcount; 921 } 922 return (0); 923 } 924 925 int32_t 926 get_fid(uint32_t inode, uint8_t *buf, uint64_t off) 927 { 928 struct file_id *fid; 929 930 /* LINTED */ 931 fid = (struct file_id *)buf; 932 if ((read_file(inode, buf, sizeof (struct file_id), off)) != 0) { 933 return (1); 934 } 935 936 if (ud_verify_tag(udh, &fid->fid_tag, UD_FILE_ID_DESC, 0, 0, 1) != 0) { 937 (void) fprintf(stdout, 938 gettext("file_id tag does not verify off %llx\n"), 939 off); 940 return (1); 941 } 942 943 if ((read_file(inode, buf, FID_LEN(fid), off)) != 0) { 944 return (1); 945 } 946 947 return (0); 948 } 949 950 /* 951 * Path is absolute path 952 */ 953 int32_t 954 inode_from_path(char *path, uint32_t *in, uint8_t *fl) 955 { 956 char dname[1024]; 957 char fname[256]; 958 int32_t err; 959 uint32_t dinode; 960 struct tag *tag; 961 uint8_t flags; 962 963 uint8_t buf[1024]; 964 uint64_t off; 965 struct file_id *fid; 966 uint8_t *addr; 967 968 if (strcmp(path, "/") == 0) { 969 *fl = FID_DIR; 970 if ((*in = ud_xlate_to_daddr(udh, ricb_prn, ricb_loc)) == 0) { 971 return (1); 972 } 973 return (0); 974 } 975 976 (void) strcpy(dname, path); 977 (void) strcpy(fname, basename(dname)); 978 (void) dirname(dname); 979 980 if ((err = inode_from_path(dname, &dinode, &flags)) != 0) { 981 return (1); 982 } 983 984 985 /* 986 * Check if dname is a directory 987 */ 988 if ((flags & FID_DIR) == 0) { 989 (void) fprintf(stdout, 990 gettext("Path %s is not a directory\n"), path); 991 } 992 993 /* 994 * Search for the fname in the directory now 995 */ 996 997 998 off = 0; 999 /* LINTED */ 1000 fid = (struct file_id *)buf; 1001 while (get_fid(dinode, buf, off) == 0) { 1002 off += FID_LEN(fid); 1003 if (fid->fid_flags & FID_DELETED) { 1004 continue; 1005 } 1006 addr = &fid->fid_spec[SWAP_16((fid)->fid_iulen) + 1]; 1007 if (fid->fid_flags & FID_PARENT) { 1008 addr[0] = '.'; 1009 addr[1] = '.'; 1010 addr[2] = '\0'; 1011 } else { 1012 addr[fid->fid_idlen] = '\0'; 1013 } 1014 if (strcmp((caddr_t)addr, fname) == 0) { 1015 *fl = fid->fid_flags; 1016 if ((*in = ud_xlate_to_daddr(udh, 1017 SWAP_16(fid->fid_icb.lad_ext_prn), 1018 SWAP_32(fid->fid_icb.lad_ext_loc))) == 0) { 1019 return (1); 1020 } 1021 /* LINTED */ 1022 if ((tag = (struct tag *)getblk(*in << l2b)) == NULL) { 1023 (void) fprintf(stdout, 1024 gettext("Could not read block %x\n"), 1025 *in); 1026 return (1); 1027 } 1028 if (ud_verify_tag(udh, tag, UD_FILE_ENTRY, 1029 0, 0, 1) != 0) { 1030 (void) fprintf(stdout, 1031 gettext("Not a file entry(inode)" 1032 " at %x\n"), *in); 1033 return (1); 1034 } 1035 if (ud_verify_tag(udh, tag, UD_FILE_ENTRY, 1036 SWAP_32(tag->tag_loc), 1, 1) != 0) { 1037 (void) fprintf(stdout, 1038 gettext("CRC failed\n")); 1039 return (1); 1040 } 1041 1042 return (0); 1043 } 1044 } 1045 return (err); 1046 } 1047 1048 struct recu_dir { 1049 struct recu_dir *next; 1050 uint32_t inode; 1051 char *nm; 1052 }; 1053 1054 void 1055 list(char *nm, uint32_t in, uint32_t fl) 1056 { 1057 uint8_t buf[1024]; 1058 uint64_t off; 1059 struct file_id *fid; 1060 struct recu_dir *rd, *erd, *temp; 1061 uint32_t iloc; 1062 1063 rd = erd = temp = NULL; 1064 if (verify_inode(in << l2b, 4) == 0) { 1065 (void) fprintf(stdout, 1066 gettext("Inode is not a directory\n")); 1067 return; 1068 } 1069 1070 if (fl & 2) { 1071 (void) printf("\n"); 1072 if (fl & 1) { 1073 (void) fprintf(stdout, 1074 gettext("i#: %x\t"), in); 1075 } 1076 (void) printf("%s\n", nm); 1077 } 1078 1079 off = 0; 1080 /* LINTED */ 1081 fid = (struct file_id *)buf; 1082 while (get_fid(in, buf, off) == 0) { 1083 off += FID_LEN(fid); 1084 if (fid->fid_flags & FID_DELETED) { 1085 continue; 1086 } 1087 iloc = ud_xlate_to_daddr(udh, SWAP_16(fid->fid_icb.lad_ext_prn), 1088 SWAP_32(fid->fid_icb.lad_ext_loc)); 1089 if (fl & 1) { 1090 (void) fprintf(stdout, 1091 gettext("i#: %x\t"), iloc); 1092 } 1093 if (fid->fid_flags & FID_PARENT) { 1094 (void) fprintf(stdout, 1095 gettext("..\n")); 1096 } else { 1097 int32_t i; 1098 uint8_t *addr; 1099 1100 addr = &fid->fid_spec[SWAP_16((fid)->fid_iulen) + 1]; 1101 for (i = 0; i < fid->fid_idlen - 1; i++) 1102 (void) fprintf(stdout, "%c", addr[i]); 1103 (void) fprintf(stdout, "\n"); 1104 if ((fid->fid_flags & FID_DIR) && 1105 (fl & 2)) { 1106 temp = (struct recu_dir *) 1107 malloc(sizeof (struct recu_dir)); 1108 if (temp == NULL) { 1109 (void) fprintf(stdout, 1110 gettext("Could not allocate memory\n")); 1111 } else { 1112 temp->next = NULL; 1113 temp->inode = iloc; 1114 temp->nm = malloc(strlen(nm) + 1 + 1115 fid->fid_idlen + 1); 1116 if (temp->nm != NULL) { 1117 (void) strcpy(temp->nm, nm); 1118 (void) strcat(temp->nm, "/"); 1119 (void) strncat(temp->nm, 1120 (char *)addr, 1121 fid->fid_idlen); 1122 } 1123 if (rd == NULL) { 1124 erd = rd = temp; 1125 } else { 1126 erd->next = temp; 1127 erd = temp; 1128 } 1129 } 1130 } 1131 } 1132 } 1133 1134 while (rd != NULL) { 1135 if (rd->nm != NULL) { 1136 list(rd->nm, rd->inode, fl); 1137 } else { 1138 list(".", rd->inode, fl); 1139 } 1140 temp = rd; 1141 rd = rd->next; 1142 if (temp->nm) { 1143 free(temp->nm); 1144 } 1145 free(temp); 1146 } 1147 } 1148 1149 void 1150 fill_pattern(uint32_t addr, uint32_t count, char *pattern) 1151 { 1152 uint32_t beg, end, soff, lcount; 1153 int32_t len = strlen(pattern); 1154 caddr_t buf, p; 1155 1156 if (openflg == O_RDONLY) { 1157 (void) fprintf(stdout, 1158 gettext("Not run with -w flag\n")); 1159 return; 1160 } 1161 1162 if (count == 0) { 1163 count = 1; 1164 } 1165 beg = addr; 1166 end = addr + count * len; 1167 soff = beg & (~bmask); 1168 lcount = ((end + bmask) & (~bmask)) - soff; 1169 1170 inval_bufs(); 1171 1172 buf = malloc(lcount); 1173 1174 if (llseek(fd, soff, SEEK_SET) != soff) { 1175 (void) fprintf(stdout, 1176 gettext("Seek failed fd %x off %llx errno %x\n"), 1177 fd, soff, errno); 1178 goto end; 1179 } 1180 1181 if (read(fd, buf, lcount) != lcount) { 1182 (void) fprintf(stdout, 1183 gettext("Read failed fd %x off %llx errno %x\n"), 1184 fd, soff, errno); 1185 goto end; 1186 } 1187 1188 p = buf + (addr & bmask); 1189 while (count--) { 1190 (void) strncpy(p, pattern, len); 1191 p += len; 1192 } 1193 1194 if (write(fd, buf, lcount) != lcount) { 1195 (void) fprintf(stdout, 1196 gettext("Write failed fd %x off %llx errno %x\n"), 1197 fd, soff, errno); 1198 goto end; 1199 } 1200 end: 1201 free(buf); 1202 } 1203 1204 void 1205 dump_disk(uint32_t addr, uint32_t count, char *format) 1206 { 1207 uint32_t beg, end, soff, lcount; 1208 int32_t len, prperline, n; 1209 uint8_t *buf, *p; 1210 uint16_t *p_16; 1211 uint32_t *p_32; 1212 1213 if (strlen(format) != 1) { 1214 (void) fprintf(stdout, 1215 gettext("Invalid command\n")); 1216 return; 1217 } 1218 if (count == 0) { 1219 count = 1; 1220 } 1221 switch (*format) { 1222 case 'b' : 1223 /* FALLTHROUGH */ 1224 case 'c' : 1225 /* FALLTHROUGH */ 1226 case 'd' : 1227 /* FALLTHROUGH */ 1228 case 'o' : 1229 len = 1; 1230 prperline = 16; 1231 break; 1232 case 'x' : 1233 len = 2; 1234 prperline = 8; 1235 break; 1236 case 'D' : 1237 /* FALLTHROUGH */ 1238 case 'O' : 1239 /* FALLTHROUGH */ 1240 case 'X' : 1241 len = 4; 1242 prperline = 4; 1243 break; 1244 default : 1245 (void) fprintf(stdout, 1246 gettext("Invalid format\n")); 1247 return; 1248 } 1249 1250 beg = addr; 1251 end = addr + count * len; 1252 soff = beg & (~bmask); 1253 lcount = ((end + bmask) & (~bmask)) - soff; 1254 1255 inval_bufs(); 1256 1257 buf = malloc(lcount); 1258 if (llseek(fd, soff, SEEK_SET) != soff) { 1259 (void) fprintf(stdout, 1260 gettext("Seek failed fd %x off %llx errno %x\n"), 1261 fd, soff, errno); 1262 goto end; 1263 } 1264 1265 if (read(fd, buf, lcount) != lcount) { 1266 (void) fprintf(stdout, 1267 gettext("Read failed fd %x off %llx errno %x\n"), 1268 fd, soff, errno); 1269 goto end; 1270 } 1271 p = buf + (addr & bmask); 1272 /* LINTED */ 1273 p_16 = (uint16_t *)p; 1274 /* LINTED */ 1275 p_32 = (uint32_t *)p; 1276 n = 0; 1277 while (n < count) { 1278 switch (*format) { 1279 case 'b' : 1280 (void) fprintf(stdout, 1281 "%4x ", *((uint8_t *)p)); 1282 break; 1283 case 'c' : 1284 (void) fprintf(stdout, 1285 "%4c ", *((uint8_t *)p)); 1286 break; 1287 case 'd' : 1288 (void) fprintf(stdout, 1289 "%4d ", *((uint8_t *)p)); 1290 break; 1291 case 'o' : 1292 (void) fprintf(stdout, 1293 "%4o ", *((uint8_t *)p)); 1294 break; 1295 case 'x' : 1296 (void) fprintf(stdout, 1297 "%8x ", *p_16); 1298 break; 1299 case 'D' : 1300 (void) fprintf(stdout, 1301 "%16d ", *p_32); 1302 break; 1303 case 'O' : 1304 (void) fprintf(stdout, 1305 "%16o ", *p_32); 1306 break; 1307 case 'X' : 1308 (void) fprintf(stdout, 1309 "%16x ", *p_32); 1310 break; 1311 } 1312 p += len; 1313 n++; 1314 if ((n % prperline) == 0) { 1315 (void) fprintf(stdout, "\n"); 1316 } 1317 } 1318 if (n % prperline) { 1319 (void) fprintf(stdout, "\n"); 1320 } 1321 end: 1322 free(buf); 1323 } 1324 1325 void 1326 find_it(char *dir, char *name, uint32_t in, uint32_t fl) 1327 { 1328 uint8_t buf[1024], *addr; 1329 uint64_t off; 1330 struct file_id *fid; 1331 uint32_t iloc, d_in; 1332 uint8_t d_fl; 1333 struct recu_dir *rd, *erd, *temp; 1334 1335 rd = erd = temp = NULL; 1336 1337 if (inode_from_path(dir, &d_in, &d_fl) != 0) { 1338 (void) fprintf(stdout, 1339 gettext("Could not find directory %s"), dir); 1340 return; 1341 } 1342 1343 if ((d_fl & FID_DIR) == 0) { 1344 (void) fprintf(stdout, 1345 gettext("Path %s is not a directory\n"), dir); 1346 return; 1347 } 1348 1349 if (verify_inode(d_in << l2b, 4) == 0) { 1350 (void) fprintf(stdout, 1351 gettext("Inode is not a directory\n")); 1352 return; 1353 } 1354 1355 off = 0; 1356 /* LINTED */ 1357 fid = (struct file_id *)buf; 1358 while (get_fid(d_in, buf, off) == 0) { 1359 off += FID_LEN(fid); 1360 if ((fid->fid_flags & FID_DELETED) || 1361 (fid->fid_flags & FID_PARENT)) { 1362 continue; 1363 } 1364 1365 iloc = ud_xlate_to_daddr(udh, SWAP_16(fid->fid_icb.lad_ext_prn), 1366 SWAP_32(fid->fid_icb.lad_ext_loc)); 1367 addr = &fid->fid_spec[SWAP_16((fid)->fid_iulen) + 1]; 1368 if (((fl & 4) && (in == iloc)) || 1369 ((fl & 2) && (strcmp(name, (char *)addr) == 0))) { 1370 (void) printf("%s %x %s\n", dir, iloc, addr); 1371 } 1372 1373 if (fid->fid_flags & FID_DIR) { 1374 temp = (struct recu_dir *) 1375 malloc(sizeof (struct recu_dir)); 1376 if (temp == NULL) { 1377 (void) fprintf(stdout, 1378 gettext("Could not allocate memory\n")); 1379 } else { 1380 temp->next = NULL; 1381 temp->inode = iloc; 1382 temp->nm = malloc(strlen(dir) + 1 + 1383 fid->fid_idlen + 1); 1384 if (temp->nm != NULL) { 1385 (void) strcpy(temp->nm, dir); 1386 (void) strcat(temp->nm, "/"); 1387 (void) strncat(temp->nm, (char *)addr, 1388 fid->fid_idlen); 1389 } else { 1390 (void) fprintf(stdout, gettext( 1391 "Could not allocate memory\n")); 1392 } 1393 if (rd == NULL) { 1394 erd = rd = temp; 1395 } else { 1396 erd->next = temp; 1397 erd = temp; 1398 } 1399 } 1400 } 1401 } 1402 1403 while (rd != NULL) { 1404 if (rd->nm != NULL) { 1405 find_it(rd->nm, name, in, fl); 1406 } 1407 temp = rd; 1408 rd = rd->next; 1409 if (temp->nm) { 1410 free(temp->nm); 1411 } 1412 free(temp); 1413 } 1414 } 1415