#include "myFunc.h"
#include "myLog.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>
#include <ctype.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#define FILE_TIP_FLAG		0xA55AA55AA55AA55A

static const char* ENV_KEY_WORK_PATH 				= "WORK_PATH";
static const char* ENV_KEY_SYS_CFG_PATH 			= "SYS_CFG_PATH";
static const char* ENV_KEY_APP_ROOT_PATH 			= "APP_ROOT_PATH";
static const char* ENV_KEY_HIS_ROOT_PATH 			= "HIS_ROOT_PATH";
static const char* ENV_KEY_LOG_ROOT_PATH 			= "LOG_ROOT_PATH";
static const char* ENV_KEY_DBC_ROOT_PATH 			= "DBC_ROOT_PATH";
static const char* ENV_KEY_SHELL_PATH				= "SHELL_PATH";
static const char* ENV_KEY_UPDATE_PATH				= "UPDATE_PATH";


/*************************************************************************************************************************** */
// 校验计算函数
/*************************************************************************************************************************** */
// CRC16 table
static uint16_t g_tableCRC16[256] =
{
	0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
	0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, 0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
	0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
	0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641, 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
	0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240, 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
	0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41, 0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
	0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, 0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
	0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640, 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
	0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240, 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
	0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, 0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
	0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, 0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
	0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640, 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
	0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241, 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
	0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, 0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
	0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, 0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
	0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040,
};

// CRC32 table
static uint32_t g_tableCRC32[256] =
{
	0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL, 0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L, 0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L, 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L,
	0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL, 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L, 0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL, 0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L,
	0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L, 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL, 0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L, 0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L,
	0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L, 0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL, 0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L, 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL,
	0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL, 0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L, 0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L, 0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L,
	0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL, 0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L, 0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL, 0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L,
	0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L, 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL, 0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L, 0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L,
	0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L, 0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL, 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L, 0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL,
	0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL, 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L, 0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L, 0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L,
	0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL, 0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L, 0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL, 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L,
	0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L, 0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL, 0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L, 0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L,
	0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L, 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL, 0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L, 0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL,
	0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL, 0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L, 0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L, 0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L,
	0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL, 0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L, 0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL, 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L,
	0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L, 0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL, 0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L, 0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L,
	0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L, 0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL, 0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L, 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL
};


// 8-bit checksum
uint8_t func_cal_sum_byte(const uint8_t *data, const uint32_t len)
{
    if(data == NULL || len == 0)
    {
        LOG_E("func_cal_sum_byte input invalid, data=%p, len=%u", data, len);
        return 0;
    }

    uint8_t sum = 0;
    for (uint32_t i = 0; i < len; i++)
    {
        sum += (uint8_t)data[i];
    }
    return sum;
}

// 16-bit checksum
uint16_t func_cal_sum_word(const uint8_t *data, const uint32_t len)
{
    if(data == NULL || len == 0)
    {
        LOG_E("func_cal_crc16 input invalid, data=%p, len=%u", data, len);
        return 0;
    }

    uint16_t sum = 0;
    for (uint32_t i = 0; i < len; i++)
    {
        sum += (uint16_t)data[i];
    }
    return sum;
}

// 16-bit crc
uint16_t func_cal_crc16(const uint8_t *data, const uint32_t len)
{
    if(data == NULL || len == 0)
    {
        LOG_E("func_cal_crc16 input invalid, data=%p, len=%u", data, len);
        return 0;
    }

    uint16_t crc = 0xFFFF;
    for (uint32_t i = 0; i < len; i++)
    {
        uint8_t table_index = (uint8_t)(crc ^ data[i]);
        crc = (crc >> 8) ^ g_tableCRC16[table_index];
    }
    return crc;
}

// 32-bit crc
uint32_t func_cal_crc32(const uint8_t *data, const uint32_t len)
{
    if(data == NULL || len == 0)
    {
        LOG_E("func_cal_crc32 input invalid, data=%p, len=%u", data, len);
        return 0;
    }

    uint32_t crc = 0xFFFFFFFF;
    for (uint32_t i = 0; i < len; i++)
    {
        uint8_t table_index = (uint8_t)((crc ^ data[i]) & 0xFF);
        crc = (crc >> 8) ^ g_tableCRC32[table_index];
    }
    return crc ^ 0xFFFFFFFF;
}

// 16-bit file crc
uint16_t func_cal_file_crc16(const char *file_path)
{
    if((file_path == NULL) || (strlen(file_path) == 0))
    {
        LOG_E("func_cal_file_crc16 input invalid, file_path=%p", file_path);
        return 0;
    }

    FILE *fp = fopen(file_path, "rb");
    if (fp == NULL)
    {
        LOG_E("func_cal_file_crc16 open file failed, file_path=%s", file_path);
        return 0;
    }

    uint16_t crc = 0xFFFF;
    uint8_t buffer[4096];
    size_t bytes_read = 0;

    while ((bytes_read = fread(buffer, 1, sizeof(buffer), fp)) > 0)
    {
        for (size_t i = 0; i < bytes_read; i++)
        {
            uint8_t table_index = (uint8_t)(crc ^ buffer[i]);
            crc = (crc >> 8) ^ g_tableCRC16[table_index];
        }
    }

    fclose(fp);
    return crc;
}

// 32-bit file crc
uint32_t func_cal_file_crc32(const char *file_path)
{
    if((file_path == NULL) || (strlen(file_path) == 0))
    {
        LOG_E("func_cal_file_crc32 input invalid, file_path=%p", file_path);
        return 0;
    }

    FILE *fp = fopen(file_path, "rb");
    if (fp == NULL)
    {
        LOG_E("func_cal_file_crc32 open file failed, file_path=%s", file_path);
        return 0;
    }

    uint32_t crc = 0xFFFFFFFF;
    uint8_t buffer[4096];
    size_t bytes_read = 0;

    while ((bytes_read = fread(buffer, 1, sizeof(buffer), fp)) > 0)
    {
        for (size_t i = 0; i < bytes_read; i++)
        {
            uint8_t table_index = (uint8_t)((crc ^ buffer[i]) & 0xFF);
            crc = (crc >> 8) ^ g_tableCRC32[table_index];
        }
    }

    fclose(fp);
    return crc ^ 0xFFFFFFFF;
}


