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);
+ − }