#include <fcntl.h>
#include <getopt.h>
#include <locale.h>
+#include <math.h>
#include <net/if.h>
#include <netinet/in.h>
#include <string.h>
#include "rlimit-util.h"
#include "sigbus.h"
#include "signal-util.h"
+#include "sort-util.h"
#include "spawn-polkit-agent.h"
#include "stdio-util.h"
#include "string-table.h"
#include "strv.h"
#include "terminal-util.h"
#include "unit-name.h"
-#include "util.h"
#include "verbs.h"
#include "web-util.h"
if (truncate) {
- if (!strextend(&addresses, special_glyph(ELLIPSIS), NULL))
+ if (!strextend(&addresses, special_glyph(SPECIAL_GLYPH_ELLIPSIS), NULL))
return -ENOMEM;
}
table_set_header(table, arg_legend);
- r = table_print(table, NULL);
+ if (OUTPUT_MODE_IS_JSON(arg_output))
+ r = table_print_json(table, NULL, output_mode_to_json_format_flags(arg_output) | JSON_FORMAT_COLOR_AUTO);
+ else
+ r = table_print(table, NULL);
if (r < 0)
return log_error_errno(r, "Failed to show table: %m");
}
if (r < 0)
return log_error_errno(r, "Could not get machines: %s", bus_error_message(&error, r));
- table = table_new("MACHINE", "CLASS", "SERVICE", "OS", "VERSION", "ADDRESSES");
+ table = table_new("machine", "class", "service", "os", "version", "addresses");
if (!table)
return log_oom();
name,
0,
"",
- "",
+ " ",
arg_addrs,
&addresses);
if (r < 0)
return log_error_errno(r, "Could not get images: %s", bus_error_message(&error, r));
- table = table_new("NAME", "TYPE", "RO", "USAGE", "CREATED", "MODIFIED");
+ table = table_new("name", "type", "ro", "usage", "created", "modified");
if (!table)
return log_oom();
static int process_forward(sd_event *event, PTYForward **forward, int master, PTYForwardFlags flags, const char *name) {
char last_char = 0;
bool machine_died;
- int ret = 0, r;
+ int r;
assert(event);
assert(master >= 0);
log_info("Connection to machine %s terminated.", name);
}
- sd_event_get_exit_code(event, &ret);
- return ret;
+ return 0;
}
static int parse_machine_uid(const char *spec, const char **machine, char **uid) {
if (r < 0)
return r;
if (r == 0) {
- log_error("Machine image '%s' does not exist.", argv[1]);
+ log_error("Machine image '%s' does not exist.", argv[i]);
return -ENXIO;
}
if (r < 0)
return r;
if (r == 0) {
- log_error("Machine image '%s' does not exist.", argv[1]);
+ log_error("Machine image '%s' does not exist.", argv[i]);
return -ENXIO;
}
return -r;
}
+static const char *nullify_dash(const char *p) {
+ if (isempty(p))
+ return NULL;
+
+ if (streq(p, "-"))
+ return NULL;
+
+ return p;
+}
+
static int import_tar(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- _cleanup_free_ char *ll = NULL;
- _cleanup_close_ int fd = -1;
+ _cleanup_free_ char *ll = NULL, *fn = NULL;
const char *local = NULL, *path = NULL;
+ _cleanup_close_ int fd = -1;
sd_bus *bus = userdata;
int r;
assert(bus);
if (argc >= 2)
- path = argv[1];
- if (isempty(path) || streq(path, "-"))
- path = NULL;
+ path = nullify_dash(argv[1]);
if (argc >= 3)
- local = argv[2];
- else if (path)
- local = basename(path);
- if (isempty(local) || streq(local, "-"))
- local = NULL;
+ local = nullify_dash(argv[2]);
+ else if (path) {
+ r = path_extract_filename(path, &fn);
+ if (r < 0)
+ return log_error_errno(r, "Cannot extract container name from filename: %m");
+ local = fn;
+ }
if (!local) {
log_error("Need either path or local name.");
return -EINVAL;
static int import_raw(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- _cleanup_free_ char *ll = NULL;
- _cleanup_close_ int fd = -1;
+ _cleanup_free_ char *ll = NULL, *fn = NULL;
const char *local = NULL, *path = NULL;
+ _cleanup_close_ int fd = -1;
sd_bus *bus = userdata;
int r;
assert(bus);
if (argc >= 2)
- path = argv[1];
- if (isempty(path) || streq(path, "-"))
- path = NULL;
+ path = nullify_dash(argv[1]);
if (argc >= 3)
- local = argv[2];
- else if (path)
- local = basename(path);
- if (isempty(local) || streq(local, "-"))
- local = NULL;
+ local = nullify_dash(argv[2]);
+ else if (path) {
+ r = path_extract_filename(path, &fn);
+ if (r < 0)
+ return log_error_errno(r, "Cannot extract container name from filename: %m");
+ local = fn;
+ }
if (!local) {
log_error("Need either path or local name.");
return -EINVAL;
return transfer_image_common(bus, m);
}
+static int import_fs(int argc, char *argv[], void *userdata) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ const char *local = NULL, *path = NULL;
+ _cleanup_free_ char *fn = NULL;
+ _cleanup_close_ int fd = -1;
+ sd_bus *bus = userdata;
+ int r;
+
+ assert(bus);
+
+ if (argc >= 2)
+ path = nullify_dash(argv[1]);
+
+ if (argc >= 3)
+ local = nullify_dash(argv[2]);
+ else if (path) {
+ r = path_extract_filename(path, &fn);
+ if (r < 0)
+ return log_error_errno(r, "Cannot extract container name from filename: %m");
+
+ local = fn;
+ }
+ if (!local) {
+ log_error("Need either path or local name.");
+ return -EINVAL;
+ }
+
+ if (!machine_name_is_valid(local)) {
+ log_error("Local name %s is not a suitable machine name.", local);
+ return -EINVAL;
+ }
+
+ if (path) {
+ fd = open(path, O_DIRECTORY|O_RDONLY|O_CLOEXEC);
+ if (fd < 0)
+ return log_error_errno(errno, "Failed to open directory '%s': %m", path);
+ }
+
+ r = sd_bus_message_new_method_call(
+ bus,
+ &m,
+ "org.freedesktop.import1",
+ "/org/freedesktop/import1",
+ "org.freedesktop.import1.Manager",
+ "ImportFileSystem");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(
+ m,
+ "hsbb",
+ fd >= 0 ? fd : STDIN_FILENO,
+ local,
+ arg_force,
+ arg_read_only);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ return transfer_image_common(bus, m);
+}
+
static void determine_compression_from_filename(const char *p) {
if (arg_format)
return;
(int) max_remote, "REMOTE");
for (j = 0; j < n_transfers; j++)
- printf("%*" PRIu32 " %*u%% %-*s %-*s %-*s\n",
- (int) MAX(2U, DECIMAL_STR_WIDTH(max_id)), transfers[j].id,
- (int) 6, (unsigned) (transfers[j].progress * 100),
- (int) max_type, transfers[j].type,
- (int) max_local, transfers[j].local,
- (int) max_remote, transfers[j].remote);
+
+ if (transfers[j].progress < 0)
+ printf("%*" PRIu32 " %*s %-*s %-*s %-*s\n",
+ (int) MAX(2U, DECIMAL_STR_WIDTH(max_id)), transfers[j].id,
+ (int) 7, "n/a",
+ (int) max_type, transfers[j].type,
+ (int) max_local, transfers[j].local,
+ (int) max_remote, transfers[j].remote);
+ else
+ printf("%*" PRIu32 " %*u%% %-*s %-*s %-*s\n",
+ (int) MAX(2U, DECIMAL_STR_WIDTH(max_id)), transfers[j].id,
+ (int) 6, (unsigned) (transfers[j].progress * 100),
+ (int) max_type, transfers[j].type,
+ (int) max_local, transfers[j].local,
+ (int) max_remote, transfers[j].remote);
if (arg_legend) {
if (n_transfers > 0)
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(reply, "(st)", &name, &usage)) > 0) {
- log_info("Removed image '%s'. Freed exclusive disk space: %s",
- name, format_bytes(fb, sizeof(fb), usage));
-
- total += usage;
+ if (usage == UINT64_MAX) {
+ log_info("Removed image '%s'", name);
+ total = UINT64_MAX;
+ } else {
+ log_info("Removed image '%s'. Freed exclusive disk space: %s",
+ name, format_bytes(fb, sizeof(fb), usage));
+ if (total != UINT64_MAX)
+ total += usage;
+ }
c++;
}
if (r < 0)
return bus_log_parse_error(r);
- log_info("Removed %u images in total. Total freed exclusive disk space %s.",
- c, format_bytes(fb, sizeof(fb), total));
+ if (total == UINT64_MAX)
+ log_info("Removed %u images in total.", c);
+ else
+ log_info("Removed %u images in total. Total freed exclusive disk space: %s.",
+ c, format_bytes(fb, sizeof(fb), total));
return 0;
}
" pull-raw URL [NAME] Download a RAW container or VM image\n"
" import-tar FILE [NAME] Import a local TAR container image\n"
" import-raw FILE [NAME] Import a local RAW container or VM image\n"
+ " import-fs DIRECTORY [NAME] Import a local directory container image\n"
" export-tar NAME [FILE] Export a TAR container image locally\n"
" export-raw NAME [FILE] Export a RAW container or VM image locally\n"
" list-transfers Show list of downloads in progress\n"
if (arg_output < 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Unknown output '%s'.", optarg);
+
+ if (OUTPUT_MODE_IS_JSON(arg_output))
+ arg_legend = false;
break;
case ARG_NO_PAGER:
{ "disable", 2, VERB_ANY, 0, enable_machine },
{ "import-tar", 2, 3, 0, import_tar },
{ "import-raw", 2, 3, 0, import_raw },
+ { "import-fs", 2, 3, 0, import_fs },
{ "export-tar", 2, 3, 0, export_tar },
{ "export-raw", 2, 3, 0, export_raw },
{ "pull-tar", 2, 3, 0, pull_tar },
return dispatch_verb(argc, argv, verbs, bus);
}
-static int run(int argc, char*argv[]) {
+static int run(int argc, char *argv[]) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r;