配置文件键值对读写API函数实现

来源:互联网 发布:淘宝美工一组图多少钱 编辑:程序博客网 时间:2024/05/22 14:27

项目中开发了一种读写配置文件键值的函数(name = value格式),非常实用,特将源码记录如下:

调用接口函数为:

int setcfgx(const char *filpath, const char *nam, char *val)  写入

int getcfgx(const char *filpath, const char *nam, char *val)  读取

Conftool.h文件源码:

/***  Copyright (c) 2012 OCS, Inc.****  Project: GPON-ONT-V2.0**  File:    conf_toolkit.h**  Author:  ychxie/xuzhe**  Date:    02/08/2012****  Purpose:**    provide funcitions for reading and writing configuration files*/#ifndef _CONF_TOOLKIT_H#define _CONF_TOOLKIT_H#ifdef __cplusplusextern "C"{#endif /* __cplusplus *//* Macro constant definitions. */#define SVC_PRINTF_BUF_LEN        4096#define SVC_PRINTF_BUF_MARGIN_LEN 32#define BOOL                   eOsBool/* Type definitions. */typedef enum{    eSVC_LL_MIN,    eSVC_LL_MINOR = eSVC_LL_MIN,    eSVC_LL_MAJOR,    eSVC_LL_CRITICAL,    eSVC_LL_NO_LOG,    eSVC_LL_MAX,    OG_ENUM_MAX} eSvcLogLevel;typedef enum{    FALSE,    TRUE} eOsBool;/* Include files. *//* Macro constant definitions. */#define MAX_LINES 4096#define LINE_LEN  128#define NAME_LEN  128/* Type definitions. */typedef enum{    eOP_ERR_SUCCESS = 0,    eOP_ERR_ERROR = 1    }eOpCfgError;/* External function declarations. *//* Macro API definitions. *//* Global variable declarations. *//****************************************************************************  Function Name: setcfgx**  Purpose:**    set single key and value pairs into conf.**  Parameters:**    filpath - full path of configuration file**    nam   - key**    val     - value**  Return:**    0       - success**    other - failure  (refer to eOpCfgError for details)**  Notes:**    None.**************************************************************************/int setcfgx(const char *filpath, const char *nam, char *val);/****************************************************************************  Function Name: getcfgx**  Purpose:**    get single key from conf.**  Parameters:**    filpath - full path of configuration file**    nam   - key**    val     - value**  Return:**    0       - success**    other - failure  (refer to eOpCfgError for details)**  Notes:**    None.**************************************************************************/int getcfgx(const char *filpath, const char *nam, char *val);/****************************************************************************  Function Name: item_write**  Purpose:**    set single key and value pairs into conf.**  Parameters:**    filpath - full path of configuration file**    nam   - key**    val     - value**  Return:**    0       - success**    other - failure  (refer to eOpCfgError for details)**  Notes:**    None.**************************************************************************/int item_write(const char *path, const char *key, const char *value);/****************************************************************************  Function Name: item_read**  Purpose:**    get single key from conf.**  Parameters:**    filpath - full path of configuration file**    nam   - key**    val     - value**  Return:**    0       - success**    other - failure  (refer to eOpCfgError for details)**  Notes:**    None.**************************************************************************/int item_read(const char *path, const char *key, char *value);/****************************************************************************  Function Name: batch_start**  Purpose:**    Identification of batch operation start.**  Parameters:**    None**  Return:**    0       - success**    other - failure  (refer to eOpCfgError for details)**  Notes:**    None.**************************************************************************/int batch_start(void);/****************************************************************************  Function Name: batch_stop**  Purpose:**    Identification of batch operation stop.**  Parameters:**    None**  Return:**    0       - success**    other - failure  (refer to eOpCfgError for details)**  Notes:**    None.**************************************************************************/int batch_stop(void);#ifdef __cplusplus} /* extern "C" */#endif /* __cplusplus */#endif

Conftool.c文件源码:

