diff --git a/tools/acrn-crashlog/acrnprobe/android_events.c b/tools/acrn-crashlog/acrnprobe/android_events.c index 476c5c7dc..c9665edb6 100644 --- a/tools/acrn-crashlog/acrnprobe/android_events.c +++ b/tools/acrn-crashlog/acrnprobe/android_events.c @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -20,25 +21,27 @@ #define VM_WARNING_LINES 2000 #define LOOP_DEV_MAX 8 -static char *android_img = "/data/android/android.img"; +#define ANDROID_EVT_KEY_LEN 20 + +static const char *android_img = "/data/android/android.img"; char *loop_dev; /* Find the head of str, caller must guarantee that 'str' is not in * the first line. */ -static char *line_head(char *str) +static char *line_head(const char *str) { while (*str != '\n') str--; - return str + 1; + return (char *)(str + 1); } /* Find the next event that needs to be synced. * 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. */ -static char *vm_next_event_to_sync(char *cursor, struct vm_t *vm) +static char *vm_next_event_to_sync(const char *cursor, const struct vm_t *vm) { char *line_to_sync = (char *)~(0); char *syncevent; @@ -88,22 +91,29 @@ static char *vm_next_event_to_sync(char *cursor, struct vm_t *vm) if (line_to_sync == (char *)~(0)) return NULL; - else - return line_to_sync; + return line_to_sync; } -static int generate_log_vmrecord(char *path) +#define VMRECORD_HEAD_LINES 6 +#define VMRECORD_TAG_LEN 9 +#define VMRECORD_TAG_WAITING_SYNC " <==" +#define VMRECORD_TAG_NOT_FOUND "NOT_FOUND" +#define VMRECORD_TAG_SUCCESS " " +static int generate_log_vmrecord(const char *path) { - char *head = "/* This file records vm id synced/will-sync from VMs,\n" - " * the tag \"<==\" indicates the events waiting to sync.\n" - " */\n\n"; + const char * const head = + "/* DONT EDIT!\n" + " * This file records VM id synced or about to be synched,\n" + " * the tag \"<==\" indicates event waiting to sync.\n" + " * the tag \"NOT_FOUND\" indicates event not found in UOS.\n" + " */\n\n"; - LOGD("generate log_vmrecordid in (%s)\n", path); + LOGD("Generate (%s)\n", path); return overwrite_file(path, head); } -enum refresh_type_t { +enum stage1_refresh_type_t { MM_ONLY, MM_FILE }; @@ -115,8 +125,10 @@ enum refresh_type_t { * * The design reason is to give UOS some time to log to storage. */ -static int refresh_key_synced_stage1(struct sender_t *sender, struct vm_t *vm, - char *key, enum refresh_type_t type) +static int refresh_key_synced_stage1(const struct sender_t *sender, + struct vm_t *vm, + const char *key, + enum stage1_refresh_type_t type) { char log_new[64]; char *log_vmrecordid; @@ -132,7 +144,7 @@ static int refresh_key_synced_stage1(struct sender_t *sender, struct vm_t *vm, /* the length of key must be 20, and its value can not be * 00000000000000000000. */ - if ((strlen(key) == 20) && + if ((strlen(key) == ANDROID_EVT_KEY_LEN) && strcmp(key, "00000000000000000000")) { sprintf(vm->last_synced_line_key[sid], "%s", key); @@ -145,41 +157,57 @@ static int refresh_key_synced_stage1(struct sender_t *sender, struct vm_t *vm, if (!file_exists(log_vmrecordid)) generate_log_vmrecord(log_vmrecordid); - sprintf(log_new, "%s %s <==\n", vm->name, key); + sprintf(log_new, "%s %s %s\n", vm->name, key, + VMRECORD_TAG_WAITING_SYNC); append_file(log_vmrecordid, log_new); return 0; } - LOGE("try to record a invalid key (%s) for (%s)\n", + LOGE("try to record an invalid key (%s) for (%s)\n", key, vm->name); return -1; } -static int refresh_key_synced_stage2(struct mm_file_t *m_vm_records, char *key) +enum stage2_refresh_type_t { + SUCCESS, + NOT_FOUND +}; + +static int refresh_key_synced_stage2(const struct mm_file_t *m_vm_records, + const char *key, + enum stage2_refresh_type_t type) { - char *begin, *end; - char *p; + char *lhead, *ltail; + char *tag; - if (*key) { - begin = strstr(m_vm_records->begin, " <=="); - end = strrstr(m_vm_records->begin, key); - if (!begin || !end) - return -1; + if (!key || strlen(key) != ANDROID_EVT_KEY_LEN || !m_vm_records || + m_vm_records->size <= 0) + return -1; - end = strchr(end, '\n'); + lhead = strstr(m_vm_records->begin, key); + if (!lhead) + return -1; - for (p = begin; p < end; p++) { - if (*p == '<' || *p == '=') - *p = ' '; - } + ltail = strchr(lhead, '\n'); + if (!ltail) + return -1; - return 0; - } + tag = strstr(lhead, VMRECORD_TAG_WAITING_SYNC); + if (!tag || tag >= ltail) + return -1; - return -1; + /* re-mark symbol "<==" for synced key */ + if (type == SUCCESS) + memcpy(tag, VMRECORD_TAG_SUCCESS, VMRECORD_TAG_LEN); + else if (type == NOT_FOUND) + memcpy(tag, VMRECORD_TAG_NOT_FOUND, VMRECORD_TAG_LEN); + else + return -1; + + return 0; } -static int get_vm_history(struct vm_t *vm, struct sender_t *sender, +static int get_vm_history(struct vm_t *vm, const struct sender_t *sender, void **data) { char vm_history[PATH_MAX]; @@ -206,6 +234,7 @@ static int get_vm_history(struct vm_t *vm, struct sender_t *sender, if (ret) { LOGE("read (%s) with error (%s)\n", vm_history, strerror(errno)); + *data = NULL; return ret; } @@ -220,15 +249,16 @@ static int get_vm_history(struct vm_t *vm, struct sender_t *sender, return size; } -static void sync_lines_stage1(struct sender_t *sender, void *data[]) +static void sync_lines_stage1(const struct sender_t *sender, const void *data[]) { int id, sid; int ret; struct vm_t *vm; char *start; char *line_to_sync; - char vmkey[SHA_DIGEST_LENGTH + 1] = {0}; - char *vm_format = "%*[^ ]%*[ ]%[^ ]%*c"; + char vmkey[ANDROID_WORD_LEN]; + const char * const vm_format = + IGN_ONEWORD ANDROID_KEY_FMT IGN_RESTS; sid = sender_id(sender); if (sid == -1) @@ -265,7 +295,7 @@ static void sync_lines_stage1(struct sender_t *sender, void *data[]) vmkey[0] = 0; ret = sscanf(line_to_sync, vm_format, vmkey); if (ret != 1) { - LOGE("get a invalid line from (%s), skip\n", + LOGE("get an invalid line from (%s), skip\n", vm->name); start = next_line(line_to_sync); continue; @@ -281,15 +311,16 @@ static void sync_lines_stage1(struct sender_t *sender, void *data[]) } -static void sync_lines_stage2(struct sender_t *sender, void *data[], - void (*fn)(char*, struct vm_t *)) +static void sync_lines_stage2(const struct sender_t *sender, const void *data[], + int (*fn)(const char*, const struct vm_t *)) { struct mm_file_t *m_vm_records; char *line; char *cursor; - char *record_fmt = "%[^ ]%*[ ]%[^ ]%*c"; - char vm_name[64]; - char vmkey[SHA_DIGEST_LENGTH + 1] = {0}; + const char * const record_fmt = + VM_NAME_FMT ANDROID_KEY_FMT IGN_RESTS; + char vm_name[32]; + char vmkey[ANDROID_WORD_LEN]; int id; struct vm_t *vm; int ret; @@ -300,18 +331,21 @@ static void sync_lines_stage2(struct sender_t *sender, void *data[], strerror(errno)); return; } - if (!m_vm_records->size) { - LOGE("size(0b) of (%s)\n", sender->log_vmrecordid); - return; + if (!m_vm_records->size || + mm_count_lines(m_vm_records) < VMRECORD_HEAD_LINES) { + LOGE("(%s) invalid\n", sender->log_vmrecordid); + goto out; } - cursor = strstr(m_vm_records->begin, " <=="); + cursor = strstr(m_vm_records->begin, " " VMRECORD_TAG_WAITING_SYNC); if (!cursor) goto out; line = line_head(cursor); while (line) { char *vm_hist_line; + + vmkey[0] = 0; /* VMNAME xxxxxxxxxxxxxxxxxxxx <== */ ret = sscanf(line, record_fmt, vm_name, vmkey); if (ret != 2) { @@ -331,31 +365,43 @@ static void sync_lines_stage2(struct sender_t *sender, void *data[], vm_hist_line = strstr(data[id], vmkey); if (!vm_hist_line) { - LOGE("not find (%s) in (%s),", vmkey, vm->name); - LOGE("history_event in UOS was deleted?\n"); + LOGE("mark vmevent(%s) as unfound,", vmkey); + LOGE("history_event in UOS was recreated?\n"); + refresh_key_synced_stage2(m_vm_records, vmkey, + NOT_FOUND); break; } - fn(line_head(vm_hist_line), vm); + ret = fn(line_head(vm_hist_line), vm); + if (!ret) + refresh_key_synced_stage2(m_vm_records, vmkey, + SUCCESS); } - line = next_line(line); + cursor = next_line(line); + if (!cursor) + break; + + line = strstr(cursor, VMRECORD_TAG_WAITING_SYNC); + if (!line) + break; + + line = line_head(line); } out: - refresh_key_synced_stage2(m_vm_records, vmkey); unmap_file(m_vm_records); } /* This function only for initialization */ -static void get_last_line_synced(struct sender_t *sender) +static void get_last_line_synced(const struct sender_t *sender) { int id; int sid; int ret; struct vm_t *vm; - char vmkey[SHA_DIGEST_LENGTH + 10] = {0}; - char word[256]; + char vmkey[ANDROID_WORD_LEN]; + char vm_name[32]; if (!sender) return; @@ -375,11 +421,11 @@ static void get_last_line_synced(struct sender_t *sender) if (vm->last_synced_line_key[sid][0]) continue; - snprintf(word, sizeof(word), "%s ", vm->name); - ret = file_read_key_value_r(sender->log_vmrecordid, - word, vmkey); + snprintf(vm_name, sizeof(vm_name), "%s ", vm->name); + ret = file_read_key_value_r(sender->log_vmrecordid, vm_name, + sizeof(vmkey), vmkey); if (ret == -ENOENT) { - LOGD("no log_vmrecordid under (%s), will generete\n", + LOGD("no (%s), will generate\n", sender->log_vmrecordid); generate_log_vmrecord(sender->log_vmrecordid); continue; @@ -393,7 +439,6 @@ static void get_last_line_synced(struct sender_t *sender) continue; } - vmkey[SHA_DIGEST_LENGTH] = 0; ret = refresh_key_synced_stage1(sender, vm, vmkey, MM_ONLY); if (ret < 0) { LOGE("get a non-key vm event (%s) for (%s)\n", @@ -478,30 +523,30 @@ static char *setup_loop_dev(void) } /* find data partition, sector unit = 512 bytes */ - char patition_start[32] = {0}; - char sectors[32] = {0}; + char partition_start[32]; + char sectors[32]; unsigned long pstart; char *partition; - char *partition_fmt = "%*[^ ]%*[ ]%[^ ]%*[ ]%*[^ ]%*[ ]%[^ ]%*c"; + const char * const partition_fmt = + IGN_ONEWORD "%31[^ ]" IGN_SPACES + IGN_ONEWORD "%31[^ ]" IGN_RESTS; char *cursor = out; int ret; while (cursor && (partition = strstr(cursor, android_img))) { cursor = strchr(partition, '\n'); - memset(patition_start, 0, sizeof(patition_start)); - memset(sectors, 0, sizeof(sectors)); - - ret = sscanf(partition, partition_fmt, patition_start, sectors); + ret = sscanf(partition, partition_fmt, + partition_start, sectors); if (ret != 2) continue; - LOGD("start (%s) sectors(%s)\n", patition_start, sectors); + LOGD("start (%s) sectors(%s)\n", partition_start, sectors); /* size < 1G */ if (atoi(sectors) < 1 * 2 * 1024 * 1024) continue; - pstart = atol(patition_start) * 512; + pstart = atol(partition_start) * 512; if (pstart == 0) continue; @@ -522,6 +567,7 @@ static char *setup_loop_dev(void) if (ret != 0) LOGE("(losetup -d %s) failed, return %d\n", loop_dev, ret); + sleep(1); } } @@ -539,12 +585,13 @@ success: static int ping_vm_fs(char *loop_dev) { int id; + int res; int count = 0; struct vm_t *vm; struct mm_file_t *vm_hist; char vm_history[PATH_MAX]; char cmd[512]; - char prefix[] = "#V1.0 CURRENTUPTIME"; + const char prefix[] = "#V1.0 CURRENTUPTIME"; /* ensure history_event in uos available */ for_each_vm(id, vm, conf) { @@ -556,7 +603,15 @@ static int ping_vm_fs(char *loop_dev) snprintf(cmd, sizeof(cmd), "dump logs/history_event %s", vm_history); - debugfs_cmd(loop_dev, cmd, NULL); + res = remove(vm_history); + if (res == -1 && errno != ENOENT) + LOGE("remove %s failed\n", vm_history); + + res = debugfs_cmd(loop_dev, cmd, NULL); + if (res) { + vm->online = 0; + continue; + } vm_hist = mmap_file(vm_history); if (vm_hist == NULL) { @@ -579,8 +634,14 @@ static int ping_vm_fs(char *loop_dev) return count; } -void refresh_vm_history(struct sender_t *sender, - void (*fn)(char*, struct vm_t *)) +/* This function searches all android vms' new events and call the fn for + * each event. + * + * Note that: fn should return 0 to indicate event has been handled, + * or fn will be called in a time loop until it returns 0. + */ +void refresh_vm_history(const struct sender_t *sender, + int (*fn)(const char*, const struct vm_t *)) { int ret; int id; @@ -612,6 +673,6 @@ void refresh_vm_history(struct sender_t *sender, get_vm_history(vm, sender, &data[id]); } - sync_lines_stage2(sender, data, fn); - sync_lines_stage1(sender, data); + sync_lines_stage2(sender, (const void **)data, fn); + sync_lines_stage1(sender, (const void **)data); } diff --git a/tools/acrn-crashlog/acrnprobe/include/android_events.h b/tools/acrn-crashlog/acrnprobe/include/android_events.h index b005783fd..6030809a5 100644 --- a/tools/acrn-crashlog/acrnprobe/include/android_events.h +++ b/tools/acrn-crashlog/acrnprobe/include/android_events.h @@ -9,7 +9,33 @@ extern char *loop_dev; -void refresh_vm_history(struct sender_t *sender, - void (*fn)(char*, struct vm_t *)); +#define VMEVT_HANDLED 0 +#define VMEVT_DEFER -1 + +#define IGN_SPACES "%*[ ]" +#define IGN_RESTS "%*c" +#define IGN_ONEWORD "%*[^ ]" IGN_SPACES +#define VM_NAME_FMT "%8[A-Z0-9]" IGN_SPACES + +/* These below macros were defined to obtain strings from + * andorid history_event + */ +#define ANDROID_WORD_LEN 32 + +/* Strings are constructed by A-Z, len < 8, e.g., CRASH REBOOT */ +#define ANDROID_ENEVT_FMT "%8[A-Z]" IGN_SPACES +/* Hashkeys are constructed by 0-9&a-z, len = 20, e.g., 0b34ae1afba54aee5cd0. + * But the hashkey was printed to history_event file in andorid side by using + * format "%22s", so also using %22 here. + */ +#define ANDROID_KEY_FMT "%22[0-9a-z]" IGN_SPACES +/* Strings, e.g., 2017-11-11/03:12:59 */ +#define ANDROID_LONGTIME_FMT "%20[0-9:/-]" IGN_SPACES +/* It's a time or a subtype of event, e.g., JAVACRASH POWER-ON 424874:19:56 */ +#define ANDROID_TYPE_FMT "%16[A-Z0-9_:-]" IGN_SPACES +#define ANDROID_LINE_REST_FMT "%4096[^\n]" IGN_RESTS + +void refresh_vm_history(const struct sender_t *sender, + int (*fn)(const char*, const struct vm_t *)); #endif diff --git a/tools/acrn-crashlog/acrnprobe/include/load_conf.h b/tools/acrn-crashlog/acrnprobe/include/load_conf.h index b696e003c..3bcd536bd 100644 --- a/tools/acrn-crashlog/acrnprobe/include/load_conf.h +++ b/tools/acrn-crashlog/acrnprobe/include/load_conf.h @@ -203,7 +203,7 @@ struct conf_t conf; int load_conf(const char *path); struct trigger_t *get_trigger_by_name(char *name); struct log_t *get_log_by_name(char *name); -int sender_id(struct sender_t *sender); +int sender_id(const struct sender_t *sender); struct sender_t *get_sender_by_name(char *name); enum event_type_t get_conf_by_wd(int wd, void **private); struct crash_t *get_crash_by_wd(int wd); diff --git a/tools/acrn-crashlog/acrnprobe/load_conf.c b/tools/acrn-crashlog/acrnprobe/load_conf.c index 09df435f7..936ac9716 100644 --- a/tools/acrn-crashlog/acrnprobe/load_conf.c +++ b/tools/acrn-crashlog/acrnprobe/load_conf.c @@ -260,7 +260,7 @@ enum event_type_t get_conf_by_wd(int wd, void **private) } -int sender_id(struct sender_t *s) +int sender_id(const struct sender_t *s) { int id; struct sender_t *sender; diff --git a/tools/acrn-crashlog/acrnprobe/main.c b/tools/acrn-crashlog/acrnprobe/main.c index 9c799e1db..6302cdf00 100644 --- a/tools/acrn-crashlog/acrnprobe/main.c +++ b/tools/acrn-crashlog/acrnprobe/main.c @@ -65,15 +65,18 @@ int main(int argc, char *argv[]) int op; struct sender_t *sender; char cfg[PATH_MAX]; - char *config_path[2] = {CONFIG_CUSTOMIZE, - CONFIG_INSTALL}; - struct option opts[] = { + const char * const config_path[2] = { + CONFIG_CUSTOMIZE, + CONFIG_INSTALL + }; + const struct option opts[] = { { "config", required_argument, NULL, 'c' }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, { NULL, 0, NULL, 0 } }; + cfg[0] = 0; while ((op = getopt_long(argc, argv, "c:hV", opts, NULL)) != -1) { switch (op) { diff --git a/tools/acrn-crashlog/acrnprobe/property.c b/tools/acrn-crashlog/acrnprobe/property.c index c6b5ee591..d83284295 100644 --- a/tools/acrn-crashlog/acrnprobe/property.c +++ b/tools/acrn-crashlog/acrnprobe/property.c @@ -70,7 +70,8 @@ static int get_buildversion(struct sender_t *sender) char *logbuildid; char *currentbuild = gbuildversion; - ret = file_read_key_value(OS_VERSION, OS_VERSION_KEY, gbuildversion); + ret = file_read_key_value(OS_VERSION, OS_VERSION_KEY, + sizeof(gbuildversion), gbuildversion); if (ret <= 0) { LOGE("failed to get version from %s, error (%s)\n", OS_VERSION, strerror(-ret)); diff --git a/tools/acrn-crashlog/acrnprobe/sender.c b/tools/acrn-crashlog/acrnprobe/sender.c index 91b0ab3d4..5b7c62f31 100644 --- a/tools/acrn-crashlog/acrnprobe/sender.c +++ b/tools/acrn-crashlog/acrnprobe/sender.c @@ -276,7 +276,7 @@ static void get_log_cmd(struct log_t *log, char *desdir) } #ifdef HAVE_TELEMETRICS_CLIENT -static bool telemd_send_data(char *payload, char *eventid, uint32_t severity, +static int telemd_send_data(char *payload, char *eventid, uint32_t severity, char *class) { int res; @@ -312,12 +312,12 @@ static bool telemd_send_data(char *payload, char *eventid, uint32_t severity, } tm_free_record(handle); - return true; + return 0; free: tm_free_record(handle); fail: - return false; + return -1; } static void telemd_get_log(struct log_t *log, void *data) @@ -638,14 +638,15 @@ static void telemd_send_reboot(void) free(class); } -static void telemd_new_vmevent(char *line_to_sync, struct vm_t *vm) +static int telemd_new_vmevent(const char *line_to_sync, + const struct vm_t *vm) { - char event[96] = {0}; - char longtime[96] = {0}; - char type[96] = {0}; - char rest[PATH_MAX] = {0}; - char *vmlogpath[1] = {0}; - char vmkey[SHA_DIGEST_LENGTH + 1] = {0}; + char event[ANDROID_WORD_LEN]; + char longtime[ANDROID_WORD_LEN]; + char type[ANDROID_WORD_LEN]; + char rest[PATH_MAX]; + char *vmlogpath = NULL; + char vmkey[ANDROID_WORD_LEN]; char *log; char *class; char *eventid; @@ -653,7 +654,8 @@ static void telemd_new_vmevent(char *line_to_sync, struct vm_t *vm) int count; int i; uint32_t severity; - int ret; + int res; + int ret = VMEVT_HANDLED; /* VM events in history_event look like this: * @@ -662,13 +664,15 @@ static void telemd_new_vmevent(char *line_to_sync, struct vm_t *vm) * "REBOOT xxxxxxxxxxxxxxxxxxxx 2011-11-11/11:20:51 POWER-ON * 0000:00:00" */ - char *vm_format = "%[^ ]%*[ ]%[^ ]%*[ ]%[^ ]%*[ ]%[^ ]%*[ ]%[^\n]%*c"; + const char * const vm_format = + ANDROID_ENEVT_FMT ANDROID_KEY_FMT ANDROID_LONGTIME_FMT + ANDROID_TYPE_FMT ANDROID_LINE_REST_FMT; - ret = sscanf(line_to_sync, vm_format, event, vmkey, longtime, + res = sscanf(line_to_sync, vm_format, event, vmkey, longtime, type, rest); - if (ret != 5) { - LOGE("get a invalied line from (%s), skip\n", vm->name); - return; + if (res != 5) { + LOGE("get an invalid line from (%s), skip\n", vm->name); + return VMEVT_HANDLED; } if (strcmp(event, "CRASH") == 0) @@ -679,60 +683,77 @@ static void telemd_new_vmevent(char *line_to_sync, struct vm_t *vm) /* if line contains log, fill vmlogpath */ log = strstr(rest, "/logs/"); if (log) { - struct sender_t *crashlog = get_sender_by_name("crashlog"); + struct sender_t *crashlog; - ret = find_file(crashlog->outdir, log + strlen("/logs/"), - 2, vmlogpath, 1); - if (ret < 0) { + crashlog = get_sender_by_name("crashlog"); + if (!crashlog) + return VMEVT_HANDLED; + + res = find_file(crashlog->outdir, log + strlen("/logs/"), + 2, &vmlogpath, 1); + if (res < 0) { LOGE("find (%s) in (%s) failed, strerror (%s)\n", log + strlen("/logs/"), crashlog->outdir, - strerror(-ret)); - return; + strerror(-res)); + return VMEVT_DEFER; } } - ret = asprintf(&class, "%s/%s/%s", vm->name, event, type); - if (ret < 0) { + res = asprintf(&class, "%s/%s/%s", vm->name, event, type); + if (res < 0) { LOGE("compute string failed, out of memory\n"); + ret = VMEVT_DEFER; goto free_vmlogpath; } eventid = generate_eventid256(class); if (eventid == NULL) { LOGE("generate eventid failed, error (%s)\n", strerror(errno)); + ret = VMEVT_DEFER; goto free_class; } - if (vmlogpath[0] == 0) { - telemd_send_data("no logs", eventid, severity, class); + if (!vmlogpath) { + res = telemd_send_data("no logs", eventid, severity, class); + if (res == -1) + ret = VMEVT_DEFER; + goto free; } /* send logs */ - count = lsdir(vmlogpath[0], files, ARRAY_SIZE(files)); + count = lsdir(vmlogpath, files, ARRAY_SIZE(files)); if (count > 2) { for (i = 0; i < count; i++) { if (!strstr(files[i], "/.") && - !strstr(files[i], "/..")) - telemd_send_data(files[i], eventid, severity, - class); + !strstr(files[i], "/..")) { + res = telemd_send_data(files[i], eventid, + severity, class); + if (res == -1) + ret = VMEVT_DEFER; + } } } else if (count == 2) { char *content; - ret = asprintf(&content, "no logs under (%s)", vmlogpath[0]); - if (ret < 0) { + res = asprintf(&content, "no logs under (%s)", vmlogpath); + if (res > 0) { + res = telemd_send_data(content, eventid, severity, + class); + if (res == -1) + ret = VMEVT_DEFER; + free(content); + } else { LOGE("compute string failed, out of memory\n"); - goto free; + ret = VMEVT_DEFER; } - - telemd_send_data(content, eventid, severity, class); - free(content); } else if (count < 0) { - LOGE("lsdir (%s) failed, error (%s)\n", vmlogpath[0], + LOGE("lsdir (%s) failed, error (%s)\n", vmlogpath, strerror(-count)); + ret = VMEVT_DEFER; } else { - LOGE("get (%d) files in (%s) ???\n", count, vmlogpath[0]); + LOGE("get (%d) files in (%s) ???\n", count, vmlogpath); + ret = VMEVT_DEFER; } while (count > 0) @@ -743,8 +764,10 @@ free: free_class: free(class); free_vmlogpath: - if (vmlogpath[0]) - free(vmlogpath[0]); + if (vmlogpath) + free(vmlogpath); + + return ret; } static void telemd_send(struct event_t *e) @@ -961,19 +984,21 @@ static void crashlog_send_reboot(void) free(key); } -static void crashlog_new_vmevent(char *line_to_sync, struct vm_t *vm) +static int crashlog_new_vmevent(const char *line_to_sync, + const struct vm_t *vm) { struct sender_t *crashlog; - char event[96] = {0}; - char longtime[96] = {0}; - char type[96] = {0}; - char rest[PATH_MAX] = {0}; - char vmkey[SHA_DIGEST_LENGTH + 1] = {0}; + char event[ANDROID_WORD_LEN]; + char longtime[ANDROID_WORD_LEN]; + char type[ANDROID_WORD_LEN]; + char rest[PATH_MAX]; + char vmkey[ANDROID_WORD_LEN]; char *vmlogpath = NULL; char *key; char *log; char *cmd; - int ret; + int ret = VMEVT_HANDLED; + int res; int quota; char *dir; @@ -984,35 +1009,38 @@ static void crashlog_new_vmevent(char *line_to_sync, struct vm_t *vm) * "REBOOT xxxxxxxxxxxxxxxxxxxx 2011-11-11/11:20:51 POWER-ON * 0000:00:00" */ - char *vm_format = "%[^ ]%*[ ]%[^ ]%*[ ]%[^ ]%*[ ]%[^ ]%*[ ]%[^\n]%*c"; + const char * const vm_format = + ANDROID_ENEVT_FMT ANDROID_KEY_FMT ANDROID_LONGTIME_FMT + ANDROID_TYPE_FMT ANDROID_LINE_REST_FMT; - ret = sscanf(line_to_sync, vm_format, event, vmkey, longtime, + res = sscanf(line_to_sync, vm_format, event, vmkey, longtime, type, rest); - if (ret != 5) { - LOGE("get a invalied line from (%s), skip\n", vm->name); - return; + if (res != 5) { + LOGE("get an invalid line from (%s), skip\n", vm->name); + return ret; } crashlog = get_sender_by_name("crashlog"); if (!crashlog) - return; + return ret; quota = atoi(crashlog->spacequota); if (!space_available(crashlog->outdir, quota)) { hist_raise_infoerror("SPACE_FULL"); - return; + return ret; } key = generate_event_id("SOS", vmkey); if (key == NULL) { LOGE("generate event id failed, error (%s)\n", strerror(errno)); - return; + return VMEVT_DEFER; } dir = generate_log_dir(MODE_VMEVENT, key); if (dir == NULL) { LOGE("generate crashlog dir failed\n"); + ret = VMEVT_DEFER; goto free_key; } @@ -1020,20 +1048,32 @@ static void crashlog_new_vmevent(char *line_to_sync, struct vm_t *vm) */ log = strstr(rest, "/logs/"); if (log) { - ret = asprintf(&vmlogpath, "%s", log + 1); - if (ret < 0) { + res = asprintf(&vmlogpath, "%s", log + 1); + if (res < 0) { LOGE("compute string failed, out of memory\n"); + remove(dir); + ret = VMEVT_DEFER; goto free_dir; } - ret = asprintf(&cmd, "rdump %s %s", vmlogpath, dir); - if (ret < 0) { + res = asprintf(&cmd, "rdump %s %s", vmlogpath, dir); + if (res < 0) { LOGE("compute string failed, out of memory\n"); free(vmlogpath); + remove(dir); + ret = VMEVT_DEFER; goto free_dir; } - debugfs_cmd(loop_dev, cmd, NULL); + res = debugfs_cmd(loop_dev, cmd, NULL); + if (res) { + LOGE("debugfs cmd %s failed (%d)\n", cmd, res); + res = remove(dir); + if (res == -1 && errno != ENOENT) + LOGE("remove %s faield (%d)\n", dir, -errno); + ret = VMEVT_DEFER; + goto free_dir; + } free(cmd); free(vmlogpath); @@ -1047,6 +1087,8 @@ free_dir: free(dir); free_key: free(key); + + return ret; } static void crashlog_send(struct event_t *e) @@ -1095,7 +1137,7 @@ int init_sender(void) if (!sender) continue; - ret = asprintf(&sender->log_vmrecordid, "%s/vmrecordid", + ret = asprintf(&sender->log_vmrecordid, "%s/VM_eventsID.log", sender->outdir); if (ret < 0) { LOGE("compute string failed, out of memory\n"); diff --git a/tools/acrn-crashlog/common/fsutils.c b/tools/acrn-crashlog/common/fsutils.c index 700ef2190..ccfda9764 100644 --- a/tools/acrn-crashlog/common/fsutils.c +++ b/tools/acrn-crashlog/common/fsutils.c @@ -94,6 +94,9 @@ int mm_count_lines(struct mm_file_t *mfile) if (!mfile || mfile->size < 0) return -EINVAL; + if (!mfile->size) + return 0; + return strcnt(mfile->begin, '\n'); } @@ -432,7 +435,7 @@ int replace_file_head(char *filename, char *text) * * @return 0 if successful, or a negative errno-style value if not. */ -int overwrite_file(char *filename, char *value) +int overwrite_file(const char *filename, const char *value) { FILE *fp; int ret = 0; @@ -833,11 +836,13 @@ close: return -1; } -static int _file_read_key_value(char *path, char op, char *key, char *value) +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; - int len; + size_t len; char *data; char *msg = NULL; char *end, *start; @@ -855,6 +860,10 @@ static int _file_read_key_value(char *path, char op, char *key, char *value) size = get_file_size(path); if (size < 0) return size; + if (!size) { + errno = ENOMSG; + return -errno; + } fd = open(path, O_RDONLY); if (fd < 0) @@ -872,12 +881,14 @@ static int _file_read_key_value(char *path, char op, char *key, char *value) errno = ENOMSG; goto unmap; } - end = strchr(msg, '\n'); + + start = msg + strlen(key); + end = strchr(start, '\n'); if (end == NULL) end = data + size; - start = msg + strlen(key); len = end - start; + len = MIN(len, limit - 1); memcpy(value, start, len); *(value + len) = 0; @@ -893,14 +904,16 @@ close: return -errno; } -int file_read_key_value(char *path, char *key, char *value) +int file_read_key_value(const char *path, const char *key, + const size_t limit, char *value) { - return _file_read_key_value(path, 'l', key, value); + return _file_read_key_value(path, 'l', key, limit, value); } -int file_read_key_value_r(char *path, char *key, char *value) +int file_read_key_value_r(const char *path, const char *key, + const size_t limit, char *value) { - return _file_read_key_value(path, 'r', key, value); + return _file_read_key_value(path, 'r', key, limit, value); } int dir_contains(const char *dir, const char *filename, int exact, diff --git a/tools/acrn-crashlog/common/include/fsutils.h b/tools/acrn-crashlog/common/include/fsutils.h index b52a4e021..a3305dd00 100644 --- a/tools/acrn-crashlog/common/include/fsutils.h +++ b/tools/acrn-crashlog/common/include/fsutils.h @@ -81,7 +81,7 @@ int append_file(char *filename, char *text); int mm_replace_str_line(struct mm_file_t *mfile, char *replace, int line); int replace_file_head(char *filename, char *text); -int overwrite_file(char *filename, char *value); +int overwrite_file(const char *filename, const char *value); int readline(int fd, char buffer[MAXLINESIZE]); int file_read_string(const char *file, char *string, int size); void file_reset_init(const char *filename); @@ -93,8 +93,10 @@ int space_available(char *path, int quota); int count_lines_in_file(const char *filename); int read_full_binary_file(const char *path, unsigned long *size, void **data); -int file_read_key_value(char *path, char *key, char *value); -int file_read_key_value_r(char *path, char *key, char *value); +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 lsdir(const char *dir, char *fullname[], int limit); diff --git a/tools/acrn-crashlog/common/include/strutils.h b/tools/acrn-crashlog/common/include/strutils.h index 1873feb1d..83ca7d066 100644 --- a/tools/acrn-crashlog/common/include/strutils.h +++ b/tools/acrn-crashlog/common/include/strutils.h @@ -9,7 +9,7 @@ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) int strlinelen(char *str); -char *strrstr(char *s, char *str); +char *strrstr(const char *s, const char *str); char *next_line(char *buf); char *strtrim(char *str); int strcnt(char *str, char c); diff --git a/tools/acrn-crashlog/common/strutils.c b/tools/acrn-crashlog/common/strutils.c index f67b3945b..5badfa073 100644 --- a/tools/acrn-crashlog/common/strutils.c +++ b/tools/acrn-crashlog/common/strutils.c @@ -37,16 +37,16 @@ int strlinelen(char *str) * @return a pointer to the beginning of the substring, * or NULL if the substring is not found. */ -char *strrstr(char *s, char *substr) +char *strrstr(const char *s, const char *substr) { - char *found; - char *p = s; + const char *found; + const char *p = s; while ((found = strstr(p, substr))) p = found + 1; if (p != s) - return p - 1; + return (char *)(p - 1); return NULL; }