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/recv_command_v10.h"
16
17 #include <cerrno>
18 #include <fcntl.h>
19 #include <set>
20 #include <sys/stat.h>
21 #include <sys/types.h>
22 #include <unistd.h>
23
24 #include "constant.h"
25 #include "datashare_result_set.h"
26 #include "directory_ex.h"
27 #include "media_file_utils.h"
28 #include "medialibrary_errno.h"
29 #include "userfile_client_ex.h"
30
31 namespace OHOS {
32 namespace Media {
33 namespace MediaTool {
34 constexpr mode_t OPEN_MODE = 0664;
GetWriteFilePath(const ExecEnv & env,const FileAsset & fileAsset,std::string & wFilePath)35 static bool GetWriteFilePath(const ExecEnv &env, const FileAsset &fileAsset, std::string &wFilePath)
36 {
37 wFilePath = env.recvParam.recvPath;
38 if (!MediaFileUtils::IsDirectory(wFilePath)) {
39 if (env.recvParam.isRecvAll) {
40 printf("RecvFilePath:%s is not a directory.\n", wFilePath.c_str());
41 return false;
42 }
43 } else {
44 wFilePath = IncludeTrailingPathDelimiter(wFilePath);
45 string displayName = fileAsset.GetDisplayName();
46 if (displayName.empty()) {
47 printf("RecvFile displayName is null.\n");
48 return false;
49 }
50 wFilePath += displayName;
51 }
52 return true;
53 }
54
RecvFile(const ExecEnv & env,const FileAsset & fileAsset)55 static int32_t RecvFile(const ExecEnv &env, const FileAsset &fileAsset)
56 {
57 std::string wFilePath;
58 if (!GetWriteFilePath(env, fileAsset, wFilePath)) {
59 return Media::E_ERR;
60 }
61 auto wfd = open(wFilePath.c_str(), O_CREAT | O_WRONLY | O_CLOEXEC, OPEN_MODE);
62 if (wfd <= 0) {
63 printf("%s open file failed. errno:%d, fileName:%s\n", STR_FAIL.c_str(), errno, wFilePath.c_str());
64 return Media::E_ERR;
65 }
66 auto rfd = UserFileClientEx::Open(fileAsset.GetUri(), Media::MEDIA_FILEMODE_READONLY);
67 if (rfd <= 0) {
68 printf("%s open failed. uri:%s\n", STR_FAIL.c_str(), fileAsset.GetUri().c_str());
69 close(wfd);
70 return Media::E_ERR;
71 }
72 auto ret = MediaFileUtils::CopyFile(rfd, wfd);
73 if (!ret) {
74 printf("%s receive data failed. uri:%s\n", STR_FAIL.c_str(), fileAsset.GetUri().c_str());
75 } else {
76 printf("%s\n", wFilePath.c_str());
77 }
78 UserFileClientEx::Close(fileAsset.GetUri(), rfd, Media::MEDIA_FILEMODE_READONLY);
79 close(wfd);
80 return ret ? Media::E_OK : Media::E_ERR;
81 }
82
RecvAsset(const ExecEnv & env,const std::string & tableName,const std::string & uri)83 static int32_t RecvAsset(const ExecEnv &env, const std::string &tableName, const std::string &uri)
84 {
85 if (tableName.empty()) {
86 printf("%s can not get query table, uri:%s\n", STR_FAIL.c_str(), uri.c_str());
87 return Media::E_ERR;
88 }
89 printf("Table Name: %s\n", tableName.c_str());
90 std::shared_ptr<DataShare::DataShareResultSet> resultSet;
91 auto res = UserFileClientEx::Query(tableName, uri, resultSet);
92 std::shared_ptr<FetchResult<FileAsset>> fetchResult = std::make_shared<FetchResult<FileAsset>>(resultSet);
93 fetchResult->SetResultNapiType(ResultNapiType::TYPE_USERFILE_MGR);
94 if (res != Media::E_OK) {
95 printf("%s query issue. tableName:%s, uri:%s\n", STR_FAIL.c_str(), tableName.c_str(), uri.c_str());
96 return Media::E_ERR;
97 }
98 if (fetchResult == nullptr) {
99 return Media::E_OK;
100 }
101 auto count = fetchResult->GetCount();
102 if (count > 1) {
103 printf("%s get result count=%d, failed, uri:%s\n", STR_FAIL.c_str(), count, uri.c_str());
104 } else if (count == 0) {
105 printf("WARN: get result count 0, uri:%s\n", uri.c_str());
106 } else {
107 auto fileAsset = fetchResult->GetFirstObject();
108 RecvFile(env, *fileAsset);
109 }
110 fetchResult->Close();
111 return Media::E_OK;
112 }
113
RecvAssets(const ExecEnv & env,const std::string & tableName)114 static int32_t RecvAssets(const ExecEnv &env, const std::string &tableName)
115 {
116 if (tableName.empty()) {
117 printf("%s table name is empty.\n", STR_FAIL.c_str());
118 return Media::E_ERR;
119 }
120 printf("Table Name: %s\n", tableName.c_str());
121 std::shared_ptr<DataShare::DataShareResultSet> resultSet;
122 auto res = UserFileClientEx::Query(tableName, "", resultSet);
123 std::shared_ptr<FetchResult<FileAsset>> fetchResult = std::make_shared<FetchResult<FileAsset>>(resultSet);
124 fetchResult->SetResultNapiType(ResultNapiType::TYPE_USERFILE_MGR);
125 if (res != Media::E_OK) {
126 printf("%s query issue. tableName:%s\n", STR_FAIL.c_str(), tableName.c_str());
127 return Media::E_ERR;
128 }
129 if (fetchResult == nullptr) {
130 return Media::E_OK;
131 }
132 auto count = fetchResult->GetCount();
133 for (int32_t index = 0; index < count; index++) {
134 auto fileAsset = fetchResult->GetObjectAtPosition(index);
135 RecvFile(env, *fileAsset);
136 }
137 fetchResult->Close();
138 return Media::E_OK;
139 }
140
Start(const ExecEnv & env)141 int32_t RecvCommandV10::Start(const ExecEnv &env)
142 {
143 if (env.recvParam.isRecvAll) {
144 bool hasError = false;
145 auto tables = UserFileClientEx::GetSupportTables();
146 for (auto tableName : tables) {
147 if (RecvAssets(env, tableName) != Media::E_OK) {
148 hasError = true;
149 }
150 printf("\n");
151 }
152 return hasError ? Media::E_ERR : Media::E_OK;
153 } else {
154 string tableName = UserFileClientEx::GetTableNameByUri(env.recvParam.recvUri);
155 return RecvAsset(env, tableName, env.recvParam.recvUri);
156 }
157 }
158 } // namespace MediaTool
159 } // namespace Media
160 } // namespace OHOS
161