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 #include "distributedfile_service.h"
16
17 #include <exception>
18 #include <fcntl.h>
19 #include <unistd.h>
20
21 #include "bundle_mgr_interface.h"
22 #include "bundle_mgr_proxy.h"
23 #include "device_manager_agent.h"
24 #include "ipc_skeleton.h"
25 #include "iservice_registry.h"
26 #include "message_parcel.h"
27 #include "parcel.h"
28 #include "softbus_agent.h"
29 #include "system_ability_definition.h"
30 #include "utils_directory.h"
31 #include "utils_log.h"
32
33 namespace OHOS {
34 namespace Storage {
35 namespace DistributedFile {
36 namespace {
37 constexpr int32_t FILE_BLOCK_SIZE = 1024;
38 constexpr char TEMP_FILE_NAME[] = "/data/system_ce/tmp";
39 }
40
41 REGISTER_SYSTEM_ABILITY_BY_ID(DistributedFileService, FILEMANAGEMENT_DISTRIBUTED_FILE_SERVICE_SA_ID, false);
42
OnDump()43 void DistributedFileService::OnDump()
44 {
45 LOGI("OnDump");
46 }
47
OnStart()48 void DistributedFileService::OnStart()
49 {
50 PublishSA();
51 StartManagers();
52 }
53
OnStop()54 void DistributedFileService::OnStop()
55 {
56 LOGI("OnStop");
57 }
58
PublishSA()59 void DistributedFileService::PublishSA()
60 {
61 bool ret = SystemAbility::Publish(this);
62 if (!ret) {
63 LOGE("Leave, publishing DistributedFileService failed!");
64 return;
65 }
66 }
67
StartManagers()68 void DistributedFileService::StartManagers()
69 {
70 DeviceManagerAgent::GetInstance();
71 }
72
CreateSourceResources(const std::vector<std::string> & sourceFileList,std::vector<char * > & sFileList)73 int32_t DistributedFileService::CreateSourceResources(const std::vector<std::string> &sourceFileList,
74 std::vector<char *> &sFileList)
75 {
76 if (sourceFileList.size() != 1) {
77 return DFS_MEM_ERROR;
78 }
79 for (int index = 0; index < sourceFileList.size(); ++index) {
80 LOGI("DistributedFileService::SendFile Source File List %{public}d, %{public}s, %{public}d",
81 index, sourceFileList.at(index).c_str(), sourceFileList.at(index).length());
82 if (index == 0) {
83 std::string tmpString("/data/system_ce/tmp");
84 int32_t length = tmpString.length();
85 if (length <= 0) {
86 return DFS_MEM_ERROR;
87 }
88 char *sTemp = new char[length + 1];
89 if (sTemp == nullptr) {
90 return DFS_MEM_ERROR;
91 }
92 sFileList.push_back(sTemp);
93 if (memset_s(sTemp, length + 1, '\0', length + 1) != EOK) {
94 return DFS_MEM_ERROR;
95 }
96 if (memcpy_s(sTemp, length + 1, tmpString.c_str(), length) != EOK) {
97 return DFS_MEM_ERROR;
98 }
99 sTemp[length] = '\0';
100 } else {
101 int32_t length = sourceFileList.at(index).length();
102 if (length <= 0) {
103 return DFS_MEM_ERROR;
104 }
105 char *sTemp = new char[length + 1];
106 if (sTemp == nullptr) {
107 return DFS_MEM_ERROR;
108 }
109 sFileList.push_back(sTemp);
110 if (memset_s(sTemp, length + 1, '\0', length + 1) != EOK) {
111 return DFS_MEM_ERROR;
112 }
113 if (memcpy_s(sTemp, length + 1, sourceFileList.at(index).c_str(), length) != EOK) {
114 return DFS_MEM_ERROR;
115 }
116 sTemp[length] = '\0';
117 }
118 }
119 return DFS_NO_ERROR;
120 }
121
CreateDestResources(const std::vector<std::string> & destinationFileList,std::vector<char * > & dFileList)122 int32_t DistributedFileService::CreateDestResources(const std::vector<std::string> &destinationFileList,
123 std::vector<char *> &dFileList)
124 {
125 if (destinationFileList.size() > 1) {
126 return DFS_MEM_ERROR;
127 }
128
129 for (int index = 0; index < destinationFileList.size(); ++index) {
130 int32_t length = destinationFileList.at(index).length();
131 if (length <= 0) {
132 return DFS_MEM_ERROR;
133 }
134 char *sTemp = new char[length + 1];
135 if (sTemp == nullptr) {
136 return DFS_MEM_ERROR;
137 }
138 dFileList.push_back(sTemp);
139 if (memset_s(sTemp, length + 1, '\0', length + 1) != EOK) {
140 return DFS_MEM_ERROR;
141 }
142 if (memcpy_s(sTemp, length + 1, destinationFileList.at(index).c_str(), length) != EOK) {
143 return DFS_MEM_ERROR;
144 }
145 sTemp[length] = '\0';
146 }
147 return DFS_NO_ERROR;
148 }
149
DestroyFileList(std::vector<char * > & fileList)150 void DistributedFileService::DestroyFileList(std::vector<char *> &fileList)
151 {
152 if (fileList.empty()) {
153 LOGE("Send file list is empty");
154 return;
155 }
156
157 for (size_t index = 0; index < fileList.size(); ++index) {
158 char *temp = fileList.at(index);
159 if (temp != nullptr) {
160 LOGI("destroy list index [%{public}d] memory", index);
161 delete[] temp;
162 }
163 }
164 fileList.clear();
165 }
166
SendFile(const std::string & cid,const std::vector<std::string> & sourceFileList,const std::vector<std::string> & destinationFileList,const uint32_t fileCount)167 int32_t DistributedFileService::SendFile(const std::string &cid,
168 const std::vector<std::string> &sourceFileList,
169 const std::vector<std::string> &destinationFileList,
170 const uint32_t fileCount)
171 {
172 int32_t result = DFS_NO_ERROR;
173 if (cid.empty() || fileCount != 1 || sourceFileList.empty() || sourceFileList.size() != fileCount ||
174 destinationFileList.size() > 1) {
175 LOGE("SendFile params failed");
176 return DFS_PARAM_FILE_COUNT_ERROR;
177 }
178
179 std::vector<char *> sFileList;
180 std::vector<char *> dFileList;
181
182 result = CreateSourceResources(sourceFileList, sFileList);
183
184 if (!destinationFileList.empty()) {
185 result = CreateDestResources(destinationFileList, dFileList);
186 }
187
188 if (result != DFS_MEM_ERROR) {
189 auto softBusAgent = SoftbusAgent::GetInstance();
190 result = softBusAgent->SendFile(cid, (const char **)sFileList.data(),
191 (const char **)dFileList.data(), fileCount);
192 }
193
194 DestroyFileList(sFileList);
195 DestroyFileList(dFileList);
196 return result;
197 }
198
OpenFile(int32_t fd,const std::string & fileName,int32_t mode)199 int32_t DistributedFileService::OpenFile(int32_t fd, const std::string &fileName, int32_t mode)
200 {
201 if (fd <= 0 || fileName.empty()) {
202 return DFS_FILE_OP_ERROR;
203 }
204
205 const char *tmpFile = TEMP_FILE_NAME;
206 struct stat fileStat;
207 bool fileExist = (stat(tmpFile, &fileStat) == 0);
208 if (fileExist) {
209 int32_t result = remove(tmpFile);
210 if (result != 0) {
211 close(fd);
212 LOGE("DFS SA remove temp file result %{public}d, %{public}d", result, errno);
213 return DFS_FILE_OP_ERROR;
214 }
215 }
216
217 int32_t writeFd = open(tmpFile, O_WRONLY | O_CREAT, (S_IREAD | S_IWRITE) | S_IRGRP | S_IROTH);
218 if (writeFd <= 0) {
219 close(fd);
220 LOGE("DFS SA open temp file failed %{public}d, %{public}d", writeFd, errno);
221 return DFS_FILE_OP_ERROR;
222 }
223 auto buffer = std::make_unique<char[]>(FILE_BLOCK_SIZE);
224 ssize_t actLen = 0;
225 do {
226 actLen = read(fd, buffer.get(), FILE_BLOCK_SIZE);
227 if (actLen > 0) {
228 write(writeFd, buffer.get(), actLen);
229 } else if (actLen == 0) {
230 break;
231 } else {
232 if (errno == EINTR) {
233 actLen = FILE_BLOCK_SIZE;
234 } else {
235 close(fd);
236 close(writeFd);
237 return DFS_FILE_OP_ERROR;
238 }
239 }
240 } while (actLen > 0);
241
242 close(fd);
243 close(writeFd);
244
245 return DFS_SUCCESS;
246 }
247
RegisterNotifyCallback(sptr<IFileTransferCallback> & callback)248 int32_t DistributedFileService::RegisterNotifyCallback(sptr<IFileTransferCallback> &callback)
249 {
250 SoftbusAgent::GetInstance()->SetTransCallback(callback);
251 LOGD("DistributedFileService::RegisterNotifyCallback: cb[%{public}p]", callback->AsObject().GetRefPtr());
252 return DFS_SUCCESS;
253 }
254
UnRegisterNotifyCallback()255 int32_t DistributedFileService::UnRegisterNotifyCallback()
256 {
257 SoftbusAgent::GetInstance()->RemoveTransCallbak();
258 return DFS_SUCCESS;
259 }
260
IsDeviceOnline(const std::string & cid)261 int32_t DistributedFileService::IsDeviceOnline(const std::string &cid)
262 {
263 std::set<std::string> onlineDevice = DeviceManagerAgent::GetInstance()->getOnlineDevs();
264 if (onlineDevice.find(cid) != onlineDevice.end()) {
265 return DEVICE_ONLINE;
266 }
267 return DEVICE_NOT_ONLINE;
268 }
269 } // namespace DistributedFile
270 } // namespace Storage
271 } // namespace OHOS
272