confile.c revision 91480a0f0a62732f3115d556b689d62d574294ae
1057N/A/*
1057N/A * lxc: linux Container library
1057N/A *
1057N/A * (C) Copyright IBM Corp. 2007, 2008
1589N/A *
1057N/A * Authors:
660N/A * Daniel Lezcano <dlezcano at fr.ibm.com>
1057N/A *
1057N/A * This library is free software; you can redistribute it and/or
1057N/A * modify it under the terms of the GNU Lesser General Public
1057N/A * License as published by the Free Software Foundation; either
1057N/A * version 2.1 of the License, or (at your option) any later version.
1057N/A *
1057N/A * This library is distributed in the hope that it will be useful,
1057N/A * but WITHOUT ANY WARRANTY; without even the implied warranty of
1057N/A * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1057N/A * Lesser General Public License for more details.
1057N/A *
1057N/A * You should have received a copy of the GNU Lesser General Public
1057N/A * License along with this library; if not, write to the Free Software
660N/A * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
3311N/A */
1109N/A#include <stdio.h>
2506N/A#include <stdlib.h>
3473N/A#include <string.h>
3473N/A#include <unistd.h>
3473N/A#include <errno.h>
2437N/A#include <fcntl.h>
2437N/A#include <pty.h>
2437N/A#include <sys/stat.h>
3356N/A#include <sys/types.h>
3356N/A#include <sys/param.h>
2506N/A#include <sys/utsname.h>
3473N/A#include <arpa/inet.h>
2737N/A#include <netinet/in.h>
2737N/A#include <net/if.h>
2557N/A
2557N/A#include "parse.h"
2557N/A#include "utils.h"
3421N/A
3404N/A#include <lxc/log.h>
2557N/A#include <lxc/conf.h>
3421N/A
3404N/Alxc_log_define(lxc_confile, lxc);
3473N/A
3404N/Astatic int config_pts(const char *, char *, struct lxc_conf *);
3404N/Astatic int config_tty(const char *, char *, struct lxc_conf *);
2557N/Astatic int config_cgroup(const char *, char *, struct lxc_conf *);
2557N/Astatic int config_mount(const char *, char *, struct lxc_conf *);
3421N/Astatic int config_rootfs(const char *, char *, struct lxc_conf *);
3404N/Astatic int config_pivotdir(const char *, char *, struct lxc_conf *);
2437N/Astatic int config_utsname(const char *, char *, struct lxc_conf *);
3421N/Astatic int config_network_type(const char *, char *, struct lxc_conf *);
3404N/Astatic int config_network_flags(const char *, char *, struct lxc_conf *);
3473N/Astatic int config_network_link(const char *, char *, struct lxc_conf *);
3404N/Astatic int config_network_name(const char *, char *, struct lxc_conf *);
3404N/Astatic int config_network_veth_pair(const char *, char *, struct lxc_conf *);
2557N/Astatic int config_network_macvlan_mode(const char *, char *, struct lxc_conf *);
2557N/Astatic int config_network_hwaddr(const char *, char *, struct lxc_conf *);
2557N/Astatic int config_network_vlan_id(const char *, char *, struct lxc_conf *);
3421N/Astatic int config_network_mtu(const char *, char *, struct lxc_conf *);
3404N/Astatic int config_network_ipv4(const char *, char *, struct lxc_conf *);
2557N/Astatic int config_network_ipv6(const char *, char *, struct lxc_conf *);
3421N/Astatic int config_cap_drop(const char *, char *, struct lxc_conf *);
3404N/Astatic int config_console(const char *, char *, struct lxc_conf *);
3473N/A
3404N/Atypedef int (*config_cb)(const char *, char *, struct lxc_conf *);
3404N/A
2437N/Astruct config {
3404N/A char *name;
3404N/A config_cb cb;
3473N/A};
3404N/A
3404N/Astatic struct config config[] = {
3404N/A
3473N/A { "lxc.pts", config_pts },
3404N/A { "lxc.tty", config_tty },
3404N/A { "lxc.cgroup", config_cgroup },
3404N/A { "lxc.mount", config_mount },
3473N/A { "lxc.rootfs", config_rootfs },
2437N/A { "lxc.pivotdir", config_pivotdir },
2437N/A { "lxc.utsname", config_utsname },
2437N/A { "lxc.network.type", config_network_type },
2437N/A { "lxc.network.flags", config_network_flags },
2506N/A { "lxc.network.link", config_network_link },
2506N/A { "lxc.network.name", config_network_name },
3473N/A { "lxc.network.macvlan.mode", config_network_macvlan_mode },
2095N/A { "lxc.network.veth.pair", config_network_veth_pair },
2437N/A { "lxc.network.hwaddr", config_network_hwaddr },
2437N/A { "lxc.network.mtu", config_network_mtu },
3473N/A { "lxc.network.vlan.id", config_network_vlan_id },
3404N/A { "lxc.network.ipv4", config_network_ipv4 },
3404N/A { "lxc.network.ipv6", config_network_ipv6 },
3404N/A { "lxc.cap.drop", config_cap_drop },
3404N/A { "lxc.console", config_console },
3404N/A};
3473N/A
3404N/Astatic const size_t config_size = sizeof(config)/sizeof(struct config);
3404N/A
3404N/Astatic struct config *getconfig(const char *key)
3404N/A{
3404N/A int i;
3404N/A
3404N/A for (i = 0; i < config_size; i++)
3404N/A if (!strncmp(config[i].name, key,
3473N/A strlen(config[i].name)))
2557N/A return &config[i];
2557N/A return NULL;
2557N/A}
2557N/A
2557N/Astatic int config_network_type(const char *key, char *value,
2557N/A struct lxc_conf *lxc_conf)
2557N/A{
3473N/A struct lxc_list *network = &lxc_conf->network;
2095N/A struct lxc_netdev *netdev;
2095N/A struct lxc_list *list;
2095N/A
2095N/A netdev = malloc(sizeof(*netdev));
2095N/A if (!netdev) {
2437N/A SYSERROR("failed to allocate memory");
2506N/A return -1;
2506N/A }
2506N/A
3473N/A memset(netdev, 0, sizeof(*netdev));
3404N/A lxc_list_init(&netdev->ipv4);
3404N/A lxc_list_init(&netdev->ipv6);
3404N/A
2557N/A list = malloc(sizeof(*list));
2557N/A if (!list) {
3421N/A SYSERROR("failed to allocate memory");
3404N/A return -1;
3404N/A }
2557N/A
3421N/A lxc_list_init(list);
3404N/A list->elem = netdev;
3473N/A
3404N/A lxc_list_add(network, list);
3404N/A
3404N/A if (!strcmp(value, "veth"))
2557N/A netdev->type = LXC_NET_VETH;
2557N/A else if (!strcmp(value, "macvlan"))
3421N/A netdev->type = LXC_NET_MACVLAN;
3404N/A else if (!strcmp(value, "vlan"))
3404N/A netdev->type = LXC_NET_VLAN;
2557N/A else if (!strcmp(value, "phys"))
3421N/A netdev->type = LXC_NET_PHYS;
3404N/A else if (!strcmp(value, "empty"))
3473N/A netdev->type = LXC_NET_EMPTY;
2506N/A else {
2506N/A ERROR("invalid network type %s", value);
2506N/A return -1;
3473N/A }
2557N/A return 0;
2557N/A}
2557N/A
2557N/Astatic int config_ip_prefix(struct in_addr *addr)
2506N/A{
2506N/A if (IN_CLASSA(addr->s_addr))
2557N/A return 32 - IN_CLASSA_NSHIFT;
2557N/A if (IN_CLASSB(addr->s_addr))
3473N/A return 32 - IN_CLASSB_NSHIFT;
2557N/A if (IN_CLASSC(addr->s_addr))
2557N/A return 32 - IN_CLASSC_NSHIFT;
2557N/A
2557N/A return 0;
2557N/A}
2557N/A
2557N/Astatic struct lxc_netdev *network_netdev(const char *key, const char *value,
3473N/A struct lxc_list *network)
3404N/A{
3404N/A struct lxc_netdev *netdev;
3404N/A
3473N/A if (lxc_list_empty(network)) {
2437N/A ERROR("network is not created for '%s' = '%s' option",
2437N/A key, value);
2437N/A return NULL;
3473N/A }
2506N/A
2506N/A netdev = lxc_list_first_elem(network);
2506N/A if (!netdev) {
3473N/A ERROR("no network device defined for '%s' = '%s' option",
2506N/A key, value);
2506N/A return NULL;
2506N/A }
3473N/A
2095N/A return netdev;
3473N/A}
3473N/A
3473N/Astatic int network_ifname(char **valuep, char *value)
2095N/A{
3473N/A if (strlen(value) > IFNAMSIZ) {
3473N/A ERROR("invalid interface name: %s", value);
3473N/A return -1;
2095N/A }
2437N/A
2437N/A *valuep = strdup(value);
3473N/A if (!*valuep) {
2095N/A ERROR("failed to dup string '%s'", value);
2095N/A return -1;
2095N/A }
2095N/A
2095N/A return 0;
2095N/A}
2095N/A
2095N/A#ifndef MACVLAN_MODE_PRIVATE
2095N/A# define MACVLAN_MODE_PRIVATE 1
2095N/A#endif
2506N/A
2095N/A#ifndef MACVLAN_MODE_VEPA
2095N/A# define MACVLAN_MODE_VEPA 2
2095N/A#endif
2095N/A
2095N/A#ifndef MACVLAN_MODE_BRIDGE
2095N/A# define MACVLAN_MODE_BRIDGE 4
2095N/A#endif
2737N/A
2095N/Astatic int macvlan_mode(int *valuep, char *value)
2737N/A{
2737N/A struct mc_mode {
3473N/A char *name;
2095N/A int mode;
3473N/A } m[] = {
3473N/A { "private", MACVLAN_MODE_PRIVATE },
3473N/A { "vepa", MACVLAN_MODE_VEPA },
2737N/A { "bridge", MACVLAN_MODE_BRIDGE },
2737N/A };
2737N/A
3473N/A int i;
2737N/A
2737N/A for (i = 0; i < sizeof(m)/sizeof(m[0]); i++) {
2737N/A if (strcmp(m[i].name, value))
3473N/A continue;
3404N/A
3404N/A *valuep = m[i].mode;
3404N/A return 0;
3404N/A }
3404N/A
3404N/A return -1;
3404N/A}
3404N/A
3473N/Astatic int config_network_flags(const char *key, char *value,
3404N/A struct lxc_conf *lxc_conf)
3404N/A{
3404N/A struct lxc_netdev *netdev;
3473N/A
3404N/A netdev = network_netdev(key, value, &lxc_conf->network);
3404N/A if (!netdev)
3404N/A return -1;
3473N/A
2437N/A netdev->flags |= IFF_UP;
2437N/A
2437N/A return 0;
3473N/A}
2737N/A
2737N/Astatic int config_network_link(const char *key, char *value,
2543N/A struct lxc_conf *lxc_conf)
2437N/A{
2437N/A struct lxc_netdev *netdev;
2437N/A
2737N/A netdev = network_netdev(key, value, &lxc_conf->network);
2737N/A if (!netdev)
3473N/A return -1;
3404N/A
3404N/A return network_ifname(&netdev->link, value);
3404N/A}
3473N/A
2543N/Astatic int config_network_name(const char *key, char *value,
2543N/A struct lxc_conf *lxc_conf)
2543N/A{
3473N/A struct lxc_netdev *netdev;
3404N/A
3404N/A netdev = network_netdev(key, value, &lxc_conf->network);
3404N/A if (!netdev)
3473N/A return -1;
2737N/A
2737N/A return network_ifname(&netdev->name, value);
2543N/A}
2437N/A
2737N/Astatic int config_network_veth_pair(const char *key, char *value,
2737N/A struct lxc_conf *lxc_conf)
3473N/A{
2437N/A struct lxc_netdev *netdev;
2437N/A
2437N/A netdev = network_netdev(key, value, &lxc_conf->network);
2437N/A if (!netdev)
2506N/A return -1;
2095N/A
3473N/A return network_ifname(&netdev->priv.veth_attr.pair, value);
2557N/A}
2557N/A
2557N/Astatic int config_network_macvlan_mode(const char *key, char *value,
3473N/A struct lxc_conf *lxc_conf)
2557N/A{
2557N/A struct lxc_netdev *netdev;
2557N/A
3473N/A netdev = network_netdev(key, value, &lxc_conf->network);
3404N/A if (!netdev)
3404N/A return -1;
3404N/A
3404N/A return macvlan_mode(&netdev->priv.macvlan_attr.mode, value);
3404N/A}
3404N/A
3473N/Astatic int config_network_hwaddr(const char *key, char *value,
3404N/A struct lxc_conf *lxc_conf)
3404N/A{
3404N/A struct lxc_netdev *netdev;
3404N/A
3473N/A netdev = network_netdev(key, value, &lxc_conf->network);
684N/A if (!netdev)
684N/A return -1;
684N/A
2506N/A netdev->hwaddr = strdup(value);
2506N/A if (!netdev->hwaddr) {
3473N/A SYSERROR("failed to dup string '%s'", value);
2095N/A return -1;
2095N/A }
2095N/A
3473N/A return 0;
2095N/A}
684N/A
2095N/Astatic int config_network_vlan_id(const char *key, char *value,
2506N/A struct lxc_conf *lxc_conf)
2506N/A{
3473N/A struct lxc_netdev *netdev;
2095N/A
684N/A netdev = network_netdev(key, value, &lxc_conf->network);
684N/A if (!netdev)
684N/A return -1;
3404N/A
1057N/A if (get_u16(&netdev->priv.vlan_attr.vid, value, 0))
684N/A return -1;
684N/A
684N/A return 0;
3404N/A}
3404N/A
3404N/Astatic int config_network_mtu(const char *key, char *value,
3473N/A struct lxc_conf *lxc_conf)
3404N/A{
3404N/A struct lxc_netdev *netdev;
3404N/A
3473N/A netdev = network_netdev(key, value, &lxc_conf->network);
3404N/A if (!netdev)
3404N/A return -1;
3404N/A
3473N/A netdev->mtu = strdup(value);
3404N/A if (!netdev->mtu) {
3404N/A SYSERROR("failed to dup string '%s'", value);
3404N/A return -1;
3404N/A }
3404N/A
3404N/A return 0;
3404N/A}
3404N/A
3404N/Astatic int config_network_ipv4(const char *key, char *value,
3404N/A struct lxc_conf *lxc_conf)
3404N/A{
3404N/A struct lxc_netdev *netdev;
3404N/A struct lxc_inetdev *inetdev;
3404N/A struct lxc_list *list;
3404N/A char *cursor, *slash, *addr = NULL, *bcast = NULL, *prefix = NULL;
3404N/A
3404N/A netdev = network_netdev(key, value, &lxc_conf->network);
3404N/A if (!netdev)
3404N/A return -1;
3473N/A
3404N/A inetdev = malloc(sizeof(*inetdev));
3404N/A if (!inetdev) {
3404N/A SYSERROR("failed to allocate ipv4 address");
3404N/A return -1;
3404N/A }
3404N/A memset(inetdev, 0, sizeof(*inetdev));
3473N/A
3404N/A list = malloc(sizeof(*list));
3404N/A if (!list) {
3404N/A SYSERROR("failed to allocate memory");
3404N/A return -1;
3404N/A }
3404N/A
3473N/A lxc_list_init(list);
3404N/A list->elem = inetdev;
3404N/A
3404N/A addr = value;
3473N/A
3404N/A cursor = strstr(addr, " ");
3404N/A if (cursor) {
3404N/A *cursor = '\0';
3473N/A bcast = cursor + 1;
3404N/A }
3404N/A
3404N/A slash = strstr(addr, "/");
3473N/A if (slash) {
3404N/A *slash = '\0';
3404N/A prefix = slash + 1;
3404N/A }
3473N/A
3404N/A if (!addr) {
3404N/A ERROR("no address specified");
3404N/A return -1;
3473N/A }
3404N/A
3404N/A if (!inet_pton(AF_INET, addr, &inetdev->addr)) {
3404N/A SYSERROR("invalid ipv4 address: %s", value);
3473N/A return -1;
3404N/A }
3404N/A
3404N/A if (bcast)
3473N/A if (!inet_pton(AF_INET, bcast, &inetdev->bcast)) {
3404N/A SYSERROR("invalid ipv4 address: %s", value);
3404N/A return -1;
3404N/A }
3473N/A
3404N/A /* no prefix specified, determine it from the network class */
3404N/A inetdev->prefix = prefix ? atoi(prefix) :
3404N/A config_ip_prefix(&inetdev->addr);
3473N/A
3404N/A
3404N/A lxc_list_add(&netdev->ipv4, list);
3404N/A
3473N/A return 0;
3404N/A}
3404N/A
3404N/Astatic int config_network_ipv6(const char *key, char *value,
3473N/A struct lxc_conf *lxc_conf)
3404N/A{
3404N/A struct lxc_netdev *netdev;
3404N/A struct lxc_inet6dev *inet6dev;
3473N/A struct lxc_list *list;
3404N/A char *slash;
3404N/A char *netmask;
3404N/A
3404N/A netdev = network_netdev(key, value, &lxc_conf->network);
3404N/A if (!netdev)
3473N/A return -1;
3404N/A
3404N/A inet6dev = malloc(sizeof(*inet6dev));
3404N/A if (!inet6dev) {
3473N/A SYSERROR("failed to allocate ipv6 address");
3404N/A return -1;
3404N/A }
3404N/A memset(inet6dev, 0, sizeof(*inet6dev));
3473N/A
3404N/A list = malloc(sizeof(*list));
3404N/A if (!list) {
3404N/A SYSERROR("failed to allocate memory");
3404N/A return -1;
3473N/A }
3473N/A
3473N/A lxc_list_init(list);
3473N/A list->elem = inet6dev;
3404N/A
3404N/A inet6dev->prefix = 64;
3404N/A slash = strstr(value, "/");
3473N/A if (slash) {
3404N/A *slash = '\0';
3404N/A netmask = slash + 1;
3404N/A inet6dev->prefix = atoi(netmask);
3473N/A }
3404N/A
3404N/A if (!inet_pton(AF_INET6, value, &inet6dev->addr)) {
3404N/A SYSERROR("invalid ipv6 address: %s", value);
3473N/A return -1;
3404N/A }
3404N/A
3404N/A lxc_list_add(&netdev->ipv6, list);
3473N/A
3404N/A return 0;
3404N/A}
3404N/A
3473N/Astatic int config_pts(const char *key, char *value, struct lxc_conf *lxc_conf)
3404N/A{
3404N/A int maxpts = atoi(value);
3404N/A
3473N/A lxc_conf->pts = maxpts;
3404N/A
3404N/A return 0;
3404N/A}
3473N/A
3404N/Astatic int config_tty(const char *key, char *value, struct lxc_conf *lxc_conf)
3404N/A{
3404N/A int nbtty = atoi(value);
3473N/A
3404N/A lxc_conf->tty = nbtty;
3404N/A
3404N/A return 0;
3473N/A}
3404N/A
3404N/Astatic int config_cgroup(const char *key, char *value, struct lxc_conf *lxc_conf)
3404N/A{
3404N/A char *token = "lxc.cgroup.";
3473N/A char *subkey;
3473N/A struct lxc_list *cglist;
3473N/A struct lxc_cgroup *cgelem;
3473N/A
3404N/A subkey = strstr(key, token);
3404N/A
3404N/A if (!subkey)
3473N/A return -1;
3404N/A
3404N/A if (!strlen(subkey))
3404N/A return -1;
3473N/A
3404N/A if (strlen(subkey) == strlen(token))
3404N/A return -1;
3404N/A
3404N/A subkey += strlen(token);
3473N/A
3404N/A cglist = malloc(sizeof(*cglist));
3404N/A if (!cglist)
3404N/A return -1;
3473N/A
3404N/A cgelem = malloc(sizeof(*cgelem));
3404N/A if (!cgelem) {
3404N/A free(cglist);
3404N/A return -1;
3473N/A }
3404N/A
3404N/A cgelem->subsystem = strdup(subkey);
3404N/A cgelem->value = strdup(value);
3404N/A cglist->elem = cgelem;
3473N/A
3404N/A lxc_list_add_tail(&lxc_conf->cgroup, cglist);
3404N/A
3404N/A return 0;
3473N/A}
3404N/A
3404N/Astatic int config_fstab(const char *key, char *value, struct lxc_conf *lxc_conf)
3404N/A{
3473N/A if (strlen(value) >= MAXPATHLEN) {
3404N/A ERROR("%s path is too long", value);
3404N/A return -1;
3404N/A }
3404N/A
3473N/A lxc_conf->fstab = strdup(value);
3404N/A if (!lxc_conf->fstab) {
3404N/A SYSERROR("failed to duplicate string %s", value);
3404N/A return -1;
3404N/A }
3473N/A
3404N/A return 0;
3404N/A}
3404N/A
3404N/Astatic int config_mount(const char *key, char *value, struct lxc_conf *lxc_conf)
3473N/A{
3404N/A char *fstab_token = "lxc.mount";
3404N/A char *token = "lxc.mount.entry";
3404N/A char *subkey;
3473N/A char *mntelem;
3473N/A struct lxc_list *mntlist;
3404N/A
3404N/A subkey = strstr(key, token);
3404N/A
3404N/A if (!subkey) {
3473N/A subkey = strstr(key, fstab_token);
3404N/A
3404N/A if (!subkey)
3404N/A return -1;
3404N/A
3404N/A return config_fstab(key, value, lxc_conf);
3404N/A }
3473N/A
3404N/A if (!strlen(subkey))
3404N/A return -1;
3404N/A
3404N/A mntlist = malloc(sizeof(*mntlist));
3404N/A if (!mntlist)
3404N/A return -1;
3473N/A
3404N/A mntelem = strdup(value);
3404N/A mntlist->elem = mntelem;
3404N/A
3404N/A lxc_list_add_tail(&lxc_conf->mount_list, mntlist);
3473N/A
3404N/A return 0;
3404N/A}
3404N/A
3473N/Astatic int config_cap_drop(const char *key, char *value,
3404N/A struct lxc_conf *lxc_conf)
3404N/A{
3404N/A char *dropcaps, *sptr, *token;
3404N/A struct lxc_list *droplist;
3473N/A int ret = -1;
3404N/A
3404N/A if (!strlen(value))
3404N/A return -1;
3404N/A
3404N/A dropcaps = strdup(value);
3404N/A if (!dropcaps) {
3473N/A SYSERROR("failed to dup '%s'", value);
3404N/A return -1;
3404N/A }
3404N/A
3404N/A /* in case several capability drop is specified in a single line
3473N/A * split these caps in a single element for the list */
3473N/A for (;;) {
3473N/A token = strtok_r(dropcaps, " \t", &sptr);
3473N/A if (!token) {
3473N/A ret = 0;
3473N/A break;
1703N/A }
1703N/A dropcaps = NULL;
3404N/A
3404N/A droplist = malloc(sizeof(*droplist));
3404N/A if (!droplist) {
3473N/A SYSERROR("failed to allocate drop list");
1703N/A break;
1703N/A }
1703N/A
1703N/A droplist->elem = strdup(token);
2506N/A if (!droplist->elem) {
2506N/A SYSERROR("failed to dup '%s'", token);
3473N/A free(droplist);
3404N/A break;
3404N/A }
3404N/A
3404N/A lxc_list_add_tail(&lxc_conf->caps, droplist);
3404N/A }
3404N/A
3473N/A free(dropcaps);
3404N/A
3404N/A return ret;
3404N/A}
3404N/A
3473N/Astatic int _config_console(const char *key, char *value, struct lxc_conf *lxc_conf)
3404N/A{
3404N/A int fd;
3404N/A
3404N/A fd = open(value, O_CLOEXEC | O_RDWR | O_CREAT | O_APPEND, 0600);
3404N/A if (fd < 0) {
3404N/A SYSERROR("failed to open '%s'", value);
3404N/A return -1;
3473N/A }
3404N/A
3404N/A lxc_conf->console.peer = fd;
3404N/A
3404N/A return 0;
3473N/A}
3404N/A
3404N/Astatic int config_console(const char *key, char *value,
3404N/A struct lxc_conf *lxc_conf)
1589N/A{
1589N/A char *path;
3404N/A
3404N/A path = strdup(value);
3473N/A if (!path) {
2437N/A SYSERROR("failed to strdup '%s': %m", value);
2437N/A return -1;
2437N/A }
2437N/A
2506N/A lxc_conf->console.path = path;
2506N/A
3473N/A return 0;
3404N/A}
3404N/A
3404N/Astatic int config_rootfs(const char *key, char *value, struct lxc_conf *lxc_conf)
3404N/A{
3473N/A if (strlen(value) >= MAXPATHLEN) {
2437N/A ERROR("%s path is too long", value);
2437N/A return -1;
2437N/A }
2506N/A
2506N/A lxc_conf->rootfs = strdup(value);
2506N/A if (!lxc_conf->rootfs) {
3473N/A SYSERROR("failed to duplicate string %s", value);
3404N/A return -1;
3404N/A }
3404N/A
3404N/A return 0;
3473N/A}
3404N/A
3473N/Astatic int config_pivotdir(const char *key, char *value, struct lxc_conf *lxc_conf)
3404N/A{
3404N/A if (strlen(value) >= MAXPATHLEN) {
3404N/A ERROR("%s path is too long", value);
3404N/A return -1;
3473N/A }
2437N/A
2437N/A lxc_conf->pivotdir = strdup(value);
2437N/A if (!lxc_conf->pivotdir) {
3473N/A SYSERROR("failed to duplicate string %s", value);
3404N/A return -1;
3404N/A }
3404N/A
3404N/A return 0;
3404N/A}
3404N/A
3473N/Astatic int config_utsname(const char *key, char *value, struct lxc_conf *lxc_conf)
3404N/A{
660N/A struct utsname *utsname;
3356N/A
3404N/A utsname = malloc(sizeof(*utsname));
3404N/A if (!utsname) {
3404N/A SYSERROR("failed to allocate memory");
3404N/A return -1;
3473N/A }
2437N/A
2437N/A if (strlen(value) >= sizeof(utsname->nodename)) {
2437N/A ERROR("node name '%s' is too long",
3473N/A utsname->nodename);
2437N/A return -1;
2437N/A }
2506N/A
2506N/A strcpy(utsname->nodename, value);
3473N/A lxc_conf->utsname = utsname;
3404N/A
3404N/A return 0;
3404N/A}
3404N/A
3473N/Astatic int parse_line(char *buffer, void *data)
3404N/A{
3404N/A struct config *config;
3404N/A char *line;
3404N/A char *dot;
3473N/A char *key;
3404N/A char *value;
3404N/A int ret = -1;
3404N/A
3404N/A if (lxc_is_line_empty(buffer))
3473N/A return 0;
3404N/A
3404N/A /* we have to dup the buffer otherwise, at the re-exec for reboot we modified
3404N/A * the original string on the stack by replacing '=' by '\0' below
3404N/A */
3473N/A line = strdup(buffer);
3404N/A if (!line) {
3404N/A SYSERROR("failed to allocate memory for '%s'", buffer);
3404N/A goto out;
3404N/A }
3473N/A
3404N/A line += lxc_char_left_gc(line, strlen(line));
3404N/A if (line[0] == '#') {
3404N/A ret = 0;
3404N/A goto out;
3473N/A }
3404N/A
3404N/A dot = strstr(line, "=");
3404N/A if (!dot) {
3404N/A ERROR("invalid configuration line: %s", line);
3404N/A goto out;
3404N/A }
3473N/A
3404N/A *dot = '\0';
3404N/A value = dot + 1;
3404N/A
3404N/A key = line;
3404N/A key[lxc_char_right_gc(key, strlen(key))] = '\0';
3404N/A
3404N/A value += lxc_char_left_gc(value, strlen(value));
3404N/A value[lxc_char_right_gc(value, strlen(value))] = '\0';
3404N/A
3404N/A config = getconfig(key);
3473N/A if (!config) {
2557N/A ERROR("unknow key %s", key);
2557N/A goto out;
2557N/A }
3473N/A
2506N/A ret = config->cb(key, value, data);
2506N/A
2506N/Aout:
3473N/A free(line);
2506N/A return ret;
2506N/A}
2506N/A
3473N/Aint lxc_config_readline(char *buffer, struct lxc_conf *conf)
3473N/A{
2506N/A return parse_line(buffer, conf);
2506N/A}
2506N/A
3473N/Aint lxc_config_read(const char *file, struct lxc_conf *conf)
2506N/A{
2506N/A return lxc_file_for_each_line(file, parse_line, conf);
2506N/A}
3473N/A
2506N/Aint lxc_config_define_add(struct lxc_list *defines, char* arg)
2506N/A{
2506N/A struct lxc_list *dent;
3473N/A
2506N/A dent = malloc(sizeof(struct lxc_list));
2506N/A if (!dent)
2506N/A return -1;
3473N/A
3404N/A dent->elem = arg;
3404N/A lxc_list_add_tail(defines, dent);
3404N/A return 0;
3404N/A}
3404N/A
3404N/Aint lxc_config_define_load(struct lxc_list *defines, struct lxc_conf *conf)
2506N/A{
3473N/A struct lxc_list *it;
2506N/A int ret = 0;
2506N/A
2506N/A lxc_list_for_each(it, defines) {
3473N/A ret = lxc_config_readline(it->elem, conf);
2506N/A if (ret)
2506N/A break;
2506N/A }
3473N/A
2506N/A lxc_list_for_each(it, defines) {
2506N/A lxc_list_del(it);
2506N/A free(it);
2506N/A }
3473N/A
2506N/A return ret;
2506N/A}
2506N/A