view ffstools/tiffs-rd/inode.c @ 944:51f580665110

gsm-fw: C139 works with non-volatile FFS enabled
author Mychaela Falconia <falcon@ivan.Harhan.ORG>
date Sun, 01 Nov 2015 05:03:35 +0000
parents 024042383a26
children 09b8b2327838
line wrap: on
line source

/*
 * 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->ino = ino;
	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);
}