]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/nspawn/nspawn-settings.c
nspawn: add new --chdir= switch
[thirdparty/systemd.git] / src / nspawn / nspawn-settings.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2015 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include "alloc-util.h"
23 #include "cap-list.h"
24 #include "conf-parser.h"
25 #include "nspawn-network.h"
26 #include "nspawn-settings.h"
27 #include "process-util.h"
28 #include "strv.h"
29 #include "util.h"
30
31 int settings_load(FILE *f, const char *path, Settings **ret) {
32 _cleanup_(settings_freep) Settings *s = NULL;
33 int r;
34
35 assert(path);
36 assert(ret);
37
38 s = new0(Settings, 1);
39 if (!s)
40 return -ENOMEM;
41
42 s->boot = -1;
43 s->personality = PERSONALITY_INVALID;
44
45 s->read_only = -1;
46 s->volatile_mode = _VOLATILE_MODE_INVALID;
47
48 s->private_network = -1;
49 s->network_veth = -1;
50
51 r = config_parse(NULL, path, f,
52 "Exec\0"
53 "Network\0"
54 "Files\0",
55 config_item_perf_lookup, nspawn_gperf_lookup,
56 false,
57 false,
58 true,
59 s);
60 if (r < 0)
61 return r;
62
63 *ret = s;
64 s = NULL;
65
66 return 0;
67 }
68
69 Settings* settings_free(Settings *s) {
70
71 if (!s)
72 return NULL;
73
74 strv_free(s->parameters);
75 strv_free(s->environment);
76 free(s->user);
77 free(s->working_directory);
78
79 strv_free(s->network_interfaces);
80 strv_free(s->network_macvlan);
81 strv_free(s->network_ipvlan);
82 strv_free(s->network_veth_extra);
83 free(s->network_bridge);
84 expose_port_free_all(s->expose_ports);
85
86 custom_mount_free_all(s->custom_mounts, s->n_custom_mounts);
87 free(s);
88
89 return NULL;
90 }
91
92 bool settings_private_network(Settings *s) {
93 assert(s);
94
95 return
96 s->private_network > 0 ||
97 s->network_veth > 0 ||
98 s->network_bridge ||
99 s->network_interfaces ||
100 s->network_macvlan ||
101 s->network_ipvlan ||
102 s->network_veth_extra;
103 }
104
105 bool settings_network_veth(Settings *s) {
106 assert(s);
107
108 return
109 s->network_veth > 0 ||
110 s->network_bridge;
111 }
112
113 DEFINE_CONFIG_PARSE_ENUM(config_parse_volatile_mode, volatile_mode, VolatileMode, "Failed to parse volatile mode");
114
115 int config_parse_expose_port(
116 const char *unit,
117 const char *filename,
118 unsigned line,
119 const char *section,
120 unsigned section_line,
121 const char *lvalue,
122 int ltype,
123 const char *rvalue,
124 void *data,
125 void *userdata) {
126
127 Settings *s = data;
128 int r;
129
130 assert(filename);
131 assert(lvalue);
132 assert(rvalue);
133
134 r = expose_port_parse(&s->expose_ports, rvalue);
135 if (r == -EEXIST) {
136 log_syntax(unit, LOG_ERR, filename, line, r, "Duplicate port specification, ignoring: %s", rvalue);
137 return 0;
138 }
139 if (r < 0) {
140 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse host port %s: %m", rvalue);
141 return 0;
142 }
143
144 return 0;
145 }
146
147 int config_parse_capability(
148 const char *unit,
149 const char *filename,
150 unsigned line,
151 const char *section,
152 unsigned section_line,
153 const char *lvalue,
154 int ltype,
155 const char *rvalue,
156 void *data,
157 void *userdata) {
158
159 uint64_t u = 0, *result = data;
160 int r;
161
162 assert(filename);
163 assert(lvalue);
164 assert(rvalue);
165
166 for (;;) {
167 _cleanup_free_ char *word = NULL;
168 int cap;
169
170 r = extract_first_word(&rvalue, &word, NULL, 0);
171 if (r < 0) {
172 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract capability string, ignoring: %s", rvalue);
173 return 0;
174 }
175 if (r == 0)
176 break;
177
178 cap = capability_from_name(word);
179 if (cap < 0) {
180 log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse capability, ignoring: %s", word);
181 continue;
182 }
183
184 u |= 1 << ((uint64_t) cap);
185 }
186
187 if (u == 0)
188 return 0;
189
190 *result |= u;
191 return 0;
192 }
193
194 int config_parse_id128(
195 const char *unit,
196 const char *filename,
197 unsigned line,
198 const char *section,
199 unsigned section_line,
200 const char *lvalue,
201 int ltype,
202 const char *rvalue,
203 void *data,
204 void *userdata) {
205
206 sd_id128_t t, *result = data;
207 int r;
208
209 assert(filename);
210 assert(lvalue);
211 assert(rvalue);
212
213 r = sd_id128_from_string(rvalue, &t);
214 if (r < 0) {
215 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse 128bit ID/UUID, ignoring: %s", rvalue);
216 return 0;
217 }
218
219 *result = t;
220 return 0;
221 }
222
223 int config_parse_bind(
224 const char *unit,
225 const char *filename,
226 unsigned line,
227 const char *section,
228 unsigned section_line,
229 const char *lvalue,
230 int ltype,
231 const char *rvalue,
232 void *data,
233 void *userdata) {
234
235 Settings *settings = data;
236 int r;
237
238 assert(filename);
239 assert(lvalue);
240 assert(rvalue);
241
242 r = bind_mount_parse(&settings->custom_mounts, &settings->n_custom_mounts, rvalue, ltype);
243 if (r < 0) {
244 log_syntax(unit, LOG_ERR, filename, line, r, "Invalid bind mount specification %s: %m", rvalue);
245 return 0;
246 }
247
248 return 0;
249 }
250
251 int config_parse_tmpfs(
252 const char *unit,
253 const char *filename,
254 unsigned line,
255 const char *section,
256 unsigned section_line,
257 const char *lvalue,
258 int ltype,
259 const char *rvalue,
260 void *data,
261 void *userdata) {
262
263 Settings *settings = data;
264 int r;
265
266 assert(filename);
267 assert(lvalue);
268 assert(rvalue);
269
270 r = tmpfs_mount_parse(&settings->custom_mounts, &settings->n_custom_mounts, rvalue);
271 if (r < 0) {
272 log_syntax(unit, LOG_ERR, filename, line, r, "Invalid temporary file system specification %s: %m", rvalue);
273 return 0;
274 }
275
276 return 0;
277 }
278
279 int config_parse_veth_extra(
280 const char *unit,
281 const char *filename,
282 unsigned line,
283 const char *section,
284 unsigned section_line,
285 const char *lvalue,
286 int ltype,
287 const char *rvalue,
288 void *data,
289 void *userdata) {
290
291 Settings *settings = data;
292 int r;
293
294 assert(filename);
295 assert(lvalue);
296 assert(rvalue);
297
298 r = veth_extra_parse(&settings->network_veth_extra, rvalue);
299 if (r < 0) {
300 log_syntax(unit, LOG_ERR, filename, line, r, "Invalid extra virtual Ethernet link specification %s: %m", rvalue);
301 return 0;
302 }
303
304 return 0;
305 }