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