|
1 /* |
|
2 * Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Handling of sis files |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include "appdep.hpp" |
|
20 |
|
21 // ---------------------------------------------------------------------------------------------------------- |
|
22 // Note that in C/C++ code \ has been replaced with \\ and " with \". |
|
23 // ---------------------------------------------------------------------------------------------------------- |
|
24 |
|
25 void DoInitialChecksAndPreparationsForSisFiles() |
|
26 { |
|
27 // specify full location for dumpsis |
|
28 _dumpsis_location = _cl_releasedir + DUMPSIS_LOCATION; |
|
29 |
|
30 // check if dumpsis can be found |
|
31 if (!FileExists(_dumpsis_location)) |
|
32 { |
|
33 cerr << "ERROR: Unable to find " + _dumpsis_location << ", check -release param" << endl; |
|
34 cerr << "Please notice that this feature is available only in Symbian OS 9.x" << endl; |
|
35 cerr << "It is possible the user to copy dumpsis.exe from some other release under" << endl; |
|
36 cerr << "this release to support this feature." << endl; |
|
37 exit(EXIT_DUMPSIS_NOT_FOUND); |
|
38 } |
|
39 |
|
40 // insert quotes to the dumpsis location to avoid any problems caused by white spaces |
|
41 InsertQuotesToFilePath(_dumpsis_location); |
|
42 |
|
43 // parse commandline argument "sisfiles" from sisfile;sisfile;... |
|
44 int last_found_semicolon_pos = -1; |
|
45 for (unsigned int i=0; i<_cl_sisfiles.length(); i++) |
|
46 { |
|
47 // try to find ';' characters |
|
48 string::size_type semicolon_pos = _cl_sisfiles.find(";", i); |
|
49 |
|
50 if (semicolon_pos == string::npos) |
|
51 { |
|
52 // could not find the ';' character, append last part of the list |
|
53 string sis_file = _cl_sisfiles.substr(last_found_semicolon_pos+1,_cl_sisfiles.length()-last_found_semicolon_pos-1); |
|
54 _sisfiles.push_back(sis_file); |
|
55 break; |
|
56 } |
|
57 else |
|
58 { |
|
59 // found a ';' character, append to the list, but needs to check if there are more |
|
60 string sis_file = _cl_sisfiles.substr(last_found_semicolon_pos+1, semicolon_pos-last_found_semicolon_pos-1); |
|
61 |
|
62 if (sis_file.length() > 0) |
|
63 _sisfiles.push_back(sis_file); |
|
64 |
|
65 last_found_semicolon_pos = semicolon_pos; |
|
66 i = last_found_semicolon_pos; |
|
67 } |
|
68 } |
|
69 |
|
70 // check that all given sisfiles can be found and it is supported |
|
71 for (unsigned int i=0; i<_sisfiles.size(); i++) |
|
72 { |
|
73 // report an error if the file does not exist |
|
74 if (!FileExists(_sisfiles.at(i))) |
|
75 { |
|
76 cerr << "ERROR: Unable to find " + _sisfiles.at(i) << ", check -sisfiles parameter" << endl; |
|
77 exit(EXIT_SIS_FILE_NOT_FOUND); |
|
78 } |
|
79 |
|
80 // open the sis file for reading to check if it is supported |
|
81 ifstream sisf(_sisfiles.at(i).c_str(), ios::binary); |
|
82 if (sisf.is_open()) |
|
83 { |
|
84 int c1, c2, c3, c4; |
|
85 c1 = sisf.get(); |
|
86 c2 = sisf.get(); |
|
87 c3 = sisf.get(); |
|
88 c4 = sisf.get(); |
|
89 |
|
90 // in valid sis first four bytes of the file are 7A1A2010 |
|
91 if (c1==0x7A && c2==0x1A && c3==0x20 && c4==0x10) |
|
92 { |
|
93 //cerr << _sisfiles.at(i) << " is supported" << endl; |
|
94 } |
|
95 else |
|
96 { |
|
97 // if starting from offset 8, four next bytes are 19040010, the file is |
|
98 // unsupported SIS file used in previous Symbian OS releases. |
|
99 sisf.seekg(8, ios::beg); |
|
100 c1 = sisf.get(); |
|
101 c2 = sisf.get(); |
|
102 c3 = sisf.get(); |
|
103 c4 = sisf.get(); |
|
104 sisf.close(); |
|
105 |
|
106 if (c1==0x19 && c2==0x04 && c3==0x00 && c4==0x10) |
|
107 { |
|
108 cerr << "ERROR: " + _sisfiles.at(i) << " is a pre-Symbian OS 9.x" << endl; |
|
109 cerr << "sisfile which is not supported, check -sisfiles parameter" << endl; |
|
110 exit(EXIT_SIS_FILE_NOT_SUPPORTED); |
|
111 } |
|
112 else |
|
113 { |
|
114 cerr << "ERROR: " + _sisfiles.at(i) << " is not a valid sis file," << endl; |
|
115 cerr << "check -sisfiles parameter" << endl; |
|
116 exit(EXIT_NOT_SIS_FILE); |
|
117 } |
|
118 } |
|
119 sisf.close(); |
|
120 } |
|
121 else |
|
122 { |
|
123 cerr << "ERROR: Cannot open " + _sisfiles.at(i) << " for reading, check -sisfiles parameter" << endl; |
|
124 exit(EXIT_SIS_FILE_CANNOT_OPEN_FOR_READING); |
|
125 } |
|
126 } |
|
127 } |
|
128 |
|
129 // ---------------------------------------------------------------------------------------------------------- |
|
130 |
|
131 void AnalyseSisFiles() |
|
132 { |
|
133 // create a new target and set some defaults |
|
134 target sis_target; |
|
135 sis_target.name = "sis"; |
|
136 sis_target.cache_dir = _cl_cachedir + sis_target.name + DIR_SEPARATOR; |
|
137 sis_target.dep_cache_path = sis_target.cache_dir + CACHE_DEP_FILENAME; |
|
138 |
|
139 cerr << "Analysing sis files..." << endl; |
|
140 |
|
141 // define path to a temp directory where dumpsis will extract the files |
|
142 const string tempdir = _cl_cachedir + SIS_TEMP_DIR + DIR_SEPARATOR; |
|
143 const string tempdir2 = _cl_cachedir + SIS_TEMP_DIR; |
|
144 |
|
145 // do analysis for each file |
|
146 for (unsigned int i=0; i<_sisfiles.size(); i++) |
|
147 { |
|
148 // create the temporary directory |
|
149 MkDirAll(tempdir); |
|
150 |
|
151 cerr << "Binaries in " << _sisfiles.at(i) << " are:" << endl; |
|
152 |
|
153 // due to bugginess of a specific version of dumpsis, we need to copy the source file under the temporary directory |
|
154 const string new_sis_loc = tempdir + "tempsis.sis"; |
|
155 |
|
156 ifstream src_sis_f(_sisfiles.at(i).c_str(), ios::binary); |
|
157 if (src_sis_f.is_open()) |
|
158 { |
|
159 ofstream trgt_sis_f(new_sis_loc.c_str(), ios::binary); |
|
160 if (trgt_sis_f.is_open()) |
|
161 { |
|
162 // read all bytes from source and write to the target |
|
163 int c1; |
|
164 |
|
165 while(!src_sis_f.eof()) |
|
166 { |
|
167 c1 = src_sis_f.get(); |
|
168 trgt_sis_f.put(c1); |
|
169 } |
|
170 |
|
171 trgt_sis_f.close(); |
|
172 |
|
173 } |
|
174 else |
|
175 { |
|
176 cerr << "ERROR: Cannot open " + new_sis_loc << " for writing, check write permissions" << endl; |
|
177 exit(EXIT_TEMP_SIS_FILE_CANNOT_OPEN_FOR_WRITING); |
|
178 } |
|
179 |
|
180 src_sis_f.close(); |
|
181 |
|
182 } |
|
183 else |
|
184 { |
|
185 cerr << "ERROR: Cannot open " + _sisfiles.at(i) << " for reading, check -sisfiles parameter" << endl; |
|
186 exit(EXIT_SIS_FILE_CANNOT_OPEN_FOR_READING); |
|
187 } |
|
188 |
|
189 |
|
190 |
|
191 // execute dumpsis |
|
192 string cmd = _dumpsis_location + " -x -d \"" + tempdir2 + "\" \"" + new_sis_loc + "\" " + CERR_TO_NULL; |
|
193 |
|
194 vector<string> tempVector; |
|
195 ExecuteCommand(cmd, tempVector); |
|
196 |
|
197 |
|
198 // check if pkg file found |
|
199 string pkgfile_location = tempdir + "tempsis.pkg"; |
|
200 |
|
201 if (!FileExists(pkgfile_location)) |
|
202 { |
|
203 // try again with an alternative |
|
204 pkgfile_location = tempdir + "tempsis.sis.pkg"; |
|
205 |
|
206 if (!FileExists(pkgfile_location)) |
|
207 { |
|
208 RemoveDirectoryWithAllFiles(tempdir); |
|
209 cerr << "ERROR: Dumpsis failed for " << _sisfiles.at(i) << " since it does not contain a pkg file, check -sisfiles parameter" << endl; |
|
210 exit(EXIT_NO_PKG_FILE_FOUND); |
|
211 } |
|
212 } |
|
213 |
|
214 // open the pkg file for reading |
|
215 ifstream pkgf(pkgfile_location.c_str(), ios::binary); |
|
216 if (pkgf.is_open()) |
|
217 { |
|
218 int c1, c2; |
|
219 c1 = pkgf.get(); |
|
220 c2 = pkgf.get(); |
|
221 |
|
222 // we only support unicode format |
|
223 if (c1 == 0xFF && c2 == 0xFE) |
|
224 { |
|
225 string line; |
|
226 |
|
227 // read more chars |
|
228 while(!pkgf.eof()) |
|
229 { |
|
230 c1 = pkgf.get(); |
|
231 c2 = pkgf.get(); |
|
232 |
|
233 // if (c1 == 0x0D && c2 == 0x00) // new line marker #1 |
|
234 // { |
|
235 // c1 = pkgf.get(); |
|
236 // c2 = pkgf.get(); |
|
237 |
|
238 if (c1 == 0x0A && c2 == 0x00) // new line marker #2 |
|
239 { |
|
240 // full line is now available, parse it |
|
241 |
|
242 boost::regex re1("^\\\"(.+)\\\"-\\\".*\\\\(\\S+)\\\",.*$"); |
|
243 boost::cmatch matches1; |
|
244 if (boost::regex_match(line.c_str(), matches1, re1)) |
|
245 { |
|
246 // match found |
|
247 string ms1(matches1[1].first, matches1[1].second); // source name |
|
248 string ms2(matches1[2].first, matches1[2].second); // target name |
|
249 |
|
250 binary_info b_info; |
|
251 b_info.directory = tempdir; |
|
252 b_info.filename = ms1; |
|
253 |
|
254 GetImportTableWithPetran(_petran_location, b_info); |
|
255 |
|
256 // make sure that Petran succeeded for this file since we don't do any file |
|
257 // extension checks when parsering the file |
|
258 if (b_info.binary_format != UNKNOWN) |
|
259 { |
|
260 // print name of the destination binary |
|
261 cerr << ms2 << endl; |
|
262 |
|
263 b_info.directory = ""; |
|
264 b_info.filename = ms2; |
|
265 |
|
266 // get statistics of the file and set the modification time |
|
267 struct stat stat_p; |
|
268 stat((tempdir + ms1).c_str(), &stat_p); |
|
269 b_info.mod_time = stat_p.st_mtime; |
|
270 |
|
271 // create a new entry to list of binary files |
|
272 sis_target.binaries.push_back( b_info ); |
|
273 } |
|
274 |
|
275 } |
|
276 |
|
277 // clear the buffer since we start scanning another line |
|
278 line = ""; |
|
279 } |
|
280 //} |
|
281 else |
|
282 { |
|
283 char c(c1); // simple unicode to ascii conversion, just ignore c2 |
|
284 line += c; // append the char to end of the line |
|
285 } |
|
286 } |
|
287 } |
|
288 else |
|
289 { |
|
290 pkgf.close(); |
|
291 RemoveDirectoryWithAllFiles(tempdir); |
|
292 cerr << "ERROR: Pkg file " + pkgfile_location << " is not supported, check -sisfiles parameter" << endl; |
|
293 exit(EXIT_PKG_FILE_CANNOT_OPEN_FOR_READING); |
|
294 } |
|
295 |
|
296 } |
|
297 else |
|
298 { |
|
299 RemoveDirectoryWithAllFiles(tempdir); |
|
300 cerr << "ERROR: Cannot open " + pkgfile_location << " for reading, check -sisfiles parameter" << endl; |
|
301 exit(EXIT_PKG_FILE_CANNOT_OPEN_FOR_READING); |
|
302 } |
|
303 |
|
304 // close handles and clear any temp files |
|
305 pkgf.close(); |
|
306 RemoveDirectoryWithAllFiles(tempdir); |
|
307 } |
|
308 |
|
309 // make sure that the cache directory exists |
|
310 MkDirAll(sis_target.cache_dir); |
|
311 |
|
312 // write the dependencies cache of the sis files |
|
313 WriteDataToDependenciesCacheFile(sis_target); |
|
314 |
|
315 // append to targets |
|
316 _targets.push_back(sis_target); |
|
317 |
|
318 cerr << endl; |
|
319 |
|
320 } |
|
321 |
|
322 // ---------------------------------------------------------------------------------------------------------- |
|
323 |
|
324 |