• 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 "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