]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/tools/lxc_destroy.c
1 /* SPDX-License-Identifier: GPL-2.0-only */
10 #include <sys/types.h>
15 #include "arguments.h"
17 #include "file_utils.h"
19 lxc_log_define(lxc_destroy
, lxc
);
21 static int my_parser(struct lxc_arguments
*args
, int c
, char *arg
);
22 static bool do_destroy(struct lxc_container
*c
);
23 static bool do_destroy_with_snapshots(struct lxc_container
*c
);
25 static const struct option my_longopts
[] = {
26 {"force", no_argument
, 0, 'f'},
27 {"snapshots", no_argument
, 0, 's'},
31 static struct lxc_arguments my_args
= {
32 .progname
= "lxc-destroy",
34 --name=NAME [-f] [-P lxcpath]\n\
36 lxc-destroy destroys a container with the identifier NAME\n\
39 -n, --name=NAME NAME of the container\n\
40 -s, --snapshots destroy including all snapshots\n\
41 -f, --force wait for the container to shut down\n\
42 --rcfile=FILE Load configuration file FILE\n",
43 .options
= my_longopts
,
46 .log_priority
= "ERROR",
51 static int my_parser(struct lxc_arguments
*args
, int c
, char *arg
)
64 static bool do_destroy(struct lxc_container
*c
)
70 /* First check whether the container has dependent clones or snapshots. */
71 ret
= snprintf(path
, PATH_MAX
, "%s/%s/lxc_snapshots", c
->config_path
, c
->name
);
72 if (ret
< 0 || ret
>= PATH_MAX
)
75 if (file_exists(path
)) {
76 ERROR("Destroying %s failed: %s has clones", c
->name
, c
->name
);
80 ret
= snprintf(path
, PATH_MAX
, "%s/%s/snaps", c
->config_path
, c
->name
);
81 if (ret
< 0 || ret
>= PATH_MAX
)
84 if (rmdir(path
) < 0 && errno
!= ENOENT
) {
85 ERROR("Destroying %s failed: %s has snapshots", c
->name
, c
->name
);
89 if (c
->is_running(c
)) {
91 ERROR("%s is running", my_args
.name
);
95 /* If the container was ephemeral it will be removed on shutdown. */
99 /* If the container was ephemeral we have already removed it when we
101 if (c
->is_defined(c
)) {
104 ret
= c
->get_config_item(c
, "lxc.ephemeral", buf
, 256);
105 if (ret
> 0 && strcmp(buf
, "0") == 0)
106 bret
= c
->destroy(c
);
110 ERROR("Destroying %s failed", my_args
.name
);
117 static bool do_destroy_with_snapshots(struct lxc_container
*c
)
119 struct lxc_container
*c1
;
124 char *lxcpath
= NULL
;
125 char *lxcname
= NULL
;
130 /* Destroy clones. */
131 ret
= snprintf(path
, PATH_MAX
, "%s/%s/lxc_snapshots", c
->config_path
, c
->name
);
132 if (ret
< 0 || ret
>= PATH_MAX
)
135 fd
= open(path
, O_RDONLY
| O_CLOEXEC
);
137 ret
= fstat(fd
, &fbuf
);
143 /* Make sure that the string is \0 terminated. */
144 buf
= calloc(fbuf
.st_size
+ 1, sizeof(char));
146 ERROR("Failed to allocate memory");
151 bytes
= lxc_read_nointr(fd
, buf
, fbuf
.st_size
);
153 if (bytes
!= (ssize_t
)fbuf
.st_size
) {
154 ERROR("Could not read %s", path
);
159 lxc_iterate_parts(lxcpath
, buf
, "\n") {
160 c1
= lxc_container_new(lxcname
, lxcpath
);
164 /* We do not destroy recursively. If a clone of a clone
165 * has clones or snapshots the user should remove it
167 if (!do_destroy(c1
)) {
168 lxc_container_put(c1
);
173 lxc_container_put(c1
);
178 /* Destroy snapshots located in the containers snap/ folder. */
179 ret
= snprintf(path
, PATH_MAX
, "%s/%s/snaps", c
->config_path
, c
->name
);
180 if (ret
< 0 || ret
>= PATH_MAX
)
183 if (rmdir(path
) < 0 && errno
!= ENOENT
)
184 bret
= c
->destroy_with_snapshots(c
);
186 bret
= do_destroy(c
);
191 int main(int argc
, char *argv
[])
193 struct lxc_container
*c
;
197 if (lxc_arguments_parse(&my_args
, argc
, argv
))
200 log
.name
= my_args
.name
;
201 log
.file
= my_args
.log_file
;
202 log
.level
= my_args
.log_priority
;
203 log
.prefix
= my_args
.progname
;
204 log
.quiet
= my_args
.quiet
;
205 log
.lxcpath
= my_args
.lxcpath
[0];
207 if (lxc_log_init(&log
))
210 c
= lxc_container_new(my_args
.name
, my_args
.lxcpath
[0]);
212 ERROR("System error loading container");
216 if (my_args
.rcfile
) {
219 if (!c
->load_config(c
, my_args
.rcfile
)) {
220 ERROR("Failed to load rcfile");
221 lxc_container_put(c
);
225 c
->configfile
= strdup(my_args
.rcfile
);
226 if (!c
->configfile
) {
227 ERROR("Out of memory setting new config filename");
228 lxc_container_put(c
);
233 if (!c
->may_control(c
)) {
234 ERROR("Insufficent privileges to control %s", my_args
.name
);
235 lxc_container_put(c
);
239 if (!c
->is_defined(c
)) {
240 ERROR("Container is not defined");
241 lxc_container_put(c
);
245 if (my_args
.task
== SNAP
) {
246 bret
= do_destroy_with_snapshots(c
);
248 INFO("Destroyed container %s including snapshots", my_args
.name
);
250 bret
= do_destroy(c
);
252 INFO("Destroyed container %s", my_args
.name
);
255 lxc_container_put(c
);