view ffstools/tiffs-rd/object.c @ 992:a7b0b426f9ca

target-utils: boot ROM UART autodetection revamped The new implementation should work with both the familiar Calypso C035 boot ROM version found in our regular targets as well as the older Calypso F741979B version found on the vintage D-Sample board.
author Mychaela Falconia <falcon@ivan.Harhan.ORG>
date Wed, 30 Dec 2015 21:28:41 +0000
parents 317936902be4
children
line wrap: on
line source

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