]> git.zerfleddert.de Git - rsbs2/blob - filesystem.c
d4b207e7b8b5cca78e86a9c82f6b72dc83ec48e0
[rsbs2] / filesystem.c
1 #include <sys/stat.h>
2 #include <sys/types.h>
3 #include <limits.h>
4 #include <fcntl.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <strings.h>
8 #include <string.h>
9 #include <unistd.h>
10 #include <errno.h>
11 #include <libgen.h>
12 #include "rsb-lz.h"
13 #include "filesystem.h"
14
15 struct file_entry* get_next_file(unsigned char *fw, int len)
16 {
17 static unsigned char *pos;
18 static unsigned char *start;
19 static unsigned char *end;
20 static struct file_entry fent;
21 int name_length;
22
23 if (fw != NULL && len != 0) {
24 pos = fw + 0x28;
25
26 #if 0
27 printf("Start of filesystem: 0x%08x\n", *((unsigned int*)pos));
28 #endif
29 start = fw;
30 pos = fw + *((unsigned int*)pos);
31 end = fw + len;
32 }
33
34 fent.unknown = *pos;
35 pos++;
36
37 if (fent.unknown == 0x00) {
38 /* EOF */
39 int fill = (4 - ((pos - start) % 4)) % 4;
40 int i;
41
42 for (i = 0; i < fill; i++) {
43 if (*pos != 0xff) {
44 fprintf(stderr, "Wrong fill byte after EOF: 0x%02x, aborting!\n", *pos);
45 exit(1);
46 }
47 pos++;
48 }
49
50 if (pos != end) {
51 fprintf(stderr, "EOF marker not at end-of-file %p <-> %p, aborting!\n", pos, end);
52 exit(1);
53 }
54
55 return NULL;
56 }
57
58
59 name_length = *((unsigned int*)pos);
60 pos += 4;
61
62 fent.length = *((unsigned int*)pos);
63 pos += 4;
64
65 if ((fent.length > (end - pos)) ||
66 (name_length > (end - pos))) {
67 printf("EOF reached without hitting EOF marker, aborting "
68 "(unknown: 0x%02x, namelen: 0x%08x, contentlen: 0x%08x!\n",
69 fent.unknown, name_length, fent.length);
70 exit(1);
71 }
72
73 fent.name = (char*)pos;
74 pos += name_length;
75
76 fent.start = pos;
77 pos += fent.length;
78
79 return &fent;
80 }
81
82 void extract_files(unsigned char *fw, int len)
83 {
84 struct file_entry *fent;
85
86 fent = get_next_file(fw, len);
87
88 while (fent) {
89 printf("%s: unknown: 0x%02x, length: %d, ",
90 fent->name, fent->unknown, fent->length);
91
92 if (fent->length > 0) {
93 write_file(extracted_file(fent->name), fent->start, fent->length);
94 if (*((unsigned int*)fent->start) == LZ_MAGIC) {
95 char *lzname;
96
97 if ((lzname = strdup(fent->name)) == NULL) {
98 perror("strdup");
99 exit(1);
100 }
101
102 if (!strcmp(lzname + strlen(lzname) - 4 , ".lz")) {
103 fprintf(stderr, "Ugh, can't derive filename...\n");
104 exit(1);
105 }
106 lzname[strlen(lzname) - 3] = 0x00;
107
108 printf("%s: packed file found, ", lzname);
109
110 extract_lz_file(fent->start, (unsigned char*)lzname, 0);
111 free(lzname);
112 } else if (!strcmp(fent->name, "firmware")) {
113 unsigned char *lzpos;
114 char lzname[128];
115
116 bzero(lzname, sizeof(lzname));
117 strcpy(lzname, "firmware.");
118
119 lzpos = fent->start + *((unsigned int*)(fent->start + 0x20));
120 memcpy(lzname + strlen(lzname), lzpos - 4, 4);
121 lzpos += 4;
122 if (*((unsigned int*)(lzpos)) == LZ_MAGIC) {
123 printf("%s: compressed firmware part found, ", lzname);
124 extract_lz_file(lzpos, (unsigned char*)lzname, 1);
125 }
126 }
127 } else {
128 printf(", ignoring...\n");
129 }
130 fent = get_next_file(NULL, 0);
131 }
132 }
133
134 void replace_add_file(unsigned char *fw, int len, char *fwname, char *lname)
135 {
136 fprintf(stderr, "%s: Implement me!\n", __func__);
137 exit(1);
138 }
139
140 void list_files(unsigned char *fw, int len)
141 {
142 struct file_entry *fent;
143
144 for (fent = get_next_file(fw, len); fent != NULL; fent = get_next_file(NULL, 0)) {
145 printf("0x%x %8d %s\n", fent->unknown, fent->length, fent->name);
146 }
147
148 }
149
150 void mkdir_p(char *dir)
151 {
152 char *copy, *parent;
153
154 if ((dir == NULL) || (!strcmp(dir, ".")))
155 return;
156
157 if ((copy = strdup(dir)) == NULL) {
158 perror("strdup");
159 exit(1);
160 }
161 parent = dirname(copy);
162 mkdir_p(parent);
163
164 errno = 0;
165 if (mkdir(dir, 0755) == -1) {
166 if (errno != EEXIST) {
167 fprintf(stderr, "%s: ", dir);
168 perror("mkdir");
169 exit(1);
170 }
171 }
172 free(copy);
173 }
174
175 void write_file(char *fname, unsigned char *buf, int len)
176 {
177 char *filename_c, *dirn;
178 int fd;
179 int remaining;
180 int ret;
181
182 if ((filename_c = strdup(fname)) == NULL) {
183 perror("strdup");
184 exit(1);
185 }
186 dirn = dirname(filename_c);
187 mkdir_p(dirn);
188 free(filename_c);
189
190 if ((fd = open(fname, O_WRONLY|O_CREAT, 0644)) == -1) {
191 fprintf(stderr, "%s: ", fname);
192 perror("open");
193 exit(1);
194 }
195
196 remaining = len;
197
198 while(remaining) {
199 ret = write(fd, buf + (len - remaining), remaining);
200 if (ret < 0) {
201 perror("write");
202 exit(1);
203 }
204 remaining -= ret;
205 }
206
207 printf("%s written.\n", fname);
208
209 close(fd);
210 }
211
212 char *extracted_file(char *fname)
213 {
214 static char filename[PATH_MAX];
215
216 strcpy(filename, "extracted/");
217 strcat(filename, fname);
218
219 return filename;
220 }
Impressum, Datenschutz