blob: fe5ba994f8406db2f1799b4b0f70e6a0ffac64fc [file] [log] [blame]
/*******************************************************************************
* °æÈ¨ËùÓÐ (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);
if(-1 == msgsnd(msgId, &sndBuf, sizeof(T_NV_MSG_RESULT) - sizeof(long), 0))
{
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