1 /*
2 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
3 *
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the
15 * distribution.
16 *
17 * Neither the name of Texas Instruments Incorporated nor the names of
18 * its contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <pch.h>
35 #include <tinfl.c>
36 #include "ziparchive.h"
37 #include "devicedb.h"
38
39 using namespace std;
40 using namespace TI::DLL430;
41 using namespace DeviceDb;
42
43
44 #pragma pack(push, 1)
45 struct LocalFileHeader
46 {
47 uint32_t signature;
48 uint16_t version;
49 uint16_t bitFlag;
50 uint16_t compression;
51 uint16_t modificationTime;
52 uint16_t modificationDate;
53 uint32_t crc;
54 uint32_t compressedSize;
55 uint32_t uncompressedSize;
56 uint16_t fileNameLength;
57 uint16_t extraFieldLength;
58 };
59
60 struct DirectoryFileHeader
61 {
62 uint32_t signature;
63 uint16_t versionMadeBy;
64 uint16_t versionNeeded;
65 uint16_t bitFlag;
66 uint16_t compression;
67 uint16_t modificationTime;
68 uint16_t modificationDate;
69 uint32_t crc;
70 uint32_t compressedSize;
71 uint32_t uncompressedSize;
72 uint16_t fileNameLength;
73 uint16_t extraFieldLength;
74 uint16_t fileCommentLength;
75 uint16_t diskNumberStart;
76 uint16_t internalFileAttributes;
77 uint32_t externalFileAttributes;
78 uint32_t offset;
79 };
80
81 struct EndOfDirectory
82 {
83 uint32_t signature;
84 uint16_t diskNumber;
85 uint16_t directoryStartDisk;
86 uint16_t entriesOnDisk;
87 uint16_t totalEntries;
88 uint32_t directorySize;
89 uint32_t directoryOffset;
90 uint16_t commentLength;
91 };
92 #pragma pack(pop)
93
94
open(const string & filename,bool usefile)95 void Archive::open(const string& filename, bool usefile)
96 {
97 useFile = usefile;
98
99 EndOfDirectory endOfDir;
100 uint8_t * pzip = &g_database[0];
101
102 if (useFile)
103 {
104 file.open(filename, ios::binary | ios::in);
105 if (!file)
106 {
107 throw runtime_error("failed to open archive");
108 }
109 file.seekg(-(int)sizeof(endOfDir), ios::end);
110 file.read((char*)&endOfDir, sizeof(endOfDir));
111 }
112 else
113 {
114 memcpy(&endOfDir, &TI::DLL430::DeviceDb::g_database[sizeof(TI::DLL430::DeviceDb::g_database) - sizeof(endOfDir)], sizeof(endOfDir));
115 }
116
117 if (endOfDir.signature != 0x06054b50)
118 {
119 throw runtime_error("no file comment allowed");
120 }
121
122 if (useFile)
123 {
124 file.seekg(endOfDir.directoryOffset, ios::beg);
125 }
126 else
127 {
128 pzip = pzip + endOfDir.directoryOffset;
129 }
130
131 DirectoryFileHeader header;
132
133 const uint16_t supportedCompressions[] = {0, 8, 9};
134
135 for (int i = 0; i < endOfDir.totalEntries; ++i)
136 {
137 if (useFile)
138 {
139 file.read((char*)&header, sizeof(header));
140 }
141 else
142 {
143 memcpy(&header, pzip, sizeof(header));
144 pzip = pzip + sizeof(header);
145 }
146
147 const uint16_t* endComp = end(supportedCompressions);
148 if (find(begin(supportedCompressions), endComp, header.compression) == endComp)
149 throw runtime_error("compression type not supported (only deflate/deflate64)");
150
151 if (header.bitFlag & 0xfff9)
152 throw runtime_error("unsupported option (encrypted?)");
153
154 vector<char> name(header.fileNameLength);
155 if (useFile)
156 {
157 file.read(name.data(), name.size());
158 }
159 else
160 {
161 memcpy(name.data(), pzip, name.size());
162 pzip = pzip + name.size();
163 }
164 if (header.compressedSize > 0)
165 {
166 string n(name.data(), name.size());
167 size_t pos = n.find_last_of("/") + 1;
168 directory[n.substr(pos)] = header.offset;
169 }
170 if (useFile)
171 {
172 file.seekg(header.extraFieldLength + header.fileCommentLength, ios::cur);
173 }
174 else
175 {
176 pzip = pzip + header.extraFieldLength + header.fileCommentLength;
177 }
178 }
179 }
180
readFile(const string & filename,vector<char> * dst) const181 void Archive::readFile(const string& filename, vector<char>* dst) const
182 {
183 const auto it = directory.find(filename);
184 if (it == directory.end())
185 throw runtime_error("file does not exist");
186
187 const uint32_t offset = it->second;
188 uint8_t * pzip = &g_database[0];
189 if (useFile)
190 {
191 file.seekg(offset, ios::beg);
192 }
193 else
194 {
195 pzip = pzip + offset;
196 }
197
198 LocalFileHeader header;
199 if (useFile)
200 {
201 file.read((char*)&header, sizeof(header));
202 }
203 else
204 {
205 memcpy(&header, pzip, sizeof(header));
206 pzip = pzip + sizeof(header);
207 }
208
209 if (useFile)
210 {
211 file.seekg(header.fileNameLength + header.extraFieldLength, ios::cur);
212 }
213 else
214 {
215 dst->resize(header.uncompressedSize);
216 pzip = pzip + header.fileNameLength + header.extraFieldLength;
217 }
218
219 if (header.compression != 0)
220 {
221 vector<unsigned char> compressedData(header.compressedSize);
222 if (useFile)
223 {
224 file.read((char*)compressedData.data(), compressedData.size());
225 }
226 else
227 {
228 memcpy(compressedData.data(), pzip, compressedData.size());
229 }
230 size_t uncompressed = tinfl_decompress_mem_to_mem(dst->data(), dst->size(), compressedData.data(), compressedData.size(), 0);
231 if (uncompressed != header.uncompressedSize)
232 {
233 throw runtime_error("error decompressing data");
234 }
235 }
236 else
237 {
238 if (useFile)
239 {
240 file.read(dst->data(), dst->size());
241 }
242 else
243 {
244 memcpy(dst->data(), pzip, dst->size());
245 pzip = pzip + dst->size();
246 }
247 }
248 }
249
250
getFileList(vector<string> * list) const251 void Archive::getFileList(vector<string>* list) const
252 {
253 for (const auto& it : directory)
254 {
255 if (it.first.rfind(".xml") != string::npos)
256 list->push_back(it.first);
257 }
258 }
259