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
main(int argc,char * argv[])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
usage()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
init_buffers()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 *
getblk(u_offset_t address)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
putblk(caddr_t address)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
inval_bufs()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
print_desc(uint32_t addr,int32_t id)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
set_file(int32_t id,uint32_t iloc,uint64_t value)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
verify_inode(uint32_t addr,uint32_t type)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
print_inode(uint32_t addr)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
verify_dent(uint32_t i_addr,uint32_t nent)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
print_dent(uint32_t i_addr,uint32_t nent)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
get_blkno(uint32_t inode,uint32_t * blkno,uint64_t off)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
read_file(uint32_t inode,uint8_t * buf,uint32_t count,uint64_t off)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
get_fid(uint32_t inode,uint8_t * buf,uint64_t off)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
inode_from_path(char * path,uint32_t * in,uint8_t * fl)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
list(char * nm,uint32_t in,uint32_t fl)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
fill_pattern(uint32_t addr,uint32_t count,char * pattern)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
dump_disk(uint32_t addr,uint32_t count,char * format)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
find_it(char * dir,char * name,uint32_t in,uint32_t fl)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