• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "hks_storage_file_lock.h"
17 
18 #include <stdbool.h>
19 #include <stdlib.h>
20 #include <string.h>
21 
22 #include "hks_lock.h"
23 #include "hks_mem.h"
24 #include "hks_mutex.h"
25 #include "hks_template.h"
26 #include "securec.h"
27 
28 struct HksStorageFileLock {
29     char *path;
30     HksLock *lock;
31     uint32_t ref;
32     HksStorageFileLock *next;
33 };
34 
35 static HksStorageFileLock *g_lockListFirst = NULL;
36 static HksStorageFileLock *g_lockListLast = NULL;
37 static HksMutex *g_lockListLock = NULL;
38 
FreeFileLock(HksStorageFileLock * lock)39 static void FreeFileLock(HksStorageFileLock *lock)
40 {
41     HKS_IF_NULL_RETURN_VOID(lock)
42 
43     if (lock->path) {
44         HKS_FREE(lock->path);
45         lock->path = NULL;
46     }
47 
48     if (lock->lock) {
49         HksLockClose(lock->lock);
50         lock->lock = NULL;
51     }
52 
53     HKS_FREE(lock);
54 }
55 
ClearLockList(void)56 static void ClearLockList(void)
57 {
58     HKS_IF_NULL_RETURN_VOID(g_lockListFirst)
59 
60     HksStorageFileLock *iter = g_lockListFirst;
61     HksStorageFileLock *temp = NULL;
62     while (iter != NULL) {
63         temp = iter->next;
64         FreeFileLock(iter);
65         iter = temp;
66     }
67 
68     g_lockListFirst = NULL;
69     g_lockListLast = NULL;
70 }
71 
FindFileLock(const char * path)72 static HksStorageFileLock *FindFileLock(const char *path)
73 {
74     HksStorageFileLock *iter = g_lockListFirst;
75     while (iter != NULL) {
76         if (strcmp(path, iter->path) == 0) {
77             return iter;
78         } else {
79             iter = iter->next;
80         }
81     }
82     return NULL;
83 }
84 
AllocFileLock(const char * path)85 static HksStorageFileLock *AllocFileLock(const char *path)
86 {
87     HksStorageFileLock *lock = HksMalloc(sizeof(HksStorageFileLock));
88     HKS_IF_NULL_RETURN(lock, NULL)
89 
90     size_t len = strlen(path);
91     lock->path = HksMalloc(len + 1);
92     if (lock->path == NULL) {
93         FreeFileLock(lock);
94         return NULL;
95     }
96     if (strcpy_s(lock->path, len + 1, path) != EOK) {
97         FreeFileLock(lock);
98         return NULL;
99     }
100     lock->lock = HksLockCreate();
101     lock->ref = 1;
102     lock->next = NULL;
103     if (lock->path == NULL || lock->lock == NULL) {
104         FreeFileLock(lock);
105         return NULL;
106     }
107     return lock;
108 }
109 
AddRef(HksStorageFileLock * lock)110 static void AddRef(HksStorageFileLock *lock)
111 {
112     HKS_IF_NULL_RETURN_VOID(lock)
113     lock->ref++;
114 }
115 
AppendFileLock(HksStorageFileLock * lock)116 static void AppendFileLock(HksStorageFileLock *lock)
117 {
118     if (g_lockListFirst == NULL) {
119         g_lockListFirst = lock;
120         g_lockListFirst->next = NULL;
121         g_lockListLast = lock;
122         return;
123     }
124 
125     if (g_lockListLast != NULL) {
126         g_lockListLast->next = lock;
127         g_lockListLast = lock;
128         g_lockListLast->next = NULL;
129     }
130 }
131 
HksStorageFileLockCreate(const char * path)132 HksStorageFileLock *HksStorageFileLockCreate(const char *path)
133 {
134     HKS_IF_TRUE_RETURN(path == NULL || g_lockListLock == NULL ||
135         HksMutexLock(g_lockListLock) != 0, NULL)
136     HksStorageFileLock *lock = FindFileLock(path);
137     if (lock == NULL) {
138         lock = AllocFileLock(path);
139         if (lock != NULL) {
140             AppendFileLock(lock);
141         }
142     } else {
143         AddRef(lock);
144     }
145     (void)HksMutexUnlock(g_lockListLock);
146 
147     return lock;
148 }
149 
HksStorageFileLockRead(HksStorageFileLock * lock)150 int32_t HksStorageFileLockRead(HksStorageFileLock *lock)
151 {
152     HKS_IF_NULL_RETURN(lock, -1)
153 
154     return HksLockLockRead(lock->lock);
155 }
156 
HksStorageFileUnlockRead(HksStorageFileLock * lock)157 int32_t HksStorageFileUnlockRead(HksStorageFileLock *lock)
158 {
159     HKS_IF_NULL_RETURN(lock, -1)
160 
161     return HksLockUnlockRead(lock->lock);
162 }
163 
HksStorageFileLockWrite(HksStorageFileLock * lock)164 int32_t HksStorageFileLockWrite(HksStorageFileLock *lock)
165 {
166     HKS_IF_NULL_RETURN(lock, -1)
167 
168     return HksLockLockWrite(lock->lock);
169 }
170 
HksStorageFileUnlockWrite(HksStorageFileLock * lock)171 int32_t HksStorageFileUnlockWrite(HksStorageFileLock *lock)
172 {
173     HKS_IF_NULL_RETURN(lock, -1)
174 
175     return HksLockUnlockWrite(lock->lock);
176 }
177 
IsLockInList(const HksStorageFileLock * lock)178 static bool IsLockInList(const HksStorageFileLock *lock)
179 {
180     HksStorageFileLock *iter = g_lockListFirst;
181     while (iter != NULL) {
182         if (lock == iter) {
183             return true;
184         } else {
185             iter = iter->next;
186         }
187     }
188     return false;
189 }
190 
Release(HksStorageFileLock * lock)191 static uint32_t Release(HksStorageFileLock *lock)
192 {
193     uint32_t ref = 0;
194     HksStorageFileLock *iter = g_lockListFirst;
195     HksStorageFileLock *previous = NULL;
196     bool remove = false;
197     while (iter != NULL) {
198         if (lock == iter) {
199             lock->ref--;
200             ref = lock->ref;
201             if (ref == 0) {
202                 remove = true;
203             }
204             break;
205         } else {
206             previous = iter;
207             iter = iter->next;
208         }
209     }
210 
211     if (remove && iter != NULL) {
212         if (previous != NULL) {
213             previous->next = iter->next;
214         } else {
215             g_lockListFirst = iter->next;
216         }
217         if (g_lockListLast == lock) {
218             g_lockListLast = previous;
219         }
220         FreeFileLock(lock);
221     }
222 
223     return ref;
224 }
225 
HksStorageFileLockRelease(HksStorageFileLock * lock)226 void HksStorageFileLockRelease(HksStorageFileLock *lock)
227 {
228     HKS_IF_TRUE_RETURN_VOID(lock == NULL || g_lockListLock == NULL || HksMutexLock(g_lockListLock) != 0)
229 
230     if (IsLockInList(lock)) {
231         Release(lock);
232     }
233 
234     (void)HksMutexUnlock(g_lockListLock);
235 }
236 
OnLoad(void)237 __attribute__((constructor)) static void OnLoad(void)
238 {
239     g_lockListLock = HksMutexCreate();
240     g_lockListFirst = NULL;
241     g_lockListLast = NULL;
242 }
243 
OnUnload(void)244 __attribute__((destructor)) static void OnUnload(void)
245 {
246     if (g_lockListLock != NULL) {
247         HksMutexClose(g_lockListLock);
248         g_lockListLock = NULL;
249     }
250 
251     ClearLockList();
252 }
253