]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/confile.c
fix sshd template
[mirror_lxc.git] / src / lxc / confile.c
CommitLineData
c2cc9f0a 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 <stdlib.h>
25#include <string.h>
26#include <unistd.h>
27#include <errno.h>
63376d7d
DL
28#include <fcntl.h>
29#include <pty.h>
30#include <sys/stat.h>
c2cc9f0a 31#include <sys/types.h>
32#include <sys/param.h>
33#include <sys/utsname.h>
34#include <arpa/inet.h>
35#include <netinet/in.h>
36#include <net/if.h>
37
b2718c72 38#include "parse.h"
26c39028 39#include "utils.h"
c2cc9f0a 40
36eb9bde 41#include <lxc/log.h>
00b3c2e2 42#include <lxc/conf.h>
36eb9bde
CLG
43
44lxc_log_define(lxc_confile, lxc);
576f946d 45
10db618d 46static int config_pts(const char *, char *, struct lxc_conf *);
b0a33c1e 47static int config_tty(const char *, char *, struct lxc_conf *);
576f946d 48static int config_cgroup(const char *, char *, struct lxc_conf *);
49static int config_mount(const char *, char *, struct lxc_conf *);
50static int config_rootfs(const char *, char *, struct lxc_conf *);
23b7ea69 51static int config_rootfs_mount(const char *, char *, struct lxc_conf *);
bf601689 52static int config_pivotdir(const char *, char *, struct lxc_conf *);
576f946d 53static int config_utsname(const char *, char *, struct lxc_conf *);
54static int config_network_type(const char *, char *, struct lxc_conf *);
55static int config_network_flags(const char *, char *, struct lxc_conf *);
56static int config_network_link(const char *, char *, struct lxc_conf *);
57static int config_network_name(const char *, char *, struct lxc_conf *);
e892973e
DL
58static int config_network_veth_pair(const char *, char *, struct lxc_conf *);
59static int config_network_macvlan_mode(const char *, char *, struct lxc_conf *);
576f946d 60static int config_network_hwaddr(const char *, char *, struct lxc_conf *);
e892973e 61static int config_network_vlan_id(const char *, char *, struct lxc_conf *);
442cbbe6 62static int config_network_mtu(const char *, char *, struct lxc_conf *);
576f946d 63static int config_network_ipv4(const char *, char *, struct lxc_conf *);
64static int config_network_ipv6(const char *, char *, struct lxc_conf *);
81810dd1 65static int config_cap_drop(const char *, char *, struct lxc_conf *);
63376d7d 66static int config_console(const char *, char *, struct lxc_conf *);
c2cc9f0a 67
b2718c72 68typedef int (*config_cb)(const char *, char *, struct lxc_conf *);
69
c2cc9f0a 70struct config {
71 char *name;
c2cc9f0a 72 config_cb cb;
73};
74
576f946d 75static struct config config[] = {
76
e892973e
DL
77 { "lxc.pts", config_pts },
78 { "lxc.tty", config_tty },
79 { "lxc.cgroup", config_cgroup },
80 { "lxc.mount", config_mount },
23b7ea69 81 { "lxc.rootfs.mount", config_rootfs_mount },
e892973e 82 { "lxc.rootfs", config_rootfs },
bf601689 83 { "lxc.pivotdir", config_pivotdir },
e892973e
DL
84 { "lxc.utsname", config_utsname },
85 { "lxc.network.type", config_network_type },
86 { "lxc.network.flags", config_network_flags },
87 { "lxc.network.link", config_network_link },
88 { "lxc.network.name", config_network_name },
89 { "lxc.network.macvlan.mode", config_network_macvlan_mode },
90 { "lxc.network.veth.pair", config_network_veth_pair },
91 { "lxc.network.hwaddr", config_network_hwaddr },
92 { "lxc.network.mtu", config_network_mtu },
93 { "lxc.network.vlan.id", config_network_vlan_id },
94 { "lxc.network.ipv4", config_network_ipv4 },
95 { "lxc.network.ipv6", config_network_ipv6 },
81810dd1 96 { "lxc.cap.drop", config_cap_drop },
63376d7d 97 { "lxc.console", config_console },
c2cc9f0a 98};
99
100static const size_t config_size = sizeof(config)/sizeof(struct config);
101
102static struct config *getconfig(const char *key)
103{
104 int i;
105
106 for (i = 0; i < config_size; i++)
a871ff6b 107 if (!strncmp(config[i].name, key,
c2cc9f0a 108 strlen(config[i].name)))
109 return &config[i];
110 return NULL;
111}
112
e892973e
DL
113static int config_network_type(const char *key, char *value,
114 struct lxc_conf *lxc_conf)
c2cc9f0a 115{
5f4535a3 116 struct lxc_list *network = &lxc_conf->network;
c2cc9f0a 117 struct lxc_netdev *netdev;
118 struct lxc_list *list;
c2cc9f0a 119
120 netdev = malloc(sizeof(*netdev));
121 if (!netdev) {
36eb9bde 122 SYSERROR("failed to allocate memory");
c2cc9f0a 123 return -1;
124 }
125
82d5ae15 126 memset(netdev, 0, sizeof(*netdev));
c2cc9f0a 127 lxc_list_init(&netdev->ipv4);
128 lxc_list_init(&netdev->ipv6);
c2cc9f0a 129
130 list = malloc(sizeof(*list));
131 if (!list) {
36eb9bde 132 SYSERROR("failed to allocate memory");
c2cc9f0a 133 return -1;
134 }
135
136 lxc_list_init(list);
5f4535a3 137 list->elem = netdev;
c2cc9f0a 138
5f4535a3 139 lxc_list_add(network, list);
a871ff6b 140
c2cc9f0a 141 if (!strcmp(value, "veth"))
24654103 142 netdev->type = LXC_NET_VETH;
c2cc9f0a 143 else if (!strcmp(value, "macvlan"))
24654103 144 netdev->type = LXC_NET_MACVLAN;
26c39028 145 else if (!strcmp(value, "vlan"))
24654103 146 netdev->type = LXC_NET_VLAN;
c2cc9f0a 147 else if (!strcmp(value, "phys"))
24654103 148 netdev->type = LXC_NET_PHYS;
5f58350a 149 else if (!strcmp(value, "empty"))
24654103 150 netdev->type = LXC_NET_EMPTY;
c2cc9f0a 151 else {
36eb9bde 152 ERROR("invalid network type %s", value);
c2cc9f0a 153 return -1;
154 }
155 return 0;
156}
157
a059591e
DL
158static int config_ip_prefix(struct in_addr *addr)
159{
160 if (IN_CLASSA(addr->s_addr))
161 return 32 - IN_CLASSA_NSHIFT;
162 if (IN_CLASSB(addr->s_addr))
163 return 32 - IN_CLASSB_NSHIFT;
164 if (IN_CLASSC(addr->s_addr))
165 return 32 - IN_CLASSC_NSHIFT;
166
167 return 0;
168}
169
16950ecb
DL
170static struct lxc_netdev *network_netdev(const char *key, const char *value,
171 struct lxc_list *network)
c2cc9f0a 172{
c2cc9f0a 173 struct lxc_netdev *netdev;
174
5f4535a3 175 if (lxc_list_empty(network)) {
16950ecb
DL
176 ERROR("network is not created for '%s' = '%s' option",
177 key, value);
33c945e0 178 return NULL;
c2cc9f0a 179 }
180
5f4535a3
DL
181 netdev = lxc_list_first_elem(network);
182 if (!netdev) {
16950ecb
DL
183 ERROR("no network device defined for '%s' = '%s' option",
184 key, value);
33c945e0 185 return NULL;
c2cc9f0a 186 }
187
33c945e0 188 return netdev;
c2cc9f0a 189}
190
33c945e0 191static int network_ifname(char **valuep, char *value)
c2cc9f0a 192{
c2cc9f0a 193 if (strlen(value) > IFNAMSIZ) {
36eb9bde 194 ERROR("invalid interface name: %s", value);
c2cc9f0a 195 return -1;
196 }
197
33c945e0 198 *valuep = strdup(value);
16950ecb
DL
199 if (!*valuep) {
200 ERROR("failed to dup string '%s'", value);
201 return -1;
202 }
33c945e0 203
c2cc9f0a 204 return 0;
205}
206
e892973e
DL
207#ifndef MACVLAN_MODE_PRIVATE
208# define MACVLAN_MODE_PRIVATE 1
209#endif
210
211#ifndef MACVLAN_MODE_VEPA
212# define MACVLAN_MODE_VEPA 2
213#endif
214
215#ifndef MACVLAN_MODE_BRIDGE
216# define MACVLAN_MODE_BRIDGE 4
217#endif
218
219static int macvlan_mode(int *valuep, char *value)
220{
221 struct mc_mode {
222 char *name;
223 int mode;
224 } m[] = {
225 { "private", MACVLAN_MODE_PRIVATE },
226 { "vepa", MACVLAN_MODE_VEPA },
227 { "bridge", MACVLAN_MODE_BRIDGE },
228 };
229
230 int i;
231
232 for (i = 0; i < sizeof(m)/sizeof(m[0]); i++) {
233 if (strcmp(m[i].name, value))
234 continue;
235
236 *valuep = m[i].mode;
237 return 0;
238 }
239
240 return -1;
241}
242
33c945e0
MT
243static int config_network_flags(const char *key, char *value,
244 struct lxc_conf *lxc_conf)
c2cc9f0a 245{
c2cc9f0a 246 struct lxc_netdev *netdev;
247
16950ecb 248 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 249 if (!netdev)
c2cc9f0a 250 return -1;
c2cc9f0a 251
33c945e0 252 netdev->flags |= IFF_UP;
c2cc9f0a 253
33c945e0
MT
254 return 0;
255}
256
257static int config_network_link(const char *key, char *value,
258 struct lxc_conf *lxc_conf)
259{
260 struct lxc_netdev *netdev;
261
16950ecb 262 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 263 if (!netdev)
c2cc9f0a 264 return -1;
c2cc9f0a 265
33c945e0 266 return network_ifname(&netdev->link, value);
c2cc9f0a 267}
268
33c945e0
MT
269static int config_network_name(const char *key, char *value,
270 struct lxc_conf *lxc_conf)
c2cc9f0a 271{
c2cc9f0a 272 struct lxc_netdev *netdev;
273
16950ecb 274 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 275 if (!netdev)
c2cc9f0a 276 return -1;
c2cc9f0a 277
33c945e0
MT
278 return network_ifname(&netdev->name, value);
279}
280
e892973e
DL
281static int config_network_veth_pair(const char *key, char *value,
282 struct lxc_conf *lxc_conf)
283{
284 struct lxc_netdev *netdev;
285
286 netdev = network_netdev(key, value, &lxc_conf->network);
287 if (!netdev)
288 return -1;
289
290 return network_ifname(&netdev->priv.veth_attr.pair, value);
291}
292
293static int config_network_macvlan_mode(const char *key, char *value,
294 struct lxc_conf *lxc_conf)
8634bc19
MT
295{
296 struct lxc_netdev *netdev;
297
298 netdev = network_netdev(key, value, &lxc_conf->network);
299 if (!netdev)
300 return -1;
301
e892973e 302 return macvlan_mode(&netdev->priv.macvlan_attr.mode, value);
8634bc19
MT
303}
304
33c945e0
MT
305static int config_network_hwaddr(const char *key, char *value,
306 struct lxc_conf *lxc_conf)
307{
308 struct lxc_netdev *netdev;
309
16950ecb 310 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 311 if (!netdev)
c2cc9f0a 312 return -1;
c2cc9f0a 313
c2cc9f0a 314 netdev->hwaddr = strdup(value);
16950ecb
DL
315 if (!netdev->hwaddr) {
316 SYSERROR("failed to dup string '%s'", value);
317 return -1;
318 }
33c945e0 319
c2cc9f0a 320 return 0;
321}
322
e892973e 323static int config_network_vlan_id(const char *key, char *value,
26c39028
JHS
324 struct lxc_conf *lxc_conf)
325{
326 struct lxc_netdev *netdev;
327
328 netdev = network_netdev(key, value, &lxc_conf->network);
329 if (!netdev)
330 return -1;
331
f6cc1de1 332 if (get_u16(&netdev->priv.vlan_attr.vid, value, 0))
26c39028
JHS
333 return -1;
334
335 return 0;
336}
337
33c945e0
MT
338static int config_network_mtu(const char *key, char *value,
339 struct lxc_conf *lxc_conf)
442cbbe6 340{
442cbbe6
TR
341 struct lxc_netdev *netdev;
342
16950ecb 343 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 344 if (!netdev)
442cbbe6 345 return -1;
442cbbe6 346
442cbbe6 347 netdev->mtu = strdup(value);
16950ecb
DL
348 if (!netdev->mtu) {
349 SYSERROR("failed to dup string '%s'", value);
350 return -1;
351 }
33c945e0 352
442cbbe6
TR
353 return 0;
354}
355
33c945e0
MT
356static int config_network_ipv4(const char *key, char *value,
357 struct lxc_conf *lxc_conf)
c2cc9f0a 358{
c2cc9f0a 359 struct lxc_netdev *netdev;
33c945e0 360 struct lxc_inetdev *inetdev;
c2cc9f0a 361 struct lxc_list *list;
362 char *cursor, *slash, *addr = NULL, *bcast = NULL, *prefix = NULL;
363
16950ecb 364 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 365 if (!netdev)
c2cc9f0a 366 return -1;
c2cc9f0a 367
368 inetdev = malloc(sizeof(*inetdev));
369 if (!inetdev) {
36eb9bde 370 SYSERROR("failed to allocate ipv4 address");
c2cc9f0a 371 return -1;
372 }
373 memset(inetdev, 0, sizeof(*inetdev));
374
375 list = malloc(sizeof(*list));
376 if (!list) {
36eb9bde 377 SYSERROR("failed to allocate memory");
c2cc9f0a 378 return -1;
379 }
380
381 lxc_list_init(list);
382 list->elem = inetdev;
383
384 addr = value;
385
386 cursor = strstr(addr, " ");
387 if (cursor) {
388 *cursor = '\0';
389 bcast = cursor + 1;
390 }
391
392 slash = strstr(addr, "/");
393 if (slash) {
394 *slash = '\0';
395 prefix = slash + 1;
396 }
397
398 if (!addr) {
36eb9bde 399 ERROR("no address specified");
c2cc9f0a 400 return -1;
401 }
402
403 if (!inet_pton(AF_INET, addr, &inetdev->addr)) {
36eb9bde 404 SYSERROR("invalid ipv4 address: %s", value);
c2cc9f0a 405 return -1;
406 }
407
0093bb8c
DL
408 if (bcast && !inet_pton(AF_INET, bcast, &inetdev->bcast)) {
409 SYSERROR("invalid ipv4 broadcast address: %s", value);
410 return -1;
411 }
c2cc9f0a 412
a059591e
DL
413 /* no prefix specified, determine it from the network class */
414 inetdev->prefix = prefix ? atoi(prefix) :
415 config_ip_prefix(&inetdev->addr);
416
b3df193c 417 /* if no broadcast address, let compute one from the
0093bb8c
DL
418 * prefix and address
419 */
420 if (!bcast) {
b3df193c 421 inetdev->bcast.s_addr =
0093bb8c
DL
422 htonl(INADDR_BROADCAST << (32 - inetdev->prefix));
423 inetdev->bcast.s_addr &= inetdev->addr.s_addr;
424 }
c2cc9f0a 425
426 lxc_list_add(&netdev->ipv4, list);
427
428 return 0;
429}
430
e892973e
DL
431static int config_network_ipv6(const char *key, char *value,
432 struct lxc_conf *lxc_conf)
c2cc9f0a 433{
c2cc9f0a 434 struct lxc_netdev *netdev;
435 struct lxc_inet6dev *inet6dev;
436 struct lxc_list *list;
437 char *slash;
438 char *netmask;
439
16950ecb 440 netdev = network_netdev(key, value, &lxc_conf->network);
33c945e0 441 if (!netdev)
c2cc9f0a 442 return -1;
c2cc9f0a 443
444 inet6dev = malloc(sizeof(*inet6dev));
445 if (!inet6dev) {
36eb9bde 446 SYSERROR("failed to allocate ipv6 address");
c2cc9f0a 447 return -1;
448 }
449 memset(inet6dev, 0, sizeof(*inet6dev));
450
451 list = malloc(sizeof(*list));
452 if (!list) {
36eb9bde 453 SYSERROR("failed to allocate memory");
c2cc9f0a 454 return -1;
455 }
456
457 lxc_list_init(list);
458 list->elem = inet6dev;
459
a059591e 460 inet6dev->prefix = 64;
c2cc9f0a 461 slash = strstr(value, "/");
462 if (slash) {
463 *slash = '\0';
464 netmask = slash + 1;
465 inet6dev->prefix = atoi(netmask);
466 }
467
468 if (!inet_pton(AF_INET6, value, &inet6dev->addr)) {
36eb9bde 469 SYSERROR("invalid ipv6 address: %s", value);
c2cc9f0a 470 return -1;
471 }
472
c2cc9f0a 473 lxc_list_add(&netdev->ipv6, list);
474
475 return 0;
476}
477
10db618d 478static int config_pts(const char *key, char *value, struct lxc_conf *lxc_conf)
479{
480 int maxpts = atoi(value);
481
482 lxc_conf->pts = maxpts;
483
484 return 0;
485}
486
b0a33c1e 487static int config_tty(const char *key, char *value, struct lxc_conf *lxc_conf)
488{
489 int nbtty = atoi(value);
490
491 lxc_conf->tty = nbtty;
492
493 return 0;
494}
495
576f946d 496static int config_cgroup(const char *key, char *value, struct lxc_conf *lxc_conf)
497{
498 char *token = "lxc.cgroup.";
499 char *subkey;
500 struct lxc_list *cglist;
501 struct lxc_cgroup *cgelem;
502
503 subkey = strstr(key, token);
504
505 if (!subkey)
506 return -1;
507
508 if (!strlen(subkey))
509 return -1;
510
511 if (strlen(subkey) == strlen(token))
512 return -1;
a871ff6b 513
576f946d 514 subkey += strlen(token);
515
516 cglist = malloc(sizeof(*cglist));
517 if (!cglist)
518 return -1;
519
520 cgelem = malloc(sizeof(*cgelem));
521 if (!cgelem) {
522 free(cglist);
523 return -1;
524 }
525
526 cgelem->subsystem = strdup(subkey);
527 cgelem->value = strdup(value);
528 cglist->elem = cgelem;
529
94d12f0a 530 lxc_list_add_tail(&lxc_conf->cgroup, cglist);
576f946d 531
532 return 0;
533}
534
e7938e9e 535static int config_fstab(const char *key, char *value, struct lxc_conf *lxc_conf)
c2cc9f0a 536{
537 if (strlen(value) >= MAXPATHLEN) {
36eb9bde 538 ERROR("%s path is too long", value);
c2cc9f0a 539 return -1;
540 }
541
542 lxc_conf->fstab = strdup(value);
543 if (!lxc_conf->fstab) {
36eb9bde 544 SYSERROR("failed to duplicate string %s", value);
c2cc9f0a 545 return -1;
546 }
547
548 return 0;
549}
550
e7938e9e
MN
551static int config_mount(const char *key, char *value, struct lxc_conf *lxc_conf)
552{
553 char *fstab_token = "lxc.mount";
554 char *token = "lxc.mount.entry";
555 char *subkey;
556 char *mntelem;
557 struct lxc_list *mntlist;
558
559 subkey = strstr(key, token);
560
561 if (!subkey) {
562 subkey = strstr(key, fstab_token);
563
564 if (!subkey)
565 return -1;
566
567 return config_fstab(key, value, lxc_conf);
568 }
569
570 if (!strlen(subkey))
571 return -1;
572
573 mntlist = malloc(sizeof(*mntlist));
574 if (!mntlist)
575 return -1;
576
577 mntelem = strdup(value);
578 mntlist->elem = mntelem;
579
580 lxc_list_add_tail(&lxc_conf->mount_list, mntlist);
581
582 return 0;
583}
584
81810dd1
DL
585static int config_cap_drop(const char *key, char *value,
586 struct lxc_conf *lxc_conf)
587{
bd288c26 588 char *dropcaps, *sptr, *token;
81810dd1
DL
589 struct lxc_list *droplist;
590 int ret = -1;
591
592 if (!strlen(value))
593 return -1;
594
595 dropcaps = strdup(value);
596 if (!dropcaps) {
597 SYSERROR("failed to dup '%s'", value);
598 return -1;
599 }
600
601 /* in case several capability drop is specified in a single line
602 * split these caps in a single element for the list */
603 for (;;) {
604 token = strtok_r(dropcaps, " \t", &sptr);
605 if (!token) {
606 ret = 0;
607 break;
608 }
609 dropcaps = NULL;
610
611 droplist = malloc(sizeof(*droplist));
612 if (!droplist) {
613 SYSERROR("failed to allocate drop list");
614 break;
615 }
616
617 droplist->elem = strdup(token);
618 if (!droplist->elem) {
619 SYSERROR("failed to dup '%s'", token);
620 free(droplist);
621 break;
622 }
623
624 lxc_list_add_tail(&lxc_conf->caps, droplist);
625 }
626
627 free(dropcaps);
628
629 return ret;
630}
631
28a4b0e5
DL
632static int config_console(const char *key, char *value,
633 struct lxc_conf *lxc_conf)
634{
635 char *path;
636
637 path = strdup(value);
638 if (!path) {
639 SYSERROR("failed to strdup '%s': %m", value);
640 return -1;
641 }
642
643 lxc_conf->console.path = path;
644
645 return 0;
646}
647
576f946d 648static int config_rootfs(const char *key, char *value, struct lxc_conf *lxc_conf)
c2cc9f0a 649{
650 if (strlen(value) >= MAXPATHLEN) {
36eb9bde 651 ERROR("%s path is too long", value);
c2cc9f0a 652 return -1;
653 }
654
33fcb7a0
DL
655 lxc_conf->rootfs.path = strdup(value);
656 if (!lxc_conf->rootfs.path) {
36eb9bde 657 SYSERROR("failed to duplicate string %s", value);
c2cc9f0a 658 return -1;
659 }
660
661 return 0;
662}
663
23b7ea69
DL
664static int config_rootfs_mount(const char *key, char *value, struct lxc_conf *lxc_conf)
665{
666 if (strlen(value) >= MAXPATHLEN) {
667 ERROR("%s path is too long", value);
668 return -1;
669 }
670
671 lxc_conf->rootfs.mount = strdup(value);
672 if (!lxc_conf->rootfs.mount) {
673 SYSERROR("failed to duplicate string '%s'", value);
674 return -1;
675 }
676
677 return 0;
678}
679
bf601689
MH
680static int config_pivotdir(const char *key, char *value, struct lxc_conf *lxc_conf)
681{
682 if (strlen(value) >= MAXPATHLEN) {
683 ERROR("%s path is too long", value);
684 return -1;
685 }
686
33fcb7a0
DL
687 lxc_conf->rootfs.pivot = strdup(value);
688 if (!lxc_conf->rootfs.pivot) {
bf601689
MH
689 SYSERROR("failed to duplicate string %s", value);
690 return -1;
691 }
692
693 return 0;
694}
695
576f946d 696static int config_utsname(const char *key, char *value, struct lxc_conf *lxc_conf)
c2cc9f0a 697{
698 struct utsname *utsname;
699
700 utsname = malloc(sizeof(*utsname));
701 if (!utsname) {
36eb9bde 702 SYSERROR("failed to allocate memory");
c2cc9f0a 703 return -1;
704 }
705
706 if (strlen(value) >= sizeof(utsname->nodename)) {
36eb9bde 707 ERROR("node name '%s' is too long",
c2cc9f0a 708 utsname->nodename);
709 return -1;
710 }
711
712 strcpy(utsname->nodename, value);
713 lxc_conf->utsname = utsname;
714
715 return 0;
716}
717
7a7ff0c6 718static int parse_line(char *buffer, void *data)
c2cc9f0a 719{
720 struct config *config;
91480a0f 721 char *line;
c2cc9f0a 722 char *dot;
723 char *key;
724 char *value;
91480a0f 725 int ret = -1;
c2cc9f0a 726
91480a0f 727 if (lxc_is_line_empty(buffer))
c2cc9f0a 728 return 0;
729
91480a0f
DL
730 /* we have to dup the buffer otherwise, at the re-exec for reboot we modified
731 * the original string on the stack by replacing '=' by '\0' below
732 */
733 line = strdup(buffer);
734 if (!line) {
735 SYSERROR("failed to allocate memory for '%s'", buffer);
736 goto out;
737 }
738
b2718c72 739 line += lxc_char_left_gc(line, strlen(line));
91480a0f
DL
740 if (line[0] == '#') {
741 ret = 0;
742 goto out;
743 }
c2cc9f0a 744
b2718c72 745 dot = strstr(line, "=");
c2cc9f0a 746 if (!dot) {
36eb9bde 747 ERROR("invalid configuration line: %s", line);
91480a0f 748 goto out;
c2cc9f0a 749 }
a871ff6b 750
c2cc9f0a 751 *dot = '\0';
752 value = dot + 1;
753
b2718c72 754 key = line;
755 key[lxc_char_right_gc(key, strlen(key))] = '\0';
c2cc9f0a 756
b2718c72 757 value += lxc_char_left_gc(value, strlen(value));
758 value[lxc_char_right_gc(value, strlen(value))] = '\0';
c2cc9f0a 759
760 config = getconfig(key);
761 if (!config) {
36eb9bde 762 ERROR("unknow key %s", key);
91480a0f 763 goto out;
c2cc9f0a 764 }
765
91480a0f
DL
766 ret = config->cb(key, value, data);
767
768out:
769 free(line);
770 return ret;
c2cc9f0a 771}
772
af5b0155
CLG
773int lxc_config_readline(char *buffer, struct lxc_conf *conf)
774{
775 return parse_line(buffer, conf);
776}
777
b2718c72 778int lxc_config_read(const char *file, struct lxc_conf *conf)
c2cc9f0a 779{
2382ecff 780 return lxc_file_for_each_line(file, parse_line, conf);
c2cc9f0a 781}
62e46035
CLG
782
783int lxc_config_define_add(struct lxc_list *defines, char* arg)
784{
785 struct lxc_list *dent;
786
787 dent = malloc(sizeof(struct lxc_list));
788 if (!dent)
789 return -1;
790
791 dent->elem = arg;
792 lxc_list_add_tail(defines, dent);
793 return 0;
794}
795
226a18d6 796int lxc_config_define_load(struct lxc_list *defines, struct lxc_conf *conf)
62e46035
CLG
797{
798 struct lxc_list *it;
799 int ret = 0;
800
801 lxc_list_for_each(it, defines) {
802 ret = lxc_config_readline(it->elem, conf);
803 if (ret)
804 break;
805 }
806
807 lxc_list_for_each(it, defines) {
808 lxc_list_del(it);
809 free(it);
810 }
811
812 return ret;
813}