Imported Upstream version 1.1.2 upstream/1.1.2
authorDariusz Michaluk <d.michaluk@samsung.com>
Tue, 5 May 2015 12:58:46 +0000 (14:58 +0200)
committerDariusz Michaluk <d.michaluk@samsung.com>
Tue, 5 May 2015 12:58:46 +0000 (14:58 +0200)
31 files changed:
README
config/init/systemd/Makefile.in
config/templates/gentoo.common.conf.in
configure
configure.ac
doc/ja/lxc-start-ephemeral.sgml.in
doc/lxc-start-ephemeral.sgml.in
lxc.spec
src/lxc/Makefile.am
src/lxc/Makefile.in
src/lxc/attach.c
src/lxc/cgfs.c
src/lxc/cgmanager.c
src/lxc/cgroup.c
src/lxc/cgroup.h
src/lxc/conf.c
src/lxc/conf.h
src/lxc/confile.c
src/lxc/list.h
src/lxc/log.c
src/lxc/log.h
src/lxc/lxc-start-ephemeral.in
src/lxc/lxc_checkpoint.c
src/lxc/lxccontainer.c
src/lxc/start.c
src/lxc/start.h
src/lxc/utils.c
src/lxc/version.h
src/tests/aa.c
src/tests/concurrent.c
templates/lxc-centos.in

diff --git a/README b/README
index 77572b3..3e2a963 100644 (file)
--- a/README
+++ b/README
@@ -9,7 +9,7 @@ What is lxc:
 
   The  linux  containers, lxc, aims to use these new functionalities to pro-
   vide a userspace container object which provides full  resource  isolation
-  and resource control for an applications or a system.
+  and resource control for an application or a system.
 
   The first objective of this project is to make the life easier for the ker-
   nel developers involved in the containers project and  especially  to  con-
index 9bf34d6..4534960 100644 (file)
@@ -461,8 +461,8 @@ maintainer-clean-generic:
        @echo "This command is intended for maintainers to use"
        @echo "it deletes files that may require special tools to rebuild."
        -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
-@INIT_SCRIPT_SYSTEMD_FALSE@uninstall-local:
 @INIT_SCRIPT_SYSTEMD_FALSE@install-data-local:
+@INIT_SCRIPT_SYSTEMD_FALSE@uninstall-local:
 clean: clean-am
 
 clean-am: clean-generic mostlyclean-am
index ca3ffc1..49cd411 100644 (file)
@@ -21,3 +21,7 @@ lxc.cgroup.devices.allow = c 10:232 rwm
 ## To use loop devices, copy the following line to the container's
 ## configuration file (uncommented).
 #lxc.cgroup.devices.allow = b 7:* rwm
+
+# /dev/shm needs to be mounted as tmpfs. It's needed by python (bug #496328)
+# and possibly other packages.
+lxc.mount.entry = none dev/shm tmpfs rw,nosuid,nodev,create=dir
index cacbc98..83bcc30 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for lxc 1.1.1.
+# Generated by GNU Autoconf 2.69 for lxc 1.1.2.
 #
 #
 # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -577,8 +577,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='lxc'
 PACKAGE_TARNAME='lxc'
-PACKAGE_VERSION='1.1.1'
-PACKAGE_STRING='lxc 1.1.1'
+PACKAGE_VERSION='1.1.2'
+PACKAGE_STRING='lxc 1.1.2'
 PACKAGE_BUGREPORT=''
 PACKAGE_URL=''
 
@@ -1435,7 +1435,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures lxc 1.1.1 to adapt to many kinds of systems.
+\`configure' configures lxc 1.1.2 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1505,7 +1505,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of lxc 1.1.1:";;
+     short | recursive ) echo "Configuration of lxc 1.1.2:";;
    esac
   cat <<\_ACEOF
 
@@ -1665,7 +1665,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-lxc configure 1.1.1
+lxc configure 1.1.2
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2130,7 +2130,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by lxc $as_me 1.1.1, which was
+It was created by lxc $as_me 1.1.2, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2601,7 +2601,7 @@ $as_echo "no" >&6; }
        fi
 fi
 
-LXC_VERSION_BASE=1.1.1
+LXC_VERSION_BASE=1.1.2
 
 
 
@@ -2609,9 +2609,9 @@ LXC_VERSION_MAJOR=1
 
 LXC_VERSION_MINOR=1
 
-LXC_VERSION_MICRO=1
+LXC_VERSION_MICRO=2
 
-LXC_VERSION=1.1.1
+LXC_VERSION=1.1.2
 
 
 
@@ -3132,7 +3132,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='lxc'
- VERSION='1.1.1'
+ VERSION='1.1.2'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -9874,7 +9874,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by lxc $as_me 1.1.1, which was
+This file was extended by lxc $as_me 1.1.2, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -9944,7 +9944,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-lxc config.status 1.1.1
+lxc config.status 1.1.2
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
index 0190d8c..574b2cd 100644 (file)
@@ -3,7 +3,7 @@
 
 m4_define([lxc_version_major], 1)
 m4_define([lxc_version_minor], 1)
-m4_define([lxc_version_micro], 1)
+m4_define([lxc_version_micro], 2)
 m4_define([lxc_version_beta], [])
 
 m4_define([lxc_version_base], [lxc_version_major.lxc_version_minor.lxc_version_micro])
index eca2a8b..3f79c74 100644 (file)
@@ -59,6 +59,7 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
       <arg choice="opt">--bdir</arg>
       <arg choice="opt">--user</arg>
       <arg choice="opt">--key</arg>
+      <arg choice="opt">--storage-type</arg>
       <arg choice="opt">--union-type</arg>
       <arg choice="opt">--keep-data</arg>
       <arg choice="opt">COMMAND</arg>
@@ -171,6 +172,20 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
 
       <varlistentry>
         <term>
+          <option><optional>--storage-type</optional></option>
+        </term>
+        <listitem>
+          <para>
+            <!--
+            Specify the type of storage used by the container. Valid types are tmpfs or dir.
+              -->
+            コンテナが使うストレージのタイプ。tmpfs か dir を指定できます。
+          </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term>
           <option><optional>--union-type</optional></option>
         </term>
         <listitem>
@@ -209,10 +224,12 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
           <para>
             <!--
             Immediately run the provided command in the container.
-            This currently uses ssh (not attach) and is incompatible
-            with daemon mode.
+            This uses attach if the kernel supports it, otherwise uses ssh.
+            This is incompatible with daemon mode.
             -->
-            即座に指定したコマンドをコンテナ内で実行します。現時点では (attach ではなく) ssh を使用します。そしてデーモンモードと両方を指定することはできません。
+            即座に指定したコマンドをコンテナ内で実行します。
+            コマンドを実行する際、カーネルがサポートしている場合は lxc-start-ephemeral は attach を使います。
+            カーネルがサポートしていない場合は ssh を使います。
           </para>
         </listitem>
       </varlistentry>
index d37ecf5..6f3a325 100644 (file)
@@ -53,6 +53,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
       <arg choice="opt">--bdir</arg>
       <arg choice="opt">--user</arg>
       <arg choice="opt">--key</arg>
+      <arg choice="opt">--storage-type</arg>
       <arg choice="opt">--union-type</arg>
       <arg choice="opt">--keep-data</arg>
       <arg choice="opt">COMMAND</arg>
@@ -141,6 +142,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
       <varlistentry>
         <term>
+          <option><optional>--storage-type</optional></option>
+        </term>
+        <listitem>
+          <para>
+            Specify the type of storage used by the container. Valid types are tmpfs or dir.
+          </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term>
           <option><optional>--union-type</optional></option>
         </term>
         <listitem>
@@ -171,8 +183,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
         <listitem>
           <para>
             Immediately run the provided command in the container.
-            This currently uses ssh (not attach) and is incompatible
-            with daemon mode.
+            This uses attach if the kernel supports it, otherwise uses ssh.
+            This is incompatible with daemon mode.
           </para>
         </listitem>
       </varlistentry>
index 15c7f32..75d2365 100644 (file)
--- a/lxc.spec
+++ b/lxc.spec
@@ -60,7 +60,7 @@ BuildRequires: systemd
 %endif
 
 Name: lxc
-Version: 1.1.1
+Version: 1.1.2
 Release: %{?beta_rel:0.1.%{beta_rel}}%{?!beta_rel:%{norm_rel}}%{?dist}
 URL: http://linuxcontainers.org
 Source: http://linuxcontainers.org/downloads/%{name}-%{version}%{?beta_dot}.tar.gz
index b1e56b9..8b79c40 100644 (file)
@@ -248,6 +248,7 @@ endif
 
 init_lxc_static_LDFLAGS = -static
 init_lxc_static_LDADD = @CAP_LIBS@
+init_lxc_static_CFLAGS = $(AM_CFLAGS) -DNO_LXC_CONF
 endif
 
 install-exec-local: install-soPROGRAMS
index 74052ef..c8ca0f0 100644 (file)
@@ -148,14 +148,17 @@ init_lxc_DEPENDENCIES = liblxc.so
 am__init_lxc_static_SOURCES_DIST = lxc_init.c error.c log.c utils.c \
        caps.c ../include/getline.c
 am__dirstamp = $(am__leading_dot)dirstamp
-@HAVE_FGETLN_TRUE@@HAVE_GETLINE_FALSE@@HAVE_STATIC_LIBCAP_TRUE@am__objects_1 = ../include/getline.$(OBJEXT)
+@HAVE_FGETLN_TRUE@@HAVE_GETLINE_FALSE@@HAVE_STATIC_LIBCAP_TRUE@am__objects_1 = ../include/init_lxc_static-getline.$(OBJEXT)
 @HAVE_STATIC_LIBCAP_TRUE@am_init_lxc_static_OBJECTS =  \
-@HAVE_STATIC_LIBCAP_TRUE@      lxc_init.$(OBJEXT) error.$(OBJEXT) \
-@HAVE_STATIC_LIBCAP_TRUE@      log.$(OBJEXT) utils.$(OBJEXT) \
-@HAVE_STATIC_LIBCAP_TRUE@      caps.$(OBJEXT) $(am__objects_1)
+@HAVE_STATIC_LIBCAP_TRUE@      init_lxc_static-lxc_init.$(OBJEXT) \
+@HAVE_STATIC_LIBCAP_TRUE@      init_lxc_static-error.$(OBJEXT) \
+@HAVE_STATIC_LIBCAP_TRUE@      init_lxc_static-log.$(OBJEXT) \
+@HAVE_STATIC_LIBCAP_TRUE@      init_lxc_static-utils.$(OBJEXT) \
+@HAVE_STATIC_LIBCAP_TRUE@      init_lxc_static-caps.$(OBJEXT) \
+@HAVE_STATIC_LIBCAP_TRUE@      $(am__objects_1)
 init_lxc_static_OBJECTS = $(am_init_lxc_static_OBJECTS)
 init_lxc_static_DEPENDENCIES =
-init_lxc_static_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+init_lxc_static_LINK = $(CCLD) $(init_lxc_static_CFLAGS) $(CFLAGS) \
        $(init_lxc_static_LDFLAGS) $(LDFLAGS) -o $@
 am__liblxc_so_SOURCES_DIST = arguments.c arguments.h bdev.c bdev.h \
        lxc-btrfs.h commands.c commands.h start.c start.h execute.c \
@@ -670,6 +673,7 @@ lxc_checkpoint_SOURCES = lxc_checkpoint.c
 @HAVE_STATIC_LIBCAP_TRUE@      log.c utils.c caps.c $(am__append_20)
 @HAVE_STATIC_LIBCAP_TRUE@init_lxc_static_LDFLAGS = -static
 @HAVE_STATIC_LIBCAP_TRUE@init_lxc_static_LDADD = @CAP_LIBS@
+@HAVE_STATIC_LIBCAP_TRUE@init_lxc_static_CFLAGS = $(AM_CFLAGS) -DNO_LXC_CONF
 all: all-am
 
 .SUFFIXES:
@@ -892,7 +896,8 @@ init.lxc$(EXEEXT): $(init_lxc_OBJECTS) $(init_lxc_DEPENDENCIES) $(EXTRA_init_lxc
 ../include/$(DEPDIR)/$(am__dirstamp):
        @$(MKDIR_P) ../include/$(DEPDIR)
        @: > ../include/$(DEPDIR)/$(am__dirstamp)
-../include/getline.$(OBJEXT): ../include/$(am__dirstamp) \
+../include/init_lxc_static-getline.$(OBJEXT):  \
+       ../include/$(am__dirstamp) \
        ../include/$(DEPDIR)/$(am__dirstamp)
 
 init.lxc.static$(EXEEXT): $(init_lxc_static_OBJECTS) $(init_lxc_static_DEPENDENCIES) $(EXTRA_init_lxc_static_DEPENDENCIES) 
@@ -1064,13 +1069,16 @@ mostlyclean-compile:
 distclean-compile:
        -rm -f *.tab.c
 
-@AMDEP_TRUE@@am__include@ @am__quote@../include/$(DEPDIR)/getline.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@../include/$(DEPDIR)/init_lxc_static-getline.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@../include/$(DEPDIR)/liblxc_so-getline.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@../include/$(DEPDIR)/liblxc_so-ifaddrs.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@../include/$(DEPDIR)/liblxc_so-lxcmntent.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@../include/$(DEPDIR)/liblxc_so-openpty.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/caps.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/init_lxc_static-caps.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/init_lxc_static-error.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/init_lxc_static-log.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/init_lxc_static-lxc_init.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/init_lxc_static-utils.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblxc_so-af_unix.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblxc_so-arguments.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblxc_so-attach.Po@am__quote@
@@ -1103,7 +1111,6 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblxc_so-state.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblxc_so-sync.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblxc_so-utils.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxc_attach.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxc_autostart.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxc_cgroup.Po@am__quote@
@@ -1130,7 +1137,6 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxc_usernsexec.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxc_wait.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/network.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@lsm/$(DEPDIR)/liblxc_so-apparmor.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@lsm/$(DEPDIR)/liblxc_so-lsm.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@lsm/$(DEPDIR)/liblxc_so-nop.Po@am__quote@
@@ -1152,6 +1158,90 @@ distclean-compile:
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
 
+init_lxc_static-lxc_init.o: lxc_init.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -MT init_lxc_static-lxc_init.o -MD -MP -MF $(DEPDIR)/init_lxc_static-lxc_init.Tpo -c -o init_lxc_static-lxc_init.o `test -f 'lxc_init.c' || echo '$(srcdir)/'`lxc_init.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/init_lxc_static-lxc_init.Tpo $(DEPDIR)/init_lxc_static-lxc_init.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='lxc_init.c' object='init_lxc_static-lxc_init.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -c -o init_lxc_static-lxc_init.o `test -f 'lxc_init.c' || echo '$(srcdir)/'`lxc_init.c
+
+init_lxc_static-lxc_init.obj: lxc_init.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -MT init_lxc_static-lxc_init.obj -MD -MP -MF $(DEPDIR)/init_lxc_static-lxc_init.Tpo -c -o init_lxc_static-lxc_init.obj `if test -f 'lxc_init.c'; then $(CYGPATH_W) 'lxc_init.c'; else $(CYGPATH_W) '$(srcdir)/lxc_init.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/init_lxc_static-lxc_init.Tpo $(DEPDIR)/init_lxc_static-lxc_init.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='lxc_init.c' object='init_lxc_static-lxc_init.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -c -o init_lxc_static-lxc_init.obj `if test -f 'lxc_init.c'; then $(CYGPATH_W) 'lxc_init.c'; else $(CYGPATH_W) '$(srcdir)/lxc_init.c'; fi`
+
+init_lxc_static-error.o: error.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -MT init_lxc_static-error.o -MD -MP -MF $(DEPDIR)/init_lxc_static-error.Tpo -c -o init_lxc_static-error.o `test -f 'error.c' || echo '$(srcdir)/'`error.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/init_lxc_static-error.Tpo $(DEPDIR)/init_lxc_static-error.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='error.c' object='init_lxc_static-error.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -c -o init_lxc_static-error.o `test -f 'error.c' || echo '$(srcdir)/'`error.c
+
+init_lxc_static-error.obj: error.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -MT init_lxc_static-error.obj -MD -MP -MF $(DEPDIR)/init_lxc_static-error.Tpo -c -o init_lxc_static-error.obj `if test -f 'error.c'; then $(CYGPATH_W) 'error.c'; else $(CYGPATH_W) '$(srcdir)/error.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/init_lxc_static-error.Tpo $(DEPDIR)/init_lxc_static-error.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='error.c' object='init_lxc_static-error.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -c -o init_lxc_static-error.obj `if test -f 'error.c'; then $(CYGPATH_W) 'error.c'; else $(CYGPATH_W) '$(srcdir)/error.c'; fi`
+
+init_lxc_static-log.o: log.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -MT init_lxc_static-log.o -MD -MP -MF $(DEPDIR)/init_lxc_static-log.Tpo -c -o init_lxc_static-log.o `test -f 'log.c' || echo '$(srcdir)/'`log.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/init_lxc_static-log.Tpo $(DEPDIR)/init_lxc_static-log.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='log.c' object='init_lxc_static-log.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -c -o init_lxc_static-log.o `test -f 'log.c' || echo '$(srcdir)/'`log.c
+
+init_lxc_static-log.obj: log.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -MT init_lxc_static-log.obj -MD -MP -MF $(DEPDIR)/init_lxc_static-log.Tpo -c -o init_lxc_static-log.obj `if test -f 'log.c'; then $(CYGPATH_W) 'log.c'; else $(CYGPATH_W) '$(srcdir)/log.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/init_lxc_static-log.Tpo $(DEPDIR)/init_lxc_static-log.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='log.c' object='init_lxc_static-log.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -c -o init_lxc_static-log.obj `if test -f 'log.c'; then $(CYGPATH_W) 'log.c'; else $(CYGPATH_W) '$(srcdir)/log.c'; fi`
+
+init_lxc_static-utils.o: utils.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -MT init_lxc_static-utils.o -MD -MP -MF $(DEPDIR)/init_lxc_static-utils.Tpo -c -o init_lxc_static-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/init_lxc_static-utils.Tpo $(DEPDIR)/init_lxc_static-utils.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils.c' object='init_lxc_static-utils.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -c -o init_lxc_static-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c
+
+init_lxc_static-utils.obj: utils.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -MT init_lxc_static-utils.obj -MD -MP -MF $(DEPDIR)/init_lxc_static-utils.Tpo -c -o init_lxc_static-utils.obj `if test -f 'utils.c'; then $(CYGPATH_W) 'utils.c'; else $(CYGPATH_W) '$(srcdir)/utils.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/init_lxc_static-utils.Tpo $(DEPDIR)/init_lxc_static-utils.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils.c' object='init_lxc_static-utils.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -c -o init_lxc_static-utils.obj `if test -f 'utils.c'; then $(CYGPATH_W) 'utils.c'; else $(CYGPATH_W) '$(srcdir)/utils.c'; fi`
+
+init_lxc_static-caps.o: caps.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -MT init_lxc_static-caps.o -MD -MP -MF $(DEPDIR)/init_lxc_static-caps.Tpo -c -o init_lxc_static-caps.o `test -f 'caps.c' || echo '$(srcdir)/'`caps.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/init_lxc_static-caps.Tpo $(DEPDIR)/init_lxc_static-caps.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='caps.c' object='init_lxc_static-caps.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -c -o init_lxc_static-caps.o `test -f 'caps.c' || echo '$(srcdir)/'`caps.c
+
+init_lxc_static-caps.obj: caps.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -MT init_lxc_static-caps.obj -MD -MP -MF $(DEPDIR)/init_lxc_static-caps.Tpo -c -o init_lxc_static-caps.obj `if test -f 'caps.c'; then $(CYGPATH_W) 'caps.c'; else $(CYGPATH_W) '$(srcdir)/caps.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/init_lxc_static-caps.Tpo $(DEPDIR)/init_lxc_static-caps.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='caps.c' object='init_lxc_static-caps.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -c -o init_lxc_static-caps.obj `if test -f 'caps.c'; then $(CYGPATH_W) 'caps.c'; else $(CYGPATH_W) '$(srcdir)/caps.c'; fi`
+
+../include/init_lxc_static-getline.o: ../include/getline.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -MT ../include/init_lxc_static-getline.o -MD -MP -MF ../include/$(DEPDIR)/init_lxc_static-getline.Tpo -c -o ../include/init_lxc_static-getline.o `test -f '../include/getline.c' || echo '$(srcdir)/'`../include/getline.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) ../include/$(DEPDIR)/init_lxc_static-getline.Tpo ../include/$(DEPDIR)/init_lxc_static-getline.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='../include/getline.c' object='../include/init_lxc_static-getline.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -c -o ../include/init_lxc_static-getline.o `test -f '../include/getline.c' || echo '$(srcdir)/'`../include/getline.c
+
+../include/init_lxc_static-getline.obj: ../include/getline.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -MT ../include/init_lxc_static-getline.obj -MD -MP -MF ../include/$(DEPDIR)/init_lxc_static-getline.Tpo -c -o ../include/init_lxc_static-getline.obj `if test -f '../include/getline.c'; then $(CYGPATH_W) '../include/getline.c'; else $(CYGPATH_W) '$(srcdir)/../include/getline.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) ../include/$(DEPDIR)/init_lxc_static-getline.Tpo ../include/$(DEPDIR)/init_lxc_static-getline.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='../include/getline.c' object='../include/init_lxc_static-getline.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -c -o ../include/init_lxc_static-getline.obj `if test -f '../include/getline.c'; then $(CYGPATH_W) '../include/getline.c'; else $(CYGPATH_W) '$(srcdir)/../include/getline.c'; fi`
+
 liblxc_so-arguments.o: arguments.c
 @am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblxc_so_CFLAGS) $(CFLAGS) -MT liblxc_so-arguments.o -MD -MP -MF $(DEPDIR)/liblxc_so-arguments.Tpo -c -o liblxc_so-arguments.o `test -f 'arguments.c' || echo '$(srcdir)/'`arguments.c
 @am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/liblxc_so-arguments.Tpo $(DEPDIR)/liblxc_so-arguments.Po
index faa90fc..69dafd4 100644 (file)
@@ -985,7 +985,7 @@ static int attach_child_main(void* data)
                new_gid = options->gid;
 
        /* setup the control tty */
-       if (options->stdin_fd) {
+       if (options->stdin_fd && isatty(options->stdin_fd)) {
                if (setsid() < 0) {
                        SYSERROR("unable to setsid");
                        shutdown(ipc_socket, SHUT_RDWR);
index 20325fa..11a5925 100644 (file)
@@ -2403,4 +2403,5 @@ static struct cgroup_ops cgfs_ops = {
        .chown = NULL,
        .mount_cgroup = cgroupfs_mount_cgroup,
        .nrtasks = cgfs_nrtasks,
+       .driver = CGFS,
 };
index 0932d96..fe8913e 100644 (file)
@@ -246,11 +246,12 @@ static void check_supports_multiple_controllers(pid_t pid)
                }
                if (strcmp(prevpath, colon) != 0) {
                        cgm_all_controllers_same = false;
-                       fclose(f);
-                       return;
+                       break;
                }
        }
+
        fclose(f);
+       free(line);
 }
 
 static int send_creds(int sock, int rpid, int ruid, int rgid)
@@ -1396,5 +1397,6 @@ static struct cgroup_ops cgmanager_ops = {
        .mount_cgroup = cgm_mount_cgroup,
        .nrtasks = cgm_get_nrtasks,
        .disconnect = NULL,
+       .driver = CGMANAGER,
 };
 #endif
index a413832..2362ad8 100644 (file)
@@ -189,3 +189,8 @@ void cgroup_disconnect(void)
        if (ops && ops->disconnect)
                ops->disconnect();
 }
+
+cgroup_driver_t cgroup_driver(void)
+{
+       return ops->driver;
+}
index 281f404..6706939 100644 (file)
@@ -32,6 +32,11 @@ struct lxc_handler;
 struct lxc_conf;
 struct lxc_list;
 
+typedef enum {
+       CGFS,
+       CGMANAGER,
+} cgroup_driver_t;
+
 struct cgroup_ops {
        const char *name;
 
@@ -51,6 +56,7 @@ struct cgroup_ops {
        bool (*mount_cgroup)(void *hdata, const char *root, int type);
        int (*nrtasks)(void *hdata);
        void (*disconnect)(void);
+       cgroup_driver_t driver;
 };
 
 extern bool cgroup_attach(const char *name, const char *lxcpath, pid_t pid);
@@ -72,5 +78,6 @@ extern const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *su
 extern const char *cgroup_canonical_path(struct lxc_handler *handler);
 extern bool cgroup_unfreeze(struct lxc_handler *handler);
 extern void cgroup_disconnect(void);
+extern cgroup_driver_t cgroup_driver(void);
 
 #endif
index 2868708..4249c6c 100644 (file)
@@ -178,6 +178,17 @@ struct caps_opt {
        int value;
 };
 
+/*
+ * The lxc_conf of the container currently being worked on in an
+ * API call
+ * This is used in the error calls
+ */
+#ifdef HAVE_TLS
+__thread struct lxc_conf *current_config;
+#else
+struct lxc_conf *current_config;
+#endif
+
 /* Declare this here, since we don't want to reshuffle the whole file. */
 static int in_caplist(int cap, struct lxc_list *caps);
 
@@ -2040,18 +2051,16 @@ static int setup_mount(const struct lxc_rootfs *rootfs, const char *fstab,
        return ret;
 }
 
-static int setup_mount_entries(const struct lxc_rootfs *rootfs, struct lxc_list *mount,
-       const char *lxc_name)
+FILE *write_mount_file(struct lxc_list *mount)
 {
        FILE *file;
        struct lxc_list *iterator;
        char *mount_entry;
-       int ret;
 
        file = tmpfile();
        if (!file) {
                ERROR("tmpfile error: %m");
-               return -1;
+               return NULL;
        }
 
        lxc_list_for_each(iterator, mount) {
@@ -2060,6 +2069,18 @@ static int setup_mount_entries(const struct lxc_rootfs *rootfs, struct lxc_list
        }
 
        rewind(file);
+       return file;
+}
+
+static int setup_mount_entries(const struct lxc_rootfs *rootfs, struct lxc_list *mount,
+       const char *lxc_name)
+{
+       FILE *file;
+       int ret;
+
+       file = write_mount_file(mount);
+       if (!file)
+               return -1;
 
        ret = mount_file_entries(rootfs, file, lxc_name);
 
@@ -2563,6 +2584,7 @@ struct lxc_conf *lxc_conf_init(void)
                return NULL;
        }
        new->kmsg = 0;
+       new->logfd = -1;
        lxc_list_init(&new->cgroup);
        lxc_list_init(&new->network);
        lxc_list_init(&new->mount_list);
@@ -4230,6 +4252,8 @@ void lxc_conf_free(struct lxc_conf *conf)
        free(conf->rootfs.path);
        free(conf->rootfs.pivot);
        free(conf->logfile);
+       if (conf->logfd != -1)
+               close(conf->logfd);
        free(conf->utsname);
        free(conf->ttydir);
        free(conf->fstab);
index afa5517..f3f8fd5 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "config.h"
 
+#include <stdio.h>
 #include <netinet/in.h>
 #include <net/if.h>
 #include <sys/param.h>
@@ -334,6 +335,7 @@ struct lxc_conf {
        // store the config file specified values here.
        char *logfile;  // the logfile as specifed in config
        int loglevel;   // loglevel as specifed in config (if any)
+       int logfd;
 
        int inherit_ns_fd[LXC_NS_MAX];
 
@@ -363,6 +365,12 @@ struct lxc_conf {
        char *init_cmd;
 };
 
+#ifdef HAVE_TLS
+extern __thread struct lxc_conf *current_config;
+#else
+extern struct lxc_conf *current_config;
+#endif
+
 int run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf,
                  const char *lxcpath, char *argv[]);
 
@@ -421,4 +429,5 @@ extern int parse_mntopts(const char *mntopts, unsigned long *mntflags,
 extern void tmp_proc_unmount(struct lxc_conf *lxc_conf);
 void remount_all_slave(void);
 extern void suggest_default_idmap(void);
+FILE *write_mount_file(struct lxc_list *mount);
 #endif
index 740487b..8189351 100644 (file)
@@ -1169,15 +1169,15 @@ static int config_lsm_se_context(const char *key, const char *value,
 }
 
 static int config_logfile(const char *key, const char *value,
-                            struct lxc_conf *lxc_conf)
+                            struct lxc_conf *c)
 {
        int ret;
 
        // store these values in the lxc_conf, and then try to set for
        // actual current logging.
-       ret = config_path_item(&lxc_conf->logfile, value);
+       ret = config_path_item(&c->logfile, value);
        if (ret == 0)
-               ret = lxc_log_set_file(lxc_conf->logfile);
+               ret = lxc_log_set_file(&c->logfd, c->logfile);
        return ret;
 }
 
@@ -1196,7 +1196,7 @@ static int config_loglevel(const char *key, const char *value,
        // store these values in the lxc_conf, and then try to set for
        // actual current logging.
        lxc_conf->loglevel = newlevel;
-       return lxc_log_set_level(newlevel);
+       return lxc_log_set_level(&lxc_conf->loglevel, newlevel);
 }
 
 static int config_autodev(const char *key, const char *value,
@@ -2367,9 +2367,9 @@ int lxc_get_config_item(struct lxc_conf *c, const char *key, char *retv,
        else if (strcmp(key, "lxc.se_context") == 0)
                v = c->lsm_se_context;
        else if (strcmp(key, "lxc.logfile") == 0)
-               v = lxc_log_get_file();
+               v = c->logfile;
        else if (strcmp(key, "lxc.loglevel") == 0)
-               v = lxc_log_priority_to_string(lxc_log_get_level());
+               v = lxc_log_priority_to_string(c->loglevel);
        else if (strcmp(key, "lxc.cgroup") == 0) // all cgroup info
                return lxc_get_cgroup_entry(c, retv, inlen, "all");
        else if (strncmp(key, "lxc.cgroup.", 11) == 0) // specific cgroup info
index 0882da0..f16af54 100644 (file)
@@ -99,4 +99,15 @@ static inline void lxc_list_del(struct lxc_list *list)
        prev->next = next;
 }
 
+static inline int lxc_list_len(struct lxc_list *list)
+{
+        int i = 0;
+        struct lxc_list *iter;
+        lxc_list_for_each(iter, list) {
+               i++;
+        }
+
+        return i;
+}
+
 #endif
index 6633e62..04ba2cc 100644 (file)
@@ -27,6 +27,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <string.h>
+#include <pthread.h>
 
 #define __USE_GNU /* for *_CLOEXEC */
 
 #define LXC_LOG_PREFIX_SIZE    32
 #define LXC_LOG_BUFFER_SIZE    512
 
-#ifdef HAVE_TLS
-__thread int lxc_log_fd = -1;
-static __thread char log_prefix[LXC_LOG_PREFIX_SIZE] = "lxc";
-static __thread char *log_fname = NULL;
-/* command line values for logfile or logpriority should always override
- * values from the configuration file or defaults
- */
-static __thread int lxc_logfile_specified = 0;
-static __thread int lxc_loglevel_specified = 0;
-static __thread int lxc_quiet_specified = 0;
-#else
+static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;
+static void lock_mutex(pthread_mutex_t *l)
+{
+       int ret;
+
+       if ((ret = pthread_mutex_lock(l)) != 0) {
+               fprintf(stderr, "pthread_mutex_lock returned:%d %s\n", ret, strerror(ret));
+               exit(1);
+       }
+}
+
+static void unlock_mutex(pthread_mutex_t *l)
+{
+       int ret;
+
+       if ((ret = pthread_mutex_unlock(l)) != 0) {
+               fprintf(stderr, "pthread_mutex_unlock returned:%d %s\n", ret, strerror(ret));
+               exit(1);
+       }
+}
+
+void log_lock(void)
+{
+       lock_mutex(&log_mutex);
+}
+
+void log_unlock(void)
+{
+       unlock_mutex(&log_mutex);
+}
+
 int lxc_log_fd = -1;
+int lxc_quiet_specified;
+int lxc_log_use_global_fd;
+static int lxc_loglevel_specified;
+
 static char log_prefix[LXC_LOG_PREFIX_SIZE] = "lxc";
 static char *log_fname = NULL;
-static int lxc_quiet_specified = 0;
-/* command line values for logfile or logpriority should always override
- * values from the configuration file or defaults
- */
-static int lxc_logfile_specified = 0;
-static int lxc_loglevel_specified = 0;
-#endif
 
 lxc_log_define(lxc_log, lxc);
 
@@ -85,8 +103,17 @@ static int log_append_logfile(const struct lxc_log_appender *appender,
        char buffer[LXC_LOG_BUFFER_SIZE];
        int n;
        int ms;
+       int fd_to_use = -1;
 
-       if (lxc_log_fd == -1)
+#ifndef NO_LXC_CONF
+       if (!lxc_log_use_global_fd && current_config)
+               fd_to_use = current_config->logfd;
+#endif
+
+       if (fd_to_use == -1)
+               fd_to_use = lxc_log_fd;
+
+       if (fd_to_use == -1)
                return 0;
 
        ms = event->timestamp.tv_usec / 1000;
@@ -111,7 +138,7 @@ static int log_append_logfile(const struct lxc_log_appender *appender,
 
        buffer[n] = '\n';
 
-       return write(lxc_log_fd, buffer, n + 1);
+       return write(fd_to_use, buffer, n + 1);
 }
 
 static struct lxc_log_appender log_appender_stderr = {
@@ -136,7 +163,7 @@ static struct lxc_log_category log_root = {
 struct lxc_log_category lxc_log_category_lxc = {
        .name           = "lxc",
        .priority       = LXC_LOG_PRIORITY_ERROR,
-       .appender       = &log_appender_stderr,
+       .appender       = &log_appender_logfile,
        .parent         = &log_root
 };
 
@@ -305,6 +332,11 @@ static int _lxc_log_set_file(const char *name, const char *lxcpath, int create_d
        return ret;
 }
 
+/*
+ * lxc_log_init:
+ * Called from lxc front-end programs (like lxc-create, lxc-start) to
+ * initalize the log defaults.
+ */
 extern int lxc_log_init(const char *name, const char *file,
                        const char *priority, const char *prefix, int quiet,
                        const char *lxcpath)
@@ -320,10 +352,12 @@ extern int lxc_log_init(const char *name, const char *file,
        if (priority)
                lxc_priority = lxc_log_priority_to_int(priority);
 
-       lxc_log_category_lxc.priority = lxc_priority;
+       if (!lxc_loglevel_specified) {
+               lxc_log_category_lxc.priority = lxc_priority;
+               lxc_loglevel_specified = 1;
+       }
 
        if (!lxc_quiet_specified) {
-               lxc_log_category_lxc.appender = &log_appender_logfile;
                if (!quiet)
                        lxc_log_category_lxc.appender->next = &log_appender_stderr;
        }
@@ -335,6 +369,7 @@ extern int lxc_log_init(const char *name, const char *file,
                if (strcmp(file, "none") == 0)
                        return 0;
                ret = __lxc_log_set_file(file, 1);
+               lxc_log_use_global_fd = 1;
        } else {
                /* if no name was specified, there nothing to do */
                if (!name)
@@ -385,15 +420,13 @@ extern void lxc_log_close(void)
  * happens after processing command line arguments, which override the .conf
  * settings.  So only set the level if previously unset.
  */
-extern int lxc_log_set_level(int level)
+extern int lxc_log_set_level(int *dest, int level)
 {
-       if (lxc_loglevel_specified)
-               return 0;
        if (level < 0 || level >= LXC_LOG_PRIORITY_NOTSET) {
                ERROR("invalid log priority %d", level);
                return -1;
        }
-       lxc_log_category_lxc.priority = level;
+       *dest = level;
        return 0;
 }
 
@@ -415,11 +448,23 @@ extern bool lxc_log_has_valid_level(void)
  * happens after processing command line arguments, which override the .conf
  * settings.  So only set the file if previously unset.
  */
-extern int lxc_log_set_file(const char *fname)
+extern int lxc_log_set_file(int *fd, const char *fname)
 {
-       if (lxc_logfile_specified)
-               return 0;
-       return __lxc_log_set_file(fname, 0);
+       if (*fd != -1) {
+               close(*fd);
+               *fd = -1;
+       }
+
+       if (build_dir(fname)) {
+               ERROR("failed to create dir for log file \"%s\" : %s", fname,
+                               strerror(errno));
+               return -1;
+       }
+
+       *fd = log_open(fname);
+       if (*fd == -1)
+               return -errno;
+       return 0;
 }
 
 extern const char *lxc_log_get_file(void)
@@ -440,11 +485,6 @@ extern const char *lxc_log_get_prefix(void)
 
 extern void lxc_log_options_no_override()
 {
-       if (lxc_log_get_file())
-               lxc_logfile_specified = 1;
-
-       if (lxc_log_get_level() != LXC_LOG_PRIORITY_NOTSET)
-               lxc_loglevel_specified = 1;
-
        lxc_quiet_specified = 1;
+       lxc_loglevel_specified = 1;
 }
index b47f120..76bd4df 100644 (file)
@@ -33,6 +33,8 @@
 #include <strings.h>
 #include <stdbool.h>
 
+#include "conf.h"
+
 #ifndef O_CLOEXEC
 #define O_CLOEXEC 02000000
 #endif
@@ -104,6 +106,10 @@ struct lxc_log_category {
        const struct lxc_log_category   *parent;
 };
 
+#ifndef NO_LXC_CONF
+extern int lxc_log_use_global_fd;
+#endif
+
 /*
  * Returns true if the chained priority is equal to or higher than
  * given priority.
@@ -116,7 +122,14 @@ lxc_log_priority_is_enabled(const struct lxc_log_category* category,
               category->parent)
                category = category->parent;
 
-       return priority >= category->priority;
+       int cmp_prio = category->priority;
+#ifndef NO_LXC_CONF
+       if (!lxc_log_use_global_fd && current_config &&
+                       current_config->loglevel != LXC_LOG_PRIORITY_NOTSET)
+               cmp_prio = current_config->loglevel;
+#endif
+
+       return priority >= cmp_prio;
 }
 
 /*
@@ -294,18 +307,14 @@ ATTR_UNUSED static inline void LXC_##PRIORITY(struct lxc_log_locinfo* locinfo,    \
        ERROR("%s - " format, strerror(errno), ##__VA_ARGS__);          \
 } while (0)
 
-#ifdef HAVE_TLS
-extern __thread int lxc_log_fd;
-#else
 extern int lxc_log_fd;
-#endif
 
 extern int lxc_log_init(const char *name, const char *file,
                        const char *priority, const char *prefix, int quiet,
                        const char *lxcpath);
 
-extern int lxc_log_set_file(const char *fname);
-extern int lxc_log_set_level(int level);
+extern int lxc_log_set_file(int *fd, const char *fname);
+extern int lxc_log_set_level(int *dest, int level);
 extern void lxc_log_set_prefix(const char *prefix);
 extern const char *lxc_log_get_file(void);
 extern int lxc_log_get_level(void);
index b049f80..7bf336e 100644 (file)
@@ -240,17 +240,15 @@ LXC_NAME="%s"
     count = 0
     for entry in overlay_dirs:
         tmpdir = "%s/tmpfs" % dest_path
+        fd.write("mkdir -p %s\n" % (tmpdir))
+        if args.storage_type == "tmpfs":
+            fd.write("mount -n -t tmpfs -o mode=0755 none %s\n" % (tmpdir))
         deltdir = "%s/delta%s" % (tmpdir, count)
         workdir = "%s/work%s" % (tmpdir, count)
         fd.write("mkdir -p %s %s\n" % (deltdir, entry[1]))
         if have_new_overlay:
             fd.write("mkdir -p %s\n" % workdir)
 
-        if args.storage_type == "tmpfs":
-            fd.write("mount -n -t tmpfs -o mode=0755 none %s\n" % (tmpdir))
-            fd.write("mkdir %s\n" % deltdir)
-            fd.write("mkdir %s\n" % workdir)
-
         fd.write("getfacl -a %s | setfacl --set-file=- %s || true\n" %
                  (entry[0], deltdir))
         fd.write("getfacl -a %s | setfacl --set-file=- %s || true\n" %
index cfa08fc..2e76c2e 100644 (file)
@@ -20,6 +20,8 @@
 #include <stdio.h>
 #include <errno.h>
 #include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
 
 #include <lxc/lxccontainer.h>
 
@@ -27,6 +29,7 @@
 #include "config.h"
 #include "lxc.h"
 #include "arguments.h"
+#include "utils.h"
 
 static char *checkpoint_dir = NULL;
 static bool stop = false;
@@ -139,36 +142,53 @@ bool checkpoint(struct lxc_container *c)
        return true;
 }
 
-bool restore(struct lxc_container *c)
+bool restore_finalize(struct lxc_container *c)
 {
-       pid_t pid = 0;
-       bool ret = true;
+       bool ret = c->restore(c, checkpoint_dir, verbose);
+       if (!ret) {
+               fprintf(stderr, "Restoring %s failed.\n", my_args.name);
+       }
 
+       lxc_container_put(c);
+       return ret;
+}
+
+bool restore(struct lxc_container *c)
+{
        if (c->is_running(c)) {
                fprintf(stderr, "%s is running, not restoring.\n", my_args.name);
                lxc_container_put(c);
                return false;
        }
 
-       if (my_args.daemonize)
+       if (my_args.daemonize) {
+               pid_t pid;
+
                pid = fork();
+               if (pid < 0) {
+                       perror("fork");
+                       return false;
+               }
 
-       if (pid == 0) {
-               if (my_args.daemonize) {
+               if (pid == 0) {
                        close(0);
                        close(1);
-               }
 
-               ret = c->restore(c, checkpoint_dir, verbose);
-
-               if (!ret) {
-                       fprintf(stderr, "Restoring %s failed.\n", my_args.name);
+                       exit(!restore_finalize(c));
+               } else {
+                       return wait_for_pid(pid) == 0;
                }
-       }
+       } else {
+               int status;
 
-       lxc_container_put(c);
+               if (!restore_finalize(c))
+                       return false;
 
-       return ret;
+               if (waitpid(-1, &status, 0) < 0)
+                       return false;
+
+               return WIFEXITED(status) && WEXITSTATUS(status) == 0;
+       }
 }
 
 int main(int argc, char *argv[])
index e02ee93..522d652 100644 (file)
@@ -35,6 +35,7 @@
 #include <libgen.h>
 #include <stdint.h>
 #include <grp.h>
+#include <stdio.h>
 #include <sys/syscall.h>
 
 #include <lxc/lxccontainer.h>
 #include <../include/ifaddrs.h>
 #endif
 
+#if IS_BIONIC
+#include <../include/lxcmntent.h>
+#else
+#include <mntent.h>
+#endif
+
 #define MAX_BUFFER 4096
 
 #define NOT_SUPPORTED_ERROR "the requested function %s is not currently supported with unprivileged containers"
@@ -82,9 +89,17 @@ return -1;
 }
 #endif
 
-
 lxc_log_define(lxc_container, lxc);
 
+static bool do_lxcapi_destroy(struct lxc_container *c);
+static const char *lxcapi_get_config_path(struct lxc_container *c);
+#define do_lxcapi_get_config_path(c) lxcapi_get_config_path(c)
+static bool do_lxcapi_set_config_item(struct lxc_container *c, const char *key, const char *v);
+static bool container_destroy(struct lxc_container *c);
+static bool get_snappath_dir(struct lxc_container *c, char *snappath);
+static bool lxcapi_snapshot_destroy_all(struct lxc_container *c);
+static bool do_lxcapi_save_config(struct lxc_container *c, const char *alt_file);
+
 static bool config_file_exists(const char *lxcpath, const char *cname)
 {
        /* $lxcpath + '/' + $cname + '/config' + \0 */
@@ -301,7 +316,7 @@ int lxc_container_put(struct lxc_container *c)
        return 0;
 }
 
-static bool lxcapi_is_defined(struct lxc_container *c)
+static bool do_lxcapi_is_defined(struct lxc_container *c)
 {
        struct stat statbuf;
        bool ret = false;
@@ -324,7 +339,53 @@ out:
        return ret;
 }
 
-static const char *lxcapi_state(struct lxc_container *c)
+#define WRAP_API(rettype, fnname)                                      \
+static rettype fnname(struct lxc_container *c)                         \
+{                                                                      \
+       rettype ret;                                                    \
+       struct lxc_conf *old = current_config;                          \
+       current_config = c ? c->lxc_conf : NULL;                        \
+       ret = do_##fnname(c);                                           \
+       current_config = old;                                           \
+       return ret;                                                     \
+}
+
+#define WRAP_API_1(rettype, fnname, t1)                                        \
+static rettype fnname(struct lxc_container *c, t1 a1)                  \
+{                                                                      \
+       rettype ret;                                                    \
+       struct lxc_conf *old = current_config;                          \
+       current_config = c ? c->lxc_conf : NULL;                        \
+       ret = do_##fnname(c, a1);                                       \
+       current_config = old;                                           \
+       return ret;                                                     \
+}
+
+#define WRAP_API_2(rettype, fnname, t1, t2)                            \
+static rettype fnname(struct lxc_container *c, t1 a1, t2 a2)           \
+{                                                                      \
+       rettype ret;                                                    \
+       struct lxc_conf *old = current_config;                          \
+       current_config = c ? c->lxc_conf : NULL;                        \
+       ret = do_##fnname(c, a1, a2);                                   \
+       current_config = old;                                           \
+       return ret;                                                     \
+}
+
+#define WRAP_API_3(rettype, fnname, t1, t2, t3)                                \
+static rettype fnname(struct lxc_container *c, t1 a1, t2 a2, t3 a3)    \
+{                                                                      \
+       rettype ret;                                                    \
+       struct lxc_conf *old = current_config;                          \
+       current_config = c ? c->lxc_conf : NULL;                        \
+       ret = do_##fnname(c, a1, a2, a3);                               \
+       current_config = old;                                           \
+       return ret;                                                     \
+}
+
+WRAP_API(bool, lxcapi_is_defined)
+
+static const char *do_lxcapi_state(struct lxc_container *c)
 {
        lxc_state_t s;
 
@@ -334,6 +395,8 @@ static const char *lxcapi_state(struct lxc_container *c)
        return lxc_state2str(s);
 }
 
+WRAP_API(const char *, lxcapi_state)
+
 static bool is_stopped(struct lxc_container *c)
 {
        lxc_state_t s;
@@ -341,19 +404,21 @@ static bool is_stopped(struct lxc_container *c)
        return (s == STOPPED);
 }
 
-static bool lxcapi_is_running(struct lxc_container *c)
+static bool do_lxcapi_is_running(struct lxc_container *c)
 {
        const char *s;
 
        if (!c)
                return false;
-       s = lxcapi_state(c);
+       s = do_lxcapi_state(c);
        if (!s || strcmp(s, "STOPPED") == 0)
                return false;
        return true;
 }
 
-static bool lxcapi_freeze(struct lxc_container *c)
+WRAP_API(bool, lxcapi_is_running)
+
+static bool do_lxcapi_freeze(struct lxc_container *c)
 {
        int ret;
        if (!c)
@@ -365,7 +430,9 @@ static bool lxcapi_freeze(struct lxc_container *c)
        return true;
 }
 
-static bool lxcapi_unfreeze(struct lxc_container *c)
+WRAP_API(bool, lxcapi_freeze)
+
+static bool do_lxcapi_unfreeze(struct lxc_container *c)
 {
        int ret;
        if (!c)
@@ -377,7 +444,9 @@ static bool lxcapi_unfreeze(struct lxc_container *c)
        return true;
 }
 
-static int lxcapi_console_getfd(struct lxc_container *c, int *ttynum, int *masterfd)
+WRAP_API(bool, lxcapi_unfreeze)
+
+static int do_lxcapi_console_getfd(struct lxc_container *c, int *ttynum, int *masterfd)
 {
        int ttyfd;
        if (!c)
@@ -387,13 +456,20 @@ static int lxcapi_console_getfd(struct lxc_container *c, int *ttynum, int *maste
        return ttyfd;
 }
 
+WRAP_API_2(int, lxcapi_console_getfd, int *, int *)
+
 static int lxcapi_console(struct lxc_container *c, int ttynum, int stdinfd,
                          int stdoutfd, int stderrfd, int escape)
 {
-       return lxc_console(c, ttynum, stdinfd, stdoutfd, stderrfd, escape);
+       int ret;
+       struct lxc_conf *old = current_config;
+       current_config = c ? c->lxc_conf : NULL;
+       ret = lxc_console(c, ttynum, stdinfd, stdoutfd, stderrfd, escape);
+       current_config = old;
+       return ret;
 }
 
-static pid_t lxcapi_init_pid(struct lxc_container *c)
+static pid_t do_lxcapi_init_pid(struct lxc_container *c)
 {
        if (!c)
                return -1;
@@ -401,6 +477,8 @@ static pid_t lxcapi_init_pid(struct lxc_container *c)
        return lxc_cmd_get_init_pid(c->name, c->config_path);
 }
 
+WRAP_API(pid_t, lxcapi_init_pid)
+
 static bool load_config_locked(struct lxc_container *c, const char *fname)
 {
        if (!c->lxc_conf)
@@ -412,7 +490,7 @@ static bool load_config_locked(struct lxc_container *c, const char *fname)
        return true;
 }
 
-static bool lxcapi_load_config(struct lxc_container *c, const char *alt_file)
+static bool do_lxcapi_load_config(struct lxc_container *c, const char *alt_file)
 {
        bool ret = false, need_disklock = false;
        int lret;
@@ -449,7 +527,9 @@ static bool lxcapi_load_config(struct lxc_container *c, const char *alt_file)
        return ret;
 }
 
-static bool lxcapi_want_daemonize(struct lxc_container *c, bool state)
+WRAP_API_1(bool, lxcapi_load_config, const char *)
+
+static bool do_lxcapi_want_daemonize(struct lxc_container *c, bool state)
 {
        if (!c || !c->lxc_conf)
                return false;
@@ -462,7 +542,9 @@ static bool lxcapi_want_daemonize(struct lxc_container *c, bool state)
        return true;
 }
 
-static bool lxcapi_want_close_all_fds(struct lxc_container *c, bool state)
+WRAP_API_1(bool, lxcapi_want_daemonize, bool)
+
+static bool do_lxcapi_want_close_all_fds(struct lxc_container *c, bool state)
 {
        if (!c || !c->lxc_conf)
                return false;
@@ -475,7 +557,9 @@ static bool lxcapi_want_close_all_fds(struct lxc_container *c, bool state)
        return true;
 }
 
-static bool lxcapi_wait(struct lxc_container *c, const char *state, int timeout)
+WRAP_API_1(bool, lxcapi_want_close_all_fds, bool)
+
+static bool do_lxcapi_wait(struct lxc_container *c, const char *state, int timeout)
 {
        int ret;
 
@@ -486,8 +570,9 @@ static bool lxcapi_wait(struct lxc_container *c, const char *state, int timeout)
        return ret == 0;
 }
 
+WRAP_API_2(bool, lxcapi_wait, const char *, int)
 
-static bool wait_on_daemonized_start(struct lxc_container *c, int pid)
+static bool do_wait_on_daemonized_start(struct lxc_container *c, int pid)
 {
        /* we'll probably want to make this timeout configurable? */
        int timeout = 5, ret, status;
@@ -499,9 +584,11 @@ static bool wait_on_daemonized_start(struct lxc_container *c, int pid)
        ret = waitpid(pid, &status, 0);
        if (ret == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0)
                DEBUG("failed waiting for first dual-fork child");
-       return lxcapi_wait(c, "RUNNING", timeout);
+       return do_lxcapi_wait(c, "RUNNING", timeout);
 }
 
+WRAP_API_1(bool, wait_on_daemonized_start, int)
+
 static bool am_single_threaded(void)
 {
        struct dirent dirent, *direntp;
@@ -534,7 +621,7 @@ static bool am_single_threaded(void)
  * I can't decide if it'd be more convenient for callers if we accept '...',
  * or a null-terminated array (i.e. execl vs execv)
  */
-static bool lxcapi_start(struct lxc_container *c, int useinit, char * const argv[])
+static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const argv[])
 {
        int ret;
        struct lxc_conf *conf;
@@ -559,7 +646,7 @@ static bool lxcapi_start(struct lxc_container *c, int useinit, char * const argv
        }
        if (ret == 2) {
                ERROR("Error: %s creation was not completed", c->name);
-               c->destroy(c);
+               do_lxcapi_destroy(c);
                return false;
        } else if (ret == 1) {
                ERROR("Error: creation of %s is ongoing", c->name);
@@ -702,6 +789,16 @@ out:
                return (ret == 0 ? true : false);
 }
 
+static bool lxcapi_start(struct lxc_container *c, int useinit, char * const argv[])
+{
+       bool ret;
+       struct lxc_conf *old = current_config;
+       current_config = c ? c->lxc_conf : NULL;
+       ret = do_lxcapi_start(c, useinit, argv);
+       current_config = old;
+       return ret;
+}
+
 /*
  * note there MUST be an ending NULL
  */
@@ -715,6 +812,9 @@ static bool lxcapi_startl(struct lxc_container *c, int useinit, ...)
        if (!c)
                return false;
 
+       struct lxc_conf *old = current_config;
+       current_config = c->lxc_conf;
+
        va_start(ap, useinit);
        inargs = lxc_va_arg_list_to_argv(ap, 0, 1);
        va_end(ap);
@@ -725,7 +825,7 @@ static bool lxcapi_startl(struct lxc_container *c, int useinit, ...)
        }
 
        /* pass NULL if no arguments were supplied */
-       bret = lxcapi_start(c, useinit, *inargs ? inargs : NULL);
+       bret = do_lxcapi_start(c, useinit, *inargs ? inargs : NULL);
 
 out:
        if (inargs) {
@@ -735,10 +835,11 @@ out:
                free(inargs);
        }
 
+       current_config = old;
        return bret;
 }
 
-static bool lxcapi_stop(struct lxc_container *c)
+static bool do_lxcapi_stop(struct lxc_container *c)
 {
        int ret;
 
@@ -750,6 +851,8 @@ static bool lxcapi_stop(struct lxc_container *c)
        return ret == 0;
 }
 
+WRAP_API(bool, lxcapi_stop)
+
 static int do_create_container_dir(const char *path, struct lxc_conf *conf)
 {
        int ret = -1, lasterr;
@@ -797,9 +900,6 @@ static bool create_container_dir(struct lxc_container *c)
        return ret == 0;
 }
 
-static const char *lxcapi_get_config_path(struct lxc_container *c);
-static bool lxcapi_set_config_item(struct lxc_container *c, const char *key, const char *v);
-
 /*
  * do_bdev_create: thin wrapper around bdev_create().  Like bdev_create(),
  * it returns a mounted bdev on success, NULL on error.
@@ -819,7 +919,7 @@ static struct bdev *do_bdev_create(struct lxc_container *c, const char *type,
                dest = alloca(len);
                ret = snprintf(dest, len, "%s", rpath);
        } else {
-               const char *lxcpath = lxcapi_get_config_path(c);
+               const char *lxcpath = do_lxcapi_get_config_path(c);
                len = strlen(c->name) + strlen(lxcpath) + 9;
                dest = alloca(len);
                ret = snprintf(dest, len, "%s/%s/rootfs", lxcpath, c->name);
@@ -833,7 +933,7 @@ static struct bdev *do_bdev_create(struct lxc_container *c, const char *type,
                return NULL;
        }
 
-       lxcapi_set_config_item(c, "lxc.rootfs", bdev->src);
+       do_lxcapi_set_config_item(c, "lxc.rootfs", bdev->src);
 
        /* if we are not root, chown the rootfs dir to root in the
         * target uidmap */
@@ -1210,9 +1310,8 @@ static void lxcapi_clear_config(struct lxc_container *c)
        }
 }
 
-static bool lxcapi_destroy(struct lxc_container *c);
-static bool container_destroy(struct lxc_container *c);
-static bool get_snappath_dir(struct lxc_container *c, char *snappath);
+#define do_lxcapi_clear_config(c) lxcapi_clear_config(c)
+
 /*
  * lxcapi_create:
  * create a container with the given parameters.
@@ -1227,7 +1326,7 @@ static bool get_snappath_dir(struct lxc_container *c, char *snappath);
  * @argv: the arguments to pass to the template, terminated by NULL.  If no
  * arguments, you can just pass NULL.
  */
-static bool lxcapi_create(struct lxc_container *c, const char *t,
+static bool do_lxcapi_create(struct lxc_container *c, const char *t,
                const char *bdevtype, struct bdev_specs *specs, int flags,
                char *const argv[])
 {
@@ -1253,14 +1352,14 @@ static bool lxcapi_create(struct lxc_container *c, const char *t,
         * an existing container.  Return an error, but do NOT delete the
         * container.
         */
-       if (lxcapi_is_defined(c) && c->lxc_conf && c->lxc_conf->rootfs.path &&
+       if (do_lxcapi_is_defined(c) && c->lxc_conf && c->lxc_conf->rootfs.path &&
                        access(c->lxc_conf->rootfs.path, F_OK) == 0 && tpath) {
                ERROR("Container %s:%s already exists", c->config_path, c->name);
                goto free_tpath;
        }
 
        if (!c->lxc_conf) {
-               if (!c->load_config(c, lxc_global_config_value("lxc.default_config"))) {
+               if (!do_lxcapi_load_config(c, lxc_global_config_value("lxc.default_config"))) {
                        ERROR("Error loading default configuration file %s", lxc_global_config_value("lxc.default_config"));
                        goto free_tpath;
                }
@@ -1280,7 +1379,7 @@ static bool lxcapi_create(struct lxc_container *c, const char *t,
        if (c->lxc_conf->rootfs.path && access(c->lxc_conf->rootfs.path, F_OK) != 0)
                /* rootfs passed into configuration, but does not exist: error */
                goto out;
-       if (lxcapi_is_defined(c) && c->lxc_conf->rootfs.path && !tpath) {
+       if (do_lxcapi_is_defined(c) && c->lxc_conf->rootfs.path && !tpath) {
                /* Rootfs already existed, user just wanted to save the
                 * loaded configuration */
                ret = true;
@@ -1316,7 +1415,7 @@ static bool lxcapi_create(struct lxc_container *c, const char *t,
                }
 
                /* save config file again to store the new rootfs location */
-               if (!c->save_config(c, NULL)) {
+               if (!do_lxcapi_save_config(c, NULL)) {
                        ERROR("failed to save starting configuration for %s", c->name);
                        // parent task won't see bdev in config so we delete it
                        bdev->ops->umount(bdev);
@@ -1339,7 +1438,7 @@ static bool lxcapi_create(struct lxc_container *c, const char *t,
 
        // now clear out the lxc_conf we have, reload from the created
        // container
-       lxcapi_clear_config(c);
+       do_lxcapi_clear_config(c);
 
        if (t) {
                if (!prepend_lxc_header(c->configfile, tpath, argv)) {
@@ -1360,15 +1459,27 @@ free_tpath:
        return ret;
 }
 
-static bool lxcapi_reboot(struct lxc_container *c)
+static bool lxcapi_create(struct lxc_container *c, const char *t,
+               const char *bdevtype, struct bdev_specs *specs, int flags,
+               char *const argv[])
+{
+       bool ret;
+       struct lxc_conf *old = current_config;
+       current_config = c ? c->lxc_conf : NULL;
+       ret = do_lxcapi_create(c, t, bdevtype, specs, flags, argv);
+       current_config = old;
+       return ret;
+}
+
+static bool do_lxcapi_reboot(struct lxc_container *c)
 {
        pid_t pid;
 
        if (!c)
                return false;
-       if (!c->is_running(c))
+       if (!do_lxcapi_is_running(c))
                return false;
-       pid = c->init_pid(c);
+       pid = do_lxcapi_init_pid(c);
        if (pid <= 0)
                return false;
        if (kill(pid, SIGINT) < 0)
@@ -1377,7 +1488,9 @@ static bool lxcapi_reboot(struct lxc_container *c)
 
 }
 
-static bool lxcapi_shutdown(struct lxc_container *c, int timeout)
+WRAP_API(bool, lxcapi_reboot)
+
+static bool do_lxcapi_shutdown(struct lxc_container *c, int timeout)
 {
        bool retv;
        pid_t pid;
@@ -1386,18 +1499,20 @@ static bool lxcapi_shutdown(struct lxc_container *c, int timeout)
        if (!c)
                return false;
 
-       if (!c->is_running(c))
+       if (!do_lxcapi_is_running(c))
                return true;
-       pid = c->init_pid(c);
+       pid = do_lxcapi_init_pid(c);
        if (pid <= 0)
                return true;
        if (c->lxc_conf && c->lxc_conf->haltsignal)
                haltsignal = c->lxc_conf->haltsignal;
        kill(pid, haltsignal);
-       retv = c->wait(c, "STOPPED", timeout);
+       retv = do_lxcapi_wait(c, "STOPPED", timeout);
        return retv;
 }
 
+WRAP_API_1(bool, lxcapi_shutdown, int)
+
 static bool lxcapi_createl(struct lxc_container *c, const char *t,
                const char *bdevtype, struct bdev_specs *specs, int flags, ...)
 {
@@ -1408,6 +1523,9 @@ static bool lxcapi_createl(struct lxc_container *c, const char *t,
        if (!c)
                return false;
 
+       struct lxc_conf *old = current_config;
+       current_config = c ? c->lxc_conf : NULL;
+
        /*
         * since we're going to wait for create to finish, I don't think we
         * need to get a copy of the arguments.
@@ -1420,10 +1538,11 @@ static bool lxcapi_createl(struct lxc_container *c, const char *t,
                goto out;
        }
 
-       bret = c->create(c, t, bdevtype, specs, flags, args);
+       bret = do_lxcapi_create(c, t, bdevtype, specs, flags, args);
 
 out:
        free(args);
+       current_config = old;
        return bret;
 }
 
@@ -1441,7 +1560,7 @@ static void do_clear_unexp_config_line(struct lxc_conf *conf, const char *key)
                WARN("Error clearing configuration for %s", key);
 }
 
-static bool lxcapi_clear_config_item(struct lxc_container *c, const char *key)
+static bool do_lxcapi_clear_config_item(struct lxc_container *c, const char *key)
 {
        int ret;
 
@@ -1456,9 +1575,11 @@ static bool lxcapi_clear_config_item(struct lxc_container *c, const char *key)
        return ret == 0;
 }
 
+WRAP_API_1(bool, lxcapi_clear_config_item, const char *)
+
 static inline bool enter_net_ns(struct lxc_container *c)
 {
-       pid_t pid = c->init_pid(c);
+       pid_t pid = do_lxcapi_init_pid(c);
 
        if ((geteuid() != 0 || (c->lxc_conf && !lxc_list_empty(&c->lxc_conf->id_map))) && access("/proc/self/ns/user", F_OK) == 0) {
                if (!switch_to_ns(pid, "user"))
@@ -1538,7 +1659,7 @@ static bool remove_from_array(char ***names, char *cname, int size)
        return false;
 }
 
-static char** lxcapi_get_interfaces(struct lxc_container *c)
+static char ** do_lxcapi_get_interfaces(struct lxc_container *c)
 {
        pid_t pid;
        int i, count = 0, pipefd[2];
@@ -1625,7 +1746,9 @@ static char** lxcapi_get_interfaces(struct lxc_container *c)
        return interfaces;
 }
 
-static char** lxcapi_get_ips(struct lxc_container *c, const char* interface, const char* family, int scope)
+WRAP_API(char **, lxcapi_get_interfaces)
+
+static char** do_lxcapi_get_ips(struct lxc_container *c, const char* interface, const char* family, int scope)
 {
        pid_t pid;
        int i, count = 0, pipefd[2];
@@ -1742,7 +1865,9 @@ static char** lxcapi_get_ips(struct lxc_container *c, const char* interface, con
        return addresses;
 }
 
-static int lxcapi_get_config_item(struct lxc_container *c, const char *key, char *retv, int inlen)
+WRAP_API_3(char **, lxcapi_get_ips, const char *, const char *, int)
+
+static int do_lxcapi_get_config_item(struct lxc_container *c, const char *key, char *retv, int inlen)
 {
        int ret;
 
@@ -1755,7 +1880,9 @@ static int lxcapi_get_config_item(struct lxc_container *c, const char *key, char
        return ret;
 }
 
-static char* lxcapi_get_running_config_item(struct lxc_container *c, const char *key)
+WRAP_API_3(int, lxcapi_get_config_item, const char *, char *, int)
+
+static char* do_lxcapi_get_running_config_item(struct lxc_container *c, const char *key)
 {
        char *ret;
 
@@ -1763,12 +1890,14 @@ static char* lxcapi_get_running_config_item(struct lxc_container *c, const char
                return NULL;
        if (container_mem_lock(c))
                return NULL;
-       ret = lxc_cmd_get_config_item(c->name, key, c->get_config_path(c));
+       ret = lxc_cmd_get_config_item(c->name, key, do_lxcapi_get_config_path(c));
        container_mem_unlock(c);
        return ret;
 }
 
-static int lxcapi_get_keys(struct lxc_container *c, const char *key, char *retv, int inlen)
+WRAP_API_1(char *, lxcapi_get_running_config_item, const char *)
+
+static int do_lxcapi_get_keys(struct lxc_container *c, const char *key, char *retv, int inlen)
 {
        if (!key)
                return lxc_listconfigs(retv, inlen);
@@ -1788,7 +1917,9 @@ static int lxcapi_get_keys(struct lxc_container *c, const char *key, char *retv,
        return ret;
 }
 
-static bool lxcapi_save_config(struct lxc_container *c, const char *alt_file)
+WRAP_API_3(int, lxcapi_get_keys, const char *, char *, int)
+
+static bool do_lxcapi_save_config(struct lxc_container *c, const char *alt_file)
 {
        FILE *fout;
        bool ret = false, need_disklock = false;
@@ -1801,7 +1932,7 @@ static bool lxcapi_save_config(struct lxc_container *c, const char *alt_file)
 
        // If we haven't yet loaded a config, load the stock config
        if (!c->lxc_conf) {
-               if (!c->load_config(c, lxc_global_config_value("lxc.default_config"))) {
+               if (!do_lxcapi_load_config(c, lxc_global_config_value("lxc.default_config"))) {
                        ERROR("Error loading default configuration file %s while saving %s", lxc_global_config_value("lxc.default_config"), c->name);
                        return false;
                }
@@ -1841,6 +1972,8 @@ out:
        return ret;
 }
 
+WRAP_API_1(bool, lxcapi_save_config, const char *)
+
 static bool mod_rdep(struct lxc_container *c, bool inc)
 {
        char path[MAXPATHLEN];
@@ -2029,7 +2162,7 @@ static bool container_destroy(struct lxc_container *c)
        bool bret = false;
        int ret;
 
-       if (!c || !lxcapi_is_defined(c))
+       if (!c || !do_lxcapi_is_defined(c))
                return false;
 
        if (container_disk_lock(c))
@@ -2054,7 +2187,7 @@ static bool container_destroy(struct lxc_container *c)
 
        mod_all_rdeps(c, false);
 
-       const char *p1 = lxcapi_get_config_path(c);
+       const char *p1 = do_lxcapi_get_config_path(c);
        char *path = alloca(strlen(p1) + strlen(c->name) + 2);
        sprintf(path, "%s/%s", p1, c->name);
        if (am_unpriv())
@@ -2072,7 +2205,7 @@ out:
        return bret;
 }
 
-static bool lxcapi_destroy(struct lxc_container *c)
+static bool do_lxcapi_destroy(struct lxc_container *c)
 {
        if (!c || !lxcapi_is_defined(c))
                return false;
@@ -2089,9 +2222,9 @@ static bool lxcapi_destroy(struct lxc_container *c)
        return container_destroy(c);
 }
 
-static bool lxcapi_snapshot_destroy_all(struct lxc_container *c);
+WRAP_API(bool, lxcapi_destroy)
 
-static bool lxcapi_destroy_with_snapshots(struct lxc_container *c)
+static bool do_lxcapi_destroy_with_snapshots(struct lxc_container *c)
 {
        if (!c || !lxcapi_is_defined(c))
                return false;
@@ -2102,6 +2235,8 @@ static bool lxcapi_destroy_with_snapshots(struct lxc_container *c)
        return lxcapi_destroy(c);
 }
 
+WRAP_API(bool, lxcapi_destroy_with_snapshots)
+
 static bool set_config_item_locked(struct lxc_container *c, const char *key, const char *v)
 {
        struct lxc_config_t *config;
@@ -2118,7 +2253,7 @@ static bool set_config_item_locked(struct lxc_container *c, const char *key, con
        return do_append_unexp_config_line(c->lxc_conf, key, v);
 }
 
-static bool lxcapi_set_config_item(struct lxc_container *c, const char *key, const char *v)
+static bool do_lxcapi_set_config_item(struct lxc_container *c, const char *key, const char *v)
 {
        bool b = false;
 
@@ -2134,6 +2269,8 @@ static bool lxcapi_set_config_item(struct lxc_container *c, const char *key, con
        return b;
 }
 
+WRAP_API_2(bool, lxcapi_set_config_item, const char *, const char *)
+
 static char *lxcapi_config_file_name(struct lxc_container *c)
 {
        if (!c || !c->configfile)
@@ -2181,7 +2318,7 @@ static bool set_config_filename(struct lxc_container *c)
        return true;
 }
 
-static bool lxcapi_set_config_path(struct lxc_container *c, const char *path)
+static bool do_lxcapi_set_config_path(struct lxc_container *c, const char *path)
 {
        char *p;
        bool b = false;
@@ -2219,8 +2356,9 @@ err:
        return b;
 }
 
+WRAP_API_1(bool, lxcapi_set_config_path, const char *)
 
-static bool lxcapi_set_cgroup_item(struct lxc_container *c, const char *subsys, const char *value)
+static bool do_lxcapi_set_cgroup_item(struct lxc_container *c, const char *subsys, const char *value)
 {
        int ret;
 
@@ -2239,7 +2377,9 @@ static bool lxcapi_set_cgroup_item(struct lxc_container *c, const char *subsys,
        return ret == 0;
 }
 
-static int lxcapi_get_cgroup_item(struct lxc_container *c, const char *subsys, char *retv, int inlen)
+WRAP_API_2(bool, lxcapi_set_cgroup_item, const char *, const char *)
+
+static int do_lxcapi_get_cgroup_item(struct lxc_container *c, const char *subsys, char *retv, int inlen)
 {
        int ret;
 
@@ -2258,6 +2398,8 @@ static int lxcapi_get_cgroup_item(struct lxc_container *c, const char *subsys, c
        return ret;
 }
 
+WRAP_API_3(int, lxcapi_get_cgroup_item, const char *, char *, int)
+
 const char *lxc_get_global_config_item(const char *key)
 {
        return lxc_global_config_value(key);
@@ -2374,7 +2516,7 @@ static int copyhooks(struct lxc_container *oldc, struct lxc_container *c)
                ERROR("Error saving new hooks in clone");
                return -1;
        }
-       c->save_config(c, NULL);
+       do_lxcapi_save_config(c, NULL);
        return 0;
 }
 
@@ -2646,7 +2788,7 @@ static int create_file_dirname(char *path, struct lxc_conf *conf)
        return ret;
 }
 
-static struct lxc_container *lxcapi_clone(struct lxc_container *c, const char *newname,
+static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char *newname,
                const char *lxcpath, int flags,
                const char *bdevtype, const char *bdevdata, uint64_t newsize,
                char **hookargs)
@@ -2659,7 +2801,7 @@ static struct lxc_container *lxcapi_clone(struct lxc_container *c, const char *n
        FILE *fout;
        pid_t pid;
 
-       if (!c || !c->is_defined(c))
+       if (!c || !do_lxcapi_is_defined(c))
                return NULL;
 
        if (container_mem_lock(c))
@@ -2674,7 +2816,7 @@ static struct lxc_container *lxcapi_clone(struct lxc_container *c, const char *n
        if (!newname)
                newname = c->name;
        if (!lxcpath)
-               lxcpath = c->get_config_path(c);
+               lxcpath = do_lxcapi_get_config_path(c);
        ret = snprintf(newpath, MAXPATHLEN, "%s/%s/config", lxcpath, newname);
        if (ret < 0 || ret >= MAXPATHLEN) {
                SYSERROR("clone: failed making config pathname");
@@ -2803,7 +2945,20 @@ out:
        return NULL;
 }
 
-static bool lxcapi_rename(struct lxc_container *c, const char *newname)
+static struct lxc_container *lxcapi_clone(struct lxc_container *c, const char *newname,
+               const char *lxcpath, int flags,
+               const char *bdevtype, const char *bdevdata, uint64_t newsize,
+               char **hookargs)
+{
+       struct lxc_container * ret;
+       struct lxc_conf *old = current_config;
+       current_config = c ? c->lxc_conf : NULL;
+       ret = do_lxcapi_clone(c, newname, lxcpath, flags, bdevtype, bdevdata, newsize, hookargs);
+       current_config = old;
+       return ret;
+}
+
+static bool do_lxcapi_rename(struct lxc_container *c, const char *newname)
 {
        struct bdev *bdev;
        struct lxc_container *newc;
@@ -2838,15 +2993,24 @@ static bool lxcapi_rename(struct lxc_container *c, const char *newname)
        return true;
 }
 
+WRAP_API_1(bool, lxcapi_rename, const char *)
+
 static int lxcapi_attach(struct lxc_container *c, lxc_attach_exec_t exec_function, void *exec_payload, lxc_attach_options_t *options, pid_t *attached_process)
 {
+       struct lxc_conf *old = current_config;
+       int ret;
+
        if (!c)
                return -1;
 
-       return lxc_attach(c->name, c->config_path, exec_function, exec_payload, options, attached_process);
+       current_config = c->lxc_conf;
+
+       ret = lxc_attach(c->name, c->config_path, exec_function, exec_payload, options, attached_process);
+       current_config = old;
+       return ret;
 }
 
-static int lxcapi_attach_run_wait(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char * const argv[])
+static int do_lxcapi_attach_run_wait(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char * const argv[])
 {
        lxc_attach_command_t command;
        pid_t pid;
@@ -2865,6 +3029,16 @@ static int lxcapi_attach_run_wait(struct lxc_container *c, lxc_attach_options_t
        return lxc_wait_for_pid_status(pid);
 }
 
+static int lxcapi_attach_run_wait(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char * const argv[])
+{
+       int ret;
+       struct lxc_conf *old = current_config;
+       current_config = c ? c->lxc_conf : NULL;
+       ret = do_lxcapi_attach_run_wait(c, options, program, argv);
+       current_config = old;
+       return ret;
+}
+
 static int get_next_index(const char *lxcpath, char *cname)
 {
        char *fname;
@@ -2908,7 +3082,7 @@ static bool get_snappath_dir(struct lxc_container *c, char *snappath)
        return true;
 }
 
-static int lxcapi_snapshot(struct lxc_container *c, const char *commentfile)
+static int do_lxcapi_snapshot(struct lxc_container *c, const char *commentfile)
 {
        int i, flags, ret;
        struct lxc_container *c2;
@@ -2950,7 +3124,7 @@ static int lxcapi_snapshot(struct lxc_container *c, const char *commentfile)
                ERROR("and keep the original container pristine.");
                flags &= ~LXC_CLONE_SNAPSHOT | LXC_CLONE_MAYBE_SNAPSHOT;
        }
-       c2 = c->clone(c, newname, snappath, flags, NULL, NULL, 0, NULL);
+       c2 = do_lxcapi_clone(c, newname, snappath, flags, NULL, NULL, 0, NULL);
        if (!c2) {
                ERROR("clone of %s:%s failed", c->config_path, c->name);
                return -1;
@@ -2998,6 +3172,8 @@ static int lxcapi_snapshot(struct lxc_container *c, const char *commentfile)
        return i;
 }
 
+WRAP_API_1(int, lxcapi_snapshot, const char *)
+
 static void lxcsnap_free(struct lxc_snapshot *s)
 {
        free(s->name);
@@ -3052,7 +3228,7 @@ static char *get_timestamp(char* snappath, char *name)
        return s;
 }
 
-static int lxcapi_snapshot_list(struct lxc_container *c, struct lxc_snapshot **ret_snaps)
+static int do_lxcapi_snapshot_list(struct lxc_container *c, struct lxc_snapshot **ret_snaps)
 {
        char snappath[MAXPATHLEN], path2[MAXPATHLEN];
        int count = 0, ret;
@@ -3128,7 +3304,9 @@ out_free:
        return -1;
 }
 
-static bool lxcapi_snapshot_restore(struct lxc_container *c, const char *snapname, const char *newname)
+WRAP_API_1(int, lxcapi_snapshot_list, struct lxc_snapshot **)
+
+static bool do_lxcapi_snapshot_restore(struct lxc_container *c, const char *snapname, const char *newname)
 {
        char clonelxcpath[MAXPATHLEN];
        int flags = 0;
@@ -3189,6 +3367,8 @@ static bool lxcapi_snapshot_restore(struct lxc_container *c, const char *snapnam
        return b;
 }
 
+WRAP_API_2(bool, lxcapi_snapshot_restore, const char *, const char *)
+
 static bool do_snapshot_destroy(const char *snapname, const char *clonelxcpath)
 {
        struct lxc_container *snap = NULL;
@@ -3200,7 +3380,7 @@ static bool do_snapshot_destroy(const char *snapname, const char *clonelxcpath)
                goto err;
        }
 
-       if (!lxcapi_destroy(snap)) {
+       if (!do_lxcapi_destroy(snap)) {
                ERROR("Could not destroy snapshot %s", snapname);
                goto err;
        }
@@ -3244,7 +3424,7 @@ static bool remove_all_snapshots(const char *path)
        return bret;
 }
 
-static bool lxcapi_snapshot_destroy(struct lxc_container *c, const char *snapname)
+static bool do_lxcapi_snapshot_destroy(struct lxc_container *c, const char *snapname)
 {
        char clonelxcpath[MAXPATHLEN];
 
@@ -3257,7 +3437,9 @@ static bool lxcapi_snapshot_destroy(struct lxc_container *c, const char *snapnam
        return do_snapshot_destroy(snapname, clonelxcpath);
 }
 
-static bool lxcapi_snapshot_destroy_all(struct lxc_container *c)
+WRAP_API_1(bool, lxcapi_snapshot_destroy, const char *)
+
+static bool do_lxcapi_snapshot_destroy_all(struct lxc_container *c)
 {
        char clonelxcpath[MAXPATHLEN];
 
@@ -3270,11 +3452,15 @@ static bool lxcapi_snapshot_destroy_all(struct lxc_container *c)
        return remove_all_snapshots(clonelxcpath);
 }
 
-static bool lxcapi_may_control(struct lxc_container *c)
+WRAP_API(bool, lxcapi_snapshot_destroy_all)
+
+static bool do_lxcapi_may_control(struct lxc_container *c)
 {
        return lxc_try_cmd(c->name, c->config_path) == 0;
 }
 
+WRAP_API(bool, lxcapi_may_control)
+
 static bool do_add_remove_node(pid_t init_pid, const char *path, bool add,
                struct stat *st)
 {
@@ -3338,7 +3524,7 @@ static bool add_remove_device_node(struct lxc_container *c, const char *src_path
        const char *p;
 
        /* make sure container is running */
-       if (!c->is_running(c)) {
+       if (!do_lxcapi_is_running(c)) {
                ERROR("container is not running");
                return false;
        }
@@ -3362,17 +3548,17 @@ static bool add_remove_device_node(struct lxc_container *c, const char *src_path
        if (ret < 0 || ret >= MAX_BUFFER)
                return false;
 
-       if (!do_add_remove_node(c->init_pid(c), p, add, &st))
+       if (!do_add_remove_node(do_lxcapi_init_pid(c), p, add, &st))
                return false;
 
        /* add or remove device to/from cgroup access list */
        if (add) {
-               if (!c->set_cgroup_item(c, "devices.allow", value)) {
+               if (!do_lxcapi_set_cgroup_item(c, "devices.allow", value)) {
                        ERROR("set_cgroup_item failed while adding the device node");
                        return false;
                }
        } else {
-               if (!c->set_cgroup_item(c, "devices.deny", value)) {
+               if (!do_lxcapi_set_cgroup_item(c, "devices.deny", value)) {
                        ERROR("set_cgroup_item failed while removing the device node");
                        return false;
                }
@@ -3381,7 +3567,7 @@ static bool add_remove_device_node(struct lxc_container *c, const char *src_path
        return true;
 }
 
-static bool lxcapi_add_device_node(struct lxc_container *c, const char *src_path, const char *dest_path)
+static bool do_lxcapi_add_device_node(struct lxc_container *c, const char *src_path, const char *dest_path)
 {
        if (am_unpriv()) {
                ERROR(NOT_SUPPORTED_ERROR, __FUNCTION__);
@@ -3390,7 +3576,9 @@ static bool lxcapi_add_device_node(struct lxc_container *c, const char *src_path
        return add_remove_device_node(c, src_path, dest_path, true);
 }
 
-static bool lxcapi_remove_device_node(struct lxc_container *c, const char *src_path, const char *dest_path)
+WRAP_API_2(bool, lxcapi_add_device_node, const char *, const char *)
+
+static bool do_lxcapi_remove_device_node(struct lxc_container *c, const char *src_path, const char *dest_path)
 {
        if (am_unpriv()) {
                ERROR(NOT_SUPPORTED_ERROR, __FUNCTION__);
@@ -3399,7 +3587,9 @@ static bool lxcapi_remove_device_node(struct lxc_container *c, const char *src_p
        return add_remove_device_node(c, src_path, dest_path, false);
 }
 
-static bool lxcapi_attach_interface(struct lxc_container *c, const char *ifname,
+WRAP_API_2(bool, lxcapi_remove_device_node, const char *, const char *)
+
+static bool do_lxcapi_attach_interface(struct lxc_container *c, const char *ifname,
                                const char *dst_ifname)
 {
        int ret = 0;
@@ -3422,7 +3612,7 @@ static bool lxcapi_attach_interface(struct lxc_container *c, const char *ifname,
                        goto err;
        }
 
-       ret = lxc_netdev_move_by_name(ifname, c->init_pid(c), dst_ifname);
+       ret = lxc_netdev_move_by_name(ifname, do_lxcapi_init_pid(c), dst_ifname);
        if (ret)
                goto err;
 
@@ -3432,7 +3622,9 @@ err:
        return false;
 }
 
-static bool lxcapi_detach_interface(struct lxc_container *c, const char *ifname,
+WRAP_API_2(bool, lxcapi_attach_interface, const char *, const char *)
+
+static bool do_lxcapi_detach_interface(struct lxc_container *c, const char *ifname,
                                        const char *dst_ifname)
 {
        pid_t pid, pid_outside;
@@ -3487,6 +3679,8 @@ static bool lxcapi_detach_interface(struct lxc_container *c, const char *ifname,
        return true;
 }
 
+WRAP_API_2(bool, lxcapi_detach_interface, const char *, const char *)
+
 struct criu_opts {
        /* The type of criu invocation, one of "dump" or "restore" */
        char *action;
@@ -3510,11 +3704,15 @@ struct criu_opts {
 
 static void exec_criu(struct criu_opts *opts)
 {
-       char **argv, log[PATH_MAX], buf[257];
+       char **argv, log[PATH_MAX];
        int static_args = 14, argc = 0, i, ret;
        int netnr = 0;
        struct lxc_list *it;
 
+       struct mntent mntent;
+       char buf[4096];
+       FILE *mnts = NULL;
+
        /* The command line always looks like:
         * criu $(action) --tcp-established --file-locks --link-remap --force-irmap \
         * --manage-cgroups action-script foo.sh -D $(directory) \
@@ -3545,6 +3743,11 @@ static void exec_criu(struct criu_opts *opts)
                return;
        }
 
+       // We need to tell criu where cgmanager's socket is bind mounted from
+       // if it exists since it's external.
+       if (cgroup_driver() == CGMANAGER)
+               static_args+=2;
+
        argv = malloc(static_args * sizeof(*argv));
        if (!argv)
                return;
@@ -3584,9 +3787,35 @@ static void exec_criu(struct criu_opts *opts)
        if (opts->verbose)
                DECLARE_ARG("-vvvvvv");
 
+       /*
+        * Note: this macro is not intended to be called unless argc is equal
+        * to the length of the array; there is nothing that keeps track of the
+        * length of the array besides the location in the code that this is
+        * called. (Yes this is bad, and we should fix it.)
+        */
+#define RESIZE_ARGS(additional)                                                \
+       do {                                                                    \
+               void *m;                                                        \
+               if (additional < 0) {                                           \
+                       ERROR("resizing by negative amount");                   \
+                       goto err;                                               \
+               } else if (additional == 0)                                     \
+                       continue;                                               \
+                                                                               \
+               m = realloc(argv, (argc + additional + 1) * sizeof(*argv));     \
+               if (!m)                                                         \
+                       goto err;                                               \
+               argv = m;                                                       \
+       } while (0)
+
        if (strcmp(opts->action, "dump") == 0) {
                char pid[32];
 
+               if (cgroup_driver() == CGMANAGER) {
+                       DECLARE_ARG("--ext-mount-map");
+                       DECLARE_ARG("/sys/fs/cgroup/cgmanager:cgmanager");
+               }
+
                if (sprintf(pid, "%d", lxcapi_init_pid(opts->c)) < 0)
                        goto err;
 
@@ -3595,6 +3824,12 @@ static void exec_criu(struct criu_opts *opts)
                if (!opts->stop)
                        DECLARE_ARG("--leave-running");
        } else if (strcmp(opts->action, "restore") == 0) {
+
+               if (cgroup_driver() == CGMANAGER) {
+                       DECLARE_ARG("--ext-mount-map");
+                       DECLARE_ARG("cgmanager:/sys/fs/cgroup/cgmanager");
+               }
+
                DECLARE_ARG("--root");
                DECLARE_ARG(opts->c->lxc_conf->rootfs.mount);
                DECLARE_ARG("--restore-detached");
@@ -3604,9 +3839,10 @@ static void exec_criu(struct criu_opts *opts)
                DECLARE_ARG("--cgroup-root");
                DECLARE_ARG(opts->cgroup_path);
 
+               RESIZE_ARGS(lxc_list_len(&opts->c->lxc_conf->network) * 2);
+
                lxc_list_for_each(it, &opts->c->lxc_conf->network) {
                        char eth[128], *veth;
-                       void *m;
                        struct lxc_netdev *n = it->elem;
 
                        if (n->name) {
@@ -3622,18 +3858,42 @@ static void exec_criu(struct criu_opts *opts)
                        if (ret < 0 || ret >= sizeof(buf))
                                goto err;
 
-                       /* final NULL and --veth-pair eth0=vethASDF */
-                       m = realloc(argv, (argc + 1 + 2) * sizeof(*argv));
-                       if (!m)
-                               goto err;
-                       argv = m;
-
                        DECLARE_ARG("--veth-pair");
                        DECLARE_ARG(buf);
-                       argv[argc] = NULL;
+               }
+       }
+
+       // CRIU wants to know about any external bind mounts the
+       // container has.
+       mnts = write_mount_file(&opts->c->lxc_conf->mount_list);
+       if (!mnts)
+               goto err;
+
+       RESIZE_ARGS(lxc_list_len(&opts->c->lxc_conf->mount_list) * 2);
+
+       while (getmntent_r(mnts, &mntent, buf, sizeof(buf))) {
+               char arg[2048], *key, *val;
+               int ret;
 
+               if (strcmp(opts->action, "dump") == 0) {
+                       key = mntent.mnt_fsname;
+                       val = mntent.mnt_dir;
+               } else {
+                       key = mntent.mnt_dir;
+                       val = mntent.mnt_fsname;
+               }
+
+               ret = snprintf(arg, sizeof(arg), "%s:%s", key, val);
+               if (ret < 0 || ret >= sizeof(arg)) {
+                       goto err;
                }
+
+               DECLARE_ARG("--ext-mount-map");
+               DECLARE_ARG(arg);
        }
+       fclose(mnts);
+
+       argv[argc] = NULL;
 
        netnr = 0;
        lxc_list_for_each(it, &opts->c->lxc_conf->network) {
@@ -3669,8 +3929,11 @@ static void exec_criu(struct criu_opts *opts)
        }
 
 #undef DECLARE_ARG
+#undef RESIZE_ARGS
        execv(argv[0], argv);
 err:
+       if (mnts)
+               fclose(mnts);
        for (i = 0; argv[i]; i++)
                free(argv[i]);
        free(argv);
@@ -3778,7 +4041,7 @@ out:
        return true;
 }
 
-static bool lxcapi_checkpoint(struct lxc_container *c, char *directory, bool stop, bool verbose)
+static bool do_lxcapi_checkpoint(struct lxc_container *c, char *directory, bool stop, bool verbose)
 {
        pid_t pid;
        int status;
@@ -3811,7 +4074,7 @@ static bool lxcapi_checkpoint(struct lxc_container *c, char *directory, bool sto
        } else {
                pid_t w = waitpid(pid, &status, 0);
                if (w == -1) {
-                       perror("waitpid");
+                       SYSERROR("waitpid");
                        return false;
                }
 
@@ -3823,6 +4086,8 @@ static bool lxcapi_checkpoint(struct lxc_container *c, char *directory, bool sto
        }
 }
 
+WRAP_API_3(bool, lxcapi_checkpoint, char *, bool, bool)
+
 static bool restore_net_info(struct lxc_container *c)
 {
        struct lxc_list *it;
@@ -3850,28 +4115,21 @@ out_unlock:
        return !has_error;
 }
 
-static bool lxcapi_restore(struct lxc_container *c, char *directory, bool verbose)
+// do_restore never returns, the calling process is used as the
+// monitor process. do_restore calls exit() if it fails.
+static void do_restore(struct lxc_container *c, int pipe, char *directory, bool verbose)
 {
        pid_t pid;
-       struct lxc_rootfs *rootfs;
        char pidfile[L_tmpnam];
        struct lxc_handler *handler;
-       bool has_error = true;
-
-       if (!criu_ok(c))
-               return false;
-
-       if (geteuid()) {
-               ERROR("Must be root to restore\n");
-               return false;
-       }
+       int status;
 
        if (!tmpnam(pidfile))
-               return false;
+               goto out;
 
        handler = lxc_init(c->name, c->lxc_conf, c->config_path);
        if (!handler)
-               return false;
+               goto out;
 
        if (!cgroup_init(handler)) {
                ERROR("failed initing cgroups");
@@ -3888,15 +4146,21 @@ static bool lxcapi_restore(struct lxc_container *c, char *directory, bool verbos
                goto out_fini_handler;
        }
 
+       resolve_clone_flags(handler);
+
        pid = fork();
        if (pid < 0)
                goto out_fini_handler;
 
        if (pid == 0) {
                struct criu_opts os;
+               struct lxc_rootfs *rootfs;
+
+               close(pipe);
+               pipe = -1;
 
                if (unshare(CLONE_NEWNS))
-                       exit(1);
+                       goto out_fini_handler;
 
                /* CRIU needs the lxc root bind mounted so that it is the root of some
                 * mount. */
@@ -3904,15 +4168,14 @@ static bool lxcapi_restore(struct lxc_container *c, char *directory, bool verbos
 
                if (rootfs_is_blockdev(c->lxc_conf)) {
                        if (do_rootfs_setup(c->lxc_conf, c->name, c->config_path) < 0)
-                               exit(1);
-               }
-               else {
+                               goto out_fini_handler;
+               } else {
                        if (mkdir(rootfs->mount, 0755) < 0 && errno != EEXIST)
-                               exit(1);
+                               goto out_fini_handler;
 
                        if (mount(rootfs->path, rootfs->mount, NULL, MS_BIND, NULL) < 0) {
                                rmdir(rootfs->mount);
-                               exit(1);
+                               goto out_fini_handler;
                        }
                }
 
@@ -3927,27 +4190,34 @@ static bool lxcapi_restore(struct lxc_container *c, char *directory, bool verbos
                exec_criu(&os);
                umount(rootfs->mount);
                rmdir(rootfs->mount);
-               exit(1);
+               goto out_fini_handler;
        } else {
-               int status;
+               int ret;
+               char title[2048];
 
                pid_t w = waitpid(pid, &status, 0);
-
                if (w == -1) {
-                       perror("waitpid");
+                       SYSERROR("waitpid");
+                       goto out_fini_handler;
+               }
+
+               ret = write(pipe, &status, sizeof(status));
+               close(pipe);
+               pipe = -1;
+
+               if (sizeof(status) != ret) {
+                       SYSERROR("failed to write all of status");
                        goto out_fini_handler;
                }
 
                if (WIFEXITED(status)) {
                        if (WEXITSTATUS(status)) {
                                goto out_fini_handler;
-                       }
-                       else {
+                       } else {
                                int ret;
                                FILE *f = fopen(pidfile, "r");
                                if (!f) {
-                                       perror("reading pidfile");
-                                       ERROR("couldn't read restore's init pidfile %s\n", pidfile);
+                                       SYSERROR("couldn't read restore's init pidfile %s\n", pidfile);
                                        goto out_fini_handler;
                                }
 
@@ -3966,19 +4236,92 @@ static bool lxcapi_restore(struct lxc_container *c, char *directory, bool verbos
                        goto out_fini_handler;
                }
 
-               if (lxc_poll(c->name, handler)) {
+               /*
+                * See comment in lxcapi_start; we don't care if these
+                * fail because it's just a beauty thing. We just
+                * assign the return here to silence potential.
+                */
+               ret = snprintf(title, sizeof(title), "[lxc monitor] %s %s", c->config_path, c->name);
+               ret = setproctitle(title);
+
+               ret = lxc_poll(c->name, handler);
+               if (ret)
                        lxc_abort(c->name, handler);
-                       goto out_fini_handler;
-               }
+               lxc_fini(c->name, handler);
+               exit(ret);
        }
 
-       has_error = false;
-
 out_fini_handler:
        lxc_fini(c->name, handler);
-       return !has_error;
+
+out:
+       if (pipe >= 0) {
+               status = 1;
+               if (write(pipe, &status, sizeof(status)) != sizeof(status)) {
+                       SYSERROR("writing status failed");
+               }
+               close(pipe);
+       }
+
+       exit(1);
 }
 
+static bool do_lxcapi_restore(struct lxc_container *c, char *directory, bool verbose)
+{
+       pid_t pid;
+       int status, nread;
+       int pipefd[2];
+
+       if (!criu_ok(c))
+               return false;
+
+       if (geteuid()) {
+               ERROR("Must be root to restore\n");
+               return false;
+       }
+
+       if (pipe(pipefd)) {
+               ERROR("failed to create pipe");
+               return false;
+       }
+
+       pid = fork();
+       if (pid < 0) {
+               close(pipefd[0]);
+               close(pipefd[1]);
+               return false;
+       }
+
+       if (pid == 0) {
+               close(pipefd[0]);
+               // this never returns
+               do_restore(c, pipefd[1], directory, verbose);
+       }
+
+       close(pipefd[1]);
+
+       nread = read(pipefd[0], &status, sizeof(status));
+       close(pipefd[0]);
+       if (sizeof(status) != nread) {
+               ERROR("reading status from pipe failed");
+               goto err_wait;
+       }
+
+       // If the criu process was killed or exited nonzero, wait() for the
+       // handler, since the restore process died. Otherwise, we don't need to
+       // wait, since the child becomes the monitor process.
+       if (!WIFEXITED(status) || WEXITSTATUS(status))
+               goto err_wait;
+       return true;
+
+err_wait:
+       if (wait_for_pid(pid))
+               ERROR("restore process died");
+       return false;
+}
+
+WRAP_API_2(bool, lxcapi_restore, char *, bool)
+
 static int lxcapi_attach_run_waitl(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char *arg, ...)
 {
        va_list ap;
@@ -3988,18 +4331,24 @@ static int lxcapi_attach_run_waitl(struct lxc_container *c, lxc_attach_options_t
        if (!c)
                return -1;
 
+       struct lxc_conf *old = current_config;
+       current_config = c->lxc_conf;
+
        va_start(ap, arg);
        argv = lxc_va_arg_list_to_argv_const(ap, 1);
        va_end(ap);
 
        if (!argv) {
                ERROR("Memory allocation error.");
-               return -1;
+               ret = -1;
+               goto out;
        }
        argv[0] = arg;
 
-       ret = lxcapi_attach_run_wait(c, options, program, (const char * const *)argv);
+       ret = do_lxcapi_attach_run_wait(c, options, program, (const char * const *)argv);
        free((void*)argv);
+out:
+       current_config = old;
        return ret;
 }
 
@@ -4116,12 +4465,6 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
        c->checkpoint = lxcapi_checkpoint;
        c->restore = lxcapi_restore;
 
-       /* we'll allow the caller to update these later */
-       if (lxc_log_init(NULL, "none", NULL, "lxc_container", 0, c->config_path)) {
-               fprintf(stderr, "failed to open log\n");
-               goto err;
-       }
-
        return c;
 
 err:
@@ -4195,7 +4538,7 @@ int list_defined_containers(const char *lxcpath, char ***names, struct lxc_conta
                                        goto free_bad;
                        continue;
                }
-               if (!lxcapi_is_defined(c)) {
+               if (!do_lxcapi_is_defined(c)) {
                        INFO("Container %s:%s has a config but is not defined",
                                lxcpath, direntp->d_name);
                        if (names)
index 70e4693..d615375 100644 (file)
@@ -840,6 +840,35 @@ static int recv_ttys_from_child(struct lxc_handler *handler)
        return 0;
 }
 
+void resolve_clone_flags(struct lxc_handler *handler)
+{
+       handler->clone_flags = CLONE_NEWPID | CLONE_NEWNS;
+
+       if (!lxc_list_empty(&handler->conf->id_map)) {
+               INFO("Cloning a new user namespace");
+               handler->clone_flags |= CLONE_NEWUSER;
+       }
+
+       if (handler->conf->inherit_ns_fd[LXC_NS_NET] == -1) {
+               if (!lxc_requests_empty_network(handler))
+                       handler->clone_flags |= CLONE_NEWNET;
+       } else {
+               INFO("Inheriting a net namespace");
+       }
+
+       if (handler->conf->inherit_ns_fd[LXC_NS_IPC] == -1) {
+               handler->clone_flags |= CLONE_NEWIPC;
+       } else {
+               INFO("Inheriting an IPC namespace");
+       }
+
+       if (handler->conf->inherit_ns_fd[LXC_NS_UTS] == -1) {
+               handler->clone_flags |= CLONE_NEWUTS;
+       } else {
+               INFO("Inheriting a UTS namespace");
+       }
+}
+
 static int lxc_spawn(struct lxc_handler *handler)
 {
        int failed_before_rename = 0;
@@ -858,21 +887,14 @@ static int lxc_spawn(struct lxc_handler *handler)
        if (lxc_sync_init(handler))
                return -1;
 
-       handler->clone_flags = CLONE_NEWPID|CLONE_NEWNS;
-       if (!lxc_list_empty(&handler->conf->id_map)) {
-               INFO("Cloning a new user namespace");
-               handler->clone_flags |= CLONE_NEWUSER;
-       }
-
        if (socketpair(AF_UNIX, SOCK_DGRAM, 0, handler->ttysock) < 0) {
                lxc_sync_fini(handler);
                return -1;
        }
 
-       if (handler->conf->inherit_ns_fd[LXC_NS_NET] == -1) {
-               if (!lxc_requests_empty_network(handler))
-                       handler->clone_flags |= CLONE_NEWNET;
+       resolve_clone_flags(handler);
 
+       if (handler->clone_flags & CLONE_NEWNET) {
                if (!lxc_list_empty(&handler->conf->network)) {
 
                        /* Find gateway addresses from the link device, which is
@@ -899,23 +921,8 @@ static int lxc_spawn(struct lxc_handler *handler)
                        ERROR("failed to save physical nic info");
                        goto out_abort;
                }
-       } else {
-               INFO("Inheriting a net namespace");
        }
 
-       if (handler->conf->inherit_ns_fd[LXC_NS_IPC] == -1) {
-               handler->clone_flags |= CLONE_NEWIPC;
-       } else {
-               INFO("Inheriting an IPC namespace");
-       }
-
-       if (handler->conf->inherit_ns_fd[LXC_NS_UTS] == -1) {
-               handler->clone_flags |= CLONE_NEWUTS;
-       } else {
-               INFO("Inheriting a UTS namespace");
-       }
-
-
        if (!cgroup_init(handler)) {
                ERROR("failed initializing cgroup support");
                goto out_delete_net;
index 2c6fc0d..aab063a 100644 (file)
@@ -87,5 +87,6 @@ extern int lxc_check_inherited(struct lxc_conf *conf, bool closeall, int fd_to_i
 int __lxc_start(const char *, struct lxc_conf *, struct lxc_operations *,
                void *, const char *);
 
+extern void resolve_clone_flags(struct lxc_handler *handler);
 #endif
 
index e66a01f..1df6e8f 100644 (file)
@@ -29,6 +29,7 @@
 #include <stddef.h>
 #include <string.h>
 #include <sys/types.h>
+#include <sys/vfs.h>
 #include <sys/stat.h>
 #include <sys/mman.h>
 #include <sys/param.h>
@@ -68,8 +69,8 @@
 
 lxc_log_define(lxc_utils, lxc);
 
-static int _recursive_rmdir_onedev(char *dirname, dev_t pdev,
-                                  const char *exclude, int level)
+static int _recursive_rmdir(char *dirname, dev_t pdev,
+                           const char *exclude, int level, bool onedev)
 {
        struct dirent dirent, *direntp;
        DIR *dir;
@@ -106,7 +107,7 @@ static int _recursive_rmdir_onedev(char *dirname, dev_t pdev,
                        if (ret < 0) {
                                switch(errno) {
                                case ENOTEMPTY:
-                                       INFO("Not deleting snapshots");
+                                       INFO("Not deleting snapshot %s", pathname);
                                        hadexclude = true;
                                        break;
                                case ENOTDIR:
@@ -129,14 +130,14 @@ static int _recursive_rmdir_onedev(char *dirname, dev_t pdev,
                        failed=1;
                        continue;
                }
-               if (mystat.st_dev != pdev)
+               if (onedev && mystat.st_dev != pdev)
                        continue;
                if (S_ISDIR(mystat.st_mode)) {
-                       if (_recursive_rmdir_onedev(pathname, pdev, exclude, level+1) < 0)
+                       if (_recursive_rmdir(pathname, pdev, exclude, level+1, onedev) < 0)
                                failed=1;
                } else {
                        if (unlink(pathname) < 0) {
-                               ERROR("%s: failed to delete %s", __func__, pathname);
+                               SYSERROR("%s: failed to delete %s", __func__, pathname);
                                failed=1;
                        }
                }
@@ -158,17 +159,41 @@ static int _recursive_rmdir_onedev(char *dirname, dev_t pdev,
        return failed ? -1 : 0;
 }
 
+/* we have two different magic values for overlayfs, yay */
+#define OVERLAYFS_SUPER_MAGIC 0x794c764f
+#define OVERLAY_SUPER_MAGIC 0x794c7630
+/*
+ * In overlayfs, st_dev is unreliable.  so on overlayfs we don't do
+ * the lxc_rmdir_onedev()
+ */
+static bool is_native_overlayfs(const char *path)
+{
+       struct statfs sb;
+
+       if (statfs(path, &sb) < 0)
+               return false;
+       if (sb.f_type == OVERLAYFS_SUPER_MAGIC ||
+                       sb.f_type == OVERLAY_SUPER_MAGIC)
+               return true;
+       return false;
+}
+
 /* returns 0 on success, -1 if there were any failures */
 extern int lxc_rmdir_onedev(char *path, const char *exclude)
 {
        struct stat mystat;
+       bool onedev = true;
+
+       if (is_native_overlayfs(path)) {
+               onedev = false;
+       }
 
        if (lstat(path, &mystat) < 0) {
                ERROR("%s: failed to stat %s", __func__, path);
                return -1;
        }
 
-       return _recursive_rmdir_onedev(path, mystat.st_dev, exclude, 0);
+       return _recursive_rmdir(path, mystat.st_dev, exclude, 0, onedev);
 }
 
 static int mount_fs(const char *source, const char *target, const char *type)
@@ -322,7 +347,7 @@ const char *lxc_global_config_value(const char *option_name)
                sprintf(user_config_path, "%s/.config/lxc/lxc.conf", user_home);
                sprintf(user_default_config_path, "%s/.config/lxc/default.conf", user_home);
                sprintf(user_lxc_path, "%s/.local/share/lxc/", user_home);
-               user_cgroup_pattern = strdup("%n");
+               user_cgroup_pattern = strdup("lxc/%n");
        }
        else {
                user_config_path = strdup(LXC_GLOBAL_CONF);
index ff6b926..40c3b5e 100644 (file)
@@ -25,7 +25,7 @@
 
 #define LXC_VERSION_MAJOR 1
 #define LXC_VERSION_MINOR 1
-#define LXC_VERSION_MICRO 1
-#define LXC_VERSION "1.1.1"
+#define LXC_VERSION_MICRO 2
+#define LXC_VERSION "1.1.2"
 
 #endif
index b8689ac..1ab1997 100644 (file)
@@ -47,9 +47,11 @@ static int test_attach_write_file(void* payload)
        if (f) {
                printf("yes\n");
                fclose(f);
+               fflush(NULL);
                return 1;
        }
        printf("no\n");
+       fflush(NULL);
        return 0;
 }
 
index acabbed..f32411a 100644 (file)
@@ -182,6 +182,10 @@ int main(int argc, char *argv[]) {
                  (tok = strtok_r(mode_tok, ",", &saveptr));
                 i++, mode_tok = NULL) {
                 modes = realloc(modes, sizeof(*modes) * (i+2));
+                if (!modes) {
+                    perror("realloc");
+                    exit(EXIT_FAILURE);
+                }
                 modes[i] = tok;
            }
             modes[i] = NULL;
index 1588042..265b7d0 100644 (file)
@@ -350,7 +350,7 @@ EOF
     # prevent mingetty from calling vhangup(2) since it fails with userns.
     # Same issue as oracle template: prevent mingetty from calling vhangup(2)
     # commit 2e83f7201c5d402478b9849f0a85c62d5b9f1589.
-    sed -i 's|mingetty|mingetty --nohangup|' $container_rootfs/etc/init/tty.conf
+    sed -i 's|mingetty|mingetty --nohangup|' $rootfs_path/etc/init/tty.conf
 
     if [ ${root_display_password} = "yes" ]
     then
@@ -413,10 +413,10 @@ download_centos()
 
     # download a mini centos into a cache
     echo "Downloading centos minimal ..."
-    if [ $release -le 5 ];then
-        YUM="yum --installroot $INSTALL_ROOT -y --nogpgcheck"
-    else
+    if yum -h | grep -q 'releasever=RELEASEVER'; then
         YUM="yum --installroot $INSTALL_ROOT -y --nogpgcheck --releasever=$release"
+    else
+        YUM="yum --installroot $INSTALL_ROOT -y --nogpgcheck"
     fi
     PKG_LIST="yum initscripts passwd rsyslog vim-minimal openssh-server openssh-clients dhclient chkconfig rootfiles policycoreutils"