/*************************************************************************************************************************** */
// 数据转换函数
/*************************************************************************************************************************** */
// 提取单个十六进制字符的数值
uint8_t func_get_hex_from_ASCLL(const char ch)
{
    if((ch >= '0') && (ch <= '9'))
    {
        return (uint8_t)(ch - '0');
    }
    else if((ch >= 'A') && (ch <= 'F'))
    {
        return (uint8_t)(ch - 'A' + 10);
    }
    else if((ch >= 'a') && (ch <= 'f'))
    {
        return (uint8_t)(ch - 'a' + 10);
    }
    else
    {
        return 0xFF;  // invalid
    }
}

// 提取单个十进制字符的数值
uint8_t func_get_dec_from_ASCLL(const char ch)
{
    if((ch >= '0') && (ch <= '9'))
    {
        return (uint8_t)(ch - '0');
    }
    else
    {
        return 0xFF;  // invalid
    }
}

// 十六进制字符串转换为十进制数值
int func_string_hex_to_dec(char *src)
{
    if((src == NULL) || (strlen(src) == 0))
    {
        LOG_E("func_string_hex_to_dec input invalid, src=%p", src);
        return -1;
    }

    int len = strlen(src);
    int result = 0;
    for(int i = 0; i < len; i++)
    {
        uint8_t hex_value = func_get_hex_from_ASCLL(src[i]);
        if(hex_value == 0xFF)
        {
            LOG_E("func_string_hex_to_dec invalid hex char, char=%c", src[i]);
            return -1;
        }
        result = (result << 4) | hex_value;
    }
    return result;
}

// 十进制字符串转换为十进制数值
int func_string_dec_to_dec(char *src)
{
    if((src == NULL) || (strlen(src) == 0))
    {
        LOG_E("func_string_dec_to_int input invalid, src=%p", src);
        return -1;
    }

    int len = strlen(src);
    int result = 0;
    for(int i = 0; i < len; i++)
    {
        uint8_t dec_value = func_get_dec_from_ASCLL(src[i]);
        if(dec_value == 0xFF)
        {
            LOG_E("func_string_dec_to_int invalid dec char, char=%c", src[i]);
            return -1;
        }
        result = result * 10 + dec_value;
    }
    return result;
}

// 十六进制字符串转换为十六进制缓冲区
int func_string_hex_to_buf(const char *src, char *dst, int *dst_size)
{
    if((src == NULL) || (dst == NULL) || (dst_size == NULL))
    {
        LOG_E("func_string_to_buf input invalid, src=%p, dst=%p, dst_size=%p", src, dst, dst_size);
        return -1;
    }

	char str[10]={0};
    int tmp=1;
    int i, len;

    len = strlen(src);
	*dst_size = len / 2;
    for(i=0; i<*dst_size; i++)
    {
    	memcpy(str, src + i*2, 2);
        tmp = func_string_hex_to_dec(str);
        dst[i] = tmp;
    }

    return 0;
}

// 十进制数值转换为十进制字符串
char *func_dec_to_string(char *src, int src_size, int dec, int width)
{
    memset(src, 0, src_size);

    switch (width)
    {
    case 2:  
        snprintf(src, src_size, "%02d", dec);
        break;
    case 4: 
        snprintf(src, src_size, "%04d", dec);
        break;
    case 8: 
        snprintf(src, src_size, "%08d", dec);
        break;
    default:
        snprintf(src, src_size, "%d", dec);
        break;
    }

    return src;
}

// 十六进制数值转换为十六进制字符串
char *func_hex_to_string(char *src, int src_size, int hex, int width)
{
    memset(src, 0, src_size);

    switch (width)
    {
    case 2: // 16-bit
        snprintf(src, src_size, "%02X", hex);
        break;
    case 4: // 32-bit
        snprintf(src, src_size, "%04X", hex);
        break;
    case 8: // 64-bit
        snprintf(src, src_size, "%08X", hex);
        break;
    default:
        snprintf(src, src_size, "%X", hex);
        break;
    }

    return src;
}

// 浮点数值转换为字符串
char *func_float_to_string(char *src, int src_size, float f, int width)
{
    memset(src, 0, src_size);

    switch (width)
    {
    case 2:
        snprintf(src, src_size, "%.2f", f);
        break;
    case 3:
        snprintf(src, src_size, "%.3f", f);
        break;
    case 6:
        snprintf(src, src_size, "%.6f", f);
        break;
    default:
        snprintf(src, src_size, "%.f", f);
        break;
    }

    return src;
}

// 缓冲区转换为十六进制字符串
char *func_buf_to_string(char *src, int src_size, const char *buf, int buf_size)
{
    memset(src, 0, src_size);

    if((buf == NULL) || (buf_size <= 0) || (src_size < (buf_size * 2 + 1)))
    {
        LOG_E("func_buf_to_string input invalid, buf=%p, buf_size=%d, src_size=%d", buf, buf_size, src_size);
        return src;
    }

    for(int i = 0; i < buf_size; i++)
    {
        snprintf(src + i * 2, 3, "%02X", (uint8_t)buf[i]);
    }

    return src;
}

// 字符串转换为参数列表
int func_string_to_argv(char *p_rx, uint8_t *argc, char *argv[], uint8_t argv_size)
{ 
    if(!p_rx || !argc || !argv || !argv_size) 
    {
        return -1;
    }
    
    (*argc) = 0;
    memset(argv, 0, sizeof(char*) * argv_size);
    
    // 使用strtok_r以支持线程安全
    char *saveptr = NULL;
    char *p_ch = strtok_r(p_rx, " ", &saveptr);
    
    while(p_ch != NULL && (*argc) < (argv_size - 1))
    { 
        argv[(*argc)] = p_ch;
        (*argc)++;
        p_ch = strtok_r(NULL, " ", &saveptr);
    }
    
    argv[(*argc)] = NULL;  // 以NULL结尾，兼容getopt

    return 0;
}


