diff --git a/tools/acrn-crashlog/acrnprobe/android_events.c b/tools/acrn-crashlog/acrnprobe/android_events.c
index c9665edb6..81e24067d 100644
--- a/tools/acrn-crashlog/acrnprobe/android_events.c
+++ b/tools/acrn-crashlog/acrnprobe/android_events.c
@@ -400,6 +400,7 @@ static void get_last_line_synced(const struct sender_t *sender)
int sid;
int ret;
struct vm_t *vm;
+ char *p;
char vmkey[ANDROID_WORD_LEN];
char vm_name[32];
@@ -438,6 +439,9 @@ static void get_last_line_synced(const struct sender_t *sender)
strerror(errno));
continue;
}
+ p = strchr(vmkey, ' ');
+ if (p)
+ *p = 0;
ret = refresh_key_synced_stage1(sender, vm, vmkey, MM_ONLY);
if (ret < 0) {
diff --git a/tools/acrn-crashlog/acrnprobe/crash_reclassify.c b/tools/acrn-crashlog/acrnprobe/crash_reclassify.c
index 1eabd4458..a966f2b4d 100644
--- a/tools/acrn-crashlog/acrnprobe/crash_reclassify.c
+++ b/tools/acrn-crashlog/acrnprobe/crash_reclassify.c
@@ -27,7 +27,7 @@
*
* @return 1 if find the same string, or 0 if not.
*/
-static int has_content(char *file, char *content)
+static int has_content(const char *file, const char *content)
{
if (content && strstr(file, content))
return 1;
@@ -44,12 +44,12 @@ static int has_content(char *file, char *content)
*
* @return 1 if all configured strings were found, or 0 if not.
*/
-static int crash_has_all_contents(struct crash_t *crash,
- char *file)
+static int crash_has_all_contents(const struct crash_t *crash,
+ const char *file)
{
int id;
int ret = 1;
- char *content;
+ const char *content;
for_each_content_crash(id, content, crash) {
if (!content)
@@ -78,14 +78,14 @@ static int crash_has_all_contents(struct crash_t *crash,
*
* @return 1 if result is true, or 0 if false.
*/
-static int crash_has_mightcontents(struct crash_t *crash,
- char *file)
+static int crash_has_mightcontents(const struct crash_t *crash,
+ const char *file)
{
int ret = 1;
int ret_exp;
int expid, cntid;
- char **exp;
- char *content;
+ char * const *exp;
+ const char *content;
for_each_expression_crash(expid, exp, crash) {
if (!exp || !exp_valid(exp))
@@ -119,13 +119,14 @@ static int crash_has_mightcontents(struct crash_t *crash,
*
* @return 1 if file matches these strings configured in crash, or 0 if not.
*/
-static int crash_reclassify(struct crash_t *crash, char *file)
+static int crash_match_content(const struct crash_t *crash, const char *file)
{
return crash_has_all_contents(crash, file) &&
crash_has_mightcontents(crash, file);
}
-static int _get_data(char *file, struct crash_t *crash, char **data, int index)
+static int _get_data(const char *file, const struct crash_t *crash,
+ char **data, const int index)
{
char *search_key;
char *value;
@@ -172,7 +173,7 @@ static int _get_data(char *file, struct crash_t *crash, char **data, int index)
*
* @return 0 if successful, or errno if not.
*/
-static int get_data(char *file, struct crash_t *crash,
+static int get_data(const char *file, const struct crash_t *crash,
char **data0, char **data1, char **data2)
{
int res;
@@ -201,6 +202,62 @@ fail:
return res;
}
+static struct crash_t *crash_find_matched_child(const struct crash_t *crash,
+ const char *rtrfmt)
+{
+ struct crash_t *child;
+ struct crash_t *matched_child = NULL;
+ int i;
+ int count;
+ int res;
+ const char *trfile_fmt;
+ char **trfiles;
+ void *content;
+ unsigned long size;
+
+ if (!crash)
+ return NULL;
+
+ for_crash_children(child, crash) {
+ if (!child->trigger)
+ continue;
+
+ if (!strcmp(child->trigger->type, "dir"))
+ trfile_fmt = rtrfmt;
+ else
+ trfile_fmt = child->trigger->path;
+
+ count = config_fmt_to_files(trfile_fmt, &trfiles);
+ if (count <= 0)
+ continue;
+
+ for (i = 0; i < count; i++) {
+ res = read_file(trfiles[i], &size, &content);
+ if (res == -1) {
+ LOGE("read %s failed, error (%s)\n",
+ trfiles[i], strerror(errno));
+ continue;
+ }
+ if (crash_match_content(child, content)) {
+ free(content);
+ matched_child = child;
+ break;
+ }
+ free(content);
+ }
+
+ for (i = 0; i < count; i++)
+ free(trfiles[i]);
+ free(trfiles);
+
+ if (matched_child)
+ break;
+ }
+
+ /* It returns the first matched crash */
+ return matched_child;
+}
+
/**
* Judge the crash type. We only got a root crash from channel, sometimes,
* we need to calculate a more specific type.
@@ -208,7 +265,7 @@ fail:
* This function couldn't use for binary file.
*
* @param rcrash Root crash obtained from channel.
- * @param trfile Path of trigger file.
+ * @param rtrfile_fmt Path fmt of trigger file of root crash.
* @param[out] data0 Searched result, according to 'data0' configuread in crash.
* @param[out] data1 Searched result, according to 'data1' configuread in crash.
* @param[out] data2 Searched result, according to 'data2' configuread in crash.
@@ -216,64 +273,64 @@ fail:
* @return a pointer to the calculated crash structure if successful,
* or NULL if not.
*/
-static struct crash_t *crash_reclassify_by_content(struct crash_t *rcrash,
- char *trfile, char **data0,
- char **data1, char **data2)
+static struct crash_t *crash_reclassify_by_content(const struct crash_t *rcrash,
+ const char *rtrfile_fmt, char **data0,
+ char **data1, char **data2)
{
- int depth;
- int level;
- int ret;
- struct crash_t *crash;
- struct crash_t *ret_crash = NULL;
- void *file;
+ int count;
+ const struct crash_t *crash;
+ const struct crash_t *ret_crash = rcrash;
+ const char *trfile_fmt;
+ char **trfiles;
+ void *content;
unsigned long size;
- int id;
+ int res;
+ int i;
if (!rcrash)
return NULL;
- if (trfile) {
- ret = read_file(trfile, &size, &file);
- if (ret == -1) {
- LOGE("read %s failed, error (%s)\n",
- trfile, strerror(errno));
- return NULL;
- }
- } else
- return rcrash;
+ crash = rcrash;
- /* traverse every crash from leaf, return the first crash we find
- * consider that we have few CRASH TYPE, so just using this simple
- * implementation.
- */
- depth = crash_depth(rcrash);
- for (level = depth; level >= 0; level--) {
- for_each_crash(id, crash, conf) {
- if (!crash ||
- crash->trigger != rcrash->trigger ||
- crash->channel != rcrash->channel ||
- crash->level != level)
- continue;
+ while (1) {
+ crash = crash_find_matched_child(crash, rtrfile_fmt);
+ if (!crash)
+ break;
- if (crash_reclassify(crash, file)) {
- ret = get_data(file, crash, data0, data1,
- data2);
- if (ret < 0) {
- LOGE("get data error, error (%s)\n",
- strerror(-ret));
- goto fail_data;
- } else {
- ret_crash = crash;
- goto fail_data;
- }
- }
- }
+ ret_crash = crash;
}
-fail_data:
- free(file);
+ if (!strcmp(ret_crash->trigger->type, "dir"))
+ trfile_fmt = rtrfile_fmt;
+ else
+ trfile_fmt = ret_crash->trigger->path;
- return ret_crash;
+ count = config_fmt_to_files(trfile_fmt, &trfiles);
+ if (count <= 0)
+ return (struct crash_t *)ret_crash;
+
+ /* get data from last file */
+ res = read_file(trfiles[count - 1], &size, &content);
+ if (res == -1) {
+ LOGE("read %s failed, error (%s)\n",
+ trfiles[count - 1], strerror(errno));
+ goto free_files;
+ }
+
+ res = get_data(content, ret_crash, data0, data1, data2);
+ if (res < 0) {
+ LOGE("get data error, error (%s)\n",
+ strerror(res));
+ }
+
+ free(content);
+
+free_files:
+ for (i = 0; i < count; i++)
+ free(trfiles[i]);
+ free(trfiles);
+
+ return (struct crash_t *)ret_crash;
}
/**
@@ -286,7 +343,7 @@ void init_crash_reclassify(void)
struct crash_t *crash;
for_each_crash(id, crash, conf) {
- if (!crash || !is_root_crash(crash))
+ if (!crash)
continue;
crash->reclassify = crash_reclassify_by_content;
diff --git a/tools/acrn-crashlog/acrnprobe/history.c b/tools/acrn-crashlog/acrnprobe/history.c
index 24cae832d..f0e099f6c 100644
--- a/tools/acrn-crashlog/acrnprobe/history.c
+++ b/tools/acrn-crashlog/acrnprobe/history.c
@@ -118,7 +118,7 @@ void hist_raise_event(char *event, char *type, char *log, char *lastuptime,
char *key)
{
char line[MAXLINESIZE];
- char eventtime[32];
+ char eventtime[LONG_TIME_SIZE];
struct sender_t *crashlog;
int maxlines;
int ret;
@@ -158,7 +158,7 @@ void hist_raise_event(char *event, char *type, char *log, char *lastuptime,
void hist_raise_uptime(char *lastuptime)
{
- char boot_time[24];
+ char boot_time[UPTIME_SIZE];
char firstline[MAXLINESIZE];
int hours;
int ret;
diff --git a/tools/acrn-crashlog/acrnprobe/include/load_conf.h b/tools/acrn-crashlog/acrnprobe/include/load_conf.h
index 3bcd536bd..b1d28f3e5 100644
--- a/tools/acrn-crashlog/acrnprobe/include/load_conf.h
+++ b/tools/acrn-crashlog/acrnprobe/include/load_conf.h
@@ -65,8 +65,8 @@ struct crash_t {
int wd;
int level;
- struct crash_t *(*reclassify)(struct crash_t *, char*, char**, char**,
- char**);
+ struct crash_t *(*reclassify)(const struct crash_t *, const char*,
+ char**, char**, char**);
};
struct info_t {
diff --git a/tools/acrn-crashlog/acrnprobe/include/probeutils.h b/tools/acrn-crashlog/acrnprobe/include/probeutils.h
index a711a645b..1ee423757 100644
--- a/tools/acrn-crashlog/acrnprobe/include/probeutils.h
+++ b/tools/acrn-crashlog/acrnprobe/include/probeutils.h
@@ -22,6 +22,9 @@
#ifndef __PROBEUTILS_H__
#define __PROBEUTILS_H__
+#define UPTIME_SIZE 24
+#define LONG_TIME_SIZE 32
+
enum e_dir_mode {
MODE_CRASH = 0,
MODE_STATS,
diff --git a/tools/acrn-crashlog/acrnprobe/probeutils.c b/tools/acrn-crashlog/acrnprobe/probeutils.c
index 1564581dd..41dccc742 100644
--- a/tools/acrn-crashlog/acrnprobe/probeutils.c
+++ b/tools/acrn-crashlog/acrnprobe/probeutils.c
@@ -50,7 +50,7 @@ unsigned long long get_uptime(void)
return time_ns;
}
-int get_uptime_string(char newuptime[24], int *hours)
+int get_uptime_string(char *newuptime, int *hours)
{
long long tm;
int seconds, minutes;
@@ -68,11 +68,11 @@ int get_uptime_string(char newuptime[24], int *hours)
/* hours */
*hours /= 60;
- return snprintf(newuptime, 24, "%04d:%02d:%02d", *hours,
+ return snprintf(newuptime, UPTIME_SIZE, "%04d:%02d:%02d", *hours,
minutes, seconds);
}
-int get_current_time_long(char buf[32])
+int get_current_time_long(char *buf)
{
time_t t;
struct tm *time_val;
@@ -82,7 +82,7 @@ int get_current_time_long(char buf[32])
if (!time_val)
return -1;
- return strftime(buf, 32, "%Y-%m-%d/%H:%M:%S ", time_val);
+ return strftime(buf, LONG_TIME_SIZE, "%Y-%m-%d/%H:%M:%S ", time_val);
}
/**
@@ -348,16 +348,18 @@ void generate_crashfile(char *dir, char *event, char *hashkey,
{
char *buf;
char *path;
- char datetime[32];
- char uptime[32];
+ char datetime[LONG_TIME_SIZE];
+ char uptime[UPTIME_SIZE];
int hours;
int ret;
const int fmtsize = 128;
int filesize;
+ datetime[0] = 0;
ret = get_current_time_long(datetime);
if (ret <= 0)
return;
+ uptime[0] = 0;
get_uptime_string(uptime, &hours);
filesize = fmtsize + strlen(event) +
diff --git a/tools/acrn-crashlog/acrnprobe/sender.c b/tools/acrn-crashlog/acrnprobe/sender.c
index 6a61c3443..c18a4f7d2 100644
--- a/tools/acrn-crashlog/acrnprobe/sender.c
+++ b/tools/acrn-crashlog/acrnprobe/sender.c
@@ -38,57 +38,62 @@ struct telemd_data_t {
};
#endif
-/* get_log_file_* only used to copy regular file which can be mmaped */
-static void get_log_file_complete(struct log_t *log, char *desdir)
+static int cal_log_filepath(char **out, const struct log_t *log,
+ const char *srcname, const char *desdir)
{
- char *des;
- char *name;
- int ret;
+ const char *filename;
+ int need_timestamp = 0;
+ int hours;
+ char timebuf[UPTIME_SIZE];
- name = log->name;
+ if (!out || !log || !desdir)
+ return -1;
- ret = asprintf(&des, "%s/%s", desdir, name);
- if (ret < 0) {
- LOGE("compute string failed, out of memory\n");
- return;
+ if (is_ac_filefmt(log->path))
+ filename = srcname;
+ else
+ filename = log->name;
+
+ if (!filename)
+ return -1;
+
+ if (!strcmp(log->type, "cmd") || log->lines)
+ need_timestamp = 1;
+
+ if (need_timestamp) {
+ timebuf[0] = 0;
+ get_uptime_string(timebuf, &hours);
+ return asprintf(out, "%s/%s_%s", desdir, filename, timebuf);
}
- ret = do_copy_tail(log->path, des, 0);
- if (ret < 0) {
- LOGE("copy (%s) failed\n, error (%s)\n", log->path,
- strerror(errno));
- }
-
- free(des);
+ return asprintf(out, "%s/%s", desdir, filename);
}
-static void get_log_file_tail(struct log_t *log, char *desdir)
+/* get_log_file_* only used to copy regular file which can be mmaped */
+static void get_log_file_complete(const char *despath, const char *srcpath)
+{
+ const int ret = do_copy_tail(srcpath, despath, 0);
+
+ if (ret < 0) {
+ LOGE("copy (%s) failed, error (%s)\n", srcpath,
+ strerror(errno));
+ }
+}
+
+static void get_log_file_tail(const char *despath, const char *srcpath,
+ const int lines)
{
- char *des;
- char timebuf[24];
- char *name;
char *start;
- int lines;
- int hours;
int start_line;
int file_lines;
struct mm_file_t *mfile;
int ret;
- lines = atoi(log->lines);
- name = log->name;
- get_uptime_string(timebuf, &hours);
- ret = asprintf(&des, "%s/%s_%s", desdir, name, timebuf);
- if (ret < 0) {
- LOGE("compute string failed, out of memory\n");
- return;
- }
-
- mfile = mmap_file(log->path);
+ mfile = mmap_file(srcpath);
if (!mfile) {
- LOGE("mmap (%s) failed, error (%s)\n", log->path,
+ LOGE("mmap (%s) failed, error (%s)\n", srcpath,
strerror(errno));
- goto free;
+ return;
}
file_lines = mm_count_lines(mfile);
if (file_lines <= 0) {
@@ -97,184 +102,65 @@ static void get_log_file_tail(struct log_t *log, char *desdir)
}
start_line = MAX(file_lines - lines, 0) + 1;
start = mm_get_line(mfile, start_line);
- ret = overwrite_file(des, start);
+ ret = overwrite_file(despath, start);
if (ret < 0) {
LOGE("create file with (%s, %p) failed, error (%s)\n",
- des, start, strerror(errno));
+ despath, start, strerror(errno));
goto unmap;
}
unmap:
unmap_file(mfile);
-free:
- free(des);
}
-static void get_log_file(struct log_t *log, char *desdir)
+static void get_log_file(const char *despath, const char *srcpath,
+ const char *tail_lines)
{
int lines;
- if (log->lines == NULL) {
- get_log_file_complete(log, desdir);
+ if (!tail_lines) {
+ get_log_file_complete(despath, srcpath);
return;
}
- lines = atoi(log->lines);
+ lines = atoi(tail_lines);
if (lines > 0)
- get_log_file_tail(log, desdir);
+ get_log_file_tail(despath, srcpath, lines);
else
- get_log_file_complete(log, desdir);
+ get_log_file_complete(despath, srcpath);
}
-static void get_log_rotation(struct log_t *log, char *desdir)
+static void get_log_node(const char *despath, const char *nodepath)
{
- char *suffix;
- char *prefix;
- char *dir;
- char *p;
- int count;
- char *files[512];
- int number;
- int target_num = -1;
- char *target_file = NULL;
- char *name;
- int i;
+ const int res = do_copy_eof(nodepath, despath);
- dir = strdup(log->path);
- if (!dir) {
- LOGE("compute string failed, out of memory\n");
- return;
- }
-
- /* dir prefix suffix
- * | | |
- * /tmp/hvlog/hvlog_cur.[biggest]
- */
- p = strrchr(dir, '/');
- if (p == NULL) {
- LOGE("invalid path (%s) in log (%s), ", dir, log->name);
- LOGE("file_rotation only support absolute path\n");
- goto free_dir;
- } else {
- prefix = p + 1;
- *p = 0;
- }
-
- p = strstr(prefix, ".[");
- if (p == NULL) {
- LOGE("invalid path (%s) in log (%s)\n", log->path, log->name);
- goto free_dir;
- } else {
- suffix = p + 2;
- *p = 0;
- }
-
- p = suffix + strlen(suffix) - 1;
- if (*p == ']') {
- *p = 0;
- } else {
- LOGE("invalid path (%s) in log (%s)\n", log->path, log->name);
- goto free_dir;
- }
-
-
- struct log_t toget;
-
- memcpy(&toget, log, sizeof(toget));
- count = lsdir(dir, files, ARRAY_SIZE(files));
- if (count > 2) {
- for (i = 0; i < count; i++) {
- name = strrchr(files[i], '/') + 1;
- if (!name && !strstr(name, prefix))
- continue;
-
- number = atoi(strrchr(name, '.') + 1);
- if (!strncmp(suffix, "biggest", 7)) {
- if (target_num == -1 ||
- number > target_num){
- target_file = files[i];
- target_num = number;
- }
- } else if (!strncmp(suffix, "smallest", 8)) {
- if (target_num == -1 ||
- number < target_num) {
- target_file = files[i];
- target_num = number;
- }
- } else if (!strncmp(suffix, "all", 3)) {
- toget.path = files[i];
- toget.name = name;
- get_log_file(&toget, desdir);
- }
- }
- } else if (count < 0) {
- LOGE("lsdir (%s) failed, error (%s)\n", dir,
- strerror(-count));
- goto free;
- }
-
- if (!strncmp(suffix, "all", 3))
- goto free;
-
- if (target_file) {
- toget.path = target_file;
- get_log_file(&toget, desdir);
- } else {
- LOGW("no logs found for (%s)\n", log->name);
- goto free;
- }
-
-free:
- while (count > 0)
- free(files[--count]);
-free_dir:
- free(dir);
-}
-
-static void get_log_node(struct log_t *log, char *desdir)
-{
- char *des;
- char *name;
- int ret;
-
- name = log->name;
- ret = asprintf(&des, "%s/%s", desdir, name);
- if (ret < 0) {
- LOGE("compute string failed, out of memory\n");
- return;
- }
-
- ret = do_copy_eof(log->path, des);
- if (ret < 0) {
- LOGE("copy (%s) failed, error (%s)\n", log->path,
+ if (res < 0) {
+ LOGE("copy (%s) failed, error (%s)\n", nodepath,
strerror(errno));
- goto free;
}
-
-free:
- free(des);
}
-static void out_via_fork(struct log_t *log, char *desdir)
+static void get_log_cmd(const char *despath, const char *cmd)
{
- char *des;
- int ret;
+ const int res = exec_out2file(despath, cmd);
- ret = asprintf(&des, "%s/%s", desdir, log->name);
- if (ret < 0) {
- LOGE("compute string failed, out of memory\n");
+ if (res)
+ LOGE("get_log_by_cmd exec %s returns (%d)\n", cmd, res);
+}
+
+static void get_log_by_type(const char *despath, const struct log_t *log,
+ const char *srcpath)
+{
+ if (!despath || !log || !srcpath)
return;
- }
- exec_out2file(des, log->path);
- free(des);
+ if (!strcmp("file", log->type))
+ get_log_file(despath, srcpath, log->lines);
+ else if (!strcmp("node", log->type))
+ get_log_node(despath, log->path);
+ else if (!strcmp("cmd", log->type))
+ get_log_cmd(despath, log->path);
}
-
-static void get_log_cmd(struct log_t *log, char *desdir)
-{
- out_via_fork(log, desdir);
-}
-
#ifdef HAVE_TELEMETRICS_CLIENT
static int telemd_send_data(char *payload, char *eventid, uint32_t severity,
char *class)
@@ -322,70 +208,47 @@ fail:
static void telemd_get_log(struct log_t *log, void *data)
{
- struct telemd_data_t *d = (struct telemd_data_t *)data;
- char name[NAME_MAX];
- char *path, *msg;
- int ret;
+ const struct telemd_data_t *d = (struct telemd_data_t *)data;
+ char fpath[PATH_MAX];
+ char *msg;
+ int count;
+ int res;
+ int i;
+ struct dirent **filelist;
if (d->srcdir == NULL)
goto send_nologs;
- ret = dir_contains(d->srcdir, log->name, 0, name);
- if (ret == 1) {
- ret = asprintf(&path, "%s/%s", d->srcdir, name);
- if (ret < 0) {
- LOGE("compute string failed, out of memory\n");
- return;
- }
- telemd_send_data(path, d->eventid, d->severity, d->class);
- free(path);
- } else if (ret == 0) {
+ /* search file which use log->name as substring */
+ count = ac_scandir(d->srcdir, &filelist, filter_filename_substr,
+ log->name, NULL);
+ if (count < 0) {
+ LOGE("search (%s) in dir (%s) failed, error (%s)\n", log->name,
+ d->srcdir, strerror(count));
+ return;
+ }
+ if (!count) {
LOGE("dir (%s) does not contains (%s)\n", d->srcdir,
log->name);
goto send_nologs;
- } else if (ret > 1) {
- /* got multiple files */
- int i;
- int count;
- char *name;
- char *files[512];
-
- if (!strstr(log->path, ".[all]")) {
- LOGE("dir (%s) contains (%d) files (%s)\n",
- d->srcdir, ret, log->name);
- goto send_nologs;
- }
-
- count = lsdir(d->srcdir, files, ARRAY_SIZE(files));
- if (count > 2) {
- for (i = 0; i < count; i++) {
- name = strrchr(files[i], '/') + 1;
- if (!strstr(name, log->name))
- continue;
-
- telemd_send_data(files[i], d->eventid,
- d->severity, d->class);
- }
- } else if (count < 0) {
- LOGE("lsdir (%s) failed, error (%s)\n", d->srcdir,
- strerror(-count));
- goto send_nologs;
- }
-
- while (count > 0)
- free(files[--count]);
- } else {
- LOGE("search (%s) in dir (%s) failed, error (%s)\n", log->name,
- d->srcdir, strerror(-ret));
- goto send_nologs;
}
+ for (i = 0; i < count; i++) {
+ snprintf(fpath, sizeof(fpath), "%s/%s", d->srcdir,
+ filelist[i]->d_name);
+ free(filelist[i]);
+ telemd_send_data(fpath, d->eventid,
+ d->severity, d->class);
+ }
+
+ free(filelist);
+
return;
send_nologs:
- ret = asprintf(&msg, "no log generated on %s, check probe's log.",
+ res = asprintf(&msg, "no log generated on %s, check probe's log.",
log->name);
- if (ret < 0) {
+ if (res < 0) {
LOGE("compute string failed, out of memory\n");
return;
}
@@ -402,6 +265,8 @@ static void crashlog_get_log(struct log_t *log, void *data)
unsigned long long start, end;
int spent;
int quota;
+ int res;
+ char *des;
char *desdir = (char *)data;
crashlog = get_sender_by_name("crashlog");
@@ -415,14 +280,53 @@ static void crashlog_get_log(struct log_t *log, void *data)
}
start = get_uptime();
- if (!strcmp("file", log->type))
- get_log_file(log, desdir);
- else if (!strcmp("node", log->type))
- get_log_node(log, desdir);
- else if (!strcmp("cmd", log->type))
- get_log_cmd(log, desdir);
- else if (!strcmp("file_rotation", log->type))
- get_log_rotation(log, desdir);
+ if (is_ac_filefmt(log->path)) {
+ int i;
+ char **files;
+ char *name;
+
+ const int count = config_fmt_to_files(log->path, &files);
+
+ if (count < 0) {
+ LOGE("parse config format (%s) failed, error (%s)\n",
+ log->path, strerror(count));
+ return;
+ }
+ if (!count) {
+ LOGW("no logs found for (%s)\n", log->name);
+ return;
+ }
+
+ for (i = 0; i < count; i++) {
+ name = strrchr(files[i], '/') + 1;
+ if (name == (char *)1) {
+ LOGE("invalid path (%s) in log (%s)", files[i],
+ log->name);
+ continue;
+ }
+ res = cal_log_filepath(&des, log, name, desdir);
+ if (res == -1) {
+ LOGE("cal_log_filepath failed, error (%s)\n",
+ strerror(errno));
+ continue;
+ }
+ get_log_by_type(des, log, files[i]);
+ free(des);
+ }
+
+ for (i = 0; i < count; i++)
+ free(files[i]);
+ free(files);
+ } else {
+ res = cal_log_filepath(&des, log, log->name, desdir);
+ if (res == -1) {
+ LOGE("cal_log_filepath failed, error (%s)\n",
+ strerror(errno));
+ return;
+ }
+ get_log_by_type(des, log, log->path);
+ free(des);
+ }
end = get_uptime();
spent = (int)((end - start) / 1000000000LL);
@@ -560,7 +464,7 @@ static void telemd_send_uptime(void)
struct sender_t *telemd;
struct uptime_t *uptime;
char *class;
- char boot_time[24];
+ char boot_time[UPTIME_SIZE];
int hours;
int ret;
static int uptime_hours;
@@ -812,22 +716,21 @@ static void crashlog_send_crash(struct event_t *e)
struct sender_t *crashlog;
char *key = NULL;
char *trfile = NULL;
- char *data0;
- char *data1;
- char *data2;
+ char *data0 = NULL;
+ char *data1 = NULL;
+ char *data2 = NULL;
int id;
int ret = 0;
int quota;
struct crash_t *rcrash = (struct crash_t *)e->private;
- if (!strcmp(rcrash->trigger->type, "file"))
- ret = asprintf(&trfile, "%s", rcrash->trigger->path);
- else if (!strcmp(rcrash->trigger->type, "dir"))
+ if (!strcmp(rcrash->trigger->type, "dir")) {
ret = asprintf(&trfile, "%s/%s", rcrash->trigger->path,
e->path);
- if (ret < 0) {
- LOGE("compute string failed, out of memory\n");
- return;
+ if (ret < 0) {
+ LOGE("compute string failed, out of memory\n");
+ return;
+ }
}
crash = rcrash->reclassify(rcrash, trfile, &data0, &data1, &data2);
diff --git a/tools/acrn-crashlog/common/cmdutils.c b/tools/acrn-crashlog/common/cmdutils.c
index 55fd4614d..d2b62480f 100644
--- a/tools/acrn-crashlog/common/cmdutils.c
+++ b/tools/acrn-crashlog/common/cmdutils.c
@@ -35,7 +35,7 @@
* If all system calls succeed, then the return value is the
* termination status of the child process used to execute command.
*/
-int execv_out2file(char *argv[], char *outfile)
+int execv_out2file(char * const argv[], const char *outfile)
{
pid_t pid;
@@ -103,13 +103,13 @@ int execv_out2file(char *argv[], char *outfile)
return -1;
}
-int debugfs_cmd(char *loop_dev, char *cmd, char *outfile)
+int debugfs_cmd(const char *loop_dev, const char *cmd, const char *outfile)
{
- char *argv[5] = {"debugfs", "-R", NULL, NULL, 0};
+ const char *argv[5] = {"debugfs", "-R", NULL, NULL, 0};
argv[2] = cmd;
argv[3] = loop_dev;
- return execv_out2file(argv, outfile);
+ return execv_out2file((char * const *)argv, outfile);
}
/**
@@ -128,7 +128,7 @@ int debugfs_cmd(char *loop_dev, char *cmd, char *outfile)
* If all system calls succeed, then the return value is the
* termination status of the child process used to execute command.
*/
-int exec_out2file(char *outfile, char *fmt, ...)
+int exec_out2file(const char *outfile, const char *fmt, ...)
{
va_list args;
char *cmd;
@@ -184,7 +184,7 @@ int exec_out2file(char *outfile, char *fmt, ...)
*
* @return a pointer to command's output if successful, or NULL if not.
*/
-char *exec_out2mem(char *fmt, ...)
+char *exec_out2mem(const char *fmt, ...)
{
va_list args;
char *cmd;
diff --git a/tools/acrn-crashlog/common/fsutils.c b/tools/acrn-crashlog/common/fsutils.c
index ccfda9764..63597b586 100644
--- a/tools/acrn-crashlog/common/fsutils.c
+++ b/tools/acrn-crashlog/common/fsutils.c
@@ -300,7 +300,7 @@ void unmap_file(struct mm_file_t *mfile)
* @return The number of bytes written to new file if successful,
* or a negative errno-style value if not.
*/
-int do_copy_tail(char *src, char *dest, int limit)
+int do_copy_tail(const char *src, const char *dest, int limit)
{
int rc = 0;
int fsrc = -1, fdest = -1;
@@ -916,41 +916,130 @@ int file_read_key_value_r(const char *path, const char *key,
return _file_read_key_value(path, 'r', key, limit, value);
}
-int dir_contains(const char *dir, const char *filename, int exact,
- char *fullname)
+/**
+ * Because scandir's filter can't receive caller's parameter, so
+ * rewrite an ac_scandir to satisfy our usage. This function is
+ * very like scandir, except it has an additional parameter farg for
+ * filter.
+ *
+ * @param dirp Dir to scan.
+ * @param namelist Andress to receive result array of struct dirent.
+ * @param filter Function pointer to filter. See also scandir.
+ * @param farg The second arg of filter.
+ * @param compar See scandir.
+ *
+ * @return the count of scanned files if successful, or a negative
+ * errno-style value if not.
+ */
+int ac_scandir(const char *dirp, struct dirent ***namelist,
+ int (*filter)(const struct dirent *, const void *),
+ const void *farg,
+ int (*compar)(const struct dirent **,
+ const struct dirent **))
{
- int ret, count = 0;
+ int i;
+ int count = 0;
+ int index = 0;
+ struct dirent **_filelist;
+
+ if (!dirp || !namelist)
+ return -EINVAL;
+
+ const int res = scandir(dirp, &_filelist, NULL, compar);
+
+ if (!filter) {
+ *namelist = _filelist;
+ return res;
+ }
+ if (res == -1)
+ return -errno;
+
+ /* overwrite filter */
+ /* calculate the matched files, free unneeded files and mark them */
+ for (i = 0; i < res; i++) {
+ if (!filter(_filelist[i], farg)) {
+ count++;
+ } else {
+ free(_filelist[i]);
+ _filelist[i] = 0;
+ }
+ }
+
+ /* no matched result */
+ if (!count) {
+ free(_filelist);
+ return 0;
+ }
+
+ /* construct the out array */
+ *namelist = malloc(count * sizeof(struct dirent *));
+ if (!(*namelist))
+ goto e_free;
+
+ for (i = 0; i < res; i++) {
+ if (_filelist[i])
+ (*namelist)[index++] = _filelist[i];
+ }
+
+ free(_filelist);
+
+ return count;
+
+e_free:
+ for (i = 0; i < res; i++)
+ if (_filelist[i])
+ free(_filelist[i]);
+ free(_filelist);
+ return -errno;
+}
+
+/* filters return zero if the match is successful */
+int filter_filename_substr(const struct dirent *entry, const void *arg)
+{
+ const char *substr = (const char *)arg;
+
+ return !strstr(entry->d_name, substr);
+}
+
+int filter_filename_exactly(const struct dirent *entry, const void *arg)
+{
+ const char *fname = (const char *)arg;
+
+ return strcmp(entry->d_name, fname);
+}
+
+int filter_filename_startswith(const struct dirent *entry,
+ const void *arg)
+{
+ const char *str = (const char *)arg;
+
+ return memcmp(entry->d_name, str, strlen(str));
+}
+
+int dir_contains(const char *dir, const char *filename, const int exact)
+{
+ int ret;
+ int i;
struct dirent **filelist;
- char *name;
if (!dir || !filename)
return -EINVAL;
- /* pass parameters to scandir's filter is not convenience, so we use
- * this implementation.
- */
- ret = scandir(dir, &filelist, 0, 0);
- if (ret < 0)
- return -errno;
+ if (exact)
+ ret = ac_scandir(dir, &filelist, filter_filename_exactly,
+ (const void *)filename, 0);
+ else
+ ret = ac_scandir(dir, &filelist, filter_filename_substr,
+ (const void *)filename, 0);
+ if (ret <= 0)
+ return ret;
- while (ret--) {
- name = filelist[ret]->d_name;
- if (exact) {
- if (!strcmp(name, filename))
- count++;
- } else {
- if (strstr(name, filename)) {
- count++;
- if (fullname)
- strcpy(fullname, name);
- }
- }
- free(filelist[ret]);
- }
+ for (i = 0; i < ret; i++)
+ free(filelist[i]);
free(filelist);
- return count;
+ return ret;
}
int lsdir(const char *dir, char *fullname[], int limit)
@@ -1087,7 +1176,7 @@ int find_file(char *dir, char *target_file, int depth, char *path[], int limit)
if (count >= limit)
goto free;
- ret = dir_contains(_dirs[i], target_file, 1, NULL);
+ ret = dir_contains(_dirs[i], target_file, 1);
if (ret == 1) {
ret = asprintf(&path[count++], "%s/%s",
_dirs[i], target_file);
@@ -1096,9 +1185,6 @@ int find_file(char *dir, char *target_file, int depth, char *path[], int limit)
ret = -ENOMEM;
goto fail;
}
- } else if (ret > 1) {
- LOGE("found (%d) (%s) under (%s)??\n",
- ret, target_file, dir);
} else if (ret < 0) {
LOGE("dir_contains failed, error (%s)\n",
strerror(-ret));
@@ -1171,3 +1257,140 @@ free:
close(fd);
return -1;
}
+
+int is_ac_filefmt(const char *file_fmt)
+{
+ /* Supported formats:
+ * - /dir/.../file[*] --> all files with prefix "file."
+ * - /dir/.../file[0] --> file with smallest subfix num.
+ * - /dir/.../file[-1] --> file with biggest subfix num.
+ */
+ if (!file_fmt)
+ return 0;
+
+ return (strstr(file_fmt, "[*]") ||
+ strstr(file_fmt, "[0]") ||
+ strstr(file_fmt, "[-1]"));
+}
+
+/**
+ * The config file of acrnprobe could use some format to indicate a file/files.
+ * This function is used to parse the format and returns found files paths.
+ *
+ * @param file_fmt A string pointer of a file format.
+ * @param out Files were found.
+ *
+ * @return the count of searched files if successful, or a negative
+ * errno-style value if not.
+ */
+int config_fmt_to_files(const char *file_fmt, char ***out)
+{
+ char type[3];
+ char *dir;
+ char *p;
+ char *subfix;
+ char *file_prefix;
+ int i;
+ int count;
+ int res;
+ int ret = 0;
+ struct dirent **filelist;
+ char **out_array;
+
+ if (!file_fmt || !out)
+ return -EINVAL;
+
+ dir = strdup(file_fmt);
+ if (!dir)
+ return -ENOMEM;
+
+ if (!is_ac_filefmt(file_fmt)) {
+ /* It's an regular file as default */
+ out_array = malloc(sizeof(char *));
+ if (!out_array) {
+ ret = -errno;
+ goto free_dir;
+ }
+
+ out_array[0] = dir;
+ *out = out_array;
+ return 1;
+ }
+
+ /* get dir and file prefix from format */
+ p = strrchr(dir, '/');
+ if (!p) {
+ ret = -EINVAL;
+ goto free_dir;
+ }
+ *p = '\0';
+ file_prefix = p + 1;
+ *strrchr(file_prefix, '[') = '\0';
+
+ if (!directory_exists(dir)) {
+ ret = 0;
+ goto free_dir;
+ }
+ /* get format type */
+ subfix = strrchr(file_fmt, '[');
+ res = sscanf(subfix, "[%2[01-*]]", type);
+ if (res != 1) {
+ ret = -EINVAL;
+ goto free_dir;
+ }
+
+ /* get all files which start with prefix */
+ count = ac_scandir(dir, &filelist, filter_filename_startswith,
+ file_prefix, alphasort);
+ if (count <= 0) {
+ ret = count;
+ goto free_dir;
+ }
+
+ /* construct output */
+ out_array = (char **)malloc(count * sizeof(char *));
+ if (!out_array) {
+ ret = -errno;
+ goto free_filelist;
+ }
+
+ if (!strcmp(type, "*")) {
+ for (i = 0; i < count; i++) {
+ res = asprintf(&out_array[i], "%s/%s", dir,
+ filelist[i]->d_name);
+ if (res == -1) {
+ /* free from 0 to i -1 */
+ while (i)
+ free(out_array[--i]);
+ break;
+ }
+ }
+ ret = count;
+ } else if (!strcmp(type, "0")) {
+ res = asprintf(&out_array[0], "%s/%s", dir,
+ filelist[0]->d_name);
+ ret = 1;
+ } else if (!strcmp(type, "-1")) {
+ res = asprintf(&out_array[0], "%s/%s", dir,
+ filelist[count - 1]->d_name);
+ ret = 1;
+ }
+
+ /* error happends while constructing output */
+ if (res == -1) {
+ ret = -errno;
+ free(out_array);
+ goto free_filelist;
+ }
+
+ *out = out_array;
+
+free_filelist:
+ for (i = 0; i < count; i++)
+ free(filelist[i]);
+ free(filelist);
+free_dir:
+ free(dir);
+
+ return ret;
+}
diff --git a/tools/acrn-crashlog/common/include/cmdutils.h b/tools/acrn-crashlog/common/include/cmdutils.h
index 498f1eb29..682568cb5 100644
--- a/tools/acrn-crashlog/common/include/cmdutils.h
+++ b/tools/acrn-crashlog/common/include/cmdutils.h
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-int execv_out2file(char *argv[], char *outfile);
-int debugfs_cmd(char *loop_dev, char *cmd, char *outfile);
-int exec_out2file(char *outfile, char *fmt, ...);
-char *exec_out2mem(char *fmt, ...);
+int execv_out2file(char * const argv[], const char *outfile);
+int debugfs_cmd(const char *loop_dev, const char *cmd, const char *outfile);
+int exec_out2file(const char *outfile, const char *fmt, ...);
+char *exec_out2mem(const char *fmt, ...);
diff --git a/tools/acrn-crashlog/common/include/fsutils.h b/tools/acrn-crashlog/common/include/fsutils.h
index a3305dd00..77047c183 100644
--- a/tools/acrn-crashlog/common/include/fsutils.h
+++ b/tools/acrn-crashlog/common/include/fsutils.h
@@ -75,7 +75,7 @@ int mkdir_p(char *path);
int mm_count_lines(struct mm_file_t *mfile);
struct mm_file_t *mmap_file(const char *path);
void unmap_file(struct mm_file_t *mfile);
-int do_copy_tail(char *src, char *dest, int limit);
+int do_copy_tail(const char *src, const char *dest, int limit);
int do_mv(char *src, char *dest);
int append_file(char *filename, char *text);
int mm_replace_str_line(struct mm_file_t *mfile, char *replace,
@@ -97,10 +97,20 @@ int file_read_key_value(const char *path, const char *key,
const size_t limit, char *value);
int file_read_key_value_r(const char *path, const char *key,
const size_t limit, char *value);
-int dir_contains(const char *dir, const char *filename, int exact,
- char *fullname);
+int ac_scandir(const char *dirp, struct dirent ***namelist,
+ int (*filter)(const struct dirent *, const void *),
+ const void *farg,
+ int (*compar)(const struct dirent **,
+ const struct dirent **));
+int filter_filename_substr(const struct dirent *entry, const void *arg);
+int filter_filename_exactly(const struct dirent *entry, const void *arg);
+int filter_filename_startswith(const struct dirent *entry,
+ const void *arg);
+int dir_contains(const char *dir, const char *filename, int exact);
int lsdir(const char *dir, char *fullname[], int limit);
int find_file(char *dir, char *target_file, int depth, char *path[], int limit);
int read_file(const char *path, unsigned long *size, void **data);
+int is_ac_filefmt(const char *file_fmt);
+int config_fmt_to_files(const char *file_fmt, char ***out);
#endif
diff --git a/tools/acrn-crashlog/data/acrnprobe.xml b/tools/acrn-crashlog/data/acrnprobe.xml
index 78fc5ce1b..a2e51c02b 100644
--- a/tools/acrn-crashlog/data/acrnprobe.xml
+++ b/tools/acrn-crashlog/data/acrnprobe.xml
@@ -77,14 +77,14 @@
acrnlog_cur
- file_rotation
- /tmp/acrnlog/acrnlog_cur.[biggest]
+ file
+ /tmp/acrnlog/acrnlog_cur.[-1]
500
acrnlog_last
- file_rotation
- /tmp/acrnlog/acrnlog_last.[all]
+ file
+ /tmp/acrnlog/acrnlog_last.[*]