]> git.proxmox.com Git - mirror_lxc.git/commitdiff
tools: Provide multicall lxc binary
authorPetr Malat <oss@malat.biz>
Wed, 15 Jun 2022 11:16:43 +0000 (13:16 +0200)
committerPetr Malat <oss@malat.biz>
Wed, 15 Jun 2022 14:27:47 +0000 (16:27 +0200)
Create a binary, which embeds all lxc tools similar way as busybox
embeds its applets. This is handy for embedded systems as it saves
roughly 90% of the disk space.

To disable normal tools and use multicall binary exclusively use the
following meson setup options:
  -Dtools=false -Dtools-multicall=true

Signed-off-by: Petr Malat <oss@malat.biz>
26 files changed:
meson.build
meson_options.txt
src/lxc/tools/lxc_attach.c
src/lxc/tools/lxc_autostart.c
src/lxc/tools/lxc_cgroup.c
src/lxc/tools/lxc_checkpoint.c
src/lxc/tools/lxc_config.c
src/lxc/tools/lxc_console.c
src/lxc/tools/lxc_copy.c
src/lxc/tools/lxc_create.c
src/lxc/tools/lxc_destroy.c
src/lxc/tools/lxc_device.c
src/lxc/tools/lxc_execute.c
src/lxc/tools/lxc_freeze.c
src/lxc/tools/lxc_info.c
src/lxc/tools/lxc_ls.c
src/lxc/tools/lxc_monitor.c
src/lxc/tools/lxc_multicall.c [new file with mode: 0644]
src/lxc/tools/lxc_snapshot.c
src/lxc/tools/lxc_start.c
src/lxc/tools/lxc_stop.c
src/lxc/tools/lxc_top.c
src/lxc/tools/lxc_unfreeze.c
src/lxc/tools/lxc_unshare.c
src/lxc/tools/lxc_wait.c
src/lxc/tools/meson.build

index d974a839227d4c168680178c377521f43564f5b2..7ec3214621182857350e9146bc71894cc4c972f6 100644 (file)
@@ -141,6 +141,7 @@ want_pam_cgroup = get_option('pam-cgroup')
 want_mans = get_option('man')
 want_tests = get_option('tests')
 want_tools = get_option('tools')
+want_tools_multicall = get_option('tools-multicall')
 want_commands = get_option('commands')
 want_capabilities = get_option('capabilities')
 want_apparmor = get_option('apparmor')
@@ -793,7 +794,7 @@ subdir('hooks')
 if want_commands
     subdir('src/lxc/cmd')
 endif
-if want_tools
+if want_tools or want_tools_multicall
     subdir('src/lxc/tools')
 endif
 subdir('src/lxc/tools/include')
index 8f9b4e118502911639f34269cf61edbd43c11eca..d82ae3486e0648c1aefa403bb5b8192d888d1838 100644 (file)
@@ -34,6 +34,9 @@ option('pam-cgroup', type: 'boolean', value: 'false',
 option('tools', type: 'boolean', value: 'true',
        description: 'build and install tools')
 
+option('tools-multicall', type: 'boolean', value: 'false',
+       description: 'build and install busybox style multicall binary')
+
 # was --{disable,enable}-commands in autotools
 option('commands', type: 'boolean', value: 'true',
        description: 'build and install commands')
index d7888ddf420068db0c1480c6c84062565cb111d4..fa303c7b4f1a008763ebb9bc4b08fa8491033d00 100644 (file)
@@ -271,7 +271,8 @@ static int lxc_attach_create_log_file(const char *log_file)
        return fd;
 }
 
-int main(int argc, char *argv[])
+int __attribute__((weak, alias("lxc_attach_main"))) main(int argc, char *argv[]);
+int lxc_attach_main(int argc, char *argv[])
 {
        int ret = -1;
        int wexit = 0;
index 062135d4039e7d7d1f94d041ec3d4340f7dcdbb9..713e8efdf550d5394fe19145428ccbe5d7d347ec 100644 (file)
@@ -304,7 +304,8 @@ static int toss_list(struct lxc_list *c_groups_list)
        return 1;
 }
 