/*************************************************************************************************************************** */
// 时间转换函数，处理函数
/*************************************************************************************************************************** */
// 时间结构体转换为字符串
char *func_sys_time_to_string(char *src, int src_size, stru_func_time_sys *p_tm_sys)
{
    memset(src, 0, src_size);

    if((p_tm_sys == NULL) || (src_size < 20))
    {
        LOG_E("func_time_to_string input invalid, p_tm_sys=%p, src_size=%d", p_tm_sys, src_size);
        return src;
    }

    char temp[128] = {0};
    snprintf(temp, sizeof(temp), "%04d-%02d-%02dT%02d:%02d:%02d.%03d+0800", 
                                    p_tm_sys->year+2000, 
                                    p_tm_sys->month, 
                                    p_tm_sys->day, 
                                    p_tm_sys->hour, 
                                    p_tm_sys->min, 
                                    p_tm_sys->ms / 1000, 
                                    p_tm_sys->ms % 1000);

    if(strlen(temp) < (size_t)src_size)
    {
        strcpy(src, temp);
    }
    else
    {
        LOG_E("func_time_to_string output buffer too small, temp_len=%zu, src_size=%d", strlen(temp), src_size);
        strncpy(src, temp, src_size - 1);
    }

    return src;
}

// 字符串转换为时间结构体
int func_string_to_sys_time(const char *src, stru_func_time_sys *p_tm_sys)
{
    if((src == NULL) || (p_tm_sys == NULL))
    {
        LOG_E("func_string_to_sys_time input invalid, src=%p, p_tm_sys=%p", src, p_tm_sys);
        return -1;
    }

    char *p_ch = (char *)src;

    p_tm_sys->year  = atoi(p_ch) - 2000;        p_ch += 5; // skip '-'
    p_tm_sys->month = atoi(p_ch);               p_ch += 3; // skip '-'
    p_tm_sys->day   = atoi(p_ch);               p_ch += 3; // skip 'T'
    p_tm_sys->hour  = atoi(p_ch);               p_ch += 3; // skip ':'
    p_tm_sys->min   = atoi(p_ch);               p_ch += 3; // skip ':'
    p_tm_sys->ms    = atoi(p_ch) * 1000;        p_ch += 3; // skip '.'
    p_tm_sys->ms   += atoi(p_ch);               // skip '+'

    return 0;
}

// 获取系统时间
int func_get_time(void *p_tm, int time_type)
{
    if(p_tm == NULL)
    {
        LOG_E("func_get_time input invalid, p_tm=%p", p_tm);
        return -1;
    }

    struct timeval tv;
	struct tm *tt;
	stru_func_time_sys *p_tm_sys = (stru_func_time_sys *)p_tm;
	stru_func_time_cal *p_tm_cal = (stru_func_time_cal *)p_tm;

    gettimeofday(&tv, NULL);
    tt = localtime(&tv.tv_sec);

    switch (time_type)
    {
        case FUNC_TIME_TYPE_SYS:
            p_tm_sys->year  = tt->tm_year + 1900 - 2000; // since 1900
            p_tm_sys->month = tt->tm_mon + 1;   // 0-11
            p_tm_sys->day   = tt->tm_mday;
            p_tm_sys->week  = tt->tm_wday;
            p_tm_sys->hour  = tt->tm_hour;
            p_tm_sys->min   = tt->tm_min;
            p_tm_sys->ms    = tt->tm_sec * 1000 + tv.tv_usec / 1000;
            break;
        case FUNC_TIME_TYPE_CAL:
            p_tm_cal->sec   = tt->tm_sec;
            p_tm_cal->usec  = tv.tv_usec;
            break;
        default:
            LOG_E("func_get_time invalid time_type=%d", time_type);
            return -1;
    }
    return 0;
}
        
// 设置系统时间
int func_set_time(void *p_tm, int time_type)
{
    if(p_tm == NULL)
    {
        LOG_E("func_set_time input invalid, p_tm=%p", p_tm);
        return -1;
    }

    struct timeval tv;
	struct tm tt;
	stru_func_time_sys *p_tm_sys = (stru_func_time_sys *)p_tm;
	stru_func_time_cal *p_tm_cal = (stru_func_time_cal *)p_tm;

    switch (time_type)
    {
        case FUNC_TIME_TYPE_SYS:
            memset(&tt, 0, sizeof(tt));
            tt.tm_year = p_tm_sys->year + 2000 - 1900; // since 1900
            tt.tm_mon  = p_tm_sys->month - 1;  // 0-11
            tt.tm_mday = p_tm_sys->day;
            tt.tm_hour = p_tm_sys->hour;
            tt.tm_min  = p_tm_sys->min;
            tt.tm_sec  = p_tm_sys->ms / 1000;
            tv.tv_sec  = mktime(&tt);
            tv.tv_usec = 0;

            usleep((1000 - p_tm_sys->ms % 1000) * 1000);
			tv.tv_sec += 1;
            break;
        case FUNC_TIME_TYPE_CAL:
            tv.tv_sec  = p_tm_cal->sec;
            tv.tv_usec = p_tm_cal->usec;
            break;
        default:
            LOG_E("func_set_time invalid time_type=%d", time_type);
            return -1;
    }

    if (settimeofday(&tv, NULL) != 0)
    {
        LOG_E("func_set_time settimeofday failed, time_type=%d", time_type);
        return -1;
    }

    if(system("hwclock -w -u &") != 0)
    {
        LOG_E("func_set_time system failed, time_type=%d, %m", time_type);
        return -1;
    }
    
    return 0;
}

// 时间结构体转换cal时间
void func_time_sys_to_cal(stru_func_time_sys *p_tm_sys, stru_func_time_cal *p_tm_cal)
{ 
    if((p_tm_sys == NULL) || (p_tm_cal == NULL))
    {
        LOG_E("func_time_sys_to_cal input invalid, p_tm_sys=%p, p_tm_cal=%p", p_tm_sys, p_tm_cal);
        return;
    }

    struct tm tt;
    memset(&tt, 0, sizeof(tt));
    tt.tm_year = p_tm_sys->year + 2000 - 1900; // since 1900
    tt.tm_mon  = p_tm_sys->month - 1;  // 0-11
    tt.tm_mday = p_tm_sys->day;
    tt.tm_hour = p_tm_sys->hour;
    tt.tm_min  = p_tm_sys->min;
    tt.tm_sec  = p_tm_sys->ms / 1000;

    p_tm_cal->sec  = mktime(&tt);
    p_tm_cal->usec = (p_tm_sys->ms % 1000) * 1000;
}

