diff ffstools/tiffs-rd/inode.c @ 231:5ceacdbd4490

tiffs IVA: finds the root inode
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Sun, 26 Jan 2014 08:11:42 +0000
parents
children 73372cfdaf7f
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ffstools/tiffs-rd/inode.c	Sun Jan 26 08:11:42 2014 +0000
@@ -0,0 +1,161 @@
+/*
+ * This C module implements the reading and decoding of inode information.
+ */
+
+#include <sys/types.h>
+#include <endian.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include "types.h"
+#include "struct.h"
+#include "globals.h"
+
+u8 blank_flash_line[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+			   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+
+alloc_inode_table()
+{
+	inode_info = malloc(sizeof(struct inode_info *) * inode_limit);
+	if (!inode_info) {
+		perror("malloc of inode table");
+		exit(1);
+	}
+	bzero(inode_info, sizeof(struct inode_info *) * inode_limit);
+}
+
+static int
+convert_ptr(in, infp)
+	int in;
+	int *infp;
+{
+	if (in == 0xFFFF) {
+		*infp = 0;
+		return(0);
+	}
+	if (in < 1 || in >= inode_limit)
+		return(-1);
+	*infp = in;
+	return(1);
+}
+
+validate_inode(ino)
+{
+	struct inode_flash *fl;
+	struct inode_info *inf;
+
+	if (ino < 1 || ino >= inode_limit)
+		return(0);
+	if (inode_info[ino])
+		return(1);
+	fl = (struct inode_flash *)inode_block + ino;
+	if (!bcmp(fl, blank_flash_line, sizeof blank_flash_line))
+		return(0);
+	inf = malloc(sizeof(struct inode_info));
+	if (!inf) {
+		perror("malloc of struct inode_info");
+		exit(1);
+	}
+	bzero(inf, sizeof(struct inode_info));
+	inf->len = le16toh(fl->len);
+	if (inf->len & 0xF) {
+		fprintf(stderr,
+			"warning: inode #%x: invalid length, skipping\n", ino);
+		free(inf);
+		return(0);
+	}
+	inf->type = fl->type;
+	switch (inf->type) {
+	case 0x00:
+		break;
+	case 0xE1:
+	case 0xF1:
+	case 0xF2:
+	case 0xF3:
+	case 0xF4:
+		if (!inf->len) {
+			fprintf(stderr,
+	"warning: inode #%x: non-deleted object has zero length, skipping\n",
+				ino);
+			free(inf);
+			return(0);
+		}
+		break;
+	default:
+		fprintf(stderr,
+		"warning: inode #%x: unexpected object type %02X, skipping\n",
+			ino, inf->type);
+		free(inf);
+		return(0);
+	}
+	if (convert_ptr(le16toh(fl->descend), &inf->descend) < 0) {
+		fprintf(stderr,
+		"warning: inode #%x: invalid descend pointer, skipping\n",
+			ino);
+		free(inf);
+		return(0);
+	}
+	if (convert_ptr(le16toh(fl->sibling), &inf->sibling) < 0) {
+		fprintf(stderr,
+		"warning: inode #%x: invalid sibling pointer, skipping\n",
+			ino);
+		free(inf);
+		return(0);
+	}
+	if (inf->len) {
+		inf->rawloc = le32toh(fl->dataptr);
+		if (inf->rawloc > 0x0FFFFFFF) {
+invdptr:		fprintf(stderr,
+			"warning: inode #%x: invalid data pointer, skipping\n",
+				ino);
+			free(inf);
+			return(0);
+		}
+		inf->offset = inf->rawloc << 4;
+		if (inf->offset >= total_ffs_size)
+			goto invdptr;
+		if (inf->offset + inf->len > total_ffs_size) {
+			fprintf(stderr,
+"warning: inode #%x: data pointer + length > FFS total size, skipping\n",
+				ino);
+			free(inf);
+			return(0);
+		}
+		inf->dataptr = image + inf->offset;
+	}
+	inode_info[ino] = inf;
+	return(1);
+}
+
+find_root_inode()
+{
+	int ino;
+
+	if (root_inode) {
+		if (!validate_inode(root_inode)) {
+			fprintf(stderr,
+			"error: root inode specified with -r is invalid\n");
+			exit(1);
+		}
+		return(1);
+	}
+	for (ino = 1; ino < inode_limit; ino++) {
+		if (!validate_inode(ino))
+			continue;
+		if (inode_info[ino]->type != 0xF2)
+			continue;
+		if (*inode_info[ino]->dataptr != '/')
+			continue;
+		root_inode = ino;
+		if (verbose)
+			fprintf(stderr, "Found root inode at #%x\n", ino);
+		if (inode_info[ino]->sibling)
+			fprintf(stderr,
+		"warning: root inode #%x has a non-null sibling pointer\n",
+				ino);
+		return(0);
+	}
+	fprintf(stderr, "error: no root inode found; try -r\n");
+	exit(1);
+}