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 } |