analyze.c revision d3eba116d14b8775eed02e433f7ec5f62cde4957
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering/***
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering This file is part of systemd.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Copyright 2010-2013 Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Copyright 2013 Simon Peeters
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering systemd is free software; you can redistribute it and/or modify it
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering under the terms of the GNU Lesser General Public License as published by
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (at your option) any later version.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering systemd is distributed in the hope that it will be useful, but
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Lesser General Public License for more details.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering You should have received a copy of the GNU Lesser General Public License
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering***/
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <stdio.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <stdlib.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <getopt.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <locale.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <sys/utsname.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <fnmatch.h>
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "sd-bus.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "bus-util.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "bus-error.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "install.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "log.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "build.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "util.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "strxcpyx.h"
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek#include "fileio.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "strv.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "unit-name.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "special.h"
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering#include "hashmap.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "pager.h"
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#define SCALE_X (0.1 / 1000.0) /* pixels per us */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#define SCALE_Y 20.0
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#define compare(a, b) (((a) > (b))? 1 : (((b) > (a))? -1 : 0))
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#define svg(...) printf(__VA_ARGS__)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#define svg_bar(class, x1, x2, y) \
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg(" <rect class=\"%s\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n", \
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (class), \
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering SCALE_X * (x1), SCALE_Y * (y), \
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering SCALE_X * ((x2) - (x1)), SCALE_Y - 1.0)
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering#define svg_text(b, x, y, format, ...) \
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering do { \
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg(" <text class=\"%s\" x=\"%.03f\" y=\"%.03f\">", (b) ? "left" : "right", SCALE_X * (x) + (b ? 5.0 : -5.0), SCALE_Y * (y) + 14.0); \
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg(format, ## __VA_ARGS__); \
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg("</text>\n"); \
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering } while(false)
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic enum dot {
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt DEP_ALL,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering DEP_ORDER,
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering DEP_REQUIRE
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering} arg_dot = DEP_ALL;
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poetteringstatic char** arg_dot_from_patterns = NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic char** arg_dot_to_patterns = NULL;
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poetteringstatic usec_t arg_fuzz = 0;
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poetteringstatic bool arg_no_pager = false;
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poetteringstruct boot_times {
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering usec_t firmware_time;
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering usec_t loader_time;
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering usec_t kernel_time;
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering usec_t kernel_done_time;
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering usec_t initrd_time;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering usec_t userspace_time;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering usec_t finish_time;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt usec_t generators_start_time;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering usec_t generators_finish_time;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering usec_t unitsload_start_time;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering usec_t unitsload_finish_time;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering};
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstruct unit_info {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *id;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *description;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *load_state;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *active_state;
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek const char *sub_state;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *following;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *unit_path;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt uint32_t job_id;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt const char *job_type;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt const char *job_path;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt};
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstruct unit_times {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char *name;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering usec_t activating;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering usec_t activated;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering usec_t deactivated;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering usec_t deactivating;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering usec_t time;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering};
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void pager_open_if_enabled(void) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (arg_no_pager)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering pager_open(false);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int bus_get_uint64_property(sd_bus *bus, const char *path, const char *interface, const char *property, uint64_t *val) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = sd_bus_get_property_trivial(
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering bus,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "org.freedesktop.systemd1",
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek path,
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek interface,
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek property,
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek &error,
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering 't', val);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0) {
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek log_error("Failed to parse reply: %s", bus_error_message(&error, -r));
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek return r;
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek return 0;
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmekstatic int compare_unit_time(const void *a, const void *b) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return compare(((struct unit_times *)b)->time,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ((struct unit_times *)a)->time);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmekstatic int compare_unit_start(const void *a, const void *b) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek return compare(((struct unit_times *)a)->activating,
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek ((struct unit_times *)b)->activating);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek}
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmekstatic int get_os_name(char **_n) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek char *n = NULL;
4b8268f843b0da1cfe1995d93a0b1f95faccc454Zbigniew Jędrzejewski-Szmek int r;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek r = parse_env_file("/etc/os-release", NEWLINE, "PRETTY_NAME", &n, NULL);
4b8268f843b0da1cfe1995d93a0b1f95faccc454Zbigniew Jędrzejewski-Szmek if (r < 0)
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek return r;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek if (!n)
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek return -ENOENT;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek *_n = n;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek return 0;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek}
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmekstatic void free_unit_times(struct unit_times *t, unsigned n) {
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek struct unit_times *p;
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek for (p = t; p < t + n; p++)
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek free(p->name);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek free(t);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek}
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmekstatic int bus_parse_unit_info(sd_bus_message *message, struct unit_info *u) {
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek int r = 0;
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek assert(message);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek assert(u);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek r = sd_bus_message_read(message, "(ssssssouso)", &u->id,
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek &u->description,
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek &u->load_state,
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek &u->active_state,
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek &u->sub_state,
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek &u->following,
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek &u->unit_path,
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek &u->job_id,
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek &u->job_type,
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek &u->job_path);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek if (r < 0) {
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek log_error("Failed to parse message as unit_info.");
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek return -EIO;
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek }
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek return r;
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek}
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int bus_get_unit_property_strv(sd_bus *bus, const char *unit_path, const char *prop, char ***strv) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek const char *s;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = sd_bus_get_property(
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering bus,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "org.freedesktop.systemd1",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unit_path,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "org.freedesktop.systemd1.Unit",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering prop,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering &error,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering &reply,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "as");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Failed to get unit property: %s %s", prop, bus_error_message(&error, -r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek }
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek if (r < 0)
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek return r;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering while ((r = sd_bus_message_read(reply, "s", &s)) > 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = strv_extend(strv, s);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_oom();
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int acquire_time_data(sd_bus *bus, struct unit_times **out) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r, c = 0, n_units = 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct unit_times *unit_times = NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct unit_info u;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = sd_bus_call_method(
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering bus,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "org.freedesktop.systemd1",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "/org/freedesktop/systemd1",
d3b6d0c21ea5a0d15ec6dbd8b8d179138b7463bcZbigniew Jędrzejewski-Szmek "org.freedesktop.systemd1.Manager",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "ListUnits",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering &error,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering &reply,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Failed to parse reply: %s", bus_error_message(&error, -r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering goto fail;
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering goto fail;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering while ((r = bus_parse_unit_info(reply, &u)) > 0) {
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek struct unit_times *t;
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering goto fail;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (c >= n_units) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek struct unit_times *w;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering n_units = MAX(2*c, 16);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek w = realloc(unit_times, sizeof(struct unit_times) * n_units);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek if (!w) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = log_oom();
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering goto fail;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unit_times = w;
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek }
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek t = unit_times+c;
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek t->name = NULL;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_cc(sizeof(usec_t) == sizeof(uint64_t));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (bus_get_uint64_property(bus, u.unit_path,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "org.freedesktop.systemd1.Unit",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "InactiveExitTimestampMonotonic",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering &t->activating) < 0 ||
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek bus_get_uint64_property(bus, u.unit_path,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "org.freedesktop.systemd1.Unit",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "ActiveEnterTimestampMonotonic",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering &t->activated) < 0 ||
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering bus_get_uint64_property(bus, u.unit_path,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "org.freedesktop.systemd1.Unit",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "ActiveExitTimestampMonotonic",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering &t->deactivating) < 0 ||
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering bus_get_uint64_property(bus, u.unit_path,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "org.freedesktop.systemd1.Unit",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "InactiveEnterTimestampMonotonic",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering &t->deactivated) < 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = -EIO;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering goto fail;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (t->activated >= t->activating)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering t->time = t->activated - t->activating;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else if (t->deactivated >= t->activating)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering t->time = t->deactivated - t->activating;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering t->time = 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (t->activating == 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering continue;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering t->name = strdup(u.id);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (t->name == NULL) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = log_oom();
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering goto fail;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering c++;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering *out = unit_times;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return c;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringfail:
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free_unit_times(unit_times, (unsigned) c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int acquire_boot_times(sd_bus *bus, struct boot_times **bt) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering static struct boot_times times;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek static bool cached = false;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (cached)
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek goto finish;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer assert_cc(sizeof(usec_t) == sizeof(uint64_t));
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (bus_get_uint64_property(bus,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "/org/freedesktop/systemd1",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "org.freedesktop.systemd1.Manager",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "FirmwareTimestampMonotonic",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek &times.firmware_time) < 0 ||
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek bus_get_uint64_property(bus,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "/org/freedesktop/systemd1",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "org.freedesktop.systemd1.Manager",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "LoaderTimestampMonotonic",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek &times.loader_time) < 0 ||
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek bus_get_uint64_property(bus,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "/org/freedesktop/systemd1",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "org.freedesktop.systemd1.Manager",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "KernelTimestamp",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek &times.kernel_time) < 0 ||
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek bus_get_uint64_property(bus,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "/org/freedesktop/systemd1",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "org.freedesktop.systemd1.Manager",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "InitRDTimestampMonotonic",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek &times.initrd_time) < 0 ||
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek bus_get_uint64_property(bus,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "/org/freedesktop/systemd1",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "org.freedesktop.systemd1.Manager",
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek "UserspaceTimestampMonotonic",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek &times.userspace_time) < 0 ||
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek bus_get_uint64_property(bus,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "/org/freedesktop/systemd1",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "org.freedesktop.systemd1.Manager",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "FinishTimestampMonotonic",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek &times.finish_time) < 0 ||
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek bus_get_uint64_property(bus,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "/org/freedesktop/systemd1",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "org.freedesktop.systemd1.Manager",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "GeneratorsStartTimestampMonotonic",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek &times.generators_start_time) < 0 ||
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek bus_get_uint64_property(bus,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "/org/freedesktop/systemd1",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "org.freedesktop.systemd1.Manager",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "GeneratorsFinishTimestampMonotonic",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek &times.generators_finish_time) < 0 ||
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek bus_get_uint64_property(bus,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "/org/freedesktop/systemd1",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "org.freedesktop.systemd1.Manager",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "UnitsLoadStartTimestampMonotonic",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek &times.unitsload_start_time) < 0 ||
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek bus_get_uint64_property(bus,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "/org/freedesktop/systemd1",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "org.freedesktop.systemd1.Manager",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "UnitsLoadFinishTimestampMonotonic",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek &times.unitsload_finish_time) < 0)
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek return -EIO;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (times.finish_time <= 0) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek log_error("Bootup is not yet finished. Please try again later.");
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek return -EAGAIN;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek }
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (times.initrd_time)
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek times.kernel_done_time = times.initrd_time;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek else
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek times.kernel_done_time = times.userspace_time;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek cached = true;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmekfinish:
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek *bt = &times;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int pretty_boot_time(sd_bus *bus, char **_buf) {
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek char ts[FORMAT_TIMESPAN_MAX];
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct boot_times *t;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering static char buf[4096];
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering size_t size;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char *ptr;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt r = acquire_boot_times(bus, &t);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek return r;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ptr = buf;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering size = sizeof(buf);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering size = strpcpyf(&ptr, size, "Startup finished in ");
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (t->firmware_time)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering size = strpcpyf(&ptr, size, "%s (firmware) + ", format_timespan(ts, sizeof(ts), t->firmware_time - t->loader_time, USEC_PER_MSEC));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (t->loader_time)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering size = strpcpyf(&ptr, size, "%s (loader) + ", format_timespan(ts, sizeof(ts), t->loader_time, USEC_PER_MSEC));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (t->kernel_time)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering size = strpcpyf(&ptr, size, "%s (kernel) + ", format_timespan(ts, sizeof(ts), t->kernel_done_time, USEC_PER_MSEC));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (t->initrd_time > 0)
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek size = strpcpyf(&ptr, size, "%s (initrd) + ", format_timespan(ts, sizeof(ts), t->userspace_time - t->initrd_time, USEC_PER_MSEC));
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek size = strpcpyf(&ptr, size, "%s (userspace) ", format_timespan(ts, sizeof(ts), t->finish_time - t->userspace_time, USEC_PER_MSEC));
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek if (t->kernel_time > 0)
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek strpcpyf(&ptr, size, "= %s", format_timespan(ts, sizeof(ts), t->firmware_time + t->finish_time, USEC_PER_MSEC));
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek else
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek strpcpyf(&ptr, size, "= %s", format_timespan(ts, sizeof(ts), t->finish_time - t->userspace_time, USEC_PER_MSEC));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ptr = strdup(buf);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!ptr)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return log_oom();
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek *_buf = ptr;
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void svg_graph_box(double height, double begin, double end) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering long long i;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* outside box, fill */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg("<rect class=\"box\" x=\"0\" y=\"0\" width=\"%.03f\" height=\"%.03f\" />\n",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering SCALE_X * (end - begin), SCALE_Y * height);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering for (i = ((long long) (begin / 100000)) * 100000; i <= end; i+=100000) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* lines for each second */
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek if (i % 5000000 == 0)
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek svg(" <line class=\"sec5\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n"
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek " <text class=\"sec\" x=\"%.03f\" y=\"%.03f\" >%.01fs</text>\n",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering SCALE_X * i, SCALE_X * i, SCALE_Y * height, SCALE_X * i, -5.0, 0.000001 * i);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else if (i % 1000000 == 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg(" <line class=\"sec1\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " <text class=\"sec\" x=\"%.03f\" y=\"%.03f\" >%.01fs</text>\n",
7ff7394d9e4e9189c30fd018235e6b1728c6f2d0Zbigniew Jędrzejewski-Szmek SCALE_X * i, SCALE_X * i, SCALE_Y * height, SCALE_X * i, -5.0, 0.000001 * i);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek svg(" <line class=\"sec01\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek SCALE_X * i, SCALE_X * i, SCALE_Y * height);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek }
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek}
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmekstatic int analyze_plot(sd_bus *bus) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct unit_times *times;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct boot_times *boot;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct utsname name;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int n, m = 1, y=0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering double width;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek _cleanup_free_ char *pretty_times = NULL, *osname = NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct unit_times *u;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek n = acquire_boot_times(bus, &boot);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (n < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return n;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering n = pretty_boot_time(bus, &pretty_times);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (n < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return n;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering get_os_name(&osname);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_se(uname(&name) >= 0);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering n = acquire_time_data(bus, &times);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (n <= 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return n;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering qsort(times, n, sizeof(struct unit_times), compare_unit_start);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering width = SCALE_X * (boot->firmware_time + boot->finish_time);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (width < 800.0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering width = 800.0;
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (boot->firmware_time > boot->loader_time)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering m++;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (boot->loader_time) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering m++;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (width < 1000.0)
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering width = 1000.0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (boot->initrd_time)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering m++;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (boot->kernel_time)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering m++;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering for (u = times; u < times + n; u++) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering double text_start, text_width;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering if (u->activating < boot->userspace_time ||
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering u->activating > boot->finish_time) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(u->name);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering u->name = NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering continue;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* If the text cannot fit on the left side then
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * increase the svg width so it fits on the right.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * TODO: calculate the text width more accurately */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering text_width = 8.0 * strlen(u->name);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering text_start = (boot->firmware_time + u->activating) * SCALE_X;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (text_width > text_start && text_width + text_start > width)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering width = text_width + text_start;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (u->deactivated > u->activating && u->deactivated <= boot->finish_time
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering && u->activated == 0 && u->deactivating == 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering u->activated = u->deactivating = u->deactivated;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (u->activated < u->activating || u->activated > boot->finish_time)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering u->activated = boot->finish_time;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (u->deactivating < u->activated || u->activated > boot->finish_time)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering u->deactivating = boot->finish_time;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (u->deactivated < u->deactivating || u->deactivated > boot->finish_time)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering u->deactivated = boot->finish_time;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering m++;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg("<?xml version=\"1.0\" standalone=\"no\"?>\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" "
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg("<svg width=\"%.0fpx\" height=\"%.0fpx\" version=\"1.1\" "
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "xmlns=\"http://www.w3.org/2000/svg\">\n\n",
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering 80.0 + width, 150.0 + (m * SCALE_Y) +
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering 5 * SCALE_Y /* legend */);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* write some basic info as a comment, including some help */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg("<!-- This file is a systemd-analyze SVG file. It is best rendered in a -->\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "<!-- browser such as Chrome, Chromium or Firefox. Other applications -->\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "<!-- that render these files properly but much slower are ImageMagick, -->\n"
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering "<!-- gimp, inkscape, etc. To display the files on your system, just -->\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "<!-- point your browser to this file. -->\n\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "<!-- This plot was generated by systemd-analyze version %-16.16s -->\n\n", VERSION);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* style sheet */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg("<defs>\n <style type=\"text/css\">\n <![CDATA[\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " rect { stroke-width: 1; stroke-opacity: 0; }\n"
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering " rect.background { fill: rgb(255,255,255); }\n"
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering " rect.activating { fill: rgb(255,0,0); fill-opacity: 0.7; }\n"
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering " rect.active { fill: rgb(200,150,150); fill-opacity: 0.7; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " rect.deactivating { fill: rgb(150,100,100); fill-opacity: 0.7; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " rect.kernel { fill: rgb(150,150,150); fill-opacity: 0.7; }\n"
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek " rect.initrd { fill: rgb(150,150,150); fill-opacity: 0.7; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " rect.firmware { fill: rgb(150,150,150); fill-opacity: 0.7; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " rect.loader { fill: rgb(150,150,150); fill-opacity: 0.7; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " rect.userspace { fill: rgb(150,150,150); fill-opacity: 0.7; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " rect.generators { fill: rgb(102,204,255); fill-opacity: 0.7; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " rect.unitsload { fill: rgb( 82,184,255); fill-opacity: 0.7; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " rect.box { fill: rgb(240,240,240); stroke: rgb(192,192,192); }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " line { stroke: rgb(64,64,64); stroke-width: 1; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "// line.sec1 { }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " line.sec5 { stroke-width: 2; }\n"
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek " line.sec01 { stroke: rgb(224,224,224); stroke-width: 1; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " text { font-family: Verdana, Helvetica; font-size: 14px; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " text.left { font-family: Verdana, Helvetica; font-size: 14px; text-anchor: start; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " text.right { font-family: Verdana, Helvetica; font-size: 14px; text-anchor: end; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " text.sec { font-size: 10px; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " ]]>\n </style>\n</defs>\n\n");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg("<rect class=\"background\" width=\"100%%\" height=\"100%%\" />\n");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg("<text x=\"20\" y=\"50\">%s</text>", pretty_times);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg("<text x=\"20\" y=\"30\">%s %s (%s %s) %s</text>",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering isempty(osname) ? "Linux" : osname,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering name.nodename, name.release, name.version, name.machine);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg("<g transform=\"translate(%.3f,100)\">\n", 20.0 + (SCALE_X * boot->firmware_time));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_graph_box(m, -boot->firmware_time, boot->finish_time);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (boot->firmware_time) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_bar("firmware", -(double) boot->firmware_time, -(double) boot->loader_time, y);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_text(true, -(double) boot->firmware_time, y, "firmware");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering y++;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (boot->loader_time) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_bar("loader", -(double) boot->loader_time, 0, y);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_text(true, -(double) boot->loader_time, y, "loader");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering y++;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (boot->kernel_time) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_bar("kernel", 0, boot->kernel_done_time, y);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_text(true, 0, y, "kernel");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering y++;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (boot->initrd_time) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_bar("initrd", boot->initrd_time, boot->userspace_time, y);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_text(true, boot->initrd_time, y, "initrd");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering y++;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_bar("active", boot->userspace_time, boot->finish_time, y);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_bar("generators", boot->generators_start_time, boot->generators_finish_time, y);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_bar("unitsload", boot->unitsload_start_time, boot->unitsload_finish_time, y);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_text(true, boot->userspace_time, y, "systemd");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering y++;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering for (u = times; u < times + n; u++) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char ts[FORMAT_TIMESPAN_MAX];
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering bool b;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!u->name)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering continue;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_bar("activating", u->activating, u->activated, y);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek svg_bar("active", u->activated, u->deactivating, y);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek svg_bar("deactivating", u->deactivating, u->deactivated, y);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek /* place the text on the left if we have passed the half of the svg width */
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek b = u->activating * SCALE_X < width / 2;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if (u->time)
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek svg_text(b, u->activating, y, "%s (%s)",
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek u->name, format_timespan(ts, sizeof(ts), u->time, USEC_PER_MSEC));
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek else
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek svg_text(b, u->activating, y, "%s", u->name);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek y++;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek }
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek /* Legend */
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek y++;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek svg_bar("activating", 0, 300000, y);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek svg_text(true, 400000, y, "Activating");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering y++;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_bar("active", 0, 300000, y);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_text(true, 400000, y, "Active");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering y++;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_bar("deactivating", 0, 300000, y);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_text(true, 400000, y, "Deactivating");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering y++;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_bar("generators", 0, 300000, y);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_text(true, 400000, y, "Generators");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering y++;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek svg_bar("unitsload", 0, 300000, y);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_text(true, 400000, y, "Loading unit files");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering y++;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg("</g>\n\n");
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg("</svg>");
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free_unit_times(times, (unsigned) n);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int list_dependencies_print(const char *name, unsigned int level, unsigned int branches,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering bool last, struct unit_times *times, struct boot_times *boot) {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek unsigned int i;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char ts[FORMAT_TIMESPAN_MAX], ts2[FORMAT_TIMESPAN_MAX];
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering for (i = level; i != 0; i--)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering printf("%s", draw_special_char(branches & (1 << (i-1)) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (times) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (times->time)
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek printf("%s%s @%s +%s%s", ANSI_HIGHLIGHT_RED_ON, name,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek format_timespan(ts, sizeof(ts), times->activating - boot->userspace_time, USEC_PER_MSEC),
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek format_timespan(ts2, sizeof(ts2), times->time, USEC_PER_MSEC), ANSI_HIGHLIGHT_OFF);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek else if (times->activated > boot->userspace_time)
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek printf("%s @%s", name, format_timespan(ts, sizeof(ts), times->activated - boot->userspace_time, USEC_PER_MSEC));
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek else
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek printf("%s", name);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek } else printf("%s", name);
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer printf("\n");
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek return 0;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek}
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
2e8fb7026d3c560194cfe9f83935ce0b16263da0Lukas Nykrynstatic int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
464264ac5a35b655065c5d95b8d8ffbbc7ff3bcfLukas Nykryn _cleanup_free_ char *path;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek int r = 0;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek char **ret = NULL;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert(bus);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek assert(name);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek assert(deps);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
2e8fb7026d3c560194cfe9f83935ce0b16263da0Lukas Nykryn path = unit_dbus_path_from_name(name);
464264ac5a35b655065c5d95b8d8ffbbc7ff3bcfLukas Nykryn if (path == NULL)
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek return -EINVAL;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek r = bus_get_unit_property_strv(bus, path, "After", &ret);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if (r < 0)
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek strv_free(ret);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek else
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek *deps = ret;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek return r;
}
static Hashmap *unit_times_hashmap;
static int list_dependencies_compare(const void *_a, const void *_b) {
const char **a = (const char**) _a, **b = (const char**) _b;
usec_t usa = 0, usb = 0;
struct unit_times *times;
times = hashmap_get(unit_times_hashmap, *a);
if (times)
usa = times->activated;
times = hashmap_get(unit_times_hashmap, *b);
if (times)
usb = times->activated;
return usb - usa;
}
static int list_dependencies_one(sd_bus *bus, const char *name, unsigned int level, char ***units,
unsigned int branches) {
_cleanup_strv_free_ char **deps = NULL;
char **c;
int r = 0;
usec_t service_longest = 0;
int to_print = 0;
struct unit_times *times;
struct boot_times *boot;
if(strv_extend(units, name))
return log_oom();
r = list_dependencies_get_dependencies(bus, name, &deps);
if (r < 0)
return r;
qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
r = acquire_boot_times(bus, &boot);
if (r < 0)
return r;
STRV_FOREACH(c, deps) {
times = hashmap_get(unit_times_hashmap, *c);
if (times
&& times->activated
&& times->activated <= boot->finish_time
&& (times->activated >= service_longest
|| service_longest == 0)) {
service_longest = times->activated;
break;
}
}
if (service_longest == 0 )
return r;
STRV_FOREACH(c, deps) {
times = hashmap_get(unit_times_hashmap, *c);
if (times && times->activated
&& times->activated <= boot->finish_time
&& (service_longest - times->activated) <= arg_fuzz) {
to_print++;
}
}
if(!to_print)
return r;
STRV_FOREACH(c, deps) {
times = hashmap_get(unit_times_hashmap, *c);
if (!times
|| !times->activated
|| times->activated > boot->finish_time
|| service_longest - times->activated > arg_fuzz)
continue;
to_print--;
r = list_dependencies_print(*c, level, branches, to_print == 0, times, boot);
if (r < 0)
return r;
if (strv_contains(*units, *c)) {
r = list_dependencies_print("...", level + 1, (branches << 1) | (to_print ? 1 : 0),
true, NULL, boot);
if (r < 0)
return r;
continue;
}
r = list_dependencies_one(bus, *c, level + 1, units,
(branches << 1) | (to_print ? 1 : 0));
if (r < 0)
return r;
if (!to_print)
break;
}
return 0;
}
static int list_dependencies(sd_bus *bus, const char *name) {
_cleanup_strv_free_ char **units = NULL;
char ts[FORMAT_TIMESPAN_MAX];
struct unit_times *times;
int r;
const char *path, *id;
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
struct boot_times *boot;
assert(bus);
path = unit_dbus_path_from_name(name);
if (path == NULL)
return -EINVAL;
r = sd_bus_get_property(
bus,
"org.freedesktop.systemd1",
path,
"org.freedesktop.systemd1.Unit",
"Id",
&error,
&reply,
"s");
if (r < 0) {
log_error("Failed to parse reply: %s", bus_error_message(&error, -r));
return r;
}
r = sd_bus_message_read(reply, "s", &id);
if (r < 0) {
log_error("Failed to parse reply.");
return r;
}
times = hashmap_get(unit_times_hashmap, id);
r = acquire_boot_times(bus, &boot);
if (r < 0)
return r;
if (times) {
if (times->time)
printf("%s%s +%s%s\n", ANSI_HIGHLIGHT_RED_ON, id,
format_timespan(ts, sizeof(ts), times->time, USEC_PER_MSEC), ANSI_HIGHLIGHT_OFF);
else if (times->activated > boot->userspace_time)
printf("%s @%s\n", id, format_timespan(ts, sizeof(ts), times->activated - boot->userspace_time, USEC_PER_MSEC));
else
printf("%s\n", id);
}
return list_dependencies_one(bus, name, 0, &units, 0);
}
static int analyze_critical_chain(sd_bus *bus, char *names[]) {
struct unit_times *times;
int n, r;
unsigned int i;
Hashmap *h;
n = acquire_time_data(bus, &times);
if (n <= 0)
return n;
h = hashmap_new(string_hash_func, string_compare_func);
if (!h)
return -ENOMEM;
for (i = 0; i < (unsigned)n; i++) {
r = hashmap_put(h, times[i].name, &times[i]);
if (r < 0)
return r;
}
unit_times_hashmap = h;
pager_open_if_enabled();
puts("The time after the unit is active or started is printed after the \"@\" character.\n"
"The time the unit takes to start is printed after the \"+\" character.\n");
if (!strv_isempty(names)) {
char **name;
STRV_FOREACH(name, names)
list_dependencies(bus, *name);
} else
list_dependencies(bus, SPECIAL_DEFAULT_TARGET);
hashmap_free(h);
free_unit_times(times, (unsigned) n);
return 0;
}
static int analyze_blame(sd_bus *bus) {
struct unit_times *times;
unsigned i;
int n;
n = acquire_time_data(bus, &times);
if (n <= 0)
return n;
qsort(times, n, sizeof(struct unit_times), compare_unit_time);
pager_open_if_enabled();
for (i = 0; i < (unsigned) n; i++) {
char ts[FORMAT_TIMESPAN_MAX];
if (times[i].time > 0)
printf("%16s %s\n", format_timespan(ts, sizeof(ts), times[i].time, USEC_PER_MSEC), times[i].name);
}
free_unit_times(times, (unsigned) n);
return 0;
}
static int analyze_time(sd_bus *bus) {
_cleanup_free_ char *buf = NULL;
int r;
r = pretty_boot_time(bus, &buf);
if (r < 0)
return r;
puts(buf);
return 0;
}
static int graph_one_property(sd_bus *bus, const struct unit_info *u, const char* prop, const char *color, char* patterns[]) {
_cleanup_strv_free_ char **units = NULL;
char **unit;
int r;
assert(u);
assert(prop);
assert(color);
r = bus_get_unit_property_strv(bus, u->unit_path, prop, &units);
if (r < 0)
return -r;
STRV_FOREACH(unit, units) {
char **p;
bool match_found;
if (!strv_isempty(arg_dot_from_patterns)) {
match_found = false;
STRV_FOREACH(p, arg_dot_from_patterns)
if (fnmatch(*p, u->id, 0) == 0) {
match_found = true;
break;
}
if (!match_found)
continue;
}
if (!strv_isempty(arg_dot_to_patterns)) {
match_found = false;
STRV_FOREACH(p, arg_dot_to_patterns)
if (fnmatch(*p, *unit, 0) == 0) {
match_found = true;
break;
}
if (!match_found)
continue;
}
if (!strv_isempty(patterns)) {
match_found = false;
STRV_FOREACH(p, patterns)
if (fnmatch(*p, u->id, 0) == 0 || fnmatch(*p, *unit, 0) == 0) {
match_found = true;
break;
}
if (!match_found)
continue;
}
printf("\t\"%s\"->\"%s\" [color=\"%s\"];\n", u->id, *unit, color);
}
return 0;
}
static int graph_one(sd_bus *bus, const struct unit_info *u, char *patterns[]) {
int r;
assert(bus);
assert(u);
if (arg_dot == DEP_ORDER ||arg_dot == DEP_ALL) {
r = graph_one_property(bus, u, "After", "green", patterns);
if (r < 0)
return r;
}
if (arg_dot == DEP_REQUIRE ||arg_dot == DEP_ALL) {
r = graph_one_property(bus, u, "Requires", "black", patterns);
if (r < 0)
return r;
r = graph_one_property(bus, u, "RequiresOverridable", "black", patterns);
if (r < 0)
return r;
r = graph_one_property(bus, u, "RequisiteOverridable", "darkblue", patterns);
if (r < 0)
return r;
r = graph_one_property(bus, u, "Wants", "grey66", patterns);
if (r < 0)
return r;
r = graph_one_property(bus, u, "Conflicts", "red", patterns);
if (r < 0)
return r;
r = graph_one_property(bus, u, "ConflictedBy", "red", patterns);
if (r < 0)
return r;
}
return 0;
}
static int dot(sd_bus *bus, char* patterns[]) {
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
struct unit_info u;
r = sd_bus_call_method(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"ListUnits",
&error,
&reply,
"");
if (r < 0) {
log_error("Failed to parse reply: %s", bus_error_message(&error, -r));
return r;
}
r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
if (r < 0)
return r;
printf("digraph systemd {\n");
while ((r = bus_parse_unit_info(reply, &u)) > 0) {
r = graph_one(bus, &u, patterns);
if (r < 0)
return r;
}
printf("}\n");
log_info(" Color legend: black = Requires\n"
" dark blue = Requisite\n"
" dark grey = Wants\n"
" red = Conflicts\n"
" green = After\n");
if (on_tty())
log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
"-- Try a shell pipeline like 'systemd-analyze dot | dot -Tsvg > systemd.svg'!\n");
return 0;
}
static int dump(sd_bus *bus, char **args) {
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
const char *text = NULL;
int r;
if (!strv_isempty(args)) {
log_error("Too many arguments.");
return -E2BIG;
}
pager_open_if_enabled();
r = sd_bus_call_method(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"Dump",
&error,
&reply,
"");
if (r < 0) {
log_error("Failed to parse reply: %s", bus_error_message(&error, -r));
return r;
}
r = sd_bus_message_read(reply, "s", &text);
if (r < 0) {
log_error("Failed to parse reply");
return r;
}
fputs(text, stdout);
return 0;
}
static int set_log_level(sd_bus *bus, char **args) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(bus);
assert(args);
if (strv_length(args) != 1) {
log_error("This command expects one argument only.");
return -E2BIG;
}
r = sd_bus_set_property(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"LogLevel",
&error,
"s",
args[0]);
if (r < 0) {
log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
return -EIO;
}
return 0;
}
static void analyze_help(void) {
pager_open_if_enabled();
printf("%s [OPTIONS...] {COMMAND} ...\n\n"
"Process systemd profiling information\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
" --system Connect to system manager\n"
" --user Connect to user service manager\n"
" --order When generating a dependency graph, show only order\n"
" --require When generating a dependency graph, show only requirement\n"
" --from-pattern=GLOB, --to-pattern=GLOB\n"
" When generating a dependency graph, filter only origins\n"
" or destinations, respectively\n"
" --fuzz=TIMESPAN When printing the tree of the critical chain, print also\n"
" services, which finished TIMESPAN earlier, than the\n"
" latest in the branch. The unit of TIMESPAN is seconds\n"
" unless specified with a different unit, i.e. 50ms\n"
" --no-pager Do not pipe output into a pager\n\n"
"Commands:\n"
" time Print time spent in the kernel before reaching userspace\n"
" blame Print list of running units ordered by time to init\n"
" critical-chain Print a tree of the time critical chain of units\n"
" plot Output SVG graphic showing service initialization\n"
" dot Output dependency graph in dot(1) format\n"
" set-log-level LEVEL Set logging threshold for systemd\n"
" dump Output state serialization of service manager\n",
program_invocation_short_name);
/* When updating this list, including descriptions, apply
* changes to shell-completion/bash/systemd and
* shell-completion/systemd-zsh-completion.zsh too. */
}
static int parse_argv(int argc, char *argv[]) {
int r;
enum {
ARG_VERSION = 0x100,
ARG_ORDER,
ARG_REQUIRE,
ARG_USER,
ARG_SYSTEM,
ARG_DOT_FROM_PATTERN,
ARG_DOT_TO_PATTERN,
ARG_FUZZ,
ARG_NO_PAGER
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "order", no_argument, NULL, ARG_ORDER },
{ "require", no_argument, NULL, ARG_REQUIRE },
{ "user", no_argument, NULL, ARG_USER },
{ "system", no_argument, NULL, ARG_SYSTEM },
{ "from-pattern", required_argument, NULL, ARG_DOT_FROM_PATTERN },
{ "to-pattern", required_argument, NULL, ARG_DOT_TO_PATTERN },
{ "fuzz", required_argument, NULL, ARG_FUZZ },
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
{ NULL, 0, NULL, 0 }
};
assert(argc >= 0);
assert(argv);
for (;;) {
switch (getopt_long(argc, argv, "h", options, NULL)) {
case 'h':
analyze_help();
return 0;
case ARG_VERSION:
puts(PACKAGE_STRING "\n" SYSTEMD_FEATURES);
return 0;
case ARG_USER:
arg_scope = UNIT_FILE_USER;
break;
case ARG_SYSTEM:
arg_scope = UNIT_FILE_SYSTEM;
break;
case ARG_ORDER:
arg_dot = DEP_ORDER;
break;
case ARG_REQUIRE:
arg_dot = DEP_REQUIRE;
break;
case ARG_DOT_FROM_PATTERN:
if (strv_extend(&arg_dot_from_patterns, optarg) < 0)
return log_oom();
break;
case ARG_DOT_TO_PATTERN:
if (strv_extend(&arg_dot_to_patterns, optarg) < 0)
return log_oom();
break;
case ARG_FUZZ:
r = parse_sec(optarg, &arg_fuzz);
if (r < 0)
return r;
break;
case ARG_NO_PAGER:
arg_no_pager = true;
break;
case -1:
return 1;
case '?':
return -EINVAL;
default:
assert_not_reached("Unhandled option");
}
}
}
int main(int argc, char *argv[]) {
_cleanup_bus_unref_ sd_bus *bus = NULL;
int r;
setlocale(LC_ALL, "");
setlocale(LC_NUMERIC, "C"); /* we want to format/parse floats in C style */
log_parse_environment();
log_open();
r = parse_argv(argc, argv);
if (r <= 0)
goto finish;
if (arg_scope == UNIT_FILE_SYSTEM)
r = sd_bus_open_system(&bus);
else
r = sd_bus_open_user(&bus);
if (r < 0) {
log_error("Failed to connect to bus: %s", strerror(-r));
goto finish;
}
if (!argv[optind] || streq(argv[optind], "time"))
r = analyze_time(bus);
else if (streq(argv[optind], "blame"))
r = analyze_blame(bus);
else if (streq(argv[optind], "critical-chain"))
r = analyze_critical_chain(bus, argv+optind+1);
else if (streq(argv[optind], "plot"))
r = analyze_plot(bus);
else if (streq(argv[optind], "dot"))
r = dot(bus, argv+optind+1);
else if (streq(argv[optind], "dump"))
r = dump(bus, argv+optind+1);
else if (streq(argv[optind], "set-log-level"))
r = set_log_level(bus, argv+optind+1);
else
log_error("Unknown operation '%s'.", argv[optind]);
finish:
pager_close();
strv_free(arg_dot_from_patterns);
strv_free(arg_dot_to_patterns);
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}