/***  Copyright (c) 2012 OCS, Inc.****  Project: GPON-ONT-V2.0**  File:    conf_toolkig.c**  Author:  ychxie/xuzhe**  Date:    02/08/2012****  Purpose:**    implement of conf_toolkit.h.*//* Include files. */#include <stdio.h>#include <sys/time.h>#include <sys/timeb.h>#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <stdlib.h>#include <fcntl.h>#include <pthread.h>#include <string.h>#include <semaphore.h>#include <errno.h>#include <stdarg.h>#include <ctype.h>#include <libgen.h>#include "conftool.h"#include "debug_log.h"/* Macro constant definitions. */#define S_ISSYMLNK(m) (((m) & S_IFMT) == S_IFLNK)  /**analyze if a file is a symbol link*/#define OPEN_FLAG O_CREAT#define OPEN_MODE 00644#define INIT_V    1#define MAX_READ_WRITE_TIMES 3#define ERR_CACHE_MAX       (2 * 1024 + 4)          // 2k for Error Buffer.#define LINE_CACHE_MAX      (5 * 1024 + 4)          // 5k for A Line.#define FILE_PATH_MAX       (1 * 1024 + 4)          // 1k for File/Dir path./* Type definitions. */struct one_line {    char *line;    char *extern_line;    char line_cache[LINE_LEN];    int line_size;};struct file_content {    struct one_line lines[MAX_LINES];    int line_cnt;};typedef enum{    eOP_TYPE_GET = 0,    eOP_TYPE_SET,    eOP_TYPE_BATCH_OP}eOpType;/* Local function declarations. */static void op_log_head(eOpType op_type, const char* filename, const char *name);static void op_log_tail(eOpType op_type, const char* filename, const char *name, const char *val, int op_ret);static void rleadingblank(char *string);static void rrearblank(char *string);static void riprt(char *str);static int readfromfile(char *filename, struct file_content *file);static int writetofile(char *filename, char *strtxt, int strsize);static int setlinecontent(struct file_content *file, int index,  char *fmt, const char *name, const char *val);static void initstaticvar(void);static void seterrstr(const char *formatP, ...);/* Macro API definitions. *//* Global variable definitions. */static struct file_content batch_op_file;//symbol of batching operation//if symbol is true,then setcfgx operations not to read file again after first reading the file to RAM ,and not write file//until executint the batch_stop(),then to set already_read false ,and begin to write filestatic BOOL batch_flag = FALSE;//indicate the file has been read into RAM, in batch_read stitution not need to read again//in single_read and call DLL stitution,must set this parameter to false before function return in setcfgx(),otherwise not to read the file in readfromfile() static BOOL already_read = FALSE;static BOOL modify_flag = FALSE;static char batch_tmp_file_name[LINE_LEN] = {0};static char batch_real_file_path[LINE_LEN] = {0};static char error_str[ERR_CACHE_MAX] = {0};static sem_t *sem = NULL;static pthread_mutex_t *ptool_lock = NULL;extern int errno;//the methods below not to release// int item_write(const char *path, const char *key, const char *value);// int item_read(const char *path, const char *key, char *value);int batch_start(void);int batch_stop(void);/****************************************************************************  Function Name: setcfgx**  Purpose:**    set single key and value pairs into conf.**  Parameters:**    filpath - full path of configuration file**    nam   - key**    val     - value**  Return:**    0       - success**    other - failure  (refer to eOpCfgError for details)**  Notes:**    None.**************************************************************************/int setcfgx(const char *filpath, const char *nam, char *val){    struct file_content tempfile;    struct file_content *file = NULL;    char tmpline[LINE_CACHE_MAX] = {0};    char tmpname[NAME_LEN] = {0};    char realname[NAME_LEN] = {0};    char *saveptr = NULL, *pname = NULL;    int i = 0, ret = 0, file_size = 0, exist = 0, firstchar = 1;    char dir_name[FILE_PATH_MAX] = {0};    char file_name[FILE_PATH_MAX] = {0};    char tmp_file_name[FILE_PATH_MAX] = {0};    char real_file_path[FILE_PATH_MAX] = {0};    char *ptoken = NULL;    char *file_buffer = NULL;    //parameter value in conf has been modified     BOOL bModified = FALSE;    //DEBUG_LOG("****bModified parameter original value is false\n");    if (NULL == ptool_lock)    {        ptool_lock = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));        if (NULL == ptool_lock)        {            DEBUG_LOG("malloc pthread_mutex_t failed.\n");            return eOP_ERR_ERROR;                }        if(pthread_mutex_init(ptool_lock, NULL) != 0)        {            DEBUG_LOG("Init Mutex agent_conf_lock failed.\n");            free(ptool_lock);            ptool_lock = NULL;            return eOP_ERR_ERROR;        }            }    pthread_mutex_lock(ptool_lock);    op_log_head(eOP_TYPE_SET, filpath, nam);    if ((NULL == filpath) || (NULL == nam) || (NULL == val))    {        seterrstr("Invalid pointer.");        op_log_tail(eOP_TYPE_SET, filpath, nam, val, eOP_ERR_ERROR);        pthread_mutex_unlock(ptool_lock);        return eOP_ERR_ERROR;            }        // file pointer points to static variable if batch flag is true    if (batch_flag)    {        file = &batch_op_file;        modify_flag = TRUE;    }    else    {        file = &tempfile;        memset(file, 0, sizeof(struct file_content));    }    strcpy(real_file_path, filpath);    ret = readfromfile(real_file_path, file);    if (eOP_ERR_SUCCESS != ret)    {    /*        if (NULL != sem)        {            sem_post(sem);            sem_close(sem);            sem = NULL;        }        */        op_log_tail(eOP_TYPE_SET, real_file_path, nam, val, ret);        pthread_mutex_unlock(ptool_lock);        return eOP_ERR_ERROR;    }    strcpy(dir_name, real_file_path);    strcpy(file_name, real_file_path);    sprintf(tmp_file_name , "%s/.tmp_%s", dirname(dir_name), basename(file_name));        //DEBUG_LOG("\n****file line count = %d\n",file->line_cnt);    for (i = 0; i < file->line_cnt; i++)     {        //DEBUG_LOG("****enter for cycle\n");        memset(tmpline, 0, sizeof(tmpline));        strcpy(tmpline, file->lines[i].line);        if (tmpline[0] == '#')continue;        rleadingblank(tmpline);        rrearblank(tmpline);        if ((saveptr = tmpline) && ((pname = strsep(&saveptr, "=")) != NULL) && (NULL != saveptr))         {            memset(tmpname, 0, sizeof(tmpname));            memset(realname, 0, sizeof(realname));            firstchar = 1;            while((NULL != pname) && (NULL != saveptr))            {                if (firstchar)                {                    firstchar = 0;                }                else                {                    strcat(tmpname, " ");                    strcat(realname, " ");                }                strcat(tmpname, pname);                strcat(realname, pname);                pname = strsep(&saveptr, "=");                            }            //op_log_tail(eOP_TYPE_SET, real_file_path, nam, val, eOP_ERR_ERROR);            rleadingblank(tmpname);            rrearblank(tmpname);            //compare set value to the original value            if (!strcmp(tmpname, nam))            {                //DEBUG_LOG("**** parameter names are the same!!\n");                //DEBUG_LOG("****original:tmpname = %s,destination:nam = %s,are the same\n",tmpname,nam);                //DEBUG_LOG("****source value = %s,destination:value = %s \n", pname, val);                                exist = 1;//not new item                if(strcmp(pname, val))//value want to be changed                {                    //DEBUG_LOG("**** parameter values are different,bModified is TRUE!!\n");                    bModified = TRUE;                    setlinecontent(file, i, "%s=%s", realname, val);                }                break;            }        }         else if ((saveptr = tmpline) && ((pname = strsep(&saveptr, "\t")) != NULL) && (NULL != saveptr))        {            memset(tmpname, 0, sizeof(tmpname));            memset(realname, 0, sizeof(realname));            firstchar = 1;            while((NULL != pname) && (NULL != saveptr))            {                if (firstchar)                {                    firstchar = 0;                }                else                {                    strcat(tmpname, " ");                    strcat(realname, "\t");                }                strcat(tmpname, pname);                strcat(realname, pname);                pname = strsep(&saveptr, "\t");                            }            rleadingblank(tmpname);            rrearblank(tmpname);            //compare set value to the original value            if (!strcmp(tmpname, nam))            {                //DEBUG_LOG("**** parameter names are the same!!\n");                //DEBUG_LOG("****original:tmpname = %s,destination:nam = %s,are the same\n",tmpname,nam);                //DEBUG_LOG("****source value = %s,destination:value = %s \n", pname, val);                                exist = 1;//not new item                if(strcmp(pname, val))//value want to be changed                {                    //DEBUG_LOG("**** parameter values are different,bModified is TRUE!!\n");                    bModified = TRUE;                    setlinecontent(file, i, "%s\t%s", realname, val);                }                break;            }        }         else if ((saveptr = tmpline) && ((pname = strsep(&saveptr, " ")) != NULL) && (NULL != saveptr))         {            memset(tmpname, 0, sizeof(tmpname));            memset(realname, 0, sizeof(realname));            firstchar = 1;            while((NULL != pname) && (NULL != saveptr))            {                if (firstchar)                {                    firstchar = 0;                }                else                {                    strcat(tmpname, " ");                    strcat(realname, " ");                }                strcat(tmpname, pname);                strcat(realname, pname);                pname = strsep(&saveptr, " ");                            }            rleadingblank(tmpname);            rrearblank(tmpname);            //compare set value to the original value            if (!strcmp(tmpname, nam))            {                //DEBUG_LOG("**** parameter names are the same!!\n");                //DEBUG_LOG("****original:tmpname = %s,destination:nam = %s,are the same\n",tmpname,nam);                //DEBUG_LOG("****source value = %s,destination:value = %s \n", pname, val);                                exist = 1;//not new item                if(strcmp(pname, val))//value want to be changed                {                    //DEBUG_LOG("**** parameter values are different,bModified is TRUE!!\n");                    bModified = TRUE;                    setlinecontent(file, i, "%s %s", realname, val);                }                break;            }        }     }    //DEBUG_LOG("****exist= %d!!\n",exist);    // the name is a new item for the cfg file while exist is 0    if (0 == exist)    {        //DEBUG_LOG("****need increase new line!!\n");        if (MAX_LINES > file->line_cnt)        {               //DEBUG_LOG("****not exceed the most line number!!\n");            setlinecontent(file, i, "%s=%s", nam, val);            file->line_cnt++;            //file need to be writed            bModified = TRUE;        }        else        {            if (!batch_flag)            {                // clean                for (i = 0; i < file->line_cnt; i++)                {                    if (NULL != file->lines[i].extern_line)                    {                        free(file->lines[i].extern_line);                        file->lines[i].extern_line = NULL;                        file->lines[i].line = NULL;                    }                }                /*                if (NULL != sem)                {                    sem_post(sem);                    sem_close(sem);                    sem = NULL;                }                */            }            // return error            seterrstr("exceed 4096 lines.");            op_log_tail(eOP_TYPE_SET, real_file_path, nam, val, eOP_ERR_ERROR);            pthread_mutex_unlock(ptool_lock);            return eOP_ERR_ERROR;        }    }    if (batch_flag)    {        // do not write file here in batch mode         op_log_tail(eOP_TYPE_SET, real_file_path, nam, val, eOP_ERR_SUCCESS);        pthread_mutex_unlock(ptool_lock);        strcpy(batch_real_file_path, real_file_path);        strcpy(batch_tmp_file_name, tmp_file_name);        return eOP_ERR_SUCCESS;    }    //if parameter value has not been changed in file ,then do not write to file      if (!bModified)    {        //DEBUG_LOG("bModified is false\n");        // clean        for (i = 0; i < file->line_cnt; i++)        {            if (NULL != file->lines[i].extern_line)            {                free(file->lines[i].extern_line);                file->lines[i].extern_line = NULL;                file->lines[i].line = NULL;            }        }        // already_read should be cleared after write to file in single mode         already_read = FALSE;        op_log_tail(eOP_TYPE_SET, real_file_path, nam, val, eOP_ERR_SUCCESS);        //DEBUG_LOG("notice:in %s,the parameter %s value still is %s, not changed,no rewrite file!!! \n",real_file_path,nam,val);        pthread_mutex_unlock(ptool_lock);        //DEBUG_LOG("\n\n");        return eOP_ERR_SUCCESS;    }         //DEBUG_LOG("bModified is true\n");    // perpare    file_size = 0;    for (i = 0; i < file->line_cnt; i++)    {        file_size += (strlen(file->lines[i].line)+1);    }    file_buffer = (char*)malloc(file_size+1);    if (NULL == file_buffer)    {        // clean        for (i = 0; i < file->line_cnt; i++)        {            if (NULL != file->lines[i].extern_line)            {                free(file->lines[i].extern_line);                file->lines[i].extern_line = NULL;                file->lines[i].line = NULL;            }        }        /*        // return error        if (NULL != sem)        {            sem_post(sem);            sem_close(sem);            sem = NULL;        }        */        seterrstr("write malloc error.");        op_log_tail(eOP_TYPE_SET, real_file_path, nam, val, eOP_ERR_ERROR);        pthread_mutex_unlock(ptool_lock);        return eOP_ERR_ERROR;    }    memset(file_buffer, 0, file_size+1);    ptoken = file_buffer;    for (i = 0; i < file->line_cnt; i++)    {        memcpy(ptoken, file->lines[i].line, strlen(file->lines[i].line));        ptoken += strlen(file->lines[i].line);        *(ptoken) = '\n';        if (NULL != file->lines[i].extern_line)        {            free(file->lines[i].extern_line);            file->lines[i].extern_line = NULL;            file->lines[i].line = NULL;        }        ptoken++;    }    ret = writetofile(tmp_file_name, file_buffer, file_size);    if (eOP_ERR_SUCCESS != ret)    {        free(file_buffer);        file_buffer = NULL;        /*        if (NULL != sem)        {            sem_post(sem);            sem_close(sem);            sem = NULL;        }        */        op_log_tail(eOP_TYPE_SET, real_file_path, nam, val, ret);        pthread_mutex_unlock(ptool_lock);        return eOP_ERR_ERROR;    }    free(file_buffer);    file_buffer = NULL;    rename(tmp_file_name, real_file_path);    // already_read should be cleared after write to file in single mode     already_read = FALSE;    /*    if (NULL != sem)        {        sem_post(sem);        sem_close(sem);        sem = NULL;    }    */    op_log_tail(eOP_TYPE_SET, real_file_path, nam, val, eOP_ERR_SUCCESS);    pthread_mutex_unlock(ptool_lock);    //DEBUG_LOG("\n\n");    return eOP_ERR_SUCCESS;}/****************************************************************************  Function Name: getcfgx**  Purpose:**    get single key from conf.**  Parameters:**    filpath - full path of configuration file**    nam   - key**    val     - value**  Return:**    0       - success**    other - failure  (refer to eOpCfgError for details)**  Notes:**    None.**************************************************************************/int getcfgx(const char *filpath, const char *nam, char *val){    struct file_content tempfile;    struct file_content *file = NULL;    char tmpline[LINE_CACHE_MAX] = {0};    char tmpname[NAME_LEN] = {0};    char dir_name[FILE_PATH_MAX] = {0};    char file_name[FILE_PATH_MAX] = {0};    char tmp_file_name[FILE_PATH_MAX] = {0};    char real_file_path[FILE_PATH_MAX] = {0};    char *saveptr = NULL, *pname = NULL;    int i = 0, ret = 0,  firstchar = 1;;    if (NULL == ptool_lock)    {        ptool_lock = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));        if (NULL == ptool_lock)        {            DEBUG_LOG("malloc pthread_mutex_t failed.\n");            return eOP_ERR_ERROR;                }        if(pthread_mutex_init(ptool_lock, NULL) != 0)        {            DEBUG_LOG("Init Mutex agent_conf_lock failed.\n");            free(ptool_lock);            ptool_lock = NULL;            return eOP_ERR_ERROR;        }            }    pthread_mutex_lock(ptool_lock);    op_log_head(eOP_TYPE_GET, filpath, nam);    if ((NULL == filpath) || (NULL == nam) || (NULL == val))    {        seterrstr("Invalid pointer.\n");        op_log_tail(eOP_TYPE_GET, filpath, nam, val, eOP_ERR_ERROR);        pthread_mutex_unlock(ptool_lock);        return eOP_ERR_ERROR;            }    // clean cache    *val = 0;    // file pointer points to static variable if batch flag is true    if (batch_flag)    {        file = &batch_op_file;    }    else    {        file = &tempfile;        memset(file, 0, sizeof(struct file_content));    }    strcpy(real_file_path, filpath);    ret = readfromfile(real_file_path, file);    if (eOP_ERR_SUCCESS != ret)    {        /*        if (NULL != sem)        {            sem_post(sem);            sem_close(sem);            sem = NULL;        }        */        op_log_tail(eOP_TYPE_GET, real_file_path, nam, val, ret);        pthread_mutex_unlock(ptool_lock);        return eOP_ERR_ERROR;    }    strcpy(dir_name, real_file_path);    strcpy(file_name, real_file_path);    sprintf(tmp_file_name , "%s/.tmp_%s", dirname(dir_name), basename(file_name));    /*    if (NULL != sem)    {        sem_post(sem);        sem_close(sem);        sem = NULL;    }    */    for (i = 0; i < file->line_cnt; i++)     {        memset(tmpline, 0, sizeof(tmpline));        strcpy(tmpline, file->lines[i].line);        if (tmpline[0] == '#')continue;        rleadingblank(tmpline);        rrearblank(tmpline);        if ((saveptr = tmpline) && ((pname = strsep(&saveptr, "=")) != NULL) && (NULL != saveptr))        {            memset(tmpname, 0, sizeof(tmpname));            firstchar = 1;            while((NULL != pname) && (NULL != saveptr))            {                if (firstchar)                {                    firstchar = 0;                }                else                {                    strcat(tmpname, " ");                }                strcat(tmpname, pname);                pname = strsep(&saveptr, "=");                            }            rleadingblank(tmpname);            rrearblank(tmpname);            if (!strcmp(tmpname, nam))             {                strcpy(val, pname);                riprt(val);                rleadingblank(val);                rrearblank(val);                break;            }        }        else if ((saveptr = tmpline) && ((pname = strsep(&saveptr, "\t")) != NULL) && (NULL != saveptr))        {            memset(tmpname, 0, sizeof(tmpname));            firstchar = 1;            while((NULL != pname) && (NULL != saveptr))            {                if (firstchar)                {                    firstchar = 0;                }                else                {                    strcat(tmpname, " ");                }                strcat(tmpname, pname);                pname = strsep(&saveptr, "\t");                            }            rleadingblank(tmpname);            rrearblank(tmpname);            if (!strcmp(tmpname, nam))             {                strcpy(val, pname);                riprt(val);                rleadingblank(val);                rrearblank(val);                break;            }        }        else if ((saveptr = tmpline) && ((pname = strsep(&saveptr, " ")) != NULL) && (NULL != saveptr))        {            memset(tmpname, 0, sizeof(tmpname));            firstchar = 1;            while((NULL != pname) && (NULL != saveptr))            {                if (firstchar)                {                    firstchar = 0;                }                else                {                    strcat(tmpname, " ");                }                strcat(tmpname, pname);                pname = strsep(&saveptr, " ");                            }            rleadingblank(tmpname);            rrearblank(tmpname);            if (!strcmp(tmpname, nam))             {                strcpy(val, pname);                riprt(val);                rleadingblank(val);                rrearblank(val);                break;            }        }    }    if (!batch_flag)    {        // already_read should be cleared after write to file in single mode         already_read = FALSE;        // clean        for (i = 0; i < file->line_cnt; i++)        {            if (NULL != file->lines[i].extern_line)            {                free(file->lines[i].extern_line);                file->lines[i].extern_line = NULL;                file->lines[i].line = NULL;            }        }    }    else    {        strcpy(batch_real_file_path, real_file_path);        strcpy(batch_tmp_file_name, tmp_file_name);    }    op_log_tail(eOP_TYPE_GET, real_file_path, nam, val, eOP_ERR_SUCCESS);    pthread_mutex_unlock(ptool_lock);    return eOP_ERR_SUCCESS;}/****************************************************************************  Function Name: item_write**  Purpose:**    set single key and value pairs into conf.**  Parameters:**    filpath - full path of configuration file**    nam   - key**    val     - value**  Return:**    0       - success**    other - failure  (refer to eOpCfgError for details)**  Notes:**    None.**************************************************************************/// int item_write(const char *path, const char *key, const char *value)// {    // return setcfgx(path, key, value);// }/****************************************************************************  Function Name: riprt**  Purpose:**    get single key from conf.**  Parameters:**    filpath - full path of configuration file**    nam   - key**    val     - value**  Return:**    0       - success**    other - failure  (refer to eOpCfgError for details)**  Notes:**    None.**************************************************************************/// int item_read(const char *path, const char *key, char *value)// {    // return getcfgx(path, key, value);// }/****************************************************************************  Function Name: batch_start**  Purpose:**    Identification of batch operation start.**  Parameters:**    None**  Return:**    0       - success**    other - failure  (refer to eOpCfgError for details)**  Notes:**    None.**************************************************************************/int batch_start(void){    batch_flag = TRUE;    memset(&batch_op_file, 0, sizeof(batch_op_file));    return 0;}/****************************************************************************  Function Name: batch_stop**  Purpose:**    Identification of batch operation stop.**  Parameters:**    None**  Return:**    0       - success**    other - failure  (refer to eOpCfgError for details)**  Notes:**    None.**************************************************************************/int batch_stop(void){    int i = 0, ret = 0, file_size = 0;    char *ptoken = NULL;    char *file_buffer = NULL;    struct file_content *file = &batch_op_file;    if (modify_flag)    {        // perpare        file_size = 0;        for (i = 0; i < file->line_cnt; i++)        {            file_size += (strlen(file->lines[i].line)+1);        }        file_buffer = (char*)malloc(file_size+1);        if (NULL == file_buffer)        {            //op_log(eOP_TYPE_BATCH_OP, -1, real_file_path, nam, val);            seterrstr("write malloc error.\n");            /*            if (NULL != sem)            {                sem_post(sem);                sem_close(sem);                sem = NULL;            }            */            // clear            initstaticvar();            return eOP_ERR_ERROR;        }        memset(file_buffer, 0, file_size+1);        ptoken = file_buffer;        for (i = 0; i < file->line_cnt; i++)        {            memcpy(ptoken, file->lines[i].line, strlen(file->lines[i].line));            ptoken += strlen(file->lines[i].line);            *(ptoken) = '\n';            ptoken++;        }        if (eOP_ERR_SUCCESS != writetofile(batch_tmp_file_name, file_buffer, file_size))        {            free(file_buffer);            file_buffer = NULL;            //op_log(eOP_TYPE_BATCH_OP, -1, real_file_path, nam, val);            /*            if (NULL != sem)            {                sem_post(sem);                sem_close(sem);                sem = NULL;            }            */            // clear            initstaticvar();            return eOP_ERR_ERROR;        }        free(file_buffer);        file_buffer = NULL;        rename(batch_tmp_file_name, batch_real_file_path);        //op_log(eOP_TYPE_BATCH_OP, 0, real_file_path, nam, val);    }    /*    if (NULL != sem)    {        sem_post(sem);        sem_close(sem);        sem = NULL;    }    */    // clear    initstaticvar();    return eOP_ERR_SUCCESS;}/****************************************************************************  Function Name: op_log_head**  Purpose:**    log operations .**  Parameters:**    op_ret - result of operation (0 = success: oter = failed)**    filename - name of the file to be operated**    nam   - key**  Return:**    0       - success**    other - failure  (refer to eOpCfgError for details)**  Notes:**    None.**************************************************************************/void op_log_head(eOpType op_type, const char* filename, const char *name){    struct timeval tv;    struct tm *pm = NULL;    char szopname[NAME_LEN] = {0};    char szdest[FILE_PATH_MAX] = {0};    int ret = 0;    // initialize cache    memset(szopname, 0, NAME_LEN);    memset(szdest, 0, FILE_PATH_MAX);    // decide op name    switch(op_type)    {    case eOP_TYPE_GET:        if (batch_flag)        {            sprintf(szopname, "BATCH GET");        }        else        {            sprintf(szopname, "GET");        }        break;    case eOP_TYPE_SET:        if (batch_flag)        {            sprintf(szopname, "BATCH SET");        }        else        {            sprintf(szopname, "SET");        }        break;    case eOP_TYPE_BATCH_OP:        sprintf(szopname, "BATCH OPTION");        break;    default:                break;    }    ret = readlink("/proc/self/exe",   szdest,   FILE_PATH_MAX);    ret = gettimeofday(&tv, NULL);    if (0 == ret)    {        pm = localtime((time_t *)&tv.tv_sec);#if 0        DEBUG_LOG("[%04d-%02d-%02d %02d:%02d:%02d:%03d] [%s] [%s] [%s] [%s = ",            pm->tm_year + 1900,             pm->tm_mon + 1,             pm->tm_mday,             pm->tm_hour,             pm->tm_min,             pm->tm_sec,             tv.tv_usec/1000,            szdest,            filename,            szopname,            name            );#endif    }}/****************************************************************************  Function Name: op_log_tail**  Purpose:**    log operations .**  Parameters:**    op_ret - result of operation (0 = success: oter = failed)**    filename - name of the file to be operated**    nam   - key**    val - value**  Return:**    0       - success**    other - failure  (refer to eOpCfgError for details)**  Notes:**    None.**************************************************************************/void op_log_tail(eOpType op_type, const char* filename, const char *name, const char *val, int op_ret){    if ((NULL == filename) || (NULL == name) || (NULL == val))    {        DEBUG_LOG("\n<<Invalid pointer.>>\n");        return;    }    if (eOP_ERR_SUCCESS == op_ret)    {        //DEBUG_LOG("%s]: %s\n", val, "SUCCESS");    }    else    {        DEBUG_LOG("%s]: %s\n Error : %s\n", val, "FAIL", error_str);    }}/****************************************************************************  Function Name: rleadingblank**  Purpose:**    remove leading blank .**  Parameters:**    string - string to handle**  Return:**    void**  Notes:**    None.**************************************************************************/void rleadingblank(char *string){    char tmpstr[LINE_CACHE_MAX] = {0};    int npos = 0;    if (NULL == string)    {        return;    }    if (0 == strlen(string))    {        return;    }    strcpy(tmpstr, string);    memset(string, 0, strlen(string));    while(isblank(tmpstr[npos]))    {        npos++;    }    strcpy(string, tmpstr+npos);}/****************************************************************************  Function Name: rrearblank**  Purpose:**    remove rear blank .**  Parameters:**    string - string to handle**  Return:**    void**  Notes:**    None.**************************************************************************/void rrearblank(char *string){    int len = 0;    if (NULL == string)    {        return;    }    len = strlen(string);    if (0 == len)    {        return;    }    while (isblank(string[len-1]))     {        string[len-1] = '\0';        len--;    }}/****************************************************************************  Function Name: riprt**  Purpose:**    remove '\r' and '\n' .**  Parameters:**    string - string to handle**  Return:**    void**  Notes:**    None.**************************************************************************/void riprt(char *str){    int len = 0, i = 0;    if (str == NULL)    {        return;    }        len = strlen(str);    if (len == 0)     {        return;    }        for (i = 0; i < len; i++)     {        if (str[i] == '\r' || str[i] == '\n')        {            str[i] = '\0';        }    }}/****************************************************************************  Function Name: readfromfile**  Purpose:**    read from file ,and translate symbo link to real path**  Parameters:**    filename - file path**    file - point of file_content**  Return:**    int**  Notes:**    None.**************************************************************************/int readfromfile(char *filename, struct file_content *file){    int fd = 0;    int ret = 0, file_size = 0, line_size = 0, newbuffer_size = 0;    char *file_buffer = NULL;    char *ptoken = NULL;    char *saveptr = NULL;    int i = 0, readtimes = 0;    char szpath[FILE_PATH_MAX] = {0};    struct stat buf;    if ((NULL == filename) || (NULL == file))    {        seterrstr("Invalid pointer.");        return eOP_ERR_ERROR;    }    ret = lstat(filename, &buf);    if (0 != ret)    {        seterrstr("file error. lstat %s = %d, err = %s.", filename, ret, strerror(errno));        return eOP_ERR_ERROR;    }    if (S_ISSYMLNK(buf.st_mode))    {        readlink(filename, szpath, FILE_PATH_MAX);        memset(filename, 0, FILE_PATH_MAX);        strcpy(filename, szpath);    }    if (already_read)    {        // return 0 if the file is read into memory in batch mode        return eOP_ERR_SUCCESS;    }    /*    //add lock    sem = sem_open((char*)basename(filename), OPEN_FLAG, OPEN_MODE, INIT_V);    if (NULL != sem)    {        sem_wait(sem);    }    else    {        seterrstr("open sem failed %s, err = %s.", filename, strerror(errno));        return eOP_ERR_ERROR;    }    */        ret = stat(filename, &buf);    if (0 != ret)    {        seterrstr("file error. stat %s = %d, err = %s.", filename, ret, strerror(errno));        return eOP_ERR_ERROR;    }    file_size = buf.st_size;    fd = open(filename, O_RDONLY|O_NONBLOCK);    if (-1 == fd)    {        seterrstr("read open file %s failed, err = %s.", filename, strerror(errno));        return eOP_ERR_ERROR;    }    file_buffer = (char*)malloc(file_size+1);    if (NULL == file_buffer)    {        seterrstr("read malloc error.");        close(fd);        return eOP_ERR_ERROR;    }    memset(file_buffer, 0, file_size+1);    do    {        ret = read(fd, file_buffer, file_size);        readtimes++;        if (-1 == ret)        {            usleep(100);        }    }while((-1 == ret) && (readtimes < MAX_READ_WRITE_TIMES));    if (readtimes >= MAX_READ_WRITE_TIMES)    {        free(file_buffer);        file_buffer = NULL;        close(fd);        seterrstr("try to read file %s exceed max times, err = %s.", filename, strerror(errno));        return eOP_ERR_ERROR;    }    close(fd);    saveptr = file_buffer;    ptoken = strsep( &saveptr, "\n");    while( (NULL != ptoken))    {                /* While there are tokens in "string" */        if (NULL != saveptr)        {            line_size = saveptr-ptoken;        }        else        {            line_size = strlen(ptoken);        }        if (LINE_LEN <= line_size)        {            newbuffer_size = (sizeof(char))*line_size+1;            file->lines[i].extern_line = (char*)malloc(newbuffer_size);            if (NULL == file->lines[i].extern_line)            {                free(file_buffer);                file_buffer = NULL;                seterrstr("read malloc extern_line error, size = %d.", newbuffer_size);                return eOP_ERR_ERROR;            }            memset(file->lines[i].extern_line, 0, newbuffer_size);            memcpy(file->lines[i].extern_line, ptoken, line_size);            file->lines[i].line = file->lines[i].extern_line;            file->lines[i].line_size = newbuffer_size;        }        else        {            memcpy(file->lines[i].line_cache, ptoken, line_size);            file->lines[i].line = file->lines[i].line_cache;            file->lines[i].line_size = LINE_LEN;        }        riprt(file->lines[i].line);        /* Get next token: */        if (NULL != saveptr)        {            ptoken = strsep(&saveptr, "\n");        }        else        {            //solution: can't get the value when line ends without '/r'             if (0 != strlen(file->lines[i].line))            {                i++;            }            break;        }        i++;        if (MAX_LINES <= i)        {            break;        }    }    free(file_buffer);    file_buffer = NULL;    file->line_cnt = i;    already_read = TRUE;    return eOP_ERR_SUCCESS;}/****************************************************************************  Function Name: writetofile**  Purpose:**    write into file **  Parameters:**    filename - file path**    strtxt - buffer of text to write**    strsize - buffer size**  Return:**    int**  Notes:**    None.**************************************************************************/int writetofile(char *filename, char *strtxt, int strsize){    int fd = 0, ret = 0, writetimes = 0;    if ((NULL == filename) || (NULL == strtxt))    {        seterrstr("Invalid pointer.");        return eOP_ERR_ERROR;    }    fd = open(filename, O_WRONLY|O_CREAT|O_NONBLOCK, S_IRWXU|S_IRWXG|S_IRWXO);    if (-1 == fd)    {        seterrstr("write open file %s failed, err = %s.", filename, strerror(errno));        return eOP_ERR_ERROR;    }    //add write lock    do    {        ret = write(fd, strtxt, strsize);        writetimes++;        if (-1 == ret)        {            usleep(100);        }    }while((-1 == ret) && (writetimes < MAX_READ_WRITE_TIMES));    if (writetimes >= MAX_READ_WRITE_TIMES)    {        close(fd);        seterrstr("try to write file %s exceed max times, err = %s.", filename, strerror(errno));        return eOP_ERR_ERROR;    }    //fsync(fd);    close(fd);    return eOP_ERR_SUCCESS;}/****************************************************************************  Function Name: setlinecontent**  Purpose:**    write into file **  Parameters:**    filename - file path**    strtxt - buffer of text to write**    strsize - buffer size**  Return:**    int**  Notes:**    None.*************************************************************************/int setlinecontent(struct file_content *file, int index,  char *fmt, const char *name, const char *val){    int line_size = 0;    int new_buffersize = 0;    char *buffer_exceed = NULL;    if ((NULL == file) || (NULL == fmt) || (NULL == name) || (NULL == val))    {        seterrstr("Invalid pointer.");        return eOP_ERR_ERROR;            }      line_size = strlen(name)+strlen(val)+1;    if (file->lines[index].line_size <= line_size)    {        new_buffersize = (sizeof(char))*line_size + 1;        buffer_exceed = (char*)malloc(new_buffersize);        if (NULL == buffer_exceed)        {            seterrstr("set line content error for invalid pointer.");            return eOP_ERR_ERROR;        }            memset(buffer_exceed, 0, new_buffersize);        sprintf(buffer_exceed, fmt, name, val);        if (NULL != file->lines[index].extern_line)        {            free(file->lines[index].extern_line);            file->lines[index].extern_line = NULL;            file->lines[index].line = NULL;        }        file->lines[index].extern_line = buffer_exceed;        file->lines[index].line = file->lines[index].extern_line;        file->lines[index].line_size = new_buffersize;    }    else    {        memset(file->lines[index].line, 0, file->lines[index].line_size);        sprintf(file->lines[index].line, fmt, name, val);    }    return eOP_ERR_SUCCESS;}/****************************************************************************  Function Name: initstaticvar**  Purpose:**    write into file **  Parameters:**    None**  Return:**    void**  Notes:**    None.*************************************************************************/void initstaticvar(void){    int i = 0;    // clean    for (i = 0; i < batch_op_file.line_cnt; i++)    {        if (NULL != batch_op_file.lines[i].extern_line)        {            free(batch_op_file.lines[i].extern_line);            batch_op_file.lines[i].extern_line = NULL;            batch_op_file.lines[i].line = NULL;        }    }    memset(&batch_op_file, 0, sizeof(batch_op_file));    memset(batch_real_file_path, 0, sizeof(batch_real_file_path));    memset(batch_tmp_file_name, 0, sizeof(batch_tmp_file_name));    batch_flag = FALSE;    already_read = FALSE;    modify_flag = FALSE;}/****************************************************************************  Function Name: seterrstr**  Purpose:**    set error string to static variable **  Parameters:**    formatP - string of format**    ... - variable stack**  Return:**    void**  Notes:**    None.*************************************************************************/void seterrstr(const char *formatP, ...){    memset(error_str, 0, sizeof(error_str));    va_list argList;    va_start(argList, formatP);    vsnprintf(error_str, sizeof(error_str), formatP, argList);    va_end(argList);}


0 0