// cal时间转换为时间结构体
void func_time_cal_to_sys(stru_func_time_cal *p_tm_cal, stru_func_time_sys *p_tm_sys)
{ 
    if((p_tm_cal == NULL) || (p_tm_sys == NULL))
    {
        LOG_E("func_time_cal_to_sys input invalid, p_tm_cal=%p, p_tm_sys=%p", p_tm_cal, p_tm_sys);
        return;
    }

    struct tm *tt;

    tt = localtime(&p_tm_cal->sec);

    p_tm_sys->year  = tt->tm_year + 1900 - 2000; // since 1900
    p_tm_sys->month = tt->tm_mon + 1;   // 0-11
    p_tm_sys->day   = tt->tm_mday;
    p_tm_sys->week  = tt->tm_wday;
    p_tm_sys->hour  = tt->tm_hour;
    p_tm_sys->min   = tt->tm_min;
    p_tm_sys->ms    = tt->tm_sec * 1000 + p_tm_cal->usec / 1000;
}


/*************************************************************************************************************************** */
// 文件和目录操作函数
/*************************************************************************************************************************** */
// 创建目录
static int func_make_dir(const char *p_dir)
{
    if(NULL == p_dir)
    {
        LOG_E("func_make_dir input invalid, p_dir=%p", p_dir);
        return -1;
    }

    return mkdir(p_dir, 0755);
}

// 目录是否存在
int func_dir_exist(const char *p_dir)
{ 
    if(NULL == p_dir)
    {
        LOG_E("func_dir_exist input invalid, p_dir=%p", p_dir);
        return -1;
    }

    if(access(p_dir, F_OK) == 0)
    {
        return 0; // exist
    }

    return -1; // not exist
}

// 按linux路径格式更新目录字符串
static void func_update_file(char *p_dir)
{
    if(NULL == p_dir)
    {
        LOG_E("func_update_file input invalid, p_dir=%p", p_dir);
        return;
    }

    uint32_t len = strlen(p_dir);
    char *p_ch = p_dir;
    char *q_ch = NULL;

    while ((*p_ch) != '\0')
    {
        if((q_ch = strchr(p_ch, '\\')) != NULL)
        {
            (*q_ch) = '/';
            p_ch = q_ch + 1;
        }

        if(q_ch == NULL)
        {
            break;
        }
    }
    
    if(p_dir[len - 1] != '/' && p_dir[len - 1] != '\\')
    {
        p_dir[len] = '/';
        p_dir[len + 1] = '\0';
    }
}



// 创建目录(支持多级目录创建)
int func_make_dirs(const char *p_dir)
{
    if(NULL == p_dir)
    {
        LOG_E("func_create_dirs input invalid, p_dir=%p", p_dir);
        return -1;
    }

    char dir[256] = {0};
    strncpy(dir, p_dir, sizeof(dir) - 1);
    func_update_file(dir);

    uint32_t len = strlen(dir);

    for(uint32_t i = 1; i < len; i++)
    {
        if(dir[i] == '/')
        {
            dir[i] = '\0';
            if(func_dir_exist(dir) != 0) // not exist
            {
                if(func_make_dir(dir) != 0)
                {
                    LOG_E("func_create_dirs make dir failed, dir=%s", dir);
                    return -1;
                }
            }
            dir[i] = '/';
        }
    }

    return 0;
}

// 删除目录(支持多级目录删除)
int func_del_dirs(const char *p_path)
{ 
    if(NULL == p_path)
    {
        LOG_E("func_del_dirs input invalid, p_dir=%p", p_path);
        return -1;
    }

    char dir[256] = {0};
    strncpy(dir, p_path, sizeof(dir) - 1);
    uint32_t len = strlen(dir);

    if(dir[len - 1] == '/')
    {
        dir[len - 1] = '\0';
    }

    DIR *p_dir = opendir(dir);
    if(p_dir == NULL)
    {
        LOG_E("func_del_dirs opendir failed, dir=%s", dir);
        return -1;
    }

    char fullpath[512] = {0};
    struct dirent *p_dirent = NULL;
    while ((p_dirent = readdir(p_dir)) != NULL)
    { 
        if(strcmp(p_dirent->d_name, ".") == 0 || strcmp(p_dirent->d_name, "..") == 0)
        {
            continue;
        }

        memset(fullpath, 0, sizeof(fullpath));

        snprintf(fullpath, sizeof(fullpath), "%s/%s", dir, p_dirent->d_name);
        if(p_dirent->d_type == DT_DIR)
        {
            if(func_del_dirs(fullpath) != 0)
            {
                closedir(p_dir);
                LOG_E("func_del_dirs remove failed, fullpath=%s", fullpath);
                return -1;
            }
        }
        else
        {
            if(remove(fullpath) != 0)
            {
                closedir(p_dir);   
                LOG_E("func_del_dirs remove failed, fullpath=%s", fullpath);
                return -1;
            }
        }
    }

    closedir(p_dir);
    if(rmdir(dir) != 0)
    {
        LOG_E("func_del_dirs remove failed, dir=%s", dir);
        return -1;
    }

    return 0;
}


// 删除目录(支持多级目录删除)，通过系统命令方式
int func_del_dirs_by_cmd(const char *p_path)
{ 
    if(NULL == p_path)
    {
        LOG_E("func_del_dirs_by_cmd input invalid, p_dir=%p", p_path);
        return -1;
    }

    char cmd[512] = {0};
    snprintf(cmd, sizeof(cmd), "rm -rf %s", p_path);
    if(system(cmd) != 0)
    {
        LOG_E("func_del_dirs_by_cmd system cmd failed, cmd=%s", cmd);
        return -1;
    }

    return 0;
}

// 文件是否存在
int func_file_exist(const char *p_file)
{ 
    if(NULL == p_file)
    {
        LOG_E("func_file_exist input invalid, p_file=%p", p_file);
        return -1;
    }

    if(access(p_file, F_OK) == 0)
    {
        return 0; // exist
    }

    return -1; // not exist
}

// 获取文件大小
uint32_t func_get_file_size(const char *p_file)
{
    if(NULL == p_file)
    {
        LOG_E("func_get_file_size input invalid, p_file=%p", p_file);
        return 0;
    }

    struct stat st;
    if(stat(p_file, &st) != 0)
    {
        LOG_E("func_get_file_size stat failed, p_file=%s", p_file);
        return 0;
    }
    return st.st_size;
}

