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