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 <climits>
22 
23 #include <dirent.h>
24 #include <fcntl.h>
25 #include <sys/stat.h>
26 #include <sys/time.h>
27 #include <sys/types.h>
28 #include <unistd.h>
29 #if defined OS_TYPE_WINDOWS
30 #include <io.h>
31 #include <stdlib.h>
32 #include <windows.h>
33 #endif
34 
35 #include "db_errno.h"
36 #include "log_print.h"
37 #include "securec.h"
38 
39 namespace DistributedDB {
40 namespace OS {
41 /*
42  * Common part that is the same between each os
43  */
44 #if defined OS_TYPE_WINDOWS
45 namespace {
46     const int ACCESS_MODE_EXISTENCE = 0;
47 }
48 
49 struct FileHandle {
50     int handle = -1;
51 };
52 
CheckPathExistence(const std::string & filePath)53 bool CheckPathExistence(const std::string &filePath)
54 {
55     int ret = _access(filePath.c_str(), ACCESS_MODE_EXISTENCE);
56     LOGI("CheckPathExistence %s error:%d", filePath.c_str(), ret);
57     return (ret == 0);
58 }
59 
RenameFilePath(const std::string & oldFilePath,const std::string & newFilePath)60 int RenameFilePath(const std::string &oldFilePath, const std::string &newFilePath)
61 {
62     int errCode = rename(oldFilePath.c_str(), newFilePath.c_str());
63     if (errCode < 0) {
64         LOGE("[Rename] Rename file fail. err = %d", errno);
65         return -E_SYSTEM_API_FAIL;
66     }
67     LOGI("Rename file path successfully!");
68     return E_OK;
69 }
70 
RemoveFile(const std::string & filePath)71 int RemoveFile(const std::string &filePath)
72 {
73 #ifdef DB_DEBUG_ENV
74     LOGD("---> remove db filePath: %s", filePath.c_str());
75 #endif
76     int errCode = remove(filePath.c_str());
77     if (errCode < 0) {
78         LOGE("[RemoveFile] Remove file fail %s %d err = %d", filePath.c_str(), errCode, errno);
79         return -E_SYSTEM_API_FAIL;
80     }
81     LOGD("Remove file successfully!");
82     return E_OK;
83 }
84 
CalFileSize(const std::string & fileUrl,uint64_t & size)85 int CalFileSize(const std::string &fileUrl, uint64_t &size)
86 {
87     struct _stat64 fileStat;
88     if (fileUrl.empty() || _stat64(fileUrl.c_str(), &fileStat) < 0 || fileStat.st_size < 0) {
89         int errCode = (errno == ENOENT) ? -E_NOT_FOUND : -E_INVALID_DB;
90         LOGD("Get file[%zu] size failed, errno [%d].", fileUrl.size(), errno);
91         return errCode;
92     }
93 
94     size = static_cast<uint64_t>(fileStat.st_size);
95     return E_OK;
96 }
97 
SplitFilePath(const std::string & filePath,std::string & fileDir,std::string & fileName)98 void SplitFilePath(const std::string &filePath, std::string &fileDir, std::string &fileName)
99 {
100     if (filePath.empty()) {
101         return;
102     }
103 
104     auto slashPos = filePath.find_last_of('/');
105     if (slashPos == std::string::npos) {
106         fileName = filePath;
107         fileDir = "";
108         return;
109     }
110 
111     fileDir = filePath.substr(0, slashPos);
112     fileName = filePath.substr(slashPos + 1);
113     return;
114 }
115 
MakeDBDirectory(const std::string & directory)116 int MakeDBDirectory(const std::string &directory)
117 {
118     int errCode = mkdir(directory.c_str());
119     if (errCode < 0) {
120         // 3 means one-third
121         std::string str = directory.length() == 0 ? "empty directory path" :
122             directory.substr(0, directory.length() / 3) + "*****" + directory.substr((2 * directory.length()) / 3);
123         LOGE("[MakeDir] Make directory fail:%d, directory path: %s", errno, str.c_str());
124         return -E_SYSTEM_API_FAIL;
125     }
126     return E_OK;
127 }
128 
RemoveDBDirectory(const std::string & directory)129 int RemoveDBDirectory(const std::string &directory)
130 {
131 #ifdef DB_DEBUG_ENV
132     LOGD("---> remove db directory: %s", directory.c_str());
133 #endif
134     int ret = rmdir(directory.c_str());
135     LOGI("CheckPathExistence %s ret:%d error %d", directory.c_str(), ret, errno);
136     return ret;
137 }
138 
CreateFileByFileName(const std::string & fileName)139 int CreateFileByFileName(const std::string &fileName)
140 {
141     int fp = _open(fileName.c_str(), (O_WRONLY | O_CREAT), _S_IREAD | _S_IWRITE);
142     if (fp < 0) {
143         LOGE("[CreateFile] Create file fail:%d.", errno);
144         return -E_SYSTEM_API_FAIL;
145     }
146     close(fp);
147     return E_OK;
148 }
149 
GetRealPath(const std::string & inOriPath,std::string & outRealPath)150 int GetRealPath(const std::string &inOriPath, std::string &outRealPath)
151 {
152     const unsigned int MAX_PATH_LENGTH = PATH_MAX;
153     if (inOriPath.length() > MAX_PATH_LENGTH || MAX_PATH_LENGTH > 0x10000) { // max limit is 64K(0x10000).
154         LOGE("[RealPath] OriPath too long.");
155         return -E_INVALID_ARGS;
156     }
157 
158     char *realPath = new (std::nothrow) char[MAX_PATH_LENGTH + 1];
159     if (realPath == nullptr) {
160         return -E_OUT_OF_MEMORY;
161     }
162     if (memset_s(realPath, MAX_PATH_LENGTH + 1, 0, MAX_PATH_LENGTH + 1) != EOK) {
163         delete [] realPath;
164         return -E_SECUREC_ERROR;
165     }
166 
167     if (_fullpath(realPath, inOriPath.c_str(), MAX_PATH_LENGTH) == nullptr) {
168         LOGE("[OS] Realpath error:%d.", errno);
169         delete [] realPath;
170         return -E_SYSTEM_API_FAIL;
171     }
172     outRealPath = std::string(realPath);
173     delete [] realPath;
174     return E_OK;
175 }
176 #ifndef DB_DEBUG_ENV
177 namespace {
178     const uint64_t MULTIPLES_BETWEEN_MICROSECONDS_AND_NANOSECONDS = 1000;
179     const uint64_t MULTIPLES_BETWEEN_MICROSECONDS_AND_100_NANOSECONDS = 10;
180     const uint64_t MICROSECONDS_OFFSET = 11644473600000000;  // microseconds from January 1, 1601 to January 1, 1970
181     const uint64_t UINT32_BIT_LENGTH = 32;
182 }
183 
GetCurrentSysTimeInMicrosecond(uint64_t & outTime)184 int GetCurrentSysTimeInMicrosecond(uint64_t &outTime)
185 {
186     FILETIME rawTime;
187     GetSystemTimeAsFileTime(&rawTime);
188     outTime = ((static_cast<uint64_t>(rawTime.dwHighDateTime) << UINT32_BIT_LENGTH) +
189         (static_cast<uint64_t>(rawTime.dwLowDateTime))) / MULTIPLES_BETWEEN_MICROSECONDS_AND_100_NANOSECONDS -
190         MICROSECONDS_OFFSET;
191     return E_OK;
192 }
193 #endif  // DB_DEBUG_ENV
194 
GetMonotonicRelativeTimeInMicrosecond(uint64_t & outTime)195 int GetMonotonicRelativeTimeInMicrosecond(uint64_t &outTime)
196 {
197     LARGE_INTEGER frequency;
198     LARGE_INTEGER rawTime;
199     if (!QueryPerformanceFrequency(&frequency)) {
200         LOGE("query performance frequency fail %d", errno);
201         return -E_SYSTEM_API_FAIL;
202     }
203 
204     if (frequency.QuadPart == 0) {
205         LOGE("frequency quadpart zero!");
206         return -E_SYSTEM_API_FAIL;
207     }
208 
209     if (!QueryPerformanceCounter(&rawTime)) {
210         LOGE("query frequency counter fail %d!", errno);
211         return -E_SYSTEM_API_FAIL;
212     }
213 
214     outTime = (static_cast<uint64_t>(rawTime.QuadPart) * MULTIPLES_BETWEEN_MICROSECONDS_AND_NANOSECONDS) /
215         static_cast<uint64_t>(frequency.QuadPart);
216     return E_OK;
217 }
218 
InitFileType(const _finddata_t & file,FileAttr & fileAttr)219 static void InitFileType(const _finddata_t &file, FileAttr& fileAttr)
220 {
221     switch (file.attrib) {
222         case _A_NORMAL:
223         case _A_ARCH:
224             fileAttr.fileType = FILE;
225             return;
226         case _A_SUBDIR:
227             fileAttr.fileType = PATH;
228             return;
229         default:
230             fileAttr.fileType = OTHER;
231             return;
232     }
233 }
234 
GetFilePathAttr(const std::string & topPath,const std::string & relativePath,std::list<FileAttr> & files,bool isNeedAllPath)235 static int GetFilePathAttr(const std::string &topPath, const std::string &relativePath,
236     std::list<FileAttr> &files, bool isNeedAllPath)
237 {
238     _finddata_t file;
239     std::string findPath = std::string(topPath) + "\\*.*";
240     intptr_t handle = _findfirst(findPath.c_str(), &file);
241     if (handle < 0) {
242         LOGE("Open dir error:%s %d.", topPath.c_str(), errno);
243         return -E_INVALID_PATH;
244     }
245     int errCode = E_OK;
246     std::string fileAbsName;
247     struct _stat64 fileStat;
248     LOGE("find first file %s  %s relativePath %s", topPath.c_str(), file.name, relativePath.c_str());
249 
250     FileAttr fileAttr;
251     do {
252         InitFileType(file, fileAttr);
253 
254         if (strlen(file.name) == 0 || strcmp(file.name, ".") == 0 ||
255             strcmp(file.name, "..") == 0) {
256             continue;
257         }
258 
259         fileAttr.fileName = relativePath + file.name;
260         fileAbsName = topPath + "/" + file.name;
261         errCode = _stat64(fileAbsName.c_str(), &fileStat);
262         if (errCode != 0) {
263             LOGE("[GetFileAttr]Get file stat failed, %s error = %d.", fileAbsName.c_str(), errno);
264             errCode = -E_INVALID_PATH;
265             break;
266         }
267         if (isNeedAllPath) {
268             fileAttr.fileName = fileAbsName;
269         }
270         fileAttr.fileLen = static_cast<uint64_t>(fileStat.st_size);
271         files.push_back(fileAttr);
272         LOGE("find fileAbsName file %s %s %d relativePath %s", topPath.c_str(), file.name,
273              file.attrib, relativePath.c_str());
274         if (fileAttr.fileType == PATH) {
275             errCode = GetFilePathAttr(fileAbsName, relativePath + file.name + "/", files, isNeedAllPath);
276             if (errCode != E_OK) {
277                 LOGE("[GetFileAttr]GetFilePathAttr finish, %s error = %d.", topPath.c_str(), errCode);
278                 printf("GetFilePathAttr the finish %s error:%d\n", topPath.c_str(), errCode);
279                 break;
280             }
281         }
282     } while (_findnext(handle, &file) == 0);
283     _findclose(handle);
284     LOGE("[GetFileAttr]GetFilePathAttr finish, %s error = %d.", topPath.c_str(), errCode);
285     printf("GetFilePathAttr the finish end %s error:%d\n", topPath.c_str(), errCode);
286     return errCode;
287 }
288 
GetFileAttrFromPath(const std::string & filePath,std::list<FileAttr> & files,bool isNeedAllPath)289 int GetFileAttrFromPath(const std::string &filePath, std::list<FileAttr> &files, bool isNeedAllPath)
290 {
291     return GetFilePathAttr(filePath, std::string(), files, isNeedAllPath);
292 }
293 
GetFilePermissions(const std::string & fileName,uint32_t & permissions)294 int GetFilePermissions(const std::string &fileName, uint32_t &permissions)
295 {
296     struct _stat64 fileStat;
297     int errCode = _stat64(fileName.c_str(), &fileStat);
298     if (errCode != E_OK) {
299         permissions = _S_IREAD | _S_IWRITE;
300         LOGE("Get file stat failed, error = %d.", errno);
301         return -E_SYSTEM_API_FAIL;
302     }
303     permissions = fileStat.st_mode & (_S_IRWXU | _S_IFMT | _S_IFDIR | _S_IFCHR | _S_IFIFO | _S_IFREG);
304     return E_OK;
305 }
306 
SetFilePermissions(const std::string & fileName,uint32_t permissions)307 int SetFilePermissions(const std::string &fileName, uint32_t permissions)
308 {
309     if (permissions > (S_IRWXU | S_IRWXG | S_IRWXO)) {
310         return -E_INVALID_ARGS;
311     }
312     int errCode = _chmod(fileName.c_str(), _S_IREAD | _S_IWRITE);
313     if (errCode != E_OK) {
314         LOGE("Set file permissions failed, error = %d.", errno);
315         return -E_SYSTEM_API_FAIL;
316     }
317     return E_OK;
318 }
319 
OpenFile(const std::string & fileName,FileHandle * & fileHandle)320 int OpenFile(const std::string &fileName, FileHandle *&fileHandle)
321 {
322     fileHandle = new (std::nothrow)FileHandle;
323     if (fileHandle == nullptr) {
324         return -E_OUT_OF_MEMORY;
325     }
326     fileHandle->handle = _open(fileName.c_str(), (O_WRONLY | O_CREAT), _S_IREAD | _S_IWRITE);
327     if (fileHandle->handle < 0) {
328         LOGE("[FileLock] can not open file when lock it:[%d]", errno);
329         delete fileHandle;
330         fileHandle = nullptr;
331         return -E_SYSTEM_API_FAIL;
332     }
333     return E_OK;
334 }
335 
CloseFile(FileHandle * fileHandle)336 int CloseFile(FileHandle *fileHandle)
337 {
338     if (fileHandle == nullptr || fileHandle->handle == -1) {
339         LOGI("[CloseFile] file handle is invalid!");
340         return -E_INVALID_ARGS;
341     }
342 
343     if (close(fileHandle->handle) != 0) {
344         LOGE("close file failed, errno:%d", errno);
345         return -E_SYSTEM_API_FAIL;
346     }
347     delete fileHandle;
348     return E_OK;
349 }
350 
FileLock(const FileHandle * fileHandle,bool isBlock)351 int FileLock(const FileHandle *fileHandle, bool isBlock)
352 {
353     if (fileHandle == nullptr) {
354         return -E_INVALID_ARGS;
355     }
356     if (fileHandle->handle < 0) {
357         LOGE("[FileLock] can not open file when lock it:[%d]", errno);
358         return -E_SYSTEM_API_FAIL;
359     }
360     // windows下的LockFile与Linux差异较大,先不替换
361     return E_OK;
362 }
363 
FileUnlock(FileHandle * fileHandle)364 int FileUnlock(FileHandle *fileHandle)
365 {
366     return E_OK;
367 }
368 #else
369 namespace {
370     const int ACCESS_MODE_EXISTENCE = 0;
371     const uint64_t MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS = 1000000;
372 }
373 
374 struct FileHandle {
375     int handle = -1;
376 };
377 
378 bool CheckPathExistence(const std::string &filePath)
379 {
380     return (access(filePath.c_str(), ACCESS_MODE_EXISTENCE) == 0);
381 }
382 
383 int RenameFilePath(const std::string &oldFilePath, const std::string &newFilePath)
384 {
385     int errCode = rename(oldFilePath.c_str(), newFilePath.c_str());
386     if (errCode < 0) {
387         LOGE("[Rename] Rename file fail. err = %d", errno);
388         return -E_SYSTEM_API_FAIL;
389     }
390     LOGI("Rename file path successfully!");
391     return E_OK;
392 }
393 
394 int RemoveFile(const std::string &filePath)
395 {
396     int errCode = remove(filePath.c_str());
397     if (errCode < 0) {
398         LOGE("[RemoveFile] Remove file fail. err = %d", errno);
399         return -E_SYSTEM_API_FAIL;
400     }
401     LOGD("Remove file successfully!");
402     return E_OK;
403 }
404 
405 int CalFileSize(const std::string &fileUrl, uint64_t &size)
406 {
407     struct stat fileStat;
408     if (fileUrl.empty() || stat(fileUrl.c_str(), &fileStat) < 0 || fileStat.st_size < 0) {
409         int errCode = (errno == ENOENT) ? -E_NOT_FOUND : -E_INVALID_DB;
410         LOGD("Get file[%zu] size failed, errno [%d].", fileUrl.size(), errno);
411         return errCode;
412     }
413 
414     size = static_cast<uint64_t>(fileStat.st_size);
415     return E_OK;
416 }
417 
418 void SplitFilePath(const std::string &filePath, std::string &fileDir, std::string &fileName)
419 {
420     if (filePath.empty()) {
421         return;
422     }
423 
424     auto slashPos = filePath.find_last_of('/');
425     if (slashPos == std::string::npos) {
426         fileName = filePath;
427         fileDir = "";
428         return;
429     }
430 
431     fileDir = filePath.substr(0, slashPos);
432     fileName = filePath.substr(slashPos + 1);
433     return;
434 }
435 
436 int MakeDBDirectory(const std::string &directory)
437 {
438     int errCode = mkdir(directory.c_str(), (S_IRWXU | S_IRWXG)); // The permission is 770 for linux based os
439     if (errCode < 0) {
440         // 3 means one-third
441         std::string str = directory.length() == 0 ? "empty directory path" :
442             directory.substr(0, directory.length() / 3) + "*****" + directory.substr((2 * directory.length()) / 3);
443         LOGE("[MakeDir] Make directory fail:%d, directory path: %s", errno, str.c_str());
444         return -E_SYSTEM_API_FAIL;
445     }
446     return E_OK;
447 }
448 
449 int RemoveDBDirectory(const std::string &directory)
450 {
451     return remove(directory.c_str());
452 }
453 
454 int CreateFileByFileName(const std::string &fileName)
455 {
456     int fp = open(fileName.c_str(), (O_WRONLY | O_CREAT), (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP));
457     if (fp < 0) {
458         LOGE("[CreateFile] Create file fail:%d.", errno);
459         return -E_SYSTEM_API_FAIL;
460     }
461     close(fp);
462     return E_OK;
463 }
464 
465 int GetRealPath(const std::string &inOriPath, std::string &outRealPath)
466 {
467     const unsigned int MAX_PATH_LENGTH = PATH_MAX;
468     if (inOriPath.length() > MAX_PATH_LENGTH || MAX_PATH_LENGTH > 0x10000) { // max limit is 64K(0x10000).
469         LOGE("[RealPath] OriPath too long.");
470         return -E_INVALID_ARGS;
471     }
472 
473     char *realPath = new (std::nothrow) char[MAX_PATH_LENGTH + 1];
474     if (realPath == nullptr) {
475         return -E_OUT_OF_MEMORY;
476     }
477     if (memset_s(realPath, MAX_PATH_LENGTH + 1, 0, MAX_PATH_LENGTH + 1) != EOK) {
478         delete []realPath;
479         return -E_SECUREC_ERROR;
480     }
481 
482     if (realpath(inOriPath.c_str(), realPath) == nullptr) {
483         LOGE("[OS] Realpath error:%d.", errno);
484         delete []realPath;
485         return -E_SYSTEM_API_FAIL;
486     }
487     outRealPath = std::string(realPath);
488     delete []realPath;
489     return E_OK;
490 }
491 
492 #ifndef DB_DEBUG_ENV
493 int GetCurrentSysTimeInMicrosecond(uint64_t &outTime)
494 {
495     struct timeval rawTime;
496     int errCode = gettimeofday(&rawTime, nullptr);
497     if (errCode < 0) {
498         LOGE("[GetSysTime] Fail:%d.", errCode);
499         return -E_SYSTEM_API_FAIL;
500     }
501     outTime = static_cast<uint64_t>(rawTime.tv_sec) * MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS +
502               static_cast<uint64_t>(rawTime.tv_usec);
503     return E_OK;
504 }
505 #endif // DB_DEBUG_ENV
506 
507 namespace {
508     const uint64_t MULTIPLES_BETWEEN_MICROSECONDS_AND_NANOSECONDS = 1000;
509 }
510 
511 int GetMonotonicRelativeTimeInMicrosecond(uint64_t &outTime)
512 {
513     struct timespec rawTime;
514     clockid_t clockId = CLOCK_REALTIME;
515 #ifdef OS_TYPE_MAC
516     clockId = CLOCK_UPTIME_RAW;
517 #else
518     clockId = CLOCK_BOOTTIME;
519 #endif
520     int errCode = clock_gettime(clockId, &rawTime);
521     if (errCode < 0) {
522         LOGE("[GetMonoTime] Fail.");
523         return -E_SYSTEM_API_FAIL;
524     }
525 
526     outTime = static_cast<uint64_t>(rawTime.tv_sec) * MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS +
527               static_cast<uint64_t>(rawTime.tv_nsec) / MULTIPLES_BETWEEN_MICROSECONDS_AND_NANOSECONDS;
528     return E_OK;
529 }
530 
531 static int GetFilePathAttr(const std::string &topPath, const std::string &relativePath,
532                            std::list<FileAttr> &files, bool isNeedAllPath)
533 {
534     DIR *dir = opendir(topPath.c_str());
535     if (dir == nullptr) {
536         LOGE("Open dir error:%d.", errno);
537         return -E_INVALID_PATH;
538     }
539     struct stat fileStat;
540     std::string fileAbsName;
541     int errCode = E_OK;
542     FileAttr file;
543     for (struct dirent *fileDirInfo = readdir(dir); fileDirInfo != nullptr; fileDirInfo = readdir(dir)) {
544         switch (fileDirInfo->d_type) {
545             case DT_REG:
546                 file.fileType = FILE;
547                 break;
548             case DT_DIR:
549                 file.fileType = PATH;
550                 break;
551             default:
552                 file.fileType = OTHER;
553         }
554         if (strlen(fileDirInfo->d_name) == 0 || strcmp(fileDirInfo->d_name, ".") == 0 ||
555             strcmp(fileDirInfo->d_name, "..") == 0) {
556             continue;
557         }
558         file.fileName = relativePath + fileDirInfo->d_name;
559         fileAbsName = topPath + "/" + fileDirInfo->d_name;
560         errCode = stat(fileAbsName.c_str(), &fileStat);
561         if (errCode != 0) {
562             LOGE("[GetFileAttr]Get file stat failed, error = %d.", errno);
563             errCode = -E_INVALID_PATH;
564             break;
565         }
566         if (isNeedAllPath) {
567             file.fileName = fileAbsName;
568         }
569         file.fileLen = static_cast<uint64_t>(fileStat.st_size);
570         files.push_back(file);
571         if (file.fileType == PATH) {
572             errCode = GetFilePathAttr(fileAbsName, relativePath + fileDirInfo->d_name + "/", files, isNeedAllPath);
573             if (errCode != E_OK) {
574                 break;
575             }
576         }
577     }
578 
579     closedir(dir);
580     return errCode;
581 }
582 
583 int GetFileAttrFromPath(const std::string &filePath, std::list<FileAttr> &files, bool isNeedAllPath)
584 {
585     return GetFilePathAttr(filePath, std::string(), files, isNeedAllPath);
586 }
587 
588 int GetFilePermissions(const std::string &fileName, uint32_t &permissions)
589 {
590     struct stat fileStat;
591     int errCode = stat(fileName.c_str(), &fileStat);
592     if (errCode != E_OK) {
593         permissions = S_IRUSR | S_IWUSR;
594         LOGE("Get file stat failed, error = %d.", errno);
595         return -E_SYSTEM_API_FAIL;
596     }
597     permissions = fileStat.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
598     return E_OK;
599 }
600 
601 int SetFilePermissions(const std::string &fileName, uint32_t permissions)
602 {
603     if (permissions > (S_IRWXU | S_IRWXG | S_IRWXO)) {
604         return -E_INVALID_ARGS;
605     }
606     int errCode = chmod(fileName.c_str(), permissions);
607     if (errCode != E_OK) {
608         LOGE("Set file permissions failed, error = %d.", errno);
609         return -E_SYSTEM_API_FAIL;
610     }
611     return E_OK;
612 }
613 
614 int OpenFile(const std::string &fileName, FileHandle *&fileHandle)
615 {
616     fileHandle = new (std::nothrow)FileHandle;
617     if (fileHandle == nullptr) {
618         return -E_OUT_OF_MEMORY;
619     }
620     fileHandle->handle = open(fileName.c_str(), (O_WRONLY | O_CREAT), (S_IRUSR | S_IWUSR | S_IRGRP));
621     if (fileHandle->handle < 0) {
622         LOGE("[FileLock] can not open file when lock it:[%d], filename: %s", errno, fileName.c_str());
623         delete fileHandle;
624         fileHandle = nullptr;
625         return -E_SYSTEM_API_FAIL;
626     }
627     return E_OK;
628 }
629 
630 int CloseFile(FileHandle *fileHandle)
631 {
632     if (fileHandle == nullptr || fileHandle->handle == -1) {
633         LOGI("[CloseFile] file handle is invalid!");
634         return -E_INVALID_ARGS;
635     }
636     if (close(fileHandle->handle) != 0) {
637         LOGE("close file failed, errno:%d", errno);
638         return -E_SYSTEM_API_FAIL;
639     }
640     delete fileHandle;
641     return E_OK;
642 }
643 
644 int FileLock(const FileHandle *fileHandle, bool isBlock)
645 {
646     if (fileHandle == nullptr) {
647         return -E_INVALID_ARGS;
648     }
649     if (fileHandle->handle < 0) {
650         LOGE("[FileLock] can not open file when lock it:[%d]", errno);
651         return -E_SYSTEM_API_FAIL;
652     }
653 
654     struct flock fileLockInfo;
655     (void)memset_s(&fileLockInfo, sizeof(fileLockInfo), 0, sizeof(fileLockInfo));
656     fileLockInfo.l_type = F_WRLCK;
657     fileLockInfo.l_whence = SEEK_SET;
658     fileLockInfo.l_start = 0;
659     fileLockInfo.l_len = 0;
660     LOGD("Lock file isBlock[%d]", isBlock);
661     if (fcntl(fileHandle->handle, isBlock ? F_SETLKW : F_SETLK, &fileLockInfo) == -1 && !isBlock) {
662         LOGD("Lock file is Blocked, please retry!");
663         return -E_BUSY;
664     }
665     LOGI("file locked! errno:%d", errno);
666     return E_OK;
667 }
668 
669 int FileUnlock(FileHandle *fileHandle)
670 {
671     if (fileHandle == nullptr || fileHandle->handle == -1) {
672         LOGI("[FileUnlock] file handle is invalid!");
673         return E_OK;
674     }
675 
676     struct flock fileLockInfo;
677     (void)memset_s(&fileLockInfo, sizeof(fileLockInfo), 0, sizeof(fileLockInfo));
678     fileLockInfo.l_type = F_UNLCK;
679     fileLockInfo.l_whence = SEEK_SET;
680     fileLockInfo.l_start = 0;
681     fileLockInfo.l_len = 0;
682     if (fcntl(fileHandle->handle, F_SETLK, &fileLockInfo) == -1) {
683         LOGE("Unlock file failed. errno:%d", errno);
684         return -E_SYSTEM_API_FAIL;
685     }
686     return E_OK;
687 }
688 #endif
689 } // namespace OS
690 } // namespace DistributedDB
691