2 * lxc: linux Container library
4 * (C) Copyright IBM Corp. 2007, 2008
7 * Daniel Lezcano <dlezcano at fr.ibm.com>
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.
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.
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
31 #include <sys/types.h>
32 #include <sys/param.h>
33 #include <sys/utsname.h>
34 #include <sys/personality.h>
35 #include <arpa/inet.h>
36 #include <netinet/in.h>
46 lxc_log_define(lxc_confile
, lxc
);
48 static int config_personality(const char *, char *, struct lxc_conf
*);
49 static int config_pts(const char *, char *, struct lxc_conf
*);
50 static int config_tty(const char *, char *, struct lxc_conf
*);
51 static int config_ttydir(const char *, char *, struct lxc_conf
*);
53 static int config_aa_profile(const char *, char *, struct lxc_conf
*);
55 static int config_cgroup(const char *, char *, struct lxc_conf
*);
56 static int config_mount(const char *, char *, struct lxc_conf
*);
57 static int config_rootfs(const char *, char *, struct lxc_conf
*);
58 static int config_rootfs_mount(const char *, char *, struct lxc_conf
*);
59 static int config_pivotdir(const char *, char *, struct lxc_conf
*);
60 static int config_utsname(const char *, char *, struct lxc_conf
*);
61 static int config_hook(const char *key
, char *value
, struct lxc_conf
*lxc_conf
);
62 static int config_network_type(const char *, char *, struct lxc_conf
*);
63 static int config_network_flags(const char *, char *, struct lxc_conf
*);
64 static int config_network_link(const char *, char *, struct lxc_conf
*);
65 static int config_network_name(const char *, char *, struct lxc_conf
*);
66 static int config_network_veth_pair(const char *, char *, struct lxc_conf
*);
67 static int config_network_macvlan_mode(const char *, char *, struct lxc_conf
*);
68 static int config_network_hwaddr(const char *, char *, struct lxc_conf
*);
69 static int config_network_vlan_id(const char *, char *, struct lxc_conf
*);
70 static int config_network_mtu(const char *, char *, struct lxc_conf
*);
71 static int config_network_ipv4(const char *, char *, struct lxc_conf
*);
72 static int config_network_ipv4_gateway(const char *, char *, struct lxc_conf
*);
73 static int config_network_script(const char *, char *, struct lxc_conf
*);
74 static int config_network_ipv6(const char *, char *, struct lxc_conf
*);
75 static int config_network_ipv6_gateway(const char *, char *, struct lxc_conf
*);
76 static int config_cap_drop(const char *, char *, struct lxc_conf
*);
77 static int config_console(const char *, char *, struct lxc_conf
*);
78 static int config_seccomp(const char *, char *, struct lxc_conf
*);
79 static int config_includefile(const char *, char *, struct lxc_conf
*);
81 typedef int (*config_cb
)(const char *, char *, struct lxc_conf
*);
88 static struct config config
[] = {
90 { "lxc.arch", config_personality
},
91 { "lxc.pts", config_pts
},
92 { "lxc.tty", config_tty
},
93 { "lxc.devttydir", config_ttydir
},
95 { "lxc.aa_profile", config_aa_profile
},
97 { "lxc.cgroup", config_cgroup
},
98 { "lxc.mount", config_mount
},
99 { "lxc.rootfs.mount", config_rootfs_mount
},
100 { "lxc.rootfs", config_rootfs
},
101 { "lxc.pivotdir", config_pivotdir
},
102 { "lxc.utsname", config_utsname
},
103 { "lxc.hook.pre-start", config_hook
},
104 { "lxc.hook.mount", config_hook
},
105 { "lxc.hook.start", config_hook
},
106 { "lxc.hook.post-stop", config_hook
},
107 { "lxc.network.type", config_network_type
},
108 { "lxc.network.flags", config_network_flags
},
109 { "lxc.network.link", config_network_link
},
110 { "lxc.network.name", config_network_name
},
111 { "lxc.network.macvlan.mode", config_network_macvlan_mode
},
112 { "lxc.network.veth.pair", config_network_veth_pair
},
113 { "lxc.network.script.up", config_network_script
},
114 { "lxc.network.hwaddr", config_network_hwaddr
},
115 { "lxc.network.mtu", config_network_mtu
},
116 { "lxc.network.vlan.id", config_network_vlan_id
},
117 { "lxc.network.ipv4.gateway", config_network_ipv4_gateway
},
118 { "lxc.network.ipv4", config_network_ipv4
},
119 { "lxc.network.ipv6.gateway", config_network_ipv6_gateway
},
120 { "lxc.network.ipv6", config_network_ipv6
},
121 { "lxc.cap.drop", config_cap_drop
},
122 { "lxc.console", config_console
},
123 { "lxc.seccomp", config_seccomp
},
124 { "lxc.include", config_includefile
},
127 static const size_t config_size
= sizeof(config
)/sizeof(struct config
);
129 static struct config
*getconfig(const char *key
)
133 for (i
= 0; i
< config_size
; i
++)
134 if (!strncmp(config
[i
].name
, key
,
135 strlen(config
[i
].name
)))
140 static int config_network_type(const char *key
, char *value
,
141 struct lxc_conf
*lxc_conf
)
143 struct lxc_list
*network
= &lxc_conf
->network
;
144 struct lxc_netdev
*netdev
;
145 struct lxc_list
*list
;
147 netdev
= malloc(sizeof(*netdev
));
149 SYSERROR("failed to allocate memory");
153 memset(netdev
, 0, sizeof(*netdev
));
154 lxc_list_init(&netdev
->ipv4
);
155 lxc_list_init(&netdev
->ipv6
);
157 list
= malloc(sizeof(*list
));
159 SYSERROR("failed to allocate memory");
166 lxc_list_add_tail(network
, list
);
168 if (!strcmp(value
, "veth"))
169 netdev
->type
= LXC_NET_VETH
;
170 else if (!strcmp(value
, "macvlan"))
171 netdev
->type
= LXC_NET_MACVLAN
;
172 else if (!strcmp(value
, "vlan"))
173 netdev
->type
= LXC_NET_VLAN
;
174 else if (!strcmp(value
, "phys"))
175 netdev
->type
= LXC_NET_PHYS
;
176 else if (!strcmp(value
, "empty"))
177 netdev
->type
= LXC_NET_EMPTY
;
179 ERROR("invalid network type %s", value
);
185 static int config_ip_prefix(struct in_addr
*addr
)
187 if (IN_CLASSA(addr
->s_addr
))
188 return 32 - IN_CLASSA_NSHIFT
;
189 if (IN_CLASSB(addr
->s_addr
))
190 return 32 - IN_CLASSB_NSHIFT
;
191 if (IN_CLASSC(addr
->s_addr
))
192 return 32 - IN_CLASSC_NSHIFT
;
197 static struct lxc_netdev
*network_netdev(const char *key
, const char *value
,
198 struct lxc_list
*network
)
200 struct lxc_netdev
*netdev
;
202 if (lxc_list_empty(network
)) {
203 ERROR("network is not created for '%s' = '%s' option",
208 netdev
= lxc_list_last_elem(network
);
210 ERROR("no network device defined for '%s' = '%s' option",
218 static int network_ifname(char **valuep
, char *value
)
220 if (strlen(value
) >= IFNAMSIZ
) {
221 ERROR("interface name '%s' too long (>%d)\n",
222 value
, IFNAMSIZ
- 1);
226 *valuep
= strdup(value
);
228 ERROR("failed to dup string '%s'", value
);
235 #ifndef MACVLAN_MODE_PRIVATE
236 # define MACVLAN_MODE_PRIVATE 1
239 #ifndef MACVLAN_MODE_VEPA
240 # define MACVLAN_MODE_VEPA 2
243 #ifndef MACVLAN_MODE_BRIDGE
244 # define MACVLAN_MODE_BRIDGE 4
247 static int macvlan_mode(int *valuep
, char *value
)
253 { "private", MACVLAN_MODE_PRIVATE
},
254 { "vepa", MACVLAN_MODE_VEPA
},
255 { "bridge", MACVLAN_MODE_BRIDGE
},
260 for (i
= 0; i
< sizeof(m
)/sizeof(m
[0]); i
++) {
261 if (strcmp(m
[i
].name
, value
))
271 static int config_network_flags(const char *key
, char *value
,
272 struct lxc_conf
*lxc_conf
)
274 struct lxc_netdev
*netdev
;
276 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
280 netdev
->flags
|= IFF_UP
;
285 static int config_network_link(const char *key
, char *value
,
286 struct lxc_conf
*lxc_conf
)
288 struct lxc_netdev
*netdev
;
290 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
294 return network_ifname(&netdev
->link
, value
);
297 static int config_network_name(const char *key
, char *value
,
298 struct lxc_conf
*lxc_conf
)
300 struct lxc_netdev
*netdev
;
302 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
306 return network_ifname(&netdev
->name
, value
);
309 static int config_network_veth_pair(const char *key
, char *value
,
310 struct lxc_conf
*lxc_conf
)
312 struct lxc_netdev
*netdev
;
314 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
318 return network_ifname(&netdev
->priv
.veth_attr
.pair
, value
);
321 static int config_network_macvlan_mode(const char *key
, char *value
,
322 struct lxc_conf
*lxc_conf
)
324 struct lxc_netdev
*netdev
;
326 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
330 return macvlan_mode(&netdev
->priv
.macvlan_attr
.mode
, value
);
333 static int config_network_hwaddr(const char *key
, char *value
,
334 struct lxc_conf
*lxc_conf
)
336 struct lxc_netdev
*netdev
;
338 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
342 netdev
->hwaddr
= strdup(value
);
343 if (!netdev
->hwaddr
) {
344 SYSERROR("failed to dup string '%s'", value
);
351 static int config_network_vlan_id(const char *key
, char *value
,
352 struct lxc_conf
*lxc_conf
)
354 struct lxc_netdev
*netdev
;
356 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
360 if (get_u16(&netdev
->priv
.vlan_attr
.vid
, value
, 0))
366 static int config_network_mtu(const char *key
, char *value
,
367 struct lxc_conf
*lxc_conf
)
369 struct lxc_netdev
*netdev
;
371 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
375 netdev
->mtu
= strdup(value
);
377 SYSERROR("failed to dup string '%s'", value
);
384 static int config_network_ipv4(const char *key
, char *value
,
385 struct lxc_conf
*lxc_conf
)
387 struct lxc_netdev
*netdev
;
388 struct lxc_inetdev
*inetdev
;
389 struct lxc_list
*list
;
390 char *cursor
, *slash
, *addr
= NULL
, *bcast
= NULL
, *prefix
= NULL
;
392 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
396 inetdev
= malloc(sizeof(*inetdev
));
398 SYSERROR("failed to allocate ipv4 address");
401 memset(inetdev
, 0, sizeof(*inetdev
));
403 list
= malloc(sizeof(*list
));
405 SYSERROR("failed to allocate memory");
410 list
->elem
= inetdev
;
414 cursor
= strstr(addr
, " ");
420 slash
= strstr(addr
, "/");
427 ERROR("no address specified");
431 if (!inet_pton(AF_INET
, addr
, &inetdev
->addr
)) {
432 SYSERROR("invalid ipv4 address: %s", value
);
436 if (bcast
&& !inet_pton(AF_INET
, bcast
, &inetdev
->bcast
)) {
437 SYSERROR("invalid ipv4 broadcast address: %s", value
);
441 /* no prefix specified, determine it from the network class */
442 inetdev
->prefix
= prefix
? atoi(prefix
) :
443 config_ip_prefix(&inetdev
->addr
);
445 /* if no broadcast address, let compute one from the
449 inetdev
->bcast
.s_addr
= inetdev
->addr
.s_addr
;
450 inetdev
->bcast
.s_addr
|=
451 htonl(INADDR_BROADCAST
>> inetdev
->prefix
);
454 lxc_list_add(&netdev
->ipv4
, list
);
459 static int config_network_ipv4_gateway(const char *key
, char *value
,
460 struct lxc_conf
*lxc_conf
)
462 struct lxc_netdev
*netdev
;
465 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
469 gw
= malloc(sizeof(*gw
));
471 SYSERROR("failed to allocate ipv4 gateway address");
476 ERROR("no ipv4 gateway address specified");
480 if (!strcmp(value
, "auto")) {
481 netdev
->ipv4_gateway
= NULL
;
482 netdev
->ipv4_gateway_auto
= true;
484 if (!inet_pton(AF_INET
, value
, gw
)) {
485 SYSERROR("invalid ipv4 gateway address: %s", value
);
489 netdev
->ipv4_gateway
= gw
;
490 netdev
->ipv4_gateway_auto
= false;
496 static int config_network_ipv6(const char *key
, char *value
,
497 struct lxc_conf
*lxc_conf
)
499 struct lxc_netdev
*netdev
;
500 struct lxc_inet6dev
*inet6dev
;
501 struct lxc_list
*list
;
505 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
509 inet6dev
= malloc(sizeof(*inet6dev
));
511 SYSERROR("failed to allocate ipv6 address");
514 memset(inet6dev
, 0, sizeof(*inet6dev
));
516 list
= malloc(sizeof(*list
));
518 SYSERROR("failed to allocate memory");
523 list
->elem
= inet6dev
;
525 inet6dev
->prefix
= 64;
526 slash
= strstr(value
, "/");
530 inet6dev
->prefix
= atoi(netmask
);
533 if (!inet_pton(AF_INET6
, value
, &inet6dev
->addr
)) {
534 SYSERROR("invalid ipv6 address: %s", value
);
538 lxc_list_add(&netdev
->ipv6
, list
);
543 static int config_network_ipv6_gateway(const char *key
, char *value
,
544 struct lxc_conf
*lxc_conf
)
546 struct lxc_netdev
*netdev
;
549 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
553 gw
= malloc(sizeof(*gw
));
555 SYSERROR("failed to allocate ipv6 gateway address");
560 ERROR("no ipv6 gateway address specified");
564 if (!strcmp(value
, "auto")) {
565 netdev
->ipv6_gateway
= NULL
;
566 netdev
->ipv6_gateway_auto
= true;
568 if (!inet_pton(AF_INET6
, value
, gw
)) {
569 SYSERROR("invalid ipv6 gateway address: %s", value
);
573 netdev
->ipv6_gateway
= gw
;
574 netdev
->ipv6_gateway_auto
= false;
580 static int config_network_script(const char *key
, char *value
,
581 struct lxc_conf
*lxc_conf
)
583 struct lxc_netdev
*netdev
;
585 netdev
= network_netdev(key
, value
, &lxc_conf
->network
);
589 char *copy
= strdup(value
);
591 SYSERROR("failed to dup string '%s'", value
);
594 if (strcmp(key
, "lxc.network.script.up") == 0) {
595 netdev
->upscript
= copy
;
598 SYSERROR("Unknown key: %s", key
);
603 static int add_hook(struct lxc_conf
*lxc_conf
, int which
, char *hook
)
605 struct lxc_list
*hooklist
;
607 hooklist
= malloc(sizeof(*hooklist
));
612 hooklist
->elem
= hook
;
613 lxc_list_add_tail(&lxc_conf
->hooks
[which
], hooklist
);
617 static int config_seccomp(const char *key
, char *value
,
618 struct lxc_conf
*lxc_conf
)
622 if (lxc_conf
->seccomp
) {
623 ERROR("seccomp already defined");
626 path
= strdup(value
);
628 SYSERROR("failed to strdup '%s': %m", value
);
632 lxc_conf
->seccomp
= path
;
637 static int config_hook(const char *key
, char *value
,
638 struct lxc_conf
*lxc_conf
)
640 char *copy
= strdup(value
);
642 SYSERROR("failed to dup string '%s'", value
);
645 if (strcmp(key
, "lxc.hook.pre-start") == 0)
646 return add_hook(lxc_conf
, LXCHOOK_PRESTART
, copy
);
647 else if (strcmp(key
, "lxc.hook.mount") == 0)
648 return add_hook(lxc_conf
, LXCHOOK_MOUNT
, copy
);
649 else if (strcmp(key
, "lxc.hook.start") == 0)
650 return add_hook(lxc_conf
, LXCHOOK_START
, copy
);
651 else if (strcmp(key
, "lxc.hook.post-stop") == 0)
652 return add_hook(lxc_conf
, LXCHOOK_POSTSTOP
, copy
);
653 SYSERROR("Unknown key: %s", key
);
658 static int config_personality(const char *key
, char *value
,
659 struct lxc_conf
*lxc_conf
)
661 signed long personality
= lxc_config_parse_arch(value
);
663 if (personality
>= 0)
664 lxc_conf
->personality
= personality
;
666 WARN("unsupported personality '%s'", value
);
671 static int config_pts(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
673 int maxpts
= atoi(value
);
675 lxc_conf
->pts
= maxpts
;
680 static int config_tty(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
682 int nbtty
= atoi(value
);
684 lxc_conf
->tty
= nbtty
;
689 static int config_ttydir(const char *key
, char *value
,
690 struct lxc_conf
*lxc_conf
)
694 if (!value
|| strlen(value
) == 0)
696 path
= strdup(value
);
698 SYSERROR("failed to strdup '%s': %m", value
);
702 lxc_conf
->ttydir
= path
;
708 static int config_aa_profile(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
712 if (!value
|| strlen(value
) == 0)
714 path
= strdup(value
);
716 SYSERROR("failed to strdup '%s': %m", value
);
720 lxc_conf
->aa_profile
= path
;
726 static int config_cgroup(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
728 char *token
= "lxc.cgroup.";
730 struct lxc_list
*cglist
= NULL
;
731 struct lxc_cgroup
*cgelem
= NULL
;
733 subkey
= strstr(key
, token
);
741 if (strlen(subkey
) == strlen(token
))
744 subkey
+= strlen(token
);
746 cglist
= malloc(sizeof(*cglist
));
750 cgelem
= malloc(sizeof(*cgelem
));
753 memset(cgelem
, 0, sizeof(*cgelem
));
755 cgelem
->subsystem
= strdup(subkey
);
756 cgelem
->value
= strdup(value
);
758 if (!cgelem
->subsystem
|| !cgelem
->value
)
761 cglist
->elem
= cgelem
;
763 lxc_list_add_tail(&lxc_conf
->cgroup
, cglist
);
772 if (cgelem
->subsystem
)
773 free(cgelem
->subsystem
);
784 static int config_fstab(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
786 if (strlen(value
) >= MAXPATHLEN
) {
787 ERROR("%s path is too long", value
);
791 lxc_conf
->fstab
= strdup(value
);
792 if (!lxc_conf
->fstab
) {
793 SYSERROR("failed to duplicate string %s", value
);
800 static int config_mount(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
802 char *fstab_token
= "lxc.mount";
803 char *token
= "lxc.mount.entry";
806 struct lxc_list
*mntlist
;
808 subkey
= strstr(key
, token
);
811 subkey
= strstr(key
, fstab_token
);
816 return config_fstab(key
, value
, lxc_conf
);
822 mntlist
= malloc(sizeof(*mntlist
));
826 mntelem
= strdup(value
);
829 mntlist
->elem
= mntelem
;
831 lxc_list_add_tail(&lxc_conf
->mount_list
, mntlist
);
836 static int config_cap_drop(const char *key
, char *value
,
837 struct lxc_conf
*lxc_conf
)
839 char *dropcaps
, *sptr
, *token
;
840 struct lxc_list
*droplist
;
846 dropcaps
= strdup(value
);
848 SYSERROR("failed to dup '%s'", value
);
852 /* in case several capability drop is specified in a single line
853 * split these caps in a single element for the list */
855 token
= strtok_r(dropcaps
, " \t", &sptr
);
862 droplist
= malloc(sizeof(*droplist
));
864 SYSERROR("failed to allocate drop list");
868 droplist
->elem
= strdup(token
);
869 if (!droplist
->elem
) {
870 SYSERROR("failed to dup '%s'", token
);
875 lxc_list_add_tail(&lxc_conf
->caps
, droplist
);
883 static int config_console(const char *key
, char *value
,
884 struct lxc_conf
*lxc_conf
)
888 path
= strdup(value
);
890 SYSERROR("failed to strdup '%s': %m", value
);
894 lxc_conf
->console
.path
= path
;
899 static int config_includefile(const char *key
, char *value
,
900 struct lxc_conf
*lxc_conf
)
902 return lxc_config_read(value
, lxc_conf
);
905 static int config_rootfs(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
907 if (strlen(value
) >= MAXPATHLEN
) {
908 ERROR("%s path is too long", value
);
912 lxc_conf
->rootfs
.path
= strdup(value
);
913 if (!lxc_conf
->rootfs
.path
) {
914 SYSERROR("failed to duplicate string %s", value
);
921 static int config_rootfs_mount(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
923 if (strlen(value
) >= MAXPATHLEN
) {
924 ERROR("%s path is too long", value
);
928 lxc_conf
->rootfs
.mount
= strdup(value
);
929 if (!lxc_conf
->rootfs
.mount
) {
930 SYSERROR("failed to duplicate string '%s'", value
);
937 static int config_pivotdir(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
939 if (strlen(value
) >= MAXPATHLEN
) {
940 ERROR("%s path is too long", value
);
944 lxc_conf
->rootfs
.pivot
= strdup(value
);
945 if (!lxc_conf
->rootfs
.pivot
) {
946 SYSERROR("failed to duplicate string %s", value
);
953 static int config_utsname(const char *key
, char *value
, struct lxc_conf
*lxc_conf
)
955 struct utsname
*utsname
;
957 utsname
= malloc(sizeof(*utsname
));
959 SYSERROR("failed to allocate memory");
963 if (strlen(value
) >= sizeof(utsname
->nodename
)) {
964 ERROR("node name '%s' is too long",
969 strcpy(utsname
->nodename
, value
);
970 lxc_conf
->utsname
= utsname
;
975 static int parse_line(char *buffer
, void *data
)
977 struct config
*config
;
984 if (lxc_is_line_empty(buffer
))
987 /* we have to dup the buffer otherwise, at the re-exec for
988 * reboot we modified the original string on the stack by
989 * replacing '=' by '\0' below
991 linep
= line
= strdup(buffer
);
993 SYSERROR("failed to allocate memory for '%s'", buffer
);
997 line
+= lxc_char_left_gc(line
, strlen(line
));
999 /* martian option - ignoring it, the commented lines beginning by '#'
1002 if (strncmp(line
, "lxc.", 4))
1007 dot
= strstr(line
, "=");
1009 ERROR("invalid configuration line: %s", line
);
1017 key
[lxc_char_right_gc(key
, strlen(key
))] = '\0';
1019 value
+= lxc_char_left_gc(value
, strlen(value
));
1020 value
[lxc_char_right_gc(value
, strlen(value
))] = '\0';
1022 config
= getconfig(key
);
1024 ERROR("unknown key %s", key
);
1028 ret
= config
->cb(key
, value
, data
);
1035 int lxc_config_readline(char *buffer
, struct lxc_conf
*conf
)
1037 return parse_line(buffer
, conf
);
1040 int lxc_config_read(const char *file
, struct lxc_conf
*conf
)
1042 return lxc_file_for_each_line(file
, parse_line
, conf
);
1045 int lxc_config_define_add(struct lxc_list
*defines
, char* arg
)
1047 struct lxc_list
*dent
;
1049 dent
= malloc(sizeof(struct lxc_list
));
1054 lxc_list_add_tail(defines
, dent
);
1058 int lxc_config_define_load(struct lxc_list
*defines
, struct lxc_conf
*conf
)
1060 struct lxc_list
*it
;
1063 lxc_list_for_each(it
, defines
) {
1064 ret
= lxc_config_readline(it
->elem
, conf
);
1069 lxc_list_for_each(it
, defines
) {
1077 signed long lxc_config_parse_arch(const char *arch
)
1083 { "x86", PER_LINUX32
},
1084 { "i686", PER_LINUX32
},
1085 { "x86_64", PER_LINUX
},
1086 { "amd64", PER_LINUX
},
1088 size_t len
= sizeof(pername
) / sizeof(pername
[0]);
1092 for (i
= 0; i
< len
; i
++) {
1093 if (!strcmp(pername
[i
].name
, arch
))
1094 return pername
[i
].per
;