FreeCalypso > hg > freecalypso-reveng
comparison mpffs/xtr.c @ 36:390be89892c4
mpffs-xtr ported over
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Sun, 30 Jun 2013 17:24:21 +0000 |
parents | |
children | 7ceab8bfacb3 |
comparison
equal
deleted
inserted
replaced
35:ee4c761187cf | 36:390be89892c4 |
---|---|
1 /* | |
2 * This module contains the main function and other code specific to mpffs-xtr | |
3 */ | |
4 | |
5 #include <sys/types.h> | |
6 #include <sys/file.h> | |
7 #include <ctype.h> | |
8 #include <stdio.h> | |
9 #include <string.h> | |
10 #include <strings.h> | |
11 #include <stdlib.h> | |
12 #include <unistd.h> | |
13 #include "types.h" | |
14 #include "struct.h" | |
15 | |
16 extern char *imgfile; | |
17 extern struct objinfo root; | |
18 extern int verbose; | |
19 | |
20 extern u8 *find_end_of_chunk(); | |
21 | |
22 char workpath[512]; | |
23 | |
24 name_safe_for_extract(oi) | |
25 struct objinfo *oi; | |
26 { | |
27 char *s; | |
28 | |
29 s = (char *)oi->dataptr; | |
30 if (!isalnum(*s) && *s != '_') | |
31 return(0); | |
32 for (s++; *s; s++) | |
33 if (!isalnum(*s) && *s != '_' && *s != '.') | |
34 return(0); | |
35 return(1); | |
36 } | |
37 | |
38 void | |
39 dump_head_chunk(fd, ch) | |
40 struct objinfo *ch; | |
41 { | |
42 u8 *endname, *endchunk; | |
43 | |
44 endname = (u8 *) index((char *)ch->dataptr, '\0') + 1; | |
45 endchunk = find_end_of_chunk(ch); | |
46 if (endchunk <= endname) | |
47 return; | |
48 write(fd, endname, endchunk - endname); | |
49 } | |
50 | |
51 void | |
52 dump_extra_chunk(fd, ch) | |
53 struct objinfo *ch; | |
54 { | |
55 u8 *endchunk; | |
56 | |
57 endchunk = find_end_of_chunk(ch); | |
58 write(fd, ch->dataptr, endchunk - ch->dataptr); | |
59 } | |
60 | |
61 extract_file(head) | |
62 struct objinfo *head; | |
63 { | |
64 int fd; | |
65 int ent; | |
66 struct objinfo ch; | |
67 | |
68 fd = open(workpath + 1, O_WRONLY|O_CREAT|O_TRUNC, 0666); | |
69 if (fd < 0) { | |
70 perror(workpath + 1); | |
71 exit(1); | |
72 } | |
73 dump_head_chunk(fd, head); | |
74 for (ent = head->descend; ent != 0xFFFF; ent = ch.descend) { | |
75 ch.entryno = ent; | |
76 get_index_entry(&ch); | |
77 if (ch.type != 0xF4) { | |
78 fprintf(stderr, | |
79 "file continuation object at index %x: type %02X != expected F4\n", | |
80 ent, ch.type); | |
81 exit(1); | |
82 } | |
83 validate_chunk(&ch); | |
84 dump_extra_chunk(fd, &ch); | |
85 if (ch.sibling != 0xFFFF) | |
86 printf("warning: file continuation object (index %x) has a non-nil sibling pointer\n", | |
87 ent); | |
88 } | |
89 close(fd); | |
90 } | |
91 | |
92 dump_dir(firstent, path_prefix) | |
93 { | |
94 int ent; | |
95 struct objinfo obj; | |
96 | |
97 for (ent = firstent; ent != 0xFFFF; ent = obj.sibling) { | |
98 obj.entryno = ent; | |
99 get_index_entry(&obj); | |
100 if (!obj.type) /* skip deleted objects w/o further validation */ | |
101 continue; | |
102 validate_chunk(&obj); | |
103 validate_obj_name(&obj); | |
104 if (path_prefix + strlen(obj.dataptr) + 2 > sizeof workpath) { | |
105 fprintf(stderr, | |
106 "handling object at index %x, name \"%s\": path buffer overflow\n", | |
107 obj.entryno, (char *)obj.dataptr); | |
108 exit(1); | |
109 } | |
110 sprintf(workpath + path_prefix, "/%s", (char *)obj.dataptr); | |
111 switch (obj.type) { | |
112 case 0xF2: | |
113 /* directory */ | |
114 if (verbose) | |
115 printf("dir: %s\n", workpath); | |
116 if (!name_safe_for_extract(&obj)) { | |
117 fprintf(stderr, | |
118 "warning: directory name contains unsafe characters; subtree skipped\n"); | |
119 continue; | |
120 } | |
121 if (mkdir(workpath + 1, 0777) < 0) { | |
122 perror(workpath + 1); | |
123 exit(1); | |
124 } | |
125 dump_dir(obj.descend, strlen(workpath)); | |
126 continue; | |
127 case 0xF1: | |
128 /* regular file */ | |
129 if (verbose) | |
130 printf("file: %s\n", workpath); | |
131 if (!name_safe_for_extract(&obj)) { | |
132 fprintf(stderr, | |
133 "warning: file name contains unsafe characters; file skipped\n"); | |
134 continue; | |
135 } | |
136 extract_file(&obj); | |
137 continue; | |
138 case 0xE1: | |
139 /* special .journal file */ | |
140 if (verbose) | |
141 printf("skipping E1 file: %s\n", workpath); | |
142 continue; | |
143 default: | |
144 fprintf(stderr, | |
145 "warning: %s (index entry #%x): unexpected type %02X; skipping\n", | |
146 workpath, obj.entryno, obj.type); | |
147 continue; | |
148 } | |
149 } | |
150 } | |
151 | |
152 usage() | |
153 { | |
154 fprintf(stderr, "usage: mpffs-xtr [options] ffs-image destdir\n"); | |
155 exit(1); | |
156 } | |
157 | |
158 main(argc, argv) | |
159 char **argv; | |
160 { | |
161 extern int optind; | |
162 | |
163 parse_cmdline_options(argc, argv); | |
164 if (argc - optind != 2) | |
165 usage(); | |
166 imgfile = argv[optind]; | |
167 preliminaries(); | |
168 if (chdir(argv[optind+1]) < 0) { | |
169 perror(argv[optind+1]); | |
170 exit(1); | |
171 } | |
172 dump_dir(root.descend, 0); | |
173 exit(0); | |
174 } |