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