[systemd-devel] [PATCH 4/6] Add COREDUMP_FILE= support to systemd-coredumpctl
Oleksii Shevchuk
alxchk at gmail.com
Mon Feb 11 15:14:41 PST 2013
---
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
More information about the systemd-devel
mailing list