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