tools:acrn-crashlog: Improve the process of crash reclassify

1. Reload the trigger file(s) of subcrash while doing crash reclassify.
2. Support simple format for trigger file.

Signed-off-by: Liu, Xinwu <xinwu.liu@intel.com>
Acked-by: Chen Gang <gang.c.chen@intel.com>
This commit is contained in:
Liu, Xinwu
2018-07-03 10:08:14 +08:00
committed by Jack Ren
parent 0683b16573
commit a5853d6d8a
12 changed files with 571 additions and 369 deletions

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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, ...);

View File

@@ -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