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