Files
acrn-hypervisor/tools/acrn-crashlog/acrnprobe/history.c
Liu, Xinwu 876cc68311 tools:acrn-crashlog: Change the algorithm of generating event key
Acrnprobe is using SHA to generate ids for events. These ids are only used
to index events, not for cryptographic purpose.

This patch unify the generating algorithm of short and long ids to
SHA256.

Tracked-On: #1024
Signed-off-by: Liu, Xinwu <xinwu.liu@intel.com>
Reviewed-by: Zhi Jin <zhi.jin@intel.com>
Acked-by: Chen Gang <gang.c.chen@intel.com>
2018-09-13 10:03:23 +08:00

295 lines
6.6 KiB
C

/*
* Copyright (C) 2018 Intel Corporation
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* Copyright (C) 2018 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <string.h>
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include "fsutils.h"
#include "load_conf.h"
#include "history.h"
#include "log_sys.h"
#include "probeutils.h"
#define HISTORY_FIRST_LINE_FMT \
"#V1.0 CURRENTUPTIME %-24s\n"
#define HISTORY_BLANK_LINE2 \
"#EVENT ID DATE TYPE\n"
struct history_entry {
char *event;
char *type;
char *log;
const char *lastuptime; /* for uptime */
char *key;
char *eventtime;
};
char *history_file;
static int current_lines;
static void entry_to_history_line(struct history_entry *entry,
char newline[MAXLINESIZE])
{
newline[0] = 0;
if (entry->log != NULL) {
char *ptr;
char tmp[PATH_MAX];
strncpy(tmp, entry->log, PATH_MAX);
tmp[PATH_MAX - 1] = 0;
ptr = strrchr(tmp, '/');
if (ptr && ptr[1] == 0)
ptr[0] = 0;
snprintf(newline, MAXLINESIZE, "%-8s%-22s%-20s%s %s\n",
entry->event, entry->key, entry->eventtime,
entry->type, tmp);
} else if (entry->type != NULL && entry->type[0]) {
if (entry->lastuptime != NULL) {
snprintf(newline, MAXLINESIZE,
"%-8s%-22s%-20s%-16s %s\n",
entry->event, entry->key,
entry->eventtime, entry->type,
entry->lastuptime);
} else {
snprintf(newline, MAXLINESIZE,
"%-8s%-22s%-20s%-16s\n",
entry->event, entry->key, entry->eventtime,
entry->type);
}
} else {
snprintf(newline, MAXLINESIZE, "%-8s%-22s%-20s%s\n",
entry->event, entry->key, entry->eventtime,
entry->lastuptime);
}
}
static void backup_history(void)
{
int ret;
char *des;
ret = asprintf(&des, "%s.bak", history_file);
if (ret < 0) {
LOGE("compute string failed, out of memory\n");
return;
}
ret = do_mv(history_file, des);
if (ret < 0) {
LOGE("backup %s failed, error (%s)\n", history_file,
strerror(errno));
goto free;
}
ret = prepare_history();
if (ret < 0) {
LOGE("Prepare new history_file failed, exit\n");
exit(EXIT_FAILURE);
}
free:
free(des);
}
void hist_raise_event(char *event, char *type, char *log, char *lastuptime,
char *key)
{
char line[MAXLINESIZE];
char eventtime[LONG_TIME_SIZE];
struct sender_t *crashlog;
int maxlines;
int ret;
struct history_entry entry = {
.event = event,
.type = type,
.log = log,
.lastuptime = lastuptime,
.key = key
};
/* here means user have configured the crashlog sender */
crashlog = get_sender_by_name("crashlog");
if (!crashlog)
return;
maxlines = atoi(crashlog->maxlines);
if (++current_lines >= maxlines) {
LOGW("lines of (%s) meet quota %d, backup... Pls clean!\n",
history_file, maxlines);
backup_history();
}
ret = get_current_time_long(eventtime);
if (ret <= 0)
return;
entry.eventtime = eventtime;
entry_to_history_line(&entry, line);
ret = append_file(history_file, line);
if (ret < 0) {
LOGE("append (%s) failed, error (%s)\n", history_file,
strerror(errno));
return;
}
}
void hist_raise_uptime(char *lastuptime)
{
char boot_time[UPTIME_SIZE];
char firstline[MAXLINESIZE];
int hours;
int ret;
char *key;
static int loop_uptime_event = 1;
struct sender_t *crashlog;
struct uptime_t *uptime;
static int uptime_hours;
/* user have configured the crashlog sender */
crashlog = get_sender_by_name("crashlog");
if (!crashlog)
return;
uptime = crashlog->uptime;
uptime_hours = atoi(uptime->eventhours);
if (lastuptime)
hist_raise_event(uptime->name, NULL, NULL, lastuptime,
"00000000000000000000");
else {
ret = get_uptime_string(boot_time, &hours);
if (ret < 0) {
LOGE("cannot get uptime - %s\n", strerror(-ret));
return;
}
sprintf(firstline, HISTORY_FIRST_LINE_FMT, boot_time);
replace_file_head(history_file, firstline);
if (hours / uptime_hours >= loop_uptime_event) {
loop_uptime_event = (hours / uptime_hours) + 1;
key = generate_event_id((const char *)uptime->name,
NULL, KEY_SHORT);
if (key == NULL) {
LOGE("generate event id failed, error (%s)\n",
strerror(errno));
return;
}
hist_raise_event(uptime->name, NULL, NULL,
boot_time, key);
free(key);
}
}
}
void hist_raise_infoerror(char *type)
{
char *key;
key = generate_event_id("ERROR", (const char *)type, KEY_SHORT);
if (key == NULL) {
LOGE("generate event id failed, error (%s)\n",
strerror(errno));
return;
}
hist_raise_event("ERROR", type, NULL, NULL, key);
free(key);
}
static int get_time_firstline(char *buffer)
{
char firstline[MAXLINESIZE];
int ret;
char *fmt = "%*[^ ]%*[ ]%*[^ ]%*[ ]%[^ ]%*c";
memset(firstline, 0, MAXLINESIZE);
ret = file_read_string(history_file, firstline, MAXLINESIZE);
if (ret <= 0) {
LOGW("file_read_string failed, %d %s\n", ret, strerror(-ret));
return -1;
}
if (!strstr(firstline, "#V1.0 "))
return -1;
ret = sscanf(firstline, fmt, buffer);
if (ret != 1) {
LOGE("get last time failed, %d %s\n", ret, firstline);
return -1;
}
return 0;
}
int prepare_history(void)
{
int ret;
struct sender_t *crashlog;
char linebuf[MAXLINESIZE] = {0};
crashlog = get_sender_by_name("crashlog");
if (!crashlog)
return 0;
if (!history_file) {
ret = asprintf(&history_file, "%s/%s", crashlog->outdir,
HISTORY_NAME);
if (ret < 0) {
LOGE("compute string failed, out of memory\n");
return -ENOMEM;
}
}
ret = get_time_firstline(linebuf);
if (ret == 0) {
current_lines = count_lines_in_file(history_file);
hist_raise_uptime(linebuf);
} else {
/* new history */
LOGW("new history\n");
sprintf(linebuf, HISTORY_FIRST_LINE_FMT, "0000:00:00");
ret = overwrite_file(history_file, linebuf);
if (ret < 0) {
LOGE("Write (%s, %s) failed, error (%s)\n",
history_file, linebuf,
strerror(errno));
return ret;
}
ret = append_file(history_file, HISTORY_BLANK_LINE2);
if (ret < 0) {
LOGE("Write (%s, %s) failed, error (%s)\n",
history_file, HISTORY_BLANK_LINE2,
strerror(errno));
return ret;
}
current_lines = count_lines_in_file(history_file);
}
return 0;
}