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