view ffstools/tiffs-rd/object.c @ 926:6a0aa8d36d06

rvinterf backslash escape: introduce libprint The new helper function library named libprint is meant to replace the badly misnamed libg23, and will soon contain functions for printing all of the same kinds of GPF TST packets that are now handled in libg23. However, we are also moving safe_print_trace() from libasync to this new library, and changing it to emit our new backslash escape format.
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 23 May 2023 03:47:46 +0000
parents 1f27fc13eab7
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"

object_name_mincheck(ino)
{
	struct inode_info *inf = inode_info[ino];
	u8 *p, *endp;

	if (!inf->len)
		return(0);
	p = inf->dataptr;
	endp = p + inf->len;
	for (; ; p++) {
		if (p >= endp)
			return(0);
		if (!*p)
			break;
	}
	inf->byte_after_name = p + 1;
	return(1);
}

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