1 /*
2 * Copyright (c) 2021-2024 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/package_parser.h"
17
18 #include <algorithm>
19 #include <climits>
20 #include <regex>
21 #include <sstream>
22
23 #include "file_entry.h"
24 #include "resconfig_parser.h"
25 #include "resource_pack.h"
26 #include "resource_util.h"
27 #include "select_compile_parse.h"
28
29 namespace OHOS {
30 namespace Global {
31 namespace Restool {
32 using namespace std;
33 const struct option PackageParser::CMD_OPTS[] = {
34 { "inputPath", required_argument, nullptr, Option::INPUTPATH },
35 { "packageName", required_argument, nullptr, Option::PACKAGENAME },
36 { "outputPath", required_argument, nullptr, Option::OUTPUTPATH },
37 { "resHeader", required_argument, nullptr, Option::RESHEADER },
38 { "forceWrite", no_argument, nullptr, Option::FORCEWRITE },
39 { "version", no_argument, nullptr, Option::VERSION},
40 { "modules", required_argument, nullptr, Option::MODULES },
41 { "json", required_argument, nullptr, Option::JSON },
42 { "startId", required_argument, nullptr, Option::STARTID },
43 { "fileList", required_argument, nullptr, Option::FILELIST },
44 { "append", required_argument, nullptr, Option::APPEND },
45 { "combine", required_argument, nullptr, Option::COMBINE },
46 { "dependEntry", required_argument, nullptr, Option::DEPENDENTRY },
47 { "help", no_argument, nullptr, Option::HELP},
48 { "ids", required_argument, nullptr, Option::IDS},
49 { "defined-ids", required_argument, nullptr, Option::DEFINED_IDS},
50 { "icon-check", no_argument, nullptr, Option::ICON_CHECK},
51 { "target-config", required_argument, nullptr, Option::TARGET_CONFIG},
52 { "defined-sysids", required_argument, nullptr, Option::DEFINED_SYSIDS},
53 { "compressed-config", required_argument, nullptr, Option::COMPRESSED_CONFIG},
54 { "thread", required_argument, nullptr, Option::THREAD},
55 { "ignored-file", required_argument, nullptr, Option::IGNORED_FILE},
56 { 0, 0, 0, 0},
57 };
58
59 const string PackageParser::CMD_PARAMS = ":i:p:o:r:m:j:e:l:x:fhvz";
60
Parse(int argc,char * argv[])61 uint32_t PackageParser::Parse(int argc, char *argv[])
62 {
63 InitCommand();
64 if (ParseCommand(argc, argv) != RESTOOL_SUCCESS) {
65 return RESTOOL_ERROR;
66 }
67 if (CheckParam() != RESTOOL_SUCCESS) {
68 return RESTOOL_ERROR;
69 }
70 AdaptResourcesDirForInput();
71 return RESTOOL_SUCCESS;
72 }
73
GetInputs() const74 const vector<string> &PackageParser::GetInputs() const
75 {
76 return inputs_;
77 }
78
GetPackageName() const79 const string &PackageParser::GetPackageName() const
80 {
81 return packageName_;
82 }
83
GetOutput() const84 const string &PackageParser::GetOutput() const
85 {
86 return output_;
87 }
88
GetResourceHeaders() const89 const vector<string> &PackageParser::GetResourceHeaders() const
90 {
91 return resourceHeaderPaths_;
92 }
93
GetForceWrite() const94 bool PackageParser::GetForceWrite() const
95 {
96 return forceWrite_;
97 }
98
GetModuleNames() const99 const vector<string> &PackageParser::GetModuleNames() const
100 {
101 return moduleNames_;
102 }
103
GetConfig() const104 const string &PackageParser::GetConfig() const
105 {
106 return configPath_;
107 }
108
GetRestoolPath() const109 const string &PackageParser::GetRestoolPath() const
110 {
111 return restoolPath_;
112 }
113
GetStartId() const114 uint32_t PackageParser::GetStartId() const
115 {
116 return startId_;
117 }
118
GetDependEntry() const119 const string &PackageParser::GetDependEntry() const
120 {
121 return dependEntry_;
122 }
123
GetSysIdDefinedPaths() const124 const vector<std::string> &PackageParser::GetSysIdDefinedPaths() const
125 {
126 return sysIdDefinedPaths_;
127 }
128
AddInput(const string & argValue)129 uint32_t PackageParser::AddInput(const string& argValue)
130 {
131 string inputPath = ResourceUtil::RealPath(argValue);
132 if (inputPath.empty()) {
133 PrintError(GetError(ERR_CODE_INVALID_INPUT).FormatCause(argValue.c_str()));
134 return RESTOOL_ERROR;
135 }
136
137 auto ret = find_if(inputs_.begin(), inputs_.end(), [inputPath](auto iter) {return inputPath == iter;});
138 if (ret != inputs_.end()) {
139 PrintError(GetError(ERR_CODE_DUPLICATE_INPUT).FormatCause(argValue.c_str()));
140 return RESTOOL_ERROR;
141 }
142
143 if (!IsAscii(inputPath)) {
144 return RESTOOL_ERROR;
145 }
146
147 if (IsOverlapInput(inputPath)) {
148 inputs_.emplace(inputs_.begin(), inputPath);
149 } else {
150 inputs_.push_back(inputPath);
151 }
152 return RESTOOL_SUCCESS;
153 }
154
IsOverlapInput(const string & inputPath)155 bool PackageParser::IsOverlapInput(const string& inputPath)
156 {
157 if (isOverlap_) {
158 return false;
159 }
160
161 string indexPath = FileEntry::FilePath(inputPath).Append(RESOURCE_INDEX_FILE).GetPath();
162 if (ResourceUtil::FileExist(indexPath)) {
163 isOverlap_ = true;
164 return true;
165 }
166
167 string jsonIndexPath = ResourceUtil::GetMainPath(inputPath).Append(RESOURCE_INDEX_FILE).GetPath();
168 string txtResHeaderPath = ResourceUtil::GetMainPath(inputPath).Append("ResourceTable.txt").GetPath();
169 string jsResHeaderPath = ResourceUtil::GetMainPath(inputPath).Append("ResourceTable.js").GetPath();
170 string hResJsHeaderPath = ResourceUtil::GetMainPath(inputPath).Append("ResourceTable.h").GetPath();
171 if (ResourceUtil::FileExist(jsonIndexPath) &&
172 !ResourceUtil::FileExist(txtResHeaderPath) &&
173 !ResourceUtil::FileExist(jsResHeaderPath) &&
174 !ResourceUtil::FileExist(hResJsHeaderPath)) {
175 isOverlap_ = true;
176 return true;
177 }
178
179 return false;
180 }
181
AddSysIdDefined(const std::string & argValue)182 uint32_t PackageParser::AddSysIdDefined(const std::string& argValue)
183 {
184 string sysIdDefinedPath = ResourceUtil::RealPath(argValue);
185 if (sysIdDefinedPath.empty()) {
186 PrintError(GetError(ERR_CODE_INVALID_SYSTEM_ID_DEFINED).FormatCause(argValue.c_str()));
187 return RESTOOL_ERROR;
188 }
189
190 auto ret = find_if(sysIdDefinedPaths_.begin(), sysIdDefinedPaths_.end(),
191 [sysIdDefinedPath](auto iter) {return sysIdDefinedPath == iter;});
192 if (ret != sysIdDefinedPaths_.end()) {
193 PrintError(GetError(ERR_CODE_DUPLICATE_SYSTEM_ID_DEFINED).FormatCause(argValue.c_str()));
194 return RESTOOL_ERROR;
195 }
196
197 if (!IsAscii(sysIdDefinedPath)) {
198 return RESTOOL_ERROR;
199 }
200 sysIdDefinedPaths_.push_back(sysIdDefinedPath);
201 return RESTOOL_SUCCESS;
202 }
203
AddPackageName(const string & argValue)204 uint32_t PackageParser::AddPackageName(const string& argValue)
205 {
206 if (!packageName_.empty()) {
207 PrintError(GetError(ERR_CODE_DOUBLE_PACKAGE_NAME).FormatCause(packageName_.c_str(), argValue.c_str()));
208 return RESTOOL_ERROR;
209 }
210
211 packageName_ = argValue;
212 return RESTOOL_SUCCESS;
213 }
214
AddOutput(const string & argValue)215 uint32_t PackageParser::AddOutput(const string& argValue)
216 {
217 if (!output_.empty()) {
218 PrintError(GetError(ERR_CODE_DOUBLE_OUTPUT).FormatCause(output_.c_str(), argValue.c_str()));
219 return RESTOOL_ERROR;
220 }
221
222 output_ = ResourceUtil::RealPath(argValue);
223 if (output_.empty()) {
224 PrintError(GetError(ERR_CODE_INVALID_OUTPUT).FormatCause(argValue.c_str()));
225 return RESTOOL_ERROR;
226 }
227 if (!IsAscii(output_)) {
228 return RESTOOL_ERROR;
229 }
230 return RESTOOL_SUCCESS;
231 }
232
AddResourceHeader(const string & argValue)233 uint32_t PackageParser::AddResourceHeader(const string &argValue)
234 {
235 if (find(resourceHeaderPaths_.begin(), resourceHeaderPaths_.end(), argValue) != resourceHeaderPaths_.end()) {
236 PrintError(GetError(ERR_CODE_DUPLICATE_RES_HEADER).FormatCause(argValue.c_str()));
237 return RESTOOL_ERROR;
238 }
239 resourceHeaderPaths_.push_back(argValue);
240 return RESTOOL_SUCCESS;
241 }
242
ForceWrite()243 uint32_t PackageParser::ForceWrite()
244 {
245 forceWrite_ = true;
246 return RESTOOL_SUCCESS;
247 }
248
PrintVersion()249 uint32_t PackageParser::PrintVersion()
250 {
251 std::string restoolVersion = RESTOOL_NAME + RESTOOL_VERSION;
252 cout << "Info: Restool version = " << restoolVersion << endl;
253 exit(RESTOOL_SUCCESS);
254 return RESTOOL_SUCCESS;
255 }
256
AddMoudleNames(const string & argValue)257 uint32_t PackageParser::AddMoudleNames(const string& argValue)
258 {
259 if (!moduleNames_.empty()) {
260 std::string existModuleNames;
261 for (const auto &module : moduleNames_) { existModuleNames.append(module).append(","); }
262 existModuleNames.pop_back();
263 PrintError(GetError(ERR_CODE_DOUBLE_MODULES).FormatCause(existModuleNames.c_str(), argValue.c_str()));
264 return RESTOOL_ERROR;
265 }
266
267 ResourceUtil::Split(argValue, moduleNames_, ",");
268 for (auto it = moduleNames_.begin(); it != moduleNames_.end(); it++) {
269 auto ret = find_if(moduleNames_.begin(), moduleNames_.end(), [it](auto iter) {return *it == iter;});
270 if (ret != it) {
271 PrintError(GetError(ERR_CODE_DUPLICATE_MODULE_NAME).FormatCause(it->c_str()));
272 return RESTOOL_ERROR;
273 }
274 }
275 return RESTOOL_SUCCESS;
276 }
277
AddConfig(const string & argValue)278 uint32_t PackageParser::AddConfig(const string& argValue)
279 {
280 if (!configPath_.empty()) {
281 PrintError(GetError(ERR_CODE_DOUBLE_CONFIG_JSON).FormatCause(configPath_.c_str(), argValue.c_str()));
282 return RESTOOL_ERROR;
283 }
284
285 configPath_ = argValue;
286 return RESTOOL_SUCCESS;
287 }
288
AddStartId(const string & argValue)289 uint32_t PackageParser::AddStartId(const string& argValue)
290 {
291 char *end;
292 errno = 0;
293 long long id = static_cast<long long>(strtoll(argValue.c_str(), &end, 16)); // 16 is hexadecimal number
294 if (end == argValue.c_str() || errno == ERANGE || *end != '\0' || id == LLONG_MAX || id == LLONG_MIN) {
295 PrintError(GetError(ERR_CODE_INVALID_START_ID).FormatCause(argValue.c_str()));
296 return RESTOOL_ERROR;
297 }
298 if (id <= 0) {
299 PrintError(GetError(ERR_CODE_INVALID_START_ID).FormatCause(argValue.c_str()));
300 return RESTOOL_ERROR;
301 }
302 if ((id >= 0x01000000 && id < 0x06ffffff) || (id >= 0x08000000 && id < 0xffffffff)) {
303 startId_ = static_cast<uint32_t>(id);
304 return RESTOOL_SUCCESS;
305 }
306 PrintError(GetError(ERR_CODE_INVALID_START_ID).FormatCause(argValue.c_str()));
307 return RESTOOL_ERROR;
308 }
309
310 // -i input directory, add the resource directory
AdaptResourcesDirForInput()311 void PackageParser::AdaptResourcesDirForInput()
312 {
313 if (!isFileList_ && !combine_) { // -l and increment compile -i, no need to add resource directory
314 for (auto &path : inputs_) {
315 path = FileEntry::FilePath(path).Append(RESOURCES_DIR).GetPath();
316 }
317 }
318 }
319
CheckParam() const320 uint32_t PackageParser::CheckParam() const
321 {
322 if (inputs_.empty() && append_.empty()) {
323 PrintError(GetError(ERR_CODE_INVALID_INPUT).FormatCause(""));
324 return RESTOOL_ERROR;
325 }
326
327 if (output_.empty()) {
328 PrintError(GetError(ERR_CODE_INVALID_OUTPUT).FormatCause(""));
329 return RESTOOL_ERROR;
330 }
331
332 if (isTargetConfig_ && !append_.empty()) {
333 PrintError(GetError(ERR_CODE_EXCLUSIVE_OPTION).FormatCause("-x", "--target-config"));
334 return RESTOOL_ERROR;
335 }
336
337 if (!append_.empty()) {
338 return RESTOOL_SUCCESS;
339 }
340
341 if (packageName_.empty()) {
342 PrintError(ERR_CODE_PACKAGE_NAME_EMPTY);
343 return RESTOOL_ERROR;
344 }
345
346 if (resourceHeaderPaths_.empty()) {
347 PrintError(ERR_CODE_RES_HEADER_PATH_EMPTY);
348 return RESTOOL_ERROR;
349 }
350
351 if (startId_ != 0 && !idDefinedInputPath_.empty()) {
352 PrintError(GetError(ERR_CODE_EXCLUSIVE_OPTION).FormatCause("-e", "--defined-ids"));
353 return RESTOOL_ERROR;
354 }
355
356 return RESTOOL_SUCCESS;
357 }
358
IsFileList() const359 bool PackageParser::IsFileList() const
360 {
361 return isFileList_;
362 }
363
AddAppend(const string & argValue)364 uint32_t PackageParser::AddAppend(const string& argValue)
365 {
366 string appendPath = ResourceUtil::RealPath(argValue);
367 if (appendPath.empty()) {
368 cout << "Warning: invalid compress '" << argValue << "'" << endl;
369 appendPath = argValue;
370 }
371 auto ret = find_if(append_.begin(), append_.end(), [appendPath](auto iter) {return appendPath == iter;});
372 if (ret != append_.end()) {
373 PrintError(GetError(ERR_CODE_DUPLICATE_APPEND_PATH).FormatCause(argValue.c_str()));
374 return RESTOOL_ERROR;
375 }
376 if (!IsAscii(appendPath)) {
377 return RESTOOL_ERROR;
378 }
379 append_.push_back(appendPath);
380 return RESTOOL_SUCCESS;
381 }
382
GetAppend() const383 const vector<string> &PackageParser::GetAppend() const
384 {
385 return append_;
386 }
387
SetCombine()388 uint32_t PackageParser::SetCombine()
389 {
390 combine_ = true;
391 return RESTOOL_SUCCESS;
392 }
393
GetCombine() const394 bool PackageParser::GetCombine() const
395 {
396 return combine_;
397 }
398
AddDependEntry(const string & argValue)399 uint32_t PackageParser::AddDependEntry(const string& argValue)
400 {
401 dependEntry_ = argValue;
402 return RESTOOL_SUCCESS;
403 }
404
ShowHelp() const405 uint32_t PackageParser::ShowHelp() const
406 {
407 auto &parser = CmdParser::GetInstance();
408 parser.ShowUseage();
409 exit(RESTOOL_SUCCESS);
410 return RESTOOL_SUCCESS;
411 }
412
SetIdDefinedOutput(const string & argValue)413 uint32_t PackageParser::SetIdDefinedOutput(const string& argValue)
414 {
415 idDefinedOutput_ = argValue;
416 return RESTOOL_SUCCESS;
417 }
418
GetIdDefinedOutput() const419 const string &PackageParser::GetIdDefinedOutput() const
420 {
421 return idDefinedOutput_;
422 }
423
SetIdDefinedInputPath(const string & argValue)424 uint32_t PackageParser::SetIdDefinedInputPath(const string& argValue)
425 {
426 idDefinedInputPath_ = argValue;
427 return RESTOOL_SUCCESS;
428 }
429
GetIdDefinedInputPath() const430 const string &PackageParser::GetIdDefinedInputPath() const
431 {
432 return idDefinedInputPath_;
433 }
434
IconCheck()435 uint32_t PackageParser::IconCheck()
436 {
437 isIconCheck_ = true;
438 return RESTOOL_SUCCESS;
439 }
440
GetIconCheck() const441 bool PackageParser::GetIconCheck() const
442 {
443 return isIconCheck_;
444 }
445
ParseTargetConfig(const string & argValue)446 uint32_t PackageParser::ParseTargetConfig(const string& argValue)
447 {
448 if (isTargetConfig_) {
449 PrintError(GetError(ERR_CODE_DOUBLE_TARGET_CONFIG).FormatCause(targetConfigValue_.c_str(), argValue.c_str()));
450 return RESTOOL_ERROR;
451 }
452 if (!SelectCompileParse::ParseTargetConfig(argValue, targetConfig_)) {
453 PrintError(GetError(ERR_CODE_INVALID_TARGET_CONFIG).FormatCause(argValue.c_str()));
454 return RESTOOL_ERROR;
455 }
456 isTargetConfig_ = true;
457 targetConfigValue_ = argValue;
458 return RESTOOL_SUCCESS;
459 }
460
ParseThread(const std::string & argValue)461 uint32_t PackageParser::ParseThread(const std::string &argValue)
462 {
463 if (argValue.empty()) {
464 return RESTOOL_SUCCESS;
465 }
466 char *end;
467 errno = 0;
468 int count = static_cast<int>(strtol(argValue.c_str(), &end, 10));
469 if (end == argValue.c_str() || errno == ERANGE || *end != '\0' || count == INT_MIN || count == INT_MAX) {
470 PrintError(GetError(ERR_CODE_INVALID_THREAD_COUNT).FormatCause(argValue.c_str()));
471 return RESTOOL_ERROR;
472 }
473 if (count <= 0) {
474 PrintError(GetError(ERR_CODE_INVALID_THREAD_COUNT).FormatCause(argValue.c_str()));
475 return RESTOOL_ERROR;
476 }
477 threadCount_ = static_cast<size_t>(count);
478 return RESTOOL_SUCCESS;
479 }
480
ParseIgnoreFileRegex(const std::string & argValue)481 uint32_t PackageParser::ParseIgnoreFileRegex(const std::string &argValue)
482 {
483 std::stringstream in(argValue);
484 std::string regex;
485 ResourceUtil::SetUseCustomIgnoreRegex(true);
486 while (getline(in, regex, ':')) {
487 bool isSucceed = ResourceUtil::AddIgnoreFileRegex(regex, IgnoreType::IGNORE_ALL);
488 if (!isSucceed) {
489 return RESTOOL_ERROR;
490 }
491 }
492 return RESTOOL_SUCCESS;
493 }
494
GetThreadCount() const495 size_t PackageParser::GetThreadCount() const
496 {
497 return threadCount_;
498 }
499
GetTargetConfigValues() const500 const TargetConfig &PackageParser::GetTargetConfigValues() const
501 {
502 return targetConfig_;
503 }
504
IsTargetConfig() const505 bool PackageParser::IsTargetConfig() const
506 {
507 return isTargetConfig_;
508 }
509
IsAscii(const string & argValue) const510 bool PackageParser::IsAscii(const string& argValue) const
511 {
512 #ifdef __WIN32
513 auto result = find_if(argValue.begin(), argValue.end(), [](auto iter) {
514 if ((iter & 0x80) != 0) {
515 return true;
516 }
517 return false;
518 });
519 if (result != argValue.end()) {
520 PrintError(GetError(ERR_CODE_NON_ASCII).FormatCause(argValue.c_str()));
521 return false;
522 }
523 #endif
524 return true;
525 }
526
AddCompressionPath(const std::string & argValue)527 uint32_t PackageParser::AddCompressionPath(const std::string& argValue)
528 {
529 if (!compressionPath_.empty()) {
530 PrintError(GetError(ERR_CODE_DOUBLE_COMPRESSION_PATH).FormatCause(compressionPath_.c_str(), argValue.c_str()));
531 return RESTOOL_ERROR;
532 }
533 compressionPath_ = argValue;
534 return RESTOOL_SUCCESS;
535 }
536
GetCompressionPath() const537 const std::string &PackageParser::GetCompressionPath() const
538 {
539 return compressionPath_;
540 }
541
IsOverlap() const542 bool PackageParser::IsOverlap() const
543 {
544 return isOverlap_;
545 }
546
InitCommand()547 void PackageParser::InitCommand()
548 {
549 using namespace placeholders;
550 handles_.emplace(Option::INPUTPATH, bind(&PackageParser::AddInput, this, _1));
551 handles_.emplace(Option::PACKAGENAME, bind(&PackageParser::AddPackageName, this, _1));
552 handles_.emplace(Option::OUTPUTPATH, bind(&PackageParser::AddOutput, this, _1));
553 handles_.emplace(Option::RESHEADER, bind(&PackageParser::AddResourceHeader, this, _1));
554 handles_.emplace(Option::FORCEWRITE, [this](const string &) -> uint32_t { return ForceWrite(); });
555 handles_.emplace(Option::VERSION, [this](const string &) -> uint32_t { return PrintVersion(); });
556 handles_.emplace(Option::MODULES, bind(&PackageParser::AddMoudleNames, this, _1));
557 handles_.emplace(Option::JSON, bind(&PackageParser::AddConfig, this, _1));
558 handles_.emplace(Option::STARTID, bind(&PackageParser::AddStartId, this, _1));
559 handles_.emplace(Option::APPEND, bind(&PackageParser::AddAppend, this, _1));
560 handles_.emplace(Option::COMBINE, [this](const string &) -> uint32_t { return SetCombine(); });
561 handles_.emplace(Option::DEPENDENTRY, bind(&PackageParser::AddDependEntry, this, _1));
562 handles_.emplace(Option::HELP, [this](const string &) -> uint32_t { return ShowHelp(); });
563 handles_.emplace(Option::IDS, bind(&PackageParser::SetIdDefinedOutput, this, _1));
564 handles_.emplace(Option::DEFINED_IDS, bind(&PackageParser::SetIdDefinedInputPath, this, _1));
565 handles_.emplace(Option::ICON_CHECK, [this](const string &) -> uint32_t { return IconCheck(); });
566 handles_.emplace(Option::TARGET_CONFIG, bind(&PackageParser::ParseTargetConfig, this, _1));
567 handles_.emplace(Option::DEFINED_SYSIDS, bind(&PackageParser::AddSysIdDefined, this, _1));
568 handles_.emplace(Option::COMPRESSED_CONFIG, bind(&PackageParser::AddCompressionPath, this, _1));
569 handles_.emplace(Option::THREAD, bind(&PackageParser::ParseThread, this, _1));
570 handles_.emplace(Option::IGNORED_FILE, bind(&PackageParser::ParseIgnoreFileRegex, this, _1));
571 }
572
HandleProcess(int c,const string & argValue)573 uint32_t PackageParser::HandleProcess(int c, const string &argValue)
574 {
575 auto handler = handles_.find(c);
576 if (handler == handles_.end()) {
577 PrintError(GetError(ERR_CODE_UNKNOWN_OPTION).FormatCause(std::to_string(c).c_str()));
578 return RESTOOL_ERROR;
579 }
580 return handler->second(argValue);
581 }
582
ParseFileList(const string & fileListPath)583 uint32_t PackageParser::ParseFileList(const string& fileListPath)
584 {
585 isFileList_ = true;
586 ResConfigParser resConfigParser;
587 if (resConfigParser.Init(fileListPath, [this](int c, const string &argValue) -> uint32_t {
588 return HandleProcess(c, argValue);
589 }) != RESTOOL_SUCCESS) {
590 return RESTOOL_ERROR;
591 }
592 return RESTOOL_SUCCESS;
593 }
594
CheckError(int argc,char * argv[],int c,int optIndex)595 uint32_t PackageParser::CheckError(int argc, char *argv[], int c, int optIndex)
596 {
597 if (optIndex != -1) {
598 if ((optarg == nullptr && (optind - 1 < 0 || optind - 1 >= argc)) ||
599 (optarg != nullptr && (optind - 2 < 0 || optind - 2 >= argc))) { // 1 or 2 menas optind offset value
600 return RESTOOL_ERROR;
601 }
602 string curOpt = (optarg == nullptr) ? argv[optind - 1] : argv[optind - 2];
603 if (curOpt != ("--" + string(CMD_OPTS[optIndex].name))) {
604 PrintError(GetError(ERR_CODE_UNKNOWN_OPTION).FormatCause(curOpt.c_str()));
605 return RESTOOL_ERROR;
606 }
607 }
608 if (c == Option::UNKNOWN) {
609 if (optopt == 0 && (optind - 1 < 0 || optind - 1 >= argc)) {
610 return RESTOOL_ERROR;
611 }
612 string optUnknown = (optopt == 0) ? argv[optind - 1] : ("-" + string(1, optopt));
613 PrintError(GetError(ERR_CODE_UNKNOWN_OPTION).FormatCause(optUnknown.c_str()));
614 return RESTOOL_ERROR;
615 }
616 if (c == Option::NO_ARGUMENT) {
617 if (optind - 1 < 0 || optind - 1 >= argc) {
618 return RESTOOL_ERROR;
619 }
620 if (IsLongOpt(argc, argv)) {
621 PrintError(GetError(ERR_CODE_MISSING_ARGUMENT).FormatCause(argv[optind - 1]));
622 } else {
623 PrintError(GetError(ERR_CODE_UNKNOWN_OPTION).FormatCause(argv[optind - 1]));
624 }
625 return RESTOOL_ERROR;
626 }
627 return RESTOOL_SUCCESS;
628 }
629
ParseCommand(int argc,char * argv[])630 uint32_t PackageParser::ParseCommand(int argc, char *argv[])
631 {
632 restoolPath_ = string(argv[0]);
633 while (optind <= argc) {
634 int optIndex = -1;
635 int c = getopt_long(argc, argv, CMD_PARAMS.c_str(), CMD_OPTS, &optIndex);
636 if (CheckError(argc, argv, c, optIndex) != RESTOOL_SUCCESS) {
637 return RESTOOL_ERROR;
638 }
639 if (c == Option::END) {
640 if (argc == optind) {
641 break;
642 }
643 string errmsg;
644 for (int i = optind; i < argc; i++) {
645 errmsg.append(argv[i]).append(",");
646 }
647 errmsg.pop_back();
648 PrintError(GetError(ERR_CODE_INVALID_ARGUMENT).FormatCause(errmsg.c_str()));
649 return RESTOOL_ERROR;
650 }
651
652 string argValue = (optarg != nullptr) ? optarg : "";
653 if (c == Option::FILELIST) {
654 return ParseFileList(argValue);
655 }
656 if (HandleProcess(c, argValue) != RESTOOL_SUCCESS) {
657 return RESTOOL_ERROR;
658 }
659 }
660 return RESTOOL_SUCCESS;
661 }
662
IsLongOpt(int argc,char * argv[]) const663 bool PackageParser::IsLongOpt(int argc, char *argv[]) const
664 {
665 if (optind - 1 < 0 || optind - 1 >= argc) {
666 return false;
667 }
668 for (auto iter : CMD_OPTS) {
669 if (optopt == iter.val && argv[optind - 1] == ("--" + string(iter.name))) {
670 return true;
671 }
672 }
673 return false;
674 }
675
ExecCommand()676 uint32_t PackageParser::ExecCommand()
677 {
678 return ResourcePack(*this).Package();
679 }
680 }
681 }
682 }
683