/* Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include <sys/file.h>
#include <stdio.h>
#include "platform.h"
#include "sml.h"
#include "sml_errcodes.h"
#include "diagnose_defs.h"
#include "utils/file_securec.h"
#include "pd_log_process.h"

static PD_LOG_PARSE *g_adapter_pd_log_parse = NULL;
/*
 * Description: 适配pd_log_parse使用的sml函数
 */
void save_pd_log_parse_fun_table(PD_LOG_PARSE **pd_log_parse)
{
    g_adapter_pd_log_parse = *pd_log_parse;
}

gint32 sml_adapter_get_pd_log(SML_PD_LOG_S *pd)
{
    if (g_adapter_pd_log_parse != NULL && g_adapter_pd_log_parse->sml_get_pd_log != NULL) {
        return g_adapter_pd_log_parse->sml_get_pd_log(pd);
    }
    return 1;
}

const gchar *sml_adapter_get_ata_smart_attr_name(guint8 attr_id)
{
    if (g_adapter_pd_log_parse != NULL && g_adapter_pd_log_parse->sml_get_ata_smart_attr_name != NULL) {
        return g_adapter_pd_log_parse->sml_get_ata_smart_attr_name(attr_id);
    }
    return "Unknown_Attribute";
}

const gchar *sml_adapter_get_ata_smart_attr_name_by_vendor(const gchar *attr_name, guint8 attr_id)
{
    if (g_adapter_pd_log_parse != NULL && g_adapter_pd_log_parse->sml_get_ata_smart_attr_name_by_vendor != NULL) {
        return g_adapter_pd_log_parse->sml_get_ata_smart_attr_name_by_vendor(attr_name, attr_id);
    }
    return "Unknown_Attribute";
}

void sml_adapter_parse_ata_smart_attr_raw_value(gchar *buf, guint32 buf_size, ATA_SMART_ATTRIBUTE_S *smart_attr,
    guint8 *format)
{
    if (g_adapter_pd_log_parse != NULL && g_adapter_pd_log_parse->sml_parse_ata_smart_attr_raw_value != NULL) {
        return g_adapter_pd_log_parse->sml_parse_ata_smart_attr_raw_value(buf, buf_size, smart_attr, format);
    }
}
/*
 * Description: 检查硬盘日志的目录是否存在，不存在则创建
 * History: 1.2018年1月13日
 * 新生成函数
 */
