mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-22 05:30:24 +00:00
tools: acrn-crashlog: command utils for acrn-crashlog
This file provides functions to call system commands. Signed-off-by: Liu Xinwu <xinwu.liu@intel.com> Reviewed-by: Zhang Yanmin <yanmin.zhang@intel.com> Reviewed-by: Liu Chuansheng <chuansheng.liu@intel.com> Reviewed-by: Zhao Yakui <yakui.zhao@intel.com> Reviewed-by: Geoffroy Van Cutsem <geoffroy.vancutsem@intel.com> Acked-by: Eddie Dong <Eddie.dong@intel.com>
This commit is contained in:
parent
780fefcc20
commit
88ba420af1
@ -1,5 +1,6 @@
|
||||
objects = log_sys.o \
|
||||
strutils.o
|
||||
strutils.o \
|
||||
cmdutils.o
|
||||
|
||||
all: check_obj $(objects)
|
||||
check_obj:
|
||||
|
232
tools/acrn-crashlog/common/cmdutils.c
Normal file
232
tools/acrn-crashlog/common/cmdutils.c
Normal file
@ -0,0 +1,232 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <malloc.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/wait.h>
|
||||
#include "cmdutils.h"
|
||||
#include "strutils.h"
|
||||
#include "log_sys.h"
|
||||
|
||||
/**
|
||||
* Execute a command described in an array of pointers to null-terminated
|
||||
* strings, and redirect the output to specified file. The file will be
|
||||
* created/truncated if it exists/non-exists. This function will be blocked
|
||||
* until the child process exits.
|
||||
*
|
||||
* @param argv An array of pointers to null-terminated strings that
|
||||
* represent the argument list available to the new program.
|
||||
* The array of pointers must be terminated by a null pointer.
|
||||
* @param outfile File to record command's output, NULL means that this
|
||||
* function doesn't handle command's output.
|
||||
*
|
||||
* @return If a child process could not be created, or its status could not be
|
||||
* retrieved, or it was killed/stopped by signal, the return value
|
||||
* is -1.
|
||||
* 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)
|
||||
{
|
||||
pid_t pid;
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
LOGE("fork error (%s)\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
int res;
|
||||
int fd;
|
||||
|
||||
if (outfile) {
|
||||
fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0664);
|
||||
if (fd < 0) {
|
||||
LOGE("open error (%s)\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
res = dup2(fd, STDOUT_FILENO);
|
||||
if (res < 0) {
|
||||
close(fd);
|
||||
LOGE("dup2 error (%s)\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
res = execvp(argv[0], argv);
|
||||
if (res == -1) {
|
||||
LOGE("execvp (%s) failed, error (%s)\n", argv[0],
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
pid_t res;
|
||||
int status;
|
||||
int exit_status;
|
||||
|
||||
res = waitpid(pid, &status, 0);
|
||||
if (res == -1) {
|
||||
LOGE("waitpid failed, error (%s)\n", strerror(errno));
|
||||
return res;
|
||||
}
|
||||
|
||||
if (WIFEXITED(status)) {
|
||||
exit_status = WEXITSTATUS(status);
|
||||
if (!exit_status)
|
||||
LOGI("%s exited, status=0\n", argv[0]);
|
||||
else
|
||||
LOGE("%s exited, status=%d\n", argv[0],
|
||||
exit_status);
|
||||
return exit_status;
|
||||
} else if (WIFSIGNALED(status)) {
|
||||
LOGE("%s killed by signal %d\n", argv[0],
|
||||
WTERMSIG(status));
|
||||
} else if (WIFSTOPPED(status)) {
|
||||
LOGE("%s stopped by signal %d\n", argv[0],
|
||||
WSTOPSIG(status));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int debugfs_cmd(char *loop_dev, char *cmd, char *outfile)
|
||||
{
|
||||
char *argv[5] = {"debugfs", "-R", NULL, NULL, 0};
|
||||
|
||||
argv[2] = cmd;
|
||||
argv[3] = loop_dev;
|
||||
return execv_out2file(argv, outfile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a command described in format string, and redirect the output
|
||||
* to specified file. The file will be created/truncated if it
|
||||
* exists/non-exists. This function will be blocked until the child process
|
||||
* exits.
|
||||
*
|
||||
* @param outfile File to record command's output, NULL means that this
|
||||
* function doesn't handle command's output.
|
||||
* @param fmt Format string of command.
|
||||
*
|
||||
* @return If a child process could not be created, or its status could not be
|
||||
* retrieved, or it was killed/stopped by signal, the return value
|
||||
* is -1.
|
||||
* 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, ...)
|
||||
{
|
||||
va_list args;
|
||||
char *cmd;
|
||||
char *start;
|
||||
char *p;
|
||||
int ret;
|
||||
int argc;
|
||||
char **argv;
|
||||
int i = 0;
|
||||
|
||||
va_start(args, fmt);
|
||||
ret = vasprintf(&cmd, fmt, args);
|
||||
va_end(args);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
strtrim(cmd);
|
||||
argc = strcnt(cmd, ' ') + 1;
|
||||
|
||||
argv = (char **)calloc(argc + 1, sizeof(char *));
|
||||
if (argv == NULL) {
|
||||
free(cmd);
|
||||
LOGE("calloc failed, error (%s)\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* string to argv[] */
|
||||
start = cmd;
|
||||
argv[i++] = start;
|
||||
while (start && (p = strchr(start, ' '))) {
|
||||
argv[i++] = p + 1;
|
||||
*p = 0;
|
||||
if (*(p + 1) != '"')
|
||||
start = p + 1;
|
||||
else
|
||||
start = strchr(p + 2, '"');
|
||||
}
|
||||
|
||||
ret = execv_out2file(argv, outfile);
|
||||
|
||||
free(argv);
|
||||
free(cmd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a command described in format string, and redirect the output
|
||||
* to memory. The memory is allocated by this function and needs to be freed
|
||||
* after return.
|
||||
*
|
||||
* @param fmt Format string of command.
|
||||
*
|
||||
* @return a pointer to command's output if successful, or NULL if not.
|
||||
*/
|
||||
char *exec_out2mem(char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char *cmd;
|
||||
FILE *pp;
|
||||
char *out = NULL;
|
||||
char *new;
|
||||
char tmp[1024];
|
||||
int memsize = 0;
|
||||
int newlen = 0;
|
||||
int len = 0;
|
||||
int ret;
|
||||
|
||||
va_start(args, fmt);
|
||||
ret = vasprintf(&cmd, fmt, args);
|
||||
va_end(args);
|
||||
if (ret < 0)
|
||||
return NULL;
|
||||
|
||||
pp = popen(cmd, "r");
|
||||
if (!pp)
|
||||
goto free_cmd;
|
||||
|
||||
while (fgets(tmp, 1024, pp) != NULL) {
|
||||
newlen += strlen(tmp);
|
||||
if (newlen + 1 > memsize) {
|
||||
memsize += 1024;
|
||||
new = realloc(out, memsize);
|
||||
if (!new) {
|
||||
if (out)
|
||||
free(out);
|
||||
goto end;
|
||||
} else {
|
||||
out = new;
|
||||
}
|
||||
}
|
||||
memcpy(out + len, tmp, strlen(tmp) + 1);
|
||||
|
||||
len = newlen;
|
||||
}
|
||||
|
||||
end:
|
||||
pclose(pp);
|
||||
free_cmd:
|
||||
free(cmd);
|
||||
|
||||
return out;
|
||||
}
|
9
tools/acrn-crashlog/common/include/cmdutils.h
Normal file
9
tools/acrn-crashlog/common/include/cmdutils.h
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
* 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, ...);
|
Loading…
Reference in New Issue
Block a user