--- src/journal/coredumpctl.c | 258 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 207 insertions(+), 51 deletions(-)
diff --git a/src/journal/coredumpctl.c b/src/journal/coredumpctl.c index b6e5581..9ad8d3b 100644 --- a/src/journal/coredumpctl.c +++ b/src/journal/coredumpctl.c @@ -43,7 +43,7 @@ static enum { } arg_action = ACTION_LIST; static Set *matches = NULL; -static FILE* output = NULL; +static const char* output_path = NULL; static char* field = NULL; static int arg_no_pager = false; @@ -75,6 +75,21 @@ static Set *new_matches(void) { return NULL; } + tmp = strdup("MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b2"); + if (!tmp) { + log_oom(); + set_free(set); + return NULL; + } + + r = set_put(set, tmp); + if (r < 0) { + log_error("failed to add to set: %s", strerror(-r)); + free(tmp); + set_free(set); + return NULL; + } + return set; } @@ -183,17 +198,12 @@ static int parse_argv(int argc, char *argv[]) { break; case 'o': - if (output) { + if (output_path) { log_error("cannot set output more than once"); return -EINVAL; } - output = fopen(optarg, "we"); - if (!output) { - log_error("writing to '%s': %m", optarg); - return -errno; - } - + output_path = optarg; break; case 'F': @@ -292,15 +302,16 @@ static int print_entry(FILE* file, sd_journal *j, int had_legend) { SD_JOURNAL_FOREACH_DATA(j, d, l) { retrieve(d, l, "COREDUMP_PID", &pid); - retrieve(d, l, "COREDUMP_PID", &pid); retrieve(d, l, "COREDUMP_UID", &uid); retrieve(d, l, "COREDUMP_GID", &gid); retrieve(d, l, "COREDUMP_SIGNAL", &sgnl); retrieve(d, l, "COREDUMP_EXE", &exe); - if (!exe) + if (!exe) { retrieve(d, l, "COREDUMP_COMM", &exe); - if (!exe) + } + if (!exe) { retrieve(d, l, "COREDUMP_CMDLINE", &exe); + } } if (!pid && !uid && !gid && !sgnl && !exe) { @@ -379,12 +390,23 @@ static int focus(sd_journal *j) { } static int dump_core(sd_journal* j) { - const void *data; + const char *data; size_t len, ret; int r; + _cleanup_fclose_ + FILE* output = NULL; + assert(j); + if (output_path) { + output = fopen(output_path, "we"); + if (!output) { + log_error("writing to '%s': %m", optarg); + return -errno; + } + } + /* We want full data, nothing truncated. */ sd_journal_set_data_threshold(j, 0); @@ -399,20 +421,103 @@ static int dump_core(sd_journal* j) { return -ENOTTY; } - r = sd_journal_get_data(j, "COREDUMP", (const void**) &data, &len); + r = sd_journal_get_data(j, "MESSAGE_ID", (const void **) &data, &len); if (r < 0) { - log_error("Failed to retrieve COREDUMP field: %s", strerror(-r)); + log_error("Failed to retrieve MESSAGE_ID field: %s", strerror(-r)); return r; } - assert(len >= 9); - data = (const uint8_t*) data + 9; - len -= 9; + assert(len >= 11); + + if (strcmp(data + 11, "fc2e22bc6ee647b6b90729ab34a250b1") == 0) { + r = sd_journal_get_data(j, "COREDUMP", (const void**) &data, &len); + if (r < 0) { + log_error("Failed to retrieve COREDUMP field: %s", strerror(-r)); + return r; + } + + assert(len >= 9); + data += 9; + len -= 9; - ret = fwrite(data, len, 1, output ? output : stdout); - if (ret != 1) { - log_error("dumping coredump: %m (%zu)", ret); - return -errno; + ret = fwrite(data, len, 1, output ? output : stdout); + if (ret != 1) { + log_error("dumping coredump: %m (%zu)", ret); + return -errno; + } + } + else if (strcmp(data + 11, "fc2e22bc6ee647b6b90729ab34a250b2") == 0) { + _cleanup_free_ char *coredump = NULL; + _cleanup_fclose_ FILE *fcoredump = NULL; + _cleanup_fclose_ FILE *fout = NULL; + const char * corepath = NULL; + const char * machineid = NULL; + + r = sd_journal_get_data(j, "COREDUMP_FILE", (const void**) &corepath, &len); + if (r < 0) { + log_error("Failed to retrieve COREDUMP_FILE field: %s", strerror(-r)); + return r; + } + + r = sd_journal_get_data(j, "_MACHINE_ID", (const void**) &machineid, &len); + if (r < 0) { + log_error("Failed to retrieve _MACHINE_ID field: %s", strerror(-r)); + return r; + } + + if (output) { + fclose(output); + output = NULL; + } + + coredump = strjoin("/var/log/journal/", machineid+12, "/", corepath+14, NULL); + if (! coredump) { + r = log_oom(); + return r; + } + + r = access(coredump, R_OK); + if (r) { + log_error("Couldn't access to core %s: %m", coredump); + return r; + } + + fcoredump = fopen(coredump, "re"); + if (! fcoredump) { + log_error("Couldn't open core %s: %m", coredump); + return -errno; + } + + fout = output_path ? fopen(output_path, "we") : stdout; + if (! fout) { + log_error("Couldn't open output file %s: %m", output_path); + return -errno; + } + + for (;;) { + uint8_t buffer[4096]; + size_t l, q; + + l = fread(buffer, 1, sizeof(buffer), fcoredump); + if (l <= 0) { + if (ferror(fcoredump)) { + log_error("Failed to read coredump: %m"); + return -errno; + } + + break; + } + + q = fwrite(buffer, 1, l, fout); + if (q != l) { + log_error("Failed to write coredump: %m"); + return -errno; + } + } + } + else { + log_error("Unknown message id %s", data+11); + return -1; } r = sd_journal_previous(j); @@ -424,7 +529,10 @@ static int dump_core(sd_journal* j) { static int run_gdb(sd_journal *j) { char path[] = "/var/tmp/coredump-XXXXXX"; - const void *data; + _cleanup_free_ char * coredump = NULL; + char * corepath = NULL; + const char *data; + const char *messageid; size_t len; ssize_t sz; pid_t pid; @@ -443,6 +551,12 @@ static int run_gdb(sd_journal *j) { print_entry(stdout, j, false); + r = sd_journal_get_data(j, "MESSAGE_ID", (const void**) &messageid, &len); + if (r < 0) { + log_error("Failed to retrieve MESSAGE_ID field: %s", strerror(-r)); + return r; + } + r = sd_journal_get_data(j, "COREDUMP_EXE", (const void**) &data, &len); if (r < 0) { log_error("Failed to retrieve COREDUMP_EXE field: %s", strerror(-r)); @@ -450,8 +564,8 @@ static int run_gdb(sd_journal *j) { } assert(len >= 13); - data = (const uint8_t*) data + 13; - len -= 13; + data += 13; + len -= 13; exe = strndup(data, len); if (!exe) @@ -462,36 +576,80 @@ static int run_gdb(sd_journal *j) { return -ENOENT; } - r = sd_journal_get_data(j, "COREDUMP", (const void**) &data, &len); - if (r < 0) { - log_error("Failed to retrieve COREDUMP field: %s", strerror(-r)); - return r; - } + if (strcmp(messageid + 11, "fc2e22bc6ee647b6b90729ab34a250b1") == 0) { + r = sd_journal_get_data(j, "COREDUMP", (const void**) &data, &len); + if (r < 0) { + log_error("Failed to retrieve COREDUMP field: %s", strerror(-r)); + return r; + } + + assert(len >= 9); + data += 9; + len -= 9; + + fd = mkostemp(path, O_WRONLY); + if (fd < 0) { + log_error("Failed to create temporary file: %m"); + return -errno; + } - assert(len >= 9); - data = (const uint8_t*) data + 9; - len -= 9; + sz = write(fd, data, len); + if (sz < 0) { + log_error("Failed to write temporary file: %s", strerror(errno)); + r = -errno; + goto finish; + } + if (sz != (ssize_t) len) { + log_error("Short write to temporary file."); + r = -EIO; + goto finish; + } - fd = mkostemp(path, O_WRONLY); - if (fd < 0) { - log_error("Failed to create temporary file: %m"); - return -errno; + close_nointr_nofail(fd); + fd = -1; + + corepath = path; } + else if (strcmp(messageid + 11, "fc2e22bc6ee647b6b90729ab34a250b2") == 0) { + const char * machineid = NULL; - sz = write(fd, data, len); - if (sz < 0) { - log_error("Failed to write temporary file: %s", strerror(errno)); - r = -errno; - goto finish; + r = sd_journal_get_data(j, "_MACHINE_ID", (const void**) &machineid, &len); + if (r < 0) { + log_error("Failed to retrieve _MACHINE_ID field: %s", strerror(-r)); + goto finish; + } + + assert(len >= 12); + + r = sd_journal_get_data(j, "COREDUMP_FILE", (const void**) &data, &len); + if (r < 0) { + log_error("Failed to retrieve COREDUMP_FILE field: %s", strerror(-r)); + goto finish; + } + + assert(len >= 14); + + coredump = strjoin("/var/log/journal/", machineid+12, "/", data+14, NULL); + if (! coredump) { + r = log_oom(); + goto finish; + } + + r = access(coredump, R_OK); + if (r) { + + log_error("Failed to access core %s: %m", coredump); + goto finish; + } + + corepath = coredump; } - if (sz != (ssize_t) len) { - log_error("Short write to temporary file."); - r = -EIO; + else { + log_error("Unknown message id %s", messageid + 11); + r = -1; goto finish; } - close_nointr_nofail(fd); - fd = -1; pid = fork(); if (pid < 0) { @@ -500,7 +658,7 @@ static int run_gdb(sd_journal *j) { goto finish; } if (pid == 0) { - execlp("gdb", "gdb", exe, path, NULL); + execlp("gdb", "gdb", exe, corepath, NULL); log_error("Failed to invoke gdb: %m"); _exit(1); } @@ -514,7 +672,8 @@ static int run_gdb(sd_journal *j) { r = st.si_code == CLD_EXITED ? st.si_status : 255; finish: - unlink(path); + if (! corepath) + unlink(path); return r; } @@ -585,8 +744,5 @@ end: pager_close(); - if (output) - fclose(output); - return r >= 0 ? r : EXIT_FAILURE; } -- 1.8.1.2 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel