/** * @brief performs a copy of the virtual file exposed by the LM_DUMP kernel * module and raises a 'RAMDUMP' event. * * @param reason - string containing the translated startup reason * * @retval returns -1 if a problem occurs (no LM_DUMP file..). 0 otherwise. */ static int crashlog_check_ramdump(const char * reason) { char destination[PATHMAX] = {'\0'}; char *crashtype = RAMDUMP_EVENT; int dir; const char *dateshort = get_current_time_short(1); char *key; dir = find_new_crashlog_dir(MODE_CRASH); if (dir < 0) { LOGE("%s: Cannot get a valid new crash directory...\n", __FUNCTION__); key = raise_event(CRASHEVENT, crashtype, NULL, NULL); LOGE("%-8s%-22s%-20s%s\n", CRASHEVENT, key, get_current_time_long(0), crashtype); free(key); return -1; } /* Copy */ if( !file_exists(LM_DUMP_FILE) ) LOGE("%s: can't find file %s - error is %s.\n", __FUNCTION__, LM_DUMP_FILE, strerror(errno) ); else { snprintf(destination, sizeof(destination), "%s%d/%s_%s.bin", CRASH_DIR, dir, SAVED_LM_BUFFER_NAME, dateshort); do_copy_eof(LM_DUMP_FILE, destination); } if ( !file_exists(LBR_DUMP_FILE) ) LOGE("%s: can't find file %s - error is %s.\n", __FUNCTION__, LBR_DUMP_FILE, strerror(errno) ); else { destination[0] = '\0'; snprintf(destination, sizeof(destination), "%s%d/%s_%s.txt", CRASH_DIR, dir, SAVED_LBR_BUFFER_NAME, dateshort); do_copy_eof(LBR_DUMP_FILE, destination); } do_last_kmsg_copy(dir); /* If startup reason contains "WDT_" without "FAKE", retrieve WDT crash event context */ if (strstr(reason, "WDT_") && !strstr(reason, "FAKE")) { snprintf(destination, sizeof(destination), "%s%d/", CRASH_DIR, dir); flush_aplog(APLOG_BOOT, "WDT", &dir, get_current_time_short(0)); usleep(TIMEOUT_VALUE); do_log_copy("WDT", dir, get_current_time_short(0), APLOG_TYPE); } destination[0] = '\0'; snprintf(destination, sizeof(destination), "%s%d/", CRASH_DIR, dir); key = raise_event(CRASHEVENT, crashtype, NULL, destination); LOGE("%-8s%-22s%-20s%s %s\n", CRASHEVENT, key, get_current_time_long(0), crashtype, destination); free(key); return 0; }
/** * @brief performs all checks required in RAMDUMP mode. * In this mode, numerous checks are bypassed. * * @param[in] test : test mode flag * * @retval returns -1 if a problem occurs (no LM_DUMP file..). 0 otherwise. */ int do_ramdump_checks(int test) { char startupreason[32] = { '\0', }; char watchdog[16] = { '\0', }; char lastuptime[32] = { '\0', }; char *key; strcpy(watchdog,"WDT"); /* Read the wake-up source */ read_startupreason(startupreason); /* Get the last UPTIME value and write current UPTIME one in history events file */ uptime_history(lastuptime); /* Change log directories permission rights */ update_logs_permission(); /* Checks for panic */ crashlog_check_panic_events(startupreason, watchdog, test); /* Dump Lakemore file and raises CRASH RAMDUMP event */ crashlog_check_ramdump(startupreason); /* Raise REBOOT event*/ key = raise_event(SYS_REBOOT, RAMCONSOLE, NULL, NULL); LOGE("%-8s%-22s%-20s%s\n", SYS_REBOOT, key, get_current_time_long(0), RAMCONSOLE); free(key); request_global_reset(); return 0; }
/** * @brief Handles treatments to do when one or severals * directories that should be watched by crashlogd couldn't * have been added to inotify watcher. */ void handle_missing_watched_dir() { int idx; const char * date = get_current_time_long(1); /* Raise first an error */ raise_infoerror(ERROREVENT, CRASHLOG_WATCHER_ERROR); /* Then raise an infoevent for each failed watched directory */ for (idx = 0 ; idx < (int)DIM(wd_array) ; idx++) { if (wd_array[idx].wd >= 0 && wd_array[idx].inotify_error == 0) continue; /* Skip if well watched */ int alreadydone = 0, j; /* Skip already treated directories */ for (j = 0 ; j < idx ; j++) { if ( !strcmp(wd_array[j].eventpath, wd_array[idx].eventpath) ) { alreadydone = 1; break; } } if (alreadydone) continue; create_infoevent(CRASHLOG_WATCHER_INFOEVENT, wd_array[idx].eventpath, strerror(wd_array[idx].inotify_error), (char *)date ); } }
/** * Create a crashfile with given params. * * @param dir Where to generate crashfile. * @param event Event name. * @param hashkey Event id. * @param type Subtype of this event. * @param data* String obtained by get_data. */ void generate_crashfile(const char *dir, const char *event, size_t elen, const char *hashkey, size_t hlen, const char *type, size_t tlen, const char *data0, size_t d0len, const char *data1, size_t d1len, const char *data2, size_t d2len) { char *buf; char *path; char *tail; char datetime[LONG_TIME_SIZE]; char uptime[UPTIME_SIZE]; int hours; const int fmtsize = 128; size_t ltlen; int n; int filesize; if (!dir || !event || !elen || !hashkey || !hlen || !type || !tlen) return; if (d0len > 0 && !data0) return; if (d1len > 0 && !data1) return; if (d2len > 0 && !data2) return; ltlen = get_current_time_long(datetime); if (!ltlen) return; n = get_uptime_string(uptime, &hours); if (n < 0) return; filesize = fmtsize + ltlen + n + elen + hlen + tlen + d0len + d1len + d2len + strnlen(guuid, UUID_SIZE) + strnlen(gbuildversion, BUILD_VERSION_SIZE); buf = malloc(filesize); if (buf == NULL) { LOGE("out of memory\n"); return; } tail = cf_line(buf, "EVENT=", 6, event, elen); tail = cf_line(tail, "ID=", 3, hashkey, hlen); tail = cf_line(tail, "DEVICEID=", 9, guuid, strnlen(guuid, UUID_SIZE)); tail = cf_line(tail, "DATE=", 5, datetime, ltlen); tail = cf_line(tail, "UPTIME=", 7, uptime, n); tail = cf_line(tail, "BUILD=", 6, gbuildversion, strnlen(gbuildversion, BUILD_VERSION_SIZE)); tail = cf_line(tail, "TYPE=", 5, type, tlen); if (d0len) tail = cf_line(tail, "DATA0=", 6, data0, d0len); if (d1len) tail = cf_line(tail, "DATA1=", 6, data1, d1len); if (d2len) tail = cf_line(tail, "DATA2=", 6, data2, d2len); tail = mempcpy(tail, "_END\n", 5); *tail = '\0'; if (asprintf(&path, "%s/crashfile", dir) == -1) { LOGE("out of memory\n"); free(buf); return; } if (overwrite_file(path, buf) != 0) LOGE("failed to new crashfile (%s), error (%s)\n", path, strerror(errno)); free(buf); free(path); }