1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "cmd_parser.h"
17 #include<algorithm>
18 #include "cmd_list.h"
19 #include "resource_util.h"
20
21 namespace OHOS {
22 namespace Global {
23 namespace Restool {
24 using namespace std;
25 const struct option PackageParser::CMD_OPTS[] = {
26 { "inputPath", required_argument, nullptr, 'i' },
27 { "packageName", required_argument, nullptr, 'p' },
28 { "outputPath", required_argument, nullptr, 'o' },
29 { "resHeader", required_argument, nullptr, 'r' },
30 { "forceWrite", no_argument, nullptr, 'f' },
31 { "version", no_argument, nullptr, 'v'},
32 { "modules", optional_argument, nullptr, 'm' },
33 { "json", optional_argument, nullptr, 'j' },
34 { "startId", optional_argument, nullptr, 'e' },
35 { "cache", optional_argument, nullptr, 'c' },
36 { "fileList", required_argument, nullptr, 'l' },
37 { "preview", no_argument, nullptr, 'a' },
38 { "priority", required_argument, nullptr, 'g' },
39 { "append", required_argument, nullptr, 'x' },
40 { "combine", required_argument, nullptr, 'z' },
41 { "dependEntry", required_argument, nullptr, 'd' },
42 { "help", no_argument, nullptr, 'h'},
43 };
44
45 const string PackageParser::CMD_PARAMS = "i:p:o:r:m:j:e:c:l:g:x:d:afhvz";
46
Parse(int argc,char * argv[])47 uint32_t PackageParser::Parse(int argc, char *argv[])
48 {
49 InitCommand();
50 if (ParseCommand(argc, argv) != RESTOOL_SUCCESS) {
51 return RESTOOL_ERROR;
52 }
53 return CheckParam();
54 }
55
GetInputs() const56 const vector<string> &PackageParser::GetInputs() const
57 {
58 return inputs_;
59 }
60
GetPackageName() const61 const string &PackageParser::GetPackageName() const
62 {
63 return packageName_;
64 }
65
GetOutput() const66 const string &PackageParser::GetOutput() const
67 {
68 return output_;
69 }
70
GetResourceHeaders() const71 const vector<string> &PackageParser::GetResourceHeaders() const
72 {
73 return resourceHeaderPaths_;
74 }
75
GetForceWrite() const76 bool PackageParser::GetForceWrite() const
77 {
78 return forceWrite_;
79 }
80
GetModuleNames() const81 const vector<string> &PackageParser::GetModuleNames() const
82 {
83 return moduleNames_;
84 }
85
GetConfig() const86 const string &PackageParser::GetConfig() const
87 {
88 return configPath_;
89 }
90
GetRestoolPath() const91 const string &PackageParser::GetRestoolPath() const
92 {
93 return restoolPath_;
94 }
95
GetStartId() const96 int32_t PackageParser::GetStartId() const
97 {
98 return startId_;
99 }
100
GetCachePath() const101 const string &PackageParser::GetCachePath() const
102 {
103 return cachePath_;
104 }
105
GetDependEntry() const106 const string &PackageParser::GetDependEntry() const
107 {
108 return dependEntry_;
109 }
110
AddInput(const string & argValue)111 uint32_t PackageParser::AddInput(const string& argValue)
112 {
113 string inputPath = ResourceUtil::RealPath(argValue);
114 if (inputPath.empty()) {
115 cerr << "Error: invalid input '" << argValue << "'" << endl;
116 return RESTOOL_ERROR;
117 }
118
119 auto ret = find_if(inputs_.begin(), inputs_.end(), [inputPath](auto iter) {return inputPath == iter;});
120 if (ret != inputs_.end()) {
121 cerr << "Error: repeat input '" << argValue << "'" << endl;
122 return RESTOOL_ERROR;
123 }
124
125 if (!IsAscii(inputPath)) {
126 return RESTOOL_ERROR;
127 }
128 inputs_.push_back(inputPath);
129 return RESTOOL_SUCCESS;
130 }
131
AddPackageName(const string & argValue)132 uint32_t PackageParser::AddPackageName(const string& argValue)
133 {
134 if (!packageName_.empty()) {
135 cerr << "Error: double package name " << packageName_ << " vs " << argValue << endl;
136 return RESTOOL_ERROR;
137 }
138
139 packageName_ = argValue;
140 return RESTOOL_SUCCESS;
141 }
142
AddOutput(const string & argValue)143 uint32_t PackageParser::AddOutput(const string& argValue)
144 {
145 if (!output_.empty()) {
146 cerr << "Error: double output " << output_ << " vs " << argValue << endl;
147 return RESTOOL_ERROR;
148 }
149
150 output_ = ResourceUtil::RealPath(argValue);
151 if (output_.empty()) {
152 cerr << "Error: invalid output '" << argValue << "'" << endl;
153 return RESTOOL_ERROR;
154 }
155 if (!IsAscii(output_)) {
156 return RESTOOL_ERROR;
157 }
158 return RESTOOL_SUCCESS;
159 }
160
AddResourceHeader(const string & argValue)161 uint32_t PackageParser::AddResourceHeader(const string& argValue)
162 {
163 if (find(resourceHeaderPaths_.begin(), resourceHeaderPaths_.end(), argValue) != resourceHeaderPaths_.end()) {
164 cerr << "Error: '" << argValue << "' input duplicated." << endl;
165 return RESTOOL_ERROR;
166 }
167 resourceHeaderPaths_.push_back(argValue);
168 return RESTOOL_SUCCESS;
169 }
170
ForceWrite()171 uint32_t PackageParser::ForceWrite()
172 {
173 forceWrite_ = true;
174 return RESTOOL_SUCCESS;
175 }
176
PrintVersion()177 uint32_t PackageParser::PrintVersion()
178 {
179 cout << "Info: Restool version= " << RESTOOL_VERSION << endl;
180 exit(RESTOOL_SUCCESS);
181 return RESTOOL_SUCCESS;
182 }
183
AddMoudleNames(const string & argValue)184 uint32_t PackageParser::AddMoudleNames(const string& argValue)
185 {
186 if (!moduleNames_.empty()) {
187 cerr << "Error: -m double module name '" << argValue << "'" << endl;
188 return RESTOOL_ERROR;
189 }
190
191 ResourceUtil::Split(argValue, moduleNames_, ",");
192 for (auto it = moduleNames_.begin(); it != moduleNames_.end(); it++) {
193 auto ret = find_if(moduleNames_.begin(), moduleNames_.end(), [it](auto iter) {return *it == iter;});
194 if (ret != it) {
195 cerr << "Error: double module name '" << *it << "'" << endl;
196 return RESTOOL_ERROR;
197 }
198 }
199 return RESTOOL_SUCCESS;
200 }
201
AddConfig(const string & argValue)202 uint32_t PackageParser::AddConfig(const string& argValue)
203 {
204 if (!configPath_.empty()) {
205 cerr << "Error: double config.json " << configPath_ << " vs " << argValue << endl;
206 return RESTOOL_ERROR;
207 }
208
209 configPath_ = argValue;
210 return RESTOOL_SUCCESS;
211 }
212
AddStartId(const string & argValue)213 uint32_t PackageParser::AddStartId(const string& argValue)
214 {
215 startId_ = strtol(argValue.c_str(), nullptr, 16); // 16 is hexadecimal number
216 if ((startId_ >= 0x01000000 && startId_ < 0x06ffffff) || (startId_ >= 0x08000000 && startId_ < 0x41ffffff)) {
217 return RESTOOL_SUCCESS;
218 }
219 cerr << "Error: invalid start id " << argValue << endl;
220 return RESTOOL_ERROR;
221 }
222
AddCachePath(const string & argValue)223 uint32_t PackageParser::AddCachePath(const string& argValue)
224 {
225 cachePath_ = argValue;
226 return RESTOOL_SUCCESS;
227 }
228
CheckParam() const229 uint32_t PackageParser::CheckParam() const
230 {
231 if (inputs_.empty() && append_.empty()) {
232 cerr << "Error: input path empty." << endl;
233 return RESTOOL_ERROR;
234 }
235
236 if (output_.empty()) {
237 cerr << "Error: output path empty." << endl;
238 return RESTOOL_ERROR;
239 }
240
241 if (previewMode_ || !append_.empty()) {
242 return RESTOOL_SUCCESS;
243 }
244 if (packageName_.empty()) {
245 cerr << "Error: package name empty." << endl;
246 return RESTOOL_ERROR;
247 }
248
249 if (resourceHeaderPaths_.empty()) {
250 cerr << "Error: resource header path empty." << endl;
251 return RESTOOL_ERROR;
252 }
253 return RESTOOL_SUCCESS;
254 }
255
IsFileList() const256 bool PackageParser::IsFileList() const
257 {
258 return isFileList_;
259 }
260
SetPreviewMode()261 uint32_t PackageParser::SetPreviewMode()
262 {
263 previewMode_ = true;
264 return RESTOOL_SUCCESS;
265 }
266
GetPreviewMode() const267 bool PackageParser::GetPreviewMode() const
268 {
269 return previewMode_;
270 }
271
GetPriority() const272 int32_t PackageParser::GetPriority() const
273 {
274 return priority_;
275 }
276
SetPriority(const string & argValue)277 uint32_t PackageParser::SetPriority(const string& argValue)
278 {
279 priority_ = atoi(argValue.c_str());
280 return RESTOOL_SUCCESS;
281 }
282
AddAppend(const string & argValue)283 uint32_t PackageParser::AddAppend(const string& argValue)
284 {
285 string appendPath = ResourceUtil::RealPath(argValue);
286 if (appendPath.empty()) {
287 cout << "Warning: invaild compress '" << argValue << "'" << endl;
288 appendPath = argValue;
289 }
290 auto ret = find_if(append_.begin(), append_.end(), [appendPath](auto iter) {return appendPath == iter;});
291 if (ret != append_.end()) {
292 cerr << "Error: repeat input '" << argValue << "'" << endl;
293 return RESTOOL_ERROR;
294 }
295 if (!IsAscii(appendPath)) {
296 return RESTOOL_ERROR;
297 }
298 append_.push_back(appendPath);
299 return RESTOOL_SUCCESS;
300 }
301
GetAppend() const302 const vector<string> &PackageParser::GetAppend() const
303 {
304 return append_;
305 }
306
SetCombine()307 uint32_t PackageParser::SetCombine()
308 {
309 combine_ = true;
310 return RESTOOL_SUCCESS;
311 }
312
GetCombine() const313 bool PackageParser::GetCombine() const
314 {
315 return combine_;
316 }
317
AddDependEntry(const string & argValue)318 uint32_t PackageParser::AddDependEntry(const string& argValue)
319 {
320 dependEntry_ = argValue;
321 return RESTOOL_SUCCESS;
322 }
323
ShowHelp() const324 uint32_t PackageParser::ShowHelp() const
325 {
326 auto &parser = CmdParser<PackageParser>::GetInstance();
327 parser.ShowUseage();
328 exit(RESTOOL_SUCCESS);
329 return RESTOOL_SUCCESS;
330 }
331
IsAscii(const string & argValue) const332 bool PackageParser::IsAscii(const string& argValue) const
333 {
334 #ifdef __WIN32
335 auto result = find_if(argValue.begin(), argValue.end(), [](auto iter) {
336 if ((iter & 0x80) != 0) {
337 return true;
338 }
339 return false;
340 });
341 if (result != argValue.end()) {
342 cerr << "Error: '" << argValue << "' must be ASCII" << endl;
343 return false;
344 }
345 #endif
346 return true;
347 }
348
InitCommand()349 void PackageParser::InitCommand()
350 {
351 using namespace placeholders;
352 handles_.emplace('i', bind(&PackageParser::AddInput, this, _1));
353 handles_.emplace('p', bind(&PackageParser::AddPackageName, this, _1));
354 handles_.emplace('o', bind(&PackageParser::AddOutput, this, _1));
355 handles_.emplace('r', bind(&PackageParser::AddResourceHeader, this, _1));
356 handles_.emplace('f', [this](const string &) -> uint32_t { return ForceWrite(); });
357 handles_.emplace('v', [this](const string &) -> uint32_t { return PrintVersion(); });
358 handles_.emplace('m', bind(&PackageParser::AddMoudleNames, this, _1));
359 handles_.emplace('j', bind(&PackageParser::AddConfig, this, _1));
360 handles_.emplace('e', bind(&PackageParser::AddStartId, this, _1));
361 handles_.emplace('c', bind(&PackageParser::AddCachePath, this, _1));
362 handles_.emplace('a', [this](const string &) -> uint32_t { return SetPreviewMode(); });
363 handles_.emplace('g', bind(&PackageParser::SetPriority, this, _1));
364 handles_.emplace('x', bind(&PackageParser::AddAppend, this, _1));
365 handles_.emplace('z', [this](const string &) -> uint32_t { return SetCombine(); });
366 handles_.emplace('d', bind(&PackageParser::AddDependEntry, this, _1));
367 handles_.emplace('h', [this](const string &) -> uint32_t { return ShowHelp(); });
368 }
369
HandleProcess(int c,const string & argValue)370 uint32_t PackageParser::HandleProcess(int c, const string& argValue)
371 {
372 auto handler = handles_.find(c);
373 if (handler == handles_.end()) {
374 cout << "Warning: unsupport " << c << endl;
375 return RESTOOL_SUCCESS;
376 }
377 return handler->second(argValue);
378 }
379
ParseFileList(const string & fileListPath)380 uint32_t PackageParser::ParseFileList(const string& fileListPath)
381 {
382 isFileList_ = true;
383 CmdList cmdList;
384 if (cmdList.Init(fileListPath, [this](int c, const string &argValue) -> int32_t {
385 return HandleProcess(c, argValue);
386 }) != RESTOOL_SUCCESS) {
387 return RESTOOL_ERROR;
388 }
389 return RESTOOL_SUCCESS;
390 }
391
ParseCommand(int argc,char * argv[])392 uint32_t PackageParser::ParseCommand(int argc, char *argv[])
393 {
394 restoolPath_ = string(argv[0]);
395 while (true) {
396 int optIndex = 0;
397 int c = getopt_long(argc, argv, CMD_PARAMS.c_str(), CMD_OPTS, &optIndex);
398 if (c == -1) {
399 break;
400 }
401
402 string argValue = (optarg != nullptr) ? optarg : "";
403 if (c == 'l') {
404 return ParseFileList(argValue);
405 }
406 if (HandleProcess(c, argValue) != RESTOOL_SUCCESS) {
407 return RESTOOL_ERROR;
408 }
409 }
410 return RESTOOL_SUCCESS;
411 }
412 }
413 }
414 }
415