• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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