view ffstools/tiffs-rd/object.c @ 587:5b88ba62b9ae

doc/Rvinterf-tools: rvinterf -P option documented
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 03 Feb 2020 07:56:57 +0000
parents e7502631a0f9
children 1f27fc13eab7
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;
		}
	}
}