mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-08-13 22:06:49 +00:00
tools: acrn-crashlog: remove unsafe strlen in common
Remove strlen in common apis, and change their caller if necessary. Tracked-On: #1254 Signed-off-by: Liu, Xinwu <xinwu.liu@intel.com> Reviewed-by: Yonghua Huang <yonghua.huang@intel.com> Acked-by: Chen Gang <gang.c.chen@intel.com>
This commit is contained in:
parent
f25bc50e68
commit
40dbdcde4f
@ -32,38 +32,6 @@ static const char *android_img = "/data/android/android.img";
|
|||||||
static const char *android_histpath = "logs/history_event";
|
static const char *android_histpath = "logs/history_event";
|
||||||
char *loop_dev;
|
char *loop_dev;
|
||||||
|
|
||||||
static char *get_line(const char *str, size_t str_size,
|
|
||||||
const char *area, size_t area_size,
|
|
||||||
const char *search_from, size_t *len)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
char *match;
|
|
||||||
char *tail;
|
|
||||||
ssize_t search_size = area + area_size - search_from;
|
|
||||||
|
|
||||||
if (search_size < 0 || (size_t)search_size < str_size)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
match = memmem(search_from, search_size, str, str_size);
|
|
||||||
if (!match)
|
|
||||||
return NULL;
|
|
||||||
tail = memchr(match + str_size, '\n',
|
|
||||||
area + area_size - match - str_size);
|
|
||||||
if (!tail)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for (p = match; p >= area; p--) {
|
|
||||||
if (*p == '\n') {
|
|
||||||
*len = tail - p - 1;
|
|
||||||
return (char *)(p + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*len = tail - area;
|
|
||||||
return (char *)area;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Find the next event that needs to be synced.
|
/* Find the next event that needs to be synced.
|
||||||
* There is a history_event file in UOS side, it records UOS's events in
|
* There is a history_event file in UOS side, it records UOS's events in
|
||||||
* real-time. Generally, the cursor point to the first unsynchronized line.
|
* real-time. Generally, the cursor point to the first unsynchronized line.
|
||||||
@ -117,8 +85,10 @@ static char *next_vm_event(const char *cursor, const char *data,
|
|||||||
* 'type'.
|
* 'type'.
|
||||||
*/
|
*/
|
||||||
if (!new || memcmp(new, type + 1, tlen - 1) ||
|
if (!new || memcmp(new, type + 1, tlen - 1) ||
|
||||||
*(new + tlen - 1) != ' ')
|
*(new + tlen - 1) != ' ') {
|
||||||
|
free(type);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
new = get_line(type, (size_t)tlen, data, dlen,
|
new = get_line(type, (size_t)tlen, data, dlen,
|
||||||
cursor, &len);
|
cursor, &len);
|
||||||
@ -136,10 +106,11 @@ static char *next_vm_event(const char *cursor, const char *data,
|
|||||||
return line_to_sync;
|
return line_to_sync;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define VMRECORD_HEAD_LINES 6
|
#define VMRECORD_HEAD_LINES 7
|
||||||
#define VMRECORD_TAG_LEN 9
|
#define VMRECORD_TAG_LEN 9
|
||||||
#define VMRECORD_TAG_WAITING_SYNC " <=="
|
#define VMRECORD_TAG_WAITING_SYNC " <=="
|
||||||
#define VMRECORD_TAG_NOT_FOUND "NOT_FOUND"
|
#define VMRECORD_TAG_NOT_FOUND "NOT_FOUND"
|
||||||
|
#define VMRECORD_TAG_MISS_LOG "MISS_LOGS"
|
||||||
#define VMRECORD_TAG_SUCCESS " "
|
#define VMRECORD_TAG_SUCCESS " "
|
||||||
static int generate_log_vmrecord(const char *path)
|
static int generate_log_vmrecord(const char *path)
|
||||||
{
|
{
|
||||||
@ -148,6 +119,7 @@ static int generate_log_vmrecord(const char *path)
|
|||||||
" * This file records VM id synced or about to be synched,\n"
|
" * This file records VM id synced or about to be synched,\n"
|
||||||
" * the tag \"<==\" indicates event waiting to sync.\n"
|
" * the tag \"<==\" indicates event waiting to sync.\n"
|
||||||
" * the tag \"NOT_FOUND\" indicates event not found in UOS.\n"
|
" * the tag \"NOT_FOUND\" indicates event not found in UOS.\n"
|
||||||
|
" * the tag \"MISS_LOGS\" indicates event miss logs in UOS.\n"
|
||||||
" */\n\n";
|
" */\n\n";
|
||||||
|
|
||||||
LOGD("Generate (%s)\n", path);
|
LOGD("Generate (%s)\n", path);
|
||||||
@ -204,7 +176,12 @@ static int refresh_key_synced_stage1(const struct sender_t *sender,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
append_file(log_vmrecordid, log_new);
|
if (append_file(log_vmrecordid, log_new,
|
||||||
|
strnlen(log_new, 64)) < 0) {
|
||||||
|
LOGE("failed to add new record (%s) to (%s)\n",
|
||||||
|
log_new, log_vmrecordid);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,7 +192,8 @@ static int refresh_key_synced_stage1(const struct sender_t *sender,
|
|||||||
|
|
||||||
enum stage2_refresh_type_t {
|
enum stage2_refresh_type_t {
|
||||||
SUCCESS,
|
SUCCESS,
|
||||||
NOT_FOUND
|
NOT_FOUND,
|
||||||
|
MISS_LOG
|
||||||
};
|
};
|
||||||
|
|
||||||
static int refresh_key_synced_stage2(char *line, size_t len,
|
static int refresh_key_synced_stage2(char *line, size_t len,
|
||||||
@ -228,6 +206,8 @@ static int refresh_key_synced_stage2(char *line, size_t len,
|
|||||||
memcpy(tag, VMRECORD_TAG_SUCCESS, VMRECORD_TAG_LEN);
|
memcpy(tag, VMRECORD_TAG_SUCCESS, VMRECORD_TAG_LEN);
|
||||||
else if (type == NOT_FOUND)
|
else if (type == NOT_FOUND)
|
||||||
memcpy(tag, VMRECORD_TAG_NOT_FOUND, VMRECORD_TAG_LEN);
|
memcpy(tag, VMRECORD_TAG_NOT_FOUND, VMRECORD_TAG_LEN);
|
||||||
|
else if (type == MISS_LOG)
|
||||||
|
memcpy(tag, VMRECORD_TAG_MISS_LOG, VMRECORD_TAG_LEN);
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -390,7 +370,7 @@ static void sync_lines_stage2(const struct sender_t *sender,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (record = next_record(recos, recos->begin, &recolen); record;
|
for (record = next_record(recos, recos->begin, &recolen); record;
|
||||||
record = next_record(recos, record, &recolen)) {
|
record = next_record(recos, record + recolen, &recolen)) {
|
||||||
const char * const record_fmt =
|
const char * const record_fmt =
|
||||||
VM_NAME_FMT ANDROID_KEY_FMT IGN_RESTS;
|
VM_NAME_FMT ANDROID_KEY_FMT IGN_RESTS;
|
||||||
char *hist_line;
|
char *hist_line;
|
||||||
@ -398,6 +378,7 @@ static void sync_lines_stage2(const struct sender_t *sender,
|
|||||||
char vm_name[32];
|
char vm_name[32];
|
||||||
char vmkey[ANDROID_WORD_LEN];
|
char vmkey[ANDROID_WORD_LEN];
|
||||||
struct vm_t *vm;
|
struct vm_t *vm;
|
||||||
|
int res;
|
||||||
|
|
||||||
/* VMNAME xxxxxxxxxxxxxxxxxxxx <== */
|
/* VMNAME xxxxxxxxxxxxxxxxxxxx <== */
|
||||||
if (str_split_ere(record, recolen,
|
if (str_split_ere(record, recolen,
|
||||||
@ -421,8 +402,11 @@ static void sync_lines_stage2(const struct sender_t *sender,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fn(hist_line, len + 1, vm) == VMEVT_HANDLED)
|
res = fn(hist_line, len + 1, vm);
|
||||||
|
if (res == VMEVT_HANDLED)
|
||||||
refresh_key_synced_stage2(record, recolen, SUCCESS);
|
refresh_key_synced_stage2(record, recolen, SUCCESS);
|
||||||
|
else if (res == VMEVT_MISSLOG)
|
||||||
|
refresh_key_synced_stage2(record, recolen, MISS_LOG);
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@ -454,8 +438,9 @@ static void get_last_line_synced(const struct sender_t *sender)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
snprintf(vm_name, sizeof(vm_name), "%s ", vm->name);
|
snprintf(vm_name, sizeof(vm_name), "%s ", vm->name);
|
||||||
ret = file_read_key_value_r(sender->log_vmrecordid, vm_name,
|
ret = file_read_key_value_r(vmkey, sizeof(vmkey),
|
||||||
sizeof(vmkey), vmkey);
|
sender->log_vmrecordid,
|
||||||
|
vm_name, strnlen(vm_name, 32));
|
||||||
if (ret == -ENOENT) {
|
if (ret == -ENOENT) {
|
||||||
LOGD("no (%s), will generate\n",
|
LOGD("no (%s), will generate\n",
|
||||||
sender->log_vmrecordid);
|
sender->log_vmrecordid);
|
||||||
@ -536,8 +521,8 @@ static char *setup_loop_dev(void)
|
|||||||
/* This function searches all android vms' new events and call the fn for
|
/* This function searches all android vms' new events and call the fn for
|
||||||
* each event.
|
* each event.
|
||||||
*
|
*
|
||||||
* Note that: fn should return 0 to indicate event has been handled,
|
* Note that: fn should return VMEVT_HANDLED to indicate event has been handled.
|
||||||
* or fn will be called in a time loop until it returns 0.
|
* fn will be called in a time loop if it returns VMEVT_DEFER.
|
||||||
*/
|
*/
|
||||||
void refresh_vm_history(const struct sender_t *sender,
|
void refresh_vm_history(const struct sender_t *sender,
|
||||||
int (*fn)(const char*, size_t, const struct vm_t *))
|
int (*fn)(const char*, size_t, const struct vm_t *))
|
||||||
|
@ -122,7 +122,6 @@ void hist_raise_event(const char *event, const char *type, const char *log,
|
|||||||
char eventtime[LONG_TIME_SIZE];
|
char eventtime[LONG_TIME_SIZE];
|
||||||
struct sender_t *crashlog;
|
struct sender_t *crashlog;
|
||||||
int maxlines;
|
int maxlines;
|
||||||
int ret;
|
|
||||||
struct history_entry entry = {
|
struct history_entry entry = {
|
||||||
.event = event,
|
.event = event,
|
||||||
.type = type,
|
.type = type,
|
||||||
@ -143,16 +142,13 @@ void hist_raise_event(const char *event, const char *type, const char *log,
|
|||||||
backup_history();
|
backup_history();
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = get_current_time_long(eventtime);
|
if (get_current_time_long(eventtime) <= 0)
|
||||||
if (ret <= 0)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
entry.eventtime = eventtime;
|
entry.eventtime = eventtime;
|
||||||
entry_to_history_line(&entry, line);
|
entry_to_history_line(&entry, line);
|
||||||
ret = append_file(history_file, line);
|
if (append_file(history_file, line, strnlen(line, MAXLINESIZE)) <= 0) {
|
||||||
if (ret < 0) {
|
LOGE("failed to append (%s) to (%s)\n", line, history_file);
|
||||||
LOGE("append (%s) failed, error (%s)\n", history_file,
|
|
||||||
strerror(errno));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -235,7 +231,8 @@ static int get_time_from_firstline(char *buffer, size_t size)
|
|||||||
const char *prefix = "#V1.0 CURRENTUPTIME ";
|
const char *prefix = "#V1.0 CURRENTUPTIME ";
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
len = file_read_key_value(history_file, prefix, MAXLINESIZE, lasttime);
|
len = file_read_key_value(lasttime, MAXLINESIZE, history_file, prefix,
|
||||||
|
strlen(prefix));
|
||||||
if (len <= 0) {
|
if (len <= 0) {
|
||||||
LOGW("failed to read value from %s, error %s\n",
|
LOGW("failed to read value from %s, error %s\n",
|
||||||
history_file, strerror(-len));
|
history_file, strerror(-len));
|
||||||
@ -289,11 +286,12 @@ int prepare_history(void)
|
|||||||
strerror(errno));
|
strerror(errno));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
ret = append_file(history_file, HISTORY_BLANK_LINE2);
|
ret = append_file(history_file, HISTORY_BLANK_LINE2,
|
||||||
|
sizeof(HISTORY_BLANK_LINE2) - 1);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
LOGE("Write (%s, %s) failed, error (%s)\n",
|
LOGE("Write (%s, %s) failed, error (%s)\n",
|
||||||
history_file, HISTORY_BLANK_LINE2,
|
history_file, HISTORY_BLANK_LINE2,
|
||||||
strerror(errno));
|
strerror(-ret));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
current_lines = count_lines_in_file(history_file);
|
current_lines = count_lines_in_file(history_file);
|
||||||
|
@ -11,7 +11,9 @@ extern char *loop_dev;
|
|||||||
|
|
||||||
#define VMEVT_HANDLED 0
|
#define VMEVT_HANDLED 0
|
||||||
#define VMEVT_DEFER -1
|
#define VMEVT_DEFER -1
|
||||||
|
#define VMEVT_MISSLOG -2
|
||||||
|
|
||||||
|
#define ANDROID_LOGS_DIR "/logs/"
|
||||||
#define IGN_SPACES "%*[[[:space:]]*]"
|
#define IGN_SPACES "%*[[[:space:]]*]"
|
||||||
#define IGN_RESTS "%*[[.]*]"
|
#define IGN_RESTS "%*[[.]*]"
|
||||||
#define IGN_ONEWORD "%*[[^[:space:]]*]" IGN_SPACES
|
#define IGN_ONEWORD "%*[[^[:space:]]*]" IGN_SPACES
|
||||||
|
@ -71,8 +71,9 @@ static int get_buildversion(struct sender_t *sender)
|
|||||||
char *logbuildid;
|
char *logbuildid;
|
||||||
char *currentbuild = gbuildversion;
|
char *currentbuild = gbuildversion;
|
||||||
|
|
||||||
ret = file_read_key_value(OS_VERSION, OS_VERSION_KEY,
|
ret = file_read_key_value(gbuildversion, sizeof(gbuildversion),
|
||||||
sizeof(gbuildversion), gbuildversion);
|
OS_VERSION, OS_VERSION_KEY,
|
||||||
|
strlen(OS_VERSION_KEY));
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
LOGE("failed to get version from %s, error (%s)\n",
|
LOGE("failed to get version from %s, error (%s)\n",
|
||||||
OS_VERSION, strerror(-ret));
|
OS_VERSION, strerror(-ret));
|
||||||
|
@ -216,13 +216,14 @@ static void telemd_get_log(struct log_t *log, void *data)
|
|||||||
int res;
|
int res;
|
||||||
int i;
|
int i;
|
||||||
struct dirent **filelist;
|
struct dirent **filelist;
|
||||||
|
struct ac_filter_data acfd = {log->name, log->name_len};
|
||||||
|
|
||||||
if (d->srcdir == NULL)
|
if (d->srcdir == NULL)
|
||||||
goto send_nologs;
|
goto send_nologs;
|
||||||
|
|
||||||
/* search file which use log->name as substring */
|
/* search file which use log->name as substring */
|
||||||
count = ac_scandir(d->srcdir, &filelist, filter_filename_substr,
|
count = ac_scandir(d->srcdir, &filelist, filter_filename_substr,
|
||||||
log->name, NULL);
|
&acfd, NULL);
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
LOGE("search (%s) in dir (%s) failed\n", log->name, d->srcdir);
|
LOGE("search (%s) in dir (%s) failed\n", log->name, d->srcdir);
|
||||||
return;
|
return;
|
||||||
@ -544,8 +545,7 @@ static void telemd_send_reboot(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int telemd_new_vmevent(const char *line_to_sync,
|
static int telemd_new_vmevent(const char *line_to_sync,
|
||||||
size_t len __attribute__((unused)),
|
size_t len, const struct vm_t *vm)
|
||||||
const struct vm_t *vm)
|
|
||||||
{
|
{
|
||||||
char event[ANDROID_WORD_LEN];
|
char event[ANDROID_WORD_LEN];
|
||||||
char longtime[ANDROID_WORD_LEN];
|
char longtime[ANDROID_WORD_LEN];
|
||||||
@ -589,21 +589,26 @@ static int telemd_new_vmevent(const char *line_to_sync,
|
|||||||
severity = INFO_SEVERITY;
|
severity = INFO_SEVERITY;
|
||||||
|
|
||||||
/* if line contains log, fill vmlogpath */
|
/* if line contains log, fill vmlogpath */
|
||||||
log = strstr(rest, "/logs/");
|
log = strstr(rest, ANDROID_LOGS_DIR);
|
||||||
if (log) {
|
if (log) {
|
||||||
struct sender_t *crashlog;
|
struct sender_t *crashlog = get_sender_by_name("crashlog");
|
||||||
|
const char *logf;
|
||||||
|
size_t logflen;
|
||||||
|
int res;
|
||||||
|
|
||||||
crashlog = get_sender_by_name("crashlog");
|
|
||||||
if (!crashlog)
|
if (!crashlog)
|
||||||
return VMEVT_HANDLED;
|
return VMEVT_HANDLED;
|
||||||
|
|
||||||
res = find_file(crashlog->outdir, log + strlen("/logs/"),
|
logf = log + sizeof(ANDROID_LOGS_DIR) - 1;
|
||||||
2, &vmlogpath, 1);
|
logflen = &rest[0] + strnlen(rest, PATH_MAX) - logf;
|
||||||
if (res < 0) {
|
res = find_file(crashlog->outdir, logf, logflen, 1,
|
||||||
LOGE("find (%s) in (%s) failed\n",
|
&vmlogpath, 1);
|
||||||
log + strlen("/logs/"), crashlog->outdir);
|
if (res == -1) {
|
||||||
|
LOGE("failed to find (%s) in (%s)\n",
|
||||||
|
logf, crashlog->outdir);
|
||||||
|
return VMEVT_DEFER;
|
||||||
|
} else if (res == 0)
|
||||||
return VMEVT_DEFER;
|
return VMEVT_DEFER;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
res = asprintf(&class, "%s/%s/%s", vm->name, event, type);
|
res = asprintf(&class, "%s/%s/%s", vm->name, event, type);
|
||||||
@ -898,8 +903,7 @@ static void crashlog_send_reboot(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int crashlog_new_vmevent(const char *line_to_sync,
|
static int crashlog_new_vmevent(const char *line_to_sync,
|
||||||
size_t len __attribute__((unused)),
|
size_t len, const struct vm_t *vm)
|
||||||
const struct vm_t *vm)
|
|
||||||
{
|
{
|
||||||
struct sender_t *crashlog;
|
struct sender_t *crashlog;
|
||||||
char event[ANDROID_WORD_LEN];
|
char event[ANDROID_WORD_LEN];
|
||||||
@ -980,12 +984,18 @@ static int crashlog_new_vmevent(const char *line_to_sync,
|
|||||||
ret = VMEVT_DEFER;
|
ret = VMEVT_DEFER;
|
||||||
} else {
|
} else {
|
||||||
LOGW("(%s) is missing\n", vmlogpath);
|
LOGW("(%s) is missing\n", vmlogpath);
|
||||||
ret = VMEVT_HANDLED; /* missing logdir */
|
ret = VMEVT_MISSLOG; /* missing logdir */
|
||||||
}
|
}
|
||||||
res = remove(dir);
|
if (remove_r(dir) == -1)
|
||||||
if (res == -1 && errno != ENOENT)
|
LOGE("failed to remove %s (%d)\n", dir, -errno);
|
||||||
|
goto free_dir;
|
||||||
|
}
|
||||||
|
if (cnt == 1) {
|
||||||
|
LOGW("(%s) is empty, will sync it in the next loop\n",
|
||||||
|
vmlogpath);
|
||||||
|
ret = VMEVT_DEFER;
|
||||||
|
if (remove_r(dir) == -1)
|
||||||
LOGE("failed to remove %s (%d)\n", dir, -errno);
|
LOGE("failed to remove %s (%d)\n", dir, -errno);
|
||||||
|
|
||||||
goto free_dir;
|
goto free_dir;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,7 @@ int exec_out2file(const char *outfile, const char *fmt, ...)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
strtrim(cmd);
|
strtrim(cmd, ret);
|
||||||
argc = strcnt(cmd, ' ') + 1;
|
argc = strcnt(cmd, ' ') + 1;
|
||||||
|
|
||||||
argv = (char **)calloc(argc + 1, sizeof(char *));
|
argv = (char **)calloc(argc + 1, sizeof(char *));
|
||||||
@ -171,11 +171,12 @@ int exec_out2file(const char *outfile, const char *fmt, ...)
|
|||||||
* to memory. The memory is allocated by this function and needs to be freed
|
* to memory. The memory is allocated by this function and needs to be freed
|
||||||
* after return.
|
* after return.
|
||||||
*
|
*
|
||||||
|
* @param[out] outmem The pointer to command's output.
|
||||||
* @param fmt Format string of command.
|
* @param fmt Format string of command.
|
||||||
*
|
*
|
||||||
* @return a pointer to command's output if successful, or NULL if not.
|
* @return the length of command's output if successful, or -1 if not.
|
||||||
*/
|
*/
|
||||||
char *exec_out2mem(const char *fmt, ...)
|
ssize_t exec_out2mem(char **outmem, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
char *cmd;
|
char *cmd;
|
||||||
@ -183,23 +184,25 @@ char *exec_out2mem(const char *fmt, ...)
|
|||||||
char *out = NULL;
|
char *out = NULL;
|
||||||
char *new;
|
char *new;
|
||||||
char tmp[1024];
|
char tmp[1024];
|
||||||
int memsize = 0;
|
size_t memsize = 0;
|
||||||
int newlen = 0;
|
size_t newlen = 0;
|
||||||
int len = 0;
|
ssize_t len = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
ret = vasprintf(&cmd, fmt, args);
|
ret = vasprintf(&cmd, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return NULL;
|
return -1;
|
||||||
|
|
||||||
pp = popen(cmd, "r");
|
pp = popen(cmd, "r");
|
||||||
if (!pp)
|
if (!pp) {
|
||||||
goto free_cmd;
|
free(cmd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
while (fgets(tmp, 1024, pp) != NULL) {
|
while (fgets(tmp, 1024, pp) != NULL) {
|
||||||
newlen += strlen(tmp);
|
newlen += strnlen(tmp, 1024);
|
||||||
if (newlen + 1 > memsize) {
|
if (newlen + 1 > memsize) {
|
||||||
memsize += 1024;
|
memsize += 1024;
|
||||||
new = realloc(out, memsize);
|
new = realloc(out, memsize);
|
||||||
@ -208,20 +211,22 @@ char *exec_out2mem(const char *fmt, ...)
|
|||||||
free(out);
|
free(out);
|
||||||
out = NULL;
|
out = NULL;
|
||||||
}
|
}
|
||||||
|
len = -1;
|
||||||
goto end;
|
goto end;
|
||||||
} else {
|
} else {
|
||||||
out = new;
|
out = new;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
memcpy(out + len, tmp, strlen(tmp) + 1);
|
/* fgets read at most 1023 bytes and plus '\0' */
|
||||||
|
memcpy(out + len, tmp, strnlen(tmp, 1024) + 1);
|
||||||
|
|
||||||
len = newlen;
|
len = newlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
|
*outmem = out;
|
||||||
pclose(pp);
|
pclose(pp);
|
||||||
free_cmd:
|
|
||||||
free(cmd);
|
free(cmd);
|
||||||
|
|
||||||
return out;
|
return len;
|
||||||
}
|
}
|
||||||
|
@ -32,13 +32,12 @@
|
|||||||
#include <sys/vfs.h>
|
#include <sys/vfs.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <ftw.h>
|
||||||
#include "fsutils.h"
|
#include "fsutils.h"
|
||||||
#include "cmdutils.h"
|
#include "cmdutils.h"
|
||||||
#include "strutils.h"
|
#include "strutils.h"
|
||||||
#include "log_sys.h"
|
#include "log_sys.h"
|
||||||
|
|
||||||
#define MAX_SEARCH_DIRS 4096
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Help function to do fclose. In some cases (full partition),
|
* Help function to do fclose. In some cases (full partition),
|
||||||
* file closure could fail, so get error message here.
|
* file closure could fail, so get error message here.
|
||||||
@ -81,6 +80,30 @@ int mkdir_p(const char *path)
|
|||||||
return exec_out2file(NULL, "mkdir -p %s", path);
|
return exec_out2file(NULL, "mkdir -p %s", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int rmfile(const char *path,
|
||||||
|
const struct stat *sbuf __attribute__((unused)),
|
||||||
|
int type __attribute__((unused)),
|
||||||
|
struct FTW *ftwb __attribute__((unused)))
|
||||||
|
{
|
||||||
|
if (remove(path) == -1) {
|
||||||
|
LOGE("failed to remove (%s), error (%s)\n", path,
|
||||||
|
strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int remove_r(const char *dir)
|
||||||
|
{
|
||||||
|
if (!dir)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (nftw(dir, rmfile, 10, FTW_DEPTH | FTW_MOUNT | FTW_PHYS) == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Count file lines.
|
* Count file lines.
|
||||||
* This function defaults to all text files ending with \n.
|
* This function defaults to all text files ending with \n.
|
||||||
@ -141,7 +164,6 @@ char *mm_get_line(struct mm_file_t *mfile, int line)
|
|||||||
struct mm_file_t *mmap_file(const char *path)
|
struct mm_file_t *mmap_file(const char *path)
|
||||||
{
|
{
|
||||||
struct mm_file_t *mfile;
|
struct mm_file_t *mfile;
|
||||||
int size;
|
|
||||||
|
|
||||||
mfile = malloc(sizeof(struct mm_file_t));
|
mfile = malloc(sizeof(struct mm_file_t));
|
||||||
if (!mfile) {
|
if (!mfile) {
|
||||||
@ -167,8 +189,7 @@ struct mm_file_t *mmap_file(const char *path)
|
|||||||
path, strerror(errno));
|
path, strerror(errno));
|
||||||
goto close_fd;
|
goto close_fd;
|
||||||
}
|
}
|
||||||
size = mfile->size > 0 ? mfile->size : PAGE_SIZE;
|
mfile->begin = mmap(NULL, mfile->size, PROT_READ|PROT_WRITE, MAP_SHARED,
|
||||||
mfile->begin = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED,
|
|
||||||
mfile->fd, 0);
|
mfile->fd, 0);
|
||||||
if (mfile->begin == MAP_FAILED) {
|
if (mfile->begin == MAP_FAILED) {
|
||||||
LOGE("mmap (%s) failed, error (%s)\n", path, strerror(errno));
|
LOGE("mmap (%s) failed, error (%s)\n", path, strerror(errno));
|
||||||
@ -293,22 +314,18 @@ int do_mv(char *src, char *dest)
|
|||||||
*
|
*
|
||||||
* @return 0 if successful, or a negative errno-style value if not.
|
* @return 0 if successful, or a negative errno-style value if not.
|
||||||
*/
|
*/
|
||||||
int append_file(char *filename, char *text)
|
ssize_t append_file(const char *filename, const char *text, size_t tlen)
|
||||||
{
|
{
|
||||||
int fd, res, len;
|
int fd, res;
|
||||||
|
|
||||||
if (!filename || !text)
|
if (!filename || !text || !tlen)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
len = strlen(text);
|
fd = open(filename, O_WRONLY | O_APPEND);
|
||||||
if (!len)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
fd = open(filename, O_RDWR | O_APPEND);
|
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
res = write(fd, text, len);
|
res = write(fd, text, tlen);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
return (res == -1 ? -errno : res);
|
return (res == -1 ? -errno : res);
|
||||||
@ -344,7 +361,7 @@ int replace_file_head(char *filename, char *text)
|
|||||||
* The file is created if it does not exist, otherwise it is truncated.
|
* The file is created if it does not exist, otherwise it is truncated.
|
||||||
*
|
*
|
||||||
* @param filename Path of file.
|
* @param filename Path of file.
|
||||||
* @param text String need to be appended.
|
* @param text String need to be written.
|
||||||
*
|
*
|
||||||
* @return 0 if successful, or a negative errno-style value if not.
|
* @return 0 if successful, or a negative errno-style value if not.
|
||||||
*/
|
*/
|
||||||
@ -368,42 +385,6 @@ int overwrite_file(const char *filename, const char *value)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Read line from file descriptor.
|
|
||||||
*
|
|
||||||
* @param fd File descriptor.
|
|
||||||
* @param[out] buffer Content of line.
|
|
||||||
*
|
|
||||||
* @return length of line if successful, or a negative errno-style value if not.
|
|
||||||
*/
|
|
||||||
int readline(int fd, char buffer[MAXLINESIZE])
|
|
||||||
{
|
|
||||||
int size = 0, res;
|
|
||||||
char *pbuffer = &buffer[0];
|
|
||||||
|
|
||||||
/* Read the file until end of line or file */
|
|
||||||
while ((res = read(fd, pbuffer, 1)) == 1 && size < MAXLINESIZE-1) {
|
|
||||||
if (pbuffer[0] == '\n') {
|
|
||||||
buffer[++size] = 0;
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
pbuffer++;
|
|
||||||
size++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check the last read result */
|
|
||||||
if (res < 0) {
|
|
||||||
/* ernno is checked in the upper layer as we could
|
|
||||||
* print the filename here
|
|
||||||
*/
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
/* last line */
|
|
||||||
buffer[size] = 0;
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the first line from file.
|
* Read the first line from file.
|
||||||
*
|
*
|
||||||
@ -414,7 +395,7 @@ int readline(int fd, char buffer[MAXLINESIZE])
|
|||||||
* @return length of string if successful, or a negative errno-style value
|
* @return length of string if successful, or a negative errno-style value
|
||||||
* if not.
|
* if not.
|
||||||
*/
|
*/
|
||||||
int file_read_string(const char *file, char *string, int size)
|
ssize_t file_read_string(const char *file, char *string, const int size)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *res;
|
char *res;
|
||||||
@ -440,7 +421,7 @@ int file_read_string(const char *file, char *string, int size)
|
|||||||
end = strchr(string, '\n');
|
end = strchr(string, '\n');
|
||||||
if (end)
|
if (end)
|
||||||
*end = 0;
|
*end = 0;
|
||||||
return strlen(string);
|
return strnlen(string, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -678,89 +659,17 @@ int count_lines_in_file(const char *filename)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static ssize_t _file_read_key_value(char *value, const size_t limit,
|
||||||
* Read binary file.
|
const char *path, const char *key,
|
||||||
*
|
size_t klen, const char op)
|
||||||
* @param path File path to read.
|
|
||||||
* @param[out] File size being read.
|
|
||||||
* @param[out] data File content.
|
|
||||||
*
|
|
||||||
* @return 0 if successful, or -1 if not.
|
|
||||||
*/
|
|
||||||
int read_full_binary_file(const char *path, unsigned long *size, void **data)
|
|
||||||
{
|
{
|
||||||
FILE *f;
|
|
||||||
long _size;
|
|
||||||
void *buf;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
if (!path || !data || !size) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
f = fopen(path, "rb");
|
|
||||||
if (!f)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (fseek(f, 0, SEEK_END) == -1) {
|
|
||||||
err = errno;
|
|
||||||
goto close;
|
|
||||||
}
|
|
||||||
|
|
||||||
_size = ftell(f);
|
|
||||||
if (_size == -1) {
|
|
||||||
err = errno;
|
|
||||||
goto close;
|
|
||||||
} else if (!_size) {
|
|
||||||
err = ERANGE;
|
|
||||||
goto close;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fseek(f, 0, SEEK_SET) == -1) {
|
|
||||||
err = errno;
|
|
||||||
goto close;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf = malloc(_size + 10);
|
|
||||||
if (!buf) {
|
|
||||||
err = ENOMEM;
|
|
||||||
goto close;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(buf, 0, _size + 10);
|
|
||||||
if (fread(buf, 1, _size, f) != (unsigned int)_size) {
|
|
||||||
err = EBADF;
|
|
||||||
goto free;
|
|
||||||
}
|
|
||||||
|
|
||||||
close_file(path, f);
|
|
||||||
|
|
||||||
*data = buf;
|
|
||||||
*size = (unsigned long)_size;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
free:
|
|
||||||
free(buf);
|
|
||||||
close:
|
|
||||||
close_file(path, f);
|
|
||||||
errno = err;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _file_read_key_value(const char *path, const char op,
|
|
||||||
const char *key, const size_t limit,
|
|
||||||
char *value)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
int size;
|
|
||||||
size_t len;
|
size_t len;
|
||||||
char *data;
|
|
||||||
char *msg = NULL;
|
char *msg = NULL;
|
||||||
char *end, *start;
|
struct mm_file_t *f = mmap_file(path);
|
||||||
|
|
||||||
if (!key || !path) {
|
if (!f)
|
||||||
|
return -errno;
|
||||||
|
if (!key) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
@ -770,63 +679,47 @@ static int _file_read_key_value(const char *path, const char op,
|
|||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
size = get_file_size(path);
|
|
||||||
if (size < 0)
|
|
||||||
return size;
|
|
||||||
if (!size) {
|
|
||||||
errno = ENOMSG;
|
|
||||||
return -errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
fd = open(path, O_RDONLY);
|
|
||||||
if (fd < 0)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
data = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
|
||||||
if (data == MAP_FAILED)
|
|
||||||
goto close;
|
|
||||||
|
|
||||||
if (op == 'l')
|
if (op == 'l')
|
||||||
msg = strstr(data, key);
|
msg = get_line(key, klen, f->begin, f->size, f->begin, &len);
|
||||||
else if (op == 'r')
|
else if (op == 'r') {
|
||||||
msg = strrstr(data, key);
|
char *msg_tmp;
|
||||||
|
|
||||||
|
msg = f->begin;
|
||||||
|
len = 0;
|
||||||
|
while ((msg_tmp = get_line(key, klen, f->begin, f->size,
|
||||||
|
msg, &len)))
|
||||||
|
msg = msg_tmp + len;
|
||||||
|
if (msg != f->begin)
|
||||||
|
msg -= len;
|
||||||
|
else
|
||||||
|
msg = NULL;
|
||||||
|
}
|
||||||
if (!msg) {
|
if (!msg) {
|
||||||
errno = ENOMSG;
|
errno = ENOMSG;
|
||||||
goto unmap;
|
goto unmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
start = msg + strlen(key);
|
len = MIN(len - klen, limit - 1);
|
||||||
end = strchr(start, '\n');
|
*(char *)mempcpy(value, msg + klen, len) = '\0';
|
||||||
if (end == NULL)
|
|
||||||
end = data + size;
|
|
||||||
|
|
||||||
len = end - start;
|
|
||||||
len = MIN(len, limit - 1);
|
|
||||||
memcpy(value, start, len);
|
|
||||||
*(value + len) = 0;
|
|
||||||
|
|
||||||
munmap(data, size);
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
|
unmap_file(f);
|
||||||
return len;
|
return len;
|
||||||
|
|
||||||
unmap:
|
unmap:
|
||||||
munmap(data, size);
|
unmap_file(f);
|
||||||
close:
|
|
||||||
close(fd);
|
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
int file_read_key_value(const char *path, const char *key,
|
ssize_t file_read_key_value(char *value, const size_t limit, const char *path,
|
||||||
const size_t limit, char *value)
|
const char *key, size_t klen)
|
||||||
{
|
{
|
||||||
return _file_read_key_value(path, 'l', key, limit, value);
|
return _file_read_key_value(value, limit, path, key, klen, 'l');
|
||||||
}
|
}
|
||||||
|
|
||||||
int file_read_key_value_r(const char *path, const char *key,
|
ssize_t file_read_key_value_r(char *value, const size_t limit, const char *path,
|
||||||
const size_t limit, char *value)
|
const char *key, size_t klen)
|
||||||
{
|
{
|
||||||
return _file_read_key_value(path, 'r', key, limit, value);
|
return _file_read_key_value(value, limit, path, key, klen, 'r');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -914,41 +807,46 @@ e_free:
|
|||||||
/* filters return zero if the match is successful */
|
/* filters return zero if the match is successful */
|
||||||
int filter_filename_substr(const struct dirent *entry, const void *arg)
|
int filter_filename_substr(const struct dirent *entry, const void *arg)
|
||||||
{
|
{
|
||||||
const char *substr = (const char *)arg;
|
struct ac_filter_data *d = (struct ac_filter_data *)arg;
|
||||||
|
|
||||||
return !strstr(entry->d_name, substr);
|
return !memmem(entry->d_name, _D_EXACT_NAMLEN(entry), d->str, d->len);
|
||||||
}
|
}
|
||||||
|
|
||||||
int filter_filename_exactly(const struct dirent *entry, const void *arg)
|
int filter_filename_exactly(const struct dirent *entry, const void *arg)
|
||||||
{
|
{
|
||||||
const char *fname = (const char *)arg;
|
struct ac_filter_data *d = (struct ac_filter_data *)arg;
|
||||||
|
|
||||||
return strcmp(entry->d_name, fname);
|
return strcmp(entry->d_name, d->str);
|
||||||
}
|
}
|
||||||
|
|
||||||
int filter_filename_startswith(const struct dirent *entry,
|
int filter_filename_startswith(const struct dirent *entry,
|
||||||
const void *arg)
|
const void *arg)
|
||||||
{
|
{
|
||||||
const char *str = (const char *)arg;
|
struct ac_filter_data *d = (struct ac_filter_data *)arg;
|
||||||
|
|
||||||
return memcmp(entry->d_name, str, strlen(str));
|
if (_D_EXACT_NAMLEN(entry) < d->len)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return memcmp(entry->d_name, d->str, d->len);
|
||||||
}
|
}
|
||||||
|
|
||||||
int dir_contains(const char *dir, const char *filename, const int exact)
|
int dir_contains(const char *dir, const char *filename, size_t flen,
|
||||||
|
const int exact)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
int i;
|
int i;
|
||||||
struct dirent **filelist;
|
struct dirent **filelist;
|
||||||
|
struct ac_filter_data acfd = {filename, flen};
|
||||||
|
|
||||||
if (!dir || !filename)
|
if (!dir || !filename || !flen)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (exact)
|
if (exact)
|
||||||
ret = ac_scandir(dir, &filelist, filter_filename_exactly,
|
ret = ac_scandir(dir, &filelist, filter_filename_exactly,
|
||||||
(const void *)filename, 0);
|
(const void *)&acfd, 0);
|
||||||
else
|
else
|
||||||
ret = ac_scandir(dir, &filelist, filter_filename_substr,
|
ret = ac_scandir(dir, &filelist, filter_filename_substr,
|
||||||
(const void *)filename, 0);
|
(const void *)&acfd, 0);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -1008,121 +906,108 @@ free_list:
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_subdir(const struct dirent *entry)
|
|
||||||
{
|
|
||||||
return (entry->d_type == DT_DIR) &&
|
|
||||||
strcmp(entry->d_name, ".") &&
|
|
||||||
strcmp(entry->d_name, "..");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void expand_dir(char *_dirs[], int *count, int depth, int max_depth)
|
|
||||||
{
|
|
||||||
int files;
|
|
||||||
int i;
|
|
||||||
int res;
|
|
||||||
struct dirent **filelist;
|
|
||||||
char *subdir;
|
|
||||||
char *name;
|
|
||||||
char *current_dir = _dirs[*count - 1];
|
|
||||||
|
|
||||||
if (depth > max_depth)
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
|
||||||
files = scandir(current_dir, &filelist, is_subdir, 0);
|
|
||||||
if (files < 0) {
|
|
||||||
LOGE("lsdir failed, error (%s)\n", strerror(-files));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < files; i++) {
|
|
||||||
if (*count >= MAX_SEARCH_DIRS) {
|
|
||||||
LOGE("too many dirs(%d) under %s\n",
|
|
||||||
*count, _dirs[0]);
|
|
||||||
goto free;
|
|
||||||
}
|
|
||||||
|
|
||||||
name = filelist[i]->d_name;
|
|
||||||
res = asprintf(&subdir, "%s/%s", current_dir, name);
|
|
||||||
if (res < 0) {
|
|
||||||
LOGE("compute string failed, out of memory\n");
|
|
||||||
goto free;
|
|
||||||
}
|
|
||||||
|
|
||||||
_dirs[*count] = subdir;
|
|
||||||
(*count)++;
|
|
||||||
expand_dir(_dirs, count, depth++, max_depth);
|
|
||||||
}
|
|
||||||
free:
|
|
||||||
for (i = 0; i < files; i++)
|
|
||||||
free(filelist[i]);
|
|
||||||
free(filelist);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find target file in specified dir.
|
* Find target file in specified dir.
|
||||||
*
|
*
|
||||||
* @param dir Where to start search.
|
* @param dir Where to start search.
|
||||||
* @param target_file Target file to search.
|
* @param target_file Target file to search.
|
||||||
* @param depth File's depth in the directory tree.
|
* @param tflen The length of target_file.
|
||||||
|
* @param depth Descend at most depth of directories below the starting dir.
|
||||||
* @param path[out] Searched file path in given dir.
|
* @param path[out] Searched file path in given dir.
|
||||||
* @param limit The number of files uplayer want to get.
|
* @param limit The number of files uplayer want to get.
|
||||||
*
|
*
|
||||||
* @return the count of searched files on success, or -1 on error.
|
* @return the count of searched files on success, or -1 on error.
|
||||||
*/
|
*/
|
||||||
int find_file(const char *dir, char *target_file, int depth, char *path[],
|
int find_file(const char *dir, const char *target_file, size_t tflen,
|
||||||
int limit)
|
int depth, char *path[], int limit)
|
||||||
{
|
{
|
||||||
int i, ret;
|
int wdepth = 0;
|
||||||
int count = 0;
|
int found = 0;
|
||||||
char *_dirs[MAX_SEARCH_DIRS];
|
char wdir[PATH_MAX];
|
||||||
int dirs;
|
DIR **dp;
|
||||||
|
|
||||||
if (depth < 1 || !dir || !target_file || !path || limit <= 0)
|
if (!dir || !target_file || !tflen || !path || limit <= 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
if (!memccpy(wdir, dir, 0, PATH_MAX))
|
||||||
ret = asprintf(&_dirs[0], "%s", dir);
|
return -1;
|
||||||
if (ret < 0) {
|
dp = calloc(depth + 1, sizeof(DIR *));
|
||||||
LOGE("compute string failed, out of memory\n");
|
if (!dp) {
|
||||||
|
LOGE("out of memory\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
dirs = 1;
|
|
||||||
|
|
||||||
/* expand all dirs */
|
while (wdepth >= 0) {
|
||||||
expand_dir(_dirs, &dirs, 1, depth);
|
struct dirent *dirp;
|
||||||
for (i = 0; i < dirs; i++) {
|
|
||||||
if (count >= limit)
|
|
||||||
goto free;
|
|
||||||
|
|
||||||
ret = dir_contains(_dirs[i], target_file, 1);
|
if (!dp[wdepth]) {
|
||||||
if (ret == 1) {
|
/* new stream */
|
||||||
ret = asprintf(&path[count++], "%s/%s",
|
dp[wdepth] = opendir(wdir);
|
||||||
_dirs[i], target_file);
|
if (!dp[wdepth]) {
|
||||||
if (ret < 0) {
|
LOGE("failed to opendir (%s), error (%s)\n",
|
||||||
LOGE("compute string failed, out of memory\n");
|
wdir, strerror(errno));
|
||||||
ret = -1;
|
goto fail_open;
|
||||||
goto fail;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!(errno = 0) && (dirp = readdir(dp[wdepth]))) {
|
||||||
|
if (!strcmp(dirp->d_name, ".") ||
|
||||||
|
!strcmp(dirp->d_name, ".."))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!strcmp(dirp->d_name, target_file)) {
|
||||||
|
if (asprintf(&path[found], "%s/%s", wdir,
|
||||||
|
dirp->d_name) == -1) {
|
||||||
|
LOGE("out of memory\n");
|
||||||
|
goto fail_read;
|
||||||
|
}
|
||||||
|
if (++found == limit)
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dirp->d_type == DT_DIR && wdepth < depth) {
|
||||||
|
/* search in subdir */
|
||||||
|
*(char *)
|
||||||
|
mempcpy(mempcpy(wdir + strnlen(wdir, PATH_MAX),
|
||||||
|
"/", 1),
|
||||||
|
dirp->d_name,
|
||||||
|
strnlen(dirp->d_name, NAME_MAX)) = '\0';
|
||||||
|
wdepth++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!dirp) {
|
||||||
|
if (!errno) {
|
||||||
|
/* meet the end of stream, back to the parent */
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
closedir(dp[wdepth]);
|
||||||
|
dp[wdepth--] = NULL;
|
||||||
|
p = strrchr(wdir, '/');
|
||||||
|
if (p)
|
||||||
|
*p = '\0';
|
||||||
|
} else {
|
||||||
|
LOGE("failed to readdir, (%s)\n",
|
||||||
|
strerror(errno));
|
||||||
|
goto fail_read;
|
||||||
}
|
}
|
||||||
} else if (ret < 0) {
|
|
||||||
LOGE("dir_contains failed\n");
|
|
||||||
ret = -1;
|
|
||||||
goto fail;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
end:
|
||||||
|
while (wdepth >= 0)
|
||||||
|
closedir(dp[wdepth--]);
|
||||||
|
free(dp);
|
||||||
|
return found;
|
||||||
|
|
||||||
free:
|
fail_read:
|
||||||
for (i = 0; i < dirs; i++)
|
LOGE("failed to search in dir %s\n", wdir);
|
||||||
free(_dirs[i]);
|
closedir(dp[wdepth]);
|
||||||
|
fail_open:
|
||||||
return count;
|
while (wdepth)
|
||||||
fail:
|
closedir(dp[--wdepth]);
|
||||||
for (i = 0; i < dirs; i++)
|
while (found)
|
||||||
free(_dirs[i]);
|
free(path[--found]);
|
||||||
|
free(dp);
|
||||||
for (i = 0; i < count; i++)
|
return -1;
|
||||||
free(path[i]);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int read_file(const char *path, unsigned long *size, void **data)
|
int read_file(const char *path, unsigned long *size, void **data)
|
||||||
@ -1214,6 +1099,7 @@ int config_fmt_to_files(const char *file_fmt, char ***out)
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct dirent **filelist;
|
struct dirent **filelist;
|
||||||
char **out_array;
|
char **out_array;
|
||||||
|
struct ac_filter_data acfd;
|
||||||
|
|
||||||
if (!file_fmt || !out)
|
if (!file_fmt || !out)
|
||||||
return -1;
|
return -1;
|
||||||
@ -1247,14 +1133,15 @@ int config_fmt_to_files(const char *file_fmt, char ***out)
|
|||||||
*p = '\0';
|
*p = '\0';
|
||||||
file_prefix = p + 1;
|
file_prefix = p + 1;
|
||||||
p = strrchr(file_prefix, '[');
|
p = strrchr(file_prefix, '[');
|
||||||
if (p) {
|
if (!p) {
|
||||||
*p = '\0';
|
|
||||||
} else {
|
|
||||||
ret = -1;
|
ret = -1;
|
||||||
LOGE("unsupported formats (%s)\n", dir);
|
LOGE("unsupported formats (%s)\n", dir);
|
||||||
goto free_dir;
|
goto free_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*p = '\0';
|
||||||
|
acfd.str = file_prefix;
|
||||||
|
acfd.len = p - file_prefix;
|
||||||
|
|
||||||
if (!directory_exists(dir)) {
|
if (!directory_exists(dir)) {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
@ -1276,7 +1163,7 @@ int config_fmt_to_files(const char *file_fmt, char ***out)
|
|||||||
|
|
||||||
/* get all files which start with prefix */
|
/* get all files which start with prefix */
|
||||||
count = ac_scandir(dir, &filelist, filter_filename_startswith,
|
count = ac_scandir(dir, &filelist, filter_filename_startswith,
|
||||||
file_prefix, alphasort);
|
&acfd, alphasort);
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
ret = -1;
|
ret = -1;
|
||||||
LOGE("failed to ac_scandir\n");
|
LOGE("failed to ac_scandir\n");
|
||||||
|
@ -5,4 +5,4 @@
|
|||||||
|
|
||||||
int execv_out2file(char * const argv[], const char *outfile);
|
int execv_out2file(char * const argv[], const char *outfile);
|
||||||
int exec_out2file(const char *outfile, const char *fmt, ...);
|
int exec_out2file(const char *outfile, const char *fmt, ...);
|
||||||
char *exec_out2mem(const char *fmt, ...);
|
ssize_t exec_out2mem(char **outmem, const char *fmt, ...);
|
||||||
|
@ -43,6 +43,11 @@ struct mm_file_t {
|
|||||||
int size;
|
int size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ac_filter_data {
|
||||||
|
const char *str;
|
||||||
|
size_t len;
|
||||||
|
};
|
||||||
|
|
||||||
static inline int file_exists(const char *filename)
|
static inline int file_exists(const char *filename)
|
||||||
{
|
{
|
||||||
struct stat info;
|
struct stat info;
|
||||||
@ -72,18 +77,17 @@ static inline int get_file_size(const char *filepath)
|
|||||||
|
|
||||||
char *mm_get_line(struct mm_file_t *mfile, int line);
|
char *mm_get_line(struct mm_file_t *mfile, int line);
|
||||||
int mkdir_p(const char *path);
|
int mkdir_p(const char *path);
|
||||||
|
int remove_r(const char *dir);
|
||||||
int mm_count_lines(struct mm_file_t *mfile);
|
int mm_count_lines(struct mm_file_t *mfile);
|
||||||
struct mm_file_t *mmap_file(const char *path);
|
struct mm_file_t *mmap_file(const char *path);
|
||||||
void unmap_file(struct mm_file_t *mfile);
|
void unmap_file(struct mm_file_t *mfile);
|
||||||
int do_copy_tail(const char *src, const char *dest, int limit);
|
int do_copy_tail(const char *src, const char *dest, int limit);
|
||||||
int do_mv(char *src, char *dest);
|
int do_mv(char *src, char *dest);
|
||||||
int append_file(char *filename, char *text);
|
ssize_t append_file(const char *filename, const char *text, size_t tlen);
|
||||||
int mm_replace_str_line(struct mm_file_t *mfile, char *replace,
|
|
||||||
int line);
|
|
||||||
int replace_file_head(char *filename, char *text);
|
int replace_file_head(char *filename, char *text);
|
||||||
int overwrite_file(const char *filename, const char *value);
|
int overwrite_file(const char *filename, const char *value);
|
||||||
int readline(int fd, char buffer[MAXLINESIZE]);
|
int readline(int fd, char buffer[MAXLINESIZE]);
|
||||||
int file_read_string(const char *file, char *string, int size);
|
ssize_t file_read_string(const char *file, char *string, const int size);
|
||||||
void file_reset_init(const char *filename);
|
void file_reset_init(const char *filename);
|
||||||
int file_read_int(const char *filename, unsigned int *pcurrent);
|
int file_read_int(const char *filename, unsigned int *pcurrent);
|
||||||
int file_update_int(const char *filename, unsigned int current,
|
int file_update_int(const char *filename, unsigned int current,
|
||||||
@ -93,10 +97,10 @@ int space_available(const char *path, int quota);
|
|||||||
int count_lines_in_file(const char *filename);
|
int count_lines_in_file(const char *filename);
|
||||||
int read_full_binary_file(const char *path, unsigned long *size,
|
int read_full_binary_file(const char *path, unsigned long *size,
|
||||||
void **data);
|
void **data);
|
||||||
int file_read_key_value(const char *path, const char *key,
|
ssize_t file_read_key_value(char *value, const size_t limit, const char *path,
|
||||||
const size_t limit, char *value);
|
const char *key, size_t klen);
|
||||||
int file_read_key_value_r(const char *path, const char *key,
|
ssize_t file_read_key_value_r(char *value, const size_t limit, const char *path,
|
||||||
const size_t limit, char *value);
|
const char *key, size_t klen);
|
||||||
int ac_scandir(const char *dirp, struct dirent ***namelist,
|
int ac_scandir(const char *dirp, struct dirent ***namelist,
|
||||||
int (*filter)(const struct dirent *, const void *),
|
int (*filter)(const struct dirent *, const void *),
|
||||||
const void *farg,
|
const void *farg,
|
||||||
@ -106,10 +110,10 @@ 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_exactly(const struct dirent *entry, const void *arg);
|
||||||
int filter_filename_startswith(const struct dirent *entry,
|
int filter_filename_startswith(const struct dirent *entry,
|
||||||
const void *arg);
|
const void *arg);
|
||||||
int dir_contains(const char *dir, const char *filename, int exact);
|
int dir_contains(const char *dir, const char *filename, size_t flen, int exact);
|
||||||
int lsdir(const char *dir, char *fullname[], int limit);
|
int lsdir(const char *dir, char *fullname[], int limit);
|
||||||
int find_file(const char *dir, char *target_file, int depth, char *path[],
|
int find_file(const char *dir, const char *target_file, size_t tflen,
|
||||||
int limit);
|
int depth, char *path[], int limit);
|
||||||
int read_file(const char *path, unsigned long *size, void **data);
|
int read_file(const char *path, unsigned long *size, void **data);
|
||||||
int is_ac_filefmt(const char *file_fmt);
|
int is_ac_filefmt(const char *file_fmt);
|
||||||
int config_fmt_to_files(const char *file_fmt, char ***out);
|
int config_fmt_to_files(const char *file_fmt, char ***out);
|
||||||
|
@ -6,42 +6,43 @@
|
|||||||
#ifndef __LOG_SYS_H__
|
#ifndef __LOG_SYS_H__
|
||||||
#define __LOG_SYS_H__
|
#define __LOG_SYS_H__
|
||||||
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <systemd/sd-journal.h>
|
||||||
|
|
||||||
void do_log(int level,
|
void debug_log(int level, const char *func, int line, ...);
|
||||||
#ifdef DEBUG_ACRN_CRASHLOG
|
|
||||||
const char *func, int line,
|
|
||||||
#endif
|
|
||||||
...);
|
|
||||||
|
|
||||||
#define MAX_LOG_LEN 1024
|
|
||||||
#define LOG_LEVEL LOG_WARNING
|
#define LOG_LEVEL LOG_WARNING
|
||||||
|
|
||||||
#ifdef DEBUG_ACRN_CRASHLOG
|
#ifdef DEBUG_ACRN_CRASHLOG
|
||||||
#define LOGE(...) \
|
#define LOGE(...) \
|
||||||
do_log(LOG_ERR, __func__, __LINE__, __VA_ARGS__)
|
debug_log(LOG_ERR, __func__, __LINE__, __VA_ARGS__)
|
||||||
|
|
||||||
#define LOGW(...) \
|
#define LOGW(...) \
|
||||||
do_log(LOG_WARNING, __func__, __LINE__, __VA_ARGS__)
|
debug_log(LOG_WARNING, __func__, __LINE__, __VA_ARGS__)
|
||||||
|
|
||||||
#define LOGI(...) \
|
#define LOGI(...) \
|
||||||
do_log(LOG_INFO, __func__, __LINE__, __VA_ARGS__)
|
debug_log(LOG_INFO, __func__, __LINE__, __VA_ARGS__)
|
||||||
|
|
||||||
#define LOGD(...) \
|
#define LOGD(...) \
|
||||||
do_log(LOG_DEBUG, __func__, __LINE__, __VA_ARGS__)
|
debug_log(LOG_DEBUG, __func__, __LINE__, __VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
|
#define ac_log(level, ...) \
|
||||||
|
do { \
|
||||||
|
if (level <= LOG_LEVEL) \
|
||||||
|
sd_journal_print(level, __VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define LOGE(...) \
|
#define LOGE(...) \
|
||||||
do_log(LOG_ERR, __VA_ARGS__)
|
ac_log(LOG_ERR, __VA_ARGS__)
|
||||||
|
|
||||||
#define LOGW(...) \
|
#define LOGW(...) \
|
||||||
do_log(LOG_WARNING, __VA_ARGS__)
|
ac_log(LOG_WARNING, __VA_ARGS__)
|
||||||
|
|
||||||
#define LOGI(...) \
|
#define LOGI(...) \
|
||||||
do_log(LOG_INFO, __VA_ARGS__)
|
ac_log(LOG_INFO, __VA_ARGS__)
|
||||||
|
|
||||||
#define LOGD(...) \
|
#define LOGD(...) \
|
||||||
do_log(LOG_DEBUG, __VA_ARGS__)
|
ac_log(LOG_DEBUG, __VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -9,10 +9,12 @@
|
|||||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||||
#define s_not_expect(res, size) (res < 0 || (size_t)res >= size)
|
#define s_not_expect(res, size) (res < 0 || (size_t)res >= size)
|
||||||
|
|
||||||
|
char *get_line(const char *str, size_t str_size,
|
||||||
|
const char *area, size_t area_size,
|
||||||
|
const char *search_from, size_t *len);
|
||||||
ssize_t strlinelen(const char *str, size_t size);
|
ssize_t strlinelen(const char *str, size_t size);
|
||||||
char *strrstr(const char *s, const char *str);
|
char *strrstr(const char *s, const char *str);
|
||||||
char *next_line(char *buf);
|
char *strtrim(char *str, size_t len);
|
||||||
char *strtrim(char *str);
|
|
||||||
int strcnt(char *str, char c);
|
int strcnt(char *str, char c);
|
||||||
int str_split_ere(const char *str, size_t slen,
|
int str_split_ere(const char *str, size_t slen,
|
||||||
const char *fmt, size_t flen, ...);
|
const char *fmt, size_t flen, ...);
|
||||||
|
@ -4,46 +4,35 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <systemd/sd-journal.h>
|
#include <stdarg.h>
|
||||||
#include "log_sys.h"
|
#include "log_sys.h"
|
||||||
|
|
||||||
void do_log(const int level,
|
void debug_log(const int level, const char *func, const int line, ...)
|
||||||
#ifdef DEBUG_ACRN_CRASHLOG
|
|
||||||
const char *func, const int line,
|
|
||||||
#endif
|
|
||||||
...)
|
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
char *fmt;
|
char *fmt;
|
||||||
char log[MAX_LOG_LEN];
|
char *head;
|
||||||
int n = 0;
|
char *msg;
|
||||||
#ifdef DEBUG_ACRN_CRASHLOG
|
|
||||||
const char header_fmt[] = "<%-20s%5d>: ";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (level > LOG_LEVEL)
|
if (level > LOG_LEVEL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef DEBUG_ACRN_CRASHLOG
|
|
||||||
va_start(args, line);
|
va_start(args, line);
|
||||||
#else
|
|
||||||
va_start(args, level);
|
|
||||||
#endif
|
|
||||||
fmt = va_arg(args, char *);
|
fmt = va_arg(args, char *);
|
||||||
if (!fmt)
|
if (!fmt)
|
||||||
return;
|
return;
|
||||||
|
if (vasprintf(&msg, fmt, args) == -1)
|
||||||
#ifdef DEBUG_ACRN_CRASHLOG
|
return;
|
||||||
/* header */
|
|
||||||
n = snprintf(log, sizeof(log), header_fmt, func, line);
|
|
||||||
if (n < 0 || (size_t)n >= sizeof(log))
|
|
||||||
n = 0;
|
|
||||||
#endif
|
|
||||||
/* msg */
|
|
||||||
vsnprintf(log + n, sizeof(log) - (size_t)n, fmt, args);
|
|
||||||
log[sizeof(log) - 1] = 0;
|
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
sd_journal_print(level, "%s", log);
|
if (asprintf(&head, "<%-20s%5d>: ", func, line) == -1) {
|
||||||
|
free(msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sd_journal_print(level, "%s%s", head, msg);
|
||||||
|
free(msg);
|
||||||
|
free(head);
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,62 @@
|
|||||||
#include "log_sys.h"
|
#include "log_sys.h"
|
||||||
#include "fsutils.h"
|
#include "fsutils.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the first line containing specified string in given area.
|
||||||
|
*
|
||||||
|
* @param str A pointer to the string contained by target line.
|
||||||
|
* @param str_size String length of str.
|
||||||
|
* @param area A pointer to the area where target line may be located.
|
||||||
|
* This pointer will be returned if the specified string is in
|
||||||
|
* the first line of area (There is not '\n' located between area
|
||||||
|
* and the head of searched string).
|
||||||
|
* @param area_size String length of area.
|
||||||
|
* @param search_from A pointer where searching starts. It should be greater
|
||||||
|
* than or equal to area, and less than area + area_size.
|
||||||
|
* @param[out] len The length of target line (excludes \n), it only be modified
|
||||||
|
* when function returns successfully.
|
||||||
|
*
|
||||||
|
* @return a pointer to the head of target line within area (it may be greater
|
||||||
|
* than search_from).
|
||||||
|
* NULL will be returned if the specified string is not found in
|
||||||
|
* any lines (lines must end with '\n'. It means the real searching
|
||||||
|
* scope is from search_from to the last '\n' in area).
|
||||||
|
*/
|
||||||
|
char *get_line(const char *str, size_t str_size,
|
||||||
|
const char *area, size_t area_size,
|
||||||
|
const char *search_from, size_t *len)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
char *match;
|
||||||
|
char *tail;
|
||||||
|
ssize_t search_size = area + area_size - search_from;
|
||||||
|
|
||||||
|
if (!str || !str_size || !area || !area_size || !search_from || !len)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (search_from < area || search_from >= area + area_size ||
|
||||||
|
(size_t)search_size < str_size)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
match = memmem(search_from, search_size, str, str_size);
|
||||||
|
if (!match)
|
||||||
|
return NULL;
|
||||||
|
tail = memchr(match + str_size, '\n',
|
||||||
|
area + area_size - match - str_size);
|
||||||
|
if (!tail)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (p = match; p >= area; p--) {
|
||||||
|
if (*p == '\n') {
|
||||||
|
*len = tail - p - 1;
|
||||||
|
return (char *)(p + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*len = tail - area;
|
||||||
|
return (char *)area;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the length of line.
|
* Get the length of line.
|
||||||
*
|
*
|
||||||
@ -57,54 +113,32 @@ char *strrstr(const char *s, const char *substr)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *next_line(char *buf)
|
char *strtrim(char *str, size_t len)
|
||||||
{
|
{
|
||||||
|
size_t h_del = 0;
|
||||||
|
size_t reserve;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
p = strchr(buf, '\n');
|
if (!len)
|
||||||
/* if meet end of buf, the return value is also NULL */
|
return str;
|
||||||
if (p)
|
|
||||||
return p + 1;
|
|
||||||
|
|
||||||
return NULL;
|
for (p = str; p < str + len && *p == ' '; p++)
|
||||||
}
|
h_del++;
|
||||||
|
|
||||||
static char *strtriml(char *str)
|
reserve = len - h_del;
|
||||||
{
|
if (!reserve) {
|
||||||
char *p = str;
|
*str = '\0';
|
||||||
|
return str;
|
||||||
while (*p == ' ')
|
|
||||||
p++;
|
|
||||||
return memmove(str, p, strlen(p) + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *strtrimr(char *str)
|
|
||||||
{
|
|
||||||
size_t len;
|
|
||||||
char *end;
|
|
||||||
|
|
||||||
len = strlen(str);
|
|
||||||
if (len > 0) {
|
|
||||||
end = str + strlen(str) - 1;
|
|
||||||
while (*end == ' ' && end >= str) {
|
|
||||||
*end = 0;
|
|
||||||
end--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (p = str + len - 1; p >= str && *p == ' '; p--)
|
||||||
|
reserve--;
|
||||||
|
|
||||||
|
memmove(str, str + h_del, reserve);
|
||||||
|
*(str + reserve) = '\0';
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *strtrim(char *str)
|
|
||||||
{
|
|
||||||
if (str) {
|
|
||||||
strtrimr(str);
|
|
||||||
return strtriml(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int strcnt(char *str, char c)
|
int strcnt(char *str, char c)
|
||||||
{
|
{
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
|
@ -129,12 +129,11 @@ static int get_backtrace(int pid, int fd, int sig, const char *comm)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
membkt = exec_out2mem(GET_GDB_INFO, format);
|
len = exec_out2mem(&membkt, GET_GDB_INFO, format);
|
||||||
if (!membkt) {
|
if (len <= 0) {
|
||||||
LOGE("get gdb info failed\n");
|
LOGE("get gdb info failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
len = strlen(membkt);
|
|
||||||
ret = write(fd, membkt, len);
|
ret = write(fd, membkt, len);
|
||||||
free(membkt);
|
free(membkt);
|
||||||
if (ret != len) {
|
if (ret != len) {
|
||||||
|
Loading…
Reference in New Issue
Block a user