// 读取文件内容到缓冲区
int func_read_file_to_buf(const char *p_file, char *p_buf, uint32_t buf_size, uint32_t *p_ret_len)
{ 
    if(NULL == p_file || NULL == p_buf || 0 == buf_size)
    {
        LOG_E("func_read_file input invalid, p_file=%p, p_buf=%p, buf_size=%p", p_file, p_buf, buf_size);
        return -1;
    }

    FILE *p_fp = fopen(p_file, "rb");
    if(NULL == p_fp)
    {
        LOG_E("func_read_file fopen failed, p_file=%s", p_file);
        return -1;
    }

    uint32_t file_size = func_get_file_size(p_file);
    uint32_t read_size = (file_size < buf_size) ? file_size : buf_size;

    if(fread(p_buf, 1, read_size, p_fp) != read_size)
    {
        LOG_E("func_read_file fread failed, p_file=%s", p_file);
        fclose(p_fp);
        return -1;
    }

    fclose(p_fp);
    if(NULL != p_ret_len)
    {
        *p_ret_len = read_size;
    }
    return 0;
}

// 读取文件内容到动态分配缓冲区
uint8_t *func_read_file_alloc_buf(const char *p_file, uint32_t *p_ret_len)
{ 
    if(NULL == p_file)
    {
        LOG_E("func_read_file_alloc_buf input invalid, p_file=%p", p_file);
        return NULL;
    }

    uint32_t file_size = func_get_file_size(p_file);
    if(file_size == 0)
    {
        LOG_E("func_read_file_alloc_buf file size is zero, p_file=%s", p_file);
        return NULL;
    }

    uint8_t *p_buf = (uint8_t *)malloc(file_size + 1);
    if(NULL == p_buf)
    {
        LOG_E("func_read_file_alloc_buf malloc failed, size=%u", file_size);
        return NULL;
    }

    FILE *p_fp = fopen(p_file, "rb");
    if(NULL == p_fp)
    {
        LOG_E("func_read_file_alloc_buf fopen failed, p_file=%s", p_file);
        free(p_buf);
        return NULL;
    }

    if(fread(p_buf, 1, file_size, p_fp) != file_size)
    {
        LOG_E("func_read_file_alloc_buf fread failed, p_file=%s", p_file);
        free(p_buf);
        fclose(p_fp);
        return NULL;
    }

    fclose(p_fp);
    if(NULL != p_ret_len)
    {
        *p_ret_len = file_size;
    }

    return p_buf;
}

// 写缓冲区内容到文件
int func_write_buf_to_file(const char *p_file, const char *p_buf, uint32_t buf_size)
{ 
    if(NULL == p_file || NULL == p_buf || 0 == buf_size)
    {
        LOG_E("func_write_buf_to_file input invalid, p_file=%p, p_buf=%p, buf_size=%p", p_file, p_buf, buf_size);
    }

    FILE *p_fp = fopen(p_file, "wb");
    if(NULL == p_fp)
    {
        LOG_E("func_write_buf_to_file fopen failed, p_file=%s", p_file);
        return -1;
    }

    if(fwrite(p_buf, 1, buf_size, p_fp) != buf_size)
    {
        LOG_E("func_write_buf_to_file fwrite failed, p_file=%s", p_file);
        fclose(p_fp);
        return -1;
    }

    fclose(p_fp);

    return 0;
}

// 按结构体格式读取文信息
int func_read_file_tip_info(const char *p_file, stru_func_file_tip_info *p_tip_info, int check)
{
    if((p_file == NULL) || (p_tip_info == NULL))
    {
        LOG_E("func_read_file_tip_info input invalid, p_file=%p, p_tip_info=%p", p_file, p_tip_info);
        return -1;
    }

    uint32_t read_size = sizeof(stru_func_file_tip_info);
    memset(p_tip_info, 0, read_size);

    uint32_t file_size = func_get_file_size(p_file);
    if(file_size < read_size)
    {
        LOG_E("func_read_file_tip_info file size invalid, file_size=%u", file_size);
        return -1;
    }

    FILE *p_fp = fopen(p_file, "rb");
    if(NULL == p_fp)
    {
        LOG_E("func_read_file_tip_info fopen failed, p_file=%s", p_file);
        return -1;
    }

    int offset = file_size - read_size;
    if(fseek(p_fp, offset, SEEK_SET) != 0)
    {
        LOG_E("func_read_file_tip_info fseek failed, p_file=%s", p_file);
        fclose(p_fp);
        return -1;
    }

    if(fread(p_tip_info, 1, read_size, p_fp) != read_size)
    {
        LOG_E("func_read_file_tip_info fread failed, p_file=%s", p_file);
        fclose(p_fp);
        return -1;
    }

    fclose(p_fp);

    if(check)
    { 
        return (p_tip_info->flag == FILE_TIP_FLAG ? 0 : -1);
    }

    return 0;   
}




/*************************************************************************/
// 进程相关信息获取函数
/*************************************************************************/

// 获取进程名称
int func_get_process_self_name(char *proc_name, uint32_t name_size)
{
    if((proc_name == NULL) || (name_size == 0))
    {
        LOG_E("func_get_process_name input invalid, proc_name=%p, name_size=%d", proc_name, name_size);
        return -1;
    }

    char path[512] = {0};

    int ret = readlink("/proc/self/exe", path, sizeof(path) - 1);
    if(ret < 0)
    {
        LOG_E("func_get_process_name readlink failed, errno=%d", errno);
        return -1;
    }
    path[ret] = '\0';

    char *p_ch = strrchr(path, '/');
    if(NULL == p_ch)
    {
        LOG_E("func_get_process_name strrchr failed");
        return -1;
    }

    if(strlen(p_ch + 1) >= name_size)
    {
        LOG_E("func_get_process_name output buffer too small, proc_name=%s, name_size=%d", p_ch + 1, name_size);
        return -1;
    }

    strncpy(proc_name, p_ch + 1, name_size - 1);
    proc_name[name_size - 1] = '\0';

    return 0;
}

// 通过pid获取进程名称
int func_get_process_name_by_pid(int pid, char *proc_name, uint32_t name_size)
{
    if((pid <= 0) || (proc_name == NULL) || (name_size == 0))
    {
        LOG_E("func_get_process_name_by_pid input invalid, pid=%d, proc_name=%p, name_size=%d", pid, proc_name, name_size);
        return -1;
    }

    char path[512] = {0};
    snprintf(path, sizeof(path), "/proc/%d/exe", pid);
    int ret = readlink(path, path, sizeof(path) - 1);
    if(ret < 0)
    {
        LOG_E("func_get_process_name_by_pid readlink failed, pid=%d, errno=%d", pid, errno);
        return -1;
    }
    path[ret] = '\0';

    char *p_ch = strrchr(path, '/');
    if(NULL == p_ch)
    {
        p_ch = path - 1;
    }

    if(strlen(p_ch + 1) >= name_size)
    {
        LOG_E("func_get_process_name_by_pid output buffer too small, proc_name=%s, name_size=%d", p_ch + 1, name_size);
        return -1;
    }

    strncpy(proc_name, p_ch + 1, name_size - 1);
    proc_name[name_size - 1] = '\0';

    return 0;
}

