blob: 16245e06d620ef6aa063113b8700814b8d6057e5 [file] [log] [blame]
/**
*
* @file log_agent_sdcard.c
* @brief
* This file is part of ZCAT.
* zcatÓ¦Óòãlog_agent´¦Àíͨ¹ýsd¿¨µÄÊý¾ÝÁ÷
*
* @details
* @author Tools Team.
* @email
* @copyright Copyright (C) 2013 Sanechips Technology Co., Ltd.
* @warning
* @date 2019/02/02
* @version 1.2
* @pre
* @post
*
* @par
* Change History :
* ---------------------------------------------------------------------------
* date version author description
* ---------------------------------------------------------------------------
* 2017/07/17 1.0 hou.bing Create file
* 2019/01/24 1.1 jiang.fenglin 1.Ìí¼Óusblog¶ÁÐ´Ëø
* 2.Ìí¼ÓÏß³ÌÃû³Æ
* 2019/02/02 1.2 jiang.fenglin ÐÞ¸Ä×¢ÊÍ·½Ê½Îªdoxygen
* 2019/07/08 1.3 jiang.fenglin Ôö¼ÓAPFS/CPFSģʽ
* ---------------------------------------------------------------------------
*
*
*/
#include <string.h>
#include <pthread.h>
#include <sys/prctl.h>
#include <sys/statfs.h>
#include "log_agent.h"
#include "cfg_api.h"
#if 0
#define DEFAULT_LOG_ROOT "/sdcard"
#define DEFAULT_LOG_ROOT_PARENT "/ZTELog"
#define CONFIG_STORAGE_FILE_PATH "/data/misc/rild/log_storage.cfg"
#endif
#define USB_DEV_SDCARD_PATH "/dev/mmcblk0p1"
#define USB_DEV_SDCARD_PATH_BACK "/dev/mmcblk0"
#define ZCAT_SDCARD_MOUNT_PATH "/tmp/udisk"
#define ZCAT_SDCARD_RULE_PATH "/tmp/udisk/log.rule"
#define ZCAT_SDCARD_LOG_PATH "/tmp/udisk/zcat_log"
#define ZCAT_FS_RULE_PATH "/var/zcat/log.rule"
#define ZCAT_FS_PATH "/var/zcat"
static T_LOG_SDCARD_PARA g_log_sdcard_para = { {0} };
pthread_t rule_heartbeat_thread = 0;
extern int deal_with_encoded_data(unsigned char *buffer,int buf_len);
typedef struct
{
char head1[16];
int heartbeat_pos;
int heartbeat_len;
int rule_pos;
int rule_len;
int ap_rule_pos;
int ap_rule_len;
int log_file_size;
int log_file_cnt;
}rule_struct;
char g_heartbeat_buff[35] = {
0x01,0xaa,0xaa,0xaa,0x01,0x55,0x73,0x01,
0x14,0x00,0x00,0x00,0x06,0x01,0xbb,0xbb,
0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
0xe6,0x7a,0x7e
};
/* É豸¾ä±ú */
extern BOOL bSDSet;
extern int cplog_fd;
/**
* @brief ÅжÏĿ¼ÊÇ·ñ´æÔÚ£¬Èç¹û²»´æÔÚÔò´´½¨Ò»¸öеÄĿ¼
* @param[in] dir_path Ŀ¼·¾¶
* @return 0 on success, -1 error.
* @note
* @see
*/
int test_dir_exist(char* dir_path)
{
DIR *p_dir = NULL;
if ((p_dir = opendir(dir_path)) == NULL)
{
printf("[zcat] opendir failed, mkdir %s\n", dir_path);
if (mkdir(dir_path, 0777) != 0)
{
printf("[zcat] mkdir %s error, error info: %s\n", dir_path, strerror(errno));
return -1;
}
}
else
{
closedir(p_dir);
p_dir = NULL;
}
return 0;
}
/**
* @brief ³õʼ»¯sd¿¨´ælogµÄÅäÖòÎÊý
* @return void
* @note
* @see
*/
static void init_sdcard_para()
{
g_log_sdcard_para.max_file_size = 1024 * 1024 * 100;
//g_log_sdcard_para.max_file_num = 8;
g_log_sdcard_para.log_overwrite = 1;
g_log_sdcard_para.compress_log_files = 1;
g_log_sdcard_para.file_counts = 0;
g_log_sdcard_para.output_fd = -1;
g_log_sdcard_para.free_space_limit = 1024 * 1024 * 1;
memset(g_log_sdcard_para.rule_path, 0, sizeof(g_log_sdcard_para.rule_path));
strcpy(g_log_sdcard_para.rule_path, ZCAT_SDCARD_RULE_PATH);
}
/**
* @brief ³õʼ»¯sd¿¨normalģʽ²ÎÊý
* @return void
* @note
* @see
*/
static int init_sdcard_flash_mode()
{
memset(g_log_sdcard_para.log_dir, 0, sizeof(g_log_sdcard_para.log_dir));
strcpy(g_log_sdcard_para.log_dir, ZCAT_SDCARD_LOG_PATH);
if(test_dir_exist(g_log_sdcard_para.log_dir) < 0)//´´½¨ÈÕÖ¾Îļþ¼Ð
{
printf("[zcat] test %s dir exist failed. \n", g_log_sdcard_para.log_dir);
return -1;
}
return 0;
}
/**
* @brief ³õʼ»¯sd¿¨uÅÌģʽ²ÎÊý
* @return void
* @note
* @see
*/
static int init_sdcard_u_mode()
{
memset(g_log_sdcard_para.log_dir, 0, sizeof(g_log_sdcard_para.log_dir));
strcpy(g_log_sdcard_para.log_dir, ZCAT_SDCARD_LOG_PATH);
if(test_dir_exist(ZCAT_SDCARD_LOG_PATH) < 0)//ÅжÏËùÓÐÈÕ־Ŀ¼ÊÇ·ñ´æÔÚ
{
printf("[zcat] test_dir_exist failed:%s. \n", ZCAT_SDCARD_LOG_PATH);
return -1;
}
/*if(test_dir_exist(MODEM_LOG_PATH) < 0)//ÅжÏcpÈÕ־Ŀ¼ÊÇ·ñ´æÔÚ
{
printf("test_dir_exist failed:%s. \n", MODEM_LOG_PATH);
return -1;
}*/
return 0;
}
int zCat_MountSd()
{
char cmd[100] = { 0 };
if(test_dir_exist(ZCAT_SDCARD_MOUNT_PATH) < 0) // ´´½¨¹ÒÔØµÄÁÙʱÎļþ¼Ð
{
printf("[zcat] create %s fail.\n", ZCAT_SDCARD_MOUNT_PATH);
return -1;
}
printf("[zcat] init sd output dir successs.\n");
memset(cmd, 0, sizeof(cmd));
sprintf(cmd, "mount -t vfat %s %s", USB_DEV_SDCARD_PATH, ZCAT_SDCARD_MOUNT_PATH);
if(0 != zxic_system(cmd))
{
printf("[zcat] cmd %s fail!\n", cmd);
memset(cmd, 0, sizeof(cmd));
sprintf(cmd, "mount -t vfat %s %s", USB_DEV_SDCARD_PATH_BACK, ZCAT_SDCARD_MOUNT_PATH);
if(0 != system(cmd))
{
printf("[zcat] cmd %s fail, mount error!\n", cmd);
return -1;
}
}
return 0;
}
/**
* @brief ɾ³ýĿ¼ÏÂÔçÆÚ´´½¨µÄÎļþ\n
* ¸ù¾ÝÎļþÃûÅжϴ´½¨Ê±¼ä£¬É¾³ý×îÏÈ´´½¨µÄÄǸöÎļþ
* @param[in] dir_path ÎÄĿ¼·¾¶
* @return void
* @note
* @see
*/
static void delete_oldest_file(char* dir_path)
{
DIR *p_dir = NULL;
struct dirent *p_entry = NULL;
char oldest_file[64] = "99999999999999"; //ÈÕÆÚµÄ×î´óÖµ
char file_name[MAX_STRING_LENGTH] = {0};
p_dir = opendir(dir_path);
if(p_dir)
{
while ((p_entry = readdir(p_dir)) != NULL)
{
if (strncmp(p_entry->d_name, ".", 1) == 0)
continue;
if (strcmp(p_entry->d_name, oldest_file) < 0)
{
strncpy(oldest_file, p_entry->d_name, 64 - 1);
}
}
snprintf(file_name, MAX_STRING_LENGTH, "%s/%s", dir_path, oldest_file);
if(remove(file_name) != 0)
{
printf("[zcat] remove %s fail!errno=%d(%s)\n",file_name,errno,strerror(errno));
}
closedir(p_dir);
}
}
/**
* @brief ÔÚdir_pathĿ¼Ï´ò¿ªlogÊä³öÎļþ²¢·µ»ØÎļþ¾ä±ú,\n
* ÒÔµ±Ç°Ê±¼äΪÎļþÃû£¬´´½¨logÊä³öÎļþ¡£logÎļþ×î´óÊýÁ¿ÓÉLOG_FILE_MAX_NO¾ö¶¨£¬
* Èôµ±Ç°ÎļþÊýÒÑ´ïÉÏÏÞ£¬É¾³ý×îÏÈ´´½¨µÄÎļþ,ÔÙÒÔµ±Ç°Ê±¼äΪÎļþÃû´´½¨Îļþ
* @param[in] log_sdcard_para ÈÕÖ¾´æT¿¨²ÎÊý
* @return ´ò¿ªµÄlogÎļþÃèÊö·û
* @note
* @see
*/
static int open_log_file(T_LOG_SDCARD_PARA* log_sdcard_para)
{
int fd = -1;
char file_name[MAX_STRING_LENGTH] = {0};
struct tm *cur_time;
time_t now;
now = time(NULL);
cur_time = localtime(&now);
if(cur_time != NULL)
snprintf(file_name, MAX_STRING_LENGTH, "%s/%d_%02d%02d_%02d%02d%02d%s", log_sdcard_para->log_dir, cur_time->tm_year + 1900,
cur_time->tm_mon + 1, cur_time->tm_mday, cur_time->tm_hour, cur_time->tm_min,
cur_time->tm_sec, ".log");
if (log_sdcard_para->log_overwrite)
{
log_sdcard_para->file_counts++;
struct statfs diskInfo;
statfs(g_log_sdcard_para.log_dir, &diskInfo);
if (diskInfo.f_bfree * diskInfo.f_bsize < log_sdcard_para->free_space_limit)
//if (log_sdcard_para->file_counts > log_sdcard_para->max_file_num)
{
delete_oldest_file(log_sdcard_para->log_dir);
log_sdcard_para->file_counts--;
}
}
fd = open(file_name, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IWOTH | S_IROTH);
if (fd >= 0)
{
fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP |S_IWGRP | S_IROTH |S_IWOTH);
}
strncpy(log_sdcard_para->log_name, file_name, MAX_STRING_LENGTH-1);
return fd;
}
/**
* @brief ³õʼ»¯logµÄĿ¼
* @param[in] n/a
* @return 0 on success, errno otherwise
* @note
* @see
*/
int init_fs_log_dir()
{
struct statfs diskInfo;
(void)(diskInfo);
g_log_sdcard_para.max_file_size = 1024 * 1024 * 10;
//g_log_sdcard_para.max_file_num = 5;
g_log_sdcard_para.log_overwrite = 1;
g_log_sdcard_para.compress_log_files = 1;
g_log_sdcard_para.file_counts = 0;
g_log_sdcard_para.output_fd = -1;
g_log_sdcard_para.free_space_limit = 1024 * 1024 * 1;
memset(g_log_sdcard_para.rule_path, 0, sizeof(g_log_sdcard_para.rule_path));
strcpy(g_log_sdcard_para.rule_path, ZCAT_FS_RULE_PATH);
memset(g_log_sdcard_para.log_dir, 0, sizeof(g_log_sdcard_para.log_dir));
strcpy(g_log_sdcard_para.log_dir, ZCAT_FS_PATH);
if(test_dir_exist(g_log_sdcard_para.log_dir) < 0)//´´½¨ÈÕÖ¾Îļþ¼Ð
{
printf("[zcat] test %s dir exist failed. \n", g_log_sdcard_para.log_dir);
return -1;
}
g_log_sdcard_para.output_fd = open_log_file(&g_log_sdcard_para);//´ò¿ªÈÕÖ¾Îļþ
if (g_log_sdcard_para.output_fd == -1)
{
printf("[zcat] failed to open log file!\n");
return -1;
}
return 0;
}
/**
* @brief ³õʼ»¯sd¿¨´ælogµÄĿ¼
* @param[in] mode normalģʽ/uÅÌģʽ
* @return 0 on success, errno otherwise
* @note
* @see
*/
int init_sdcard_log_dir(E_FLASH_MODE mode)
{
init_sdcard_para();
if(mode == FLASH_MODE_U)
{
if(init_sdcard_u_mode() < 0)
{
printf("[zcat] init_sdcard_u_mode failed!\n");
return -1;
}
}
else
{
if(init_sdcard_flash_mode() < 0)
{
printf("[zcat] init_sdcard_flash_mode failed!\n");
return -1;
}
}
g_log_sdcard_para.output_fd = open_log_file(&g_log_sdcard_para);//´ò¿ªÈÕÖ¾Îļþ
if (g_log_sdcard_para.output_fd == -1)
{
printf("[zcat] failed to open log file!\n");
return -1;
}
return 0;
}
/**
* @brief дlogµ½SD¿¨.\n
* @param[in] fd ÉÏÒ»´ÎдÈësd¿¨ÖеÄzlfÎļþÃèÊö·û
* @param[in] buf ´ýдÈëµÄÊý¾ÝÖ¸Õë
* @param[in] len ´ýдÈëµÄÊý¾ÝÖ¸³¤¶È
* @param[in] log_sdcard_para sd¿¨²ÎÊý
* @return ʵ¼ÊдÈëµÄ³¤¶È
* @note
* @see
*/
static int output_log_to_sdcard(int fd, unsigned char *buf, int len, T_LOG_SDCARD_PARA* log_sdcard_para)
{
int output_fd = fd;
int write_len = 0;
//static int file_size = 0;
log_sdcard_para->file_size += len;
// Èç¹ûÎļþ´óС´ïµ½×î´óÎļþ³ß´ç£¬Ôòн¨Ò»¸öÎļþ
if (log_sdcard_para->file_size > log_sdcard_para->max_file_size)
{
close(fd);
if (log_sdcard_para->compress_log_files)
{
//compress_log_files(g_log_dir);
}
output_fd = open_log_file(log_sdcard_para);
if (output_fd == -1)
{
return -1;
}
log_sdcard_para->output_fd = output_fd;
log_sdcard_para->file_size = len;
}
write_len = write(output_fd, buf, len);
if(write_len != len) // Èç¹ûT¿¨Ð´Âú£¬Ôòɾ³ý֮ǰµÄlogÎļþ
{
delete_oldest_file(log_sdcard_para->log_dir);
log_sdcard_para->file_counts--;
write_len = write(output_fd, buf, len);
if(write_len != len)
{
return -1;
}
}
return write_len;
}
/**
* @brief bufferÄÚÈÝдÈëµ½T¿¨
* @param[in] buffer ´ýдÈëÊý¾ÝÖ¸Õë
* @param[in] buffer_len ´ýдÈëÊý¾Ý³¤¶È
* @return ʵ¼ÊдÈëµÄ³¤¶È
* @note
* @see
*/
int send_message_to_sdcard(unsigned char* buf, int len)
{
return output_log_to_sdcard(g_log_sdcard_para.output_fd, buf, len, &g_log_sdcard_para);
}
/**
* @brief ·¢Ë͹æÔòÎļþµ½cp.\n
* @param[in] fd ¹æÔòÎļþÃèÊö·û
* @param[in] offset ÎļþÆ«ÒÆ
* @param[in] length ·¢ËÍÊý¾Ý³¤¶È
* @return 0 on success, -1 otherwise
* @note
* @see
*/
static int send_rules_to_cp(int fd, int offset, int length)
{
char buf[1024] = {0};
int left_len = 0;
int next_buf_len = 0;
int read_len = 0;
if(lseek(fd, offset, SEEK_SET) == -1)
{
printf("[zcat] rules file lseek to pos %d failed (%s)\n", offset, strerror(errno));
return -1;
}
left_len = length;
next_buf_len = sizeof(buf) < left_len ? sizeof(buf) : left_len;
while((read_len = read(fd, buf, next_buf_len)) > 0)
{
int write_len = write(cplog_fd, buf, read_len);
if (write_len != read_len)
{
printf("[zcat] send_rule error, write_len = %d, len = %d.\n", write_len, read_len);
return -1;
}
left_len -= read_len;
next_buf_len = sizeof(buf) < left_len ? sizeof(buf) : left_len;
}
return 0;
}
/**
* @brief ·¢Ë͹æÔòÎļþµ½ap, app devºÍkernel dev.\n
* @param[in] fd ¹æÔòÎļþÃèÊö·û
* @param[in] offset ÎļþÆ«ÒÆ
* @param[in] length ·¢ËÍÊý¾Ý³¤¶È
* @return 0 on success, -1 otherwise
* @note
* @see
*/
static int send_rules_to_ap(int fd, int offset, int length)
{
unsigned char buf[1024] = {0};
int left_len = 0;
int next_buf_len = 0;
int read_len = 0;
if(lseek(fd, offset, SEEK_SET) == -1)
{
printf("[zcat] rules file lseek to pos %d failed (%s)\n", offset, strerror(errno));
return -1;
}
left_len = length;
next_buf_len = sizeof(buf) < left_len ? sizeof(buf) : left_len;
while((read_len = read(fd, buf, next_buf_len)) > 0)
{
deal_with_encoded_data(buf, read_len);
next_buf_len = sizeof(buf) < left_len ? sizeof(buf) : left_len;
}
return 0;
}
/**
* @brief ¼ì¹æÔòÎļþºÏ·¨ÐÔ£¬¶ÁȡժҪÐÅÏ¢.\n
* @param[in] fd ¹æÔòÎļþÃèÊö·û
* @param[out] rule_info ¹æÔòÎļþ¸ÅÒªÐÅÏ¢
* @return ¹æÔòÎļþµÄ´óС
* @note
* @see
*/
static int get_rule(int fd, rule_struct *rule_info)
{
int len = 0;
len = read(fd, rule_info, sizeof(rule_struct));
if(len <= 0)
{
printf("[zcat] rule file len = %d\n", len);
return len;
}
printf("[zcat] rule_info\n\theartbeat_pos : %d\n\theartbeat_len : %d\n\trule_pos : %d\n\trule_len : %d\n",
rule_info->heartbeat_pos,
rule_info->heartbeat_len,
rule_info->rule_pos,
rule_info->rule_len
);
if(rule_info->heartbeat_len > sizeof(g_heartbeat_buff))
{
printf("[zcat] check_rule, heartbeat voerload %d error.\n", sizeof(g_heartbeat_buff));
return -1;
}
// ¶ÁÈ¡¹æÔòÎļþÖеÄÐÄÌø°üÊý¾Ý£¬Ì滻ĬÈÏÐÄÌøÊý¾Ý
if(lseek(fd, rule_info->heartbeat_pos, SEEK_SET) == -1)
{
printf("[zcat] check_rule, lseek to heartbeat_pos error.\n");
return -1;
}
if(read(fd, g_heartbeat_buff, rule_info->heartbeat_len) <= 0)
{
printf("[zcat] check_rule, read heartbeat data error.\n");
return -1;
}
return len;
}
/**
* @brief ¹æÔòºÍÐÄÌø·¢ËÍỊ̈߳¬\n
* ¶ÁÈ¡sd¿¨ÖеĹæÔòÎļþ·¢Ë͸øpc£¬ÖÜÆÚÐԵķ¢ËÍÐÄÌø.
* @param[in] arg sd¿¨ÎļþÃèÊö·û
* @return void
* @note
* @see
*/
static void rule_heartbeat_entry(void *arg)
{
BOOL bSendRule = FALSE;
int rule_file_fd = 0;
int rule_len = 0;
rule_struct rule_info = { {0} };
char* heartbeat_buf = g_heartbeat_buff;
int heartbeat_len = sizeof(g_heartbeat_buff);
prctl(PR_SET_NAME, "heartbeat");
while(TRUE)
{
int write_len = write(cplog_fd, heartbeat_buf, heartbeat_len);
if (write_len != heartbeat_len)
{
printf("[zcat] send heartbeat failed! %d, %d, %d\n", cplog_fd, heartbeat_len, write_len);
}
sleep(2);
if(bSDSet == TRUE && bSendRule == FALSE)
{
rule_file_fd = open(g_log_sdcard_para.rule_path, O_RDONLY, S_IRUSR);
if (rule_file_fd < 0)
{
printf("[zcat] failed to open rule file %s.\n", g_log_sdcard_para.rule_path);
return;
}
// ¼ì²é¹æÔòÎļþºÏ·¨ÐÔ
rule_len = get_rule(rule_file_fd, &rule_info);
if(rule_len <= 0)
{
close(rule_file_fd);
return;
}
printf("[zcat] check rule success,len is %d\n", rule_len);
// ·¢ËÍcp¹æÔò
send_rules_to_cp(rule_file_fd, rule_info.rule_pos, rule_info.rule_len);
printf("[zcat] send rules to cp %d bytes,position %d\n",
rule_info.rule_len,
rule_info.rule_pos);
// ·¢ËÍap¹æÔò
send_rules_to_cp(rule_file_fd, rule_info.ap_rule_pos, rule_info.ap_rule_len);
printf("[zcat] send rules to cp %d bytes,position %d\n",
rule_info.ap_rule_len,
rule_info.ap_rule_pos);
close(rule_file_fd);
bSendRule = TRUE;
}
}
}
#if 0
/**
* @brief »ñÈ¡sdcardģʽ
* @param[in] void
* @return sdcardģʽ
* @note
* @see
*/
static E_FLASH_MODE get_flash_mode()
{
E_FLASH_MODE flash_mode = FLASH_MODE_NOMAL;
return flash_mode;
}
#endif
/**
* @brief ³õʼ»¯sdcardģʽ£¬´´½¨¹æÔòºÍÐÄÌø·¢ËÍÏß³Ì.
* @param[in] void
* @return 0 on success, errno otherwise
* @note
* @see
*/
int init_sdcard_mode()
{
//E_FLASH_MODE flash_mode = FLASH_MODE_NOMAL;
//flash_mode = get_flash_mode();
pthread_create(&rule_heartbeat_thread, NULL, (void*)rule_heartbeat_entry, NULL);
return 0;
}