1d9f0492fSopenharmony_ci/*
2d9f0492fSopenharmony_ci * Copyright (c) 2024 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
25d9f0492fSopenharmony_ci// for linux, no mutex
26d9f0492fSopenharmony_cistatic ParamMutex g_saveMutex = {};
27d9f0492fSopenharmony_ci
28d9f0492fSopenharmony_cistatic int LoadOnePersistParam_(const uint32_t *context, const char *name, const char *value)
29d9f0492fSopenharmony_ci{
30d9f0492fSopenharmony_ci    UNUSED(context);
31d9f0492fSopenharmony_ci    uint32_t dataIndex = 0;
32d9f0492fSopenharmony_ci    return WriteParam(name, value, &dataIndex, 0);
33d9f0492fSopenharmony_ci}
34d9f0492fSopenharmony_ci
35d9f0492fSopenharmony_cistatic void LoadPersistParam_(const char *fileName, char *buffer, uint32_t buffSize)
36d9f0492fSopenharmony_ci{
37d9f0492fSopenharmony_ci    FILE *fp = fopen(fileName, "r");
38d9f0492fSopenharmony_ci    PARAM_WARNING_CHECK(fp != NULL, return, "No valid persist parameter file %s", fileName);
39d9f0492fSopenharmony_ci
40d9f0492fSopenharmony_ci    uint32_t paramNum = 0;
41d9f0492fSopenharmony_ci    while (fgets(buffer, buffSize, fp) != NULL) {
42d9f0492fSopenharmony_ci        buffer[buffSize - 1] = '\0';
43d9f0492fSopenharmony_ci        int ret = SplitParamString(buffer, NULL, 0, LoadOnePersistParam_, NULL);
44d9f0492fSopenharmony_ci        PARAM_CHECK(ret == 0, continue, "Failed to set param %d %s", ret, buffer);
45d9f0492fSopenharmony_ci        paramNum++;
46d9f0492fSopenharmony_ci    }
47d9f0492fSopenharmony_ci    (void)fclose(fp);
48d9f0492fSopenharmony_ci    PARAM_LOGI("LoadPersistParam from file %s paramNum %d", fileName, paramNum);
49d9f0492fSopenharmony_ci}
50d9f0492fSopenharmony_ci
51d9f0492fSopenharmony_cistatic int LoadPersistParam(void)
52d9f0492fSopenharmony_ci{
53d9f0492fSopenharmony_ci    CheckAndCreateDir(PARAM_PERSIST_SAVE_PATH);
54d9f0492fSopenharmony_ci    const uint32_t buffSize = PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX + 10;  // 10 max len
55d9f0492fSopenharmony_ci    char *buffer = malloc(buffSize);
56d9f0492fSopenharmony_ci    PARAM_CHECK(buffer != NULL, return -1, "Failed to alloc");
57d9f0492fSopenharmony_ci
58d9f0492fSopenharmony_ci    int updaterMode = InUpdaterMode();
59d9f0492fSopenharmony_ci    char *tmpPath = (updaterMode == 0) ? PARAM_PERSIST_SAVE_PATH : "/param/persist_parameters";
60d9f0492fSopenharmony_ci    LoadPersistParam_(tmpPath, buffer, buffSize);
61d9f0492fSopenharmony_ci    tmpPath = (updaterMode == 0) ? PARAM_PERSIST_SAVE_TMP_PATH : "/param/tmp_persist_parameters";
62d9f0492fSopenharmony_ci    LoadPersistParam_(tmpPath, buffer, buffSize);
63d9f0492fSopenharmony_ci    free(buffer);
64d9f0492fSopenharmony_ci    return 0;
65d9f0492fSopenharmony_ci}
66d9f0492fSopenharmony_ci
67d9f0492fSopenharmony_cistatic int SavePersistParam(const char *name, const char *value)
68d9f0492fSopenharmony_ci{
69d9f0492fSopenharmony_ci    ParamMutexPend(&g_saveMutex);
70d9f0492fSopenharmony_ci    char *path = (InUpdaterMode() == 0) ? PARAM_PERSIST_SAVE_PATH : "/param/persist_parameters";
71d9f0492fSopenharmony_ci    FILE *fp = fopen(path, "a+");
72d9f0492fSopenharmony_ci    int ret = -1;
73d9f0492fSopenharmony_ci    if (fp != NULL) {
74d9f0492fSopenharmony_ci        ret = fprintf(fp, "%s=%s\n", name, value);
75d9f0492fSopenharmony_ci        (void)fclose(fp);
76d9f0492fSopenharmony_ci    }
77d9f0492fSopenharmony_ci    ParamMutexPost(&g_saveMutex);
78d9f0492fSopenharmony_ci    if (ret <= 0) {
79d9f0492fSopenharmony_ci        PARAM_LOGE("Failed to save persist param %s", name);
80d9f0492fSopenharmony_ci    }
81d9f0492fSopenharmony_ci    return ret;
82d9f0492fSopenharmony_ci}
83d9f0492fSopenharmony_ci
84d9f0492fSopenharmony_cistatic int BatchSavePersistParamBegin(PERSIST_SAVE_HANDLE *handle)
85d9f0492fSopenharmony_ci{
86d9f0492fSopenharmony_ci    ParamMutexPend(&g_saveMutex);
87d9f0492fSopenharmony_ci    char *path = (InUpdaterMode() == 0) ? PARAM_PERSIST_SAVE_TMP_PATH : "/param/tmp_persist_parameters";
88d9f0492fSopenharmony_ci    unlink(path);
89d9f0492fSopenharmony_ci    FILE *fp = fopen(path, "w");
90d9f0492fSopenharmony_ci    if (fp == NULL) {
91d9f0492fSopenharmony_ci        ParamMutexPost(&g_saveMutex);
92d9f0492fSopenharmony_ci        PARAM_LOGE("Open file %s fail error %d", path, errno);
93d9f0492fSopenharmony_ci        return -1;
94d9f0492fSopenharmony_ci    }
95d9f0492fSopenharmony_ci    *handle = (PERSIST_SAVE_HANDLE)fp;
96d9f0492fSopenharmony_ci    return 0;
97d9f0492fSopenharmony_ci}
98d9f0492fSopenharmony_ci
99d9f0492fSopenharmony_cistatic int BatchSavePersistParam(PERSIST_SAVE_HANDLE handle, const char *name, const char *value)
100d9f0492fSopenharmony_ci{
101d9f0492fSopenharmony_ci    FILE *fp = (FILE *)handle;
102d9f0492fSopenharmony_ci    int ret = fprintf(fp, "%s=%s\n", name, value);
103d9f0492fSopenharmony_ci    PARAM_LOGV("BatchSavePersistParam %s=%s", name, value);
104d9f0492fSopenharmony_ci    return (ret > 0) ? 0 : -1;
105d9f0492fSopenharmony_ci}
106d9f0492fSopenharmony_ci
107d9f0492fSopenharmony_cistatic void BatchSavePersistParamEnd(PERSIST_SAVE_HANDLE handle)
108d9f0492fSopenharmony_ci{
109d9f0492fSopenharmony_ci    int ret;
110d9f0492fSopenharmony_ci    FILE *fp = (FILE *)handle;
111d9f0492fSopenharmony_ci    (void)fflush(fp);
112d9f0492fSopenharmony_ci    (void)fsync(fileno(fp));
113d9f0492fSopenharmony_ci    (void)fclose(fp);
114d9f0492fSopenharmony_ci    if (InUpdaterMode() == 0) {
115d9f0492fSopenharmony_ci        unlink(PARAM_PERSIST_SAVE_PATH);
116d9f0492fSopenharmony_ci        ret = rename(PARAM_PERSIST_SAVE_TMP_PATH, PARAM_PERSIST_SAVE_PATH);
117d9f0492fSopenharmony_ci    } else {
118d9f0492fSopenharmony_ci        unlink("/param/persist_parameters");
119d9f0492fSopenharmony_ci        ret = rename("/param/tmp_persist_parameters", "/param/persist_parameters");
120d9f0492fSopenharmony_ci    }
121d9f0492fSopenharmony_ci    ParamMutexPost(&g_saveMutex);
122d9f0492fSopenharmony_ci    PARAM_CHECK(ret == 0, return, "BatchSavePersistParamEnd %s fail error %d", PARAM_PERSIST_SAVE_TMP_PATH, errno);
123d9f0492fSopenharmony_ci}
124d9f0492fSopenharmony_ci
125d9f0492fSopenharmony_ciint RegisterPersistParamOps(PersistParamOps *ops)
126d9f0492fSopenharmony_ci{
127d9f0492fSopenharmony_ci    ParamMutexCreate(&g_saveMutex);
128d9f0492fSopenharmony_ci    PARAM_CHECK(ops != NULL, return -1, "Invalid ops");
129d9f0492fSopenharmony_ci    ops->save = SavePersistParam;
130d9f0492fSopenharmony_ci    ops->load = LoadPersistParam;
131d9f0492fSopenharmony_ci    ops->batchSaveBegin = BatchSavePersistParamBegin;
132d9f0492fSopenharmony_ci    ops->batchSave = BatchSavePersistParam;
133d9f0492fSopenharmony_ci    ops->batchSaveEnd = BatchSavePersistParamEnd;
134d9f0492fSopenharmony_ci    return 0;
135d9f0492fSopenharmony_ci}