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