journal-upload.c revision 2cf4172a71860c6e44edd27a3b68047ae062d7fc
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/***
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2014 Zbigniew Jędrzejewski-Szmek
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (at your option) any later version.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is distributed in the hope that it will be useful, but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Lesser General Public License for more details.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering***/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
8bdbb8d9cbe1d35708385573d70984ab4533812dLennart Poettering#include <stdio.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <curl/curl.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <sys/stat.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <fcntl.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <getopt.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "sd-daemon.h"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering#include "log.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "util.h"
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#include "build.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "fileio.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "mkdir.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "conf-parser.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "sigbus.h"
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#include "journal-upload.h"
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define PRIV_KEY_FILE CERTIFICATE_ROOT "/private/journal-upload.pem"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define CERT_FILE CERTIFICATE_ROOT "/certs/journal-upload.pem"
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering#define TRUST_FILE CERTIFICATE_ROOT "/ca/trusted.pem"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define DEFAULT_PORT 19532
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic const char* arg_url = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic const char *arg_key = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic const char *arg_cert = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic const char *arg_trust = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic const char *arg_directory = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic char **arg_file = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic const char *arg_cursor = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic bool arg_after_cursor = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int arg_journal_type = 0;
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poetteringstatic const char *arg_machine = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic bool arg_merge = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int arg_follow = -1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic const char *arg_save_state = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void close_fd_input(Uploader *u);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define SERVER_ANSWER_KEEP 2048
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define STATE_FILE "/var/lib/systemd/journal-upload/state"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define easy_setopt(curl, opt, value, level, cmd) \
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen do { \
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen code = curl_easy_setopt(curl, opt, value); \
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (code) { \
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_full(level, \
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "curl_easy_setopt " #opt " failed: %s", \
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering curl_easy_strerror(code)); \
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering cmd; \
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering } \
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering } while(0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic size_t output_callback(char *buf,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen size_t size,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen size_t nmemb,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen void *userp) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen Uploader *u = userp;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(u);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_debug("The server answers (%zu bytes): %.*s",
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen size*nmemb, (int)(size*nmemb), buf);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (nmemb && !u->answer) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering u->answer = strndup(buf, size*nmemb);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!u->answer)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning_errno(ENOMEM, "Failed to store server answer (%zu bytes): %m",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering size*nmemb);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return size * nmemb;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int check_cursor_updating(Uploader *u) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_free_ char *temp_path = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (!u->state_file)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return 0;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = mkdir_parents(u->state_file, 0755);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return log_error_errno(r, "Cannot create parent directory of state file %s: %m",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering u->state_file);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = fopen_temporary(u->state_file, &f, &temp_path);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return log_error_errno(r, "Cannot save state to %s: %m",
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen u->state_file);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen unlink(temp_path);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic int update_cursor_state(Uploader *u) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen _cleanup_free_ char *temp_path = NULL;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering int r;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (!u->state_file || !u->last_cursor)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return 0;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering r = fopen_temporary(u->state_file, &f, &temp_path);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (r < 0)
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering goto finish;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering fprintf(f,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering "# This is private data. Do not parse.\n"
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering "LAST_CURSOR=%s\n",
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering u->last_cursor);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering fflush(f);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (ferror(f) || rename(temp_path, u->state_file) < 0) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering r = -errno;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering unlink(u->state_file);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering unlink(temp_path);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poetteringfinish:
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (r < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_error_errno(r, "Failed to save state %s: %m", u->state_file);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return r;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering}
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic int load_cursor_state(Uploader *u) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen int r;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (!u->state_file)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return 0;
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering r = parse_env_file(u->state_file, NEWLINE,
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering "LAST_CURSOR", &u->last_cursor,
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering NULL);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering if (r == -ENOENT)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering log_debug("State file %s is not present.", u->state_file);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering else if (r < 0)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return log_error_errno(r, "Failed to read state file %s: %m",
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering u->state_file);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering else
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering log_debug("Last cursor was %s", u->last_cursor);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return 0;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering}
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringint start_upload(Uploader *u,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering size_t (*input_callback)(void *ptr,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering size_t size,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers size_t nmemb,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering void *userdata),
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers void *data) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers CURLcode code;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers assert(u);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(input_callback);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!u->header) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct curl_slist *h;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering h = curl_slist_append(NULL, "Content-Type: application/vnd.fdo.journal");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!h)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return log_oom();
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering h = curl_slist_append(h, "Transfer-Encoding: chunked");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!h) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering curl_slist_free_all(h);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return log_oom();
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering h = curl_slist_append(h, "Accept: text/plain");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!h) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering curl_slist_free_all(h);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return log_oom();
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering u->header = h;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!u->easy) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering CURL *curl;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering curl = curl_easy_init();
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!curl) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Call to curl_easy_init failed.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -ENOSR;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* tell it to POST to the URL */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering easy_setopt(curl, CURLOPT_POST, 1L,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering LOG_ERR, return -EXFULL);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering easy_setopt(curl, CURLOPT_ERRORBUFFER, u->error,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering LOG_ERR, return -EXFULL);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* set where to write to */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering easy_setopt(curl, CURLOPT_WRITEFUNCTION, output_callback,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering LOG_ERR, return -EXFULL);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering easy_setopt(curl, CURLOPT_WRITEDATA, data,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering LOG_ERR, return -EXFULL);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* set where to read from */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering easy_setopt(curl, CURLOPT_READFUNCTION, input_callback,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering LOG_ERR, return -EXFULL);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering easy_setopt(curl, CURLOPT_READDATA, data,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering LOG_ERR, return -EXFULL);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* use our special own mime type and chunked transfer */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers easy_setopt(curl, CURLOPT_HTTPHEADER, u->header,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers LOG_ERR, return -EXFULL);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* enable verbose for easier tracing */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers easy_setopt(curl, CURLOPT_VERBOSE, 1L, LOG_WARNING, );
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers easy_setopt(curl, CURLOPT_USERAGENT,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers "systemd-journal-upload " PACKAGE_STRING,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers LOG_WARNING, );
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (arg_key || startswith(u->url, "https://")) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers easy_setopt(curl, CURLOPT_SSLKEY, arg_key ?: PRIV_KEY_FILE,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers LOG_ERR, return -EXFULL);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen easy_setopt(curl, CURLOPT_SSLCERT, arg_cert ?: CERT_FILE,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen LOG_ERR, return -EXFULL);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (streq_ptr(arg_trust, "all"))
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers LOG_ERR, return -EUCLEAN);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers else if (arg_trust || startswith(u->url, "https://"))
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers easy_setopt(curl, CURLOPT_CAINFO, arg_trust ?: TRUST_FILE,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers LOG_ERR, return -EXFULL);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (arg_key || arg_trust)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering LOG_WARNING, );
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering u->easy = curl;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering } else {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* truncate the potential old error message */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering u->error[0] = '\0';
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(u->answer);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers u->answer = 0;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers }
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* upload to this place */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers code = curl_easy_setopt(u->easy, CURLOPT_URL, u->url);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (code) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers log_error("curl_easy_setopt CURLOPT_URL failed: %s",
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers curl_easy_strerror(code));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EXFULL;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers }
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering u->uploading = true;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic size_t fd_input_callback(void *buf, size_t size, size_t nmemb, void *userp) {
27e72d6b22890ba4a8cbc05c49667cd1cccf1461Simon Peeters Uploader *u = userp;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers ssize_t r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering assert(u);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(nmemb <= SSIZE_MAX / size);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (u->input < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return 0;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers r = read(u->input, buf, size * nmemb);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_debug("%s: allowed %zu, read %zu", __func__, size*nmemb, r);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r > 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering u->uploading = false;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (r == 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_debug("Reached EOF");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering close_fd_input(u);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers } else {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_error_errno(errno, "Aborting transfer after read error on input: %m.");
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return CURL_READFUNC_ABORT;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers}
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sieversstatic void close_fd_input(Uploader *u) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers assert(u);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (u->input >= 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering close_nointr(u->input);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering u->input = -1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering u->timeout = 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic int dispatch_fd_input(sd_event_source *event,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen int fd,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen uint32_t revents,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen void *userp) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen Uploader *u = userp;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(u);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(fd >= 0);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (revents & EPOLLHUP) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_debug("Received HUP");
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen close_fd_input(u);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return 0;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (!(revents & EPOLLIN)) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers log_warning("Unexpected poll event %"PRIu32".", revents);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EINVAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (u->uploading) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers log_warning("dispatch_fd_input called when uploading, ignoring.");
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return start_upload(u, fd_input_callback, u);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic int open_file_for_upload(Uploader *u, const char *filename) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen int fd, r = 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (streq(filename, "-"))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fd = STDIN_FILENO;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fd = open(filename, O_RDONLY|O_CLOEXEC|O_NOCTTY);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (fd < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return log_error_errno(errno, "Failed to open %s: %m", filename);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering u->input = fd;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (arg_follow) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = sd_event_add_io(u->events, &u->input_event,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen fd, EPOLLIN, dispatch_fd_input, u);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (r < 0) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (r != -EPERM || arg_follow > 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return log_error_errno(r, "Failed to register input event: %m");
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen /* Normal files should just be consumed without polling. */
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = start_upload(u, fd_input_callback, u);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int dispatch_sigterm(sd_event_source *event,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const struct signalfd_siginfo *si,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen void *userdata) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen Uploader *u = userdata;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(u);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_received_signal(LOG_INFO, si);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering close_fd_input(u);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering close_journal_input(u);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen sd_event_exit(u->events, 0);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return 0;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic int setup_signals(Uploader *u) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen sigset_t mask;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen int r;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(u);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(sigemptyset(&mask) == 0);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen sigset_add_many(&mask, SIGINT, SIGTERM, -1);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_event_add_signal(u->events, &u->sigterm_event, SIGTERM, dispatch_sigterm, u);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = sd_event_add_signal(u->events, &u->sigint_event, SIGINT, dispatch_sigterm, u);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (r < 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return r;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmekstatic int setup_uploader(Uploader *u, const char *url, const char *state_file) {
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek int r;
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek const char *host, *proto = "";
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(u);
f69157a66ffe413b4cf8bd79057487fc8921e78bThomas Hindoe Paaboel Andersen assert(url);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering memzero(u, sizeof(Uploader));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering u->input = -1;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (!(host = startswith(url, "http://")) && !(host = startswith(url, "https://"))) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering host = url;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering proto = "https://";
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (strchr(host, ':'))
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering u->url = strjoin(proto, url, "/upload", NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering else {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering char *t;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering size_t x;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering t = strdupa(url);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering x = strlen(t);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering while (x > 0 && t[x - 1] == '/')
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering t[x - 1] = '\0';
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering u->url = strjoin(proto, t, ":" STRINGIFY(DEFAULT_PORT), "/upload", NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (!u->url)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return log_oom();
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering u->state_file = state_file;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = sd_event_default(&u->events);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (r < 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return log_error_errno(r, "sd_event_default failed: %m");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = setup_signals(u);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (r < 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return log_error_errno(r, "Failed to set up signals: %m");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return load_cursor_state(u);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic void destroy_uploader(Uploader *u) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(u);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering curl_easy_cleanup(u->easy);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering curl_slist_free_all(u->header);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering free(u->answer);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering free(u->last_cursor);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering free(u->current_cursor);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering free(u->url);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering u->input_event = sd_event_source_unref(u->input_event);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering close_fd_input(u);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering close_journal_input(u);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering sd_event_source_unref(u->sigterm_event);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering sd_event_source_unref(u->sigint_event);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering sd_event_unref(u->events);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic int perform_upload(Uploader *u) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering CURLcode code;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering long status;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(u);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering code = curl_easy_perform(u->easy);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (code) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (u->error[0])
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error("Upload to %s failed: %.*s",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering u->url, (int) sizeof(u->error), u->error);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering else
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error("Upload to %s failed: %s",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering u->url, curl_easy_strerror(code));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -EIO;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering code = curl_easy_getinfo(u->easy, CURLINFO_RESPONSE_CODE, &status);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (code) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error("Failed to retrieve response code: %s",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering curl_easy_strerror(code));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -EUCLEAN;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (status >= 300) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error("Upload to %s failed with code %lu: %s",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering u->url, status, strna(u->answer));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -EIO;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering } else if (status < 200) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error("Upload to %s finished with unexpected code %lu: %s",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering u->url, status, strna(u->answer));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -EIO;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering } else
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_debug("Upload finished successfully with code %lu: %s",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering status, strna(u->answer));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering free(u->last_cursor);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering u->last_cursor = u->current_cursor;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering u->current_cursor = NULL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return update_cursor_state(u);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic int parse_config(void) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering const ConfigTableItem items[] = {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "Upload", "URL", config_parse_string, 0, &arg_url },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "Upload", "ServerKeyFile", config_parse_path, 0, &arg_key },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "Upload", "ServerCertificateFile", config_parse_path, 0, &arg_cert },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "Upload", "TrustedCertificateFile", config_parse_path, 0, &arg_trust },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering {}};
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return config_parse_many(PKGSYSCONFDIR "/journal-upload.conf",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering CONF_DIRS_NULSTR("systemd/journal-upload.conf"),
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering "Upload\0", config_item_table_lookup, items,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering false, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic void help(void) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering printf("%s -u URL {FILE|-}...\n\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering "Upload journal events to a remote server.\n\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " -h --help Show this help\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " --version Show package version\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " -u --url=URL Upload to this address (default port "
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering STRINGIFY(DEFAULT_PORT) ")\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " --key=FILENAME Specify key in PEM format (default:\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " \"" PRIV_KEY_FILE "\")\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " --cert=FILENAME Specify certificate in PEM format (default:\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " \"" CERT_FILE "\")\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " --trust=FILENAME|all Specify CA certificate or disable checking (default:\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " \"" TRUST_FILE "\")\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " --system Use the system journal\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " --user Use the user journal for the current user\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " -m --merge Use all available journals\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " -M --machine=CONTAINER Operate on local container\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " -D --directory=PATH Use journal files from directory\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " --file=PATH Use this journal file\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " --cursor=CURSOR Start at the specified cursor\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " --after-cursor=CURSOR Start after the specified cursor\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " --follow[=BOOL] Do [not] wait for input\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " --save-state[=FILE] Save uploaded cursors (default \n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " " STATE_FILE ")\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " -h --help Show this help and exit\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering " --version Print version string and exit\n"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering , program_invocation_short_name);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic int parse_argv(int argc, char *argv[]) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering enum {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering ARG_VERSION = 0x100,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering ARG_KEY,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering ARG_CERT,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering ARG_TRUST,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering ARG_USER,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering ARG_SYSTEM,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering ARG_FILE,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering ARG_CURSOR,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering ARG_AFTER_CURSOR,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering ARG_FOLLOW,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering ARG_SAVE_STATE,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering };
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering static const struct option options[] = {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "help", no_argument, NULL, 'h' },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "version", no_argument, NULL, ARG_VERSION },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "url", required_argument, NULL, 'u' },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "key", required_argument, NULL, ARG_KEY },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "cert", required_argument, NULL, ARG_CERT },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "trust", required_argument, NULL, ARG_TRUST },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "system", no_argument, NULL, ARG_SYSTEM },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "user", no_argument, NULL, ARG_USER },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "merge", no_argument, NULL, 'm' },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "machine", required_argument, NULL, 'M' },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "directory", required_argument, NULL, 'D' },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "file", required_argument, NULL, ARG_FILE },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "cursor", required_argument, NULL, ARG_CURSOR },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "after-cursor", required_argument, NULL, ARG_AFTER_CURSOR },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "follow", optional_argument, NULL, ARG_FOLLOW },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "save-state", optional_argument, NULL, ARG_SAVE_STATE },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering {}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering };
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering int c, r;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(argc >= 0);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(argv);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering opterr = 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering while ((c = getopt_long(argc, argv, "hu:mM:D:", options, NULL)) >= 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering switch(c) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering case 'h':
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering help();
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return 0 /* done */;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering case ARG_VERSION:
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering puts(PACKAGE_STRING);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering puts(SYSTEMD_FEATURES);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return 0 /* done */;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering case 'u':
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (arg_url) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error("cannot use more than one --url");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -EINVAL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering arg_url = optarg;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering break;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering case ARG_KEY:
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (arg_key) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error("cannot use more than one --key");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -EINVAL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering arg_key = optarg;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering break;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case ARG_CERT:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (arg_cert) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("cannot use more than one --cert");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EINVAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering arg_cert = optarg;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering break;
53755121e1c8ebd3db0330bc82965ecf9a986449Lennart Poettering
53755121e1c8ebd3db0330bc82965ecf9a986449Lennart Poettering case ARG_TRUST:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (arg_trust) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("cannot use more than one --trust");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EINVAL;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering }
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering arg_trust = optarg;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
19887cd06a3af2f045e763986eda19e208bd3f85Zbigniew Jędrzejewski-Szmek case ARG_SYSTEM:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering arg_journal_type |= SD_JOURNAL_SYSTEM;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering break;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case ARG_USER:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering arg_journal_type |= SD_JOURNAL_CURRENT_USER;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case 'm':
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering arg_merge = true;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case 'M':
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (arg_machine) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("cannot use more than one --machine/-M");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EINVAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering arg_machine = optarg;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case 'D':
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (arg_directory) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("cannot use more than one --directory/-D");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EINVAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering arg_directory = optarg;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering case ARG_FILE:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = glob_extend(&arg_file, optarg);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering return log_error_errno(r, "Failed to add paths: %m");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case ARG_CURSOR:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (arg_cursor) {
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering log_error("cannot use more than one --cursor/--after-cursor");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EINVAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering arg_cursor = optarg;
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case ARG_AFTER_CURSOR:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (arg_cursor) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("cannot use more than one --cursor/--after-cursor");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EINVAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering arg_cursor = optarg;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering arg_after_cursor = true;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case ARG_FOLLOW:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (optarg) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = parse_boolean(optarg);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Failed to parse --follow= parameter.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EINVAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering arg_follow = !!r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering } else
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering arg_follow = true;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case ARG_SAVE_STATE:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering arg_save_state = optarg ?: STATE_FILE;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case '?':
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Unknown option %s.", argv[optind-1]);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EINVAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case ':':
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Missing argument to %s.", argv[optind-1]);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EINVAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering default:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_not_reached("Unhandled option code.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!arg_url) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Required --url/-u option missing.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EINVAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering if (!!arg_key != !!arg_cert) {
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering log_error("Options --key and --cert must be used together.");
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering return -EINVAL;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering }
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering if (optind < argc && (arg_directory || arg_file || arg_machine || arg_journal_type)) {
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering log_error("Input arguments make no sense with journal input.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EINVAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poetteringstatic int open_journal(sd_journal **j) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (arg_directory)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_journal_open_directory(j, arg_directory, arg_journal_type);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else if (arg_file)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_journal_open_files(j, (const char**) arg_file, 0);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering else if (arg_machine)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_journal_open_container(j, arg_machine, 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_journal_open(j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error_errno(r, "Failed to open %s: %m",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering arg_directory ? arg_directory : arg_file ? "files" : "journal");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenint main(int argc, char **argv) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Uploader u;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering bool use_journal;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_show_color(true);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_parse_environment();
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = parse_config();
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto finish;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = parse_argv(argc, argv);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r <= 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto finish;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sigbus_install();
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = setup_uploader(&u, arg_url, arg_save_state);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto cleanup;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_event_set_watchdog(u.events, true);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = check_cursor_updating(&u);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto cleanup;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_debug("%s running as pid "PID_FMT,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering program_invocation_short_name, getpid());
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering use_journal = optind >= argc;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (use_journal) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_journal *j;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = open_journal(&j);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto finish;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = open_journal_for_upload(&u, j,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering arg_cursor ?: u.last_cursor,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering arg_cursor ? arg_after_cursor : true,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering !!arg_follow);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto finish;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_notify(false,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "READY=1\n"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "STATUS=Processing input...");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering while (true) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_event_get_state(u.events);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r == SD_EVENT_FINISHED)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (use_journal) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!u.journal)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = check_journal_input(&u);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering } else if (u.input < 0 && !use_journal) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (optind >= argc)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_debug("Using %s as input.", argv[optind]);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = open_file_for_upload(&u, argv[optind++]);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto cleanup;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (u.uploading) {
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering r = perform_upload(&u);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_event_run(u.events, u.timeout);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0) {
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering log_error_errno(r, "Failed to run event loop: %m");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poetteringcleanup:
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen sd_notify(false,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen "STOPPING=1\n"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "STATUS=Shutting down...");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering destroy_uploader(&u);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringfinish:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering}
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering