1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
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 * Description: HiLinkKV harmonyos file实现源文件(此文件为DEMO,需集成方适配修改)
15 */
16
17 #include "hilink_kv_adapter.h"
18 #include <stdbool.h>
19 #include "hilink_sal_defines.h"
20 #include "securec.h"
21 #include "hilink_str_adapter.h"
22 #include "lfs.h"
23 #include "fcntl.h"
24 #include "sfc.h"
25 #include "securec.h"
26 #include "soc_osal.h"
27 #include "littlefs_config.h"
28 #include "securec.h"
29 #include "partition.h"
30 #include "littlefs_adapt.h"
31
32 #if defined(HILINK_SDK_BUILD_IN) && defined(HI_3861)
33 #define MAX_PATH_LEN 16
34 #define MAX_FILENAME_LEN 16
35 #else
36 #define MAX_PATH_LEN 32
37 #define MAX_FILENAME_LEN 32
38 #endif
39
40 static bool g_isKVInit = false;
41 static char g_filePath[MAX_PATH_LEN];
42
43 typedef struct KeyNameItem {
44 const char *hilinkKey;
45 const char *fileName;
46 } KeyNameItem;
47
48 /* 需要对key进行转换,防止key变更导致无法前向兼容 */
49 static const KeyNameItem KEY_NAME_LIST[] = {
50 {
51 "hilink_running",
52 "running"
53 },
54 {
55 "hilink_timer",
56 "timer"
57 },
58
59 {
60 "hilink_ble_sensitive",
61 "sensitive"
62 },
63 {
64 "hilink_ble_regstate",
65 "regstate"
66 },
67 {
68 "hilink_cert",
69 "cert"
70 },
71 };
72
73 #ifdef DUAL_FILE_BACKUP
74 /* 使用双备份后对于非预置文件,以.bak为后缀做备份 */
75 static const char *BACKUP_FILE_SUFFIX = ".bak";
76 static const char *PRESET_FILE[] = {"hilink.cfg", "hilink_bak.cfg"};
77
IsPresetFile(const char * fileName)78 static bool IsPresetFile(const char *fileName)
79 {
80 for (unsigned int i = 0; i < sizeof(PRESET_FILE) / sizeof(char *); ++i) {
81 if (HILINK_Strcmp(fileName, PRESET_FILE[i]) == 0) {
82 return true;
83 }
84 }
85 return false;
86 }
87
GetBackupFileName(const char * fileName,char * buf,unsigned int len)88 static const char *GetBackupFileName(const char *fileName, char *buf, unsigned int len)
89 {
90 if (sprintf_s(buf, len, "%s%s", fileName, BACKUP_FILE_SUFFIX) <= 0) {
91 HILINK_SAL_WARN("sprintf error\r\n");
92 return NULL;
93 }
94 return buf;
95 }
96 #endif
97
FindFileName(const char * key)98 static const char *FindFileName(const char *key)
99 {
100 for (unsigned int i = 0; i < (sizeof(KEY_NAME_LIST) / sizeof(KEY_NAME_LIST[0])); ++i) {
101 if (HILINK_Strcmp(key, KEY_NAME_LIST[i].hilinkKey) == 0) {
102 return KEY_NAME_LIST[i].fileName;
103 }
104 }
105 return NULL;
106 }
107
SetConfigInfoPath(const char * path)108 static int SetConfigInfoPath(const char *path)
109 {
110 if (HILINK_Strlen(path) >= MAX_PATH_LEN) {
111 HILINK_SAL_WARN("path too long: %s\r\n", path);
112 return HILINK_SAL_KV_INTI_ERR;
113 }
114
115 (void)memset_s(g_filePath, MAX_PATH_LEN, 0, MAX_PATH_LEN);
116 /* 长度为0保存在根目录下 */
117 if (HILINK_Strlen(path) == 0) {
118 HILINK_SAL_NOTICE("empty path\r\n");
119 return HILINK_SAL_OK;
120 }
121 if (strcpy_s(g_filePath, MAX_PATH_LEN, path) != EOK) {
122 HILINK_SAL_WARN("strncpy_s error\r\n");
123 return HILINK_SAL_STRCPY_ERR;
124 }
125 if (g_filePath[HILINK_Strlen(path) - 1] == '/') {
126 g_filePath[HILINK_Strlen(path) - 1] = '\0';
127 }
128
129 return HILINK_SAL_OK;
130 }
131
CreateFileIfNotExists(const char * filePath)132 static int CreateFileIfNotExists(const char *filePath)
133 {
134 if (filePath == NULL) {
135 HILINK_SAL_ERROR("Create filepath is null.\r\n");
136 return HILINK_SAL_KV_INTI_ERR;
137 }
138
139 HILINK_SAL_DEBUG("Create file [%s]\r\n", filePath);
140 int fp = fs_adapt_open(filePath, O_RDWR | O_CREAT);
141 if (fp < 0) {
142 HILINK_SAL_ERROR("Create file failed.\r\n");
143 return HILINK_SAL_KV_INTI_ERR;
144 }
145
146 int ret = fs_adapt_close(fp);
147 if (ret < LFS_ERR_OK) {
148 HILINK_SAL_ERROR("close file %s failed\n", filePath);
149 return HILINK_SAL_NOK;
150 }
151
152 HILINK_SAL_DEBUG("Create file %s SUCCESS\r\n", filePath);
153
154 return HILINK_SAL_OK;
155 }
156
ReadFile(const char * filePath,unsigned int offset,unsigned char * value,unsigned int len)157 static int ReadFile(const char *filePath, unsigned int offset, unsigned char *value, unsigned int len)
158 {
159 if ((filePath == NULL) || (filePath[0] == '\0')) {
160 HILINK_SAL_ERROR("invalid path\r\n");
161 return HILINK_SAL_PARAM_INVALID;
162 }
163 HILINK_SAL_DEBUG("read %s, read len %u, offset %u\r\n", filePath, len, offset);
164
165 int fp = fs_adapt_open(filePath, O_RDWR);
166 if (fp < 0) {
167 HILINK_SAL_ERROR("open %s failed\r\n", filePath);
168 return HILINK_SAL_NOK;
169 }
170
171 int ret = fs_adapt_seek(fp, (int)offset, LFS_SEEK_SET);
172 if (ret < LFS_ERR_OK) {
173 HILINK_SAL_ERROR("set file %s offset %u failed\n", filePath, offset);
174 goto unnormal_close;
175 }
176
177 ret = fs_adapt_read(fp, (char *)value, len);
178 if (ret < 0) {
179 HILINK_SAL_ERROR("read file %s failed\n", filePath);
180 goto unnormal_close;
181 }
182
183 ret = fs_adapt_close(fp);
184 if (ret < LFS_ERR_OK) {
185 HILINK_SAL_ERROR("close file %s failed\n", filePath);
186 return HILINK_SAL_NOK;
187 }
188
189 return HILINK_SAL_OK;
190
191 unnormal_close:
192 ret = fs_adapt_close(fp);
193 if (ret < LFS_ERR_OK) {
194 HILINK_SAL_ERROR("close file %s failed\n", filePath);
195 }
196
197 return HILINK_SAL_NOK;
198 }
199
WritFile(const char * filePath,unsigned int offset,const unsigned char * value,unsigned int len)200 static int WritFile(const char *filePath, unsigned int offset, const unsigned char *value, unsigned int len)
201 {
202 HILINK_SAL_DEBUG("write %s, write len %u, offset %u\r\n", filePath, len, offset);
203
204 int fp = fs_adapt_open(filePath, O_RDWR | O_CREAT);
205 if (fp < 0) {
206 HILINK_SAL_ERROR("open %s failed\r\n", filePath);
207 return HILINK_SAL_NOK;
208 }
209
210 int ret = fs_adapt_seek(fp, (int)offset, LFS_SEEK_SET);
211 if (ret < LFS_ERR_OK) {
212 HILINK_SAL_ERROR("set file %s offset %u failed\n", filePath, offset);
213 goto unnormal_close;
214 }
215
216 ret = fs_adapt_write(fp, (char *)value, len);
217 if (ret < 0) {
218 HILINK_SAL_ERROR("write file %s failed\n", filePath);
219 goto unnormal_close;
220 }
221
222 ret = fs_adapt_close(fp);
223 if (ret < LFS_ERR_OK) {
224 HILINK_SAL_ERROR("close file %s failed\n", filePath);
225 return HILINK_SAL_NOK;
226 }
227
228 return HILINK_SAL_OK;
229
230 unnormal_close:
231 ret = fs_adapt_close(fp);
232 if (ret < LFS_ERR_OK) {
233 HILINK_SAL_ERROR("close file %s failed\n", filePath);
234 }
235
236 return HILINK_SAL_NOK;
237 }
238
CreateEmptyFileAfterDelete(const char * filePath)239 static int CreateEmptyFileAfterDelete(const char *filePath)
240 {
241 HILINK_SAL_NOTICE("delete %s\r\n", filePath);
242 return HILINK_SAL_OK;
243 }
244
GetFilePathByKey(const char * key,char * buf,unsigned int len)245 static int GetFilePathByKey(const char *key, char *buf, unsigned int len)
246 {
247 const char *fileName = NULL;
248
249 fileName = FindFileName(key);
250 if (fileName == NULL) {
251 HILINK_SAL_ERROR("get file path failed\n");
252 return HILINK_SAL_NOK;
253 }
254
255 if (memcpy_s(buf, len - 1, fileName, strlen(fileName)) != EOK) {
256 HILINK_SAL_ERROR("memcpy_s error\n");
257 return HILINK_SAL_NOK;
258 }
259
260 return HILINK_SAL_OK;
261 }
262
263 #if defined(HILINK_SDK_BUILD_IN) && defined(DUAL_FILE_BACKUP)
GetBakFilePathByKey(const char * key,char * buf,unsigned int len)264 static const char *GetBakFilePathByKey(const char *key, char *buf, unsigned int len)
265 {
266 const char *fileName = FindFileName(key);
267 /* 预置文件不做备份 */
268 if (IsPresetFile(fileName)) {
269 return NULL;
270 }
271 char bakFileName[MAX_FILENAME_LEN] = {0};
272 if (GetBackupFileName(fileName, bakFileName, sizeof(bakFileName)) == NULL) {
273 return NULL;
274 }
275
276 return GetFullFilePath(bakFileName, buf, len);
277 }
278 #endif
279
DeleteFileByKey(const char * key)280 static void DeleteFileByKey(const char *key)
281 {
282 char filePath[MAX_PATH_LEN + MAX_FILENAME_LEN] = {0};
283 if (GetFilePathByKey(key, filePath, sizeof(filePath)) != HILINK_SAL_OK) {
284 return;
285 }
286 (void)CreateEmptyFileAfterDelete(filePath);
287 #if defined(HILINK_SDK_BUILD_IN) && defined(DUAL_FILE_BACKUP)
288 (void)memset_s(filePath, sizeof(filePath), 0, sizeof(filePath));
289 if (GetBakFilePathByKey(key, filePath, sizeof(filePath)) != NULL) {
290 CreateEmptyFileAfterDelete(filePath);
291 }
292 #endif
293 }
294
ReadFileByKey(const char * key,unsigned int offset,unsigned char * value,unsigned int len)295 static int ReadFileByKey(const char *key, unsigned int offset, unsigned char *value, unsigned int len)
296 {
297 char filePath[MAX_PATH_LEN + MAX_FILENAME_LEN] = {0};
298 if (GetFilePathByKey(key, filePath, sizeof(filePath)) != HILINK_SAL_OK) {
299 return HILINK_SAL_KV_GET_ITEM_ERR;
300 }
301 int ret = ReadFile(filePath, offset, value, len);
302 if (ret == HILINK_SAL_OK) {
303 return HILINK_SAL_OK;
304 }
305 #if defined(HILINK_SDK_BUILD_IN) && defined(DUAL_FILE_BACKUP)
306 (void)memset_s(filePath, sizeof(filePath), 0, sizeof(filePath));
307 if (GetBakFilePathByKey(key, filePath, sizeof(filePath)) != NULL) {
308 ret = ReadFile(filePath, offset, value, len);
309 if (ret == HILINK_SAL_OK) {
310 return HILINK_SAL_OK;
311 }
312 }
313 #endif
314 return ret;
315 }
316
WriteFileByKey(const char * key,unsigned int offset,const unsigned char * value,unsigned int len)317 static int WriteFileByKey(const char *key, unsigned int offset, const unsigned char *value, unsigned int len)
318 {
319 char filePath[MAX_PATH_LEN + MAX_FILENAME_LEN] = {0};
320 if (GetFilePathByKey(key, filePath, sizeof(filePath)) != HILINK_SAL_OK) {
321 return HILINK_SAL_KV_SET_ITEM_ERR;
322 }
323 int ret = WritFile(filePath, offset, value, len);
324 if (ret != HILINK_SAL_OK) {
325 return ret;
326 }
327
328 #if defined(HILINK_SDK_BUILD_IN) && defined(DUAL_FILE_BACKUP)
329 (void)memset_s(filePath, sizeof(filePath), 0, sizeof(filePath));
330 if (GetBakFilePathByKey(key, filePath, sizeof(filePath)) != NULL) {
331 ret = WritFile(filePath, offset, value, len);
332 if (ret != HILINK_SAL_OK) {
333 return ret;
334 }
335 }
336 #endif
337 return HILINK_SAL_OK;
338 }
339
InitFileByKey(const char * key)340 static int InitFileByKey(const char *key)
341 {
342 if ((key == NULL) || (key[0] == '\0')) {
343 HILINK_SAL_WARN("invalid parm\r\n");
344 return HILINK_SAL_PARAM_INVALID;
345 }
346
347 char filePath[MAX_PATH_LEN + MAX_FILENAME_LEN] = {0};
348 if (GetFilePathByKey(key, filePath, sizeof(filePath)) != HILINK_SAL_OK) {
349 return HILINK_SAL_KV_INTI_ERR;
350 }
351
352 int ret = CreateFileIfNotExists(filePath);
353 if (ret != 0) {
354 return ret;
355 }
356
357 #if defined(HILINK_SDK_BUILD_IN) && defined(DUAL_FILE_BACKUP)
358 (void)memset_s(filePath, sizeof(filePath), 0, sizeof(filePath));
359 if (GetBakFilePathByKey(key, filePath, sizeof(filePath)) == NULL) {
360 return HILINK_SAL_KV_INTI_ERR;
361 }
362 ret = CreateFileIfNotExists(filePath);
363 if (ret != 0) {
364 return ret;
365 }
366 #endif
367 return HILINK_SAL_OK;
368 }
369
HILINK_KVStoreInit(const char * path,const char * key[],unsigned int num)370 int HILINK_KVStoreInit(const char *path, const char *key[], unsigned int num)
371 {
372 if ((key == NULL) || (num == 0) || (path == NULL)) {
373 HILINK_SAL_WARN("invalid parm\r\n");
374 return HILINK_SAL_PARAM_INVALID;
375 }
376
377 HILINK_SAL_DEBUG("HILINK_KVStoreInit path[%s], num %d\r\n", path, num);
378 if (SetConfigInfoPath(path) != HILINK_SAL_OK) {
379 HILINK_SAL_WARN("set config path error\r\n");
380 return HILINK_SAL_KV_INTI_ERR;
381 }
382 int ret;
383 for (unsigned int i = 0; i < num; ++i) {
384 HILINK_SAL_DEBUG("HILINK_KVStoreInit key [%s]\r\n", key[i]);
385 ret = InitFileByKey(key[i]);
386 if (ret != HILINK_SAL_OK) {
387 return ret;
388 }
389 }
390 g_isKVInit = true;
391 return HILINK_SAL_OK;
392 }
393
HILINK_SetValue(const char * key,unsigned int offset,const unsigned char * value,unsigned int len)394 int HILINK_SetValue(const char *key, unsigned int offset, const unsigned char *value, unsigned int len)
395 {
396 if ((key == NULL) || (key[0] == '\0') || (value == NULL) || (len == 0)) {
397 HILINK_SAL_WARN("invalid parm\r\n");
398 return HILINK_SAL_PARAM_INVALID;
399 }
400
401 if (!g_isKVInit) {
402 HILINK_SAL_WARN("not init\r\n");
403 return HILINK_SAL_NOT_INIT;
404 }
405
406 return WriteFileByKey(key, offset, value, len);
407 }
408
HILINK_GetValue(const char * key,unsigned int offset,unsigned char * value,unsigned int len)409 int HILINK_GetValue(const char *key, unsigned int offset, unsigned char *value, unsigned int len)
410 {
411 if ((key == NULL) || (key[0] == '\0') || (value == NULL) || (len == 0)) {
412 HILINK_SAL_WARN("invalid parm\r\n");
413 return HILINK_SAL_PARAM_INVALID;
414 }
415
416 if (!g_isKVInit) {
417 HILINK_SAL_WARN("not init\r\n");
418 return HILINK_SAL_NOT_INIT;
419 }
420
421 return ReadFileByKey(key, offset, value, len);
422 }
423
HILINK_DeleteValue(const char * key)424 void HILINK_DeleteValue(const char * key)
425 {
426 if ((key == NULL) || (key[0] == '\0')) {
427 HILINK_SAL_NOTICE("invalid parm\r\n");
428 return;
429 }
430
431 if (!g_isKVInit) {
432 HILINK_SAL_WARN("not init\r\n");
433 return;
434 }
435
436 DeleteFileByKey(key);
437 }
438
HILINK_GetFileName(const char * key,char * out,unsigned int len)439 int HILINK_GetFileName(const char *key, char *out, unsigned int len)
440 {
441 if (key == NULL || out == NULL || len < MAX_FILENAME_LEN) {
442 HILINK_SAL_WARN("invalid parm\r\n");
443 return HILINK_SAL_PARAM_INVALID;
444 }
445 const char *fileName = key;
446 #ifdef HILINK_SDK_BUILD_IN
447 fileName = FindFileName(key);
448 #endif
449 if (strcpy_s(out, len, fileName) != EOK) {
450 HILINK_SAL_WARN("cpy file name err\n");
451 return HILINK_SAL_NOK;
452 }
453 return HILINK_SAL_OK;
454 }
455