machinectl.c revision d8f52ed25a9edce75fda5251c977b7898e33887e
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/***
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering This file is part of systemd.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Copyright 2013 Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is free software; you can redistribute it and/or modify it
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering under the terms of the GNU Lesser General Public License as published by
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (at your option) any later version.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is distributed in the hope that it will be useful, but
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Lesser General Public License for more details.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering You should have received a copy of the GNU Lesser General Public License
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering***/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1e02e182f1e06fcbe389474175de228103be39cbLennart Poettering#include <sys/socket.h>
1e02e182f1e06fcbe389474175de228103be39cbLennart Poettering#include <unistd.h>
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include <errno.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <string.h>
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering#include <getopt.h>
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include <pwd.h>
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen#include <locale.h>
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering#include <fcntl.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <netinet/in.h>
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen#include <arpa/inet.h>
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen#include <net/if.h>
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen#include <sys/mount.h>
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen#include <libgen.h>
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen#include "sd-bus.h"
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen#include "log.h"
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen#include "util.h"
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen#include "macro.h"
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen#include "pager.h"
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen#include "bus-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "bus-error.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "build.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "strv.h"
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering#include "unit-name.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "cgroup-show.h"
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering#include "cgroup-util.h"
3c0cf502796be355431d4a64d738e75f543aa51dLennart Poettering#include "ptyfwd.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "event-util.h"
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering#include "path-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "mkdir.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "copy.h"
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering#include "verbs.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic char **arg_property = NULL;
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poetteringstatic bool arg_all = false;
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poetteringstatic bool arg_full = false;
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poetteringstatic bool arg_no_pager = false;
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poetteringstatic bool arg_legend = true;
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poetteringstatic const char *arg_kill_who = NULL;
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poetteringstatic int arg_signal = SIGTERM;
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poetteringstatic BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poetteringstatic char *arg_host = NULL;
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poetteringstatic bool arg_read_only = false;
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poetteringstatic bool arg_mkdir = false;
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poetteringstatic bool arg_quiet = false;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic void pager_open_if_enabled(void) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Cache result before we open the pager */
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen if (arg_no_pager)
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering return;
f4461e5641d53f27d6e76e0607bdaa9c0c58c1f6Lennart Poettering
f4461e5641d53f27d6e76e0607bdaa9c0c58c1f6Lennart Poettering pager_open(false);
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen}
d74fb368b18f0fbd9a4fe6f15691bbea7f3c4a01Tom Gundersen
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poetteringstatic int list_machines(int argc, char *argv[], void *userdata) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *name, *class, *service, *object;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering sd_bus *bus = userdata;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering unsigned k = 0;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering int r;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering assert(bus);
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering pager_open_if_enabled();
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering r = sd_bus_call_method(
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering bus,
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering "org.freedesktop.machine1",
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering "/org/freedesktop/machine1",
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering "org.freedesktop.machine1.Manager",
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering "ListMachines",
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering &error,
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering &reply,
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering "");
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering if (r < 0) {
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering log_error("Could not get machines: %s", bus_error_message(&error, -r));
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering return r;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering if (arg_legend)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering printf("%-32s %-9s %-16s\n", "MACHINE", "CONTAINER", "SERVICE");
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssso)");
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering if (r < 0)
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering return bus_log_parse_error(r);
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering while ((r = sd_bus_message_read(reply, "(ssso)", &name, &class, &service, &object)) > 0) {
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering printf("%-32s %-9s %-16s\n", name, class, service);
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering k++;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return bus_log_parse_error(r);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_bus_message_exit_container(reply);
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return bus_log_parse_error(r);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (arg_legend)
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen printf("\n%u machines listed.\n", k);
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen
cab5b05903096e1c9cf5575ccc73f89d15c8db69Lennart Poettering return 0;
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen}
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersentypedef struct ImageInfo {
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering const char *name;
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen const char *type;
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen bool read_only;
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering usec_t crtime;
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering usec_t mtime;
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering uint64_t size;
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen} ImageInfo;
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poetteringstatic int compare_image_info(const void *a, const void *b) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const ImageInfo *x = a, *y = b;
6cb08a8930bdaca950b152b1e8b82466ed59511cLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return strcmp(x->name, y->name);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poetteringstatic int list_images(int argc, char *argv[], void *userdata) {
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering size_t max_name = strlen("NAME"), max_type = strlen("TYPE"), max_size = strlen("SIZE"), max_crtime = strlen("CREATED"), max_mtime = strlen("MODIFIED");
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering _cleanup_free_ ImageInfo *images = NULL;
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering size_t n_images = 0, n_allocated = 0, j;
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering const char *name, *type, *object;
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen sd_bus *bus = userdata;
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering uint64_t crtime, mtime, size;
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering int read_only, r;
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering assert(bus);
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering pager_open_if_enabled();
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering r = sd_bus_call_method(
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering bus,
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering "org.freedesktop.machine1",
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering "/org/freedesktop/machine1",
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering "org.freedesktop.machine1.Manager",
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering "ListImages",
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering &error,
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering &reply,
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering "");
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering if (r < 0) {
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering log_error("Could not get images: %s", bus_error_message(&error, -r));
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering return r;
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering }
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssbttto)");
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering if (r < 0)
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering return bus_log_parse_error(r);
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering while ((r = sd_bus_message_read(reply, "(ssbttto)", &name, &type, &read_only, &crtime, &mtime, &size, &object)) > 0) {
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering char buf[MAX(FORMAT_TIMESTAMP_MAX, FORMAT_BYTES_MAX)];
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering size_t l;
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering if (name[0] == '.' && !arg_all)
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering continue;
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering if (!GREEDY_REALLOC(images, n_allocated, n_images + 1))
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen return log_oom();
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering images[n_images].name = name;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering images[n_images].type = type;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering images[n_images].read_only = read_only;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering images[n_images].crtime = crtime;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering images[n_images].mtime = mtime;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering images[n_images].size = size;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering l = strlen(name);
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering if (l > max_name)
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering max_name = l;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering l = strlen(type);
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering if (l > max_type)
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering max_type = l;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering if (crtime != 0) {
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering l = strlen(strna(format_timestamp(buf, sizeof(buf), crtime)));
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering if (l > max_crtime)
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering max_crtime = l;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering }
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering if (mtime != 0) {
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering l = strlen(strna(format_timestamp(buf, sizeof(buf), mtime)));
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering if (l > max_mtime)
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering max_mtime = l;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering }
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering if (size != (uint64_t) -1) {
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering l = strlen(strna(format_bytes(buf, sizeof(buf), size)));
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering if (l > max_size)
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering max_size = l;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering }
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering n_images++;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering }
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering if (r < 0)
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering return bus_log_parse_error(r);
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering r = sd_bus_message_exit_container(reply);
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering if (r < 0)
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering return bus_log_parse_error(r);
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering qsort_safe(images, n_images, sizeof(ImageInfo), compare_image_info);
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen if (arg_legend)
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering printf("%-*s %-*s %-3s %-*s %-*s %-*s\n",
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering (int) max_name, "NAME",
b652d4a2099d1c167584dcc1d179d47c58dc38a2Lennart Poettering (int) max_type, "TYPE",
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering "RO",
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering (int) max_size, "SIZE",
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering (int) max_crtime, "CREATED",
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering (int) max_mtime, "MODIFIED");
f4461e5641d53f27d6e76e0607bdaa9c0c58c1f6Lennart Poettering
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen for (j = 0; j < n_images; j++) {
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen char crtime_buf[FORMAT_TIMESTAMP_MAX], mtime_buf[FORMAT_TIMESTAMP_MAX], size_buf[FORMAT_BYTES_MAX];
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering printf("%-*s %-*s %s%-3s%s %-*s %-*s %-*s\n",
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering (int) max_name, images[j].name,
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering (int) max_type, images[j].type,
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering images[j].read_only ? ansi_highlight_red() : "", yes_no(images[j].read_only), images[j].read_only ? ansi_highlight_off() : "",
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering (int) max_size, strna(format_bytes(size_buf, sizeof(size_buf), images[j].size)),
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering (int) max_crtime, strna(format_timestamp(crtime_buf, sizeof(crtime_buf), images[j].crtime)),
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering (int) max_mtime, strna(format_timestamp(mtime_buf, sizeof(mtime_buf), images[j].mtime)));
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering }
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering
b64513580ce627578351b76a502455e7bc62cae4Lennart Poettering if (r < 0)
b64513580ce627578351b76a502455e7bc62cae4Lennart Poettering return bus_log_parse_error(r);
b64513580ce627578351b76a502455e7bc62cae4Lennart Poettering
b64513580ce627578351b76a502455e7bc62cae4Lennart Poettering
b64513580ce627578351b76a502455e7bc62cae4Lennart Poettering if (arg_legend)
b64513580ce627578351b76a502455e7bc62cae4Lennart Poettering printf("\n%zu images listed.\n", n_images);
b64513580ce627578351b76a502455e7bc62cae4Lennart Poettering
b64513580ce627578351b76a502455e7bc62cae4Lennart Poettering return 0;
b64513580ce627578351b76a502455e7bc62cae4Lennart Poettering}
b64513580ce627578351b76a502455e7bc62cae4Lennart Poettering
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poetteringstatic int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) {
b64513580ce627578351b76a502455e7bc62cae4Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering _cleanup_free_ char *path = NULL;
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering const char *cgroup;
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering int r, output_flags;
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering unsigned c;
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering assert(bus);
b64513580ce627578351b76a502455e7bc62cae4Lennart Poettering assert(unit);
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering
84129d46cd6e95e142973da93aede4c7433c9600Lennart Poettering if (arg_transport == BUS_TRANSPORT_REMOTE)
b64513580ce627578351b76a502455e7bc62cae4Lennart Poettering return 0;
b64513580ce627578351b76a502455e7bc62cae4Lennart Poettering
d74fb368b18f0fbd9a4fe6f15691bbea7f3c4a01Tom Gundersen path = unit_dbus_path_from_name(unit);
d74fb368b18f0fbd9a4fe6f15691bbea7f3c4a01Tom Gundersen if (!path)
d74fb368b18f0fbd9a4fe6f15691bbea7f3c4a01Tom Gundersen return log_oom();
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering
d74fb368b18f0fbd9a4fe6f15691bbea7f3c4a01Tom Gundersen r = sd_bus_get_property(
d74fb368b18f0fbd9a4fe6f15691bbea7f3c4a01Tom Gundersen bus,
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen "org.freedesktop.systemd1",
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen path,
efd46a696d31097c38f653b36921e00c4df62319Lennart Poettering endswith(unit, ".scope") ? "org.freedesktop.systemd1.Scope" : "org.freedesktop.systemd1.Service",
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen "ControlGroup",
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen &error,
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen &reply,
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering "s");
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen if (r < 0) {
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen log_error("Failed to query ControlGroup: %s", bus_error_message(&error, -r));
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen return r;
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering }
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering r = sd_bus_message_read(reply, "s", &cgroup);
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering if (r < 0)
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering return bus_log_parse_error(r);
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen if (isempty(cgroup))
84129d46cd6e95e142973da93aede4c7433c9600Lennart Poettering return 0;
84129d46cd6e95e142973da93aede4c7433c9600Lennart Poettering
84129d46cd6e95e142973da93aede4c7433c9600Lennart Poettering if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup, false) != 0 && leader <= 0)
84129d46cd6e95e142973da93aede4c7433c9600Lennart Poettering return 0;
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen output_flags =
f4461e5641d53f27d6e76e0607bdaa9c0c58c1f6Lennart Poettering arg_all * OUTPUT_SHOW_ALL |
4e0b8b17a7465653f4e7b819dad5f8e30d64c0c4Tom Gundersen arg_full * OUTPUT_FULL_WIDTH;
4e0b8b17a7465653f4e7b819dad5f8e30d64c0c4Tom Gundersen
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering c = columns();
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering if (c > 18)
f4461e5641d53f27d6e76e0607bdaa9c0c58c1f6Lennart Poettering c -= 18;
4e0b8b17a7465653f4e7b819dad5f8e30d64c0c4Tom Gundersen else
4e0b8b17a7465653f4e7b819dad5f8e30d64c0c4Tom Gundersen c = 0;
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, false, &leader, leader > 0, output_flags);
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering return 0;
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering}
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering
571370c1555d2aa697733479a50957aff024bbcbLennart Poetteringstatic int print_addresses(sd_bus *bus, const char *name, int ifi, const char *prefix, const char *prefix2) {
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering int r;
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering
571370c1555d2aa697733479a50957aff024bbcbLennart Poettering assert(bus);
571370c1555d2aa697733479a50957aff024bbcbLennart Poettering assert(name);
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering assert(prefix);
4e0b8b17a7465653f4e7b819dad5f8e30d64c0c4Tom Gundersen assert(prefix2);
4e0b8b17a7465653f4e7b819dad5f8e30d64c0c4Tom Gundersen
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering r = sd_bus_call_method(bus,
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering "org.freedesktop.machine1",
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering "/org/freedesktop/machine1",
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering "org.freedesktop.machine1.Manager",
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering "GetMachineAddresses",
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering NULL,
b64513580ce627578351b76a502455e7bc62cae4Lennart Poettering &reply,
b64513580ce627578351b76a502455e7bc62cae4Lennart Poettering "s", name);
b64513580ce627578351b76a502455e7bc62cae4Lennart Poettering if (r < 0)
b64513580ce627578351b76a502455e7bc62cae4Lennart Poettering return r;
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering r = sd_bus_message_enter_container(reply, 'a', "(iay)");
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering if (r < 0)
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering return bus_log_parse_error(r);
b652d4a2099d1c167584dcc1d179d47c58dc38a2Lennart Poettering
b652d4a2099d1c167584dcc1d179d47c58dc38a2Lennart Poettering while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) {
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering int family;
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering const void *a;
b652d4a2099d1c167584dcc1d179d47c58dc38a2Lennart Poettering size_t sz;
b64513580ce627578351b76a502455e7bc62cae4Lennart Poettering char buffer[MAX(INET6_ADDRSTRLEN, INET_ADDRSTRLEN)];
b64513580ce627578351b76a502455e7bc62cae4Lennart Poettering
b64513580ce627578351b76a502455e7bc62cae4Lennart Poettering r = sd_bus_message_read(reply, "i", &family);
b64513580ce627578351b76a502455e7bc62cae4Lennart Poettering if (r < 0)
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering return bus_log_parse_error(r);
b652d4a2099d1c167584dcc1d179d47c58dc38a2Lennart Poettering
b652d4a2099d1c167584dcc1d179d47c58dc38a2Lennart Poettering r = sd_bus_message_read_array(reply, 'y', &a, &sz);
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen if (r < 0)
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen return bus_log_parse_error(r);
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen fputs(prefix, stdout);
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen fputs(inet_ntop(family, a, buffer, sizeof(buffer)), stdout);
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen if (family == AF_INET6 && ifi > 0)
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen printf("%%%i", ifi);
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen fputc('\n', stdout);
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen r = sd_bus_message_exit_container(reply);
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen if (r < 0)
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen return bus_log_parse_error(r);
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen if (prefix != prefix2)
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen prefix = prefix2;
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen }
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen if (r < 0)
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen return bus_log_parse_error(r);
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen
011842775f750711833526d5bba1b818713947f5Lennart Poettering r = sd_bus_message_exit_container(reply);
011842775f750711833526d5bba1b818713947f5Lennart Poettering if (r < 0)
011842775f750711833526d5bba1b818713947f5Lennart Poettering return bus_log_parse_error(r);
011842775f750711833526d5bba1b818713947f5Lennart Poettering
011842775f750711833526d5bba1b818713947f5Lennart Poettering return 0;
011842775f750711833526d5bba1b818713947f5Lennart Poettering}
011842775f750711833526d5bba1b818713947f5Lennart Poettering
011842775f750711833526d5bba1b818713947f5Lennart Poetteringstatic int print_os_release(sd_bus *bus, const char *name, const char *prefix) {
cc450722a02ab9c59bca1d9a5b5012f356336a8cLennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
cc450722a02ab9c59bca1d9a5b5012f356336a8cLennart Poettering const char *k, *v, *pretty = NULL;
cc450722a02ab9c59bca1d9a5b5012f356336a8cLennart Poettering int r;
cc450722a02ab9c59bca1d9a5b5012f356336a8cLennart Poettering
cc450722a02ab9c59bca1d9a5b5012f356336a8cLennart Poettering assert(bus);
cc450722a02ab9c59bca1d9a5b5012f356336a8cLennart Poettering assert(name);
cc450722a02ab9c59bca1d9a5b5012f356336a8cLennart Poettering assert(prefix);
cc450722a02ab9c59bca1d9a5b5012f356336a8cLennart Poettering
cc450722a02ab9c59bca1d9a5b5012f356336a8cLennart Poettering r = sd_bus_call_method(bus,
cc450722a02ab9c59bca1d9a5b5012f356336a8cLennart Poettering "org.freedesktop.machine1",
cc450722a02ab9c59bca1d9a5b5012f356336a8cLennart Poettering "/org/freedesktop/machine1",
011842775f750711833526d5bba1b818713947f5Lennart Poettering "org.freedesktop.machine1.Manager",
011842775f750711833526d5bba1b818713947f5Lennart Poettering "GetMachineOSRelease",
f4461e5641d53f27d6e76e0607bdaa9c0c58c1f6Lennart Poettering NULL,
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen &reply,
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen "s", name);
f4461e5641d53f27d6e76e0607bdaa9c0c58c1f6Lennart Poettering if (r < 0)
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen return r;
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen
f4461e5641d53f27d6e76e0607bdaa9c0c58c1f6Lennart Poettering r = sd_bus_message_enter_container(reply, 'a', "{ss}");
cc450722a02ab9c59bca1d9a5b5012f356336a8cLennart Poettering if (r < 0)
011842775f750711833526d5bba1b818713947f5Lennart Poettering return bus_log_parse_error(r);
011842775f750711833526d5bba1b818713947f5Lennart Poettering
cc450722a02ab9c59bca1d9a5b5012f356336a8cLennart Poettering while ((r = sd_bus_message_read(reply, "{ss}", &k, &v)) > 0) {
cc450722a02ab9c59bca1d9a5b5012f356336a8cLennart Poettering if (streq(k, "PRETTY_NAME"))
cc450722a02ab9c59bca1d9a5b5012f356336a8cLennart Poettering pretty = v;
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering
6cb08a8930bdaca950b152b1e8b82466ed59511cLennart Poettering }
6cb08a8930bdaca950b152b1e8b82466ed59511cLennart Poettering if (r < 0)
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering return bus_log_parse_error(r);
f4461e5641d53f27d6e76e0607bdaa9c0c58c1f6Lennart Poettering
f4461e5641d53f27d6e76e0607bdaa9c0c58c1f6Lennart Poettering r = sd_bus_message_exit_container(reply);
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering if (r < 0)
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering return bus_log_parse_error(r);
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering if (pretty)
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering printf("%s%s\n", prefix, pretty);
6a1a5eec43892dee3ff6e208bceb1931c25c782eLennart Poettering
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering return 0;
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering}
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poetteringtypedef struct MachineStatusInfo {
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering char *name;
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering sd_id128_t id;
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering char *class;
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering char *service;
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering char *unit;
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering char *root_directory;
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering pid_t leader;
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering usec_t timestamp;
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering int *netif;
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering unsigned n_netif;
6a1a5eec43892dee3ff6e208bceb1931c25c782eLennart Poettering} MachineStatusInfo;
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poetteringstatic void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) {
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering char since2[FORMAT_TIMESTAMP_MAX], *s2;
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering int ifi = -1;
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering assert(bus);
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering assert(i);
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering fputs(strna(i->name), stdout);
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering if (!sd_id128_equal(i->id, SD_ID128_NULL))
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering printf("(" SD_ID128_FORMAT_STR ")\n", SD_ID128_FORMAT_VAL(i->id));
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering else
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering putchar('\n');
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering s1 = format_timestamp_relative(since1, sizeof(since1), i->timestamp);
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering s2 = format_timestamp(since2, sizeof(since2), i->timestamp);
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering if (s1)
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering printf("\t Since: %s; %s\n", s2, s1);
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering else if (s2)
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering printf("\t Since: %s\n", s2);
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering if (i->leader > 0) {
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering _cleanup_free_ char *t = NULL;
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering printf("\t Leader: %u", (unsigned) i->leader);
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering get_process_comm(i->leader, &t);
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering if (t)
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering printf(" (%s)", t);
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering putchar('\n');
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering }
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering if (i->service) {
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering printf("\t Service: %s", i->service);
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering if (i->class)
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering printf("; class %s", i->class);
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering putchar('\n');
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering } else if (i->class)
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering printf("\t Class: %s\n", i->class);
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering if (i->root_directory)
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering printf("\t Root: %s\n", i->root_directory);
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering
011842775f750711833526d5bba1b818713947f5Lennart Poettering if (i->n_netif > 0) {
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering unsigned c;
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering
6cb08a8930bdaca950b152b1e8b82466ed59511cLennart Poettering fputs("\t Iface:", stdout);
6cb08a8930bdaca950b152b1e8b82466ed59511cLennart Poettering
6bb2c08597c999c429e889cd2403b2fef5f3e1a0Lennart Poettering for (c = 0; c < i->n_netif; c++) {
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen char name[IF_NAMESIZE+1] = "";
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen
f4461e5641d53f27d6e76e0607bdaa9c0c58c1f6Lennart Poettering if (if_indextoname(i->netif[c], name)) {
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen fputc(' ', stdout);
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen fputs(name, stdout);
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering if (ifi < 0)
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering ifi = i->netif[c];
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering else
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering ifi = 0;
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering } else
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering printf(" %i", i->netif[c]);
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering }
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering fputc('\n', stdout);
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering }
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering print_addresses(bus, i->name, ifi,
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering "\t Address: ",
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering "\t ");
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering print_os_release(bus, i->name, "\t OS: ");
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering if (i->unit) {
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering printf("\t Unit: %s\n", i->unit);
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering show_unit_cgroup(bus, i->unit, i->leader);
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering }
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering}
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poetteringstatic int map_netif(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering MachineStatusInfo *i = userdata;
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering size_t l;
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering const void *v;
6cb08a8930bdaca950b152b1e8b82466ed59511cLennart Poettering int r;
6cb08a8930bdaca950b152b1e8b82466ed59511cLennart Poettering
6cb08a8930bdaca950b152b1e8b82466ed59511cLennart Poettering assert_cc(sizeof(int32_t) == sizeof(int));
6cb08a8930bdaca950b152b1e8b82466ed59511cLennart Poettering r = sd_bus_message_read_array(m, SD_BUS_TYPE_INT32, &v, &l);
6cb08a8930bdaca950b152b1e8b82466ed59511cLennart Poettering if (r < 0)
6cb08a8930bdaca950b152b1e8b82466ed59511cLennart Poettering return r;
6cb08a8930bdaca950b152b1e8b82466ed59511cLennart Poettering if (r == 0)
6cb08a8930bdaca950b152b1e8b82466ed59511cLennart Poettering return -EBADMSG;
6cb08a8930bdaca950b152b1e8b82466ed59511cLennart Poettering
92ec902aad1ade7acbe50efd7b8ef87fbdc63af3Lennart Poettering i->n_netif = l / sizeof(int32_t);
92ec902aad1ade7acbe50efd7b8ef87fbdc63af3Lennart Poettering i->netif = memdup(v, l);
92ec902aad1ade7acbe50efd7b8ef87fbdc63af3Lennart Poettering if (!i->netif)
92ec902aad1ade7acbe50efd7b8ef87fbdc63af3Lennart Poettering return -ENOMEM;
92ec902aad1ade7acbe50efd7b8ef87fbdc63af3Lennart Poettering
92ec902aad1ade7acbe50efd7b8ef87fbdc63af3Lennart Poettering return 0;
92ec902aad1ade7acbe50efd7b8ef87fbdc63af3Lennart Poettering}
92ec902aad1ade7acbe50efd7b8ef87fbdc63af3Lennart Poettering
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poetteringstatic int show_machine_info(const char *verb, sd_bus *bus, const char *path, bool *new_line) {
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering static const struct bus_properties_map map[] = {
de54e62b4bd7856fb897c9a2ee93cc228adb2135Lennart Poettering { "Name", "s", NULL, offsetof(MachineStatusInfo, name) },
92ec902aad1ade7acbe50efd7b8ef87fbdc63af3Lennart Poettering { "Class", "s", NULL, offsetof(MachineStatusInfo, class) },
92ec902aad1ade7acbe50efd7b8ef87fbdc63af3Lennart Poettering { "Service", "s", NULL, offsetof(MachineStatusInfo, service) },
92ec902aad1ade7acbe50efd7b8ef87fbdc63af3Lennart Poettering { "Unit", "s", NULL, offsetof(MachineStatusInfo, unit) },
92ec902aad1ade7acbe50efd7b8ef87fbdc63af3Lennart Poettering { "RootDirectory", "s", NULL, offsetof(MachineStatusInfo, root_directory) },
92ec902aad1ade7acbe50efd7b8ef87fbdc63af3Lennart Poettering { "Leader", "u", NULL, offsetof(MachineStatusInfo, leader) },
92ec902aad1ade7acbe50efd7b8ef87fbdc63af3Lennart Poettering { "Timestamp", "t", NULL, offsetof(MachineStatusInfo, timestamp) },
92ec902aad1ade7acbe50efd7b8ef87fbdc63af3Lennart Poettering { "Id", "ay", bus_map_id128, offsetof(MachineStatusInfo, id) },
92ec902aad1ade7acbe50efd7b8ef87fbdc63af3Lennart Poettering { "NetworkInterfaces", "ai", map_netif, 0 },
92ec902aad1ade7acbe50efd7b8ef87fbdc63af3Lennart Poettering {}
1e02e182f1e06fcbe389474175de228103be39cbLennart Poettering };
1e02e182f1e06fcbe389474175de228103be39cbLennart Poettering
1e02e182f1e06fcbe389474175de228103be39cbLennart Poettering MachineStatusInfo info = {};
1e02e182f1e06fcbe389474175de228103be39cbLennart Poettering int r;
1e02e182f1e06fcbe389474175de228103be39cbLennart Poettering
1e02e182f1e06fcbe389474175de228103be39cbLennart Poettering assert(verb);
1e02e182f1e06fcbe389474175de228103be39cbLennart Poettering assert(bus);
1e02e182f1e06fcbe389474175de228103be39cbLennart Poettering assert(path);
1e02e182f1e06fcbe389474175de228103be39cbLennart Poettering assert(new_line);
1e02e182f1e06fcbe389474175de228103be39cbLennart Poettering
1e02e182f1e06fcbe389474175de228103be39cbLennart Poettering r = bus_map_all_properties(bus,
1e02e182f1e06fcbe389474175de228103be39cbLennart Poettering "org.freedesktop.machine1",
1e02e182f1e06fcbe389474175de228103be39cbLennart Poettering path,
1e02e182f1e06fcbe389474175de228103be39cbLennart Poettering map,
1e02e182f1e06fcbe389474175de228103be39cbLennart Poettering &info);
1e02e182f1e06fcbe389474175de228103be39cbLennart Poettering if (r < 0)
b826ab586c9e0a9c0d438a75c28cf3a8ab485929Tom Gundersen return log_error_errno(r, "Could not get properties: %m");
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering if (*new_line)
b826ab586c9e0a9c0d438a75c28cf3a8ab485929Tom Gundersen printf("\n");
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering *new_line = true;
b826ab586c9e0a9c0d438a75c28cf3a8ab485929Tom Gundersen
b826ab586c9e0a9c0d438a75c28cf3a8ab485929Tom Gundersen print_machine_status_info(bus, &info);
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering free(info.name);
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt free(info.class);
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering free(info.service);
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering free(info.unit);
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering free(info.root_directory);
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering free(info.netif);
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering return r;
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering}
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poetteringstatic int show_machine_properties(sd_bus *bus, const char *path, bool *new_line) {
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt int r;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt assert(bus);
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt assert(path);
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt assert(new_line);
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering if (*new_line)
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering printf("\n");
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering *new_line = true;
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, arg_property, arg_all);
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering if (r < 0)
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering log_error_errno(r, "Could not get properties: %m");
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering return r;
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering}
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poetteringstatic int show_machine(int argc, char *argv[], void *userdata) {
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering bool properties, new_line = false;
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering sd_bus *bus = userdata;
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering int r = 0, i;
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering assert(bus);
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering properties = !strstr(argv[0], "status");
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering pager_open_if_enabled();
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering if (properties && argc <= 1) {
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering /* If no argument is specified, inspect the manager
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering * itself */
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering r = show_machine_properties(bus, "/org/freedesktop/machine1", &new_line);
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering if (r < 0)
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering return r;
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering }
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering for (i = 1; i < argc; i++) {
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering const char *path = NULL;
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering r = sd_bus_call_method(
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering bus,
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering "org.freedesktop.machine1",
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering "/org/freedesktop/machine1",
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering "org.freedesktop.machine1.Manager",
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering "GetMachine",
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering &error,
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering &reply,
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering "s", argv[i]);
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering if (r < 0) {
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering log_error("Could not get path to machine: %s", bus_error_message(&error, -r));
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering return r;
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering }
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering r = sd_bus_message_read(reply, "o", &path);
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering if (r < 0)
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering return bus_log_parse_error(r);
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering if (properties)
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering r = show_machine_properties(bus, path, &new_line);
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering else
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering r = show_machine_info(argv[0], bus, path, &new_line);
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering }
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering return r;
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering}
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poetteringtypedef struct ImageStatusInfo {
6cb08a8930bdaca950b152b1e8b82466ed59511cLennart Poettering char *name;
6cb08a8930bdaca950b152b1e8b82466ed59511cLennart Poettering char *path;
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering char *type;
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering int read_only;
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering usec_t crtime;
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering usec_t mtime;
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering uint64_t size;
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering uint64_t limit;
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering uint64_t size_exclusive;
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering uint64_t limit_exclusive;
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering} ImageStatusInfo;
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poetteringstatic void print_image_status_info(sd_bus *bus, ImageStatusInfo *i) {
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering char ts_relative[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering char ts_absolute[FORMAT_TIMESTAMP_MAX], *s2;
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering char bs[FORMAT_BYTES_MAX], *s3;
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering char bs_exclusive[FORMAT_BYTES_MAX], *s4;
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering assert(bus);
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering assert(i);
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering if (i->name) {
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering fputs(i->name, stdout);
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering putchar('\n');
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering }
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering if (i->path)
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering printf("\t Type: %s\n", i->type);
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering if (i->path)
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering printf("\t Path: %s\n", i->path);
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering printf("\t RO: %s%s%s\n",
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering i->read_only ? ansi_highlight_red() : "",
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering i->read_only ? "read-only" : "writable",
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering i->read_only ? ansi_highlight_off() : "");
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering s1 = format_timestamp_relative(ts_relative, sizeof(ts_relative), i->crtime);
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering s2 = format_timestamp(ts_absolute, sizeof(ts_absolute), i->crtime);
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering if (s1 && s2)
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering printf("\t Created: %s; %s\n", s2, s1);
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering else if (s2)
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering printf("\t Created: %s\n", s2);
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering s1 = format_timestamp_relative(ts_relative, sizeof(ts_relative), i->mtime);
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering s2 = format_timestamp(ts_absolute, sizeof(ts_absolute), i->mtime);
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering if (s1 && s2)
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering printf("\tModified: %s; %s\n", s2, s1);
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering else if (s2)
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering printf("\tModified: %s\n", s2);
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering s3 = format_bytes(bs, sizeof(bs), i->size);
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering s4 = i->size_exclusive != i->size ? format_bytes(bs_exclusive, sizeof(bs_exclusive), i->size_exclusive) : NULL;
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering if (s3 && s4)
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering printf("\t Size: %s (exclusive: %s)\n", s3, s4);
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering else if (s3)
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering printf("\t Size: %s\n", s3);
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering s3 = format_bytes(bs, sizeof(bs), i->limit);
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering s4 = i->limit_exclusive != i->limit ? format_bytes(bs_exclusive, sizeof(bs_exclusive), i->limit_exclusive) : NULL;
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering if (s3 && s4)
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering printf("\t Limit: %s (exclusive: %s)\n", s3, s4);
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering else if (s3)
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering printf("\t Limit: %s\n", s3);
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering}
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersenstatic int show_image_info(const char *verb, sd_bus *bus, const char *path, bool *new_line) {
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen static const struct bus_properties_map map[] = {
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen { "Name", "s", NULL, offsetof(ImageStatusInfo, name) },
9c5e12a4314e7192e834e1b855e5e80111e636a6Tom Gundersen { "Path", "s", NULL, offsetof(ImageStatusInfo, path) },
7586f4d172dd9c3ccc3126fc47dca9e49adec132Tom Gundersen { "Type", "s", NULL, offsetof(ImageStatusInfo, type) },
d74fb368b18f0fbd9a4fe6f15691bbea7f3c4a01Tom Gundersen { "ReadOnly", "b", NULL, offsetof(ImageStatusInfo, read_only) },
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen { "CreationTimestamp", "t", NULL, offsetof(ImageStatusInfo, crtime) },
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen { "ModificationTimestamp", "t", NULL, offsetof(ImageStatusInfo, mtime) },
{ "Size", "t", NULL, offsetof(ImageStatusInfo, size) },
{ "Limit", "t", NULL, offsetof(ImageStatusInfo, limit) },
{ "SizeExclusive", "t", NULL, offsetof(ImageStatusInfo, size_exclusive) },
{ "LimitExclusive", "t", NULL, offsetof(ImageStatusInfo, limit_exclusive) },
{}
};
ImageStatusInfo info = {};
int r;
assert(verb);
assert(bus);
assert(path);
assert(new_line);
r = bus_map_all_properties(bus,
"org.freedesktop.machine1",
path,
map,
&info);
if (r < 0)
return log_error_errno(r, "Could not get properties: %m");
if (*new_line)
printf("\n");
*new_line = true;
print_image_status_info(bus, &info);
free(info.name);
free(info.path);
free(info.type);
return r;
}
static int show_image_properties(sd_bus *bus, const char *path, bool *new_line) {
int r;
assert(bus);
assert(path);
assert(new_line);
if (*new_line)
printf("\n");
*new_line = true;
r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, arg_property, arg_all);
if (r < 0)
log_error_errno(r, "Could not get properties: %m");
return r;
}
static int show_image(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 *reply = NULL;
bool properties, new_line = false;
sd_bus *bus = userdata;
int r = 0, i;
assert(bus);
properties = !strstr(argv[0], "status");
pager_open_if_enabled();
if (properties && argc <= 1) {
/* If no argument is specified, inspect the manager
* itself */
r = show_image_properties(bus, "/org/freedesktop/machine1", &new_line);
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(argv[0], bus, path, &new_line);
}
return r;
}
static int kill_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);
if (!arg_kill_who)
arg_kill_who = "all";
for (i = 1; i < argc; i++) {
int r;
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_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, arg_quiet);
if (r < 0)
return r;
return 0;
}
static int enable_machine(int argc, char *argv[], void *userdata) {
_cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
_cleanup_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);
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_set_allow_interactive_authorization(m, true);
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 *e = NULL, *unit = NULL;
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_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);
if (r < 0)
return r;
m = sd_bus_message_unref(m);
r = sd_bus_message_new_method_call(
bus,
&m,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"Reload");
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_call(bus, m, 0, &error, NULL);
if (r < 0) {
log_error("Failed to reload daemon: %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"
" -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"
" --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"
" 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 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 },
{ "quiet", no_argument, NULL, 'q' },
{}
};
int c, r;
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, "hp:als:H:M:q", 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 'q':
arg_quiet = 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 },
{ "enable", 2, VERB_ANY, 0, enable_machine },
{ "disable", 2, VERB_ANY, 0, enable_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;
}