1 /* SPDX-License-Identifier: GPL-2.0-only */
15 #include <sys/ioctl.h>
16 #include <sys/socket.h>
18 #include <sys/types.h>
24 #include "arguments.h"
27 #include "memory_utils.h"
30 lxc_log_define(lxc_ls
, lxc
);
32 /* Per default we only allow five levels of recursion to protect the stack at
33 * least a little bit. */
45 # define SOCK_CLOEXEC 02000000
48 /* Store container info. */
65 /* Keep track of field widths for printing. */
67 unsigned int name_length
;
68 unsigned int state_length
;
69 unsigned int groups_length
;
70 unsigned int interface_length
;
71 unsigned int ipv4_length
;
72 unsigned int ipv6_length
;
73 unsigned int init_length
;
74 unsigned int ram_length
;
75 unsigned int swap_length
;
76 unsigned int autostart_length
;
77 unsigned int unprivileged_length
;
80 static int ls_deserialize(int rpipefd
, struct ls
**m
, size_t *len
);
81 static void ls_field_width(const struct ls
*l
, const size_t size
,
83 static void ls_free(struct ls
*l
, size_t size
);
84 static void ls_free_arr(char **arr
, size_t size
);
85 static int ls_get(struct ls
**m
, size_t *size
, const struct lxc_arguments
*args
,
86 const char *basepath
, const char *parent
, unsigned int lvl
,
87 char **lockpath
, size_t len_lockpath
, char **grps_must
,
88 size_t grps_must_len
);
89 static char *ls_get_cgroup_item(struct lxc_container
*c
, const char *item
);
90 static char *ls_get_config_item(struct lxc_container
*c
, const char *item
,
92 static char *ls_get_groups(struct lxc_container
*c
, bool running
);
93 static char *ls_get_ips(struct lxc_container
*c
, const char *inet
);
94 static int ls_recv_str(int fd
, char **buf
);
95 static int ls_send_str(int fd
, const char *buf
);
98 const struct lxc_arguments
*args
;
100 size_t grps_must_len
;
104 unsigned int nestlvl
;
108 * Takes struct wrapargs as argument.
110 static int ls_get_wrapper(void *wrap
);
113 * To calculate swap usage we should not simply check memory.usage_in_bytes and
114 * memory.memsw.usage_in_bytes and then do:
115 * swap = memory.memsw.usage_in_bytes - memory.usage_in_bytes;
116 * because we might receive an incorrect/negative value.
117 * Instead we check memory.stat and check the "swap" value.
119 static double ls_get_swap(struct lxc_container
*c
);
120 static unsigned int ls_get_term_width(void);
121 static char *ls_get_interface(struct lxc_container
*c
);
122 static bool ls_has_all_grps(const char *has
, char **must
, size_t must_len
);
123 static struct ls
*ls_new(struct ls
**ls
, size_t *size
);
126 * Print user-specified fancy format.
128 static void ls_print_fancy_format(struct ls
*l
, struct lengths
*lht
,
129 size_t size
, const char *fancy_fmt
);
132 * Only print names of containers.
134 static void ls_print_names(struct ls
*l
, struct lengths
*lht
,
135 size_t ls_arr
, size_t termwidth
, bool list
);
138 * Print default fancy format.
140 static void ls_print_table(struct ls
*l
, struct lengths
*lht
,
144 * id can only be 79 + \0 chars long.
146 static int ls_remove_lock(const char *path
, const char *name
,
147 char **lockpath
, size_t *len_lockpath
, bool recalc
);
148 static int ls_serialize(int wpipefd
, struct ls
*n
);
149 static int my_parser(struct lxc_arguments
*args
, int c
, char *arg
);
151 static const struct option my_longopts
[] = {
152 {"line", no_argument
, 0, '1'},
153 {"fancy", no_argument
, 0, 'f'},
154 {"fancy-format", required_argument
, 0, 'F'},
155 {"active", no_argument
, 0, LS_ACTIVE
},
156 {"running", no_argument
, 0, LS_RUNNING
},
157 {"frozen", no_argument
, 0, LS_FROZEN
},
158 {"stopped", no_argument
, 0, LS_STOPPED
},
159 {"defined", no_argument
, 0, LS_DEFINED
},
160 {"nesting", optional_argument
, 0, LS_NESTING
},
161 {"groups", required_argument
, 0, 'g'},
162 {"filter", required_argument
, 0, LS_FILTER
},
166 static struct lxc_arguments my_args
= {
167 .progname
= "lxc-ls",
169 [-P lxcpath] [--active] [--running] [--frozen] [--stopped] [--nesting] [-g groups] [--filter regex]\n\
170 [-1] [-P lxcpath] [--active] [--running] [--frozen] [--stopped] [--nesting] [-g groups] [--filter regex]\n\
171 [-f] [-P lxcpath] [--active] [--running] [--frozen] [--stopped] [--nesting] [-g groups] [--filter regex]\n\
173 lxc-ls list containers\n\
176 -1, --line show one entry per line\n\
177 -f, --fancy use a fancy, column-based output\n\
178 -F, --fancy-format comma separated list of columns to show in the fancy output\n\
179 valid columns are: NAME, STATE, PID, RAM, SWAP, AUTOSTART,\n\
180 GROUPS, INTERFACE, IPV4 and IPV6, UNPRIVILEGED\n\
181 --active list only active containers\n\
182 --running list only running containers\n\
183 --frozen list only frozen containers\n\
184 --stopped list only stopped containers\n\
185 --defined list only defined containers\n\
186 --nesting=NUM list nested containers up to NUM (default is 5) levels of nesting\n\
187 --filter=REGEX filter container names by regular expression\n\
188 -g --groups comma separated list of groups a container must have to be displayed\n",
189 .options
= my_longopts
,
194 int main(int argc
, char *argv
[])
196 int ret
= EXIT_FAILURE
;
200 * The lxc parser requires that my_args.name is set. So let's satisfy
201 * that condition by setting a placeholder name which is never used.
204 if (lxc_arguments_parse(&my_args
, argc
, argv
))
207 /* Only create log if explicitly instructed */
208 if (my_args
.log_file
|| my_args
.log_priority
) {
210 log
.file
= my_args
.log_file
;
211 log
.level
= my_args
.log_priority
;
212 log
.prefix
= my_args
.progname
;
213 log
.quiet
= my_args
.quiet
;
214 log
.lxcpath
= my_args
.lxcpath
[0];
216 if (lxc_log_init(&log
))
220 struct lengths max_len
= {
221 /* default header length */
222 .name_length
= 4, /* NAME */
223 .state_length
= 5, /* STATE */
224 .groups_length
= 6, /* GROUPS */
225 .interface_length
= 9, /* INTERFACE */
226 .ipv4_length
= 4, /* IPV4 */
227 .ipv6_length
= 4, /* IPV6 */
228 .init_length
= 3, /* PID */
229 .ram_length
= 3, /* RAM */
230 .swap_length
= 4, /* SWAP */
231 .autostart_length
= 9, /* AUTOSTART */
232 .unprivileged_length
= 12, /* UNPRIVILEGED */
237 if (my_args
.groups
) {
238 grps
= lxc_string_split_and_trim(my_args
.groups
, ',');
239 ngrps
= lxc_array_len((void **)grps
);
242 struct ls
*ls_arr
= NULL
;
245 /* &(char *){NULL} is no magic. It's just a compound literal which
246 * avoids having a pointless variable in main() that serves no purpose
248 int status
= ls_get(&ls_arr
, &ls_size
, &my_args
, "", NULL
, 0, &(char *){NULL
}, 0, grps
, ngrps
);
249 if (!ls_arr
&& status
== 0)
250 /* We did not fail. There was just nothing to do. */
252 else if (!ls_arr
|| status
== -1)
255 ls_field_width(ls_arr
, ls_size
, &max_len
);
257 if (my_args
.ls_fancy
&& !my_args
.ls_fancy_format
) {
258 ls_print_table(ls_arr
, &max_len
, ls_size
);
259 } else if (my_args
.ls_fancy
&& my_args
.ls_fancy_format
) {
260 ls_print_fancy_format(ls_arr
, &max_len
, ls_size
, my_args
.ls_fancy_format
);
262 unsigned int cols
= 0;
263 if (!my_args
.ls_line
)
264 cols
= ls_get_term_width();
265 ls_print_names(ls_arr
, &max_len
, ls_size
, cols
, my_args
.ls_line
);
271 ls_free(ls_arr
, ls_size
);
272 lxc_free_array((void **)grps
, free
);
277 static void ls_free(struct ls
*l
, size_t size
)
282 for (i
= 0, m
= l
; i
< size
; i
++, m
++) {
293 static char *ls_get_config_item(struct lxc_container
*c
, const char *item
, bool running
)
295 __do_free
char *val
= NULL
;
299 return c
->get_running_config_item(c
, item
);
301 len
= c
->get_config_item(c
, item
, NULL
, 0);
305 val
= malloc((len
+ 1) * sizeof(*val
));
309 if (c
->get_config_item(c
, item
, val
, len
+ 1) != len
)
312 return move_ptr(val
);
315 static void ls_free_arr(char **arr
, size_t size
)
319 for (i
= 0; i
< size
; i
++)
325 static int ls_get(struct ls
**m
, size_t *size
, const struct lxc_arguments
*args
,
326 const char *basepath
, const char *parent
, unsigned int lvl
, char **lockpath
,
327 size_t len_lockpath
, char **grps_must
, size_t grps_must_len
)
329 /* As ls_get() is non-tail recursive we face the inherent danger of
330 * blowing up the stack at some level of nesting. To have at least some
331 * security we define MAX_NESTLVL to be 5. That should be sufficient for
332 * most users. The argument lvl can be used to keep track of the level
333 * of nesting we are at. If lvl is greater than the allowed default
334 * level or the level the user specified on the command line we return
335 * and unwind the stack. */
336 if (lvl
> args
->ls_nesting
)
339 int num
= 0, ret
= -1;
340 char **containers
= NULL
;
341 /* If we, at some level of nesting, encounter a stopped container but
342 * want to retrieve nested containers we need to build an absolute path
343 * beginning from it. Initially, at nesting level 0, basepath will
344 * simply be the empty string and path will simply be whatever the
345 * default lxcpath or the path the user gave us is. Basepath will also
346 * be the empty string in case we encounter a running container since we
347 * can simply attach to its namespace to retrieve nested containers. */
348 char *path
= lxc_append_paths(basepath
, args
->lxcpath
[0]);
352 if (!dir_exists(path
)) {
357 /* Do not do more work than is necessary right from the start. */
358 if (args
->ls_active
|| args
->ls_frozen
)
359 num
= list_active_containers(path
, &containers
, NULL
);
361 num
= list_all_containers(path
, &containers
, NULL
);
370 struct lxc_container
*c
= NULL
;
373 for (i
= 0; i
< (size_t)num
; i
++) {
374 char *name
= containers
[i
];
376 /* Filter container names by regex the user gave us. */
377 if (args
->ls_filter
|| args
->argc
== 1) {
380 tmp
= args
->ls_filter
? args
->ls_filter
: args
->argv
[0];
381 check
= regcomp(&preg
, tmp
, REG_NOSUB
| REG_EXTENDED
);
382 if (check
== REG_ESPACE
) /* we're out of memory */
387 check
= regexec(&preg
, name
, 0, NULL
, 0);
394 c
= lxc_container_new(name
, path
);
395 if ((errno
== ENOMEM
) && !c
)
400 if (args
->ls_defined
&& !c
->is_defined(c
))
403 /* This does not allocate memory so no worries about freeing it
404 * when we goto next or out. */
405 const char *state_tmp
= c
->state(c
);
407 state_tmp
= "UNKNOWN";
409 if (args
->ls_running
&& !c
->is_running(c
))
412 if (args
->ls_frozen
&& !args
->ls_active
&& strcmp(state_tmp
, "FROZEN"))
415 if (args
->ls_stopped
&& strcmp(state_tmp
, "STOPPED"))
418 bool running
= c
->is_running(c
);
420 char *grp_tmp
= ls_get_groups(c
, running
);
421 if (!ls_has_all_grps(grp_tmp
, grps_must
, grps_must_len
)) {
426 /* Now it makes sense to allocate memory. */
433 /* How deeply nested are we? */
438 l
->running
= running
;
440 if (parent
&& args
->ls_nesting
&& (args
->ls_line
|| !args
->ls_fancy
))
441 /* Prepend the name of the container with all its parents when
442 * the user requests it. */
443 l
->name
= lxc_append_paths(parent
, name
);
445 /* Otherwise simply record the name. */
446 l
->name
= strdup(name
);
450 /* Do not record stuff the user did not explicitly request. */
451 if (args
->ls_fancy
) {
452 /* Maybe we should even consider the name sensitive and
453 * hide it when you're not allowed to control the
455 if (!c
->may_control(c
))
458 l
->state
= strdup(state_tmp
);
462 tmp
= ls_get_config_item(c
, "lxc.start.auto", running
);
464 unsigned int astart
= 0;
465 if (lxc_safe_uint(tmp
, &astart
) < 0)
466 printf("Could not parse value for 'lxc.start.auto'.\n");
468 printf("Wrong value for 'lxc.start.auto = %d'.\n", astart
);
469 l
->autostart
= astart
== 1 ? true : false;
476 l
->init
= c
->init_pid(c
);
480 l
->interface
= ls_get_interface(c
);
482 l
->ipv4
= ls_get_ips(c
, "inet");
484 l
->ipv6
= ls_get_ips(c
, "inet6");
486 tmp
= ls_get_cgroup_item(c
, "memory.usage_in_bytes");
488 l
->ram
= strtoull(tmp
, NULL
, 0);
489 l
->ram
= l
->ram
/ 1024 /1024;
493 l
->swap
= ls_get_swap(c
);
495 val
= c
->get_running_config_item(c
, "lxc.idmap");
496 l
->unprivileged
= !(val
== NULL
);
499 ret
= c
->get_config_item(c
, "lxc.idmap", NULL
, 0);
500 l
->unprivileged
= !(ret
== 0);
504 /* Get nested containers: Only do this after we have gathered
505 * all other information we need. */
506 if (args
->ls_nesting
&& running
) {
507 struct wrapargs wargs
= (struct wrapargs
){.args
= NULL
};
509 /* Open a socket so that the child can communicate with us. */
510 check
= socketpair(AF_UNIX
, SOCK_STREAM
| SOCK_CLOEXEC
, 0, wargs
.pipefd
);
514 /* Set the next nesting level. */
515 wargs
.nestlvl
= lvl
+ 1;
516 /* Send in the parent for the next nesting level. */
517 wargs
.parent
= l
->name
;
519 wargs
.grps_must
= grps_must
;
520 wargs
.grps_must_len
= grps_must_len
;
524 lxc_attach_options_t aopt
= LXC_ATTACH_OPTIONS_DEFAULT
;
525 aopt
.env_policy
= LXC_ATTACH_CLEAR_ENV
;
527 /* fork(): Attach to the namespace of the container and
528 * run ls_get() in it which is called in ls_get_wrapper(). */
529 check
= c
->attach(c
, ls_get_wrapper
, &wargs
, &aopt
, &out
);
530 /* close the socket */
531 close(wargs
.pipefd
[1]);
533 /* Retrieve all information we want from the child. */
535 if (ls_deserialize(wargs
.pipefd
[0], m
, size
) == -1)
538 /* Wait for the child to finish. */
541 /* We've done all the communication we need so shutdown
542 * the socket and close it. */
543 shutdown(wargs
.pipefd
[0], SHUT_RDWR
);
544 close(wargs
.pipefd
[0]);
545 } else if (args
->ls_nesting
&& !running
) {
546 /* This way of extracting the rootfs is not safe since
547 * it will return very different things depending on the
548 * storage backend that is used for the container. We
549 * need a path-extractor function. We face the same
550 * problem with the ovl_mkdir() function in
551 * lxcoverlay.{c,h}. */
552 char *curr_path
= ls_get_config_item(c
, "lxc.rootfs.path", running
);
556 /* Since the container is not running and we cannot
557 * attach to it we need another strategy to retrieve
558 * nested containers. What we do is simply create a
559 * growing path which will lead us into the rootfs of
560 * the next container where it stores its containers. */
561 char *newpath
= lxc_append_paths(basepath
, curr_path
);
566 /* We want to remove all locks we create under
567 * /run/lxc/lock so we create a string pointing us to
568 * the lock path for the current container. */
569 if (ls_remove_lock(path
, name
, lockpath
, &len_lockpath
, true) == -1) {
574 ls_get(m
, size
, args
, newpath
, l
->name
, lvl
+ 1, lockpath
, len_lockpath
, grps_must
, grps_must_len
);
577 /* Remove the lock. No need to check for failure here. */
578 ls_remove_lock(path
, name
, lockpath
, &len_lockpath
, false);
582 lxc_container_put(c
);
587 ls_free_arr(containers
, num
);
590 /* lockpath is shared amongst all non-fork()ing recursive calls to
591 * ls_get() so only free it on the uppermost level. */
598 static char *ls_get_cgroup_item(struct lxc_container
*c
, const char *item
)
600 __do_free
char *val
= NULL
;
602 int len
= c
->get_cgroup_item(c
, item
, NULL
, 0);
606 val
= malloc((len
+ 1) * sizeof(*val
));
610 if (c
->get_cgroup_item(c
, item
, val
, len
+ 1) != len
)
613 return move_ptr(val
);
616 static char *ls_get_groups(struct lxc_container
*c
, bool running
)
619 __do_free
char *val
= NULL
;
622 val
= c
->get_running_config_item(c
, "lxc.group");
624 len
= c
->get_config_item(c
, "lxc.group", NULL
, 0);
626 if (!val
&& (len
> 0 && len
< INT_MAX
)) {
627 val
= malloc((len
+ 1) * sizeof(*val
));
631 if (c
->get_config_item(c
, "lxc.group", val
, len
+ 1) != len
)
638 if ((tmp
= strrchr(val
, '\n')))
641 tmp
= lxc_string_replace("\n", ", ", val
);
646 return move_ptr(val
);
649 static char *ls_get_ips(struct lxc_container
*c
, const char *inet
)
654 iptmp
= c
->get_ips(c
, NULL
, inet
, 0);
656 ips
= lxc_string_join(", ", (const char **)iptmp
, false);
658 lxc_free_array((void **)iptmp
, free
);
663 static char *ls_get_interface(struct lxc_container
*c
)
665 char **interfaces
= c
->get_interfaces(c
);
669 char *interface
= lxc_string_join(", ", (const char **)interfaces
, false);
671 lxc_free_array((void **)interfaces
, free
);
677 * To calculate swap usage we should not simply check memory.usage_in_bytes and
678 * memory.memsw.usage_in_bytes and then do:
679 * swap = memory.memsw.usage_in_bytes - memory.usage_in_bytes;
680 * because we might receive an incorrect/negative value.
681 * Instead we check memory.stat and check the "swap" value.
683 static double ls_get_swap(struct lxc_container
*c
)
685 __do_free
char *stat
= NULL
;
687 unsigned long long int num
= 0;
689 stat
= ls_get_cgroup_item(c
, "memory.stat");
693 swap
= strstr(stat
, "\nswap");
697 /* start_of_swap_value = '\n' + strlen(swap) + ' ' */
698 swap
= 1 + swap
+ 4 + 1;
700 /* find end of swap value */
701 tmp
= strchr(swap
, '\n');
707 num
= strtoull(swap
, NULL
, 0);
708 num
= num
/ 1024 / 1024;
713 static unsigned int ls_get_term_width(void)
717 if (((ioctl(STDOUT_FILENO
, TIOCGWINSZ
, &ws
) == -1) &&
718 (ioctl(STDERR_FILENO
, TIOCGWINSZ
, &ws
) == -1) &&
719 (ioctl(STDIN_FILENO
, TIOCGWINSZ
, &ws
) == -1)) ||
726 static bool ls_has_all_grps(const char *has
, char **must
, size_t must_len
)
735 char **tmp_has
= lxc_string_split_and_trim(has
, ',');
736 size_t tmp_has_len
= lxc_array_len((void **)tmp_has
);
738 /* Don't do any unnecessary work. */
739 if (must_len
> tmp_has_len
)
743 for (i
= 0; i
< must_len
; i
++) {
744 for (j
= 0; j
< tmp_has_len
; j
++)
745 if (strcmp(must
[i
], tmp_has
[j
]) == 0)
747 if (j
== tmp_has_len
)
755 lxc_free_array((void **)tmp_has
, free
);
760 static struct ls
*ls_new(struct ls
**ls
, size_t *size
)
764 n
= realloc(*ls
, (*size
+ 1) * sizeof(struct ls
));
772 *m
= (struct ls
){.name
= NULL
, .init
= -1};
777 static void ls_print_names(struct ls
*l
, struct lengths
*lht
, size_t size
, size_t termwidth
, bool list
)
779 /* If list is empty do nothing. */
786 for (i
= 0, m
= l
; i
< size
; i
++, m
++) {
788 printf("%s\n", m
->name
? m
->name
: "-");
790 printf("%-*s", lht
->name_length
, m
->name
? m
->name
: "-");
792 len
+= lht
->name_length
;
793 if ((len
+ lht
->name_length
) >= termwidth
) {
807 static void ls_print_fancy_format(struct ls
*l
, struct lengths
*lht
, size_t size
,
808 const char *fancy_fmt
)
810 /* If list is empty do nothing. */
814 char **tmp
= lxc_string_split_and_trim(fancy_fmt
, ',');
819 /* Check for invalid keys. */
820 for (s
= tmp
; s
&& *s
; s
++) {
821 if (strcasecmp(*s
, "NAME") && strcasecmp(*s
, "STATE") &&
822 strcasecmp(*s
, "PID") && strcasecmp(*s
, "RAM") &&
823 strcasecmp(*s
, "SWAP") && strcasecmp(*s
, "AUTOSTART") &&
824 strcasecmp(*s
, "GROUPS") && strcasecmp(*s
, "INTERFACE") &&
825 strcasecmp(*s
, "IPV4") && strcasecmp(*s
, "IPV6") &&
826 strcasecmp(*s
, "UNPRIVILEGED")) {
827 fprintf(stderr
, "Invalid key: %s\n", *s
);
828 lxc_free_array((void **)tmp
, free
);
834 for (s
= tmp
; s
&& *s
; s
++) {
835 if (strcasecmp(*s
, "NAME") == 0)
836 printf("%-*s ", lht
->name_length
, "NAME");
837 else if (strcasecmp(*s
, "STATE") == 0)
838 printf("%-*s ", lht
->state_length
, "STATE");
839 else if (strcasecmp(*s
, "PID") == 0)
840 printf("%-*s ", lht
->init_length
, "PID");
841 else if (strcasecmp(*s
, "RAM") == 0)
842 printf("%-*s ", lht
->ram_length
+ 2, "RAM");
843 else if (strcasecmp(*s
, "SWAP") == 0)
844 printf("%-*s ", lht
->swap_length
+ 2, "SWAP");
845 else if (strcasecmp(*s
, "AUTOSTART") == 0)
846 printf("%-*s ", lht
->autostart_length
, "AUTOSTART");
847 else if (strcasecmp(*s
, "GROUPS") == 0)
848 printf("%-*s ", lht
->groups_length
, "GROUPS");
849 else if (strcasecmp(*s
, "INTERFACE") == 0)
850 printf("%-*s ", lht
->interface_length
, "INTERFACE");
851 else if (strcasecmp(*s
, "IPV4") == 0)
852 printf("%-*s ", lht
->ipv4_length
, "IPV4");
853 else if (strcasecmp(*s
, "IPV6") == 0)
854 printf("%-*s ", lht
->ipv6_length
, "IPV6");
855 else if (strcasecmp(*s
, "UNPRIVILEGED") == 0)
856 printf("%-*s ", lht
->unprivileged_length
, "UNPRIVILEGED");
863 for (i
= 0, m
= l
; i
< size
; i
++, m
++) {
864 for (s
= tmp
; s
&& *s
; s
++) {
865 if (strcasecmp(*s
, "NAME") == 0) {
866 if (m
->nestlvl
> 0) {
867 printf("%*s", m
->nestlvl
, "\\");
868 printf("%-*s ", lht
->name_length
- m
->nestlvl
, m
->name
? m
->name
: "-");
870 printf("%-*s ", lht
->name_length
, m
->name
? m
->name
: "-");
872 } else if (strcasecmp(*s
, "STATE") == 0) {
873 printf("%-*s ", lht
->state_length
, m
->state
? m
->state
: "-");
874 } else if (strcasecmp(*s
, "PID") == 0) {
876 printf("%-*d ", lht
->init_length
, m
->init
);
878 printf("%-*s ", lht
->init_length
, "-");
879 } else if (strcasecmp(*s
, "RAM") == 0) {
880 if ((m
->ram
>= 0) && m
->running
)
881 printf("%*.2fMB ", lht
->ram_length
, m
->ram
);
883 printf("%-*s ", lht
->ram_length
, "-");
884 } else if (strcasecmp(*s
, "SWAP") == 0) {
885 if ((m
->swap
>= 0) && m
->running
)
886 printf("%*.2fMB ", lht
->swap_length
, m
->swap
);
888 printf("%-*s ", lht
->swap_length
, "-");
889 } else if (strcasecmp(*s
, "AUTOSTART") == 0) {
890 printf("%-*d ", lht
->autostart_length
, m
->autostart
);
891 } else if (strcasecmp(*s
, "GROUPS") == 0) {
892 printf("%-*s ", lht
->groups_length
, m
->groups
? m
->groups
: "-");
893 } else if (strcasecmp(*s
, "INTERFACE") == 0) {
894 printf("%-*s ", lht
->interface_length
, m
->interface
? m
->interface
: "-");
895 } else if (strcasecmp(*s
, "IPV4") == 0) {
896 printf("%-*s ", lht
->ipv4_length
, m
->ipv4
? m
->ipv4
: "-");
897 } else if (strcasecmp(*s
, "IPV6") == 0) {
898 printf("%-*s ", lht
->ipv6_length
, m
->ipv6
? m
->ipv6
: "-");
899 } else if (strcasecmp(*s
, "UNPRIVILEGED") == 0) {
900 printf("%-*s ", lht
->unprivileged_length
, m
->unprivileged
? "true" : "false");
906 lxc_free_array((void **)tmp
, free
);
909 static void ls_print_table(struct ls
*l
, struct lengths
*lht
, size_t size
)
913 /* If list is empty do nothing. */
920 printf("%-*s ", lht
->name_length
, "NAME");
921 printf("%-*s ", lht
->state_length
, "STATE");
922 printf("%-*s ", lht
->autostart_length
, "AUTOSTART");
923 printf("%-*s ", lht
->groups_length
, "GROUPS");
924 printf("%-*s ", lht
->ipv4_length
, "IPV4");
925 printf("%-*s ", lht
->ipv6_length
, "IPV6");
926 printf("%-*s ", lht
->unprivileged_length
, "UNPRIVILEGED");
929 for (i
= 0, m
= l
; i
< size
; i
++, m
++) {
930 if (m
->nestlvl
> 0) {
931 printf("%*s", m
->nestlvl
, "\\");
932 printf("%-*s ", lht
->name_length
- m
->nestlvl
, m
->name
? m
->name
: "-");
934 printf("%-*s ", lht
->name_length
, m
->name
? m
->name
: "-");
937 printf("%-*s ", lht
->state_length
, m
->state
? m
->state
: "-");
938 printf("%-*d ", lht
->autostart_length
, m
->autostart
);
939 printf("%-*s ", lht
->groups_length
, m
->groups
? m
->groups
: "-");
940 printf("%-*s ", lht
->ipv4_length
, m
->ipv4
? m
->ipv4
: "-");
941 printf("%-*s ", lht
->ipv6_length
, m
->ipv6
? m
->ipv6
: "-");
942 printf("%-*s ", lht
->unprivileged_length
, m
->unprivileged
? "true" : "false");
947 static int my_parser(struct lxc_arguments
*args
, int c
, char *arg
)
950 unsigned long int m
, n
= MAX_NESTLVL
;
954 args
->ls_line
= true;
957 args
->ls_fancy
= true;
960 args
->ls_active
= true;
963 args
->ls_frozen
= true;
966 args
->ls_running
= true;
969 args
->ls_stopped
= true;
972 args
->ls_defined
= true;
975 /* In case strtoul() receives a string that represents a
976 * negative number it will return ULONG_MAX - the number that
977 * the string represents if the number the string represents is
978 * < ULONG_MAX and ULONG_MAX otherwise. But it will consider
979 * this valid input and not set errno. So we check manually if
980 * the first character of num_string == '-'. Otherwise the
981 * default level remains set. */
982 if (arg
&& !(*arg
== '-')) {
984 m
= strtoul(arg
, &invalid
, 0);
985 /* ls_nesting has type unsigned int. */
986 if (!errno
&& (*invalid
== '\0') && (m
<= UINT_MAX
))
989 args
->ls_nesting
= n
;
995 args
->ls_filter
= arg
;
998 args
->ls_fancy_format
= arg
;
1005 static int ls_get_wrapper(void *wrap
)
1009 struct wrapargs
*wargs
= (struct wrapargs
*)wrap
;
1010 struct ls
*m
= NULL
, *n
= NULL
;
1014 close(wargs
->pipefd
[0]);
1016 /* &(char *){NULL} is no magic. It's just a compound literal which
1017 * allows us to avoid keeping a pointless variable around. */
1018 ls_get(&m
, &len
, wargs
->args
, "", wargs
->parent
, wargs
->nestlvl
, &(char *){NULL
}, 0, wargs
->grps_must
, wargs
->grps_must_len
);
1023 if (lxc_write_nointr(wargs
->pipefd
[1], &len
, sizeof(len
)) <= 0)
1026 for (i
= 0, n
= m
; i
< len
; i
++, n
++) {
1027 if (ls_serialize(wargs
->pipefd
[1], n
) == -1)
1033 shutdown(wargs
->pipefd
[1], SHUT_RDWR
);
1034 close(wargs
->pipefd
[1]);
1040 static int ls_remove_lock(const char *path
, const char *name
, char **lockpath
, size_t *len_lockpath
,
1046 /* lockfile will be:
1047 * "/run" + "/lxc/lock/$lxcpath/$lxcname + '\0' if root
1049 * $XDG_RUNTIME_DIR + "/lxc/lock/$lxcpath/$lxcname + '\0' if non-root
1051 rundir
= get_rundir();
1055 /* Avoid doing unnecessary work if we can. */
1057 size_t newlen
= strlen(path
) + strlen(name
) + strlen(rundir
) + /* / + lxc + / + lock + / + / = */ 11 + 1;
1058 if (newlen
> *len_lockpath
) {
1059 char *tmp
= realloc(*lockpath
, newlen
* 2);
1063 *len_lockpath
= newlen
* 2;
1067 int check
= snprintf(*lockpath
, *len_lockpath
, "%s/lxc/lock/%s/%s", rundir
, path
, name
);
1068 if (check
< 0 || (size_t)check
>= *len_lockpath
)
1071 ret
= lxc_rm_rf(*lockpath
);
1073 WARN("Failed to destroy \"%s\"", *lockpath
);
1082 static int ls_send_str(int fd
, const char *buf
)
1089 if (lxc_write_nointr(fd
, &slen
, sizeof(slen
)) != sizeof(slen
))
1092 if (slen
> 0 && slen
< SIZE_MAX
) {
1093 if (lxc_write_nointr(fd
, buf
, slen
) != (ssize_t
)slen
)
1100 static int ls_serialize(int wpipefd
, struct ls
*n
)
1102 ssize_t nbytes
= sizeof(n
->ram
);
1103 if (lxc_write_nointr(wpipefd
, &n
->ram
, (size_t)nbytes
) != nbytes
)
1106 nbytes
= sizeof(n
->swap
);
1107 if (lxc_write_nointr(wpipefd
, &n
->swap
, (size_t)nbytes
) != nbytes
)
1110 nbytes
= sizeof(n
->init
);
1111 if (lxc_write_nointr(wpipefd
, &n
->init
, (size_t)nbytes
) != nbytes
)
1114 nbytes
= sizeof(n
->autostart
);
1115 if (lxc_write_nointr(wpipefd
, &n
->autostart
, (size_t)nbytes
) != nbytes
)
1118 nbytes
= sizeof(n
->running
);
1119 if (lxc_write_nointr(wpipefd
, &n
->running
, (size_t)nbytes
) != nbytes
)
1122 nbytes
= sizeof(n
->unprivileged
);
1123 if (lxc_write_nointr(wpipefd
, &n
->unprivileged
, (size_t)nbytes
) != nbytes
)
1126 nbytes
= sizeof(n
->nestlvl
);
1127 if (lxc_write_nointr(wpipefd
, &n
->nestlvl
, (size_t)nbytes
) != nbytes
)
1131 if (ls_send_str(wpipefd
, n
->name
) < 0)
1135 if (ls_send_str(wpipefd
, n
->state
) < 0)
1139 if (ls_send_str(wpipefd
, n
->groups
) < 0)
1143 if (ls_send_str(wpipefd
, n
->interface
) < 0)
1147 if (ls_send_str(wpipefd
, n
->ipv4
) < 0)
1151 if (ls_send_str(wpipefd
, n
->ipv6
) < 0)
1157 static int ls_recv_str(int fd
, char **buf
)
1162 ret
= lxc_read_nointr(fd
, &slen
, sizeof(slen
));
1163 if (ret
!= sizeof(slen
))
1167 if (slen
> 0 && slen
< SIZE_MAX
) {
1168 __do_free
char *s
= NULL
;
1170 s
= malloc(sizeof(char) * (slen
+ 1));
1174 ret
= lxc_read_nointr(fd
, s
, slen
);
1175 if (ret
!= (ssize_t
)slen
)
1178 (*buf
)[slen
] = '\0';
1186 static int ls_deserialize(int rpipefd
, struct ls
**m
, size_t *len
)
1193 nbytes
= sizeof(sublen
);
1194 if (lxc_read_nointr(rpipefd
, &sublen
, (size_t)nbytes
) != nbytes
)
1197 while (sublen
-- > 0) {
1202 nbytes
= sizeof(n
->ram
);
1203 if (lxc_read_nointr(rpipefd
, &n
->ram
, (size_t)nbytes
) != nbytes
)
1206 nbytes
= sizeof(n
->swap
);
1207 if (lxc_read_nointr(rpipefd
, &n
->swap
, (size_t)nbytes
) != nbytes
)
1210 nbytes
= sizeof(n
->init
);
1211 if (lxc_read_nointr(rpipefd
, &n
->init
, (size_t)nbytes
) != nbytes
)
1214 nbytes
= sizeof(n
->autostart
);
1215 if (lxc_read_nointr(rpipefd
, &n
->autostart
, (size_t)nbytes
) != nbytes
)
1218 nbytes
= sizeof(n
->running
);
1219 if (lxc_read_nointr(rpipefd
, &n
->running
, (size_t)nbytes
) != nbytes
)
1222 nbytes
= sizeof(n
->unprivileged
);
1223 if (lxc_read_nointr(rpipefd
, &n
->unprivileged
, (size_t)nbytes
) != nbytes
)
1226 nbytes
= sizeof(n
->nestlvl
);
1227 if (lxc_read_nointr(rpipefd
, &n
->nestlvl
, (size_t)nbytes
) != nbytes
)
1231 if (ls_recv_str(rpipefd
, &n
->name
) < 0)
1235 if (ls_recv_str(rpipefd
, &n
->state
) < 0)
1239 if (ls_recv_str(rpipefd
, &n
->groups
) < 0)
1243 if (ls_recv_str(rpipefd
, &n
->interface
) < 0)
1247 if (ls_recv_str(rpipefd
, &n
->ipv4
) < 0)
1251 if (ls_recv_str(rpipefd
, &n
->ipv6
) < 0)
1258 static void ls_field_width(const struct ls
*l
, const size_t size
, struct lengths
*lht
)
1263 for (i
= 0, m
= l
; i
< size
; i
++, m
++) {
1265 len
= strlen(m
->name
) + m
->nestlvl
;
1266 if (len
> lht
->name_length
)
1267 lht
->name_length
= len
;
1271 len
= strlen(m
->state
);
1272 if (len
> lht
->state_length
)
1273 lht
->state_length
= len
;
1277 len
= strlen(m
->interface
);
1278 if (len
> lht
->interface_length
)
1279 lht
->interface_length
= len
;
1283 len
= strlen(m
->groups
);
1284 if (len
> lht
->groups_length
)
1285 lht
->groups_length
= len
;
1288 len
= strlen(m
->ipv4
);
1289 if (len
> lht
->ipv4_length
)
1290 lht
->ipv4_length
= len
;
1294 len
= strlen(m
->ipv6
);
1295 if (len
> lht
->ipv6_length
)
1296 lht
->ipv6_length
= len
;
1299 if ((len
= snprintf(NULL
, 0, "%.2f", m
->ram
)) > lht
->ram_length
)
1300 lht
->ram_length
= len
;
1302 if ((len
= snprintf(NULL
, 0, "%.2f", m
->swap
)) > lht
->swap_length
)
1303 lht
->swap_length
= len
;
1305 if (m
->init
!= -1) {
1306 if ((len
= snprintf(NULL
, 0, "%d", m
->init
)) > lht
->init_length
)
1307 lht
->init_length
= len
;