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