• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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