# HG changeset patch # User Michael Spacefalcon # Date 1390779162 0 # Node ID 0b13839f782c1787832aa938cfb0de8d9857abd7 # Parent 317936902be4bdd2a9d35ca779bd904e32840bcd tiffs IVA: lsino (non-specific) implemented diff -r 317936902be4 -r 0b13839f782c ffstools/tiffs-rd/ls.c --- a/ffstools/tiffs-rd/ls.c Sun Jan 26 21:12:15 2014 +0000 +++ b/ffstools/tiffs-rd/ls.c Sun Jan 26 23:32:42 2014 +0000 @@ -174,3 +174,99 @@ ls_by_pathname(argv[optind]); exit(0); } + +lsino_all() +{ + int ino, last_ino = 0; + struct inode_info *inf; + char pathname[PATHNAME_BUF_SIZE], typech; + int pathstat; + char descend_str[8], sibling_str[8]; + + for (ino = 1; ino < inode_limit; ino++) { + if (!validate_inode(ino)) + continue; + if (ino != last_ino + 1) + printf("GAP in inode numbers\n"); + inf = inode_info[ino]; + pathstat = pathname_of_inode(ino, pathname); + if (pathstat < 0) + strcpy(pathname, "-nopath-"); + switch (inf->type) { + case 0x00: + typech = '~'; + break; + case 0xE1: + case 0xF1: + typech = 'f'; + break; + case 0xF2: + typech = 'd'; + break; + case 0xF3: + typech = 'l'; + break; + case 0xF4: + typech = '.'; + break; + default: + typech = '?'; + } + printf("#%04x %c %s\n", ino, typech, pathname); + if (inf->type && !(inf->type & 0x10)) + printf("\tread-only object\n"); + if (ino == root_inode) + printf("\tactive root\n"); + else if (inf->nparents < 1) + printf("\torphan\n"); + else if (inf->nparents > 1) + printf("\tparent: #%x (%d)\n", inf->parent, + inf->nparents); + else if (pathstat < 0 || verbose2) + printf("\tparent: #%x\n", inf->parent); + if (verbose2 > 1) { + if (inf->descend) + sprintf(descend_str, "#%x", inf->descend); + else + strcpy(descend_str, "null"); + if (inf->sibling) + sprintf(sibling_str, "#%x", inf->sibling); + else + strcpy(sibling_str, "null"); + printf("\tchild: %s, sibling: %s\n", + descend_str, sibling_str); + } + if (!inf->len) + printf("\treclaimed\n"); + last_ino = ino; + } + exit(0); +} + +cmd_lsino(argc, argv) + char **argv; +{ + extern int optind; + int c; + + read_ffs_image(); + find_inode_block(); + alloc_inode_table(); + find_root_inode(); + treewalk_all(); + + optind = 0; + while ((c = getopt(argc, argv, "v")) != EOF) + switch (c) { + case 'v': + verbose2++; + continue; + default: + fprintf(stderr, "usage: lsino [-v[v]] [ino...]\n"); + exit(1); + } + if (optind >= argc) + return lsino_all(); + fprintf(stderr, "lsino of specific inodes not implemented yet\n"); + exit(1); +} diff -r 317936902be4 -r 0b13839f782c ffstools/tiffs-rd/main.c --- a/ffstools/tiffs-rd/main.c Sun Jan 26 21:12:15 2014 +0000 +++ b/ffstools/tiffs-rd/main.c Sun Jan 26 23:32:42 2014 +0000 @@ -56,6 +56,7 @@ extern int cmd_blkhdr(); extern int cmd_fsinfo(); extern int cmd_ls(); +extern int cmd_lsino(); static struct cmdtab { char *cmd; @@ -66,6 +67,7 @@ {"fsck", NULL}, {"fsinfo", cmd_fsinfo}, {"ls", cmd_ls}, + {"lsino", cmd_lsino}, {"xtr", NULL}, {NULL, NULL} }; diff -r 317936902be4 -r 0b13839f782c ffstools/tiffs-rd/tree.c --- a/ffstools/tiffs-rd/tree.c Sun Jan 26 21:12:15 2014 +0000 +++ b/ffstools/tiffs-rd/tree.c Sun Jan 26 23:32:42 2014 +0000 @@ -165,3 +165,72 @@ } return(ino); } + +/* + * treewalk_all() walks the entire inode tree from the root down, without + * regard to object types, including deleted objects and even reclaimed ones. + * The output is the filling of the parent and nparents fields in the inode + * info array. + */ + +static void +treewalk_all_node(parent) +{ + int child; + struct inode_info *inf; + + for (child = inode_info[parent]->descend; child; child = inf->sibling) { + if (!validate_inode(child)) { + fprintf(stderr, + "error: walk of complete tree hit invalid inode #%x\n", + child); + return; + } + inf = inode_info[child]; + inf->parent = parent; + inf->nparents++; + if (inf->nparents >= inode_limit) { + fprintf(stderr, + "error: detected loop in inode tree at #%x, child of #%x\n", + child, parent); + return; + } + treewalk_all_node(child); + } +} + +treewalk_all() +{ + treewalk_all_node(root_inode); +} + +pathname_of_inode(ino, pnbuf) + char *pnbuf; +{ + int level; + char *revpath[MAX_DIR_NEST+1]; + struct inode_info *inf; + char *op; + + for (level = 0; ino != root_inode; ino = inf->parent) { + if (!validate_obj_name(ino, 0)) + return(-1); + inf = inode_info[ino]; + if (!inf->parent) + return(-1); + if (level > MAX_DIR_NEST) + return(-1); + revpath[level++] = (char *) inf->dataptr; + } + op = pnbuf; + if (!level) + *op++ = '/'; + while (level) { + level--; + *op++ = '/'; + strcpy(op, revpath[level]); + op = index(op, '\0'); + } + *op = '\0'; + return(0); +}