1 /*
2 * Copyright (c) 2022-2023 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 "errors.h"
17 #include "tools_op.h"
18
19 #include <algorithm>
20 #include <cstddef>
21 #include <cstdio>
22 #include <getopt.h>
23 #include <iostream>
24 #include <optional>
25 #include <sstream>
26
27 namespace OHOS::FileManagement::Backup {
28 using namespace std;
29
GetArgsMap(int argc,char * const argv[],const vector<ToolsOp::CmdInfo> & argList)30 optional<map<string, vector<string>>> GetArgsMap(int argc, char *const argv[], const vector<ToolsOp::CmdInfo> &argList)
31 {
32 int i = 0;
33 map<int, string> mapOptToName;
34 vector<struct option> vecLongOptions;
35 for (auto &&arg : argList) {
36 mapOptToName[i] = arg.paramName;
37 vecLongOptions.emplace_back(option {
38 .name = arg.paramName.c_str(),
39 .has_arg = required_argument,
40 .flag = nullptr,
41 .val = i++,
42 });
43 }
44 vecLongOptions.emplace_back(option {nullptr, 0, nullptr, 0});
45
46 int opt = 0;
47 int options_index = 0;
48 map<string, vector<string>> mapArgToVals;
49 while ((opt = getopt_long(argc, argv, "", vecLongOptions.data(), &options_index)) != -1) {
50 if (opt == '?') {
51 // "我们匹配到了一个奇怪的命令 返回 nullopt,getopt_long 在opterr 未被赋值0时 会自动打印未被定义参数到终端"
52 return nullopt;
53 }
54 string argName = mapOptToName[opt];
55 if (mapArgToVals.find(argName) != mapArgToVals.end() && argList[opt].repeatable == true) {
56 mapArgToVals[argName].emplace_back(optarg);
57 } else if (mapArgToVals.find(argName) != mapArgToVals.end()) {
58 fprintf(stderr, "%s can only be entered once, but you repeat it.\n", argName.c_str());
59 return nullopt;
60 } else {
61 mapArgToVals.emplace(argName, vector<string> {optarg});
62 }
63 }
64 return mapArgToVals;
65 }
66
ParseOpAndExecute(int argc,char * const argv[])67 int ParseOpAndExecute(int argc, char *const argv[])
68 {
69 int flag = -1;
70 for (int i = 1; i < argc; i++) {
71 // 暂存 {argv[1]...argv[i]};
72 vector<string_view> curOp;
73 for (int j = 1; j <= i; ++j) {
74 curOp.emplace_back(argv[j]);
75 }
76
77 // 尝试匹配当前命令,成功后执行
78 auto tryOpSucceed = [&curOp](const ToolsOp &op) { return op.TryMatch(curOp); };
79 auto &&opeartions = ToolsOp::GetAllOperations();
80 auto matchedOp = find_if(opeartions.begin(), opeartions.end(), tryOpSucceed);
81 if (matchedOp != opeartions.end()) {
82 vector<ToolsOp::CmdInfo> argList = matchedOp->GetParams();
83 optional<map<string, vector<string>>> mapNameToArgs = GetArgsMap(argc, argv, argList);
84 if (mapNameToArgs.has_value()) {
85 flag = matchedOp->Execute(mapNameToArgs.value());
86 }
87 }
88 }
89 if (flag != 0) {
90 printf("backup_tool: missing operand\nTry 'backup_tool help' for more information.\n");
91 }
92 return flag;
93 }
94 } // namespace OHOS::FileManagement::Backup
95
main(int argc,char * const argv[])96 int main(int argc, char *const argv[])
97 {
98 return OHOS::FileManagement::Backup::ParseOpAndExecute(argc, argv);
99 }