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