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
16 #include "send_file.h"
17
18 #include <fcntl.h>
19 #include <unistd.h>
20 #include <tuple>
21
22 #include "dfs_filetransfer_callback.h"
23 #include "event_agent.h"
24 #include "filetransfer_callback_proxy.h"
25 #include "i_distributedfile_service.h"
26 #include "iservice_registry.h"
27 #include "service_proxy.h"
28 #include "system_ability_definition.h"
29 #include "system_ability_manager.h"
30 #include "utils_directory.h"
31 #include "utils_log.h"
32
33 namespace OHOS {
34 namespace Storage {
35 namespace DistributedFile {
36 std::mutex SendFile::g_uidMutex;
37 std::unordered_map<std::string, EventAgent*> SendFile::mapUidToEventAgent_;
38
RegisterCallback()39 int32_t SendFile::RegisterCallback()
40 {
41 sptr<ISystemAbilityManager> systemAbilityMgr =
42 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
43 if (systemAbilityMgr == nullptr) {
44 LOGE("SendFile::RegisterCallback: Get ISystemAbilityManager failed\n");
45 return NAPI_SENDFILE_SA_ERROR;
46 }
47
48 sptr<IRemoteObject> remote = systemAbilityMgr->GetSystemAbility(FILEMANAGEMENT_DISTRIBUTED_FILE_SERVICE_SA_ID);
49 if (remote == nullptr) {
50 LOGE("SendFile::RegisterCallback: SaId = %{public}d fail\n", FILEMANAGEMENT_DISTRIBUTED_FILE_SERVICE_SA_ID);
51 return NAPI_SENDFILE_SA_ERROR;
52 }
53
54 sptr<IDistributedFileService> distributedFileService = iface_cast<IDistributedFileService>(remote);
55 if (distributedFileService == nullptr) {
56 LOGE("SendFile::RegisterCallback: nullptr\n");
57 return NAPI_SENDFILE_IPC_ERROR;
58 }
59
60 sptr<IFileTransferCallback> callback = (std::make_unique<DfsFileTransferCallback>()).release();
61 LOGD("SendFile::RegisterCallback: cb[%{public}p]", callback->AsObject().GetRefPtr());
62 if (distributedFileService->RegisterNotifyCallback(callback) != IDistributedFileService::DFS_NO_ERROR) {
63 LOGD("SendFile::RegisterCallback: remote call failed.\n");
64 return NAPI_SENDFILE_IPC_ERROR;
65 }
66 return NAPI_SENDFILE_NO_ERROR;
67 }
68
JoinCidToAppId(const std::string & cid,const std::string & AppId)69 int32_t SendFile::JoinCidToAppId(const std::string &cid, const std::string &AppId)
70 {
71 if (cid.empty() || AppId.empty()) {
72 LOGE("SendFile::JoinCidToAppId: input para error.\n");
73 return NAPI_SENDFILE_PARA_ERROR;
74 }
75
76 auto iter = mapUidToEventAgent_.find(AppId);
77 if (mapUidToEventAgent_.end() == iter) {
78 LOGE("SendFile::JoinCidToAppId: can't find app agent.\n");
79 return NAPI_SENDFILE_APP_AGENT_ERROR;
80 }
81
82 EventAgent* agent = iter->second;
83 if (agent != nullptr && !agent->FindDevice(cid)) {
84 LOGI("SendFile::JoinCidToAppId: device[%{public}s] insert into list.", cid.c_str());
85 agent->InsertDevice(cid);
86 }
87 return NAPI_SENDFILE_NO_ERROR;
88 }
89
DisjoinCidToAppId(const std::string & cid,const std::string & AppId)90 int32_t SendFile::DisjoinCidToAppId(const std::string &cid, const std::string &AppId)
91 {
92 if (cid.empty() || AppId.empty()) {
93 LOGE("SendFile::DisJoinCidToAppId: input para error.\n");
94 return NAPI_SENDFILE_PARA_ERROR;
95 }
96
97 auto iter = mapUidToEventAgent_.find(AppId);
98 if (mapUidToEventAgent_.end() == iter) {
99 LOGE("SendFile::DisJoinCidToAppId: can't find app agent.\n");
100 return NAPI_SENDFILE_APP_AGENT_ERROR;
101 }
102
103 EventAgent* agent = iter->second;
104 if (agent != nullptr && agent->FindDevice(cid)) {
105 LOGI("SendFile::DisJoinCidToAppId: device[%{public}s] remove from list.", cid.c_str());
106 agent->RemoveDevice(cid);
107 }
108 return NAPI_SENDFILE_NO_ERROR;
109 }
110
EmitTransEvent(TransEvent & event,const std::string & cid,const std::string & AppId)111 int32_t SendFile::EmitTransEvent(TransEvent &event, const std::string &cid, const std::string &AppId)
112 {
113 if (cid.empty() || AppId.empty()) {
114 LOGE("SendFile::EmitTransEvent: input para error.\n");
115 return NAPI_SENDFILE_PARA_ERROR;
116 }
117
118 auto iter = mapUidToEventAgent_.find(AppId);
119 if (mapUidToEventAgent_.end() == iter) {
120 LOGE("SendFile::EmitTransEvent: can't find app agent.\n");
121 return NAPI_SENDFILE_APP_AGENT_ERROR;
122 }
123
124 EventAgent* agent = iter->second;
125 if (agent == nullptr) {
126 LOGE("SendFile::EmitTransEvent: app agent null.\n");
127 return NAPI_SENDFILE_APP_AGENT_ERROR;
128 }
129
130 LOGI("SendFile::EmitTransEvent: [%{public}s, %{public}s]", cid.c_str(), event.GetName().c_str());
131 agent->Emit(event.GetName().c_str(), reinterpret_cast<Event*>(&event));
132 return NAPI_SENDFILE_NO_ERROR;
133 }
134
WriteFile(int32_t fd,const std::string & fileName)135 int32_t SendFile::WriteFile(int32_t fd, const std::string &fileName)
136 {
137 if (fd <= 0) {
138 return NAPI_SENDFILE_FD_ERROR;
139 }
140 std::string filePath = APP_PATH + fileName;
141 unsigned int flags = O_WRONLY;
142
143 if (!Utils::IsFileExist(filePath)) {
144 flags |= O_CREAT;
145 }
146
147 char *realPath = realpath(filePath.c_str(), nullptr);
148 if (realPath == nullptr) {
149 return NAPI_SENDFILE_FD_ERROR;
150 }
151
152 int32_t writeFd = open(realPath, static_cast<int>(flags), (S_IREAD | S_IWRITE) | S_IRGRP | S_IROTH);
153 free(realPath);
154 if (writeFd <= 0) {
155 close(fd);
156 LOGE("NapiWriteFile open file failed %{public}d, %{public}s, %{public}d", writeFd, filePath.c_str(), errno);
157 return NAPI_SENDFILE_FD_ERROR;
158 }
159 auto buffer = std::make_unique<char[]>(FILE_BLOCK_SIZE);
160 ssize_t actLen = 0;
161 do {
162 actLen = read(fd, buffer.get(), FILE_BLOCK_SIZE);
163 if (actLen > 0) {
164 write(writeFd, buffer.get(), actLen);
165 } else if (actLen == 0) {
166 break;
167 } else {
168 if (errno == EINTR) {
169 actLen = FILE_BLOCK_SIZE;
170 } else {
171 close(fd);
172 close(writeFd);
173 return NAPI_SENDFILE_FD_ERROR;
174 }
175 }
176 } while (actLen > 0);
177
178 close(fd);
179 close(writeFd);
180
181 return NAPI_SENDFILE_NO_ERROR;
182 }
183
ExecSendFile(const std::string & deviceId,const std::vector<std::string> & srcList,const std::vector<std::string> & dstList,uint32_t num)184 int32_t SendFile::ExecSendFile(const std::string &deviceId, const std::vector<std::string>& srcList,
185 const std::vector<std::string>& dstList, uint32_t num)
186 {
187 if (deviceId.empty() || srcList.empty()) {
188 LOGE("SendFile::ExecSendFile: para error.\n");
189 return NAPI_SENDFILE_PARA_ERROR;
190 }
191
192 sptr<ISystemAbilityManager> systemAbilityMgr =
193 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
194 if (systemAbilityMgr == nullptr) {
195 LOGE("SendFile::ExecSendFile: Get ISystemAbilityManager failed.\n");
196 return NAPI_SENDFILE_SA_ERROR;
197 }
198
199 sptr<IRemoteObject> remote = systemAbilityMgr->CheckSystemAbility(FILEMANAGEMENT_DISTRIBUTED_FILE_SERVICE_SA_ID);
200 if (remote == nullptr) {
201 LOGE("SendFile::ExecSendFile: SaId = %{public}d fail.\n", FILEMANAGEMENT_DISTRIBUTED_FILE_SERVICE_SA_ID);
202 return NAPI_SENDFILE_SA_ERROR;
203 }
204
205 sptr<IDistributedFileService> distributedFileService = iface_cast<IDistributedFileService>(remote);
206 if (distributedFileService == nullptr) {
207 LOGE("SendFile::ExecSendFile: get remote service proxy failed.\n");
208 return NAPI_SENDFILE_IPC_ERROR;
209 }
210
211 char *realPath = realpath(srcList.at(0).c_str(), nullptr);
212 if (realPath == nullptr) {
213 return NAPI_SENDFILE_FD_ERROR;
214 }
215
216 int32_t fd = open(realPath, O_RDONLY);
217 free(realPath);
218 int32_t result = distributedFileService->OpenFile(fd, srcList.at(0), (S_IREAD | S_IWRITE) | S_IRGRP | S_IROTH);
219 if (result != IDistributedFileService::DFS_SUCCESS) {
220 LOGE("SendFile::ExecSendFile: error code %{public}d", result);
221 return NAPI_SENDFILE_SEND_ERROR;
222 }
223
224 result = distributedFileService->SendFile(deviceId, srcList, dstList, num);
225 if (result != IDistributedFileService::DFS_SENDFILE_SUCCESS) {
226 LOGE("SendFile::ExecSendFile: error code %{public}d", result);
227 return NAPI_SENDFILE_SEND_ERROR;
228 }
229
230 LOGD("SendFile::ExecSendFile: napi sendfile success.");
231 return NAPI_SENDFILE_NO_ERROR;
232 }
233 } // namespace DistributedFile
234 } // namespace Storage
235 } // namespace OHOS