// 获取当前进程PID
int func_get_process_pid()
{ 
    return getpid();
}

// 通过进程名称获取进程PID
int func_get_process_pid_by_name(const char *proc_name)
{ 
    if(proc_name == NULL)
    {
        LOG_E("func_get_process_pid_by_name input invalid, proc_name=%p", proc_name);
        return -1;
    }

    DIR *p_dir = opendir("/proc");
    if(p_dir == NULL)
    {
        LOG_E("func_get_process_pid_by_name opendir failed");
        return -1;
    }

    char path[512] = {0};
    struct dirent *p_dirent = NULL;
    int target_pid = -1; // 初始化目标PID为-1（未找到）

    while ((p_dirent = readdir(p_dir)) != NULL)
    {
        if(strcmp(p_dirent->d_name, ".") == 0 || strcmp(p_dirent->d_name, "..") == 0)
        {
            continue;
        }

        // 忽略非数字开头的目录
        if(!isdigit(p_dirent->d_name[0]))
        {
            continue;
        }

        // 拼接路径 /proc/[pid]/exe
        snprintf(path, sizeof(path), "/proc/%s/exe", p_dirent->d_name);
        int ret = readlink(path, path, sizeof(path) - 1);
        if(ret < 0)
        {
            continue;   
        }
        path[ret] = '\0';
    
        char *p_ch = strrchr(path, '/');
        if(NULL == p_ch)
        {
            p_ch = path - 1;
        }

        const char *p_name = p_ch + 1;
        if(strcmp(p_name, proc_name) == 0)
        {
            target_pid = atoi(p_dirent->d_name);

            if(target_pid <=  0)
            {
                target_pid = -1;
                continue;
            }

            break;
        }
    }
    closedir(p_dir);

    return target_pid;
}

// 通过名称判断进程是否存在
int func_process_exist_by_name(const char *name)
{
    if(NULL == name)
    {
        LOG_E("func_process_exist_by_name input invalid, name=%p", name);
        return -1;
    }

    return (func_get_process_pid_by_name(name) > 0 ? 0 : -1);
}

// 通过PID判断进程是否存在
int func_process_exist_by_pid(int pid)
{
    if(pid <= 0)
    {
        LOG_E("func_process_exist_by_pid input invalid, pid=%d", pid);
        return -1;
    }

    char path[128] = {0};
    snprintf(path, sizeof(path), "/proc/%d", pid);
    DIR *dir = opendir(path);
    if(NULL == dir)
    {
        LOG_E("func_process_exist_by_pid opendir /proc failed, errno=%d", errno);
        return -1;
    }
    closedir(dir);

    return 0;
}

// 通过PID获取进程路径
int func_get_process_path_by_pid(int pid, char *path, uint32_t len)
{
    if((pid <= 0) || (path == NULL) || (len == 0))
    {
        LOG_E("func_get_process_path_by_pid input invalid, pid=%d, path=%p, len=%d", pid, path, len);
        return -1;
    }

    char link_path[256] = {0};
    char sub_path[64] = {0};
    snprintf(sub_path, sizeof(sub_path), "/proc/%d/exe", pid);

    int ret = readlink(sub_path, link_path, sizeof(link_path) - 1);
    if(ret < 0)
    {
        LOG_E("func_get_process_path_by_pid readlink failed, pid=%d, errno=%d", pid, errno);
        return -1;
    }
    link_path[ret] = '\0';

    if(strlen(link_path) >= len)
    {
        LOG_E("func_get_process_path_by_pid output buffer too small, link_path=%s, len=%d", link_path, len);
        return -1;
    }

    strncpy(path, link_path, len- 1);
    path[len - 1] = '\0';

    return 0;
}

// 获取当前进程路径
int func_get_process_self_path(char *path, uint32_t len)
{ 
    if((path == NULL) || (len == 0))
    {
        LOG_E("func_get_process_self_path input invalid, path=%p, len=%d", path, len);
        return -1;
    }

    char link_path[256] = {0};
    int ret = readlink("/proc/self/exe", link_path, sizeof(link_path) - 1);
    if(ret < 0)
    {
        LOG_E("func_get_process_self_path readlink failed, errno=%d", errno);
        return -1;
    }
    link_path[ret] = '\0';

    if(strlen(link_path) >= len)
    {
        LOG_E("func_get_process_self_path path too long, path=%s, len=%d", link_path, len);
        return -1;
    }

    strncpy(path, link_path, len - 1);
    path[len - 1] = '\0';

    return 0;
}


/*************************************************************************/
// 环境变量操作函数
/*************************************************************************/

// 获取环境变量值
static int func_get_env_value(const char *key, char *value, uint32_t len)
{ 
    if(NULL == key || NULL == value || len == 0)
    {
        LOG_E("func_get_env_value param error, key=%p, value=%p, len=%d", key, value, len);
        return -1;
    }

    char *p_env = getenv(key);
    if(NULL == p_env)
    {
        LOG_E("func_get_env_value getenv failed, key=%s", key);
        return -1;
    }

    if(strlen(p_env) >= len)
    {
        LOG_E("func_get_env_value output buffer too small, env=%s, len=%d", p_env, len);
        return -1;
    }

    strncpy(value, p_env, len - 1);
    value[len - 1] = '\0';

    return 0;
}


// 获取环境变量路径
static int func_get_env_path(const char *key, char *path, uint32_t len)
{ 
    if(NULL == key || NULL == path || len == 0)
    {
        LOG_E("func_get_env_path param error, key=%p, path=%p, len=%d", key, path, len);
        return -1;
    }

    char env_value[512] = {0};
    if(func_get_env_value(key, env_value, sizeof(env_value)) != 0)
    {
        LOG_E("func_get_env_path func_get_env_value failed, key=%s", key);
        return -1;
    }

    int size = strlen(env_value);

    if(size > 0 && size < sizeof(env_value) - 1)
    {
        if(env_value[size - 1] != '/')
        {
            env_value[size++] = '/';
            env_value[size] = '\0';
        }

        if(len > size)
        {
            strncpy(path, env_value, len - 1);
            path[len - 1] = '\0';

            return 0;
        }
    }

    return -1;
}