-int main(int argc, char *argv[])
+int __attribute__((weak, alias("lxc_autostart_main"))) main(int argc, char *argv[]);
+int lxc_autostart_main(int argc, char *argv[])
 {
        int count = 0, failed = 0, i = 0, ret = 0;
        struct lxc_list *cmd_group;
index eb96c63ee4ae66a70747459a559e5f65a3fdf986..017d6c734b7ff02eb1e58875e1d04ea1d75518cd 100644 (file)
@@ -50,7 +50,8 @@ static int my_checker(const struct lxc_arguments *args)
        return 0;
 }
 
-int main(int argc, char *argv[])
+int __attribute__((weak, alias("lxc_cgroup_main"))) main(int argc, char *argv[]);
+int lxc_cgroup_main(int argc, char *argv[])
 {
        char *state_object = NULL, *value = NULL;
        struct lxc_container *c;
index a8edb4526cb98f4f8f927b0f34173f143a19e22f..3287904f696c321bca9d7f560e1d9ef23af4882f 100644 (file)
@@ -246,7 +246,8 @@ static bool restore(struct lxc_container *c)
        }
 }
 
-int main(int argc, char *argv[])
+int __attribute__((weak, alias("lxc_checkpoint_main"))) main(int argc, char *argv[]);
+int lxc_checkpoint_main(int argc, char *argv[])
 {
        struct lxc_container *c;
        struct lxc_log log;
index e4424c4cf779d8aa6f8eec2bf08788a3b125fb8a..a240d02c9a7fd86c578e1015bdfea439a1c7a130 100644 (file)
@@ -40,7 +40,8 @@ static void list_config_items(void)
        exit(EXIT_SUCCESS);
 }
 
-int main(int argc, char *argv[])
+int __attribute__((weak, alias("lxc_config_main"))) main(int argc, char *argv[]);
+int lxc_config_main(int argc, char *argv[])
 {
        struct lxc_config_items *i;
        const char *value;
index 7f43f506b7b08f5153239e12b3dcb941252131a5..13d9844cae158c8e32430a87f0f5b6d040d54bf4 100644 (file)
@@ -77,7 +77,8 @@ static char etoc(const char *expr)
        return 1 + ((c > 'Z') ? (c - 'a') : (c - 'Z'));
 }
 
-int main(int argc, char *argv[])
+int __attribute__((weak, alias("lxc_console_main"))) main(int argc, char *argv[]);
+int lxc_console_main(int argc, char *argv[])
 {
        int ret;
        struct lxc_container *c;
index c7158cc0b8e2e582328a88ead9a59b4f06bc5519..04118e9fa4a4096bee52c9a709482f53d3918006 100644 (file)
@@ -142,7 +142,8 @@ static int parse_mntsubopts(char *subopts, char *const *keys,
 static int parse_bind_mnt(char *mntstring, enum mnttype type);
 static int parse_ovl_mnt(char *mntstring, enum mnttype type);
 
-int main(int argc, char *argv[])
+int __attribute__((weak, alias("lxc_copy_main"))) main(int argc, char *argv[]);
+int lxc_copy_main(int argc, char *argv[])
 {
        struct lxc_container *c;
        struct lxc_log log;
index f0482867a1895a320944f69d8bd9a688c2094ae7..9eda550f5c815829ffbd2669dab2ab52cc2f483f 100644 (file)
@@ -190,7 +190,8 @@ static bool validate_bdev_args(struct lxc_arguments *args)
        return true;
 }
 
-int main(int argc, char *argv[])
+int __attribute__((weak, alias("lxc_create_main"))) main(int argc, char *argv[]);
+int lxc_create_main(int argc, char *argv[])
 {
        struct lxc_container *c;
        struct bdev_specs spec;
index 581460ae4b066543995e29ddb8c51cef282a4fbf..e0fb09c576682e85cf00c8e683c20dac3bad77cd 100644 (file)
@@ -188,7 +188,8 @@ static bool do_destroy_with_snapshots(struct lxc_container *c)
        return bret;
 }
 
-int main(int argc, char *argv[])
+int __attribute__((weak, alias("lxc_destroy_main"))) main(int argc, char *argv[]);
+int lxc_destroy_main(int argc, char *argv[])
 {
        struct lxc_container *c;
        struct lxc_log log;
index 82e54346218d946dbeb8de0872c7ff5c52a469ac..2dcdab7d38d4393145ed884d8d3be966393a0c6d 100644 (file)
@@ -78,7 +78,8 @@ static bool is_interface(const char *dev_name, pid_t pid)
        return false;
 }
 
-int main(int argc, char *argv[])
+int __attribute__((weak, alias("lxc_device_main"))) main(int argc, char *argv[]);
+int lxc_device_main(int argc, char *argv[])
 {
        struct lxc_container *c;
        struct lxc_log log;
index 5b6a863b4541773e29f5e6f64ff89dfaadea8f53..c5c6d56c35288f5444d5744f5a60ef553b342418 100644 (file)
@@ -128,7 +128,8 @@ static bool set_argv(struct lxc_container *c, struct lxc_arguments *args)
        return true;
 }
 
-int main(int argc, char *argv[])
+int __attribute__((weak, alias("lxc_execute_main"))) main(int argc, char *argv[]);
+int lxc_execute_main(int argc, char *argv[])
 {
        struct lxc_container *c;
        struct lxc_log log;
index c18779ba3458820f8d74bbd4ec44e17943772987..99dad95781e40c2257316c8c788fe27436030123 100644 (file)
@@ -36,7 +36,8 @@ Options :\n\
        .log_file     = "none",
 };
 
-int main(int argc, char *argv[])
+int __attribute__((weak, alias("lxc_freeze_main"))) main(int argc, char *argv[]);
+int lxc_freeze_main(int argc, char *argv[])
 {
        struct lxc_container *c;
        struct lxc_log log;
index 9755a503d23dbfcdb82f7bdd4fcced042aa42e86..8929720b142d8df527f8531dc18ce864fc1a86d0 100644 (file)
@@ -388,7 +388,8 @@ static int print_info(const char *name, const char *lxcpath)
        return 0;
 }
 
-int main(int argc, char *argv[])
+int __attribute__((weak, alias("lxc_info_main"))) main(int argc, char *argv[]);
+int lxc_info_main(int argc, char *argv[])
 {
        int ret = EXIT_FAILURE;
        struct lxc_log log;
index 23bee59de7d297546a30bdcabc3e168297790fdc..2be4e790a52c866f3dea18443f08ee55ab720275 100644 (file)
@@ -188,7 +188,8 @@ Options :\n\
        .ls_nesting = 0,
 };
 
-int main(int argc, char *argv[])
+int __attribute__((weak, alias("lxc_ls_main"))) main(int argc, char *argv[]);
+int lxc_ls_main(int argc, char *argv[])
 {
        int ret = EXIT_FAILURE;
        struct lxc_log log;
index 6065f26830a775f074af7a4dfe01877748aab1f5..4c6d063e305e3b74fb315743becf4a49bcf50b01 100644 (file)
@@ -216,7 +216,8 @@ static int lxc_tool_monitord_spawn(const char *lxcpath)
        _exit(EXIT_FAILURE);
 }
 
-int main(int argc, char *argv[])
+int __attribute__((weak, alias("lxc_monitor_main"))) main(int argc, char *argv[]);
+int lxc_monitor_main(int argc, char *argv[])
 {
        char *regexp;
        struct lxc_msg msg;
diff --git a/src/lxc/tools/lxc_multicall.c b/src/lxc/tools/lxc_multicall.c
new file mode 100644 (file)
index 0000000..a90923e
--- /dev/null
@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <string.h>
+#include <stdio.h>
+
+#define PREFIX "lxc-"
+
+int lxc_attach_main(int argc, char *argv[]);
+int lxc_autostart_main(int argc, char *argv[]);
+int lxc_cgroup_main(int argc, char *argv[]);
+int lxc_checkpoint_main(int argc, char *argv[]);
+int lxc_config_main(int argc, char *argv[]);
+int lxc_console_main(int argc, char *argv[]);
+int lxc_copy_main(int argc, char *argv[]);
+int lxc_create_main(int argc, char *argv[]);
+int lxc_destroy_main(int argc, char *argv[]);
+int lxc_device_main(int argc, char *argv[]);
+int lxc_execute_main(int argc, char *argv[]);
+int lxc_freeze_main(int argc, char *argv[]);
+int lxc_info_main(int argc, char *argv[]);
+int lxc_ls_main(int argc, char *argv[]);
+int lxc_monitor_main(int argc, char *argv[]);
+int lxc_snapshot_main(int argc, char *argv[]);
+int lxc_start_main(int argc, char *argv[]);
+int lxc_stop_main(int argc, char *argv[]);
+int lxc_top_main(int argc, char *argv[]);
+int lxc_unfreeze_main(int argc, char *argv[]);
+int lxc_unshare_main(int argc, char *argv[]);
+int lxc_wait_main(int argc, char *argv[]);
+
+static const struct {
+       const char *cmd;
+       int (*main)(int argc, char *argv[]);
+} applets[] = {
+       { "attach", lxc_attach_main },
+       { "autostart", lxc_autostart_main },
+       { "cgroup", lxc_cgroup_main },
+       { "checkpoint", lxc_checkpoint_main },
+       { "config", lxc_config_main },
+       { "console", lxc_console_main },
+       { "copy", lxc_copy_main },
+       { "create", lxc_create_main },
+       { "destroy", lxc_destroy_main },
+       { "device", lxc_device_main },
+       { "execute", lxc_execute_main },
+       { "freeze", lxc_freeze_main },
+       { "info", lxc_info_main },
+       { "ls", lxc_ls_main },
+       { "monitor", lxc_monitor_main },
+       { "snapshot", lxc_snapshot_main },
+       { "start", lxc_start_main },
+       { "stop", lxc_stop_main },
+       { "top", lxc_top_main },
+       { "unfreeze", lxc_unfreeze_main },
+       { "unshare", lxc_unshare_main },
+       { "wait", lxc_wait_main }
+};
+
+const int applets_nmemb = (int)(sizeof(applets)/sizeof(applets[0]));
+
+int main(int argc, char *argv[])
+{
+       const char *cmd;
+       int i;
+
+       if (argc < 1)
+               goto err0;
+
+       cmd = strrchr(argv[0], '/');
+       cmd = cmd ? cmd + 1 : argv[0];
+
+
+       if (!strcmp(cmd, "lxc")) {
+               if (argc < 2)
+                       goto err0;
+               cmd = argv[1];
+               argc -= 1;
+               argv += 1;
+               if (!strcmp(cmd, "-h") || !strcmp(cmd, "--help"))
+                       goto err0;
+       } else if (!strncmp(cmd, PREFIX, strlen(PREFIX))) {
+               cmd += strlen(PREFIX);
+       } else {
+               goto err0;
+       }
+
+       for (i = 0; i < applets_nmemb; i++) {
+               if (!strcmp(applets[i].cmd, cmd))
+                       return applets[i].main(argc, argv);
+       }
+
+       fprintf(stderr, "Unsupported command '%s'\n", cmd);
+       goto err1;
+
+err0:  fprintf(stderr, "This is a multi-call binary, argv[0] is expected to be\n"
+                       "  a name of the requested command prefixed with '%s'\n"
+                       "or\n"
+                       "  'lxc' and the command should be the 1st argument.\n\n"
+                       "For example calling this program as '%sls' or 'lxc' "
+                       "with the argument 'ls' lists containers.\n\n",
+                       PREFIX, PREFIX);
+err1:  fprintf(stderr, "Known commands:\n");
+       for (i = 0; i < applets_nmemb; i++) {
+               fprintf(stderr, "%s ", applets[i].cmd);
+       }
+       putc('\n', stderr);
+       return 1;
+}
index fc2e91c6b75f88c6e46498ba02603927a4c66b33..83effaf686965c9b632b3f63058ef98248ab9d0c 100644 (file)
@@ -61,7 +61,8 @@ static int do_snapshot_restore(struct lxc_container *c,
 static int do_snapshot_task(struct lxc_container *c, enum task task);
 static void print_file(char *path);
 
-int main(int argc, char *argv[])
+int __attribute__((weak, alias("lxc_snapshot_main"))) main(int argc, char *argv[]);
+int lxc_snapshot_main(int argc, char *argv[])
 {
        struct lxc_container *c;
        struct lxc_log log;
index 6d2c0ae252960f5aa18747ce02b94faec931608b..b1b3ca5da2a5359c2111d386c5914b80677ec40f 100644 (file)
@@ -149,7 +149,8 @@ static int ensure_path(char **confpath, const char *path)
        return 0;
 }
 
-int main(int argc, char *argv[])
+int __attribute__((weak, alias("lxc_start_main"))) main(int argc, char *argv[]);
+int lxc_start_main(int argc, char *argv[])
 {
        const char *lxcpath;
        char *const *args;
index 8787bacd548a5913206b5c7e521ece5d9fc2ecba..98e567353a9fe6dfb618849e979630bc12ac538f 100644 (file)
@@ -81,7 +81,8 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg)
        return 0;
 }
 
-int main(int argc, char *argv[])
+int __attribute__((weak, alias("lxc_stop_main"))) main(int argc, char *argv[]);
+int lxc_stop_main(int argc, char *argv[])
 {
        struct lxc_container *c;
        struct lxc_log log;
index d3db4142c761089be7ad6b54a565e3e34b1eaddb..3ddaf89e7a8919042e9d110ea6dc66b7c607a819 100644 (file)
@@ -564,7 +564,8 @@ static int stdin_handler(int fd, uint32_t events, void *data,
        return LXC_MAINLOOP_CLOSE;
 }
 
-int main(int argc, char *argv[])
+int __attribute__((weak, alias("lxc_top_main"))) main(int argc, char *argv[]);
+int lxc_top_main(int argc, char *argv[])
 {
        struct lxc_async_descr descr;
        int ret, ct_print_cnt;
index 818447cadc9483c966c72196a72d409ca818ce6e..9c8dd36136d2c0add7dabfc03f4ad8bee5090322 100644 (file)
@@ -36,7 +36,8 @@ Options :\n\
        .log_file     = "none",
 };
 
-int main(int argc, char *argv[])
+int __attribute__((weak, alias("lxc_unfreeze_main"))) main(int argc, char *argv[]);
+int lxc_unfreeze_main(int argc, char *argv[])
 {
        struct lxc_container *c;
        struct lxc_log log;
index d53f4299b5cfb01eeccd7825463958be374b2a0d..d4ab2e34785e45180fbc7016ffb310087fbf264a 100644 (file)
@@ -280,7 +280,8 @@ static void free_ifname_list(void)
        }
 }
 
-int main(int argc, char *argv[])
+int __attribute__((weak, alias("lxc_unshare_main"))) main(int argc, char *argv[]);
+int lxc_unshare_main(int argc, char *argv[])
 {
        int ret;
        pid_t pid;
index 7bafbd52ccbcfd82bc87567c87d519b2d7ec4779..1c415e8c2567952bbb775172d56d67b29ceefaa4 100644 (file)
@@ -72,7 +72,8 @@ static int my_checker(const struct lxc_arguments *args)
        return 0;
 }
 
-int main(int argc, char *argv[])
+int __attribute__((weak, alias("lxc_wait_main"))) main(int argc, char *argv[]);
+int lxc_wait_main(int argc, char *argv[])
 {
        struct lxc_container *c;
        struct lxc_log log;
index 1bf3be0c24149f6b8125fda6b99a7f4985b03c35..c98d0e5beb7a381d27d9c01c6feb513e4b83b6b4 100644 (file)
@@ -17,3 +17,26 @@ if want_tools
             install: true)
     endforeach
 endif
+
+if want_tools_multicall
+    tools_all_sources = files('lxc_multicall.c') + tools_common_sources
+    foreach cmd : tools_commands
+        tools_all_sources += files('lxc_' + cmd + '.c')
+    endforeach
+
+    public_programs += executable(
+        'lxc',
+        tools_all_sources,
+        include_directories: liblxc_includes,
+        dependencies: liblxc_dep,
+        install: true)
+
+    if want_tools == false
+        foreach cmd : tools_commands
+            public_programs += install_symlink(
+                'lxc-' + cmd,
+                pointing_to: 'lxc',
+                install_dir: get_option('bindir'))
+        endforeach
+    endif
+endif