]>
Commit | Line | Data |
---|---|---|
620eff3c | 1 | /* |
2 | * lxc: linux Container library | |
3 | * | |
4 | * (C) Copyright IBM Corp. 2007, 2008 | |
5 | * | |
6 | * Authors: | |
7 | * Daniel Lezcano <dlezcano at fr.ibm.com> | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
22 | */ | |
23 | #include <stdio.h> | |
24 | #include <string.h> | |
25 | #include <fcntl.h> | |
26 | #include <errno.h> | |
27 | #include <unistd.h> | |
28 | #include <sys/types.h> | |
29 | #include <sys/types.h> | |
30 | #include <sys/param.h> | |
31 | #include <sys/stat.h> | |
32 | #include <sys/file.h> | |
33 | ||
34 | #include <lxc.h> | |
c2cc9f0a | 35 | #include "monitor.h" |
620eff3c | 36 | |
37 | static char *strstate[] = { | |
38 | "STOPPED", "STARTING", "RUNNING", "STOPPING", | |
39 | "ABORTING", "FREEZING", "FROZEN", | |
40 | }; | |
41 | ||
c2cc9f0a | 42 | const char *lxc_state2str(lxc_state_t state) |
620eff3c | 43 | { |
44 | if (state < STOPPED || state > MAX_STATE - 1) | |
45 | return NULL; | |
46 | return strstate[state]; | |
47 | } | |
48 | ||
c2cc9f0a | 49 | lxc_state_t lxc_str2state(const char *state) |
620eff3c | 50 | { |
51 | int i, len; | |
52 | len = sizeof(strstate)/sizeof(strstate[0]); | |
53 | for (i = 0; i < len; i++) | |
54 | if (!strcmp(strstate[i], state)) | |
55 | return i; | |
56 | return -1; | |
57 | } | |
58 | ||
59 | int lxc_setstate(const char *name, lxc_state_t state) | |
60 | { | |
61 | int fd, err; | |
62 | char file[MAXPATHLEN]; | |
c2cc9f0a | 63 | const char *str = lxc_state2str(state); |
620eff3c | 64 | |
65 | if (!str) | |
66 | return -1; | |
67 | ||
68 | snprintf(file, MAXPATHLEN, LXCPATH "/%s/state", name); | |
69 | ||
70 | fd = open(file, O_WRONLY); | |
71 | if (fd < 0) { | |
72 | lxc_log_syserror("failed to open %s file", file); | |
73 | return -1; | |
74 | } | |
75 | ||
76 | if (flock(fd, LOCK_EX)) { | |
77 | lxc_log_syserror("failed to take the lock to %s", file); | |
78 | goto out; | |
79 | } | |
80 | ||
81 | if (ftruncate(fd, 0)) { | |
82 | lxc_log_syserror("failed to truncate the file %s", file); | |
83 | goto out; | |
84 | } | |
85 | ||
86 | if (write(fd, str, strlen(str)) < 0) { | |
87 | lxc_log_syserror("failed to write state to %s", file); | |
88 | goto out; | |
89 | } | |
90 | ||
91 | err = 0; | |
92 | out: | |
93 | close(fd); | |
94 | ||
c2cc9f0a | 95 | lxc_monitor_send_state(name, state); |
96 | ||
620eff3c | 97 | /* let the event to be propagated, crappy but that works, |
98 | * otherwise the events will be folded into only one event, | |
99 | * and I want to have them to be one by one in order | |
100 | * to follow the different states of the container. | |
101 | */ | |
102 | usleep(200000); | |
103 | ||
104 | return -err; | |
105 | } | |
106 | ||
c2cc9f0a | 107 | int lxc_mkstate(const char *name) |
620eff3c | 108 | { |
109 | int fd; | |
110 | char file[MAXPATHLEN]; | |
111 | ||
112 | snprintf(file, MAXPATHLEN, LXCPATH "/%s/state", name); | |
113 | fd = creat(file, S_IRUSR|S_IWUSR); | |
114 | if (fd < 0) { | |
115 | lxc_log_syserror("failed to create file %s", file); | |
116 | return -1; | |
117 | } | |
118 | close(fd); | |
119 | return 0; | |
120 | } | |
121 | ||
c2cc9f0a | 122 | int lxc_rmstate(const char *name) |
620eff3c | 123 | { |
124 | char file[MAXPATHLEN]; | |
125 | snprintf(file, MAXPATHLEN, LXCPATH "/%s/state", name); | |
126 | unlink(file); | |
127 | return 0; | |
128 | } | |
129 | ||
130 | lxc_state_t lxc_getstate(const char *name) | |
131 | { | |
132 | int fd, err; | |
133 | char file[MAXPATHLEN]; | |
134 | ||
135 | snprintf(file, MAXPATHLEN, LXCPATH "/%s/state", name); | |
136 | ||
137 | fd = open(file, O_RDONLY); | |
138 | if (fd < 0) { | |
139 | lxc_log_syserror("failed to open %s", file); | |
140 | return -1; | |
141 | } | |
142 | ||
143 | if (flock(fd, LOCK_SH)) { | |
144 | lxc_log_syserror("failed to take the lock to %s", file); | |
145 | close(fd); | |
146 | return -1; | |
147 | } | |
148 | ||
149 | err = read(fd, file, strlen(file)); | |
150 | if (err < 0) { | |
151 | lxc_log_syserror("failed to read file %s", file); | |
152 | close(fd); | |
153 | return -1; | |
154 | } | |
155 | file[err] = '\0'; | |
156 | ||
157 | close(fd); | |
c2cc9f0a | 158 | return lxc_str2state(file); |
620eff3c | 159 | } |
160 | ||
161 | static int freezer_state(const char *name) | |
162 | { | |
163 | char freezer[MAXPATHLEN]; | |
164 | char status[MAXPATHLEN]; | |
165 | FILE *file; | |
166 | int err; | |
167 | ||
168 | snprintf(freezer, MAXPATHLEN, | |
169 | LXCPATH "/%s/freezer.freeze", name); | |
170 | ||
171 | file = fopen(freezer, "r"); | |
c2cc9f0a | 172 | if (!file) { |
620eff3c | 173 | lxc_log_syserror("failed to open %s", freezer); |
174 | return -1; | |
175 | } | |
176 | ||
177 | err = fscanf(file, "%s", status); | |
178 | fclose(file); | |
179 | ||
180 | if (err == EOF) { | |
181 | lxc_log_syserror("failed to read %s", freezer); | |
182 | return -1; | |
183 | } | |
184 | ||
c2cc9f0a | 185 | return lxc_str2state(status); |
620eff3c | 186 | } |
187 | ||
188 | lxc_state_t lxc_state(const char *name) | |
189 | { | |
190 | int state = freezer_state(name); | |
191 | if (state != FROZEN && state != FREEZING) | |
192 | state = lxc_getstate(name); | |
193 | return state; | |
194 | } |