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