• 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,const FileInfo & fileInfo,bool isRestart)153 static int32_t WriteFile(const ExecEnv &env, const FileInfo &fileInfo, bool isRestart)
154 {
155     int32_t rfd = open(fileInfo.path.c_str(), O_RDONLY | O_CLOEXEC);
156     if (rfd < 0) {
157         printf("%s open file failed. rfd:%d, path:%s\n", STR_FAIL.c_str(), rfd, fileInfo.path.c_str());
158         return Media::E_ERR;
159     }
160     int32_t wfd = UserFileClientEx::Open(fileInfo.uri, Media::MEDIA_FILEMODE_WRITETRUNCATE, isRestart);
161     if (wfd <= 0) {
162         printf("%s open failed. wfd:%d, uri:%s\n", STR_FAIL.c_str(), wfd, fileInfo.uri.c_str());
163         close(rfd);
164         return Media::E_ERR;
165     }
166     int32_t ret = MediaFileUtils::CopyFile(rfd, wfd);
167     if (!ret) {
168         printf("%s send data failed. rfd:%d, wfd:%d\n", STR_FAIL.c_str(), rfd, wfd);
169         close(rfd);
170         close(wfd);
171         return Media::E_ERR;
172     }
173     if (env.sendParam.isCreateThumbSyncInSend) {
174         ret = UserFileClientEx::Close(fileInfo.uri, wfd, Media::MEDIA_FILEMODE_WRITETRUNCATE, true, isRestart);
175     } else {
176         ret = UserFileClientEx::Close(fileInfo.uri, wfd, Media::MEDIA_FILEMODE_WRITETRUNCATE, false, isRestart);
177     }
178     if (ret != E_OK) {
179         printf("close file has err [%d]\n", ret);
180     }
181 
182     close(rfd);
183     return ret;
184 }
185 
186 static constexpr int MAX_RESTART_TIME = 5;
RestartMediaLibraryServer(int32_t restartTime)187 static void RestartMediaLibraryServer(int32_t restartTime)
188 {
189     printf("Run operations failed, restart Time %d\n", restartTime);
190     std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_NOTIFY_TIME));
191 }
192 
SendFile(const ExecEnv & env,FileInfo & fileInfo)193 static int32_t SendFile(const ExecEnv &env, FileInfo &fileInfo)
194 {
195     int32_t restartTime = 0;
196 
197     while (restartTime < MAX_RESTART_TIME) {
198         fileInfo.result = CreateRecord(env, fileInfo, (restartTime > 0) ? true : false);
199         if (fileInfo.result != Media::E_OK) {
200             restartTime++;
201             RestartMediaLibraryServer(restartTime);
202             continue;
203         } else {
204             break;
205         }
206     }
207     if (fileInfo.result != Media::E_OK) {
208         return Media::E_ERR;
209     }
210 
211     std::string tableName = UserFileClientEx::GetTableNameByUri(fileInfo.uri);
212     if (tableName.empty()) {
213         printf("%s uri issue. uri:%s\n", STR_FAIL.c_str(), fileInfo.uri.c_str());
214         return Media::E_ERR;
215     }
216 
217     while (restartTime < MAX_RESTART_TIME) {
218         fileInfo.result = WriteFile(env, fileInfo, (restartTime > 0) ? true : false);
219         if (fileInfo.result != Media::E_OK) {
220             restartTime++;
221             RestartMediaLibraryServer(restartTime);
222             continue;
223         } else {
224             break;
225         }
226     }
227     if (fileInfo.result != Media::E_OK) {
228         return Media::E_ERR;
229     }
230     fileInfo.result = Media::E_OK;
231     return Media::E_OK;
232 }
233 
SendFiles(const ExecEnv & env,std::vector<FileInfo> & fileInfos)234 static int32_t SendFiles(const ExecEnv &env, std::vector<FileInfo> &fileInfos)
235 {
236     int count = 0;
237     int correctCount = 0;
238     for (auto &fileInfo : fileInfos) {
239         ++count;
240         int32_t ret = SendFile(env, fileInfo);
241         if (ret != Media::E_OK) {
242             printf("%s send uri [%s] failed.\n", STR_FAIL.c_str(), fileInfo.uri.c_str());
243         } else {
244             fileInfo.toBeRemove = true;
245             printf("%s\n", fileInfo.uri.c_str());
246             ++correctCount;
247         }
248     }
249 
250     if (count > ARGS_ONE) {
251         if (count == correctCount) {
252             printf("%s send %d and %d is successful.\n", STR_SUCCESS.c_str(), count, correctCount);
253             return Media::E_OK;
254         } else {
255             printf("%s send %d and %d is successful.\n", STR_FAIL.c_str(), count, correctCount);
256             return Media::E_FAIL;
257         }
258     } else {
259         if (correctCount == count) {
260             return Media::E_OK;
261         } else {
262             return Media::E_FAIL;
263         }
264     }
265 }
266 
Start(const ExecEnv & env)267 int32_t SendCommandV10::Start(const ExecEnv &env)
268 {
269     std::vector<FileInfo> fileInfos;
270     auto ret = (env.sendParam.isFile) ? GetFileInfo(env, env.sendParam.sendPath, fileInfos) : GetDirInfo(env,
271         env.sendParam.sendPath, fileInfos);
272     if (ret != Media::E_OK) {
273         printf("%s get file information failed. ret:%d\n", STR_FAIL.c_str(), ret);
274         return ret;
275     }
276     ret = SendFiles(env, fileInfos);
277     if (env.sendParam.isRemoveOriginFileInSend) {
278         RemoveFiles(env, fileInfos);
279     }
280     return ret;
281 }
282 } // namespace MediaTool
283 } // namespace Media
284 } // namespace OHOS
285