diff ffstools/tiffs-rd/object.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/object.c	Sat Jun 11 00:13:35 2016 +0000
@@ -0,0 +1,153 @@
+/*
+ * This C module implements object-level analysis.
+ */
+
+#include <sys/types.h>
+#include <ctype.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"
+
+validate_obj_name(ino, root_special)
+{
+	struct inode_info *inf = inode_info[ino];
+	u8 *p, *endp;
+	int c;
+
+	if (!inf->len)
+		return(0);
+	p = inf->dataptr;
+	endp = p + inf->len;
+	for (; ; p++) {
+		if (p >= endp)
+			return(0);
+		c = *p;
+		if (!c)
+			break;
+		if (c < ' ' || c > '~')
+			return(0);
+		if (root_special || isalnum(c))
+			continue;
+		switch (c) {
+		case '.':
+		case ',':
+		case '_':
+		case '-':
+		case '+':
+		case '%':
+		case '$':
+		case '#':
+			continue;
+		default:
+			return(0);
+		}
+	}
+	if (!root_special) {
+		c = p - inf->dataptr;
+		if (c < 1 || c > MAX_FN_COMPONENT)
+			return(0);
+		if (!strcmp(inf->dataptr, ".") || !strcmp(inf->dataptr, ".."))
+			return(0);
+	}
+	inf->byte_after_name = p + 1;
+	return(1);
+}
+
+u8 *
+find_end_of_chunk(inf)
+	struct inode_info *inf;
+{
+	u8 *p;
+	int i;
+
+	p = inf->dataptr + inf->len;
+	for (i = 1; i <= 16; i++) {
+		if (!p[-i])
+			return(p - i);
+		if (p[-i] != 0xFF)
+			break;
+	}
+	fprintf(stderr,
+		"error: chunk @%x (inode #%x): no valid termination found\n",
+		inf->offset, inf->ino);
+	return(p);	/* bogon, allows the rest to continue */
+}
+
+size_head_chunk(inf, chi)
+	struct inode_info *inf;
+	struct chunkinfo *chi;
+{
+	chi->start = inf->byte_after_name;
+	chi->end = find_end_of_chunk(inf);
+	if (chi->start >= chi->end) {
+		chi->len = 0;
+		return(0);
+	} else {
+		chi->len = chi->end - chi->start;
+		return(1);
+	}
+}
+
+size_extra_chunk(inf, chi)
+	struct inode_info *inf;
+	struct chunkinfo *chi;
+{
+	chi->start = inf->dataptr;
+	chi->end = find_end_of_chunk(inf);
+	chi->len = chi->end - chi->start;
+}
+
+void
+iterate_seg_file(seghead, callback, callback_data, deleted, verbose)
+	void (*callback)();
+	u_long callback_data;
+{
+	int ino;
+	struct inode_info *inf;
+
+	for (ino = inode_info[seghead]->descend; ino; ino = inf->descend) {
+loop:		if (!validate_inode(ino)) {
+			fprintf(stderr,
+			"error: following seg file hit invalid inode #%x\n",
+				ino);
+			return;
+		}
+		inf = inode_info[ino];
+		switch (inf->type) {
+		case 0xF4:
+			callback(inf, callback_data);
+			continue;
+		case 0x00:
+			if (deleted) {
+				if (inf->len)
+					callback(inf, callback_data);
+				else
+					fprintf(stderr,
+	"error: presumed deleted segment inode #%x has been reclaimed\n",
+						ino);
+				continue;
+			}
+			if (!inf->sibling) {
+				fprintf(stderr,
+	"error: segment object at inode #%x: marked deleted, but no sibling\n",
+					ino);
+				return;
+			}
+			if (verbose)
+				printf("seg inode #%x deleted, moved to #%x\n",
+					ino, inf->sibling);
+			ino = inf->sibling;
+			goto loop;
+		default:
+			fprintf(stderr,
+	"error: inode #%x: unexpected type %02X when expecting segment (F4)\n",
+				ino, inf->type);
+			return;
+		}
+	}
+}