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