view ffstools/tiffs-rd/ls.c @ 233:e434df27e4d9

fc-fsio format command: don't stop scripts on NOPREFORMAT error, i.e., if the FFS is already formatted
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 12 Aug 2017 17:31:50 +0000
parents e7502631a0f9
children 1f27fc13eab7
line wrap: on
line source

/*
 * This C module implements the ls and lsino commands.
 */

#include <sys/types.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"

static void
segment_size_callback(inf, opaque)
	struct inode_info *inf;
	u_long opaque;
{
	size_t *accump = (size_t *) opaque;
	struct chunkinfo chi;

	size_extra_chunk(inf, &chi);
	*accump += chi.len;
}

size_t
get_file_size(seghead_ino, deleted)
{
	struct chunkinfo chi;
	size_t accum;

	size_head_chunk(inode_info[seghead_ino], &chi);
	accum = chi.len;
	iterate_seg_file(seghead_ino, segment_size_callback, (u_long) &accum,
			 deleted, 0);
	return(accum);
}

static void
segment_ls_callback(inf, opaque)
	struct inode_info *inf;
	u_long opaque;
{
	struct chunkinfo chi;

	size_extra_chunk(inf, &chi);
	if (verbose2 > 1)
		printf("seg #%04x @%08x length=%lu\n", inf->ino, inf->offset,
			(u_long) chi.len);
	else
		printf("seg #%04x length=%lu\n", inf->ino, (u_long) chi.len);
}

ls_seg_file(seghead_ino, deleted)
{
	struct inode_info *inf = inode_info[seghead_ino];
	struct chunkinfo chi;

	size_head_chunk(inf, &chi);
	printf("%lu bytes in seghead", (u_long) chi.len);
	if (verbose2 > 1)
		printf(", starting at offset %lx",
			(u_long)(inf->byte_after_name - image));
	putchar('\n');
	iterate_seg_file(seghead_ino, segment_ls_callback, 0L, deleted,
			 verbose2 > 1);
}

void
ls_tree_callback(pathname, ino, depth)
	char *pathname;
{
	struct inode_info *inf = inode_info[ino];
	u_long size;
	char readonly;

	if (inf->type & 0x10)
		readonly = ' ';
	else
		readonly = 'r';
	switch (inf->type) {
	case 0xE1:
	case 0xF1:
		size = get_file_size(ino, 0);
		printf("f%c %7lu %s\n", readonly, size, pathname);
		if (verbose2)
			ls_seg_file(ino, 0);
		return;
	case 0xE2:
	case 0xF2:
		printf("d%c         %s\n", readonly, pathname);
		return;
	case 0xE3:
	case 0xF3:
		printf("l%c         %s\n", readonly, pathname);
		return;
	default:
		fprintf(stderr,
			"BUG: bad inode byte %02X reached ls_tree_callback()\n",
			inf->type);
		exit(1);
	}
}

ls_by_pathname(pathname)
	char *pathname;
{
	int ino;
	struct inode_info *inf;
	char *type;

	printf("%s\n", pathname);
	ino = find_pathname(pathname);
	printf("inode #%x\n", ino);
	inf = inode_info[ino];
	switch (inf->type) {
	case 0xE1:
		type = "read-only file";
		break;
	case 0xF1:
		type = "file";
		break;
	case 0xF2:
		type = "directory";
		break;
	case 0xF3:
		type = "symlink";
		break;
	default:
		type = "???";
	}
	printf("object type %02X (%s)\n", inf->type, type);
	if (!validate_obj_name(ino, ino == root_inode)) {
		printf("No valid object name in the chunk!\n");
		exit(1);
	}
	printf("object name: %s\n", inf->dataptr);
	if (inf->type == 0xF1 || inf->type == 0xE1) {
		printf("total size: %lu bytes\n",
			(u_long) get_file_size(ino, 0));
		if (verbose2)
			ls_seg_file(ino, 0);
	}
	putchar('\n');
}

cmd_ls(argc, argv)
	char **argv;
{
	extern int optind;
	int c;

	read_ffs_image();
	find_inode_block();
	alloc_inode_table();
	find_root_inode();

	optind = 0;
	while ((c = getopt(argc, argv, "v")) != EOF)
		switch (c) {
		case 'v':
			verbose2++;
			continue;
		default:
			fprintf(stderr, "usage: ls [-v[v]] [pathname...]\n");
			exit(1);
		}
	if (optind >= argc) {
		traverse_visible_tree(ls_tree_callback);
		exit(0);
	}
	for (; optind < argc; optind++)
		ls_by_pathname(argv[optind]);
	exit(0);
}

