+static void print_entry(sd_journal *j, unsigned n_found) {
+ assert(j);
+
+ if (arg_action == ACTION_INFO)
+ print_info(stdout, j, n_found);
+ else if (arg_field)
+ print_field(stdout, j);
+ else
+ print_list(stdout, j, n_found);
+}
+
+static int dump_list(sd_journal *j) {
+ unsigned n_found = 0;
+ int r;
+
+ assert(j);
+
+ /* The coredumps are likely to compressed, and for just
+ * listing them we don't need to decompress them, so let's
+ * pick a fairly low data threshold here */
+ sd_journal_set_data_threshold(j, 4096);
+
+ if (arg_one) {
+ r = focus(j);
+ if (r < 0)
+ return r;
+
+ print_entry(j, 0);
+ } else {
+ SD_JOURNAL_FOREACH(j)
+ print_entry(j, n_found++);
+
+ if (!arg_field && n_found <= 0) {
+ log_notice("No coredumps found.");
+ return -ESRCH;
+ }
+ }
+
+ return 0;
+}
+
+static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) {
+ const char *data;
+ _cleanup_free_ char *filename = NULL;
+ size_t len;
+ int r;
+
+ assert((fd >= 0) != !!path);
+ assert(!!path == !!unlink_temp);
+
+ /* Prefer uncompressed file to journal (probably cached) to
+ * compressed file (probably uncached). */
+ r = sd_journal_get_data(j, "COREDUMP_FILENAME", (const void**) &data, &len);
+ if (r < 0 && r != -ENOENT)
+ log_warning("Failed to retrieve COREDUMP_FILENAME: %s", strerror(-r));
+ else if (r == 0)
+ retrieve(data, len, "COREDUMP_FILENAME", &filename);
+
+ if (filename && access(filename, R_OK) < 0) {
+ log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
+ "File %s is not readable: %m", filename);
+ free(filename);
+ filename = NULL;
+ }
+
+ if (filename && !endswith(filename, ".xz") && !endswith(filename, ".lz4")) {
+ if (path) {
+ *path = filename;
+ filename = NULL;
+ }
+
+ return 0;
+ } else {
+ _cleanup_close_ int fdt = -1;
+ char *temp = NULL;
+
+ if (fd < 0) {
+ temp = strdup("/var/tmp/coredump-XXXXXX");
+ if (!temp)
+ return log_oom();
+
+ fdt = mkostemp_safe(temp, O_WRONLY|O_CLOEXEC);
+ if (fdt < 0) {
+ log_error("Failed to create temporary file: %m");
+ return -errno;
+ }
+ log_debug("Created temporary file %s", temp);
+
+ fd = fdt;
+ }
+
+ r = sd_journal_get_data(j, "COREDUMP", (const void**) &data, &len);
+ if (r == 0) {
+ ssize_t sz;
+
+ assert(len >= 9);
+ data += 9;
+ len -= 9;
+
+ sz = write(fdt, data, len);
+ if (sz < 0) {
+ log_error("Failed to write temporary file: %m");
+ r = -errno;
+ goto error;
+ }
+ if (sz != (ssize_t) len) {
+ log_error("Short write to temporary file.");
+ r = -EIO;
+ goto error;
+ }
+ } else if (filename) {
+#if defined(HAVE_XZ) || defined(HAVE_LZ4)
+ _cleanup_close_ int fdf;
+
+ fdf = open(filename, O_RDONLY | O_CLOEXEC);
+ if (fdf < 0) {
+ log_error("Failed to open %s: %m", filename);
+ r = -errno;
+ goto error;
+ }
+
+ r = decompress_stream(filename, fdf, fd, -1);
+ if (r < 0) {
+ log_error("Failed to decompress %s: %s", filename, strerror(-r));
+ goto error;
+ }
+#else
+ log_error("Cannot decompress file. Compiled without compression support.");
+ r = -ENOTSUP;
+ goto error;
+#endif
+ } else {
+ if (r == -ENOENT)
+ log_error("Cannot retrieve coredump from journal nor disk.");
+ else
+ log_error("Failed to retrieve COREDUMP field: %s", strerror(-r));
+ goto error;
+ }
+
+ if (temp) {
+ *path = temp;
+ *unlink_temp = true;
+ }
+
+ return 0;
+
+error:
+ if (temp) {
+ unlink(temp);
+ log_debug("Removed temporary file %s", temp);
+ }
+ return r;
+ }
+}
+