1 /*
2 * Copyright (c) 2023 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 "preferences_file_lock.h"
17
18 #include <fcntl.h>
19 #include <sys/stat.h>
20 #include <unistd.h>
21
22 #include <cerrno>
23 #include <cstdio>
24 #include <thread>
25
26 #include "log_print.h"
27 namespace OHOS {
28 namespace NativePreferences {
29
30 #if !defined(WINDOWS_PLATFORM)
31 static const std::chrono::microseconds WAIT_CONNECT_TIMEOUT(20);
32 static const int ATTEMPTS = 5;
33
PreferencesFileLock()34 PreferencesFileLock::PreferencesFileLock()
35 {
36 }
37
~PreferencesFileLock()38 PreferencesFileLock::~PreferencesFileLock()
39 {
40 if (fd_ > 0) {
41 close(fd_);
42 }
43 }
44
TryLock(const std::string & fileName)45 int PreferencesFileLock::TryLock(const std::string &fileName)
46 {
47 int fd = open(fileName.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
48 if (fd == -1) {
49 LOG_ERROR("Couldn't open file %{public}s errno %{public}d.", fileName.c_str(), errno);
50 return (errno == EACCES) ? PERMISSION_DENIED : E_ERROR;
51 }
52 struct flock fileLockInfo = { 0 };
53 fileLockInfo.l_type = F_WRLCK;
54 fileLockInfo.l_whence = SEEK_SET;
55 fileLockInfo.l_start = 0;
56 fileLockInfo.l_len = 0;
57
58 for (size_t i = 0; i < ATTEMPTS; ++i) {
59 if (fcntl(fd, F_SETLK, &fileLockInfo) != -1) {
60 fd_ = fd;
61 return E_OK;
62 }
63 std::this_thread::sleep_for(WAIT_CONNECT_TIMEOUT);
64 }
65 close(fd);
66 return E_ERROR;
67 }
68
UnLock()69 int PreferencesFileLock::UnLock()
70 {
71 int errCode = E_OK;
72 if (fd_ > 0) {
73 struct flock fileLockInfo = { 0 };
74 fileLockInfo.l_type = F_UNLCK;
75 fileLockInfo.l_whence = SEEK_SET;
76 fileLockInfo.l_start = 0;
77 fileLockInfo.l_len = 0;
78 if (fcntl(fd_, F_SETLK, &fileLockInfo) == -1) {
79 LOG_ERROR("failed to release file lock error %{public}d.", errno);
80 errCode = E_ERROR;
81 }
82 close(fd_);
83 fd_ = -1;
84 }
85 return errCode;
86 }
87
88 #else
89
90 PreferencesFileLock::PreferencesFileLock()
91 {
92 fd_ = -1;
93 }
94
95 PreferencesFileLock::~PreferencesFileLock()
96 {
97 }
98
99 int PreferencesFileLock::TryLock(const std::string &fileName)
100 {
101 return E_OK;
102 }
103
104 int PreferencesFileLock::UnLock()
105 {
106 return E_OK;
107 }
108 #endif
109 } // End of namespace NativePreferences
110 } // End of namespace OHOS