dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / fs.d / udfs / fsdb / fsdb.c
blob9ca0ebcadfc02402d34b2f6d02dc1ddaada6cd15
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
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>
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>
50 #include <sys/fs/udf_volume.h>
51 #include "ud_lib.h"
52 #include "y.tab.h"
54 typedef unsigned short unicode_t;
55 #define MAXNAMLEN 0x200
57 extern uint32_t i_number;
59 extern int32_t run_fsdb();
61 void usage();
62 void init_buffers();
63 char *getblk(uoff_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);
73 char *progname;
74 char prompt[256] = "fsdb>";
76 #define ARG_OVERRIDE 0
77 #define ARG_NEW_PROMPT 1
78 #define ARG_WR_ENABLED 2
79 #define ARG_USAGE 3
81 char *subopt_v[] = {
82 "o",
83 "p",
84 "w",
85 "?",
86 NULL
88 int32_t override = 0;
89 int32_t openflg = O_RDONLY;
91 #define MAX_PARTS 10
94 * udp_flags
96 #define UDP_BITMAPS 0x00
97 #define UDP_SPACETBLS 0x01
99 ud_handle_t udh;
100 int32_t fd, nparts, nmaps;
101 int32_t bmask, l2d, l2b;
104 uint16_t ricb_prn;
105 uint32_t ricb_loc, ricb_len;
106 extern int value;
109 int32_t
110 main(int argc, char *argv[])
112 int opt, ret;
113 uint32_t bsize;
114 char *subopts, *optval;
116 #if !defined(TEXT_DOMAIN)
117 #define TEXT_DOMAIN "SYS_TEST"
118 #endif
119 (void) textdomain(TEXT_DOMAIN);
121 progname = argv[0];
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();
139 if (strlen(optval) > 255) {
140 (void) fprintf(stdout,
141 gettext("prompt should be less"
142 "than 255 bytes\n"));
143 exit(1);
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();
155 break;
156 default :
157 usage();
161 if ((argc - optind) != 1) { /* Should just have "special" left */
162 usage();
165 if (ud_init(-1, &udh) != 0) {
166 (void) fprintf(stderr,
167 gettext("udfs labelit: cannot initialize ud_lib\n"));
168 exit(1);
171 if ((fd = ud_open_dev(udh, argv[optind], openflg)) < 0) {
172 perror("open");
173 exit(1);
176 if ((ret = ud_fill_udfs_info(udh)) != 0) {
177 return (ret);
180 if ((udh->udfs.flags & VALID_UDFS) == 0) {
181 return (1);
184 bsize = udh->udfs.lbsize;
185 bmask = bsize - 1;
186 l2d = 0;
187 while ((bsize >> l2d) > DEV_BSIZE) {
188 l2d++;
190 l2b = l2d + 9;
192 ricb_prn = udh->udfs.ricb_prn;
193 ricb_loc = udh->udfs.ricb_loc;
194 ricb_len = udh->udfs.ricb_len;
196 value = i_number = ud_xlate_to_daddr(udh, ricb_prn, ricb_loc);
198 init_buffers();
200 run_fsdb();
202 ud_fini(udh);
203 (void) close(fd);
205 return (0);
209 * usage - print usage and exit
211 void
212 usage()
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);
233 #define NBUF 10
234 static struct lbuf {
235 struct lbuf *fwd;
236 struct lbuf *back;
237 int32_t valid;
238 char *blkaddr;
239 uoff_t blkno;
240 } lbuf[NBUF], bhdr;
242 #define INSERT(bp) \
244 bp->back = &bhdr; \
245 bp->fwd = bhdr.fwd; \
246 bhdr.fwd->back = bp; \
247 bhdr.fwd = bp; \
250 void
251 init_buffers()
253 int32_t i;
254 char *addr;
255 struct lbuf *bp;
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);
267 char *
268 getblk(uoff_t address)
270 uoff_t off, block;
271 struct lbuf *bp;
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;
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);
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);
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);
306 int32_t
307 putblk(caddr_t address)
309 uoff_t off;
310 struct lbuf *bp;
312 if (openflg == O_RDONLY) {
313 (void) fprintf(stdout,
314 gettext("Not run with -w flag\n"));
315 return (1);
318 for (bp = bhdr.fwd; bp != &bhdr; bp = bp->fwd) {
319 if (bp->valid && bp->blkaddr == address) {
320 goto found;
323 (void) fprintf(stdout,
324 gettext("Could not find the buffer\n"));
325 return (1);
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);
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);
342 return (1);
345 void
346 inval_bufs()
348 struct lbuf *bp;
350 for (bp = bhdr.fwd; bp != &bhdr; bp = bp->fwd) {
351 bp->valid = 0;
356 * If addr == NULL then use id to print the desc
357 * other wise use addr to self identify the type of desc
359 void
360 print_desc(uint32_t addr, int32_t id)
362 struct tag *tag;
363 caddr_t baddr;
366 * Read the block at addr
367 * find out the type of tag
368 * and print the descriptor
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);
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"));
387 break;
388 case MVDS :
389 case RVDS :
390 case INTS :
392 uint32_t i, end;
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);
408 for (; i < end; i++) {
409 print_desc(i << l2b, 0);
412 return;
413 case FSDS :
414 case ROOT :
416 uint16_t prn;
417 uint32_t i, end, block;
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);
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;
439 print_desc(block << l2b, 0);
442 /* FALLTHROUGH */
443 default :
444 return;
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;
509 void
510 set_file(int32_t id, uint32_t iloc, uint64_t value)
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;
521 /* LINTED */
522 if ((fe = (struct file_entry *)getblk(iloc)) == NULL) {
523 return;
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;
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;
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)) {
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;
661 ud_make_tag(udh, &eah->eah_tag,
662 UD_EXT_ATTR_HDR, block,
663 eah->eah_tag.tag_crc_len);
664 break;
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"));
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);
691 caddr_t
692 verify_inode(uint32_t addr, uint32_t type)
694 struct file_entry *fe;
695 struct tag *tag;
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);
722 return (0);
725 void
726 print_inode(uint32_t addr)
728 if (verify_inode(addr, 0) != NULL) {
729 print_desc(addr, 0);
733 int32_t
734 verify_dent(uint32_t i_addr, uint32_t nent)
736 uint32_t ent = 0;
737 uint64_t off = 0;
738 uint8_t buf[1024];
739 struct file_id *fid;
741 /* LINTED */
742 fid = (struct file_id *)buf;
744 if (verify_inode(i_addr, 4) == 0) {
745 (void) fprintf(stdout,
746 gettext("Inode is not a directory\n"));
747 return (1);
750 while (get_fid(i_addr >> l2b, buf, off) == 0) {
751 off += FID_LEN(fid);
752 if (ent == nent) {
753 return (0);
755 ent++;
757 (void) fprintf(stdout,
758 gettext("Reached EOF\n"));
759 return (1);
762 void
763 print_dent(uint32_t i_addr, uint32_t nent)
765 uint32_t ent = 0;
766 uint64_t off = 0;
767 uint8_t buf[1024];
768 struct file_id *fid;
770 /* LINTED */
771 fid = (struct file_id *)buf;
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;
780 ent++;
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;
794 int32_t
795 get_blkno(uint32_t inode, uint32_t *blkno, uint64_t off)
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;
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);
814 desc_type = SWAP_16(fe->fe_icb_tag.itag_flags) & 0x7;
815 if (desc_type == ICB_FLAG_SHORT_AD) {
816 elen = sizeof (struct short_ad);
817 /* LINTED */
818 sad = (struct short_ad *)
819 (fe->fe_spec + SWAP_32(fe->fe_len_ear));
820 } else if (desc_type == ICB_FLAG_LONG_AD) {
821 elen = sizeof (struct long_ad);
822 /* LINTED */
823 lad = (struct long_ad *)
824 (fe->fe_spec + SWAP_32(fe->fe_len_ear));
825 } else if (desc_type == ICB_FLAG_ONE_AD) {
826 *blkno = inode;
827 return (0);
828 } else {
829 /* This cannot happen return */
830 return (EINVAL);
833 nent = SWAP_32(fe->fe_len_adesc) / elen;
834 de = malloc(nent * sizeof (struct ext));
835 if (de == NULL) {
836 (void) fprintf(stdout,
837 gettext("could not allocate memeory\n"));
838 return (1);
840 in = inode;
841 de_count = nent;
842 for (d = 0, i = 0; i < nent; i++) {
843 if (desc_type == ICB_FLAG_SHORT_AD) {
844 prn = 0;
845 bno = SWAP_32(sad->sad_ext_loc);
846 len = SWAP_32(sad->sad_ext_len);
847 } else if (desc_type == ICB_FLAG_LONG_AD) {
848 prn = SWAP_16(lad->lad_ext_prn);
849 bno = SWAP_32(lad->lad_ext_loc);
850 len = SWAP_32(lad->lad_ext_len);
852 flags = len >> 30;
853 if (flags == 0x3) {
854 (void) fprintf(stdout,
855 gettext("Handle IE\n"));
856 } else {
857 de[d].prn = prn;
858 de[d].flags = flags;
859 de[d].blkno = bno;
860 de[d].len = len & 0x3FFFFFFF;
861 d++;
866 b_off = 0;
867 for (i = 0; i < de_count; i++) {
868 e_off = b_off + de[i].len;
869 if (off < e_off) {
870 bno = de[i].blkno + ((off - b_off) >> l2b);
871 if ((*blkno = ud_xlate_to_daddr(
872 udh, de[i].prn, bno)) == 0) {
873 return (1);
875 return (0);
877 b_off = e_off;
879 return (1);
883 * assume the buffer is big enough
884 * for the entire request
886 int32_t
887 read_file(uint32_t inode, uint8_t *buf, uint32_t count, uint64_t off)
889 caddr_t addr;
890 uint32_t bno, tcount;
893 while (count) {
894 if (get_blkno(inode, &bno, off) != 0) {
895 return (1);
897 if ((addr = getblk(bno << l2b)) == NULL) {
898 return (1);
900 if (bno == inode) {
901 struct file_entry *fe;
903 * embedded file
905 /* LINTED */
906 fe = (struct file_entry *)addr;
907 addr += 0xB0 + SWAP_32(fe->fe_len_ear);
908 if (off >= SWAP_64(fe->fe_info_len)) {
909 return (1);
912 tcount = udh->udfs.lbsize - (off & bmask);
913 if (tcount > count) {
914 tcount = count;
916 addr += off & bmask;
917 (void) memcpy(buf, addr, tcount);
918 count -= tcount;
919 buf += tcount;
920 off += tcount;
922 return (0);
925 int32_t
926 get_fid(uint32_t inode, uint8_t *buf, uint64_t off)
928 struct file_id *fid;
930 /* LINTED */
931 fid = (struct file_id *)buf;
932 if ((read_file(inode, buf, sizeof (struct file_id), off)) != 0) {
933 return (1);
936 if (ud_verify_tag(udh, &fid->fid_tag, UD_FILE_ID_DESC, 0, 0, 1) != 0) {
937 (void) fprintf(stdout,
938 gettext("file_id tag does not verify off %llx\n"),
939 off);
940 return (1);
943 if ((read_file(inode, buf, FID_LEN(fid), off)) != 0) {
944 return (1);
947 return (0);
951 * Path is absolute path
953 int32_t
954 inode_from_path(char *path, uint32_t *in, uint8_t *fl)
956 char dname[1024];
957 char fname[256];
958 int32_t err;
959 uint32_t dinode;
960 struct tag *tag;
961 uint8_t flags;
963 uint8_t buf[1024];
964 uint64_t off;
965 struct file_id *fid;
966 uint8_t *addr;
968 if (strcmp(path, "/") == 0) {
969 *fl = FID_DIR;
970 if ((*in = ud_xlate_to_daddr(udh, ricb_prn, ricb_loc)) == 0) {
971 return (1);
973 return (0);
976 (void) strcpy(dname, path);
977 (void) strcpy(fname, basename(dname));
978 (void) dirname(dname);
980 if ((err = inode_from_path(dname, &dinode, &flags)) != 0) {
981 return (1);
986 * Check if dname is a directory
988 if ((flags & FID_DIR) == 0) {
989 (void) fprintf(stdout,
990 gettext("Path %s is not a directory\n"), path);
994 * Search for the fname in the directory now
998 off = 0;
999 /* LINTED */
1000 fid = (struct file_id *)buf;
1001 while (get_fid(dinode, buf, off) == 0) {
1002 off += FID_LEN(fid);
1003 if (fid->fid_flags & FID_DELETED) {
1004 continue;
1006 addr = &fid->fid_spec[SWAP_16((fid)->fid_iulen) + 1];
1007 if (fid->fid_flags & FID_PARENT) {
1008 addr[0] = '.';
1009 addr[1] = '.';
1010 addr[2] = '\0';
1011 } else {
1012 addr[fid->fid_idlen] = '\0';
1014 if (strcmp((caddr_t)addr, fname) == 0) {
1015 *fl = fid->fid_flags;
1016 if ((*in = ud_xlate_to_daddr(udh,
1017 SWAP_16(fid->fid_icb.lad_ext_prn),
1018 SWAP_32(fid->fid_icb.lad_ext_loc))) == 0) {
1019 return (1);
1021 /* LINTED */
1022 if ((tag = (struct tag *)getblk(*in << l2b)) == NULL) {
1023 (void) fprintf(stdout,
1024 gettext("Could not read block %x\n"),
1025 *in);
1026 return (1);
1028 if (ud_verify_tag(udh, tag, UD_FILE_ENTRY,
1029 0, 0, 1) != 0) {
1030 (void) fprintf(stdout,
1031 gettext("Not a file entry(inode)"
1032 " at %x\n"), *in);
1033 return (1);
1035 if (ud_verify_tag(udh, tag, UD_FILE_ENTRY,
1036 SWAP_32(tag->tag_loc), 1, 1) != 0) {
1037 (void) fprintf(stdout,
1038 gettext("CRC failed\n"));
1039 return (1);
1042 return (0);
1045 return (err);
1048 struct recu_dir {
1049 struct recu_dir *next;
1050 uint32_t inode;
1051 char *nm;
1054 void
1055 list(char *nm, uint32_t in, uint32_t fl)
1057 uint8_t buf[1024];
1058 uint64_t off;
1059 struct file_id *fid;
1060 struct recu_dir *rd, *erd, *temp;
1061 uint32_t iloc;
1063 rd = erd = temp = NULL;
1064 if (verify_inode(in << l2b, 4) == 0) {
1065 (void) fprintf(stdout,
1066 gettext("Inode is not a directory\n"));
1067 return;
1070 if (fl & 2) {
1071 (void) printf("\n");
1072 if (fl & 1) {
1073 (void) fprintf(stdout,
1074 gettext("i#: %x\t"), in);
1076 (void) printf("%s\n", nm);
1079 off = 0;
1080 /* LINTED */
1081 fid = (struct file_id *)buf;
1082 while (get_fid(in, buf, off) == 0) {
1083 off += FID_LEN(fid);
1084 if (fid->fid_flags & FID_DELETED) {
1085 continue;
1087 iloc = ud_xlate_to_daddr(udh, SWAP_16(fid->fid_icb.lad_ext_prn),
1088 SWAP_32(fid->fid_icb.lad_ext_loc));
1089 if (fl & 1) {
1090 (void) fprintf(stdout,
1091 gettext("i#: %x\t"), iloc);
1093 if (fid->fid_flags & FID_PARENT) {
1094 (void) fprintf(stdout,
1095 gettext("..\n"));
1096 } else {
1097 int32_t i;
1098 uint8_t *addr;
1100 addr = &fid->fid_spec[SWAP_16((fid)->fid_iulen) + 1];
1101 for (i = 0; i < fid->fid_idlen - 1; i++)
1102 (void) fprintf(stdout, "%c", addr[i]);
1103 (void) fprintf(stdout, "\n");
1104 if ((fid->fid_flags & FID_DIR) &&
1105 (fl & 2)) {
1106 temp = (struct recu_dir *)
1107 malloc(sizeof (struct recu_dir));
1108 if (temp == NULL) {
1109 (void) fprintf(stdout,
1110 gettext("Could not allocate memory\n"));
1111 } else {
1112 temp->next = NULL;
1113 temp->inode = iloc;
1114 temp->nm = malloc(strlen(nm) + 1 +
1115 fid->fid_idlen + 1);
1116 if (temp->nm != NULL) {
1117 (void) strcpy(temp->nm, nm);
1118 (void) strcat(temp->nm, "/");
1119 (void) strncat(temp->nm,
1120 (char *)addr,
1121 fid->fid_idlen);
1123 if (rd == NULL) {
1124 erd = rd = temp;
1125 } else {
1126 erd->next = temp;
1127 erd = temp;
1134 while (rd != NULL) {
1135 if (rd->nm != NULL) {
1136 list(rd->nm, rd->inode, fl);
1137 } else {
1138 list(".", rd->inode, fl);
1140 temp = rd;
1141 rd = rd->next;
1142 if (temp->nm) {
1143 free(temp->nm);
1145 free(temp);
1149 void
1150 fill_pattern(uint32_t addr, uint32_t count, char *pattern)
1152 uint32_t beg, end, soff, lcount;
1153 int32_t len = strlen(pattern);
1154 caddr_t buf, p;
1156 if (openflg == O_RDONLY) {
1157 (void) fprintf(stdout,
1158 gettext("Not run with -w flag\n"));
1159 return;
1162 if (count == 0) {
1163 count = 1;
1165 beg = addr;
1166 end = addr + count * len;
1167 soff = beg & (~bmask);
1168 lcount = ((end + bmask) & (~bmask)) - soff;
1170 inval_bufs();
1172 buf = malloc(lcount);
1174 if (llseek(fd, soff, SEEK_SET) != soff) {
1175 (void) fprintf(stdout,
1176 gettext("Seek failed fd %x off %llx errno %x\n"),
1177 fd, soff, errno);
1178 goto end;
1181 if (read(fd, buf, lcount) != lcount) {
1182 (void) fprintf(stdout,
1183 gettext("Read failed fd %x off %llx errno %x\n"),
1184 fd, soff, errno);
1185 goto end;
1188 p = buf + (addr & bmask);
1189 while (count--) {
1190 (void) strncpy(p, pattern, len);
1191 p += len;
1194 if (write(fd, buf, lcount) != lcount) {
1195 (void) fprintf(stdout,
1196 gettext("Write failed fd %x off %llx errno %x\n"),
1197 fd, soff, errno);
1198 goto end;
1200 end:
1201 free(buf);
1204 void
1205 dump_disk(uint32_t addr, uint32_t count, char *format)
1207 uint32_t beg, end, soff, lcount;
1208 int32_t len, prperline, n;
1209 uint8_t *buf, *p;
1210 uint16_t *p_16;
1211 uint32_t *p_32;
1213 if (strlen(format) != 1) {
1214 (void) fprintf(stdout,
1215 gettext("Invalid command\n"));
1216 return;
1218 if (count == 0) {
1219 count = 1;
1221 switch (*format) {
1222 case 'b' :
1223 /* FALLTHROUGH */
1224 case 'c' :
1225 /* FALLTHROUGH */
1226 case 'd' :
1227 /* FALLTHROUGH */
1228 case 'o' :
1229 len = 1;
1230 prperline = 16;
1231 break;
1232 case 'x' :
1233 len = 2;
1234 prperline = 8;
1235 break;
1236 case 'D' :
1237 /* FALLTHROUGH */
1238 case 'O' :
1239 /* FALLTHROUGH */
1240 case 'X' :
1241 len = 4;
1242 prperline = 4;
1243 break;
1244 default :
1245 (void) fprintf(stdout,
1246 gettext("Invalid format\n"));
1247 return;
1250 beg = addr;
1251 end = addr + count * len;
1252 soff = beg & (~bmask);
1253 lcount = ((end + bmask) & (~bmask)) - soff;
1255 inval_bufs();
1257 buf = malloc(lcount);
1258 if (llseek(fd, soff, SEEK_SET) != soff) {
1259 (void) fprintf(stdout,
1260 gettext("Seek failed fd %x off %llx errno %x\n"),
1261 fd, soff, errno);
1262 goto end;
1265 if (read(fd, buf, lcount) != lcount) {
1266 (void) fprintf(stdout,
1267 gettext("Read failed fd %x off %llx errno %x\n"),
1268 fd, soff, errno);
1269 goto end;
1271 p = buf + (addr & bmask);
1272 /* LINTED */
1273 p_16 = (uint16_t *)p;
1274 /* LINTED */
1275 p_32 = (uint32_t *)p;
1276 n = 0;
1277 while (n < count) {
1278 switch (*format) {
1279 case 'b' :
1280 (void) fprintf(stdout,
1281 "%4x ", *((uint8_t *)p));
1282 break;
1283 case 'c' :
1284 (void) fprintf(stdout,
1285 "%4c ", *((uint8_t *)p));
1286 break;
1287 case 'd' :
1288 (void) fprintf(stdout,
1289 "%4d ", *((uint8_t *)p));
1290 break;
1291 case 'o' :
1292 (void) fprintf(stdout,
1293 "%4o ", *((uint8_t *)p));
1294 break;
1295 case 'x' :
1296 (void) fprintf(stdout,
1297 "%8x ", *p_16);
1298 break;
1299 case 'D' :
1300 (void) fprintf(stdout,
1301 "%16d ", *p_32);
1302 break;
1303 case 'O' :
1304 (void) fprintf(stdout,
1305 "%16o ", *p_32);
1306 break;
1307 case 'X' :
1308 (void) fprintf(stdout,
1309 "%16x ", *p_32);
1310 break;
1312 p += len;
1313 n++;
1314 if ((n % prperline) == 0) {
1315 (void) fprintf(stdout, "\n");
1318 if (n % prperline) {
1319 (void) fprintf(stdout, "\n");
1321 end:
1322 free(buf);
1325 void
1326 find_it(char *dir, char *name, uint32_t in, uint32_t fl)
1328 uint8_t buf[1024], *addr;
1329 uint64_t off;
1330 struct file_id *fid;
1331 uint32_t iloc, d_in;
1332 uint8_t d_fl;
1333 struct recu_dir *rd, *erd, *temp;
1335 rd = erd = temp = NULL;
1337 if (inode_from_path(dir, &d_in, &d_fl) != 0) {
1338 (void) fprintf(stdout,
1339 gettext("Could not find directory %s"), dir);
1340 return;
1343 if ((d_fl & FID_DIR) == 0) {
1344 (void) fprintf(stdout,
1345 gettext("Path %s is not a directory\n"), dir);
1346 return;
1349 if (verify_inode(d_in << l2b, 4) == 0) {
1350 (void) fprintf(stdout,
1351 gettext("Inode is not a directory\n"));
1352 return;
1355 off = 0;
1356 /* LINTED */
1357 fid = (struct file_id *)buf;
1358 while (get_fid(d_in, buf, off) == 0) {
1359 off += FID_LEN(fid);
1360 if ((fid->fid_flags & FID_DELETED) ||
1361 (fid->fid_flags & FID_PARENT)) {
1362 continue;
1365 iloc = ud_xlate_to_daddr(udh, SWAP_16(fid->fid_icb.lad_ext_prn),
1366 SWAP_32(fid->fid_icb.lad_ext_loc));
1367 addr = &fid->fid_spec[SWAP_16((fid)->fid_iulen) + 1];
1368 if (((fl & 4) && (in == iloc)) ||
1369 ((fl & 2) && (strcmp(name, (char *)addr) == 0))) {
1370 (void) printf("%s %x %s\n", dir, iloc, addr);
1373 if (fid->fid_flags & FID_DIR) {
1374 temp = (struct recu_dir *)
1375 malloc(sizeof (struct recu_dir));
1376 if (temp == NULL) {
1377 (void) fprintf(stdout,
1378 gettext("Could not allocate memory\n"));
1379 } else {
1380 temp->next = NULL;
1381 temp->inode = iloc;
1382 temp->nm = malloc(strlen(dir) + 1 +
1383 fid->fid_idlen + 1);
1384 if (temp->nm != NULL) {
1385 (void) strcpy(temp->nm, dir);
1386 (void) strcat(temp->nm, "/");
1387 (void) strncat(temp->nm, (char *)addr,
1388 fid->fid_idlen);
1389 } else {
1390 (void) fprintf(stdout, gettext(
1391 "Could not allocate memory\n"));
1393 if (rd == NULL) {
1394 erd = rd = temp;
1395 } else {
1396 erd->next = temp;
1397 erd = temp;
1403 while (rd != NULL) {
1404 if (rd->nm != NULL) {
1405 find_it(rd->nm, name, in, fl);
1407 temp = rd;
1408 rd = rd->next;
1409 if (temp->nm) {
1410 free(temp->nm);
1412 free(temp);