# HG changeset patch # User Michael Spacefalcon # Date 1390770735 0 # Node ID 317936902be4bdd2a9d35ca779bd904e32840bcd # Parent 254de9560ef33a86086eb11ca60a908d25a50deb tiffs IVA: regular ls fully implemented diff -r 254de9560ef3 -r 317936902be4 ffstools/tiffs-rd/ls.c --- a/ffstools/tiffs-rd/ls.c Sun Jan 26 19:03:33 2014 +0000 +++ b/ffstools/tiffs-rd/ls.c Sun Jan 26 21:12:15 2014 +0000 @@ -33,7 +33,7 @@ size_head_chunk(inode_info[seghead_ino], &chi); accum = chi.len; iterate_seg_file(seghead_ino, segment_size_callback, (u_long) &accum, - deleted); + deleted, 0); return(accum); } @@ -45,7 +45,11 @@ struct chunkinfo chi; size_extra_chunk(inf, &chi); - printf("seg #%04x length=%lu\n", inf->ino, (u_long) chi.len); + if (verbose2 > 1) + printf("seg #%04x @%08x length=%lu\n", inf->ino, inf->offset, + (u_long) chi.len); + else + printf("seg #%04x length=%lu\n", inf->ino, (u_long) chi.len); } ls_seg_file(seghead_ino, deleted) @@ -54,12 +58,17 @@ struct chunkinfo chi; size_head_chunk(inf, &chi); - printf("%lu bytes in seghead\n", (u_long) chi.len); - iterate_seg_file(seghead_ino, segment_ls_callback, 0L, deleted); + printf("%lu bytes in seghead", (u_long) chi.len); + if (verbose2 > 1) + printf(", starting at offset %lx", + (u_long)(inf->byte_after_name - image)); + putchar('\n'); + iterate_seg_file(seghead_ino, segment_ls_callback, 0L, deleted, + verbose2 > 1); } void -ls_callback(pathname, ino, depth) +ls_tree_callback(pathname, ino, depth) char *pathname; { struct inode_info *inf = inode_info[ino]; @@ -94,28 +103,74 @@ } } -ls_visible_tree() +ls_by_pathname(pathname) + char *pathname; { - read_ffs_image(); - find_inode_block(); - alloc_inode_table(); - find_root_inode(); - traverse_visible_tree(ls_callback); - exit(0); + int ino; + struct inode_info *inf; + char *type; + + printf("%s\n", pathname); + ino = find_pathname(pathname); + printf("inode #%x\n", ino); + inf = inode_info[ino]; + switch (inf->type) { + case 0xE1: + type = "read-only file"; + break; + case 0xF1: + type = "file"; + break; + case 0xF2: + type = "directory"; + break; + case 0xF3: + type = "symlink"; + break; + default: + type = "???"; + } + printf("object type %02X (%s)\n", inf->type, type); + if (!validate_obj_name(ino, ino == root_inode)) { + printf("No valid object name in the chunk!\n"); + exit(1); + } + printf("object name: %s\n", inf->dataptr); + if (inf->type == 0xF1 || inf->type == 0xE1) { + printf("total size: %lu bytes\n", + (u_long) get_file_size(ino, 0)); + if (verbose2) + ls_seg_file(ino, 0); + } + putchar('\n'); } cmd_ls(argc, argv) char **argv; { - char **ap; + extern int optind; + int c; + + read_ffs_image(); + find_inode_block(); + alloc_inode_table(); + find_root_inode(); - ap = argv + 1; - if (*ap && !strcmp(*ap, "-v")) { - verbose2++; - ap++; + optind = 0; + while ((c = getopt(argc, argv, "v")) != EOF) + switch (c) { + case 'v': + verbose2++; + continue; + default: + fprintf(stderr, "usage: ls [-v[v]] [pathname...]\n"); + exit(1); + } + if (optind >= argc) { + traverse_visible_tree(ls_tree_callback); + exit(0); } - if (!*ap) - return ls_visible_tree(); - fprintf(stderr, "ls of individual files not yet implemented\n"); - exit(1); + for (; optind < argc; optind++) + ls_by_pathname(argv[optind]); + exit(0); } diff -r 254de9560ef3 -r 317936902be4 ffstools/tiffs-rd/object.c --- a/ffstools/tiffs-rd/object.c Sun Jan 26 19:03:33 2014 +0000 +++ b/ffstools/tiffs-rd/object.c Sun Jan 26 21:12:15 2014 +0000 @@ -103,7 +103,7 @@ } void -iterate_seg_file(seghead, callback, callback_data, deleted) +iterate_seg_file(seghead, callback, callback_data, deleted, verbose) void (*callback)(); u_long callback_data; { @@ -138,6 +138,9 @@ ino); return; } + if (verbose) + printf("seg inode #%x deleted, moved to #%x\n", + ino, inf->sibling); ino = inf->sibling; goto loop; default: diff -r 254de9560ef3 -r 317936902be4 ffstools/tiffs-rd/tree.c --- a/ffstools/tiffs-rd/tree.c Sun Jan 26 19:03:33 2014 +0000 +++ b/ffstools/tiffs-rd/tree.c Sun Jan 26 21:12:15 2014 +0000 @@ -67,3 +67,101 @@ visible_walk_dir(pathbuf, pathbuf, root_inode, 0, callback); } + +/* + * The following function iterates through the descendants of a directory + * object looking for a specific directory-member filename. + * + * Arguments: + * - inode # of the parent directory + * - inode # of the first descendant (descendant pointer from the dir object) + * - filename to search for + * + * Returns: inode # of the sought descendant object if found, 0 otherwise. + */ +find_dir_member(dirino, first_descend, srchname) + char *srchname; +{ + int ino; + struct inode_info *inf; + + for (ino = first_descend; ino; ino = inf->sibling) { + if (!validate_inode(ino)) { + fprintf(stderr, + "error: pathname search hit invalid inode #%x\n", + ino); + exit(1); + } + inf = inode_info[ino]; + switch (inf->type) { + case 0x00: + /* walking the *visible* tree: skip deleted objects */ + continue; + case 0xF4: + fprintf(stderr, + "warning: directory #%x has child #%x of type segment (F4), skipping\n", + dirino, ino); + continue; + } + if (!validate_obj_name(ino, 0)) { + fprintf(stderr, + "visible tree walk error: no valid name for inode #%x\n", + ino); + continue; + } + if (!strcmp(inf->dataptr, srchname)) + return(ino); + } + return(0); +} + +/* + * The following function searches for a pathname from the root down. + * Returns the inode # if found, otherwise exits with an error message + * indicating which step failed. + * + * Warning: the pathname in the argument buffer will be destroyed: + * 0s put in place of the slashes. + */ +find_pathname(pathname) + char *pathname; +{ + char *cur, *next; + int ino; + struct inode_info *inf; + + cur = pathname; + if (*cur == '/') + cur++; + else { + fprintf(stderr, + "bad pathname \"%s\": TIFFS pathnames must be absolute\n", + pathname); + exit(1); + } + for (ino = root_inode; cur; cur = next) { + if (!*cur) + break; + next = index(cur, '/'); + if (next == cur) { + fprintf(stderr, + "malformed pathname: multiple adjacent slashes\n"); + exit(1); + } + if (next) + *next++ = '\0'; + inf = inode_info[ino]; + if (inf->type != 0xF2) { + fprintf(stderr, + "pathname search error: encountered a non-directory\n"); + exit(1); + } + ino = find_dir_member(ino, inf->descend, cur); + if (!ino) { + fprintf(stderr, + "pathname search error: component name not found\n"); + exit(1); + } + } + return(ino); +}