1 /*
2  * Copyright (c) 2023-2024 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 #define FUSE_USE_VERSION 34
17 
18 #include "clouddisk_rdb_utils.h"
19 
20 #include <fuse_lowlevel.h>
21 
22 #include "utils_log.h"
23 #include "dfs_error.h"
24 #include "clouddisk_db_const.h"
25 #include "file_column.h"
26 #include "result_set.h"
27 
28 namespace OHOS::FileManagement::CloudDisk {
29 using namespace std;
30 using namespace NativeRdb;
31 
32 static const int32_t LOCAL_ID_OFFSET = 100;
33 static const uint32_t STAT_MODE_REG = 0660;
34 static const uint32_t STAT_MODE_DIR = 0771;
35 
GetInt(const string & key,int32_t & val,const shared_ptr<ResultSet> resultSet)36 int32_t CloudDiskRdbUtils::GetInt(const string &key, int32_t &val,
37                                   const shared_ptr<ResultSet> resultSet)
38 {
39     int32_t index;
40     int32_t err = resultSet->GetColumnIndex(key, index);
41     if (err != E_OK) {
42         LOGE("result set get column index err %{public}d", err);
43         return E_RDB;
44     }
45     err = resultSet->GetInt(index, val);
46     if (err != 0) {
47         LOGE("result set get int err %{public}d", err);
48         return E_RDB;
49     }
50     return E_OK;
51 }
52 
GetLong(const string & key,int64_t & val,const shared_ptr<ResultSet> resultSet)53 int32_t CloudDiskRdbUtils::GetLong(const string &key, int64_t &val,
54                                    const shared_ptr<ResultSet> resultSet)
55 {
56     int32_t index;
57     int32_t err = resultSet->GetColumnIndex(key, index);
58     if (err != E_OK) {
59         LOGE("result set get column index err %{public}d", err);
60         return E_RDB;
61     }
62     err = resultSet->GetLong(index, val);
63     if (err != 0) {
64         LOGE("result set get int err %{public}d", err);
65         return E_RDB;
66     }
67     return E_OK;
68 }
69 
GetString(const string & key,string & val,const shared_ptr<ResultSet> resultSet)70 int32_t CloudDiskRdbUtils::GetString(const string &key, string &val,
71                                      const shared_ptr<ResultSet> resultSet)
72 {
73     int32_t index;
74     int32_t err = resultSet->GetColumnIndex(key, index);
75     if (err != E_OK) {
76         LOGE("result set get column index err %{public}d", err);
77         return E_RDB;
78     }
79     err = resultSet->GetString(index, val);
80     if (err != 0) {
81         LOGE("result set get string err %{public}d", err);
82         return E_RDB;
83     }
84     return E_OK;
85 }
86 
FillFileInfo(const RowEntity & rowEntity,CloudDiskFileInfo & info)87 static void FillFileInfo(const RowEntity &rowEntity, CloudDiskFileInfo &info)
88 {
89     rowEntity.Get(FileColumn::FILE_NAME).GetString(info.name);
90     rowEntity.Get(FileColumn::CLOUD_ID).GetString(info.cloudId);
91     rowEntity.Get(FileColumn::PARENT_CLOUD_ID).GetString(info.parentCloudId);
92     int32_t int_variable;
93     rowEntity.Get(FileColumn::POSITION).GetInt(int_variable);
94     info.location = static_cast<uint32_t>(int_variable);
95     int64_t long_variable;
96     rowEntity.Get(FileColumn::FILE_SIZE).GetLong(long_variable);
97     info.size = static_cast<unsigned long long>(long_variable);
98     rowEntity.Get(FileColumn::FILE_TIME_ADDED).GetLong(long_variable);
99     info.atime = static_cast<unsigned long long>(long_variable);
100     rowEntity.Get(FileColumn::META_TIME_EDITED).GetLong(long_variable);
101     info.ctime = static_cast<unsigned long long>(long_variable);
102     rowEntity.Get(FileColumn::FILE_TIME_EDITED).GetLong(long_variable);
103     info.mtime = static_cast<unsigned long long>(long_variable);
104     rowEntity.Get(FileColumn::IS_DIRECTORY).GetInt(int_variable);
105     info.IsDirectory = (int_variable == DIRECTORY);
106     info.mode = (info.IsDirectory) ? (S_IFDIR | STAT_MODE_DIR) : (S_IFREG | STAT_MODE_REG);
107     rowEntity.Get(FileColumn::ROW_ID).GetLong(long_variable);
108     info.localId = static_cast<long long>(long_variable) + LOCAL_ID_OFFSET;
109 }
110 
ResultSetToFileInfo(const shared_ptr<ResultSet> resultSet,CloudDiskFileInfo & info)111 int32_t CloudDiskRdbUtils::ResultSetToFileInfo(const shared_ptr<ResultSet> resultSet,
112                                                CloudDiskFileInfo &info)
113 {
114     if (resultSet == nullptr) {
115         LOGE("result set is nullptr");
116         return E_RDB;
117     }
118     if (resultSet->GoToNextRow() != E_OK) {
119         LOGE("result set to file info go to next row failed");
120         return E_RDB;
121     }
122     RowEntity rowEntity;
123     if (resultSet->GetRow(rowEntity) != E_OK) {
124         LOGE("result set to file info get row failed");
125         return E_RDB;
126     }
127     FillFileInfo(rowEntity, info);
128     return E_OK;
129 }
130 
FuseDentryAlignSize(const char * name)131 size_t CloudDiskRdbUtils::FuseDentryAlignSize(const char *name)
132 {
133     return fuse_add_direntry({}, nullptr, 0, name, nullptr, 0);
134 }
135 
ResultSetToFileInfos(const shared_ptr<ResultSet> resultSet,vector<CloudDiskFileInfo> & infos)136 int32_t CloudDiskRdbUtils::ResultSetToFileInfos(const shared_ptr<ResultSet> resultSet,
137                                                 vector<CloudDiskFileInfo> &infos)
138 {
139     if (resultSet == nullptr) {
140         LOGE("result set is nullptr");
141         return E_RDB;
142     }
143     off_t nextOff = 0;
144     while (resultSet->GoToNextRow() == E_OK) {
145         CloudDiskFileInfo info;
146         GetString(FileColumn::FILE_NAME, info.name, resultSet);
147         int32_t isDirectory;
148         GetInt(FileColumn::IS_DIRECTORY, isDirectory, resultSet);
149         info.IsDirectory = (isDirectory == DIRECTORY);
150         info.mode = (info.IsDirectory) ? (S_IFDIR | STAT_MODE_DIR) : (S_IFREG | STAT_MODE_REG);
151         nextOff += FuseDentryAlignSize(info.name.c_str());
152         info.nextOff = nextOff;
153         infos.emplace_back(info);
154     }
155     return E_OK;
156 }
157 }