]> git.zerfleddert.de Git - rsbs2/blame - extract.c
add functions to reliably read files in the filesystem, to be used by the
[rsbs2] / extract.c
CommitLineData
1f1fa7b6
MG
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 "extract.h"
14
81a1093d
MG
15struct file_entry* get_next_file(unsigned char *fw, int len)
16{
17 static unsigned char *pos;
18 static unsigned char *end;
19 static struct file_entry fent;
20 int name_length;
21
22 if (fw != NULL && len != 0) {
23 pos = fw + 0x28;
24
25 printf("Start of filesystem: 0x%08x\n", *((unsigned int*)pos));
26 pos = fw + *((unsigned int*)pos);
27 end = fw + len;
28 }
29
30 fent.unknown = *pos;
31 pos++;
32
33 name_length = *((unsigned int*)pos);
34 pos += 4;
35
36 fent.length = *((unsigned int*)pos);
37 pos += 4;
38
39 if ((fent.length > (end - pos)) ||
40 (name_length > (end - pos))) {
41 printf("EOF reached\n");
42 return NULL;
43 }
44
45 fent.name = (char*)pos;
46 pos += name_length;
47
48 fent.start = pos;
49 pos += fent.length;
50
51 return &fent;
52}
53
1f1fa7b6
MG
54void extract_files(unsigned char *fw, int len)
55{
81a1093d 56 struct file_entry *fent;
358935b6 57
81a1093d
MG
58 fent = get_next_file(fw, len);
59
60 while (fent) {
358935b6 61 printf("%s: unknown: 0x%02x, length: %d",
81a1093d 62 fent->name, fent->unknown, fent->length);
1f1fa7b6 63
81a1093d
MG
64 if (fent->length > 0) {
65 write_file(fent->name, fent->start, fent->length);
66 if (*((unsigned int*)fent->start) == LZ_MAGIC) {
1f1fa7b6
MG
67 char *lzname;
68
81a1093d 69 if ((lzname = strdup(fent->name)) == NULL) {
1f1fa7b6
MG
70 perror("strdup");
71 exit(1);
72 }
73
74 if (!strcmp(lzname + strlen(lzname) - 4 , ".lz")) {
75 fprintf(stderr, "Ugh, can't derive filename...\n");
76 exit(1);
77 }
78 lzname[strlen(lzname) - 3] = 0x00;
79
80 printf("%s: packed file found", lzname);
81
81a1093d 82 extract_lz_file(fent->start, (unsigned char*)lzname);
1f1fa7b6 83 free(lzname);
81a1093d 84 } else if (!strcmp(fent->name, "firmware")) {
1f1fa7b6
MG
85 unsigned char *lzpos;
86 char lzname[128];
87
88 bzero(lzname, sizeof(lzname));
89 strcpy(lzname, "firmware.");
90
81a1093d 91 lzpos = fent->start + *((unsigned int*)(fent->start + 0x20));
1f1fa7b6
MG
92 memcpy(lzname + strlen(lzname), lzpos - 4, 4);
93 lzpos += 4;
94 if (*((unsigned int*)(lzpos)) == LZ_MAGIC) {
95 printf("%s: compressed firmware part found", lzname);
96 extract_lz_file(lzpos, (unsigned char*)lzname);
97 }
98 }
99 }
81a1093d 100 fent = get_next_file(NULL, 0);
1f1fa7b6
MG
101 }
102}
103
104void mkdir_p(char *dir)
105{
106 char *copy, *parent;
107
108 if ((dir == NULL) || (!strcmp(dir, ".")))
109 return;
110
111 if ((copy = strdup(dir)) == NULL) {
112 perror("strdup");
113 exit(1);
114 }
115 parent = dirname(copy);
116 mkdir_p(parent);
117
118 errno = 0;
119 if (mkdir(dir, 0755) == -1) {
120 if (errno != EEXIST) {
121 fprintf(stderr, "%s: ", dir);
122 perror("mkdir");
123 exit(1);
124 }
125 }
126 free(copy);
127}
128
129void write_file(char *fname, unsigned char *buf, int len)
130{
131 char filename[PATH_MAX];
132 char *filename_c, *dirn;
133 int fd;
134 int remaining;
135 int ret;
136
137 strcpy(filename, "extracted/");
138 strcat(filename, fname);
139
140 if ((filename_c = strdup(filename)) == NULL) {
141 perror("strdup");
142 exit(1);
143 }
144 dirn = dirname(filename_c);
145 mkdir_p(dirn);
146 free(filename_c);
147
148 if ((fd = open(filename, O_WRONLY|O_CREAT, 0644)) == -1) {
149 fprintf(stderr, "%s: ", filename);
150 perror("open");
151 exit(1);
152 }
153
154 remaining = len;
155
156 while(remaining) {
157 ret = write(fd, buf + (len - remaining), remaining);
158 if (ret < 0) {
159 perror("write");
160 exit(1);
161 }
162 remaining -= ret;
163 }
164
165 printf(", %s written.\n", filename);
166
167 close(fd);
168}
Impressum, Datenschutz