FreeCalypso > hg > freecalypso-tools
diff ffstools/tiffs-rd/inode.c @ 0:e7502631a0f9
initial import from freecalypso-sw rev 1033:5ab737ac3ad7
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 11 Jun 2016 00:13:35 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ffstools/tiffs-rd/inode.c Sat Jun 11 00:13:35 2016 +0000 @@ -0,0 +1,164 @@ +/* + * This C module implements the reading and decoding of inode information. + */ + +#include <sys/types.h> +#include <endian.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include "types.h" +#include "struct.h" +#include "globals.h" + +u8 blank_flash_line[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + +alloc_inode_table() +{ + inode_info = malloc(sizeof(struct inode_info *) * inode_limit); + if (!inode_info) { + perror("malloc of inode table"); + exit(1); + } + bzero(inode_info, sizeof(struct inode_info *) * inode_limit); +} + +static int +convert_ptr(in, infp) + int in; + int *infp; +{ + if (in == 0xFFFF) { + *infp = 0; + return(0); + } + if (in < 1 || in >= inode_limit) + return(-1); + *infp = in; + return(1); +} + +validate_inode(ino) +{ + struct inode_flash *fl; + struct inode_info *inf; + + if (ino < 1 || ino >= inode_limit) + return(0); + if (inode_info[ino]) + return(1); + fl = (struct inode_flash *)inode_block + ino; + if (!bcmp(fl, blank_flash_line, sizeof blank_flash_line)) + return(0); + inf = malloc(sizeof(struct inode_info)); + if (!inf) { + perror("malloc of struct inode_info"); + exit(1); + } + bzero(inf, sizeof(struct inode_info)); + inf->ino = ino; + inf->len = le16toh(fl->len); + if (inf->len & 0xF) { + fprintf(stderr, + "warning: inode #%x: invalid length, skipping\n", ino); + free(inf); + return(0); + } + inf->type = fl->type; + switch (inf->type) { + case 0x00: + break; + case 0xE1: + case 0xF1: + case 0xF2: + case 0xF3: + case 0xF4: + if (!inf->len) { + fprintf(stderr, + "warning: inode #%x: non-deleted object has zero length, skipping\n", + ino); + free(inf); + return(0); + } + break; + default: + fprintf(stderr, + "warning: inode #%x: unexpected object type %02X, skipping\n", + ino, inf->type); + free(inf); + return(0); + } + if (convert_ptr(le16toh(fl->descend), &inf->descend) < 0) { + fprintf(stderr, + "warning: inode #%x: invalid descend pointer, skipping\n", + ino); + free(inf); + return(0); + } + if (convert_ptr(le16toh(fl->sibling), &inf->sibling) < 0) { + fprintf(stderr, + "warning: inode #%x: invalid sibling pointer, skipping\n", + ino); + free(inf); + return(0); + } + if (inf->len) { + inf->rawloc = le32toh(fl->dataptr); + if (old_16bit_location) + inf->rawloc >>= 16; + if (inf->rawloc > 0x0FFFFFFF) { +invdptr: fprintf(stderr, + "warning: inode #%x: invalid data pointer, skipping\n", + ino); + free(inf); + return(0); + } + inf->offset = inf->rawloc << 4; + if (inf->offset >= total_ffs_size) + goto invdptr; + if (inf->offset + inf->len > total_ffs_size) { + fprintf(stderr, +"warning: inode #%x: data pointer + length > FFS total size, skipping\n", + ino); + free(inf); + return(0); + } + inf->dataptr = image + inf->offset; + } + inode_info[ino] = inf; + return(1); +} + +find_root_inode() +{ + int ino; + + if (root_inode) { + if (!validate_inode(root_inode)) { + fprintf(stderr, + "error: root inode specified with -r is invalid\n"); + exit(1); + } + return(1); + } + for (ino = 1; ino < inode_limit; ino++) { + if (!validate_inode(ino)) + continue; + if (inode_info[ino]->type != 0xF2) + continue; + if (*inode_info[ino]->dataptr != '/') + continue; + root_inode = ino; + if (verbose) + fprintf(stderr, "Found root inode at #%x\n", ino); + if (inode_info[ino]->sibling) + fprintf(stderr, + "warning: root inode #%x has a non-null sibling pointer\n", + ino); + return(0); + } + fprintf(stderr, "error: no root inode found; try -r\n"); + exit(1); +}