FreeCalypso > hg > freecalypso-tools
diff ffstools/tiffs-rd/object.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 | 1f27fc13eab7 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ffstools/tiffs-rd/object.c Sat Jun 11 00:13:35 2016 +0000 @@ -0,0 +1,153 @@ +/* + * This C module implements object-level analysis. + */ + +#include <sys/types.h> +#include <ctype.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" + +validate_obj_name(ino, root_special) +{ + struct inode_info *inf = inode_info[ino]; + u8 *p, *endp; + int c; + + if (!inf->len) + return(0); + p = inf->dataptr; + endp = p + inf->len; + for (; ; p++) { + if (p >= endp) + return(0); + c = *p; + if (!c) + break; + if (c < ' ' || c > '~') + return(0); + if (root_special || isalnum(c)) + continue; + switch (c) { + case '.': + case ',': + case '_': + case '-': + case '+': + case '%': + case '$': + case '#': + continue; + default: + return(0); + } + } + if (!root_special) { + c = p - inf->dataptr; + if (c < 1 || c > MAX_FN_COMPONENT) + return(0); + if (!strcmp(inf->dataptr, ".") || !strcmp(inf->dataptr, "..")) + return(0); + } + inf->byte_after_name = p + 1; + return(1); +} + +u8 * +find_end_of_chunk(inf) + struct inode_info *inf; +{ + u8 *p; + int i; + + p = inf->dataptr + inf->len; + for (i = 1; i <= 16; i++) { + if (!p[-i]) + return(p - i); + if (p[-i] != 0xFF) + break; + } + fprintf(stderr, + "error: chunk @%x (inode #%x): no valid termination found\n", + inf->offset, inf->ino); + return(p); /* bogon, allows the rest to continue */ +} + +size_head_chunk(inf, chi) + struct inode_info *inf; + struct chunkinfo *chi; +{ + chi->start = inf->byte_after_name; + chi->end = find_end_of_chunk(inf); + if (chi->start >= chi->end) { + chi->len = 0; + return(0); + } else { + chi->len = chi->end - chi->start; + return(1); + } +} + +size_extra_chunk(inf, chi) + struct inode_info *inf; + struct chunkinfo *chi; +{ + chi->start = inf->dataptr; + chi->end = find_end_of_chunk(inf); + chi->len = chi->end - chi->start; +} + +void +iterate_seg_file(seghead, callback, callback_data, deleted, verbose) + void (*callback)(); + u_long callback_data; +{ + int ino; + struct inode_info *inf; + + for (ino = inode_info[seghead]->descend; ino; ino = inf->descend) { +loop: if (!validate_inode(ino)) { + fprintf(stderr, + "error: following seg file hit invalid inode #%x\n", + ino); + return; + } + inf = inode_info[ino]; + switch (inf->type) { + case 0xF4: + callback(inf, callback_data); + continue; + case 0x00: + if (deleted) { + if (inf->len) + callback(inf, callback_data); + else + fprintf(stderr, + "error: presumed deleted segment inode #%x has been reclaimed\n", + ino); + continue; + } + if (!inf->sibling) { + fprintf(stderr, + "error: segment object at inode #%x: marked deleted, but no sibling\n", + ino); + return; + } + if (verbose) + printf("seg inode #%x deleted, moved to #%x\n", + ino, inf->sibling); + ino = inf->sibling; + goto loop; + default: + fprintf(stderr, + "error: inode #%x: unexpected type %02X when expecting segment (F4)\n", + ino, inf->type); + return; + } + } +}