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