diff options
Diffstat (limited to 'src/journal-remote/journal-upload.c')
-rw-r--r-- | src/journal-remote/journal-upload.c | 263 |
1 files changed, 130 insertions, 133 deletions
diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c index 209e5011d9..1e08fcc554 100644 --- a/src/journal-remote/journal-upload.c +++ b/src/journal-remote/journal-upload.c @@ -10,19 +10,26 @@ #include "alloc-util.h" #include "conf-parser.h" +#include "daemon-util.h" #include "def.h" +#include "env-file.h" #include "fd-util.h" #include "fileio.h" #include "format-util.h" #include "glob-util.h" #include "journal-upload.h" #include "log.h" +#include "main-func.h" #include "mkdir.h" #include "parse-util.h" +#include "pretty-print.h" #include "process-util.h" +#include "rlimit-util.h" #include "sigbus.h" #include "signal-util.h" #include "string-util.h" +#include "strv.h" +#include "tmpfile-util.h" #include "util.h" #define PRIV_KEY_FILE CERTIFICATE_ROOT "/private/journal-upload.pem" @@ -75,8 +82,7 @@ static size_t output_callback(char *buf, if (nmemb && !u->answer) { u->answer = strndup(buf, size*nmemb); if (!u->answer) - log_warning_errno(ENOMEM, "Failed to store server answer (%zu bytes): %m", - size*nmemb); + log_warning("Failed to store server answer (%zu bytes): out of memory", size*nmemb); } return size * nmemb; @@ -147,10 +153,7 @@ static int load_cursor_state(Uploader *u) { if (!u->state_file) return 0; - r = parse_env_file(NULL, u->state_file, NEWLINE, - "LAST_CURSOR", &u->last_cursor, - NULL); - + r = parse_env_file(NULL, u->state_file, "LAST_CURSOR", &u->last_cursor); if (r == -ENOENT) log_debug("State file %s is not present.", u->state_file); else if (r < 0) @@ -199,10 +202,9 @@ int start_upload(Uploader *u, CURL *curl; curl = curl_easy_init(); - if (!curl) { - log_error("Call to curl_easy_init failed."); - return -ENOSR; - } + if (!curl) + return log_error_errno(SYNTHETIC_ERRNO(ENOSR), + "Call to curl_easy_init failed."); /* tell it to POST to the URL */ easy_setopt(curl, CURLOPT_POST, 1L, @@ -266,11 +268,10 @@ int start_upload(Uploader *u, /* upload to this place */ code = curl_easy_setopt(u->easy, CURLOPT_URL, u->url); - if (code) { - log_error("curl_easy_setopt CURLOPT_URL failed: %s", - curl_easy_strerror(code)); - return -EXFULL; - } + if (code) + return log_error_errno(SYNTHETIC_ERRNO(EXFULL), + "curl_easy_setopt CURLOPT_URL failed: %s", + curl_easy_strerror(code)); u->uploading = true; @@ -279,30 +280,30 @@ int start_upload(Uploader *u, static size_t fd_input_callback(void *buf, size_t size, size_t nmemb, void *userp) { Uploader *u = userp; - - ssize_t r; + ssize_t n; assert(u); - assert(nmemb <= SSIZE_MAX / size); + assert(nmemb < SSIZE_MAX / size); if (u->input < 0) return 0; - r = read(u->input, buf, size * nmemb); - log_debug("%s: allowed %zu, read %zd", __func__, size*nmemb, r); + assert(!size_multiply_overflow(size, nmemb)); - if (r > 0) - return r; + n = read(u->input, buf, size * nmemb); + log_debug("%s: allowed %zu, read %zd", __func__, size*nmemb, n); + if (n > 0) + return n; u->uploading = false; - if (r == 0) { - log_debug("Reached EOF"); - close_fd_input(u); - return 0; - } else { + if (n < 0) { log_error_errno(errno, "Aborting transfer after read error on input: %m."); return CURL_READFUNC_ABORT; } + + log_debug("Reached EOF"); + close_fd_input(u); + return 0; } static void close_fd_input(Uploader *u) { @@ -409,10 +410,12 @@ static int setup_uploader(Uploader *u, const char *url, const char *state_file) assert(u); assert(url); - memzero(u, sizeof(Uploader)); - u->input = -1; + *u = (Uploader) { + .input = -1 + }; - if (!(host = startswith(url, "http://")) && !(host = startswith(url, "https://"))) { + host = STARTSWITH_SET(url, "http://", "https://"); + if (!host) { host = url; proto = "https://"; } @@ -489,21 +492,20 @@ static int perform_upload(Uploader *u) { } code = curl_easy_getinfo(u->easy, CURLINFO_RESPONSE_CODE, &status); - if (code) { - log_error("Failed to retrieve response code: %s", - curl_easy_strerror(code)); - return -EUCLEAN; - } - - if (status >= 300) { - log_error("Upload to %s failed with code %ld: %s", - u->url, status, strna(u->answer)); - return -EIO; - } else if (status < 200) { - log_error("Upload to %s finished with unexpected code %ld: %s", - u->url, status, strna(u->answer)); - return -EIO; - } else + if (code) + return log_error_errno(SYNTHETIC_ERRNO(EUCLEAN), + "Failed to retrieve response code: %s", + curl_easy_strerror(code)); + + if (status >= 300) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Upload to %s failed with code %ld: %s", + u->url, status, strna(u->answer)); + else if (status < 200) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Upload to %s finished with unexpected code %ld: %s", + u->url, status, strna(u->answer)); + else log_debug("Upload finished successfully with code %ld: %s", status, strna(u->answer)); @@ -526,7 +528,14 @@ static int parse_config(void) { CONFIG_PARSE_WARN, NULL); } -static void help(void) { +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-journal-upload.service", "8", &link); + if (r < 0) + return log_oom(); + printf("%s -u URL {FILE|-}...\n\n" "Upload journal events to a remote server.\n\n" " -h --help Show this help\n" @@ -550,7 +559,12 @@ static void help(void) { " --follow[=BOOL] Do [not] wait for input\n" " --save-state[=FILE] Save uploaded cursors (default \n" " " STATE_FILE ")\n" - , program_invocation_short_name); + "\nSee the %s for details.\n" + , program_invocation_short_name + , link + ); + + return 0; } static int parse_argv(int argc, char *argv[]) { @@ -598,44 +612,39 @@ static int parse_argv(int argc, char *argv[]) { while ((c = getopt_long(argc, argv, "hu:mM:D:", options, NULL)) >= 0) switch(c) { case 'h': - help(); - return 0 /* done */; + return help(); case ARG_VERSION: return version(); case 'u': - if (arg_url) { - log_error("cannot use more than one --url"); - return -EINVAL; - } + if (arg_url) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "cannot use more than one --url"); arg_url = optarg; break; case ARG_KEY: - if (arg_key) { - log_error("cannot use more than one --key"); - return -EINVAL; - } + if (arg_key) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "cannot use more than one --key"); arg_key = optarg; break; case ARG_CERT: - if (arg_cert) { - log_error("cannot use more than one --cert"); - return -EINVAL; - } + if (arg_cert) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "cannot use more than one --cert"); arg_cert = optarg; break; case ARG_TRUST: - if (arg_trust) { - log_error("cannot use more than one --trust"); - return -EINVAL; - } + if (arg_trust) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "cannot use more than one --trust"); arg_trust = optarg; break; @@ -653,19 +662,17 @@ static int parse_argv(int argc, char *argv[]) { break; case 'M': - if (arg_machine) { - log_error("cannot use more than one --machine/-M"); - return -EINVAL; - } + if (arg_machine) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "cannot use more than one --machine/-M"); arg_machine = optarg; break; case 'D': - if (arg_directory) { - log_error("cannot use more than one --directory/-D"); - return -EINVAL; - } + if (arg_directory) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "cannot use more than one --directory/-D"); arg_directory = optarg; break; @@ -677,19 +684,17 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_CURSOR: - if (arg_cursor) { - log_error("cannot use more than one --cursor/--after-cursor"); - return -EINVAL; - } + if (arg_cursor) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "cannot use more than one --cursor/--after-cursor"); arg_cursor = optarg; break; case ARG_AFTER_CURSOR: - if (arg_cursor) { - log_error("cannot use more than one --cursor/--after-cursor"); - return -EINVAL; - } + if (arg_cursor) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "cannot use more than one --cursor/--after-cursor"); arg_cursor = optarg; arg_after_cursor = true; @@ -698,10 +703,9 @@ static int parse_argv(int argc, char *argv[]) { case ARG_FOLLOW: if (optarg) { r = parse_boolean(optarg); - if (r < 0) { - log_error("Failed to parse --follow= parameter."); - return -EINVAL; - } + if (r < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse --follow= parameter."); arg_follow = !!r; } else @@ -714,31 +718,30 @@ static int parse_argv(int argc, char *argv[]) { break; case '?': - log_error("Unknown option %s.", argv[optind-1]); - return -EINVAL; + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown option %s.", + argv[optind - 1]); case ':': - log_error("Missing argument to %s.", argv[optind-1]); - return -EINVAL; + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Missing argument to %s.", + argv[optind - 1]); default: assert_not_reached("Unhandled option code."); } - if (!arg_url) { - log_error("Required --url/-u option missing."); - return -EINVAL; - } + if (!arg_url) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Required --url/-u option missing."); - if (!!arg_key != !!arg_cert) { - log_error("Options --key and --cert must be used together."); - return -EINVAL; - } + if (!!arg_key != !!arg_cert) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Options --key and --cert must be used together."); - if (optind < argc && (arg_directory || arg_file || arg_machine || arg_journal_type)) { - log_error("Input arguments make no sense with journal input."); - return -EINVAL; - } + if (optind < argc && (arg_directory || arg_file || arg_machine || arg_journal_type)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Input arguments make no sense with journal input."); return 1; } @@ -760,33 +763,37 @@ static int open_journal(sd_journal **j) { return r; } -int main(int argc, char **argv) { - Uploader u; - int r; +static int run(int argc, char **argv) { + _cleanup_(notify_on_cleanup) const char *notify_message = NULL; + _cleanup_(destroy_uploader) Uploader u = {}; bool use_journal; + int r; log_show_color(true); log_parse_environment(); + /* The journal merging logic potentially needs a lot of fds. */ + (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE); + r = parse_config(); if (r < 0) - goto finish; + return r; r = parse_argv(argc, argv); if (r <= 0) - goto finish; + return r; sigbus_install(); r = setup_uploader(&u, arg_url, arg_save_state); if (r < 0) - goto cleanup; + return r; sd_event_set_watchdog(u.events, true); r = check_cursor_updating(&u); if (r < 0) - goto cleanup; + return r; log_debug("%s running as pid "PID_FMT, program_invocation_short_name, getpid_cached()); @@ -796,61 +803,51 @@ int main(int argc, char **argv) { sd_journal *j; r = open_journal(&j); if (r < 0) - goto finish; + return r; r = open_journal_for_upload(&u, j, arg_cursor ?: u.last_cursor, arg_cursor ? arg_after_cursor : true, !!arg_follow); if (r < 0) - goto finish; + return r; } - sd_notify(false, - "READY=1\n" - "STATUS=Processing input..."); + notify_message = notify_start("READY=1\n" + "STATUS=Processing input...", + NOTIFY_STOPPING); for (;;) { r = sd_event_get_state(u.events); if (r < 0) - break; + return r; if (r == SD_EVENT_FINISHED) - break; + return 0; if (use_journal) { if (!u.journal) - break; + return 0; r = check_journal_input(&u); } else if (u.input < 0 && !use_journal) { if (optind >= argc) - break; + return 0; log_debug("Using %s as input.", argv[optind]); r = open_file_for_upload(&u, argv[optind++]); } if (r < 0) - goto cleanup; + return r; if (u.uploading) { r = perform_upload(&u); if (r < 0) - break; + return r; } r = sd_event_run(u.events, u.timeout); - if (r < 0) { - log_error_errno(r, "Failed to run event loop: %m"); - break; - } + if (r < 0) + return log_error_errno(r, "Failed to run event loop: %m"); } - -cleanup: - sd_notify(false, - "STOPPING=1\n" - "STATUS=Shutting down..."); - - destroy_uploader(&u); - -finish: - return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE; } + +DEFINE_MAIN_FUNCTION(run); |