• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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