# HG changeset patch # User Michael Spacefalcon # Date 1420618170 0 # Node ID 37f78f986a0acae94176a0b2562704ff3ef24eeb # Parent 5d84f63eff72108eb77d623d7e7fdb14b709f9e0 grokdsn: tree dump implemented diff -r 5d84f63eff72 -r 37f78f986a0a miscprog/grokdsn.c --- a/miscprog/grokdsn.c Wed Jan 07 07:12:51 2015 +0000 +++ b/miscprog/grokdsn.c Wed Jan 07 08:09:30 2015 +0000 @@ -47,11 +47,31 @@ uint32_t fat_secids[HEADER_MFAT_ENTRIES]; }; +struct dir_entry { + uint16_t uni_name[32]; + uint16_t name_len; + u_char type; + u_char color; + uint32_t left_child; + uint32_t right_child; + uint32_t subtree_dirid; + u_char uid[16]; + u_char user_flags[4]; + u_char time_creat[8]; + u_char time_lastmod[8]; + uint32_t content_secid; + uint32_t content_bytes; + u_char rsvd[4]; +}; + char *dsnfilename; u_char *filemapping; struct cdf_header *cdf_header; unsigned total_sectors, fat_nsectors; +#define MAX_DIR_SECTORS 64 +unsigned dir_nsectors, dir_secids[MAX_DIR_SECTORS]; + open_and_mmap_file() { int fd; @@ -175,6 +195,100 @@ return(0); } +locate_dir_sectors() +{ + int sec, next, num; + + sec = le32toh(cdf_header->dir_start); + for (num = 0; sec >= 0; sec = next) { + if (num >= MAX_DIR_SECTORS) { + fprintf(stderr, "error: MAX_DIR_SECTORS exceeded\n"); + exit(1); + } + dir_secids[num++] = sec; + next = get_fat_entry(sec); + } + dir_nsectors = num; + return(0); +} + +u_char * +get_dir_sector(dir_sec_no) + unsigned dir_sec_no; +{ + unsigned secid; + + if (dir_sec_no > dir_nsectors) { + fprintf(stderr, + "error: request for dir sector #%u; we only have %u in total\n", + dir_sec_no, dir_nsectors); + exit(1); + } + secid = dir_secids[dir_sec_no]; + return get_sector_ptr(secid); +} + +struct dir_entry * +get_dir_entry(dirid) + unsigned dirid; +{ + unsigned dir_sec_no, entry_in_sec; + struct dir_entry *dir_sector; + + dir_sec_no = dirid / 4; + entry_in_sec = dirid % 4; + dir_sector = (struct dir_entry *) get_dir_sector(dir_sec_no); + return dir_sector + entry_in_sec; +} + +dump_dir_entry(rec, indent) + struct dir_entry *rec; +{ + int i, u; + + for (i = indent; i; i--) + putchar(' '); + for (i = 0; i < 32; i++) { + u = le16toh(rec->uni_name[i]); + if (u == 0) + break; + if (u >= ' ' && u <= '~') + putchar(u); + else + printf("<%04X>", u); + } + printf(" (type %02X, length %u)\n", rec->type, rec->content_bytes); + return(0); +} + +dump_dir_level(dirid, indent) + unsigned dirid; +{ + struct dir_entry *rec; + int32_t ndir; + + rec = get_dir_entry(dirid); + ndir = le32toh(rec->left_child); + if (ndir >= 0) + dump_dir_level(ndir, indent); + dump_dir_entry(rec, indent); + ndir = le32toh(rec->right_child); + if (ndir >= 0) + dump_dir_level(ndir, indent); + ndir = le32toh(rec->subtree_dirid); + if (ndir >= 0) + dump_dir_level(ndir, indent + 2); + return(0); +} + +dump_dir_tree() +{ + init_fat_access(); + locate_dir_sectors(); + dump_dir_level(0, 0); + return(0); +} + main(argc, argv) char **argv; { @@ -182,6 +296,10 @@ fprintf(stderr, "error: struct cdf_header is misdefined\n"); exit(1); } + if (sizeof(struct dir_entry) != 128) { + fprintf(stderr, "error: struct dir_entry is misdefined\n"); + exit(1); + } if (argc < 3) { fprintf(stderr, "usage: %s binfile.dsn [args]\n", argv[0]); exit(1); @@ -192,6 +310,8 @@ return dump_cdf_header(); if (!strcmp(argv[2], "fatchain")) return dump_fat_chain(argv[3]); + if (!strcmp(argv[2], "ls")) + return dump_dir_tree(); fprintf(stderr, "error: \"%s\" is not a recognized command\n", argv[2]); exit(1); }