view target-utils/libmpffs/basicfind.c @ 101:7029fe8ae0bc

pirexplore: FFS find command implemented
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Mon, 02 Sep 2013 00:33:54 +0000
parents
children 7f75ffdd674f
line wrap: on
line source

#include <sys/types.h>
#include "types.h"
#include "struct.h"
#include "globals.h"
#include "macros.h"

extern char *index();

static u8 *
find_endofchunk(ino)
{
	struct inode *irec = mpffs_active_index + ino;
	u8 *p;
	int i;

	p = inode_to_dataptr(irec) + irec->len;
	for (i = 0; i < 16; i++) {
		p--;
		if (!*p)
			return(p);
		if (*p != 0xFF)
			break;
	}
	printf("Error: inode #%x has no valid termination\n", ino);
	return(p);	/* XXX */
}

static
find_named_child(start, seekname)
	char *seekname;
{
	int ino;
	struct inode *irec;

	for (ino = start; ino != 0xFFFF; ino = irec->sibling) {
		irec = mpffs_active_index + ino;
		if (!irec->type)
			continue;
		if (!strcmp(inode_to_dataptr(irec), seekname))
			return(ino);
	}
	return(0);
}

mpffs_pathname_to_inode(pathname)
	char *pathname;
{
	int ino, stat;
	struct inode *irec;
	char *cur, *next;

	stat = mpffs_init();
	if (stat < 0)
		return(stat);
	cur = pathname;
	if (*cur == '/')
		cur++;
	for (ino = mpffs_root_ino; cur; cur = next) {
		if (!*cur)
			break;
		next = index(cur, '/');
		if (next == cur) {
		    printf("malformed pathname: multiple adjacent slashes\n");
			return(-1);
		}
		if (next)
			*next++ = '\0';
		irec = mpffs_active_index + ino;
		if (irec->type != OBJTYPE_DIR) {
			printf("Error: non-terminal non-directory\n");
			if (next)
				next[-1] = '/';
			return(-1);
		}
		ino = find_named_child(irec->descend, cur);
		if (next)
			next[-1] = '/';
		if (!ino) {
			printf("Error: pathname component not found\n");
			return(-1);
		}
	}
	return(ino);
}

mpffs_find_file(pathname, startret, sizeret, continue_ret)
	char *pathname;
	u8 **startret;
	size_t *sizeret;
	int *continue_ret;
{
	int ino, cont;
	struct inode *irec;
	u8 *start, *end;
	size_t size;

	ino = mpffs_pathname_to_inode(pathname);
	if (ino <= 0)
		return(-1);
	irec = mpffs_active_index + ino;
	if (irec->type != OBJTYPE_FILE) {
		printf("Error: %s is not a regular file\n", pathname);
		return(-1);
	}
	start = inode_to_dataptr(irec);
	start += strlen(start) + 1;
	end = find_endofchunk(ino);
	size = end - start;
	if (size < 0)
		size = 0;
	cont = irec->descend;
	if (cont == 0xFFFF)
		cont = 0;
	if (startret)
		*startret = start;
	if (sizeret)
		*sizeret = size;
	if (continue_ret)
		*continue_ret = cont;
	return(0);
}

mpffs_get_segment(ino, startret, sizeret, continue_ret)
	int ino;
	u8 **startret;
	size_t *sizeret;
	int *continue_ret;
{
	int cont;
	struct inode *irec;
	u8 *start, *end;
	size_t size;

	for (;;) {
		irec = mpffs_active_index + ino;
		if (irec->type)
			break;
		if (irec->sibling == 0xFFFF) {
		    printf("Error: segment inode #%d: deleted and no sibling\n",
				ino);
			return(-1);
		}
		ino = irec->sibling;
	}
	if (irec->type != OBJTYPE_SEGMENT) {
		printf("Error: inode #%x is not a segment\n", ino);
		return(-1);
	}
	start = inode_to_dataptr(irec);
	end = find_endofchunk(ino);
	size = end - start;
	if (size <= 0) {
		printf("Error: segment inode #%x: bad length\n", ino);
		return(-1);
	}
	cont = irec->descend;
	if (cont == 0xFFFF)
		cont = 0;
	if (startret)
		*startret = start;
	if (sizeret)
		*sizeret = size;
	if (continue_ret)
		*continue_ret = cont;
	return(0);
}