machinectl.c revision 4afd3348c7506dd1d36305b7bcb9feb8952b9d6b
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/***
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2013 Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (at your option) any later version.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is distributed in the hope that it will be useful, but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Lesser General Public License for more details.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering***/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
8bdbb8d9cbe1d35708385573d70984ab4533812dLennart Poettering#include <arpa/inet.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <errno.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <fcntl.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <getopt.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <locale.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <net/if.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <netinet/in.h>
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering#include <string.h>
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering#include <sys/mount.h>
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering#include <sys/socket.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <unistd.h>
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "sd-bus.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "alloc-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "bus-error.h"
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#include "bus-util.h"
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#include "cgroup-show.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "cgroup-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "copy.h"
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering#include "env-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "fd-util.h"
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering#include "hostname-util.h"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering#include "import-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "log.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "logs-show.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "macro.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "mkdir.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "pager.h"
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen#include "parse-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "path-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "process-util.h"
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering#include "ptyfwd.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "signal-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "spawn-polkit-agent.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "strv.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "terminal-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "unit-name.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "verbs.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "web-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic char **arg_property = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic bool arg_all = false;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic bool arg_full = false;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic bool arg_no_pager = false;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic bool arg_legend = true;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic const char *arg_kill_who = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int arg_signal = SIGTERM;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic char *arg_host = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic bool arg_read_only = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic bool arg_mkdir = false;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic bool arg_quiet = false;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic bool arg_ask_password = true;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic unsigned arg_lines = 10;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic OutputMode arg_output = OUTPUT_SHORT;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic bool arg_force = false;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic ImportVerify arg_verify = IMPORT_VERIFY_SIGNATURE;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic const char* arg_dkr_index_url = NULL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic const char* arg_format = NULL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic const char *arg_uid = NULL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic char **arg_setenv = NULL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void pager_open_if_enabled(void) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (arg_no_pager)
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen return;
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering pager_open(false);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poetteringstatic void polkit_agent_open_if_enabled(void) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen /* Open the polkit agent as a child process if necessary */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!arg_ask_password)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (arg_transport != BUS_TRANSPORT_LOCAL)
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering return;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen polkit_agent_open();
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic OutputFlags get_output_flags(void) {
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen return
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen arg_all * OUTPUT_SHOW_ALL |
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering arg_full * OUTPUT_FULL_WIDTH |
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering on_tty() * OUTPUT_COLOR |
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering !arg_quiet * OUTPUT_WARN_CUTOFF;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersentypedef struct MachineInfo {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering const char *name;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering const char *class;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering const char *service;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering} MachineInfo;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstatic int compare_machine_info(const void *a, const void *b) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering const MachineInfo *x = a, *y = b;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering return strcmp(x->name, y->name);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering}
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstatic int list_machines(int argc, char *argv[], void *userdata) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering size_t max_name = strlen("MACHINE"), max_class = strlen("CLASS"), max_service = strlen("SERVICE");
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering _cleanup_free_ MachineInfo *machines = NULL;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering const char *name, *class, *service, *object;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering size_t n_machines = 0, n_allocated = 0, j;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering sd_bus *bus = userdata;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering int r;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(bus);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering pager_open_if_enabled();
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering r = sd_bus_call_method(
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering bus,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering "org.freedesktop.machine1",
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering "/org/freedesktop/machine1",
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering "org.freedesktop.machine1.Manager",
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering "ListMachines",
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering &error,
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering &reply,
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering NULL);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering if (r < 0) {
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering log_error("Could not get machines: %s", bus_error_message(&error, -r));
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering return r;
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering }
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering r = sd_bus_message_enter_container(reply, 'a', "(ssso)");
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (r < 0)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return bus_log_parse_error(r);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering while ((r = sd_bus_message_read(reply, "(ssso)", &name, &class, &service, &object)) > 0) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering size_t l;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (name[0] == '.' && !arg_all)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering continue;
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (!GREEDY_REALLOC(machines, n_allocated, n_machines + 1))
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return log_oom();
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering machines[n_machines].name = name;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering machines[n_machines].class = class;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering machines[n_machines].service = service;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering l = strlen(name);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (l > max_name)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering max_name = l;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering l = strlen(class);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (l > max_class)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering max_class = l;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering l = strlen(service);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (l > max_service)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering max_service = l;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering n_machines ++;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering }
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (r < 0)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return bus_log_parse_error(r);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering r = sd_bus_message_exit_container(reply);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (r < 0)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return bus_log_parse_error(r);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering qsort_safe(machines, n_machines, sizeof(MachineInfo), compare_machine_info);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (arg_legend)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering printf("%-*s %-*s %-*s\n",
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering (int) max_name, "MACHINE",
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering (int) max_class, "CLASS",
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering (int) max_service, "SERVICE");
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering for (j = 0; j < n_machines; j++)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering printf("%-*s %-*s %-*s\n",
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering (int) max_name, machines[j].name,
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering (int) max_class, machines[j].class,
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering (int) max_service, machines[j].service);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (arg_legend)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering printf("\n%zu machines listed.\n", n_machines);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return 0;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering}
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poetteringtypedef struct ImageInfo {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering const char *name;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering const char *type;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering bool read_only;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering usec_t crtime;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering usec_t mtime;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering uint64_t size;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering} ImageInfo;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poetteringstatic int compare_image_info(const void *a, const void *b) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering const ImageInfo *x = a, *y = b;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return strcmp(x->name, y->name);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering}
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poetteringstatic int list_images(int argc, char *argv[], void *userdata) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering size_t max_name = strlen("NAME"), max_type = strlen("TYPE"), max_size = strlen("USAGE"), max_crtime = strlen("CREATED"), max_mtime = strlen("MODIFIED");
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering _cleanup_free_ ImageInfo *images = NULL;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering size_t n_images = 0, n_allocated = 0, j;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering const char *name, *type, *object;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering sd_bus *bus = userdata;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering uint64_t crtime, mtime, size;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering int read_only, r;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering assert(bus);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering pager_open_if_enabled();
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering r = sd_bus_call_method(
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering bus,
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering "org.freedesktop.machine1",
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering "/org/freedesktop/machine1",
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering "org.freedesktop.machine1.Manager",
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering "ListImages",
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering &error,
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering &reply,
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering "");
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (r < 0) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering log_error("Could not get images: %s", bus_error_message(&error, -r));
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return r;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering }
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssbttto)");
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (r < 0)
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return bus_log_parse_error(r);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering while ((r = sd_bus_message_read(reply, "(ssbttto)", &name, &type, &read_only, &crtime, &mtime, &size, &object)) > 0) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering char buf[MAX(FORMAT_TIMESTAMP_MAX, FORMAT_BYTES_MAX)];
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering size_t l;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (name[0] == '.' && !arg_all)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering continue;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!GREEDY_REALLOC(images, n_allocated, n_images + 1))
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return log_oom();
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering images[n_images].name = name;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers images[n_images].type = type;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering images[n_images].read_only = read_only;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering images[n_images].crtime = crtime;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering images[n_images].mtime = mtime;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering images[n_images].size = size;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering l = strlen(name);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (l > max_name)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering max_name = l;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering l = strlen(type);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (l > max_type)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering max_type = l;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (crtime != 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering l = strlen(strna(format_timestamp(buf, sizeof(buf), crtime)));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (l > max_crtime)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering max_crtime = l;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (mtime != 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering l = strlen(strna(format_timestamp(buf, sizeof(buf), mtime)));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (l > max_mtime)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering max_mtime = l;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (size != (uint64_t) -1) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering l = strlen(strna(format_bytes(buf, sizeof(buf), size)));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (l > max_size)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering max_size = l;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering n_images++;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return bus_log_parse_error(r);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_message_exit_container(reply);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return bus_log_parse_error(r);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering qsort_safe(images, n_images, sizeof(ImageInfo), compare_image_info);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (arg_legend)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("%-*s %-*s %-3s %-*s %-*s %-*s\n",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (int) max_name, "NAME",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (int) max_type, "TYPE",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "RO",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (int) max_size, "USAGE",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (int) max_crtime, "CREATED",
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering (int) max_mtime, "MODIFIED");
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering for (j = 0; j < n_images; j++) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering char crtime_buf[FORMAT_TIMESTAMP_MAX], mtime_buf[FORMAT_TIMESTAMP_MAX], size_buf[FORMAT_BYTES_MAX];
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering printf("%-*s %-*s %s%-3s%s %-*s %-*s %-*s\n",
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering (int) max_name, images[j].name,
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering (int) max_type, images[j].type,
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering images[j].read_only ? ansi_highlight_red() : "", yes_no(images[j].read_only), images[j].read_only ? ansi_normal() : "",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (int) max_size, strna(format_bytes(size_buf, sizeof(size_buf), images[j].size)),
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (int) max_crtime, strna(format_timestamp(crtime_buf, sizeof(crtime_buf), images[j].crtime)),
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (int) max_mtime, strna(format_timestamp(mtime_buf, sizeof(mtime_buf), images[j].mtime)));
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers }
a6c616024db23fef34152c1432892824a07799ccLennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (arg_legend)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers printf("\n%zu images listed.\n", n_images);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return 0;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering}
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sieversstatic int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers _cleanup_free_ char *path = NULL;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers const char *cgroup;
a6c616024db23fef34152c1432892824a07799ccLennart Poettering int r;
a6c616024db23fef34152c1432892824a07799ccLennart Poettering unsigned c;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(unit);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (arg_transport == BUS_TRANSPORT_REMOTE)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return 0;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers path = unit_dbus_path_from_name(unit);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (!path)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return log_oom();
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers r = sd_bus_get_property(
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen bus,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "org.freedesktop.systemd1",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering path,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering unit_dbus_interface_from_name(unit),
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "ControlGroup",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering &error,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering &reply,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers "s");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers log_error("Failed to query ControlGroup: %s", bus_error_message(&error, -r));
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return r;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers }
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers r = sd_bus_message_read(reply, "s", &cgroup);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return bus_log_parse_error(r);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup) != 0 && leader <= 0)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return 0;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering c = columns();
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (c > 18)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers c -= 18;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers c = 0;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
27e72d6b22890ba4a8cbc05c49667cd1cccf1461Simon Peeters show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, false, &leader, leader > 0, get_output_flags());
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return 0;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poetteringstatic int print_addresses(sd_bus *bus, const char *name, int ifi, const char *prefix, const char *prefix2) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(bus);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(name);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers assert(prefix);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(prefix2);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_call_method(bus,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "org.freedesktop.machine1",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "/org/freedesktop/machine1",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "org.freedesktop.machine1.Manager",
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers "GetMachineAddresses",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering NULL,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering &reply,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "s", name);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (r < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return r;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_message_enter_container(reply, 'a', "(iay)");
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (r < 0)
8c841f21f5042b11acc91cc1b039cb162cbbe8f4Djalal Harouni return bus_log_parse_error(r);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int family;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const void *a;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering size_t sz;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char buffer[MAX(INET6_ADDRSTRLEN, INET_ADDRSTRLEN)];
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = sd_bus_message_read(reply, "i", &family);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (r < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return bus_log_parse_error(r);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = sd_bus_message_read_array(reply, 'y', &a, &sz);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (r < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return bus_log_parse_error(r);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen fputs(prefix, stdout);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen fputs(inet_ntop(family, a, buffer, sizeof(buffer)), stdout);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (family == AF_INET6 && ifi > 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen printf("%%%i", ifi);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen fputc('\n', stdout);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering r = sd_bus_message_exit_container(reply);
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return bus_log_parse_error(r);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (prefix != prefix2)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers prefix = prefix2;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return bus_log_parse_error(r);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_message_exit_container(reply);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return bus_log_parse_error(r);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int print_os_release(sd_bus *bus, const char *name, const char *prefix) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const char *k, *v, *pretty = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(name);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(prefix);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = sd_bus_call_method(bus,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen "org.freedesktop.machine1",
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen "/org/freedesktop/machine1",
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen "org.freedesktop.machine1.Manager",
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen "GetMachineOSRelease",
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen NULL,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen &reply,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen "s", name);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_message_enter_container(reply, 'a', "{ss}");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return bus_log_parse_error(r);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering while ((r = sd_bus_message_read(reply, "{ss}", &k, &v)) > 0) {
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering if (streq(k, "PRETTY_NAME"))
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering pretty = v;
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering if (r < 0)
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering return bus_log_parse_error(r);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering r = sd_bus_message_exit_container(reply);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering if (r < 0)
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering return bus_log_parse_error(r);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering if (pretty)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("%s%s\n", prefix, pretty);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering return 0;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering}
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poetteringtypedef struct MachineStatusInfo {
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering char *name;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering sd_id128_t id;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering char *class;
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering char *service;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering char *unit;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering char *root_directory;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering pid_t leader;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering struct dual_timestamp timestamp;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering int *netif;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering unsigned n_netif;
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering} MachineStatusInfo;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poetteringstatic void machine_status_info_clear(MachineStatusInfo *info) {
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering if (info) {
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering free(info->name);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering free(info->class);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering free(info->service);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering free(info->unit);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering free(info->root_directory);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering free(info->netif);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering zero(*info);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering }
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
3d94f76c99da13e5603831d0b278f8c8c21bcb02Lennart Poetteringstatic void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) {
a4475f577bd0daf762d6c3b4e58bc484e0cb74afLennart Poettering char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering char since2[FORMAT_TIMESTAMP_MAX], *s2;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering int ifi = -1;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek assert(bus);
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek assert(i);
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek fputs(strna(i->name), stdout);
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (!sd_id128_equal(i->id, SD_ID128_NULL))
f69157a66ffe413b4cf8bd79057487fc8921e78bThomas Hindoe Paaboel Andersen printf("(" SD_ID128_FORMAT_STR ")\n", SD_ID128_FORMAT_VAL(i->id));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering else
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering putchar('\n');
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering s1 = format_timestamp_relative(since1, sizeof(since1), i->timestamp.realtime);
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poettering s2 = format_timestamp(since2, sizeof(since2), i->timestamp.realtime);
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (s1)
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poettering printf("\t Since: %s; %s\n", s2, s1);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering else if (s2)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering printf("\t Since: %s\n", s2);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (i->leader > 0) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering _cleanup_free_ char *t = NULL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering printf("\t Leader: %u", (unsigned) i->leader);
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering get_process_comm(i->leader, &t);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (t)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering printf(" (%s)", t);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering putchar('\n');
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (i->service) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering printf("\t Service: %s", i->service);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (i->class)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering printf("; class %s", i->class);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering putchar('\n');
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering } else if (i->class)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering printf("\t Class: %s\n", i->class);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poettering if (i->root_directory)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering printf("\t Root: %s\n", i->root_directory);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (i->n_netif > 0) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering unsigned c;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering fputs("\t Iface:", stdout);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
fbadf04511389c4a0687ba5e9baf0ecebdbb07f1Lennart Poettering for (c = 0; c < i->n_netif; c++) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering char name[IF_NAMESIZE+1] = "";
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (if_indextoname(i->netif[c], name)) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering fputc(' ', stdout);
fbadf04511389c4a0687ba5e9baf0ecebdbb07f1Lennart Poettering fputs(name, stdout);
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (ifi < 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering ifi = i->netif[c];
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering else
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering ifi = 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering } else
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering printf(" %i", i->netif[c]);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering fputc('\n', stdout);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering print_addresses(bus, i->name, ifi,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering "\t Address: ",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering "\t ");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering print_os_release(bus, i->name, "\t OS: ");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (i->unit) {
6261f11fc3d0a8b63c5afa5313d96607a008b54eLennart Poettering printf("\t Unit: %s\n", i->unit);
6261f11fc3d0a8b63c5afa5313d96607a008b54eLennart Poettering show_unit_cgroup(bus, i->unit, i->leader);
6261f11fc3d0a8b63c5afa5313d96607a008b54eLennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (arg_transport == BUS_TRANSPORT_LOCAL)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering show_journal_by_unit(
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering stdout,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering i->unit,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering arg_output,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering 0,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering i->timestamp.monotonic,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering arg_lines,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering 0,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering get_output_flags() | OUTPUT_BEGIN_NEWLINE,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering SD_JOURNAL_LOCAL_ONLY,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering true,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic int map_netif(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering MachineStatusInfo *i = userdata;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering size_t l;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering const void *v;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering int r;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert_cc(sizeof(int32_t) == sizeof(int));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = sd_bus_message_read_array(m, SD_BUS_TYPE_INT32, &v, &l);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (r < 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return r;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (r == 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -EBADMSG;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering i->n_netif = l / sizeof(int32_t);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering i->netif = memdup(v, l);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (!i->netif)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -ENOMEM;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poetteringstatic int show_machine_info(const char *verb, sd_bus *bus, const char *path, bool *new_line) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering static const struct bus_properties_map map[] = {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "Name", "s", NULL, offsetof(MachineStatusInfo, name) },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "Class", "s", NULL, offsetof(MachineStatusInfo, class) },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "Service", "s", NULL, offsetof(MachineStatusInfo, service) },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "Unit", "s", NULL, offsetof(MachineStatusInfo, unit) },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "RootDirectory", "s", NULL, offsetof(MachineStatusInfo, root_directory) },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "Leader", "u", NULL, offsetof(MachineStatusInfo, leader) },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "Timestamp", "t", NULL, offsetof(MachineStatusInfo, timestamp.realtime) },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "TimestampMonotonic", "t", NULL, offsetof(MachineStatusInfo, timestamp.monotonic) },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "Id", "ay", bus_map_id128, offsetof(MachineStatusInfo, id) },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering { "NetworkInterfaces", "ai", map_netif, 0 },
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering {}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering };
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering _cleanup_(machine_status_info_clear) MachineStatusInfo info = {};
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering int r;
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(verb);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(bus);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(path);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(new_line);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = bus_map_all_properties(bus,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering "org.freedesktop.machine1",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering path,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering map,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering &info);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (r < 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return log_error_errno(r, "Could not get properties: %m");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (*new_line)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering printf("\n");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering *new_line = true;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering print_machine_status_info(bus, &info);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
3db729cb8e6822114e9323f4041dcdc080f2fb3cJason A. Donenfeld return r;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic int show_machine_properties(sd_bus *bus, const char *path, bool *new_line) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering int r;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(bus);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(path);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(new_line);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (*new_line)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering printf("\n");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering *new_line = true;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, arg_property, arg_all);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (r < 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error_errno(r, "Could not get properties: %m");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return r;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic int show_machine(int argc, char *argv[], void *userdata) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering bool properties, new_line = false;
a6c616024db23fef34152c1432892824a07799ccLennart Poettering sd_bus *bus = userdata;
a6c616024db23fef34152c1432892824a07799ccLennart Poettering int r = 0, i;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(bus);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering properties = !strstr(argv[0], "status");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering pager_open_if_enabled();
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (properties && argc <= 1) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* If no argument is specified, inspect the manager
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * itself */
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = show_machine_properties(bus, "/org/freedesktop/machine1", &new_line);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (r < 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return r;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering for (i = 1; i < argc; i++) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering const char *path = NULL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_call_method(
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering bus,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "org.freedesktop.machine1",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "/org/freedesktop/machine1",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "org.freedesktop.machine1.Manager",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "GetMachine",
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering &error,
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen &reply,
53755121e1c8ebd3db0330bc82965ecf9a986449Lennart Poettering "s", argv[i]);
53755121e1c8ebd3db0330bc82965ecf9a986449Lennart Poettering if (r < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Could not get path to machine: %s", bus_error_message(&error, -r));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering r = sd_bus_message_read(reply, "o", &path);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return bus_log_parse_error(r);
4f8f66cb4236783cd3cbee97fefc9aaa8469ac08Zbigniew Jędrzejewski-Szmek
4f8f66cb4236783cd3cbee97fefc9aaa8469ac08Zbigniew Jędrzejewski-Szmek if (properties)
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering r = show_machine_properties(bus, path, &new_line);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering else
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering r = show_machine_info(argv[0], bus, path, &new_line);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering }
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringtypedef struct ImageStatusInfo {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char *name;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char *path;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char *type;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int read_only;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering usec_t crtime;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering usec_t mtime;
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen uint64_t usage;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering uint64_t limit;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering uint64_t usage_exclusive;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering uint64_t limit_exclusive;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering} ImageStatusInfo;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void image_status_info_clear(ImageStatusInfo *info) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (info) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(info->name);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(info->path);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(info->type);
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen zero(*info);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poetteringstatic void print_image_status_info(sd_bus *bus, ImageStatusInfo *i) {
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering char ts_relative[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char ts_absolute[FORMAT_TIMESTAMP_MAX], *s2;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char bs[FORMAT_BYTES_MAX], *s3;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering char bs_exclusive[FORMAT_BYTES_MAX], *s4;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(i);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering if (i->name) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fputs(i->name, stdout);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering putchar('\n');
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering if (i->type)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\t Type: %s\n", i->type);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (i->path)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\t Path: %s\n", i->path);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\t RO: %s%s%s\n",
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering i->read_only ? ansi_highlight_red() : "",
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering i->read_only ? "read-only" : "writable",
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering i->read_only ? ansi_normal() : "");
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s1 = format_timestamp_relative(ts_relative, sizeof(ts_relative), i->crtime);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s2 = format_timestamp(ts_absolute, sizeof(ts_absolute), i->crtime);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (s1 && s2)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\t Created: %s; %s\n", s2, s1);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else if (s2)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\t Created: %s\n", s2);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s1 = format_timestamp_relative(ts_relative, sizeof(ts_relative), i->mtime);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s2 = format_timestamp(ts_absolute, sizeof(ts_absolute), i->mtime);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (s1 && s2)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\tModified: %s; %s\n", s2, s1);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else if (s2)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\tModified: %s\n", s2);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s3 = format_bytes(bs, sizeof(bs), i->usage);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s4 = i->usage_exclusive != i->usage ? format_bytes(bs_exclusive, sizeof(bs_exclusive), i->usage_exclusive) : NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (s3 && s4)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\t Usage: %s (exclusive: %s)\n", s3, s4);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else if (s3)
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen printf("\t Usage: %s\n", s3);
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen s3 = format_bytes(bs, sizeof(bs), i->limit);
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen s4 = i->limit_exclusive != i->limit ? format_bytes(bs_exclusive, sizeof(bs_exclusive), i->limit_exclusive) : NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (s3 && s4)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\t Limit: %s (exclusive: %s)\n", s3, s4);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else if (s3)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\t Limit: %s\n", s3);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int show_image_info(sd_bus *bus, const char *path, bool *new_line) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering static const struct bus_properties_map map[] = {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "Name", "s", NULL, offsetof(ImageStatusInfo, name) },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "Path", "s", NULL, offsetof(ImageStatusInfo, path) },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "Type", "s", NULL, offsetof(ImageStatusInfo, type) },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "ReadOnly", "b", NULL, offsetof(ImageStatusInfo, read_only) },
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering { "CreationTimestamp", "t", NULL, offsetof(ImageStatusInfo, crtime) },
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering { "ModificationTimestamp", "t", NULL, offsetof(ImageStatusInfo, mtime) },
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering { "Usage", "t", NULL, offsetof(ImageStatusInfo, usage) },
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering { "Limit", "t", NULL, offsetof(ImageStatusInfo, limit) },
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering { "UsageExclusive", "t", NULL, offsetof(ImageStatusInfo, usage_exclusive) },
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering { "LimitExclusive", "t", NULL, offsetof(ImageStatusInfo, limit_exclusive) },
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering {}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering };
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_(image_status_info_clear) ImageStatusInfo info = {};
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(bus);
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering assert(path);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(new_line);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = bus_map_all_properties(bus,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "org.freedesktop.machine1",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering path,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering map,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering &info);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return log_error_errno(r, "Could not get properties: %m");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (*new_line)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\n");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *new_line = true;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering print_image_status_info(bus, &info);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringtypedef struct PoolStatusInfo {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char *path;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering uint64_t usage;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering uint64_t limit;
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering} PoolStatusInfo;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic void pool_status_info_clear(PoolStatusInfo *info) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (info) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(info->path);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering zero(*info);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering info->usage = -1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering info->limit = -1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void print_pool_status_info(sd_bus *bus, PoolStatusInfo *i) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char bs[FORMAT_BYTES_MAX], *s;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
46e65dcc3a522b5e992e165b5e61d14254026859Lennart Poettering if (i->path)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\t Path: %s\n", i->path);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s = format_bytes(bs, sizeof(bs), i->usage);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (s)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\t Usage: %s\n", s);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s = format_bytes(bs, sizeof(bs), i->limit);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (s)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\t Limit: %s\n", s);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int show_pool_info(sd_bus *bus) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering static const struct bus_properties_map map[] = {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "PoolPath", "s", NULL, offsetof(PoolStatusInfo, path) },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "PoolUsage", "t", NULL, offsetof(PoolStatusInfo, usage) },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "PoolLimit", "t", NULL, offsetof(PoolStatusInfo, limit) },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering {}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering };
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_(pool_status_info_clear) PoolStatusInfo info = {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering .usage = (uint64_t) -1,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering .limit = (uint64_t) -1,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering };
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = bus_map_all_properties(bus,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "org.freedesktop.machine1",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "/org/freedesktop/machine1",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering map,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering &info);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return log_error_errno(r, "Could not get properties: %m");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering print_pool_status_info(bus, &info);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int show_image_properties(sd_bus *bus, const char *path, bool *new_line) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(path);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(new_line);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (*new_line)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\n");
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering *new_line = true;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, arg_property, arg_all);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error_errno(r, "Could not get properties: %m");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int show_image(int argc, char *argv[], void *userdata) {
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen bool properties, new_line = false;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen sd_bus *bus = userdata;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r = 0, i;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering properties = !strstr(argv[0], "status");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering pager_open_if_enabled();
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering if (argc <= 1) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
/* If no argument is specified, inspect the manager
* itself */
if (properties)
r = show_image_properties(bus, "/org/freedesktop/machine1", &new_line);
else
r = show_pool_info(bus);
if (r < 0)
return r;
}
for (i = 1; i < argc; i++) {
const char *path = NULL;
r = sd_bus_call_method(
bus,
"org.freedesktop.machine1",
"/org/freedesktop/machine1",
"org.freedesktop.machine1.Manager",
"GetImage",
&error,
&reply,
"s", argv[i]);
if (r < 0) {
log_error("Could not get path to image: %s", bus_error_message(&error, -r));
return r;
}
r = sd_bus_message_read(reply, "o", &path);
if (r < 0)
return bus_log_parse_error(r);
if (properties)
r = show_image_properties(bus, path, &new_line);
else
r = show_image_info(bus, path, &new_line);
}
return r;
}
static int kill_machine(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r, i;
assert(bus);
polkit_agent_open_if_enabled();
if (!arg_kill_who)
arg_kill_who = "all";
for (i = 1; i < argc; i++) {
r = sd_bus_call_method(
bus,
"org.freedesktop.machine1",
"/org/freedesktop/machine1",
"org.freedesktop.machine1.Manager",
"KillMachine",
&error,
NULL,
"ssi", argv[i], arg_kill_who, arg_signal);
if (r < 0) {
log_error("Could not kill machine: %s", bus_error_message(&error, -r));
return r;
}
}
return 0;
}
static int reboot_machine(int argc, char *argv[], void *userdata) {
arg_kill_who = "leader";
arg_signal = SIGINT; /* sysvinit + systemd */
return kill_machine(argc, argv, userdata);
}
static int poweroff_machine(int argc, char *argv[], void *userdata) {
arg_kill_who = "leader";
arg_signal = SIGRTMIN+4; /* only systemd */
return kill_machine(argc, argv, userdata);
}
static int terminate_machine(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r, i;
assert(bus);
polkit_agent_open_if_enabled();
for (i = 1; i < argc; i++) {
r = sd_bus_call_method(
bus,
"org.freedesktop.machine1",
"/org/freedesktop/machine1",
"org.freedesktop.machine1.Manager",
"TerminateMachine",
&error,
NULL,
"s", argv[i]);
if (r < 0) {
log_error("Could not terminate machine: %s", bus_error_message(&error, -r));
return r;
}
}
return 0;
}
static int copy_files(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_free_ char *abs_host_path = NULL;
char *dest, *host_path, *container_path;
sd_bus *bus = userdata;
bool copy_from;
int r;
assert(bus);
polkit_agent_open_if_enabled();
copy_from = streq(argv[0], "copy-from");
dest = argv[3] ?: argv[2];
host_path = copy_from ? dest : argv[2];
container_path = copy_from ? argv[2] : dest;
if (!path_is_absolute(host_path)) {
r = path_make_absolute_cwd(host_path, &abs_host_path);
if (r < 0)
return log_error_errno(r, "Failed to make path absolute: %m");
host_path = abs_host_path;
}
r = sd_bus_call_method(
bus,
"org.freedesktop.machine1",
"/org/freedesktop/machine1",
"org.freedesktop.machine1.Manager",
copy_from ? "CopyFromMachine" : "CopyToMachine",
&error,
NULL,
"sss",
argv[1],
copy_from ? container_path : host_path,
copy_from ? host_path : container_path);
if (r < 0)
return log_error_errno(r, "Failed to copy: %s", bus_error_message(&error, r));
return 0;
}
static int bind_mount(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r;
assert(bus);
polkit_agent_open_if_enabled();
r = sd_bus_call_method(
bus,
"org.freedesktop.machine1",
"/org/freedesktop/machine1",
"org.freedesktop.machine1.Manager",
"BindMountMachine",
&error,
NULL,
"sssbb",
argv[1],
argv[2],
argv[3],
arg_read_only,
arg_mkdir);
if (r < 0) {
log_error("Failed to bind mount: %s", bus_error_message(&error, -r));
return r;
}
return 0;
}
static int on_machine_removed(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
PTYForward ** forward = (PTYForward**) userdata;
int r;
assert(m);
assert(forward);
if (*forward) {
/* If the forwarder is already initialized, tell it to
* exit on the next vhangup(), so that we still flush
* out what might be queued and exit then. */
r = pty_forward_set_ignore_vhangup(*forward, false);
if (r >= 0)
return 0;
log_error_errno(r, "Failed to set ignore_vhangup flag: %m");
}
/* On error, or when the forwarder is not initialized yet, quit immediately */
sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), EXIT_FAILURE);
return 0;
}
static int process_forward(sd_event *event, PTYForward **forward, int master, PTYForwardFlags flags, const char *name) {
char last_char = 0;
bool machine_died;
int ret = 0, r;
assert(event);
assert(master >= 0);
assert(name);
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGWINCH, SIGTERM, SIGINT, -1) >= 0);
if (streq(name, ".host"))
log_info("Connected to the local host. Press ^] three times within 1s to exit session.");
else
log_info("Connected to machine %s. Press ^] three times within 1s to exit session.", name);
sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
r = pty_forward_new(event, master, flags, forward);
if (r < 0)
return log_error_errno(r, "Failed to create PTY forwarder: %m");
r = sd_event_loop(event);
if (r < 0)
return log_error_errno(r, "Failed to run event loop: %m");
pty_forward_get_last_char(*forward, &last_char);
machine_died =
(flags & PTY_FORWARD_IGNORE_VHANGUP) &&
pty_forward_get_ignore_vhangup(*forward) == 0;
*forward = pty_forward_free(*forward);
if (last_char != '\n')
fputc('\n', stdout);
if (machine_died)
log_info("Machine %s terminated.", name);
else if (streq(name, ".host"))
log_info("Connection to the local host terminated.");
else
log_info("Connection to machine %s terminated.", name);
sd_event_get_exit_code(event, &ret);
return ret;
}
static int login_machine(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(pty_forward_freep) PTYForward *forward = NULL;
_cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL;
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
int master = -1, r;
sd_bus *bus = userdata;
const char *pty, *match, *machine;
assert(bus);
if (!strv_isempty(arg_setenv) || arg_uid) {
log_error("--setenv= and --uid= are not supported for 'login'. Use 'shell' instead.");
return -EINVAL;
}
if (arg_transport != BUS_TRANSPORT_LOCAL &&
arg_transport != BUS_TRANSPORT_MACHINE) {
log_error("Login only supported on local machines.");
return -EOPNOTSUPP;
}
polkit_agent_open_if_enabled();
r = sd_event_default(&event);
if (r < 0)
return log_error_errno(r, "Failed to get event loop: %m");
r = sd_bus_attach_event(bus, event, 0);
if (r < 0)
return log_error_errno(r, "Failed to attach bus to event loop: %m");
machine = argc < 2 || isempty(argv[1]) ? ".host" : argv[1];
match = strjoina("type='signal',"
"sender='org.freedesktop.machine1',"
"path='/org/freedesktop/machine1',",
"interface='org.freedesktop.machine1.Manager',"
"member='MachineRemoved',"
"arg0='", machine, "'");
r = sd_bus_add_match(bus, &slot, match, on_machine_removed, &forward);
if (r < 0)
return log_error_errno(r, "Failed to add machine removal match: %m");
r = sd_bus_call_method(
bus,
"org.freedesktop.machine1",
"/org/freedesktop/machine1",
"org.freedesktop.machine1.Manager",
"OpenMachineLogin",
&error,
&reply,
"s", machine);
if (r < 0) {
log_error("Failed to get login PTY: %s", bus_error_message(&error, -r));
return r;
}
r = sd_bus_message_read(reply, "hs", &master, &pty);
if (r < 0)
return bus_log_parse_error(r);
return process_forward(event, &forward, master, PTY_FORWARD_IGNORE_VHANGUP, machine);
}
static int shell_machine(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(pty_forward_freep) PTYForward *forward = NULL;
_cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL;
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
int master = -1, r;
sd_bus *bus = userdata;
const char *pty, *match, *machine, *path, *uid = NULL;
assert(bus);
if (arg_transport != BUS_TRANSPORT_LOCAL &&
arg_transport != BUS_TRANSPORT_MACHINE) {
log_error("Shell only supported on local machines.");
return -EOPNOTSUPP;
}
/* Pass $TERM to shell session, if not explicitly specified. */
if (!strv_find_prefix(arg_setenv, "TERM=")) {
const char *t;
t = strv_find_prefix(environ, "TERM=");
if (t) {
if (strv_extend(&arg_setenv, t) < 0)
return log_oom();
}
}
polkit_agent_open_if_enabled();
r = sd_event_default(&event);
if (r < 0)
return log_error_errno(r, "Failed to get event loop: %m");
r = sd_bus_attach_event(bus, event, 0);
if (r < 0)
return log_error_errno(r, "Failed to attach bus to event loop: %m");
machine = argc < 2 || isempty(argv[1]) ? NULL : argv[1];
if (arg_uid)
uid = arg_uid;
else if (machine) {
const char *at;
at = strchr(machine, '@');
if (at) {
uid = strndupa(machine, at - machine);
machine = at + 1;
}
}
if (isempty(machine))
machine = ".host";
match = strjoina("type='signal',"
"sender='org.freedesktop.machine1',"
"path='/org/freedesktop/machine1',",
"interface='org.freedesktop.machine1.Manager',"
"member='MachineRemoved',"
"arg0='", machine, "'");
r = sd_bus_add_match(bus, &slot, match, on_machine_removed, &forward);
if (r < 0)
return log_error_errno(r, "Failed to add machine removal match: %m");
r = sd_bus_message_new_method_call(
bus,
&m,
"org.freedesktop.machine1",
"/org/freedesktop/machine1",
"org.freedesktop.machine1.Manager",
"OpenMachineShell");
if (r < 0)
return bus_log_create_error(r);
path = argc < 3 || isempty(argv[2]) ? NULL : argv[2];
r = sd_bus_message_append(m, "sss", machine, uid, path);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_append_strv(m, strv_length(argv) <= 3 ? NULL : argv + 2);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_append_strv(m, arg_setenv);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_call(bus, m, 0, &error, &reply);
if (r < 0) {
log_error("Failed to get shell PTY: %s", bus_error_message(&error, -r));
return r;
}
r = sd_bus_message_read(reply, "hs", &master, &pty);
if (r < 0)
return bus_log_parse_error(r);
return process_forward(event, &forward, master, 0, machine);
}
static int remove_image(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r, i;
assert(bus);
polkit_agent_open_if_enabled();
for (i = 1; i < argc; i++) {
r = sd_bus_call_method(
bus,
"org.freedesktop.machine1",
"/org/freedesktop/machine1",
"org.freedesktop.machine1.Manager",
"RemoveImage",
&error,
NULL,
"s", argv[i]);
if (r < 0) {
log_error("Could not remove image: %s", bus_error_message(&error, -r));
return r;
}
}
return 0;
}
static int rename_image(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r;
polkit_agent_open_if_enabled();
r = sd_bus_call_method(
bus,
"org.freedesktop.machine1",
"/org/freedesktop/machine1",
"org.freedesktop.machine1.Manager",
"RenameImage",
&error,
NULL,
"ss", argv[1], argv[2]);
if (r < 0) {
log_error("Could not rename image: %s", bus_error_message(&error, -r));
return r;
}
return 0;
}
static int clone_image(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r;
polkit_agent_open_if_enabled();
r = sd_bus_call_method(
bus,
"org.freedesktop.machine1",
"/org/freedesktop/machine1",
"org.freedesktop.machine1.Manager",
"CloneImage",
&error,
NULL,
"ssb", argv[1], argv[2], arg_read_only);
if (r < 0) {
log_error("Could not clone image: %s", bus_error_message(&error, -r));
return r;
}
return 0;
}
static int read_only_image(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int b = true, r;
if (argc > 2) {
b = parse_boolean(argv[2]);
if (b < 0) {
log_error("Failed to parse boolean argument: %s", argv[2]);
return -EINVAL;
}
}
polkit_agent_open_if_enabled();
r = sd_bus_call_method(
bus,
"org.freedesktop.machine1",
"/org/freedesktop/machine1",
"org.freedesktop.machine1.Manager",
"MarkImageReadOnly",
&error,
NULL,
"sb", argv[1], b);
if (r < 0) {
log_error("Could not mark image read-only: %s", bus_error_message(&error, -r));
return r;
}
return 0;
}
static int make_service_name(const char *name, char **ret) {
_cleanup_free_ char *e = NULL;
int r;
assert(name);
assert(ret);
if (!machine_name_is_valid(name)) {
log_error("Invalid machine name %s.", name);
return -EINVAL;
}
e = unit_name_escape(name);
if (!e)
return log_oom();
r = unit_name_build("systemd-nspawn", e, ".service", ret);
if (r < 0)
return log_error_errno(r, "Failed to build unit name: %m");
return 0;
}
static int start_machine(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
sd_bus *bus = userdata;
int r, i;
assert(bus);
polkit_agent_open_if_enabled();
r = bus_wait_for_jobs_new(bus, &w);
if (r < 0)
return log_oom();
for (i = 1; i < argc; i++) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_free_ char *unit = NULL;
const char *object;
r = make_service_name(argv[i], &unit);
if (r < 0)
return r;
r = sd_bus_call_method(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"StartUnit",
&error,
&reply,
"ss", unit, "fail");
if (r < 0) {
log_error("Failed to start unit: %s", bus_error_message(&error, -r));
return r;
}
r = sd_bus_message_read(reply, "o", &object);
if (r < 0)
return bus_log_parse_error(r);
r = bus_wait_for_jobs_add(w, object);
if (r < 0)
return log_oom();
}
r = bus_wait_for_jobs(w, arg_quiet);
if (r < 0)
return r;
return 0;
}
static int enable_machine(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int carries_install_info = 0;
const char *method = NULL;
sd_bus *bus = userdata;
int r, i;
assert(bus);
polkit_agent_open_if_enabled();
method = streq(argv[0], "enable") ? "EnableUnitFiles" : "DisableUnitFiles";
r = sd_bus_message_new_method_call(
bus,
&m,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
method);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_open_container(m, 'a', "s");
if (r < 0)
return bus_log_create_error(r);
for (i = 1; i < argc; i++) {
_cleanup_free_ char *unit = NULL;
r = make_service_name(argv[i], &unit);
if (r < 0)
return r;
r = sd_bus_message_append(m, "s", unit);
if (r < 0)
return bus_log_create_error(r);
}
r = sd_bus_message_close_container(m);
if (r < 0)
return bus_log_create_error(r);
if (streq(argv[0], "enable"))
r = sd_bus_message_append(m, "bb", false, false);
else
r = sd_bus_message_append(m, "b", false);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_call(bus, m, 0, &error, &reply);
if (r < 0) {
log_error("Failed to enable or disable unit: %s", bus_error_message(&error, -r));
return r;
}
if (streq(argv[0], "enable")) {
r = sd_bus_message_read(reply, "b", carries_install_info);
if (r < 0)
return bus_log_parse_error(r);
}
r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, NULL, NULL);
if (r < 0)
return r;
r = sd_bus_call_method(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"Reload",
&error,
NULL,
NULL);
if (r < 0) {
log_error("Failed to reload daemon: %s", bus_error_message(&error, -r));
return r;
}
return 0;
}
static int match_log_message(sd_bus_message *m, void *userdata, sd_bus_error *error) {
const char **our_path = userdata, *line;
unsigned priority;
int r;
assert(m);
assert(our_path);
r = sd_bus_message_read(m, "us", &priority, &line);
if (r < 0) {
bus_log_parse_error(r);
return 0;
}
if (!streq_ptr(*our_path, sd_bus_message_get_path(m)))
return 0;
if (arg_quiet && LOG_PRI(priority) >= LOG_INFO)
return 0;
log_full(priority, "%s", line);
return 0;
}
static int match_transfer_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
const char **our_path = userdata, *path, *result;
uint32_t id;
int r;
assert(m);
assert(our_path);
r = sd_bus_message_read(m, "uos", &id, &path, &result);
if (r < 0) {
bus_log_parse_error(r);
return 0;
}
if (!streq_ptr(*our_path, path))
return 0;
sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), !streq_ptr(result, "done"));
return 0;
}
static int transfer_signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
assert(s);
assert(si);
if (!arg_quiet)
log_info("Continuing download in the background. Use \"machinectl cancel-transfer %" PRIu32 "\" to abort transfer.", PTR_TO_UINT32(userdata));
sd_event_exit(sd_event_source_get_event(s), EINTR);
return 0;
}
static int transfer_image_common(sd_bus *bus, sd_bus_message *m) {
_cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot_job_removed = NULL, *slot_log_message = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_(sd_event_unrefp) sd_event* event = NULL;
const char *path = NULL;
uint32_t id;
int r;
assert(bus);
assert(m);
polkit_agent_open_if_enabled();
r = sd_event_default(&event);
if (r < 0)
return log_error_errno(r, "Failed to get event loop: %m");
r = sd_bus_attach_event(bus, event, 0);
if (r < 0)
return log_error_errno(r, "Failed to attach bus to event loop: %m");
r = sd_bus_add_match(
bus,
&slot_job_removed,
"type='signal',"
"sender='org.freedesktop.import1',"
"interface='org.freedesktop.import1.Manager',"
"member='TransferRemoved',"
"path='/org/freedesktop/import1'",
match_transfer_removed, &path);
if (r < 0)
return log_error_errno(r, "Failed to install match: %m");
r = sd_bus_add_match(
bus,
&slot_log_message,
"type='signal',"
"sender='org.freedesktop.import1',"
"interface='org.freedesktop.import1.Transfer',"
"member='LogMessage'",
match_log_message, &path);
if (r < 0)
return log_error_errno(r, "Failed to install match: %m");
r = sd_bus_call(bus, m, 0, &error, &reply);
if (r < 0) {
log_error("Failed transfer image: %s", bus_error_message(&error, -r));
return r;
}
r = sd_bus_message_read(reply, "uo", &id, &path);
if (r < 0)
return bus_log_parse_error(r);
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
if (!arg_quiet)
log_info("Enqueued transfer job %u. Press C-c to continue download in background.", id);
sd_event_add_signal(event, NULL, SIGINT, transfer_signal_handler, UINT32_TO_PTR(id));
sd_event_add_signal(event, NULL, SIGTERM, transfer_signal_handler, UINT32_TO_PTR(id));
r = sd_event_loop(event);
if (r < 0)
return log_error_errno(r, "Failed to run event loop: %m");
return -r;
}
static int import_tar(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_free_ char *ll = NULL;
_cleanup_close_ int fd = -1;
const char *local = NULL, *path = NULL;
sd_bus *bus = userdata;
int r;
assert(bus);
if (argc >= 2)
path = argv[1];
if (isempty(path) || streq(path, "-"))
path = NULL;
if (argc >= 3)
local = argv[2];
else if (path)
local = basename(path);
if (isempty(local) || streq(local, "-"))
local = NULL;
if (!local) {
log_error("Need either path or local name.");
return -EINVAL;
}
r = tar_strip_suffixes(local, &ll);
if (r < 0)
return log_oom();
local = ll;
if (!machine_name_is_valid(local)) {
log_error("Local name %s is not a suitable machine name.", local);
return -EINVAL;
}
if (path) {
fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY);
if (fd < 0)
return log_error_errno(errno, "Failed to open %s: %m", path);
}
r = sd_bus_message_new_method_call(
bus,
&m,
"org.freedesktop.import1",
"/org/freedesktop/import1",
"org.freedesktop.import1.Manager",
"ImportTar");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_append(
m,
"hsbb",
fd >= 0 ? fd : STDIN_FILENO,
local,
arg_force,
arg_read_only);
if (r < 0)
return bus_log_create_error(r);
return transfer_image_common(bus, m);
}
static int import_raw(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_free_ char *ll = NULL;
_cleanup_close_ int fd = -1;
const char *local = NULL, *path = NULL;
sd_bus *bus = userdata;
int r;
assert(bus);
if (argc >= 2)
path = argv[1];
if (isempty(path) || streq(path, "-"))
path = NULL;
if (argc >= 3)
local = argv[2];
else if (path)
local = basename(path);
if (isempty(local) || streq(local, "-"))
local = NULL;
if (!local) {
log_error("Need either path or local name.");
return -EINVAL;
}
r = raw_strip_suffixes(local, &ll);
if (r < 0)
return log_oom();
local = ll;
if (!machine_name_is_valid(local)) {
log_error("Local name %s is not a suitable machine name.", local);
return -EINVAL;
}
if (path) {
fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY);
if (fd < 0)
return log_error_errno(errno, "Failed to open %s: %m", path);
}
r = sd_bus_message_new_method_call(
bus,
&m,
"org.freedesktop.import1",
"/org/freedesktop/import1",
"org.freedesktop.import1.Manager",
"ImportRaw");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_append(
m,
"hsbb",
fd >= 0 ? fd : STDIN_FILENO,
local,
arg_force,
arg_read_only);
if (r < 0)
return bus_log_create_error(r);
return transfer_image_common(bus, m);
}
static void determine_compression_from_filename(const char *p) {
if (arg_format)
return;
if (!p)
return;
if (endswith(p, ".xz"))
arg_format = "xz";
else if (endswith(p, ".gz"))
arg_format = "gzip";
else if (endswith(p, ".bz2"))
arg_format = "bzip2";
}
static int export_tar(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_close_ int fd = -1;
const char *local = NULL, *path = NULL;
sd_bus *bus = userdata;
int r;
assert(bus);
local = argv[1];
if (!machine_name_is_valid(local)) {
log_error("Machine name %s is not valid.", local);
return -EINVAL;
}
if (argc >= 3)
path = argv[2];
if (isempty(path) || streq(path, "-"))
path = NULL;
if (path) {
determine_compression_from_filename(path);
fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC|O_NOCTTY, 0666);
if (fd < 0)
return log_error_errno(errno, "Failed to open %s: %m", path);
}
r = sd_bus_message_new_method_call(
bus,
&m,
"org.freedesktop.import1",
"/org/freedesktop/import1",
"org.freedesktop.import1.Manager",
"ExportTar");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_append(
m,
"shs",
local,
fd >= 0 ? fd : STDOUT_FILENO,
arg_format);
if (r < 0)
return bus_log_create_error(r);
return transfer_image_common(bus, m);
}
static int export_raw(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_close_ int fd = -1;
const char *local = NULL, *path = NULL;
sd_bus *bus = userdata;
int r;
assert(bus);
local = argv[1];
if (!machine_name_is_valid(local)) {
log_error("Machine name %s is not valid.", local);
return -EINVAL;
}
if (argc >= 3)
path = argv[2];
if (isempty(path) || streq(path, "-"))
path = NULL;
if (path) {
determine_compression_from_filename(path);
fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC|O_NOCTTY, 0666);
if (fd < 0)
return log_error_errno(errno, "Failed to open %s: %m", path);
}
r = sd_bus_message_new_method_call(
bus,
&m,
"org.freedesktop.import1",
"/org/freedesktop/import1",
"org.freedesktop.import1.Manager",
"ExportRaw");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_append(
m,
"shs",
local,
fd >= 0 ? fd : STDOUT_FILENO,
arg_format);
if (r < 0)
return bus_log_create_error(r);
return transfer_image_common(bus, m);
}
static int pull_tar(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_free_ char *l = NULL, *ll = NULL;
const char *local, *remote;
sd_bus *bus = userdata;
int r;
assert(bus);
remote = argv[1];
if (!http_url_is_valid(remote)) {
log_error("URL '%s' is not valid.", remote);
return -EINVAL;
}
if (argc >= 3)
local = argv[2];
else {
r = import_url_last_component(remote, &l);
if (r < 0)
return log_error_errno(r, "Failed to get final component of URL: %m");
local = l;
}
if (isempty(local) || streq(local, "-"))
local = NULL;
if (local) {
r = tar_strip_suffixes(local, &ll);
if (r < 0)
return log_oom();
local = ll;
if (!machine_name_is_valid(local)) {
log_error("Local name %s is not a suitable machine name.", local);
return -EINVAL;
}
}
r = sd_bus_message_new_method_call(
bus,
&m,
"org.freedesktop.import1",
"/org/freedesktop/import1",
"org.freedesktop.import1.Manager",
"PullTar");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_append(
m,
"sssb",
remote,
local,
import_verify_to_string(arg_verify),
arg_force);
if (r < 0)
return bus_log_create_error(r);
return transfer_image_common(bus, m);
}
static int pull_raw(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_free_ char *l = NULL, *ll = NULL;
const char *local, *remote;
sd_bus *bus = userdata;
int r;
assert(bus);
remote = argv[1];
if (!http_url_is_valid(remote)) {
log_error("URL '%s' is not valid.", remote);
return -EINVAL;
}
if (argc >= 3)
local = argv[2];
else {
r = import_url_last_component(remote, &l);
if (r < 0)
return log_error_errno(r, "Failed to get final component of URL: %m");
local = l;
}
if (isempty(local) || streq(local, "-"))
local = NULL;
if (local) {
r = raw_strip_suffixes(local, &ll);
if (r < 0)
return log_oom();
local = ll;
if (!machine_name_is_valid(local)) {
log_error("Local name %s is not a suitable machine name.", local);
return -EINVAL;
}
}
r = sd_bus_message_new_method_call(
bus,
&m,
"org.freedesktop.import1",
"/org/freedesktop/import1",
"org.freedesktop.import1.Manager",
"PullRaw");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_append(
m,
"sssb",
remote,
local,
import_verify_to_string(arg_verify),
arg_force);
if (r < 0)
return bus_log_create_error(r);
return transfer_image_common(bus, m);
}
static int pull_dkr(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
const char *local, *remote, *tag;
sd_bus *bus = userdata;
int r;
if (arg_verify != IMPORT_VERIFY_NO) {
log_error("Imports from DKR do not support image verification, please pass --verify=no.");
return -EINVAL;
}
remote = argv[1];
tag = strchr(remote, ':');
if (tag) {
remote = strndupa(remote, tag - remote);
tag++;
}
if (!dkr_name_is_valid(remote)) {
log_error("DKR name '%s' is invalid.", remote);
return -EINVAL;
}
if (tag && !dkr_tag_is_valid(tag)) {
log_error("DKR tag '%s' is invalid.", remote);
return -EINVAL;
}
if (argc >= 3)
local = argv[2];
else {
local = strchr(remote, '/');
if (local)
local++;
else
local = remote;
}
if (isempty(local) || streq(local, "-"))
local = NULL;
if (local) {
if (!machine_name_is_valid(local)) {
log_error("Local name %s is not a suitable machine name.", local);
return -EINVAL;
}
}
r = sd_bus_message_new_method_call(
bus,
&m,
"org.freedesktop.import1",
"/org/freedesktop/import1",
"org.freedesktop.import1.Manager",
"PullDkr");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_append(
m,
"sssssb",
arg_dkr_index_url,
remote,
tag,
local,
import_verify_to_string(arg_verify),
arg_force);
if (r < 0)
return bus_log_create_error(r);
return transfer_image_common(bus, m);
}
typedef struct TransferInfo {
uint32_t id;
const char *type;
const char *remote;
const char *local;
double progress;
} TransferInfo;
static int compare_transfer_info(const void *a, const void *b) {
const TransferInfo *x = a, *y = b;
return strcmp(x->local, y->local);
}
static int list_transfers(int argc, char *argv[], void *userdata) {
size_t max_type = strlen("TYPE"), max_local = strlen("LOCAL"), max_remote = strlen("REMOTE");
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_free_ TransferInfo *transfers = NULL;
size_t n_transfers = 0, n_allocated = 0, j;
const char *type, *remote, *local, *object;
sd_bus *bus = userdata;
uint32_t id, max_id = 0;
double progress;
int r;
pager_open_if_enabled();
r = sd_bus_call_method(
bus,
"org.freedesktop.import1",
"/org/freedesktop/import1",
"org.freedesktop.import1.Manager",
"ListTransfers",
&error,
&reply,
NULL);
if (r < 0) {
log_error("Could not get transfers: %s", bus_error_message(&error, -r));
return r;
}
r = sd_bus_message_enter_container(reply, 'a', "(usssdo)");
if (r < 0)
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(reply, "(usssdo)", &id, &type, &remote, &local, &progress, &object)) > 0) {
size_t l;
if (!GREEDY_REALLOC(transfers, n_allocated, n_transfers + 1))
return log_oom();
transfers[n_transfers].id = id;
transfers[n_transfers].type = type;
transfers[n_transfers].remote = remote;
transfers[n_transfers].local = local;
transfers[n_transfers].progress = progress;
l = strlen(type);
if (l > max_type)
max_type = l;
l = strlen(remote);
if (l > max_remote)
max_remote = l;
l = strlen(local);
if (l > max_local)
max_local = l;
if (id > max_id)
max_id = id;
n_transfers ++;
}
if (r < 0)
return bus_log_parse_error(r);
r = sd_bus_message_exit_container(reply);
if (r < 0)
return bus_log_parse_error(r);
qsort_safe(transfers, n_transfers, sizeof(TransferInfo), compare_transfer_info);
if (arg_legend)
printf("%-*s %-*s %-*s %-*s %-*s\n",
(int) MAX(2U, DECIMAL_STR_WIDTH(max_id)), "ID",
(int) 7, "PERCENT",
(int) max_type, "TYPE",
(int) max_local, "LOCAL",
(int) max_remote, "REMOTE");
for (j = 0; j < n_transfers; j++)
printf("%*" PRIu32 " %*u%% %-*s %-*s %-*s\n",
(int) MAX(2U, DECIMAL_STR_WIDTH(max_id)), transfers[j].id,
(int) 6, (unsigned) (transfers[j].progress * 100),
(int) max_type, transfers[j].type,
(int) max_local, transfers[j].local,
(int) max_remote, transfers[j].remote);
if (arg_legend)
printf("\n%zu transfers listed.\n", n_transfers);
return 0;
}
static int cancel_transfer(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r, i;
assert(bus);
polkit_agent_open_if_enabled();
for (i = 1; i < argc; i++) {
uint32_t id;
r = safe_atou32(argv[i], &id);
if (r < 0)
return log_error_errno(r, "Failed to parse transfer id: %s", argv[i]);
r = sd_bus_call_method(
bus,
"org.freedesktop.import1",
"/org/freedesktop/import1",
"org.freedesktop.import1.Manager",
"CancelTransfer",
&error,
NULL,
"u", id);
if (r < 0) {
log_error("Could not cancel transfer: %s", bus_error_message(&error, -r));
return r;
}
}
return 0;
}
static int set_limit(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
uint64_t limit;
int r;
if (STR_IN_SET(argv[argc-1], "-", "none", "infinity"))
limit = (uint64_t) -1;
else {
r = parse_size(argv[argc-1], 1024, &limit);
if (r < 0)
return log_error("Failed to parse size: %s", argv[argc-1]);
}
if (argc > 2)
/* With two arguments changes the quota limit of the
* specified image */
r = sd_bus_call_method(
bus,
"org.freedesktop.machine1",
"/org/freedesktop/machine1",
"org.freedesktop.machine1.Manager",
"SetImageLimit",
&error,
NULL,
"st", argv[1], limit);
else
/* With one argument changes the pool quota limit */
r = sd_bus_call_method(
bus,
"org.freedesktop.machine1",
"/org/freedesktop/machine1",
"org.freedesktop.machine1.Manager",
"SetPoolLimit",
&error,
NULL,
"t", limit);
if (r < 0) {
log_error("Could not set limit: %s", bus_error_message(&error, -r));
return r;
}
return 0;
}
static int help(int argc, char *argv[], void *userdata) {
printf("%s [OPTIONS...] {COMMAND} ...\n\n"
"Send control commands to or query the virtual machine and container\n"
"registration manager.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
" --no-pager Do not pipe output into a pager\n"
" --no-legend Do not show the headers and footers\n"
" --no-ask-password Do not ask for system passwords\n"
" -H --host=[USER@]HOST Operate on remote host\n"
" -M --machine=CONTAINER Operate on local container\n"
" -p --property=NAME Show only properties by this name\n"
" -q --quiet Suppress output\n"
" -a --all Show all properties, including empty ones\n"
" -l --full Do not ellipsize output\n"
" --kill-who=WHO Who to send signal to\n"
" -s --signal=SIGNAL Which signal to send\n"
" --uid=USER Specify user ID to invoke shell as\n"
" --setenv=VAR=VALUE Add an environment variable for shell\n"
" --read-only Create read-only bind mount\n"
" --mkdir Create directory before bind mounting, if missing\n"
" -n --lines=INTEGER Number of journal entries to show\n"
" -o --output=STRING Change journal output mode (short,\n"
" short-monotonic, verbose, export, json,\n"
" json-pretty, json-sse, cat)\n"
" --verify=MODE Verification mode for downloaded images (no,\n"
" checksum, signature)\n"
" --force Download image even if already exists\n"
" --dkr-index-url=URL Specify the index URL to use for DKR image\n"
" downloads\n\n"
"Machine Commands:\n"
" list List running VMs and containers\n"
" status NAME... Show VM/container details\n"
" show [NAME...] Show properties of one or more VMs/containers\n"
" start NAME... Start container as a service\n"
" login [NAME] Get a login prompt in a container or on the\n"
" local host\n"
" shell [[USER@]NAME [COMMAND...]]\n"
" Invoke a shell (or other command) in a container\n"
" or on the local host\n"
" enable NAME... Enable automatic container start at boot\n"
" disable NAME... Disable automatic container start at boot\n"
" poweroff NAME... Power off one or more containers\n"
" reboot NAME... Reboot one or more containers\n"
" terminate NAME... Terminate one or more VMs/containers\n"
" kill NAME... Send signal to processes of a VM/container\n"
" copy-to NAME PATH [PATH] Copy files from the host to a container\n"
" copy-from NAME PATH [PATH] Copy files from a container to the host\n"
" bind NAME PATH [PATH] Bind mount a path from the host into a container\n\n"
"Image Commands:\n"
" list-images Show available container and VM images\n"
" image-status [NAME...] Show image details\n"
" show-image [NAME...] Show properties of image\n"
" clone NAME NAME Clone an image\n"
" rename NAME NAME Rename an image\n"
" read-only NAME [BOOL] Mark or unmark image read-only\n"
" remove NAME... Remove an image\n"
" set-limit [NAME] BYTES Set image or pool size limit (disk quota)\n\n"
"Image Transfer Commands:\n"
" pull-tar URL [NAME] Download a TAR container image\n"
" pull-raw URL [NAME] Download a RAW container or VM image\n"
" pull-dkr REMOTE [NAME] Download a DKR container image\n"
" import-tar FILE [NAME] Import a local TAR container image\n"
" import-raw FILE [NAME] Import a local RAW container or VM image\n"
" export-tar NAME [FILE] Export a TAR container image locally\n"
" export-raw NAME [FILE] Export a RAW container or VM image locally\n"
" list-transfers Show list of downloads in progress\n"
" cancel-transfer Cancel a download\n"
, program_invocation_short_name);
return 0;
}
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
ARG_NO_PAGER,
ARG_NO_LEGEND,
ARG_KILL_WHO,
ARG_READ_ONLY,
ARG_MKDIR,
ARG_NO_ASK_PASSWORD,
ARG_VERIFY,
ARG_FORCE,
ARG_DKR_INDEX_URL,
ARG_FORMAT,
ARG_UID,
ARG_SETENV,
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "property", required_argument, NULL, 'p' },
{ "all", no_argument, NULL, 'a' },
{ "full", no_argument, NULL, 'l' },
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
{ "no-legend", no_argument, NULL, ARG_NO_LEGEND },
{ "kill-who", required_argument, NULL, ARG_KILL_WHO },
{ "signal", required_argument, NULL, 's' },
{ "host", required_argument, NULL, 'H' },
{ "machine", required_argument, NULL, 'M' },
{ "read-only", no_argument, NULL, ARG_READ_ONLY },
{ "mkdir", no_argument, NULL, ARG_MKDIR },
{ "quiet", no_argument, NULL, 'q' },
{ "lines", required_argument, NULL, 'n' },
{ "output", required_argument, NULL, 'o' },
{ "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
{ "verify", required_argument, NULL, ARG_VERIFY },
{ "force", no_argument, NULL, ARG_FORCE },
{ "dkr-index-url", required_argument, NULL, ARG_DKR_INDEX_URL },
{ "format", required_argument, NULL, ARG_FORMAT },
{ "uid", required_argument, NULL, ARG_UID },
{ "setenv", required_argument, NULL, ARG_SETENV },
{}
};
int c, r;
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, "hp:als:H:M:qn:o:", options, NULL)) >= 0)
switch (c) {
case 'h':
return help(0, NULL, NULL);
case ARG_VERSION:
return version();
case 'p':
r = strv_extend(&arg_property, optarg);
if (r < 0)
return log_oom();
/* If the user asked for a particular
* property, show it to him, even if it is
* empty. */
arg_all = true;
break;
case 'a':
arg_all = true;
break;
case 'l':
arg_full = true;
break;
case 'n':
if (safe_atou(optarg, &arg_lines) < 0) {
log_error("Failed to parse lines '%s'", optarg);
return -EINVAL;
}
break;
case 'o':
arg_output = output_mode_from_string(optarg);
if (arg_output < 0) {
log_error("Unknown output '%s'.", optarg);
return -EINVAL;
}
break;
case ARG_NO_PAGER:
arg_no_pager = true;
break;
case ARG_NO_LEGEND:
arg_legend = false;
break;
case ARG_KILL_WHO:
arg_kill_who = optarg;
break;
case 's':
arg_signal = signal_from_string_try_harder(optarg);
if (arg_signal < 0) {
log_error("Failed to parse signal string %s.", optarg);
return -EINVAL;
}
break;
case ARG_NO_ASK_PASSWORD:
arg_ask_password = false;
break;
case 'H':
arg_transport = BUS_TRANSPORT_REMOTE;
arg_host = optarg;
break;
case 'M':
arg_transport = BUS_TRANSPORT_MACHINE;
arg_host = optarg;
break;
case ARG_READ_ONLY:
arg_read_only = true;
break;
case ARG_MKDIR:
arg_mkdir = true;
break;
case 'q':
arg_quiet = true;
break;
case ARG_VERIFY:
arg_verify = import_verify_from_string(optarg);
if (arg_verify < 0) {
log_error("Failed to parse --verify= setting: %s", optarg);
return -EINVAL;
}
break;
case ARG_FORCE:
arg_force = true;
break;
case ARG_DKR_INDEX_URL:
if (!http_url_is_valid(optarg)) {
log_error("Index URL is invalid: %s", optarg);
return -EINVAL;
}
arg_dkr_index_url = optarg;
break;
case ARG_FORMAT:
if (!STR_IN_SET(optarg, "uncompressed", "xz", "gzip", "bzip2")) {
log_error("Unknown format: %s", optarg);
return -EINVAL;
}
arg_format = optarg;
break;
case ARG_UID:
arg_uid = optarg;
break;
case ARG_SETENV:
if (!env_assignment_is_valid(optarg)) {
log_error("Environment assignment invalid: %s", optarg);
return -EINVAL;
}
r = strv_extend(&arg_setenv, optarg);
if (r < 0)
return log_oom();
break;
case '?':
return -EINVAL;
default:
assert_not_reached("Unhandled option");
}
return 1;
}
static int machinectl_main(int argc, char *argv[], sd_bus *bus) {
static const Verb verbs[] = {
{ "help", VERB_ANY, VERB_ANY, 0, help },
{ "list", VERB_ANY, 1, VERB_DEFAULT, list_machines },
{ "list-images", VERB_ANY, 1, 0, list_images },
{ "status", 2, VERB_ANY, 0, show_machine },
{ "image-status", VERB_ANY, VERB_ANY, 0, show_image },
{ "show", VERB_ANY, VERB_ANY, 0, show_machine },
{ "show-image", VERB_ANY, VERB_ANY, 0, show_image },
{ "terminate", 2, VERB_ANY, 0, terminate_machine },
{ "reboot", 2, VERB_ANY, 0, reboot_machine },
{ "poweroff", 2, VERB_ANY, 0, poweroff_machine },
{ "kill", 2, VERB_ANY, 0, kill_machine },
{ "login", VERB_ANY, 2, 0, login_machine },
{ "shell", VERB_ANY, VERB_ANY, 0, shell_machine },
{ "bind", 3, 4, 0, bind_mount },
{ "copy-to", 3, 4, 0, copy_files },
{ "copy-from", 3, 4, 0, copy_files },
{ "remove", 2, VERB_ANY, 0, remove_image },
{ "rename", 3, 3, 0, rename_image },
{ "clone", 3, 3, 0, clone_image },
{ "read-only", 2, 3, 0, read_only_image },
{ "start", 2, VERB_ANY, 0, start_machine },
{ "enable", 2, VERB_ANY, 0, enable_machine },
{ "disable", 2, VERB_ANY, 0, enable_machine },
{ "import-tar", 2, 3, 0, import_tar },
{ "import-raw", 2, 3, 0, import_raw },
{ "export-tar", 2, 3, 0, export_tar },
{ "export-raw", 2, 3, 0, export_raw },
{ "pull-tar", 2, 3, 0, pull_tar },
{ "pull-raw", 2, 3, 0, pull_raw },
{ "pull-dkr", 2, 3, 0, pull_dkr },
{ "list-transfers", VERB_ANY, 1, 0, list_transfers },
{ "cancel-transfer", 2, VERB_ANY, 0, cancel_transfer },
{ "set-limit", 2, 3, 0, set_limit },
{}
};
return dispatch_verb(argc, argv, verbs, bus);
}
int main(int argc, char*argv[]) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r;
setlocale(LC_ALL, "");
log_parse_environment();
log_open();
r = parse_argv(argc, argv);
if (r <= 0)
goto finish;
r = bus_connect_transport(arg_transport, arg_host, false, &bus);
if (r < 0) {
log_error_errno(r, "Failed to create bus connection: %m");
goto finish;
}
sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
r = machinectl_main(argc, argv, bus);
finish:
pager_close();
polkit_agent_close();
strv_free(arg_property);
strv_free(arg_setenv);
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}