FreeCalypso > hg > freecalypso-sw
view ffstools/tiffs-rd/tree.c @ 270:d1388095ab27
doc/RVTMUX write-up
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Thu, 06 Feb 2014 09:54:02 +0000 |
parents | 190121a34b3b |
children |
line wrap: on
line source
/* * 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); }