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 "platform_specific.h"
17
18 #include <ctime>
19 #include <cstdlib>
20 #include <cstring>
21 #include <unistd.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <linux/limits.h>
25 #include <sys/time.h>
26 #include <fcntl.h>
27 #include <dirent.h>
28
29 #include "securec.h"
30 #include "db_errno.h"
31 #include "log_print.h"
32
33 namespace DistributedDB {
34 namespace OS {
35 /*
36 * Common part that is the same between each os
37 */
38 namespace {
39 const int ACCESS_MODE_EXISTENCE = 0;
40 const uint64_t MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS = 1000000;
41 }
CheckPathExistence(const std::string & filePath)42 bool CheckPathExistence(const std::string &filePath)
43 {
44 if (access(filePath.c_str(), ACCESS_MODE_EXISTENCE) < 0) {
45 return false;
46 }
47 return true;
48 }
49
RenameFilePath(const std::string & oldFilePath,const std::string & newFilePath)50 int RenameFilePath(const std::string &oldFilePath, const std::string &newFilePath)
51 {
52 int errCode = rename(oldFilePath.c_str(), newFilePath.c_str());
53 if (errCode < 0) {
54 LOGE("[Rename] Rename file fail. err = %d", errno);
55 return -E_SYSTEM_API_FAIL;
56 }
57 LOGI("Rename file path successfully!");
58 return E_OK;
59 }
60
RemoveFile(const std::string & filePath)61 int RemoveFile(const std::string &filePath)
62 {
63 int errCode = remove(filePath.c_str());
64 if (errCode < 0) {
65 LOGE("[RemoveFile] Remove file fail. err = %d", errno);
66 return -E_SYSTEM_API_FAIL;
67 }
68 LOGI("Remove file successfully!");
69 return E_OK;
70 }
71
CalFileSize(const std::string & fileUrl,uint64_t & size)72 int CalFileSize(const std::string &fileUrl, uint64_t &size)
73 {
74 struct stat fileStat;
75 if (fileUrl.empty() || stat(fileUrl.c_str(), &fileStat) < 0 || fileStat.st_size < 0) {
76 int errCode = (errno == ENOENT) ? -E_NOT_FOUND : -E_INVALID_DB;
77 LOGD("Get file[%zu] size failed, errno [%d].", fileUrl.size(), errno);
78 return errCode;
79 }
80
81 size = static_cast<uint64_t>(fileStat.st_size);
82 return E_OK;
83 }
84
SplitFilePath(const std::string & filePath,std::string & fileDir,std::string & fileName)85 void SplitFilePath(const std::string &filePath, std::string &fileDir, std::string &fileName)
86 {
87 if (filePath.empty()) {
88 return;
89 }
90
91 auto slashPos = filePath.find_last_of('/');
92 if (slashPos == std::string::npos) {
93 fileName = filePath;
94 fileDir = "";
95 return;
96 }
97
98 fileDir = filePath.substr(0, slashPos);
99 fileName = filePath.substr(slashPos + 1);
100 return;
101 }
102
MakeDBDirectory(const std::string & directory)103 int MakeDBDirectory(const std::string &directory)
104 {
105 int errCode = mkdir(directory.c_str(), (S_IRWXU | S_IRGRP | S_IXGRP)); // The permission is 750 for linux based os
106 if (errCode < 0) {
107 LOGE("[MakeDir] Make directory fail:%d.", errno);
108 return -E_SYSTEM_API_FAIL;
109 }
110 return E_OK;
111 }
112
RemoveDBDirectory(const std::string & directory)113 int RemoveDBDirectory(const std::string &directory)
114 {
115 return remove(directory.c_str());
116 }
117
CreateFileByFileName(const std::string & fileName)118 int CreateFileByFileName(const std::string &fileName)
119 {
120 int fp = open(fileName.c_str(), (O_WRONLY | O_CREAT), (S_IRUSR | S_IWUSR | S_IRGRP));
121 if (fp < 0) {
122 LOGE("[CreateFile] Create file fail:%d.", errno);
123 return -E_SYSTEM_API_FAIL;
124 }
125 close(fp);
126 return E_OK;
127 }
128
GetRealPath(const std::string & inOriPath,std::string & outRealPath)129 int GetRealPath(const std::string &inOriPath, std::string &outRealPath)
130 {
131 const unsigned int MAX_PATH_LENGTH = PATH_MAX;
132 if (inOriPath.length() > MAX_PATH_LENGTH || MAX_PATH_LENGTH > 0x10000) { // max limit is 64K(0x10000).
133 LOGE("[RealPath] OriPath too long.");
134 return -E_INVALID_ARGS;
135 }
136
137 char *realPath = new (std::nothrow) char[MAX_PATH_LENGTH + 1];
138 if (realPath == nullptr) {
139 return -E_OUT_OF_MEMORY;
140 }
141 if (memset_s(realPath, MAX_PATH_LENGTH + 1, 0, MAX_PATH_LENGTH + 1) != EOK) {
142 delete []realPath;
143 return -E_SECUREC_ERROR;
144 }
145
146 if (realpath(inOriPath.c_str(), realPath) == nullptr) {
147 LOGE("[OS] Realpath error:%d.", errno);
148 delete []realPath;
149 return -E_SYSTEM_API_FAIL;
150 }
151 outRealPath = std::string(realPath);
152 delete []realPath;
153 return E_OK;
154 }
155
GetCurrentSysTimeInMicrosecond(uint64_t & outTime)156 int GetCurrentSysTimeInMicrosecond(uint64_t &outTime)
157 {
158 struct timeval rawTime;
159 int errCode = gettimeofday(&rawTime, nullptr);
160 if (errCode < 0) {
161 LOGE("[GetSysTime] Fail:%d.", errCode);
162 return -E_SYSTEM_API_FAIL;
163 }
164 outTime = static_cast<uint64_t>(rawTime.tv_sec) * MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS +
165 static_cast<uint64_t>(rawTime.tv_usec);
166 return E_OK;
167 }
168
169 namespace {
170 const uint64_t MULTIPLES_BETWEEN_MICROSECONDS_AND_NANOSECONDS = 1000;
171 }
172
GetMonotonicRelativeTimeInMicrosecond(uint64_t & outTime)173 int GetMonotonicRelativeTimeInMicrosecond(uint64_t &outTime)
174 {
175 struct timespec rawTime;
176 int errCode = clock_gettime(CLOCK_BOOTTIME, &rawTime);
177 if (errCode < 0) {
178 LOGE("[GetMonoTime] Fail.");
179 return -E_SYSTEM_API_FAIL;
180 }
181 outTime = static_cast<uint64_t>(rawTime.tv_sec) * MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS +
182 static_cast<uint64_t>(rawTime.tv_nsec) / MULTIPLES_BETWEEN_MICROSECONDS_AND_NANOSECONDS;
183 return E_OK;
184 }
185
GetFilePathAttr(const std::string & topPath,const std::string & relativePath,std::list<FileAttr> & files,bool isNeedAllPath)186 static int GetFilePathAttr(const std::string &topPath, const std::string &relativePath,
187 std::list<FileAttr> &files, bool isNeedAllPath)
188 {
189 DIR *dir = opendir(topPath.c_str());
190 if (dir == nullptr) {
191 LOGE("Open dir error:%d.", errno);
192 return -E_INVALID_PATH;
193 }
194 struct stat fileStat;
195 std::string fileAbsName;
196 int errCode = E_OK;
197 FileAttr file;
198 for (struct dirent *fileDirInfo = readdir(dir); fileDirInfo != nullptr; fileDirInfo = readdir(dir)) {
199 switch (fileDirInfo->d_type) {
200 case DT_REG:
201 file.fileType = FILE;
202 break;
203 case DT_DIR:
204 file.fileType = PATH;
205 break;
206 default:
207 file.fileType = OTHER;
208 }
209 if (strlen(fileDirInfo->d_name) == 0 || strcmp(fileDirInfo->d_name, ".") == 0 ||
210 strcmp(fileDirInfo->d_name, "..") == 0) {
211 continue;
212 }
213 file.fileName = relativePath + fileDirInfo->d_name;
214 fileAbsName = topPath + "/" + fileDirInfo->d_name;
215 errCode = stat(fileAbsName.c_str(), &fileStat);
216 if (errCode != 0) {
217 LOGE("[GetFileAttr]Get file stat failed, error = %d.", errno);
218 errCode = -E_INVALID_PATH;
219 break;
220 }
221 if (isNeedAllPath) {
222 file.fileName = fileAbsName;
223 }
224 file.fileLen = static_cast<uint64_t>(fileStat.st_size);
225 files.push_back(file);
226 if (file.fileType == PATH) {
227 errCode = GetFilePathAttr(fileAbsName, relativePath + fileDirInfo->d_name + "/", files, isNeedAllPath);
228 if (errCode != E_OK) {
229 break;
230 }
231 }
232 }
233
234 closedir(dir);
235 return errCode;
236 }
237
GetFileAttrFromPath(const std::string & filePath,std::list<FileAttr> & files,bool isNeedAllPath)238 int GetFileAttrFromPath(const std::string &filePath, std::list<FileAttr> &files, bool isNeedAllPath)
239 {
240 return GetFilePathAttr(filePath, std::string(), files, isNeedAllPath);
241 }
242
GetFilePermissions(const std::string & fileName,uint32_t & permissions)243 int GetFilePermissions(const std::string &fileName, uint32_t &permissions)
244 {
245 struct stat fileStat;
246 int errCode = stat(fileName.c_str(), &fileStat);
247 if (errCode != E_OK) {
248 permissions = S_IRUSR | S_IWUSR;
249 LOGE("Get file stat failed, error = %d.", errno);
250 return -E_SYSTEM_API_FAIL;
251 }
252 permissions = fileStat.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
253 return E_OK;
254 }
255
SetFilePermissions(const std::string & fileName,uint32_t permissions)256 int SetFilePermissions(const std::string &fileName, uint32_t permissions)
257 {
258 if (permissions > (S_IRWXU | S_IRWXG | S_IRWXO)) {
259 return -E_INVALID_ARGS;
260 }
261 int errCode = chmod(fileName.c_str(), permissions);
262 if (errCode != E_OK) {
263 LOGE("Set file permissions failed, error = %d.", errno);
264 return -E_SYSTEM_API_FAIL;
265 }
266 return E_OK;
267 }
268
OpenFile(const std::string & fileName,FileHandle & handle)269 int OpenFile(const std::string &fileName, FileHandle &handle)
270 {
271 handle.handle = open(fileName.c_str(), (O_WRONLY | O_CREAT), (S_IRUSR | S_IWUSR | S_IRGRP));
272 if (handle.handle < 0) {
273 LOGE("[FileLock] can not open file when lock it:[%d]", errno);
274 return -E_SYSTEM_API_FAIL;
275 }
276 return E_OK;
277 }
278
CloseFile(FileHandle & handle)279 int CloseFile(FileHandle &handle)
280 {
281 if (close(handle.handle) != 0) {
282 LOGE("close file failed, errno:%d", errno);
283 return -E_SYSTEM_API_FAIL;
284 }
285 handle.handle = -1;
286 return E_OK;
287 }
288
FileLock(const FileHandle & handle,bool isBlock)289 int FileLock(const FileHandle &handle, bool isBlock)
290 {
291 if (handle.handle < 0) {
292 LOGE("[FileLock] can not open file when lock it:[%d]", errno);
293 return -E_SYSTEM_API_FAIL;
294 }
295
296 struct flock fileLockInfo;
297 (void)memset_s(&fileLockInfo, sizeof(fileLockInfo), 0, sizeof(fileLockInfo));
298 fileLockInfo.l_type = F_WRLCK;
299 fileLockInfo.l_whence = SEEK_SET;
300 fileLockInfo.l_start = 0;
301 fileLockInfo.l_len = 0;
302 LOGD("Lock file isBlock[%d]", isBlock);
303 if (fcntl(handle.handle, isBlock ? F_SETLKW : F_SETLK, &fileLockInfo) == -1 && !isBlock) {
304 LOGD("Lock file is Blocked, please retry!");
305 return -E_BUSY;
306 }
307 LOGI("file locked! errno:%d", errno);
308 return E_OK;
309 }
310
FileUnlock(FileHandle & handle)311 int FileUnlock(FileHandle &handle)
312 {
313 if (handle.handle == -1) {
314 LOGI("[FileUnlock] file handle is invalid!");
315 return E_OK;
316 }
317
318 struct flock fileLockInfo;
319 (void)memset_s(&fileLockInfo, sizeof(fileLockInfo), 0, sizeof(fileLockInfo));
320 fileLockInfo.l_type = F_UNLCK;
321 fileLockInfo.l_whence = SEEK_SET;
322 fileLockInfo.l_start = 0;
323 fileLockInfo.l_len = 0;
324 if (fcntl(handle.handle, F_SETLK, &fileLockInfo) == -1) {
325 LOGE("Unlock file failed. errno:%d", errno);
326 return -E_SYSTEM_API_FAIL;
327 }
328 return CloseFile(handle);
329 }
330 } // namespace OS
331 } // namespace DistributedDB
332