1 /*
2 * Copyright (C) 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 #include "command_line.h"
16
17 #include <cstddef>
18 #include <string>
19
20 #include "constant.h"
21 #include "directory_ex.h"
22 #include "exec_env.h"
23 #include "file_ex.h"
24 #include "media_column.h"
25 #include "media_file_utils.h"
26 #include "media_log.h"
27 #include "medialibrary_errno.h"
28 #include "option_args.h"
29 #include "userfile_client_ex.h"
30
31 namespace OHOS {
32 namespace Media {
33 namespace MediaTool {
34 constexpr char CHAR_PATH_DELIMITER = '/';
35 constexpr int MEDIATOOL_ARG_MIN = 3;
36 constexpr int MEDIATOOL_ARG_CMD = 1;
37 constexpr int MEDIATOOL_ARG_FIRST = 2;
38 constexpr int MEDIATOOL_ARG_SECOND = 3;
39 const std::string OPT_STR_SEND = "send";
40 const std::string OPT_STR_RECV = "recv";
41 const std::string OPT_STR_LIST = "list";
42 const std::string OPT_STR_DELETE = "delete";
43 const std::string OPT_STR_QUERY = "query";
44 const std::string OPT_STR_LS = "ls";
45 const std::string OPT_STR_ALL = "all";
46
47 const std::string SEND_CREATE_THUMBNAIL_SYNC = "-ts";
48 const std::string SEND_CREATE_THUMBNAIL_ASYNC = "-tas";
49 const std::string SEND_CREATE_REMOVE_ORIGIN_FILE = "-rf";
50 const std::string SEND_CREATE_UNREMOVE_ORIGIN_FILE = "-urf";
51
52 const std::string DELETE_ONLY_DATABASE = "-db";
53
ShowUsage(bool isRoot)54 static void ShowUsage(bool isRoot)
55 {
56 std::string str;
57 str.append("usage:\n");
58 if (isRoot) {
59 str.append(" send file from path to medialibrary\n");
60 str.append(" command: mediatool send <file-or-dir-path> [-ts] [-tas] [-rf] [-urf]\n");
61 str.append(" list media assets in medialibrary\n");
62 str.append(" command: mediatool list <media-uri>\n");
63 }
64 str.append(" receive file from medialibrary to path\n");
65 str.append(" command: mediatool recv <src-media> <dest-path>\n");
66 str.append(" delete media assets in medialibrary\n");
67 str.append(" command: mediatool delete <media-uri>\n");
68 str.append(" query path or uri by displayname in medialibrary\n");
69 str.append(" command: mediatool query <display-name> [-p] [-u]\n");
70 str.append(" execute ls -l in system media directory\n");
71 str.append(" command: mediatool ls -l <media-directory>\n");
72
73 printf("%s", str.c_str());
74 }
75
IsDirPath(const std::string path)76 static inline bool IsDirPath(const std::string path)
77 {
78 if (path.empty()) {
79 return false;
80 }
81 string subName;
82 string::size_type delimiterPos = path.rfind(CHAR_PATH_DELIMITER);
83 if (delimiterPos == std::string::npos) {
84 subName = path;
85 } else {
86 subName = path.substr(delimiterPos + 1);
87 }
88 if (subName.find('.') == std::string::npos || subName == "." || subName == "..") {
89 return true;
90 } else {
91 return false;
92 }
93 }
94
CheckRecvPath(ExecEnv & env)95 static bool CheckRecvPath(ExecEnv &env)
96 {
97 std::string path;
98 if (IsDirPath(env.recvParam.recvPath)) {
99 env.recvParam.isRecvPathDir = true;
100 path = env.recvParam.recvPath;
101 } else {
102 env.recvParam.isRecvPathDir = false;
103 path = ExtractFilePath(env.recvParam.recvPath);
104 }
105
106 if (!MediaFileUtils::IsDirectory(path)) {
107 ForceCreateDirectory(path);
108 }
109 if (!MediaFileUtils::IsDirectory(path)) {
110 MEDIA_ERR_LOG("recv path issue. path: %{public}s", path.c_str());
111 printf("%s path issue. path:%s\n", STR_FAIL.c_str(), path.c_str());
112 return false;
113 }
114 if (!env.recvParam.isRecvPathDir) {
115 if (FileExists(env.recvParam.recvPath)) {
116 MEDIA_ERR_LOG("recv file has exist. file: %{public}s", env.recvParam.recvPath.c_str());
117 printf("%s file has exist. file:%s\n", STR_FAIL.c_str(), env.recvParam.recvPath.c_str());
118 return false;
119 }
120 } else {
121 env.recvParam.recvPath = IncludeTrailingPathDelimiter(env.recvParam.recvPath);
122 }
123 return true;
124 }
125
CheckList(ExecEnv & env)126 static bool CheckList(ExecEnv &env)
127 {
128 if (env.optArgs.uri == OPT_STR_ALL) {
129 env.listParam.isListAll = true;
130 env.listParam.listUri.clear();
131 } else if (!env.optArgs.uri.empty()) {
132 std::string tableName = UserFileClientEx::GetTableNameByUri(env.optArgs.uri);
133 if (tableName.empty()) {
134 printf("%s uri invalid. uri:%s\n", STR_FAIL.c_str(), env.optArgs.uri.c_str());
135 return false;
136 }
137 env.listParam.listUri = env.optArgs.uri;
138 } else {
139 printf("%s input uri incorrect.\n", STR_FAIL.c_str());
140 return false;
141 }
142 return true;
143 }
144
CheckRecv(ExecEnv & env)145 static bool CheckRecv(ExecEnv &env)
146 {
147 if (env.optArgs.uri == OPT_STR_ALL) {
148 env.recvParam.recvTarget.clear();
149 env.recvParam.isRecvAll = true;
150 } else if (!env.optArgs.uri.empty()) {
151 env.recvParam.recvTarget = env.optArgs.uri;
152 env.recvParam.isRecvAll = false;
153 } else {
154 MEDIA_ERR_LOG("recv target is empty");
155 printf("%s recv target is empty.\n", STR_FAIL.c_str());
156 return false;
157 }
158 if (env.optArgs.recvPath.empty()) {
159 MEDIA_ERR_LOG("recv path empty");
160 printf("%s recv path empty.\n", STR_FAIL.c_str());
161 return false;
162 }
163 if (env.optArgs.recvPath.find(CHAR_PATH_DELIMITER) == 0) {
164 env.recvParam.recvPath = env.optArgs.recvPath;
165 } else {
166 env.recvParam.recvPath = env.workPath + env.optArgs.recvPath;
167 }
168 if (!CheckRecvPath(env)) {
169 return false;
170 }
171 return true;
172 }
173
CheckExtraArgsInSend(ExecEnv & env)174 static void CheckExtraArgsInSend(ExecEnv &env)
175 {
176 for (size_t i = 0; i < env.optArgs.extraArgs.size(); i++) {
177 string param = env.optArgs.extraArgs[i];
178 if (param == SEND_CREATE_THUMBNAIL_SYNC) {
179 env.sendParam.isCreateThumbSyncInSend = true;
180 }
181 if (param == SEND_CREATE_THUMBNAIL_ASYNC) {
182 env.sendParam.isCreateThumbSyncInSend = false;
183 }
184 if (param == SEND_CREATE_REMOVE_ORIGIN_FILE) {
185 env.sendParam.isRemoveOriginFileInSend = true;
186 }
187 if (param == SEND_CREATE_UNREMOVE_ORIGIN_FILE) {
188 env.sendParam.isRemoveOriginFileInSend = false;
189 }
190 }
191 }
192
CheckSend(ExecEnv & env)193 static bool CheckSend(ExecEnv &env)
194 {
195 if (env.optArgs.path.empty()) {
196 printf("%s path empty.\n", STR_FAIL.c_str());
197 return false;
198 }
199 if (!PathToRealPath(env.optArgs.path, env.sendParam.sendPath)) {
200 printf("%s path issue. errno:%d, path:%s.\n", STR_FAIL.c_str(), errno, env.optArgs.path.c_str());
201 return false;
202 }
203 if (!MediaFileUtils::IsDirectory(env.sendParam.sendPath)) {
204 env.sendParam.isFile = true;
205 } else if (MediaFileUtils::IsDirectory(env.sendParam.sendPath)) {
206 env.sendParam.sendPath = IncludeTrailingPathDelimiter(env.sendParam.sendPath);
207 env.sendParam.isFile = false;
208 } else {
209 printf("%s path issue. not file and not directory. path:%s.\n", STR_FAIL.c_str(),
210 env.sendParam.sendPath.c_str());
211 return false;
212 }
213 CheckExtraArgsInSend(env);
214 return true;
215 }
216
CheckDelete(ExecEnv & env)217 static bool CheckDelete(ExecEnv &env)
218 {
219 if (env.optArgs.uri == OPT_STR_ALL) {
220 env.deleteParam.deleteUri.clear();
221 env.deleteParam.isDeleteAll = true;
222 for (size_t i = 0; i < env.optArgs.extraArgs.size(); i++) {
223 string param = env.optArgs.extraArgs[i];
224 if (param == DELETE_ONLY_DATABASE) {
225 env.deleteParam.isOnlyDeleteDb = true;
226 }
227 }
228 } else if (!env.optArgs.uri.empty()) {
229 std::string tableName = UserFileClientEx::GetTableNameByUri(env.optArgs.uri);
230 if (tableName.empty()) {
231 printf("%s uri invalid. uri:%s\n", STR_FAIL.c_str(), env.optArgs.uri.c_str());
232 return false;
233 }
234 env.deleteParam.isDeleteAll = false;
235 env.deleteParam.deleteUri = env.optArgs.uri;
236 } else {
237 printf("%s input uri incorrect.\n", STR_FAIL.c_str());
238 return false;
239 }
240
241 return true;
242 }
243
CheckQuery(ExecEnv & env)244 static bool CheckQuery(ExecEnv &env)
245 {
246 for (size_t i = 0; i < env.optArgs.extraArgs.size(); i++) {
247 string param = env.optArgs.extraArgs[i];
248 if (param == "-p") {
249 env.queryParam.pathFlag = true;
250 } else if (param == "-u") {
251 env.queryParam.uriFlag = true;
252 } else if (env.queryParam.displayName.empty()) {
253 env.queryParam.displayName = param;
254 }
255 }
256
257 if ((env.queryParam.pathFlag && env.queryParam.uriFlag) || env.queryParam.displayName.empty()) {
258 printf("The command is not a valid query command. See 'mediatool -h'\n");
259 ShowUsage(env.isRoot);
260 return false;
261 }
262 if (!env.queryParam.pathFlag && !env.queryParam.uriFlag) {
263 env.queryParam.pathFlag = true;
264 }
265
266 return true;
267 }
268
Check(ExecEnv & env)269 static bool Check(ExecEnv &env)
270 {
271 if (env.optArgs.cmdType == OptCmdType::TYPE_SEND) {
272 return CheckSend(env);
273 }
274 if (env.optArgs.cmdType == OptCmdType::TYPE_RECV) {
275 return CheckRecv(env);
276 }
277 if (env.optArgs.cmdType == OptCmdType::TYPE_LIST) {
278 return CheckList(env);
279 }
280 if (env.optArgs.cmdType == OptCmdType::TYPE_DELETE) {
281 return CheckDelete(env);
282 }
283 if (env.optArgs.cmdType == OptCmdType::TYPE_QUERY) {
284 return CheckQuery(env);
285 }
286 if (env.optArgs.cmdType == OptCmdType::TYPE_LS) {
287 // ls command performs check later
288 return true;
289 }
290 return false;
291 }
292
PutExtraString(ExecEnv & env,size_t start,size_t end=0)293 static void PutExtraString(ExecEnv &env, size_t start, size_t end = 0)
294 {
295 if (end == 0) {
296 for (size_t i = start; i < env.args.size(); i++) {
297 env.optArgs.extraArgs.push_back(env.args[i]);
298 }
299 } else {
300 for (size_t i = start; i <= std::min(env.args.size(), end); i++) {
301 env.optArgs.extraArgs.push_back(env.args[i]);
302 }
303 }
304 }
305
Parser(ExecEnv & env)306 int32_t CommandLine::Parser(ExecEnv &env)
307 {
308 if (env.args.size() < MEDIATOOL_ARG_MIN) {
309 ShowUsage(env.isRoot);
310 return Media::E_ERR;
311 }
312 env.commandArgs = std::vector<std::string>(env.args.begin() + MEDIATOOL_ARG_MIN - 1, env.args.end());
313 std::string cmd = env.args[MEDIATOOL_ARG_CMD];
314 std::string optFirst = (env.args.size() > MEDIATOOL_ARG_FIRST) ? env.args[MEDIATOOL_ARG_FIRST] : "";
315 std::string optSecond = (env.args.size() > MEDIATOOL_ARG_SECOND) ? env.args[MEDIATOOL_ARG_SECOND] : "";
316 if (cmd == OPT_STR_SEND) {
317 env.optArgs.cmdType = OptCmdType::TYPE_SEND;
318 env.optArgs.path = optFirst;
319 if (env.args.size() > MEDIATOOL_ARG_SECOND) {
320 PutExtraString(env, MEDIATOOL_ARG_SECOND);
321 }
322 } else if (cmd == OPT_STR_RECV) {
323 env.optArgs.cmdType = OptCmdType::TYPE_RECV;
324 env.optArgs.uri = optFirst;
325 env.optArgs.recvPath = optSecond;
326 } else if (cmd == OPT_STR_LIST) {
327 env.optArgs.cmdType = OptCmdType::TYPE_LIST;
328 env.optArgs.uri = optFirst;
329 } else if (cmd == OPT_STR_DELETE) {
330 env.optArgs.uri = optFirst;
331 env.optArgs.cmdType = OptCmdType::TYPE_DELETE;
332 PutExtraString(env, MEDIATOOL_ARG_SECOND);
333 } else if (cmd == OPT_STR_QUERY) {
334 env.optArgs.cmdType = OptCmdType::TYPE_QUERY;
335 PutExtraString(env, MEDIATOOL_ARG_FIRST);
336 } else if (cmd == OPT_STR_LS) {
337 env.optArgs.cmdType = OptCmdType::TYPE_LS;
338 } else {
339 ShowUsage(env.isRoot);
340 return Media::E_ERR;
341 }
342 if (!Check(env)) {
343 return Media::E_ERR;
344 }
345 return Media::E_OK;
346 }
347
348 } // namespace MediaTool
349 } // namespace Media
350 } // namespace OHOS
351