gint32 pd_log_check_file_path(const gchar *device_name)
{
    gint32 iRet = -1;
    gchar log_file_path[MAX_FILEPATH_LENGTH] = {0};
    struct stat file_stat;
    if (stat_s(STORAGE_DIAGNOSE_LOG_BASE_PATH, &file_stat) < 0) {
        if (-1 ==
            g_mkdir_with_parents(STORAGE_DIAGNOSE_LOG_BASE_PATH, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
            return RET_ERR;
        }
        (void)chmod_s(STORAGE_DIAGNOSE_LOG_BASE_PATH, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
    }

    if (stat_s(PD_LOG_BASE_PATH, &file_stat) < 0) {
        if (-1 == g_mkdir_with_parents(PD_LOG_BASE_PATH, S_IRWXU | S_IRGRP | S_IXGRP)) {
            return RET_ERR;
        }
        (void)chmod_s(PD_LOG_BASE_PATH, S_IRWXU | S_IRGRP | S_IXGRP);
    }

    iRet = snprintf_s(log_file_path, sizeof(log_file_path), sizeof(log_file_path) - 1, "%s/%s", PD_LOG_BASE_PATH,
        device_name);
    if (iRet <= 0) {
        debug_log(DLOG_ERROR, "%s: snprintf_s fail, ret = %d", __FUNCTION__, iRet);
    }

    if (stat_s(log_file_path, &file_stat) < 0) {
        if (-1 == g_mkdir_with_parents(log_file_path, 0755)) {
            return RET_ERR;
        }
        (void)chmod_s(log_file_path, 0755);
    }

    return RET_OK;
}

/*
 * Description: 校验原始数据有效性
 * History: 1.2018年5月18日
 * 新生成函数
 * 2.2018年9月20日, 				AR.SR.SFEA02130924.009.007
 * 添加超时参数
 */
gint32 pd_log_check_raw_data(FILE *file, gint32 result, guint32 scsi_status, guint8 *data, guint32 data_length,
    gulong timeout)
{
    if (NULL == file) {
        return RET_ERR;
    }

    if (SML_SUCCESS != result && SML_ERR_PD_SCSI_RESP_TRUNCATED != result && SML_ERR_PD_SCSI_RESP_NO_DATA != result) {
        g_fprintf(file, "Get Data failed.");
        if ((SML_ERR_PD_SCSI_STATUS_BUSY == result || SML_ERR_PD_SCSI_CMD_FAIL == result) && 0 != scsi_status) {
            g_fprintf(file, "SCSI command is busy or failed, status code : 0x%02x .\n", scsi_status);
        } else if (SML_ERR_PD_SCSI_TIMEOUT == result) {
            g_fprintf(file, "SCSI command timeout (over %lu seconds).\n", timeout / 1000);
        } else {
            g_fprintf(file, "Unknown error : 0x%04x .\n", result);
        }
        return RET_ERR;
    }

    if (SML_ERR_PD_SCSI_RESP_NO_DATA == result || NULL == data || 0 == data_length) {
        g_fprintf(file, "Data is empty.\n");
        return RET_ERR;
    } else if (SML_ERR_PD_SCSI_RESP_TRUNCATED == result) {
        g_fprintf(file, "Data is truncated.\n");
    }

    return RET_OK;
}

/*
 * Description: 带外通道收集硬盘某一类日志的原始数据
 */
void pd_log_collect_raw_data_from_oob(guint8 ctrl_index, guint16 pd_device_id,
    SML_PD_LOG_DATA_S *pd_log_raw_data, guint32 pd_log_collect_timeout)
{
    SML_PD_LOG_S pd_log_s;

    if (pd_log_raw_data == NULL) {
        return;
    }

    (void)memset_s(&pd_log_s, sizeof(SML_PD_LOG_S), 0, sizeof(SML_PD_LOG_S));

    pd_log_s.i_controller_index = ctrl_index;
    pd_log_s.i_device_id = pd_device_id;
    (void)memcpy_s(&pd_log_s.log, sizeof(SML_PD_LOG_DATA_S), pd_log_raw_data, sizeof(SML_PD_LOG_DATA_S));

    guint32 t1 = vos_tick_get();
    gint32 retval = sml_adapter_get_pd_log(&pd_log_s);
    guint32 t2 = vos_tick_get();
    /* 如果获取日志的接口执行时间超过了指定时间180s, 则认为超时 */
    if (pd_log_collect_timeout < (t2 - t1)) {
        pd_log_raw_data->result = SML_ERR_PD_SCSI_TIMEOUT;
        pd_log_raw_data->scsi_status_code = pd_log_s.log.scsi_status_code;
        pd_log_raw_data->data = NULL;
        pd_log_raw_data->data_length = 0;

        if (pd_log_s.log.data != NULL) {
            g_free(pd_log_s.log.data);
        }

        return;
    }

    /* 如果获取日志的接口返回成功，则记录收集的结果和SCSI状态码以及日志数据 */
    if (retval == SML_SUCCESS) {
        pd_log_raw_data->result = pd_log_s.log.result;
        pd_log_raw_data->scsi_status_code = pd_log_s.log.scsi_status_code;
        pd_log_raw_data->data = pd_log_s.log.data;
        pd_log_raw_data->data_length = pd_log_s.log.data_length;
        /* SAS 以bytes作为数据单位 */
        if (pd_log_raw_data->log_type >= PD_LOG_SAS_SELF_TEST) {
            pd_log_raw_data->max_raw_data_size.bytes = pd_log_s.log.max_raw_data_size.bytes;
        /* SATA 以sector作为数据单位 */
        } else {
            pd_log_raw_data->max_raw_data_size.sectors = pd_log_s.log.max_raw_data_size.sectors;
        }
    /* 如果获取日志的接口返回失败，则记录收集的结果和SCSI状态码，并释放已经分配的内存 */
    } else {
        pd_log_raw_data->result = retval;
        pd_log_raw_data->scsi_status_code = pd_log_s.log.scsi_status_code;
        pd_log_raw_data->data = NULL;
        pd_log_raw_data->data_length = 0;

        if (pd_log_s.log.data != NULL) {
            g_free(pd_log_s.log.data);
        }
    }

    return;
}

/*
 * Description: 向日志文件中写入硬盘的基本信息
 * History: 1.2018年1月13日
 * 新生成函数
 */
void pd_log_write_header(FILE *file, PD_LOG_S *pd_log)
{
    gint32 retval = 0;
    gchar  timestamp_str[PROP_VAL_LENGTH] = {0};
    struct tm cur_tm = { 0 };
    static const gchar *pd_media_type_str[] = {
        MEDIA_TYPE_HDD,
        MEDIA_TYPE_SSD,
        MEDIA_TYPE_SSM
    };

    if (NULL == file || NULL == pd_log) {
        return;
    }

    g_fprintf(file, "%-40s: %s\n", "Device Name", pd_log->pd_device_name);

    if (STORAGE_INFO_INVALID_WORD == pd_log->pd_enclosure_id) {
        g_fprintf(file, "%-40s: %s\n", "Enclosure Id", "N/A");
    } else {
        g_fprintf(file, "%-40s: %d\n", "Enclosure Id", pd_log->pd_enclosure_id);
    }

    if (STORAGE_INFO_INVALID_BYTE == pd_log->pd_slot_number) {
        g_fprintf(file, "%-40s: %s\n", "Slot Number", "N/A");
    } else {
        g_fprintf(file, "%-40s: %d\n", "Slot Number", pd_log->pd_slot_number);
    }

    g_fprintf(file, "%-40s: %s\n", "Manufacturer", pd_log->pd_manufacturer);
    g_fprintf(file, "%-40s: %s\n", "Serial Number", pd_log->pd_serial_number);
    g_fprintf(file, "%-40s: %s\n", "Model", pd_log->pd_model);
    g_fprintf(file, "%-40s: %s\n", "Interface Type", pd_log->pd_interface_type_str);
    if (pd_log->pd_media_type <= PD_MEDIA_TYPE_SSM_FLASH) {
        g_fprintf(file, "%-40s: %s\n", "Media Type", pd_media_type_str[pd_log->pd_media_type]);
    }

    (void)memset_s(timestamp_str, PROP_VAL_LENGTH, 0, PROP_VAL_LENGTH);
    retval = dal_localtime_r(NULL, &cur_tm);
    if (RET_OK == retval) {
        (void)snprintf_s(timestamp_str, PROP_VAL_LENGTH, PROP_VAL_LENGTH - 1, "%04d-%02d-%02d %02d:%02d:%02d",
            cur_tm.tm_year + 1900, cur_tm.tm_mon + 1, cur_tm.tm_mday, cur_tm.tm_hour, cur_tm.tm_min, cur_tm.tm_sec);
    }

    g_fprintf(file, "%-40s: %s\n", "Timestamp", timestamp_str);

    return;
}

/*
 * Description: 释放存SATA盘日志数据的内存
 * History: 1.2018年1月9日
 * 新生成函数
 * 2.2018年9月15日, 		AR.SR.SFEA02130924.009.007
 * 新增释放FARM Log日志数据的内存
 */
static void pd_log_clear_sata(PD_LOG_S *pd_log)
{
    if (NULL == pd_log) {
        return;
    }

    if (NULL != pd_log->SATADevice.smart_attribute.data) {
        g_free(pd_log->SATADevice.smart_attribute.data);
        pd_log->SATADevice.smart_attribute.data = NULL;
    }

    if (NULL != pd_log->SATADevice.smart_attribute_threshold.data) {
        g_free(pd_log->SATADevice.smart_attribute_threshold.data);
        pd_log->SATADevice.smart_attribute_threshold.data = NULL;
    }

    if (NULL != pd_log->SATADevice.error.data) {
        g_free(pd_log->SATADevice.error.data);
        pd_log->SATADevice.error.data = NULL;
    }

    if (NULL != pd_log->SATADevice.extent_error.data) {
        g_free(pd_log->SATADevice.extent_error.data);
        pd_log->SATADevice.extent_error.data = NULL;
    }

    if (NULL != pd_log->SATADevice.extended_selftest.data) {
        g_free(pd_log->SATADevice.extended_selftest.data);
        pd_log->SATADevice.extended_selftest.data = NULL;
    }

    if (NULL != pd_log->SATADevice.phy_event.data) {
        g_free(pd_log->SATADevice.phy_event.data);
        pd_log->SATADevice.phy_event.data = NULL;
    }

    if (NULL != pd_log->SATADevice.seagate_glist.data) {
        g_free(pd_log->SATADevice.seagate_glist.data);
        pd_log->SATADevice.seagate_glist.data = NULL;
    }

    if (NULL != pd_log->SATADevice.seagate_plist.data) {
        g_free(pd_log->SATADevice.seagate_plist.data);
        pd_log->SATADevice.seagate_plist.data = NULL;
    }

    if (NULL != pd_log->SATADevice.seagate_critical_event.data) {
        g_free(pd_log->SATADevice.seagate_critical_event.data);
        pd_log->SATADevice.seagate_critical_event.data = NULL;
    }

    if (NULL != pd_log->SATADevice.seagate_farm.data) {
        g_free(pd_log->SATADevice.seagate_farm.data);
        pd_log->SATADevice.seagate_farm.data = NULL;
    }

    return;
}

/*
 * Description: 释放存SAS盘日志数据的内存
 * History: 1.2018年1月9日
 * 新生成函数
 */
static void pd_log_clear_sas(PD_LOG_S *pd_log)
{
    if (NULL == pd_log) {
        return;
    }

    if (NULL != pd_log->SASDevice.selftest.data) {
        g_free(pd_log->SASDevice.selftest.data);
        pd_log->SASDevice.selftest.data = NULL;
    }

    if (NULL != pd_log->SASDevice.read_error_cnt.data) {
        g_free(pd_log->SASDevice.read_error_cnt.data);
        pd_log->SASDevice.read_error_cnt.data = NULL;
    }

    if (NULL != pd_log->SASDevice.write_error_cnt.data) {
        g_free(pd_log->SASDevice.write_error_cnt.data);
        pd_log->SASDevice.write_error_cnt.data = NULL;
    }

    if (NULL != pd_log->SASDevice.verify_error_cnt.data) {
        g_free(pd_log->SASDevice.verify_error_cnt.data);
        pd_log->SASDevice.verify_error_cnt.data = NULL;
    }

    if (NULL != pd_log->SASDevice.nonmedium_error_cnt.data) {
        g_free(pd_log->SASDevice.nonmedium_error_cnt.data);
        pd_log->SASDevice.nonmedium_error_cnt.data = NULL;
    }

    if (NULL != pd_log->SASDevice.phy_error_cnt.data) {
        g_free(pd_log->SASDevice.phy_error_cnt.data);
        pd_log->SASDevice.phy_error_cnt.data = NULL;
    }

    if (NULL != pd_log->SASDevice.glist.data) {
        g_free(pd_log->SASDevice.glist.data);
        pd_log->SASDevice.glist.data = NULL;
    }

    if (NULL != pd_log->SASDevice.temperature.data) {
        g_free(pd_log->SASDevice.temperature.data);
        pd_log->SASDevice.temperature.data = NULL;
    }

    if (NULL != pd_log->SASDevice.ie.data) {
        g_free(pd_log->SASDevice.ie.data);
        pd_log->SASDevice.ie.data = NULL;
    }

    if (NULL != pd_log->SASDevice.bms.data) {
        g_free(pd_log->SASDevice.bms.data);
        pd_log->SASDevice.bms.data = NULL;
    }

    return;
}

/*
 * Description: 释放存硬盘日志数据的内存
 * History: 1.2018年1月9日
 * 新生成函数
 */
void pd_log_clear_data(PD_LOG_S *pd_log)
{
    if (NULL == pd_log) {
        return;
    }

    if (PD_INTERFACE_TYPE_SATA == pd_log->pd_interface_type) {
        pd_log_clear_sata(pd_log);
    } else if (PD_INTERFACE_TYPE_SAS == pd_log->pd_interface_type) {
        pd_log_clear_sas(pd_log);
    }

    return;
}

/*
 * Description: 清除指定的日志数据
 * History: 1.2019年1月22日,
 * 新生成函数        PN:UADP135084
 */
void pd_log_clear_specific_data(SML_PD_LOG_DATA_S *pd_log_data)
{
    if (NULL == pd_log_data) {
        return;
    }

    if (NULL != pd_log_data->data) {
        g_free(pd_log_data->data);
        pd_log_data->data = NULL;
    }

    pd_log_data->data_length = 0;
    pd_log_data->result = SML_ERR_PD_SCSI_RESP_NO_DATA;

    return;
}

/*
 * Description: 日志打印
 * History: 1.2018年4月17日
 * 新生成函数
 */
void pd_log_fprintf(FILE *file, gchar const * format, ...)
{
#define PD_LOG_MAX_LEN 4096

    gint32 i_ret = -1;
    va_list args;
    gchar log_tmp_buf[PD_LOG_MAX_LEN] = {0};
    if (file == NULL || format == NULL) {
        return;
    }

    va_start(args, format);
    i_ret = vsnprintf_s(log_tmp_buf, sizeof(log_tmp_buf), sizeof(log_tmp_buf) - 1, format, args);
    if (i_ret <= 0) {
        debug_log(DLOG_ERROR, "%s: snprintf_s fail, ret = %d", __FUNCTION__, i_ret);
    }
    g_fprintf(file, "%s", log_tmp_buf);
    va_end(args);
    return;
}

/*
 * Description: 格式化显示时间
 * History: 1.2018年3月30日
 * 新生成函数
 */
void pd_log_format_time(guint32 time_ms, gchar *str, gint32 str_len)
{
    guint32 day, hour, minute, second;
    if (NULL == str || 0 == str_len) {
        return;
    }

    (void)memset_s(str, str_len, 0, str_len);
    day = time_ms / 86400000U;
    time_ms = time_ms - day * 86400000U;
    hour = time_ms / 3600000U;
    time_ms = time_ms - hour * 3600000U;
    minute = time_ms / 60000U;
    time_ms = time_ms - minute * 60000U;
    second = time_ms / 1000U;
    time_ms = time_ms - second * 1000U;

    if (day) {
        (void)snprintf_s(str, str_len, str_len - 1, "%2ud+", day);
    }

    (void)snprintf_s(str + strlen(str), str_len - strlen(str), str_len - strlen(str) - 1, "%02u:%02u:%02u.%03u", hour,
        minute, second, time_ms);
    return;
}

/*
 * Description: 重命名有相同base name的同一类日志文件名
 * History: 1.2017年12月29日,  新生成函数
 *          2.2018年9月26日,  AR.SR.SFEA02130924.009.007 修改rotate_num后，删除掉大于rotate_num的已存在文件
 */
void check_log_file_rotate(const gchar *base_name, const gchar *ext_name, guint8 max_log_num)
{
    gint32 iRet = -1;
    gint32 i = 0;
    gint32 next_unused_seq_num = 0;
    gchar file_name[MAX_FILEPATH_LENGTH + 1] = {0};
    gchar new_name[MAX_FILEPATH_LENGTH + 1] = {0};
    struct stat file_stat;

    if (base_name == NULL || max_log_num == 0) {
        return;
    }

    /* 删除掉大于rotate_num的已存在文件，即后缀.n大于等于max_log_num的文件 */
    i = max_log_num;
    if (NULL != ext_name) {
        iRet = snprintf_s(file_name, MAX_FILEPATH_LENGTH + 1, MAX_FILEPATH_LENGTH, "%s.%s.%d", base_name, ext_name, i);
        if (iRet <= 0) {
            debug_log(DLOG_ERROR, "%s: snprintf_s fail, ret = %d", __FUNCTION__, iRet);
        }
    } else {
        iRet = snprintf_s(file_name, MAX_FILEPATH_LENGTH + 1, MAX_FILEPATH_LENGTH, "%s.%d", base_name, i);
        if (iRet <= 0) {
            debug_log(DLOG_ERROR, "%s: snprintf_s fail, ret = %d", __FUNCTION__, iRet);
        }
    }
    while (stat_s(file_name, &file_stat) >= 0) {
        (void)vos_rm_filepath(file_name);
        i++;
        if (NULL != ext_name) {
            iRet =
                snprintf_s(file_name, MAX_FILEPATH_LENGTH + 1, MAX_FILEPATH_LENGTH, "%s.%s.%d", base_name, ext_name, i);
            if (iRet <= 0) {
                debug_log(DLOG_ERROR, "%s: snprintf_s fail, ret = %d", __FUNCTION__, iRet);
            }
        } else {
            iRet = snprintf_s(file_name, MAX_FILEPATH_LENGTH + 1, MAX_FILEPATH_LENGTH, "%s.%d", base_name, i);
            if (iRet <= 0) {
                debug_log(DLOG_ERROR, "%s: snprintf_s fail, ret = %d", __FUNCTION__, iRet);
            }
        }
    }

    // 检查系列日志文件是否存在，从序号低的开始检查，检查到不存在指定的日志文件时停止
    for (i = 0; i < max_log_num; i++) {
        if (0 == i) {
            if (NULL != ext_name) {
                iRet =
                    snprintf_s(file_name, MAX_FILEPATH_LENGTH + 1, MAX_FILEPATH_LENGTH, "%s.%s", base_name, ext_name);
                if (iRet <= 0) {
                    debug_log(DLOG_ERROR, "%s: snprintf_s fail, ret = %d", __FUNCTION__, iRet);
                }
            } else {
                iRet = snprintf_s(file_name, MAX_FILEPATH_LENGTH + 1, MAX_FILEPATH_LENGTH, "%s", base_name);
                if (iRet <= 0) {
                    debug_log(DLOG_ERROR, "%s: snprintf_s fail, ret = %d", __FUNCTION__, iRet);
                }
            }
        } else {
            if (NULL != ext_name) {
                iRet = snprintf_s(file_name, MAX_FILEPATH_LENGTH + 1, MAX_FILEPATH_LENGTH, "%s.%d.%s", base_name, i,
                    ext_name);
                if (iRet <= 0) {
                    debug_log(DLOG_ERROR, "%s: snprintf_s fail, ret = %d", __FUNCTION__, iRet);
                }
            } else {
                iRet = snprintf_s(file_name, MAX_FILEPATH_LENGTH + 1, MAX_FILEPATH_LENGTH, "%s.%d", base_name, i);
                if (iRet <= 0) {
                    debug_log(DLOG_ERROR, "%s: snprintf_s fail, ret = %d", __FUNCTION__, iRet);
                }
            }
        }

        // 文件不存在停止检查
        if (stat_s(file_name, &file_stat) < 0) {
            break;
        }
    }

    // 下一个没有被使用的日志文件序号
    next_unused_seq_num = i;
    /* next_unused_seq_num == 0 ? 不需要处理
       next_unused_seq_num == 1 ~ max_log_num - 1  文件名序号改为1 ~ max_log_num - 1
       next_unused_seq_num == max_log_num ? 删除MAX_PHY_LOG_FILE_NUM - 1，文件名序号改为1 ~ max_log_num - 2
    */

    // 先从序号最高未被占用的文件名名称开始改名，以避免修改名名称后存在冲突
    for (i = next_unused_seq_num; i > 0; i--) {
        if (max_log_num == i) {
            continue;
        } else if (1 == i) {
            if (NULL != ext_name) {
                iRet =
                    snprintf_s(file_name, MAX_FILEPATH_LENGTH + 1, MAX_FILEPATH_LENGTH, "%s.%s", base_name, ext_name);
                if (iRet <= 0) {
                    debug_log(DLOG_ERROR, "%s: snprintf_s fail, ret = %d", __FUNCTION__, iRet);
                }
                iRet =
                    snprintf_s(new_name, MAX_FILEPATH_LENGTH + 1, MAX_FILEPATH_LENGTH, "%s.1.%s", base_name, ext_name);
                if (iRet <= 0) {
                    debug_log(DLOG_ERROR, "%s: snprintf_s fail, ret = %d", __FUNCTION__, iRet);
                }
            } else {
                iRet = snprintf_s(file_name, MAX_FILEPATH_LENGTH + 1, MAX_FILEPATH_LENGTH, "%s", base_name);
                if (iRet <= 0) {
                    debug_log(DLOG_ERROR, "%s: snprintf_s fail, ret = %d", __FUNCTION__, iRet);
                }
                iRet = snprintf_s(new_name, MAX_FILEPATH_LENGTH + 1, MAX_FILEPATH_LENGTH, "%s.1", base_name);
                if (iRet <= 0) {
                    debug_log(DLOG_ERROR, "%s: snprintf_s fail, ret = %d", __FUNCTION__, iRet);
                }
            }
        } else {
            if (NULL != ext_name) {
                iRet = snprintf_s(file_name, MAX_FILEPATH_LENGTH + 1, MAX_FILEPATH_LENGTH, "%s.%d.%s", base_name, i - 1,
                    ext_name);
                if (iRet <= 0) {
                    debug_log(DLOG_ERROR, "%s: snprintf_s fail, ret = %d", __FUNCTION__, iRet);
                }
                iRet = snprintf_s(new_name, MAX_FILEPATH_LENGTH + 1, MAX_FILEPATH_LENGTH, "%s.%d.%s", base_name, i,
                    ext_name);
                if (iRet <= 0) {
                    debug_log(DLOG_ERROR, "%s: snprintf_s fail, ret = %d", __FUNCTION__, iRet);
                }
            } else {
                iRet = snprintf_s(file_name, MAX_FILEPATH_LENGTH + 1, MAX_FILEPATH_LENGTH, "%s.%d", base_name, i - 1);
                if (iRet <= 0) {
                    debug_log(DLOG_ERROR, "%s: snprintf_s fail, ret = %d", __FUNCTION__, iRet);
                }
                iRet = snprintf_s(new_name, MAX_FILEPATH_LENGTH + 1, MAX_FILEPATH_LENGTH, "%s.%d", base_name, i);
                if (iRet <= 0) {
                    debug_log(DLOG_ERROR, "%s: snprintf_s fail, ret = %d", __FUNCTION__, iRet);
                }
            }
        }

        // 如果new_name文件已经存在，rename函数会先将该文件删除，然后再改名
        if (-1 == rename(file_name, new_name)) {
            debug_log(DLOG_ERROR, "[%s]Rename file name from %s to %s failed, errno = %d\n", __FUNCTION__, file_name,
                new_name, errno);
        }
    }

    return;
}

/*
 * Description: 读取日志文件内容到缓冲区，并返回实际文件内容大小
 */
gint32 pd_log_read_file(const gchar *file_path, gchar *file_buf, guint32 buf_size, guint32 *p_content_size)
{
    if (file_path == NULL || file_buf == NULL || buf_size == 0 || p_content_size == NULL) {
        debug_log(DLOG_INFO, "%s: Invalid input parameter", __FUNCTION__);
        return RET_ERR;
    }

    struct stat file_stat;
    *p_content_size = 0;

    gint32 ret = stat_s(file_path, &file_stat);
    if (ret < 0) {
        debug_log(DLOG_INFO, "%s: stat_s file failed, ret:%d", __FUNCTION__, ret);
        return RET_ERR;
    }

    if (file_stat.st_size <= 0) {
        debug_log(DLOG_INFO, "%s: get file length failed", __FUNCTION__);
        return RET_ERR;
    }

    *p_content_size = (guint32)file_stat.st_size;
    if (*p_content_size > buf_size) {
        debug_log(DLOG_INFO, "%s: p_content_size:%u greater than buf_size:%u failed", __FUNCTION__,
            *p_content_size, buf_size);
        return RET_ERR;
    }

    // 读取指定的文件
    ret = read_file_s(file_path, file_buf, *p_content_size);
    if (ret != 0) {
        debug_log(DLOG_INFO, "%s: read file failed, file content size:%u", __FUNCTION__, *p_content_size);
        return RET_ERR;
    }

    return RET_OK;
}

/*
 * Description: 将缓冲区的内容写入日志文件
 * History: 1.2017年12月30日,
 * 新生成函数
 */
gint32 pd_log_write_file(const gchar *file_path, const gchar *file_buf, guint32 content_size)
{
    if (file_path == NULL || file_buf == NULL || content_size == 0) {
        debug_log(DLOG_INFO, "%s: Invalid input parameter", __FUNCTION__);
        return RET_ERR;
    }

    // 打开文件写，直接覆盖原文件
    FILE *fp = fopen_s(file_path, "w+", file_path);
    if (fp == NULL) {
        debug_log(DLOG_INFO, "[%s]Create file failed", __FUNCTION__);
        return RET_ERR;
    }

    if (fwrite(file_buf, content_size, 1, fp) != 1) {
        debug_log(DLOG_INFO, "[%s]Write file failed", __FUNCTION__);
        (void)fclose_s(fp);
        return RET_ERR;
    }

    // 修改生成的文件权限为0640
    (void)fchmod(fileno(fp), 0640);

    // 强制刷新文件内容到存储设备上，否则异常掉电可能会导致文件内容没有写入
    (void)fflush(fp);
    (void)fsync(fileno(fp));

    (void)fclose_s(fp);

    return RET_OK;
}

/*
 * Description: 在日志缓冲区的指定位置删除指定长度的信息，后面的信息前移
 */
gint32 pd_log_buf_delete(gchar *buf, guint32 buf_size, guint32 start_pos, guint32 delete_len,
    guint32 *p_content_size)
{
    errno_t safe_fun_ret = EOK;
    if (buf == NULL || buf_size == 0 || p_content_size == NULL) {
        return RET_ERR;
    }
    if (buf_size < *p_content_size || start_pos >= *p_content_size) {
        return RET_ERR;
    }

    if (delete_len >= (*p_content_size - start_pos)) {
        *p_content_size = start_pos;
        return RET_OK;
    }

    // 将start_pos + delete_len位置开始的内容向前移动delete_len个字符位置
    safe_fun_ret = memmove_s(&buf[start_pos], (buf_size - start_pos), &buf[start_pos + delete_len],
        (*p_content_size - start_pos - delete_len));
    if (safe_fun_ret != EOK) {
        debug_log(DLOG_ERROR, "%s: memmove_s fail, ret = %d\n", __FUNCTION__, safe_fun_ret);
    }

    // 重新计算缓冲区内容大小
    *p_content_size = *p_content_size - delete_len;

    return RET_OK;
}

/*
 * Description: 获取当前时间戳字符串
 */
gint32 get_current_time_stamp(gchar *time_stamp, guint32 len)
{
    gint32 retval = RET_OK;
    struct tm cur_tm = { 0 };

    if (time_stamp == NULL || len == 0) {
        return RET_ERR;
    }

    (void)memset_s(time_stamp, len, 0, len);
    retval = dal_localtime_r(NULL, &cur_tm);
    if (retval == RET_OK) {
        (void)snprintf_s(time_stamp, len, len - 1, "%04d-%02d-%02d %02d:%02d:%02d,", cur_tm.tm_year + 1900, // 1900年
            cur_tm.tm_mon + 1, cur_tm.tm_mday, cur_tm.tm_hour, cur_tm.tm_min, cur_tm.tm_sec);
    }

    return RET_OK;
}

/*
 * Description: 在日志缓冲区的指定位置插入信息
 */
gint32 pd_log_buf_insert(gchar *buf, guint32 buf_size, guint32 insert_pos, const gchar *str_to_add,
    guint32 *p_content_size)
{
    errno_t safe_fun_ret = EOK;
    size_t insert_info_len = 0;

    if (buf == NULL || buf_size == 0 || p_content_size == NULL || str_to_add == NULL) {
        return RET_ERR;
    }
    if (buf_size < *p_content_size || insert_pos > *p_content_size) {
        return RET_ERR;
    }

    insert_info_len = strlen(str_to_add);
    if ((insert_pos + insert_info_len) > buf_size) {
        return RET_ERR;
    }

    // 将insert_pos位置开始的内容向后移动insert_info_len个字符位置
    safe_fun_ret = memmove_s(&buf[insert_pos + insert_info_len], (buf_size - insert_pos - insert_info_len),
        &buf[insert_pos], (*p_content_size - insert_pos));
    if (safe_fun_ret != EOK) {
        debug_log(DLOG_ERROR, "%s: memmove_s fail, ret = %d\n", __FUNCTION__, safe_fun_ret);
    }

    // 在insert_pos位置插入新增内容
    safe_fun_ret = memcpy_s(&buf[insert_pos], insert_info_len, str_to_add, insert_info_len);
    if (safe_fun_ret != EOK) {
        debug_log(DLOG_ERROR, "%s: memcpy_s fail, ret = %d\n", __FUNCTION__, safe_fun_ret);
    }

    // 重新计算缓冲区内容大小
    *p_content_size = ((*p_content_size + insert_info_len) > buf_size) ? buf_size : (*p_content_size + insert_info_len);

    return RET_OK;
}
