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 <errno.h>
17d9f0492fSopenharmony_ci#include <time.h>
18d9f0492fSopenharmony_ci#include <unistd.h>
19d9f0492fSopenharmony_ci
20d9f0492fSopenharmony_ci#include "init_utils.h"
21d9f0492fSopenharmony_ci#include "param_manager.h"
22d9f0492fSopenharmony_ci#include "param_persist.h"
23d9f0492fSopenharmony_ci#include "param_utils.h"
24d9f0492fSopenharmony_ci#if !(defined __LITEOFS_A__ || defined __LITEOS_M__)
25d9f0492fSopenharmony_ci#include "trigger_manager.h"
26d9f0492fSopenharmony_ci#endif
27d9f0492fSopenharmony_ci
28d9f0492fSopenharmony_ci// for linux, no mutex
29d9f0492fSopenharmony_cistatic ParamMutex g_saveMutex = {};
30d9f0492fSopenharmony_ci
31d9f0492fSopenharmony_cistatic int LoadOnePersistParam_(const uint32_t *context, const char *name, const char *value)
32d9f0492fSopenharmony_ci{
33d9f0492fSopenharmony_ci    if (strncmp(name, "persist", strlen("persist")) != 0) {
34d9f0492fSopenharmony_ci        PARAM_LOGE("%s is not persist param, do not load", name);
35d9f0492fSopenharmony_ci        return 0;
36d9f0492fSopenharmony_ci    }
37d9f0492fSopenharmony_ci    bool clearFactoryPersistParams = *(bool*)context;
38d9f0492fSopenharmony_ci    uint32_t dataIndex = 0;
39d9f0492fSopenharmony_ci    unsigned int mode = 0;
40d9f0492fSopenharmony_ci    int result = 0;
41d9f0492fSopenharmony_ci    do {
42d9f0492fSopenharmony_ci        if (!clearFactoryPersistParams) {
43d9f0492fSopenharmony_ci            mode |= LOAD_PARAM_PERSIST;
44d9f0492fSopenharmony_ci            result = WriteParam(name, value, &dataIndex, mode);
45d9f0492fSopenharmony_ci            break;
46d9f0492fSopenharmony_ci        }
47d9f0492fSopenharmony_ci
48d9f0492fSopenharmony_ci        char persetValue[PARAM_VALUE_LEN_MAX] = {0};
49d9f0492fSopenharmony_ci        uint32_t len = PARAM_VALUE_LEN_MAX;
50d9f0492fSopenharmony_ci        int ret = SystemReadParam(name, persetValue, &len);
51d9f0492fSopenharmony_ci        if (ret != 0) {
52d9f0492fSopenharmony_ci            mode |= LOAD_PARAM_PERSIST;
53d9f0492fSopenharmony_ci            result = WriteParam(name, value, &dataIndex, mode);
54d9f0492fSopenharmony_ci            break;
55d9f0492fSopenharmony_ci        }
56d9f0492fSopenharmony_ci
57d9f0492fSopenharmony_ci        if ((strcmp(persetValue, value) != 0)) {
58d9f0492fSopenharmony_ci            PARAM_LOGI("%s value is different, preset value is:%s, persist value is:%s", name, persetValue, value);
59d9f0492fSopenharmony_ci            mode |= LOAD_PARAM_PERSIST;
60d9f0492fSopenharmony_ci            result = WriteParam(name, value, &dataIndex, mode);
61d9f0492fSopenharmony_ci        }
62d9f0492fSopenharmony_ci    } while (0);
63d9f0492fSopenharmony_ci#if !(defined __LITEOFS_A__ || defined __LITEOS_M__)
64d9f0492fSopenharmony_ci    if (result == 0) {
65d9f0492fSopenharmony_ci        PostParamTrigger(EVENT_TRIGGER_PARAM_WATCH, name, value);
66d9f0492fSopenharmony_ci    }
67d9f0492fSopenharmony_ci#endif
68d9f0492fSopenharmony_ci    return result;
69d9f0492fSopenharmony_ci}
70d9f0492fSopenharmony_ci
71d9f0492fSopenharmony_cistatic bool IsPublicParam(const char *param)
72d9f0492fSopenharmony_ci{
73d9f0492fSopenharmony_ci    const char *publicPersistParams[] = {
74d9f0492fSopenharmony_ci        "persist.arkui.libace.og", "persist.ddgr.opinctype",
75d9f0492fSopenharmony_ci        "persist.dfx.leak.threshold", "persist.rosen.animationtrace.enabled",
76d9f0492fSopenharmony_ci        "persist.rosen.ddgr.opinctype.debugtype", "persist.sys.graphic.blurEnabled",
77d9f0492fSopenharmony_ci        "persist.sys.graphic.drawing.test", "persist.sys.graphic.filterCacheEnabled",
78d9f0492fSopenharmony_ci        "persist.sys.graphic.foregroundFilterEnabled", "persist.sys.graphic.GpuApitype",
79d9f0492fSopenharmony_ci        "persist.sys.graphic.hmsymbolcfg.enable", "persist.sys.graphic.hmsymboltxt.enable",
80d9f0492fSopenharmony_ci        "persist.sys.graphic.HpsBlurEnable", "persist.sys.graphic.kawaseEnable",
81d9f0492fSopenharmony_ci        "persist.sys.graphic.openDebugTrace", "persist.sys.graphic.subSurface",
82d9f0492fSopenharmony_ci        "persist.sys.text.autospacing.enable", "persist.sys.hilog.binary.forhota.on",
83d9f0492fSopenharmony_ci        "persist.sys.hilog.fuse.on", "persist.sys.xlog.debug",
84d9f0492fSopenharmony_ci        "persist.sys.hiview.testtype", "persist.security.jitfort.disabled",
85d9f0492fSopenharmony_ci        "persist.sys.prefork.enable", "persist.time.timezone",
86d9f0492fSopenharmony_ci        "persist.global.tz_override", "persist.dupdate_engine.update_type",
87d9f0492fSopenharmony_ci        "persist.update.hmos_to_next_flag", "persist.hiview.leak_detector",
88d9f0492fSopenharmony_ci        "persist.hiviewdfx.debugenv", "persist.swing.switch_enable",
89d9f0492fSopenharmony_ci        "persist.hiviewdfx.priv.diagnosis.time.deadline", "persist.hmos_fusion_mgr.ctl.support_hmos",
90d9f0492fSopenharmony_ci        "persist.init.debug.dump.trigger", "persist.init.bootchart.enabled",
91d9f0492fSopenharmony_ci        "persist.init.debug.loglevel", "persist.samgr.cache.sa",
92d9f0492fSopenharmony_ci        "persist.sys.hilog.binary.on", "persist.sys.hilog.debug.on",
93d9f0492fSopenharmony_ci        "persist.bluetooth.collaboration_service", "persist.bluetooth.switch_enable",
94d9f0492fSopenharmony_ci        "persist.edc.proxy_ap_startup", "persist.edm.edm_enable",
95d9f0492fSopenharmony_ci        "persist.moduleupdate.bms.scan", "persist.nearlink.switch_enable",
96d9f0492fSopenharmony_ci        "persist.parentcontrol.enable", "persist.samgr.moduleupdate.start",
97d9f0492fSopenharmony_ci    };
98d9f0492fSopenharmony_ci    int size = sizeof(publicPersistParams) / sizeof(char*);
99d9f0492fSopenharmony_ci    for (int i = 0; i < size; i++) {
100d9f0492fSopenharmony_ci        if (strncmp(param, publicPersistParams[i], strlen(publicPersistParams[i])) == 0) {
101d9f0492fSopenharmony_ci            return true;
102d9f0492fSopenharmony_ci        }
103d9f0492fSopenharmony_ci    }
104d9f0492fSopenharmony_ci    return false;
105d9f0492fSopenharmony_ci}
106d9f0492fSopenharmony_ci
107d9f0492fSopenharmony_cistatic int LoadOnePublicPersistParam_(const uint32_t *context, const char *name, const char *value)
108d9f0492fSopenharmony_ci{
109d9f0492fSopenharmony_ci    if (IsPublicParam(name)) {
110d9f0492fSopenharmony_ci        return LoadOnePersistParam_(context, name, value);
111d9f0492fSopenharmony_ci    }
112d9f0492fSopenharmony_ci    PARAM_LOGI("%s is private, ignore", name);
113d9f0492fSopenharmony_ci    return 0;
114d9f0492fSopenharmony_ci}
115d9f0492fSopenharmony_ci
116d9f0492fSopenharmony_cistatic void LoadPersistParam_(const bool clearFactoryPersistParams, const char *fileName,
117d9f0492fSopenharmony_ci    char *buffer, uint32_t buffSize, bool isFullLoad)
118d9f0492fSopenharmony_ci{
119d9f0492fSopenharmony_ci    FILE *fp = fopen(fileName, "r");
120d9f0492fSopenharmony_ci    PARAM_WARNING_CHECK(fp != NULL, return, "No valid persist parameter file %s", fileName);
121d9f0492fSopenharmony_ci    int ret = 0;
122d9f0492fSopenharmony_ci    uint32_t paramNum = 0;
123d9f0492fSopenharmony_ci    while (fgets(buffer, buffSize, fp) != NULL) {
124d9f0492fSopenharmony_ci        buffer[buffSize - 1] = '\0';
125d9f0492fSopenharmony_ci        if (isFullLoad) {
126d9f0492fSopenharmony_ci            ret = SplitParamString(buffer, NULL, 0, LoadOnePersistParam_, (uint32_t*)&clearFactoryPersistParams);
127d9f0492fSopenharmony_ci        } else {
128d9f0492fSopenharmony_ci            ret = SplitParamString(buffer, NULL, 0, LoadOnePublicPersistParam_, (uint32_t*)&clearFactoryPersistParams);
129d9f0492fSopenharmony_ci        }
130d9f0492fSopenharmony_ci        PARAM_CHECK(ret == 0, continue, "Failed to set param %d %s", ret, buffer);
131d9f0492fSopenharmony_ci        paramNum++;
132d9f0492fSopenharmony_ci    }
133d9f0492fSopenharmony_ci    (void)fclose(fp);
134d9f0492fSopenharmony_ci    PARAM_LOGI("LoadPersistParam from file %s paramNum %d", fileName, paramNum);
135d9f0492fSopenharmony_ci}
136d9f0492fSopenharmony_ci
137d9f0492fSopenharmony_cistatic bool GetPersistFilePath(char **path, char **tmpPath, int fileType)
138d9f0492fSopenharmony_ci{
139d9f0492fSopenharmony_ci    bool isFullLoad = true;
140d9f0492fSopenharmony_ci    if (InUpdaterMode() == 1) {
141d9f0492fSopenharmony_ci        *path = "/param/persist_parameters";
142d9f0492fSopenharmony_ci        *tmpPath = "/param/tmp_persist_paramters";
143d9f0492fSopenharmony_ci        return isFullLoad;
144d9f0492fSopenharmony_ci    }
145d9f0492fSopenharmony_ci    if (fileType == PUBLIC_PERSIST_FILE) {
146d9f0492fSopenharmony_ci        isFullLoad = false;
147d9f0492fSopenharmony_ci        if (access(PARAM_PERSIST_SAVE_PATH, F_OK) == 0 && access(PARAM_PUBLIC_PERSIST_SAVE_PATH, F_OK) != 0) {
148d9f0492fSopenharmony_ci            int ret = rename(PARAM_PERSIST_SAVE_PATH, PARAM_PUBLIC_PERSIST_SAVE_PATH);
149d9f0492fSopenharmony_ci            if (ret != 0) {
150d9f0492fSopenharmony_ci                PARAM_LOGE("rename failed %s", PARAM_PERSIST_SAVE_PATH);
151d9f0492fSopenharmony_ci            }
152d9f0492fSopenharmony_ci        } else {
153d9f0492fSopenharmony_ci            CheckAndCreateDir(PARAM_PUBLIC_PERSIST_SAVE_PATH);
154d9f0492fSopenharmony_ci        }
155d9f0492fSopenharmony_ci        *path = PARAM_PUBLIC_PERSIST_SAVE_PATH;
156d9f0492fSopenharmony_ci        *tmpPath = PARAM_PUBLIC_PERSIST_SAVE_TMP_PATH;
157d9f0492fSopenharmony_ci        return isFullLoad;
158d9f0492fSopenharmony_ci    }
159d9f0492fSopenharmony_ci    if (access(PARAM_OLD_PERSIST_SAVE_PATH, F_OK) == 0 && access(PARAM_PRIVATE_PERSIST_SAVE_PATH, F_OK) != 0) {
160d9f0492fSopenharmony_ci        int ret = rename(PARAM_OLD_PERSIST_SAVE_PATH, PARAM_PRIVATE_PERSIST_SAVE_PATH);
161d9f0492fSopenharmony_ci        if (ret != 0) {
162d9f0492fSopenharmony_ci            PARAM_LOGE("rename failed %s", PARAM_OLD_PERSIST_SAVE_PATH);
163d9f0492fSopenharmony_ci        }
164d9f0492fSopenharmony_ci    } else {
165d9f0492fSopenharmony_ci        CheckAndCreateDir(PARAM_PRIVATE_PERSIST_SAVE_PATH);
166d9f0492fSopenharmony_ci    }
167d9f0492fSopenharmony_ci    *path = PARAM_PRIVATE_PERSIST_SAVE_PATH;
168d9f0492fSopenharmony_ci    *tmpPath = PARAM_PRIVATE_PERSIST_SAVE_TMP_PATH;
169d9f0492fSopenharmony_ci    return isFullLoad;
170d9f0492fSopenharmony_ci}
171d9f0492fSopenharmony_ci
172d9f0492fSopenharmony_cistatic int LoadPersistParam(int fileType)
173d9f0492fSopenharmony_ci{
174d9f0492fSopenharmony_ci    bool clearFactoryPersistParams = false;
175d9f0492fSopenharmony_ci    char value[PARAM_VALUE_LEN_MAX] = {0};
176d9f0492fSopenharmony_ci    uint32_t len = PARAM_VALUE_LEN_MAX;
177d9f0492fSopenharmony_ci    int ret = SystemReadParam("const.startup.param.version", value, &len);
178d9f0492fSopenharmony_ci    if ((ret != 0 || strcmp(value, "1") != 0) &&
179d9f0492fSopenharmony_ci        (access(PERSIST_PARAM_FIXED_FLAGS, F_OK) != 0)) {
180d9f0492fSopenharmony_ci        clearFactoryPersistParams = true;
181d9f0492fSopenharmony_ci    }
182d9f0492fSopenharmony_ci    const uint32_t buffSize = PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX + 10;  // 10 max len
183d9f0492fSopenharmony_ci    char *buffer = calloc(1, buffSize);
184d9f0492fSopenharmony_ci    PARAM_CHECK(buffer != NULL, return -1, "Failed to alloc");
185d9f0492fSopenharmony_ci
186d9f0492fSopenharmony_ci    char *tmpPath = "";
187d9f0492fSopenharmony_ci    char *path = "";
188d9f0492fSopenharmony_ci    bool isFullLoad = GetPersistFilePath(&path, &tmpPath, fileType);
189d9f0492fSopenharmony_ci    LoadPersistParam_(clearFactoryPersistParams, path, buffer, buffSize, isFullLoad);
190d9f0492fSopenharmony_ci    LoadPersistParam_(clearFactoryPersistParams, tmpPath, buffer, buffSize, isFullLoad);
191d9f0492fSopenharmony_ci    free(buffer);
192d9f0492fSopenharmony_ci    if (clearFactoryPersistParams) {
193d9f0492fSopenharmony_ci        FILE *fp = fopen(PERSIST_PARAM_FIXED_FLAGS, "w");
194d9f0492fSopenharmony_ci        PARAM_CHECK(fp != NULL, return -1, "create file %s fail error %d", PERSIST_PARAM_FIXED_FLAGS, errno);
195d9f0492fSopenharmony_ci        (void)fclose(fp);
196d9f0492fSopenharmony_ci    }
197d9f0492fSopenharmony_ci    return 0;
198d9f0492fSopenharmony_ci}
199d9f0492fSopenharmony_ci
200d9f0492fSopenharmony_cistatic int SavePersistParam(const char *name, const char *value)
201d9f0492fSopenharmony_ci{
202d9f0492fSopenharmony_ci    ParamMutexPend(&g_saveMutex);
203d9f0492fSopenharmony_ci    int ret = -1;
204d9f0492fSopenharmony_ci    if (InUpdaterMode() == 1) {
205d9f0492fSopenharmony_ci        char *path = "/param/persist_parameters";
206d9f0492fSopenharmony_ci        FILE *fp = fopen(path, "a+");
207d9f0492fSopenharmony_ci        if (fp != NULL) {
208d9f0492fSopenharmony_ci            ret = fprintf(fp, "%s=%s\n", name, value);
209d9f0492fSopenharmony_ci            (void)fclose(fp);
210d9f0492fSopenharmony_ci        }
211d9f0492fSopenharmony_ci        ParamMutexPost(&g_saveMutex);
212d9f0492fSopenharmony_ci        return ret;
213d9f0492fSopenharmony_ci    }
214d9f0492fSopenharmony_ci    const char *path[PERSIST_HANDLE_MAX] = { PARAM_PUBLIC_PERSIST_SAVE_PATH, PARAM_PRIVATE_PERSIST_SAVE_PATH };
215d9f0492fSopenharmony_ci    for (int i = 0; i < PERSIST_HANDLE_MAX; i++) {
216d9f0492fSopenharmony_ci        FILE *fp = fopen(path[i], "a+");
217d9f0492fSopenharmony_ci        if (fp != NULL) {
218d9f0492fSopenharmony_ci            ret = fprintf(fp, "%s=%s\n", name, value);
219d9f0492fSopenharmony_ci            (void)fclose(fp);
220d9f0492fSopenharmony_ci        }
221d9f0492fSopenharmony_ci    }
222d9f0492fSopenharmony_ci    ParamMutexPost(&g_saveMutex);
223d9f0492fSopenharmony_ci    if (ret <= 0) {
224d9f0492fSopenharmony_ci        PARAM_LOGE("Failed to save persist param %s", name);
225d9f0492fSopenharmony_ci    }
226d9f0492fSopenharmony_ci    return ret;
227d9f0492fSopenharmony_ci}
228d9f0492fSopenharmony_ci
229d9f0492fSopenharmony_cistatic int BatchSavePersistParamBegin(PERSIST_SAVE_HANDLE *handle)
230d9f0492fSopenharmony_ci{
231d9f0492fSopenharmony_ci    ParamMutexPend(&g_saveMutex);
232d9f0492fSopenharmony_ci    if (InUpdaterMode() == 1) {
233d9f0492fSopenharmony_ci        char *path = "/param/tmp_persist_parameters";
234d9f0492fSopenharmony_ci        unlink(path);
235d9f0492fSopenharmony_ci        FILE *fp = fopen(path, "w");
236d9f0492fSopenharmony_ci        if (fp == NULL) {
237d9f0492fSopenharmony_ci            ParamMutexPost(&g_saveMutex);
238d9f0492fSopenharmony_ci            PARAM_LOGE("Open file %s fail error %d", path, errno);
239d9f0492fSopenharmony_ci            return -1;
240d9f0492fSopenharmony_ci        }
241d9f0492fSopenharmony_ci        handle[0] = (PERSIST_SAVE_HANDLE)fp;
242d9f0492fSopenharmony_ci        return 0;
243d9f0492fSopenharmony_ci    }
244d9f0492fSopenharmony_ci    const char *path[PERSIST_HANDLE_MAX] = {
245d9f0492fSopenharmony_ci        PARAM_PUBLIC_PERSIST_SAVE_TMP_PATH,
246d9f0492fSopenharmony_ci        PARAM_PRIVATE_PERSIST_SAVE_TMP_PATH
247d9f0492fSopenharmony_ci    };
248d9f0492fSopenharmony_ci    for (int i = 0; i < PERSIST_HANDLE_MAX; i++) {
249d9f0492fSopenharmony_ci        unlink(path[i]);
250d9f0492fSopenharmony_ci        FILE *fp = fopen(path[i], "w");
251d9f0492fSopenharmony_ci        if (fp == NULL) {
252d9f0492fSopenharmony_ci            PARAM_LOGE("Open file %s fail error %d", path[i], errno);
253d9f0492fSopenharmony_ci        } else {
254d9f0492fSopenharmony_ci            handle[i] = (PERSIST_SAVE_HANDLE)fp;
255d9f0492fSopenharmony_ci        }
256d9f0492fSopenharmony_ci    }
257d9f0492fSopenharmony_ci    return 0;
258d9f0492fSopenharmony_ci}
259d9f0492fSopenharmony_ci
260d9f0492fSopenharmony_cistatic int BatchSavePersistParam(PERSIST_SAVE_HANDLE handle[], const char *name, const char *value)
261d9f0492fSopenharmony_ci{
262d9f0492fSopenharmony_ci    int ret = 0;
263d9f0492fSopenharmony_ci    for (int i = 0; i < PERSIST_HANDLE_MAX; i++) {
264d9f0492fSopenharmony_ci        FILE *fp = (FILE*)handle[i];
265d9f0492fSopenharmony_ci        if (fp != NULL) {
266d9f0492fSopenharmony_ci            ret = fprintf(fp, "%s=%s\n", name, value);
267d9f0492fSopenharmony_ci            PARAM_CHECK(ret > 0, return -1, "Batchsavepersistparam fail, error %d", errno);
268d9f0492fSopenharmony_ci        }
269d9f0492fSopenharmony_ci    }
270d9f0492fSopenharmony_ci    return (ret > 0) ? 0 : -1;
271d9f0492fSopenharmony_ci}
272d9f0492fSopenharmony_ci
273d9f0492fSopenharmony_cistatic void BatchSavePersistParamEnd(PERSIST_SAVE_HANDLE handle[])
274d9f0492fSopenharmony_ci{
275d9f0492fSopenharmony_ci    int ret = 0;
276d9f0492fSopenharmony_ci    if (InUpdaterMode() == 1) {
277d9f0492fSopenharmony_ci        FILE *fp = (FILE *)handle[0];
278d9f0492fSopenharmony_ci        (void)fflush(fp);
279d9f0492fSopenharmony_ci        (void)fsync(fileno(fp));
280d9f0492fSopenharmony_ci        (void)fclose(fp);
281d9f0492fSopenharmony_ci        unlink("/param/persist_parameters");
282d9f0492fSopenharmony_ci        ret = rename("/param/tmp_persist_parameters", "/param/persist_parameters");
283d9f0492fSopenharmony_ci        ParamMutexPost(&g_saveMutex);
284d9f0492fSopenharmony_ci        return;
285d9f0492fSopenharmony_ci    }
286d9f0492fSopenharmony_ci    const char *tmpPath[PERSIST_HANDLE_MAX] = {
287d9f0492fSopenharmony_ci        PARAM_PUBLIC_PERSIST_SAVE_TMP_PATH,
288d9f0492fSopenharmony_ci        PARAM_PRIVATE_PERSIST_SAVE_TMP_PATH
289d9f0492fSopenharmony_ci    };
290d9f0492fSopenharmony_ci    const char *path[PERSIST_HANDLE_MAX] = {
291d9f0492fSopenharmony_ci        PARAM_PUBLIC_PERSIST_SAVE_PATH,
292d9f0492fSopenharmony_ci        PARAM_PRIVATE_PERSIST_SAVE_PATH
293d9f0492fSopenharmony_ci    };
294d9f0492fSopenharmony_ci    for (int i = 0; i < PERSIST_HANDLE_MAX; i++) {
295d9f0492fSopenharmony_ci        if (handle[i] != NULL) {
296d9f0492fSopenharmony_ci            FILE *fp = (FILE *)handle[i];
297d9f0492fSopenharmony_ci            (void)fflush(fp);
298d9f0492fSopenharmony_ci            (void)fsync(fileno(fp));
299d9f0492fSopenharmony_ci            (void)fclose(fp);
300d9f0492fSopenharmony_ci        }
301d9f0492fSopenharmony_ci        unlink(path[i]);
302d9f0492fSopenharmony_ci        ret = rename(tmpPath[i], path[i]);
303d9f0492fSopenharmony_ci    }
304d9f0492fSopenharmony_ci    ParamMutexPost(&g_saveMutex);
305d9f0492fSopenharmony_ci}
306d9f0492fSopenharmony_ci
307d9f0492fSopenharmony_ciint RegisterPersistParamOps(PersistParamOps *ops)
308d9f0492fSopenharmony_ci{
309d9f0492fSopenharmony_ci    ParamMutexCreate(&g_saveMutex);
310d9f0492fSopenharmony_ci    PARAM_CHECK(ops != NULL, return -1, "Invalid ops");
311d9f0492fSopenharmony_ci    ops->save = SavePersistParam;
312d9f0492fSopenharmony_ci    ops->load = LoadPersistParam;
313d9f0492fSopenharmony_ci    ops->batchSaveBegin = BatchSavePersistParamBegin;
314d9f0492fSopenharmony_ci    ops->batchSave = BatchSavePersistParam;
315d9f0492fSopenharmony_ci    ops->batchSaveEnd = BatchSavePersistParamEnd;
316d9f0492fSopenharmony_ci    return 0;
317d9f0492fSopenharmony_ci}