• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, Option::INPUTPATH },
27     { "packageName", required_argument, nullptr, Option::PACKAGENAME },
28     { "outputPath", required_argument, nullptr, Option::OUTPUTPATH },
29     { "resHeader", required_argument, nullptr, Option::RESHEADER },
30     { "forceWrite", no_argument, nullptr, Option::FORCEWRITE },
31     { "version", no_argument, nullptr, Option::VERSION},
32     { "modules", required_argument, nullptr, Option::MODULES },
33     { "json", required_argument, nullptr, Option::JSON },
34     { "startId", required_argument, nullptr, Option::STARTID },
35     { "fileList", required_argument, nullptr, Option::FILELIST },
36     { "append", required_argument, nullptr, Option::APPEND },
37     { "combine", required_argument, nullptr, Option::COMBINE },
38     { "dependEntry", required_argument, nullptr, Option::DEPENDENTRY },
39     { "help", no_argument, nullptr, Option::HELP},
40     { "ids", required_argument, nullptr, Option::IDS},
41     { "defined-ids", required_argument, nullptr, Option::DEFINED_IDS},
42     { "icon-check", no_argument, nullptr, Option::ICON_CHECK},
43     { 0, 0, 0, 0},
44 };
45 
46 const string PackageParser::CMD_PARAMS = ":i:p:o:r:m:j:e:l:x:fhvz";
47 
Parse(int argc,char * argv[])48 uint32_t PackageParser::Parse(int argc, char *argv[])
49 {
50     InitCommand();
51     if (ParseCommand(argc, argv) != RESTOOL_SUCCESS) {
52         return RESTOOL_ERROR;
53     }
54     if (CheckParam() != RESTOOL_SUCCESS) {
55         return RESTOOL_ERROR;
56     }
57     AdaptResourcesDirForInput();
58     return RESTOOL_SUCCESS;
59 }
60 
GetInputs() const61 const vector<string> &PackageParser::GetInputs() const
62 {
63     return inputs_;
64 }
65 
GetPackageName() const66 const string &PackageParser::GetPackageName() const
67 {
68     return packageName_;
69 }
70 
GetOutput() const71 const string &PackageParser::GetOutput() const
72 {
73     return output_;
74 }
75 
GetResourceHeaders() const76 const vector<string> &PackageParser::GetResourceHeaders() const
77 {
78     return resourceHeaderPaths_;
79 }
80 
GetForceWrite() const81 bool PackageParser::GetForceWrite() const
82 {
83     return forceWrite_;
84 }
85 
GetModuleNames() const86 const vector<string> &PackageParser::GetModuleNames() const
87 {
88     return moduleNames_;
89 }
90 
GetConfig() const91 const string &PackageParser::GetConfig() const
92 {
93     return configPath_;
94 }
95 
GetRestoolPath() const96 const string &PackageParser::GetRestoolPath() const
97 {
98     return restoolPath_;
99 }
100 
GetStartId() const101 int32_t PackageParser::GetStartId() const
102 {
103     return startId_;
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 
223 // -i input directory, add the resource directory
AdaptResourcesDirForInput()224 void PackageParser::AdaptResourcesDirForInput()
225 {
226     if (!isFileList_ && !combine_) { // -l and increment compile -i, no need to add resource directory
227         for (auto &path : inputs_) {
228             path = FileEntry::FilePath(path).Append(RESOURCES_DIR).GetPath();
229         }
230     }
231 }
232 
CheckParam() const233 uint32_t PackageParser::CheckParam() const
234 {
235     if (inputs_.empty() && append_.empty()) {
236         cerr << "Error: input path empty." << endl;
237         return RESTOOL_ERROR;
238     }
239 
240     if (output_.empty()) {
241         cerr << "Error: output path empty." << endl;
242         return RESTOOL_ERROR;
243     }
244 
245     if (!append_.empty()) {
246         return RESTOOL_SUCCESS;
247     }
248     if (packageName_.empty()) {
249         cerr << "Error: package name empty." << endl;
250         return RESTOOL_ERROR;
251     }
252 
253     if (resourceHeaderPaths_.empty()) {
254         cerr << "Error: resource header path empty." << endl;
255         return RESTOOL_ERROR;
256     }
257 
258     if (startId_ != 0 && !idDefinedInputPath_.empty()) {
259         cerr << "Error: set -e and --defined-ids cannot be used together." << endl;
260         return RESTOOL_ERROR;
261     }
262 
263     return RESTOOL_SUCCESS;
264 }
265 
IsFileList() const266 bool PackageParser::IsFileList() const
267 {
268     return isFileList_;
269 }
270 
AddAppend(const string & argValue)271 uint32_t PackageParser::AddAppend(const string& argValue)
272 {
273     string appendPath = ResourceUtil::RealPath(argValue);
274     if (appendPath.empty()) {
275         cout << "Warning: invaild compress '" << argValue << "'" << endl;
276         appendPath = argValue;
277     }
278     auto ret = find_if(append_.begin(), append_.end(), [appendPath](auto iter) {return appendPath == iter;});
279     if (ret != append_.end()) {
280         cerr << "Error: repeat input '" << argValue << "'" << endl;
281         return RESTOOL_ERROR;
282     }
283     if (!IsAscii(appendPath)) {
284         return RESTOOL_ERROR;
285     }
286     append_.push_back(appendPath);
287     return RESTOOL_SUCCESS;
288 }
289 
GetAppend() const290 const vector<string> &PackageParser::GetAppend() const
291 {
292     return append_;
293 }
294 
SetCombine()295 uint32_t PackageParser::SetCombine()
296 {
297     combine_ = true;
298     return RESTOOL_SUCCESS;
299 }
300 
GetCombine() const301 bool PackageParser::GetCombine() const
302 {
303     return combine_;
304 }
305 
AddDependEntry(const string & argValue)306 uint32_t PackageParser::AddDependEntry(const string& argValue)
307 {
308     dependEntry_ = argValue;
309     return RESTOOL_SUCCESS;
310 }
311 
ShowHelp() const312 uint32_t PackageParser::ShowHelp() const
313 {
314     auto &parser = CmdParser<PackageParser>::GetInstance();
315     parser.ShowUseage();
316     exit(RESTOOL_SUCCESS);
317     return RESTOOL_SUCCESS;
318 }
319 
SetIdDefinedOutput(const string & argValue)320 uint32_t PackageParser::SetIdDefinedOutput(const string& argValue)
321 {
322     idDefinedOutput_ = argValue;
323     return RESTOOL_SUCCESS;
324 }
325 
GetIdDefinedOutput() const326 const string &PackageParser::GetIdDefinedOutput() const
327 {
328     return idDefinedOutput_;
329 }
330 
SetIdDefinedInputPath(const string & argValue)331 uint32_t PackageParser::SetIdDefinedInputPath(const string& argValue)
332 {
333     idDefinedInputPath_ = argValue;
334     return RESTOOL_SUCCESS;
335 }
336 
GetIdDefinedInputPath() const337 const string &PackageParser::GetIdDefinedInputPath() const
338 {
339     return idDefinedInputPath_;
340 }
341 
IconCheck()342 uint32_t PackageParser::IconCheck()
343 {
344     isIconCheck_ = true;
345     return RESTOOL_SUCCESS;
346 }
347 
GetIconCheck() const348 bool PackageParser::GetIconCheck() const
349 {
350     return isIconCheck_;
351 }
352 
IsAscii(const string & argValue) const353 bool PackageParser::IsAscii(const string& argValue) const
354 {
355 #ifdef __WIN32
356     auto result = find_if(argValue.begin(), argValue.end(), [](auto iter) {
357         if ((iter & 0x80) != 0) {
358             return true;
359         }
360         return false;
361     });
362     if (result != argValue.end()) {
363         cerr << "Error: '" << argValue << "' must be ASCII" << endl;
364         return false;
365     }
366 #endif
367     return true;
368 }
369 
InitCommand()370 void PackageParser::InitCommand()
371 {
372     using namespace placeholders;
373     handles_.emplace(Option::INPUTPATH, bind(&PackageParser::AddInput, this, _1));
374     handles_.emplace(Option::PACKAGENAME, bind(&PackageParser::AddPackageName, this, _1));
375     handles_.emplace(Option::OUTPUTPATH, bind(&PackageParser::AddOutput, this, _1));
376     handles_.emplace(Option::RESHEADER, bind(&PackageParser::AddResourceHeader, this, _1));
377     handles_.emplace(Option::FORCEWRITE, [this](const string &) -> uint32_t { return ForceWrite(); });
378     handles_.emplace(Option::VERSION, [this](const string &) -> uint32_t { return PrintVersion(); });
379     handles_.emplace(Option::MODULES, bind(&PackageParser::AddMoudleNames, this, _1));
380     handles_.emplace(Option::JSON, bind(&PackageParser::AddConfig, this,  _1));
381     handles_.emplace(Option::STARTID, bind(&PackageParser::AddStartId, this, _1));
382     handles_.emplace(Option::APPEND, bind(&PackageParser::AddAppend, this, _1));
383     handles_.emplace(Option::COMBINE, [this](const string &) -> uint32_t { return SetCombine(); });
384     handles_.emplace(Option::DEPENDENTRY, bind(&PackageParser::AddDependEntry, this, _1));
385     handles_.emplace(Option::HELP, [this](const string &) -> uint32_t { return ShowHelp(); });
386     handles_.emplace(Option::IDS, bind(&PackageParser::SetIdDefinedOutput, this, _1));
387     handles_.emplace(Option::DEFINED_IDS, bind(&PackageParser::SetIdDefinedInputPath, this, _1));
388     handles_.emplace(Option::ICON_CHECK, [this](const string &) -> uint32_t { return IconCheck(); });
389 }
390 
HandleProcess(int c,const string & argValue)391 uint32_t PackageParser::HandleProcess(int c, const string& argValue)
392 {
393     auto handler = handles_.find(c);
394     if (handler == handles_.end()) {
395         cout << "Error: unsupport " << c << endl;
396         return RESTOOL_ERROR;
397     }
398     return handler->second(argValue);
399 }
400 
ParseFileList(const string & fileListPath)401 uint32_t PackageParser::ParseFileList(const string& fileListPath)
402 {
403     isFileList_ = true;
404     CmdList cmdList;
405     if (cmdList.Init(fileListPath, [this](int c, const string &argValue) -> int32_t {
406         return HandleProcess(c, argValue);
407     }) != RESTOOL_SUCCESS) {
408         return RESTOOL_ERROR;
409     }
410     return RESTOOL_SUCCESS;
411 }
412 
ParseCommand(int argc,char * argv[])413 uint32_t PackageParser::ParseCommand(int argc, char *argv[])
414 {
415     restoolPath_ = string(argv[0]);
416     while (true) {
417         int optIndex = -1;
418         opterr = 0;
419         int c = getopt_long(argc, argv, CMD_PARAMS.c_str(), CMD_OPTS, &optIndex);
420         if (optIndex != -1) {
421             string curOpt = (optarg == nullptr) ? argv[optind - 1] : argv[optind - 2];
422             if (curOpt != ("--" + string(CMD_OPTS[optIndex].name))) {
423                 cout << "Error: unknown option " << curOpt << endl;
424                 return RESTOOL_ERROR;
425             }
426         }
427         if (c == Option::END) {
428             if (argc == optind) {
429                 break;
430             }
431             string errmsg = "Error: invalid arguments : ";
432             for (int i = optind; i < argc; i++) {
433                 errmsg.append(argv[i]).append(" ");
434             }
435             cout << errmsg << endl;
436             return RESTOOL_ERROR;
437         }
438         if (c == Option::UNKNOWN) {
439             string optUnknown = (optopt == 0) ? argv[optind - 1] : ("-" + string(1, optopt));
440             cout << "Error: unknown option " << optUnknown << endl;
441             return RESTOOL_ERROR;
442         }
443         if (c == Option::NO_ARGUMENT) {
444             if (IsLongOpt(argv)) {
445                 cout << "Error: option " << argv[optind - 1] << " must have argument" << endl;
446             } else {
447                 cout << "Error: unknown option " << argv[optind - 1] << endl;
448             }
449             return RESTOOL_ERROR;
450         }
451         string argValue = (optarg != nullptr) ? optarg : "";
452         if (c == Option::FILELIST) {
453             return ParseFileList(argValue);
454         }
455         if (HandleProcess(c, argValue) != RESTOOL_SUCCESS) {
456             return RESTOOL_ERROR;
457         }
458     }
459     return RESTOOL_SUCCESS;
460 }
461 
IsLongOpt(char * argv[]) const462 bool PackageParser::IsLongOpt(char *argv[]) const
463 {
464     for (auto iter : CMD_OPTS) {
465         if (optopt == iter.val && argv[optind - 1] == ("--" + string(iter.name))) {
466             return true;
467         }
468     }
469     return false;
470 }
471 }
472 }
473 }
474