diff ffstools/tiffs-rd/cat.c @ 240:acedd4c88d2e

tiffs cat command implemented
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Mon, 27 Jan 2014 02:32:46 +0000
parents
children c95efd27fb2e
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ffstools/tiffs-rd/cat.c	Mon Jan 27 02:32:46 2014 +0000
@@ -0,0 +1,170 @@
+/*
+ * This C module implements the cat and catino commands.
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include "types.h"
+#include "struct.h"
+#include "globals.h"
+#include "pathname.h"
+
+int cat_mode;
+
+static u8 hex_buf[16];
+static int hex_fill;
+static u32 hex_offset;
+
+cat_hex_flush()
+{
+	int i, c;
+
+	printf("%08X:  ", hex_offset);
+	for (i = 0; i < 16; i++) {
+		if (i < hex_fill)
+			printf("%02X ", hex_buf[i]);
+		else
+			fputs("   ", stdout);
+		if (i == 7 || i == 15)
+			putchar(' ');
+	}
+	for (i = 0; i < hex_fill; i++) {
+		c = hex_buf[i];
+		if (c < ' ' || c > '~')
+			c = '.';
+		putchar(c);
+	}
+	putchar('\n');
+}
+
+cat_hex_byte(inb)
+{
+	hex_buf[hex_fill++] = inb;
+	if (hex_fill >= 16) {
+		cat_hex_flush();
+		hex_offset += hex_fill;
+		hex_fill = 0;
+	}
+}
+
+void
+cat_chunk(ch)
+	struct chunkinfo *ch;
+{
+	u8 *p;
+	int c;
+
+	if (!ch->len)
+		return;
+	switch (cat_mode) {
+	case 0:
+		write(1, ch->start, ch->len);
+		return;
+	case 1:
+		for (p = ch->start; p < ch->end; p++) {
+			c = *p;
+			if (c >= ' ' && c <= '~' || c == '\n')
+				putchar(c);
+			else {
+				if (c & 0x80) {
+					putchar('M');
+					putchar('-');
+					c &= 0x7F;
+				}
+				putchar('^');
+				if (c == 0x7F)
+					putchar('?');
+				else
+					putchar(c + '@');
+			}
+		}
+		return;
+	case 2:
+		for (p = ch->start; p < ch->end; p++)
+			cat_hex_byte(*p);
+		return;
+	}
+}
+
+void
+cat_finish()
+{
+	switch (cat_mode) {
+	case 1:
+		putchar('\n');
+		return;
+	case 2:
+		if (hex_fill)
+			cat_hex_flush();
+		return;
+	}
+}
+
+static void
+segment_cat_callback(inf, opaque)
+	struct inode_info *inf;
+	u_long opaque;
+{
+	struct chunkinfo chi;
+
+	size_extra_chunk(inf, &chi);
+	cat_chunk(&chi);
+}
+
+cmd_cat(argc, argv)
+	char **argv;
+{
+	extern int optind;
+	int c, headino;
+	struct inode_info *inf;
+	struct chunkinfo chi;
+
+	optind = 0;
+	while ((c = getopt(argc, argv, "hv")) != EOF)
+		switch (c) {
+		case 'h':
+			cat_mode = 2;
+			continue;
+		case 'v':
+			cat_mode = 1;
+			continue;
+		default:
+usage:			fprintf(stderr, "usage: cat [-v|-h] pathname\n");
+			exit(1);
+		}
+	if (argc != optind + 1)
+		goto usage;
+
+	read_ffs_image();
+	find_inode_block();
+	alloc_inode_table();
+	find_root_inode();
+
+	headino = find_pathname(argv[optind]);
+	inf = inode_info[headino];
+	switch (inf->type) {
+	case 0xE1:
+	case 0xF1:
+		break;
+	case 0xF2:
+		fprintf(stderr, "error: the requested object is a directory\n");
+		exit(1);
+	case 0xF3:
+		fprintf(stderr,
+"error: the requested object is a symlink; use readlink instead of cat\n");
+		exit(1);
+	default:
+		fprintf(stderr, "error: unexpected object type %02X\n",
+			inf->type);
+		exit(1);
+	}
+	size_head_chunk(inf, &chi);
+	cat_chunk(&chi);
+	iterate_seg_file(headino, segment_cat_callback, 0L, 0, 0);
+	cat_finish();
+	exit(0);
+}