3 * Copyright © 2016 Christian Brauner <christian.brauner@mailbox.org>.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2, as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 #include <sys/ioctl.h>
32 #include <sys/socket.h>
34 #include <sys/types.h>
38 #include <lxc/lxccontainer.h>
40 #include "arguments.h"
45 lxc_log_define(lxc_ls
, lxc
);
47 /* Per default we only allow five levels of recursion to protect the stack at
48 * least a little bit. */
60 # define SOCK_CLOEXEC 02000000
63 /* Store container info. */
80 /* Keep track of field widths for printing. */
82 unsigned int name_length
;
83 unsigned int state_length
;
84 unsigned int groups_length
;
85 unsigned int interface_length
;
86 unsigned int ipv4_length
;
87 unsigned int ipv6_length
;
88 unsigned int init_length
;
89 unsigned int ram_length
;
90 unsigned int swap_length
;
91 unsigned int autostart_length
;
92 unsigned int unprivileged_length
;
95 static int ls_deserialize(int rpipefd
, struct ls
**m
, size_t *len
);
96 static void ls_field_width(const struct ls
*l
, const size_t size
,
98 static void ls_free(struct ls
*l
, size_t size
);
99 static void ls_free_arr(char **arr
, size_t size
);
100 static int ls_get(struct ls
**m
, size_t *size
, const struct lxc_arguments
*args
,
101 const char *basepath
, const char *parent
, unsigned int lvl
,
102 char **lockpath
, size_t len_lockpath
, char **grps_must
,
103 size_t grps_must_len
);
104 static char *ls_get_cgroup_item(struct lxc_container
*c
, const char *item
);
105 static char *ls_get_config_item(struct lxc_container
*c
, const char *item
,
107 static char *ls_get_groups(struct lxc_container
*c
, bool running
);
108 static char *ls_get_ips(struct lxc_container
*c
, const char *inet
);
109 static int ls_recv_str(int fd
, char **buf
);
110 static int ls_send_str(int fd
, const char *buf
);
113 const struct lxc_arguments
*args
;
115 size_t grps_must_len
;
119 unsigned int nestlvl
;
123 * Takes struct wrapargs as argument.
125 static int ls_get_wrapper(void *wrap
);
128 * To calculate swap usage we should not simply check memory.usage_in_bytes and
129 * memory.memsw.usage_in_bytes and then do:
130 * swap = memory.memsw.usage_in_bytes - memory.usage_in_bytes;
131 * because we might receive an incorrect/negative value.
132 * Instead we check memory.stat and check the "swap" value.
134 static double ls_get_swap(struct lxc_container
*c
);
135 static unsigned int ls_get_term_width(void);
136 static char *ls_get_interface(struct lxc_container
*c
);
137 static bool ls_has_all_grps(const char *has
, char **must
, size_t must_len
);
138 static struct ls
*ls_new(struct ls
**ls
, size_t *size
);
141 * Print user-specified fancy format.
143 static void ls_print_fancy_format(struct ls
*l
, struct lengths
*lht
,
144 size_t size
, const char *fancy_fmt
);
147 * Only print names of containers.
149 static void ls_print_names(struct ls
*l
, struct lengths
*lht
,
150 size_t ls_arr
, size_t termwidth
, bool list
);
153 * Print default fancy format.
155 static void ls_print_table(struct ls
*l
, struct lengths
*lht
,
159 * id can only be 79 + \0 chars long.
161 static int ls_remove_lock(const char *path
, const char *name
,
162 char **lockpath
, size_t *len_lockpath
, bool recalc
);
163 static int ls_serialize(int wpipefd
, struct ls
*n
);
164 static int my_parser(struct lxc_arguments
*args
, int c
, char *arg
);
166 static const struct option my_longopts
[] = {
167 {"line", no_argument
, 0, '1'},
168 {"fancy", no_argument
, 0, 'f'},
169 {"fancy-format", required_argument
, 0, 'F'},
170 {"active", no_argument
, 0, LS_ACTIVE
},
171 {"running", no_argument
, 0, LS_RUNNING
},
172 {"frozen", no_argument
, 0, LS_FROZEN
},
173 {"stopped", no_argument
, 0, LS_STOPPED
},
174 {"defined", no_argument
, 0, LS_DEFINED
},
175 {"nesting", optional_argument
, 0, LS_NESTING
},
176 {"groups", required_argument
, 0, 'g'},
177 {"filter", required_argument
, 0, LS_FILTER
},
181 static struct lxc_arguments my_args
= {
182 .progname
= "lxc-ls",
184 [-P lxcpath] [--active] [--running] [--frozen] [--stopped] [--nesting] [-g groups] [--filter regex]\n\
185 [-1] [-P lxcpath] [--active] [--running] [--frozen] [--stopped] [--nesting] [-g groups] [--filter regex]\n\
186 [-f] [-P lxcpath] [--active] [--running] [--frozen] [--stopped] [--nesting] [-g groups] [--filter regex]\n\
188 lxc-ls list containers\n\
191 -1, --line show one entry per line\n\
192 -f, --fancy use a fancy, column-based output\n\
193 -F, --fancy-format comma separated list of columns to show in the fancy output\n\
194 valid columns are: NAME, STATE, PID, RAM, SWAP, AUTOSTART,\n\
195 GROUPS, INTERFACE, IPV4 and IPV6, UNPRIVILEGED\n\
196 --active list only active containers\n\
197 --running list only running containers\n\
198 --frozen list only frozen containers\n\
199 --stopped list only stopped containers\n\
200 --defined list only defined containers\n\
201 --nesting=NUM list nested containers up to NUM (default is 5) levels of nesting\n\
202 --filter=REGEX filter container names by regular expression\n\
203 -g --groups comma separated list of groups a container must have to be displayed\n",
204 .options
= my_longopts
,
209 int main(int argc
, char *argv
[])
211 int ret
= EXIT_FAILURE
;
215 * The lxc parser requires that my_args.name is set. So let's satisfy
216 * that condition by setting a dummy name which is never used.
219 if (lxc_arguments_parse(&my_args
, argc
, argv
))
222 /* Only create log if explicitly instructed */
223 if (my_args
.log_file
|| my_args
.log_priority
) {
225 log
.file
= my_args
.log_file
;
226 log
.level
= my_args
.log_priority
;
227 log
.prefix
= my_args
.progname
;
228 log
.quiet
= my_args
.quiet
;
229 log
.lxcpath
= my_args
.lxcpath
[0];
231 if (lxc_log_init(&log
))
235 struct lengths max_len
= {
236 /* default header length */
237 .name_length
= 4, /* NAME */
238 .state_length
= 5, /* STATE */
239 .groups_length
= 6, /* GROUPS */
240 .interface_length
= 9, /* INTERFACE */
241 .ipv4_length
= 4, /* IPV4 */
242 .ipv6_length
= 4, /* IPV6 */
243 .init_length
= 3, /* PID */
244 .ram_length
= 3, /* RAM */
245 .swap_length
= 4, /* SWAP */
246 .autostart_length
= 9, /* AUTOSTART */
247 .unprivileged_length
= 12, /* UNPRIVILEGED */
252 if (my_args
.groups
) {
253 grps
= lxc_string_split_and_trim(my_args
.groups
, ',');
254 ngrps
= lxc_array_len((void **)grps
);
257 struct ls
*ls_arr
= NULL
;
260 /* &(char *){NULL} is no magic. It's just a compound literal which
261 * avoids having a pointless variable in main() that serves no purpose
263 int status
= ls_get(&ls_arr
, &ls_size
, &my_args
, "", NULL
, 0, &(char *){NULL
}, 0, grps
, ngrps
);
264 if (!ls_arr
&& status
== 0)
265 /* We did not fail. There was just nothing to do. */
267 else if (!ls_arr
|| status
== -1)
270 ls_field_width(ls_arr
, ls_size
, &max_len
);
272 if (my_args
.ls_fancy
&& !my_args
.ls_fancy_format
) {
273 ls_print_table(ls_arr
, &max_len
, ls_size
);
274 } else if (my_args
.ls_fancy
&& my_args
.ls_fancy_format
) {
275 ls_print_fancy_format(ls_arr
, &max_len
, ls_size
, my_args
.ls_fancy_format
);
277 unsigned int cols
= 0;
278 if (!my_args
.ls_line
)
279 cols
= ls_get_term_width();
280 ls_print_names(ls_arr
, &max_len
, ls_size
, cols
, my_args
.ls_line
);
286 ls_free(ls_arr
, ls_size
);
287 lxc_free_array((void **)grps
, free
);
292 static void ls_free(struct ls
*l
, size_t size
)
297 for (i
= 0, m
= l
; i
< size
; i
++, m
++) {
308 static char *ls_get_config_item(struct lxc_container
*c
, const char *item
,
312 return c
->get_running_config_item(c
, item
);
314 int len
= c
->get_config_item(c
, item
, NULL
, 0);
318 char *val
= malloc((len
+ 1) * sizeof(*val
));
322 if (c
->get_config_item(c
, item
, val
, len
+ 1) != len
) {
330 static void ls_free_arr(char **arr
, size_t size
)
334 for (i
= 0; i
< size
; i
++)
340 static int ls_get(struct ls
**m
, size_t *size
, const struct lxc_arguments
*args
,
341 const char *basepath
, const char *parent
, unsigned int lvl
,
342 char **lockpath
, size_t len_lockpath
, char **grps_must
,
343 size_t grps_must_len
)
345 /* As ls_get() is non-tail recursive we face the inherent danger of
346 * blowing up the stack at some level of nesting. To have at least some
347 * security we define MAX_NESTLVL to be 5. That should be sufficient for
348 * most users. The argument lvl can be used to keep track of the level
349 * of nesting we are at. If lvl is greater than the allowed default
350 * level or the level the user specified on the command line we return
351 * and unwind the stack. */
352 if (lvl
> args
->ls_nesting
)
355 int num
= 0, ret
= -1;
356 char **containers
= NULL
;
357 /* If we, at some level of nesting, encounter a stopped container but
358 * want to retrieve nested containers we need to build an absolute path
359 * beginning from it. Initially, at nesting level 0, basepath will
360 * simply be the empty string and path will simply be whatever the
361 * default lxcpath or the path the user gave us is. Basepath will also
362 * be the empty string in case we encounter a running container since we
363 * can simply attach to its namespace to retrieve nested containers. */
364 char *path
= lxc_append_paths(basepath
, args
->lxcpath
[0]);
368 if (!dir_exists(path
)) {
373 /* Do not do more work than is necessary right from the start. */
374 if (args
->ls_active
|| args
->ls_frozen
)
375 num
= list_active_containers(path
, &containers
, NULL
);
377 num
= list_all_containers(path
, &containers
, NULL
);
386 struct lxc_container
*c
= NULL
;
389 for (i
= 0; i
< (size_t)num
; i
++) {
390 char *name
= containers
[i
];
392 /* Filter container names by regex the user gave us. */
393 if (args
->ls_filter
|| args
->argc
== 1) {
396 tmp
= args
->ls_filter
? args
->ls_filter
: args
->argv
[0];
397 check
= regcomp(&preg
, tmp
, REG_NOSUB
| REG_EXTENDED
);
398 if (check
== REG_ESPACE
) /* we're out of memory */
403 check
= regexec(&preg
, name
, 0, NULL
, 0);
410 c
= lxc_container_new(name
, path
);
411 if ((errno
== ENOMEM
) && !c
)
416 if (args
->ls_defined
&& !c
->is_defined(c
))
419 /* This does not allocate memory so no worries about freeing it
420 * when we goto next or out. */
421 const char *state_tmp
= c
->state(c
);
423 state_tmp
= "UNKNOWN";
425 if (args
->ls_running
&& !c
->is_running(c
))
428 if (args
->ls_frozen
&& !args
->ls_active
&& strcmp(state_tmp
, "FROZEN"))
431 if (args
->ls_stopped
&& strcmp(state_tmp
, "STOPPED"))
434 bool running
= c
->is_running(c
);
436 char *grp_tmp
= ls_get_groups(c
, running
);
437 if (!ls_has_all_grps(grp_tmp
, grps_must
, grps_must_len
)) {
442 /* Now it makes sense to allocate memory. */
449 /* How deeply nested are we? */
454 l
->running
= running
;
456 if (parent
&& args
->ls_nesting
&& (args
->ls_line
|| !args
->ls_fancy
))
457 /* Prepend the name of the container with all its parents when
458 * the user requests it. */
459 l
->name
= lxc_append_paths(parent
, name
);
461 /* Otherwise simply record the name. */
462 l
->name
= strdup(name
);
466 /* Do not record stuff the user did not explicitly request. */
467 if (args
->ls_fancy
) {
468 /* Maybe we should even consider the name sensitive and
469 * hide it when you're not allowed to control the
471 if (!c
->may_control(c
))
474 l
->state
= strdup(state_tmp
);
478 tmp
= ls_get_config_item(c
, "lxc.start.auto", running
);
480 unsigned int astart
= 0;
481 if (lxc_safe_uint(tmp
, &astart
) < 0)
482 printf("Could not parse value for 'lxc.start.auto'.\n");
484 printf("Wrong value for 'lxc.start.auto = %d'.\n", astart
);
485 l
->autostart
= astart
== 1 ? true : false;
492 l
->init
= c
->init_pid(c
);
496 l
->interface
= ls_get_interface(c
);
498 l
->ipv4
= ls_get_ips(c
, "inet");
500 l
->ipv6
= ls_get_ips(c
, "inet6");
502 tmp
= ls_get_cgroup_item(c
, "memory.usage_in_bytes");
504 l
->ram
= strtoull(tmp
, NULL
, 0);
505 l
->ram
= l
->ram
/ 1024 /1024;
509 l
->swap
= ls_get_swap(c
);
511 val
= c
->get_running_config_item(c
, "lxc.idmap");
512 l
->unprivileged
= !(val
== NULL
);
517 ret
= c
->get_config_item(c
, "lxc.idmap", NULL
, 0);
518 l
->unprivileged
= !(ret
== 0);
522 /* Get nested containers: Only do this after we have gathered
523 * all other information we need. */
524 if (args
->ls_nesting
&& running
) {
525 struct wrapargs wargs
= (struct wrapargs
){.args
= NULL
};
527 /* Open a socket so that the child can communicate with us. */
528 check
= socketpair(AF_UNIX
, SOCK_STREAM
| SOCK_CLOEXEC
, 0, wargs
.pipefd
);
532 /* Set the next nesting level. */
533 wargs
.nestlvl
= lvl
+ 1;
534 /* Send in the parent for the next nesting level. */
535 wargs
.parent
= l
->name
;
537 wargs
.grps_must
= grps_must
;
538 wargs
.grps_must_len
= grps_must_len
;
542 lxc_attach_options_t aopt
= LXC_ATTACH_OPTIONS_DEFAULT
;
543 aopt
.env_policy
= LXC_ATTACH_CLEAR_ENV
;
545 /* fork(): Attach to the namespace of the container and
546 * run ls_get() in it which is called in ls_get_wrapper(). */
547 check
= c
->attach(c
, ls_get_wrapper
, &wargs
, &aopt
, &out
);
548 /* close the socket */
549 close(wargs
.pipefd
[1]);
551 /* Retrieve all information we want from the child. */
553 if (ls_deserialize(wargs
.pipefd
[0], m
, size
) == -1)
556 /* Wait for the child to finish. */
559 /* We've done all the communication we need so shutdown
560 * the socket and close it. */
561 shutdown(wargs
.pipefd
[0], SHUT_RDWR
);
562 close(wargs
.pipefd
[0]);
563 } else if (args
->ls_nesting
&& !running
) {
564 /* This way of extracting the rootfs is not safe since
565 * it will return very different things depending on the
566 * storage backend that is used for the container. We
567 * need a path-extractor function. We face the same
568 * problem with the ovl_mkdir() function in
569 * lxcoverlay.{c,h}. */
570 char *curr_path
= ls_get_config_item(c
, "lxc.rootfs.path", running
);
574 /* Since the container is not running and we cannot
575 * attach to it we need another strategy to retrieve
576 * nested containers. What we do is simply create a
577 * growing path which will lead us into the rootfs of
578 * the next container where it stores its containers. */
579 char *newpath
= lxc_append_paths(basepath
, curr_path
);
584 /* We want to remove all locks we create under
585 * /run/lxc/lock so we create a string pointing us to
586 * the lock path for the current container. */
587 if (ls_remove_lock(path
, name
, lockpath
, &len_lockpath
, true) == -1) {
592 ls_get(m
, size
, args
, newpath
, l
->name
, lvl
+ 1, lockpath
, len_lockpath
, grps_must
, grps_must_len
);
595 /* Remove the lock. No need to check for failure here. */
596 ls_remove_lock(path
, name
, lockpath
, &len_lockpath
, false);
600 lxc_container_put(c
);
605 ls_free_arr(containers
, num
);
608 /* lockpath is shared amongst all non-fork()ing recursive calls to
609 * ls_get() so only free it on the uppermost level. */
616 static char *ls_get_cgroup_item(struct lxc_container
*c
, const char *item
)
618 int len
= c
->get_cgroup_item(c
, item
, NULL
, 0);
622 char *val
= malloc((len
+ 1) * sizeof(*val
));
626 if (c
->get_cgroup_item(c
, item
, val
, len
+ 1) != len
) {
634 static char *ls_get_groups(struct lxc_container
*c
, bool running
)
640 val
= c
->get_running_config_item(c
, "lxc.group");
642 len
= c
->get_config_item(c
, "lxc.group", NULL
, 0);
644 if (!val
&& (len
> 0)) {
645 val
= malloc((len
+ 1) * sizeof(*val
));
646 if (c
->get_config_item(c
, "lxc.group", val
, len
+ 1) != len
) {
655 if ((tmp
= strrchr(val
, '\n')))
658 tmp
= lxc_string_replace("\n", ", ", val
);
666 static char *ls_get_ips(struct lxc_container
*c
, const char *inet
)
671 iptmp
= c
->get_ips(c
, NULL
, inet
, 0);
673 ips
= lxc_string_join(", ", (const char **)iptmp
, false);
675 lxc_free_array((void **)iptmp
, free
);
680 static char *ls_get_interface(struct lxc_container
*c
)
682 char **interfaces
= c
->get_interfaces(c
);
686 char *interface
= lxc_string_join(", ", (const char **)interfaces
, false);
688 lxc_free_array((void **)interfaces
, free
);
694 * To calculate swap usage we should not simply check memory.usage_in_bytes and
695 * memory.memsw.usage_in_bytes and then do:
696 * swap = memory.memsw.usage_in_bytes - memory.usage_in_bytes;
697 * because we might receive an incorrect/negative value.
698 * Instead we check memory.stat and check the "swap" value.
700 static double ls_get_swap(struct lxc_container
*c
)
702 char *stat
, *swap
, *tmp
;
703 unsigned long long int num
= 0;
705 stat
= ls_get_cgroup_item(c
, "memory.stat");
709 swap
= strstr(stat
, "\nswap");
713 /* start_of_swap_value = '\n' + strlen(swap) + ' ' */
714 swap
= 1 + swap
+ 4 + 1;
716 /* find end of swap value */
717 tmp
= strchr(swap
, '\n');
723 num
= strtoull(swap
, NULL
, 0);
724 num
= num
/ 1024 / 1024;
732 static unsigned int ls_get_term_width(void)
736 if (((ioctl(STDOUT_FILENO
, TIOCGWINSZ
, &ws
) == -1) &&
737 (ioctl(STDERR_FILENO
, TIOCGWINSZ
, &ws
) == -1) &&
738 (ioctl(STDIN_FILENO
, TIOCGWINSZ
, &ws
) == -1)) ||
745 static bool ls_has_all_grps(const char *has
, char **must
, size_t must_len
)
754 char **tmp_has
= lxc_string_split_and_trim(has
, ',');
755 size_t tmp_has_len
= lxc_array_len((void **)tmp_has
);
757 /* Don't do any unnecessary work. */
758 if (must_len
> tmp_has_len
)
762 for (i
= 0; i
< must_len
; i
++) {
763 for (j
= 0; j
< tmp_has_len
; j
++)
764 if (strcmp(must
[i
], tmp_has
[j
]) == 0)
766 if (j
== tmp_has_len
)
774 lxc_free_array((void **)tmp_has
, free
);
779 static struct ls
*ls_new(struct ls
**ls
, size_t *size
)
783 n
= realloc(*ls
, (*size
+ 1) * sizeof(struct ls
));
791 *m
= (struct ls
){.name
= NULL
, .init
= -1};
796 static void ls_print_names(struct ls
*l
, struct lengths
*lht
,
797 size_t size
, size_t termwidth
, bool list
)
799 /* If list is empty do nothing. */
806 for (i
= 0, m
= l
; i
< size
; i
++, m
++) {
808 printf("%s\n", m
->name
? m
->name
: "-");
810 printf("%-*s", lht
->name_length
, m
->name
? m
->name
: "-");
812 len
+= lht
->name_length
;
813 if ((len
+ lht
->name_length
) >= termwidth
) {
827 static void ls_print_fancy_format(struct ls
*l
, struct lengths
*lht
,
828 size_t size
, const char *fancy_fmt
)
830 /* If list is empty do nothing. */
834 char **tmp
= lxc_string_split_and_trim(fancy_fmt
, ',');
839 /* Check for invalid keys. */
840 for (s
= tmp
; s
&& *s
; s
++) {
841 if (strcasecmp(*s
, "NAME") && strcasecmp(*s
, "STATE") &&
842 strcasecmp(*s
, "PID") && strcasecmp(*s
, "RAM") &&
843 strcasecmp(*s
, "SWAP") && strcasecmp(*s
, "AUTOSTART") &&
844 strcasecmp(*s
, "GROUPS") && strcasecmp(*s
, "INTERFACE") &&
845 strcasecmp(*s
, "IPV4") && strcasecmp(*s
, "IPV6") &&
846 strcasecmp(*s
, "UNPRIVILEGED")) {
847 fprintf(stderr
, "Invalid key: %s\n", *s
);
848 lxc_free_array((void **)tmp
, free
);
854 for (s
= tmp
; s
&& *s
; s
++) {
855 if (strcasecmp(*s
, "NAME") == 0)
856 printf("%-*s ", lht
->name_length
, "NAME");
857 else if (strcasecmp(*s
, "STATE") == 0)
858 printf("%-*s ", lht
->state_length
, "STATE");
859 else if (strcasecmp(*s
, "PID") == 0)
860 printf("%-*s ", lht
->init_length
, "PID");
861 else if (strcasecmp(*s
, "RAM") == 0)
862 printf("%-*s ", lht
->ram_length
+ 2, "RAM");
863 else if (strcasecmp(*s
, "SWAP") == 0)
864 printf("%-*s ", lht
->swap_length
+ 2, "SWAP");
865 else if (strcasecmp(*s
, "AUTOSTART") == 0)
866 printf("%-*s ", lht
->autostart_length
, "AUTOSTART");
867 else if (strcasecmp(*s
, "GROUPS") == 0)
868 printf("%-*s ", lht
->groups_length
, "GROUPS");
869 else if (strcasecmp(*s
, "INTERFACE") == 0)
870 printf("%-*s ", lht
->interface_length
, "INTERFACE");
871 else if (strcasecmp(*s
, "IPV4") == 0)
872 printf("%-*s ", lht
->ipv4_length
, "IPV4");
873 else if (strcasecmp(*s
, "IPV6") == 0)
874 printf("%-*s ", lht
->ipv6_length
, "IPV6");
875 else if (strcasecmp(*s
, "UNPRIVILEGED") == 0)
876 printf("%-*s ", lht
->unprivileged_length
, "UNPRIVILEGED");
883 for (i
= 0, m
= l
; i
< size
; i
++, m
++) {
884 for (s
= tmp
; s
&& *s
; s
++) {
885 if (strcasecmp(*s
, "NAME") == 0) {
886 if (m
->nestlvl
> 0) {
887 printf("%*s", m
->nestlvl
, "\\");
888 printf("%-*s ", lht
->name_length
- m
->nestlvl
, m
->name
? m
->name
: "-");
890 printf("%-*s ", lht
->name_length
, m
->name
? m
->name
: "-");
892 } else if (strcasecmp(*s
, "STATE") == 0) {
893 printf("%-*s ", lht
->state_length
, m
->state
? m
->state
: "-");
894 } else if (strcasecmp(*s
, "PID") == 0) {
896 printf("%-*d ", lht
->init_length
, m
->init
);
898 printf("%-*s ", lht
->init_length
, "-");
899 } else if (strcasecmp(*s
, "RAM") == 0) {
900 if ((m
->ram
>= 0) && m
->running
)
901 printf("%*.2fMB ", lht
->ram_length
, m
->ram
);
903 printf("%-*s ", lht
->ram_length
, "-");
904 } else if (strcasecmp(*s
, "SWAP") == 0) {
905 if ((m
->swap
>= 0) && m
->running
)
906 printf("%*.2fMB ", lht
->swap_length
, m
->swap
);
908 printf("%-*s ", lht
->swap_length
, "-");
909 } else if (strcasecmp(*s
, "AUTOSTART") == 0) {
910 printf("%-*d ", lht
->autostart_length
, m
->autostart
);
911 } else if (strcasecmp(*s
, "GROUPS") == 0) {
912 printf("%-*s ", lht
->groups_length
, m
->groups
? m
->groups
: "-");
913 } else if (strcasecmp(*s
, "INTERFACE") == 0) {
914 printf("%-*s ", lht
->interface_length
, m
->interface
? m
->interface
: "-");
915 } else if (strcasecmp(*s
, "IPV4") == 0) {
916 printf("%-*s ", lht
->ipv4_length
, m
->ipv4
? m
->ipv4
: "-");
917 } else if (strcasecmp(*s
, "IPV6") == 0) {
918 printf("%-*s ", lht
->ipv6_length
, m
->ipv6
? m
->ipv6
: "-");
919 } else if (strcasecmp(*s
, "UNPRIVILEGED") == 0) {
920 printf("%-*s ", lht
->unprivileged_length
, m
->unprivileged
? "true" : "false");
926 lxc_free_array((void **)tmp
, free
);
929 static void ls_print_table(struct ls
*l
, struct lengths
*lht
,
934 /* If list is empty do nothing. */
941 printf("%-*s ", lht
->name_length
, "NAME");
942 printf("%-*s ", lht
->state_length
, "STATE");
943 printf("%-*s ", lht
->autostart_length
, "AUTOSTART");
944 printf("%-*s ", lht
->groups_length
, "GROUPS");
945 printf("%-*s ", lht
->ipv4_length
, "IPV4");
946 printf("%-*s ", lht
->ipv6_length
, "IPV6");
947 printf("%-*s ", lht
->unprivileged_length
, "UNPRIVILEGED");
950 for (i
= 0, m
= l
; i
< size
; i
++, m
++) {
951 if (m
->nestlvl
> 0) {
952 printf("%*s", m
->nestlvl
, "\\");
953 printf("%-*s ", lht
->name_length
- m
->nestlvl
, m
->name
? m
->name
: "-");
955 printf("%-*s ", lht
->name_length
, m
->name
? m
->name
: "-");
958 printf("%-*s ", lht
->state_length
, m
->state
? m
->state
: "-");
959 printf("%-*d ", lht
->autostart_length
, m
->autostart
);
960 printf("%-*s ", lht
->groups_length
, m
->groups
? m
->groups
: "-");
961 printf("%-*s ", lht
->ipv4_length
, m
->ipv4
? m
->ipv4
: "-");
962 printf("%-*s ", lht
->ipv6_length
, m
->ipv6
? m
->ipv6
: "-");
963 printf("%-*s ", lht
->unprivileged_length
, m
->unprivileged
? "true" : "false");
968 static int my_parser(struct lxc_arguments
*args
, int c
, char *arg
)
971 unsigned long int m
, n
= MAX_NESTLVL
;
975 args
->ls_line
= true;
978 args
->ls_fancy
= true;
981 args
->ls_active
= true;
984 args
->ls_frozen
= true;
987 args
->ls_running
= true;
990 args
->ls_stopped
= true;
993 args
->ls_defined
= true;
996 /* In case strtoul() receives a string that represents a
997 * negative number it will return ULONG_MAX - the number that
998 * the string represents if the number the string represents is
999 * < ULONG_MAX and ULONG_MAX otherwise. But it will consider
1000 * this valid input and not set errno. So we check manually if
1001 * the first character of num_string == '-'. Otherwise the
1002 * default level remains set. */
1003 if (arg
&& !(*arg
== '-')) {
1005 m
= strtoul(arg
, &invalid
, 0);
1006 /* ls_nesting has type unsigned int. */
1007 if (!errno
&& (*invalid
== '\0') && (m
<= UINT_MAX
))
1010 args
->ls_nesting
= n
;
1016 args
->ls_filter
= arg
;
1019 args
->ls_fancy_format
= arg
;
1026 static int ls_get_wrapper(void *wrap
)
1030 struct wrapargs
*wargs
= (struct wrapargs
*)wrap
;
1031 struct ls
*m
= NULL
, *n
= NULL
;
1035 close(wargs
->pipefd
[0]);
1037 /* &(char *){NULL} is no magic. It's just a compound literal which
1038 * allows us to avoid keeping a pointless variable around. */
1039 ls_get(&m
, &len
, wargs
->args
, "", wargs
->parent
, wargs
->nestlvl
, &(char *){NULL
}, 0, wargs
->grps_must
, wargs
->grps_must_len
);
1044 if (lxc_write_nointr(wargs
->pipefd
[1], &len
, sizeof(len
)) <= 0)
1047 for (i
= 0, n
= m
; i
< len
; i
++, n
++) {
1048 if (ls_serialize(wargs
->pipefd
[1], n
) == -1)
1054 shutdown(wargs
->pipefd
[1], SHUT_RDWR
);
1055 close(wargs
->pipefd
[1]);
1061 static int ls_remove_lock(const char *path
, const char *name
,
1062 char **lockpath
, size_t *len_lockpath
, bool recalc
)
1067 /* lockfile will be:
1068 * "/run" + "/lxc/lock/$lxcpath/$lxcname + '\0' if root
1070 * $XDG_RUNTIME_DIR + "/lxc/lock/$lxcpath/$lxcname + '\0' if non-root
1072 rundir
= get_rundir();
1076 /* Avoid doing unnecessary work if we can. */
1078 size_t newlen
= strlen(path
) + strlen(name
) + strlen(rundir
) + /* / + lxc + / + lock + / + / = */ 11 + 1;
1079 if (newlen
> *len_lockpath
) {
1080 char *tmp
= realloc(*lockpath
, newlen
* 2);
1084 *len_lockpath
= newlen
* 2;
1088 int check
= snprintf(*lockpath
, *len_lockpath
, "%s/lxc/lock/%s/%s", rundir
, path
, name
);
1089 if (check
< 0 || (size_t)check
>= *len_lockpath
)
1092 ret
= recursive_destroy(*lockpath
);
1094 WARN("Failed to destroy \"%s\"", *lockpath
);
1103 static int ls_send_str(int fd
, const char *buf
)
1110 if (lxc_write_nointr(fd
, &slen
, sizeof(slen
)) != sizeof(slen
))
1114 if (lxc_write_nointr(fd
, buf
, slen
) != (ssize_t
)slen
)
1121 static int ls_serialize(int wpipefd
, struct ls
*n
)
1123 ssize_t nbytes
= sizeof(n
->ram
);
1124 if (lxc_write_nointr(wpipefd
, &n
->ram
, (size_t)nbytes
) != nbytes
)
1127 nbytes
= sizeof(n
->swap
);
1128 if (lxc_write_nointr(wpipefd
, &n
->swap
, (size_t)nbytes
) != nbytes
)
1131 nbytes
= sizeof(n
->init
);
1132 if (lxc_write_nointr(wpipefd
, &n
->init
, (size_t)nbytes
) != nbytes
)
1135 nbytes
= sizeof(n
->autostart
);
1136 if (lxc_write_nointr(wpipefd
, &n
->autostart
, (size_t)nbytes
) != nbytes
)
1139 nbytes
= sizeof(n
->running
);
1140 if (lxc_write_nointr(wpipefd
, &n
->running
, (size_t)nbytes
) != nbytes
)
1143 nbytes
= sizeof(n
->unprivileged
);
1144 if (lxc_write_nointr(wpipefd
, &n
->unprivileged
, (size_t)nbytes
) != nbytes
)
1147 nbytes
= sizeof(n
->nestlvl
);
1148 if (lxc_write_nointr(wpipefd
, &n
->nestlvl
, (size_t)nbytes
) != nbytes
)
1152 if (ls_send_str(wpipefd
, n
->name
) < 0)
1156 if (ls_send_str(wpipefd
, n
->state
) < 0)
1160 if (ls_send_str(wpipefd
, n
->groups
) < 0)
1164 if (ls_send_str(wpipefd
, n
->interface
) < 0)
1168 if (ls_send_str(wpipefd
, n
->ipv4
) < 0)
1172 if (ls_send_str(wpipefd
, n
->ipv6
) < 0)
1178 static int ls_recv_str(int fd
, char **buf
)
1183 ret
= lxc_read_nointr(fd
, &slen
, sizeof(slen
));
1184 if (ret
!= sizeof(slen
))
1188 *buf
= malloc(sizeof(char) * (slen
+ 1));
1192 ret
= lxc_read_nointr(fd
, *buf
, slen
);
1193 if (ret
!= (ssize_t
)slen
) {
1198 (*buf
)[slen
] = '\0';
1204 static int ls_deserialize(int rpipefd
, struct ls
**m
, size_t *len
)
1211 nbytes
= sizeof(sublen
);
1212 if (lxc_read_nointr(rpipefd
, &sublen
, (size_t)nbytes
) != nbytes
)
1215 while (sublen
-- > 0) {
1220 nbytes
= sizeof(n
->ram
);
1221 if (lxc_read_nointr(rpipefd
, &n
->ram
, (size_t)nbytes
) != nbytes
)
1224 nbytes
= sizeof(n
->swap
);
1225 if (lxc_read_nointr(rpipefd
, &n
->swap
, (size_t)nbytes
) != nbytes
)
1228 nbytes
= sizeof(n
->init
);
1229 if (lxc_read_nointr(rpipefd
, &n
->init
, (size_t)nbytes
) != nbytes
)
1232 nbytes
= sizeof(n
->autostart
);
1233 if (lxc_read_nointr(rpipefd
, &n
->autostart
, (size_t)nbytes
) != nbytes
)
1236 nbytes
= sizeof(n
->running
);
1237 if (lxc_read_nointr(rpipefd
, &n
->running
, (size_t)nbytes
) != nbytes
)
1240 nbytes
= sizeof(n
->unprivileged
);
1241 if (lxc_read_nointr(rpipefd
, &n
->unprivileged
, (size_t)nbytes
) != nbytes
)
1244 nbytes
= sizeof(n
->nestlvl
);
1245 if (lxc_read_nointr(rpipefd
, &n
->nestlvl
, (size_t)nbytes
) != nbytes
)
1249 if (ls_recv_str(rpipefd
, &n
->name
) < 0)
1253 if (ls_recv_str(rpipefd
, &n
->state
) < 0)
1257 if (ls_recv_str(rpipefd
, &n
->groups
) < 0)
1261 if (ls_recv_str(rpipefd
, &n
->interface
) < 0)
1265 if (ls_recv_str(rpipefd
, &n
->ipv4
) < 0)
1269 if (ls_recv_str(rpipefd
, &n
->ipv6
) < 0)
1276 static void ls_field_width(const struct ls
*l
, const size_t size
,
1277 struct lengths
*lht
)
1282 for (i
= 0, m
= l
; i
< size
; i
++, m
++) {
1284 len
= strlen(m
->name
) + m
->nestlvl
;
1285 if (len
> lht
->name_length
)
1286 lht
->name_length
= len
;
1290 len
= strlen(m
->state
);
1291 if (len
> lht
->state_length
)
1292 lht
->state_length
= len
;
1296 len
= strlen(m
->interface
);
1297 if (len
> lht
->interface_length
)
1298 lht
->interface_length
= len
;
1302 len
= strlen(m
->groups
);
1303 if (len
> lht
->groups_length
)
1304 lht
->groups_length
= len
;
1307 len
= strlen(m
->ipv4
);
1308 if (len
> lht
->ipv4_length
)
1309 lht
->ipv4_length
= len
;
1313 len
= strlen(m
->ipv6
);
1314 if (len
> lht
->ipv6_length
)
1315 lht
->ipv6_length
= len
;
1318 if ((len
= snprintf(NULL
, 0, "%.2f", m
->ram
)) > lht
->ram_length
)
1319 lht
->ram_length
= len
;
1321 if ((len
= snprintf(NULL
, 0, "%.2f", m
->swap
)) > lht
->swap_length
)
1322 lht
->swap_length
= len
;
1324 if (m
->init
!= -1) {
1325 if ((len
= snprintf(NULL
, 0, "%d", m
->init
)) > lht
->init_length
)
1326 lht
->init_length
= len
;