view ffstools/tiffs-rd/cat.c @ 823:d93ecff8544b
aci: psa_mms.c imported from TCS211 version
author |
Space Falcon <falcon@ivan.Harhan.ORG> |
date |
Sun, 05 Apr 2015 20:45:18 +0000 (2015-04-05) |
parents |
c95efd27fb2e |
children |
|
line source
/*
* 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);
}
cmd_catino(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: catino [-v|-h] ino\n");
exit(1);
}
if (argc != optind + 1)
goto usage;
headino = strtoul(argv[optind], 0, 16);
read_ffs_image();
find_inode_block();
alloc_inode_table();
if (!validate_inode(headino)) {
fprintf(stderr, "catino: specified inode number is invalid\n");
exit(1);
}
inf = inode_info[headino];
switch (inf->type) {
case 0x00:
case 0xE1:
case 0xF1:
case 0xF3:
break;
case 0xF2:
fprintf(stderr, "error: the requested object is a directory\n");
exit(1);
default:
fprintf(stderr, "error: unexpected object type %02X\n",
inf->type);
exit(1);
}
if (!inf->len) {
fprintf(stderr, "error: requested inode has been reclaimed\n");
exit(1);
}
if (!validate_obj_name(headino, 0)) {
fprintf(stderr,
"error: no valid name at the beginning of the requested seghead chunk\n");
exit(1);
}
size_head_chunk(inf, &chi);
cat_chunk(&chi);
iterate_seg_file(headino, segment_cat_callback, 0L, !inf->type, 0);
cat_finish();
exit(0);
}