machinectl.c revision ebd011d95b61a86258dece9864f65b7c4af721c0
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
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <sys/socket.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <unistd.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <errno.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <string.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <getopt.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <pwd.h>
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering#include <locale.h>
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering#include <fcntl.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <netinet/in.h>
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#include <arpa/inet.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <net/if.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <sys/mount.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <libgen.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#include "sd-bus.h"
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#include "log.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "macro.h"
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering#include "pager.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "bus-util.h"
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering#include "bus-error.h"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering#include "build.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "strv.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "unit-name.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "cgroup-show.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "cgroup-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "ptyfwd.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "event-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "path-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "mkdir.h"
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering#include "copy.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "verbs.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic char **arg_property = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic bool arg_all = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic bool arg_full = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic bool arg_no_pager = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic bool arg_legend = true;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic 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;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic bool arg_read_only = false;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic bool arg_mkdir = false;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic void pager_open_if_enabled(void) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Cache result before we open the pager */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (arg_no_pager)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen pager_open(false);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic int list_machines(int argc, char *argv[], void *userdata) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen const char *name, *class, *service, *object;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen sd_bus *bus = userdata;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen unsigned k = 0;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering pager_open_if_enabled();
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_call_method(
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen bus,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen "org.freedesktop.machine1",
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen "/org/freedesktop/machine1",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "org.freedesktop.machine1.Manager",
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen "ListMachines",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering &error,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering &reply,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_error("Could not get machines: %s", bus_error_message(&error, -r));
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return r;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (arg_legend)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen printf("%-32s %-9s %-16s\n", "MACHINE", "CONTAINER", "SERVICE");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssso)");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return bus_log_parse_error(r);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen while ((r = sd_bus_message_read(reply, "(ssso)", &name, &class, &service, &object)) > 0) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen printf("%-32s %-9s %-16s\n", name, class, service);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering k++;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return bus_log_parse_error(r);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = sd_bus_message_exit_container(reply);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (r < 0)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return bus_log_parse_error(r);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (arg_legend)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering printf("\n%u machines listed.\n", k);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return 0;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering}
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringtypedef struct ImageInfo {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering const char *name;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering const char *type;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering bool read_only;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering usec_t crtime;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering usec_t mtime;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering uint64_t size;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering} ImageInfo;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstatic int compare_image_info(const void *a, const void *b) {
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering const ImageInfo *x = a, *y = b;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return strcmp(x->name, y->name);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstatic int list_images(int argc, char *argv[], void *userdata) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering size_t max_name = strlen("NAME"), max_type = strlen("TYPE"), max_size = strlen("SIZE"), max_crtime = strlen("CREATED"), max_mtime = strlen("MODIFIED");
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering _cleanup_free_ ImageInfo *images = NULL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen size_t n_images = 0, n_allocated = 0, j;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen const char *name, *type, *object;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen sd_bus *bus = userdata;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering uint64_t crtime, mtime, size;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering int read_only, r;
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering assert(bus);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering pager_open_if_enabled();
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering r = sd_bus_call_method(
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering bus,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering "org.freedesktop.machine1",
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering "/org/freedesktop/machine1",
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering "org.freedesktop.machine1.Manager",
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering "ListImages",
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering &error,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering &reply,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering "");
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (r < 0) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering log_error("Could not get images: %s", bus_error_message(&error, -r));
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering return r;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering }
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssbttto)");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return bus_log_parse_error(r);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers while ((r = sd_bus_message_read(reply, "(ssbttto)", &name, &type, &read_only, &crtime, &mtime, &size, &object)) > 0) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers char buf[MAX(FORMAT_TIMESTAMP_MAX, FORMAT_BYTES_MAX)];
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers size_t l;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (name[0] == '.' && !arg_all)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering continue;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!GREEDY_REALLOC(images, n_allocated, n_images + 1))
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return log_oom();
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering images[n_images].name = name;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering 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;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
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);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (arg_legend)
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering printf("%-*s %-*s %-3s %-*s %-*s %-*s\n",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (int) max_name, "NAME",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (int) max_type, "TYPE",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "RO",
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers (int) max_size, "SIZE",
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers (int) max_crtime, "CREATED",
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers (int) max_mtime, "MODIFIED");
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers for (j = 0; j < n_images; j++) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers char crtime_buf[FORMAT_TIMESTAMP_MAX], mtime_buf[FORMAT_TIMESTAMP_MAX], size_buf[FORMAT_BYTES_MAX];
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers printf("%-*s %-*s %s%-3s%s %-*s %-*s %-*s\n",
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers (int) max_name, images[j].name,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers (int) max_type, images[j].type,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers images[j].read_only ? ansi_highlight_red() : "", yes_no(images[j].read_only), images[j].read_only ? ansi_highlight_off() : "",
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers (int) max_size, strna(format_bytes(size_buf, sizeof(size_buf), images[j].size)),
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers (int) max_crtime, strna(format_timestamp(crtime_buf, sizeof(crtime_buf), images[j].crtime)),
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen (int) max_mtime, strna(format_timestamp(mtime_buf, sizeof(mtime_buf), images[j].mtime)));
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return bus_log_parse_error(r);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (arg_legend)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers printf("\n%zu images listed.\n", n_images);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return 0;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_free_ char *path = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const char *cgroup;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r, output_flags;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers unsigned c;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers assert(bus);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers assert(unit);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (arg_transport == BUS_TRANSPORT_REMOTE)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers path = unit_dbus_path_from_name(unit);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (!path)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return log_oom();
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers r = sd_bus_get_property(
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering bus,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers "org.freedesktop.systemd1",
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers path,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering endswith(unit, ".scope") ? "org.freedesktop.systemd1.Scope" : "org.freedesktop.systemd1.Service",
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers "ControlGroup",
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen &error,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers &reply,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen "s");
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (r < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Failed to query ControlGroup: %s", bus_error_message(&error, -r));
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = sd_bus_message_read(reply, "s", &cgroup);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (r < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return bus_log_parse_error(r);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (isempty(cgroup))
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup, false) != 0 && leader <= 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers output_flags =
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering arg_all * OUTPUT_SHOW_ALL |
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering arg_full * OUTPUT_FULL_WIDTH;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers c = columns();
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (c > 18)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers c -= 18;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers c = 0;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, false, &leader, leader > 0, output_flags);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return 0;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int print_addresses(sd_bus *bus, const char *name, int ifi, const char *prefix, const char *prefix2) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(bus);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(name);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(prefix);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(prefix2);
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 "GetMachineAddresses",
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen NULL,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen &reply,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen "s", name);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (r < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return r;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = sd_bus_message_enter_container(reply, 'a', "(iay)");
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return bus_log_parse_error(r);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers int family;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers const void *a;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers size_t sz;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char buffer[MAX(INET6_ADDRSTRLEN, INET_ADDRSTRLEN)];
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers r = sd_bus_message_read(reply, "i", &family);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return bus_log_parse_error(r);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = sd_bus_message_read_array(reply, 'y', &a, &sz);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return bus_log_parse_error(r);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fputs(prefix, stdout);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fputs(inet_ntop(family, a, buffer, sizeof(buffer)), stdout);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (family == AF_INET6 && ifi > 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("%%%i", ifi);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fputc('\n', stdout);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_message_exit_container(reply);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (r < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return bus_log_parse_error(r);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (prefix != prefix2)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen prefix = prefix2;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (r < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return bus_log_parse_error(r);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = sd_bus_message_exit_container(reply);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering 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_bus_message_unref_ sd_bus_message *reply = NULL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen const char *k, *v, *pretty = NULL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(name);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(prefix);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_call_method(bus,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "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)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return r;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = sd_bus_message_enter_container(reply, 'a', "{ss}");
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return bus_log_parse_error(r);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering while ((r = sd_bus_message_read(reply, "{ss}", &k, &v)) > 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (streq(k, "PRETTY_NAME"))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering pretty = v;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (r < 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return bus_log_parse_error(r);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = sd_bus_message_exit_container(reply);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (r < 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return bus_log_parse_error(r);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (pretty)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering printf("%s%s\n", prefix, pretty);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
f69157a66ffe413b4cf8bd79057487fc8921e78bThomas Hindoe Paaboel Andersen return 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringtypedef struct MachineStatusInfo {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering char *name;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering sd_id128_t id;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering char *class;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering char *service;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering char *unit;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering char *root_directory;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering pid_t leader;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering usec_t timestamp;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering int *netif;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering unsigned n_netif;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering} MachineStatusInfo;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering char since2[FORMAT_TIMESTAMP_MAX], *s2;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering int ifi = -1;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(bus);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(i);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering fputs(strna(i->name), stdout);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (!sd_id128_equal(i->id, SD_ID128_NULL))
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering printf("(" SD_ID128_FORMAT_STR ")\n", SD_ID128_FORMAT_VAL(i->id));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering else
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering putchar('\n');
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering s1 = format_timestamp_relative(since1, sizeof(since1), i->timestamp);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering s2 = format_timestamp(since2, sizeof(since2), i->timestamp);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (s1)
04d39279245834494baccfdb9349db8bf80abd13Lennart 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);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering get_process_comm(i->leader, &t);
04d39279245834494baccfdb9349db8bf80abd13Lennart 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
04d39279245834494baccfdb9349db8bf80abd13Lennart 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
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering fputs("\t Iface:", stdout);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering for (c = 0; c < i->n_netif; c++) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering char name[IF_NAMESIZE+1] = "";
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (if_indextoname(i->netif[c], name)) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering fputc(' ', stdout);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering fputs(name, stdout);
04d39279245834494baccfdb9349db8bf80abd13Lennart 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) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering printf("\t Unit: %s\n", i->unit);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering show_unit_cgroup(bus, i->unit, i->leader);
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) {
04d39279245834494baccfdb9349db8bf80abd13Lennart 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}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart 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) },
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 MachineStatusInfo info = {};
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering int r;
04d39279245834494baccfdb9349db8bf80abd13Lennart 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
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering free(info.name);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering free(info.class);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering free(info.service);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering free(info.unit);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering free(info.root_directory);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering free(info.netif);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering 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_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering bool properties, new_line = false;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering sd_bus *bus = userdata;
04d39279245834494baccfdb9349db8bf80abd13Lennart 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
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = sd_bus_call_method(
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering bus,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering "org.freedesktop.machine1",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering "/org/freedesktop/machine1",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering "org.freedesktop.machine1.Manager",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering "GetMachine",
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering &error,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering &reply,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering "s", argv[i]);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (r < 0) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error("Could not get path to machine: %s", bus_error_message(&error, -r));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_message_read(reply, "o", &path);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return bus_log_parse_error(r);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering if (properties)
53755121e1c8ebd3db0330bc82965ecf9a986449Lennart Poettering r = show_machine_properties(bus, path, &new_line);
53755121e1c8ebd3db0330bc82965ecf9a986449Lennart Poettering else
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = show_machine_info(argv[0], bus, path, &new_line);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering return r;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringtypedef struct ImageStatusInfo {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char *name;
19887cd06a3af2f045e763986eda19e208bd3f85Zbigniew Jędrzejewski-Szmek char *path;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char *type;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering int read_only;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering usec_t crtime;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering usec_t mtime;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering uint64_t size;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering uint64_t limit;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering uint64_t size_exclusive;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering uint64_t limit_exclusive;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering} ImageStatusInfo;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void print_image_status_info(sd_bus *bus, ImageStatusInfo *i) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart 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;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char bs_exclusive[FORMAT_BYTES_MAX], *s4;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(i);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (i->name) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fputs(i->name, stdout);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering putchar('\n');
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (i->path)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\t Type: %s\n", i->type);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering if (i->path)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\t Path: %s\n", i->path);
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\t RO: %s%s%s\n",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering i->read_only ? ansi_highlight_red() : "",
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering i->read_only ? "read-only" : "writable",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering i->read_only ? ansi_highlight_off() : "");
1ee306e1248866617c96ed9f4263f375588ad838Lennart 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);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart 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
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart 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
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering s3 = format_bytes(bs, sizeof(bs), i->size);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering s4 = i->size_exclusive != i->size ? format_bytes(bs_exclusive, sizeof(bs_exclusive), i->size_exclusive) : NULL;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering if (s3 && s4)
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering printf("\t Size: %s (exclusive: %s)\n", s3, s4);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else if (s3)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("\t Size: %s\n", s3);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s3 = format_bytes(bs, sizeof(bs), i->limit);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering 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(const char *verb, 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) },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "CreationTimestamp", "t", NULL, offsetof(ImageStatusInfo, crtime) },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "ModificationTimestamp", "t", NULL, offsetof(ImageStatusInfo, mtime) },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "Size", "t", NULL, offsetof(ImageStatusInfo, size) },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "Limit", "t", NULL, offsetof(ImageStatusInfo, limit) },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "SizeExclusive", "t", NULL, offsetof(ImageStatusInfo, size_exclusive) },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { "LimitExclusive", "t", NULL, offsetof(ImageStatusInfo, limit_exclusive) },
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering {}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering };
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering ImageStatusInfo info = {};
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(verb);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(path);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(new_line);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = bus_map_all_properties(bus,
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering "org.freedesktop.machine1",
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering path,
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering map,
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering &info);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering if (r < 0)
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering return log_error_errno(r, "Could not get properties: %m");
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart 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
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering free(info.name);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(info.path);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(info.type);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart 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");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen *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;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int show_image(int argc, char *argv[], void *userdata) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering bool properties, new_line = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_bus *bus = userdata;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r = 0, i;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering properties = !strstr(argv[0], "status");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering pager_open_if_enabled();
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (properties && argc <= 1) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* If no argument is specified, inspect the manager
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * itself */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = show_image_properties(bus, "/org/freedesktop/machine1", &new_line);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (i = 1; i < argc; i++) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const char *path = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart 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 "GetImage",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering &error,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering &reply,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "s", argv[i]);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Could not get path to image: %s", bus_error_message(&error, -r));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_message_read(reply, "o", &path);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return bus_log_parse_error(r);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (properties)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = show_image_properties(bus, path, &new_line);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = show_image_info(argv[0], bus, path, &new_line);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int kill_machine(int argc, char *argv[], void *userdata) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_bus *bus = userdata;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int i;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!arg_kill_who)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering arg_kill_who = "all";
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering for (i = 1; i < argc; i++) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_call_method(
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering bus,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "org.freedesktop.machine1",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "/org/freedesktop/machine1",
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering "org.freedesktop.machine1.Manager",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "KillMachine",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering &error,
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering NULL,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen "ssi", argv[i], arg_kill_who, arg_signal);
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering if (r < 0) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_error("Could not kill machine: %s", bus_error_message(&error, -r));
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poetteringstatic int reboot_machine(int argc, char *argv[], void *userdata) {
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering arg_kill_who = "leader";
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering arg_signal = SIGINT; /* sysvinit + systemd */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
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_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int i;
assert(bus);
for (i = 1; i < argc; i++) {
int r;
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 machine_get_leader(sd_bus *bus, const char *name, pid_t *ret) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *reply2 = NULL;
const char *object;
uint32_t leader;
int r;
assert(bus);
assert(name);
assert(ret);
r = sd_bus_call_method(
bus,
"org.freedesktop.machine1",
"/org/freedesktop/machine1",
"org.freedesktop.machine1.Manager",
"GetMachine",
&error,
&reply,
"s", name);
if (r < 0) {
log_error("Could not get path to machine: %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 = sd_bus_get_property(
bus,
"org.freedesktop.machine1",
object,
"org.freedesktop.machine1.Machine",
"Leader",
&error,
&reply2,
"u");
if (r < 0)
return log_error_errno(r, "Failed to retrieve PID of leader: %m");
r = sd_bus_message_read(reply2, "u", &leader);
if (r < 0)
return bus_log_parse_error(r);
*ret = leader;
return 0;
}
static int copy_files(int argc, char *argv[], void *userdata) {
char *dest, *host_path, *container_path, *host_dirname, *host_basename, *container_dirname, *container_basename, *t;
_cleanup_close_ int hostfd = -1;
sd_bus *bus = userdata;
pid_t child, leader;
bool copy_from;
siginfo_t si;
int r;
assert(bus);
copy_from = streq(argv[0], "copy-from");
dest = argv[3] ?: argv[2];
host_path = strdupa(copy_from ? dest : argv[2]);
container_path = strdupa(copy_from ? argv[2] : dest);
if (!path_is_absolute(container_path)) {
log_error("Container path not absolute.");
return -EINVAL;
}
t = strdup(host_path);
host_basename = basename(t);
host_dirname = dirname(host_path);
t = strdup(container_path);
container_basename = basename(t);
container_dirname = dirname(container_path);
r = machine_get_leader(bus, argv[1], &leader);
if (r < 0)
return r;
hostfd = open(host_dirname, O_CLOEXEC|O_RDONLY|O_NOCTTY|O_DIRECTORY);
if (r < 0)
return log_error_errno(errno, "Failed to open source directory: %m");
child = fork();
if (child < 0)
return log_error_errno(errno, "Failed to fork(): %m");
if (child == 0) {
int containerfd;
const char *q;
int mntfd;
q = procfs_file_alloca(leader, "ns/mnt");
mntfd = open(q, O_RDONLY|O_NOCTTY|O_CLOEXEC);
if (mntfd < 0) {
log_error_errno(errno, "Failed to open mount namespace of leader: %m");
_exit(EXIT_FAILURE);
}
if (setns(mntfd, CLONE_NEWNS) < 0) {
log_error_errno(errno, "Failed to join namespace of leader: %m");
_exit(EXIT_FAILURE);
}
containerfd = open(container_dirname, O_CLOEXEC|O_RDONLY|O_NOCTTY|O_DIRECTORY);
if (containerfd < 0) {
log_error_errno(errno, "Failed top open destination directory: %m");
_exit(EXIT_FAILURE);
}
if (copy_from)
r = copy_tree_at(containerfd, container_basename, hostfd, host_basename, true);
else
r = copy_tree_at(hostfd, host_basename, containerfd, container_basename, true);
if (r < 0) {
log_error_errno(errno, "Failed to copy tree: %m");
_exit(EXIT_FAILURE);
}
_exit(EXIT_SUCCESS);
}
r = wait_for_terminate(child, &si);
if (r < 0)
return log_error_errno(r, "Failed to wait for client: %m");
if (si.si_code != CLD_EXITED) {
log_error("Client died abnormally.");
return -EIO;
}
if (si.si_status != EXIT_SUCCESS)
return -EIO;
return 0;
}
static int bind_mount(int argc, char *argv[], void *userdata) {
char mount_slave[] = "/tmp/propagate.XXXXXX", *mount_tmp, *mount_outside, *p;
sd_bus *bus = userdata;
pid_t child, leader;
const char *dest;
siginfo_t si;
bool mount_slave_created = false, mount_slave_mounted = false,
mount_tmp_created = false, mount_tmp_mounted = false,
mount_outside_created = false, mount_outside_mounted = false;
int r;
assert(bus);
/* One day, when bind mounting /proc/self/fd/n works across
* namespace boundaries we should rework this logic to make
* use of it... */
dest = argv[3] ?: argv[2];
if (!path_is_absolute(dest)) {
log_error("Destination path not absolute.");
return -EINVAL;
}
p = strappenda("/run/systemd/nspawn/propagate/", argv[1], "/");
if (access(p, F_OK) < 0) {
log_error("Container does not allow propagation of mount points.");
return -ENOTSUP;
}
r = machine_get_leader(bus, argv[1], &leader);
if (r < 0)
return r;
/* Our goal is to install a new bind mount into the container,
possibly read-only. This is irritatingly complex
unfortunately, currently.
First, we start by creating a private playground in /tmp,
that we can mount MS_SLAVE. (Which is necessary, since
MS_MOUNT cannot be applied to mounts with MS_SHARED parent
mounts.) */
if (!mkdtemp(mount_slave))
return log_error_errno(errno, "Failed to create playground: %m");
mount_slave_created = true;
if (mount(mount_slave, mount_slave, NULL, MS_BIND, NULL) < 0) {
r = log_error_errno(errno, "Failed to make bind mount: %m");
goto finish;
}
mount_slave_mounted = true;
if (mount(NULL, mount_slave, NULL, MS_SLAVE, NULL) < 0) {
r = log_error_errno(errno, "Failed to remount slave: %m");
goto finish;
}
/* Second, we mount the source directory to a directory inside
of our MS_SLAVE playground. */
mount_tmp = strappenda(mount_slave, "/mount");
if (mkdir(mount_tmp, 0700) < 0) {
r = log_error_errno(errno, "Failed to create temporary mount: %m");
goto finish;
}
mount_tmp_created = true;
if (mount(argv[2], mount_tmp, NULL, MS_BIND, NULL) < 0) {
r = log_error_errno(errno, "Failed to overmount: %m");
goto finish;
}
mount_tmp_mounted = true;
/* Third, we remount the new bind mount read-only if requested. */
if (arg_read_only)
if (mount(NULL, mount_tmp, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY, NULL) < 0) {
r = log_error_errno(errno, "Failed to mark read-only: %m");
goto finish;
}
/* Fourth, we move the new bind mount into the propagation
* directory. This way it will appear there read-only
* right-away. */
mount_outside = strappenda("/run/systemd/nspawn/propagate/", argv[1], "/XXXXXX");
if (!mkdtemp(mount_outside)) {
r = log_error_errno(errno, "Cannot create propagation directory: %m");
goto finish;
}
mount_outside_created = true;
if (mount(mount_tmp, mount_outside, NULL, MS_MOVE, NULL) < 0) {
r = log_error_errno(errno, "Failed to move: %m");
goto finish;
}
mount_outside_mounted = true;
mount_tmp_mounted = false;
(void) rmdir(mount_tmp);
mount_tmp_created = false;
(void) umount(mount_slave);
mount_slave_mounted = false;
(void) rmdir(mount_slave);
mount_slave_created = false;
child = fork();
if (child < 0) {
r = log_error_errno(errno, "Failed to fork(): %m");
goto finish;
}
if (child == 0) {
const char *mount_inside;
int mntfd;
const char *q;
q = procfs_file_alloca(leader, "ns/mnt");
mntfd = open(q, O_RDONLY|O_NOCTTY|O_CLOEXEC);
if (mntfd < 0) {
log_error_errno(errno, "Failed to open mount namespace of leader: %m");
_exit(EXIT_FAILURE);
}
if (setns(mntfd, CLONE_NEWNS) < 0) {
log_error_errno(errno, "Failed to join namespace of leader: %m");
_exit(EXIT_FAILURE);
}
if (arg_mkdir)
mkdir_p(dest, 0755);
/* Fifth, move the mount to the right place inside */
mount_inside = strappenda("/run/systemd/nspawn/incoming/", basename(mount_outside));
if (mount(mount_inside, dest, NULL, MS_MOVE, NULL) < 0) {
log_error_errno(errno, "Failed to mount: %m");
_exit(EXIT_FAILURE);
}
_exit(EXIT_SUCCESS);
}
r = wait_for_terminate(child, &si);
if (r < 0) {
log_error_errno(r, "Failed to wait for client: %m");
goto finish;
}
if (si.si_code != CLD_EXITED) {
log_error("Client died abnormally.");
r = -EIO;
goto finish;
}
if (si.si_status != EXIT_SUCCESS) {
r = -EIO;
goto finish;
}
r = 0;
finish:
if (mount_outside_mounted)
umount(mount_outside);
if (mount_outside_created)
rmdir(mount_outside);
if (mount_tmp_mounted)
umount(mount_tmp);
if (mount_tmp_created)
umount(mount_tmp);
if (mount_slave_mounted)
umount(mount_slave);
if (mount_slave_created)
umount(mount_slave);
return r;
}
static int login_machine(int argc, char *argv[], void *userdata) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
_cleanup_(pty_forward_freep) PTYForward *forward = NULL;
_cleanup_event_unref_ sd_event *event = NULL;
int master = -1, r, ret = 0;
sd_bus *bus = userdata;
const char *pty;
sigset_t mask;
char last_char = 0;
assert(bus);
if (arg_transport != BUS_TRANSPORT_LOCAL &&
arg_transport != BUS_TRANSPORT_MACHINE) {
log_error("Login only supported on local machines.");
return -ENOTSUP;
}
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_message_new_method_call(bus,
&m,
"org.freedesktop.machine1",
"/org/freedesktop/machine1",
"org.freedesktop.machine1.Manager",
"OpenMachineLogin");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_set_allow_interactive_authorization(m, true);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_append(m, "s", argv[1]);
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 machine 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);
assert_se(sigemptyset(&mask) == 0);
sigset_add_many(&mask, SIGWINCH, SIGTERM, SIGINT, -1);
assert_se(sigprocmask(SIG_BLOCK, &mask, NULL) == 0);
log_info("Connected to container %s. Press ^] three times within 1s to exit session.", argv[1]);
sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
r = pty_forward_new(event, master, true, &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_last_char(forward, &last_char);
forward = pty_forward_free(forward);
if (last_char != '\n')
fputc('\n', stdout);
log_info("Connection to container %s terminated.", argv[1]);
sd_event_get_exit_code(event, &ret);
return ret;
}
static int remove_image(int argc, char *argv[], void *userdata) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r, i;
assert(bus);
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_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r;
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_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus *bus = userdata;
int r;
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_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;
}
}
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 start_machine(int argc, char *argv[], void *userdata) {
_cleanup_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);
r = bus_wait_for_jobs_new(bus, &w);
if (r < 0)
return log_oom();
for (i = 1; i < argc; i++) {
_cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
_cleanup_free_ char *e = NULL, *unit = NULL;
const char *object;
if (!machine_name_is_valid(argv[i])) {
log_error("Invalid machine name %s.", argv[i]);
return -EINVAL;
}
e = unit_name_escape(argv[i]);
if (!e)
return log_oom();
unit = unit_name_build("systemd-nspawn", e, ".service");
if (!unit)
return log_oom();
r = sd_bus_message_new_method_call(
bus,
&m,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"StartUnit");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_set_allow_interactive_authorization(m, true);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_append(m, "ss", unit, "fail");
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 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, false);
if (r < 0)
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"
" -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"
" -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"
" --read-only Create read-only bind mount\n"
" --mkdir Create directory before bind mounting, if missing\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"
" login NAME Get a login prompt on a container\n"
" start NAME... Start container as a service\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 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",
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,
};
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 },
{}
};
int c, r;
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, "hp:als:H:M:", options, NULL)) >= 0)
switch (c) {
case 'h':
return help(0, NULL, NULL);
case ARG_VERSION:
puts(PACKAGE_STRING);
puts(SYSTEMD_FEATURES);
return 0;
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 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 '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 '?':
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",2, 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", 2, 2, 0, login_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 },
{}
};
return dispatch_verb(argc, argv, verbs, bus);
}
int main(int argc, char*argv[]) {
_cleanup_bus_close_unref_ 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_open_transport(arg_transport, arg_host, false, &bus);
if (r < 0) {
log_error_errno(r, "Failed to create bus connection: %m");
goto finish;
}
r = machinectl_main(argc, argv, bus);
finish:
pager_close();
strv_free(arg_property);
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}