int func_get_work_path(char *path, uint32_t len)
{
    if(NULL == path || len == 0)
    {
        LOG_E("func_get_work_path param error, path=%p, len=%d", path, len);
        return -1;
    }

    return func_get_env_value(ENV_KEY_WORK_PATH, path, len);
}

int func_get_sys_cfg_path(char *path, uint32_t len)
{ 
    if(NULL == path || len == 0)
    {
        LOG_E("func_get_sys_cfg_path param error, path=%p, len=%d", path, len);
        return -1;
    }

    return func_get_env_path(ENV_KEY_SYS_CFG_PATH, path, len);
}

int func_get_app_root_path(char *path, uint32_t len)
{ 
    if (NULL == path || len == 0)
    {
        LOG_E("func_get_app_root_path param error, path=%p, len=%d", path, len);
        return -1;
    }

    return func_get_env_path(ENV_KEY_APP_ROOT_PATH, path, len);
}

int func_get_his_root_path(char *path, uint32_t len)
{ 
    if (NULL == path || len == 0)
    {
        LOG_E("func_get_his_root_path param error, path=%p, len=%d", path, len);
        return -1;
    }

    return func_get_env_path(ENV_KEY_HIS_ROOT_PATH, path, len);
}

int func_get_log_root_path(char *path, uint32_t len)
{ 
    if (NULL == path || len == 0)
    {
        LOG_E("func_get_log_root_path param error, path=%p, len=%d", path, len);
        return -1;
    }

    return func_get_env_path(ENV_KEY_LOG_ROOT_PATH, path, len);
}

int func_get_dbc_root_path(char *path, uint32_t len)
{ 
    if (NULL == path || len == 0)
    {
        LOG_E("func_get_dbc_root_path param error, path=%p, len=%d", path, len);
        return -1;
    }

    return func_get_env_path(ENV_KEY_DBC_ROOT_PATH, path, len);
}

int func_get_shell_path(char *path, uint32_t len)
{ 
    if (NULL == path || len == 0)
    {
        LOG_E("func_get_shell_path param error, path=%p, len=%d", path, len);
        return -1;
    }

    return func_get_env_path(ENV_KEY_SHELL_PATH, path, len);
}

int func_get_update_path(char *path, uint32_t len)
{ 
    if (NULL == path || len == 0)
    {
        LOG_E("func_get_update_path param error, path=%p, len=%d", path, len);
        return -1;
    }

    return func_get_env_path(ENV_KEY_UPDATE_PATH, path, len);
}

// 获取应用程序路径
int func_get_app_path(const char *app_name, char *path, uint32_t len)
{ 
    if(NULL == app_name || NULL == path || len == 0)
    {
        LOG_E("func_get_app_path param error, app_name=%p, path=%p, len=%d", app_name, path, len);
        return -1;
    }

    char value[512] = {0};
    if(func_get_app_root_path(value, sizeof(value)) != 0)
    {
        LOG_E("func_get_app_path func_get_app_root_path failed, app_name=%s", app_name);
        return -1;
    }

    snprintf(value+strlen(value), sizeof(value)-strlen(value), "%s/", app_name);

    if(strlen(value) + 1 >= len)
    {
        LOG_E("func_get_app_path output buffer too small, path=%s, app_name=%s, len=%d", path, app_name, len);
        return -1;
    }

    strncpy(path, value, len - 1);
    path[len - 1] = '\0';

    return 0;
}

// 获取应用程序配置文件路径
int func_get_app_cfg_path(const char *app_name, const char *postfix, char *path, uint32_t len)
{ 
    if(NULL == app_name || NULL == path || len == 0)
    {
        LOG_E("func_get_app_cfg_path param error, app_name=%p, path=%p, len=%d", app_name, path, len);
        return -1;
    }

    char value[512] = {0};

    if(func_get_app_root_path(value, sizeof(value)) != 0)
    {
        LOG_E("func_get_app_path func_get_app_root_path failed, app_name=%s", app_name);
        return -1;
    }

    if(NULL != postfix)
    {
        snprintf(value+strlen(value), sizeof(value)-strlen(value), "%s/%s.%s", app_name, app_name, postfix);
    }
    else
    {
        snprintf(value+strlen(value), sizeof(value)-strlen(value), "%s/%s.json", app_name, app_name);
    }
    
    if(strlen(value) + 1 >= len)
    {
        LOG_E("func_get_app_cfg_path output buffer too small, path=%s, app_name=%s, len=%d", path, app_name, len);
        return -1;
    }

    strncpy(path, value, len - 1);
    path[len - 1] = '\0';

    return 0;
}

// 获取应用程序历史数据路径
int func_get_app_his_path(const char *app_name, char *path, uint32_t len)
{ 
    if(NULL == app_name || NULL == path || len == 0)
    {
        LOG_E("func_get_app_his_path param error, app_name=%p, path=%p, len=%d", app_name, path, len);
        return -1;
    }

    char value[512] = {0};
    if(func_get_his_root_path(value, sizeof(value)) != 0)
    {
        LOG_E("func_get_app_his_path func_get_his_root_path failed, app_name=%s", app_name);
        return -1;
    }

    snprintf(value+strlen(value), sizeof(value)-strlen(value), "%s/", app_name);

    if(strlen(value) + 1 >= len)
    {
        LOG_E("func_get_app_his_path output buffer too small, path=%s, app_name=%s, len=%d", path, app_name, len);
        return -1;
    }

    strncpy(path, value, len - 1);
    path[len - 1] = '\0';

    return 0;
}

// 获取应用程序日志数据路径
int func_get_app_log_path(const char *app_name, char *path, uint32_t len)
{ 
    if(NULL == app_name || NULL == path || len == 0)
    {
        LOG_E("func_get_app_log_path param error, app_name=%p, path=%p, len=%d", app_name, path, len);
        return -1;
    }

    char value[512] = {0};
    if(func_get_log_root_path(value, sizeof(value)) != 0)
    {
        LOG_E("func_get_app_log_path func_get_log_root_path failed, app_name=%s", app_name);
        return -1;
    }

    snprintf(value+strlen(value), sizeof(value)-strlen(value), "%s/", app_name);

    if(strlen(value) + 1 >= len)
    {
        LOG_E("func_get_app_log_path output buffer too small, path=%s, app_name=%s, len=%d", path, app_name, len);
        return -1;
    }

    strncpy(path, value, len - 1);
    path[len - 1] = '\0';

    return 0;
}