lsino_all()
{
	int ino, last_ino = 0;
	struct inode_info *inf;
	char pathname[PATHNAME_BUF_SIZE], typech;
	int pathstat;
	char descend_str[8], sibling_str[8];

	for (ino = 1; ino < inode_limit; ino++) {
		if (!validate_inode(ino))
			continue;
		if (ino != last_ino + 1)
			printf("GAP in inode numbers\n");
		inf = inode_info[ino];
		pathstat = pathname_of_inode(ino, pathname);
		if (pathstat < 0)
			strcpy(pathname, "-nopath-");
		switch (inf->type) {
		case 0x00:
			typech = '~';
			break;
		case 0xE1:
		case 0xF1:
			typech = 'f';
			break;
		case 0xF2:
			typech = 'd';
			break;
		case 0xF3:
			typech = 'l';
			break;
		case 0xF4:
			typech = '.';
			break;
		default:
			typech = '?';
		}
		printf("#%04x %c %s\n", ino, typech, pathname);
		if (inf->type && !(inf->type & 0x10))
			printf("\tread-only object\n");
		if (ino == root_inode)
			printf("\tactive root\n");
		else if (inf->nparents < 1)
			printf("\torphan\n");
		else if (inf->nparents > 1)
			printf("\tparent: #%x (%d)\n", inf->parent,
				inf->nparents);
		else if (pathstat < 0 || verbose2)
			printf("\tparent: #%x\n", inf->parent);
		if (verbose2 > 1) {
			if (inf->descend)
				sprintf(descend_str, "#%x", inf->descend);
			else
				strcpy(descend_str, "null");
			if (inf->sibling)
				sprintf(sibling_str, "#%x", inf->sibling);
			else
				strcpy(sibling_str, "null");
			printf("\tchild: %s, sibling: %s\n",
				descend_str, sibling_str);
		}
		if (!inf->len)
			printf("\treclaimed\n");
		last_ino = ino;
	}
	exit(0);
}

void
lsino_one(ino, assume_file)
{
	struct inode_info *inf;
	char pathname[PATHNAME_BUF_SIZE], *type;

	if (!validate_inode(ino)) {
		fprintf(stderr, "lsino: specified inode number is invalid\n");
		exit(1);
	}
	printf("inode #%x\n", ino);
	inf = inode_info[ino];
	if (pathname_of_inode(ino, pathname) >= 0)
		printf("Pathname: %s\n", pathname);
	else
		printf("No pathname found\n");
	inf = inode_info[ino];
	switch (inf->type) {
	case 0x00:
		type = "deleted";
		break;
	case 0xE1:
		type = "read-only file";
		break;
	case 0xF1:
		type = "file";
		break;
	case 0xF2:
		type = "directory";
		break;
	case 0xF3:
		type = "symlink";
		break;
	case 0xF4:
		type = "segment";
		break;
	default:
		type = "???";
	}
	printf("object type %02X (%s)\n", inf->type, type);
	if (!inf->len) {
		printf("This inode has been reclaimed\n\n");
		return;
	}
	if (validate_obj_name(ino, 1))
		printf("object name: %s\n", inf->dataptr);
	else {
		printf("No valid object name in the chunk\n\n");
		return;
	}
	if (inf->type == 0xF1 || inf->type == 0xE1 ||
	    !inf->type && assume_file) {
		printf("total size: %lu bytes\n",
			(u_long) get_file_size(ino, !inf->type));
		if (verbose2)
			ls_seg_file(ino, !inf->type);
	}
	putchar('\n');
}

cmd_lsino(argc, argv)
	char **argv;
{
	extern int optind;
	int c, assume_file = 0, ino;

	read_ffs_image();
	find_inode_block();
	alloc_inode_table();
	find_root_inode();
	treewalk_all();

	optind = 0;
	while ((c = getopt(argc, argv, "fv")) != EOF)
		switch (c) {
		case 'f':
			assume_file++;
			continue;
		case 'v':
			verbose2++;
			continue;
		default:
			fprintf(stderr, "usage: lsino [-v[v]] [ino...]\n");
			exit(1);
		}
	if (optind >= argc)
		return lsino_all();
	for (; optind < argc; optind++) {
		ino = strtoul(argv[optind], 0, 16);
		lsino_one(ino, assume_file);
	}
	exit(0);
}