• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/send_command_v10.h"
16 
17 #include <chrono>
18 #include <fcntl.h>
19 #include <sys/stat.h>
20 #include <sys/types.h>
21 #include <thread>
22 #include <unistd.h>
23 
24 #include "constant.h"
25 #include "directory_ex.h"
26 #include "exec_env.h"
27 #include "media_file_uri.h"
28 #include "media_file_utils.h"
29 #include "medialibrary_errno.h"
30 #include "medialibrary_napi_utils.h"
31 #include "userfile_client_ex.h"
32 
33 namespace OHOS {
34 namespace Media {
35 namespace MediaTool {
36 static constexpr int32_t SLEEP_NOTIFY_TIME = 2000;
37 
38 struct FileInfo {
39     Media::MediaType mediaType {Media::MediaType::MEDIA_TYPE_DEFAULT};
40     std::string displayName;
41     std::string path;
42     std::string uri;
43     int32_t id {-1};
44     bool toBeRemove {false};
45     int32_t result {-1};
ToStrOHOS::Media::MediaTool::FileInfo46     [[nodiscard]] std::string ToStr() const
47     {
48         std::string str;
49         str.append("mediaType:");
50         str.append(std::to_string(static_cast<uint32_t>(mediaType)));
51         str.append(", displayName:");
52         str.append(displayName);
53         str.append(", path:");
54         str.append(path);
55         str.append(", uri:");
56         str.append(uri);
57         str.append(", id:");
58         str.append(std::to_string(id));
59         return str;
60     }
61 };
62 
GetFileInfo(const ExecEnv & env,const std::string & path,std::vector<FileInfo> & fileInfos)63 static inline int32_t GetFileInfo(const ExecEnv &env, const std::string &path, std::vector<FileInfo> &fileInfos)
64 {
65     FileInfo fileInfo;
66     fileInfo.displayName = ExtractFileName(path);
67     fileInfo.mediaType = MediaFileUtils::GetMediaType(fileInfo.displayName);
68     fileInfo.path = path;
69     fileInfo.result = Media::E_ERR;
70     auto mediaTypes = UserFileClientEx::GetSupportTypes();
71     for (auto mediaType : mediaTypes) {
72         if (mediaType != fileInfo.mediaType) {
73             continue;
74         }
75         fileInfos.push_back(fileInfo);
76         return Media::E_OK;
77     }
78     return Media::E_ERR;
79 }
80 
GetDirInfo(const ExecEnv & env,const std::string & path,std::vector<FileInfo> & fileInfos)81 static int32_t GetDirInfo(const ExecEnv &env, const std::string &path, std::vector<FileInfo> &fileInfos)
82 {
83     std::vector<std::string> files;
84     GetDirFiles(path, files);
85     if (!files.size() && errno) {
86         printf("%s can not get dir files. errno:%d\n", STR_FAIL.c_str(), errno);
87     }
88     for (auto &file : files) {
89         auto ret = GetFileInfo(env, file, fileInfos);
90         if (ret != Media::E_OK) {
91             printf("%s get dir information failed. ret:%d, file:%s\n", STR_FAIL.c_str(), ret, file.c_str());
92             return ret;
93         }
94     }
95     return Media::E_OK;
96 }
97 
RemoveFiles(const ExecEnv & env,std::vector<FileInfo> & fileInfos)98 static void RemoveFiles(const ExecEnv &env, std::vector<FileInfo> &fileInfos)
99 {
100     for (auto &fileInfo : fileInfos) {
101         if (fileInfo.result != Media::E_OK) {
102             continue;
103         }
104         if (!fileInfo.toBeRemove) {
105             continue;
106         }
107         RemoveFile(fileInfo.path);
108     }
109     fileInfos.clear();
110 }
111 
EncodeDisplayName(const std::string & displayName)112 static std::string EncodeDisplayName(const std::string &displayName)
113 {
114     std::set<char> CHAR_FILTERS = {
115         '\\', '/', ':',
116         '*', '?', '"',
117         '<', '>', '|',
118     };
119     std::string encodedStr = "";
120     for (char c : displayName) {
121         if (CHAR_FILTERS.find(c) != CHAR_FILTERS.end()) {
122             encodedStr += MediaFileUtils::Encode(string(1, c));
123         } else {
124             encodedStr += c;
125         }
126     }
127     return encodedStr;
128 }
129 
CreateRecord(const ExecEnv & env,FileInfo & fileInfo,bool isRestart)130 static int32_t CreateRecord(const ExecEnv &env, FileInfo &fileInfo, bool isRestart)
131 {
132     const MediaType mediaType = fileInfo.mediaType;
133     std::string tableName = UserFileClientEx::GetTableNameByMediaType(mediaType);
134     const std::string displayName = EncodeDisplayName(fileInfo.displayName);
135     string uri;
136     auto fileId = UserFileClientEx::InsertExt(tableName, displayName, uri, isRestart);
137     if (fileId <= 0) {
138         printf("%s create record failed. fileId:%d, fileInfo:%s\n",
139             STR_FAIL.c_str(), fileId, fileInfo.ToStr().c_str());
140         return Media::E_ERR;
141     }
142     if (!uri.empty()) {
143         fileInfo.uri = uri;
144     } else {
145         printf("%s create record failed. uri is empty. fileInfo:%s\n",
146             STR_FAIL.c_str(), fileInfo.ToStr().c_str());
147         return Media::E_FAIL;
148     }
149     fileInfo.id = fileId;
150     return Media::E_OK;
151 }
152 
WriteFile(const ExecEnv & env,FileInfo & fileInfo,bool isRestart)153 static int32_t WriteFile(const ExecEnv &env, FileInfo &fileInfo, bool isRestart)
154 {
155     if (!PathToRealPath(fileInfo.path, fileInfo.path)) {
156         printf("%s path issue. errno:%d, path:%s.\n", STR_FAIL.c_str(), errno, fileInfo.path.c_str());
157         return Media::E_ERR;
158     }
159     int32_t rfd = open(fileInfo.path.c_str(), O_RDONLY | O_CLOEXEC);
160     if (rfd < 0) {
161         printf("%s open file failed. rfd:%d, path:%s\n", STR_FAIL.c_str(), rfd, fileInfo.path.c_str());
162         return Media::E_ERR;
163     }
164     int32_t wfd = UserFileClientEx::Open(fileInfo.uri, Media::MEDIA_FILEMODE_WRITETRUNCATE, isRestart);
165     if (wfd <= 0) {
166         printf("%s open failed. wfd:%d, uri:%s\n", STR_FAIL.c_str(), wfd, fileInfo.uri.c_str());
167         close(rfd);
168         return Media::E_ERR;
169     }
170     int32_t ret = MediaFileUtils::CopyFile(rfd, wfd);
171     if (!ret) {
172         printf("%s send data failed. rfd:%d, wfd:%d\n", STR_FAIL.c_str(), rfd, wfd);
173         close(rfd);
174         close(wfd);
175         return Media::E_ERR;
176     }
177     if (env.sendParam.isCreateThumbSyncInSend) {
178         ret = UserFileClientEx::Close(fileInfo.uri, wfd, Media::MEDIA_FILEMODE_WRITETRUNCATE, true, isRestart);
179     } else {
180         ret = UserFileClientEx::Close(fileInfo.uri, wfd, Media::MEDIA_FILEMODE_WRITETRUNCATE, false, isRestart);
181     }
182     if (ret != E_OK) {
183         printf("close file has err [%d]\n", ret);
184     }
185 
186     close(rfd);
187     return ret;
188 }
189 
190 static constexpr int MAX_RESTART_TIME = 5;
RestartMediaLibraryServer(int32_t restartTime)191 static void RestartMediaLibraryServer(int32_t restartTime)
192 {
193     printf("Run operations failed, restart Time %d\n", restartTime);
194     std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_NOTIFY_TIME));
195 }
196 
SendFile(const ExecEnv & env,FileInfo & fileInfo)197 static int32_t SendFile(const ExecEnv &env, FileInfo &fileInfo)
198 {
199     int32_t restartTime = 0;
200 
201     while (restartTime < MAX_RESTART_TIME) {
202         fileInfo.result = CreateRecord(env, fileInfo, (restartTime > 0) ? true : false);
203         if (fileInfo.result != Media::E_OK) {
204             restartTime++;
205             RestartMediaLibraryServer(restartTime);
206             continue;
207         } else {
208             break;
209         }
210     }
211     if (fileInfo.result != Media::E_OK) {
212         return Media::E_ERR;
213     }
214 
215     std::string tableName = UserFileClientEx::GetTableNameByUri(fileInfo.uri);
216     if (tableName.empty()) {
217         printf("%s uri issue. uri:%s\n", STR_FAIL.c_str(), fileInfo.uri.c_str());
218         return Media::E_ERR;
219     }
220 
221     while (restartTime < MAX_RESTART_TIME) {
222         fileInfo.result = WriteFile(env, fileInfo, (restartTime > 0) ? true : false);
223         if (fileInfo.result != Media::E_OK) {
224             restartTime++;
225             RestartMediaLibraryServer(restartTime);
226             continue;
227         } else {
228             break;
229         }
230     }
231     if (fileInfo.result != Media::E_OK) {
232         return Media::E_ERR;
233     }
234     fileInfo.result = Media::E_OK;
235     return Media::E_OK;
236 }
237 
SendFiles(const ExecEnv & env,std::vector<FileInfo> & fileInfos)238 static int32_t SendFiles(const ExecEnv &env, std::vector<FileInfo> &fileInfos)
239 {
240     int count = 0;
241     int correctCount = 0;
242     for (auto &fileInfo : fileInfos) {
243         ++count;
244         int32_t ret = SendFile(env, fileInfo);
245         if (ret != Media::E_OK) {
246             printf("%s send uri [%s] failed.\n", STR_FAIL.c_str(), fileInfo.uri.c_str());
247         } else {
248             fileInfo.toBeRemove = true;
249             printf("%s\n", fileInfo.uri.c_str());
250             ++correctCount;
251         }
252     }
253 
254     if (count > ARGS_ONE) {
255         if (count == correctCount) {
256             printf("%s send %d and %d is successful.\n", STR_SUCCESS.c_str(), count, correctCount);
257             return Media::E_OK;
258         } else {
259             printf("%s send %d and %d is successful.\n", STR_FAIL.c_str(), count, correctCount);
260             return Media::E_FAIL;
261         }
262     } else {
263         if (correctCount == count) {
264             return Media::E_OK;
265         } else {
266             return Media::E_FAIL;
267         }
268     }
269 }
270 
Start(const ExecEnv & env)271 int32_t SendCommandV10::Start(const ExecEnv &env)
272 {
273     std::vector<FileInfo> fileInfos;
274     auto ret = (env.sendParam.isFile) ? GetFileInfo(env, env.sendParam.sendPath, fileInfos) : GetDirInfo(env,
275         env.sendParam.sendPath, fileInfos);
276     if (ret != Media::E_OK) {
277         printf("%s get file information failed. ret:%d\n", STR_FAIL.c_str(), ret);
278         return ret;
279     }
280     ret = SendFiles(env, fileInfos);
281     if (env.sendParam.isRemoveOriginFileInSend) {
282         RemoveFiles(env, fileInfos);
283     }
284     return ret;
285 }
286 } // namespace MediaTool
287 } // namespace Media
288 } // namespace OHOS
289