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