journal-upload.c revision 3d090cc6f34e5970765dd1e7ee5e648a056d180d
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2014 Zbigniew Jędrzejewski-Szmek
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 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 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/>.
3f6fd1ba65f962702753c4ad284b588e59689a23Lennart Poetteringstatic const char* arg_url;
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering#define easy_setopt(curl, opt, value, level, cmd) \
3f6fd1ba65f962702753c4ad284b588e59689a23Lennart Poettering code = curl_easy_setopt(curl, opt, value); \
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering "curl_easy_setopt " #opt " failed: %s", \
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering h = curl_slist_append(NULL, "Content-Type: application/vnd.fdo.journal");
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering h = curl_slist_append(h, "Transfer-Encoding: chunked");
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering h = curl_slist_append(h, "Accept: text/plain");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Call to curl_easy_init failed.");
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering /* tell it to POST to the URL */
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering /* set where to read from */
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering easy_setopt(curl, CURLOPT_READFUNCTION, input_callback,
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering easy_setopt(curl, CURLOPT_READDATA, data,
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering /* use our special own mime type and chunked transfer */
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering easy_setopt(curl, CURLOPT_HTTPHEADER, u->header,
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering /* enable verbose for easier tracing */
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering easy_setopt(curl, CURLOPT_VERBOSE, 1L, LOG_WARNING, );
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering "systemd-journal-upload " PACKAGE_STRING,
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering /* upload to this place */
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering code = curl_easy_setopt(u->easy, CURLOPT_URL, u->url);
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering log_error("curl_easy_setopt CURLOPT_URL failed: %s",
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poetteringstatic size_t fd_input_callback(void *buf, size_t size, size_t nmemb, void *userp) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_debug("%s: allowed %zu, read %zu", __func__, size*nmemb, r);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Aborting transfer after read error on input: %m.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int dispatch_fd_input(sd_event_source *event,
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering log_warning("dispatch_fd_input called when uploading, ignoring.");
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering return start_upload(u, fd_input_callback, u);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int open_file_for_upload(Uploader *u, const char *filename) {
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering fd = open(filename, O_RDONLY|O_CLOEXEC|O_NOCTTY);
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering log_error("Failed to open %s: %m", filename);
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering r = sd_event_add_io(u->events, &u->input_event,
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering log_error("Failed to register input event: %s", strerror(-r));
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering /* Normal files should just be consumed without polling. */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = start_upload(u, fd_input_callback, u);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poetteringstatic int setup_uploader(Uploader *u, const char *url) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering log_error("sd_event_default failed: %s", strerror(-r));
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poetteringstatic void destroy_uploader(Uploader *u) {
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering u->input_event = sd_event_source_unref(u->input_event);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poetteringstatic void help(void) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering "Upload journal events to a remote server.\n\n"
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering " --url=URL Upload to this address\n"
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering " -h --help Show this help and exit\n"
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering " --version Print version string and exit\n"
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poetteringstatic int parse_argv(int argc, char *argv[]) {
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering { "version", no_argument, NULL, ARG_VERSION },
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering while ((c = getopt_long(argc, argv, "hu:", options, NULL)) >= 0)
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering return 0 /* done */;
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering return 0 /* done */;
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering log_error("cannot use more than one --url");
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering log_error("Unknown option %s.", argv[optind-1]);
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering log_error("Missing argument to %s.", argv[optind-1]);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering assert_not_reached("Unhandled option code.");
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering log_error("Required --url/-u option missing.");
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering program_invocation_short_name, getpid());
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering "STATUS=Processing input...");
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering while (true) {
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering log_debug("Using %s as input.", argv[optind]);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering r = open_file_for_upload(&u, argv[optind++]);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering log_debug("Upload finished successfully.");
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering r = sd_event_run(u.events, u.input >= 0 ? -1 : 0);
6f883237f1b8a96ec0ea354866e033b6fcea9506Lennart Poettering log_error("Failed to run event loop: %s", strerror(-r));
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering sd_notify(false, "STATUS=Shutting down...");
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;