FreeCalypso > hg > freecalypso-tools
diff ffstools/tiffs-rd/tree.c @ 0:e7502631a0f9
initial import from freecalypso-sw rev 1033:5ab737ac3ad7
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 11 Jun 2016 00:13:35 +0000 |
parents | |
children | 1f27fc13eab7 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ffstools/tiffs-rd/tree.c Sat Jun 11 00:13:35 2016 +0000 @@ -0,0 +1,237 @@ +/* + * This C module implements operations on the tree level. + */ + +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include "types.h" +#include "struct.h" +#include "globals.h" +#include "pathname.h" + +static void +visible_walk_dir(pathbuf_start, pathbuf_ptr, dirino, depth, callback) + char *pathbuf_start, *pathbuf_ptr; + void (*callback)(); +{ + int ndepth = depth + 1; + int child; + struct inode_info *inf; + + if (depth > MAX_DIR_NEST) { + fprintf(stderr, + "error: max dir nesting exceeded at inode #%x\n", + dirino); + return; + } + for (child = inode_info[dirino]->descend; child; child = inf->sibling) { + if (!validate_inode(child)) { + fprintf(stderr, + "error: walk of visible tree hit invalid inode #%x\n", + child); + return; + } + inf = inode_info[child]; + 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, child); + continue; + } + if (!validate_obj_name(child, 0)) { + fprintf(stderr, + "visible tree walk error: no valid name for inode #%x\n", + child); + continue; + } + sprintf(pathbuf_ptr, "/%s", inf->dataptr); + callback(pathbuf_start, child, ndepth); + if (inf->type == 0xF2) + visible_walk_dir(pathbuf_start, + index(pathbuf_ptr, '\0'), child, + ndepth, callback); + } +} + +traverse_visible_tree(callback) + void (*callback)(); +{ + char pathbuf[PATHNAME_BUF_SIZE]; + + 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); +} + +/* + * 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; + } + if (inf->nparents == 1) + 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); +}