FreeCalypso > hg > freecalypso-sw
comparison ffstools/tiffs-rd/inode.c @ 231:5ceacdbd4490
tiffs IVA: finds the root inode
| author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
|---|---|
| date | Sun, 26 Jan 2014 08:11:42 +0000 |
| parents | |
| children | 73372cfdaf7f |
comparison
equal
deleted
inserted
replaced
| 230:ffaa033e7643 | 231:5ceacdbd4490 |
|---|---|
| 1 /* | |
| 2 * This C module implements the reading and decoding of inode information. | |
| 3 */ | |
| 4 | |
| 5 #include <sys/types.h> | |
| 6 #include <endian.h> | |
| 7 #include <stdio.h> | |
| 8 #include <stdlib.h> | |
| 9 #include <string.h> | |
| 10 #include <strings.h> | |
| 11 #include "types.h" | |
| 12 #include "struct.h" | |
| 13 #include "globals.h" | |
| 14 | |
| 15 u8 blank_flash_line[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |
| 16 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; | |
| 17 | |
| 18 alloc_inode_table() | |
| 19 { | |
| 20 inode_info = malloc(sizeof(struct inode_info *) * inode_limit); | |
| 21 if (!inode_info) { | |
| 22 perror("malloc of inode table"); | |
| 23 exit(1); | |
| 24 } | |
| 25 bzero(inode_info, sizeof(struct inode_info *) * inode_limit); | |
| 26 } | |
| 27 | |
| 28 static int | |
| 29 convert_ptr(in, infp) | |
| 30 int in; | |
| 31 int *infp; | |
| 32 { | |
| 33 if (in == 0xFFFF) { | |
| 34 *infp = 0; | |
| 35 return(0); | |
| 36 } | |
| 37 if (in < 1 || in >= inode_limit) | |
| 38 return(-1); | |
| 39 *infp = in; | |
| 40 return(1); | |
| 41 } | |
| 42 | |
| 43 validate_inode(ino) | |
| 44 { | |
| 45 struct inode_flash *fl; | |
| 46 struct inode_info *inf; | |
| 47 | |
| 48 if (ino < 1 || ino >= inode_limit) | |
| 49 return(0); | |
| 50 if (inode_info[ino]) | |
| 51 return(1); | |
| 52 fl = (struct inode_flash *)inode_block + ino; | |
| 53 if (!bcmp(fl, blank_flash_line, sizeof blank_flash_line)) | |
| 54 return(0); | |
| 55 inf = malloc(sizeof(struct inode_info)); | |
| 56 if (!inf) { | |
| 57 perror("malloc of struct inode_info"); | |
| 58 exit(1); | |
| 59 } | |
| 60 bzero(inf, sizeof(struct inode_info)); | |
| 61 inf->len = le16toh(fl->len); | |
| 62 if (inf->len & 0xF) { | |
| 63 fprintf(stderr, | |
| 64 "warning: inode #%x: invalid length, skipping\n", ino); | |
| 65 free(inf); | |
| 66 return(0); | |
| 67 } | |
| 68 inf->type = fl->type; | |
| 69 switch (inf->type) { | |
| 70 case 0x00: | |
| 71 break; | |
| 72 case 0xE1: | |
| 73 case 0xF1: | |
| 74 case 0xF2: | |
| 75 case 0xF3: | |
| 76 case 0xF4: | |
| 77 if (!inf->len) { | |
| 78 fprintf(stderr, | |
| 79 "warning: inode #%x: non-deleted object has zero length, skipping\n", | |
| 80 ino); | |
| 81 free(inf); | |
| 82 return(0); | |
| 83 } | |
| 84 break; | |
| 85 default: | |
| 86 fprintf(stderr, | |
| 87 "warning: inode #%x: unexpected object type %02X, skipping\n", | |
| 88 ino, inf->type); | |
| 89 free(inf); | |
| 90 return(0); | |
| 91 } | |
| 92 if (convert_ptr(le16toh(fl->descend), &inf->descend) < 0) { | |
| 93 fprintf(stderr, | |
| 94 "warning: inode #%x: invalid descend pointer, skipping\n", | |
| 95 ino); | |
| 96 free(inf); | |
| 97 return(0); | |
| 98 } | |
| 99 if (convert_ptr(le16toh(fl->sibling), &inf->sibling) < 0) { | |
| 100 fprintf(stderr, | |
| 101 "warning: inode #%x: invalid sibling pointer, skipping\n", | |
| 102 ino); | |
| 103 free(inf); | |
| 104 return(0); | |
| 105 } | |
| 106 if (inf->len) { | |
| 107 inf->rawloc = le32toh(fl->dataptr); | |
| 108 if (inf->rawloc > 0x0FFFFFFF) { | |
| 109 invdptr: fprintf(stderr, | |
| 110 "warning: inode #%x: invalid data pointer, skipping\n", | |
| 111 ino); | |
| 112 free(inf); | |
| 113 return(0); | |
| 114 } | |
| 115 inf->offset = inf->rawloc << 4; | |
| 116 if (inf->offset >= total_ffs_size) | |
| 117 goto invdptr; | |
| 118 if (inf->offset + inf->len > total_ffs_size) { | |
| 119 fprintf(stderr, | |
| 120 "warning: inode #%x: data pointer + length > FFS total size, skipping\n", | |
| 121 ino); | |
| 122 free(inf); | |
| 123 return(0); | |
| 124 } | |
| 125 inf->dataptr = image + inf->offset; | |
| 126 } | |
| 127 inode_info[ino] = inf; | |
| 128 return(1); | |
| 129 } | |
| 130 | |
| 131 find_root_inode() | |
| 132 { | |
| 133 int ino; | |
| 134 | |
| 135 if (root_inode) { | |
| 136 if (!validate_inode(root_inode)) { | |
| 137 fprintf(stderr, | |
| 138 "error: root inode specified with -r is invalid\n"); | |
| 139 exit(1); | |
| 140 } | |
| 141 return(1); | |
| 142 } | |
| 143 for (ino = 1; ino < inode_limit; ino++) { | |
| 144 if (!validate_inode(ino)) | |
| 145 continue; | |
| 146 if (inode_info[ino]->type != 0xF2) | |
| 147 continue; | |
| 148 if (*inode_info[ino]->dataptr != '/') | |
| 149 continue; | |
| 150 root_inode = ino; | |
| 151 if (verbose) | |
| 152 fprintf(stderr, "Found root inode at #%x\n", ino); | |
| 153 if (inode_info[ino]->sibling) | |
| 154 fprintf(stderr, | |
| 155 "warning: root inode #%x has a non-null sibling pointer\n", | |
| 156 ino); | |
| 157 return(0); | |
| 158 } | |
| 159 fprintf(stderr, "error: no root inode found; try -r\n"); | |
| 160 exit(1); | |
| 161 } |
