| /******************************************************************************* |
| * °æÈ¨ËùÓÐ (C)2016, ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£ |
| * |
| * ÎļþÃû³Æ: nvserver.c |
| * Îļþ±êʶ: nvserver.c |
| * ÄÚÈÝÕªÒª: nvºǫ́ӦÓÃʵÏÖÎļþ |
| * |
| * ÐÞ¸ÄÈÕÆÚ °æ±¾ºÅ Ð޸ıê¼Ç ÐÞ¸ÄÈË ÐÞ¸ÄÄÚÈÝ |
| * ------------------------------------------------------------------------------ |
| * 2016/06/13 V1.0 Create ÁõÑÇÄÏ ´´½¨ |
| * |
| *******************************************************************************/ |
| |
| /******************************************************************************* |
| * Í·Îļþ * |
| *******************************************************************************/ |
| #include <unistd.h> |
| #include <errno.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <dirent.h> |
| #include <string.h> |
| #include <sys/file.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <sys/ipc.h> |
| #include <sys/msg.h> |
| |
| #include "nvserver.h" |
| #include "nv_typedef.h" |
| #include <message.h> |
| |
| #ifdef FOTA_AB |
| #include "pub_flags.h" |
| #include "flags_api.h" |
| #endif |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| /******************************************************************************* |
| * ³£Á¿¶¨Òå * |
| *******************************************************************************/ |
| |
| /******************************************************************************* |
| * ºê¶¨Òå * |
| *******************************************************************************/ |
| |
| /******************************************************************************* |
| * Êý¾ÝÀàÐͶ¨Òå * |
| *******************************************************************************/ |
| |
| /******************************************************************************* |
| * ¾Ö²¿º¯ÊýÉùÃ÷ * |
| *******************************************************************************/ |
| static void nvConfig(); |
| static void nvInit(); |
| static int nvDirInit(); |
| static void analyMsg(T_NV_MSG_INFO *msgrecv, T_NV_MSG_RESULT *msgsnd); |
| static bool checkNvFs(char *file); |
| static bool isCfgConfiged(char *configFile); |
| static bool isNvConfiged(char *configFile); |
| static uint getSum(const char *s, int len); |
| static int loadFactroyParam(T_NV_NODE *list); |
| static int restoreNvFs(char *dstFile, char *srcFile); |
| static int loadNvFs(char *file); |
| static int addConfigFile(char *nvFile, char *configFile); |
| static int saveNvFs(char *nvName, char *nvFile); |
| static int nvset(char *file, const char *key, const char *value, int saveFlag); |
| static int nvget(char *file, char *key, char *value); |
| static int nvunset(char *file, char *key); |
| static int nvclear(char *file); |
| static int nvreset(char *file); |
| static int nvcommit(char *file); |
| |
| /******************************************************************************* |
| * ¾Ö²¿¾²Ì¬±äÁ¿¶¨Òå * |
| *******************************************************************************/ |
| |
| /******************************************************************************* |
| * È«¾Ö±äÁ¿¶¨Òå * |
| *******************************************************************************/ |
| T_NV_NODE *nv_list; |
| |
| /******************************************************************************* |
| * ¾Ö²¿º¯ÊýʵÏÖ * |
| *******************************************************************************/ |
| |
| /******************************************************************************* |
| * È«¾Öº¯ÊýʵÏÖ * |
| *******************************************************************************/ |
| |
| /******************************************************************************* |
| * ¹¦ÄÜÃèÊö: main |
| * ²ÎÊý˵Ã÷: |
| * (´«Èë²ÎÊý) void |
| * (´«³ö²ÎÊý) void |
| * ·µ »Ø Öµ: void |
| * ÆäËü˵Ã÷: void |
| *******************************************************************************/ |
| int nvserver_main(int argc, char *argv[]) |
| { |
| int msgId = 0; |
| T_NV_MSG_INFO rcvBuf; |
| T_NV_MSG_RESULT sndBuf; |
| struct msqid_ds msgInfo; |
| |
| prctl(PR_SET_NAME, "nvserver", 0, 0, 0); |
| |
| memset( &rcvBuf, 0, sizeof(rcvBuf)); |
| memset( &sndBuf, 0, sizeof(sndBuf)); |
| memset( &msgInfo, 0, sizeof(msgInfo)); |
| |
| msgId = msgget(MODULE_ID_NV, IPC_CREAT | 0600); |
| if(-1 == msgId) |
| { |
| printf("nvserver error: msgget msgId fail, errno = %d\n", errno); |
| return -1; |
| } |
| |
| if(-1 != msgctl(msgId, IPC_STAT, &msgInfo)) |
| { |
| msgInfo.msg_qbytes = 262144; // 256k |
| if(-1 == msgctl(msgId, IPC_SET, &msgInfo)) |
| printf("nvserver error: msgctl msgId fail, errno = %d\n", errno); |
| } |
| |
| if(nvDirInit() != 0) |
| { |
| printf("nvDirInit faile!\n"); |
| return -1; |
| } |
| |
| nvConfig(); |
| |
| nvInit(); |
| |
| // ÏûÏ¢½»»¥ |
| while(1) |
| { |
| if(-1 == msgrcv(msgId, &rcvBuf, sizeof(T_NV_MSG_INFO) - sizeof(long), MSG_TYPE_NV, 0)) |
| { |
| printf("nvserver error: nvserver msgrcv fail, errno = %d!\n", errno); |
| continue; |
| } |
| |
| analyMsg(&rcvBuf, &sndBuf); |
| msgsnd_retry: |
| if(-1 == msgsnd(msgId, &sndBuf, sizeof(T_NV_MSG_RESULT) - sizeof(long), 0)) |
| { |
| if (errno == EINTR) |
| { |
| printf("nvserver error: msgsnd fail, errno = EINTR!\n"); |
| goto msgsnd_retry; |
| } |
| printf("nvserver error: nvserver msgsnd fail, errno = %d!\n", errno); |
| continue; |
| } |
| } |
| |
| return (0); |
| } |
| |
| /******************************************************************************* |
| * ¹¦ÄÜÃèÊö: configdir |
| * ²ÎÊý˵Ã÷: |
| * (´«Èë²ÎÊý) dir |
| * (´«³ö²ÎÊý) void |
| * ·µ »Ø Öµ: void |
| * ÆäËü˵Ã÷: void |
| *******************************************************************************/ |
| static void configdir(char *dir) |
| { |
| DIR *dp; |
| int ret; |
| |
| struct dirent *entry; |
| struct stat statbuf; |
| if((dp = opendir(dir)) == NULL) |
| { |
| fprintf(stderr,"cannot open directory: %s\n", dir); |
| return; |
| } |
| |
| chdir(dir); |
| while((entry = readdir(dp)) != NULL) |
| { |
| ret = lstat(entry->d_name,&statbuf); |
| if (ret < 0) |
| { |
| fprintf(stderr,"lstat error: %s\n", strerror(errno)); |
| chdir(".."); |
| closedir(dp); |
| return; |
| } |
| if(!S_ISDIR(statbuf.st_mode)) |
| { |
| |
| if(strcmp(".",entry->d_name) == 0 ||strcmp("..",entry->d_name) == 0) |
| continue; |
| |
| if(!isNvConfiged(entry->d_name)) |
| { |
| if(addConfigFile(entry->d_name, NULL) != RESULT_SUCCESS) |
| printf("nvserver error:config %s error!\n", entry->d_name); |
| } |
| } |
| } |
| chdir(".."); |
| closedir(dp); |
| } |
| |
| /******************************************************************************* |
| * ¹¦ÄÜÃèÊö: nvConfig |
| * ²ÎÊý˵Ã÷: |
| * (´«Èë²ÎÊý) void |
| * (´«³ö²ÎÊý) void |
| * ·µ »Ø Öµ: void |
| * ÆäËü˵Ã÷: void |
| *******************************************************************************/ |
| static void nvConfig() |
| { |
| char *val = NULL; |
| FILE *fp = NULL; |
| char buf[NV_MAX_CONFIG_LEN] = {0}; |
| |
| fp = fopen(NV_CONFIG_FILE, "ro"); |
| if(!fp) |
| { |
| printf("nvserver error:open %s file fail errno = %d!\n", NV_CONFIG_FILE, errno); |
| return; |
| } |
| |
| while (fgets(buf, NV_MAX_CONFIG_LEN, fp)) |
| { |
| if (buf[0] == '\n' || buf[0] == '#') |
| continue; |
| |
| val = strchr(buf, '='); |
| if (!val) |
| { |
| printf("nvserver error:%s file format error: str = %s!\n", NV_CONFIG_FILE, buf); |
| continue; |
| } |
| |
| // buf=nvconfig val=nvfile |
| buf[strlen(buf) - 1] = '\0'; |
| *val++ = '\0'; |
| |
| if(!isCfgConfiged(buf)) |
| { |
| if(addConfigFile(val, buf) != RESULT_SUCCESS) |
| printf("nvserver error:config %s error!\n", buf); |
| } |
| } |
| |
| fclose(fp); |
| |
| configdir(NV_FS_MAIN_PATH); |
| } |
| |
| /******************************************************************************* |
| * ¹¦ÄÜÃèÊö: nvDirInit |
| * ²ÎÊý˵Ã÷: |
| * (´«Èë²ÎÊý) void |
| * (´«³ö²ÎÊý) void |
| * ·µ »Ø Öµ: void |
| * ÆäËü˵Ã÷: void |
| *******************************************************************************/ |
| static int nvDirInit() |
| { |
| if(access(NV_FS_PATH, F_OK) != 0) |
| { |
| if(mkdir(NV_FS_PATH, 0755) != 0) |
| { |
| printf("nerver mkdir %s fali,errno=%d\n", NV_FS_PATH, errno); |
| return -1; |
| } |
| |
| if(mkdir(NV_FS_MAIN_PATH, 0755) != 0) |
| { |
| printf("nerver mkdir %s fali,errno=%d\n", NV_FS_MAIN_PATH, errno); |
| return -1; |
| } |
| |
| if(mkdir(NV_FS_BACKUP_PATH, 0755) != 0) |
| { |
| printf("nerver mkdir %s fali,errno=%d\n", NV_FS_BACKUP_PATH, errno); |
| return -1; |
| } |
| } |
| else |
| { |
| if(access(NV_FS_MAIN_PATH, F_OK) != 0) |
| { |
| if(mkdir(NV_FS_MAIN_PATH, 0755) != 0) |
| { |
| printf("nerver mkdir %s fali,errno=%d\n", NV_FS_MAIN_PATH, errno); |
| return -1; |
| } |
| } |
| |
| if(access(NV_FS_BACKUP_PATH, F_OK) != 0) |
| { |
| if(mkdir(NV_FS_BACKUP_PATH, 0755) != 0) |
| { |
| printf("nerver mkdir %s fali,errno=%d\n", NV_FS_BACKUP_PATH, errno); |
| return -1; |
| } |
| } |
| } |
| |
| return 0; |
| } |
| |
| |
| /******************************************************************************* |
| * ¹¦ÄÜÃèÊö: nvInit |
| * ²ÎÊý˵Ã÷: |
| * (´«Èë²ÎÊý) void |
| * (´«³ö²ÎÊý) void |
| * ·µ »Ø Öµ: void |
| * ÆäËü˵Ã÷: void |
| *******************************************************************************/ |
| static void nvInit() |
| { |
| T_NV_NODE *list = NULL; |
| char nvMainFile[NV_PATH_LEN] = {0}; |
| char nvBackupFile[NV_PATH_LEN] = {0}; |
| #ifdef FOTA_AB |
| T_FLAGS_INFO flags_info = {0}; |
| int ret = 0; |
| #endif |
| |
| for(list = nv_list; list; list = list->next) |
| { |
| snprintf(nvMainFile, NV_PATH_LEN, "%s/%s", NV_FS_MAIN_PATH, list->nvFile); |
| snprintf(nvBackupFile, NV_PATH_LEN, "%s/%s", NV_FS_BACKUP_PATH, list->nvFile); |
| |
| if(checkNvFs(nvMainFile)) |
| { |
| if(!checkNvFs(nvBackupFile)) |
| restoreNvFs(nvBackupFile, nvMainFile); |
| } |
| else if(checkNvFs(nvBackupFile)) |
| { |
| restoreNvFs(nvMainFile, nvBackupFile); |
| } |
| else |
| { |
| loadFactroyParam(list); |
| nvcommit(list->nvFile); |
| continue; |
| } |
| |
| loadNvFs(list->nvFile); |
| if(!strcmp(list->nvFile, NV_CFG) && get_update_status() == 2 ){ |
| reloadFactroyParam(list); |
| delete_not_needed(list); |
| nvcommit(list->nvFile); |
| #ifdef FOTA_AB |
| ret = flags_get(&flags_info); |
| flags_info.boot_fota_flag.fota_status = 0; |
| ret = flags_set(&flags_info); |
| #endif |
| } |
| } |
| } |
| |
| /******************************************************************************* |
| * ¹¦ÄÜÃèÊö: hash |
| * ²ÎÊý˵Ã÷: |
| * (´«Èë²ÎÊý) void |
| * (´«³ö²ÎÊý) void |
| * ·µ »Ø Öµ: hash value |
| * ÆäËü˵Ã÷: void |
| *******************************************************************************/ |
| uint hash(const char *s) |
| { |
| uint hash = 0; |
| |
| while (*s) |
| { |
| hash = NV_HASH_MUL * hash + *s++; |
| } |
| |
| return hash; |
| } |
| |
| /******************************************************************************* |
| * ¹¦ÄÜÃèÊö: loadFactroyParam |
| * ²ÎÊý˵Ã÷: |
| * (´«Èë²ÎÊý) list |
| * (´«³ö²ÎÊý) void |
| * ·µ »Ø Öµ: 0±íʾ³É¹¦ -1±íʾʧ°Ü |
| * ÆäËü˵Ã÷: void |
| *******************************************************************************/ |
| static int loadFactroyParam(T_NV_NODE *list) |
| { |
| char *val = NULL; |
| FILE *fp = NULL; |
| T_NV_CONFIG *config = NULL; |
| char buf[NV_MAX_ITEM_LEN] = {0}; |
| |
| for(config = list->fileList; config; config = config->next) |
| { |
| fp = fopen(config->configFile, "ro"); |
| if(!fp) |
| { |
| printf("nvserver error:open %s file fail errno = %d!\n", config->configFile, errno); |
| return RESULT_FILE_OPEN_FAIL; |
| } |
| |
| while (fgets(buf, NV_MAX_ITEM_LEN, fp)) |
| { |
| if (buf[0] == '\n' || buf[0] == '#') |
| continue; |
| |
| val = strchr(buf, '='); |
| if (!val) |
| { |
| printf("nvserver error:%s file format error:string = %s\n", config->configFile, buf); |
| continue; |
| } |
| |
| /*strip line break,the last line may not have a line break*/ |
| if (buf[strlen(buf) - 1] == '\n') |
| buf[strlen(buf) - 1] = '\0'; |
| |
| *val++ = '\0'; |
| |
| nvset(list->nvFile, buf, val, 1); |
| } |
| printf("nvserver loadFactroyParam %s!\n", config->configFile); |
| fclose(fp); |
| } |
| |
| return RESULT_SUCCESS; |
| } |
| |
| /******************************************************************************* |
| * ¹¦ÄÜÃèÊö: checkNvFs |
| * ²ÎÊý˵Ã÷: |
| * (´«Èë²ÎÊý) void |
| * (´«³ö²ÎÊý) void |
| * ·µ »Ø Öµ: bool |
| * ÆäËü˵Ã÷: void |
| *******************************************************************************/ |
| static bool checkNvFs(char *file) |
| { |
| int len = 0; |
| int cnt = 0; |
| FILE * fp = NULL; |
| char * buf = NULL; |
| struct stat statbuff = {0}; |
| |
| if(stat(file, &statbuff) < 0) |
| return false; |
| |
| len = statbuff.st_size; |
| if(len < NV_CHECK_SIZE) |
| return false; |
| |
| fp = fopen(file, "ro"); |
| if (!fp) |
| return false; |
| |
| buf = (char *)malloc(len); |
| if(!buf) |
| { |
| fclose(fp); |
| return false; |
| } |
| |
| cnt = 0; |
| while (cnt < len) |
| { |
| cnt = cnt + fread(buf + cnt, 1, len - cnt, fp); |
| if (ferror(fp)) |
| { |
| clearerr(fp); |
| free(buf); |
| fclose(fp); |
| return false; |
| } |
| } |
| if (len != cnt) |
| { |
| free(buf); |
| fclose(fp); |
| return false; |
| } |
| |
| if(getSum(buf, len - NV_CHECK_SIZE) + NV_FILE_FLAG != *(uint *)(buf + len - NV_CHECK_SIZE)) |
| { |
| free(buf); |
| fclose(fp); |
| return false; |
| } |
| |
| free(buf); |
| fclose(fp); |
| |
| return true; |
| } |
| |
| /******************************************************************************* |
| * ¹¦ÄÜÃèÊö: copyfile |
| * ²ÎÊý˵Ã÷: |
| * (´«Èë²ÎÊý) to:Ä¿±êÎļþ |
| * (´«Èë²ÎÊý) from:Ô´Îļþ |
| * ·µ »Ø Öµ: 0±íʾ³É¹¦,¸ºÖµÊ§°Ü |
| * ÆäËü˵Ã÷: |
| *******************************************************************************/ |
| static int copyfile(const char *from, const char *to) |
| { |
| int fd_to; |
| int fd_from; |
| char buf[4096]; |
| ssize_t nread; |
| int ret = -1; |
| |
| fd_from = open(from, O_RDONLY); |
| if (fd_from < 0) |
| return -2; |
| |
| fd_to = open(to, O_RDWR | O_CREAT | O_TRUNC | O_SYNC, 0640); |
| if (fd_to < 0) { |
| ret = -3; |
| goto out_error; |
| } |
| |
| while (1) |
| { |
| char *out_ptr; |
| ssize_t nwritten; |
| |
| nread = read(fd_from, buf, sizeof(buf)); |
| if (nread == 0) |
| { |
| break; /* read file done*/ |
| } |
| else |
| { |
| if (nread < 0 ) |
| { |
| if (errno == EINTR || errno == EAGAIN) |
| { |
| continue; |
| } |
| else |
| { |
| ret = -4; |
| goto out_error; |
| } |
| } |
| } |
| |
| out_ptr = buf; |
| do |
| { |
| nwritten = write(fd_to, out_ptr, nread); |
| if (nwritten > 0) |
| { |
| nread -= nwritten; |
| out_ptr += nwritten; |
| } |
| else |
| { |
| if (nwritten < 0) |
| { |
| if (errno == EINTR || errno == EAGAIN) |
| { |
| continue; |
| } |
| else |
| { |
| ret = -5; |
| goto out_error; |
| } |
| } |
| } |
| } while (nread > 0); |
| } |
| |
| ret = fsync(fd_to); |
| if (ret < 0) { |
| printf("Sync Failed:%s, file path:%s", strerror(errno), to); |
| goto out_error; |
| } |
| |
| if (close(fd_to) < 0) |
| { |
| fd_to = -1; |
| ret = -6; |
| goto out_error; |
| } |
| close(fd_from); |
| |
| /* Success! */ |
| return 0; |
| |
| out_error: |
| printf("copyfile %s to %s error:%d\n", from, to, ret); |
| close(fd_from); |
| if (fd_to >= 0) |
| close(fd_to); |
| |
| return ret; |
| } |
| |
| /******************************************************************************* |
| * ¹¦ÄÜÃèÊö: restoreNvFs |
| * ²ÎÊý˵Ã÷: |
| * (´«Èë²ÎÊý) dstFile:Ä¿±êÎļþ |
| * (´«Èë²ÎÊý) srcFile:Ô´Îļþ |
| * ·µ »Ø Öµ: 0±íʾ³É¹¦ |
| * ÆäËü˵Ã÷: void |
| *******************************************************************************/ |
| static int restoreNvFs(char *dstFile, char *srcFile) |
| { |
| if (copyfile(srcFile, dstFile) != 0) |
| return RESULT_FAIL; |
| |
| return RESULT_SUCCESS; |
| } |
| |
| /******************************************************************************* |
| * ¹¦ÄÜÃèÊö: loadNvFs |
| * ²ÎÊý˵Ã÷: |
| * (´«Èë²ÎÊý) file:nvÎļþ |
| * (´«³ö²ÎÊý) void |
| * ·µ »Ø Öµ: 0±íʾ³É¹¦ |
| * ÆäËü˵Ã÷: void |
| *******************************************************************************/ |
| static int loadNvFs(char *file) |
| { |
| int len = 0; |
| int cnt = 0; |
| FILE *fp = NULL; |
| char *buf = NULL; |
| char *name = NULL; |
| char *value = NULL; |
| char *eq = NULL; |
| |
| struct stat statbuff = {0}; |
| char nvFile[NV_PATH_LEN] = {0}; |
| |
| sprintf(nvFile, "%s/%s", NV_FS_MAIN_PATH, file); |
| |
| if(stat(nvFile, &statbuff) < 0) |
| return RESULT_FAIL; |
| |
| len = statbuff.st_size; |
| if(NV_CHECK_SIZE > len) |
| return RESULT_FAIL; |
| |
| fp = fopen(nvFile, "ro"); |
| if (!fp) |
| return RESULT_FILE_OPEN_FAIL; |
| |
| len = len - NV_CHECK_SIZE; |
| buf = (char *)malloc(len + 1); |
| if(!buf) |
| { |
| fclose(fp); |
| return RESULT_MALLOC_FAIL; |
| } |
| memset(buf, 0, len + 1); |
| |
| cnt = 0; |
| while (cnt < len) |
| { |
| cnt = cnt + fread(buf + cnt, 1, len - cnt, fp); |
| if (ferror(fp)) |
| { |
| clearerr(fp); |
| fclose(fp); |
| free(buf); |
| return RESULT_FILE_READ_FAIL; |
| } |
| } |
| if (cnt != len) |
| { |
| fclose(fp); |
| free(buf); |
| return RESULT_FILE_READ_FAIL; |
| } |
| |
| buf[len] = '\0'; /* fix warning for coverity */ |
| name = buf; |
| while(*name) |
| { |
| if (!(eq = strchr(name, '='))) |
| { |
| break; |
| } |
| *eq = '\0'; |
| value = eq + 1; |
| |
| nvset(file, name, value, 1); |
| |
| *eq = '='; |
| name = value + strlen(value) + 1; |
| } |
| |
| free(buf); |
| fclose(fp); |
| |
| return RESULT_SUCCESS; |
| } |
| |
| /******************************************************************************* |
| * ¹¦ÄÜÃèÊö: analyMsg |
| * ²ÎÊý˵Ã÷: |
| * (´«Èë²ÎÊý) msgrecv:½ÓÊÕÏûÏ¢ |
| * (´«³ö²ÎÊý) msgsnd:·¢ËÍÏûÏ¢ |
| * ·µ »Ø Öµ: 0±íʾ³É¹¦ |
| * ÆäËü˵Ã÷: void |
| *******************************************************************************/ |
| static void analyMsg(T_NV_MSG_INFO *msgrecv, T_NV_MSG_RESULT *msgsnd) |
| { |
| switch(msgrecv->nvType) |
| { |
| case MSG_GET: |
| msgsnd->result = nvget(msgrecv->file, msgrecv->key, msgsnd->value); |
| break; |
| case MSG_SET: |
| msgsnd->result = nvset(msgrecv->file, msgrecv->key, msgrecv->value, msgrecv->saveflag); |
| break; |
| case MSG_UNSET: |
| msgsnd->result = nvunset(msgrecv->file, msgrecv->key); |
| break; |
| case MSG_CLEAR: |
| msgsnd->result = nvclear(msgrecv->file); |
| break; |
| case MSG_RESET: |
| msgsnd->result = nvreset(msgrecv->file); |
| break; |
| case MSG_SHOW: |
| msgsnd->result = saveNvFs(msgrecv->file, NV_FS_SHOW);; |
| break; |
| case MSG_COMMIT: |
| msgsnd->result = nvcommit(msgrecv->file); |
| break; |
| default: |
| break; |
| } |
| |
| msgsnd->msgType = msgrecv->pid; |
| msgsnd->msgIndex = msgrecv->msgIndex; |
| } |
| |
| /******************************************************************************* |
| * ¹¦ÄÜÃèÊö: addConfigFile |
| * ²ÎÊý˵Ã÷: |
| * (´«Èë²ÎÊý) nvFile:nvÎļþ |
| * (´«Èë²ÎÊý) configFile:ÅäÖÃÎļþ |
| * ·µ »Ø Öµ: 0±íʾ³É¹¦ |
| * ÆäËü˵Ã÷: void |
| *******************************************************************************/ |
| static int addConfigFile(char *nvFile, char *configFile) |
| { |
| T_NV_NODE *list = NULL; |
| T_NV_NODE *newList = NULL; |
| T_NV_CONFIG *newConfig = NULL; |
| |
| if(!nvFile) |
| { |
| printf("nvserver error: param illegal!\n"); |
| return RESULT_INVAL; |
| } |
| |
| if(configFile)// nv has no config file |
| { |
| newConfig = (T_NV_CONFIG * )malloc(sizeof(T_NV_CONFIG)); |
| if(!newConfig) |
| return RESULT_MALLOC_FAIL; |
| |
| strncpy(newConfig->configFile, configFile, NV_PATH_LEN - 1); |
| newConfig->configFile[NV_PATH_LEN - 1] = '\0'; |
| newConfig->next = NULL; |
| } |
| |
| for(list = nv_list; list; list =list->next) |
| { |
| if(strcmp(list->nvFile, nvFile) == 0) |
| break; |
| } |
| |
| if(!list) //can't fine the nv |
| { |
| newList = (T_NV_NODE *)malloc(sizeof(T_NV_NODE)); |
| if(!newList) |
| { |
| if(newConfig) |
| free(newConfig); |
| return RESULT_MALLOC_FAIL; |
| } |
| |
| newList->next = NULL; |
| strncpy(newList->nvFile, nvFile, NV_PATH_LEN - 1); |
| newList->nvFile[NV_PATH_LEN - 1] = '\0'; |
| memset(newList->nvTable, 0, NV_HASH_LEN * 4); |
| |
| newList->fileList = newConfig; |
| |
| if(!nv_list) |
| nv_list = newList; |
| else |
| { |
| newList->next = nv_list->next; |
| nv_list->next = newList; |
| } |
| } |
| else if(!list->fileList) //can't fine the filelist |
| list->fileList = newConfig; |
| else //can't fine the file |
| { |
| if(newConfig == NULL) |
| return RESULT_FAIL; |
| newConfig->next = list->fileList->next; |
| list->fileList->next = newConfig; |
| } |
| |
| return RESULT_SUCCESS; |
| } |
| |
| /******************************************************************************* |
| * ¹¦ÄÜÃèÊö: isConfiged |
| * ²ÎÊý˵Ã÷: |
| * (´«Èë²ÎÊý) configFile:ÅäÖÃÎļþÃû |
| * ·µ »Ø Öµ: void |
| * ÆäËü˵Ã÷: void |
| *******************************************************************************/ |
| static bool isCfgConfiged(char *configFile) |
| { |
| T_NV_NODE *list = NULL; |
| T_NV_CONFIG *config = NULL; |
| |
| for(list = nv_list; list; list = list->next) |
| { |
| for(config = list->fileList; config; config = config->next) |
| { |
| if(!strcmp(config->configFile, configFile)) |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /******************************************************************************* |
| * ¹¦ÄÜÃèÊö: isNvConfiged |
| * ²ÎÊý˵Ã÷: |
| * (´«Èë²ÎÊý) configFile:ÅäÖÃÎļþÃû |
| * ·µ »Ø Öµ: void |
| * ÆäËü˵Ã÷: void |
| *******************************************************************************/ |
| static bool isNvConfiged(char *nvFile) |
| { |
| T_NV_NODE *list = NULL; |
| |
| for(list = nv_list; list; list = list->next) |
| { |
| if(!strcmp(list->nvFile, nvFile)) |
| return true; |
| } |
| return false; |
| } |
| |
| /******************************************************************************* |
| * ¹¦ÄÜÃèÊö: getSum |
| * ²ÎÊý˵Ã÷: |
| * (´«Èë²ÎÊý) s:×Ö·û´®»º³å |
| * ·µ »Ø Öµ: sumÊýÖµ |
| * ÆäËü˵Ã÷: void |
| *******************************************************************************/ |
| static uint getSum(const char *s, int len) |
| { |
| uint sum = 0; |
| char *data = (char*)s; |
| |
| while (len-- > 0) |
| { |
| sum += (*data++); |
| } |
| |
| return sum; |
| } |
| |
| /******************************************************************************* |
| * ¹¦ÄÜÃèÊö: saveNvFs |
| * ²ÎÊý˵Ã÷: |
| * (´«Èë²ÎÊý) nvName:nvÎļþÃû |
| * (´«Èë²ÎÊý) nvFile:nv±£´æÎļþ |
| * ·µ »Ø Öµ: 0±íʾ³É¹¦ |
| * ÆäËü˵Ã÷: void |
| *******************************************************************************/ |
| static int saveNvFs(char *nvName, char *nvFile) |
| { |
| int i = 0; |
| int sum = 0; |
| int bufSize = 0; |
| int itemSize = 0; |
| int ret = 0; |
| int fp = 0; |
| char *buf = NULL; |
| T_NV_NODE * list = NULL; |
| T_NV_ITEM * item = NULL; |
| |
| for(list = nv_list; list; list = list->next) |
| { |
| if(strcmp(list->nvFile, nvName)) |
| continue; |
| |
| fp= open(nvFile, O_SYNC | O_RDWR | O_CREAT | O_TRUNC, 0640); |
| if(fp == -1) |
| { |
| printf("open %s fail,errno = %d\n", nvFile, errno); |
| return RESULT_FILE_OPEN_FAIL; |
| } |
| |
| buf = (char *)malloc(NV_BLOCK_SIZE); |
| if(!buf) |
| { |
| close(fp); |
| return RESULT_MALLOC_FAIL; |
| } |
| |
| for(i = 0; i < NV_HASH_LEN; i ++) |
| { |
| for(item = list->nvTable[i]; item; item = item->next) |
| { |
| if(strcmp(nvFile, NV_FS_SHOW) && !item->saveFlag) |
| continue; |
| |
| itemSize = strlen(item->key) + strlen(item->value) + 2; |
| if(bufSize + itemSize > NV_BLOCK_SIZE) |
| { |
| if(write(fp, buf, bufSize) < 0) |
| { |
| printf("error %s %d: write fail errno = %d\n", __FILE__, __LINE__, errno); |
| close(fp); |
| free(buf); |
| return RESULT_FILE_WRITE_FAIL; |
| } |
| sum += getSum(buf, bufSize); |
| bufSize = 0; |
| } |
| |
| sprintf(buf + bufSize, "%s=%s", item->key, item->value); |
| bufSize += itemSize; |
| } |
| } |
| |
| // last block |
| if(bufSize != 0) |
| { |
| if(write(fp, buf, bufSize) < 0) |
| { |
| printf("nvserver error: write fail errno = %d\n", errno); |
| close(fp); |
| free(buf); |
| return RESULT_FILE_WRITE_FAIL; |
| } |
| sum += getSum(buf, bufSize); |
| } |
| sum += NV_FILE_FLAG; |
| |
| // write sum |
| if(write(fp, &sum, NV_CHECK_SIZE) < 0) |
| { |
| printf("nvserver error: write fail errno = %d\n", errno); |
| close(fp); |
| free(buf); |
| return RESULT_FILE_WRITE_FAIL; |
| } |
| |
| ret = fsync(fp); |
| |
| free(buf); |
| close(fp); |
| |
| if (ret < 0) { |
| printf("Sync Failed:%s, file path:%s", strerror(errno), nvFile); |
| return ret; |
| } |
| |
| return RESULT_SUCCESS; |
| } |
| |
| return RESULT_NO_FILE; |
| } |
| |
| |
| /******************************************************************************* |
| * ¹¦ÄÜÃèÊö: nvget |
| * ²ÎÊý˵Ã÷: |
| * (´«Èë²ÎÊý) file:nvÎļþ |
| * (´«Èë²ÎÊý) key:nvÏîÃû |
| * (´«³ö²ÎÊý) value:nvÖµ |
| * ·µ »Ø Öµ: 0±íʾ³É¹¦ |
| * ÆäËü˵Ã÷: void |
| *******************************************************************************/ |
| static int nvget(char *file, char *key, char *value) |
| { |
| int index = 0; |
| T_NV_NODE *list = NULL; |
| T_NV_ITEM *item = NULL; |
| |
| for(list = nv_list; list; list = list->next) |
| { |
| if(strcmp(list->nvFile, file)) |
| continue; |
| |
| index = hash(key) % NV_HASH_LEN; |
| for(item = list->nvTable[index]; item; item = item->next) |
| { |
| if(strcmp(item->key, key)) |
| continue; |
| |
| strncpy(value, item->value, NV_MAX_VAL_LEN - 1); |
| value[NV_MAX_VAL_LEN - 1] = '\0'; |
| return RESULT_SUCCESS; |
| } |
| } |
| |
| return RESULT_NO_ITEM; |
| } |
| |
| /******************************************************************************* |
| * ¹¦ÄÜÃèÊö: nvset |
| * ²ÎÊý˵Ã÷: |
| * (´«Èë²ÎÊý) file:nvÎļþ |
| * (´«Èë²ÎÊý) key:nvÏîÃû |
| * (´«Èë²ÎÊý) value:nvÖµ |
| * (´«Èë²ÎÊý) saveFlag:±£´æ±êÖ¾ |
| * ·µ »Ø Öµ: 0±íʾ³É¹¦ |
| * ÆäËü˵Ã÷: void |
| *******************************************************************************/ |
| static int nvset(char *file, const char *key, const char *value, int saveFlag) |
| { |
| int index = 0; |
| int ret = 0; |
| int key_buf_len = 0; |
| int value_buf_len = 0; |
| T_NV_NODE *list = NULL; |
| T_NV_ITEM *item = NULL; |
| T_NV_ITEM *newItem = NULL; |
| |
| if (NULL == key || NULL == value) |
| return RESULT_FAIL; |
| |
| key_buf_len = strlen(key) + 1; |
| value_buf_len = strlen(value) + 1; |
| |
| for(list = nv_list; list; list = list->next) |
| { |
| if(strcmp(list->nvFile, file)) |
| continue; |
| |
| index = hash(key) % NV_HASH_LEN; |
| for(item = list->nvTable[index]; item; item = item->next) |
| { |
| // change item |
| if(strcmp(item->key, key)) |
| continue; |
| |
| if(saveFlag) |
| item->saveFlag = saveFlag; |
| |
| if(!strcmp(item->value, value)) |
| return RESULT_SUCCESS; |
| |
| free(item->value); |
| item->value = (char *)malloc(value_buf_len); |
| if(!item->value) |
| return RESULT_MALLOC_FAIL; |
| |
| strncpy(item->value, value, value_buf_len - 1); |
| item->value[value_buf_len - 1] = '\0'; |
| |
| return RESULT_SUCCESS; |
| } |
| |
| // add item |
| newItem = (T_NV_ITEM *)malloc(sizeof(T_NV_ITEM )); |
| if(!newItem) |
| return RESULT_MALLOC_FAIL; |
| |
| newItem->key = (char *)malloc(key_buf_len); |
| if(!newItem->key) |
| { |
| free(newItem); |
| return RESULT_MALLOC_FAIL; |
| } |
| |
| newItem->value = (char *)malloc(value_buf_len); |
| if(!newItem->value) |
| { |
| free(newItem->key); |
| free(newItem); |
| return RESULT_MALLOC_FAIL; |
| } |
| |
| strncpy(newItem->key, key, key_buf_len - 1); |
| newItem->key[key_buf_len - 1] = '\0'; |
| strncpy(newItem->value, value, value_buf_len - 1); |
| newItem->value[value_buf_len - 1] = '\0'; |
| |
| newItem->next = NULL; |
| newItem->saveFlag = saveFlag; |
| newItem->update_flag=0;// 0: not update , 1: updated |
| |
| if(!list->nvTable[index]) |
| list->nvTable[index] = newItem; |
| else |
| { |
| newItem->next = list->nvTable[index]->next; |
| list->nvTable[index]->next = newItem; |
| } |
| |
| return RESULT_SUCCESS; |
| } |
| |
| // add nv |
| ret = addConfigFile(file, NULL); |
| if(ret == RESULT_SUCCESS) |
| return nvset(file, key, value, saveFlag); |
| else |
| return ret; |
| } |
| |
| /******************************************************************************* |
| * ¹¦ÄÜÃèÊö: nvunset |
| * ²ÎÊý˵Ã÷: |
| * (´«Èë²ÎÊý) file:nvÎļþ |
| * (´«Èë²ÎÊý) key:nvÏîÃû |
| * ·µ »Ø Öµ: 0±íʾ³É¹¦ |
| * ÆäËü˵Ã÷: void |
| *******************************************************************************/ |
| static int nvunset(char * file, char *key) |
| { |
| int index = 0; |
| T_NV_NODE *list = NULL; |
| T_NV_ITEM *item = NULL; |
| T_NV_ITEM *prev = NULL; |
| |
| for(list = nv_list; list; list = list->next) |
| { |
| if(strcmp(list->nvFile, file)) |
| continue; |
| |
| index = hash(key) % NV_HASH_LEN; |
| for(item = list->nvTable[index]; item; prev = item, item = item->next) |
| { |
| if(strcmp(item->key, key)) |
| continue; |
| |
| if(!prev) |
| list->nvTable[index] = item->next; |
| else |
| prev->next = item->next; |
| |
| free(item->key); |
| free(item->value); |
| free(item); |
| |
| return RESULT_SUCCESS; |
| } |
| } |
| |
| return RESULT_NO_ITEM; |
| } |
| |
| /******************************************************************************* |
| * ¹¦ÄÜÃèÊö: nvreset |
| * ²ÎÊý˵Ã÷: |
| * (´«Èë²ÎÊý) file:nvÎļþ |
| * ·µ »Ø Öµ: 0±íʾ³É¹¦ |
| * ÆäËü˵Ã÷: ɾ³ýnvÎļþ |
| *******************************************************************************/ |
| static int nvreset(char *file) |
| { |
| int ret = 0; |
| T_NV_NODE *list = NULL; |
| |
| for(list = nv_list; list; list = list->next) |
| { |
| if(strcmp(list->nvFile, file)) |
| continue; |
| |
| ret = nvclear(file); |
| if(ret != RESULT_SUCCESS) |
| return ret; |
| |
| if(loadFactroyParam(list) != RESULT_SUCCESS) |
| return RESULT_FAIL; |
| |
| return nvcommit(file); |
| } |
| |
| return RESULT_NO_FILE; |
| } |
| |
| /******************************************************************************* |
| * ¹¦ÄÜÃèÊö: nvclear |
| * ²ÎÊý˵Ã÷: |
| * (´«Èë²ÎÊý) file:nvÎļþ |
| * ·µ »Ø Öµ: 0±íʾ³É¹¦ |
| * ÆäËü˵Ã÷: ²Á³ýÄÚ´ænv |
| *******************************************************************************/ |
| static int nvclear(char *file) |
| { |
| int i = 0; |
| T_NV_NODE *list = NULL; |
| T_NV_ITEM *cur = NULL; |
| T_NV_ITEM *item = NULL; |
| |
| for(list = nv_list; list; list = list->next) |
| { |
| if(strcmp(list->nvFile, file)) |
| continue; |
| |
| for(i = 0; i < NV_HASH_LEN; i ++) |
| { |
| for(item = list->nvTable[i]; item; ) |
| { |
| cur = item; |
| item = item->next; |
| |
| free(cur->key); |
| free(cur->value); |
| free(cur); |
| } |
| list->nvTable[i] = NULL; |
| } |
| |
| return RESULT_SUCCESS; |
| } |
| |
| return RESULT_NO_FILE; |
| } |
| |
| /******************************************************************************* |
| * ¹¦ÄÜÃèÊö: nvcommit |
| * ²ÎÊý˵Ã÷: |
| * (´«Èë²ÎÊý) file:nvÎļþ |
| * ·µ »Ø Öµ: RESULT_SUCCESS±íʾ³É¹¦ |
| * ÆäËü˵Ã÷: void |
| *******************************************************************************/ |
| static int nvcommit(char *file) |
| { |
| int ret = 0; |
| char nvMainFile[NV_PATH_LEN] = {0}; |
| char nvBackupFile[NV_PATH_LEN] = {0}; |
| |
| sprintf(nvMainFile, "%s/%s", NV_FS_MAIN_PATH, file); |
| sprintf(nvBackupFile, "%s/%s", NV_FS_BACKUP_PATH, file); |
| |
| ret = saveNvFs(file, nvMainFile); |
| if(ret != RESULT_SUCCESS) |
| return ret; |
| |
| return restoreNvFs(nvBackupFile, nvMainFile); |
| } |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |