Merge lp:~ubuntu-branches/ubuntu/precise/lxc/precise-201202110437 into lp:ubuntu/precise/lxc

Proposed by Ubuntu Package Importer
Status: Needs review
Proposed branch: lp:~ubuntu-branches/ubuntu/precise/lxc/precise-201202110437
Merge into: lp:ubuntu/precise/lxc
Diff against target: 3940 lines (+3890/-0) (has conflicts)
8 files modified
.pc/.quilt_patches (+1/-0)
.pc/.quilt_series (+1/-0)
.pc/0040-consoles-into-devlxc.patch/src/lxc/conf.c (+1767/-0)
.pc/0040-consoles-into-devlxc.patch/src/lxc/conf.h (+230/-0)
.pc/0040-consoles-into-devlxc.patch/src/lxc/confile.c (+898/-0)
.pc/0041-ubuntu-template-user-and-tty/templates/lxc-ubuntu.in (+595/-0)
debian/patches/0040-consoles-into-devlxc.patch (+278/-0)
debian/patches/0041-ubuntu-template-user-and-tty (+120/-0)
Conflict adding file .pc/0040-consoles-into-devlxc.patch.  Moved existing file to .pc/0040-consoles-into-devlxc.patch.moved.
Conflict adding file .pc/0041-ubuntu-template-user-and-tty.  Moved existing file to .pc/0041-ubuntu-template-user-and-tty.moved.
Conflict adding file debian/patches/0040-consoles-into-devlxc.patch.  Moved existing file to debian/patches/0040-consoles-into-devlxc.patch.moved.
Conflict adding file debian/patches/0041-ubuntu-template-user-and-tty.  Moved existing file to debian/patches/0041-ubuntu-template-user-and-tty.moved.
To merge this branch: bzr merge lp:~ubuntu-branches/ubuntu/precise/lxc/precise-201202110437
Reviewer Review Type Date Requested Status
Ubuntu branches Pending
Review via email: mp+92607@code.launchpad.net

Description of the change

The package importer has detected a possible inconsistency between the package history in the archive and the history in bzr. As the archive is authoritative the importer has made lp:ubuntu/precise/lxc reflect what is in the archive and the old bzr branch has been pushed to lp:~ubuntu-branches/ubuntu/precise/lxc/precise-201202110437. This merge proposal was created so that an Ubuntu developer can review the situations and perform a merge/upload if necessary. There are three typical cases where this can happen.
  1. Where someone pushes a change to bzr and someone else uploads the package without that change. This is the reason that this check is done by the importer. If this appears to be the case then a merge/upload should be done if the changes that were in bzr are still desirable.
  2. The importer incorrectly detected the above situation when someone made a change in bzr and then uploaded it.
  3. The importer incorrectly detected the above situation when someone just uploaded a package and didn't touch bzr.

If this case doesn't appear to be the first situation then set the status of the merge proposal to "Rejected" and help avoid the problem in future by filing a bug at https://bugs.launchpad.net/udd linking to this merge proposal.

(this is an automatically generated message)

To post a comment you must log in.

Unmerged revisions

65. By Stéphane Graber

releasing version 0.7.5-3ubuntu24

64. By Stéphane Graber

update Ubuntu template to use devttydir, switch to using ubuntu/ubuntu and sudo by default instead of root/root, move information message about default username/password to the end of the template creation.

63. By Stéphane Graber

Add patch from Serge to support devttydir as a prefix for /dev/console and /dev/tty[1234].

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file '.pc/.dpkg-source-unapply'
2=== added file '.pc/.quilt_patches'
3--- .pc/.quilt_patches 1970-01-01 00:00:00 +0000
4+++ .pc/.quilt_patches 2012-02-11 04:43:19 +0000
5@@ -0,0 +1,1 @@
6+debian/patches
7
8=== added file '.pc/.quilt_series'
9--- .pc/.quilt_series 1970-01-01 00:00:00 +0000
10+++ .pc/.quilt_series 2012-02-11 04:43:19 +0000
11@@ -0,0 +1,1 @@
12+series
13
14=== added directory '.pc/0040-consoles-into-devlxc.patch'
15=== renamed directory '.pc/0040-consoles-into-devlxc.patch' => '.pc/0040-consoles-into-devlxc.patch.moved'
16=== added directory '.pc/0040-consoles-into-devlxc.patch/src'
17=== added directory '.pc/0040-consoles-into-devlxc.patch/src/lxc'
18=== added file '.pc/0040-consoles-into-devlxc.patch/src/lxc/conf.c'
19--- .pc/0040-consoles-into-devlxc.patch/src/lxc/conf.c 1970-01-01 00:00:00 +0000
20+++ .pc/0040-consoles-into-devlxc.patch/src/lxc/conf.c 2012-02-11 04:43:19 +0000
21@@ -0,0 +1,1767 @@
22+/*
23+ * lxc: linux Container library
24+ *
25+ * (C) Copyright IBM Corp. 2007, 2008
26+ *
27+ * Authors:
28+ * Daniel Lezcano <dlezcano at fr.ibm.com>
29+ *
30+ * This library is free software; you can redistribute it and/or
31+ * modify it under the terms of the GNU Lesser General Public
32+ * License as published by the Free Software Foundation; either
33+ * version 2.1 of the License, or (at your option) any later version.
34+ *
35+ * This library is distributed in the hope that it will be useful,
36+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
37+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
38+ * Lesser General Public License for more details.
39+ *
40+ * You should have received a copy of the GNU Lesser General Public
41+ * License along with this library; if not, write to the Free Software
42+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
43+ */
44+#define _GNU_SOURCE
45+#include <stdio.h>
46+#undef _GNU_SOURCE
47+#include <stdlib.h>
48+#include <stdarg.h>
49+#include <errno.h>
50+#include <string.h>
51+#include <dirent.h>
52+#include <mntent.h>
53+#include <unistd.h>
54+#include <sys/wait.h>
55+#include <pty.h>
56+
57+#include <linux/loop.h>
58+
59+#include <sys/types.h>
60+#include <sys/utsname.h>
61+#include <sys/param.h>
62+#include <sys/stat.h>
63+#include <sys/socket.h>
64+#include <sys/mount.h>
65+#include <sys/mman.h>
66+#include <sys/prctl.h>
67+#include <sys/capability.h>
68+#include <sys/personality.h>
69+
70+#include <arpa/inet.h>
71+#include <fcntl.h>
72+#include <netinet/in.h>
73+#include <net/if.h>
74+#include <libgen.h>
75+
76+#include "network.h"
77+#include "error.h"
78+#include "parse.h"
79+#include "config.h"
80+#include "utils.h"
81+#include "conf.h"
82+#include "log.h"
83+#include "lxc.h" /* for lxc_cgroup_set() */
84+
85+lxc_log_define(lxc_conf, lxc);
86+
87+#define MAXHWLEN 18
88+#define MAXINDEXLEN 20
89+#define MAXMTULEN 16
90+#define MAXLINELEN 128
91+
92+#ifndef MS_DIRSYNC
93+#define MS_DIRSYNC 128
94+#endif
95+
96+#ifndef MS_REC
97+#define MS_REC 16384
98+#endif
99+
100+#ifndef MNT_DETACH
101+#define MNT_DETACH 2
102+#endif
103+
104+#ifndef MS_RELATIME
105+#define MS_RELATIME (1 << 21)
106+#endif
107+
108+#ifndef MS_STRICTATIME
109+#define MS_STRICTATIME (1 << 24)
110+#endif
111+
112+#ifndef CAP_SETFCAP
113+#define CAP_SETFCAP 31
114+#endif
115+
116+#ifndef CAP_MAC_OVERRIDE
117+#define CAP_MAC_OVERRIDE 32
118+#endif
119+
120+#ifndef CAP_MAC_ADMIN
121+#define CAP_MAC_ADMIN 33
122+#endif
123+
124+#ifndef PR_CAPBSET_DROP
125+#define PR_CAPBSET_DROP 24
126+#endif
127+
128+extern int pivot_root(const char * new_root, const char * put_old);
129+
130+typedef int (*instanciate_cb)(struct lxc_handler *, struct lxc_netdev *);
131+
132+struct mount_opt {
133+ char *name;
134+ int clear;
135+ int flag;
136+};
137+
138+struct caps_opt {
139+ char *name;
140+ int value;
141+};
142+
143+static int instanciate_veth(struct lxc_handler *, struct lxc_netdev *);
144+static int instanciate_macvlan(struct lxc_handler *, struct lxc_netdev *);
145+static int instanciate_vlan(struct lxc_handler *, struct lxc_netdev *);
146+static int instanciate_phys(struct lxc_handler *, struct lxc_netdev *);
147+static int instanciate_empty(struct lxc_handler *, struct lxc_netdev *);
148+
149+static instanciate_cb netdev_conf[LXC_NET_MAXCONFTYPE + 1] = {
150+ [LXC_NET_VETH] = instanciate_veth,
151+ [LXC_NET_MACVLAN] = instanciate_macvlan,
152+ [LXC_NET_VLAN] = instanciate_vlan,
153+ [LXC_NET_PHYS] = instanciate_phys,
154+ [LXC_NET_EMPTY] = instanciate_empty,
155+};
156+
157+static struct mount_opt mount_opt[] = {
158+ { "defaults", 0, 0 },
159+ { "ro", 0, MS_RDONLY },
160+ { "rw", 1, MS_RDONLY },
161+ { "suid", 1, MS_NOSUID },
162+ { "nosuid", 0, MS_NOSUID },
163+ { "dev", 1, MS_NODEV },
164+ { "nodev", 0, MS_NODEV },
165+ { "exec", 1, MS_NOEXEC },
166+ { "noexec", 0, MS_NOEXEC },
167+ { "sync", 0, MS_SYNCHRONOUS },
168+ { "async", 1, MS_SYNCHRONOUS },
169+ { "dirsync", 0, MS_DIRSYNC },
170+ { "remount", 0, MS_REMOUNT },
171+ { "mand", 0, MS_MANDLOCK },
172+ { "nomand", 1, MS_MANDLOCK },
173+ { "atime", 1, MS_NOATIME },
174+ { "noatime", 0, MS_NOATIME },
175+ { "diratime", 1, MS_NODIRATIME },
176+ { "nodiratime", 0, MS_NODIRATIME },
177+ { "bind", 0, MS_BIND },
178+ { "rbind", 0, MS_BIND|MS_REC },
179+ { "relatime", 0, MS_RELATIME },
180+ { "norelatime", 1, MS_RELATIME },
181+ { "strictatime", 0, MS_STRICTATIME },
182+ { "nostrictatime", 1, MS_STRICTATIME },
183+ { NULL, 0, 0 },
184+};
185+
186+static struct caps_opt caps_opt[] = {
187+ { "chown", CAP_CHOWN },
188+ { "dac_override", CAP_DAC_OVERRIDE },
189+ { "dac_read_search", CAP_DAC_READ_SEARCH },
190+ { "fowner", CAP_FOWNER },
191+ { "fsetid", CAP_FSETID },
192+ { "kill", CAP_KILL },
193+ { "setgid", CAP_SETGID },
194+ { "setuid", CAP_SETUID },
195+ { "setpcap", CAP_SETPCAP },
196+ { "linux_immutable", CAP_LINUX_IMMUTABLE },
197+ { "net_bind_service", CAP_NET_BIND_SERVICE },
198+ { "net_broadcast", CAP_NET_BROADCAST },
199+ { "net_admin", CAP_NET_ADMIN },
200+ { "net_raw", CAP_NET_RAW },
201+ { "ipc_lock", CAP_IPC_LOCK },
202+ { "ipc_owner", CAP_IPC_OWNER },
203+ { "sys_module", CAP_SYS_MODULE },
204+ { "sys_rawio", CAP_SYS_RAWIO },
205+ { "sys_chroot", CAP_SYS_CHROOT },
206+ { "sys_ptrace", CAP_SYS_PTRACE },
207+ { "sys_pacct", CAP_SYS_PACCT },
208+ { "sys_admin", CAP_SYS_ADMIN },
209+ { "sys_boot", CAP_SYS_BOOT },
210+ { "sys_nice", CAP_SYS_NICE },
211+ { "sys_resource", CAP_SYS_RESOURCE },
212+ { "sys_time", CAP_SYS_TIME },
213+ { "sys_tty_config", CAP_SYS_TTY_CONFIG },
214+ { "mknod", CAP_MKNOD },
215+ { "lease", CAP_LEASE },
216+#ifdef CAP_AUDIT_WRITE
217+ { "audit_write", CAP_AUDIT_WRITE },
218+#endif
219+#ifdef CAP_AUDIT_CONTROL
220+ { "audit_control", CAP_AUDIT_CONTROL },
221+#endif
222+ { "setfcap", CAP_SETFCAP },
223+ { "mac_override", CAP_MAC_OVERRIDE },
224+ { "mac_admin", CAP_MAC_ADMIN },
225+};
226+
227+static int run_script(const char *name, const char *section,
228+ const char *script, ...)
229+{
230+ int ret;
231+ FILE *f;
232+ char *buffer, *p, *output;
233+ size_t size = 0;
234+ va_list ap;
235+
236+ INFO("Executing script '%s' for container '%s', config section '%s'",
237+ script, name, section);
238+
239+ va_start(ap, script);
240+ while ((p = va_arg(ap, char *)))
241+ size += strlen(p) + 1;
242+ va_end(ap);
243+
244+ size += strlen(script);
245+ size += strlen(name);
246+ size += strlen(section);
247+ size += 3;
248+
249+ if (size > INT_MAX)
250+ return -1;
251+
252+ buffer = alloca(size);
253+ if (!buffer) {
254+ ERROR("failed to allocate memory");
255+ return -1;
256+ }
257+
258+ ret = sprintf(buffer, "%s %s %s", script, name, section);
259+
260+ va_start(ap, script);
261+ while ((p = va_arg(ap, char *)))
262+ ret += sprintf(buffer + ret, " %s", p);
263+ va_end(ap);
264+
265+ f = popen(buffer, "r");
266+ if (!f) {
267+ SYSERROR("popen failed");
268+ return -1;
269+ }
270+
271+ output = malloc(LXC_LOG_BUFFER_SIZE);
272+ if (!output) {
273+ ERROR("failed to allocate memory for script output");
274+ return -1;
275+ }
276+
277+ while(fgets(output, LXC_LOG_BUFFER_SIZE, f))
278+ DEBUG("script output: %s", output);
279+
280+ free(output);
281+
282+ if (pclose(f)) {
283+ ERROR("Script exited on error");
284+ return -1;
285+ }
286+
287+ return 0;
288+}
289+
290+static int find_fstype_cb(char* buffer, void *data)
291+{
292+ struct cbarg {
293+ const char *rootfs;
294+ const char *target;
295+ int mntopt;
296+ } *cbarg = data;
297+
298+ char *fstype;
299+
300+ /* we don't try 'nodev' entries */
301+ if (strstr(buffer, "nodev"))
302+ return 0;
303+
304+ fstype = buffer;
305+ fstype += lxc_char_left_gc(fstype, strlen(fstype));
306+ fstype[lxc_char_right_gc(fstype, strlen(fstype))] = '\0';
307+
308+ DEBUG("trying to mount '%s'->'%s' with fstype '%s'",
309+ cbarg->rootfs, cbarg->target, fstype);
310+
311+ if (mount(cbarg->rootfs, cbarg->target, fstype, cbarg->mntopt, NULL)) {
312+ DEBUG("mount failed with error: %s", strerror(errno));
313+ return 0;
314+ }
315+
316+ INFO("mounted '%s' on '%s', with fstype '%s'",
317+ cbarg->rootfs, cbarg->target, fstype);
318+
319+ return 1;
320+}
321+
322+static int mount_unknow_fs(const char *rootfs, const char *target, int mntopt)
323+{
324+ int i;
325+
326+ struct cbarg {
327+ const char *rootfs;
328+ const char *target;
329+ int mntopt;
330+ } cbarg = {
331+ .rootfs = rootfs,
332+ .target = target,
333+ .mntopt = mntopt,
334+ };
335+
336+ /*
337+ * find the filesystem type with brute force:
338+ * first we check with /etc/filesystems, in case the modules
339+ * are auto-loaded and fall back to the supported kernel fs
340+ */
341+ char *fsfile[] = {
342+ "/etc/filesystems",
343+ "/proc/filesystems",
344+ };
345+
346+ for (i = 0; i < sizeof(fsfile)/sizeof(fsfile[0]); i++) {
347+
348+ int ret;
349+
350+ if (access(fsfile[i], F_OK))
351+ continue;
352+
353+ ret = lxc_file_for_each_line(fsfile[i], find_fstype_cb, &cbarg);
354+ if (ret < 0) {
355+ ERROR("failed to parse '%s'", fsfile[i]);
356+ return -1;
357+ }
358+
359+ if (ret)
360+ return 0;
361+ }
362+
363+ ERROR("failed to determine fs type for '%s'", rootfs);
364+ return -1;
365+}
366+
367+static int mount_rootfs_dir(const char *rootfs, const char *target)
368+{
369+ return mount(rootfs, target, "none", MS_BIND | MS_REC, NULL);
370+}
371+
372+static int setup_lodev(const char *rootfs, int fd, struct loop_info64 *loinfo)
373+{
374+ int rfd;
375+ int ret = -1;
376+
377+ rfd = open(rootfs, O_RDWR);
378+ if (rfd < 0) {
379+ SYSERROR("failed to open '%s'", rootfs);
380+ return -1;
381+ }
382+
383+ memset(loinfo, 0, sizeof(*loinfo));
384+
385+ loinfo->lo_flags = LO_FLAGS_AUTOCLEAR;
386+
387+ if (ioctl(fd, LOOP_SET_FD, rfd)) {
388+ SYSERROR("failed to LOOP_SET_FD");
389+ goto out;
390+ }
391+
392+ if (ioctl(fd, LOOP_SET_STATUS64, loinfo)) {
393+ SYSERROR("failed to LOOP_SET_STATUS64");
394+ goto out;
395+ }
396+
397+ ret = 0;
398+out:
399+ close(rfd);
400+
401+ return ret;
402+}
403+
404+static int mount_rootfs_file(const char *rootfs, const char *target)
405+{
406+ struct dirent dirent, *direntp;
407+ struct loop_info64 loinfo;
408+ int ret = -1, fd = -1;
409+ DIR *dir;
410+ char path[MAXPATHLEN];
411+
412+ dir = opendir("/dev");
413+ if (!dir) {
414+ SYSERROR("failed to open '/dev'");
415+ return -1;
416+ }
417+
418+ while (!readdir_r(dir, &dirent, &direntp)) {
419+
420+ if (!direntp)
421+ break;
422+
423+ if (!strcmp(direntp->d_name, "."))
424+ continue;
425+
426+ if (!strcmp(direntp->d_name, ".."))
427+ continue;
428+
429+ if (strncmp(direntp->d_name, "loop", 4))
430+ continue;
431+
432+ sprintf(path, "/dev/%s", direntp->d_name);
433+ fd = open(path, O_RDWR);
434+ if (fd < 0)
435+ continue;
436+
437+ if (ioctl(fd, LOOP_GET_STATUS64, &loinfo) == 0) {
438+ close(fd);
439+ continue;
440+ }
441+
442+ if (errno != ENXIO) {
443+ WARN("unexpected error for ioctl on '%s': %m",
444+ direntp->d_name);
445+ continue;
446+ }
447+
448+ DEBUG("found '%s' free lodev", path);
449+
450+ ret = setup_lodev(rootfs, fd, &loinfo);
451+ if (!ret)
452+ ret = mount_unknow_fs(path, target, 0);
453+ close(fd);
454+
455+ break;
456+ }
457+
458+ if (closedir(dir))
459+ WARN("failed to close directory");
460+
461+ return ret;
462+}
463+
464+static int mount_rootfs_block(const char *rootfs, const char *target)
465+{
466+ return mount_unknow_fs(rootfs, target, 0);
467+}
468+
469+static int mount_rootfs(const char *rootfs, const char *target)
470+{
471+ char absrootfs[MAXPATHLEN];
472+ struct stat s;
473+ int i;
474+
475+ typedef int (*rootfs_cb)(const char *, const char *);
476+
477+ struct rootfs_type {
478+ int type;
479+ rootfs_cb cb;
480+ } rtfs_type[] = {
481+ { S_IFDIR, mount_rootfs_dir },
482+ { S_IFBLK, mount_rootfs_block },
483+ { S_IFREG, mount_rootfs_file },
484+ };
485+
486+ if (!realpath(rootfs, absrootfs)) {
487+ SYSERROR("failed to get real path for '%s'", rootfs);
488+ return -1;
489+ }
490+
491+ if (access(absrootfs, F_OK)) {
492+ SYSERROR("'%s' is not accessible", absrootfs);
493+ return -1;
494+ }
495+
496+ if (stat(absrootfs, &s)) {
497+ SYSERROR("failed to stat '%s'", absrootfs);
498+ return -1;
499+ }
500+
501+ for (i = 0; i < sizeof(rtfs_type)/sizeof(rtfs_type[0]); i++) {
502+
503+ if (!__S_ISTYPE(s.st_mode, rtfs_type[i].type))
504+ continue;
505+
506+ return rtfs_type[i].cb(absrootfs, target);
507+ }
508+
509+ ERROR("unsupported rootfs type for '%s'", absrootfs);
510+ return -1;
511+}
512+
513+static int setup_utsname(struct utsname *utsname)
514+{
515+ if (!utsname)
516+ return 0;
517+
518+ if (sethostname(utsname->nodename, strlen(utsname->nodename))) {
519+ SYSERROR("failed to set the hostname to '%s'", utsname->nodename);
520+ return -1;
521+ }
522+
523+ INFO("'%s' hostname has been setup", utsname->nodename);
524+
525+ return 0;
526+}
527+
528+static int setup_tty(const struct lxc_rootfs *rootfs,
529+ const struct lxc_tty_info *tty_info)
530+{
531+ char path[MAXPATHLEN];
532+ int i;
533+
534+ if (!rootfs->path)
535+ return 0;
536+
537+ for (i = 0; i < tty_info->nbtty; i++) {
538+
539+ struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
540+
541+ snprintf(path, sizeof(path), "%s/dev/tty%d",
542+ rootfs->mount, i + 1);
543+
544+ /* At this point I can not use the "access" function
545+ * to check the file is present or not because it fails
546+ * with EACCES errno and I don't know why :( */
547+
548+ if (mount(pty_info->name, path, "none", MS_BIND, 0)) {
549+ WARN("failed to mount '%s'->'%s'",
550+ pty_info->name, path);
551+ continue;
552+ }
553+ }
554+
555+ INFO("%d tty(s) has been setup", tty_info->nbtty);
556+
557+ return 0;
558+}
559+
560+static int setup_rootfs_pivot_root_cb(char *buffer, void *data)
561+{
562+ struct lxc_list *mountlist, *listentry, *iterator;
563+ char *pivotdir, *mountpoint, *mountentry;
564+ int found;
565+ void **cbparm;
566+
567+ mountentry = buffer;
568+ cbparm = (void **)data;
569+
570+ mountlist = cbparm[0];
571+ pivotdir = cbparm[1];
572+
573+ /* parse entry, first field is mountname, ignore */
574+ mountpoint = strtok(mountentry, " ");
575+ if (!mountpoint)
576+ return -1;
577+
578+ /* second field is mountpoint */
579+ mountpoint = strtok(NULL, " ");
580+ if (!mountpoint)
581+ return -1;
582+
583+ /* only consider mountpoints below old root fs */
584+ if (strncmp(mountpoint, pivotdir, strlen(pivotdir)))
585+ return 0;
586+
587+ /* filter duplicate mountpoints */
588+ found = 0;
589+ lxc_list_for_each(iterator, mountlist) {
590+ if (!strcmp(iterator->elem, mountpoint)) {
591+ found = 1;
592+ break;
593+ }
594+ }
595+ if (found)
596+ return 0;
597+
598+ /* add entry to list */
599+ listentry = malloc(sizeof(*listentry));
600+ if (!listentry) {
601+ SYSERROR("malloc for mountpoint listentry failed");
602+ return -1;
603+ }
604+
605+ listentry->elem = strdup(mountpoint);
606+ if (!listentry->elem) {
607+ SYSERROR("strdup failed");
608+ return -1;
609+ }
610+ lxc_list_add_tail(mountlist, listentry);
611+
612+ return 0;
613+}
614+
615+static int umount_oldrootfs(const char *oldrootfs)
616+{
617+ char path[MAXPATHLEN];
618+ void *cbparm[2];
619+ struct lxc_list mountlist, *iterator;
620+ int ok, still_mounted, last_still_mounted;
621+
622+ /* read and parse /proc/mounts in old root fs */
623+ lxc_list_init(&mountlist);
624+
625+ /* oldrootfs is on the top tree directory now */
626+ snprintf(path, sizeof(path), "/%s", oldrootfs);
627+ cbparm[0] = &mountlist;
628+
629+ cbparm[1] = strdup(path);
630+ if (!cbparm[1]) {
631+ SYSERROR("strdup failed");
632+ return -1;
633+ }
634+
635+ snprintf(path, sizeof(path), "%s/proc/mounts", oldrootfs);
636+
637+ ok = lxc_file_for_each_line(path,
638+ setup_rootfs_pivot_root_cb, &cbparm);
639+ if (ok < 0) {
640+ SYSERROR("failed to read or parse mount list '%s'", path);
641+ return -1;
642+ }
643+
644+ /* umount filesystems until none left or list no longer shrinks */
645+ still_mounted = 0;
646+ do {
647+ last_still_mounted = still_mounted;
648+ still_mounted = 0;
649+
650+ lxc_list_for_each(iterator, &mountlist) {
651+
652+ /* umount normally */
653+ if (!umount(iterator->elem)) {
654+ DEBUG("umounted '%s'", (char *)iterator->elem);
655+ lxc_list_del(iterator);
656+ continue;
657+ }
658+
659+ still_mounted++;
660+ }
661+
662+ } while (still_mounted > 0 && still_mounted != last_still_mounted);
663+
664+
665+ lxc_list_for_each(iterator, &mountlist) {
666+
667+ /* let's try a lazy umount */
668+ if (!umount2(iterator->elem, MNT_DETACH)) {
669+ INFO("lazy unmount of '%s'", (char *)iterator->elem);
670+ continue;
671+ }
672+
673+ /* be more brutal (nfs) */
674+ if (!umount2(iterator->elem, MNT_FORCE)) {
675+ INFO("forced unmount of '%s'", (char *)iterator->elem);
676+ continue;
677+ }
678+
679+ WARN("failed to unmount '%s'", (char *)iterator->elem);
680+ }
681+
682+ return 0;
683+}
684+
685+static int setup_rootfs_pivot_root(const char *rootfs, const char *pivotdir)
686+{
687+ char path[MAXPATHLEN];
688+ int remove_pivotdir = 0;
689+
690+ /* change into new root fs */
691+ if (chdir(rootfs)) {
692+ SYSERROR("can't chdir to new rootfs '%s'", rootfs);
693+ return -1;
694+ }
695+
696+ if (!pivotdir)
697+ pivotdir = "mnt";
698+
699+ /* compute the full path to pivotdir under rootfs */
700+ snprintf(path, sizeof(path), "%s/%s", rootfs, pivotdir);
701+
702+ if (access(path, F_OK)) {
703+
704+ if (mkdir_p(path, 0755)) {
705+ SYSERROR("failed to create pivotdir '%s'", path);
706+ return -1;
707+ }
708+
709+ remove_pivotdir = 1;
710+ DEBUG("created '%s' directory", path);
711+ }
712+
713+ DEBUG("mountpoint for old rootfs is '%s'", path);
714+
715+ /* pivot_root into our new root fs */
716+ if (pivot_root(".", path)) {
717+ SYSERROR("pivot_root syscall failed");
718+ return -1;
719+ }
720+
721+ if (chdir("/")) {
722+ SYSERROR("can't chdir to / after pivot_root");
723+ return -1;
724+ }
725+
726+ DEBUG("pivot_root syscall to '%s' successful", rootfs);
727+
728+ /* we switch from absolute path to relative path */
729+ if (umount_oldrootfs(pivotdir))
730+ return -1;
731+
732+ /* remove temporary mount point, we don't consider the removing
733+ * as fatal */
734+ if (remove_pivotdir && rmdir(pivotdir))
735+ WARN("can't remove mountpoint '%s': %m", pivotdir);
736+
737+ return 0;
738+}
739+
740+static int setup_rootfs(const struct lxc_rootfs *rootfs)
741+{
742+ if (!rootfs->path)
743+ return 0;
744+
745+ if (access(rootfs->mount, F_OK)) {
746+ SYSERROR("failed to access to '%s', check it is present",
747+ rootfs->mount);
748+ return -1;
749+ }
750+
751+ if (mount_rootfs(rootfs->path, rootfs->mount)) {
752+ ERROR("failed to mount rootfs");
753+ return -1;
754+ }
755+
756+ DEBUG("mounted '%s' on '%s'", rootfs->path, rootfs->mount);
757+
758+ return 0;
759+}
760+
761+int setup_pivot_root(const struct lxc_rootfs *rootfs)
762+{
763+ if (!rootfs->path)
764+ return 0;
765+
766+ if (setup_rootfs_pivot_root(rootfs->mount, rootfs->pivot)) {
767+ ERROR("failed to setup pivot root");
768+ return -1;
769+ }
770+
771+ return 0;
772+}
773+
774+static int setup_pts(int pts)
775+{
776+ char target[PATH_MAX];
777+
778+ if (!pts)
779+ return 0;
780+
781+ if (!access("/dev/pts/ptmx", F_OK) && umount("/dev/pts")) {
782+ SYSERROR("failed to umount 'dev/pts'");
783+ return -1;
784+ }
785+
786+ if (mount("devpts", "/dev/pts", "devpts", MS_MGC_VAL,
787+ "newinstance,ptmxmode=0666")) {
788+ SYSERROR("failed to mount a new instance of '/dev/pts'");
789+ return -1;
790+ }
791+
792+ if (access("/dev/ptmx", F_OK)) {
793+ if (!symlink("/dev/pts/ptmx", "/dev/ptmx"))
794+ goto out;
795+ SYSERROR("failed to symlink '/dev/pts/ptmx'->'/dev/ptmx'");
796+ return -1;
797+ }
798+
799+ if (realpath("/dev/ptmx", target) && !strcmp(target, "/dev/pts/ptmx"))
800+ goto out;
801+
802+ /* fallback here, /dev/pts/ptmx exists just mount bind */
803+ if (mount("/dev/pts/ptmx", "/dev/ptmx", "none", MS_BIND, 0)) {
804+ SYSERROR("mount failed '/dev/pts/ptmx'->'/dev/ptmx'");
805+ return -1;
806+ }
807+
808+ INFO("created new pts instance");
809+
810+out:
811+ return 0;
812+}
813+
814+static int setup_personality(int persona)
815+{
816+ if (persona == -1)
817+ return 0;
818+
819+ if (personality(persona) < 0) {
820+ SYSERROR("failed to set personality to '0x%x'", persona);
821+ return -1;
822+ }
823+
824+ INFO("set personality to '0x%x'", persona);
825+
826+ return 0;
827+}
828+
829+static int setup_console(const struct lxc_rootfs *rootfs,
830+ const struct lxc_console *console)
831+{
832+ char path[MAXPATHLEN];
833+ struct stat s;
834+
835+ /* We don't have a rootfs, /dev/console will be shared */
836+ if (!rootfs->path)
837+ return 0;
838+
839+ snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount);
840+
841+ if (access(path, F_OK)) {
842+ WARN("rootfs specified but no console found at '%s'", path);
843+ return 0;
844+ }
845+
846+ if (console->peer == -1) {
847+ INFO("no console output required");
848+ return 0;
849+ }
850+
851+ if (stat(path, &s)) {
852+ SYSERROR("failed to stat '%s'", path);
853+ return -1;
854+ }
855+
856+ if (chmod(console->name, s.st_mode)) {
857+ SYSERROR("failed to set mode '0%o' to '%s'",
858+ s.st_mode, console->name);
859+ return -1;
860+ }
861+
862+ if (mount(console->name, path, "none", MS_BIND, 0)) {
863+ ERROR("failed to mount '%s' on '%s'", console->name, path);
864+ return -1;
865+ }
866+
867+ INFO("console has been setup");
868+
869+ return 0;
870+}
871+
872+static int setup_cgroup(const char *name, struct lxc_list *cgroups)
873+{
874+ struct lxc_list *iterator;
875+ struct lxc_cgroup *cg;
876+ int ret = -1;
877+
878+ if (lxc_list_empty(cgroups))
879+ return 0;
880+
881+ lxc_list_for_each(iterator, cgroups) {
882+
883+ cg = iterator->elem;
884+
885+ if (lxc_cgroup_set(name, cg->subsystem, cg->value))
886+ goto out;
887+
888+ DEBUG("cgroup '%s' set to '%s'", cg->subsystem, cg->value);
889+ }
890+
891+ ret = 0;
892+ INFO("cgroup has been setup");
893+out:
894+ return ret;
895+}
896+
897+static void parse_mntopt(char *opt, unsigned long *flags, char **data)
898+{
899+ struct mount_opt *mo;
900+
901+ /* If opt is found in mount_opt, set or clear flags.
902+ * Otherwise append it to data. */
903+
904+ for (mo = &mount_opt[0]; mo->name != NULL; mo++) {
905+ if (!strncmp(opt, mo->name, strlen(mo->name))) {
906+ if (mo->clear)
907+ *flags &= ~mo->flag;
908+ else
909+ *flags |= mo->flag;
910+ return;
911+ }
912+ }
913+
914+ if (strlen(*data))
915+ strcat(*data, ",");
916+ strcat(*data, opt);
917+}
918+
919+static int parse_mntopts(const char *mntopts, unsigned long *mntflags,
920+ char **mntdata)
921+{
922+ char *s, *data;
923+ char *p, *saveptr = NULL;
924+
925+ *mntdata = NULL;
926+ *mntflags = 0L;
927+
928+ if (!mntopts)
929+ return 0;
930+
931+ s = strdup(mntopts);
932+ if (!s) {
933+ SYSERROR("failed to allocate memory");
934+ return -1;
935+ }
936+
937+ data = malloc(strlen(s) + 1);
938+ if (!data) {
939+ SYSERROR("failed to allocate memory");
940+ free(s);
941+ return -1;
942+ }
943+ *data = 0;
944+
945+ for (p = strtok_r(s, ",", &saveptr); p != NULL;
946+ p = strtok_r(NULL, ",", &saveptr))
947+ parse_mntopt(p, mntflags, &data);
948+
949+ if (*data)
950+ *mntdata = data;
951+ else
952+ free(data);
953+ free(s);
954+
955+ return 0;
956+}
957+
958+static int mount_entry(const char *fsname, const char *target,
959+ const char *fstype, unsigned long mountflags,
960+ const char *data)
961+{
962+ if (mount(fsname, target, fstype, mountflags & ~MS_REMOUNT, data)) {
963+ SYSERROR("failed to mount '%s' on '%s'", fsname, target);
964+ return -1;
965+ }
966+
967+ if ((mountflags & MS_REMOUNT) || (mountflags & MS_BIND)) {
968+
969+ DEBUG("remounting %s on %s to respect bind or remount options",
970+ fsname, target);
971+
972+ if (mount(fsname, target, fstype,
973+ mountflags | MS_REMOUNT, data)) {
974+ SYSERROR("failed to mount '%s' on '%s'",
975+ fsname, target);
976+ return -1;
977+ }
978+ }
979+
980+ DEBUG("mounted '%s' on '%s', type '%s'", fsname, target, fstype);
981+
982+ return 0;
983+}
984+
985+static inline int mount_entry_on_systemfs(struct mntent *mntent)
986+{
987+ unsigned long mntflags;
988+ char *mntdata;
989+ int ret;
990+
991+ if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
992+ ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
993+ return -1;
994+ }
995+
996+ ret = mount_entry(mntent->mnt_fsname, mntent->mnt_dir,
997+ mntent->mnt_type, mntflags, mntdata);
998+
999+ free(mntdata);
1000+
1001+ return ret;
1002+}
1003+
1004+static int mount_entry_on_absolute_rootfs(struct mntent *mntent,
1005+ const struct lxc_rootfs *rootfs)
1006+{
1007+ char *aux;
1008+ char path[MAXPATHLEN];
1009+ unsigned long mntflags;
1010+ char *mntdata;
1011+ int ret = 0;
1012+
1013+ if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
1014+ ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
1015+ return -1;
1016+ }
1017+
1018+ aux = strstr(mntent->mnt_dir, rootfs->path);
1019+ if (!aux) {
1020+ WARN("ignoring mount point '%s'", mntent->mnt_dir);
1021+ goto out;
1022+ }
1023+
1024+ snprintf(path, MAXPATHLEN, "%s/%s", rootfs->mount,
1025+ aux + strlen(rootfs->path));
1026+
1027+ ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type,
1028+ mntflags, mntdata);
1029+
1030+out:
1031+ free(mntdata);
1032+ return ret;
1033+}
1034+
1035+static int mount_entry_on_relative_rootfs(struct mntent *mntent,
1036+ const char *rootfs)
1037+{
1038+ char path[MAXPATHLEN];
1039+ unsigned long mntflags;
1040+ char *mntdata;
1041+ int ret;
1042+
1043+ if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
1044+ ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
1045+ return -1;
1046+ }
1047+
1048+ /* relative to root mount point */
1049+ snprintf(path, sizeof(path), "%s/%s", rootfs, mntent->mnt_dir);
1050+
1051+ ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type,
1052+ mntflags, mntdata);
1053+
1054+ free(mntdata);
1055+
1056+ return ret;
1057+}
1058+
1059+static int mount_file_entries(const struct lxc_rootfs *rootfs, FILE *file)
1060+{
1061+ struct mntent *mntent;
1062+ int ret = -1;
1063+
1064+ while ((mntent = getmntent(file))) {
1065+
1066+ if (!rootfs->path) {
1067+ if (mount_entry_on_systemfs(mntent))
1068+ goto out;
1069+ continue;
1070+ }
1071+
1072+ /* We have a separate root, mounts are relative to it */
1073+ if (mntent->mnt_dir[0] != '/') {
1074+ if (mount_entry_on_relative_rootfs(mntent,
1075+ rootfs->mount))
1076+ goto out;
1077+ continue;
1078+ }
1079+
1080+ if (mount_entry_on_absolute_rootfs(mntent, rootfs))
1081+ goto out;
1082+ }
1083+
1084+ ret = 0;
1085+
1086+ INFO("mount points have been setup");
1087+out:
1088+ return ret;
1089+}
1090+
1091+static int setup_mount(const struct lxc_rootfs *rootfs, const char *fstab)
1092+{
1093+ FILE *file;
1094+ int ret;
1095+
1096+ if (!fstab)
1097+ return 0;
1098+
1099+ file = setmntent(fstab, "r");
1100+ if (!file) {
1101+ SYSERROR("failed to use '%s'", fstab);
1102+ return -1;
1103+ }
1104+
1105+ ret = mount_file_entries(rootfs, file);
1106+
1107+ endmntent(file);
1108+ return ret;
1109+}
1110+
1111+static int setup_mount_entries(const struct lxc_rootfs *rootfs, struct lxc_list *mount)
1112+{
1113+ FILE *file;
1114+ struct lxc_list *iterator;
1115+ char *mount_entry;
1116+ int ret;
1117+
1118+ file = tmpfile();
1119+ if (!file) {
1120+ ERROR("tmpfile error: %m");
1121+ return -1;
1122+ }
1123+
1124+ lxc_list_for_each(iterator, mount) {
1125+ mount_entry = iterator->elem;
1126+ fprintf(file, "%s\n", mount_entry);
1127+ }
1128+
1129+ rewind(file);
1130+
1131+ ret = mount_file_entries(rootfs, file);
1132+
1133+ fclose(file);
1134+ return ret;
1135+}
1136+
1137+static int setup_caps(struct lxc_list *caps)
1138+{
1139+ struct lxc_list *iterator;
1140+ char *drop_entry;
1141+ int i, capid;
1142+
1143+ lxc_list_for_each(iterator, caps) {
1144+
1145+ drop_entry = iterator->elem;
1146+
1147+ capid = -1;
1148+
1149+ for (i = 0; i < sizeof(caps_opt)/sizeof(caps_opt[0]); i++) {
1150+
1151+ if (strcmp(drop_entry, caps_opt[i].name))
1152+ continue;
1153+
1154+ capid = caps_opt[i].value;
1155+ break;
1156+ }
1157+
1158+ if (capid < 0) {
1159+ ERROR("unknown capability %s", drop_entry);
1160+ return -1;
1161+ }
1162+
1163+ DEBUG("drop capability '%s' (%d)", drop_entry, capid);
1164+
1165+ if (prctl(PR_CAPBSET_DROP, capid, 0, 0, 0)) {
1166+ SYSERROR("failed to remove %s capability", drop_entry);
1167+ return -1;
1168+ }
1169+
1170+ }
1171+
1172+ DEBUG("capabilities has been setup");
1173+
1174+ return 0;
1175+}
1176+
1177+static int setup_hw_addr(char *hwaddr, const char *ifname)
1178+{
1179+ struct sockaddr sockaddr;
1180+ struct ifreq ifr;
1181+ int ret, fd;
1182+
1183+ ret = lxc_convert_mac(hwaddr, &sockaddr);
1184+ if (ret) {
1185+ ERROR("mac address '%s' conversion failed : %s",
1186+ hwaddr, strerror(-ret));
1187+ return -1;
1188+ }
1189+
1190+ memcpy(ifr.ifr_name, ifname, IFNAMSIZ);
1191+ memcpy((char *) &ifr.ifr_hwaddr, (char *) &sockaddr, sizeof(sockaddr));
1192+
1193+ fd = socket(AF_INET, SOCK_DGRAM, 0);
1194+ if (fd < 0) {
1195+ ERROR("socket failure : %s", strerror(errno));
1196+ return -1;
1197+ }
1198+
1199+ ret = ioctl(fd, SIOCSIFHWADDR, &ifr);
1200+ close(fd);
1201+ if (ret)
1202+ ERROR("ioctl failure : %s", strerror(errno));
1203+
1204+ DEBUG("mac address '%s' on '%s' has been setup", hwaddr, ifname);
1205+
1206+ return ret;
1207+}
1208+
1209+static int setup_ipv4_addr(struct lxc_list *ip, int ifindex)
1210+{
1211+ struct lxc_list *iterator;
1212+ struct lxc_inetdev *inetdev;
1213+ int err;
1214+
1215+ lxc_list_for_each(iterator, ip) {
1216+
1217+ inetdev = iterator->elem;
1218+
1219+ err = lxc_ipv4_addr_add(ifindex, &inetdev->addr,
1220+ &inetdev->bcast, inetdev->prefix);
1221+ if (err) {
1222+ ERROR("failed to setup_ipv4_addr ifindex %d : %s",
1223+ ifindex, strerror(-err));
1224+ return -1;
1225+ }
1226+ }
1227+
1228+ return 0;
1229+}
1230+
1231+static int setup_ipv6_addr(struct lxc_list *ip, int ifindex)
1232+{
1233+ struct lxc_list *iterator;
1234+ struct lxc_inet6dev *inet6dev;
1235+ int err;
1236+
1237+ lxc_list_for_each(iterator, ip) {
1238+
1239+ inet6dev = iterator->elem;
1240+
1241+ err = lxc_ipv6_addr_add(ifindex, &inet6dev->addr,
1242+ &inet6dev->mcast, &inet6dev->acast,
1243+ inet6dev->prefix);
1244+ if (err) {
1245+ ERROR("failed to setup_ipv6_addr ifindex %d : %s",
1246+ ifindex, strerror(-err));
1247+ return -1;
1248+ }
1249+ }
1250+
1251+ return 0;
1252+}
1253+
1254+static int setup_netdev(struct lxc_netdev *netdev)
1255+{
1256+ char ifname[IFNAMSIZ];
1257+ char *current_ifname = ifname;
1258+ int err;
1259+
1260+ /* empty network namespace */
1261+ if (!netdev->ifindex) {
1262+ if (netdev->flags & IFF_UP) {
1263+ err = lxc_netdev_up("lo");
1264+ if (err) {
1265+ ERROR("failed to set the loopback up : %s",
1266+ strerror(-err));
1267+ return -1;
1268+ }
1269+ }
1270+ return 0;
1271+ }
1272+
1273+ /* retrieve the name of the interface */
1274+ if (!if_indextoname(netdev->ifindex, current_ifname)) {
1275+ ERROR("no interface corresponding to index '%d'",
1276+ netdev->ifindex);
1277+ return -1;
1278+ }
1279+
1280+ /* default: let the system to choose one interface name */
1281+ if (!netdev->name)
1282+ netdev->name = netdev->type == LXC_NET_PHYS ?
1283+ netdev->link : "eth%d";
1284+
1285+ /* rename the interface name */
1286+ err = lxc_netdev_rename_by_name(ifname, netdev->name);
1287+ if (err) {
1288+ ERROR("failed to rename %s->%s : %s", ifname, netdev->name,
1289+ strerror(-err));
1290+ return -1;
1291+ }
1292+
1293+ /* Re-read the name of the interface because its name has changed
1294+ * and would be automatically allocated by the system
1295+ */
1296+ if (!if_indextoname(netdev->ifindex, current_ifname)) {
1297+ ERROR("no interface corresponding to index '%d'",
1298+ netdev->ifindex);
1299+ return -1;
1300+ }
1301+
1302+ /* set a mac address */
1303+ if (netdev->hwaddr) {
1304+ if (setup_hw_addr(netdev->hwaddr, current_ifname)) {
1305+ ERROR("failed to setup hw address for '%s'",
1306+ current_ifname);
1307+ return -1;
1308+ }
1309+ }
1310+
1311+ /* setup ipv4 addresses on the interface */
1312+ if (setup_ipv4_addr(&netdev->ipv4, netdev->ifindex)) {
1313+ ERROR("failed to setup ip addresses for '%s'",
1314+ ifname);
1315+ return -1;
1316+ }
1317+
1318+ /* setup ipv6 addresses on the interface */
1319+ if (setup_ipv6_addr(&netdev->ipv6, netdev->ifindex)) {
1320+ ERROR("failed to setup ipv6 addresses for '%s'",
1321+ ifname);
1322+ return -1;
1323+ }
1324+
1325+ /* set the network device up */
1326+ if (netdev->flags & IFF_UP) {
1327+ int err;
1328+
1329+ err = lxc_netdev_up(current_ifname);
1330+ if (err) {
1331+ ERROR("failed to set '%s' up : %s", current_ifname,
1332+ strerror(-err));
1333+ return -1;
1334+ }
1335+
1336+ /* the network is up, make the loopback up too */
1337+ err = lxc_netdev_up("lo");
1338+ if (err) {
1339+ ERROR("failed to set the loopback up : %s",
1340+ strerror(-err));
1341+ return -1;
1342+ }
1343+ }
1344+
1345+ DEBUG("'%s' has been setup", current_ifname);
1346+
1347+ return 0;
1348+}
1349+
1350+static int setup_network(struct lxc_list *network)
1351+{
1352+ struct lxc_list *iterator;
1353+ struct lxc_netdev *netdev;
1354+
1355+ lxc_list_for_each(iterator, network) {
1356+
1357+ netdev = iterator->elem;
1358+
1359+ if (setup_netdev(netdev)) {
1360+ ERROR("failed to setup netdev");
1361+ return -1;
1362+ }
1363+ }
1364+
1365+ if (!lxc_list_empty(network))
1366+ INFO("network has been setup");
1367+
1368+ return 0;
1369+}
1370+
1371+struct lxc_conf *lxc_conf_init(void)
1372+{
1373+ struct lxc_conf *new;
1374+
1375+ new = malloc(sizeof(*new));
1376+ if (!new) {
1377+ ERROR("lxc_conf_init : %m");
1378+ return NULL;
1379+ }
1380+ memset(new, 0, sizeof(*new));
1381+
1382+ new->personality = -1;
1383+ new->console.path = NULL;
1384+ new->console.peer = -1;
1385+ new->console.master = -1;
1386+ new->console.slave = -1;
1387+ new->console.name[0] = '\0';
1388+ new->rootfs.mount = LXCROOTFSMOUNT;
1389+ lxc_list_init(&new->cgroup);
1390+ lxc_list_init(&new->network);
1391+ lxc_list_init(&new->mount_list);
1392+ lxc_list_init(&new->caps);
1393+
1394+ return new;
1395+}
1396+
1397+static int instanciate_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
1398+{
1399+ char veth1buf[IFNAMSIZ], *veth1;
1400+ char veth2buf[IFNAMSIZ], *veth2;
1401+ int err;
1402+
1403+ if (netdev->priv.veth_attr.pair)
1404+ veth1 = netdev->priv.veth_attr.pair;
1405+ else {
1406+ snprintf(veth1buf, sizeof(veth1buf), "vethXXXXXX");
1407+ veth1 = mktemp(veth1buf);
1408+ }
1409+
1410+ snprintf(veth2buf, sizeof(veth2buf), "vethXXXXXX");
1411+ veth2 = mktemp(veth2buf);
1412+
1413+ if (!strlen(veth1) || !strlen(veth2)) {
1414+ ERROR("failed to allocate a temporary name");
1415+ return -1;
1416+ }
1417+
1418+ err = lxc_veth_create(veth1, veth2);
1419+ if (err) {
1420+ ERROR("failed to create %s-%s : %s", veth1, veth2,
1421+ strerror(-err));
1422+ return -1;
1423+ }
1424+
1425+ if (netdev->mtu) {
1426+ err = lxc_netdev_set_mtu(veth1, atoi(netdev->mtu));
1427+ if (!err)
1428+ err = lxc_netdev_set_mtu(veth2, atoi(netdev->mtu));
1429+ if (err) {
1430+ ERROR("failed to set mtu '%s' for %s-%s : %s",
1431+ netdev->mtu, veth1, veth2, strerror(-err));
1432+ goto out_delete;
1433+ }
1434+ }
1435+
1436+ if (netdev->link) {
1437+ err = lxc_bridge_attach(netdev->link, veth1);
1438+ if (err) {
1439+ ERROR("failed to attach '%s' to the bridge '%s' : %s",
1440+ veth1, netdev->link, strerror(-err));
1441+ goto out_delete;
1442+ }
1443+ }
1444+
1445+ netdev->ifindex = if_nametoindex(veth2);
1446+ if (!netdev->ifindex) {
1447+ ERROR("failed to retrieve the index for %s", veth2);
1448+ goto out_delete;
1449+ }
1450+
1451+ err = lxc_netdev_up(veth1);
1452+ if (err) {
1453+ ERROR("failed to set %s up : %s", veth1, strerror(-err));
1454+ goto out_delete;
1455+ }
1456+
1457+ if (netdev->upscript) {
1458+ err = run_script(handler->name, "net", netdev->upscript, "up",
1459+ "veth", veth1, (char*) NULL);
1460+ if (err)
1461+ goto out_delete;
1462+ }
1463+
1464+ DEBUG("instanciated veth '%s/%s', index is '%d'",
1465+ veth1, veth2, netdev->ifindex);
1466+
1467+ return 0;
1468+
1469+out_delete:
1470+ lxc_netdev_delete_by_name(veth1);
1471+ return -1;
1472+}
1473+
1474+static int instanciate_macvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
1475+{
1476+ char peerbuf[IFNAMSIZ], *peer;
1477+ int err;
1478+
1479+ if (!netdev->link) {
1480+ ERROR("no link specified for macvlan netdev");
1481+ return -1;
1482+ }
1483+
1484+ snprintf(peerbuf, sizeof(peerbuf), "mcXXXXXX");
1485+
1486+ peer = mktemp(peerbuf);
1487+ if (!strlen(peer)) {
1488+ ERROR("failed to make a temporary name");
1489+ return -1;
1490+ }
1491+
1492+ err = lxc_macvlan_create(netdev->link, peer,
1493+ netdev->priv.macvlan_attr.mode);
1494+ if (err) {
1495+ ERROR("failed to create macvlan interface '%s' on '%s' : %s",
1496+ peer, netdev->link, strerror(-err));
1497+ return -1;
1498+ }
1499+
1500+ netdev->ifindex = if_nametoindex(peer);
1501+ if (!netdev->ifindex) {
1502+ ERROR("failed to retrieve the index for %s", peer);
1503+ lxc_netdev_delete_by_name(peer);
1504+ return -1;
1505+ }
1506+
1507+ if (netdev->upscript) {
1508+ err = run_script(handler->name, "net", netdev->upscript, "up",
1509+ "macvlan", netdev->link, (char*) NULL);
1510+ if (err)
1511+ return -1;
1512+ }
1513+
1514+ DEBUG("instanciated macvlan '%s', index is '%d' and mode '%d'",
1515+ peer, netdev->ifindex, netdev->priv.macvlan_attr.mode);
1516+
1517+ return 0;
1518+}
1519+
1520+/* XXX: merge with instanciate_macvlan */
1521+static int instanciate_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
1522+{
1523+ char peer[IFNAMSIZ];
1524+ int err;
1525+
1526+ if (!netdev->link) {
1527+ ERROR("no link specified for vlan netdev");
1528+ return -1;
1529+ }
1530+
1531+ snprintf(peer, sizeof(peer), "vlan%d", netdev->priv.vlan_attr.vid);
1532+
1533+ err = lxc_vlan_create(netdev->link, peer, netdev->priv.vlan_attr.vid);
1534+ if (err) {
1535+ ERROR("failed to create vlan interface '%s' on '%s' : %s",
1536+ peer, netdev->link, strerror(-err));
1537+ return -1;
1538+ }
1539+
1540+ netdev->ifindex = if_nametoindex(peer);
1541+ if (!netdev->ifindex) {
1542+ ERROR("failed to retrieve the ifindex for %s", peer);
1543+ lxc_netdev_delete_by_name(peer);
1544+ return -1;
1545+ }
1546+
1547+ DEBUG("instanciated vlan '%s', ifindex is '%d'", " vlan1000",
1548+ netdev->ifindex);
1549+
1550+ return 0;
1551+}
1552+
1553+static int instanciate_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
1554+{
1555+ if (!netdev->link) {
1556+ ERROR("no link specified for the physical interface");
1557+ return -1;
1558+ }
1559+
1560+ netdev->ifindex = if_nametoindex(netdev->link);
1561+ if (!netdev->ifindex) {
1562+ ERROR("failed to retrieve the index for %s", netdev->link);
1563+ return -1;
1564+ }
1565+
1566+ if (netdev->upscript) {
1567+ int err;
1568+ err = run_script(handler->name, "net", netdev->upscript,
1569+ "up", "phys", netdev->link, (char*) NULL);
1570+ if (err)
1571+ return -1;
1572+ }
1573+
1574+ return 0;
1575+}
1576+
1577+static int instanciate_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
1578+{
1579+ netdev->ifindex = 0;
1580+ if (netdev->upscript) {
1581+ int err;
1582+ err = run_script(handler->name, "net", netdev->upscript,
1583+ "up", "empty", (char*) NULL);
1584+ if (err)
1585+ return -1;
1586+ }
1587+ return 0;
1588+}
1589+
1590+int lxc_create_network(struct lxc_handler *handler)
1591+{
1592+ struct lxc_list *network = &handler->conf->network;
1593+ struct lxc_list *iterator;
1594+ struct lxc_netdev *netdev;
1595+
1596+ lxc_list_for_each(iterator, network) {
1597+
1598+ netdev = iterator->elem;
1599+
1600+ if (netdev->type < 0 || netdev->type > LXC_NET_MAXCONFTYPE) {
1601+ ERROR("invalid network configuration type '%d'",
1602+ netdev->type);
1603+ return -1;
1604+ }
1605+
1606+ if (netdev_conf[netdev->type](handler, netdev)) {
1607+ ERROR("failed to create netdev");
1608+ return -1;
1609+ }
1610+
1611+ }
1612+
1613+ return 0;
1614+}
1615+
1616+void lxc_delete_network(struct lxc_list *network)
1617+{
1618+ struct lxc_list *iterator;
1619+ struct lxc_netdev *netdev;
1620+
1621+ lxc_list_for_each(iterator, network) {
1622+ netdev = iterator->elem;
1623+ if (netdev->ifindex == 0)
1624+ continue;
1625+
1626+ /* Recent kernels already delete the virtual devices */
1627+ if (netdev->type != LXC_NET_PHYS)
1628+ continue;
1629+
1630+ if (lxc_netdev_rename_by_index(netdev->ifindex, netdev->link))
1631+ WARN("failed to rename to the initial name the netdev '%s'",
1632+ netdev->link);
1633+ }
1634+}
1635+
1636+int lxc_assign_network(struct lxc_list *network, pid_t pid)
1637+{
1638+ struct lxc_list *iterator;
1639+ struct lxc_netdev *netdev;
1640+ int err;
1641+
1642+ lxc_list_for_each(iterator, network) {
1643+
1644+ netdev = iterator->elem;
1645+
1646+ /* empty network namespace, nothing to move */
1647+ if (!netdev->ifindex)
1648+ continue;
1649+
1650+ err = lxc_netdev_move_by_index(netdev->ifindex, pid);
1651+ if (err) {
1652+ ERROR("failed to move '%s' to the container : %s",
1653+ netdev->link, strerror(-err));
1654+ return -1;
1655+ }
1656+
1657+ DEBUG("move '%s' to '%d'", netdev->name, pid);
1658+ }
1659+
1660+ return 0;
1661+}
1662+
1663+int lxc_create_tty(const char *name, struct lxc_conf *conf)
1664+{
1665+ struct lxc_tty_info *tty_info = &conf->tty_info;
1666+ int i;
1667+
1668+ /* no tty in the configuration */
1669+ if (!conf->tty)
1670+ return 0;
1671+
1672+ tty_info->pty_info =
1673+ malloc(sizeof(*tty_info->pty_info)*conf->tty);
1674+ if (!tty_info->pty_info) {
1675+ SYSERROR("failed to allocate pty_info");
1676+ return -1;
1677+ }
1678+
1679+ for (i = 0; i < conf->tty; i++) {
1680+
1681+ struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
1682+
1683+ if (openpty(&pty_info->master, &pty_info->slave,
1684+ pty_info->name, NULL, NULL)) {
1685+ SYSERROR("failed to create pty #%d", i);
1686+ tty_info->nbtty = i;
1687+ lxc_delete_tty(tty_info);
1688+ return -1;
1689+ }
1690+
1691+ DEBUG("allocated pty '%s' (%d/%d)",
1692+ pty_info->name, pty_info->master, pty_info->slave);
1693+
1694+ /* Prevent leaking the file descriptors to the container */
1695+ fcntl(pty_info->master, F_SETFD, FD_CLOEXEC);
1696+ fcntl(pty_info->slave, F_SETFD, FD_CLOEXEC);
1697+
1698+ pty_info->busy = 0;
1699+ }
1700+
1701+ tty_info->nbtty = conf->tty;
1702+
1703+ INFO("tty's configured");
1704+
1705+ return 0;
1706+}
1707+
1708+void lxc_delete_tty(struct lxc_tty_info *tty_info)
1709+{
1710+ int i;
1711+
1712+ for (i = 0; i < tty_info->nbtty; i++) {
1713+ struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
1714+
1715+ close(pty_info->master);
1716+ close(pty_info->slave);
1717+ }
1718+
1719+ free(tty_info->pty_info);
1720+ tty_info->nbtty = 0;
1721+}
1722+
1723+int lxc_setup(const char *name, struct lxc_conf *lxc_conf)
1724+{
1725+ if (setup_utsname(lxc_conf->utsname)) {
1726+ ERROR("failed to setup the utsname for '%s'", name);
1727+ return -1;
1728+ }
1729+
1730+ if (setup_network(&lxc_conf->network)) {
1731+ ERROR("failed to setup the network for '%s'", name);
1732+ return -1;
1733+ }
1734+
1735+ if (setup_rootfs(&lxc_conf->rootfs)) {
1736+ ERROR("failed to setup rootfs for '%s'", name);
1737+ return -1;
1738+ }
1739+
1740+ if (setup_mount(&lxc_conf->rootfs, lxc_conf->fstab)) {
1741+ ERROR("failed to setup the mounts for '%s'", name);
1742+ return -1;
1743+ }
1744+
1745+ if (setup_mount_entries(&lxc_conf->rootfs, &lxc_conf->mount_list)) {
1746+ ERROR("failed to setup the mount entries for '%s'", name);
1747+ return -1;
1748+ }
1749+
1750+ if (setup_cgroup(name, &lxc_conf->cgroup)) {
1751+ ERROR("failed to setup the cgroups for '%s'", name);
1752+ return -1;
1753+ }
1754+
1755+ if (setup_console(&lxc_conf->rootfs, &lxc_conf->console)) {
1756+ ERROR("failed to setup the console for '%s'", name);
1757+ return -1;
1758+ }
1759+
1760+ if (setup_tty(&lxc_conf->rootfs, &lxc_conf->tty_info)) {
1761+ ERROR("failed to setup the ttys for '%s'", name);
1762+ return -1;
1763+ }
1764+
1765+ if (setup_pivot_root(&lxc_conf->rootfs)) {
1766+ ERROR("failed to set rootfs for '%s'", name);
1767+ return -1;
1768+ }
1769+
1770+ if (setup_pts(lxc_conf->pts)) {
1771+ ERROR("failed to setup the new pts instance");
1772+ return -1;
1773+ }
1774+
1775+ if (setup_personality(lxc_conf->personality)) {
1776+ ERROR("failed to setup personality");
1777+ return -1;
1778+ }
1779+
1780+ if (setup_caps(&lxc_conf->caps)) {
1781+ ERROR("failed to drop capabilities");
1782+ return -1;
1783+ }
1784+
1785+ NOTICE("'%s' is setup.", name);
1786+
1787+ return 0;
1788+}
1789
1790=== added file '.pc/0040-consoles-into-devlxc.patch/src/lxc/conf.h'
1791--- .pc/0040-consoles-into-devlxc.patch/src/lxc/conf.h 1970-01-01 00:00:00 +0000
1792+++ .pc/0040-consoles-into-devlxc.patch/src/lxc/conf.h 2012-02-11 04:43:19 +0000
1793@@ -0,0 +1,230 @@
1794+/*
1795+ * lxc: linux Container library
1796+ *
1797+ * (C) Copyright IBM Corp. 2007, 2008
1798+ *
1799+ * Authors:
1800+ * Daniel Lezcano <dlezcano at fr.ibm.com>
1801+ *
1802+ * This library is free software; you can redistribute it and/or
1803+ * modify it under the terms of the GNU Lesser General Public
1804+ * License as published by the Free Software Foundation; either
1805+ * version 2.1 of the License, or (at your option) any later version.
1806+ *
1807+ * This library is distributed in the hope that it will be useful,
1808+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1809+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1810+ * Lesser General Public License for more details.
1811+ *
1812+ * You should have received a copy of the GNU Lesser General Public
1813+ * License along with this library; if not, write to the Free Software
1814+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1815+ */
1816+#ifndef _conf_h
1817+#define _conf_h
1818+
1819+#include <netinet/in.h>
1820+#include <sys/param.h>
1821+
1822+#include <lxc/list.h>
1823+
1824+#include <lxc/start.h> /* for lxc_handler */
1825+
1826+enum {
1827+ LXC_NET_EMPTY,
1828+ LXC_NET_VETH,
1829+ LXC_NET_MACVLAN,
1830+ LXC_NET_PHYS,
1831+ LXC_NET_VLAN,
1832+ LXC_NET_MAXCONFTYPE,
1833+};
1834+
1835+/*
1836+ * Defines the structure to configure an ipv4 address
1837+ * @address : ipv4 address
1838+ * @broadcast : ipv4 broadcast address
1839+ * @mask : network mask
1840+ */
1841+struct lxc_inetdev {
1842+ struct in_addr addr;
1843+ struct in_addr bcast;
1844+ int prefix;
1845+};
1846+
1847+struct lxc_route {
1848+ struct in_addr addr;
1849+};
1850+
1851+/*
1852+ * Defines the structure to configure an ipv6 address
1853+ * @flags : set the address up
1854+ * @address : ipv6 address
1855+ * @broadcast : ipv6 broadcast address
1856+ * @mask : network mask
1857+ */
1858+struct lxc_inet6dev {
1859+ struct in6_addr addr;
1860+ struct in6_addr mcast;
1861+ struct in6_addr acast;
1862+ int prefix;
1863+};
1864+
1865+struct lxc_route6 {
1866+ struct in6_addr addr;
1867+};
1868+
1869+struct ifla_veth {
1870+ char *pair; /* pair name */
1871+};
1872+
1873+struct ifla_vlan {
1874+ uint flags;
1875+ uint fmask;
1876+ ushort vid;
1877+ ushort pad;
1878+};
1879+
1880+struct ifla_macvlan {
1881+ int mode; /* private, vepa, bridge */
1882+};
1883+
1884+union netdev_p {
1885+ struct ifla_veth veth_attr;
1886+ struct ifla_vlan vlan_attr;
1887+ struct ifla_macvlan macvlan_attr;
1888+};
1889+
1890+/*
1891+ * Defines a structure to configure a network device
1892+ * @link : lxc.network.link, name of bridge or host iface to attach if any
1893+ * @name : lxc.network.name, name of iface on the container side
1894+ * @flags : flag of the network device (IFF_UP, ... )
1895+ * @ipv4 : a list of ipv4 addresses to be set on the network device
1896+ * @ipv6 : a list of ipv6 addresses to be set on the network device
1897+ * @upscript : a script filename to be executed during interface configuration
1898+ */
1899+struct lxc_netdev {
1900+ int type;
1901+ int flags;
1902+ int ifindex;
1903+ char *link;
1904+ char *name;
1905+ char *hwaddr;
1906+ char *mtu;
1907+ union netdev_p priv;
1908+ struct lxc_list ipv4;
1909+ struct lxc_list ipv6;
1910+ char *upscript;
1911+};
1912+
1913+/*
1914+ * Defines a generic struct to configure the control group.
1915+ * It is up to the programmer to specify the right subsystem.
1916+ * @subsystem : the targetted subsystem
1917+ * @value : the value to set
1918+ */
1919+struct lxc_cgroup {
1920+ char *subsystem;
1921+ char *value;
1922+};
1923+
1924+/*
1925+ * Defines a structure containing a pty information for
1926+ * virtualizing a tty
1927+ * @name : the path name of the slave pty side
1928+ * @master : the file descriptor of the master
1929+ * @slave : the file descriptor of the slave
1930+ */
1931+struct lxc_pty_info {
1932+ char name[MAXPATHLEN];
1933+ int master;
1934+ int slave;
1935+ int busy;
1936+};
1937+
1938+/*
1939+ * Defines the number of tty configured and contains the
1940+ * instanciated ptys
1941+ * @nbtty = number of configured ttys
1942+ */
1943+struct lxc_tty_info {
1944+ int nbtty;
1945+ struct lxc_pty_info *pty_info;
1946+};
1947+
1948+/*
1949+ * Defines the structure to store the console information
1950+ * @peer : the file descriptor put/get console traffic
1951+ * @name : the file name of the slave pty
1952+ */
1953+struct lxc_console {
1954+ int slave;
1955+ int master;
1956+ int peer;
1957+ char *path;
1958+ char name[MAXPATHLEN];
1959+ struct termios *tios;
1960+};
1961+
1962+/*
1963+ * Defines a structure to store the rootfs location, the
1964+ * optionals pivot_root, rootfs mount paths
1965+ * @rootfs : a path to the rootfs
1966+ * @pivot_root : a path to a pivot_root location to be used
1967+ */
1968+struct lxc_rootfs {
1969+ char *path;
1970+ char *mount;
1971+ char *pivot;
1972+};
1973+
1974+/*
1975+ * Defines the global container configuration
1976+ * @rootfs : root directory to run the container
1977+ * @pivotdir : pivotdir path, if not set default will be used
1978+ * @mount : list of mount points
1979+ * @tty : numbers of tty
1980+ * @pts : new pts instance
1981+ * @mount_list : list of mount point (alternative to fstab file)
1982+ * @network : network configuration
1983+ * @utsname : container utsname
1984+ * @fstab : path to a fstab file format
1985+ * @caps : list of the capabilities
1986+ * @tty_info : tty data
1987+ * @console : console data
1988+ */
1989+struct lxc_conf {
1990+ char *fstab;
1991+ int tty;
1992+ int pts;
1993+ int reboot;
1994+ int need_utmp_watch;
1995+ int personality;
1996+ struct utsname *utsname;
1997+ struct lxc_list cgroup;
1998+ struct lxc_list network;
1999+ struct lxc_list mount_list;
2000+ struct lxc_list caps;
2001+ struct lxc_tty_info tty_info;
2002+ struct lxc_console console;
2003+ struct lxc_rootfs rootfs;
2004+};
2005+
2006+/*
2007+ * Initialize the lxc configuration structure
2008+ */
2009+extern struct lxc_conf *lxc_conf_init(void);
2010+
2011+extern int lxc_create_network(struct lxc_handler *handler);
2012+extern void lxc_delete_network(struct lxc_list *networks);
2013+extern int lxc_assign_network(struct lxc_list *networks, pid_t pid);
2014+
2015+extern int lxc_create_tty(const char *name, struct lxc_conf *conf);
2016+extern void lxc_delete_tty(struct lxc_tty_info *tty_info);
2017+
2018+/*
2019+ * Configure the container from inside
2020+ */
2021+
2022+extern int lxc_setup(const char *name, struct lxc_conf *lxc_conf);
2023+#endif
2024
2025=== added file '.pc/0040-consoles-into-devlxc.patch/src/lxc/confile.c'
2026--- .pc/0040-consoles-into-devlxc.patch/src/lxc/confile.c 1970-01-01 00:00:00 +0000
2027+++ .pc/0040-consoles-into-devlxc.patch/src/lxc/confile.c 2012-02-11 04:43:19 +0000
2028@@ -0,0 +1,898 @@
2029+/*
2030+ * lxc: linux Container library
2031+ *
2032+ * (C) Copyright IBM Corp. 2007, 2008
2033+ *
2034+ * Authors:
2035+ * Daniel Lezcano <dlezcano at fr.ibm.com>
2036+ *
2037+ * This library is free software; you can redistribute it and/or
2038+ * modify it under the terms of the GNU Lesser General Public
2039+ * License as published by the Free Software Foundation; either
2040+ * version 2.1 of the License, or (at your option) any later version.
2041+ *
2042+ * This library is distributed in the hope that it will be useful,
2043+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2044+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2045+ * Lesser General Public License for more details.
2046+ *
2047+ * You should have received a copy of the GNU Lesser General Public
2048+ * License along with this library; if not, write to the Free Software
2049+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2050+ */
2051+#include <stdio.h>
2052+#include <stdlib.h>
2053+#include <string.h>
2054+#include <unistd.h>
2055+#include <errno.h>
2056+#include <fcntl.h>
2057+#include <pty.h>
2058+#include <sys/stat.h>
2059+#include <sys/types.h>
2060+#include <sys/param.h>
2061+#include <sys/utsname.h>
2062+#include <sys/personality.h>
2063+#include <arpa/inet.h>
2064+#include <netinet/in.h>
2065+#include <net/if.h>
2066+
2067+#include "parse.h"
2068+#include "utils.h"
2069+
2070+#include <lxc/log.h>
2071+#include <lxc/conf.h>
2072+
2073+lxc_log_define(lxc_confile, lxc);
2074+
2075+static int config_personality(const char *, char *, struct lxc_conf *);
2076+static int config_pts(const char *, char *, struct lxc_conf *);
2077+static int config_tty(const char *, char *, struct lxc_conf *);
2078+static int config_cgroup(const char *, char *, struct lxc_conf *);
2079+static int config_mount(const char *, char *, struct lxc_conf *);
2080+static int config_rootfs(const char *, char *, struct lxc_conf *);
2081+static int config_rootfs_mount(const char *, char *, struct lxc_conf *);
2082+static int config_pivotdir(const char *, char *, struct lxc_conf *);
2083+static int config_utsname(const char *, char *, struct lxc_conf *);
2084+static int config_network_type(const char *, char *, struct lxc_conf *);
2085+static int config_network_flags(const char *, char *, struct lxc_conf *);
2086+static int config_network_link(const char *, char *, struct lxc_conf *);
2087+static int config_network_name(const char *, char *, struct lxc_conf *);
2088+static int config_network_veth_pair(const char *, char *, struct lxc_conf *);
2089+static int config_network_macvlan_mode(const char *, char *, struct lxc_conf *);
2090+static int config_network_hwaddr(const char *, char *, struct lxc_conf *);
2091+static int config_network_vlan_id(const char *, char *, struct lxc_conf *);
2092+static int config_network_mtu(const char *, char *, struct lxc_conf *);
2093+static int config_network_ipv4(const char *, char *, struct lxc_conf *);
2094+static int config_network_script(const char *, char *, struct lxc_conf *);
2095+static int config_network_ipv6(const char *, char *, struct lxc_conf *);
2096+static int config_cap_drop(const char *, char *, struct lxc_conf *);
2097+static int config_console(const char *, char *, struct lxc_conf *);
2098+
2099+typedef int (*config_cb)(const char *, char *, struct lxc_conf *);
2100+
2101+struct config {
2102+ char *name;
2103+ config_cb cb;
2104+};
2105+
2106+static struct config config[] = {
2107+
2108+ { "lxc.arch", config_personality },
2109+ { "lxc.pts", config_pts },
2110+ { "lxc.tty", config_tty },
2111+ { "lxc.cgroup", config_cgroup },
2112+ { "lxc.mount", config_mount },
2113+ { "lxc.rootfs.mount", config_rootfs_mount },
2114+ { "lxc.rootfs", config_rootfs },
2115+ { "lxc.pivotdir", config_pivotdir },
2116+ { "lxc.utsname", config_utsname },
2117+ { "lxc.network.type", config_network_type },
2118+ { "lxc.network.flags", config_network_flags },
2119+ { "lxc.network.link", config_network_link },
2120+ { "lxc.network.name", config_network_name },
2121+ { "lxc.network.macvlan.mode", config_network_macvlan_mode },
2122+ { "lxc.network.veth.pair", config_network_veth_pair },
2123+ { "lxc.network.script.up", config_network_script },
2124+ { "lxc.network.hwaddr", config_network_hwaddr },
2125+ { "lxc.network.mtu", config_network_mtu },
2126+ { "lxc.network.vlan.id", config_network_vlan_id },
2127+ { "lxc.network.ipv4", config_network_ipv4 },
2128+ { "lxc.network.ipv6", config_network_ipv6 },
2129+ { "lxc.cap.drop", config_cap_drop },
2130+ { "lxc.console", config_console },
2131+};
2132+
2133+static const size_t config_size = sizeof(config)/sizeof(struct config);
2134+
2135+static struct config *getconfig(const char *key)
2136+{
2137+ int i;
2138+
2139+ for (i = 0; i < config_size; i++)
2140+ if (!strncmp(config[i].name, key,
2141+ strlen(config[i].name)))
2142+ return &config[i];
2143+ return NULL;
2144+}
2145+
2146+static int config_network_type(const char *key, char *value,
2147+ struct lxc_conf *lxc_conf)
2148+{
2149+ struct lxc_list *network = &lxc_conf->network;
2150+ struct lxc_netdev *netdev;
2151+ struct lxc_list *list;
2152+
2153+ netdev = malloc(sizeof(*netdev));
2154+ if (!netdev) {
2155+ SYSERROR("failed to allocate memory");
2156+ return -1;
2157+ }
2158+
2159+ memset(netdev, 0, sizeof(*netdev));
2160+ lxc_list_init(&netdev->ipv4);
2161+ lxc_list_init(&netdev->ipv6);
2162+
2163+ list = malloc(sizeof(*list));
2164+ if (!list) {
2165+ SYSERROR("failed to allocate memory");
2166+ return -1;
2167+ }
2168+
2169+ lxc_list_init(list);
2170+ list->elem = netdev;
2171+
2172+ lxc_list_add_tail(network, list);
2173+
2174+ if (!strcmp(value, "veth"))
2175+ netdev->type = LXC_NET_VETH;
2176+ else if (!strcmp(value, "macvlan"))
2177+ netdev->type = LXC_NET_MACVLAN;
2178+ else if (!strcmp(value, "vlan"))
2179+ netdev->type = LXC_NET_VLAN;
2180+ else if (!strcmp(value, "phys"))
2181+ netdev->type = LXC_NET_PHYS;
2182+ else if (!strcmp(value, "empty"))
2183+ netdev->type = LXC_NET_EMPTY;
2184+ else {
2185+ ERROR("invalid network type %s", value);
2186+ return -1;
2187+ }
2188+ return 0;
2189+}
2190+
2191+static int config_ip_prefix(struct in_addr *addr)
2192+{
2193+ if (IN_CLASSA(addr->s_addr))
2194+ return 32 - IN_CLASSA_NSHIFT;
2195+ if (IN_CLASSB(addr->s_addr))
2196+ return 32 - IN_CLASSB_NSHIFT;
2197+ if (IN_CLASSC(addr->s_addr))
2198+ return 32 - IN_CLASSC_NSHIFT;
2199+
2200+ return 0;
2201+}
2202+
2203+static struct lxc_netdev *network_netdev(const char *key, const char *value,
2204+ struct lxc_list *network)
2205+{
2206+ struct lxc_netdev *netdev;
2207+
2208+ if (lxc_list_empty(network)) {
2209+ ERROR("network is not created for '%s' = '%s' option",
2210+ key, value);
2211+ return NULL;
2212+ }
2213+
2214+ netdev = lxc_list_last_elem(network);
2215+ if (!netdev) {
2216+ ERROR("no network device defined for '%s' = '%s' option",
2217+ key, value);
2218+ return NULL;
2219+ }
2220+
2221+ return netdev;
2222+}
2223+
2224+static int network_ifname(char **valuep, char *value)
2225+{
2226+ if (strlen(value) >= IFNAMSIZ) {
2227+ ERROR("invalid interface name: %s", value);
2228+ return -1;
2229+ }
2230+
2231+ *valuep = strdup(value);
2232+ if (!*valuep) {
2233+ ERROR("failed to dup string '%s'", value);
2234+ return -1;
2235+ }
2236+
2237+ return 0;
2238+}
2239+
2240+#ifndef MACVLAN_MODE_PRIVATE
2241+# define MACVLAN_MODE_PRIVATE 1
2242+#endif
2243+
2244+#ifndef MACVLAN_MODE_VEPA
2245+# define MACVLAN_MODE_VEPA 2
2246+#endif
2247+
2248+#ifndef MACVLAN_MODE_BRIDGE
2249+# define MACVLAN_MODE_BRIDGE 4
2250+#endif
2251+
2252+static int macvlan_mode(int *valuep, char *value)
2253+{
2254+ struct mc_mode {
2255+ char *name;
2256+ int mode;
2257+ } m[] = {
2258+ { "private", MACVLAN_MODE_PRIVATE },
2259+ { "vepa", MACVLAN_MODE_VEPA },
2260+ { "bridge", MACVLAN_MODE_BRIDGE },
2261+ };
2262+
2263+ int i;
2264+
2265+ for (i = 0; i < sizeof(m)/sizeof(m[0]); i++) {
2266+ if (strcmp(m[i].name, value))
2267+ continue;
2268+
2269+ *valuep = m[i].mode;
2270+ return 0;
2271+ }
2272+
2273+ return -1;
2274+}
2275+
2276+static int config_network_flags(const char *key, char *value,
2277+ struct lxc_conf *lxc_conf)
2278+{
2279+ struct lxc_netdev *netdev;
2280+
2281+ netdev = network_netdev(key, value, &lxc_conf->network);
2282+ if (!netdev)
2283+ return -1;
2284+
2285+ netdev->flags |= IFF_UP;
2286+
2287+ return 0;
2288+}
2289+
2290+static int config_network_link(const char *key, char *value,
2291+ struct lxc_conf *lxc_conf)
2292+{
2293+ struct lxc_netdev *netdev;
2294+
2295+ netdev = network_netdev(key, value, &lxc_conf->network);
2296+ if (!netdev)
2297+ return -1;
2298+
2299+ return network_ifname(&netdev->link, value);
2300+}
2301+
2302+static int config_network_name(const char *key, char *value,
2303+ struct lxc_conf *lxc_conf)
2304+{
2305+ struct lxc_netdev *netdev;
2306+
2307+ netdev = network_netdev(key, value, &lxc_conf->network);
2308+ if (!netdev)
2309+ return -1;
2310+
2311+ return network_ifname(&netdev->name, value);
2312+}
2313+
2314+static int config_network_veth_pair(const char *key, char *value,
2315+ struct lxc_conf *lxc_conf)
2316+{
2317+ struct lxc_netdev *netdev;
2318+
2319+ netdev = network_netdev(key, value, &lxc_conf->network);
2320+ if (!netdev)
2321+ return -1;
2322+
2323+ return network_ifname(&netdev->priv.veth_attr.pair, value);
2324+}
2325+
2326+static int config_network_macvlan_mode(const char *key, char *value,
2327+ struct lxc_conf *lxc_conf)
2328+{
2329+ struct lxc_netdev *netdev;
2330+
2331+ netdev = network_netdev(key, value, &lxc_conf->network);
2332+ if (!netdev)
2333+ return -1;
2334+
2335+ return macvlan_mode(&netdev->priv.macvlan_attr.mode, value);
2336+}
2337+
2338+static int config_network_hwaddr(const char *key, char *value,
2339+ struct lxc_conf *lxc_conf)
2340+{
2341+ struct lxc_netdev *netdev;
2342+
2343+ netdev = network_netdev(key, value, &lxc_conf->network);
2344+ if (!netdev)
2345+ return -1;
2346+
2347+ netdev->hwaddr = strdup(value);
2348+ if (!netdev->hwaddr) {
2349+ SYSERROR("failed to dup string '%s'", value);
2350+ return -1;
2351+ }
2352+
2353+ return 0;
2354+}
2355+
2356+static int config_network_vlan_id(const char *key, char *value,
2357+ struct lxc_conf *lxc_conf)
2358+{
2359+ struct lxc_netdev *netdev;
2360+
2361+ netdev = network_netdev(key, value, &lxc_conf->network);
2362+ if (!netdev)
2363+ return -1;
2364+
2365+ if (get_u16(&netdev->priv.vlan_attr.vid, value, 0))
2366+ return -1;
2367+
2368+ return 0;
2369+}
2370+
2371+static int config_network_mtu(const char *key, char *value,
2372+ struct lxc_conf *lxc_conf)
2373+{
2374+ struct lxc_netdev *netdev;
2375+
2376+ netdev = network_netdev(key, value, &lxc_conf->network);
2377+ if (!netdev)
2378+ return -1;
2379+
2380+ netdev->mtu = strdup(value);
2381+ if (!netdev->mtu) {
2382+ SYSERROR("failed to dup string '%s'", value);
2383+ return -1;
2384+ }
2385+
2386+ return 0;
2387+}
2388+
2389+static int config_network_ipv4(const char *key, char *value,
2390+ struct lxc_conf *lxc_conf)
2391+{
2392+ struct lxc_netdev *netdev;
2393+ struct lxc_inetdev *inetdev;
2394+ struct lxc_list *list;
2395+ char *cursor, *slash, *addr = NULL, *bcast = NULL, *prefix = NULL;
2396+
2397+ netdev = network_netdev(key, value, &lxc_conf->network);
2398+ if (!netdev)
2399+ return -1;
2400+
2401+ inetdev = malloc(sizeof(*inetdev));
2402+ if (!inetdev) {
2403+ SYSERROR("failed to allocate ipv4 address");
2404+ return -1;
2405+ }
2406+ memset(inetdev, 0, sizeof(*inetdev));
2407+
2408+ list = malloc(sizeof(*list));
2409+ if (!list) {
2410+ SYSERROR("failed to allocate memory");
2411+ return -1;
2412+ }
2413+
2414+ lxc_list_init(list);
2415+ list->elem = inetdev;
2416+
2417+ addr = value;
2418+
2419+ cursor = strstr(addr, " ");
2420+ if (cursor) {
2421+ *cursor = '\0';
2422+ bcast = cursor + 1;
2423+ }
2424+
2425+ slash = strstr(addr, "/");
2426+ if (slash) {
2427+ *slash = '\0';
2428+ prefix = slash + 1;
2429+ }
2430+
2431+ if (!addr) {
2432+ ERROR("no address specified");
2433+ return -1;
2434+ }
2435+
2436+ if (!inet_pton(AF_INET, addr, &inetdev->addr)) {
2437+ SYSERROR("invalid ipv4 address: %s", value);
2438+ return -1;
2439+ }
2440+
2441+ if (bcast && !inet_pton(AF_INET, bcast, &inetdev->bcast)) {
2442+ SYSERROR("invalid ipv4 broadcast address: %s", value);
2443+ return -1;
2444+ }
2445+
2446+ /* no prefix specified, determine it from the network class */
2447+ inetdev->prefix = prefix ? atoi(prefix) :
2448+ config_ip_prefix(&inetdev->addr);
2449+
2450+ /* if no broadcast address, let compute one from the
2451+ * prefix and address
2452+ */
2453+ if (!bcast) {
2454+ inetdev->bcast.s_addr = inetdev->addr.s_addr;
2455+ inetdev->bcast.s_addr |=
2456+ htonl(INADDR_BROADCAST >> inetdev->prefix);
2457+ }
2458+
2459+ lxc_list_add(&netdev->ipv4, list);
2460+
2461+ return 0;
2462+}
2463+
2464+static int config_network_ipv6(const char *key, char *value,
2465+ struct lxc_conf *lxc_conf)
2466+{
2467+ struct lxc_netdev *netdev;
2468+ struct lxc_inet6dev *inet6dev;
2469+ struct lxc_list *list;
2470+ char *slash;
2471+ char *netmask;
2472+
2473+ netdev = network_netdev(key, value, &lxc_conf->network);
2474+ if (!netdev)
2475+ return -1;
2476+
2477+ inet6dev = malloc(sizeof(*inet6dev));
2478+ if (!inet6dev) {
2479+ SYSERROR("failed to allocate ipv6 address");
2480+ return -1;
2481+ }
2482+ memset(inet6dev, 0, sizeof(*inet6dev));
2483+
2484+ list = malloc(sizeof(*list));
2485+ if (!list) {
2486+ SYSERROR("failed to allocate memory");
2487+ return -1;
2488+ }
2489+
2490+ lxc_list_init(list);
2491+ list->elem = inet6dev;
2492+
2493+ inet6dev->prefix = 64;
2494+ slash = strstr(value, "/");
2495+ if (slash) {
2496+ *slash = '\0';
2497+ netmask = slash + 1;
2498+ inet6dev->prefix = atoi(netmask);
2499+ }
2500+
2501+ if (!inet_pton(AF_INET6, value, &inet6dev->addr)) {
2502+ SYSERROR("invalid ipv6 address: %s", value);
2503+ return -1;
2504+ }
2505+
2506+ lxc_list_add(&netdev->ipv6, list);
2507+
2508+ return 0;
2509+}
2510+
2511+static int config_network_script(const char *key, char *value,
2512+ struct lxc_conf *lxc_conf)
2513+{
2514+ struct lxc_netdev *netdev;
2515+
2516+ netdev = network_netdev(key, value, &lxc_conf->network);
2517+ if (!netdev)
2518+ return -1;
2519+
2520+ char *copy = strdup(value);
2521+ if (!copy) {
2522+ SYSERROR("failed to dup string '%s'", value);
2523+ return -1;
2524+ }
2525+ if (strcmp(key, "lxc.network.script.up") == 0) {
2526+ netdev->upscript = copy;
2527+ return 0;
2528+ }
2529+ SYSERROR("Unknown key: %s", key);
2530+ free(copy);
2531+ return -1;
2532+}
2533+
2534+static int config_personality(const char *key, char *value,
2535+ struct lxc_conf *lxc_conf)
2536+{
2537+ struct per_name {
2538+ char *name;
2539+ int per;
2540+ } pername[4] = {
2541+ { "x86", PER_LINUX32 },
2542+ { "i686", PER_LINUX32 },
2543+ { "x86_64", PER_LINUX },
2544+ { "amd64", PER_LINUX },
2545+ };
2546+ size_t len = sizeof(pername) / sizeof(pername[0]);
2547+
2548+ int i;
2549+
2550+ for (i = 0; i < len; i++) {
2551+
2552+ if (strcmp(pername[i].name, value))
2553+ continue;
2554+
2555+ lxc_conf->personality = pername[i].per;
2556+
2557+ return 0;
2558+ }
2559+
2560+ WARN("unsupported personality '%s'", value);
2561+
2562+ return 0;
2563+}
2564+
2565+static int config_pts(const char *key, char *value, struct lxc_conf *lxc_conf)
2566+{
2567+ int maxpts = atoi(value);
2568+
2569+ lxc_conf->pts = maxpts;
2570+
2571+ return 0;
2572+}
2573+
2574+static int config_tty(const char *key, char *value, struct lxc_conf *lxc_conf)
2575+{
2576+ int nbtty = atoi(value);
2577+
2578+ lxc_conf->tty = nbtty;
2579+
2580+ return 0;
2581+}
2582+
2583+static int config_cgroup(const char *key, char *value, struct lxc_conf *lxc_conf)
2584+{
2585+ char *token = "lxc.cgroup.";
2586+ char *subkey;
2587+ struct lxc_list *cglist = NULL;
2588+ struct lxc_cgroup *cgelem = NULL;
2589+
2590+ subkey = strstr(key, token);
2591+
2592+ if (!subkey)
2593+ return -1;
2594+
2595+ if (!strlen(subkey))
2596+ return -1;
2597+
2598+ if (strlen(subkey) == strlen(token))
2599+ return -1;
2600+
2601+ subkey += strlen(token);
2602+
2603+ cglist = malloc(sizeof(*cglist));
2604+ if (!cglist)
2605+ goto out;
2606+
2607+ cgelem = malloc(sizeof(*cgelem));
2608+ if (!cgelem)
2609+ goto out;
2610+ memset(cgelem, 0, sizeof(*cgelem));
2611+
2612+ cgelem->subsystem = strdup(subkey);
2613+ cgelem->value = strdup(value);
2614+
2615+ if (!cgelem->subsystem || !cgelem->value)
2616+ goto out;
2617+
2618+ cglist->elem = cgelem;
2619+
2620+ lxc_list_add_tail(&lxc_conf->cgroup, cglist);
2621+
2622+ return 0;
2623+
2624+out:
2625+ if (cglist)
2626+ free(cglist);
2627+
2628+ if (cgelem) {
2629+ if (cgelem->subsystem)
2630+ free(cgelem->subsystem);
2631+
2632+ if (cgelem->value)
2633+ free(cgelem->value);
2634+
2635+ free(cgelem);
2636+ }
2637+
2638+ return -1;
2639+}
2640+
2641+static int config_fstab(const char *key, char *value, struct lxc_conf *lxc_conf)
2642+{
2643+ if (strlen(value) >= MAXPATHLEN) {
2644+ ERROR("%s path is too long", value);
2645+ return -1;
2646+ }
2647+
2648+ lxc_conf->fstab = strdup(value);
2649+ if (!lxc_conf->fstab) {
2650+ SYSERROR("failed to duplicate string %s", value);
2651+ return -1;
2652+ }
2653+
2654+ return 0;
2655+}
2656+
2657+static int config_mount(const char *key, char *value, struct lxc_conf *lxc_conf)
2658+{
2659+ char *fstab_token = "lxc.mount";
2660+ char *token = "lxc.mount.entry";
2661+ char *subkey;
2662+ char *mntelem;
2663+ struct lxc_list *mntlist;
2664+
2665+ subkey = strstr(key, token);
2666+
2667+ if (!subkey) {
2668+ subkey = strstr(key, fstab_token);
2669+
2670+ if (!subkey)
2671+ return -1;
2672+
2673+ return config_fstab(key, value, lxc_conf);
2674+ }
2675+
2676+ if (!strlen(subkey))
2677+ return -1;
2678+
2679+ mntlist = malloc(sizeof(*mntlist));
2680+ if (!mntlist)
2681+ return -1;
2682+
2683+ mntelem = strdup(value);
2684+ if (!mntelem)
2685+ return -1;
2686+ mntlist->elem = mntelem;
2687+
2688+ lxc_list_add_tail(&lxc_conf->mount_list, mntlist);
2689+
2690+ return 0;
2691+}
2692+
2693+static int config_cap_drop(const char *key, char *value,
2694+ struct lxc_conf *lxc_conf)
2695+{
2696+ char *dropcaps, *sptr, *token;
2697+ struct lxc_list *droplist;
2698+ int ret = -1;
2699+
2700+ if (!strlen(value))
2701+ return -1;
2702+
2703+ dropcaps = strdup(value);
2704+ if (!dropcaps) {
2705+ SYSERROR("failed to dup '%s'", value);
2706+ return -1;
2707+ }
2708+
2709+ /* in case several capability drop is specified in a single line
2710+ * split these caps in a single element for the list */
2711+ for (;;) {
2712+ token = strtok_r(dropcaps, " \t", &sptr);
2713+ if (!token) {
2714+ ret = 0;
2715+ break;
2716+ }
2717+ dropcaps = NULL;
2718+
2719+ droplist = malloc(sizeof(*droplist));
2720+ if (!droplist) {
2721+ SYSERROR("failed to allocate drop list");
2722+ break;
2723+ }
2724+
2725+ droplist->elem = strdup(token);
2726+ if (!droplist->elem) {
2727+ SYSERROR("failed to dup '%s'", token);
2728+ free(droplist);
2729+ break;
2730+ }
2731+
2732+ lxc_list_add_tail(&lxc_conf->caps, droplist);
2733+ }
2734+
2735+ free(dropcaps);
2736+
2737+ return ret;
2738+}
2739+
2740+static int config_console(const char *key, char *value,
2741+ struct lxc_conf *lxc_conf)
2742+{
2743+ char *path;
2744+
2745+ path = strdup(value);
2746+ if (!path) {
2747+ SYSERROR("failed to strdup '%s': %m", value);
2748+ return -1;
2749+ }
2750+
2751+ lxc_conf->console.path = path;
2752+
2753+ return 0;
2754+}
2755+
2756+static int config_rootfs(const char *key, char *value, struct lxc_conf *lxc_conf)
2757+{
2758+ if (strlen(value) >= MAXPATHLEN) {
2759+ ERROR("%s path is too long", value);
2760+ return -1;
2761+ }
2762+
2763+ lxc_conf->rootfs.path = strdup(value);
2764+ if (!lxc_conf->rootfs.path) {
2765+ SYSERROR("failed to duplicate string %s", value);
2766+ return -1;
2767+ }
2768+
2769+ return 0;
2770+}
2771+
2772+static int config_rootfs_mount(const char *key, char *value, struct lxc_conf *lxc_conf)
2773+{
2774+ if (strlen(value) >= MAXPATHLEN) {
2775+ ERROR("%s path is too long", value);
2776+ return -1;
2777+ }
2778+
2779+ lxc_conf->rootfs.mount = strdup(value);
2780+ if (!lxc_conf->rootfs.mount) {
2781+ SYSERROR("failed to duplicate string '%s'", value);
2782+ return -1;
2783+ }
2784+
2785+ return 0;
2786+}
2787+
2788+static int config_pivotdir(const char *key, char *value, struct lxc_conf *lxc_conf)
2789+{
2790+ if (strlen(value) >= MAXPATHLEN) {
2791+ ERROR("%s path is too long", value);
2792+ return -1;
2793+ }
2794+
2795+ lxc_conf->rootfs.pivot = strdup(value);
2796+ if (!lxc_conf->rootfs.pivot) {
2797+ SYSERROR("failed to duplicate string %s", value);
2798+ return -1;
2799+ }
2800+
2801+ return 0;
2802+}
2803+
2804+static int config_utsname(const char *key, char *value, struct lxc_conf *lxc_conf)
2805+{
2806+ struct utsname *utsname;
2807+
2808+ utsname = malloc(sizeof(*utsname));
2809+ if (!utsname) {
2810+ SYSERROR("failed to allocate memory");
2811+ return -1;
2812+ }
2813+
2814+ if (strlen(value) >= sizeof(utsname->nodename)) {
2815+ ERROR("node name '%s' is too long",
2816+ utsname->nodename);
2817+ return -1;
2818+ }
2819+
2820+ strcpy(utsname->nodename, value);
2821+ lxc_conf->utsname = utsname;
2822+
2823+ return 0;
2824+}
2825+
2826+static int parse_line(char *buffer, void *data)
2827+{
2828+ struct config *config;
2829+ char *line, *linep;
2830+ char *dot;
2831+ char *key;
2832+ char *value;
2833+ int ret = 0;
2834+
2835+ if (lxc_is_line_empty(buffer))
2836+ return 0;
2837+
2838+ /* we have to dup the buffer otherwise, at the re-exec for
2839+ * reboot we modified the original string on the stack by
2840+ * replacing '=' by '\0' below
2841+ */
2842+ linep = line = strdup(buffer);
2843+ if (!line) {
2844+ SYSERROR("failed to allocate memory for '%s'", buffer);
2845+ return -1;
2846+ }
2847+
2848+ line += lxc_char_left_gc(line, strlen(line));
2849+
2850+ /* martian option - ignoring it, the commented lines beginning by '#'
2851+ * fall in this case
2852+ */
2853+ if (strncmp(line, "lxc.", 4))
2854+ goto out;
2855+
2856+ ret = -1;
2857+
2858+ dot = strstr(line, "=");
2859+ if (!dot) {
2860+ ERROR("invalid configuration line: %s", line);
2861+ goto out;
2862+ }
2863+
2864+ *dot = '\0';
2865+ value = dot + 1;
2866+
2867+ key = line;
2868+ key[lxc_char_right_gc(key, strlen(key))] = '\0';
2869+
2870+ value += lxc_char_left_gc(value, strlen(value));
2871+ value[lxc_char_right_gc(value, strlen(value))] = '\0';
2872+
2873+ config = getconfig(key);
2874+ if (!config) {
2875+ ERROR("unknow key %s", key);
2876+ goto out;
2877+ }
2878+
2879+ ret = config->cb(key, value, data);
2880+
2881+out:
2882+ free(linep);
2883+ return ret;
2884+}
2885+
2886+int lxc_config_readline(char *buffer, struct lxc_conf *conf)
2887+{
2888+ return parse_line(buffer, conf);
2889+}
2890+
2891+int lxc_config_read(const char *file, struct lxc_conf *conf)
2892+{
2893+ return lxc_file_for_each_line(file, parse_line, conf);
2894+}
2895+
2896+int lxc_config_define_add(struct lxc_list *defines, char* arg)
2897+{
2898+ struct lxc_list *dent;
2899+
2900+ dent = malloc(sizeof(struct lxc_list));
2901+ if (!dent)
2902+ return -1;
2903+
2904+ dent->elem = arg;
2905+ lxc_list_add_tail(defines, dent);
2906+ return 0;
2907+}
2908+
2909+int lxc_config_define_load(struct lxc_list *defines, struct lxc_conf *conf)
2910+{
2911+ struct lxc_list *it;
2912+ int ret = 0;
2913+
2914+ lxc_list_for_each(it, defines) {
2915+ ret = lxc_config_readline(it->elem, conf);
2916+ if (ret)
2917+ break;
2918+ }
2919+
2920+ lxc_list_for_each(it, defines) {
2921+ lxc_list_del(it);
2922+ free(it);
2923+ }
2924+
2925+ return ret;
2926+}
2927
2928=== added directory '.pc/0041-ubuntu-template-user-and-tty'
2929=== renamed directory '.pc/0041-ubuntu-template-user-and-tty' => '.pc/0041-ubuntu-template-user-and-tty.moved'
2930=== added directory '.pc/0041-ubuntu-template-user-and-tty/templates'
2931=== added file '.pc/0041-ubuntu-template-user-and-tty/templates/lxc-ubuntu.in'
2932--- .pc/0041-ubuntu-template-user-and-tty/templates/lxc-ubuntu.in 1970-01-01 00:00:00 +0000
2933+++ .pc/0041-ubuntu-template-user-and-tty/templates/lxc-ubuntu.in 2012-02-11 04:43:19 +0000
2934@@ -0,0 +1,595 @@
2935+#!/bin/bash
2936+
2937+#
2938+# template script for generating ubuntu container for LXC
2939+#
2940+# This script consolidates and extends the existing lxc ubuntu scripts
2941+#
2942+
2943+# Copyright © 2011 Serge Hallyn <serge.hallyn@canonical.com>
2944+# Copyright © 2010 Wilhelm Meier
2945+# Author: Wilhelm Meier <wilhelm.meier@fh-kl.de>
2946+#
2947+# This program is free software; you can redistribute it and/or modify
2948+# it under the terms of the GNU General Public License version 2, as
2949+# published by the Free Software Foundation.
2950+
2951+# This program is distributed in the hope that it will be useful,
2952+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2953+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2954+# GNU General Public License for more details.
2955+
2956+# You should have received a copy of the GNU General Public License along
2957+# with this program; if not, write to the Free Software Foundation, Inc.,
2958+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
2959+#
2960+
2961+set -e
2962+
2963+if [ -r /etc/default/lxc ]; then
2964+ . /etc/default/lxc
2965+fi
2966+
2967+configure_ubuntu()
2968+{
2969+ rootfs=$1
2970+ hostname=$2
2971+
2972+ # configure the network using the dhcp
2973+ cat <<EOF > $rootfs/etc/network/interfaces
2974+auto lo
2975+iface lo inet loopback
2976+
2977+auto eth0
2978+iface eth0 inet dhcp
2979+EOF
2980+
2981+ # so you can 'ssh $hostname.' or 'ssh $hostname.local'
2982+ if [ -f $rootfs/etc/dhcp/dhclient.conf ]; then
2983+ sed -i "s/<hostname>/$hostname/" $rootfs/etc/dhcp/dhclient.conf
2984+ elif [ -f $rootfs/etc/dhcp3/dhclient.conf ]; then
2985+ sed -i "s/<hostname>/$hostname/" $rootfs/etc/dhcp3/dhclient.conf
2986+ fi
2987+
2988+ # set the hostname
2989+ cat <<EOF > $rootfs/etc/hostname
2990+$hostname
2991+EOF
2992+ # set minimal hosts
2993+ cat <<EOF > $rootfs/etc/hosts
2994+127.0.0.1 localhost $hostname
2995+EOF
2996+
2997+ # suppress log level output for udev
2998+ sed -i "s/=\"err\"/=0/" $rootfs/etc/udev/udev.conf
2999+
3000+ # remove jobs for consoles 5 and 6 since we only create 4 consoles in
3001+ # this template
3002+ rm -f $rootfs/etc/init/tty{5,6}.conf
3003+
3004+ echo "Please change root-password !"
3005+ echo "root:root" | chroot $rootfs chpasswd
3006+
3007+ return 0
3008+}
3009+
3010+write_sourceslist()
3011+{
3012+ # $1 => path to the rootfs
3013+ # $2 => architecture we want to add
3014+ # $3 => whether to use the multi-arch syntax or not
3015+
3016+ case $2 in
3017+ amd64|i386)
3018+ MIRROR=${MIRROR:-http://archive.ubuntu.com/ubuntu}
3019+ SECURITY_MIRROR=${SECURITY_MIRROR:-http://security.ubuntu.com/ubuntu}
3020+ ;;
3021+ sparc)
3022+ case $SUITE in
3023+ gutsy)
3024+ MIRROR=${MIRROR:-http://archive.ubuntu.com/ubuntu}
3025+ SECURITY_MIRROR=${SECURITY_MIRRORMIRROR:-http://security.ubuntu.com/ubuntu}
3026+ ;;
3027+ *)
3028+ MIRROR=${MIRROR:-http://ports.ubuntu.com/ubuntu-ports}
3029+ SECURITY_MIRROR=${SECURITY_MIRROR:-http://ports.ubuntu.com/ubuntu-ports}
3030+ ;;
3031+ esac
3032+ ;;
3033+ *)
3034+ MIRROR=${MIRROR:-http://ports.ubuntu.com/ubuntu-ports}
3035+ SECURITY_MIRROR=${SECURITY_MIRROR:-http://ports.ubuntu.com/ubuntu-ports}
3036+ ;;
3037+ esac
3038+ if [ -n "$3" ]; then
3039+ cat >> "$1/etc/apt/sources.list" << EOF
3040+deb [arch=$2] $MIRROR ${release} main restricted universe multiverse
3041+deb [arch=$2] $MIRROR ${release}-updates main restricted universe multiverse
3042+deb [arch=$2] $SECURITY_MIRROR ${release}-security main restricted universe multiverse
3043+EOF
3044+ else
3045+ cat >> "$1/etc/apt/sources.list" << EOF
3046+deb $MIRROR ${release} main restricted universe multiverse
3047+deb $MIRROR ${release}-updates main restricted universe multiverse
3048+deb $SECURITY_MIRROR ${release}-security main restricted universe multiverse
3049+EOF
3050+ fi
3051+}
3052+
3053+download_ubuntu()
3054+{
3055+ cache=$1
3056+ arch=$2
3057+ release=$3
3058+
3059+ if [ $release = "lucid" ]; then
3060+ packages=dialog,apt,apt-utils,resolvconf,iproute,inetutils-ping,vim,dhcp3-client,ssh,lsb-release,gnupg
3061+ elif [ $release = "maverick" ]; then
3062+ packages=dialog,apt,apt-utils,resolvconf,iproute,inetutils-ping,vim,dhcp3-client,ssh,lsb-release,gnupg,netbase
3063+ elif [ $release = "natty" ]; then
3064+ packages=dialog,apt,apt-utils,resolvconf,iproute,inetutils-ping,vim,isc-dhcp-client,isc-dhcp-common,ssh,lsb-release,gnupg,netbase
3065+ else
3066+ packages=dialog,apt,apt-utils,iproute,inetutils-ping,vim,isc-dhcp-client,isc-dhcp-common,ssh,lsb-release,gnupg,netbase,ubuntu-keyring
3067+ fi
3068+ echo "installing packages: $packages"
3069+
3070+ # check the mini ubuntu was not already downloaded
3071+ mkdir -p "$cache/partial-$arch"
3072+ if [ $? -ne 0 ]; then
3073+ echo "Failed to create '$cache/partial-$arch' directory"
3074+ return 1
3075+ fi
3076+
3077+ # download a mini ubuntu into a cache
3078+ echo "Downloading ubuntu $release minimal ..."
3079+ if [ -n "$(which qemu-debootstrap)" ]; then
3080+ qemu-debootstrap --verbose --components=main,universe --arch=$arch --include=$packages $release $cache/partial-$arch $MIRROR
3081+ else
3082+ debootstrap --verbose --components=main,universe --arch=$arch --include=$packages $release $cache/partial-$arch $MIRROR
3083+ fi
3084+
3085+ if [ $? -ne 0 ]; then
3086+ echo "Failed to download the rootfs, aborting."
3087+ return 1
3088+ fi
3089+
3090+ # Serge isn't sure whether we should avoid doing this when
3091+ # $release == `distro-info -d`
3092+ echo "Installing updates"
3093+ > $cache/partial-$arch/etc/apt/sources.list
3094+ write_sourceslist $cache/partial-$arch/ $arch
3095+
3096+ chroot "$1/partial-${arch}" apt-get update
3097+ if [ $? -ne 0 ]; then
3098+ echo "Failed to update the apt cache"
3099+ return 1
3100+ fi
3101+ cat > "$1/partial-${arch}"/usr/sbin/policy-rc.d << EOF
3102+#!/bin/sh
3103+exit 101
3104+EOF
3105+ chmod +x "$1/partial-${arch}"/usr/sbin/policy-rc.d
3106+
3107+ lxc-unshare -s MOUNT -- chroot "$1/partial-${arch}" apt-get dist-upgrade -y
3108+ ret=$?
3109+ rm -f "$1/partial-${arch}"/usr/sbin/policy-rc.d
3110+
3111+ if [ $ret -ne 0 ]; then
3112+ echo "Failed to upgrade the cache"
3113+ return 1
3114+ fi
3115+
3116+ mv "$1/partial-$arch" "$1/rootfs-$arch"
3117+ echo "Download complete"
3118+ return 0
3119+}
3120+
3121+copy_ubuntu()
3122+{
3123+ cache=$1
3124+ arch=$2
3125+ rootfs=$3
3126+
3127+ # make a local copy of the miniubuntu
3128+ echo -n "Copying rootfs to $rootfs ..."
3129+ mkdir -p $rootfs
3130+ rsync -a $cache/rootfs-$arch/ $rootfs/ || return 1
3131+ return 0
3132+}
3133+
3134+install_ubuntu()
3135+{
3136+ rootfs=$1
3137+ release=$2
3138+ flushcache=$3
3139+ cache="/var/cache/lxc/$release"
3140+ mkdir -p /var/lock/subsys/
3141+ (
3142+ flock -n -x 200
3143+ if [ $? -ne 0 ]; then
3144+ echo "Cache repository is busy."
3145+ return 1
3146+ fi
3147+
3148+
3149+ if [ $flushcache -eq 1 ]; then
3150+ echo "Flushing cache..."
3151+ rm -rf "$cache/partial-$arch"
3152+ rm -rf "$cache/rootfs-$arch"
3153+ fi
3154+
3155+ echo "Checking cache download in $cache/rootfs-$arch ... "
3156+ if [ ! -e "$cache/rootfs-$arch" ]; then
3157+ download_ubuntu $cache $arch $release
3158+ if [ $? -ne 0 ]; then
3159+ echo "Failed to download 'ubuntu $release base'"
3160+ return 1
3161+ fi
3162+ fi
3163+
3164+ echo "Copy $cache/rootfs-$arch to $rootfs ... "
3165+ copy_ubuntu $cache $arch $rootfs
3166+ if [ $? -ne 0 ]; then
3167+ echo "Failed to copy rootfs"
3168+ return 1
3169+ fi
3170+
3171+ return 0
3172+
3173+ ) 200>/var/lock/subsys/lxc
3174+
3175+ return $?
3176+}
3177+
3178+copy_configuration()
3179+{
3180+ path=$1
3181+ rootfs=$2
3182+ name=$3
3183+ arch=$4
3184+
3185+ if [ $arch = "i386" ]; then
3186+ arch="i686"
3187+ fi
3188+
3189+ cat <<EOF >> $path/config
3190+lxc.utsname = $name
3191+
3192+lxc.tty = 4
3193+lxc.pts = 1024
3194+lxc.rootfs = $rootfs
3195+lxc.mount = $path/fstab
3196+lxc.arch = $arch
3197+lxc.cap.drop = sys_module mac_admin
3198+
3199+lxc.cgroup.devices.deny = a
3200+# Allow any mknod (but not using the node)
3201+lxc.cgroup.devices.allow = c *:* m
3202+lxc.cgroup.devices.allow = b *:* m
3203+# /dev/null and zero
3204+lxc.cgroup.devices.allow = c 1:3 rwm
3205+lxc.cgroup.devices.allow = c 1:5 rwm
3206+# consoles
3207+lxc.cgroup.devices.allow = c 5:1 rwm
3208+lxc.cgroup.devices.allow = c 5:0 rwm
3209+#lxc.cgroup.devices.allow = c 4:0 rwm
3210+#lxc.cgroup.devices.allow = c 4:1 rwm
3211+# /dev/{,u}random
3212+lxc.cgroup.devices.allow = c 1:9 rwm
3213+lxc.cgroup.devices.allow = c 1:8 rwm
3214+lxc.cgroup.devices.allow = c 136:* rwm
3215+lxc.cgroup.devices.allow = c 5:2 rwm
3216+# rtc
3217+lxc.cgroup.devices.allow = c 254:0 rwm
3218+#fuse
3219+lxc.cgroup.devices.allow = c 10:229 rwm
3220+#tun
3221+lxc.cgroup.devices.allow = c 10:200 rwm
3222+#full
3223+lxc.cgroup.devices.allow = c 1:7 rwm
3224+#hpet
3225+lxc.cgroup.devices.allow = c 10:228 rwm
3226+#kvm
3227+lxc.cgroup.devices.allow = c 10:232 rwm
3228+EOF
3229+
3230+ cat <<EOF > $path/fstab
3231+proc $rootfs/proc proc nodev,noexec,nosuid 0 0
3232+sysfs $rootfs/sys sysfs defaults 0 0
3233+EOF
3234+
3235+ if [ $? -ne 0 ]; then
3236+ echo "Failed to add configuration"
3237+ return 1
3238+ fi
3239+
3240+ return 0
3241+}
3242+
3243+trim()
3244+{
3245+ rootfs=$1
3246+ release=$2
3247+
3248+ # provide the lxc service
3249+ cat <<EOF > $rootfs/etc/init/lxc.conf
3250+# fake some events needed for correct startup other services
3251+
3252+description "Container Upstart"
3253+
3254+start on startup
3255+
3256+script
3257+ rm -rf /var/run/*.pid
3258+ rm -rf /var/run/network/*
3259+ /sbin/initctl emit stopped JOB=udevtrigger --no-wait
3260+ /sbin/initctl emit started JOB=udev --no-wait
3261+end script
3262+EOF
3263+
3264+ # fix buggus runlevel with sshd
3265+ cat <<EOF > $rootfs/etc/init/ssh.conf
3266+# ssh - OpenBSD Secure Shell server
3267+#
3268+# The OpenSSH server provides secure shell access to the system.
3269+
3270+description "OpenSSH server"
3271+
3272+start on filesystem
3273+stop on runlevel [!2345]
3274+
3275+expect fork
3276+respawn
3277+respawn limit 10 5
3278+umask 022
3279+# replaces SSHD_OOM_ADJUST in /etc/default/ssh
3280+oom never
3281+
3282+pre-start script
3283+ test -x /usr/sbin/sshd || { stop; exit 0; }
3284+ test -e /etc/ssh/sshd_not_to_be_run && { stop; exit 0; }
3285+ test -c /dev/null || { stop; exit 0; }
3286+
3287+ mkdir -p -m0755 /var/run/sshd
3288+end script
3289+
3290+# if you used to set SSHD_OPTS in /etc/default/ssh, you can change the
3291+# 'exec' line here instead
3292+exec /usr/sbin/sshd
3293+EOF
3294+
3295+ cat <<EOF > $rootfs/etc/init/console.conf
3296+# console - getty
3297+#
3298+# This service maintains a console on tty1 from the point the system is
3299+# started until it is shut down again.
3300+
3301+start on stopped rc RUNLEVEL=[2345]
3302+stop on runlevel [!2345]
3303+
3304+respawn
3305+exec /sbin/getty -8 38400 /dev/console
3306+EOF
3307+
3308+ cat <<EOF > $rootfs/lib/init/fstab
3309+# /lib/init/fstab: cleared out for bare-bones lxc
3310+EOF
3311+
3312+ # reconfigure some services
3313+ if [ -z "$LANG" ]; then
3314+ chroot $rootfs locale-gen en_US.UTF-8
3315+ chroot $rootfs update-locale LANG=en_US.UTF-8
3316+ else
3317+ chroot $rootfs locale-gen $LANG
3318+ chroot $rootfs update-locale LANG=$LANG
3319+ fi
3320+
3321+ # remove pointless services in a container
3322+ chroot $rootfs /usr/sbin/update-rc.d -f ondemand remove
3323+
3324+ chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls u*.conf); do mv $f $f.orig; done'
3325+ chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls tty[2-9].conf); do mv $f $f.orig; done'
3326+ chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls plymouth*.conf); do mv $f $f.orig; done'
3327+ chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls hwclock*.conf); do mv $f $f.orig; done'
3328+ chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls module*.conf); do mv $f $f.orig; done'
3329+
3330+ # if this isn't lucid, then we need to twiddle the network upstart bits :(
3331+ if [ $release != "lucid" ]; then
3332+ sed -i 's/^.*emission handled.*$/echo Emitting lo/' $rootfs/etc/network/if-up.d/upstart
3333+ fi
3334+}
3335+
3336+post_process()
3337+{
3338+ rootfs=$1
3339+ release=$2
3340+ trim_container=$3
3341+
3342+ if [ $trim_container -eq 1 ]; then
3343+ trim $rootfs $release
3344+ elif [ $release = "lucid" -o $release = "maverick" -o $release = "natty" \
3345+ -o $release = "oneiric" ]; then
3346+ # for lucid and maverick, if not trimming, then add the ubuntu-virt
3347+ # ppa and install lxcguest
3348+ if [ $release = "lucid" -o $release = "maverick" ]; then
3349+ chroot $rootfs apt-get install --force-yes -y python-software-properties
3350+ chroot $rootfs add-apt-repository ppa:ubuntu-virt/ppa
3351+ fi
3352+ cresolvonf="${rootfs}/etc/resolv.conf"
3353+ mv $cresolvonf ${cresolvonf}.lxcbak
3354+ cat /etc/resolv.conf > ${cresolvonf}
3355+ chroot $rootfs apt-get update
3356+ chroot $rootfs apt-get install --force-yes -y lxcguest
3357+ rm -f ${cresolvonf}
3358+ mv ${cresolvonf}.lxcbak ${cresolvonf}
3359+ fi
3360+
3361+ # If the container isn't running a native architecture, setup multiarch
3362+ if [ -x "$(ls -1 ${rootfs}/usr/bin/qemu-*-static 2>/dev/null)" ]; then
3363+ mkdir -p ${rootfs}/etc/dpkg/dpkg.cfg.d
3364+ echo "foreign-architecture ${hostarch}" > ${rootfs}/etc/dpkg/dpkg.cfg.d/lxc-multiarch
3365+
3366+ # Save existing value of MIRROR and SECURITY_MIRROR
3367+ DEFAULT_MIRROR=$MIRROR
3368+ DEFAULT_SECURITY_MIRROR=$SECURITY_MIRROR
3369+
3370+ # Write a new sources.list containing both native and multiarch entries
3371+ > ${rootfs}/etc/apt/sources.list
3372+ write_sourceslist $rootfs $arch "native"
3373+
3374+ MIRROR=$DEFAULT_MIRROR
3375+ SECURITY_MIRROR=$DEFAULT_SECURITY_MIRROR
3376+ write_sourceslist $rootfs $hostarch "multiarch"
3377+
3378+ # Finally update the lists and install upstart using the host architecture
3379+ chroot $rootfs apt-get update
3380+ chroot $rootfs apt-get install --force-yes -y --no-install-recommends upstart:${hostarch} mountall:amd64 iproute:amd64 isc-dhcp-client:amd64
3381+ fi
3382+}
3383+
3384+do_bindhome()
3385+{
3386+ rootfs=$1
3387+ user=$2
3388+
3389+ # copy /etc/passwd, /etc/shadow, and /etc/group entries into container
3390+ pwd=`getent passwd $user`
3391+ if [ $? -ne 0 ]; then
3392+ echo 'Warning: failed to copy password entry for $user'
3393+ return
3394+ else
3395+ echo $pwd >> $rootfs/etc/passwd
3396+ fi
3397+ shad=`getent shadow $user`
3398+ echo $shad >> $rootfs/etc/shadow
3399+
3400+ # bind-mount the user's path into the container's /home
3401+ h=`getent passwd $user | cut -d: -f 6`
3402+ mkdir -p $rootfs/$h
3403+ echo "$h $rootfs/$h none bind 0 0" >> $path/fstab
3404+}
3405+
3406+usage()
3407+{
3408+ cat <<EOF
3409+$1 -h|--help [-a|--arch] [-b|--bindhome <user>] [--trim]
3410+ [-F | --flush-cache] [-r|--release <release>]
3411+release: lucid | maverick | natty | oneiric | precise
3412+trim: make a minimal (faster, but not upgrade-safe) container
3413+bindhome: bind <user>'s home into the container
3414+arch: amd64 or i386: defaults to host arch
3415+EOF
3416+ return 0
3417+}
3418+
3419+options=$(getopt -o a:b:hp:r:xn:F -l arch:,bindhome:,help,path:,release:,trim,name:,flush-cache -- "$@")
3420+if [ $? -ne 0 ]; then
3421+ usage $(basename $0)
3422+ exit 1
3423+fi
3424+eval set -- "$options"
3425+
3426+release=lucid
3427+if [ -f /etc/lsb-release ]; then
3428+ . /etc/lsb-release
3429+ case "$DISTRIB_CODENAME" in
3430+ lucid|maverick|natty|oneiric|precise)
3431+ release=$DISTRIB_CODENAME
3432+ ;;
3433+ esac
3434+fi
3435+
3436+bindhome=
3437+arch=$(arch)
3438+
3439+# Code taken from debootstrap
3440+if [ -x /usr/bin/dpkg ] && /usr/bin/dpkg --print-architecture >/dev/null 2>&1; then
3441+ arch=`/usr/bin/dpkg --print-architecture`
3442+elif type udpkg >/dev/null 2>&1 && udpkg --print-architecture >/dev/null 2>&1; then
3443+ arch=`/usr/bin/udpkg --print-architecture`
3444+else
3445+ arch=$(arch)
3446+ if [ "$arch" = "i686" ]; then
3447+ arch="i386"
3448+ elif [ "$arch" = "x86_64" ]; then
3449+ arch="amd64"
3450+ elif [ "$arch" = "armv7l" ]; then
3451+ arch="armel"
3452+ fi
3453+fi
3454+
3455+trim_container=0
3456+hostarch=$arch
3457+flushcache=0
3458+while true
3459+do
3460+ case "$1" in
3461+ -h|--help) usage $0 && exit 0;;
3462+ -p|--path) path=$2; shift 2;;
3463+ -n|--name) name=$2; shift 2;;
3464+ -F|--flush-cache) flushcache=1; shift 1;;
3465+ -r|--release) release=$2; shift 2;;
3466+ -b|--bindhome) bindhome=$2; shift 2;;
3467+ -a|--arch) arch=$2; shift 2;;
3468+ -x|--trim) trim_container=1; shift 1;;
3469+ --) shift 1; break ;;
3470+ *) break ;;
3471+ esac
3472+done
3473+
3474+pwd=`getent passwd $bindhome`
3475+if [ $? -ne 0 ]; then
3476+ echo "Error: no password entry found for $bindhome"
3477+ exit 1
3478+fi
3479+
3480+
3481+if [ "$arch" == "i686" ]; then
3482+ arch=i386
3483+fi
3484+
3485+if [ $hostarch = "i386" -a $arch = "amd64" ]; then
3486+ echo "can't create amd64 container on i386"
3487+ exit 1
3488+fi
3489+
3490+type debootstrap
3491+if [ $? -ne 0 ]; then
3492+ echo "'debootstrap' command is missing"
3493+ exit 1
3494+fi
3495+
3496+if [ -z "$path" ]; then
3497+ echo "'path' parameter is required"
3498+ exit 1
3499+fi
3500+
3501+if [ "$(id -u)" != "0" ]; then
3502+ echo "This script should be run as 'root'"
3503+ exit 1
3504+fi
3505+
3506+rootfs=$path/rootfs
3507+
3508+install_ubuntu $rootfs $release $flushcache
3509+if [ $? -ne 0 ]; then
3510+ echo "failed to install ubuntu $release"
3511+ exit 1
3512+fi
3513+
3514+configure_ubuntu $rootfs $name
3515+if [ $? -ne 0 ]; then
3516+ echo "failed to configure ubuntu $release for a container"
3517+ exit 1
3518+fi
3519+
3520+copy_configuration $path $rootfs $name $arch
3521+if [ $? -ne 0 ]; then
3522+ echo "failed write configuration file"
3523+ exit 1
3524+fi
3525+
3526+post_process $rootfs $release $trim_container
3527+if [ ! -z $bindhome ]; then
3528+ do_bindhome $rootfs $bindhome
3529+fi
3530
3531=== added file 'debian/patches/0040-consoles-into-devlxc.patch'
3532--- debian/patches/0040-consoles-into-devlxc.patch 1970-01-01 00:00:00 +0000
3533+++ debian/patches/0040-consoles-into-devlxc.patch 2012-02-11 04:43:19 +0000
3534@@ -0,0 +1,278 @@
3535+Description: add lxc.devttydir config variable
3536+ If set, then the console and ttys will be bind-mounted not over
3537+ /dev/console but /dev/<ttydir>/console, then symlinked from there
3538+ to /dev/console.
3539+ This will be forwarded but has not yet been.
3540+Author: Serge Hallyn <serge.hallyn@ubuntu.com>
3541+Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/lxc/+bug/927519
3542+Forwarded: no
3543+
3544+Index: lxc-0.7.5/src/lxc/conf.c
3545+===================================================================
3546+--- lxc-0.7.5.orig/src/lxc/conf.c 2011-07-24 22:27:10.000000000 +0000
3547++++ lxc-0.7.5/src/lxc/conf.c 2012-02-10 21:34:45.204739567 +0000
3548+@@ -505,10 +505,10 @@
3549+ }
3550+
3551+ static int setup_tty(const struct lxc_rootfs *rootfs,
3552+- const struct lxc_tty_info *tty_info)
3553++ const struct lxc_tty_info *tty_info, char *ttydir)
3554+ {
3555+- char path[MAXPATHLEN];
3556+- int i;
3557++ char path[MAXPATHLEN], lxcpath[MAXPATHLEN];
3558++ int i, ret;
3559+
3560+ if (!rootfs->path)
3561+ return 0;
3562+@@ -517,17 +517,50 @@
3563+
3564+ struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
3565+
3566+- snprintf(path, sizeof(path), "%s/dev/tty%d",
3567++ ret = snprintf(path, sizeof(path), "%s/dev/tty%d",
3568+ rootfs->mount, i + 1);
3569++ if (ret >= sizeof(path)) {
3570++ ERROR("pathname too long for ttys");
3571++ return -1;
3572++ }
3573++ if (ttydir) {
3574++ /* create dev/lxc/tty%d" */
3575++ snprintf(lxcpath, sizeof(lxcpath), "%s/dev/%s/tty%d",
3576++ rootfs->mount, ttydir, i + 1);
3577++ if (ret >= sizeof(lxcpath)) {
3578++ ERROR("pathname too long for ttys");
3579++ return -1;
3580++ }
3581++ ret = creat(lxcpath, 0660);
3582++ if (ret==-1 && errno != EEXIST) {
3583++ SYSERROR("error creating %s\n", lxcpath);
3584++ return -1;
3585++ }
3586++ close(ret);
3587++ ret = unlink(path);
3588++ if (ret && errno != ENOENT) {
3589++ SYSERROR("error unlinking %s\n", path);
3590++ return -1;
3591++ }
3592+
3593+- /* At this point I can not use the "access" function
3594+- * to check the file is present or not because it fails
3595+- * with EACCES errno and I don't know why :( */
3596+-
3597+- if (mount(pty_info->name, path, "none", MS_BIND, 0)) {
3598+- WARN("failed to mount '%s'->'%s'",
3599+- pty_info->name, path);
3600+- continue;
3601++ if (mount(pty_info->name, lxcpath, "none", MS_BIND, 0)) {
3602++ WARN("failed to mount '%s'->'%s'",
3603++ pty_info->name, path);
3604++ continue;
3605++ }
3606++
3607++ snprintf(lxcpath, sizeof(lxcpath), "%s/tty%d", ttydir, i+1);
3608++ ret = symlink(lxcpath, path);
3609++ if (ret) {
3610++ SYSERROR("failed to create symlink for tty %d\n", i+1);
3611++ return -1;
3612++ }
3613++ } else {
3614++ if (mount(pty_info->name, path, "none", MS_BIND, 0)) {
3615++ WARN("failed to mount '%s'->'%s'",
3616++ pty_info->name, path);
3617++ continue;
3618++ }
3619+ }
3620+ }
3621+
3622+@@ -805,17 +838,18 @@
3623+ return 0;
3624+ }
3625+
3626+-static int setup_console(const struct lxc_rootfs *rootfs,
3627++static int setup_dev_console(const struct lxc_rootfs *rootfs,
3628+ const struct lxc_console *console)
3629+ {
3630+ char path[MAXPATHLEN];
3631+ struct stat s;
3632++ int ret;
3633+
3634+- /* We don't have a rootfs, /dev/console will be shared */
3635+- if (!rootfs->path)
3636+- return 0;
3637+-
3638+- snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount);
3639++ ret = snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount);
3640++ if (ret >= sizeof(path)) {
3641++ ERROR("console path too long\n");
3642++ return -1;
3643++ }
3644+
3645+ if (access(path, F_OK)) {
3646+ WARN("rootfs specified but no console found at '%s'", path);
3647+@@ -844,10 +878,85 @@
3648+ }
3649+
3650+ INFO("console has been setup");
3651++ return 0;
3652++}
3653++
3654++static int setup_ttydir_console(const struct lxc_rootfs *rootfs,
3655++ const struct lxc_console *console,
3656++ char *ttydir)
3657++{
3658++ char path[MAXPATHLEN], lxcpath[MAXPATHLEN];
3659++ int ret;
3660++
3661++ /* create rootfs/dev/<ttydir> directory */
3662++ ret = snprintf(path, sizeof(path), "%s/dev/%s", rootfs->mount,
3663++ ttydir);
3664++ if (ret >= sizeof(path))
3665++ return -1;
3666++ ret = mkdir(path, 0755);
3667++ if (ret && errno != EEXIST) {
3668++ SYSERROR("failed with errno %d to create %s\n", errno, path);
3669++ return -1;
3670++ }
3671++ INFO("created %s\n", path);
3672++
3673++ ret = snprintf(lxcpath, sizeof(lxcpath), "%s/dev/%s/console",
3674++ rootfs->mount, ttydir);
3675++ if (ret >= sizeof(lxcpath)) {
3676++ ERROR("console path too long\n");
3677++ return -1;
3678++ }
3679++
3680++ snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount);
3681++ ret = unlink(path);
3682++ if (ret && errno != ENOENT) {
3683++ SYSERROR("error unlinking %s\n", path);
3684++ return -1;
3685++ }
3686++
3687++ ret = creat(lxcpath, 0660);
3688++ if (ret==-1 && errno != EEXIST) {
3689++ SYSERROR("error %d creating %s\n", errno, lxcpath);
3690++ return -1;
3691++ }
3692++ close(ret);
3693++
3694++ if (console->peer == -1) {
3695++ INFO("no console output required");
3696++ return 0;
3697++ }
3698++
3699++ if (mount(console->name, lxcpath, "none", MS_BIND, 0)) {
3700++ ERROR("failed to mount '%s' on '%s'", console->name, lxcpath);
3701++ return -1;
3702++ }
3703++
3704++ /* create symlink from rootfs/dev/console to 'lxc/console' */
3705++ snprintf(lxcpath, sizeof(lxcpath), "%s/console", ttydir);
3706++ ret = symlink(lxcpath, path);
3707++ if (ret) {
3708++ SYSERROR("failed to create symlink for console");
3709++ return -1;
3710++ }
3711++
3712++ INFO("console has been setup on %s", lxcpath);
3713+
3714+ return 0;
3715+ }
3716+
3717++static int setup_console(const struct lxc_rootfs *rootfs,
3718++ const struct lxc_console *console,
3719++ char *ttydir)
3720++{
3721++ /* We don't have a rootfs, /dev/console will be shared */
3722++ if (!rootfs->path)
3723++ return 0;
3724++ if (!ttydir)
3725++ return setup_dev_console(rootfs, console);
3726++
3727++ return setup_ttydir_console(rootfs, console, ttydir);
3728++}
3729++
3730+ static int setup_cgroup(const char *name, struct lxc_list *cgroups)
3731+ {
3732+ struct lxc_list *iterator;
3733+@@ -1731,12 +1840,12 @@
3734+ return -1;
3735+ }
3736+
3737+- if (setup_console(&lxc_conf->rootfs, &lxc_conf->console)) {
3738++ if (setup_console(&lxc_conf->rootfs, &lxc_conf->console, lxc_conf->ttydir)) {
3739+ ERROR("failed to setup the console for '%s'", name);
3740+ return -1;
3741+ }
3742+
3743+- if (setup_tty(&lxc_conf->rootfs, &lxc_conf->tty_info)) {
3744++ if (setup_tty(&lxc_conf->rootfs, &lxc_conf->tty_info, lxc_conf->ttydir)) {
3745+ ERROR("failed to setup the ttys for '%s'", name);
3746+ return -1;
3747+ }
3748+Index: lxc-0.7.5/src/lxc/conf.h
3749+===================================================================
3750+--- lxc-0.7.5.orig/src/lxc/conf.h 2012-02-10 21:11:00.000000000 +0000
3751++++ lxc-0.7.5/src/lxc/conf.h 2012-02-10 21:11:32.882527859 +0000
3752+@@ -192,6 +192,7 @@
3753+ * @caps : list of the capabilities
3754+ * @tty_info : tty data
3755+ * @console : console data
3756++ * @ttydir : directory (under /dev) in which to create console and ttys
3757+ */
3758+ struct lxc_conf {
3759+ char *fstab;
3760+@@ -208,6 +209,7 @@
3761+ struct lxc_tty_info tty_info;
3762+ struct lxc_console console;
3763+ struct lxc_rootfs rootfs;
3764++ char *ttydir;
3765+ };
3766+
3767+ /*
3768+Index: lxc-0.7.5/src/lxc/confile.c
3769+===================================================================
3770+--- lxc-0.7.5.orig/src/lxc/confile.c 2012-02-10 21:11:00.000000000 +0000
3771++++ lxc-0.7.5/src/lxc/confile.c 2012-02-11 03:22:45.963238636 +0000
3772+@@ -47,6 +47,7 @@
3773+ static int config_personality(const char *, char *, struct lxc_conf *);
3774+ static int config_pts(const char *, char *, struct lxc_conf *);
3775+ static int config_tty(const char *, char *, struct lxc_conf *);
3776++static int config_ttydir(const char *, char *, struct lxc_conf *);
3777+ static int config_cgroup(const char *, char *, struct lxc_conf *);
3778+ static int config_mount(const char *, char *, struct lxc_conf *);
3779+ static int config_rootfs(const char *, char *, struct lxc_conf *);
3780+@@ -80,6 +81,7 @@
3781+ { "lxc.arch", config_personality },
3782+ { "lxc.pts", config_pts },
3783+ { "lxc.tty", config_tty },
3784++ { "lxc.devttydir", config_ttydir },
3785+ { "lxc.cgroup", config_cgroup },
3786+ { "lxc.mount", config_mount },
3787+ { "lxc.rootfs.mount", config_rootfs_mount },
3788+@@ -551,6 +553,24 @@
3789+
3790+ return 0;
3791+ }
3792++
3793++static int config_ttydir(const char *key, char *value,
3794++ struct lxc_conf *lxc_conf)
3795++{
3796++ char *path;
3797++
3798++ if (!value || strlen(value) == 0)
3799++ return 0;
3800++ path = strdup(value);
3801++ if (!path) {
3802++ SYSERROR("failed to strdup '%s': %m", value);
3803++ return -1;
3804++ }
3805++
3806++ lxc_conf->ttydir = path;
3807++
3808++ return 0;
3809++}
3810+
3811+ static int config_cgroup(const char *key, char *value, struct lxc_conf *lxc_conf)
3812+ {
3813
3814=== renamed file 'debian/patches/0040-consoles-into-devlxc.patch' => 'debian/patches/0040-consoles-into-devlxc.patch.moved'
3815=== added file 'debian/patches/0041-ubuntu-template-user-and-tty'
3816--- debian/patches/0041-ubuntu-template-user-and-tty 1970-01-01 00:00:00 +0000
3817+++ debian/patches/0041-ubuntu-template-user-and-tty 2012-02-11 04:43:19 +0000
3818@@ -0,0 +1,120 @@
3819+Description: Use ubuntu/ubuntu instead of root/root by default.
3820+ Also stop removing tty[56].conf in Precise.
3821+ Stop messing with dhclient.conf (default behavior is identical)
3822+ Set devttydir on Precise to /dev/lxc to allow for clean upgrades.
3823+Author: Stéphane Graber <stgraber@ubuntu.com>
3824+
3825+Index: lxc/templates/lxc-ubuntu.in
3826+===================================================================
3827+--- lxc.orig/templates/lxc-ubuntu.in 2012-02-10 22:30:22.188422468 -0500
3828++++ lxc/templates/lxc-ubuntu.in 2012-02-10 23:23:23.521324942 -0500
3829+@@ -34,6 +34,7 @@
3830+ {
3831+ rootfs=$1
3832+ hostname=$2
3833++ release=$3
3834+
3835+ # configure the network using the dhcp
3836+ cat <<EOF > $rootfs/etc/network/interfaces
3837+@@ -44,13 +45,6 @@
3838+ iface eth0 inet dhcp
3839+ EOF
3840+
3841+- # so you can 'ssh $hostname.' or 'ssh $hostname.local'
3842+- if [ -f $rootfs/etc/dhcp/dhclient.conf ]; then
3843+- sed -i "s/<hostname>/$hostname/" $rootfs/etc/dhcp/dhclient.conf
3844+- elif [ -f $rootfs/etc/dhcp3/dhclient.conf ]; then
3845+- sed -i "s/<hostname>/$hostname/" $rootfs/etc/dhcp3/dhclient.conf
3846+- fi
3847+-
3848+ # set the hostname
3849+ cat <<EOF > $rootfs/etc/hostname
3850+ $hostname
3851+@@ -60,16 +54,22 @@
3852+ 127.0.0.1 localhost $hostname
3853+ EOF
3854+
3855+- # suppress log level output for udev
3856+- sed -i "s/=\"err\"/=0/" $rootfs/etc/udev/udev.conf
3857++ if [ "$release" = "precise" ]; then
3858++ group="sudo"
3859++ else
3860++ group="admin"
3861+
3862+- # remove jobs for consoles 5 and 6 since we only create 4 consoles in
3863+- # this template
3864+- rm -f $rootfs/etc/init/tty{5,6}.conf
3865++ # suppress log level output for udev
3866++ sed -i "s/=\"err\"/=0/" $rootfs/etc/udev/udev.conf
3867+
3868+- echo "Please change root-password !"
3869+- echo "root:root" | chroot $rootfs chpasswd
3870++ # remove jobs for consoles 5 and 6 since we only create 4 consoles in
3871++ # this template
3872++ rm -f $rootfs/etc/init/tty{5,6}.conf
3873++ fi
3874+
3875++ chroot $rootfs groupadd --system $group >/dev/null 2>&1 || true
3876++ chroot $rootfs useradd --create-home -s /bin/bash -G $group ubuntu
3877++ echo "ubuntu:ubuntu" | chroot $rootfs chpasswd
3878+ return 0
3879+ }
3880+
3881+@@ -191,7 +191,7 @@
3882+ rootfs=$3
3883+
3884+ # make a local copy of the miniubuntu
3885+- echo -n "Copying rootfs to $rootfs ..."
3886++ echo "Copying rootfs to $rootfs ..."
3887+ mkdir -p $rootfs
3888+ rsync -a $cache/rootfs-$arch/ $rootfs/ || return 1
3889+ return 0
3890+@@ -247,14 +247,21 @@
3891+ rootfs=$2
3892+ name=$3
3893+ arch=$4
3894++ release=$5
3895+
3896+ if [ $arch = "i386" ]; then
3897+ arch="i686"
3898+ fi
3899+
3900++ ttydir=""
3901++ if [ $release = "precise" ]; then
3902++ ttydir=" lxc"
3903++ fi
3904++
3905+ cat <<EOF >> $path/config
3906+ lxc.utsname = $name
3907+
3908++lxc.devttydir = $ttydir
3909+ lxc.tty = 4
3910+ lxc.pts = 1024
3911+ lxc.rootfs = $rootfs
3912+@@ -577,13 +584,13 @@
3913+ exit 1
3914+ fi
3915+
3916+-configure_ubuntu $rootfs $name
3917++configure_ubuntu $rootfs $name $release
3918+ if [ $? -ne 0 ]; then
3919+ echo "failed to configure ubuntu $release for a container"
3920+ exit 1
3921+ fi
3922+
3923+-copy_configuration $path $rootfs $name $arch
3924++copy_configuration $path $rootfs $name $arch $release
3925+ if [ $? -ne 0 ]; then
3926+ echo "failed write configuration file"
3927+ exit 1
3928+@@ -593,3 +600,10 @@
3929+ if [ ! -z $bindhome ]; then
3930+ do_bindhome $rootfs $bindhome
3931+ fi
3932++
3933++echo ""
3934++echo "##"
3935++echo "# The default user is 'ubuntu' with password 'ubuntu'!"
3936++echo "# Use the 'sudo' command to run tasks as root in the container."
3937++echo "##"
3938++echo ""
3939
3940=== renamed file 'debian/patches/0041-ubuntu-template-user-and-tty' => 'debian/patches/0041-ubuntu-template-user-and-tty.moved'

Subscribers

People subscribed via source and target branches

to all changes: