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 29static ParamMutex g_saveMutex = {}; 30 31static 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 71static 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 107static 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 116static 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 137static 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 172static 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 200static 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 229static 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 260static 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 273static 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 307int 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}