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