1d9f0492fSopenharmony_ci/*
2d9f0492fSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
3d9f0492fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4d9f0492fSopenharmony_ci * you may not use this file except in compliance with the License.
5d9f0492fSopenharmony_ci * You may obtain a copy of the License at
6d9f0492fSopenharmony_ci *
7d9f0492fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8d9f0492fSopenharmony_ci *
9d9f0492fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10d9f0492fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11d9f0492fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12d9f0492fSopenharmony_ci * See the License for the specific language governing permissions and
13d9f0492fSopenharmony_ci * limitations under the License.
14d9f0492fSopenharmony_ci */
15d9f0492fSopenharmony_ci
16d9f0492fSopenharmony_ci#include <ctype.h>
17d9f0492fSopenharmony_ci#include <errno.h>
18d9f0492fSopenharmony_ci#include <fcntl.h>
19d9f0492fSopenharmony_ci#include <time.h>
20d9f0492fSopenharmony_ci#include <unistd.h>
21d9f0492fSopenharmony_ci
22d9f0492fSopenharmony_ci#include "init_utils.h"
23d9f0492fSopenharmony_ci#include "param_manager.h"
24d9f0492fSopenharmony_ci#include "param_persist.h"
25d9f0492fSopenharmony_ci#include "param_utils.h"
26d9f0492fSopenharmony_ci#include "securec.h"
27d9f0492fSopenharmony_ci#include "utils_file.h"
28d9f0492fSopenharmony_ci
29d9f0492fSopenharmony_ci// for linux, no mutex
30d9f0492fSopenharmony_cistatic ParamMutex g_saveMutex = {0};
31d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_POSIX
32d9f0492fSopenharmony_ci#define MODE_READ O_RDONLY
33d9f0492fSopenharmony_ci#define MODE_APPEND (O_RDWR | O_CREAT | O_APPEND)
34d9f0492fSopenharmony_ci#define MODE_CREATE (O_RDWR | O_CREAT | O_TRUNC)
35d9f0492fSopenharmony_ci#else
36d9f0492fSopenharmony_ci#define MODE_READ O_RDONLY_FS
37d9f0492fSopenharmony_ci#define MODE_APPEND (O_RDWR_FS | O_CREAT_FS | O_APPEND_FS)
38d9f0492fSopenharmony_ci#define MODE_CREATE (O_RDWR_FS | O_CREAT_FS | O_TRUNC_FS)
39d9f0492fSopenharmony_ci#endif
40d9f0492fSopenharmony_ci
41d9f0492fSopenharmony_cistatic int ParamFileOpen(const char* path, int oflag, int mode)
42d9f0492fSopenharmony_ci{
43d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_POSIX
44d9f0492fSopenharmony_ci    return open(path, oflag, mode);
45d9f0492fSopenharmony_ci#else
46d9f0492fSopenharmony_ci    return UtilsFileOpen(path, oflag, mode);
47d9f0492fSopenharmony_ci#endif
48d9f0492fSopenharmony_ci}
49d9f0492fSopenharmony_ci
50d9f0492fSopenharmony_cistatic int ParamFileClose(int fd)
51d9f0492fSopenharmony_ci{
52d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_POSIX
53d9f0492fSopenharmony_ci    return close(fd);
54d9f0492fSopenharmony_ci#else
55d9f0492fSopenharmony_ci    return UtilsFileClose(fd);
56d9f0492fSopenharmony_ci#endif
57d9f0492fSopenharmony_ci}
58d9f0492fSopenharmony_ci
59d9f0492fSopenharmony_cistatic int ParamFileRead(int fd, char* buf, unsigned int len)
60d9f0492fSopenharmony_ci{
61d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_POSIX
62d9f0492fSopenharmony_ci    return read(fd, buf, len);
63d9f0492fSopenharmony_ci#else
64d9f0492fSopenharmony_ci    return UtilsFileRead(fd, buf, len);
65d9f0492fSopenharmony_ci#endif
66d9f0492fSopenharmony_ci}
67d9f0492fSopenharmony_ci
68d9f0492fSopenharmony_cistatic int ParamFileWrite(int fd, const char* buf, unsigned int len)
69d9f0492fSopenharmony_ci{
70d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_POSIX
71d9f0492fSopenharmony_ci    return write(fd, buf, len);
72d9f0492fSopenharmony_ci#else
73d9f0492fSopenharmony_ci    return UtilsFileWrite(fd, buf, len);
74d9f0492fSopenharmony_ci#endif
75d9f0492fSopenharmony_ci}
76d9f0492fSopenharmony_ci
77d9f0492fSopenharmony_cistatic int ParamFileDelete(const char* path)
78d9f0492fSopenharmony_ci{
79d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_POSIX
80d9f0492fSopenharmony_ci    return unlink(path);
81d9f0492fSopenharmony_ci#else
82d9f0492fSopenharmony_ci    return UtilsFileDelete(path);
83d9f0492fSopenharmony_ci#endif
84d9f0492fSopenharmony_ci}
85d9f0492fSopenharmony_ci
86d9f0492fSopenharmony_cistatic int ParamFileStat(const char* path, unsigned int* fileSize)
87d9f0492fSopenharmony_ci{
88d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_POSIX
89d9f0492fSopenharmony_ci    int fd = open(path, O_RDONLY);
90d9f0492fSopenharmony_ci    if (fd < 0) {
91d9f0492fSopenharmony_ci        return -1;
92d9f0492fSopenharmony_ci    }
93d9f0492fSopenharmony_ci	*fileSize = lseek(fd, 0, SEEK_END);
94d9f0492fSopenharmony_ci    lseek(fd, 0, SEEK_SET);
95d9f0492fSopenharmony_ci    close(fd);
96d9f0492fSopenharmony_ci    return 0;
97d9f0492fSopenharmony_ci#else
98d9f0492fSopenharmony_ci    return UtilsFileStat(path, fileSize);
99d9f0492fSopenharmony_ci#endif
100d9f0492fSopenharmony_ci}
101d9f0492fSopenharmony_ci
102d9f0492fSopenharmony_cistatic void ParamFileSync(int ft)
103d9f0492fSopenharmony_ci{
104d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_POSIX
105d9f0492fSopenharmony_ci    fsync(ft);
106d9f0492fSopenharmony_ci#else
107d9f0492fSopenharmony_ci    (void)ft;
108d9f0492fSopenharmony_ci#endif
109d9f0492fSopenharmony_ci}
110d9f0492fSopenharmony_ci
111d9f0492fSopenharmony_cistatic int LoadOnePersistParam_(const uint32_t *context, const char *name, const char *value)
112d9f0492fSopenharmony_ci{
113d9f0492fSopenharmony_ci    (void)context;
114d9f0492fSopenharmony_ci    uint32_t dataIndex = 0;
115d9f0492fSopenharmony_ci    int ret = WriteParam(name, value, &dataIndex, 0);
116d9f0492fSopenharmony_ci    PARAM_CHECK(ret == 0, return ret, "Failed to write param %d name:%s %s", ret, name, value);
117d9f0492fSopenharmony_ci    return 0;
118d9f0492fSopenharmony_ci}
119d9f0492fSopenharmony_ci
120d9f0492fSopenharmony_cistatic int LoadPersistParam(void)
121d9f0492fSopenharmony_ci{
122d9f0492fSopenharmony_ci    const char *path = PARAM_PERSIST_SAVE_TMP_PATH;
123d9f0492fSopenharmony_ci    CheckAndCreateDir(path);
124d9f0492fSopenharmony_ci    char *buffer = NULL;
125d9f0492fSopenharmony_ci    int fd = -1;
126d9f0492fSopenharmony_ci    uint32_t paramNum = 0;
127d9f0492fSopenharmony_ci    do {
128d9f0492fSopenharmony_ci        fd = ParamFileOpen(path, MODE_READ, 0);
129d9f0492fSopenharmony_ci        if (fd < 0) {
130d9f0492fSopenharmony_ci            path = PARAM_PERSIST_SAVE_PATH;
131d9f0492fSopenharmony_ci            fd = ParamFileOpen(path, MODE_READ, 0);
132d9f0492fSopenharmony_ci            PARAM_LOGI("LoadPersistParam open file %s", path);
133d9f0492fSopenharmony_ci        }
134d9f0492fSopenharmony_ci        PARAM_CHECK(fd >= 0, break, "No valid persist parameter file %s", path);
135d9f0492fSopenharmony_ci        // read file
136d9f0492fSopenharmony_ci        uint32_t fileSize = 0;
137d9f0492fSopenharmony_ci        int ret = ParamFileStat(path, &fileSize);
138d9f0492fSopenharmony_ci        PARAM_CHECK(ret == 0, break, "Failed to get file state %s", path);
139d9f0492fSopenharmony_ci        buffer = calloc(fileSize, sizeof(char));
140d9f0492fSopenharmony_ci        PARAM_CHECK(buffer != NULL, break, "Failed to get file");
141d9f0492fSopenharmony_ci        ret = ParamFileRead(fd, buffer, fileSize);
142d9f0492fSopenharmony_ci        PARAM_CHECK(ret >= 0, break, "Failed to read file %s", path);
143d9f0492fSopenharmony_ci
144d9f0492fSopenharmony_ci        uint32_t currLen = 0;
145d9f0492fSopenharmony_ci        char *tmp = buffer;
146d9f0492fSopenharmony_ci        while (currLen < fileSize) {
147d9f0492fSopenharmony_ci            if (buffer[currLen] == '\n') { // split line
148d9f0492fSopenharmony_ci                buffer[currLen] = '\0';
149d9f0492fSopenharmony_ci                ret = SplitParamString(tmp, NULL, 0, LoadOnePersistParam_, NULL);
150d9f0492fSopenharmony_ci                PARAM_CHECK(ret == 0, continue, "Failed to set param %d %s", ret, buffer);
151d9f0492fSopenharmony_ci                paramNum++;
152d9f0492fSopenharmony_ci                if (currLen + 1 >= fileSize) {
153d9f0492fSopenharmony_ci                    break;
154d9f0492fSopenharmony_ci                }
155d9f0492fSopenharmony_ci                tmp = buffer + currLen + 1;
156d9f0492fSopenharmony_ci            }
157d9f0492fSopenharmony_ci            currLen++;
158d9f0492fSopenharmony_ci        }
159d9f0492fSopenharmony_ci    } while (0);
160d9f0492fSopenharmony_ci    if (fd > 0) {
161d9f0492fSopenharmony_ci        ParamFileClose(fd);
162d9f0492fSopenharmony_ci    }
163d9f0492fSopenharmony_ci    if (buffer != NULL) {
164d9f0492fSopenharmony_ci        free(buffer);
165d9f0492fSopenharmony_ci    }
166d9f0492fSopenharmony_ci    PARAM_LOGI("LoadPersistParam paramNum %d", paramNum);
167d9f0492fSopenharmony_ci    return 0;
168d9f0492fSopenharmony_ci}
169d9f0492fSopenharmony_ci
170d9f0492fSopenharmony_cistatic int PersistWrite(int fd, const char *name, const char *value)
171d9f0492fSopenharmony_ci{
172d9f0492fSopenharmony_ci    int ret = ParamFileWrite(fd, name, strlen(name));
173d9f0492fSopenharmony_ci    if (ret <= 0) {
174d9f0492fSopenharmony_ci        PARAM_LOGE("Failed to save persist param %s", name);
175d9f0492fSopenharmony_ci    }
176d9f0492fSopenharmony_ci    ret = ParamFileWrite(fd, "=", strlen("="));
177d9f0492fSopenharmony_ci    if (ret <= 0) {
178d9f0492fSopenharmony_ci        PARAM_LOGE("Failed to save persist param %s", name);
179d9f0492fSopenharmony_ci    }
180d9f0492fSopenharmony_ci    ret = ParamFileWrite(fd, value, strlen(value));
181d9f0492fSopenharmony_ci    if (ret <= 0) {
182d9f0492fSopenharmony_ci        PARAM_LOGE("Failed to save persist param %s", name);
183d9f0492fSopenharmony_ci    }
184d9f0492fSopenharmony_ci    ret = ParamFileWrite(fd, "\n", strlen("\n"));
185d9f0492fSopenharmony_ci    if (ret <= 0) {
186d9f0492fSopenharmony_ci        PARAM_LOGE("Failed to save persist param %s", name);
187d9f0492fSopenharmony_ci    }
188d9f0492fSopenharmony_ci    return 0;
189d9f0492fSopenharmony_ci}
190d9f0492fSopenharmony_ci
191d9f0492fSopenharmony_cistatic int SavePersistParam(const char *name, const char *value)
192d9f0492fSopenharmony_ci{
193d9f0492fSopenharmony_ci    ParamMutexPend(&g_saveMutex);
194d9f0492fSopenharmony_ci    int ret = -1;
195d9f0492fSopenharmony_ci    int fd = ParamFileOpen(PARAM_PERSIST_SAVE_PATH, MODE_APPEND, 0);
196d9f0492fSopenharmony_ci    if (fd > 0) {
197d9f0492fSopenharmony_ci        ret = PersistWrite(fd, name, value);
198d9f0492fSopenharmony_ci        ParamFileSync(fd);
199d9f0492fSopenharmony_ci        ParamFileClose(fd);
200d9f0492fSopenharmony_ci    }
201d9f0492fSopenharmony_ci    if (ret != 0) {
202d9f0492fSopenharmony_ci        PARAM_LOGE("SavePersistParam %s errno %d", name, errno);
203d9f0492fSopenharmony_ci    }
204d9f0492fSopenharmony_ci    ParamMutexPost(&g_saveMutex);
205d9f0492fSopenharmony_ci    return ret;
206d9f0492fSopenharmony_ci}
207d9f0492fSopenharmony_ci
208d9f0492fSopenharmony_cistatic int BatchSavePersistParamBegin(PERSIST_SAVE_HANDLE *handle)
209d9f0492fSopenharmony_ci{
210d9f0492fSopenharmony_ci    ParamMutexPend(&g_saveMutex);
211d9f0492fSopenharmony_ci    int fd = ParamFileOpen(PARAM_PERSIST_SAVE_PATH, MODE_CREATE, 0);
212d9f0492fSopenharmony_ci    if (fd < 0) {
213d9f0492fSopenharmony_ci        ParamMutexPost(&g_saveMutex);
214d9f0492fSopenharmony_ci        PARAM_LOGE("Open file %s fail error %d", PARAM_PERSIST_SAVE_PATH, errno);
215d9f0492fSopenharmony_ci        return -1;
216d9f0492fSopenharmony_ci    }
217d9f0492fSopenharmony_ci    *handle = (PERSIST_SAVE_HANDLE)fd;
218d9f0492fSopenharmony_ci    return 0;
219d9f0492fSopenharmony_ci}
220d9f0492fSopenharmony_ci
221d9f0492fSopenharmony_cistatic int BatchSavePersistParam(PERSIST_SAVE_HANDLE handle, const char *name, const char *value)
222d9f0492fSopenharmony_ci{
223d9f0492fSopenharmony_ci    int fd = (int)handle;
224d9f0492fSopenharmony_ci    int ret = PersistWrite(fd, name, value);
225d9f0492fSopenharmony_ci    PARAM_CHECK(ret == 0, return -1, "Failed to write param %s", name);
226d9f0492fSopenharmony_ci    PARAM_LOGV("BatchSavePersistParam %s=%s", name, value);
227d9f0492fSopenharmony_ci    return 0;
228d9f0492fSopenharmony_ci}
229d9f0492fSopenharmony_ci
230d9f0492fSopenharmony_cistatic void BatchSavePersistParamEnd(PERSIST_SAVE_HANDLE handle)
231d9f0492fSopenharmony_ci{
232d9f0492fSopenharmony_ci    int ret;
233d9f0492fSopenharmony_ci    int fd = (int)handle;
234d9f0492fSopenharmony_ci    ParamFileSync(fd);
235d9f0492fSopenharmony_ci    ret = ParamFileClose(fd);
236d9f0492fSopenharmony_ci    ParamMutexPost(&g_saveMutex);
237d9f0492fSopenharmony_ci    PARAM_CHECK(ret == 0, return, "BatchSavePersistParamEnd fail error %d", errno);
238d9f0492fSopenharmony_ci}
239d9f0492fSopenharmony_ci
240d9f0492fSopenharmony_ciint RegisterPersistParamOps(PersistParamOps *ops)
241d9f0492fSopenharmony_ci{
242d9f0492fSopenharmony_ci    ParamMutexCreate(&g_saveMutex);
243d9f0492fSopenharmony_ci    PARAM_CHECK(ops != NULL, return -1, "Invalid ops");
244d9f0492fSopenharmony_ci    ops->save = SavePersistParam;
245d9f0492fSopenharmony_ci    ops->load = LoadPersistParam;
246d9f0492fSopenharmony_ci    ops->batchSaveBegin = BatchSavePersistParamBegin;
247d9f0492fSopenharmony_ci    ops->batchSave = BatchSavePersistParam;
248d9f0492fSopenharmony_ci    ops->batchSaveEnd = BatchSavePersistParamEnd;
249d9f0492fSopenharmony_ci    return 0;
250d9f0492fSopenharmony_ci}
251