#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <dirent.h> | |
#include <regex.h> | |
#include <sys/stat.h> | |
#include <sys/time.h> | |
#include <time.h> | |
#include <limits.h> | |
#include <fcntl.h> | |
#include <unistd.h> | |
#include <ctype.h> | |
#include <dlfcn.h> | |
typedef void (*mbtk_log)(int level, const char *format,...); | |
static void *handle = NULL; | |
static mbtk_log fun_ptr_log = NULL; | |
#define LIB_PATH "/lib/libmbtk_lib.so" | |
#define LOG_LEVLE_CONFIG_FILE "/etc/telinit" | |
#define MAX_FILES 500 | |
#define MAX_PATH 100 | |
#define CP_LOG_PATH "/media/var/log" | |
#define DUMP_LOG_PATH "/media/var/log/modem_dump" | |
#define EMMC_HEALTH "/sys/kernel/debug/mmc0/mmc0:0001/health" | |
#define CP_LOG_MAX_SIZE (600 * 1024 * 1024) | |
#define DUMP_LOG_MAX_SIZE (100 * 1024 * 1024) | |
#define SEVEN_DAYS_SECONDS (7 * 24 * 60 * 60) | |
#ifndef LOG_ERR_LEVEL | |
#define LOG_ERR_LEVEL 3 /* error conditions */ | |
#endif | |
#ifndef LOG_WARN_LEVEL | |
#define LOG_WARN_LEVEL 4 /* warning conditions */ | |
#endif | |
#ifndef LOG_INFO_LEVEL | |
#define LOG_INFO_LEVEL 6 /* informational */ | |
#endif | |
#ifndef LOG_DEBUG_LEVEL | |
#define LOG_DEBUG_LEVEL 7 /* debug-level messages */ | |
#endif | |
#ifndef LOG_VERBOSE_LEVEL | |
#define LOG_VERBOSE_LEVEL 8 | |
#endif | |
#define LOGV(fmt, args ...) \ | |
do{ \ | |
char *file_ptr_1001 = __FILE__; \ | |
char *ptr_1001 = file_ptr_1001 + strlen(file_ptr_1001) - 1; \ | |
char line_1001[10] = {0}; \ | |
sprintf(line_1001, "%d", __LINE__); \ | |
while(ptr_1001 >= file_ptr_1001 && *ptr_1001){ \ | |
if(*ptr_1001 == '/') \ | |
break; \ | |
ptr_1001--; \ | |
} \ | |
fun_ptr_log(LOG_INFO_LEVEL, "%s#%s: [log_check]" fmt, ptr_1001 + 1, line_1001, ##args); \ | |
} while(0) | |
#define LOGI(fmt, args...) \ | |
do{ \ | |
char *file_ptr_1001 = __FILE__; \ | |
char *ptr_1001 = file_ptr_1001 + strlen(file_ptr_1001) - 1; \ | |
char line_1001[10] = {0}; \ | |
sprintf(line_1001, "%d", __LINE__); \ | |
while(ptr_1001 >= file_ptr_1001 && *ptr_1001){ \ | |
if(*ptr_1001 == '/') \ | |
break; \ | |
ptr_1001--; \ | |
} \ | |
fun_ptr_log(LOG_INFO_LEVEL, "%s#%s: [log_check]" fmt, ptr_1001 + 1, line_1001, ##args); \ | |
} while(0) | |
#define LOGD(fmt, args...) \ | |
do{ \ | |
char *file_ptr_1001 = __FILE__; \ | |
char *ptr_1001 = file_ptr_1001 + strlen(file_ptr_1001) - 1; \ | |
char line_1001[10] = {0}; \ | |
sprintf(line_1001, "%d", __LINE__); \ | |
while(ptr_1001 >= file_ptr_1001 && *ptr_1001){ \ | |
if(*ptr_1001 == '/') \ | |
break; \ | |
ptr_1001--; \ | |
} \ | |
fun_ptr_log(LOG_INFO_LEVEL, "%s#%s: [log_check]" fmt, ptr_1001 + 1, line_1001, ##args); \ | |
} while(0) | |
#define LOGW(fmt, args...) \ | |
do{ \ | |
char *file_ptr_1001 = __FILE__; \ | |
char *ptr_1001 = file_ptr_1001 + strlen(file_ptr_1001) - 1; \ | |
char line_1001[10] = {0}; \ | |
sprintf(line_1001, "%d", __LINE__); \ | |
while(ptr_1001 >= file_ptr_1001 && *ptr_1001){ \ | |
if(*ptr_1001 == '/') \ | |
break; \ | |
ptr_1001--; \ | |
} \ | |
fun_ptr_log(LOG_INFO_LEVEL, "%s#%s: [log_check]" fmt, ptr_1001 + 1, line_1001, ##args); \ | |
} while(0) | |
#define LOGE(fmt, args...) \ | |
do{ \ | |
char *file_ptr_1001 = __FILE__; \ | |
char *ptr_1001 = file_ptr_1001 + strlen(file_ptr_1001) - 1; \ | |
char line_1001[10] = {0}; \ | |
sprintf(line_1001, "%d", __LINE__); \ | |
while(ptr_1001 >= file_ptr_1001 && *ptr_1001){ \ | |
if(*ptr_1001 == '/') \ | |
break; \ | |
ptr_1001--; \ | |
} \ | |
fun_ptr_log(LOG_INFO_LEVEL, "%s#%s: [log_check]" fmt, ptr_1001 + 1, line_1001, ##args); \ | |
} while(0) | |
int32_t init_handle() | |
{ | |
handle = dlopen(LIB_PATH, RTLD_NOW); | |
if(handle == NULL) | |
{ | |
return -1; | |
} | |
if(fun_ptr_log == NULL) | |
{ | |
fun_ptr_log = (mbtk_log)dlsym(handle, "mbtk_log"); | |
if(fun_ptr_log == NULL) | |
{ | |
return -1; | |
} | |
} | |
return 0; | |
} | |
typedef struct { | |
char name[128]; | |
time_t mtime; | |
off_t size; | |
} LogDir; | |
int compare_mtime(const void *a, const void *b) { | |
LogDir *dirA = (LogDir *)a; | |
LogDir *dirB = (LogDir *)b; | |
return (dirA->mtime - dirB->mtime); // 升序排序 | |
} | |
static int get_cp_log_folder(char *path, LogDir *dirs, int *dirs_count) | |
{ | |
DIR *dp = NULL; | |
DIR *subdp = NULL; | |
struct dirent *entry; | |
struct dirent *subentry; | |
struct stat st; | |
regex_t regex; | |
int count = 0; | |
int folder_size = 0; | |
int total_size = 0; | |
char full_path[1024]; | |
char temp_path[1024]; | |
// 编译正则表达式:^Log[0-9]{3}.* | |
if (regcomp(®ex, "^Log[0-9]{3}.*", REG_EXTENDED) != 0) | |
{ | |
fprintf(stderr, "Failed to compile regex.\n"); | |
return -1; | |
} | |
dp = opendir(path); | |
if (dp == NULL) | |
{ | |
perror("opendir"); | |
return -1; | |
} | |
while ((entry = readdir(dp)) != NULL) | |
{ | |
if (regexec(®ex, entry->d_name, 0, NULL, 0) == 0) //entr:Log00x | |
{ | |
snprintf(full_path, sizeof(full_path), "%s/%s", path, entry->d_name); | |
strncpy(dirs[count].name, full_path, sizeof(dirs[count].name)); | |
//printf("flod:%s \n", full_path); | |
if (strstr(full_path, "tar.gz") != NULL) //tar file | |
{ | |
if (lstat(full_path, &st) < 0) | |
{ | |
perror("lstat"); | |
} | |
folder_size += st.st_size; | |
dirs[count].mtime = st.st_mtime; | |
} | |
else | |
{ | |
subdp = opendir(full_path); //Log00x Folder | |
if (NULL == subdp) | |
{ | |
LOGE("cant open:%s\n", full_path); | |
continue; | |
} | |
while ((subentry = readdir(subdp)) != NULL) | |
{ | |
if (strcmp(subentry->d_name, ".") == 0 || strcmp(subentry->d_name, "..") == 0) | |
continue; | |
//snprintf(temp_path, sizeof(temp_path), "%s/%s", full_path, subentry->d_name); | |
temp_path[0] = '\0'; | |
strncat(temp_path, full_path, sizeof(temp_path) - 1); | |
strncat(temp_path, "/", sizeof(temp_path) - strlen(temp_path) - 1); | |
strncat(temp_path, subentry->d_name, sizeof(temp_path) - strlen(temp_path) - 1); | |
//printf("file:%s \n", temp_path); | |
if (lstat(temp_path, &st) < 0) | |
{ | |
perror("lstat"); | |
continue; | |
} | |
if (S_ISREG(st.st_mode)) | |
{ | |
folder_size += st.st_size; | |
dirs[count].mtime = st.st_mtime; | |
} | |
} | |
if(NULL != subdp) | |
closedir(subdp); | |
} | |
dirs[count].size = folder_size; | |
total_size += folder_size; | |
folder_size = 0; | |
count++; | |
if (count >= MAX_FILES) | |
{ | |
fprintf(stderr, "Too many matching directories, increase MAX_DIRS.\n"); | |
break; | |
} | |
} | |
} | |
closedir(dp); | |
regfree(®ex); | |
qsort(dirs, count, sizeof(LogDir), compare_mtime); | |
*dirs_count = count; | |
return total_size; | |
} | |
static int get_dump_log_folder(char *path, LogDir *files, int *dirs_count) | |
{ | |
DIR *dp = NULL; | |
struct dirent *entry; | |
char full_path[4096]; | |
int total_size = 0; | |
int count = 0; | |
struct stat st; | |
dp = opendir(path); | |
if (NULL == dp) | |
{ | |
perror("opendir"); | |
return -1; | |
} | |
while ((entry = readdir(dp)) != NULL) | |
{ | |
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) | |
continue; | |
snprintf(full_path, sizeof(full_path), "%s/%s", path, entry->d_name); | |
//printf("file:%s \n", full_path); | |
if (lstat(full_path, &st) < 0) { | |
perror("lstat"); | |
continue; | |
} | |
if (S_ISREG(st.st_mode)) { | |
total_size += st.st_size; | |
strncpy(files[count].name, full_path, sizeof(files[count].name)); | |
files[count].size = st.st_size; | |
files[count++].mtime = st.st_mtime; | |
} | |
} | |
if(NULL != dp) | |
closedir(dp); | |
*dirs_count = count; | |
qsort(files, count, sizeof(LogDir), compare_mtime); | |
return total_size; | |
} | |
int get_emmc_health(char *path) | |
{ | |
char buffer[1024]; | |
int result = -1; | |
int i = 0; | |
int fd = open(path, O_RDONLY); | |
if (fd == -1) | |
{ | |
LOGE("can not open health node"); | |
return -1; | |
} | |
ssize_t bytes_read = read(fd, buffer, sizeof(buffer) - 1); | |
if (bytes_read > 0) | |
{ | |
buffer[bytes_read] = '\0'; | |
LOGI("emmc health node string:\n%s len:%d\n", buffer, bytes_read); | |
} | |
close(fd); | |
for(i = 0; i < bytes_read; i++) | |
{ | |
if('-' == buffer[i]) | |
{ | |
char num_str[4] = {buffer[i+1], buffer[i+2], buffer[i+3], '\0'}; | |
result = atoi(num_str); | |
LOGI("emmc health %d\n", result); | |
break; | |
} | |
} | |
return result; | |
} | |
int set_log_level(const char *log_level) | |
{ | |
char command[256] = {0}; | |
char *log_levl_param[6] = {"default", "cp_load", "atcmdsrv", "ciClientStubTas", "nvmproxy", "rild"}; | |
int i = 0; | |
for(i = 0; i < 6; i++) | |
{ | |
snprintf(command, sizeof(command), | |
"sed -i 's/\\(setprop sys.%s.loglevel \\)\\S*/\\1%s/' %s", | |
log_levl_param[i], log_level, LOG_LEVLE_CONFIG_FILE); | |
int result = system(command); | |
if (result != 0) | |
{ | |
LOGE("command execution failed.\n", command); | |
return -1; | |
} | |
} | |
return 0; | |
} | |
int is_modified_within_7_days(LogDir dir) | |
{ | |
time_t now = time(NULL); | |
time_t mtime = dir.mtime; | |
// 计算时间差 | |
double diff = difftime(now, mtime); | |
if (diff <= SEVEN_DAYS_SECONDS) | |
{ | |
return 1; | |
} else { | |
return 0; | |
} | |
} | |
int tar_log_file(const char *path_name, time_t mtime) | |
{ | |
char command[256] = {0}; | |
struct timeval times[2]; | |
char tar_file[128]; | |
struct stat st; | |
time_t now; | |
struct tm *tm_info; | |
char time_str[64]; | |
int ret; | |
LOGI("input log file: %s\n", path_name); | |
time(&now); | |
tm_info = localtime(&now); | |
strftime(time_str, sizeof(time_str), "%Y-%m-%d-%H:%M:%S", tm_info); | |
snprintf(tar_file, sizeof(tar_file)," %s-%s.tar.gz", path_name, time_str); | |
LOGI("input log file: %s\n", tar_file); | |
snprintf(command, sizeof(command), "tar -czvf %s %s", tar_file, path_name); | |
ret = system(command); | |
if (ret != 0) | |
{ | |
LOGE("command execution failed.\n", command); | |
return -1; | |
} | |
if (lstat(tar_file, &st) < 0) | |
{ | |
return -1; | |
} | |
times[0].tv_sec = st.st_atime; | |
times[0].tv_usec = 0; | |
times[1].tv_sec = mtime; | |
times[1].tv_usec = 0; | |
if (utimes(tar_file, times) < 0) | |
{ | |
return -1; | |
} //update tar file mtime | |
return 0; | |
} | |
int main(int argc, char* argv[]) | |
{ | |
int health; | |
LogDir cp_dirs[MAX_FILES]; | |
LogDir dump_files[MAX_FILES]; | |
int cp_dirs_count = 0; | |
int dump_files_count = 0; | |
int i = 0; | |
int ret = 0; | |
char command[128] = {0}; | |
int total_size = 0; | |
int modify_7day; | |
init_handle(); | |
health = get_emmc_health(EMMC_HEALTH); | |
if(health != -1) | |
{ | |
if(health >= 50 && health < 70) | |
{ | |
ret = set_log_level("5"); //warn | |
if(ret != 0) | |
LOGE("set log level error\n"); | |
} | |
if(health >= 70) | |
{ | |
ret = set_log_level("0"); | |
if(ret != 0) | |
LOGE("set log level error\n"); | |
} | |
} | |
else | |
{ | |
LOGE("get emmc health error\n"); | |
} | |
while(1) | |
{ | |
i = 0; | |
total_size = get_cp_log_folder(CP_LOG_PATH, cp_dirs, &cp_dirs_count); | |
LOGI("module %s files size:%d MB\n",CP_LOG_PATH, (total_size/1024)/1024); | |
while(total_size >= CP_LOG_MAX_SIZE) | |
{ | |
LOGI("Exceed capacity limit:%d MB now:%d MB\n", (CP_LOG_MAX_SIZE/1024)/1024, (total_size/1024)/1024); | |
if(i >= cp_dirs_count) | |
{ | |
LOGE("No more files that can be compressed\n"); | |
break; | |
} | |
modify_7day = is_modified_within_7_days(cp_dirs[i]); | |
if(modify_7day == 0) | |
{ | |
//Delete files created for more than 7 days | |
//snprintf(command, sizeof(command), "rm -rf %s", cp_dirs[i].name); | |
command[0] = '\0'; | |
strncat(command, "rm -rf ", sizeof(command) - 1); | |
strncat(command, cp_dirs[i].name, sizeof(command) - strlen(command) - 1); | |
LOGI("Delete files:%s created for more than 7 days\n", cp_dirs[i].name); | |
ret = system(command); | |
if (ret != 0) | |
{ | |
LOGE("command execution failed.\n", command); | |
return -1; | |
} | |
LOGI("Execute the command:%s\n", command); | |
} | |
if(modify_7day == 1) | |
{ | |
if(strstr(cp_dirs[i].name, "tar.gz") != NULL) | |
{ | |
LOGI("Tar file:%s already exists, No more compression at once\n", cp_dirs[i].name); | |
i++; | |
continue; | |
} | |
tar_log_file(cp_dirs[i].name, cp_dirs[i].mtime); | |
//snprintf(command, sizeof(command), "rm -rf %s", cp_dirs[i].name); | |
command[0] = '\0'; | |
strncat(command, "rm -rf ", sizeof(command) - 1); | |
strncat(command, cp_dirs[i].name, sizeof(command) - strlen(command) - 1); | |
LOGI("del folder command:%s\n", command); | |
ret = system(command); | |
if (ret != 0) | |
{ | |
LOGE("command execution failed.\n", command); | |
return -1; | |
} | |
} | |
i++; | |
total_size = get_cp_log_folder(CP_LOG_PATH, cp_dirs, &cp_dirs_count); | |
sleep(2); | |
} | |
i = 0; | |
total_size = get_dump_log_folder(DUMP_LOG_PATH, dump_files, &dump_files_count); | |
LOGI("module %s files size:%d MB\n",DUMP_LOG_PATH, (total_size/1024)/1024); | |
while(total_size >= DUMP_LOG_MAX_SIZE) | |
{ | |
LOGI("Exceed capacity limit:%d MB now:%d MB\n", (DUMP_LOG_MAX_SIZE/1024)/1024, (total_size/1024)/1024); | |
if(i >= dump_files_count) | |
{ | |
LOGE("No more files that can be compressed\n"); | |
break; | |
} | |
modify_7day = is_modified_within_7_days(dump_files[i]); | |
if(modify_7day == 0) | |
{ | |
//del timeout file | |
//snprintf(command, sizeof(command), "rm -rf %s", dump_files[i].name); | |
command[0] = '\0'; | |
strncat(command, "rm -rf ", sizeof(command) - 1); | |
strncat(command, cp_dirs[i].name, sizeof(command) - strlen(command) - 1); | |
LOGI("command:%s, total_size:%d \n", command, total_size); | |
ret = system(command); | |
if (ret != 0) | |
{ | |
LOGE("command execution failed.\n", command); | |
return -1; | |
} | |
} | |
if(modify_7day == 1) | |
{ | |
if(strstr(dump_files[i].name, "tar.gz") != NULL) | |
{ | |
LOGI("Tar file:%s already exists, No more compression at once\n", dump_files[i].name); | |
i++; | |
continue; | |
} | |
tar_log_file(dump_files[i].name, dump_files[i].mtime); | |
//del source file | |
//snprintf(command, sizeof(command), "rm -rf %s", dump_files[i].name); | |
command[0] = '\0'; | |
strncat(command, "rm -rf ", sizeof(command) - 1); | |
strncat(command, dump_files[i].name, sizeof(command) - strlen(command) - 1); | |
LOGI("del folder command:%s\n", command); | |
ret = system(command); | |
if (ret != 0) | |
{ | |
LOGE("command execution failed.\n", command); | |
return -1; | |
} | |
} | |
i++; | |
total_size = get_dump_log_folder(DUMP_LOG_PATH, dump_files, &dump_files_count); | |
sleep(2); | |
} | |
sleep(60); | |
#if 0 | |
for(i = 0; i < cp_dirs_count && cp_dirs_count < MAX_FILES; i++) { | |
struct tm *tm_info = localtime(&cp_dirs[i].mtime); | |
strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S", tm_info); | |
printf("folder:%s, files:%ld, time:%s\n", cp_dirs[i].name, cp_dirs[i].size, timebuf); | |
} | |
for(i = 0; i < dump_files_count && dump_files_count < MAX_FILES; i++) { | |
struct tm *tm_info = localtime(&dump_files[i].mtime); | |
strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S", tm_info); | |
printf("folder:%s, files:%ld, time:%s\n", dump_files[i].name, dump_files[i].size, timebuf); | |
} | |
#endif | |
} | |
return 0; | |
} | |