]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/state.c
commands_utils: fix lxc-wait
[mirror_lxc.git] / src / lxc / state.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #ifndef _GNU_SOURCE
4 #define _GNU_SOURCE 1
5 #endif
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/file.h>
12 #include <sys/param.h>
13 #include <sys/socket.h>
14 #include <sys/stat.h>
15 #include <sys/types.h>
16 #include <time.h>
17 #include <unistd.h>
18
19 #include "cgroup.h"
20 #include "commands.h"
21 #include "commands_utils.h"
22 #include "config.h"
23 #include "log.h"
24 #include "lxc.h"
25 #include "monitor.h"
26 #include "start.h"
27 #include "utils.h"
28
29 lxc_log_define(state, lxc);
30
31 static const char *const strstate[] = {
32 "STOPPED", "STARTING", "RUNNING", "STOPPING",
33 "ABORTING", "FREEZING", "FROZEN", "THAWED",
34 };
35
36 const char *lxc_state2str(lxc_state_t state)
37 {
38 if (state < STOPPED || state > MAX_STATE - 1)
39 return NULL;
40 return strstate[state];
41 }
42
43 lxc_state_t lxc_str2state(const char *state)
44 {
45 size_t len;
46 lxc_state_t i;
47 len = sizeof(strstate)/sizeof(strstate[0]);
48 for (i = 0; i < len; i++)
49 if (!strcmp(strstate[i], state))
50 return i;
51
52 ERROR("invalid state '%s'", state);
53 return -1;
54 }
55
56 lxc_state_t lxc_getstate(const char *name, const char *lxcpath)
57 {
58 return lxc_cmd_get_state(name, lxcpath);
59 }
60
61 static int fillwaitedstates(const char *strstates, lxc_state_t *states)
62 {
63 char *token;
64 char *strstates_dup;
65 int state;
66
67 strstates_dup = strdup(strstates);
68 if (!strstates_dup)
69 return -1;
70
71 lxc_iterate_parts(token, strstates_dup, "|") {
72 state = lxc_str2state(token);
73 if (state < 0) {
74 free(strstates_dup);
75 return -1;
76 }
77
78 states[state] = 1;
79 }
80 free(strstates_dup);
81 return 0;
82 }
83
84 int lxc_wait(const char *lxcname, const char *states, int timeout,
85 const char *lxcpath)
86 {
87 int state = -1;
88 lxc_state_t s[MAX_STATE] = {0};
89
90 if (fillwaitedstates(states, s))
91 return -1;
92
93 for (;;) {
94 struct timespec onesec = {
95 .tv_sec = 1,
96 .tv_nsec = 0,
97 };
98
99 state = lxc_cmd_sock_get_state(lxcname, lxcpath, s, timeout);
100 if (state >= 0)
101 break;
102
103 if (errno != ECONNREFUSED)
104 return log_error_errno(-1, errno, "Failed to receive state from monitor");
105
106 if (timeout > 0)
107 timeout--;
108
109 if (timeout == 0)
110 return -1;
111
112 (void)nanosleep(&onesec, NULL);
113 }
114
115 TRACE("Retrieved state of container %s", lxc_state2str(state));
116 if (!s[state])
117 return -1;
118
119 return 0;
120 }