/*************************************************************************/
// ipc消息队列操作函数
/*************************************************************************/

// 根据进程PID创建ipc消息队列
int func_create_ipc_msg_queue_by_pid(int pid, int *p_msg_queue_id)
{ 
    if(pid <= 0)
    {
        LOG_E("func_create_ipc_msg_queue_by_pid: pid is invalid, pid=%d", pid);
        return -1;
    }
    
    int msg_id;

    char str[64] = {0};
    snprintf(str, sizeof(str), "/proc/%d", pid);

    key_t key = ftok(str, 1);
    msg_id = msgget(key, IPC_CREAT | 0777);

    if(msg_id < 0)
    {
        LOG_E("func_create_ipc_msg_queue_by_pid msgget failed, pid=%d", pid);
        return -1;
    }

    if(p_msg_queue_id != NULL)
    {
        *p_msg_queue_id = msg_id;
    }

    return 0;
}

// 根据进程名称创建ipc消息队列
int func_create_ipc_msg_queue_by_name(char *proc_name, int *p_msg_queue_id)
{
    if(NULL == proc_name)
    {
        LOG_E("func_create_ipc_msg_queue: proc_name is null");
        return -1;
    }
    
    int pid = func_get_process_pid_by_name(proc_name);
    if(pid < 0)
    {
        LOG_E("func_create_ipc_msg_queue get pid failed, proc_name=%s", proc_name);
        return -1;
    }

    return func_create_ipc_msg_queue_by_pid(pid, p_msg_queue_id);
}

// 根据进程PID获取ipc消息队列ID
int func_get_ipc_msg_queue_by_pid(int pid, int *p_msg_queue_id)
{ 
    if(pid <= 0)
    {
        LOG_E("func_get_ipc_msg_queue_by_id: pid is invalid, pid=%d", pid);
        return -1;
    }
    
    int msg_id;

    char str[64] = {0};
    snprintf(str, sizeof(str), "/proc/%d", pid);

    key_t key = ftok(str, 1);
    msg_id = msgget(key, 0);

    if(msg_id < 0)
    {
        LOG_E("func_get_ipc_msg_queue_by_id msgget failed, str=%s pid=%d", str, pid);
        return -1;
    }

    if(p_msg_queue_id != NULL)
    {
        *p_msg_queue_id = msg_id;
    }

    return 0;
}

// 根据进程名称获取ipc消息队列ID
int func_get_ipc_msg_queue_by_name(const char *proc_name, int *p_msg_queue_id)
{
    if(NULL == proc_name)
    {
        LOG_E("func_get_ipc_msg_queue: proc_name is null");
        return -1;
    }
    
    int pid = func_get_process_pid_by_name(proc_name);
    if(pid < 0)
    {
        LOG_E("func_get_ipc_msg_queue get pid failed, proc_name=%s", proc_name);
        return -1;
    }

    return func_get_ipc_msg_queue_by_pid(pid, p_msg_queue_id);
}

// 发送ipc消息
int func_ipc_msg_send_buf(int msg_queue_id, uint8_t *p_tx, uint32_t len)
{ 
    if((msg_queue_id < 0) || (p_tx == NULL) || (len == 0))
    {
        LOG_E("func_ipc_msg_send input invalid, msg_queue_id=%d, p_tx=%p, len=%d", msg_queue_id, p_tx, len);
        return -1;
    }

    if(msgsnd(msg_queue_id, (void *)p_tx, len, IPC_NOWAIT) < 0)
    {
        LOG_E("func_ipc_msg_send msgsnd failed, msg_queue_id=%d", msg_queue_id);
        return -1;
    }

    return 0;
}

// 接收ipc消息
int func_ipc_msg_recv_buf(int msg_queue_id, uint8_t *p_rx, uint32_t len)
{
    if((msg_queue_id < 0) || (p_rx == NULL) || (len == 0))
    {
        LOG_E("func_ipc_msg_recv input invalid, msg_queue_id=%d, p_rx=%p", msg_queue_id, p_rx, len);
        return -1;
    }

    if(msgrcv(msg_queue_id, (void *)p_rx, len, 0, IPC_NOWAIT) < 0)
    {
        // LOG_E("func_ipc_msg_recv msgrcv failed, msg_queue_id=%d", msg_queue_id);
        return -1;
    }

    return 0;
}

// 发送ipc消息
int func_ipc_msg_send_struct(int msg_queue_id, stru_func_ipc_msg *p_msg)
{ 
    if((msg_queue_id < 0) || (p_msg == NULL))
    {
        LOG_E("func_ipc_msg_send input invalid, msg_queue_id=%d, p_msg=%p", msg_queue_id, p_msg);
        return -1;
    }

    if(msgsnd(msg_queue_id, (void *)p_msg, sizeof(stru_func_ipc_msg), IPC_NOWAIT) < 0)
    {
        LOG_E("func_ipc_msg_send msgsnd failed, msg_queue_id=%d", msg_queue_id);
        return -1;
    }

    return 0;
}

// 接收ipc消息
int func_ipc_msg_recv_struct(int msg_queue_id, stru_func_ipc_msg *p_msg)
{
    if((msg_queue_id < 0) || (p_msg == NULL))
    {
        LOG_E("func_ipc_msg_recv input invalid, msg_queue_id=%d, p_msg=%p", msg_queue_id, p_msg);
        return -1;
    }

    if(msgrcv(msg_queue_id, (void *)p_msg, sizeof(stru_func_ipc_msg), 0, IPC_NOWAIT) < 0)
    {
        LOG_E("func_ipc_msg_recv msgrcv failed, msg_queue_id=%d", msg_queue_id);
        return -1;
    }

    return 0;
}

// 删除ipc消息队列
int func_delete_ipc_msg_queue(int msg_queue_id)
{
    if(msg_queue_id < 0)
    {
        LOG_E("func_delete_ipc_msg_queue input invalid, msg_queue_id=%d", msg_queue_id);
        return -1;
    }

    if(msgctl(msg_queue_id, IPC_RMID, NULL) < 0)
    {
        LOG_E("func_delete_ipc_msg_queue msgctl failed, msg_queue_id=%d", msg_queue_id);
        return -1;
    }

    return 0;
}
