lxc-2.0.8/0000755061062106075000000000000013105117016007313 500000000000000lxc-2.0.8/INSTALL0000644061062106075000000002275013105116772010302 00000000000000Installation Instructions ************************* Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, 2006 Free Software Foundation, Inc. This file is free documentation; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. Basic Installation ================== Briefly, the shell commands `./autogen.sh; ./configure; make; make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 0. If the sources are not coming from a package maintainer and the 'configure' file does not exist, you should run './autogen.sh' in the directory containing the package's source code in order to generate the 'configure' file from the 'configure.ac' file. 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. Running `configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package. 4. Type `make install' to install the programs and any data files and documentation. 5. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Optional Features ================= Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf bug. Until the bug is fixed you can use this workaround: CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of the options to `configure', and exit. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. lxc-2.0.8/aclocal.m40000644061062106075000000017213213105116773011112 00000000000000# generated automatically by aclocal 1.15 -*- Autoconf -*- # Copyright (C) 1996-2014 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- dnl serial 11 (pkg-config-0.29.1) dnl dnl Copyright © 2004 Scott James Remnant . dnl Copyright © 2012-2015 Dan Nicholson dnl dnl This program is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by dnl the Free Software Foundation; either version 2 of the License, or dnl (at your option) any later version. dnl dnl This program is distributed in the hope that it will be useful, but dnl WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU dnl General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License dnl along with this program; if not, write to the Free Software dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA dnl 02111-1307, USA. dnl dnl As a special exception to the GNU General Public License, if you dnl distribute this file as part of a program that contains a dnl configuration script generated by Autoconf, you may include it under dnl the same distribution terms that you use for the rest of that dnl program. dnl PKG_PREREQ(MIN-VERSION) dnl ----------------------- dnl Since: 0.29 dnl dnl Verify that the version of the pkg-config macros are at least dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's dnl installed version of pkg-config, this checks the developer's version dnl of pkg.m4 when generating configure. dnl dnl To ensure that this macro is defined, also add: dnl m4_ifndef([PKG_PREREQ], dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) dnl dnl See the "Since" comment for each macro you use to see what version dnl of the macros you require. m4_defun([PKG_PREREQ], [m4_define([PKG_MACROS_VERSION], [0.29.1]) m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) ])dnl PKG_PREREQ dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) dnl ---------------------------------- dnl Since: 0.16 dnl dnl Search for the pkg-config tool and set the PKG_CONFIG variable to dnl first found in the path. Checks that the version of pkg-config found dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is dnl used since that's the first version where most current features of dnl pkg-config existed. AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])dnl PKG_PROG_PKG_CONFIG dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------------------------------- dnl Since: 0.18 dnl dnl Check to see whether a particular set of modules exists. Similar to dnl PKG_CHECK_MODULES(), but does not set variables or print errors. dnl dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) dnl only at the first occurence in configure.ac, so if the first place dnl it's called might be skipped (such as if it is within an "if", you dnl have to call PKG_CHECK_EXISTS manually AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_default([$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) dnl --------------------------------------------- dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting dnl pkg_failed based on the result. m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])dnl _PKG_CONFIG dnl _PKG_SHORT_ERRORS_SUPPORTED dnl --------------------------- dnl Internal check to see if pkg-config supports short errors. AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])dnl _PKG_SHORT_ERRORS_SUPPORTED dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl -------------------------------------------------------------- dnl Since: 0.4.0 dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES might not happen, you should be sure to include an dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])[]dnl ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) $3 fi[]dnl ])dnl PKG_CHECK_MODULES dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl --------------------------------------------------------------------- dnl Since: 0.29 dnl dnl Checks for existence of MODULES and gathers its build flags with dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags dnl and VARIABLE-PREFIX_LIBS from --libs. dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to dnl include an explicit call to PKG_PROG_PKG_CONFIG in your dnl configure.ac. AC_DEFUN([PKG_CHECK_MODULES_STATIC], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl _save_PKG_CONFIG=$PKG_CONFIG PKG_CONFIG="$PKG_CONFIG --static" PKG_CHECK_MODULES($@) PKG_CONFIG=$_save_PKG_CONFIG[]dnl ])dnl PKG_CHECK_MODULES_STATIC dnl PKG_INSTALLDIR([DIRECTORY]) dnl ------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable pkgconfigdir as the location where a module dnl should install pkg-config .pc files. By default the directory is dnl $libdir/pkgconfig, but the default can be changed by passing dnl DIRECTORY. The user can override through the --with-pkgconfigdir dnl parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([pkgconfigdir], [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, [with_pkgconfigdir=]pkg_default) AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_INSTALLDIR dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) dnl -------------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable noarch_pkgconfigdir as the location where a dnl module should install arch-independent pkg-config .pc files. By dnl default the directory is $datadir/pkgconfig, but the default can be dnl changed by passing DIRECTORY. The user can override through the dnl --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([noarch-pkgconfigdir], [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, [with_noarch_pkgconfigdir=]pkg_default) AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_NOARCH_INSTALLDIR dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------- dnl Since: 0.28 dnl dnl Retrieves the value of the pkg-config variable for the given module. AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl _PKG_CONFIG([$1], [variable="][$3]["], [$2]) AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl ])dnl PKG_CHECK_VAR # Copyright (C) 2002-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.15' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.15], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.15])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` ]) # AM_COND_IF -*- Autoconf -*- # Copyright (C) 2008-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_COND_IF # _AM_COND_ELSE # _AM_COND_ENDIF # -------------- # These macros are only used for tracing. m4_define([_AM_COND_IF]) m4_define([_AM_COND_ELSE]) m4_define([_AM_COND_ENDIF]) # AM_COND_IF(COND, [IF-TRUE], [IF-FALSE]) # --------------------------------------- # If the shell condition COND is true, execute IF-TRUE, otherwise execute # IF-FALSE. Allow automake to learn about conditional instantiating macros # (the AC_CONFIG_FOOS). AC_DEFUN([AM_COND_IF], [m4_ifndef([_AM_COND_VALUE_$1], [m4_fatal([$0: no such condition "$1"])])dnl _AM_COND_IF([$1])dnl if test -z "$$1_TRUE"; then : m4_n([$2])[]dnl m4_ifval([$3], [_AM_COND_ELSE([$1])dnl else $3 ])dnl _AM_COND_ENDIF([$1])dnl fi[]dnl ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each '.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC]) [_AM_PROG_CC_C_O ]) # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.65])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi fi dnl The trailing newline in this macro's definition is deliberate, for dnl backward compatibility and to allow trailing 'dnl'-style comments dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it is modern enough. # If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Copyright (C) 1999-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_CC_C_O # --------------- # Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC # to automatically call this. AC_DEFUN([_AM_PROG_CC_C_O], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl AC_LANG_PUSH([C])dnl AC_CACHE_CHECK( [whether $CC understands -c and -o together], [am_cv_prog_cc_c_o], [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i]) if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) # Copyright (C) 1999-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # --------------------------------------------------------------------------- # Adds support for distributing Python modules and packages. To # install modules, copy them to $(pythondir), using the python_PYTHON # automake variable. To install a package with the same name as the # automake package, install to $(pkgpythondir), or use the # pkgpython_PYTHON automake variable. # # The variables $(pyexecdir) and $(pkgpyexecdir) are provided as # locations to install python extension modules (shared libraries). # Another macro is required to find the appropriate flags to compile # extension modules. # # If your package is configured with a different prefix to python, # users will have to add the install directory to the PYTHONPATH # environment variable, or create a .pth file (see the python # documentation for details). # # If the MINIMUM-VERSION argument is passed, AM_PATH_PYTHON will # cause an error if the version of python installed on the system # doesn't meet the requirement. MINIMUM-VERSION should consist of # numbers and dots only. AC_DEFUN([AM_PATH_PYTHON], [ dnl Find a Python interpreter. Python versions prior to 2.0 are not dnl supported. (2.0 was released on October 16, 2000). m4_define_default([_AM_PYTHON_INTERPRETER_LIST], [python python2 python3 python3.3 python3.2 python3.1 python3.0 python2.7 dnl python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0]) AC_ARG_VAR([PYTHON], [the Python interpreter]) m4_if([$1],[],[ dnl No version check is needed. # Find any Python interpreter. if test -z "$PYTHON"; then AC_PATH_PROGS([PYTHON], _AM_PYTHON_INTERPRETER_LIST, :) fi am_display_PYTHON=python ], [ dnl A version check is needed. if test -n "$PYTHON"; then # If the user set $PYTHON, use it and don't search something else. AC_MSG_CHECKING([whether $PYTHON version is >= $1]) AM_PYTHON_CHECK_VERSION([$PYTHON], [$1], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AC_MSG_ERROR([Python interpreter is too old])]) am_display_PYTHON=$PYTHON else # Otherwise, try each interpreter until we find one that satisfies # VERSION. AC_CACHE_CHECK([for a Python interpreter with version >= $1], [am_cv_pathless_PYTHON],[ for am_cv_pathless_PYTHON in _AM_PYTHON_INTERPRETER_LIST none; do test "$am_cv_pathless_PYTHON" = none && break AM_PYTHON_CHECK_VERSION([$am_cv_pathless_PYTHON], [$1], [break]) done]) # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON. if test "$am_cv_pathless_PYTHON" = none; then PYTHON=: else AC_PATH_PROG([PYTHON], [$am_cv_pathless_PYTHON]) fi am_display_PYTHON=$am_cv_pathless_PYTHON fi ]) if test "$PYTHON" = :; then dnl Run any user-specified action, or abort. m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])]) else dnl Query Python for its version number. Getting [:3] seems to be dnl the best way to do this; it's what "site.py" does in the standard dnl library. AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version], [am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[[:3]])"`]) AC_SUBST([PYTHON_VERSION], [$am_cv_python_version]) dnl Use the values of $prefix and $exec_prefix for the corresponding dnl values of PYTHON_PREFIX and PYTHON_EXEC_PREFIX. These are made dnl distinct variables so they can be overridden if need be. However, dnl general consensus is that you shouldn't need this ability. AC_SUBST([PYTHON_PREFIX], ['${prefix}']) AC_SUBST([PYTHON_EXEC_PREFIX], ['${exec_prefix}']) dnl At times (like when building shared libraries) you may want dnl to know which OS platform Python thinks this is. AC_CACHE_CHECK([for $am_display_PYTHON platform], [am_cv_python_platform], [am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`]) AC_SUBST([PYTHON_PLATFORM], [$am_cv_python_platform]) # Just factor out some code duplication. am_python_setup_sysconfig="\ import sys # Prefer sysconfig over distutils.sysconfig, for better compatibility # with python 3.x. See automake bug#10227. try: import sysconfig except ImportError: can_use_sysconfig = 0 else: can_use_sysconfig = 1 # Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs: # try: from platform import python_implementation if python_implementation() == 'CPython' and sys.version[[:3]] == '2.7': can_use_sysconfig = 0 except ImportError: pass" dnl Set up 4 directories: dnl pythondir -- where to install python scripts. This is the dnl site-packages directory, not the python standard library dnl directory like in previous automake betas. This behavior dnl is more consistent with lispdir.m4 for example. dnl Query distutils for this directory. AC_CACHE_CHECK([for $am_display_PYTHON script directory], [am_cv_python_pythondir], [if test "x$prefix" = xNONE then am_py_prefix=$ac_default_prefix else am_py_prefix=$prefix fi am_cv_python_pythondir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix') sys.stdout.write(sitedir)"` case $am_cv_python_pythondir in $am_py_prefix*) am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'` am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"` ;; *) case $am_py_prefix in /usr|/System*) ;; *) am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac ]) AC_SUBST([pythondir], [$am_cv_python_pythondir]) dnl pkgpythondir -- $PACKAGE directory under pythondir. Was dnl PYTHON_SITE_PACKAGE in previous betas, but this naming is dnl more consistent with the rest of automake. AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE]) dnl pyexecdir -- directory for installing python extension modules dnl (shared libraries) dnl Query distutils for this directory. AC_CACHE_CHECK([for $am_display_PYTHON extension module directory], [am_cv_python_pyexecdir], [if test "x$exec_prefix" = xNONE then am_py_exec_prefix=$am_py_prefix else am_py_exec_prefix=$exec_prefix fi am_cv_python_pyexecdir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix') sys.stdout.write(sitedir)"` case $am_cv_python_pyexecdir in $am_py_exec_prefix*) am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'` am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"` ;; *) case $am_py_exec_prefix in /usr|/System*) ;; *) am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac ]) AC_SUBST([pyexecdir], [$am_cv_python_pyexecdir]) dnl pkgpyexecdir -- $(pyexecdir)/$(PACKAGE) AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE]) dnl Run any user-specified action. $2 fi ]) # AM_PYTHON_CHECK_VERSION(PROG, VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) # --------------------------------------------------------------------------- # Run ACTION-IF-TRUE if the Python interpreter PROG has version >= VERSION. # Run ACTION-IF-FALSE otherwise. # This test uses sys.hexversion instead of the string equivalent (first # word of sys.version), in order to cope with versions such as 2.2c1. # This supports Python 2.0 or higher. (2.0 was released on October 16, 2000). AC_DEFUN([AM_PYTHON_CHECK_VERSION], [prog="import sys # split strings by '.' and convert to numeric. Append some zeros # because we need at least 4 digits for the hex conversion. # map returns an iterator in Python 3.0 and a list in 2.x minver = list(map(int, '$2'.split('.'))) + [[0, 0, 0]] minverhex = 0 # xrange is not present in Python 3.0 and range returns an iterator for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]] sys.exit(sys.hexversion < minverhex)" AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])]) # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar # AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([config/acinclude.m4]) m4_include([config/libtool.m4]) m4_include([config/ltoptions.m4]) m4_include([config/ltsugar.m4]) m4_include([config/ltversion.m4]) m4_include([config/lt~obsolete.m4]) m4_include([config/tls.m4]) lxc-2.0.8/Makefile.am0000644061062106075000000000120413105116772011274 00000000000000# Makefile.am ACLOCAL_AMFLAGS = -I config LIBTOOL_DEPS = @LIBTOOL_DEPS@ SUBDIRS = config src templates doc hooks DIST_SUBDIRS = config src templates doc hooks EXTRA_DIST = \ autogen.sh \ lxc.spec \ CONTRIBUTING \ MAINTAINERS RPMARGS = if ENABLE_LUA RPMARGS += --with lua endif if ENABLE_PYTHON RPMARGS += --with python endif pcdatadir = $(libdir)/pkgconfig pcdata_DATA = lxc.pc libtool: $(LIBTOOL_DEPS) $(SHELL) ./config.status libtool install-data-local: $(MKDIR_P) $(DESTDIR)$(LXCPATH) $(MKDIR_P) $(DESTDIR)$(localstatedir)/cache/lxc ChangeLog:: @touch ChangeLog rpm: dist rpmbuild --clean -ta ${distdir}.tar.gz $(RPMARGS) lxc-2.0.8/MAINTAINERS0000644061062106075000000000106313105116772010740 00000000000000Before submitting your patches, check they are signed-off-by conforming with the DCO contained in the ./CONTRIBUTING file. Maintainer ---------- Committers : Serge Hallyn, Stéphane Graber, Dwight Engen and Christian Brauner Mail patches to : lxc-devel@lists.linuxcontainers.org Send pull requests at : https://github.com/lxc/lxc Mailing lists : lxc-devel@lists.linuxcontainers.org, lxc-users@lists.linuxcontainers.org Web page : https://linuxcontainers.org/lxc GIT location : git://github.com/lxc/lxc lxc-2.0.8/config/0000755061062106075000000000000013105117015010557 500000000000000lxc-2.0.8/config/missing0000755061062106075000000001533013105116775012114 00000000000000#! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2013-10-28.13; # UTC # Copyright (C) 1996-2014 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=http://www.perl.org/ flex_URL=http://flex.sourceforge.net/ gnu_software_URL=http://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'autom4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: lxc-2.0.8/config/acinclude.m40000644061062106075000000001115213105116772012701 00000000000000dnl as-ac-expand.m4 0.2.0 dnl autostars m4 macro for expanding directories using configure's prefix dnl thomas@apestaart.org dnl dnl AS_AC_EXPAND(VAR, CONFIGURE_VAR) dnl example dnl AS_AC_EXPAND(SYSCONFDIR, $sysconfdir) dnl will set SYSCONFDIR to /usr/local/etc if prefix=/usr/local AC_DEFUN([AS_AC_EXPAND], [ EXP_VAR=[$1] FROM_VAR=[$2] dnl first expand prefix and exec_prefix if necessary prefix_save=$prefix exec_prefix_save=$exec_prefix dnl if no prefix given, then use /usr/local, the default prefix if test "x$prefix" = "xNONE"; then prefix="$ac_default_prefix" fi dnl if no exec_prefix given, then use prefix if test "x$exec_prefix" = "xNONE"; then exec_prefix=$prefix fi full_var="$FROM_VAR" dnl loop until it doesn't change anymore while true; do new_full_var="`eval echo $full_var`" if test "x$new_full_var" = "x$full_var"; then break; fi full_var=$new_full_var done dnl clean up full_var=$new_full_var AC_SUBST([$1], "$full_var") dnl restore prefix and exec_prefix prefix=$prefix_save exec_prefix=$exec_prefix_save ]) dnl Available from the GNU Autoconf Macro Archive at: dnl http://www.gnu.org/software/ac-archive/htmldoc/ax_compare_version.html AC_DEFUN([AX_COMPARE_VERSION], [ # Used to indicate true or false condition ax_compare_version=false # Convert the two version strings to be compared into a format that # allows a simple string comparison. The end result is that a version # string of the form 1.12.5-r617 will be converted to the form # 0001001200050617. In other words, each number is zero padded to four # digits, and non digits are removed. AS_VAR_PUSHDEF([A],[ax_compare_version_A]) A=`echo "$1" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \ -e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \ -e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \ -e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \ -e 's/[[^0-9]]//g'` AS_VAR_PUSHDEF([B],[ax_compare_version_B]) B=`echo "$3" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \ -e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \ -e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \ -e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \ -e 's/[[^0-9]]//g'` dnl # In the case of le, ge, lt, and gt, the strings are sorted as necessary dnl # then the first line is used to determine if the condition is true. dnl # The sed right after the echo is to remove any indented white space. m4_case(m4_tolower($2), [lt],[ ax_compare_version=`echo "x$A x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/false/;s/x${B}/true/;1q"` ], [gt],[ ax_compare_version=`echo "x$A x$B" | sed 's/^ *//' | sort | sed "s/x${A}/false/;s/x${B}/true/;1q"` ], [le],[ ax_compare_version=`echo "x$A x$B" | sed 's/^ *//' | sort | sed "s/x${A}/true/;s/x${B}/false/;1q"` ], [ge],[ ax_compare_version=`echo "x$A x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/true/;s/x${B}/false/;1q"` ],[ dnl Split the operator from the subversion count if present. m4_bmatch(m4_substr($2,2), [0],[ # A count of zero means use the length of the shorter version. # Determine the number of characters in A and B. ax_compare_version_len_A=`echo "$A" | awk '{print(length)}'` ax_compare_version_len_B=`echo "$B" | awk '{print(length)}'` # Set A to no more than B's length and B to no more than A's length. A=`echo "$A" | sed "s/\(.\{$ax_compare_version_len_B\}\).*/\1/"` B=`echo "$B" | sed "s/\(.\{$ax_compare_version_len_A\}\).*/\1/"` ], [[0-9]+],[ # A count greater than zero means use only that many subversions A=`echo "$A" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"` B=`echo "$B" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"` ], [.+],[ AC_WARNING( [illegal OP numeric parameter: $2]) ],[]) # Pad zeros at end of numbers to make same length. ax_compare_version_tmp_A="$A`echo $B | sed 's/./0/g'`" B="$B`echo $A | sed 's/./0/g'`" A="$ax_compare_version_tmp_A" # Check for equality or inequality as necessary. m4_case(m4_tolower(m4_substr($2,0,2)), [eq],[ test "x$A" = "x$B" && ax_compare_version=true ], [ne],[ test "x$A" != "x$B" && ax_compare_version=true ],[ AC_WARNING([illegal OP parameter: $2]) ]) ]) AS_VAR_POPDEF([A])dnl AS_VAR_POPDEF([B])dnl dnl # Execute ACTION-IF-TRUE / ACTION-IF-FALSE. if test "$ax_compare_version" = "true" ; then m4_ifvaln([$4],[$4],[:])dnl m4_ifvaln([$5],[else $5])dnl fi ]) dnl AX_COMPARE_VERSION lxc-2.0.8/config/templates/0000755061062106075000000000000013105117015012555 500000000000000lxc-2.0.8/config/templates/ubuntu-cloud.lucid.conf.in0000644061062106075000000000014513105116772017507 00000000000000# This derives from the main Ubuntu lucid config lxc.include = @LXCTEMPLATECONFIG@/ubuntu.lucid.conf lxc-2.0.8/config/templates/oracle.common.conf.in0000644061062106075000000000170513105116772016521 00000000000000# This derives from the global common config lxc.include = @LXCTEMPLATECONFIG@/common.conf # Capabilities # Uncomment these if you don't run anything that needs the capability, and # would like the container to run with less privilege. # # Dropping sys_admin disables container root from doing a lot of things # that could be bad like re-mounting lxc fstab entries rw for example, # but also disables some useful things like being able to nfs mount, and # things that are already namespaced with ns_capable() kernel checks, like # hostname(1). # lxc.cap.drop = sys_admin # lxc.cap.drop = net_raw # breaks dhcp/ping # lxc.cap.drop = setgid # breaks login (initgroups/setgroups) # lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd) # lxc.cap.drop = setuid # breaks sshd,nfs statd # lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed) # lxc.cap.drop = audit_write lxc.cap.drop = sys_nice sys_pacct sys_rawio lxc-2.0.8/config/templates/gentoo.moresecure.conf.in0000644061062106075000000000470413105116772017432 00000000000000# This derives from the global common config lxc.include = @LXCTEMPLATECONFIG@/common.conf # Gentoo security oriented default configuration # This is a more security oriented container configuration # "More" because this is far from fully secure # Looking for more working features and you trust your # Container user ? see gentoo.common.conf # do not mount sysfs, see http://blog.bofh.it/debian/id_413 lxc.mount.entry=mqueue dev/mqueue mqueue rw,nodev,noexec,nosuid,create=dir 0 0 lxc.mount.entry=shm dev/shm tmpfs rw,nosuid,nodev,noexec,relatime,create=dir 0 0 lxc.mount.entry=run run tmpfs rw,nosuid,nodev,relatime,mode=755 0 0 # Capabilities # Uncomment these if you don't run anything that needs the capability, and # would like the container to run with less privilege. # # Dropping sys_admin disables container root from doing a lot of things # that could be bad like re-mounting lxc fstab entries rw for example, # but also disables some useful things like being able to nfs mount, and # things that are already namespaced with ns_capable() kernel checks, like # hostname(1). # lxc.cap.drop = sys_admin # breaks systemd # lxc.cap.drop = net_raw # breaks dhcp/ping # lxc.cap.drop = setgid # breaks login (initgroups/setgroups) # lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd) # lxc.cap.drop = setuid # breaks sshd,nfs statd # lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed) # lxc.cap.drop = audit_write # lxc.cap.drop = setpcap # breaks journald # lxc.cap.drop = sys_resource # breaks systemd lxc.cap.drop = audit_control audit_write dac_read_search fsetid ipc_owner linux_immutable mknod setfcap setpcap sys_admin sys_boot sys_nice sys_pacct sys_ptrace sys_rawio sys_resource sys_tty_config syslog # WARNING: the security vulnerability reported for 'cap_net_admin' at # http://mainisusuallyafunction.blogspot.com/2012/11/attacking-hardened-linux-systems-with.html # via JIT spraying (the BPF JIT module disabled on most systems was used # in the example, but others are suggested vulnerable) meant that users # with root in a container, that capability and kernel module may escape # the container. ALWAYS be extremely careful granting any process root # within a container, use a minimal configuration at all levels - # including the kernel - and multiple layers of security on any system # where security is a priority. note that not only LXC but PAX (and # others?) were vulnerable to this issue. lxc-2.0.8/config/templates/archlinux.userns.conf.in0000644061062106075000000000013313105116772017272 00000000000000# This derives from the global userns config lxc.include = @LXCTEMPLATECONFIG@/userns.conf lxc-2.0.8/config/templates/sparclinux.common.conf.in0000644061062106075000000000170513105116772017444 00000000000000# This derives from the global common config lxc.include = @LXCTEMPLATECONFIG@/common.conf # Capabilities # Uncomment these if you don't run anything that needs the capability, and # would like the container to run with less privilege. # # Dropping sys_admin disables container root from doing a lot of things # that could be bad like re-mounting lxc fstab entries rw for example, # but also disables some useful things like being able to nfs mount, and # things that are already namespaced with ns_capable() kernel checks, like # hostname(1). # lxc.cap.drop = sys_admin # lxc.cap.drop = net_raw # breaks dhcp/ping # lxc.cap.drop = setgid # breaks login (initgroups/setgroups) # lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd) # lxc.cap.drop = setuid # breaks sshd,nfs statd # lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed) # lxc.cap.drop = audit_write lxc.cap.drop = sys_nice sys_pacct sys_rawio lxc-2.0.8/config/templates/debian.common.conf.in0000644061062106075000000000173713105116772016503 00000000000000# This derives from the global common config lxc.include = @LXCTEMPLATECONFIG@/common.conf # Doesn't support consoles in /dev/lxc/ lxc.devttydir = # When using LXC with apparmor, the container will be confined by default. # If you wish for it to instead run unconfined, copy the following line # (uncommented) to the container's configuration file. #lxc.aa_profile = unconfined # If you wish to allow mounting block filesystems, then use the following # line instead, and make sure to grant access to the block device and/or loop # devices below in lxc.cgroup.devices.allow. #lxc.aa_profile = lxc-container-default-with-mounting # Extra cgroup device access ## rtc lxc.cgroup.devices.allow = c 254:0 rm ## tun lxc.cgroup.devices.allow = c 10:200 rwm ## hpet lxc.cgroup.devices.allow = c 10:228 rwm ## kvm 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 lxc-2.0.8/config/templates/Makefile.am0000644061062106075000000000156413105116772014550 00000000000000templatesconfigdir=@LXCTEMPLATECONFIG@ EXTRA_DIST = common.seccomp SUBDIRS = common.conf.d templatesconfig_DATA = \ alpine.common.conf \ alpine.userns.conf \ archlinux.common.conf \ archlinux.userns.conf \ centos.common.conf \ centos.userns.conf \ common.conf \ common.seccomp \ debian.common.conf \ debian.userns.conf \ fedora.common.conf \ fedora.userns.conf \ gentoo.common.conf \ gentoo.moresecure.conf \ gentoo.userns.conf \ nesting.conf \ opensuse.common.conf \ opensuse.userns.conf \ oracle.common.conf \ oracle.userns.conf \ plamo.common.conf \ plamo.userns.conf \ slackware.common.conf \ slackware.userns.conf \ ubuntu-cloud.common.conf \ ubuntu-cloud.lucid.conf \ ubuntu-cloud.userns.conf \ ubuntu.common.conf \ ubuntu.lucid.conf \ ubuntu.userns.conf \ openwrt.common.conf \ sparclinux.common.conf \ sparclinux.userns.conf \ userns.conf lxc-2.0.8/config/templates/common.conf.d/0000755061062106075000000000000013105117015015213 500000000000000lxc-2.0.8/config/templates/common.conf.d/Makefile.in0000644061062106075000000004075313105116775017225 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = config/templates/common.conf.d ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/acinclude.m4 \ $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/tls.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(templatesconfigdir)" DATA = $(templatesconfig_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in README DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APPARMOR_LIBS = @APPARMOR_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BINDIR = @BINDIR@ CAP_LIBS = @CAP_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CGMANAGER_CFLAGS = @CGMANAGER_CFLAGS@ CGMANAGER_LIBS = @CGMANAGER_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIR = @DATADIR@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFAULT_CGROUP_PATTERN = @DEFAULT_CGROUP_PATTERN@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOCDIR = @DOCDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ HAVE_DOXYGEN = @HAVE_DOXYGEN@ INCLUDEDIR = @INCLUDEDIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDIR = @LIBDIR@ LIBEXECDIR = @LIBEXECDIR@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCALSTATEDIR = @LOCALSTATEDIR@ LOGPATH = @LOGPATH@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBDIR = @LUA_LIBDIR@ LUA_LIBS = @LUA_LIBS@ LUA_SHAREDIR = @LUA_SHAREDIR@ LUA_VERSION = @LUA_VERSION@ LXCBINHOOKDIR = @LXCBINHOOKDIR@ LXCHOOKDIR = @LXCHOOKDIR@ LXCINITDIR = @LXCINITDIR@ LXCPATH = @LXCPATH@ LXCROOTFSMOUNT = @LXCROOTFSMOUNT@ LXCTEMPLATECONFIG = @LXCTEMPLATECONFIG@ LXCTEMPLATEDIR = @LXCTEMPLATEDIR@ LXC_ABI = @LXC_ABI@ LXC_ABI_MAJOR = @LXC_ABI_MAJOR@ LXC_ABI_MICRO = @LXC_ABI_MICRO@ LXC_ABI_MINOR = @LXC_ABI_MINOR@ LXC_DEFAULT_CONFIG = @LXC_DEFAULT_CONFIG@ LXC_DEVEL = @LXC_DEVEL@ LXC_DISTRO_SYSCONF = @LXC_DISTRO_SYSCONF@ LXC_GENERATE_DATE = @LXC_GENERATE_DATE@ LXC_GLOBAL_CONF = @LXC_GLOBAL_CONF@ LXC_USERNIC_CONF = @LXC_USERNIC_CONF@ LXC_USERNIC_DB = @LXC_USERNIC_DB@ LXC_VERSION = @LXC_VERSION@ LXC_VERSION_BASE = @LXC_VERSION_BASE@ LXC_VERSION_BETA = @LXC_VERSION_BETA@ LXC_VERSION_MAJOR = @LXC_VERSION_MAJOR@ LXC_VERSION_MICRO = @LXC_VERSION_MICRO@ LXC_VERSION_MINOR = @LXC_VERSION_MINOR@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NIH_CFLAGS = @NIH_CFLAGS@ NIH_DBUS_CFLAGS = @NIH_DBUS_CFLAGS@ NIH_DBUS_LIBS = @NIH_DBUS_LIBS@ NIH_LIBS = @NIH_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PREFIX = @PREFIX@ PYTHON = @PYTHON@ PYTHONDEV_CFLAGS = @PYTHONDEV_CFLAGS@ PYTHONDEV_LIBS = @PYTHONDEV_LIBS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RUNTIME_PATH = @RUNTIME_PATH@ SBINDIR = @SBINDIR@ SECCOMP_CFLAGS = @SECCOMP_CFLAGS@ SECCOMP_LIBS = @SECCOMP_LIBS@ SED = @SED@ SELINUX_LIBS = @SELINUX_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SYSCONFDIR = @SYSCONFDIR@ SYSTEMD_UNIT_DIR = @SYSTEMD_UNIT_DIR@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bashcompdir = @bashcompdir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ db2xman = @db2xman@ docdir = @docdir@ docdtd = @docdtd@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ templatesconfigdir = @LXCTEMPLATECONFIG@/common.conf.d/ EXTRA_DIST = README templatesconfig_DATA = \ README all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu config/templates/common.conf.d/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu config/templates/common.conf.d/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-templatesconfigDATA: $(templatesconfig_DATA) @$(NORMAL_INSTALL) @list='$(templatesconfig_DATA)'; test -n "$(templatesconfigdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(templatesconfigdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(templatesconfigdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(templatesconfigdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(templatesconfigdir)" || exit $$?; \ done uninstall-templatesconfigDATA: @$(NORMAL_UNINSTALL) @list='$(templatesconfig_DATA)'; test -n "$(templatesconfigdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(templatesconfigdir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(DATA) installdirs: for dir in "$(DESTDIR)$(templatesconfigdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-templatesconfigDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-templatesconfigDATA .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip install-templatesconfigDATA installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am uninstall-templatesconfigDATA .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lxc-2.0.8/config/templates/common.conf.d/Makefile.am0000644061062106075000000000015513105116772017201 00000000000000templatesconfigdir=@LXCTEMPLATECONFIG@/common.conf.d/ EXTRA_DIST = README templatesconfig_DATA = \ README lxc-2.0.8/config/templates/common.conf.d/README0000644061062106075000000000044713105116772016031 00000000000000This directory can be used by packages and users to dump LXC configuration snippets which will then be used by all containers using the common.conf configuration file (directly or indirectly). Configuration files must end with the .conf suffix and LXC will include those in alphabetical order. lxc-2.0.8/config/templates/plamo.userns.conf.in0000644061062106075000000000013313105116772016405 00000000000000# This derives from the global userns config lxc.include = @LXCTEMPLATECONFIG@/userns.conf lxc-2.0.8/config/templates/slackware.common.conf.in0000644061062106075000000000327713105116772017236 00000000000000# This derives from the global common config lxc.include = @LXCTEMPLATECONFIG@/common.conf # Doesn't support consoles in /dev/lxc/ lxc.devttydir = # Extra cgroup device access ## rtc lxc.cgroup.devices.allow = c 254:0 rm ## tun lxc.cgroup.devices.allow = c 10:200 rwm ## hpet lxc.cgroup.devices.allow = c 10:228 rwm ## kvm 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 # mount /dev/shm as tmpfs lxc.mount.entry = none dev/shm tmpfs rw,nosuid,nodev,create=dir # Capabilities # Uncomment these if you don't run anything that needs the capability, and # would like the container to run with less privilege. # Note that some are already dropped in common.conf. # # Dropping sys_admin disables container root from doing a lot of things # that could be bad like re-mounting lxc fstab entries rw for example, # but also disables some useful things like being able to nfs mount, and # things that are already namespaced with ns_capable() kernel checks, like # hostname(1). # # Some of these don't apply in Slackware but are here for future reference. # # lxc.cap.drop = sys_admin # breaks systemd # lxc.cap.drop = net_raw # breaks dhcp/ping # lxc.cap.drop = setgid # breaks login (initgroups/setgroups) # lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd) # lxc.cap.drop = setuid # breaks sshd,nfs statd # lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed) # lxc.cap.drop = audit_write # lxc.cap.drop = setpcap # breaks journald # lxc.cap.drop = sys_resource # breaks systemd # lxc.cap.drop = mknod setfcap setpcap lxc-2.0.8/config/templates/alpine.common.conf.in0000644061062106075000000000137413105116772016526 00000000000000# This derives from the global common config. lxc.include = @LXCTEMPLATECONFIG@/common.conf # Doesn't support consoles in /dev/lxc/. lxc.devttydir = # Drop another (potentially) harmful capabilities. lxc.cap.drop = audit_write lxc.cap.drop = ipc_owner lxc.cap.drop = mknod lxc.cap.drop = setpcap lxc.cap.drop = sys_nice lxc.cap.drop = sys_pacct lxc.cap.drop = sys_ptrace lxc.cap.drop = sys_rawio lxc.cap.drop = sys_resource lxc.cap.drop = sys_tty_config lxc.cap.drop = syslog lxc.cap.drop = wake_alarm # Mount /run as tmpfs. lxc.mount.entry=run run tmpfs rw,nodev,relatime,mode=755 0 0 # Mount /dev/shm as tmpfs; needed for building python and possibly other packages. lxc.mount.entry=shm dev/shm tmpfs rw,nodev,noexec,nosuid,relatime,mode=1777,create=dir 0 0 lxc-2.0.8/config/templates/nesting.conf.in0000644061062106075000000000046513105116772015436 00000000000000# Use a profile which allows nesting lxc.aa_profile = lxc-container-default-with-nesting # Add uncovered mounts of proc and sys, else unprivileged users # cannot remount those lxc.mount.entry = proc dev/.lxc/proc proc create=dir,optional 0 0 lxc.mount.entry = sys dev/.lxc/sys sysfs create=dir,optional 0 0 lxc-2.0.8/config/templates/ubuntu.userns.conf.in0000644061062106075000000000052013105116772016617 00000000000000# This derives from the global userns config lxc.include = @LXCTEMPLATECONFIG@/userns.conf # Extra fstab entries as mountall can't mount those by itself lxc.mount.entry = /sys/firmware/efi/efivars sys/firmware/efi/efivars none bind,optional 0 0 lxc.mount.entry = /proc/sys/fs/binfmt_misc proc/sys/fs/binfmt_misc none bind,optional 0 0 lxc-2.0.8/config/templates/fedora.common.conf.in0000644061062106075000000000203313105116772016507 00000000000000# This derives from the global common config lxc.include = @LXCTEMPLATECONFIG@/common.conf # Capabilities # Uncomment these if you don't run anything that needs the capability, and # would like the container to run with less privilege. # # Dropping sys_admin disables container root from doing a lot of things # that could be bad like re-mounting lxc fstab entries rw for example, # but also disables some useful things like being able to nfs mount, and # things that are already namespaced with ns_capable() kernel checks, like # hostname(1). # lxc.cap.drop = sys_admin # lxc.cap.drop = net_raw # breaks dhcp/ping # lxc.cap.drop = setgid # breaks login (initgroups/setgroups) # lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd) # lxc.cap.drop = setuid # breaks sshd,nfs statd # lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed) # lxc.cap.drop = audit_write # lxc.cap.drop = setpcap # big big login delays in Fedora 20 systemd lxc.cap.drop = setfcap sys_nice sys_pacct sys_rawio lxc-2.0.8/config/templates/centos.userns.conf.in0000644061062106075000000000013313105116772016570 00000000000000# This derives from the global userns config lxc.include = @LXCTEMPLATECONFIG@/userns.conf lxc-2.0.8/config/templates/Makefile.in0000644061062106075000000007360013105116775014564 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = config/templates ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/acinclude.m4 \ $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/tls.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h CONFIG_CLEAN_FILES = alpine.common.conf alpine.userns.conf \ archlinux.common.conf archlinux.userns.conf centos.common.conf \ centos.userns.conf common.conf debian.common.conf \ debian.userns.conf fedora.common.conf fedora.userns.conf \ gentoo.common.conf gentoo.moresecure.conf gentoo.userns.conf \ nesting.conf opensuse.common.conf opensuse.userns.conf \ oracle.common.conf oracle.userns.conf plamo.common.conf \ plamo.userns.conf slackware.common.conf slackware.userns.conf \ ubuntu-cloud.common.conf ubuntu-cloud.lucid.conf \ ubuntu-cloud.userns.conf ubuntu.common.conf ubuntu.lucid.conf \ ubuntu.userns.conf openwrt.common.conf sparclinux.common.conf \ sparclinux.userns.conf userns.conf CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(templatesconfigdir)" DATA = $(templatesconfig_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in \ $(srcdir)/alpine.common.conf.in \ $(srcdir)/alpine.userns.conf.in \ $(srcdir)/archlinux.common.conf.in \ $(srcdir)/archlinux.userns.conf.in \ $(srcdir)/centos.common.conf.in \ $(srcdir)/centos.userns.conf.in $(srcdir)/common.conf.in \ $(srcdir)/debian.common.conf.in \ $(srcdir)/debian.userns.conf.in \ $(srcdir)/fedora.common.conf.in \ $(srcdir)/fedora.userns.conf.in \ $(srcdir)/gentoo.common.conf.in \ $(srcdir)/gentoo.moresecure.conf.in \ $(srcdir)/gentoo.userns.conf.in $(srcdir)/nesting.conf.in \ $(srcdir)/opensuse.common.conf.in \ $(srcdir)/opensuse.userns.conf.in \ $(srcdir)/openwrt.common.conf.in \ $(srcdir)/oracle.common.conf.in \ $(srcdir)/oracle.userns.conf.in $(srcdir)/plamo.common.conf.in \ $(srcdir)/plamo.userns.conf.in \ $(srcdir)/slackware.common.conf.in \ $(srcdir)/slackware.userns.conf.in \ $(srcdir)/sparclinux.common.conf.in \ $(srcdir)/sparclinux.userns.conf.in \ $(srcdir)/ubuntu-cloud.common.conf.in \ $(srcdir)/ubuntu-cloud.lucid.conf.in \ $(srcdir)/ubuntu-cloud.userns.conf.in \ $(srcdir)/ubuntu.common.conf.in $(srcdir)/ubuntu.lucid.conf.in \ $(srcdir)/ubuntu.userns.conf.in $(srcdir)/userns.conf.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APPARMOR_LIBS = @APPARMOR_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BINDIR = @BINDIR@ CAP_LIBS = @CAP_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CGMANAGER_CFLAGS = @CGMANAGER_CFLAGS@ CGMANAGER_LIBS = @CGMANAGER_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIR = @DATADIR@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFAULT_CGROUP_PATTERN = @DEFAULT_CGROUP_PATTERN@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOCDIR = @DOCDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ HAVE_DOXYGEN = @HAVE_DOXYGEN@ INCLUDEDIR = @INCLUDEDIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDIR = @LIBDIR@ LIBEXECDIR = @LIBEXECDIR@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCALSTATEDIR = @LOCALSTATEDIR@ LOGPATH = @LOGPATH@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBDIR = @LUA_LIBDIR@ LUA_LIBS = @LUA_LIBS@ LUA_SHAREDIR = @LUA_SHAREDIR@ LUA_VERSION = @LUA_VERSION@ LXCBINHOOKDIR = @LXCBINHOOKDIR@ LXCHOOKDIR = @LXCHOOKDIR@ LXCINITDIR = @LXCINITDIR@ LXCPATH = @LXCPATH@ LXCROOTFSMOUNT = @LXCROOTFSMOUNT@ LXCTEMPLATECONFIG = @LXCTEMPLATECONFIG@ LXCTEMPLATEDIR = @LXCTEMPLATEDIR@ LXC_ABI = @LXC_ABI@ LXC_ABI_MAJOR = @LXC_ABI_MAJOR@ LXC_ABI_MICRO = @LXC_ABI_MICRO@ LXC_ABI_MINOR = @LXC_ABI_MINOR@ LXC_DEFAULT_CONFIG = @LXC_DEFAULT_CONFIG@ LXC_DEVEL = @LXC_DEVEL@ LXC_DISTRO_SYSCONF = @LXC_DISTRO_SYSCONF@ LXC_GENERATE_DATE = @LXC_GENERATE_DATE@ LXC_GLOBAL_CONF = @LXC_GLOBAL_CONF@ LXC_USERNIC_CONF = @LXC_USERNIC_CONF@ LXC_USERNIC_DB = @LXC_USERNIC_DB@ LXC_VERSION = @LXC_VERSION@ LXC_VERSION_BASE = @LXC_VERSION_BASE@ LXC_VERSION_BETA = @LXC_VERSION_BETA@ LXC_VERSION_MAJOR = @LXC_VERSION_MAJOR@ LXC_VERSION_MICRO = @LXC_VERSION_MICRO@ LXC_VERSION_MINOR = @LXC_VERSION_MINOR@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NIH_CFLAGS = @NIH_CFLAGS@ NIH_DBUS_CFLAGS = @NIH_DBUS_CFLAGS@ NIH_DBUS_LIBS = @NIH_DBUS_LIBS@ NIH_LIBS = @NIH_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PREFIX = @PREFIX@ PYTHON = @PYTHON@ PYTHONDEV_CFLAGS = @PYTHONDEV_CFLAGS@ PYTHONDEV_LIBS = @PYTHONDEV_LIBS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RUNTIME_PATH = @RUNTIME_PATH@ SBINDIR = @SBINDIR@ SECCOMP_CFLAGS = @SECCOMP_CFLAGS@ SECCOMP_LIBS = @SECCOMP_LIBS@ SED = @SED@ SELINUX_LIBS = @SELINUX_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SYSCONFDIR = @SYSCONFDIR@ SYSTEMD_UNIT_DIR = @SYSTEMD_UNIT_DIR@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bashcompdir = @bashcompdir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ db2xman = @db2xman@ docdir = @docdir@ docdtd = @docdtd@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ templatesconfigdir = @LXCTEMPLATECONFIG@ EXTRA_DIST = common.seccomp SUBDIRS = common.conf.d templatesconfig_DATA = \ alpine.common.conf \ alpine.userns.conf \ archlinux.common.conf \ archlinux.userns.conf \ centos.common.conf \ centos.userns.conf \ common.conf \ common.seccomp \ debian.common.conf \ debian.userns.conf \ fedora.common.conf \ fedora.userns.conf \ gentoo.common.conf \ gentoo.moresecure.conf \ gentoo.userns.conf \ nesting.conf \ opensuse.common.conf \ opensuse.userns.conf \ oracle.common.conf \ oracle.userns.conf \ plamo.common.conf \ plamo.userns.conf \ slackware.common.conf \ slackware.userns.conf \ ubuntu-cloud.common.conf \ ubuntu-cloud.lucid.conf \ ubuntu-cloud.userns.conf \ ubuntu.common.conf \ ubuntu.lucid.conf \ ubuntu.userns.conf \ openwrt.common.conf \ sparclinux.common.conf \ sparclinux.userns.conf \ userns.conf all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu config/templates/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu config/templates/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): alpine.common.conf: $(top_builddir)/config.status $(srcdir)/alpine.common.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ alpine.userns.conf: $(top_builddir)/config.status $(srcdir)/alpine.userns.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ archlinux.common.conf: $(top_builddir)/config.status $(srcdir)/archlinux.common.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ archlinux.userns.conf: $(top_builddir)/config.status $(srcdir)/archlinux.userns.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ centos.common.conf: $(top_builddir)/config.status $(srcdir)/centos.common.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ centos.userns.conf: $(top_builddir)/config.status $(srcdir)/centos.userns.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ common.conf: $(top_builddir)/config.status $(srcdir)/common.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ debian.common.conf: $(top_builddir)/config.status $(srcdir)/debian.common.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ debian.userns.conf: $(top_builddir)/config.status $(srcdir)/debian.userns.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ fedora.common.conf: $(top_builddir)/config.status $(srcdir)/fedora.common.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ fedora.userns.conf: $(top_builddir)/config.status $(srcdir)/fedora.userns.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gentoo.common.conf: $(top_builddir)/config.status $(srcdir)/gentoo.common.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gentoo.moresecure.conf: $(top_builddir)/config.status $(srcdir)/gentoo.moresecure.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gentoo.userns.conf: $(top_builddir)/config.status $(srcdir)/gentoo.userns.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ nesting.conf: $(top_builddir)/config.status $(srcdir)/nesting.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ opensuse.common.conf: $(top_builddir)/config.status $(srcdir)/opensuse.common.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ opensuse.userns.conf: $(top_builddir)/config.status $(srcdir)/opensuse.userns.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ oracle.common.conf: $(top_builddir)/config.status $(srcdir)/oracle.common.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ oracle.userns.conf: $(top_builddir)/config.status $(srcdir)/oracle.userns.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ plamo.common.conf: $(top_builddir)/config.status $(srcdir)/plamo.common.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ plamo.userns.conf: $(top_builddir)/config.status $(srcdir)/plamo.userns.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ slackware.common.conf: $(top_builddir)/config.status $(srcdir)/slackware.common.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ slackware.userns.conf: $(top_builddir)/config.status $(srcdir)/slackware.userns.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ ubuntu-cloud.common.conf: $(top_builddir)/config.status $(srcdir)/ubuntu-cloud.common.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ ubuntu-cloud.lucid.conf: $(top_builddir)/config.status $(srcdir)/ubuntu-cloud.lucid.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ ubuntu-cloud.userns.conf: $(top_builddir)/config.status $(srcdir)/ubuntu-cloud.userns.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ ubuntu.common.conf: $(top_builddir)/config.status $(srcdir)/ubuntu.common.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ ubuntu.lucid.conf: $(top_builddir)/config.status $(srcdir)/ubuntu.lucid.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ ubuntu.userns.conf: $(top_builddir)/config.status $(srcdir)/ubuntu.userns.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ openwrt.common.conf: $(top_builddir)/config.status $(srcdir)/openwrt.common.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ sparclinux.common.conf: $(top_builddir)/config.status $(srcdir)/sparclinux.common.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ sparclinux.userns.conf: $(top_builddir)/config.status $(srcdir)/sparclinux.userns.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ userns.conf: $(top_builddir)/config.status $(srcdir)/userns.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-templatesconfigDATA: $(templatesconfig_DATA) @$(NORMAL_INSTALL) @list='$(templatesconfig_DATA)'; test -n "$(templatesconfigdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(templatesconfigdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(templatesconfigdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(templatesconfigdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(templatesconfigdir)" || exit $$?; \ done uninstall-templatesconfigDATA: @$(NORMAL_UNINSTALL) @list='$(templatesconfig_DATA)'; test -n "$(templatesconfigdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(templatesconfigdir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(DATA) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(templatesconfigdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-templatesconfigDATA install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-templatesconfigDATA .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip install-templatesconfigDATA installcheck \ installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-templatesconfigDATA .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lxc-2.0.8/config/templates/openwrt.common.conf.in0000644061062106075000000000247313105116772016755 00000000000000# Default console settings lxc.devttydir = lxc lxc.tty = 4 lxc.pts = 1024 # Default capabilities lxc.cap.drop = mac_admin lxc.cap.drop = mac_override lxc.cap.drop = sys_admin lxc.cap.drop = sys_module lxc.cap.drop = sys_nice lxc.cap.drop = sys_pacct lxc.cap.drop = sys_ptrace lxc.cap.drop = sys_rawio lxc.cap.drop = sys_resource lxc.cap.drop = sys_time lxc.cap.drop = sys_tty_config lxc.cap.drop = syslog lxc.cap.drop = wake_alarm # Default cgroups - all denied except those whitelisted lxc.cgroup.devices.deny = a ## /dev/null and zero lxc.cgroup.devices.allow = c 1:3 rwm lxc.cgroup.devices.allow = c 1:5 rwm ## consoles lxc.cgroup.devices.allow = c 5:0 rwm lxc.cgroup.devices.allow = c 5:1 rwm ## /dev/{,u}random lxc.cgroup.devices.allow = c 1:8 rwm lxc.cgroup.devices.allow = c 1:9 rwm ## /dev/pts/* lxc.cgroup.devices.allow = c 5:2 rwm lxc.cgroup.devices.allow = c 136:* rwm ## rtc lxc.cgroup.devices.allow = c 254:0 rm ## tun lxc.cgroup.devices.allow = c 10:200 rwm ## dev/tty0 lxc.cgroup.devices.allow = c 4:0 rwm ## dev/tty1 lxc.cgroup.devices.allow = c 4:1 rwm ## To use loop devices, copy the following line to the container's ## configuration file (uncommented). #lxc.cgroup.devices.allow = b 7:* rwm # Blacklist some syscalls which are not safe in privileged # containers lxc.seccomp = /usr/share/lxc/config/common.seccomp lxc-2.0.8/config/templates/opensuse.common.conf.in0000644061062106075000000000205413105116772017113 00000000000000# This derives from the global common config lxc.include = @LXCTEMPLATECONFIG@/common.conf # Capabilities # Uncomment these if you don't run anything that needs the capability, and # would like the container to run with less privilege. # # Dropping sys_admin disables container root from doing a lot of things # that could be bad like re-mounting lxc fstab entries rw for example, # but also disables some useful things like being able to nfs mount, and # things that are already namespaced with ns_capable() kernel checks, like # hostname(1). # lxc.cap.drop = sys_admin # lxc.cap.drop = net_raw # breaks dhcp/ping # lxc.cap.drop = setgid # breaks login (initgroups/setgroups) # lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd) # lxc.cap.drop = setuid # breaks sshd,nfs statd # lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed) # lxc.cap.drop = audit_write # lxc.cap.drop = setpcap # big big login delays in Fedora 20 systemd # lxc.cap.drop = setfcap lxc.cap.drop = sys_nice sys_pacct sys_rawio lxc-2.0.8/config/templates/ubuntu-cloud.userns.conf.in0000644061062106075000000000014713105116772017730 00000000000000# This derives from the main Ubuntu userns config lxc.include = @LXCTEMPLATECONFIG@/ubuntu.userns.conf lxc-2.0.8/config/templates/gentoo.userns.conf.in0000644061062106075000000000013313105116772016570 00000000000000# This derives from the global userns config lxc.include = @LXCTEMPLATECONFIG@/userns.conf lxc-2.0.8/config/templates/userns.conf.in0000644061062106075000000000113313105116772015277 00000000000000# CAP_SYS_ADMIN in init-user-ns is required for cgroup.devices lxc.cgroup.devices.deny = lxc.cgroup.devices.allow = # We can't move bind-mounts, so don't use /dev/lxc/ lxc.devttydir = # Extra bind-mounts for userns lxc.mount.entry = /dev/full dev/full none bind,create=file 0 0 lxc.mount.entry = /dev/null dev/null none bind,create=file 0 0 lxc.mount.entry = /dev/random dev/random none bind,create=file 0 0 lxc.mount.entry = /dev/tty dev/tty none bind,create=file 0 0 lxc.mount.entry = /dev/urandom dev/urandom none bind,create=file 0 0 lxc.mount.entry = /dev/zero dev/zero none bind,create=file 0 0 lxc-2.0.8/config/templates/plamo.common.conf.in0000644061062106075000000000033713105116772016364 00000000000000# This derives from the global common config lxc.include = @LXCTEMPLATECONFIG@/common.conf # Doesn't support consoles in /dev/lxc/ lxc.devttydir = # Extra cgroup device access ## rtc lxc.cgroup.devices.allow = c 254:0 rm lxc-2.0.8/config/templates/sparclinux.userns.conf.in0000644061062106075000000000013313105116772017465 00000000000000# This derives from the global userns config lxc.include = @LXCTEMPLATECONFIG@/userns.conf lxc-2.0.8/config/templates/debian.userns.conf.in0000644061062106075000000000013313105116772016517 00000000000000# This derives from the global userns config lxc.include = @LXCTEMPLATECONFIG@/userns.conf lxc-2.0.8/config/templates/archlinux.common.conf.in0000644061062106075000000000236513105116772017254 00000000000000# This derives from the global common config lxc.include = @LXCTEMPLATECONFIG@/common.conf # Allow for 6 tty devices by default lxc.tty = 6 # Set the halt/stop signals lxc.haltsignal=SIGRTMIN+4 lxc.stopsignal=SIGRTMIN+14 # Uncomment to disable creating tty devices subdirectory in /dev # lxc.devttydir = # Capabilities # Uncomment these if you don't run anything that needs the capability, and # would like the container to run with less privilege. # # Dropping sys_admin disables container root from doing a lot of things # that could be bad like re-mounting lxc fstab entries rw for example, # but also disables some useful things like being able to nfs mount, and # things that are already namespaced with ns_capable() kernel checks, like # hostname(1). # lxc.cap.drop = sys_admin # lxc.cap.drop = net_raw # breaks dhcp/ping # lxc.cap.drop = setgid # breaks login (initgroups/setgroups) # lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd) # lxc.cap.drop = setuid # breaks sshd,nfs statd # lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed) # lxc.cap.drop = audit_write # lxc.cap.drop = setpcap # big big login delays in Fedora 20 systemd # lxc.cap.drop = setfcap sys_nice sys_pacct sys_rawio lxc-2.0.8/config/templates/common.seccomp0000644061062106075000000000030713105116772015351 000000000000002 blacklist reject_force_umount # comment this to allow umount -f; not recommended [all] kexec_load errno 1 open_by_handle_at errno 1 init_module errno 1 finit_module errno 1 delete_module errno 1 lxc-2.0.8/config/templates/oracle.userns.conf.in0000644061062106075000000000013313105116772016542 00000000000000# This derives from the global userns config lxc.include = @LXCTEMPLATECONFIG@/userns.conf lxc-2.0.8/config/templates/common.conf.in0000644061062106075000000000303113105116772015247 00000000000000# Default configuration shared by all containers # Setup the LXC devices in /dev/lxc/ lxc.devttydir = lxc # Allow for 1024 pseudo terminals lxc.pts = 1024 # Setup 4 tty devices lxc.tty = 4 # Drop some harmful capabilities lxc.cap.drop = mac_admin mac_override sys_time sys_module sys_rawio # Set the pivot directory lxc.pivotdir = lxc_putold # Ensure hostname is changed on clone lxc.hook.clone = @LXCHOOKDIR@/clonehostname # CGroup whitelist lxc.cgroup.devices.deny = a ## Allow any mknod (but not reading/writing the node) lxc.cgroup.devices.allow = c *:* m lxc.cgroup.devices.allow = b *:* m ## Allow specific devices ### /dev/null lxc.cgroup.devices.allow = c 1:3 rwm ### /dev/zero lxc.cgroup.devices.allow = c 1:5 rwm ### /dev/full lxc.cgroup.devices.allow = c 1:7 rwm ### /dev/tty lxc.cgroup.devices.allow = c 5:0 rwm ### /dev/console lxc.cgroup.devices.allow = c 5:1 rwm ### /dev/ptmx lxc.cgroup.devices.allow = c 5:2 rwm ### /dev/random lxc.cgroup.devices.allow = c 1:8 rwm ### /dev/urandom lxc.cgroup.devices.allow = c 1:9 rwm ### /dev/pts/* lxc.cgroup.devices.allow = c 136:* rwm ### fuse lxc.cgroup.devices.allow = c 10:229 rwm # Setup the default mounts lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed lxc.mount.entry = /sys/fs/fuse/connections sys/fs/fuse/connections none bind,optional 0 0 # Blacklist some syscalls which are not safe in privileged # containers lxc.seccomp = @LXCTEMPLATECONFIG@/common.seccomp # Lastly, include all the configs from @LXCTEMPLATECONFIG@/common.conf.d/ lxc.include = @LXCTEMPLATECONFIG@/common.conf.d/ lxc-2.0.8/config/templates/ubuntu.lucid.conf.in0000644061062106075000000000007213105116772016402 00000000000000# Ubuntu 10.04 LTS doesn't have /dev/lxc/ lxc.devttydir = lxc-2.0.8/config/templates/centos.common.conf.in0000644061062106075000000000170513105116772016547 00000000000000# This derives from the global common config lxc.include = @LXCTEMPLATECONFIG@/common.conf # Capabilities # Uncomment these if you don't run anything that needs the capability, and # would like the container to run with less privilege. # # Dropping sys_admin disables container root from doing a lot of things # that could be bad like re-mounting lxc fstab entries rw for example, # but also disables some useful things like being able to nfs mount, and # things that are already namespaced with ns_capable() kernel checks, like # hostname(1). # lxc.cap.drop = sys_admin # lxc.cap.drop = net_raw # breaks dhcp/ping # lxc.cap.drop = setgid # breaks login (initgroups/setgroups) # lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd) # lxc.cap.drop = setuid # breaks sshd,nfs statd # lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed) # lxc.cap.drop = audit_write lxc.cap.drop = sys_nice sys_pacct sys_rawio lxc-2.0.8/config/templates/gentoo.common.conf.in0000644061062106075000000000153713105116772016552 00000000000000# This derives from the global common config lxc.include = @LXCTEMPLATECONFIG@/common.conf # Gentoo common default configuration # This is the most feature-full container configuration # But security is not the goal. # Looking for more security, see gentoo.moresecure.conf # Doesn't support consoles in /dev/lxc/ lxc.devttydir = # Extra cgroup device access ## rtc lxc.cgroup.devices.allow = c 254:0 rm ## tun lxc.cgroup.devices.allow = c 10:200 rwm ## hpet lxc.cgroup.devices.allow = c 10:228 rwm ## kvm 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 lxc-2.0.8/config/templates/ubuntu-cloud.common.conf.in0000644061062106075000000000022113105116772017672 00000000000000# This derives from the main Ubuntu config lxc.include = @LXCTEMPLATECONFIG@/ubuntu.common.conf lxc.hook.clone = @LXCHOOKDIR@/ubuntu-cloud-prep lxc-2.0.8/config/templates/opensuse.userns.conf.in0000644061062106075000000000013313105116772017136 00000000000000# This derives from the global userns config lxc.include = @LXCTEMPLATECONFIG@/userns.conf lxc-2.0.8/config/templates/alpine.userns.conf.in0000644061062106075000000000013413105116772016546 00000000000000# This derives from the global userns config. lxc.include = @LXCTEMPLATECONFIG@/userns.conf lxc-2.0.8/config/templates/fedora.userns.conf.in0000644061062106075000000000013313105116772016535 00000000000000# This derives from the global userns config lxc.include = @LXCTEMPLATECONFIG@/userns.conf lxc-2.0.8/config/templates/ubuntu.common.conf.in0000644061062106075000000000267113105116772016601 00000000000000# This derives from the global common config lxc.include = @LXCTEMPLATECONFIG@/common.conf # Default mount entries lxc.mount.entry = /sys/kernel/debug sys/kernel/debug none bind,optional 0 0 lxc.mount.entry = /sys/kernel/security sys/kernel/security none bind,optional 0 0 lxc.mount.entry = /sys/fs/pstore sys/fs/pstore none bind,optional 0 0 lxc.mount.entry = mqueue dev/mqueue mqueue rw,relatime,create=dir,optional 0 0 # When using LXC with apparmor, the container will be confined by default. # If you wish for it to instead run unconfined, copy the following line # (uncommented) to the container's configuration file. #lxc.aa_profile = unconfined # Uncomment the following line to autodetect squid-deb-proxy configuration on the # host and forward it to the guest at start time. #lxc.hook.pre-start = /usr/share/lxc/hooks/squid-deb-proxy-client # If you wish to allow mounting block filesystems, then use the following # line instead, and make sure to grant access to the block device and/or loop # devices below in lxc.cgroup.devices.allow. #lxc.aa_profile = lxc-container-default-with-mounting # Extra cgroup device access ## rtc lxc.cgroup.devices.allow = c 254:0 rm ## tun lxc.cgroup.devices.allow = c 10:200 rwm ## hpet lxc.cgroup.devices.allow = c 10:228 rwm ## kvm 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 lxc-2.0.8/config/templates/slackware.userns.conf.in0000644061062106075000000000013313105116772017251 00000000000000# This derives from the global userns config lxc.include = @LXCTEMPLATECONFIG@/userns.conf lxc-2.0.8/config/ltversion.m40000644061062106075000000000127312756047127013012 00000000000000# ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # @configure_input@ # serial 4179 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.6]) m4_define([LT_PACKAGE_REVISION], [2.4.6]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.6' macro_revision='2.4.6' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) lxc-2.0.8/config/depcomp0000755061062106075000000005601613105116776012101 00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2013-05-30.07; # UTC # Copyright (C) 1999-2014 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # Get the directory component of the given path, and save it in the # global variables '$dir'. Note that this directory component will # be either empty or ending with a '/' character. This is deliberate. set_dir_from () { case $1 in */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; *) dir=;; esac } # Get the suffix-stripped basename of the given path, and save it the # global variable '$base'. set_base_from () { base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` } # If no dependency file was actually created by the compiler invocation, # we still have to create a dummy depfile, to avoid errors with the # Makefile "include basename.Plo" scheme. make_dummy_depfile () { echo "#dummy" > "$depfile" } # Factor out some common post-processing of the generated depfile. # Requires the auxiliary global variable '$tmpdepfile' to be set. aix_post_process_depfile () { # If the compiler actually managed to produce a dependency file, # post-process it. if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependency.h'. # Do two passes, one to just change these to # $object: dependency.h # and one to simply output # dependency.h: # which is needed to avoid the deleted-header problem. { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" } > "$depfile" rm -f "$tmpdepfile" else make_dummy_depfile fi } # A tabulation character. tab=' ' # A newline character. nl=' ' # Character ranges might be problematic outside the C locale. # These definitions help. upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz digits=0123456789 alpha=${upper}${lower} if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Avoid interferences from the environment. gccflag= dashmflag= # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The second -e expression handles DOS-style file names with drive # letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done aix_post_process_depfile ;; tcc) # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 # FIXME: That version still under development at the moment of writing. # Make that this statement remains true also for stable, released # versions. # It will wrap lines (doesn't matter whether long or short) with a # trailing '\', as in: # # foo.o : \ # foo.c \ # foo.h \ # # It will put a trailing '\' even on the last line, and will use leading # spaces rather than leading tabs (at least since its commit 0394caf7 # "Emit spaces for -MD"). "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. # We have to change lines of the first kind to '$object: \'. sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" # And for each line of the second kind, we have to emit a 'dep.h:' # dummy dependency, to avoid the deleted-header problem. sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... set_dir_from "$object" # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. set_base_from "$source" tmpdepfile=$base.d # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir=$base.d-lock trap " echo '$0: caught signal, cleaning up...' >&2 rmdir '$lockdir' exit 1 " 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0; do # mkdir is a portable test-and-set. if mkdir "$lockdir" 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rmdir "$lockdir" break else # If the lock is being held by a different process, wait # until the winning process is done or we timeout. while test -d "$lockdir" && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then # Libtool generates 2 separate objects for the 2 libraries. These # two compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir$base.o.d # libtool 1.5 tmpdepfile2=$dir.libs/$base.o.d # Likewise. tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d "$@" -MD fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done # Same post-processing that is required for AIX mode. aix_post_process_depfile ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" echo >> "$depfile" # make sure the fragment doesn't end with a backslash rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this sed invocation # correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process the last invocation # correctly. Breaking it into two sed invocations is a workaround. sed '1,2d' "$tmpdepfile" \ | tr ' ' "$nl" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E \ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: lxc-2.0.8/config/config.sub0000755061062106075000000010676313105116775012513 00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2016 Free Software Foundation, Inc. timestamp='2016-11-04' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2016 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ kopensolaris*-gnu* | cloudabi*-eabi* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ | ba \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ | e2k | epiphany \ | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | k1om \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa32r6 | mipsisa32r6el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64r6 | mipsisa64r6el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 | or1k | or1knd | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pru \ | pyramid \ | riscv32 | riscv64 \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | visium \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; leon|leon[3-9]) basic_machine=sparc-$basic_machine ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | ba-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | e2k-* | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | k1om-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa32r6-* | mipsisa32r6el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64r6-* | mipsisa64r6el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | or1k*-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pru-* \ | pyramid-* \ | riscv32-* | riscv64-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | visium-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; asmjs) basic_machine=asmjs-unknown ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; e500v[12]) basic_machine=powerpc-unknown os=$os"spe" ;; e500v[12]-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` os=$os"spe" ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; leon-*|leon[3-9]-*) basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze*) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i686-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; moxiebox) basic_machine=moxie-unknown os=-moxiebox ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i686-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos | rdos64) basic_machine=x86_64-pc os=-rdos ;; rdos32) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* | -cloudabi* | -sortix* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ | -onefs* | -tirtos* | -phoenix* | -fuchsia*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -ios) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; c8051-*) os=-elf ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: lxc-2.0.8/config/init/0000755061062106075000000000000013105117015011522 500000000000000lxc-2.0.8/config/init/sysvinit/0000755061062106075000000000000013105117015013412 500000000000000lxc-2.0.8/config/init/sysvinit/Makefile.am0000644061062106075000000000133413105116772015400 00000000000000EXTRA_DIST = lxc-containers.in lxc-net.in if INIT_SCRIPT_SYSV # If we're installing for sysv init, install the helper scripts # directly to the rc directory under the appropriate name. if HAVE_DEBIAN initdir = "init.d" else initdir = "rc.d/init.d" endif install-sysvinit: lxc-containers lxc-net $(MKDIR_P) $(DESTDIR)$(sysconfdir)/$(initdir) $(INSTALL_SCRIPT) lxc-containers $(DESTDIR)$(sysconfdir)/$(initdir)/lxc $(INSTALL_SCRIPT) lxc-net $(DESTDIR)$(sysconfdir)/$(initdir)/lxc-net uninstall-sysvinit: rm -f $(DESTDIR)$(sysconfdir)/$(initdir)/lxc rm -f $(DESTDIR)$(sysconfdir)/$(initdir)/lxc-net rmdir $(DESTDIR)$(sysconfdir)/$(initdir) || : install-data-local: install-sysvinit uninstall-local: uninstall-sysvinit endif lxc-2.0.8/config/init/sysvinit/lxc-containers.in0000644061062106075000000000247313105116772016632 00000000000000#!/bin/sh # # lxc Start/Stop LXC autoboot containers # # chkconfig: 345 99 01 # description: Starts/Stops all LXC containers configured for autostart. # ### BEGIN INIT INFO # Provides: lxc # Required-Start: $syslog $remote_fs # Required-Stop: $syslog $remote_fs # Should-Start: cgroupfs-mount # Should-Stop: cgroupfs-mount # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Bring up/down LXC autostart containers # Description: Bring up/down LXC autostart containers ### END INIT INFO # To be replaced by LSB functions, if they can be found # Defined here for distributions that don't have log_daemon_msg log_daemon_msg () { echo $@ } # Try to source LSB init functions to define LSB log_* functions. test ! -r /lib/lsb/init-functions || . /lib/lsb/init-functions start() { # Setup host /dev for autodev containers. log_daemon_msg "Starting LXC autoboot containers: " @LIBEXECDIR@/lxc/lxc-containers start } stop() { log_daemon_msg "Stopping LXC containers: " @LIBEXECDIR@/lxc/lxc-containers stop } # See how we were called. case "$1" in start) start ;; stop) stop ;; restart|reload|force-reload) $0 stop $0 start ;; *) echo "Usage: $0 {start|stop|restart|reload|force-reload}" exit 2 ;; esac exit $? lxc-2.0.8/config/init/sysvinit/lxc-net.in0000644061062106075000000000227313105116772015251 00000000000000#!/bin/sh - # # lxc-net Start/Stop LXC Networking # # chkconfig: 345 98 01 # description: Starts/Stops LXC Network Bridge # ### BEGIN INIT INFO # Provides: lxc-net # Required-Start: $syslog $remote_fs # Required-Stop: $syslog $remote_fs # Should-Start: # Should-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Bring up/down LXC Network Bridge # Description: Bring up/down LXC Network Bridge ### END INIT INFO # To be replaced by LSB functions, if they can be found # Defined here for distributions that don't have log_daemon_msg log_daemon_msg () { echo $@ } # Try to source LSB init functions to define LSB log_* functions. test ! -r /lib/lsb/init-functions || . /lib/lsb/init-functions start() { log_daemon_msg "Starting LXC network bridge: " @LIBEXECDIR@/lxc/lxc-net start } stop() { log_daemon_msg "Stopping LXC network bridge: " @LIBEXECDIR@/lxc/lxc-net stop } # See how we were called. case "$1" in start) start ;; stop) stop ;; restart|reload|force-reload) $0 stop $0 start ;; *) echo "Usage: $0 {start|stop|restart|reload|force-reload}" exit 2 ;; esac exit $? lxc-2.0.8/config/init/sysvinit/Makefile.in0000644061062106075000000003670713105116775015430 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = config/init/sysvinit ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/acinclude.m4 \ $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/tls.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h CONFIG_CLEAN_FILES = lxc-containers lxc-net CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/lxc-containers.in \ $(srcdir)/lxc-net.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APPARMOR_LIBS = @APPARMOR_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BINDIR = @BINDIR@ CAP_LIBS = @CAP_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CGMANAGER_CFLAGS = @CGMANAGER_CFLAGS@ CGMANAGER_LIBS = @CGMANAGER_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIR = @DATADIR@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFAULT_CGROUP_PATTERN = @DEFAULT_CGROUP_PATTERN@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOCDIR = @DOCDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ HAVE_DOXYGEN = @HAVE_DOXYGEN@ INCLUDEDIR = @INCLUDEDIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDIR = @LIBDIR@ LIBEXECDIR = @LIBEXECDIR@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCALSTATEDIR = @LOCALSTATEDIR@ LOGPATH = @LOGPATH@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBDIR = @LUA_LIBDIR@ LUA_LIBS = @LUA_LIBS@ LUA_SHAREDIR = @LUA_SHAREDIR@ LUA_VERSION = @LUA_VERSION@ LXCBINHOOKDIR = @LXCBINHOOKDIR@ LXCHOOKDIR = @LXCHOOKDIR@ LXCINITDIR = @LXCINITDIR@ LXCPATH = @LXCPATH@ LXCROOTFSMOUNT = @LXCROOTFSMOUNT@ LXCTEMPLATECONFIG = @LXCTEMPLATECONFIG@ LXCTEMPLATEDIR = @LXCTEMPLATEDIR@ LXC_ABI = @LXC_ABI@ LXC_ABI_MAJOR = @LXC_ABI_MAJOR@ LXC_ABI_MICRO = @LXC_ABI_MICRO@ LXC_ABI_MINOR = @LXC_ABI_MINOR@ LXC_DEFAULT_CONFIG = @LXC_DEFAULT_CONFIG@ LXC_DEVEL = @LXC_DEVEL@ LXC_DISTRO_SYSCONF = @LXC_DISTRO_SYSCONF@ LXC_GENERATE_DATE = @LXC_GENERATE_DATE@ LXC_GLOBAL_CONF = @LXC_GLOBAL_CONF@ LXC_USERNIC_CONF = @LXC_USERNIC_CONF@ LXC_USERNIC_DB = @LXC_USERNIC_DB@ LXC_VERSION = @LXC_VERSION@ LXC_VERSION_BASE = @LXC_VERSION_BASE@ LXC_VERSION_BETA = @LXC_VERSION_BETA@ LXC_VERSION_MAJOR = @LXC_VERSION_MAJOR@ LXC_VERSION_MICRO = @LXC_VERSION_MICRO@ LXC_VERSION_MINOR = @LXC_VERSION_MINOR@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NIH_CFLAGS = @NIH_CFLAGS@ NIH_DBUS_CFLAGS = @NIH_DBUS_CFLAGS@ NIH_DBUS_LIBS = @NIH_DBUS_LIBS@ NIH_LIBS = @NIH_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PREFIX = @PREFIX@ PYTHON = @PYTHON@ PYTHONDEV_CFLAGS = @PYTHONDEV_CFLAGS@ PYTHONDEV_LIBS = @PYTHONDEV_LIBS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RUNTIME_PATH = @RUNTIME_PATH@ SBINDIR = @SBINDIR@ SECCOMP_CFLAGS = @SECCOMP_CFLAGS@ SECCOMP_LIBS = @SECCOMP_LIBS@ SED = @SED@ SELINUX_LIBS = @SELINUX_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SYSCONFDIR = @SYSCONFDIR@ SYSTEMD_UNIT_DIR = @SYSTEMD_UNIT_DIR@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bashcompdir = @bashcompdir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ db2xman = @db2xman@ docdir = @docdir@ docdtd = @docdtd@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = lxc-containers.in lxc-net.in @HAVE_DEBIAN_FALSE@@INIT_SCRIPT_SYSV_TRUE@initdir = "rc.d/init.d" # If we're installing for sysv init, install the helper scripts # directly to the rc directory under the appropriate name. @HAVE_DEBIAN_TRUE@@INIT_SCRIPT_SYSV_TRUE@initdir = "init.d" all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu config/init/sysvinit/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu config/init/sysvinit/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): lxc-containers: $(top_builddir)/config.status $(srcdir)/lxc-containers.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ lxc-net: $(top_builddir)/config.status $(srcdir)/lxc-net.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." @INIT_SCRIPT_SYSV_FALSE@uninstall-local: @INIT_SCRIPT_SYSV_FALSE@install-data-local: clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-data-local install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-local .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am \ install-data-local install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am uninstall-local .PRECIOUS: Makefile @INIT_SCRIPT_SYSV_TRUE@install-sysvinit: lxc-containers lxc-net @INIT_SCRIPT_SYSV_TRUE@ $(MKDIR_P) $(DESTDIR)$(sysconfdir)/$(initdir) @INIT_SCRIPT_SYSV_TRUE@ $(INSTALL_SCRIPT) lxc-containers $(DESTDIR)$(sysconfdir)/$(initdir)/lxc @INIT_SCRIPT_SYSV_TRUE@ $(INSTALL_SCRIPT) lxc-net $(DESTDIR)$(sysconfdir)/$(initdir)/lxc-net @INIT_SCRIPT_SYSV_TRUE@uninstall-sysvinit: @INIT_SCRIPT_SYSV_TRUE@ rm -f $(DESTDIR)$(sysconfdir)/$(initdir)/lxc @INIT_SCRIPT_SYSV_TRUE@ rm -f $(DESTDIR)$(sysconfdir)/$(initdir)/lxc-net @INIT_SCRIPT_SYSV_TRUE@ rmdir $(DESTDIR)$(sysconfdir)/$(initdir) || : @INIT_SCRIPT_SYSV_TRUE@install-data-local: install-sysvinit @INIT_SCRIPT_SYSV_TRUE@uninstall-local: uninstall-sysvinit # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lxc-2.0.8/config/init/Makefile.am0000644061062106075000000000005213105116772013504 00000000000000SUBDIRS = common systemd sysvinit upstart lxc-2.0.8/config/init/upstart/0000755061062106075000000000000013105117015013224 500000000000000lxc-2.0.8/config/init/upstart/lxc-instance.conf0000644061062106075000000000067613105116772016425 00000000000000description "lxc instance" author "Christian Kampka " stop on stopping lxc # wait for 120 seconds for container to shutdown before killing it kill timeout 120 # send SIGPWR to container to trigger a shutdown (see lxc-shutdown(1)) kill signal SIGPWR instance $NAME usage "NAME=name of LXC instance" pre-start script lxc-wait -s RUNNING -n $NAME -t 0 && { stop; exit 0; } || true end script exec lxc-start -F -n $NAME lxc-2.0.8/config/init/upstart/lxc-net.conf.in0000644061062106075000000000032413105116772016002 00000000000000description "lxc network" author "Serge Hallyn " start on starting lxc stop on stopped lxc pre-start exec @LIBEXECDIR@/lxc/lxc-net start post-stop exec @LIBEXECDIR@/lxc/lxc-net stop lxc-2.0.8/config/init/upstart/lxc.conf0000644061062106075000000000416513105117006014607 00000000000000description "lxc" author "Serge Hallyn " start on runlevel [2345] stop on starting rc RUNLEVEL=[016] env LXC_AUTO="false" # These can be overridden in /etc/default/lxc # BOOTGROUPS - What groups should start on bootup? # Comma separated list of groups. # Leading comma, trailing comma or embedded double # comma indicates when the NULL group should be run. # Example (default): boot the onboot group first then the NULL group env BOOTGROUPS="onboot," # SHUTDOWNDELAY - Wait time for a container to shut down. # Container shutdown can result in lengthy system # shutdown times. Even 5 seconds per container can be # too long. env SHUTDOWNDELAY=5 # OPTIONS can be used for anything else. # If you want to boot everything then # options can be "-a" or "-a -A". env OPTIONS= # STOPOPTS are stop options. The can be used for anything else to stop. # If you want to kill containers fast, use -k env STOPOPTS="-a -A -s" pre-start script [ -f /etc/default/lxc ] && . /etc/default/lxc # don't load profiles if mount mediation is not supported SYSF=/sys/kernel/security/apparmor/features/mount/mask if [ -f $SYSF ]; then if [ -x /lib/apparmor/profile-load ]; then /lib/apparmor/profile-load usr.bin.lxc-start /lib/apparmor/profile-load lxc-containers elif [ -x /lib/init/apparmor-profile-load ]; then /lib/init/apparmor-profile-load usr.bin.lxc-start /lib/init/apparmor-profile-load lxc-containers fi fi [ "x$LXC_AUTO" = "xtrue" ] || exit 0 if [ -n "$BOOTGROUPS" ] then BOOTGROUPS="-g $BOOTGROUPS" fi # Process the "onboot" group first then the NULL group. lxc-autostart -L $OPTIONS $BOOTGROUPS | while read line; do set -- $line (start lxc-instance NAME=$1 && sleep $2) || true done end script # The stop is serialized and can take excessive time. We need to avoid # delaying the system shutdown / reboot as much as we can since it's not # parallelized... Even 5 second timout may be too long. post-stop script [ -f /etc/default/lxc ] && . /etc/default/lxc if [ -n "$SHUTDOWNDELAY" ] then SHUTDOWNDELAY="-t $SHUTDOWNDELAY" fi lxc-autostart $STOPOPTS $SHUTDOWNDELAY || true end script lxc-2.0.8/config/init/upstart/lxc.conf.in0000644061062106075000000000416513105116772015225 00000000000000description "lxc" author "Serge Hallyn " start on runlevel [2345] stop on starting rc RUNLEVEL=[016] env LXC_AUTO="false" # These can be overridden in /etc/default/lxc # BOOTGROUPS - What groups should start on bootup? # Comma separated list of groups. # Leading comma, trailing comma or embedded double # comma indicates when the NULL group should be run. # Example (default): boot the onboot group first then the NULL group env BOOTGROUPS="onboot," # SHUTDOWNDELAY - Wait time for a container to shut down. # Container shutdown can result in lengthy system # shutdown times. Even 5 seconds per container can be # too long. env SHUTDOWNDELAY=5 # OPTIONS can be used for anything else. # If you want to boot everything then # options can be "-a" or "-a -A". env OPTIONS= # STOPOPTS are stop options. The can be used for anything else to stop. # If you want to kill containers fast, use -k env STOPOPTS="-a -A -s" pre-start script [ -f /etc/default/lxc ] && . /etc/default/lxc # don't load profiles if mount mediation is not supported SYSF=/sys/kernel/security/apparmor/features/mount/mask if [ -f $SYSF ]; then if [ -x /lib/apparmor/profile-load ]; then /lib/apparmor/profile-load usr.bin.lxc-start /lib/apparmor/profile-load lxc-containers elif [ -x /lib/init/apparmor-profile-load ]; then /lib/init/apparmor-profile-load usr.bin.lxc-start /lib/init/apparmor-profile-load lxc-containers fi fi [ "x$LXC_AUTO" = "xtrue" ] || exit 0 if [ -n "$BOOTGROUPS" ] then BOOTGROUPS="-g $BOOTGROUPS" fi # Process the "onboot" group first then the NULL group. lxc-autostart -L $OPTIONS $BOOTGROUPS | while read line; do set -- $line (start lxc-instance NAME=$1 && sleep $2) || true done end script # The stop is serialized and can take excessive time. We need to avoid # delaying the system shutdown / reboot as much as we can since it's not # parallelized... Even 5 second timout may be too long. post-stop script [ -f /etc/default/lxc ] && . /etc/default/lxc if [ -n "$SHUTDOWNDELAY" ] then SHUTDOWNDELAY="-t $SHUTDOWNDELAY" fi lxc-autostart $STOPOPTS $SHUTDOWNDELAY || true end script lxc-2.0.8/config/init/upstart/Makefile.in0000644061062106075000000003662213105116775015236 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = config/init/upstart ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/acinclude.m4 \ $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/tls.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h CONFIG_CLEAN_FILES = lxc.conf lxc-net.conf CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/lxc-net.conf.in \ $(srcdir)/lxc.conf.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APPARMOR_LIBS = @APPARMOR_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BINDIR = @BINDIR@ CAP_LIBS = @CAP_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CGMANAGER_CFLAGS = @CGMANAGER_CFLAGS@ CGMANAGER_LIBS = @CGMANAGER_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIR = @DATADIR@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFAULT_CGROUP_PATTERN = @DEFAULT_CGROUP_PATTERN@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOCDIR = @DOCDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ HAVE_DOXYGEN = @HAVE_DOXYGEN@ INCLUDEDIR = @INCLUDEDIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDIR = @LIBDIR@ LIBEXECDIR = @LIBEXECDIR@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCALSTATEDIR = @LOCALSTATEDIR@ LOGPATH = @LOGPATH@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBDIR = @LUA_LIBDIR@ LUA_LIBS = @LUA_LIBS@ LUA_SHAREDIR = @LUA_SHAREDIR@ LUA_VERSION = @LUA_VERSION@ LXCBINHOOKDIR = @LXCBINHOOKDIR@ LXCHOOKDIR = @LXCHOOKDIR@ LXCINITDIR = @LXCINITDIR@ LXCPATH = @LXCPATH@ LXCROOTFSMOUNT = @LXCROOTFSMOUNT@ LXCTEMPLATECONFIG = @LXCTEMPLATECONFIG@ LXCTEMPLATEDIR = @LXCTEMPLATEDIR@ LXC_ABI = @LXC_ABI@ LXC_ABI_MAJOR = @LXC_ABI_MAJOR@ LXC_ABI_MICRO = @LXC_ABI_MICRO@ LXC_ABI_MINOR = @LXC_ABI_MINOR@ LXC_DEFAULT_CONFIG = @LXC_DEFAULT_CONFIG@ LXC_DEVEL = @LXC_DEVEL@ LXC_DISTRO_SYSCONF = @LXC_DISTRO_SYSCONF@ LXC_GENERATE_DATE = @LXC_GENERATE_DATE@ LXC_GLOBAL_CONF = @LXC_GLOBAL_CONF@ LXC_USERNIC_CONF = @LXC_USERNIC_CONF@ LXC_USERNIC_DB = @LXC_USERNIC_DB@ LXC_VERSION = @LXC_VERSION@ LXC_VERSION_BASE = @LXC_VERSION_BASE@ LXC_VERSION_BETA = @LXC_VERSION_BETA@ LXC_VERSION_MAJOR = @LXC_VERSION_MAJOR@ LXC_VERSION_MICRO = @LXC_VERSION_MICRO@ LXC_VERSION_MINOR = @LXC_VERSION_MINOR@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NIH_CFLAGS = @NIH_CFLAGS@ NIH_DBUS_CFLAGS = @NIH_DBUS_CFLAGS@ NIH_DBUS_LIBS = @NIH_DBUS_LIBS@ NIH_LIBS = @NIH_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PREFIX = @PREFIX@ PYTHON = @PYTHON@ PYTHONDEV_CFLAGS = @PYTHONDEV_CFLAGS@ PYTHONDEV_LIBS = @PYTHONDEV_LIBS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RUNTIME_PATH = @RUNTIME_PATH@ SBINDIR = @SBINDIR@ SECCOMP_CFLAGS = @SECCOMP_CFLAGS@ SECCOMP_LIBS = @SECCOMP_LIBS@ SED = @SED@ SELINUX_LIBS = @SELINUX_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SYSCONFDIR = @SYSCONFDIR@ SYSTEMD_UNIT_DIR = @SYSTEMD_UNIT_DIR@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bashcompdir = @bashcompdir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ db2xman = @db2xman@ docdir = @docdir@ docdtd = @docdtd@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = lxc.conf lxc-instance.conf lxc-net.conf.in all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu config/init/upstart/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu config/init/upstart/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): lxc.conf: $(top_builddir)/config.status $(srcdir)/lxc.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ lxc-net.conf: $(top_builddir)/config.status $(srcdir)/lxc-net.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." @INIT_SCRIPT_UPSTART_FALSE@install-data-local: @INIT_SCRIPT_UPSTART_FALSE@uninstall-local: clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-data-local install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-local .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am \ install-data-local install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am uninstall-local .PRECIOUS: Makefile @INIT_SCRIPT_UPSTART_TRUE@install-upstart: lxc.conf lxc-instance.conf lxc-net.conf @INIT_SCRIPT_UPSTART_TRUE@ $(MKDIR_P) $(DESTDIR)$(sysconfdir)/init/ @INIT_SCRIPT_UPSTART_TRUE@ $(INSTALL_DATA) lxc.conf $(DESTDIR)$(sysconfdir)/init/ @INIT_SCRIPT_UPSTART_TRUE@ $(INSTALL_DATA) $(srcdir)/lxc-instance.conf $(DESTDIR)$(sysconfdir)/init/ @INIT_SCRIPT_UPSTART_TRUE@ $(INSTALL_DATA) lxc-net.conf $(DESTDIR)$(sysconfdir)/init/ @INIT_SCRIPT_UPSTART_TRUE@uninstall-upstart: @INIT_SCRIPT_UPSTART_TRUE@ rm -f $(DESTDIR)$(sysconfdir)/init/lxc.conf @INIT_SCRIPT_UPSTART_TRUE@ rm -f $(DESTDIR)$(sysconfdir)/init/lxc-instance.conf @INIT_SCRIPT_UPSTART_TRUE@ rm -f $(DESTDIR)$(sysconfdir)/init/lxc-net.conf @INIT_SCRIPT_UPSTART_TRUE@ rmdir $(DESTDIR)$(sysconfdir)/init || : @INIT_SCRIPT_UPSTART_TRUE@install-data-local: install-upstart @INIT_SCRIPT_UPSTART_TRUE@uninstall-local: uninstall-upstart # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lxc-2.0.8/config/init/upstart/Makefile.am0000644061062106075000000000122113105116772015205 00000000000000EXTRA_DIST = lxc.conf lxc-instance.conf lxc-net.conf.in if INIT_SCRIPT_UPSTART install-upstart: lxc.conf lxc-instance.conf lxc-net.conf $(MKDIR_P) $(DESTDIR)$(sysconfdir)/init/ $(INSTALL_DATA) lxc.conf $(DESTDIR)$(sysconfdir)/init/ $(INSTALL_DATA) $(srcdir)/lxc-instance.conf $(DESTDIR)$(sysconfdir)/init/ $(INSTALL_DATA) lxc-net.conf $(DESTDIR)$(sysconfdir)/init/ uninstall-upstart: rm -f $(DESTDIR)$(sysconfdir)/init/lxc.conf rm -f $(DESTDIR)$(sysconfdir)/init/lxc-instance.conf rm -f $(DESTDIR)$(sysconfdir)/init/lxc-net.conf rmdir $(DESTDIR)$(sysconfdir)/init || : install-data-local: install-upstart uninstall-local: uninstall-upstart endif lxc-2.0.8/config/init/systemd/0000755061062106075000000000000013105117015013212 500000000000000lxc-2.0.8/config/init/systemd/Makefile.am0000644061062106075000000000131213105116772015174 00000000000000EXTRA_DIST = \ lxc-apparmor-load \ lxc.service.in \ lxc@.service.in \ lxc-net.service.in if INIT_SCRIPT_SYSTEMD BUILT_SOURCES = lxc.service lxc@.service lxc-net.service install-systemd: lxc.service lxc@.service lxc-net.service lxc-apparmor-load $(MKDIR_P) $(DESTDIR)$(SYSTEMD_UNIT_DIR) $(INSTALL_DATA) lxc.service lxc@.service lxc-net.service $(DESTDIR)$(SYSTEMD_UNIT_DIR)/ uninstall-systemd: rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/lxc.service rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/lxc@.service rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/lxc-net.service rmdir $(DESTDIR)$(SYSTEMD_UNIT_DIR) || : pkglibexec_SCRIPTS = lxc-apparmor-load install-data-local: install-systemd uninstall-local: uninstall-systemd endif lxc-2.0.8/config/init/systemd/lxc-net.service.in0000644061062106075000000000037513105116772016511 00000000000000[Unit] Description=LXC network bridge setup After=network-online.target Before=lxc.service [Service] Type=oneshot RemainAfterExit=yes ExecStart=@LIBEXECDIR@/lxc/lxc-net start ExecStop=@LIBEXECDIR@/lxc/lxc-net stop [Install] WantedBy=multi-user.target lxc-2.0.8/config/init/systemd/Makefile.in0000644061062106075000000004542113105116775015221 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = config/init/systemd ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/acinclude.m4 \ $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/tls.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h CONFIG_CLEAN_FILES = lxc.service lxc@.service lxc-net.service CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(pkglibexecdir)" SCRIPTS = $(pkglibexec_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/lxc-net.service.in \ $(srcdir)/lxc.service.in $(srcdir)/lxc@.service.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APPARMOR_LIBS = @APPARMOR_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BINDIR = @BINDIR@ CAP_LIBS = @CAP_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CGMANAGER_CFLAGS = @CGMANAGER_CFLAGS@ CGMANAGER_LIBS = @CGMANAGER_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIR = @DATADIR@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFAULT_CGROUP_PATTERN = @DEFAULT_CGROUP_PATTERN@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOCDIR = @DOCDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ HAVE_DOXYGEN = @HAVE_DOXYGEN@ INCLUDEDIR = @INCLUDEDIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDIR = @LIBDIR@ LIBEXECDIR = @LIBEXECDIR@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCALSTATEDIR = @LOCALSTATEDIR@ LOGPATH = @LOGPATH@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBDIR = @LUA_LIBDIR@ LUA_LIBS = @LUA_LIBS@ LUA_SHAREDIR = @LUA_SHAREDIR@ LUA_VERSION = @LUA_VERSION@ LXCBINHOOKDIR = @LXCBINHOOKDIR@ LXCHOOKDIR = @LXCHOOKDIR@ LXCINITDIR = @LXCINITDIR@ LXCPATH = @LXCPATH@ LXCROOTFSMOUNT = @LXCROOTFSMOUNT@ LXCTEMPLATECONFIG = @LXCTEMPLATECONFIG@ LXCTEMPLATEDIR = @LXCTEMPLATEDIR@ LXC_ABI = @LXC_ABI@ LXC_ABI_MAJOR = @LXC_ABI_MAJOR@ LXC_ABI_MICRO = @LXC_ABI_MICRO@ LXC_ABI_MINOR = @LXC_ABI_MINOR@ LXC_DEFAULT_CONFIG = @LXC_DEFAULT_CONFIG@ LXC_DEVEL = @LXC_DEVEL@ LXC_DISTRO_SYSCONF = @LXC_DISTRO_SYSCONF@ LXC_GENERATE_DATE = @LXC_GENERATE_DATE@ LXC_GLOBAL_CONF = @LXC_GLOBAL_CONF@ LXC_USERNIC_CONF = @LXC_USERNIC_CONF@ LXC_USERNIC_DB = @LXC_USERNIC_DB@ LXC_VERSION = @LXC_VERSION@ LXC_VERSION_BASE = @LXC_VERSION_BASE@ LXC_VERSION_BETA = @LXC_VERSION_BETA@ LXC_VERSION_MAJOR = @LXC_VERSION_MAJOR@ LXC_VERSION_MICRO = @LXC_VERSION_MICRO@ LXC_VERSION_MINOR = @LXC_VERSION_MINOR@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NIH_CFLAGS = @NIH_CFLAGS@ NIH_DBUS_CFLAGS = @NIH_DBUS_CFLAGS@ NIH_DBUS_LIBS = @NIH_DBUS_LIBS@ NIH_LIBS = @NIH_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PREFIX = @PREFIX@ PYTHON = @PYTHON@ PYTHONDEV_CFLAGS = @PYTHONDEV_CFLAGS@ PYTHONDEV_LIBS = @PYTHONDEV_LIBS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RUNTIME_PATH = @RUNTIME_PATH@ SBINDIR = @SBINDIR@ SECCOMP_CFLAGS = @SECCOMP_CFLAGS@ SECCOMP_LIBS = @SECCOMP_LIBS@ SED = @SED@ SELINUX_LIBS = @SELINUX_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SYSCONFDIR = @SYSCONFDIR@ SYSTEMD_UNIT_DIR = @SYSTEMD_UNIT_DIR@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bashcompdir = @bashcompdir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ db2xman = @db2xman@ docdir = @docdir@ docdtd = @docdtd@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ lxc-apparmor-load \ lxc.service.in \ lxc@.service.in \ lxc-net.service.in @INIT_SCRIPT_SYSTEMD_TRUE@BUILT_SOURCES = lxc.service lxc@.service lxc-net.service @INIT_SCRIPT_SYSTEMD_TRUE@pkglibexec_SCRIPTS = lxc-apparmor-load all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu config/init/systemd/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu config/init/systemd/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): lxc.service: $(top_builddir)/config.status $(srcdir)/lxc.service.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ lxc@.service: $(top_builddir)/config.status $(srcdir)/lxc@.service.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ lxc-net.service: $(top_builddir)/config.status $(srcdir)/lxc-net.service.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-pkglibexecSCRIPTS: $(pkglibexec_SCRIPTS) @$(NORMAL_INSTALL) @list='$(pkglibexec_SCRIPTS)'; test -n "$(pkglibexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkglibexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibexecdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(pkglibexecdir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(pkglibexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-pkglibexecSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(pkglibexec_SCRIPTS)'; test -n "$(pkglibexecdir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(pkglibexecdir)'; $(am__uninstall_files_from_dir) mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(SCRIPTS) installdirs: for dir in "$(DESTDIR)$(pkglibexecdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) 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: clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-data-local install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibexecSCRIPTS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-local uninstall-pkglibexecSCRIPTS .MAKE: all check install install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am \ install-data-local install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-pkglibexecSCRIPTS install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags-am uninstall uninstall-am uninstall-local \ uninstall-pkglibexecSCRIPTS .PRECIOUS: Makefile @INIT_SCRIPT_SYSTEMD_TRUE@install-systemd: lxc.service lxc@.service lxc-net.service lxc-apparmor-load @INIT_SCRIPT_SYSTEMD_TRUE@ $(MKDIR_P) $(DESTDIR)$(SYSTEMD_UNIT_DIR) @INIT_SCRIPT_SYSTEMD_TRUE@ $(INSTALL_DATA) lxc.service lxc@.service lxc-net.service $(DESTDIR)$(SYSTEMD_UNIT_DIR)/ @INIT_SCRIPT_SYSTEMD_TRUE@uninstall-systemd: @INIT_SCRIPT_SYSTEMD_TRUE@ rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/lxc.service @INIT_SCRIPT_SYSTEMD_TRUE@ rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/lxc@.service @INIT_SCRIPT_SYSTEMD_TRUE@ rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/lxc-net.service @INIT_SCRIPT_SYSTEMD_TRUE@ rmdir $(DESTDIR)$(SYSTEMD_UNIT_DIR) || : @INIT_SCRIPT_SYSTEMD_TRUE@install-data-local: install-systemd @INIT_SCRIPT_SYSTEMD_TRUE@uninstall-local: uninstall-systemd # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lxc-2.0.8/config/init/systemd/lxc-apparmor-load0000755061062106075000000000101113105116772016404 00000000000000#!/bin/sh # lxc-apparmor-load: Load AppArmor profiles, if supported by the system set -eu # don't load profiles if mount mediation is not supported SYSF=/sys/kernel/security/apparmor/features/mount/mask if [ -f $SYSF ]; then if [ -x /lib/apparmor/profile-load ]; then /lib/apparmor/profile-load usr.bin.lxc-start /lib/apparmor/profile-load lxc-containers elif [ -x /lib/init/apparmor-profile-load ]; then /lib/init/apparmor-profile-load usr.bin.lxc-start /lib/init/apparmor-profile-load lxc-containers fi fi lxc-2.0.8/config/init/systemd/lxc@.service.in0000644061062106075000000000064713105116772016027 00000000000000[Unit] Description=LXC Container: %i # This pulls in apparmor, dev-setup, lxc-net After=lxc.service Wants=lxc.service Documentation=man:lxc-start man:lxc [Service] Type=simple KillMode=mixed KillSignal=SIGPWR TimeoutStopSec=120s ExecStart=@BINDIR@/lxc-start -F -n %i # Environment=BOOTUP=serial # Environment=CONSOLETYPE=serial Delegate=yes StandardOutput=syslog StandardError=syslog [Install] WantedBy=multi-user.target lxc-2.0.8/config/init/systemd/lxc.service.in0000644061062106075000000000077213105116772015726 00000000000000[Unit] Description=LXC Container Initialization and Autoboot Code After=network.target lxc-net.service Wants=lxc-net.service Documentation=man:lxc-autostart man:lxc [Service] Type=oneshot RemainAfterExit=yes ExecStartPre=@LIBEXECDIR@/lxc/lxc-apparmor-load ExecStart=@LIBEXECDIR@/lxc/lxc-containers start ExecStop=@LIBEXECDIR@/lxc/lxc-containers stop # Environment=BOOTUP=serial # Environment=CONSOLETYPE=serial Delegate=yes StandardOutput=syslog StandardError=syslog [Install] WantedBy=multi-user.target lxc-2.0.8/config/init/common/0000755061062106075000000000000013105117015013012 500000000000000lxc-2.0.8/config/init/common/lxc-net.in0000644061062106075000000001441713105116772014654 00000000000000#!/bin/sh - distrosysconfdir="@LXC_DISTRO_SYSCONF@" varrun="@RUNTIME_PATH@/lxc" varlib="@LOCALSTATEDIR@/lib" # These can be overridden in @LXC_DISTRO_SYSCONF@/lxc # or in @LXC_DISTRO_SYSCONF@/lxc-net USE_LXC_BRIDGE="true" LXC_BRIDGE="lxcbr0" LXC_BRIDGE_MAC="00:16:3e:00:00:00" LXC_ADDR="10.0.3.1" LXC_NETMASK="255.255.255.0" LXC_NETWORK="10.0.3.0/24" LXC_DHCP_RANGE="10.0.3.2,10.0.3.254" LXC_DHCP_MAX="253" LXC_DHCP_CONFILE="" LXC_DOMAIN="" LXC_IPV6_ADDR="" LXC_IPV6_MASK="" LXC_IPV6_NETWORK="" LXC_IPV6_NAT="false" [ ! -f $distrosysconfdir/lxc ] || . $distrosysconfdir/lxc use_iptables_lock="-w" iptables -w -L -n > /dev/null 2>&1 || use_iptables_lock="" _netmask2cidr () { # Assumes there's no "255." after a non-255 byte in the mask local x=${1##*255.} set -- 0^^^128^192^224^240^248^252^254^ $(( (${#1} - ${#x})*2 )) ${x%%.*} x=${1%%$3*} echo $(( $2 + (${#x}/4) )) } ifdown() { ip addr flush dev $1 ip link set dev $1 down } ifup() { MASK=`_netmask2cidr ${LXC_NETMASK}` CIDR_ADDR="${LXC_ADDR}/${MASK}" ip addr add ${CIDR_ADDR} dev $1 ip link set dev $1 address $LXC_BRIDGE_MAC ip link set dev $1 up } start() { [ "x$USE_LXC_BRIDGE" = "xtrue" ] || { exit 0; } [ ! -f "${varrun}/network_up" ] || { echo "lxc-net is already running"; exit 1; } if [ -d /sys/class/net/${LXC_BRIDGE} ]; then stop force || true fi FAILED=1 cleanup() { set +e if [ "$FAILED" = "1" ]; then echo "Failed to setup lxc-net." >&2 stop force exit 1 fi } trap cleanup EXIT HUP INT TERM set -e # set up the lxc network [ ! -d /sys/class/net/${LXC_BRIDGE} ] && ip link add dev ${LXC_BRIDGE} type bridge echo 1 > /proc/sys/net/ipv4/ip_forward echo 0 > /proc/sys/net/ipv6/conf/${LXC_BRIDGE}/accept_dad || true # if we are run from systemd on a system with selinux enabled, # the mkdir will create /run/lxc as init_var_run_t which dnsmasq # can't write its pid into, so we restorecon it (to var_run_t) if [ ! -d "${varrun}" ]; then mkdir -p "${varrun}" if which restorecon >/dev/null 2>&1; then restorecon "${varrun}" fi fi ifup ${LXC_BRIDGE} ${LXC_ADDR} ${LXC_NETMASK} LXC_IPV6_ARG="" if [ -n "$LXC_IPV6_ADDR" ] && [ -n "$LXC_IPV6_MASK" ] && [ -n "$LXC_IPV6_NETWORK" ]; then echo 1 > /proc/sys/net/ipv6/conf/all/forwarding echo 0 > /proc/sys/net/ipv6/conf/${LXC_BRIDGE}/autoconf ip -6 addr add dev ${LXC_BRIDGE} ${LXC_IPV6_ADDR}/${LXC_IPV6_MASK} if [ "$LXC_IPV6_NAT" = "true" ]; then ip6tables $use_iptables_lock -t nat -A POSTROUTING -s ${LXC_IPV6_NETWORK} ! -d ${LXC_IPV6_NETWORK} -j MASQUERADE fi LXC_IPV6_ARG="--dhcp-range=${LXC_IPV6_ADDR},ra-only --listen-address ${LXC_IPV6_ADDR}" fi iptables $use_iptables_lock -I INPUT -i ${LXC_BRIDGE} -p udp --dport 67 -j ACCEPT iptables $use_iptables_lock -I INPUT -i ${LXC_BRIDGE} -p tcp --dport 67 -j ACCEPT iptables $use_iptables_lock -I INPUT -i ${LXC_BRIDGE} -p udp --dport 53 -j ACCEPT iptables $use_iptables_lock -I INPUT -i ${LXC_BRIDGE} -p tcp --dport 53 -j ACCEPT iptables $use_iptables_lock -I FORWARD -i ${LXC_BRIDGE} -j ACCEPT iptables $use_iptables_lock -I FORWARD -o ${LXC_BRIDGE} -j ACCEPT iptables $use_iptables_lock -t nat -A POSTROUTING -s ${LXC_NETWORK} ! -d ${LXC_NETWORK} -j MASQUERADE iptables $use_iptables_lock -t mangle -A POSTROUTING -o ${LXC_BRIDGE} -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill LXC_DOMAIN_ARG="" if [ -n "$LXC_DOMAIN" ]; then LXC_DOMAIN_ARG="-s $LXC_DOMAIN -S /$LXC_DOMAIN/" fi LXD_DHCP_CONFILE_ARG="" if [ -n "$LXC_DHCP_CONFILE" ]; then LXC_DHCP_CONFILE_ARG="--conf-file=${LXC_DHCP_CONFILE}" fi # https://lists.linuxcontainers.org/pipermail/lxc-devel/2014-October/010561.html for DNSMASQ_USER in lxc-dnsmasq dnsmasq nobody do if getent passwd ${DNSMASQ_USER} >/dev/null; then break fi done dnsmasq $LXC_DHCP_CONFILE_ARG $LXC_DOMAIN_ARG -u ${DNSMASQ_USER} \ --strict-order --bind-interfaces --pid-file="${varrun}"/dnsmasq.pid \ --listen-address ${LXC_ADDR} --dhcp-range ${LXC_DHCP_RANGE} \ --dhcp-lease-max=${LXC_DHCP_MAX} --dhcp-no-override \ --except-interface=lo --interface=${LXC_BRIDGE} \ --dhcp-leasefile="${varlib}"/misc/dnsmasq.${LXC_BRIDGE}.leases \ --dhcp-authoritative $LXC_IPV6_ARG || cleanup touch "${varrun}"/network_up FAILED=0 } stop() { [ "x$USE_LXC_BRIDGE" = "xtrue" ] || { exit 0; } [ -f "${varrun}/network_up" ] || [ "$1" = "force" ] || { echo "lxc-net isn't running"; exit 1; } if [ -d /sys/class/net/${LXC_BRIDGE} ]; then ifdown ${LXC_BRIDGE} iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p udp --dport 67 -j ACCEPT iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p tcp --dport 67 -j ACCEPT iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p udp --dport 53 -j ACCEPT iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p tcp --dport 53 -j ACCEPT iptables $use_iptables_lock -D FORWARD -i ${LXC_BRIDGE} -j ACCEPT iptables $use_iptables_lock -D FORWARD -o ${LXC_BRIDGE} -j ACCEPT iptables $use_iptables_lock -t nat -D POSTROUTING -s ${LXC_NETWORK} ! -d ${LXC_NETWORK} -j MASQUERADE iptables $use_iptables_lock -t mangle -D POSTROUTING -o ${LXC_BRIDGE} -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill if [ "$LXC_IPV6_NAT" = "true" ]; then ip6tables $use_iptables_lock -t nat -D POSTROUTING -s ${LXC_IPV6_NETWORK} ! -d ${LXC_IPV6_NETWORK} -j MASQUERADE fi pid=`cat "${varrun}"/dnsmasq.pid 2>/dev/null` && kill -9 $pid rm -f "${varrun}"/dnsmasq.pid # if $LXC_BRIDGE has attached interfaces, don't destroy the bridge ls /sys/class/net/${LXC_BRIDGE}/brif/* > /dev/null 2>&1 || ip link delete ${LXC_BRIDGE} fi rm -f "${varrun}"/network_up } # See how we were called. case "$1" in start) start ;; stop) stop ;; restart|reload|force-reload) $0 stop $0 start ;; *) echo "Usage: $0 {start|stop|restart|reload|force-reload}" exit 2 esac exit $? lxc-2.0.8/config/init/common/Makefile.in0000644061062106075000000004252713105116775015025 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = config/init/common ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/acinclude.m4 \ $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/tls.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h CONFIG_CLEAN_FILES = lxc-containers lxc-net CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(pkglibexecdir)" SCRIPTS = $(pkglibexec_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/lxc-containers.in \ $(srcdir)/lxc-net.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APPARMOR_LIBS = @APPARMOR_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BINDIR = @BINDIR@ CAP_LIBS = @CAP_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CGMANAGER_CFLAGS = @CGMANAGER_CFLAGS@ CGMANAGER_LIBS = @CGMANAGER_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIR = @DATADIR@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFAULT_CGROUP_PATTERN = @DEFAULT_CGROUP_PATTERN@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOCDIR = @DOCDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ HAVE_DOXYGEN = @HAVE_DOXYGEN@ INCLUDEDIR = @INCLUDEDIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDIR = @LIBDIR@ LIBEXECDIR = @LIBEXECDIR@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCALSTATEDIR = @LOCALSTATEDIR@ LOGPATH = @LOGPATH@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBDIR = @LUA_LIBDIR@ LUA_LIBS = @LUA_LIBS@ LUA_SHAREDIR = @LUA_SHAREDIR@ LUA_VERSION = @LUA_VERSION@ LXCBINHOOKDIR = @LXCBINHOOKDIR@ LXCHOOKDIR = @LXCHOOKDIR@ LXCINITDIR = @LXCINITDIR@ LXCPATH = @LXCPATH@ LXCROOTFSMOUNT = @LXCROOTFSMOUNT@ LXCTEMPLATECONFIG = @LXCTEMPLATECONFIG@ LXCTEMPLATEDIR = @LXCTEMPLATEDIR@ LXC_ABI = @LXC_ABI@ LXC_ABI_MAJOR = @LXC_ABI_MAJOR@ LXC_ABI_MICRO = @LXC_ABI_MICRO@ LXC_ABI_MINOR = @LXC_ABI_MINOR@ LXC_DEFAULT_CONFIG = @LXC_DEFAULT_CONFIG@ LXC_DEVEL = @LXC_DEVEL@ LXC_DISTRO_SYSCONF = @LXC_DISTRO_SYSCONF@ LXC_GENERATE_DATE = @LXC_GENERATE_DATE@ LXC_GLOBAL_CONF = @LXC_GLOBAL_CONF@ LXC_USERNIC_CONF = @LXC_USERNIC_CONF@ LXC_USERNIC_DB = @LXC_USERNIC_DB@ LXC_VERSION = @LXC_VERSION@ LXC_VERSION_BASE = @LXC_VERSION_BASE@ LXC_VERSION_BETA = @LXC_VERSION_BETA@ LXC_VERSION_MAJOR = @LXC_VERSION_MAJOR@ LXC_VERSION_MICRO = @LXC_VERSION_MICRO@ LXC_VERSION_MINOR = @LXC_VERSION_MINOR@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NIH_CFLAGS = @NIH_CFLAGS@ NIH_DBUS_CFLAGS = @NIH_DBUS_CFLAGS@ NIH_DBUS_LIBS = @NIH_DBUS_LIBS@ NIH_LIBS = @NIH_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PREFIX = @PREFIX@ PYTHON = @PYTHON@ PYTHONDEV_CFLAGS = @PYTHONDEV_CFLAGS@ PYTHONDEV_LIBS = @PYTHONDEV_LIBS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RUNTIME_PATH = @RUNTIME_PATH@ SBINDIR = @SBINDIR@ SECCOMP_CFLAGS = @SECCOMP_CFLAGS@ SECCOMP_LIBS = @SECCOMP_LIBS@ SED = @SED@ SELINUX_LIBS = @SELINUX_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SYSCONFDIR = @SYSCONFDIR@ SYSTEMD_UNIT_DIR = @SYSTEMD_UNIT_DIR@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bashcompdir = @bashcompdir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ db2xman = @db2xman@ docdir = @docdir@ docdtd = @docdtd@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = lxc-containers.in lxc-net.in pkglibexec_SCRIPTS = lxc-containers lxc-net all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu config/init/common/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu config/init/common/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): lxc-containers: $(top_builddir)/config.status $(srcdir)/lxc-containers.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ lxc-net: $(top_builddir)/config.status $(srcdir)/lxc-net.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-pkglibexecSCRIPTS: $(pkglibexec_SCRIPTS) @$(NORMAL_INSTALL) @list='$(pkglibexec_SCRIPTS)'; test -n "$(pkglibexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkglibexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibexecdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(pkglibexecdir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(pkglibexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-pkglibexecSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(pkglibexec_SCRIPTS)'; test -n "$(pkglibexecdir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(pkglibexecdir)'; $(am__uninstall_files_from_dir) mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(SCRIPTS) installdirs: for dir in "$(DESTDIR)$(pkglibexecdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibexecSCRIPTS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibexecSCRIPTS .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-pkglibexecSCRIPTS \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am uninstall-pkglibexecSCRIPTS .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lxc-2.0.8/config/init/common/Makefile.am0000644061062106075000000000012613105116772014776 00000000000000EXTRA_DIST = lxc-containers.in lxc-net.in pkglibexec_SCRIPTS = lxc-containers lxc-net lxc-2.0.8/config/init/common/lxc-containers.in0000644061062106075000000000606613105116772016234 00000000000000#!/bin/sh sysconfdir="@SYSCONFDIR@" distrosysconfdir="@LXC_DISTRO_SYSCONF@" bindir="@BINDIR@" localstatedir="@LOCALSTATEDIR@" # These can be overridden in @LXC_DISTRO_SYSCONF@/lxc # Autostart containers? LXC_AUTO="true" # BOOTGROUPS - What groups should start on bootup? # Comma separated list of groups. # Leading comma, trailing comma or embedded double # comma indicates when the NULL group should be run. # Example (default): boot the onboot group first then the NULL group BOOTGROUPS="onboot," # SHUTDOWNDELAY - Wait time for a container to shut down. # Container shutdown can result in lengthy system # shutdown times. Even 5 seconds per container can be # too long. SHUTDOWNDELAY=5 # OPTIONS can be used for anything else. # If you want to boot everything then # options can be "-a" or "-a -A". OPTIONS= # STOPOPTS are stop options. The can be used for anything else to stop. # If you want to kill containers fast, use -k STOPOPTS="-a -A -s" if [ -d "$localstatedir"/lock/subsys ] then lockdir="$localstatedir"/lock/subsys else lockdir="$localstatedir"/lock fi # Source any configurable options [ ! -f "$distrosysconfdir"/lxc ] || . "$distrosysconfdir"/lxc # Check for needed utility program [ -x "$bindir"/lxc-autostart ] || exit 1 # If libvirtd is providing the bridge, it might not be # immediately available, so wait a bit for it before starting # up the containers or else any that use the bridge will fail # to start wait_for_bridge() { [ "x$USE_LXC_BRIDGE" = "xtrue" ] || { return 0; } local BRNAME try flags br [ -f "$sysconfdir"/lxc/default.conf ] || { return 0; } BRNAME=`grep '^[ ]*lxc.network.link' "$sysconfdir"/lxc/default.conf | sed 's/^.*=[ ]*//'` if [ -z "$BRNAME" ]; then return 0 fi for try in `seq 1 30`; do for br in ${BRNAME}; do [ -r /sys/class/net/${br}/flags ] || { sleep 1; continue 2; } read flags < /sys/class/net/${br}/flags [ $((flags & 0x1)) -eq 1 ] || { sleep 1; continue 2; } done return 0 done } # See how we were called. case "$1" in start) [ "x$LXC_AUTO" = "xtrue" ] || { exit 0; } [ ! -f "$lockdir"/lxc ] || { exit 0; } if [ -n "$BOOTGROUPS" ]; then BOOTGROUPS="-g $BOOTGROUPS" fi touch "$lockdir"/lxc # Start containers wait_for_bridge # Start autoboot containers first then the NULL group "onboot,". "$bindir"/lxc-autostart $OPTIONS $BOOTGROUPS rm -f "$lockdir"/lxc ;; stop) if [ -n "$SHUTDOWNDELAY" ]; then SHUTDOWNDELAY="-t $SHUTDOWNDELAY" fi # The stop is serialized and can take excessive time. We need to avoid # delaying the system shutdown / reboot as much as we can since it's not # parallelized... Even 5 second timout may be too long. "$bindir"/lxc-autostart $STOPOPTS $SHUTDOWNDELAY ;; restart|reload|force-reload) $0 stop $0 start ;; *) echo "Usage: $0 {start|stop|restart|reload|force-reload}" exit 2 ;; esac exit $? lxc-2.0.8/config/init/Makefile.in0000644061062106075000000005037213105116775013532 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = config/init ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/acinclude.m4 \ $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/tls.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APPARMOR_LIBS = @APPARMOR_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BINDIR = @BINDIR@ CAP_LIBS = @CAP_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CGMANAGER_CFLAGS = @CGMANAGER_CFLAGS@ CGMANAGER_LIBS = @CGMANAGER_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIR = @DATADIR@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFAULT_CGROUP_PATTERN = @DEFAULT_CGROUP_PATTERN@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOCDIR = @DOCDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ HAVE_DOXYGEN = @HAVE_DOXYGEN@ INCLUDEDIR = @INCLUDEDIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDIR = @LIBDIR@ LIBEXECDIR = @LIBEXECDIR@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCALSTATEDIR = @LOCALSTATEDIR@ LOGPATH = @LOGPATH@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBDIR = @LUA_LIBDIR@ LUA_LIBS = @LUA_LIBS@ LUA_SHAREDIR = @LUA_SHAREDIR@ LUA_VERSION = @LUA_VERSION@ LXCBINHOOKDIR = @LXCBINHOOKDIR@ LXCHOOKDIR = @LXCHOOKDIR@ LXCINITDIR = @LXCINITDIR@ LXCPATH = @LXCPATH@ LXCROOTFSMOUNT = @LXCROOTFSMOUNT@ LXCTEMPLATECONFIG = @LXCTEMPLATECONFIG@ LXCTEMPLATEDIR = @LXCTEMPLATEDIR@ LXC_ABI = @LXC_ABI@ LXC_ABI_MAJOR = @LXC_ABI_MAJOR@ LXC_ABI_MICRO = @LXC_ABI_MICRO@ LXC_ABI_MINOR = @LXC_ABI_MINOR@ LXC_DEFAULT_CONFIG = @LXC_DEFAULT_CONFIG@ LXC_DEVEL = @LXC_DEVEL@ LXC_DISTRO_SYSCONF = @LXC_DISTRO_SYSCONF@ LXC_GENERATE_DATE = @LXC_GENERATE_DATE@ LXC_GLOBAL_CONF = @LXC_GLOBAL_CONF@ LXC_USERNIC_CONF = @LXC_USERNIC_CONF@ LXC_USERNIC_DB = @LXC_USERNIC_DB@ LXC_VERSION = @LXC_VERSION@ LXC_VERSION_BASE = @LXC_VERSION_BASE@ LXC_VERSION_BETA = @LXC_VERSION_BETA@ LXC_VERSION_MAJOR = @LXC_VERSION_MAJOR@ LXC_VERSION_MICRO = @LXC_VERSION_MICRO@ LXC_VERSION_MINOR = @LXC_VERSION_MINOR@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NIH_CFLAGS = @NIH_CFLAGS@ NIH_DBUS_CFLAGS = @NIH_DBUS_CFLAGS@ NIH_DBUS_LIBS = @NIH_DBUS_LIBS@ NIH_LIBS = @NIH_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PREFIX = @PREFIX@ PYTHON = @PYTHON@ PYTHONDEV_CFLAGS = @PYTHONDEV_CFLAGS@ PYTHONDEV_LIBS = @PYTHONDEV_LIBS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RUNTIME_PATH = @RUNTIME_PATH@ SBINDIR = @SBINDIR@ SECCOMP_CFLAGS = @SECCOMP_CFLAGS@ SECCOMP_LIBS = @SECCOMP_LIBS@ SED = @SED@ SELINUX_LIBS = @SELINUX_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SYSCONFDIR = @SYSCONFDIR@ SYSTEMD_UNIT_DIR = @SYSTEMD_UNIT_DIR@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bashcompdir = @bashcompdir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ db2xman = @db2xman@ docdir = @docdir@ docdtd = @docdtd@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = common systemd sysvinit upstart all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu config/init/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu config/init/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lxc-2.0.8/config/ltoptions.m40000644061062106075000000003426212756047127013024 00000000000000# Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 8 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option '$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl 'shared' nor 'disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], [_LT_WITH_AIX_SONAME([aix])]) ]) ])# _LT_SET_OPTIONS ## --------------------------------- ## ## Macros to handle LT_INIT options. ## ## --------------------------------- ## # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the 'shared' and # 'disable-shared' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS=$lt_save_ifs ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the 'static' and # 'disable-static' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS=$lt_save_ifs ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the 'fast-install' # and 'disable-fast-install' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS=$lt_save_ifs ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_AIX_SONAME([DEFAULT]) # ---------------------------------- # implement the --with-aix-soname flag, and support the `aix-soname=aix' # and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT # is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. m4_define([_LT_WITH_AIX_SONAME], [m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[[5-9]]*,yes) AC_MSG_CHECKING([which variant of shared library versioning to provide]) AC_ARG_WITH([aix-soname], [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], [case $withval in aix|svr4|both) ;; *) AC_MSG_ERROR([Unknown argument to --with-aix-soname]) ;; esac lt_cv_with_aix_soname=$with_aix_soname], [AC_CACHE_VAL([lt_cv_with_aix_soname], [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) with_aix_soname=$lt_cv_with_aix_soname]) AC_MSG_RESULT([$with_aix_soname]) if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac _LT_DECL([], [shared_archive_member_spec], [0], [Shared archive member basename, for filename based shared library versioning on AIX])dnl ])# _LT_WITH_AIX_SONAME LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the 'pic-only' and 'no-pic' # LT_INIT options. # MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS=$lt_save_ifs ;; esac], [pic_mode=m4_default([$1], [default])]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) ## ----------------- ## ## LTDL_INIT Options ## ## ----------------- ## m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) lxc-2.0.8/config/compile0000755061062106075000000001624513105116775012101 00000000000000#! /bin/sh # Wrapper for compilers which do not understand '-c -o'. scriptversion=2012-10-14.11; # UTC # Copyright (C) 1999-2014 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . nl=' ' # We need space, tab and new line, in precisely that order. Quoting is # there to prevent tools from complaining about whitespace usage. IFS=" "" $nl" file_conv= # func_file_conv build_file lazy # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. If the determined conversion # type is listed in (the comma separated) LAZY, no conversion will # take place. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv/,$2, in *,$file_conv,*) ;; mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_cl_dashL linkdir # Make cl look for libraries in LINKDIR func_cl_dashL () { func_file_conv "$1" if test -z "$lib_path"; then lib_path=$file else lib_path="$lib_path;$file" fi linker_opts="$linker_opts -LIBPATH:$file" } # func_cl_dashl library # Do a library search-path lookup for cl func_cl_dashl () { lib=$1 found=no save_IFS=$IFS IFS=';' for dir in $lib_path $LIB do IFS=$save_IFS if $shared && test -f "$dir/$lib.dll.lib"; then found=yes lib=$dir/$lib.dll.lib break fi if test -f "$dir/$lib.lib"; then found=yes lib=$dir/$lib.lib break fi if test -f "$dir/lib$lib.a"; then found=yes lib=$dir/lib$lib.a break fi done IFS=$save_IFS if test "$found" != yes; then lib=$lib.lib fi } # func_cl_wrapper cl arg... # Adjust compile command to suit cl func_cl_wrapper () { # Assume a capable shell lib_path= shared=: linker_opts= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. eat=1 case $2 in *.o | *.[oO][bB][jJ]) func_file_conv "$2" set x "$@" -Fo"$file" shift ;; *) func_file_conv "$2" set x "$@" -Fe"$file" shift ;; esac ;; -I) eat=1 func_file_conv "$2" mingw set x "$@" -I"$file" shift ;; -I*) func_file_conv "${1#-I}" mingw set x "$@" -I"$file" shift ;; -l) eat=1 func_cl_dashl "$2" set x "$@" "$lib" shift ;; -l*) func_cl_dashl "${1#-l}" set x "$@" "$lib" shift ;; -L) eat=1 func_cl_dashL "$2" ;; -L*) func_cl_dashL "${1#-L}" ;; -static) shared=false ;; -Wl,*) arg=${1#-Wl,} save_ifs="$IFS"; IFS=',' for flag in $arg; do IFS="$save_ifs" linker_opts="$linker_opts $flag" done IFS="$save_ifs" ;; -Xlinker) eat=1 linker_opts="$linker_opts $2" ;; -*) set x "$@" "$1" shift ;; *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) func_file_conv "$1" set x "$@" -Tp"$file" shift ;; *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) func_file_conv "$1" mingw set x "$@" "$file" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -n "$linker_opts"; then linker_opts="-link$linker_opts" fi exec "$@" $linker_opts exit 1 } eat= case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand '-c -o'. Remove '-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file 'INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac ofile= cfile= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. # So we strip '-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no '-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # '.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` # Create the lock directory. # Note: use '[/\\:.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then test "$cofile" = "$ofile" || mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: lxc-2.0.8/config/lt~obsolete.m40000644061062106075000000001377412756047127013350 00000000000000# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software # Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) lxc-2.0.8/config/selinux/0000755061062106075000000000000013105117015012246 500000000000000lxc-2.0.8/config/selinux/Makefile.am0000644061062106075000000000014413105116772014232 00000000000000selinuxdir=@DATADIR@/lxc/selinux EXTRA_DIST = \ lxc.if lxc.te selinux_DATA = \ lxc.if \ lxc.te lxc-2.0.8/config/selinux/Makefile.in0000644061062106075000000004042113105116775014250 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = config/selinux ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/acinclude.m4 \ $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/tls.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(selinuxdir)" DATA = $(selinux_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APPARMOR_LIBS = @APPARMOR_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BINDIR = @BINDIR@ CAP_LIBS = @CAP_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CGMANAGER_CFLAGS = @CGMANAGER_CFLAGS@ CGMANAGER_LIBS = @CGMANAGER_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIR = @DATADIR@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFAULT_CGROUP_PATTERN = @DEFAULT_CGROUP_PATTERN@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOCDIR = @DOCDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ HAVE_DOXYGEN = @HAVE_DOXYGEN@ INCLUDEDIR = @INCLUDEDIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDIR = @LIBDIR@ LIBEXECDIR = @LIBEXECDIR@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCALSTATEDIR = @LOCALSTATEDIR@ LOGPATH = @LOGPATH@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBDIR = @LUA_LIBDIR@ LUA_LIBS = @LUA_LIBS@ LUA_SHAREDIR = @LUA_SHAREDIR@ LUA_VERSION = @LUA_VERSION@ LXCBINHOOKDIR = @LXCBINHOOKDIR@ LXCHOOKDIR = @LXCHOOKDIR@ LXCINITDIR = @LXCINITDIR@ LXCPATH = @LXCPATH@ LXCROOTFSMOUNT = @LXCROOTFSMOUNT@ LXCTEMPLATECONFIG = @LXCTEMPLATECONFIG@ LXCTEMPLATEDIR = @LXCTEMPLATEDIR@ LXC_ABI = @LXC_ABI@ LXC_ABI_MAJOR = @LXC_ABI_MAJOR@ LXC_ABI_MICRO = @LXC_ABI_MICRO@ LXC_ABI_MINOR = @LXC_ABI_MINOR@ LXC_DEFAULT_CONFIG = @LXC_DEFAULT_CONFIG@ LXC_DEVEL = @LXC_DEVEL@ LXC_DISTRO_SYSCONF = @LXC_DISTRO_SYSCONF@ LXC_GENERATE_DATE = @LXC_GENERATE_DATE@ LXC_GLOBAL_CONF = @LXC_GLOBAL_CONF@ LXC_USERNIC_CONF = @LXC_USERNIC_CONF@ LXC_USERNIC_DB = @LXC_USERNIC_DB@ LXC_VERSION = @LXC_VERSION@ LXC_VERSION_BASE = @LXC_VERSION_BASE@ LXC_VERSION_BETA = @LXC_VERSION_BETA@ LXC_VERSION_MAJOR = @LXC_VERSION_MAJOR@ LXC_VERSION_MICRO = @LXC_VERSION_MICRO@ LXC_VERSION_MINOR = @LXC_VERSION_MINOR@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NIH_CFLAGS = @NIH_CFLAGS@ NIH_DBUS_CFLAGS = @NIH_DBUS_CFLAGS@ NIH_DBUS_LIBS = @NIH_DBUS_LIBS@ NIH_LIBS = @NIH_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PREFIX = @PREFIX@ PYTHON = @PYTHON@ PYTHONDEV_CFLAGS = @PYTHONDEV_CFLAGS@ PYTHONDEV_LIBS = @PYTHONDEV_LIBS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RUNTIME_PATH = @RUNTIME_PATH@ SBINDIR = @SBINDIR@ SECCOMP_CFLAGS = @SECCOMP_CFLAGS@ SECCOMP_LIBS = @SECCOMP_LIBS@ SED = @SED@ SELINUX_LIBS = @SELINUX_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SYSCONFDIR = @SYSCONFDIR@ SYSTEMD_UNIT_DIR = @SYSTEMD_UNIT_DIR@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bashcompdir = @bashcompdir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ db2xman = @db2xman@ docdir = @docdir@ docdtd = @docdtd@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ selinuxdir = @DATADIR@/lxc/selinux EXTRA_DIST = \ lxc.if lxc.te selinux_DATA = \ lxc.if \ lxc.te all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu config/selinux/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu config/selinux/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-selinuxDATA: $(selinux_DATA) @$(NORMAL_INSTALL) @list='$(selinux_DATA)'; test -n "$(selinuxdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(selinuxdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(selinuxdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(selinuxdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(selinuxdir)" || exit $$?; \ done uninstall-selinuxDATA: @$(NORMAL_UNINSTALL) @list='$(selinux_DATA)'; test -n "$(selinuxdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(selinuxdir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(DATA) installdirs: for dir in "$(DESTDIR)$(selinuxdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-selinuxDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-selinuxDATA .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-selinuxDATA install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags-am uninstall uninstall-am uninstall-selinuxDATA .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lxc-2.0.8/config/selinux/lxc.te0000644061062106075000000000531013105116772013316 00000000000000# # SELinux policy for LXC for RHEL/CentOS/Oracle 6.5. # It attempts to restrict the container to the same amount of access # as an unprivileged user. To build and insert this policy module: # # make -f /usr/share/selinux/devel/Makefile lxc.pp # semodule -i lxc.pp # # In your container's lxc config: # lxc.se_context = system_u:system_r:lxc_t:s0:c62,c86,c150,c228 # # Ensure your container's rootfs files are labeled: # chcon -R system_u:object_r:lxc_file_t:s0:c62,c86,c150,c228 /path/to/rootfs # # To keep containers separated from each other, you should vary the MCS # portion of the contexts above to be a unique set of values for each # container, each MCS compartment can be a number from 0-1023. # policy_module(lxc,0.35) userdom_unpriv_user_template(lxc) type lxc_file_t; files_type(lxc_file_t); role system_r types { lxc_t lxc_file_t }; gen_require(` type devpts_t; type proc_t; type ssh_port_t; type sysctl_kernel_t; type sysctl_modprobe_t; type sysctl_net_t; type tmpfs_t; type unconfined_t; class filesystem { relabelfrom unmount }; class tcp_socket name_bind; class udp_socket name_bind; '); # So lxc can transition to lxc_t on exec allow unconfined_t lxc_t:process transition; can_exec(lxc_t, lxc_file_t) # So lxc can dyntransition to lxc_t for attach executing a function allow unconfined_t lxc_t:process dyntransition; # So lxc-start can relabel the pty allocated for the console allow lxc_file_t devpts_t:filesystem associate; # So container can mount /dev/shm and relabel it allow lxc_t tmpfs_t:filesystem relabelfrom; # Allow all access to an lxc_file_t type; devices can be restricted # with the device cgroup, they are not here allow lxc_t lxc_file_t:file *; allow lxc_t lxc_file_t:lnk_file *; allow lxc_t lxc_file_t:chr_file *; allow lxc_t lxc_file_t:blk_file *; allow lxc_t lxc_file_t:sock_file *; allow lxc_t lxc_file_t:fifo_file *; allow lxc_t lxc_file_t:socket *; allow lxc_t lxc_file_t:dir *; allow lxc_t lxc_file_t:filesystem unmount; fs_unmount_all_fs(lxc_t) allow lxc_t proc_t:dir mounton; allow lxc_t proc_t:filesystem mount; allow lxc_t tmpfs_t:filesystem mount; allow lxc_t self:capability { dac_override dac_read_search fsetid ipc_lock net_admin net_bind_service net_broadcast net_raw sys_admin sys_boot sys_tty_config }; allow lxc_t sysctl_net_t:file write; allow lxc_t ssh_port_t:tcp_socket name_bind; corenet_tcp_connect_all_ports(lxc_t) corenet_tcp_bind_all_ports(lxc_t) corenet_udp_bind_all_ports(lxc_t) # Needed for ifup/ip/dhcp allow lxc_t self:packet_socket create_socket_perms; allow lxc_t self:rawip_socket create_socket_perms; allow lxc_t self:netlink_route_socket create_netlink_socket_perms; dontaudit lxc_t sysctl_kernel_t:file write; dontaudit lxc_t sysctl_modprobe_t:file write; lxc-2.0.8/config/selinux/lxc.if0000644061062106075000000000006013105116772013301 00000000000000## Policy for LXC containers lxc-2.0.8/config/libtool.m40000644061062106075000000112617112756047127012437 00000000000000# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl # Copyright (C) 2014 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program or library that is built # using GNU Libtool, you may include this file under the same # distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ]) # serial 58 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl _LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_PREPARE_CC_BASENAME # ----------------------- m4_defun([_LT_PREPARE_CC_BASENAME], [ # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in @S|@*""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } ])# _LT_PREPARE_CC_BASENAME # _LT_CC_BASENAME(CC) # ------------------- # It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, # but that macro is also expanded into generated libtool script, which # arranges for $SED and $ECHO to be set by different means. m4_defun([_LT_CC_BASENAME], [m4_require([_LT_PREPARE_CC_BASENAME])dnl AC_REQUIRE([_LT_DECL_SED])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl func_cc_basename $1 cc_basename=$func_cc_basename_result ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl _LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl m4_require([_LT_CMD_TRUNCATE])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a '.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld old_CC=$CC old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PREPARE_SED_QUOTE_VARS # -------------------------- # Define a few sed substitution that help us do robust quoting. m4_defun([_LT_PREPARE_SED_QUOTE_VARS], [# Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ]) # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from 'configure', and 'config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # 'config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain=$ac_aux_dir/ltmain.sh ])# _LT_PROG_LTMAIN ## ------------------------------------- ## ## Accumulate code for creating libtool. ## ## ------------------------------------- ## # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the 'libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) ## ------------------------ ## ## FIXME: Eliminate VARNAME ## ## ------------------------ ## # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to 'config.status' so that its # declaration there will have the same value as in 'configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags='_LT_TAGS'dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into 'config.status', and then the shell code to quote escape them in # for loops in 'config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$[]1 _LTECHO_EOF' } # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done _LT_OUTPUT_LIBTOOL_INIT ]) # _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) # ------------------------------------ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the # '#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). m4_ifdef([AS_INIT_GENERATED], [m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], [m4_defun([_LT_GENERATED_FILE_INIT], [m4_require([AS_PREPARE])]dnl [m4_pushdef([AS_MESSAGE_LOG_FD])]dnl [lt_write_fail=0 cat >$1 <<_ASEOF || lt_write_fail=1 #! $SHELL # Generated by $as_me. $2 SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$1 <<\_ASEOF || lt_write_fail=1 AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF test 0 = "$lt_write_fail" && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) _LT_GENERATED_FILE_INIT(["$CONFIG_LT"], [# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ '$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test 0 != $[#] do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try '$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try '$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: test yes = "$silent" && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. # Written by Gordon Matzigkeit, 1996 _LT_COPYING _LT_LIBTOOL_TAGS # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE _LT_PREPARE_MUNGE_PATH_LIST _LT_PREPARE_CC_BASENAME # ### END FUNCTIONS SHARED WITH CONFIGURE _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Go], [_LT_LANG(GO)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG m4_ifndef([AC_PROG_GO], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_GO. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_GO], [AC_LANG_PUSH(Go)dnl AC_ARG_VAR([GOC], [Go compiler command])dnl AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl _AC_ARG_VAR_LDFLAGS()dnl AC_CHECK_TOOL(GOC, gccgo) if test -z "$GOC"; then if test -n "$ac_tool_prefix"; then AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) fi fi if test -z "$GOC"; then AC_CHECK_PROG(GOC, gccgo, gccgo, false) fi ])#m4_defun ])#m4_ifndef # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([AC_PROG_GO], [LT_LANG(GO)], [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS=$save_LDFLAGS ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], [lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; 10.[[012]][[,.]]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi if test yes = "$lt_cv_ld_exported_symbols_list"; then _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES([TAG]) # --------------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported if test yes = "$lt_cv_ld_force_load"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" m4_if([$1], [CXX], [ if test yes != "$lt_cv_apple_cc_single_mod"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX([TAGNAME]) # ---------------------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. # Store the results from the different compilers for each TAGNAME. # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ lt_aix_libpath_sed='[ /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }]' _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [m4_divert_text([M4SH-INIT], [$1 ])])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start # of the generated configure script that will find a shell with a builtin # printf (that we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO AC_MSG_CHECKING([how to print strings]) # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $[]1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } case $ECHO in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; esac m4_ifdef([_AS_DETECT_SUGGESTED], [_AS_DETECT_SUGGESTED([ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test "X`printf %s $ECHO`" = "X$ECHO" \ || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], [Search for dependent libraries within DIR (or the compiler's sysroot if not specified).])], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= case $with_sysroot in #( yes) if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) AC_MSG_RESULT([$with_sysroot]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl [dependent libraries, and where our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out what ABI is being produced by ac_compile, and set mode # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; *ELF-64*) HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test yes = "$lt_cv_prog_gnu_ld"; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; mips64*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then emul=elf case `/usr/bin/file conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `/usr/bin/file conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `/usr/bin/file conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; esac LD="${LD-ld} -m $emul" fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. Note that the listed cases only cover the # situations where additional linker options are needed (such as when # doing 32-bit compilation for a host where ld defaults to 64-bit, or # vice versa); the common cases where no linker options are needed do # not appear in the list. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD=${LD-ld}_sol2 fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks=$enable_libtool_lock ])# _LT_ENABLE_LOCK # _LT_PROG_AR # ----------- m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} : ${AR_FLAGS=cru} _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi _LT_DECL([], [archiver_list_spec], [1], [How to feed a file listing to the archiver]) ])# _LT_PROG_AR # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) _LT_DECL([], [lock_old_archive_extraction], [0], [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test yes = "[$]$2"; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS ]) if test yes = "[$]$2"; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring=ABCD case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n "$lt_cv_sys_max_cmd_len"; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes = "$cross_compiling"; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; tpf*) # Don't try to run any link tests for TPF. We know it's impossible # because TPF is a cross-compiler, and we know how we open DSOs. lt_cv_dlopen=dlopen lt_cv_dlopen_libs= lt_cv_dlopen_self=no ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen=shl_load], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen=dlopen], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) ]) ]) ]) ]) ]) ;; esac if test no = "$lt_cv_dlopen"; then enable_dlopen=no else enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS=$CPPFLAGS test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links=nottested if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test no = "$hard_links"; then AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", [Define to the sub-directory where libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then # We can hardcode non-existent directories. if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP"; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_PREPARE_MUNGE_PATH_LIST # --------------------------- # Make sure func_munge_path_list() is defined correctly. m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], [[# func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x@S|@2 in x) ;; *:) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" ;; x:*) eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; *::*) eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" ;; *) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; esac } ]])# _LT_PREPARE_PATH_LIST # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test yes = "$GCC"; then case $host_os in darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` # ...but if some path component already ends with the multilib dir we assume # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). case "$lt_multi_os_dir; $lt_search_path_spec " in "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) lt_multi_os_dir= ;; esac for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS = " "; FS = "/|\n";} { lt_foo = ""; lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown AC_ARG_VAR([LT_SYS_LIBRARY_PATH], [User-defined run-time library search path.]) case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[[4-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a[(]lib.so.V[)]' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[23]].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[[3-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], [lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [lt_cv_shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir ]) shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [install_override_mode], [1], [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], [Detected run-time system search path for libraries]) _LT_DECL([], [configure_time_lt_sys_library_path], [2], [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program that can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$1"; then lt_cv_path_MAGIC_CMD=$ac_dir/"$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac]) MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program that can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test no = "$withval" || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], [if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: fi]) rm -f conftest.i conftest2.i conftest.out]) ])# _LT_PATH_DD # _LT_CMD_TRUNCATE # ---------------- # find command to truncate a binary pipe m4_defun([_LT_CMD_TRUNCATE], [m4_require([_LT_PATH_DD]) AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], [printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i lt_cv_truncate_bin= if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" fi rm -f conftest.i conftest2.i conftest.out test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) _LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], [Command to truncate a binary pipe]) ])# _LT_CMD_TRUNCATE # _LT_CHECK_MAGIC_METHOD # ---------------------- # how to check for library dependencies # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_MAGIC_METHOD], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) AC_CACHE_CHECK([how to recognize dependent libraries], lt_cv_deplibs_check_method, [lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # that responds to the $file_magic_cmd with a given extended regex. # If you have 'file' or equivalent on your system and you're not sure # whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[[4-9]]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[[45]]*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd* | bitrig*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; os2*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method = "file_magic"]) _LT_DECL([], [file_magic_glob], [1], [How to find potential files when deplibs_check_method = "file_magic"]) _LT_DECL([], [want_nocaseglob], [1], [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM=$NM else lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/$lt_tmp_nm if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty case $build_os in mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi]) if test no != "$lt_cv_path_NM"; then NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: ;; esac fi AC_SUBST([DUMPBIN]) if test : != "$DUMPBIN"; then NM=$DUMPBIN fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # _LT_CHECK_SHAREDLIB_FROM_LINKLIB # -------------------------------- # how to determine the name of the shared library # associated with a specific link library. # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) m4_require([_LT_DECL_DLLTOOL]) AC_CACHE_CHECK([how to associate runtime and link libraries], lt_cv_sharedlib_from_linklib_cmd, [lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh; # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac ]) sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO _LT_DECL([], [sharedlib_from_linklib_cmd], [1], [Command to associate shared and link libraries]) ])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB # _LT_PATH_MANIFEST_TOOL # ---------------------- # locate the manifest tool m4_defun([_LT_PATH_MANIFEST_TOOL], [AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], [lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&AS_MESSAGE_LOG_FD if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # _LT_DLL_DEF_P([FILE]) # --------------------- # True iff FILE is a Windows DLL '.def' file. # Keep in sync with func_dll_def_p in the libtool script AC_DEFUN([_LT_DLL_DEF_P], [dnl test DEF = "`$SED -n dnl -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl -e q dnl Only consider the first "real" line $1`" dnl ])# _LT_DLL_DEF_P # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM=-lm) ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test yes = "$GCC"; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; *) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test ia64 = "$host_cpu"; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" lt_c_name_lib_hook="\ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" else # Disable hooks by default. lt_cv_sys_global_symbol_to_import= lt_cdecl_hook= lt_c_name_hook= lt_c_name_lib_hook= fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ " /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ " /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ " {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ " s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else # define LT@&t@_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT@&t@_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then nm_file_list_spec='@' fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], [Transform the output of nm into a list of symbols to manually relocate]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) _LT_DECL([nm_interface], [lt_cv_nm_interface], [1], [The name lister interface]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' if test ia64 != "$host_cpu"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64, which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test yes = "$GCC"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' case $cc_basename in nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64, which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; *Sun\ F* | *Sun*Fortran*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Intel*\ [[CF]]*Compiler*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; *Portland\ Group*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_CACHE_CHECK([for $compiler option to produce PIC], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; esac ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ' (' and ')$', so one must not match beginning or # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', # as well as any symbol that contains 'd'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test ia64 != "$host_cpu"; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; nagfor*) # NAGFOR 5.3 tmp_sharedflag='-Wl,-shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in tcc*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # traditional, no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GCC"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag="$shared_flag "'$wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; hpux10*) if test yes,no = "$GCC,$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], [save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], [C++], [[int foo (void) { return 0; }]], [Fortran 77], [[ subroutine foo end]], [Fortran], [[ subroutine foo end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) LDFLAGS=$save_LDFLAGS]) if test yes = "$lt_cv_irix_exported_symbol"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi _LT_TAGVAR(link_all_deplibs, $1)=no else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(ld_shlibs, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; osf3*) if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test yes = "$GCC"; then wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test yes = "$GCC"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test yes,yes = "$GCC,$enable_shared"; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_CACHE_CHECK([whether -lc should be explicitly linked in], [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), [$RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no else lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ]) _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting $shlibpath_var if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [postlink_cmds], [2], [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC=$CC AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report what library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC=$lt_save_CC ])# _LT_LANG_C_CONFIG # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl if test -n "$CXX" && ( test no != "$CXX" && ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || (test g++ != "$CXX"))); then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_caught_CXX_error"; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test yes = "$GXX"; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test yes = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='$wl' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GXX"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag=$shared_flag' $wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. # The "-G" linker flag allows undefined symbols. _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ func_to_tool_file "$lt_outputfile"~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(GCC, $1)=$GXX _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test yes != "$_lt_caught_CXX_error" AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_FUNC_STRIPNAME_CNF # ---------------------- # func_stripname_cnf prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # # This function is identical to the (non-XSI) version of func_stripname, # except this one can be used by m4 code that may be executed by configure, # rather than the libtool script. m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { case @S|@2 in .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF package foo func foo() { } _LT_EOF ]) _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case $prev$p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test x-L = "$p" || test x-R = "$p"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test no = "$pre_test_object_deps_done"; then case $prev in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)=$prev$p else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test no = "$pre_test_object_deps_done"; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)=$p else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)=$p else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) if test -z "$F77" || test no = "$F77"; then _lt_disable_F77=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_F77"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$G77 _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_F77" AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) if test -z "$FC" || test no = "$FC"; then _lt_disable_FC=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_FC"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_FC" AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_GO_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE # Source file extension for Go test sources. ac_ext=go # Object file extension for compiled Go test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="package main; func main() { }" # Code to be used in simple link tests lt_simple_link_test_code='package main; func main() { }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GO_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code=$lt_simple_compile_test_code # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_GO # ---------- AC_DEFUN([LT_PROG_GO], [AC_CHECK_TOOL(GOC, gccgo,) ]) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_DLLTOOL # ---------------- # Ensure DLLTOOL variable is set. m4_defun([_LT_DECL_DLLTOOL], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f "$lt_ac_sed" && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test 10 -lt "$lt_ac_count" && break lt_ac_count=`expr $lt_ac_count + 1` if test "$lt_ac_count" -gt "$lt_ac_max"; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine what file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_MSG_CHECKING([how to convert $build file names to $host format]) AC_CACHE_VAL(lt_cv_to_host_file_cmd, [case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac ]) to_host_file_cmd=$lt_cv_to_host_file_cmd AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) _LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], [0], [convert $build file names to $host format])dnl AC_MSG_CHECKING([how to convert $build file names to toolchain format]) AC_CACHE_VAL(lt_cv_to_tool_file_cmd, [#assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac ]) to_tool_file_cmd=$lt_cv_to_tool_file_cmd AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], [0], [convert $build files to toolchain format])dnl ])# _LT_PATH_CONVERSION_FUNCTIONS lxc-2.0.8/config/bash/0000755061062106075000000000000013105117015011474 500000000000000lxc-2.0.8/config/bash/Makefile.am0000644061062106075000000000010013105116772013450 00000000000000EXTRA_DIST = lxc if ENABLE_BASH dist_bashcomp_DATA = lxc endif lxc-2.0.8/config/bash/Makefile.in0000644061062106075000000004076013105116775013504 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = config/bash ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/acinclude.m4 \ $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/tls.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__dist_bashcomp_DATA_DIST) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h CONFIG_CLEAN_FILES = lxc CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__dist_bashcomp_DATA_DIST = lxc am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(bashcompdir)" DATA = $(dist_bashcomp_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/lxc.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APPARMOR_LIBS = @APPARMOR_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BINDIR = @BINDIR@ CAP_LIBS = @CAP_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CGMANAGER_CFLAGS = @CGMANAGER_CFLAGS@ CGMANAGER_LIBS = @CGMANAGER_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIR = @DATADIR@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFAULT_CGROUP_PATTERN = @DEFAULT_CGROUP_PATTERN@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOCDIR = @DOCDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ HAVE_DOXYGEN = @HAVE_DOXYGEN@ INCLUDEDIR = @INCLUDEDIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDIR = @LIBDIR@ LIBEXECDIR = @LIBEXECDIR@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCALSTATEDIR = @LOCALSTATEDIR@ LOGPATH = @LOGPATH@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBDIR = @LUA_LIBDIR@ LUA_LIBS = @LUA_LIBS@ LUA_SHAREDIR = @LUA_SHAREDIR@ LUA_VERSION = @LUA_VERSION@ LXCBINHOOKDIR = @LXCBINHOOKDIR@ LXCHOOKDIR = @LXCHOOKDIR@ LXCINITDIR = @LXCINITDIR@ LXCPATH = @LXCPATH@ LXCROOTFSMOUNT = @LXCROOTFSMOUNT@ LXCTEMPLATECONFIG = @LXCTEMPLATECONFIG@ LXCTEMPLATEDIR = @LXCTEMPLATEDIR@ LXC_ABI = @LXC_ABI@ LXC_ABI_MAJOR = @LXC_ABI_MAJOR@ LXC_ABI_MICRO = @LXC_ABI_MICRO@ LXC_ABI_MINOR = @LXC_ABI_MINOR@ LXC_DEFAULT_CONFIG = @LXC_DEFAULT_CONFIG@ LXC_DEVEL = @LXC_DEVEL@ LXC_DISTRO_SYSCONF = @LXC_DISTRO_SYSCONF@ LXC_GENERATE_DATE = @LXC_GENERATE_DATE@ LXC_GLOBAL_CONF = @LXC_GLOBAL_CONF@ LXC_USERNIC_CONF = @LXC_USERNIC_CONF@ LXC_USERNIC_DB = @LXC_USERNIC_DB@ LXC_VERSION = @LXC_VERSION@ LXC_VERSION_BASE = @LXC_VERSION_BASE@ LXC_VERSION_BETA = @LXC_VERSION_BETA@ LXC_VERSION_MAJOR = @LXC_VERSION_MAJOR@ LXC_VERSION_MICRO = @LXC_VERSION_MICRO@ LXC_VERSION_MINOR = @LXC_VERSION_MINOR@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NIH_CFLAGS = @NIH_CFLAGS@ NIH_DBUS_CFLAGS = @NIH_DBUS_CFLAGS@ NIH_DBUS_LIBS = @NIH_DBUS_LIBS@ NIH_LIBS = @NIH_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PREFIX = @PREFIX@ PYTHON = @PYTHON@ PYTHONDEV_CFLAGS = @PYTHONDEV_CFLAGS@ PYTHONDEV_LIBS = @PYTHONDEV_LIBS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RUNTIME_PATH = @RUNTIME_PATH@ SBINDIR = @SBINDIR@ SECCOMP_CFLAGS = @SECCOMP_CFLAGS@ SECCOMP_LIBS = @SECCOMP_LIBS@ SED = @SED@ SELINUX_LIBS = @SELINUX_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SYSCONFDIR = @SYSCONFDIR@ SYSTEMD_UNIT_DIR = @SYSTEMD_UNIT_DIR@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bashcompdir = @bashcompdir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ db2xman = @db2xman@ docdir = @docdir@ docdtd = @docdtd@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = lxc @ENABLE_BASH_TRUE@dist_bashcomp_DATA = lxc all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu config/bash/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu config/bash/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): lxc: $(top_builddir)/config.status $(srcdir)/lxc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-dist_bashcompDATA: $(dist_bashcomp_DATA) @$(NORMAL_INSTALL) @list='$(dist_bashcomp_DATA)'; test -n "$(bashcompdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bashcompdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bashcompdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(bashcompdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(bashcompdir)" || exit $$?; \ done uninstall-dist_bashcompDATA: @$(NORMAL_UNINSTALL) @list='$(dist_bashcomp_DATA)'; test -n "$(bashcompdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(bashcompdir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(DATA) installdirs: for dir in "$(DESTDIR)$(bashcompdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dist_bashcompDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-dist_bashcompDATA .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am \ install-dist_bashcompDATA install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am uninstall-dist_bashcompDATA .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lxc-2.0.8/config/bash/lxc.in0000644061062106075000000000456113105116772012551 00000000000000_have lxc-start && { _lxc_names() { COMPREPLY=( $( compgen -W "$( lxc-ls )" "$cur" ) ) } _lxc_states() { COMPREPLY=( $( compgen -W "STOPPED STARTING RUNNING STOPPING ABORTING FREEZING FROZEN THAWED" "$cur" ) ) } _lxc_templates() { COMPREPLY=( $( compgen -W "$(ls @LXCTEMPLATEDIR@/ | sed -e 's|^lxc-||' )" "$cur" ) ) } _lxc_generic_n() { local cur prev COMPREPLY=() _get_comp_words_by_ref cur prev case $prev in -n) _lxc_names "$cur" return 0 ;; esac return 1 } _lxc_generic_ns() { local cur prev COMPREPLY=() _get_comp_words_by_ref cur prev case $prev in -n) _lxc_names "$cur" return 0 ;; -s) _lxc_states "$cur" return 0 ;; esac return 1 } _lxc_generic_t() { local cur prev COMPREPLY=() _get_comp_words_by_ref cur prev case $prev in -t) _lxc_templates "$cur" return 0 ;; esac return 1 } _lxc_generic_o() { local cur prev COMPREPLY=() _get_comp_words_by_ref cur prev case $prev in -o) _lxc_names "$cur" return 0 ;; esac return 1 } complete -o default -F _lxc_generic_n lxc-attach complete -o default -F _lxc_generic_n lxc-cgroup complete -o default -F _lxc_generic_n lxc-console complete -o default -F _lxc_generic_n lxc-destroy complete -o default -F _lxc_generic_n lxc-device complete -o default -F _lxc_generic_n lxc-execute complete -o default -F _lxc_generic_n lxc-freeze complete -o default -F _lxc_generic_n lxc-info complete -o default -F _lxc_generic_n lxc-monitor complete -o default -F _lxc_generic_n lxc-snapshot complete -o default -F _lxc_generic_n lxc-start complete -o default -F _lxc_generic_n lxc-stop complete -o default -F _lxc_generic_n lxc-unfreeze complete -o default -F _lxc_generic_ns lxc-wait complete -o default -F _lxc_generic_t lxc-create complete -o default -F _lxc_generic_o lxc-copy complete -o default -F _lxc_generic_o lxc-start-ephemeral } lxc-2.0.8/config/bash/lxc0000644061062106075000000000457713105117006012142 00000000000000_have lxc-start && { _lxc_names() { COMPREPLY=( $( compgen -W "$( lxc-ls )" "$cur" ) ) } _lxc_states() { COMPREPLY=( $( compgen -W "STOPPED STARTING RUNNING STOPPING ABORTING FREEZING FROZEN THAWED" "$cur" ) ) } _lxc_templates() { COMPREPLY=( $( compgen -W "$(ls /usr/local/share/lxc/templates/ | sed -e 's|^lxc-||' )" "$cur" ) ) } _lxc_generic_n() { local cur prev COMPREPLY=() _get_comp_words_by_ref cur prev case $prev in -n) _lxc_names "$cur" return 0 ;; esac return 1 } _lxc_generic_ns() { local cur prev COMPREPLY=() _get_comp_words_by_ref cur prev case $prev in -n) _lxc_names "$cur" return 0 ;; -s) _lxc_states "$cur" return 0 ;; esac return 1 } _lxc_generic_t() { local cur prev COMPREPLY=() _get_comp_words_by_ref cur prev case $prev in -t) _lxc_templates "$cur" return 0 ;; esac return 1 } _lxc_generic_o() { local cur prev COMPREPLY=() _get_comp_words_by_ref cur prev case $prev in -o) _lxc_names "$cur" return 0 ;; esac return 1 } complete -o default -F _lxc_generic_n lxc-attach complete -o default -F _lxc_generic_n lxc-cgroup complete -o default -F _lxc_generic_n lxc-console complete -o default -F _lxc_generic_n lxc-destroy complete -o default -F _lxc_generic_n lxc-device complete -o default -F _lxc_generic_n lxc-execute complete -o default -F _lxc_generic_n lxc-freeze complete -o default -F _lxc_generic_n lxc-info complete -o default -F _lxc_generic_n lxc-monitor complete -o default -F _lxc_generic_n lxc-snapshot complete -o default -F _lxc_generic_n lxc-start complete -o default -F _lxc_generic_n lxc-stop complete -o default -F _lxc_generic_n lxc-unfreeze complete -o default -F _lxc_generic_ns lxc-wait complete -o default -F _lxc_generic_t lxc-create complete -o default -F _lxc_generic_o lxc-copy complete -o default -F _lxc_generic_o lxc-start-ephemeral } lxc-2.0.8/config/ltmain.sh0000644061062106075000000117147412756047127012357 00000000000000#! /bin/sh ## DO NOT EDIT - This file generated from ./build-aux/ltmain.in ## by inline-source v2014-01-03.01 # libtool (GNU libtool) 2.4.6 # Provide generalized library-building support services. # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996-2015 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . PROGRAM=libtool PACKAGE=libtool VERSION="2.4.6 Debian-2.4.6-2" package_revision=2.4.6 ## ------ ## ## Usage. ## ## ------ ## # Run './libtool --help' for help with using this script from the # command line. ## ------------------------------- ## ## User overridable command paths. ## ## ------------------------------- ## # After configure completes, it has a better idea of some of the # shell tools we need than the defaults used by the functions shared # with bootstrap, so set those here where they can still be over- # ridden by the user, but otherwise take precedence. : ${AUTOCONF="autoconf"} : ${AUTOMAKE="automake"} ## -------------------------- ## ## Source external libraries. ## ## -------------------------- ## # Much of our low-level functionality needs to be sourced from external # libraries, which are installed to $pkgauxdir. # Set a version string for this script. scriptversion=2015-01-20.17; # UTC # General shell script boiler plate, and helper functions. # Written by Gary V. Vaughan, 2004 # Copyright (C) 2004-2015 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # As a special exception to the GNU General Public License, if you distribute # this file as part of a program or library that is built using GNU Libtool, # you may include this file under the same distribution terms that you use # for the rest of that program. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNES FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # Please report bugs or propose patches to gary@gnu.org. ## ------ ## ## Usage. ## ## ------ ## # Evaluate this file near the top of your script to gain access to # the functions and variables defined here: # # . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh # # If you need to override any of the default environment variable # settings, do that before evaluating this file. ## -------------------- ## ## Shell normalisation. ## ## -------------------- ## # Some shells need a little help to be as Bourne compatible as possible. # Before doing anything else, make sure all that help has been provided! DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # NLS nuisances: We save the old values in case they are required later. _G_user_locale= _G_safe_locale= for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test set = \"\${$_G_var+set}\"; then save_$_G_var=\$$_G_var $_G_var=C export $_G_var _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" fi" done # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Make sure IFS has a sensible default sp=' ' nl=' ' IFS="$sp $nl" # There are apparently some retarded systems that use ';' as a PATH separator! if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi ## ------------------------- ## ## Locate command utilities. ## ## ------------------------- ## # func_executable_p FILE # ---------------------- # Check that FILE is an executable regular file. func_executable_p () { test -f "$1" && test -x "$1" } # func_path_progs PROGS_LIST CHECK_FUNC [PATH] # -------------------------------------------- # Search for either a program that responds to --version with output # containing "GNU", or else returned by CHECK_FUNC otherwise, by # trying all the directories in PATH with each of the elements of # PROGS_LIST. # # CHECK_FUNC should accept the path to a candidate program, and # set $func_check_prog_result if it truncates its output less than # $_G_path_prog_max characters. func_path_progs () { _G_progs_list=$1 _G_check_func=$2 _G_PATH=${3-"$PATH"} _G_path_prog_max=0 _G_path_prog_found=false _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} for _G_dir in $_G_PATH; do IFS=$_G_save_IFS test -z "$_G_dir" && _G_dir=. for _G_prog_name in $_G_progs_list; do for _exeext in '' .EXE; do _G_path_prog=$_G_dir/$_G_prog_name$_exeext func_executable_p "$_G_path_prog" || continue case `"$_G_path_prog" --version 2>&1` in *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; *) $_G_check_func $_G_path_prog func_path_progs_result=$func_check_prog_result ;; esac $_G_path_prog_found && break 3 done done done IFS=$_G_save_IFS test -z "$func_path_progs_result" && { echo "no acceptable sed could be found in \$PATH" >&2 exit 1 } } # We want to be able to use the functions in this file before configure # has figured out where the best binaries are kept, which means we have # to search for them ourselves - except when the results are already set # where we skip the searches. # Unless the user overrides by setting SED, search the path for either GNU # sed, or the sed that truncates its output the least. test -z "$SED" && { _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for _G_i in 1 2 3 4 5 6 7; do _G_sed_script=$_G_sed_script$nl$_G_sed_script done echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed _G_sed_script= func_check_prog_sed () { _G_path_prog=$1 _G_count=0 printf 0123456789 >conftest.in while : do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo '' >> conftest.nl "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break diff conftest.out conftest.nl >/dev/null 2>&1 || break _G_count=`expr $_G_count + 1` if test "$_G_count" -gt "$_G_path_prog_max"; then # Best one so far, save it but keep looking for a better one func_check_prog_result=$_G_path_prog _G_path_prog_max=$_G_count fi # 10*(2^10) chars as input seems more than enough test 10 -lt "$_G_count" && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out } func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin rm -f conftest.sed SED=$func_path_progs_result } # Unless the user overrides by setting GREP, search the path for either GNU # grep, or the grep that truncates its output the least. test -z "$GREP" && { func_check_prog_grep () { _G_path_prog=$1 _G_count=0 _G_path_prog_max=0 printf 0123456789 >conftest.in while : do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo 'GREP' >> conftest.nl "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break diff conftest.out conftest.nl >/dev/null 2>&1 || break _G_count=`expr $_G_count + 1` if test "$_G_count" -gt "$_G_path_prog_max"; then # Best one so far, save it but keep looking for a better one func_check_prog_result=$_G_path_prog _G_path_prog_max=$_G_count fi # 10*(2^10) chars as input seems more than enough test 10 -lt "$_G_count" && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out } func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin GREP=$func_path_progs_result } ## ------------------------------- ## ## User overridable command paths. ## ## ------------------------------- ## # All uppercase variable names are used for environment variables. These # variables can be overridden by the user before calling a script that # uses them if a suitable command of that name is not already available # in the command search PATH. : ${CP="cp -f"} : ${ECHO="printf %s\n"} : ${EGREP="$GREP -E"} : ${FGREP="$GREP -F"} : ${LN_S="ln -s"} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} ## -------------------- ## ## Useful sed snippets. ## ## -------------------- ## sed_dirname='s|/[^/]*$||' sed_basename='s|^.*/||' # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='s|\([`"$\\]\)|\\\1|g' # Same as above, but do not quote variable references. sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution that turns a string into a regex matching for the # string literally. sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' # Sed substitution that converts a w32 file name or path # that contains forward slashes, into one that contains # (escaped) backslashes. A very naive implementation. sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Re-'\' parameter expansions in output of sed_double_quote_subst that # were '\'-ed in input to the same. If an odd number of '\' preceded a # '$' in input to sed_double_quote_subst, that '$' was protected from # expansion. Since each input '\' is now two '\'s, look for any number # of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. _G_bs='\\' _G_bs2='\\\\' _G_bs4='\\\\\\\\' _G_dollar='\$' sed_double_backslash="\ s/$_G_bs4/&\\ /g s/^$_G_bs2$_G_dollar/$_G_bs&/ s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g s/\n//g" ## ----------------- ## ## Global variables. ## ## ----------------- ## # Except for the global variables explicitly listed below, the following # functions in the '^func_' namespace, and the '^require_' namespace # variables initialised in the 'Resource management' section, sourcing # this file will not pollute your global namespace with anything # else. There's no portable way to scope variables in Bourne shell # though, so actually running these functions will sometimes place # results into a variable named after the function, and often use # temporary variables in the '^_G_' namespace. If you are careful to # avoid using those namespaces casually in your sourcing script, things # should continue to work as you expect. And, of course, you can freely # overwrite any of the functions or variables defined here before # calling anything to customize them. EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. # Allow overriding, eg assuming that you follow the convention of # putting '$debug_cmd' at the start of all your functions, you can get # bash to show function call trace with: # # debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name debug_cmd=${debug_cmd-":"} exit_cmd=: # By convention, finish your script with: # # exit $exit_status # # so that you can set exit_status to non-zero if you want to indicate # something went wrong during execution without actually bailing out at # the point of failure. exit_status=$EXIT_SUCCESS # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath=$0 # The name of this program. progname=`$ECHO "$progpath" |$SED "$sed_basename"` # Make sure we have an absolute progpath for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` progdir=`cd "$progdir" && pwd` progpath=$progdir/$progname ;; *) _G_IFS=$IFS IFS=${PATH_SEPARATOR-:} for progdir in $PATH; do IFS=$_G_IFS test -x "$progdir/$progname" && break done IFS=$_G_IFS test -n "$progdir" || progdir=`pwd` progpath=$progdir/$progname ;; esac ## ----------------- ## ## Standard options. ## ## ----------------- ## # The following options affect the operation of the functions defined # below, and should be set appropriately depending on run-time para- # meters passed on the command line. opt_dry_run=false opt_quiet=false opt_verbose=false # Categories 'all' and 'none' are always available. Append any others # you will pass as the first argument to func_warning from your own # code. warning_categories= # By default, display warnings according to 'opt_warning_types'. Set # 'warning_func' to ':' to elide all warnings, or func_fatal_error to # treat the next displayed warning as a fatal error. warning_func=func_warn_and_continue # Set to 'all' to display all warnings, 'none' to suppress all # warnings, or a space delimited list of some subset of # 'warning_categories' to display only the listed warnings. opt_warning_types=all ## -------------------- ## ## Resource management. ## ## -------------------- ## # This section contains definitions for functions that each ensure a # particular resource (a file, or a non-empty configuration variable for # example) is available, and if appropriate to extract default values # from pertinent package files. Call them using their associated # 'require_*' variable to ensure that they are executed, at most, once. # # It's entirely deliberate that calling these functions can set # variables that don't obey the namespace limitations obeyed by the rest # of this file, in order that that they be as useful as possible to # callers. # require_term_colors # ------------------- # Allow display of bold text on terminals that support it. require_term_colors=func_require_term_colors func_require_term_colors () { $debug_cmd test -t 1 && { # COLORTERM and USE_ANSI_COLORS environment variables take # precedence, because most terminfo databases neglect to describe # whether color sequences are supported. test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} if test 1 = "$USE_ANSI_COLORS"; then # Standard ANSI escape sequences tc_reset='' tc_bold=''; tc_standout='' tc_red=''; tc_green='' tc_blue=''; tc_cyan='' else # Otherwise trust the terminfo database after all. test -n "`tput sgr0 2>/dev/null`" && { tc_reset=`tput sgr0` test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` tc_standout=$tc_bold test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` } fi } require_term_colors=: } ## ----------------- ## ## Function library. ## ## ----------------- ## # This section contains a variety of useful functions to call in your # scripts. Take note of the portable wrappers for features provided by # some modern shells, which will fall back to slower equivalents on # less featureful shells. # func_append VAR VALUE # --------------------- # Append VALUE onto the existing contents of VAR. # We should try to minimise forks, especially on Windows where they are # unreasonably slow, so skip the feature probes when bash or zsh are # being used: if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then : ${_G_HAVE_ARITH_OP="yes"} : ${_G_HAVE_XSI_OPS="yes"} # The += operator was introduced in bash 3.1 case $BASH_VERSION in [12].* | 3.0 | 3.0*) ;; *) : ${_G_HAVE_PLUSEQ_OP="yes"} ;; esac fi # _G_HAVE_PLUSEQ_OP # Can be empty, in which case the shell is probed, "yes" if += is # useable or anything else if it does not work. test -z "$_G_HAVE_PLUSEQ_OP" \ && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ && _G_HAVE_PLUSEQ_OP=yes if test yes = "$_G_HAVE_PLUSEQ_OP" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_append () { $debug_cmd eval "$1+=\$2" }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_append () { $debug_cmd eval "$1=\$$1\$2" } fi # func_append_quoted VAR VALUE # ---------------------------- # Quote VALUE and append to the end of shell variable VAR, separated # by a space. if test yes = "$_G_HAVE_PLUSEQ_OP"; then eval 'func_append_quoted () { $debug_cmd func_quote_for_eval "$2" eval "$1+=\\ \$func_quote_for_eval_result" }' else func_append_quoted () { $debug_cmd func_quote_for_eval "$2" eval "$1=\$$1\\ \$func_quote_for_eval_result" } fi # func_append_uniq VAR VALUE # -------------------------- # Append unique VALUE onto the existing contents of VAR, assuming # entries are delimited by the first character of VALUE. For example: # # func_append_uniq options " --another-option option-argument" # # will only append to $options if " --another-option option-argument " # is not already present somewhere in $options already (note spaces at # each end implied by leading space in second argument). func_append_uniq () { $debug_cmd eval _G_current_value='`$ECHO $'$1'`' _G_delim=`expr "$2" : '\(.\)'` case $_G_delim$_G_current_value$_G_delim in *"$2$_G_delim"*) ;; *) func_append "$@" ;; esac } # func_arith TERM... # ------------------ # Set func_arith_result to the result of evaluating TERMs. test -z "$_G_HAVE_ARITH_OP" \ && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ && _G_HAVE_ARITH_OP=yes if test yes = "$_G_HAVE_ARITH_OP"; then eval 'func_arith () { $debug_cmd func_arith_result=$(( $* )) }' else func_arith () { $debug_cmd func_arith_result=`expr "$@"` } fi # func_basename FILE # ------------------ # Set func_basename_result to FILE with everything up to and including # the last / stripped. if test yes = "$_G_HAVE_XSI_OPS"; then # If this shell supports suffix pattern removal, then use it to avoid # forking. Hide the definitions single quotes in case the shell chokes # on unsupported syntax... _b='func_basename_result=${1##*/}' _d='case $1 in */*) func_dirname_result=${1%/*}$2 ;; * ) func_dirname_result=$3 ;; esac' else # ...otherwise fall back to using sed. _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` if test "X$func_dirname_result" = "X$1"; then func_dirname_result=$3 else func_append func_dirname_result "$2" fi' fi eval 'func_basename () { $debug_cmd '"$_b"' }' # func_dirname FILE APPEND NONDIR_REPLACEMENT # ------------------------------------------- # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. eval 'func_dirname () { $debug_cmd '"$_d"' }' # func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT # -------------------------------------------------------- # Perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # For efficiency, we do not delegate to the functions above but instead # duplicate the functionality here. eval 'func_dirname_and_basename () { $debug_cmd '"$_b"' '"$_d"' }' # func_echo ARG... # ---------------- # Echo program name prefixed message. func_echo () { $debug_cmd _G_message=$* func_echo_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_IFS $ECHO "$progname: $_G_line" done IFS=$func_echo_IFS } # func_echo_all ARG... # -------------------- # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } # func_echo_infix_1 INFIX ARG... # ------------------------------ # Echo program name, followed by INFIX on the first line, with any # additional lines not showing INFIX. func_echo_infix_1 () { $debug_cmd $require_term_colors _G_infix=$1; shift _G_indent=$_G_infix _G_prefix="$progname: $_G_infix: " _G_message=$* # Strip color escape sequences before counting printable length for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" do test -n "$_G_tc" && { _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` } done _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes func_echo_infix_1_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_infix_1_IFS $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 _G_prefix=$_G_indent done IFS=$func_echo_infix_1_IFS } # func_error ARG... # ----------------- # Echo program name prefixed message to standard error. func_error () { $debug_cmd $require_term_colors func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 } # func_fatal_error ARG... # ----------------------- # Echo program name prefixed message to standard error, and exit. func_fatal_error () { $debug_cmd func_error "$*" exit $EXIT_FAILURE } # func_grep EXPRESSION FILENAME # ----------------------------- # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $debug_cmd $GREP "$1" "$2" >/dev/null 2>&1 } # func_len STRING # --------------- # Set func_len_result to the length of STRING. STRING may not # start with a hyphen. test -z "$_G_HAVE_XSI_OPS" \ && (eval 'x=a/b/c; test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ && _G_HAVE_XSI_OPS=yes if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_len () { $debug_cmd func_len_result=${#1} }' else func_len () { $debug_cmd func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` } fi # func_mkdir_p DIRECTORY-PATH # --------------------------- # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { $debug_cmd _G_directory_path=$1 _G_dir_list= if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then # Protect directory names starting with '-' case $_G_directory_path in -*) _G_directory_path=./$_G_directory_path ;; esac # While some portion of DIR does not yet exist... while test ! -d "$_G_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. _G_dir_list=$_G_directory_path:$_G_dir_list # If the last portion added has no slash in it, the list is done case $_G_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` done _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` func_mkdir_p_IFS=$IFS; IFS=: for _G_dir in $_G_dir_list; do IFS=$func_mkdir_p_IFS # mkdir can fail with a 'File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! $MKDIR "$_G_dir" 2>/dev/null || : done IFS=$func_mkdir_p_IFS # Bail out if we (or some other process) failed to create a directory. test -d "$_G_directory_path" || \ func_fatal_error "Failed to create '$1'" fi } # func_mktempdir [BASENAME] # ------------------------- # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, BASENAME is the basename for that directory. func_mktempdir () { $debug_cmd _G_template=${TMPDIR-/tmp}/${1-$progname} if test : = "$opt_dry_run"; then # Return a directory name, but don't create it in dry-run mode _G_tmpdir=$_G_template-$$ else # If mktemp works, use that first and foremost _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` if test ! -d "$_G_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race _G_tmpdir=$_G_template-${RANDOM-0}$$ func_mktempdir_umask=`umask` umask 0077 $MKDIR "$_G_tmpdir" umask $func_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$_G_tmpdir" || \ func_fatal_error "cannot create temporary directory '$_G_tmpdir'" fi $ECHO "$_G_tmpdir" } # func_normal_abspath PATH # ------------------------ # Remove doubled-up and trailing slashes, "." path components, # and cancel out any ".." path components in PATH after making # it an absolute path. func_normal_abspath () { $debug_cmd # These SED scripts presuppose an absolute path with a trailing slash. _G_pathcar='s|^/\([^/]*\).*$|\1|' _G_pathcdr='s|^/[^/]*||' _G_removedotparts=':dotsl s|/\./|/|g t dotsl s|/\.$|/|' _G_collapseslashes='s|/\{1,\}|/|g' _G_finalslash='s|/*$|/|' # Start from root dir and reassemble the path. func_normal_abspath_result= func_normal_abspath_tpath=$1 func_normal_abspath_altnamespace= case $func_normal_abspath_tpath in "") # Empty path, that just means $cwd. func_stripname '' '/' "`pwd`" func_normal_abspath_result=$func_stripname_result return ;; # The next three entries are used to spot a run of precisely # two leading slashes without using negated character classes; # we take advantage of case's first-match behaviour. ///*) # Unusual form of absolute path, do nothing. ;; //*) # Not necessarily an ordinary path; POSIX reserves leading '//' # and for example Cygwin uses it to access remote file shares # over CIFS/SMB, so we conserve a leading double slash if found. func_normal_abspath_altnamespace=/ ;; /*) # Absolute path, do nothing. ;; *) # Relative path, prepend $cwd. func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath ;; esac # Cancel out all the simple stuff to save iterations. We also want # the path to end with a slash for ease of parsing, so make sure # there is one (and only one) here. func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` while :; do # Processed it all yet? if test / = "$func_normal_abspath_tpath"; then # If we ascended to the root using ".." the result may be empty now. if test -z "$func_normal_abspath_result"; then func_normal_abspath_result=/ fi break fi func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_pathcar"` func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_pathcdr"` # Figure out what to do with it case $func_normal_abspath_tcomponent in "") # Trailing empty path component, ignore it. ;; ..) # Parent dir; strip last assembled component from result. func_dirname "$func_normal_abspath_result" func_normal_abspath_result=$func_dirname_result ;; *) # Actual path component, append it. func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" ;; esac done # Restore leading double-slash if one was found on entry. func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result } # func_notquiet ARG... # -------------------- # Echo program name prefixed message only when not in quiet mode. func_notquiet () { $debug_cmd $opt_quiet || func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to # work around that: : } # func_relative_path SRCDIR DSTDIR # -------------------------------- # Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. func_relative_path () { $debug_cmd func_relative_path_result= func_normal_abspath "$1" func_relative_path_tlibdir=$func_normal_abspath_result func_normal_abspath "$2" func_relative_path_tbindir=$func_normal_abspath_result # Ascend the tree starting from libdir while :; do # check if we have found a prefix of bindir case $func_relative_path_tbindir in $func_relative_path_tlibdir) # found an exact match func_relative_path_tcancelled= break ;; $func_relative_path_tlibdir*) # found a matching prefix func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" func_relative_path_tcancelled=$func_stripname_result if test -z "$func_relative_path_result"; then func_relative_path_result=. fi break ;; *) func_dirname $func_relative_path_tlibdir func_relative_path_tlibdir=$func_dirname_result if test -z "$func_relative_path_tlibdir"; then # Have to descend all the way to the root! func_relative_path_result=../$func_relative_path_result func_relative_path_tcancelled=$func_relative_path_tbindir break fi func_relative_path_result=../$func_relative_path_result ;; esac done # Now calculate path; take care to avoid doubling-up slashes. func_stripname '' '/' "$func_relative_path_result" func_relative_path_result=$func_stripname_result func_stripname '/' '/' "$func_relative_path_tcancelled" if test -n "$func_stripname_result"; then func_append func_relative_path_result "/$func_stripname_result" fi # Normalisation. If bindir is libdir, return '.' else relative path. if test -n "$func_relative_path_result"; then func_stripname './' '' "$func_relative_path_result" func_relative_path_result=$func_stripname_result fi test -n "$func_relative_path_result" || func_relative_path_result=. : } # func_quote_for_eval ARG... # -------------------------- # Aesthetically quote ARGs to be evaled later. # This function returns two values: # i) func_quote_for_eval_result # double-quoted, suitable for a subsequent eval # ii) func_quote_for_eval_unquoted_result # has all characters that are still active within double # quotes backslashified. func_quote_for_eval () { $debug_cmd func_quote_for_eval_unquoted_result= func_quote_for_eval_result= while test 0 -lt $#; do case $1 in *[\\\`\"\$]*) _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; *) _G_unquoted_arg=$1 ;; esac if test -n "$func_quote_for_eval_unquoted_result"; then func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" else func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" fi case $_G_unquoted_arg in # Double-quote args containing shell metacharacters to delay # word splitting, command substitution and variable expansion # for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") _G_quoted_arg=\"$_G_unquoted_arg\" ;; *) _G_quoted_arg=$_G_unquoted_arg ;; esac if test -n "$func_quote_for_eval_result"; then func_append func_quote_for_eval_result " $_G_quoted_arg" else func_append func_quote_for_eval_result "$_G_quoted_arg" fi shift done } # func_quote_for_expand ARG # ------------------------- # Aesthetically quote ARG to be evaled later; same as above, # but do not quote variable references. func_quote_for_expand () { $debug_cmd case $1 in *[\\\`\"]*) _G_arg=`$ECHO "$1" | $SED \ -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; *) _G_arg=$1 ;; esac case $_G_arg in # Double-quote args containing shell metacharacters to delay # word splitting and command substitution for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") _G_arg=\"$_G_arg\" ;; esac func_quote_for_expand_result=$_G_arg } # func_stripname PREFIX SUFFIX NAME # --------------------------------- # strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_stripname () { $debug_cmd # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary variable first. func_stripname_result=$3 func_stripname_result=${func_stripname_result#"$1"} func_stripname_result=${func_stripname_result%"$2"} }' else func_stripname () { $debug_cmd case $2 in .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; esac } fi # func_show_eval CMD [FAIL_EXP] # ----------------------------- # Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { $debug_cmd _G_cmd=$1 _G_fail_exp=${2-':'} func_quote_for_expand "$_G_cmd" eval "func_notquiet $func_quote_for_expand_result" $opt_dry_run || { eval "$_G_cmd" _G_status=$? if test 0 -ne "$_G_status"; then eval "(exit $_G_status); $_G_fail_exp" fi } } # func_show_eval_locale CMD [FAIL_EXP] # ------------------------------------ # Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { $debug_cmd _G_cmd=$1 _G_fail_exp=${2-':'} $opt_quiet || { func_quote_for_expand "$_G_cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || { eval "$_G_user_locale $_G_cmd" _G_status=$? eval "$_G_safe_locale" if test 0 -ne "$_G_status"; then eval "(exit $_G_status); $_G_fail_exp" fi } } # func_tr_sh # ---------- # Turn $1 into a string suitable for a shell variable name. # Result is stored in $func_tr_sh_result. All characters # not in the set a-zA-Z0-9_ are replaced with '_'. Further, # if $1 begins with a digit, a '_' is prepended as well. func_tr_sh () { $debug_cmd case $1 in [0-9]* | *[!a-zA-Z0-9_]*) func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` ;; * ) func_tr_sh_result=$1 ;; esac } # func_verbose ARG... # ------------------- # Echo program name prefixed message in verbose mode only. func_verbose () { $debug_cmd $opt_verbose && func_echo "$*" : } # func_warn_and_continue ARG... # ----------------------------- # Echo program name prefixed warning message to standard error. func_warn_and_continue () { $debug_cmd $require_term_colors func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 } # func_warning CATEGORY ARG... # ---------------------------- # Echo program name prefixed warning message to standard error. Warning # messages can be filtered according to CATEGORY, where this function # elides messages where CATEGORY is not listed in the global variable # 'opt_warning_types'. func_warning () { $debug_cmd # CATEGORY must be in the warning_categories list! case " $warning_categories " in *" $1 "*) ;; *) func_internal_error "invalid warning category '$1'" ;; esac _G_category=$1 shift case " $opt_warning_types " in *" $_G_category "*) $warning_func ${1+"$@"} ;; esac } # func_sort_ver VER1 VER2 # ----------------------- # 'sort -V' is not generally available. # Note this deviates from the version comparison in automake # in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a # but this should suffice as we won't be specifying old # version formats or redundant trailing .0 in bootstrap.conf. # If we did want full compatibility then we should probably # use m4_version_compare from autoconf. func_sort_ver () { $debug_cmd printf '%s\n%s\n' "$1" "$2" \ | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n } # func_lt_ver PREV CURR # --------------------- # Return true if PREV and CURR are in the correct order according to # func_sort_ver, otherwise false. Use it like this: # # func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." func_lt_ver () { $debug_cmd test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` } # Local variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" # time-stamp-time-zone: "UTC" # End: #! /bin/sh # Set a version string for this script. scriptversion=2014-01-07.03; # UTC # A portable, pluggable option parser for Bourne shell. # Written by Gary V. Vaughan, 2010 # Copyright (C) 2010-2015 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # Please report bugs or propose patches to gary@gnu.org. ## ------ ## ## Usage. ## ## ------ ## # This file is a library for parsing options in your shell scripts along # with assorted other useful supporting features that you can make use # of too. # # For the simplest scripts you might need only: # # #!/bin/sh # . relative/path/to/funclib.sh # . relative/path/to/options-parser # scriptversion=1.0 # func_options ${1+"$@"} # eval set dummy "$func_options_result"; shift # ...rest of your script... # # In order for the '--version' option to work, you will need to have a # suitably formatted comment like the one at the top of this file # starting with '# Written by ' and ending with '# warranty; '. # # For '-h' and '--help' to work, you will also need a one line # description of your script's purpose in a comment directly above the # '# Written by ' line, like the one at the top of this file. # # The default options also support '--debug', which will turn on shell # execution tracing (see the comment above debug_cmd below for another # use), and '--verbose' and the func_verbose function to allow your script # to display verbose messages only when your user has specified # '--verbose'. # # After sourcing this file, you can plug processing for additional # options by amending the variables from the 'Configuration' section # below, and following the instructions in the 'Option parsing' # section further down. ## -------------- ## ## Configuration. ## ## -------------- ## # You should override these variables in your script after sourcing this # file so that they reflect the customisations you have added to the # option parser. # The usage line for option parsing errors and the start of '-h' and # '--help' output messages. You can embed shell variables for delayed # expansion at the time the message is displayed, but you will need to # quote other shell meta-characters carefully to prevent them being # expanded when the contents are evaled. usage='$progpath [OPTION]...' # Short help message in response to '-h' and '--help'. Add to this or # override it after sourcing this library to reflect the full set of # options your script accepts. usage_message="\ --debug enable verbose shell tracing -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] -v, --verbose verbosely report processing --version print version information and exit -h, --help print short or long help message and exit " # Additional text appended to 'usage_message' in response to '--help'. long_help_message=" Warning categories include: 'all' show all warnings 'none' turn off all the warnings 'error' warnings are treated as fatal errors" # Help message printed before fatal option parsing errors. fatal_help="Try '\$progname --help' for more information." ## ------------------------- ## ## Hook function management. ## ## ------------------------- ## # This section contains functions for adding, removing, and running hooks # to the main code. A hook is just a named list of of function, that can # be run in order later on. # func_hookable FUNC_NAME # ----------------------- # Declare that FUNC_NAME will run hooks added with # 'func_add_hook FUNC_NAME ...'. func_hookable () { $debug_cmd func_append hookable_fns " $1" } # func_add_hook FUNC_NAME HOOK_FUNC # --------------------------------- # Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must # first have been declared "hookable" by a call to 'func_hookable'. func_add_hook () { $debug_cmd case " $hookable_fns " in *" $1 "*) ;; *) func_fatal_error "'$1' does not accept hook functions." ;; esac eval func_append ${1}_hooks '" $2"' } # func_remove_hook FUNC_NAME HOOK_FUNC # ------------------------------------ # Remove HOOK_FUNC from the list of functions called by FUNC_NAME. func_remove_hook () { $debug_cmd eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' } # func_run_hooks FUNC_NAME [ARG]... # --------------------------------- # Run all hook functions registered to FUNC_NAME. # It is assumed that the list of hook functions contains nothing more # than a whitespace-delimited list of legal shell function names, and # no effort is wasted trying to catch shell meta-characters or preserve # whitespace. func_run_hooks () { $debug_cmd case " $hookable_fns " in *" $1 "*) ;; *) func_fatal_error "'$1' does not support hook funcions.n" ;; esac eval _G_hook_fns=\$$1_hooks; shift for _G_hook in $_G_hook_fns; do eval $_G_hook '"$@"' # store returned options list back into positional # parameters for next 'cmd' execution. eval _G_hook_result=\$${_G_hook}_result eval set dummy "$_G_hook_result"; shift done func_quote_for_eval ${1+"$@"} func_run_hooks_result=$func_quote_for_eval_result } ## --------------- ## ## Option parsing. ## ## --------------- ## # In order to add your own option parsing hooks, you must accept the # full positional parameter list in your hook function, remove any # options that you action, and then pass back the remaining unprocessed # options in '_result', escaped suitably for # 'eval'. Like this: # # my_options_prep () # { # $debug_cmd # # # Extend the existing usage message. # usage_message=$usage_message' # -s, --silent don'\''t print informational messages # ' # # func_quote_for_eval ${1+"$@"} # my_options_prep_result=$func_quote_for_eval_result # } # func_add_hook func_options_prep my_options_prep # # # my_silent_option () # { # $debug_cmd # # # Note that for efficiency, we parse as many options as we can # # recognise in a loop before passing the remainder back to the # # caller on the first unrecognised argument we encounter. # while test $# -gt 0; do # opt=$1; shift # case $opt in # --silent|-s) opt_silent=: ;; # # Separate non-argument short options: # -s*) func_split_short_opt "$_G_opt" # set dummy "$func_split_short_opt_name" \ # "-$func_split_short_opt_arg" ${1+"$@"} # shift # ;; # *) set dummy "$_G_opt" "$*"; shift; break ;; # esac # done # # func_quote_for_eval ${1+"$@"} # my_silent_option_result=$func_quote_for_eval_result # } # func_add_hook func_parse_options my_silent_option # # # my_option_validation () # { # $debug_cmd # # $opt_silent && $opt_verbose && func_fatal_help "\ # '--silent' and '--verbose' options are mutually exclusive." # # func_quote_for_eval ${1+"$@"} # my_option_validation_result=$func_quote_for_eval_result # } # func_add_hook func_validate_options my_option_validation # # You'll alse need to manually amend $usage_message to reflect the extra # options you parse. It's preferable to append if you can, so that # multiple option parsing hooks can be added safely. # func_options [ARG]... # --------------------- # All the functions called inside func_options are hookable. See the # individual implementations for details. func_hookable func_options func_options () { $debug_cmd func_options_prep ${1+"$@"} eval func_parse_options \ ${func_options_prep_result+"$func_options_prep_result"} eval func_validate_options \ ${func_parse_options_result+"$func_parse_options_result"} eval func_run_hooks func_options \ ${func_validate_options_result+"$func_validate_options_result"} # save modified positional parameters for caller func_options_result=$func_run_hooks_result } # func_options_prep [ARG]... # -------------------------- # All initialisations required before starting the option parse loop. # Note that when calling hook functions, we pass through the list of # positional parameters. If a hook function modifies that list, and # needs to propogate that back to rest of this script, then the complete # modified list must be put in 'func_run_hooks_result' before # returning. func_hookable func_options_prep func_options_prep () { $debug_cmd # Option defaults: opt_verbose=false opt_warning_types= func_run_hooks func_options_prep ${1+"$@"} # save modified positional parameters for caller func_options_prep_result=$func_run_hooks_result } # func_parse_options [ARG]... # --------------------------- # The main option parsing loop. func_hookable func_parse_options func_parse_options () { $debug_cmd func_parse_options_result= # this just eases exit handling while test $# -gt 0; do # Defer to hook functions for initial option parsing, so they # get priority in the event of reusing an option name. func_run_hooks func_parse_options ${1+"$@"} # Adjust func_parse_options positional parameters to match eval set dummy "$func_run_hooks_result"; shift # Break out of the loop if we already parsed every option. test $# -gt 0 || break _G_opt=$1 shift case $_G_opt in --debug|-x) debug_cmd='set -x' func_echo "enabling shell trace mode" $debug_cmd ;; --no-warnings|--no-warning|--no-warn) set dummy --warnings none ${1+"$@"} shift ;; --warnings|--warning|-W) test $# = 0 && func_missing_arg $_G_opt && break case " $warning_categories $1" in *" $1 "*) # trailing space prevents matching last $1 above func_append_uniq opt_warning_types " $1" ;; *all) opt_warning_types=$warning_categories ;; *none) opt_warning_types=none warning_func=: ;; *error) opt_warning_types=$warning_categories warning_func=func_fatal_error ;; *) func_fatal_error \ "unsupported warning category: '$1'" ;; esac shift ;; --verbose|-v) opt_verbose=: ;; --version) func_version ;; -\?|-h) func_usage ;; --help) func_help ;; # Separate optargs to long options (plugins may need this): --*=*) func_split_equals "$_G_opt" set dummy "$func_split_equals_lhs" \ "$func_split_equals_rhs" ${1+"$@"} shift ;; # Separate optargs to short options: -W*) func_split_short_opt "$_G_opt" set dummy "$func_split_short_opt_name" \ "$func_split_short_opt_arg" ${1+"$@"} shift ;; # Separate non-argument short options: -\?*|-h*|-v*|-x*) func_split_short_opt "$_G_opt" set dummy "$func_split_short_opt_name" \ "-$func_split_short_opt_arg" ${1+"$@"} shift ;; --) break ;; -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; esac done # save modified positional parameters for caller func_quote_for_eval ${1+"$@"} func_parse_options_result=$func_quote_for_eval_result } # func_validate_options [ARG]... # ------------------------------ # Perform any sanity checks on option settings and/or unconsumed # arguments. func_hookable func_validate_options func_validate_options () { $debug_cmd # Display all warnings if -W was not given. test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" func_run_hooks func_validate_options ${1+"$@"} # Bail if the options were screwed! $exit_cmd $EXIT_FAILURE # save modified positional parameters for caller func_validate_options_result=$func_run_hooks_result } ## ----------------- ## ## Helper functions. ## ## ----------------- ## # This section contains the helper functions used by the rest of the # hookable option parser framework in ascii-betical order. # func_fatal_help ARG... # ---------------------- # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { $debug_cmd eval \$ECHO \""Usage: $usage"\" eval \$ECHO \""$fatal_help"\" func_error ${1+"$@"} exit $EXIT_FAILURE } # func_help # --------- # Echo long help message to standard output and exit. func_help () { $debug_cmd func_usage_message $ECHO "$long_help_message" exit 0 } # func_missing_arg ARGNAME # ------------------------ # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { $debug_cmd func_error "Missing argument for '$1'." exit_cmd=exit } # func_split_equals STRING # ------------------------ # Set func_split_equals_lhs and func_split_equals_rhs shell variables after # splitting STRING at the '=' sign. test -z "$_G_HAVE_XSI_OPS" \ && (eval 'x=a/b/c; test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ && _G_HAVE_XSI_OPS=yes if test yes = "$_G_HAVE_XSI_OPS" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_split_equals () { $debug_cmd func_split_equals_lhs=${1%%=*} func_split_equals_rhs=${1#*=} test "x$func_split_equals_lhs" = "x$1" \ && func_split_equals_rhs= }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_split_equals () { $debug_cmd func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` func_split_equals_rhs= test "x$func_split_equals_lhs" = "x$1" \ || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` } fi #func_split_equals # func_split_short_opt SHORTOPT # ----------------------------- # Set func_split_short_opt_name and func_split_short_opt_arg shell # variables after splitting SHORTOPT after the 2nd character. if test yes = "$_G_HAVE_XSI_OPS" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_split_short_opt () { $debug_cmd func_split_short_opt_arg=${1#??} func_split_short_opt_name=${1%"$func_split_short_opt_arg"} }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_split_short_opt () { $debug_cmd func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` } fi #func_split_short_opt # func_usage # ---------- # Echo short help message to standard output and exit. func_usage () { $debug_cmd func_usage_message $ECHO "Run '$progname --help |${PAGER-more}' for full usage" exit 0 } # func_usage_message # ------------------ # Echo short help message to standard output. func_usage_message () { $debug_cmd eval \$ECHO \""Usage: $usage"\" echo $SED -n 's|^# || /^Written by/{ x;p;x } h /^Written by/q' < "$progpath" echo eval \$ECHO \""$usage_message"\" } # func_version # ------------ # Echo version message to standard output and exit. func_version () { $debug_cmd printf '%s\n' "$progname $scriptversion" $SED -n ' /(C)/!b go :more /\./!{ N s|\n# | | b more } :go /^# Written by /,/# warranty; / { s|^# || s|^# *$|| s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| p } /^# Written by / { s|^# || p } /^warranty; /q' < "$progpath" exit $? } # Local variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" # time-stamp-time-zone: "UTC" # End: # Set a version string. scriptversion='(GNU libtool) 2.4.6' # func_echo ARG... # ---------------- # Libtool also displays the current mode in messages, so override # funclib.sh func_echo with this custom definition. func_echo () { $debug_cmd _G_message=$* func_echo_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_IFS $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" done IFS=$func_echo_IFS } # func_warning ARG... # ------------------- # Libtool warnings are not categorized, so override funclib.sh # func_warning with this simpler definition. func_warning () { $debug_cmd $warning_func ${1+"$@"} } ## ---------------- ## ## Options parsing. ## ## ---------------- ## # Hook in the functions to make sure our own options are parsed during # the option parsing loop. usage='$progpath [OPTION]... [MODE-ARG]...' # Short help message in response to '-h'. usage_message="Options: --config show all configuration variables --debug enable verbose shell tracing -n, --dry-run display commands without modifying any files --features display basic configuration information and exit --mode=MODE use operation mode MODE --no-warnings equivalent to '-Wnone' --preserve-dup-deps don't remove duplicate dependency libraries --quiet, --silent don't print informational messages --tag=TAG use configuration variables from tag TAG -v, --verbose print more informational messages than default --version print version information -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] -h, --help, --help-all print short, long, or detailed help message " # Additional text appended to 'usage_message' in response to '--help'. func_help () { $debug_cmd func_usage_message $ECHO "$long_help_message MODE must be one of the following: clean remove files from the build directory compile compile a source file into a libtool object execute automatically set library path, then run a program finish complete the installation of libtool libraries install install libraries or executables link create a library or an executable uninstall remove libraries from an installed directory MODE-ARGS vary depending on the MODE. When passed as first option, '--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. Try '$progname --help --mode=MODE' for a more detailed description of MODE. When reporting a bug, please describe a test case to reproduce it and include the following information: host-triplet: $host shell: $SHELL compiler: $LTCC compiler flags: $LTCFLAGS linker: $LD (gnu? $with_gnu_ld) version: $progname $scriptversion Debian-2.4.6-2 automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` Report bugs to . GNU libtool home page: . General help using GNU software: ." exit 0 } # func_lo2o OBJECT-NAME # --------------------- # Transform OBJECT-NAME from a '.lo' suffix to the platform specific # object suffix. lo2o=s/\\.lo\$/.$objext/ o2lo=s/\\.$objext\$/.lo/ if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_lo2o () { case $1 in *.lo) func_lo2o_result=${1%.lo}.$objext ;; * ) func_lo2o_result=$1 ;; esac }' # func_xform LIBOBJ-OR-SOURCE # --------------------------- # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) # suffix to a '.lo' libtool-object suffix. eval 'func_xform () { func_xform_result=${1%.*}.lo }' else # ...otherwise fall back to using sed. func_lo2o () { func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` } func_xform () { func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` } fi # func_fatal_configuration ARG... # ------------------------------- # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. func_fatal_configuration () { func__fatal_error ${1+"$@"} \ "See the $PACKAGE documentation for more information." \ "Fatal configuration error." } # func_config # ----------- # Display the configuration for all the tags in this script. func_config () { re_begincf='^# ### BEGIN LIBTOOL' re_endcf='^# ### END LIBTOOL' # Default configuration. $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" # Now print the configurations for the tags. for tagname in $taglist; do $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" done exit $? } # func_features # ------------- # Display the features supported by this script. func_features () { echo "host: $host" if test yes = "$build_libtool_libs"; then echo "enable shared libraries" else echo "disable shared libraries" fi if test yes = "$build_old_libs"; then echo "enable static libraries" else echo "disable static libraries" fi exit $? } # func_enable_tag TAGNAME # ----------------------- # Verify that TAGNAME is valid, and either flag an error and exit, or # enable the TAGNAME tag. We also add TAGNAME to the global $taglist # variable here. func_enable_tag () { # Global variable: tagname=$1 re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" sed_extractcf=/$re_begincf/,/$re_endcf/p # Validate tagname. case $tagname in *[!-_A-Za-z0-9,/]*) func_fatal_error "invalid tag name: $tagname" ;; esac # Don't test for the "default" C tag, as we know it's # there but not specially marked. case $tagname in CC) ;; *) if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then taglist="$taglist $tagname" # Evaluate the configuration. Be careful to quote the path # and the sed script, to avoid splitting on whitespace, but # also don't use non-portable quotes within backquotes within # quotes we have to do it in 2 steps: extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` eval "$extractedcf" else func_error "ignoring unknown tag $tagname" fi ;; esac } # func_check_version_match # ------------------------ # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { if test "$package_revision" != "$macro_revision"; then if test "$VERSION" != "$macro_version"; then if test -z "$macro_version"; then cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF fi else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF fi exit $EXIT_MISMATCH fi } # libtool_options_prep [ARG]... # ----------------------------- # Preparation for options parsed by libtool. libtool_options_prep () { $debug_mode # Option defaults: opt_config=false opt_dlopen= opt_dry_run=false opt_help=false opt_mode= opt_preserve_dup_deps=false opt_quiet=false nonopt= preserve_args= # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) shift; set dummy --mode clean ${1+"$@"}; shift ;; compile|compil|compi|comp|com|co|c) shift; set dummy --mode compile ${1+"$@"}; shift ;; execute|execut|execu|exec|exe|ex|e) shift; set dummy --mode execute ${1+"$@"}; shift ;; finish|finis|fini|fin|fi|f) shift; set dummy --mode finish ${1+"$@"}; shift ;; install|instal|insta|inst|ins|in|i) shift; set dummy --mode install ${1+"$@"}; shift ;; link|lin|li|l) shift; set dummy --mode link ${1+"$@"}; shift ;; uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; esac # Pass back the list of options. func_quote_for_eval ${1+"$@"} libtool_options_prep_result=$func_quote_for_eval_result } func_add_hook func_options_prep libtool_options_prep # libtool_parse_options [ARG]... # --------------------------------- # Provide handling for libtool specific options. libtool_parse_options () { $debug_cmd # Perform our own loop to consume as many options as possible in # each iteration. while test $# -gt 0; do _G_opt=$1 shift case $_G_opt in --dry-run|--dryrun|-n) opt_dry_run=: ;; --config) func_config ;; --dlopen|-dlopen) opt_dlopen="${opt_dlopen+$opt_dlopen }$1" shift ;; --preserve-dup-deps) opt_preserve_dup_deps=: ;; --features) func_features ;; --finish) set dummy --mode finish ${1+"$@"}; shift ;; --help) opt_help=: ;; --help-all) opt_help=': help-all' ;; --mode) test $# = 0 && func_missing_arg $_G_opt && break opt_mode=$1 case $1 in # Valid mode arguments: clean|compile|execute|finish|install|link|relink|uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $_G_opt" exit_cmd=exit break ;; esac shift ;; --no-silent|--no-quiet) opt_quiet=false func_append preserve_args " $_G_opt" ;; --no-warnings|--no-warning|--no-warn) opt_warning=false func_append preserve_args " $_G_opt" ;; --no-verbose) opt_verbose=false func_append preserve_args " $_G_opt" ;; --silent|--quiet) opt_quiet=: opt_verbose=false func_append preserve_args " $_G_opt" ;; --tag) test $# = 0 && func_missing_arg $_G_opt && break opt_tag=$1 func_append preserve_args " $_G_opt $1" func_enable_tag "$1" shift ;; --verbose|-v) opt_quiet=false opt_verbose=: func_append preserve_args " $_G_opt" ;; # An option not handled by this hook function: *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; esac done # save modified positional parameters for caller func_quote_for_eval ${1+"$@"} libtool_parse_options_result=$func_quote_for_eval_result } func_add_hook func_parse_options libtool_parse_options # libtool_validate_options [ARG]... # --------------------------------- # Perform any sanity checks on option settings and/or unconsumed # arguments. libtool_validate_options () { # save first non-option argument if test 0 -lt $#; then nonopt=$1 shift fi # preserve --debug test : = "$debug_cmd" || func_append preserve_args " --debug" case $host in # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) # don't eliminate duplications in $postdeps and $predeps opt_duplicate_compiler_generated_deps=: ;; *) opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps ;; esac $opt_help || { # Sanity checks first: func_check_version_match test yes != "$build_libtool_libs" \ && test yes != "$build_old_libs" \ && func_fatal_configuration "not configured to build any kind of library" # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$opt_dlopen" && test execute != "$opt_mode"; then func_error "unrecognized option '-dlopen'" $ECHO "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help=$help help="Try '$progname --help --mode=$opt_mode' for more information." } # Pass back the unparsed argument list func_quote_for_eval ${1+"$@"} libtool_validate_options_result=$func_quote_for_eval_result } func_add_hook func_validate_options libtool_validate_options # Process options as early as possible so that --help and --version # can return quickly. func_options ${1+"$@"} eval set dummy "$func_options_result"; shift ## ----------- ## ## Main. ## ## ----------- ## magic='%%%MAGIC variable%%%' magic_exe='%%%MAGIC EXE variable%%%' # Global variables. extracted_archives= extracted_serial=0 # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } # func_generated_by_libtool # True iff stdin has been generated by Libtool. This function is only # a basic sanity check; it will hardly flush out determined imposters. func_generated_by_libtool_p () { $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_p file # True iff FILE is a libtool '.la' library or '.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p } # func_lalib_unsafe_p file # True iff FILE is a libtool '.la' library or '.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be # fatal anyway. Works if 'file' does not exist. func_lalib_unsafe_p () { lalib_p=no if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line case $lalib_p_line in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi test yes = "$lalib_p" } # func_ltwrapper_script_p file # True iff FILE is a libtool wrapper script # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_script_p () { test -f "$1" && $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p } # func_ltwrapper_executable_p file # True iff FILE is a libtool wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_executable_p () { func_ltwrapper_exec_suffix= case $1 in *.exe) ;; *) func_ltwrapper_exec_suffix=.exe ;; esac $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 } # func_ltwrapper_scriptname file # Assumes file is an ltwrapper_executable # uses $file to determine the appropriate filename for a # temporary ltwrapper_script. func_ltwrapper_scriptname () { func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper } # func_ltwrapper_p file # True iff FILE is a libtool wrapper script or wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_p () { func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" } # func_execute_cmds commands fail_cmd # Execute tilde-delimited COMMANDS. # If FAIL_CMD is given, eval that upon failure. # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { $debug_cmd save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$sp$nl eval cmd=\"$cmd\" IFS=$save_ifs func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs } # func_source file # Source FILE, adding directory component if necessary. # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # 'FILE.' does not work on cygwin managed mounts. func_source () { $debug_cmd case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; esac } # func_resolve_sysroot PATH # Replace a leading = in PATH with a sysroot. Store the result into # func_resolve_sysroot_result func_resolve_sysroot () { func_resolve_sysroot_result=$1 case $func_resolve_sysroot_result in =*) func_stripname '=' '' "$func_resolve_sysroot_result" func_resolve_sysroot_result=$lt_sysroot$func_stripname_result ;; esac } # func_replace_sysroot PATH # If PATH begins with the sysroot, replace it with = and # store the result into func_replace_sysroot_result. func_replace_sysroot () { case $lt_sysroot:$1 in ?*:"$lt_sysroot"*) func_stripname "$lt_sysroot" '' "$1" func_replace_sysroot_result='='$func_stripname_result ;; *) # Including no sysroot. func_replace_sysroot_result=$1 ;; esac } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { $debug_cmd if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case "$@ " in " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" func_fatal_error "specify a tag with '--tag'" # else # func_verbose "using $tagname tagged configuration" fi ;; esac fi } # func_write_libtool_object output_name pic_name nonpic_name # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. func_write_libtool_object () { write_libobj=$1 if test yes = "$build_libtool_libs"; then write_lobj=\'$2\' else write_lobj=none fi if test yes = "$build_old_libs"; then write_oldobj=\'$3\' else write_oldobj=none fi $opt_dry_run || { cat >${write_libobj}T </dev/null` if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | $SED -e "$sed_naive_backslashify"` else func_convert_core_file_wine_to_w32_result= fi fi } # end: func_convert_core_file_wine_to_w32 # func_convert_core_path_wine_to_w32 ARG # Helper function used by path conversion functions when $build is *nix, and # $host is mingw, cygwin, or some other w32 environment. Relies on a correctly # configured wine environment available, with the winepath program in $build's # $PATH. Assumes ARG has no leading or trailing path separator characters. # # ARG is path to be converted from $build format to win32. # Result is available in $func_convert_core_path_wine_to_w32_result. # Unconvertible file (directory) names in ARG are skipped; if no directory names # are convertible, then the result may be empty. func_convert_core_path_wine_to_w32 () { $debug_cmd # unfortunately, winepath doesn't convert paths, only file names func_convert_core_path_wine_to_w32_result= if test -n "$1"; then oldIFS=$IFS IFS=: for func_convert_core_path_wine_to_w32_f in $1; do IFS=$oldIFS func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" if test -n "$func_convert_core_file_wine_to_w32_result"; then if test -z "$func_convert_core_path_wine_to_w32_result"; then func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result else func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" fi fi done IFS=$oldIFS fi } # end: func_convert_core_path_wine_to_w32 # func_cygpath ARGS... # Wrapper around calling the cygpath program via LT_CYGPATH. This is used when # when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) # $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or # (2), returns the Cygwin file name or path in func_cygpath_result (input # file name or path is assumed to be in w32 format, as previously converted # from $build's *nix or MSYS format). In case (3), returns the w32 file name # or path in func_cygpath_result (input file name or path is assumed to be in # Cygwin format). Returns an empty string on error. # # ARGS are passed to cygpath, with the last one being the file name or path to # be converted. # # Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH # environment variable; do not put it in $PATH. func_cygpath () { $debug_cmd if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` if test "$?" -ne 0; then # on failure, ensure result is empty func_cygpath_result= fi else func_cygpath_result= func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" fi } #end: func_cygpath # func_convert_core_msys_to_w32 ARG # Convert file name or path ARG from MSYS format to w32 format. Return # result in func_convert_core_msys_to_w32_result. func_convert_core_msys_to_w32 () { $debug_cmd # awkward: cmd appends spaces to result func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` } #end: func_convert_core_msys_to_w32 # func_convert_file_check ARG1 ARG2 # Verify that ARG1 (a file name in $build format) was converted to $host # format in ARG2. Otherwise, emit an error message, but continue (resetting # func_to_host_file_result to ARG1). func_convert_file_check () { $debug_cmd if test -z "$2" && test -n "$1"; then func_error "Could not determine host file name corresponding to" func_error " '$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_file_result=$1 fi } # end func_convert_file_check # func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH # Verify that FROM_PATH (a path in $build format) was converted to $host # format in TO_PATH. Otherwise, emit an error message, but continue, resetting # func_to_host_file_result to a simplistic fallback value (see below). func_convert_path_check () { $debug_cmd if test -z "$4" && test -n "$3"; then func_error "Could not determine the host path corresponding to" func_error " '$3'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This is a deliberately simplistic "conversion" and # should not be "improved". See libtool.info. if test "x$1" != "x$2"; then lt_replace_pathsep_chars="s|$1|$2|g" func_to_host_path_result=`echo "$3" | $SED -e "$lt_replace_pathsep_chars"` else func_to_host_path_result=$3 fi fi } # end func_convert_path_check # func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG # Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT # and appending REPL if ORIG matches BACKPAT. func_convert_path_front_back_pathsep () { $debug_cmd case $4 in $1 ) func_to_host_path_result=$3$func_to_host_path_result ;; esac case $4 in $2 ) func_append func_to_host_path_result "$3" ;; esac } # end func_convert_path_front_back_pathsep ################################################## # $build to $host FILE NAME CONVERSION FUNCTIONS # ################################################## # invoked via '$to_host_file_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # Result will be available in $func_to_host_file_result. # func_to_host_file ARG # Converts the file name ARG from $build format to $host format. Return result # in func_to_host_file_result. func_to_host_file () { $debug_cmd $to_host_file_cmd "$1" } # end func_to_host_file # func_to_tool_file ARG LAZY # converts the file name ARG from $build format to toolchain format. Return # result in func_to_tool_file_result. If the conversion in use is listed # in (the comma separated) LAZY, no conversion takes place. func_to_tool_file () { $debug_cmd case ,$2, in *,"$to_tool_file_cmd",*) func_to_tool_file_result=$1 ;; *) $to_tool_file_cmd "$1" func_to_tool_file_result=$func_to_host_file_result ;; esac } # end func_to_tool_file # func_convert_file_noop ARG # Copy ARG to func_to_host_file_result. func_convert_file_noop () { func_to_host_file_result=$1 } # end func_convert_file_noop # func_convert_file_msys_to_w32 ARG # Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_file_result. func_convert_file_msys_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_to_host_file_result=$func_convert_core_msys_to_w32_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_w32 # func_convert_file_cygwin_to_w32 ARG # Convert file name ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_file_cygwin_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then # because $build is cygwin, we call "the" cygpath in $PATH; no need to use # LT_CYGPATH in this case. func_to_host_file_result=`cygpath -m "$1"` fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_cygwin_to_w32 # func_convert_file_nix_to_w32 ARG # Convert file name ARG from *nix to w32 format. Requires a wine environment # and a working winepath. Returns result in func_to_host_file_result. func_convert_file_nix_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_file_wine_to_w32 "$1" func_to_host_file_result=$func_convert_core_file_wine_to_w32_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_w32 # func_convert_file_msys_to_cygwin ARG # Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_file_msys_to_cygwin () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_cygpath -u "$func_convert_core_msys_to_w32_result" func_to_host_file_result=$func_cygpath_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_cygwin # func_convert_file_nix_to_cygwin ARG # Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed # in a wine environment, working winepath, and LT_CYGPATH set. Returns result # in func_to_host_file_result. func_convert_file_nix_to_cygwin () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. func_convert_core_file_wine_to_w32 "$1" func_cygpath -u "$func_convert_core_file_wine_to_w32_result" func_to_host_file_result=$func_cygpath_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_cygwin ############################################# # $build to $host PATH CONVERSION FUNCTIONS # ############################################# # invoked via '$to_host_path_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # The result will be available in $func_to_host_path_result. # # Path separators are also converted from $build format to $host format. If # ARG begins or ends with a path separator character, it is preserved (but # converted to $host format) on output. # # All path conversion functions are named using the following convention: # file name conversion function : func_convert_file_X_to_Y () # path conversion function : func_convert_path_X_to_Y () # where, for any given $build/$host combination the 'X_to_Y' value is the # same. If conversion functions are added for new $build/$host combinations, # the two new functions must follow this pattern, or func_init_to_host_path_cmd # will break. # func_init_to_host_path_cmd # Ensures that function "pointer" variable $to_host_path_cmd is set to the # appropriate value, based on the value of $to_host_file_cmd. to_host_path_cmd= func_init_to_host_path_cmd () { $debug_cmd if test -z "$to_host_path_cmd"; then func_stripname 'func_convert_file_' '' "$to_host_file_cmd" to_host_path_cmd=func_convert_path_$func_stripname_result fi } # func_to_host_path ARG # Converts the path ARG from $build format to $host format. Return result # in func_to_host_path_result. func_to_host_path () { $debug_cmd func_init_to_host_path_cmd $to_host_path_cmd "$1" } # end func_to_host_path # func_convert_path_noop ARG # Copy ARG to func_to_host_path_result. func_convert_path_noop () { func_to_host_path_result=$1 } # end func_convert_path_noop # func_convert_path_msys_to_w32 ARG # Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_path_result. func_convert_path_msys_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # Remove leading and trailing path separator characters from ARG. MSYS # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; # and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result=$func_convert_core_msys_to_w32_result func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_msys_to_w32 # func_convert_path_cygwin_to_w32 ARG # Convert path ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_path_cygwin_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_cygwin_to_w32 # func_convert_path_nix_to_w32 ARG # Convert path ARG from *nix to w32 format. Requires a wine environment and # a working winepath. Returns result in func_to_host_file_result. func_convert_path_nix_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result=$func_convert_core_path_wine_to_w32_result func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_nix_to_w32 # func_convert_path_msys_to_cygwin ARG # Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_path_msys_to_cygwin () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_msys_to_w32_result" func_to_host_path_result=$func_cygpath_result func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_msys_to_cygwin # func_convert_path_nix_to_cygwin ARG # Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a # a wine environment, working winepath, and LT_CYGPATH set. Returns result in # func_to_host_file_result. func_convert_path_nix_to_cygwin () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" func_to_host_path_result=$func_cygpath_result func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_nix_to_cygwin # func_dll_def_p FILE # True iff FILE is a Windows DLL '.def' file. # Keep in sync with _LT_DLL_DEF_P in libtool.m4 func_dll_def_p () { $debug_cmd func_dll_def_p_tmp=`$SED -n \ -e 's/^[ ]*//' \ -e '/^\(;.*\)*$/d' \ -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ -e q \ "$1"` test DEF = "$func_dll_def_p_tmp" } # func_mode_compile arg... func_mode_compile () { $debug_cmd # Get the compilation command and the source file. base_compile= srcfile=$nonopt # always keep a non-empty value in "srcfile" suppress_opt=yes suppress_output= arg_mode=normal libobj= later= pie_flag= for arg do case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile lastarg=$arg arg_mode=normal ;; target ) libobj=$arg arg_mode=normal continue ;; normal ) # Accept any command-line options. case $arg in -o) test -n "$libobj" && \ func_fatal_error "you cannot specify '-o' more than once" arg_mode=target continue ;; -pie | -fpie | -fPIE) func_append pie_flag " $arg" continue ;; -shared | -static | -prefer-pic | -prefer-non-pic) func_append later " $arg" continue ;; -no-suppress) suppress_opt=no continue ;; -Xcompiler) arg_mode=arg # the next one goes into the "base_compile" arg list continue # The current "srcfile" will either be retained or ;; # replaced later. I would guess that would be a bug. -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result lastarg= save_ifs=$IFS; IFS=, for arg in $args; do IFS=$save_ifs func_append_quoted lastarg "$arg" done IFS=$save_ifs func_stripname ' ' '' "$lastarg" lastarg=$func_stripname_result # Add the arguments to base_compile. func_append base_compile " $lastarg" continue ;; *) # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # lastarg=$srcfile srcfile=$arg ;; esac # case $arg ;; esac # case $arg_mode # Aesthetically quote the previous argument. func_append_quoted base_compile "$lastarg" done # for arg case $arg_mode in arg) func_fatal_error "you must specify an argument for -Xcompile" ;; target) func_fatal_error "you must specify a target with '-o'" ;; *) # Get the name of the library object. test -z "$libobj" && { func_basename "$srcfile" libobj=$func_basename_result } ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo case $libobj in *.[cCFSifmso] | \ *.ada | *.adb | *.ads | *.asm | \ *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) func_xform "$libobj" libobj=$func_xform_result ;; esac case $libobj in *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; *) func_fatal_error "cannot determine name of library object from '$libobj'" ;; esac func_infer_tag $base_compile for arg in $later; do case $arg in -shared) test yes = "$build_libtool_libs" \ || func_fatal_configuration "cannot build a shared library" build_old_libs=no continue ;; -static) build_libtool_libs=no build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; esac done func_quote_for_eval "$libobj" test "X$libobj" != "X$func_quote_for_eval_result" \ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ && func_warning "libobj name '$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" objname=$func_basename_result xdir=$func_dirname_result lobj=$xdir$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. if test yes = "$build_old_libs"; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2* | cegcc*) pic_mode=default ;; esac if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test no = "$compiler_c_o"; then output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext lockfile=$output_obj.lock else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test yes = "$need_locks"; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done elif test warn = "$need_locks"; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi func_append removelist " $output_obj" $ECHO "$srcfile" > "$lockfile" fi $opt_dry_run || $RM $removelist func_append removelist " $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 srcfile=$func_to_tool_file_result func_quote_for_eval "$srcfile" qsrcfile=$func_quote_for_eval_result # Only build a PIC object if we are building libtool libraries. if test yes = "$build_libtool_libs"; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test no != "$pic_mode"; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code command="$base_compile $qsrcfile" fi func_mkdir_p "$xdir$objdir" if test -z "$output_obj"; then # Place PIC objects in $objdir func_append command " -o $lobj" fi func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' if test warn = "$need_locks" && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then func_show_eval '$MV "$output_obj" "$lobj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi # Allow error messages only from the first compilation. if test yes = "$suppress_opt"; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test yes = "$build_old_libs"; then if test yes != "$pic_mode"; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test yes = "$compiler_c_o"; then func_append command " -o $obj" fi # Suppress compiler output if we already did a PIC compilation. func_append command "$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' if test warn = "$need_locks" && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then func_show_eval '$MV "$output_obj" "$obj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi fi $opt_dry_run || { func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked if test no != "$need_locks"; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test compile = "$opt_mode" && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. case $opt_mode in "") # Generic help is extracted from the usage comments # at the start of this file. func_help ;; clean) $ECHO \ "Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $ECHO \ "Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to build PIC objects only -prefer-non-pic try to build non-PIC objects only -shared do not build a '.o' file suitable for static linking -static only build a '.o' file suitable for static linking -Wc,FLAG pass FLAG directly to the compiler COMPILE-COMMAND is a command to be used in creating a 'standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix '.c' with the library object suffix, '.lo'." ;; execute) $ECHO \ "Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to '-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $ECHO \ "Usage: $progname [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the '--dry-run' option if you just want to see what would be executed." ;; install) $ECHO \ "Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the 'install' or 'cp' program. The following components of INSTALL-COMMAND are treated specially: -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $ECHO \ "Usage: $progname [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -bindir BINDIR specify path to binaries directory (for systems where libraries must be found in the PATH setting at runtime) -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE use a list of object files found in FILE to specify objects -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -shared only do dynamic linking of libtool libraries -shrext SUFFIX override the standard shared library file extension -static do not do any dynamic linking of uninstalled libtool libraries -static-libtool-libs do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] -weak LIBNAME declare that the target provides the LIBNAME interface -Wc,FLAG -Xcompiler FLAG pass linker-specific FLAG directly to the compiler -Wl,FLAG -Xlinker FLAG pass linker-specific FLAG directly to the linker -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) All other options (arguments beginning with '-') are ignored. Every other argument is treated as a filename. Files ending in '.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in '.la', then a libtool library is created, only library objects ('.lo' files) may be specified, and '-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created using 'ar' and 'ranlib', or on Windows using 'lib'. If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $ECHO \ "Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) func_fatal_help "invalid operation mode '$opt_mode'" ;; esac echo $ECHO "Try '$progname --help' for more information about other modes." } # Now that we've collected a possible --mode arg, show help if necessary if $opt_help; then if test : = "$opt_help"; then func_mode_help else { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do func_mode_help done } | $SED -n '1p; 2,$s/^Usage:/ or: /p' { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do echo func_mode_help done } | $SED '1d /^When reporting/,/^Report/{ H d } $x /information about other modes/d /more detailed .*MODE/d s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' fi exit $? fi # func_mode_execute arg... func_mode_execute () { $debug_cmd # The first argument is the command name. cmd=$nonopt test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $opt_dlopen; do test -f "$file" \ || func_fatal_help "'$file' is not a file" dir= case $file in *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "'$lib' is not a valid libtool archive" # Read the libtool library. dlname= library_names= func_source "$file" # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ func_warning "'$file' was not linked with '-export-dynamic'" continue fi func_dirname "$file" "" "." dir=$func_dirname_result if test -f "$dir/$objdir/$dlname"; then func_append dir "/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" fi fi ;; *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." dir=$func_dirname_result ;; *) func_warning "'-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir=$absdir # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic=$magic # Check if any of the arguments is a wrapper script. args= for file do case $file in -* | *.la | *.lo ) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. file=$progdir/$program elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. file=$progdir/$program fi ;; esac # Quote arguments (to preserve shell metacharacters). func_append_quoted args "$file" done if $opt_dry_run; then # Display what would be done. if test -n "$shlibpath_var"; then eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" echo "export $shlibpath_var" fi $ECHO "$cmd$args" exit $EXIT_SUCCESS else if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${save_$lt_var+set}\" = set; then $lt_var=\$save_$lt_var; export $lt_var else $lt_unset $lt_var fi" done # Now prepare to actually exec the command. exec_cmd=\$cmd$args fi } test execute = "$opt_mode" && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $debug_cmd libs= libdirs= admincmds= for opt in "$nonopt" ${1+"$@"} do if test -d "$opt"; then func_append libdirs " $opt" elif test -f "$opt"; then if func_lalib_unsafe_p "$opt"; then func_append libs " $opt" else func_warning "'$opt' is not a valid libtool archive" fi else func_fatal_error "invalid argument '$opt'" fi done if test -n "$libs"; then if test -n "$lt_sysroot"; then sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" else sysroot_cmd= fi # Remove sysroot references if $opt_dry_run; then for lib in $libs; do echo "removing references to $lt_sysroot and '=' prefixes from $lib" done else tmpdir=`func_mktempdir` for lib in $libs; do $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ > $tmpdir/tmp-la mv -f $tmpdir/tmp-la $lib done ${RM}r "$tmpdir" fi fi if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. func_execute_cmds "$finish_cmds" 'admincmds="$admincmds '"$cmd"'"' fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $opt_dry_run || eval "$cmds" || func_append admincmds " $cmds" fi done fi # Exit here if they wanted silent mode. $opt_quiet && exit $EXIT_SUCCESS if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then echo "----------------------------------------------------------------------" echo "Libraries have been installed in:" for libdir in $libdirs; do $ECHO " $libdir" done echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" echo "specify the full pathname of the library, or use the '-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then echo " - add LIBDIR to the '$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then echo " - add LIBDIR to the '$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $ECHO " - use the '$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" fi echo echo "See any operating system documentation about shared libraries for" case $host in solaris2.[6789]|solaris2.1[0-9]) echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" echo "pages." ;; *) echo "more information, such as the ld(1) and ld.so(8) manual pages." ;; esac echo "----------------------------------------------------------------------" fi exit $EXIT_SUCCESS } test finish = "$opt_mode" && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $debug_cmd # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || # Allow the use of GNU shtool's install command. case $nonopt in *shtool*) :;; *) false;; esac then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " arg=$1 shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_for_eval "$arg" func_append install_prog "$func_quote_for_eval_result" install_shared_prog=$install_prog case " $install_prog " in *[\\\ /]cp\ *) install_cp=: ;; *) install_cp=false ;; esac # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=false stripme= no_mode=: for arg do arg2= if test -n "$dest"; then func_append files " $dest" dest=$arg continue fi case $arg in -d) isdir=: ;; -f) if $install_cp; then :; else prev=$arg fi ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then if test X-m = "X$prev" && test -n "$install_override_mode"; then arg2=$install_override_mode no_mode=false fi prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. func_quote_for_eval "$arg" func_append install_prog " $func_quote_for_eval_result" if test -n "$arg2"; then func_quote_for_eval "$arg2" fi func_append install_shared_prog " $func_quote_for_eval_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ func_fatal_help "the '$prev' option requires an argument" if test -n "$install_override_mode" && $no_mode; then if $install_cp; then :; else func_quote_for_eval "$install_override_mode" func_append install_shared_prog " -m $func_quote_for_eval_result" fi fi if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" else func_fatal_help "you must specify a destination" fi fi # Strip any trailing slash from the destination. func_stripname '' '/' "$dest" dest=$func_stripname_result # Check to see that the destination is a directory. test -d "$dest" && isdir=: if $isdir; then destdir=$dest destname= else func_dirname_and_basename "$dest" "" "." destdir=$func_dirname_result destname=$func_basename_result # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ func_fatal_help "'$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) func_fatal_help "'$destdir' must be an absolute directory name" ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic=$magic staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. func_append staticlibs " $file" ;; *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "'$file' is not a valid libtool archive" library_names= old_library= relink_command= func_source "$file" # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) func_append current_libdirs " $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) func_append future_libdirs " $libdir" ;; esac fi func_dirname "$file" "/" "" dir=$func_dirname_result func_append dir "$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi func_warning "relinking '$file'" func_show_eval "$relink_command" \ 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then realname=$1 shift srcname=$realname test -n "$relink_command" && srcname=${realname}T # Install the shared library and build the symlinks. func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme=$stripme case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme= ;; esac ;; os2*) case $realname in *_dll.a) tstripme= ;; esac ;; esac if test -n "$tstripme" && test -n "$striplib"; then func_show_eval "$striplib $destdir/$realname" 'exit $?' fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try 'ln -sf' first, because the 'ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do test "$linkname" != "$realname" \ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" done fi # Do each command in the postinstall commands. lib=$destdir/$realname func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" name=$func_basename_result instname=$dir/${name}i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. test -n "$old_library" && func_append staticlibs " $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile=$destdir/$destname else func_basename "$file" destfile=$func_basename_result destfile=$destdir/$destfile fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) func_lo2o "$destfile" staticdest=$func_lo2o_result ;; *.$objext) staticdest=$destfile destfile= ;; *) func_fatal_help "cannot copy a libtool object to '$destfile'" ;; esac # Install the libtool object if requested. test -n "$destfile" && \ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. if test yes = "$build_old_libs"; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile=$destdir/$destname else func_basename "$file" destfile=$func_basename_result destfile=$destdir/$destfile fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext= case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result stripped_ext=.exe fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result else func_stripname '' '.exe' "$file" wrapper=$func_stripname_result fi ;; *) wrapper=$file ;; esac if func_ltwrapper_script_p "$wrapper"; then notinst_deplibs= relink_command= func_source "$wrapper" # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ func_fatal_error "invalid libtool wrapper script '$wrapper'" finalize=: for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` if test -n "$libdir" && test ! -f "$libfile"; then func_warning "'$lib' has not been installed in '$libdir'" finalize=false fi done relink_command= func_source "$wrapper" outputname= if test no = "$fast_install" && test -n "$relink_command"; then $opt_dry_run || { if $finalize; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" file=$func_basename_result outputname=$tmpdir/$file # Replace the output file specification. relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` $opt_quiet || { func_quote_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_result" } if eval "$relink_command"; then : else func_error "error: relink '$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi file=$outputname else func_warning "cannot relink '$file'" fi } else # Install the binary that we compiled earlier. file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) func_stripname '' '.exe' "$destfile" destfile=$func_stripname_result ;; esac ;; esac func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' $opt_dry_run || if test -n "$outputname"; then ${RM}r "$tmpdir" fi ;; esac done for file in $staticlibs; do func_basename "$file" name=$func_basename_result # Set up the ranlib parameters. oldlib=$destdir/$name func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then func_show_eval "$old_striplib $tool_oldlib" 'exit $?' fi # Do each command in the postinstall commands. func_execute_cmds "$old_postinstall_cmds" 'exit $?' done test -n "$future_libdirs" && \ func_warning "remember to run '$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } test install = "$opt_mode" && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p # Extract symbols from dlprefiles and create ${outputname}S.o with # a dlpreopen symbol table. func_generate_dlsyms () { $debug_cmd my_outputname=$1 my_originator=$2 my_pic_p=${3-false} my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then if test -n "$NM" && test -n "$global_symbol_pipe"; then my_dlsyms=${my_outputname}S.c else func_error "not configured to extract global symbols from dlpreopened files" fi fi if test -n "$my_dlsyms"; then case $my_dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist=$output_objdir/$my_outputname.nm func_show_eval "$RM $nlist ${nlist}S ${nlist}T" # Parse the name list into a source file. func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ /* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ /* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif #if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) #pragma GCC diagnostic ignored \"-Wstrict-prototypes\" #endif /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) /* External symbol declarations for the compiler. */\ " if test yes = "$dlself"; then func_verbose "generating symbol list for '$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do func_to_tool_file "$progfile" func_convert_file_msys_to_w32 func_verbose "extracting global C symbols from '$func_to_tool_file_result'" $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $opt_dry_run || { eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols=$output_objdir/$outputname.exp $opt_dry_run || { $RM $export_symbols eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac } else $opt_dry_run || { eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac } fi fi for dlprefile in $dlprefiles; do func_verbose "extracting global C symbols from '$dlprefile'" func_basename "$dlprefile" name=$func_basename_result case $host in *cygwin* | *mingw* | *cegcc* ) # if an import library, we need to obtain dlname if func_win32_import_lib_p "$dlprefile"; then func_tr_sh "$dlprefile" eval "curr_lafile=\$libfile_$func_tr_sh_result" dlprefile_dlbasename= if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then # Use subshell, to avoid clobbering current variable values dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` if test -n "$dlprefile_dlname"; then func_basename "$dlprefile_dlname" dlprefile_dlbasename=$func_basename_result else # no lafile. user explicitly requested -dlpreopen . $sharedlib_from_linklib_cmd "$dlprefile" dlprefile_dlbasename=$sharedlib_from_linklib_result fi fi $opt_dry_run || { if test -n "$dlprefile_dlbasename"; then eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' else func_warning "Could not compute DLL name from $name" eval '$ECHO ": $name " >> "$nlist"' fi func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" } else # not an import lib $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } fi ;; *) $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } ;; esac done $opt_dry_run || { # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if $GREP -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else $GREP -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi func_show_eval '$RM "${nlist}I"' if test -n "$global_symbol_to_import"; then eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' fi echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[];\ " if test -s "$nlist"I; then echo >> "$output_objdir/$my_dlsyms" "\ static void lt_syminit(void) { LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; for (; symbol->name; ++symbol) {" $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" echo >> "$output_objdir/$my_dlsyms" "\ } }" fi echo >> "$output_objdir/$my_dlsyms" "\ LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = { {\"$my_originator\", (void *) 0}," if test -s "$nlist"I; then echo >> "$output_objdir/$my_dlsyms" "\ {\"@INIT@\", (void *) <_syminit}," fi case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac echo >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) $my_pic_p && pic_flag_for_symtable=" $pic_flag" ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) func_append symtab_cflags " $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' # Transform the symbol file into the correct name. symfileobj=$output_objdir/${my_outputname}S.$objext case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for '$my_dlsyms'" ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` fi } # func_cygming_gnu_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is a GNU/binutils-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_gnu_implib_p () { $debug_cmd func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` test -n "$func_cygming_gnu_implib_tmp" } # func_cygming_ms_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is an MS-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_ms_implib_p () { $debug_cmd func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` test -n "$func_cygming_ms_implib_tmp" } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. # Despite the name, also deal with 64 bit binaries. func_win32_libid () { $debug_cmd win32_libid_type=unknown win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then case $nm_interface in "MS dumpbin") if func_cygming_ms_implib_p "$1" || func_cygming_gnu_implib_p "$1" then win32_nmres=import else win32_nmres= fi ;; *) func_to_tool_file "$1" func_convert_file_msys_to_w32 win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | $SED -n -e ' 1,100{ / I /{ s|.*|import| p q } }'` ;; esac case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $ECHO "$win32_libid_type" } # func_cygming_dll_for_implib ARG # # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib () { $debug_cmd sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` } # func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs # # The is the core of a fallback implementation of a # platform-specific function to extract the name of the # DLL associated with the specified import library LIBNAME. # # SECTION_NAME is either .idata$6 or .idata$7, depending # on the platform and compiler that created the implib. # # Echos the name of the DLL associated with the # specified import library. func_cygming_dll_for_implib_fallback_core () { $debug_cmd match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` $OBJDUMP -s --section "$1" "$2" 2>/dev/null | $SED '/^Contents of section '"$match_literal"':/{ # Place marker at beginning of archive member dllname section s/.*/====MARK====/ p d } # These lines can sometimes be longer than 43 characters, but # are always uninteresting /:[ ]*file format pe[i]\{,1\}-/d /^In archive [^:]*:/d # Ensure marker is printed /^====MARK====/p # Remove all lines with less than 43 characters /^.\{43\}/!d # From remaining lines, remove first 43 characters s/^.\{43\}//' | $SED -n ' # Join marker and all lines until next marker into a single line /^====MARK====/ b para H $ b para b :para x s/\n//g # Remove the marker s/^====MARK====// # Remove trailing dots and whitespace s/[\. \t]*$// # Print /./p' | # we now have a list, one entry per line, of the stringified # contents of the appropriate section of all members of the # archive that possess that section. Heuristic: eliminate # all those that have a first or second character that is # a '.' (that is, objdump's representation of an unprintable # character.) This should work for all archives with less than # 0x302f exports -- but will fail for DLLs whose name actually # begins with a literal '.' or a single character followed by # a '.'. # # Of those that remain, print the first one. $SED -e '/^\./d;/^.\./d;q' } # func_cygming_dll_for_implib_fallback ARG # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # # This fallback implementation is for use when $DLLTOOL # does not support the --identify-strict option. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib_fallback () { $debug_cmd if func_cygming_gnu_implib_p "$1"; then # binutils import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` elif func_cygming_ms_implib_p "$1"; then # ms-generated import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` else # unknown sharedlib_from_linklib_result= fi } # func_extract_an_archive dir oldlib func_extract_an_archive () { $debug_cmd f_ex_an_ar_dir=$1; shift f_ex_an_ar_oldlib=$1 if test yes = "$lock_old_archive_extraction"; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' if test yes = "$lock_old_archive_extraction"; then $opt_dry_run || rm -f "$lockfile" fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $debug_cmd my_gentop=$1; shift my_oldlibs=${1+"$@"} my_oldobjs= my_xlib= my_xabs= my_xdir= for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" my_xlib=$func_basename_result my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir=$my_gentop/$my_xlib_u func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` func_basename "$darwin_archive" darwin_base_archive=$func_basename_result darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches; do func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" cd "unfat-$$/$darwin_base_archive-$darwin_arch" func_extract_an_archive "`pwd`" "$darwin_base_archive" cd "$darwin_curdir" $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done func_extract_archives_result=$my_oldobjs } # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory where it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=${1-no} $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='$sed_quote_subst' # Be Bourne compatible if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variables: generated_by_libtool_version='$macro_version' notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then file=\"\$0\"" qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` $ECHO "\ # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } ECHO=\"$qECHO\" fi # Very basic option parsing. These options are (a) specific to # the libtool wrapper, (b) are identical between the wrapper # /script/ and the wrapper /executable/ that is used only on # windows platforms, and (c) all begin with the string "--lt-" # (application programs are unlikely to have options that match # this pattern). # # There are only two supported options: --lt-debug and # --lt-dump-script. There is, deliberately, no --lt-help. # # The first argument to this parsing function should be the # script's $0 value, followed by "$@". lt_option_debug= func_parse_lt_options () { lt_script_arg0=\$0 shift for lt_opt do case \"\$lt_opt\" in --lt-debug) lt_option_debug=1 ;; --lt-dump-script) lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` cat \"\$lt_dump_D/\$lt_dump_F\" exit 0 ;; --lt-*) \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 exit 1 ;; esac done # Print the debug banner immediately: if test -n \"\$lt_option_debug\"; then echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 fi } # Used when --lt-debug. Prints its arguments to stdout # (redirection is the responsibility of the caller) func_lt_dump_args () { lt_dump_args_N=1; for lt_arg do \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` done } # Core function for launching the target application func_exec_program_core () { " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 } # A function to encapsulate launching the target application # Strips options in the --lt-* namespace from \$@ and # launches target application with the remaining arguments. func_exec_program () { case \" \$* \" in *\\ --lt-*) for lt_wr_arg do case \$lt_wr_arg in --lt-*) ;; *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; esac shift done ;; esac func_exec_program_core \${1+\"\$@\"} } # Parse options func_parse_lt_options \"\$0\" \${1+\"\$@\"} # Find the directory that this script lives in. thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` done # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test yes = "$fast_install"; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $MKDIR \"\$progdir\" else $RM \"\$progdir/\$file\" fi" $ECHO "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else \$ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # fixup the dll searchpath if we need to. # # Fix the DLL searchpath if we need to. Do this before prepending # to shlibpath, because on Windows, both are PATH and uninstalled # libraries must come first. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi # Export our shlibpath_var if we have one. if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` export $shlibpath_var " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. func_exec_program \${1+\"\$@\"} fi else # The program doesn't exist. \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat < #include #ifdef _MSC_VER # include # include # include #else # include # include # ifdef __CYGWIN__ # include # endif #endif #include #include #include #include #include #include #include #include #define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) /* declarations of non-ANSI functions */ #if defined __MINGW32__ # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif #elif defined __CYGWIN__ # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif /* #elif defined other_platform || defined ... */ #endif /* portability defines, excluding path handling macros */ #if defined _MSC_VER # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC #elif defined __MINGW32__ # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv #elif defined __CYGWIN__ # define HAVE_SETENV # define FOPEN_WB "wb" /* #elif defined other platforms ... */ #endif #if defined PATH_MAX # define LT_PATHMAX PATH_MAX #elif defined MAXPATHLEN # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif /* path handling portability macros */ #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ defined __OS2__ # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free (stale); stale = 0; } \ } while (0) #if defined LT_DEBUGWRAPPER static int lt_debug = 1; #else static int lt_debug = 0; #endif const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_debugprintf (const char *file, int line, const char *fmt, ...); void lt_fatal (const char *file, int line, const char *message, ...); static const char *nonnull (const char *s); static const char *nonempty (const char *s); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); char **prepare_spawn (char **argv); void lt_dump_script (FILE *f); EOF cat <= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", nonempty (path)); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ char * find_executable (const char *wrapper) { int has_slash = 0; const char *p; const char *p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; size_t tmp_len; char *concat_name; lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", nonempty (wrapper)); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined HAVE_DOS_BASED_FILE_SYSTEM if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } #if defined HAVE_DOS_BASED_FILE_SYSTEM } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char *path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char *q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR (*q)) break; p_len = (size_t) (q - p); p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); return NULL; } char * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { lt_debugprintf (__FILE__, __LINE__, "checking path component for symlinks: %s\n", tmp_pathspec); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { lt_fatal (__FILE__, __LINE__, "error accessing file \"%s\": %s", tmp_pathspec, nonnull (strerror (errno))); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal (__FILE__, __LINE__, "could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } char * strendzap (char *str, const char *pat) { size_t len, patlen; assert (str != NULL); assert (pat != NULL); len = strlen (str); patlen = strlen (pat); if (patlen <= len) { str += len - patlen; if (STREQ (str, pat)) *str = '\0'; } return str; } void lt_debugprintf (const char *file, int line, const char *fmt, ...) { va_list args; if (lt_debug) { (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } } static void lt_error_core (int exit_status, const char *file, int line, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *file, int line, const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); va_end (ap); } static const char * nonnull (const char *s) { return s ? s : "(null)"; } static const char * nonempty (const char *s) { return (s && !*s) ? "(empty)" : nonnull (s); } void lt_setenv (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_setenv) setting '%s' to '%s'\n", nonnull (name), nonnull (value)); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else size_t len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { size_t orig_value_len = strlen (orig_value); size_t add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } void lt_update_exe_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ size_t len = strlen (new_value); while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[--len] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF case $host_os in mingw*) cat <<"EOF" /* Prepares an argument vector before calling spawn(). Note that spawn() does not by itself call the command interpreter (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&v); v.dwPlatformId == VER_PLATFORM_WIN32_NT; }) ? "cmd.exe" : "command.com"). Instead it simply concatenates the arguments, separated by ' ', and calls CreateProcess(). We must quote the arguments since Win32 CreateProcess() interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a special way: - Space and tab are interpreted as delimiters. They are not treated as delimiters if they are surrounded by double quotes: "...". - Unescaped double quotes are removed from the input. Their only effect is that within double quotes, space and tab are treated like normal characters. - Backslashes not followed by double quotes are not special. - But 2*n+1 backslashes followed by a double quote become n backslashes followed by a double quote (n >= 0): \" -> " \\\" -> \" \\\\\" -> \\" */ #define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" #define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" char ** prepare_spawn (char **argv) { size_t argc; char **new_argv; size_t i; /* Count number of arguments. */ for (argc = 0; argv[argc] != NULL; argc++) ; /* Allocate new argument vector. */ new_argv = XMALLOC (char *, argc + 1); /* Put quoted arguments into the new argument vector. */ for (i = 0; i < argc; i++) { const char *string = argv[i]; if (string[0] == '\0') new_argv[i] = xstrdup ("\"\""); else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) { int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); size_t length; unsigned int backslashes; const char *s; char *quoted_string; char *p; length = 0; backslashes = 0; if (quote_around) length++; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') length += backslashes + 1; length++; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) length += backslashes + 1; quoted_string = XMALLOC (char, length + 1); p = quoted_string; backslashes = 0; if (quote_around) *p++ = '"'; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') { unsigned int j; for (j = backslashes + 1; j > 0; j--) *p++ = '\\'; } *p++ = c; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) { unsigned int j; for (j = backslashes; j > 0; j--) *p++ = '\\'; *p++ = '"'; } *p = '\0'; new_argv[i] = quoted_string; } else new_argv[i] = (char *) string; } new_argv[argc] = NULL; return new_argv; } EOF ;; esac cat <<"EOF" void lt_dump_script (FILE* f) { EOF func_emit_wrapper yes | $SED -n -e ' s/^\(.\{79\}\)\(..*\)/\1\ \2/ h s/\([\\"]\)/\\\1/g s/$/\\n/ s/\([^\n]*\).*/ fputs ("\1", f);/p g D' cat <<"EOF" } EOF } # end: func_emit_cwrapperexe_src # func_win32_import_lib_p ARG # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { $debug_cmd case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } # func_suncc_cstd_abi # !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! # Several compiler flags select an ABI that is incompatible with the # Cstd library. Avoid specifying it if any are in CXXFLAGS. func_suncc_cstd_abi () { $debug_cmd case " $compile_command " in *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) suncc_use_cstd_abi=no ;; *) suncc_use_cstd_abi=yes ;; esac } # func_mode_link arg... func_mode_link () { $debug_cmd case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # what system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll that has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args=$nonopt base_compile="$nonopt $@" compile_command=$nonopt finalize_command=$nonopt compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` inst_prefix_dir= new_inherited_linker_flags= avoid_version=no bindir= dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= os2dllname= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=false prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module=$wl-single_module func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test yes != "$build_libtool_libs" \ && func_fatal_configuration "cannot build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg=$1 shift func_quote_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result func_append libtool_args " $func_quote_for_eval_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in bindir) bindir=$arg prev= continue ;; dlfiles|dlprefiles) $preload || { # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=: } case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test no = "$dlself"; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test dlprefiles = "$prev"; then dlself=yes elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test dlfiles = "$prev"; then func_append dlfiles " $arg" else func_append dlprefiles " $arg" fi prev= continue ;; esac ;; expsyms) export_symbols=$arg test -f "$arg" \ || func_fatal_error "symbol file '$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex=$arg prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) func_append deplibs " $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir=$arg prev= continue ;; mllvm) # Clang does not use LLVM to link, so we can simply discard any # '-mllvm $arg' options when doing the link step. prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # func_append moreargs " $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test none = "$pic_object" && test none = "$non_pic_object"; then func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result if test none != "$pic_object"; then # Prepend the subdirectory the object is found in. pic_object=$xdir$pic_object if test dlfiles = "$prev"; then if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg=$pic_object fi # Non-PIC object. if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test none = "$pic_object"; then arg=$non_pic_object fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object=$pic_object func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "'$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file '$arg' does not exist" fi arg=$save_arg prev= continue ;; os2dllname) os2dllname=$arg prev= continue ;; precious_regex) precious_files_regex=$arg prev= continue ;; release) release=-$arg prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test rpath = "$prev"; then case "$rpath " in *" $arg "*) ;; *) func_append rpath " $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) func_append xrpath " $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds=$arg prev= continue ;; weak) func_append weak_libs " $arg" prev= continue ;; xcclinker) func_append linker_flags " $qarg" func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) func_append linker_flags " $qarg" func_append compiler_flags " $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg=$arg case $arg in -all-static) if test -n "$link_static_flag"; then # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "'-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -bindir) prev=bindir continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test X-export-symbols = "X$arg"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname "-L" '' "$arg" if test -z "$func_stripname_result"; then if test "$#" -gt 0; then func_fatal_error "require no space between '-L' and '$1'" else func_fatal_error "need path for '-L' option" fi fi func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of '$dir'" dir=$absdir ;; esac case "$deplibs " in *" -L$dir "* | *" $arg "*) # Will only happen for absolute or sysroot arguments ;; *) # Preserve sysroot, but never include relative directories case $dir in [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; *) func_append deplibs " -L$dir" ;; esac func_append lib_search_path " $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) func_append dllsearchpath ":$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac continue ;; -l*) if test X-lc = "X$arg" || test X-lm = "X$arg"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test X-lc = "X$arg" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) # Do not include libc due to us having libc/libc_r. test X-lc = "X$arg" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework func_append deplibs " System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test X-lc = "X$arg" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test X-lc = "X$arg" && continue ;; esac elif test X-lc_r = "X$arg"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi func_append deplibs " $arg" continue ;; -mllvm) prev=mllvm continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot|--sysroot) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) func_append new_inherited_linker_flags " $arg" ;; esac continue ;; -multi_module) single_module=$wl-multi_module continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "'-no-install' is ignored for $host" func_warning "assuming '-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -os2dllname) prev=os2dllname continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; =*) func_stripname '=' '' "$dir" dir=$lt_sysroot$func_stripname_result ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs=$IFS; IFS=, for flag in $args; do IFS=$save_ifs func_quote_for_eval "$flag" func_append arg " $func_quote_for_eval_result" func_append compiler_flags " $func_quote_for_eval_result" done IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs=$IFS; IFS=, for flag in $args; do IFS=$save_ifs func_quote_for_eval "$flag" func_append arg " $wl$func_quote_for_eval_result" func_append compiler_flags " $wl$func_quote_for_eval_result" func_append linker_flags " $func_quote_for_eval_result" done IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" arg=$func_quote_for_eval_result ;; # Flags to be passed through unchanged, with rationale: # -64, -mips[0-9] enable 64-bit mode for the SGI compiler # -r[0-9][0-9]* specify processor for the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler # +DA*, +DD* enable 64-bit mode for the HP compiler # -q* compiler args for the IBM compiler # -m*, -t[45]*, -txscale* architecture-specific flags for GCC # -F/path path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* profiling flags for GCC # -fstack-protector* stack protector flags for GCC # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization # -specs=* GCC specs files # -stdlib=* select c++ std lib with clang # -fsanitize=* Clang/GCC memory and address sanitizer -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ -specs=*|-fsanitize=*) func_quote_for_eval "$arg" arg=$func_quote_for_eval_result func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; -Z*) if test os2 = "`expr $host : '.*\(os2\)'`"; then # OS/2 uses -Zxxx to specify OS/2-specific options compiler_flags="$compiler_flags $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case $arg in -Zlinker | -Zstack) prev=xcompiler ;; esac continue else # Otherwise treat like 'Some other compiler flag' below func_quote_for_eval "$arg" arg=$func_quote_for_eval_result fi ;; # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" arg=$func_quote_for_eval_result ;; *.$objext) # A standard object. func_append objs " $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test none = "$pic_object" && test none = "$non_pic_object"; then func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result test none = "$pic_object" || { # Prepend the subdirectory the object is found in. pic_object=$xdir$pic_object if test dlfiles = "$prev"; then if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg=$pic_object } # Non-PIC object. if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test none = "$pic_object"; then arg=$non_pic_object fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object=$pic_object func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "'$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. func_append deplibs " $arg" func_append old_deplibs " $arg" continue ;; *.la) # A libtool-controlled library. func_resolve_sysroot "$arg" if test dlfiles = "$prev"; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= elif test dlprefiles = "$prev"; then # The library was specified with -dlpreopen. func_append dlprefiles " $func_resolve_sysroot_result" prev= else func_append deplibs " $func_resolve_sysroot_result" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_for_eval "$arg" arg=$func_quote_for_eval_result ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the '$prevarg' option requires an argument" if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname=$func_basename_result libobjs_save=$libobjs if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" # Definition is injected by LT_CONFIG during libtool generation. func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" func_dirname "$output" "/" "" output_objdir=$func_dirname_result$objdir func_to_tool_file "$output_objdir/" tool_output_objdir=$func_to_tool_file_result # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if $opt_preserve_dup_deps; then case "$libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append libs " $deplib" done if test lib = "$linkmode"; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; esac func_append pre_post_deps " $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=false newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test lib,link = "$linkmode,$pass"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs=$tmp_deplibs fi if test lib,link = "$linkmode,$pass" || test prog,scan = "$linkmode,$pass"; then libs=$deplibs deplibs= fi if test prog = "$linkmode"; then case $pass in dlopen) libs=$dlfiles ;; dlpreopen) libs=$dlprefiles ;; link) libs="$deplibs %DEPLIBS%" test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" ;; esac fi if test lib,dlpreopen = "$linkmode,$pass"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= func_resolve_sysroot "$lib" case $lib in *.la) func_source "$func_resolve_sysroot_result" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do func_basename "$deplib" deplib_base=$func_basename_result case " $weak_libs " in *" $deplib_base "*) ;; *) func_append deplibs " $deplib" ;; esac done done libs=$dlprefiles fi if test dlopen = "$pass"; then # Collect dlpreopened libraries save_deplibs=$deplibs deplibs= fi for deplib in $libs; do lib= found=false case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -l*) if test lib != "$linkmode" && test prog != "$linkmode"; then func_warning "'-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test lib = "$linkmode"; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib=$searchdir/lib$name$search_ext if test -f "$lib"; then if test .la = "$search_ext"; then found=: else found=false fi break 2 fi done done if $found; then # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll=$l done if test "X$ll" = "X$old_library"; then # only static version available found=false func_dirname "$lib" "" "." ladir=$func_dirname_result lib=$ladir/$old_library if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi else # deplib doesn't seem to be a libtool library if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" fi continue fi ;; # -l *.ltframework) if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test conv = "$pass" && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi if test scan = "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) func_warning "'-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test link = "$pass"; then func_stripname '-R' '' "$deplib" func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) func_resolve_sysroot "$deplib" lib=$func_resolve_sysroot_result ;; *.$libext) if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=false case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=: fi ;; pass_all) valid_a_lib=: ;; esac if $valid_a_lib; then echo $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" else echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not use here." fi ;; esac continue ;; prog) if test link != "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test conv = "$pass"; then deplibs="$deplib $deplibs" elif test prog = "$linkmode"; then if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then # If there is no dlopen support or we're linking statically, # we need to preload. func_append newdlprefiles " $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append newdlfiles " $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=: continue ;; esac # case $deplib $found || test -f "$lib" \ || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "'$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir=$func_dirname_result dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` if test lib,link = "$linkmode,$pass" || test prog,scan = "$linkmode,$pass" || { test prog != "$linkmode" && test lib != "$linkmode"; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi if test conv = "$pass"; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for '$lib'" fi # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done elif test prog != "$linkmode" && test lib != "$linkmode"; then func_fatal_error "'$lib' is not a convenience library" fi continue fi # $pass = conv # Get the name of the library we link against. linklib= if test -n "$old_library" && { test yes = "$prefer_static_libs" || test built,no = "$prefer_static_libs,$installed"; }; then linklib=$old_library else for l in $old_library $library_names; do linklib=$l done fi if test -z "$linklib"; then func_fatal_error "cannot find name of link library for '$lib'" fi # This library was specified with -dlopen. if test dlopen = "$pass"; then test -z "$libdir" \ && func_fatal_error "cannot -dlopen a convenience library: '$lib'" if test -z "$dlname" || test yes != "$dlopen_support" || test no = "$build_libtool_libs" then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. func_append dlprefiles " $lib $dependency_libs" else func_append newdlfiles " $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then func_warning "cannot determine absolute directory name of '$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir=$ladir fi ;; esac func_basename "$lib" laname=$func_basename_result # Find the relevant object directory and library name. if test yes = "$installed"; then if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library '$lib' was moved." dir=$ladir absdir=$abs_ladir libdir=$abs_ladir else dir=$lt_sysroot$libdir absdir=$lt_sysroot$libdir fi test yes = "$hardcode_automatic" && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir=$ladir absdir=$abs_ladir # Remove this search path later func_append notinst_path " $abs_ladir" else dir=$ladir/$objdir absdir=$abs_ladir/$objdir # Remove this search path later func_append notinst_path " $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test dlpreopen = "$pass"; then if test -z "$libdir" && test prog = "$linkmode"; then func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" fi case $host in # special handling for platforms with PE-DLLs. *cygwin* | *mingw* | *cegcc* ) # Linker will automatically link against shared library if both # static and shared are present. Therefore, ensure we extract # symbols from the import library if a shared library is present # (otherwise, the dlopen module name will be incorrect). We do # this by putting the import library name into $newdlprefiles. # We recover the dlopen module name by 'saving' the la file # name in a special purpose variable, and (later) extracting the # dlname from the la file. if test -n "$dlname"; then func_tr_sh "$dir/$linklib" eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" func_append newdlprefiles " $dir/$linklib" else func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" fi ;; * ) # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then func_append newdlprefiles " $dir/$dlname" else func_append newdlprefiles " $dir/$linklib" fi ;; esac fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test lib = "$linkmode"; then deplibs="$dir/$old_library $deplibs" elif test prog,link = "$linkmode,$pass"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test prog = "$linkmode" && test link != "$pass"; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" linkalldeplibs=false if test no != "$link_all_deplibs" || test -z "$library_names" || test no = "$build_libtool_libs"; then linkalldeplibs=: fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; esac # Need to link against all dependency_libs? if $linkalldeplibs; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done # for deplib continue fi # $linkmode = prog... if test prog,link = "$linkmode,$pass"; then if test -n "$library_names" && { { test no = "$prefer_static_libs" || test built,yes = "$prefer_static_libs,$installed"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then # Make sure the rpath contains only unique directories. case $temp_rpath: in *"$absdir:"*) ;; *) func_append temp_rpath "$absdir:" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi # $linkmode,$pass = prog,link... if $alldeplibs && { test pass_all = "$deplibs_check_method" || { test yes = "$build_libtool_libs" && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test built = "$use_static_libs" && test yes = "$installed"; then use_static_libs=no fi if test -n "$library_names" && { test no = "$use_static_libs" || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc* | *os2*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) if test no = "$installed"; then func_append notinst_deplibs " $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule= for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule=$dlpremoduletest break fi done if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then echo if test prog = "$linkmode"; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi if test lib = "$linkmode" && test yes = "$hardcode_into_libs"; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname=$1 shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname=$dlname elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw* | *cegcc* | *os2*) func_arith $current - $age major=$func_arith_result versuffix=-$major ;; esac eval soname=\"$soname_spec\" else soname=$realname fi # Make a new name for the extract_expsyms_cmds to use soroot=$soname func_basename "$soroot" soname=$func_basename_result func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from '$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for '$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test prog = "$linkmode" || test relink != "$opt_mode"; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test no = "$hardcode_direct"; then add=$dir/$linklib case $host in *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; *-*-sysv4*uw2*) add_dir=-L$dir ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir=-L$dir ;; *-*-darwin* ) # if the lib is a (non-dlopened) module then we cannot # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library"; then echo echo "*** And there doesn't seem to be a static archive available" echo "*** The link will probably fail, sorry" else add=$dir/$old_library fi elif test -n "$old_library"; then add=$dir/$old_library fi fi esac elif test no = "$hardcode_minus_L"; then case $host in *-*-sunos*) add_shlibpath=$dir ;; esac add_dir=-L$dir add=-l$name elif test no = "$hardcode_shlibpath_var"; then add_shlibpath=$dir add=-l$name else lib_linked=no fi ;; relink) if test yes = "$hardcode_direct" && test no = "$hardcode_direct_absolute"; then add=$dir/$linklib elif test yes = "$hardcode_minus_L"; then add_dir=-L$absdir # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add=-l$name elif test yes = "$hardcode_shlibpath_var"; then add_shlibpath=$dir add=-l$name else lib_linked=no fi ;; *) lib_linked=no ;; esac if test yes != "$lib_linked"; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi if test prog = "$linkmode"; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test yes != "$hardcode_direct" && test yes != "$hardcode_minus_L" && test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac fi fi fi if test prog = "$linkmode" || test relink = "$opt_mode"; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test yes = "$hardcode_direct" && test no = "$hardcode_direct_absolute"; then add=$libdir/$linklib elif test yes = "$hardcode_minus_L"; then add_dir=-L$libdir add=-l$name elif test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac add=-l$name elif test yes = "$hardcode_automatic"; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib"; then add=$inst_prefix_dir$libdir/$linklib else add=$libdir/$linklib fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir=-L$libdir # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add=-l$name fi if test prog = "$linkmode"; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test prog = "$linkmode"; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test unsupported != "$hardcode_direct"; then test -n "$old_library" && linklib=$old_library compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test yes = "$build_libtool_libs"; then # Not a shared library if test pass_all != "$deplibs_check_method"; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo $ECHO "*** Warning: This system cannot link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." if test yes = "$module"; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using 'nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** 'nm' from GNU binutils and a full rebuild may help." fi if test no = "$build_old_libs"; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test lib = "$linkmode"; then if test -n "$dependency_libs" && { test yes != "$hardcode_into_libs" || test yes = "$build_old_libs" || test yes = "$link_static"; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) func_append xrpath " $temp_xrpath";; esac;; *) func_append temp_deplibs " $libdir";; esac done dependency_libs=$temp_deplibs fi func_append newlib_search_path " $absdir" # Link against this library test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result";; *) func_resolve_sysroot "$deplib" ;; esac if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $func_resolve_sysroot_result "*) func_append specialdeplibs " $func_resolve_sysroot_result" ;; esac fi func_append tmp_libs " $func_resolve_sysroot_result" done if test no != "$link_all_deplibs"; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in -L*) path=$deplib ;; *.la) func_resolve_sysroot "$deplib" deplib=$func_resolve_sysroot_result func_dirname "$deplib" "" "." dir=$func_dirname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of '$dir'" absdir=$dir fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names"; then for tmp in $deplibrary_names; do depdepl=$tmp done if test -f "$absdir/$objdir/$depdepl"; then depdepl=$absdir/$objdir/$depdepl darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" path= fi fi ;; *) path=-L$absdir/$objdir ;; esac else eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "'$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "'$deplib' seems to be moved" path=-L$absdir fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test link = "$pass"; then if test prog = "$linkmode"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs=$newdependency_libs if test dlpreopen = "$pass"; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test dlopen != "$pass"; then test conv = "$pass" || { # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) func_append lib_search_path " $dir" ;; esac done newlib_search_path= } if test prog,link = "$linkmode,$pass"; then vars="compile_deplibs finalize_deplibs" else vars=deplibs fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) func_append tmp_libs " $deplib" ;; esac ;; *) func_append tmp_libs " $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Add Sun CC postdeps if required: test CXX = "$tagname" && { case $host_os in linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 func_suncc_cstd_abi if test no != "$suncc_use_cstd_abi"; then func_append postdeps ' -library=Cstd -library=Crun' fi ;; esac ;; solaris*) func_cc_basename "$CC" case $func_cc_basename_result in CC* | sunCC*) func_suncc_cstd_abi if test no != "$suncc_use_cstd_abi"; then func_append postdeps ' -library=Cstd -library=Crun' fi ;; esac ;; esac } # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i= ;; esac if test -n "$i"; then func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs done # for pass if test prog = "$linkmode"; then dlfiles=$newdlfiles fi if test prog = "$linkmode" || test lib = "$linkmode"; then dlprefiles=$newdlprefiles fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then func_warning "'-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "'-l' and '-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "'-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "'-R' is ignored for archives" test -n "$vinfo" && \ func_warning "'-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "'-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "'-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs=$output func_append objs "$old_deplibs" ;; lib) # Make sure we only generate libraries of the form 'libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test no = "$module" \ && func_fatal_help "libtool library '$output' must begin with 'lib'" if test no != "$need_lib_prefix"; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test pass_all != "$deplibs_check_method"; then func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" else echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" func_append libobjs " $objs" fi fi test no = "$dlself" \ || func_warning "'-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test 1 -lt "$#" \ && func_warning "ignoring multiple '-rpath's for a libtool library" install_libdir=$1 oldlibs= if test -z "$rpath"; then if test yes = "$build_libtool_libs"; then # Building a libtool convenience library. # Some compilers have problems with a '.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi test -n "$vinfo" && \ func_warning "'-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "'-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs=$IFS; IFS=: set dummy $vinfo 0 0 0 shift IFS=$save_ifs test -n "$7" && \ func_fatal_help "too many parameters to '-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major=$1 number_minor=$2 number_revision=$3 # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # that has an extra 1 added just for fun # case $version_type in # correct linux to gnu/linux during the next big refactor darwin|freebsd-elf|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age=$number_minor revision=$number_revision ;; freebsd-aout|qnx|sunos) current=$number_major revision=$number_minor age=0 ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age=$number_minor revision=$number_minor lt_irix_increment=no ;; *) func_fatal_configuration "$modename: unknown library version type '$version_type'" ;; esac ;; no) current=$1 revision=$2 age=$3 ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "CURRENT '$current' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "REVISION '$revision' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "AGE '$age' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE '$age' is greater than the current interface number '$current'" func_fatal_error "'$vinfo' is not valid version information" fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" # On Darwin other compilers case $CC in nagfor*) verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" ;; *) verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; esac ;; freebsd-aout) major=.$current versuffix=.$current.$revision ;; freebsd-elf) func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision ;; irix | nonstopux) if test no = "$lt_irix_increment"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring=$verstring_prefix$major.$revision # Add in all the interfaces that we are compatible with. loop=$revision while test 0 -ne "$loop"; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring=$verstring_prefix$major.$iface:$verstring done # Before this point, $major must not contain '.'. major=.$major versuffix=$major.$revision ;; linux) # correct to gnu/linux during the next big refactor func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=.$current.$age.$revision verstring=$current.$age.$revision # Add in all the interfaces that we are compatible with. loop=$age while test 0 -ne "$loop"; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring=$verstring:$iface.0 done # Make executables depend on our current version. func_append verstring ":$current.0" ;; qnx) major=.$current versuffix=.$current ;; sco) major=.$current versuffix=.$current ;; sunos) major=.$current versuffix=.$current.$revision ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 file systems. func_arith $current - $age major=$func_arith_result versuffix=-$major ;; *) func_fatal_configuration "unknown library version type '$version_type'" ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring=0.0 ;; esac if test no = "$need_version"; then versuffix= else versuffix=.0.0 fi fi # Remove version info from name if versioning should be avoided if test yes,no = "$avoid_version,$need_version"; then major= versuffix= verstring= fi # Check to see if the archive will have undefined symbols. if test yes = "$allow_undefined"; then if test unsupported = "$allow_undefined_flag"; then if test yes = "$build_old_libs"; then func_warning "undefined symbols not allowed in $host shared libraries; building static only" build_libtool_libs=no else func_fatal_error "can't build $host shared library unless -no-undefined is specified" fi fi else # Don't allow undefined symbols. allow_undefined_flag=$no_undefined_flag fi fi func_generate_dlsyms "$libname" "$libname" : func_append libobjs " $symfileobj" test " " = "$libobjs" && libobjs= if test relink != "$opt_mode"; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) if test -n "$precious_files_regex"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi func_append removelist " $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do func_replace_sysroot "$libdir" func_append temp_xrpath " -R$func_replace_sysroot_result" case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles=$dlfiles dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) func_append dlfiles " $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles=$dlprefiles dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) func_append dlprefiles " $lib" ;; esac done if test yes = "$build_libtool_libs"; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework func_append deplibs " System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test yes = "$build_libtool_need_lc"; then func_append deplibs " -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release= versuffix= major= newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $opt_dry_run || $RM conftest.c cat > conftest.c </dev/null` $nocaseglob else potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` fi for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | $GREP " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib=$potent_lib while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | $SED 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib= break 2 fi done done fi if test -n "$a_deplib"; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib"; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a file magic. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" a_deplib= ;; esac fi if test -n "$a_deplib"; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib=$potent_lib # see symlink-check above in file_magic test if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib= break 2 fi done done fi if test -n "$a_deplib"; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib"; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a regex pattern. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs= tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` if test yes = "$allow_libtool_libs_with_static_runtimes"; then for i in $predeps $postdeps; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` done fi case $tmp_deplibs in *[!\ \ ]*) echo if test none = "$deplibs_check_method"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." fi echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes ;; esac ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac if test yes = "$droppeddeps"; then if test yes = "$module"; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" echo "*** a static module, that should work as long as the dlopening" echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using 'nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** 'nm' from GNU binutils and a full rebuild may help." fi if test no = "$build_old_libs"; then oldlibs=$output_objdir/$libname.$libext build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else echo "*** The inter-library dependencies that have been dropped here will be" echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." if test no = "$allow_undefined"; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." if test no = "$build_old_libs"; then oldlibs=$output_objdir/$libname.$libext build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done deplibs=$new_libs # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test yes = "$build_libtool_libs"; then # Remove $wl instances when linking with ld. # FIXME: should test the right _cmds variable. case $archive_cmds in *\$LD\ *) wl= ;; esac if test yes = "$hardcode_into_libs"; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath=$finalize_rpath test relink = "$opt_mode" || rpath=$compile_rpath$rpath for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append dep_rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath=$finalize_shlibpath test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names shift realname=$1 shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname=$realname fi if test -z "$dlname"; then dlname=$soname fi lib=$output_objdir/$realname linknames= for link do func_append linknames " $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols=$output_objdir/$libname.uexp func_append delfiles " $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile func_dll_def_p "$export_symbols" || { # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols=$export_symbols export_symbols= always_export_symbols=yes } fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for '$libname.la'" export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs=$IFS; IFS='~' for cmd1 in $cmds; do IFS=$save_ifs # Take the normal branch if the nm_file_list_spec branch # doesn't work or if tool conversion is not needed. case $nm_file_list_spec~$to_tool_file_cmd in *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) try_normal_branch=yes eval cmd=\"$cmd1\" func_len " $cmd" len=$func_len_result ;; *) try_normal_branch=no ;; esac if test yes = "$try_normal_branch" \ && { test "$len" -lt "$max_cmd_len" \ || test "$max_cmd_len" -le -1; } then func_show_eval "$cmd" 'exit $?' skipped_export=false elif test -n "$nm_file_list_spec"; then func_basename "$output" output_la=$func_basename_result save_libobjs=$libobjs save_output=$output output=$output_objdir/$output_la.nm func_to_tool_file "$output" libobjs=$nm_file_list_spec$func_to_tool_file_result func_append delfiles " $output" func_verbose "creating $NM input file list: $output" for obj in $save_libobjs; do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > "$output" eval cmd=\"$cmd1\" func_show_eval "$cmd" 'exit $?' output=$save_output libobjs=$save_libobjs skipped_export=false else # The command line is too long to execute in one step. func_verbose "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS=$save_ifs if test -n "$export_symbols_regex" && test : != "$skipped_export"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols=$export_symbols test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test : != "$skipped_export" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) func_append tmp_deplibs " $test_deplib" ;; esac done deplibs=$tmp_deplibs if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test yes = "$compiler_needs_object" && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $convenience func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking if test relink = "$opt_mode"; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test yes = "$module" && test -n "$module_cmds"; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test : != "$skipped_export" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output func_basename "$output" output_la=$func_basename_result # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then output=$output_objdir/$output_la.lnkscript func_verbose "creating GNU ld script: $output" echo 'INPUT (' > $output for obj in $save_libobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done echo ')' >> $output func_append delfiles " $output" func_to_tool_file "$output" output=$func_to_tool_file_result elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then output=$output_objdir/$output_la.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test yes = "$compiler_needs_object"; then firstobj="$1 " shift fi for obj do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done func_append delfiles " $output" func_to_tool_file "$output" output=$firstobj\"$file_list_spec$func_to_tool_file_result\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-$k.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test -z "$objlist" || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test 1 -eq "$k"; then # The first file doesn't have a previous command to add. reload_objs=$objlist eval concat_cmds=\"$reload_cmds\" else # All subsequent reloadable object files will link in # the last one created. reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-$k.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-$k.$objext objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds$reload_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi func_append delfiles " $output" else output= fi ${skipped_export-false} && { func_verbose "generating symbol list for '$libname.la'" export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi } test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs=$IFS; IFS='~' for cmd in $concat_cmds; do IFS=$save_ifs $opt_quiet || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test relink = "$opt_mode"; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS=$save_ifs if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi ${skipped_export-false} && { if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols=$export_symbols test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi } libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test yes = "$module" && test -n "$module_cmds"; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs=$IFS; IFS='~' for cmd in $cmds; do IFS=$sp$nl eval cmd=\"$cmd\" IFS=$save_ifs $opt_quiet || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test relink = "$opt_mode"; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS=$save_ifs # Restore the uninstalled library and exit if test relink = "$opt_mode"; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then func_show_eval '${RM}r "$gentop"' fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' fi done # If -module or -export-dynamic was specified, set the dlname. if test yes = "$module" || test yes = "$export_dynamic"; then # On all known operating systems, these are identical. dlname=$soname fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then func_warning "'-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "'-l' and '-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "'-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "'-R' is ignored for objects" test -n "$vinfo" && \ func_warning "'-version-info' is ignored for objects" test -n "$release" && \ func_warning "'-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object '$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj=$output ;; esac # Delete the old objects. $opt_dry_run || $RM $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # if reload_cmds runs $LD directly, get rid of -Wl from # whole_archive_flag_spec and hope we can get by with turning comma # into space. case $reload_cmds in *\$LD[\ \$]*) wl= ;; esac if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags else gentop=$output_objdir/${obj}x func_append generated " $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # If we're not building shared, we need to use non_pic_objs test yes = "$build_libtool_libs" || libobjs=$non_pic_objects # Create the old-style object. reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs output=$obj func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi test yes = "$build_libtool_libs" || { if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS } if test -n "$pic_flag" || test default != "$pic_mode"; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output=$libobj func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "'-version-info' is ignored for programs" test -n "$release" && \ func_warning "'-release' is ignored for programs" $preload \ && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test CXX = "$tagname"; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) func_append compile_command " $wl-bind_at_load" func_append finalize_command " $wl-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done compile_deplibs=$new_libs func_append compile_command " $compile_deplibs" func_append finalize_command " $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) func_append dllsearchpath ":$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath=$rpath rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) func_append finalize_perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath=$rpath if test -n "$libobjs" && test yes = "$build_old_libs"; then # Transform all the library objects into standard objects. compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" false # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=: case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. wrappers_required=false ;; *cygwin* | *mingw* ) test yes = "$build_libtool_libs" || wrappers_required=false ;; *) if test no = "$need_relink" || test yes != "$build_libtool_libs"; then wrappers_required=false fi ;; esac $wrappers_required || { # Replace the output file specification. compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` link_command=$compile_command$compile_rpath # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Delete the generated files. if test -f "$output_objdir/${outputname}S.$objext"; then func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' fi exit $exit_status } if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do func_append rpath "$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test yes = "$no_install"; then # We don't need to create a wrapper script. link_command=$compile_var$compile_command$compile_rpath # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi exit $EXIT_SUCCESS fi case $hardcode_action,$fast_install in relink,*) # Fast installation is not supported link_command=$compile_var$compile_command$compile_rpath relink_command=$finalize_var$finalize_command$finalize_rpath func_warning "this platform does not like uninstalled shared libraries" func_warning "'$output' will be relinked during installation" ;; *,yes) link_command=$finalize_var$compile_command$finalize_rpath relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` ;; *,no) link_command=$compile_var$compile_command$compile_rpath relink_command=$finalize_var$finalize_command$finalize_rpath ;; *,needless) link_command=$finalize_var$compile_command$finalize_rpath relink_command= ;; esac # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output_objdir/$outputname" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Now create the wrapper script. func_verbose "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result cwrappersource=$output_path/$objdir/lt-$output_name.c cwrapper=$output_path/$output_name.exe $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host"; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do case $build_libtool_libs in convenience) oldobjs="$libobjs_save $symfileobj" addlibs=$convenience build_libtool_libs=no ;; module) oldobjs=$libobjs_save addlibs=$old_convenience build_libtool_libs=no ;; *) oldobjs="$old_deplibs $non_pic_objects" $preload && test -f "$symfileobj" \ && func_append oldobjs " $symfileobj" addlibs=$old_convenience ;; esac if test -n "$addlibs"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $addlibs func_append oldobjs " $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append oldobjs " $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else echo "copying selected object files to avoid basename conflicts..." gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase=$func_basename_result case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" func_append oldobjs " $gentop/$newobj" ;; *) func_append oldobjs " $obj" ;; esac done fi func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds elif test -n "$archiver_list_spec"; then func_verbose "using command file archive linking..." for obj in $oldobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > $output_objdir/$libname.libcmd func_to_tool_file "$output_objdir/$libname.libcmd" oldobjs=" $archiver_list_spec$func_to_tool_file_result" cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs oldobjs= # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj"; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test -z "$oldobjs"; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test yes = "$build_old_libs" && old_library=$libname.$libext func_verbose "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` if test yes = "$hardcode_automatic"; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test yes = "$installed"; then if test -z "$install_libdir"; then break fi output=$output_objdir/${outputname}i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" name=$func_basename_result func_resolve_sysroot "$deplib" eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` test -z "$libdir" && \ func_fatal_error "'$deplib' is not a valid libtool archive" func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" ;; -L*) func_stripname -L '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -L$func_replace_sysroot_result" ;; -R*) func_stripname -R '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -R$func_replace_sysroot_result" ;; *) func_append newdependency_libs " $deplib" ;; esac done dependency_libs=$newdependency_libs newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name=$func_basename_result eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; *) func_append newdlfiles " $lib" ;; esac done dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name=$func_basename_result eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done dlprefiles=$newdlprefiles else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlfiles " $abs" done dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlprefiles " $abs" done dlprefiles=$newdlprefiles fi $RM $output # place dlname in correct position for cygwin # In fact, it would be nice if we could use this code for all target # systems that can't hard-code library paths into their executables # and that have no shared library path variable independent of PATH, # but it turns out we can't easily determine that from inspecting # libtool variables, so we have to hard-code the OSs to which it # applies here; at the moment, that means platforms that use the PE # object format with DLL files. See the long comment at the top of # tests/bindir.at for full details. tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. if test -n "$bindir"; then func_relative_path "$install_libdir" "$bindir" tdlname=$func_relative_path_result/$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname fi ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Linker flags that cannot go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test no,yes = "$installed,$need_relink"; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } if test link = "$opt_mode" || test relink = "$opt_mode"; then func_mode_link ${1+"$@"} fi # func_mode_uninstall arg... func_mode_uninstall () { $debug_cmd RM=$nonopt files= rmforce=false exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic=$magic for arg do case $arg in -f) func_append RM " $arg"; rmforce=: ;; -*) func_append RM " $arg" ;; *) func_append files " $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= for file in $files; do func_dirname "$file" "" "." dir=$func_dirname_result if test . = "$dir"; then odir=$objdir else odir=$dir/$objdir fi func_basename "$file" name=$func_basename_result test uninstall = "$opt_mode" && odir=$dir # Remember odir for removal later, being careful to avoid duplicates if test clean = "$opt_mode"; then case " $rmdirs " in *" $odir "*) ;; *) func_append rmdirs " $odir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if { test -L "$file"; } >/dev/null 2>&1 || { test -h "$file"; } >/dev/null 2>&1 || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif $rmforce; then continue fi rmfiles=$file case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do func_append rmfiles " $odir/$n" done test -n "$old_library" && func_append rmfiles " $odir/$old_library" case $opt_mode in clean) case " $library_names " in *" $dlname "*) ;; *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; esac test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test none != "$pic_object"; then func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test none != "$non_pic_object"; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) if test clean = "$opt_mode"; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe func_append rmfiles " $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result func_append rmfiles " $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles func_append rmfiles " $odir/$name $odir/${name}S.$objext" if test yes = "$fast_install" && test -n "$relink_command"; then func_append rmfiles " $odir/lt-$name" fi if test "X$noexename" != "X$name"; then func_append rmfiles " $odir/lt-$noexename.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done # Try to remove the $objdir's in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then func_mode_uninstall ${1+"$@"} fi test -z "$opt_mode" && { help=$generic_help func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode '$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # where we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: lxc-2.0.8/config/apparmor/0000755061062106075000000000000013105117015012400 500000000000000lxc-2.0.8/config/apparmor/Makefile.am0000644061062106075000000000407413105116772014372 00000000000000EXTRA_DIST = \ abstractions/container-base \ abstractions/container-base.in \ abstractions/start-container \ container-rules \ container-rules.base \ lxc-containers \ lxc-generate-aa-rules.py \ profiles/lxc-default \ profiles/lxc-default-cgns \ profiles/lxc-default-with-mounting \ profiles/lxc-default-with-nesting \ usr.bin.lxc-start if ENABLE_APPARMOR install-apparmor: $(MKDIR_P) $(DESTDIR)$(sysconfdir)/apparmor.d/ $(MKDIR_P) $(DESTDIR)$(sysconfdir)/apparmor.d/abstractions/lxc/ $(MKDIR_P) $(DESTDIR)$(sysconfdir)/apparmor.d/lxc/ $(INSTALL_DATA) $(srcdir)/abstractions/container-base $(DESTDIR)$(sysconfdir)/apparmor.d/abstractions/lxc/ $(INSTALL_DATA) $(srcdir)/abstractions/start-container $(DESTDIR)$(sysconfdir)/apparmor.d/abstractions/lxc/ $(INSTALL_DATA) $(srcdir)/profiles/lxc-default $(DESTDIR)$(sysconfdir)/apparmor.d/lxc/ $(INSTALL_DATA) $(srcdir)/profiles/lxc-default-cgns $(DESTDIR)$(sysconfdir)/apparmor.d/lxc/ $(INSTALL_DATA) $(srcdir)/profiles/lxc-default-with-mounting $(DESTDIR)$(sysconfdir)/apparmor.d/lxc/ $(INSTALL_DATA) $(srcdir)/profiles/lxc-default-with-nesting $(DESTDIR)$(sysconfdir)/apparmor.d/lxc/ $(INSTALL_DATA) $(srcdir)/lxc-containers $(DESTDIR)$(sysconfdir)/apparmor.d/ $(INSTALL_DATA) $(srcdir)/usr.bin.lxc-start $(DESTDIR)$(sysconfdir)/apparmor.d/ uninstall-apparmor: rm -f $(DESTDIR)$(sysconfdir)/apparmor.d/usr.bin.lxc-start rm -f $(DESTDIR)$(sysconfdir)/apparmor.d/lxc-containers rm -f $(DESTDIR)$(sysconfdir)/apparmor.d/lxc/lxc-default-with-nesting rm -f $(DESTDIR)$(sysconfdir)/apparmor.d/lxc/lxc-default-with-mounting rm -f $(DESTDIR)$(sysconfdir)/apparmor.d/lxc/lxc-default-cgns rm -f $(DESTDIR)$(sysconfdir)/apparmor.d/lxc/lxc-default rm -f $(DESTDIR)$(sysconfdir)/apparmor.d/abstractions/lxc/start-container rm -f $(DESTDIR)$(sysconfdir)/apparmor.d/abstractions/lxc/container-base rmdir $(DESTDIR)$(sysconfdir)/apparmor.d/lxc/ || : rmdir $(DESTDIR)$(sysconfdir)/apparmor.d/abstractions/lxc/ || : rmdir $(DESTDIR)$(sysconfdir)/apparmor.d/ || : install-data-local: install-apparmor uninstall-local: uninstall-apparmor endif lxc-2.0.8/config/apparmor/lxc-containers0000644061062106075000000000030613105116772015204 00000000000000# This file exists only to ensure that all per-container policies # listed under /etc/apparmor.d/lxc get loaded at boot. Please do # not edit this file. #include #include lxc-2.0.8/config/apparmor/Makefile.in0000644061062106075000000004136113105116775014406 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = config/apparmor ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/acinclude.m4 \ $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/tls.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in README DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APPARMOR_LIBS = @APPARMOR_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BINDIR = @BINDIR@ CAP_LIBS = @CAP_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CGMANAGER_CFLAGS = @CGMANAGER_CFLAGS@ CGMANAGER_LIBS = @CGMANAGER_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIR = @DATADIR@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFAULT_CGROUP_PATTERN = @DEFAULT_CGROUP_PATTERN@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOCDIR = @DOCDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ HAVE_DOXYGEN = @HAVE_DOXYGEN@ INCLUDEDIR = @INCLUDEDIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDIR = @LIBDIR@ LIBEXECDIR = @LIBEXECDIR@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCALSTATEDIR = @LOCALSTATEDIR@ LOGPATH = @LOGPATH@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBDIR = @LUA_LIBDIR@ LUA_LIBS = @LUA_LIBS@ LUA_SHAREDIR = @LUA_SHAREDIR@ LUA_VERSION = @LUA_VERSION@ LXCBINHOOKDIR = @LXCBINHOOKDIR@ LXCHOOKDIR = @LXCHOOKDIR@ LXCINITDIR = @LXCINITDIR@ LXCPATH = @LXCPATH@ LXCROOTFSMOUNT = @LXCROOTFSMOUNT@ LXCTEMPLATECONFIG = @LXCTEMPLATECONFIG@ LXCTEMPLATEDIR = @LXCTEMPLATEDIR@ LXC_ABI = @LXC_ABI@ LXC_ABI_MAJOR = @LXC_ABI_MAJOR@ LXC_ABI_MICRO = @LXC_ABI_MICRO@ LXC_ABI_MINOR = @LXC_ABI_MINOR@ LXC_DEFAULT_CONFIG = @LXC_DEFAULT_CONFIG@ LXC_DEVEL = @LXC_DEVEL@ LXC_DISTRO_SYSCONF = @LXC_DISTRO_SYSCONF@ LXC_GENERATE_DATE = @LXC_GENERATE_DATE@ LXC_GLOBAL_CONF = @LXC_GLOBAL_CONF@ LXC_USERNIC_CONF = @LXC_USERNIC_CONF@ LXC_USERNIC_DB = @LXC_USERNIC_DB@ LXC_VERSION = @LXC_VERSION@ LXC_VERSION_BASE = @LXC_VERSION_BASE@ LXC_VERSION_BETA = @LXC_VERSION_BETA@ LXC_VERSION_MAJOR = @LXC_VERSION_MAJOR@ LXC_VERSION_MICRO = @LXC_VERSION_MICRO@ LXC_VERSION_MINOR = @LXC_VERSION_MINOR@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NIH_CFLAGS = @NIH_CFLAGS@ NIH_DBUS_CFLAGS = @NIH_DBUS_CFLAGS@ NIH_DBUS_LIBS = @NIH_DBUS_LIBS@ NIH_LIBS = @NIH_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PREFIX = @PREFIX@ PYTHON = @PYTHON@ PYTHONDEV_CFLAGS = @PYTHONDEV_CFLAGS@ PYTHONDEV_LIBS = @PYTHONDEV_LIBS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RUNTIME_PATH = @RUNTIME_PATH@ SBINDIR = @SBINDIR@ SECCOMP_CFLAGS = @SECCOMP_CFLAGS@ SECCOMP_LIBS = @SECCOMP_LIBS@ SED = @SED@ SELINUX_LIBS = @SELINUX_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SYSCONFDIR = @SYSCONFDIR@ SYSTEMD_UNIT_DIR = @SYSTEMD_UNIT_DIR@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bashcompdir = @bashcompdir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ db2xman = @db2xman@ docdir = @docdir@ docdtd = @docdtd@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ abstractions/container-base \ abstractions/container-base.in \ abstractions/start-container \ container-rules \ container-rules.base \ lxc-containers \ lxc-generate-aa-rules.py \ profiles/lxc-default \ profiles/lxc-default-cgns \ profiles/lxc-default-with-mounting \ profiles/lxc-default-with-nesting \ usr.bin.lxc-start all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu config/apparmor/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu config/apparmor/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." @ENABLE_APPARMOR_FALSE@uninstall-local: @ENABLE_APPARMOR_FALSE@install-data-local: clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-data-local install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-local .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am \ install-data-local install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am uninstall-local .PRECIOUS: Makefile @ENABLE_APPARMOR_TRUE@install-apparmor: @ENABLE_APPARMOR_TRUE@ $(MKDIR_P) $(DESTDIR)$(sysconfdir)/apparmor.d/ @ENABLE_APPARMOR_TRUE@ $(MKDIR_P) $(DESTDIR)$(sysconfdir)/apparmor.d/abstractions/lxc/ @ENABLE_APPARMOR_TRUE@ $(MKDIR_P) $(DESTDIR)$(sysconfdir)/apparmor.d/lxc/ @ENABLE_APPARMOR_TRUE@ $(INSTALL_DATA) $(srcdir)/abstractions/container-base $(DESTDIR)$(sysconfdir)/apparmor.d/abstractions/lxc/ @ENABLE_APPARMOR_TRUE@ $(INSTALL_DATA) $(srcdir)/abstractions/start-container $(DESTDIR)$(sysconfdir)/apparmor.d/abstractions/lxc/ @ENABLE_APPARMOR_TRUE@ $(INSTALL_DATA) $(srcdir)/profiles/lxc-default $(DESTDIR)$(sysconfdir)/apparmor.d/lxc/ @ENABLE_APPARMOR_TRUE@ $(INSTALL_DATA) $(srcdir)/profiles/lxc-default-cgns $(DESTDIR)$(sysconfdir)/apparmor.d/lxc/ @ENABLE_APPARMOR_TRUE@ $(INSTALL_DATA) $(srcdir)/profiles/lxc-default-with-mounting $(DESTDIR)$(sysconfdir)/apparmor.d/lxc/ @ENABLE_APPARMOR_TRUE@ $(INSTALL_DATA) $(srcdir)/profiles/lxc-default-with-nesting $(DESTDIR)$(sysconfdir)/apparmor.d/lxc/ @ENABLE_APPARMOR_TRUE@ $(INSTALL_DATA) $(srcdir)/lxc-containers $(DESTDIR)$(sysconfdir)/apparmor.d/ @ENABLE_APPARMOR_TRUE@ $(INSTALL_DATA) $(srcdir)/usr.bin.lxc-start $(DESTDIR)$(sysconfdir)/apparmor.d/ @ENABLE_APPARMOR_TRUE@uninstall-apparmor: @ENABLE_APPARMOR_TRUE@ rm -f $(DESTDIR)$(sysconfdir)/apparmor.d/usr.bin.lxc-start @ENABLE_APPARMOR_TRUE@ rm -f $(DESTDIR)$(sysconfdir)/apparmor.d/lxc-containers @ENABLE_APPARMOR_TRUE@ rm -f $(DESTDIR)$(sysconfdir)/apparmor.d/lxc/lxc-default-with-nesting @ENABLE_APPARMOR_TRUE@ rm -f $(DESTDIR)$(sysconfdir)/apparmor.d/lxc/lxc-default-with-mounting @ENABLE_APPARMOR_TRUE@ rm -f $(DESTDIR)$(sysconfdir)/apparmor.d/lxc/lxc-default-cgns @ENABLE_APPARMOR_TRUE@ rm -f $(DESTDIR)$(sysconfdir)/apparmor.d/lxc/lxc-default @ENABLE_APPARMOR_TRUE@ rm -f $(DESTDIR)$(sysconfdir)/apparmor.d/abstractions/lxc/start-container @ENABLE_APPARMOR_TRUE@ rm -f $(DESTDIR)$(sysconfdir)/apparmor.d/abstractions/lxc/container-base @ENABLE_APPARMOR_TRUE@ rmdir $(DESTDIR)$(sysconfdir)/apparmor.d/lxc/ || : @ENABLE_APPARMOR_TRUE@ rmdir $(DESTDIR)$(sysconfdir)/apparmor.d/abstractions/lxc/ || : @ENABLE_APPARMOR_TRUE@ rmdir $(DESTDIR)$(sysconfdir)/apparmor.d/ || : @ENABLE_APPARMOR_TRUE@install-data-local: install-apparmor @ENABLE_APPARMOR_TRUE@uninstall-local: uninstall-apparmor # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lxc-2.0.8/config/apparmor/lxc-generate-aa-rules.py0000755061062106075000000000727213105116772017003 00000000000000#!/usr/bin/env python3 import sys blocks = [] # # blocks is an array of paths under which we want to block by # default. # # blocks[0] = ['path' = '/sys', 'children' = [A,B] ] # blocks[1] = ['path' = '/proc/sys', 'children' = [ E ] ] # A = [ 'path' = 'fs', children = [C] ] # C = [ 'path' = 'cgroup', children = [F] ] # B = [ 'path' = 'class', children = [D] ] # D = [ 'path' = 'net', children = [F] ] # E = [ 'path' = 'shm*' ] # F = [ 'path' = '**' ] def add_block(path): for b in blocks: if b['path'] == path: # duplicate return blocks.append({'path': path.strip(), 'children': []}) # @prev is an array of dicts which containing 'path' and # 'children'. @path is a string. We are looking for an entry # in @prev which contains @path, and will return its # children array. def child_get(prev, path): for p in prev: if p['path'] == path: return p['children'] return None def add_allow(path): # find which block we belong to found = None for b in blocks: l = len(b['path']) if len(path) <= l: continue # TODO - should we find the longest match? if path[0:l] == b['path']: found = b break if found is None: print("allow with no previous block at %s" % path) sys.exit(1) p = path[l:].strip() while p[:1] == "/": p = p[1:] prev = b['children'] for s in p.split('/'): n = {'path': s.strip(), 'children': []} tmp = child_get(prev, n['path']) if tmp is not None: prev = tmp else: prev.append(n) prev = n['children'] config = "config" if len(sys.argv) > 1: config = sys.argv[1] with open(config) as f: for x in f.readlines(): x.strip() if x[:1] == '#': continue try: (cmd, path) = x.split(' ') except: # blank line continue if cmd == "block": add_block(path) elif cmd == "allow": add_allow(path) else: print("Unknown command: %s" % cmd) sys.exit(1) denies = [] def collect_chars(children, ref, index): r = "" for c in children: if index >= len(c['path']): continue if ref[0:index] != c['path'][0:index]: continue if c['path'][index] not in r: r = r + c['path'][index] return r def append_deny(s): s = "%s wklx," % s if s not in denies: denies.append(s) def gen_denies(pathsofar, children): for c in children: for char in range(len(c['path'])): if char == len(c['path'])-1 and c['path'][char] == '*': continue if char == len(c['path'])-2: if c['path'][char:char+2] == '**': continue x = collect_chars(children, c['path'], char) newdeny = "deny %s/%s[^%s]*{,/**}" % (pathsofar, c['path'][0:char], x) append_deny(newdeny) if c['path'] != '**' and c['path'][len(c['path'])-1] != '*': newdeny = "deny %s/%s?*{,/**}" % (pathsofar, c['path']) append_deny(newdeny) elif c['path'] != '**': newdeny = "deny %s/%s/**" % (pathsofar, c['path']) append_deny(newdeny) if len(c['children']) != 0: newpath = "%s/%s" % (pathsofar, c['path']) gen_denies(newpath, c['children']) for b in blocks: gen_denies(b['path'], b['children']) denies.sort() genby = " # generated by: lxc-generate-aa-rules.py" for a in sys.argv[1:]: genby += " %s" % a print(genby) for d in denies: print(" %s" % d) lxc-2.0.8/config/apparmor/README0000644061062106075000000000067713105116772013223 00000000000000The abstractions/container-base file is partially automatically generated. The two source files are container-rules.base and abstractions/container-base.in. If these file are updated, then 1. Generate a new container-rules file using ./lxc-generate-aa-rules.py container-rules.base > container-rules 2. Concatenate container-base.in with container-rules using cat abstractions/container-base.in container-rules > abstractions/container-base lxc-2.0.8/config/apparmor/container-rules0000644061062106075000000000576013105116772015376 00000000000000 # generated by: lxc-generate-aa-rules.py container-rules.base deny /proc/sys/[^kn]*{,/**} wklx, deny /proc/sys/k[^e]*{,/**} wklx, deny /proc/sys/ke[^r]*{,/**} wklx, deny /proc/sys/ker[^n]*{,/**} wklx, deny /proc/sys/kern[^e]*{,/**} wklx, deny /proc/sys/kerne[^l]*{,/**} wklx, deny /proc/sys/kernel/[^smhd]*{,/**} wklx, deny /proc/sys/kernel/d[^o]*{,/**} wklx, deny /proc/sys/kernel/do[^m]*{,/**} wklx, deny /proc/sys/kernel/dom[^a]*{,/**} wklx, deny /proc/sys/kernel/doma[^i]*{,/**} wklx, deny /proc/sys/kernel/domai[^n]*{,/**} wklx, deny /proc/sys/kernel/domain[^n]*{,/**} wklx, deny /proc/sys/kernel/domainn[^a]*{,/**} wklx, deny /proc/sys/kernel/domainna[^m]*{,/**} wklx, deny /proc/sys/kernel/domainnam[^e]*{,/**} wklx, deny /proc/sys/kernel/domainname?*{,/**} wklx, deny /proc/sys/kernel/h[^o]*{,/**} wklx, deny /proc/sys/kernel/ho[^s]*{,/**} wklx, deny /proc/sys/kernel/hos[^t]*{,/**} wklx, deny /proc/sys/kernel/host[^n]*{,/**} wklx, deny /proc/sys/kernel/hostn[^a]*{,/**} wklx, deny /proc/sys/kernel/hostna[^m]*{,/**} wklx, deny /proc/sys/kernel/hostnam[^e]*{,/**} wklx, deny /proc/sys/kernel/hostname?*{,/**} wklx, deny /proc/sys/kernel/m[^s]*{,/**} wklx, deny /proc/sys/kernel/ms[^g]*{,/**} wklx, deny /proc/sys/kernel/msg*/** wklx, deny /proc/sys/kernel/s[^he]*{,/**} wklx, deny /proc/sys/kernel/se[^m]*{,/**} wklx, deny /proc/sys/kernel/sem*/** wklx, deny /proc/sys/kernel/sh[^m]*{,/**} wklx, deny /proc/sys/kernel/shm*/** wklx, deny /proc/sys/kernel?*{,/**} wklx, deny /proc/sys/n[^e]*{,/**} wklx, deny /proc/sys/ne[^t]*{,/**} wklx, deny /proc/sys/net?*{,/**} wklx, deny /sys/[^fdc]*{,/**} wklx, deny /sys/c[^l]*{,/**} wklx, deny /sys/cl[^a]*{,/**} wklx, deny /sys/cla[^s]*{,/**} wklx, deny /sys/clas[^s]*{,/**} wklx, deny /sys/class/[^n]*{,/**} wklx, deny /sys/class/n[^e]*{,/**} wklx, deny /sys/class/ne[^t]*{,/**} wklx, deny /sys/class/net?*{,/**} wklx, deny /sys/class?*{,/**} wklx, deny /sys/d[^e]*{,/**} wklx, deny /sys/de[^v]*{,/**} wklx, deny /sys/dev[^i]*{,/**} wklx, deny /sys/devi[^c]*{,/**} wklx, deny /sys/devic[^e]*{,/**} wklx, deny /sys/device[^s]*{,/**} wklx, deny /sys/devices/[^v]*{,/**} wklx, deny /sys/devices/v[^i]*{,/**} wklx, deny /sys/devices/vi[^r]*{,/**} wklx, deny /sys/devices/vir[^t]*{,/**} wklx, deny /sys/devices/virt[^u]*{,/**} wklx, deny /sys/devices/virtu[^a]*{,/**} wklx, deny /sys/devices/virtua[^l]*{,/**} wklx, deny /sys/devices/virtual/[^n]*{,/**} wklx, deny /sys/devices/virtual/n[^e]*{,/**} wklx, deny /sys/devices/virtual/ne[^t]*{,/**} wklx, deny /sys/devices/virtual/net?*{,/**} wklx, deny /sys/devices/virtual?*{,/**} wklx, deny /sys/devices?*{,/**} wklx, deny /sys/f[^s]*{,/**} wklx, deny /sys/fs/[^c]*{,/**} wklx, deny /sys/fs/c[^g]*{,/**} wklx, deny /sys/fs/cg[^r]*{,/**} wklx, deny /sys/fs/cgr[^o]*{,/**} wklx, deny /sys/fs/cgro[^u]*{,/**} wklx, deny /sys/fs/cgrou[^p]*{,/**} wklx, deny /sys/fs/cgroup?*{,/**} wklx, deny /sys/fs?*{,/**} wklx, lxc-2.0.8/config/apparmor/abstractions/0000755061062106075000000000000013105117015015074 500000000000000lxc-2.0.8/config/apparmor/abstractions/container-base.in0000644061062106075000000001210613105116772020247 00000000000000 network, capability, file, umount, # dbus, signal, ptrace and unix are only supported by recent apparmor # versions. Comment them if the apparmor parser doesn't recognize them. # This also needs additional rules to reach outside of the container via # DBus, so just let all of DBus within the container. dbus, # Allow us to receive signals from anywhere. Note: if per-container profiles # are supported, for container isolation this should be changed to something # like: # signal (receive) peer=unconfined, # signal (receive) peer=/usr/bin/lxc-start, signal (receive), # Allow us to send signals to ourselves signal peer=@{profile_name}, # Allow other processes to read our /proc entries, futexes, perf tracing and # kcmp for now (they will need 'read' in the first place). Administrators can # override with: # deny ptrace (readby) ... ptrace (readby), # Allow other processes to trace us by default (they will need 'trace' in # the first place). Administrators can override with: # deny ptrace (tracedby) ... ptrace (tracedby), # Allow us to ptrace ourselves ptrace peer=@{profile_name}, # Allow receive via unix sockets from anywhere. Note: if per-container # profiles are supported, for container isolation this should be changed to # something like: # unix (receive) peer=(label=unconfined), unix (receive), # Allow all unix in the container unix peer=(label=@{profile_name}), # ignore DENIED message on / remount deny mount options=(ro, remount) -> /, deny mount options=(ro, remount, silent) -> /, # allow tmpfs mounts everywhere mount fstype=tmpfs, # allow hugetlbfs mounts everywhere mount fstype=hugetlbfs, # allow mqueue mounts everywhere mount fstype=mqueue, # allow fuse mounts everywhere mount fstype=fuse, mount fstype=fuse.*, # deny access under /proc/bus to avoid e.g. messing with pci devices directly deny @{PROC}/bus/** wklx, # deny writes in /proc/sys/fs but allow binfmt_misc to be mounted mount fstype=binfmt_misc -> /proc/sys/fs/binfmt_misc/, deny @{PROC}/sys/fs/** wklx, # allow efivars to be mounted, writing to it will be blocked though mount fstype=efivarfs -> /sys/firmware/efi/efivars/, # block some other dangerous paths deny @{PROC}/kcore rwklx, deny @{PROC}/kmem rwklx, deny @{PROC}/mem rwklx, deny @{PROC}/sysrq-trigger rwklx, # deny writes in /sys except for /sys/fs/cgroup, also allow # fusectl, securityfs and debugfs to be mounted there (read-only) mount fstype=fusectl -> /sys/fs/fuse/connections/, mount fstype=securityfs -> /sys/kernel/security/, mount fstype=debugfs -> /sys/kernel/debug/, deny mount fstype=debugfs -> /var/lib/ureadahead/debugfs/, mount fstype=proc -> /proc/, mount fstype=sysfs -> /sys/, mount options=(rw, nosuid, nodev, noexec, remount) -> /sys/, deny /sys/firmware/efi/efivars/** rwklx, deny /sys/kernel/security/** rwklx, mount options=(move) /sys/fs/cgroup/cgmanager/ -> /sys/fs/cgroup/cgmanager.lower/, mount options=(ro, nosuid, nodev, noexec, remount, strictatime) -> /sys/fs/cgroup/, # deny reads from debugfs deny /sys/kernel/debug/{,**} rwklx, # allow paths to be made slave, shared, private or unbindable # FIXME: This currently doesn't work due to the apparmor parser treating those as allowing all mounts. # mount options=(rw,make-slave) -> **, # mount options=(rw,make-rslave) -> **, # mount options=(rw,make-shared) -> **, # mount options=(rw,make-rshared) -> **, # mount options=(rw,make-private) -> **, # mount options=(rw,make-rprivate) -> **, # mount options=(rw,make-unbindable) -> **, # mount options=(rw,make-runbindable) -> **, # allow bind-mounts of anything except /proc, /sys and /dev mount options=(rw,bind) /[^spd]*{,/**}, mount options=(rw,bind) /d[^e]*{,/**}, mount options=(rw,bind) /de[^v]*{,/**}, mount options=(rw,bind) /dev/.[^l]*{,/**}, mount options=(rw,bind) /dev/.l[^x]*{,/**}, mount options=(rw,bind) /dev/.lx[^c]*{,/**}, mount options=(rw,bind) /dev/.lxc?*{,/**}, mount options=(rw,bind) /dev/[^.]*{,/**}, mount options=(rw,bind) /dev?*{,/**}, mount options=(rw,bind) /p[^r]*{,/**}, mount options=(rw,bind) /pr[^o]*{,/**}, mount options=(rw,bind) /pro[^c]*{,/**}, mount options=(rw,bind) /proc?*{,/**}, mount options=(rw,bind) /s[^y]*{,/**}, mount options=(rw,bind) /sy[^s]*{,/**}, mount options=(rw,bind) /sys?*{,/**}, # allow moving mounts except for /proc, /sys and /dev mount options=(rw,move) /[^spd]*{,/**}, mount options=(rw,move) /d[^e]*{,/**}, mount options=(rw,move) /de[^v]*{,/**}, mount options=(rw,move) /dev/.[^l]*{,/**}, mount options=(rw,move) /dev/.l[^x]*{,/**}, mount options=(rw,move) /dev/.lx[^c]*{,/**}, mount options=(rw,move) /dev/.lxc?*{,/**}, mount options=(rw,move) /dev/[^.]*{,/**}, mount options=(rw,move) /dev?*{,/**}, mount options=(rw,move) /p[^r]*{,/**}, mount options=(rw,move) /pr[^o]*{,/**}, mount options=(rw,move) /pro[^c]*{,/**}, mount options=(rw,move) /proc?*{,/**}, mount options=(rw,move) /s[^y]*{,/**}, mount options=(rw,move) /sy[^s]*{,/**}, mount options=(rw,move) /sys?*{,/**}, lxc-2.0.8/config/apparmor/abstractions/container-base0000644061062106075000000002006613105116772017646 00000000000000 network, capability, file, umount, # dbus, signal, ptrace and unix are only supported by recent apparmor # versions. Comment them if the apparmor parser doesn't recognize them. # This also needs additional rules to reach outside of the container via # DBus, so just let all of DBus within the container. dbus, # Allow us to receive signals from anywhere. Note: if per-container profiles # are supported, for container isolation this should be changed to something # like: # signal (receive) peer=unconfined, # signal (receive) peer=/usr/bin/lxc-start, signal (receive), # Allow us to send signals to ourselves signal peer=@{profile_name}, # Allow other processes to read our /proc entries, futexes, perf tracing and # kcmp for now (they will need 'read' in the first place). Administrators can # override with: # deny ptrace (readby) ... ptrace (readby), # Allow other processes to trace us by default (they will need 'trace' in # the first place). Administrators can override with: # deny ptrace (tracedby) ... ptrace (tracedby), # Allow us to ptrace ourselves ptrace peer=@{profile_name}, # Allow receive via unix sockets from anywhere. Note: if per-container # profiles are supported, for container isolation this should be changed to # something like: # unix (receive) peer=(label=unconfined), unix (receive), # Allow all unix in the container unix peer=(label=@{profile_name}), # ignore DENIED message on / remount deny mount options=(ro, remount) -> /, deny mount options=(ro, remount, silent) -> /, # allow tmpfs mounts everywhere mount fstype=tmpfs, # allow hugetlbfs mounts everywhere mount fstype=hugetlbfs, # allow mqueue mounts everywhere mount fstype=mqueue, # allow fuse mounts everywhere mount fstype=fuse, mount fstype=fuse.*, # deny access under /proc/bus to avoid e.g. messing with pci devices directly deny @{PROC}/bus/** wklx, # deny writes in /proc/sys/fs but allow binfmt_misc to be mounted mount fstype=binfmt_misc -> /proc/sys/fs/binfmt_misc/, deny @{PROC}/sys/fs/** wklx, # allow efivars to be mounted, writing to it will be blocked though mount fstype=efivarfs -> /sys/firmware/efi/efivars/, # block some other dangerous paths deny @{PROC}/kcore rwklx, deny @{PROC}/kmem rwklx, deny @{PROC}/mem rwklx, deny @{PROC}/sysrq-trigger rwklx, # deny writes in /sys except for /sys/fs/cgroup, also allow # fusectl, securityfs and debugfs to be mounted there (read-only) mount fstype=fusectl -> /sys/fs/fuse/connections/, mount fstype=securityfs -> /sys/kernel/security/, mount fstype=debugfs -> /sys/kernel/debug/, deny mount fstype=debugfs -> /var/lib/ureadahead/debugfs/, mount fstype=proc -> /proc/, mount fstype=sysfs -> /sys/, mount options=(rw, nosuid, nodev, noexec, remount) -> /sys/, deny /sys/firmware/efi/efivars/** rwklx, deny /sys/kernel/security/** rwklx, mount options=(move) /sys/fs/cgroup/cgmanager/ -> /sys/fs/cgroup/cgmanager.lower/, mount options=(ro, nosuid, nodev, noexec, remount, strictatime) -> /sys/fs/cgroup/, # deny reads from debugfs deny /sys/kernel/debug/{,**} rwklx, # allow paths to be made slave, shared, private or unbindable # FIXME: This currently doesn't work due to the apparmor parser treating those as allowing all mounts. # mount options=(rw,make-slave) -> **, # mount options=(rw,make-rslave) -> **, # mount options=(rw,make-shared) -> **, # mount options=(rw,make-rshared) -> **, # mount options=(rw,make-private) -> **, # mount options=(rw,make-rprivate) -> **, # mount options=(rw,make-unbindable) -> **, # mount options=(rw,make-runbindable) -> **, # allow bind-mounts of anything except /proc, /sys and /dev mount options=(rw,bind) /[^spd]*{,/**}, mount options=(rw,bind) /d[^e]*{,/**}, mount options=(rw,bind) /de[^v]*{,/**}, mount options=(rw,bind) /dev/.[^l]*{,/**}, mount options=(rw,bind) /dev/.l[^x]*{,/**}, mount options=(rw,bind) /dev/.lx[^c]*{,/**}, mount options=(rw,bind) /dev/.lxc?*{,/**}, mount options=(rw,bind) /dev/[^.]*{,/**}, mount options=(rw,bind) /dev?*{,/**}, mount options=(rw,bind) /p[^r]*{,/**}, mount options=(rw,bind) /pr[^o]*{,/**}, mount options=(rw,bind) /pro[^c]*{,/**}, mount options=(rw,bind) /proc?*{,/**}, mount options=(rw,bind) /s[^y]*{,/**}, mount options=(rw,bind) /sy[^s]*{,/**}, mount options=(rw,bind) /sys?*{,/**}, # allow moving mounts except for /proc, /sys and /dev mount options=(rw,move) /[^spd]*{,/**}, mount options=(rw,move) /d[^e]*{,/**}, mount options=(rw,move) /de[^v]*{,/**}, mount options=(rw,move) /dev/.[^l]*{,/**}, mount options=(rw,move) /dev/.l[^x]*{,/**}, mount options=(rw,move) /dev/.lx[^c]*{,/**}, mount options=(rw,move) /dev/.lxc?*{,/**}, mount options=(rw,move) /dev/[^.]*{,/**}, mount options=(rw,move) /dev?*{,/**}, mount options=(rw,move) /p[^r]*{,/**}, mount options=(rw,move) /pr[^o]*{,/**}, mount options=(rw,move) /pro[^c]*{,/**}, mount options=(rw,move) /proc?*{,/**}, mount options=(rw,move) /s[^y]*{,/**}, mount options=(rw,move) /sy[^s]*{,/**}, mount options=(rw,move) /sys?*{,/**}, # generated by: lxc-generate-aa-rules.py container-rules.base deny /proc/sys/[^kn]*{,/**} wklx, deny /proc/sys/k[^e]*{,/**} wklx, deny /proc/sys/ke[^r]*{,/**} wklx, deny /proc/sys/ker[^n]*{,/**} wklx, deny /proc/sys/kern[^e]*{,/**} wklx, deny /proc/sys/kerne[^l]*{,/**} wklx, deny /proc/sys/kernel/[^smhd]*{,/**} wklx, deny /proc/sys/kernel/d[^o]*{,/**} wklx, deny /proc/sys/kernel/do[^m]*{,/**} wklx, deny /proc/sys/kernel/dom[^a]*{,/**} wklx, deny /proc/sys/kernel/doma[^i]*{,/**} wklx, deny /proc/sys/kernel/domai[^n]*{,/**} wklx, deny /proc/sys/kernel/domain[^n]*{,/**} wklx, deny /proc/sys/kernel/domainn[^a]*{,/**} wklx, deny /proc/sys/kernel/domainna[^m]*{,/**} wklx, deny /proc/sys/kernel/domainnam[^e]*{,/**} wklx, deny /proc/sys/kernel/domainname?*{,/**} wklx, deny /proc/sys/kernel/h[^o]*{,/**} wklx, deny /proc/sys/kernel/ho[^s]*{,/**} wklx, deny /proc/sys/kernel/hos[^t]*{,/**} wklx, deny /proc/sys/kernel/host[^n]*{,/**} wklx, deny /proc/sys/kernel/hostn[^a]*{,/**} wklx, deny /proc/sys/kernel/hostna[^m]*{,/**} wklx, deny /proc/sys/kernel/hostnam[^e]*{,/**} wklx, deny /proc/sys/kernel/hostname?*{,/**} wklx, deny /proc/sys/kernel/m[^s]*{,/**} wklx, deny /proc/sys/kernel/ms[^g]*{,/**} wklx, deny /proc/sys/kernel/msg*/** wklx, deny /proc/sys/kernel/s[^he]*{,/**} wklx, deny /proc/sys/kernel/se[^m]*{,/**} wklx, deny /proc/sys/kernel/sem*/** wklx, deny /proc/sys/kernel/sh[^m]*{,/**} wklx, deny /proc/sys/kernel/shm*/** wklx, deny /proc/sys/kernel?*{,/**} wklx, deny /proc/sys/n[^e]*{,/**} wklx, deny /proc/sys/ne[^t]*{,/**} wklx, deny /proc/sys/net?*{,/**} wklx, deny /sys/[^fdc]*{,/**} wklx, deny /sys/c[^l]*{,/**} wklx, deny /sys/cl[^a]*{,/**} wklx, deny /sys/cla[^s]*{,/**} wklx, deny /sys/clas[^s]*{,/**} wklx, deny /sys/class/[^n]*{,/**} wklx, deny /sys/class/n[^e]*{,/**} wklx, deny /sys/class/ne[^t]*{,/**} wklx, deny /sys/class/net?*{,/**} wklx, deny /sys/class?*{,/**} wklx, deny /sys/d[^e]*{,/**} wklx, deny /sys/de[^v]*{,/**} wklx, deny /sys/dev[^i]*{,/**} wklx, deny /sys/devi[^c]*{,/**} wklx, deny /sys/devic[^e]*{,/**} wklx, deny /sys/device[^s]*{,/**} wklx, deny /sys/devices/[^v]*{,/**} wklx, deny /sys/devices/v[^i]*{,/**} wklx, deny /sys/devices/vi[^r]*{,/**} wklx, deny /sys/devices/vir[^t]*{,/**} wklx, deny /sys/devices/virt[^u]*{,/**} wklx, deny /sys/devices/virtu[^a]*{,/**} wklx, deny /sys/devices/virtua[^l]*{,/**} wklx, deny /sys/devices/virtual/[^n]*{,/**} wklx, deny /sys/devices/virtual/n[^e]*{,/**} wklx, deny /sys/devices/virtual/ne[^t]*{,/**} wklx, deny /sys/devices/virtual/net?*{,/**} wklx, deny /sys/devices/virtual?*{,/**} wklx, deny /sys/devices?*{,/**} wklx, deny /sys/f[^s]*{,/**} wklx, deny /sys/fs/[^c]*{,/**} wklx, deny /sys/fs/c[^g]*{,/**} wklx, deny /sys/fs/cg[^r]*{,/**} wklx, deny /sys/fs/cgr[^o]*{,/**} wklx, deny /sys/fs/cgro[^u]*{,/**} wklx, deny /sys/fs/cgrou[^p]*{,/**} wklx, deny /sys/fs/cgroup?*{,/**} wklx, deny /sys/fs?*{,/**} wklx, lxc-2.0.8/config/apparmor/abstractions/start-container0000644061062106075000000000254713105116772020075 00000000000000 network, capability, file, # The following 3 entries are only supported by recent apparmor versions. # Comment them if the apparmor parser doesn't recognize them. dbus, signal, ptrace, # currently blocked by apparmor bug mount -> /usr/lib/*/lxc/{**,}, mount -> /usr/lib/lxc/{**,}, mount fstype=devpts -> /dev/pts/, mount options=bind /dev/pts/ptmx/ -> /dev/ptmx/, mount options=bind /dev/pts/** -> /dev/**, mount options=(rw, make-slave) -> **, mount options=(rw, make-rslave) -> **, mount fstype=debugfs, # allow pre-mount hooks to stage mounts under /var/lib/lxc// mount -> /var/lib/lxc/{**,}, # required for some pre-mount hooks (like the new lxc-start-ephemeral) mount fstype=overlayfs, mount fstype=aufs, mount fstype=ecryptfs, # all umounts are under the original root's /mnt, but right now we # can't allow those umounts after pivot_root. So allow all umounts # right now. They'll be restricted for the container at least. umount, #umount /mnt/{**,}, # This may look a bit redundant, however it appears we need all of # them if we want things to work properly on all combinations of kernel # and userspace parser... pivot_root /usr/lib/lxc/, pivot_root /usr/lib/*/lxc/, pivot_root /usr/lib/lxc/**, pivot_root /usr/lib/*/lxc/**, change_profile -> lxc-*, change_profile -> unconfined, lxc-2.0.8/config/apparmor/usr.bin.lxc-start0000644061062106075000000000017513105116772015557 00000000000000#include /usr/bin/lxc-start flags=(attach_disconnected) { #include } lxc-2.0.8/config/apparmor/profiles/0000755061062106075000000000000013105117015014223 500000000000000lxc-2.0.8/config/apparmor/profiles/lxc-default0000644061062106075000000000073713105116772016316 00000000000000# Do not load this file. Rather, load /etc/apparmor.d/lxc-containers, which # will source all profiles under /etc/apparmor.d/lxc profile lxc-container-default flags=(attach_disconnected,mediate_deleted) { #include # the container may never be allowed to mount devpts. If it does, it # will remount the host's devpts. We could allow it to do it with # the newinstance option (but, right now, we don't). deny mount fstype=devpts, } lxc-2.0.8/config/apparmor/profiles/lxc-default-with-nesting0000644061062106075000000000101713105116772020724 00000000000000# Do not load this file. Rather, load /etc/apparmor.d/lxc-containers, which # will source all profiles under /etc/apparmor.d/lxc profile lxc-container-default-with-nesting flags=(attach_disconnected,mediate_deleted) { #include #include deny /dev/.lxc/proc/** rw, deny /dev/.lxc/sys/** rw, mount fstype=proc -> /var/cache/lxc/**, mount fstype=sysfs -> /var/cache/lxc/**, mount options=(rw,bind), mount fstype=cgroup -> /sys/fs/cgroup/**, } lxc-2.0.8/config/apparmor/profiles/lxc-default-with-mounting0000644061062106075000000000104013105116772021111 00000000000000# Do not load this file. Rather, load /etc/apparmor.d/lxc-containers, which # will source all profiles under /etc/apparmor.d/lxc profile lxc-container-default-with-mounting flags=(attach_disconnected,mediate_deleted) { #include # allow standard blockdevtypes. # The concern here is in-kernel superblock parsers bringing down the # host with bad data. However, we continue to disallow proc, sys, securityfs, # etc to nonstandard locations. mount fstype=ext*, mount fstype=xfs, mount fstype=btrfs, } lxc-2.0.8/config/apparmor/profiles/lxc-default-cgns0000644061062106075000000000102013105116772017230 00000000000000# Do not load this file. Rather, load /etc/apparmor.d/lxc-containers, which # will source all profiles under /etc/apparmor.d/lxc profile lxc-container-default-cgns flags=(attach_disconnected,mediate_deleted) { #include # the container may never be allowed to mount devpts. If it does, it # will remount the host's devpts. We could allow it to do it with # the newinstance option (but, right now, we don't). deny mount fstype=devpts, mount fstype=cgroup -> /sys/fs/cgroup/**, } lxc-2.0.8/config/apparmor/container-rules.base0000644061062106075000000000074013105116772016300 00000000000000# Run lxc-generate-aa-rules.py on this file after any modification, to generate # the container-rules file which is appended to container-base.in to create the # final abstractions/container-base. block /sys allow /sys/fs/cgroup/** allow /sys/devices/virtual/net/** allow /sys/class/net/** block /proc/sys allow /proc/sys/kernel/shm* allow /proc/sys/kernel/sem* allow /proc/sys/kernel/msg* allow /proc/sys/kernel/hostname allow /proc/sys/kernel/domainname allow /proc/sys/net/** lxc-2.0.8/config/etc/0000755061062106075000000000000013105117015011332 500000000000000lxc-2.0.8/config/etc/default.conf.unknown0000644061062106075000000000003113105116772015246 00000000000000lxc.network.type = empty lxc-2.0.8/config/etc/Makefile.am0000644061062106075000000000042313105116772013316 00000000000000configdir = $(sysconfdir)/lxc config_DATA = default.conf EXTRA_DIST = default.conf.lxcbr default.conf.libvirt default.conf.unknown distclean-local: @$(RM) -f default.conf @$(RM) -f compile config.guess config.sub depcomp install-sh ltmain.sh missing Makefile.in Makefile lxc-2.0.8/config/etc/default.conf.libvirt0000644061062106075000000000011113105116772015221 00000000000000lxc.network.type = veth lxc.network.link = virbr0 lxc.network.flags = up lxc-2.0.8/config/etc/Makefile.in0000644061062106075000000004071613105116775013343 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = config/etc ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/acinclude.m4 \ $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/tls.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h CONFIG_CLEAN_FILES = default.conf CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(configdir)" DATA = $(config_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APPARMOR_LIBS = @APPARMOR_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BINDIR = @BINDIR@ CAP_LIBS = @CAP_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CGMANAGER_CFLAGS = @CGMANAGER_CFLAGS@ CGMANAGER_LIBS = @CGMANAGER_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIR = @DATADIR@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFAULT_CGROUP_PATTERN = @DEFAULT_CGROUP_PATTERN@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOCDIR = @DOCDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ HAVE_DOXYGEN = @HAVE_DOXYGEN@ INCLUDEDIR = @INCLUDEDIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDIR = @LIBDIR@ LIBEXECDIR = @LIBEXECDIR@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCALSTATEDIR = @LOCALSTATEDIR@ LOGPATH = @LOGPATH@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBDIR = @LUA_LIBDIR@ LUA_LIBS = @LUA_LIBS@ LUA_SHAREDIR = @LUA_SHAREDIR@ LUA_VERSION = @LUA_VERSION@ LXCBINHOOKDIR = @LXCBINHOOKDIR@ LXCHOOKDIR = @LXCHOOKDIR@ LXCINITDIR = @LXCINITDIR@ LXCPATH = @LXCPATH@ LXCROOTFSMOUNT = @LXCROOTFSMOUNT@ LXCTEMPLATECONFIG = @LXCTEMPLATECONFIG@ LXCTEMPLATEDIR = @LXCTEMPLATEDIR@ LXC_ABI = @LXC_ABI@ LXC_ABI_MAJOR = @LXC_ABI_MAJOR@ LXC_ABI_MICRO = @LXC_ABI_MICRO@ LXC_ABI_MINOR = @LXC_ABI_MINOR@ LXC_DEFAULT_CONFIG = @LXC_DEFAULT_CONFIG@ LXC_DEVEL = @LXC_DEVEL@ LXC_DISTRO_SYSCONF = @LXC_DISTRO_SYSCONF@ LXC_GENERATE_DATE = @LXC_GENERATE_DATE@ LXC_GLOBAL_CONF = @LXC_GLOBAL_CONF@ LXC_USERNIC_CONF = @LXC_USERNIC_CONF@ LXC_USERNIC_DB = @LXC_USERNIC_DB@ LXC_VERSION = @LXC_VERSION@ LXC_VERSION_BASE = @LXC_VERSION_BASE@ LXC_VERSION_BETA = @LXC_VERSION_BETA@ LXC_VERSION_MAJOR = @LXC_VERSION_MAJOR@ LXC_VERSION_MICRO = @LXC_VERSION_MICRO@ LXC_VERSION_MINOR = @LXC_VERSION_MINOR@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NIH_CFLAGS = @NIH_CFLAGS@ NIH_DBUS_CFLAGS = @NIH_DBUS_CFLAGS@ NIH_DBUS_LIBS = @NIH_DBUS_LIBS@ NIH_LIBS = @NIH_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PREFIX = @PREFIX@ PYTHON = @PYTHON@ PYTHONDEV_CFLAGS = @PYTHONDEV_CFLAGS@ PYTHONDEV_LIBS = @PYTHONDEV_LIBS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RUNTIME_PATH = @RUNTIME_PATH@ SBINDIR = @SBINDIR@ SECCOMP_CFLAGS = @SECCOMP_CFLAGS@ SECCOMP_LIBS = @SECCOMP_LIBS@ SED = @SED@ SELINUX_LIBS = @SELINUX_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SYSCONFDIR = @SYSCONFDIR@ SYSTEMD_UNIT_DIR = @SYSTEMD_UNIT_DIR@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bashcompdir = @bashcompdir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ db2xman = @db2xman@ docdir = @docdir@ docdtd = @docdtd@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ configdir = $(sysconfdir)/lxc config_DATA = default.conf EXTRA_DIST = default.conf.lxcbr default.conf.libvirt default.conf.unknown all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu config/etc/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu config/etc/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-configDATA: $(config_DATA) @$(NORMAL_INSTALL) @list='$(config_DATA)'; test -n "$(configdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(configdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(configdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(configdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(configdir)" || exit $$?; \ done uninstall-configDATA: @$(NORMAL_UNINSTALL) @list='$(config_DATA)'; test -n "$(configdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(configdir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(DATA) installdirs: for dir in "$(DESTDIR)$(configdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic distclean-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-configDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-configDATA .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distclean-local distdir dvi dvi-am html \ html-am info info-am install install-am install-configDATA \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am uninstall-configDATA .PRECIOUS: Makefile distclean-local: @$(RM) -f default.conf @$(RM) -f compile config.guess config.sub depcomp install-sh ltmain.sh missing Makefile.in Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lxc-2.0.8/config/etc/default.conf.lxcbr0000644061062106075000000000016013105116772014664 00000000000000lxc.network.type = veth lxc.network.link = lxcbr0 lxc.network.flags = up lxc.network.hwaddr = 00:16:3e:xx:xx:xx lxc-2.0.8/config/install-sh0000755061062106075000000003546313105116775012532 00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2014-09-12.12; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. tab=' ' nl=' ' IFS=" $tab$nl" # Set DOITPROG to "echo" to test this script. doit=${DOITPROG-} doit_exec=${doit:-exec} # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false is_target_a_directory=possibly usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) is_target_a_directory=always dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done # We allow the use of options -d and -T together, by making -d # take the precedence; this is for compatibility with GNU install. if test -n "$dir_arg"; then if test -n "$dst_arg"; then echo "$0: target directory not allowed when installing a directory." >&2 exit 1 fi fi if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then if test $# -gt 1 || test "$is_target_a_directory" = always; then if test ! -d "$dst_arg"; then echo "$0: $dst_arg: Is not a directory." >&2 exit 1 fi fi fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test "$is_target_a_directory" = never; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) # $RANDOM is not portable (e.g. dash); use it when possible to # lower collision chance tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 # As "mkdir -p" follows symlinks and we work in /tmp possibly; so # create the $tmpdir first (and fail if unsuccessful) to make sure # that nobody tries to guess the $tmpdir name. if (umask $mkdir_umask && $mkdirprog $mkdir_mode "$tmpdir" && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. test_tmpdir="$tmpdir/a" ls_ld_tmpdir=`ls -ld "$test_tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac oIFS=$IFS IFS=/ set -f set fnord $dstdir shift set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: lxc-2.0.8/config/ltsugar.m40000644061062106075000000001044012756047127012442 00000000000000# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59, which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) lxc-2.0.8/config/config.guess0000755061062106075000000012564413105116775013047 00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2016 Free Software Foundation, Inc. timestamp='2016-10-02' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess # # Please send patches to . me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2016 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_SYSTEM}" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu eval $set_cc_for_build cat <<-EOF > $dummy.c #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #else LIBC=gnu #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` ;; esac # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ /sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || \ echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; earmv*) arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` machine=${arch}${endian}-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently (or will in the future) and ABI. case "${UNAME_MACHINE_ARCH}" in earm*) os=netbsdelf ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # Determine ABI tags. case "${UNAME_MACHINE_ARCH}" in earm*) expr='s/^earmv[0-9]/-eabi/;s/eb$//' abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}${abi}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; *:Sortix:*:*) echo ${UNAME_MACHINE}-unknown-sortix exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE=alpha ;; "EV4.5 (21064)") UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") UNAME_MACHINE=alpha ;; "EV5 (21164)") UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH=x86_64 fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/lslpp ] ; then IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH=hppa2.0n ;; 64) HP_ARCH=hppa2.0w ;; '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = hppa2.0w ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH=hppa2.0w else HP_ARCH=hppa64 fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW64*:*) echo ${UNAME_MACHINE}-pc-mingw64 exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; *:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC=gnulibc1 ; fi echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arc:Linux:*:* | arceb:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-${LIBC} else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi else echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf fi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; cris:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; e2k:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; hexagon:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; k1om:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; mips64el:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; openrisc*:Linux:*:*) echo or1k-unknown-linux-${LIBC} exit ;; or32:Linux:*:* | or1k*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) echo sparc-unknown-linux-${LIBC} exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; *) echo hppa-unknown-linux-${LIBC} ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-${LIBC} exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-${LIBC} exit ;; ppc64le:Linux:*:*) echo powerpc64le-unknown-linux-${LIBC} exit ;; ppcle:Linux:*:*) echo powerpcle-unknown-linux-${LIBC} exit ;; riscv32:Linux:*:* | riscv64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; tile*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; SX-ACE:SUPER-UX:*:*) echo sxace-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown eval $set_cc_for_build if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi fi elif test "$UNAME_PROCESSOR" = i386 ; then # Avoid executing cc on OS X 10.9, as it ships with a stub # that puts up a graphical alert prompting to install # developer tools. Any system running Mac OS X 10.7 or # later (Darwin 11 and later) is required to have a 64-bit # processor. This is not true of the ARM version of Darwin # that Apple uses in portable devices. UNAME_PROCESSOR=x86_64 fi echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-?:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = 386; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'` exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; amd64:Isilon\ OneFS:*:*) echo x86_64-unknown-onefs exit ;; esac cat >&2 </dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: lxc-2.0.8/config/Makefile.am0000644061062106075000000000010113105116772012534 00000000000000SUBDIRS = apparmor bash etc init selinux templates yum sysconfig lxc-2.0.8/config/sysconfig/0000755061062106075000000000000013105117015012563 500000000000000lxc-2.0.8/config/sysconfig/lxc0000644061062106075000000000164513105117007013223 00000000000000# LXC_AUTO - whether or not to start containers at boot LXC_AUTO="true" # BOOTGROUPS - What groups should start on bootup? # Comma separated list of groups. # Leading comma, trailing comma or embedded double # comma indicates when the NULL group should be run. # Example (default): boot the onboot group first then the NULL group BOOTGROUPS="onboot," # SHUTDOWNDELAY - Wait time for a container to shut down. # Container shutdown can result in lengthy system # shutdown times. Even 5 seconds per container can be # too long. SHUTDOWNDELAY=5 # OPTIONS can be used for anything else. # If you want to boot everything then # options can be "-a" or "-a -A". OPTIONS= # STOPOPTS are stop options. The can be used for anything else to stop. # If you want to kill containers fast, use -k STOPOPTS="-a -A -s" USE_LXC_BRIDGE="false" # overridden in lxc-net [ ! -f /usr/local/etc/default/lxc-net ] || . /usr/local/etc/default/lxc-net lxc-2.0.8/config/sysconfig/Makefile.am0000644061062106075000000000013513105116772014547 00000000000000sysconfigdir="@LXC_DISTRO_SYSCONF@" sysconfig_DATA = \ lxc EXTRA_DIST = $(sysconfig_DATA) lxc-2.0.8/config/sysconfig/lxc.in0000644061062106075000000000164113105116772013634 00000000000000# LXC_AUTO - whether or not to start containers at boot LXC_AUTO="true" # BOOTGROUPS - What groups should start on bootup? # Comma separated list of groups. # Leading comma, trailing comma or embedded double # comma indicates when the NULL group should be run. # Example (default): boot the onboot group first then the NULL group BOOTGROUPS="onboot," # SHUTDOWNDELAY - Wait time for a container to shut down. # Container shutdown can result in lengthy system # shutdown times. Even 5 seconds per container can be # too long. SHUTDOWNDELAY=5 # OPTIONS can be used for anything else. # If you want to boot everything then # options can be "-a" or "-a -A". OPTIONS= # STOPOPTS are stop options. The can be used for anything else to stop. # If you want to kill containers fast, use -k STOPOPTS="-a -A -s" USE_LXC_BRIDGE="false" # overridden in lxc-net [ ! -f @LXC_DISTRO_SYSCONF@/lxc-net ] || . @LXC_DISTRO_SYSCONF@/lxc-net lxc-2.0.8/config/sysconfig/Makefile.in0000644061062106075000000004067613105116775014601 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = config/sysconfig ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/acinclude.m4 \ $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/tls.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h CONFIG_CLEAN_FILES = lxc CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(sysconfigdir)" DATA = $(sysconfig_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/lxc.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APPARMOR_LIBS = @APPARMOR_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BINDIR = @BINDIR@ CAP_LIBS = @CAP_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CGMANAGER_CFLAGS = @CGMANAGER_CFLAGS@ CGMANAGER_LIBS = @CGMANAGER_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIR = @DATADIR@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFAULT_CGROUP_PATTERN = @DEFAULT_CGROUP_PATTERN@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOCDIR = @DOCDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ HAVE_DOXYGEN = @HAVE_DOXYGEN@ INCLUDEDIR = @INCLUDEDIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDIR = @LIBDIR@ LIBEXECDIR = @LIBEXECDIR@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCALSTATEDIR = @LOCALSTATEDIR@ LOGPATH = @LOGPATH@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBDIR = @LUA_LIBDIR@ LUA_LIBS = @LUA_LIBS@ LUA_SHAREDIR = @LUA_SHAREDIR@ LUA_VERSION = @LUA_VERSION@ LXCBINHOOKDIR = @LXCBINHOOKDIR@ LXCHOOKDIR = @LXCHOOKDIR@ LXCINITDIR = @LXCINITDIR@ LXCPATH = @LXCPATH@ LXCROOTFSMOUNT = @LXCROOTFSMOUNT@ LXCTEMPLATECONFIG = @LXCTEMPLATECONFIG@ LXCTEMPLATEDIR = @LXCTEMPLATEDIR@ LXC_ABI = @LXC_ABI@ LXC_ABI_MAJOR = @LXC_ABI_MAJOR@ LXC_ABI_MICRO = @LXC_ABI_MICRO@ LXC_ABI_MINOR = @LXC_ABI_MINOR@ LXC_DEFAULT_CONFIG = @LXC_DEFAULT_CONFIG@ LXC_DEVEL = @LXC_DEVEL@ LXC_DISTRO_SYSCONF = @LXC_DISTRO_SYSCONF@ LXC_GENERATE_DATE = @LXC_GENERATE_DATE@ LXC_GLOBAL_CONF = @LXC_GLOBAL_CONF@ LXC_USERNIC_CONF = @LXC_USERNIC_CONF@ LXC_USERNIC_DB = @LXC_USERNIC_DB@ LXC_VERSION = @LXC_VERSION@ LXC_VERSION_BASE = @LXC_VERSION_BASE@ LXC_VERSION_BETA = @LXC_VERSION_BETA@ LXC_VERSION_MAJOR = @LXC_VERSION_MAJOR@ LXC_VERSION_MICRO = @LXC_VERSION_MICRO@ LXC_VERSION_MINOR = @LXC_VERSION_MINOR@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NIH_CFLAGS = @NIH_CFLAGS@ NIH_DBUS_CFLAGS = @NIH_DBUS_CFLAGS@ NIH_DBUS_LIBS = @NIH_DBUS_LIBS@ NIH_LIBS = @NIH_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PREFIX = @PREFIX@ PYTHON = @PYTHON@ PYTHONDEV_CFLAGS = @PYTHONDEV_CFLAGS@ PYTHONDEV_LIBS = @PYTHONDEV_LIBS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RUNTIME_PATH = @RUNTIME_PATH@ SBINDIR = @SBINDIR@ SECCOMP_CFLAGS = @SECCOMP_CFLAGS@ SECCOMP_LIBS = @SECCOMP_LIBS@ SED = @SED@ SELINUX_LIBS = @SELINUX_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SYSCONFDIR = @SYSCONFDIR@ SYSTEMD_UNIT_DIR = @SYSTEMD_UNIT_DIR@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bashcompdir = @bashcompdir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ db2xman = @db2xman@ docdir = @docdir@ docdtd = @docdtd@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ sysconfigdir = "@LXC_DISTRO_SYSCONF@" sysconfig_DATA = \ lxc EXTRA_DIST = $(sysconfig_DATA) all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu config/sysconfig/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu config/sysconfig/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): lxc: $(top_builddir)/config.status $(srcdir)/lxc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-sysconfigDATA: $(sysconfig_DATA) @$(NORMAL_INSTALL) @list='$(sysconfig_DATA)'; test -n "$(sysconfigdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sysconfigdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sysconfigdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(sysconfigdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(sysconfigdir)" || exit $$?; \ done uninstall-sysconfigDATA: @$(NORMAL_UNINSTALL) @list='$(sysconfig_DATA)'; test -n "$(sysconfigdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(sysconfigdir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(DATA) installdirs: for dir in "$(DESTDIR)$(sysconfigdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-sysconfigDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-sysconfigDATA .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip install-sysconfigDATA installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am uninstall-sysconfigDATA .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lxc-2.0.8/config/Makefile.in0000644061062106075000000005050213105116775012562 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = config ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/acinclude.m4 \ $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/tls.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in compile config.guess \ config.sub install-sh ltmain.sh missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APPARMOR_LIBS = @APPARMOR_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BINDIR = @BINDIR@ CAP_LIBS = @CAP_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CGMANAGER_CFLAGS = @CGMANAGER_CFLAGS@ CGMANAGER_LIBS = @CGMANAGER_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIR = @DATADIR@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFAULT_CGROUP_PATTERN = @DEFAULT_CGROUP_PATTERN@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOCDIR = @DOCDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ HAVE_DOXYGEN = @HAVE_DOXYGEN@ INCLUDEDIR = @INCLUDEDIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDIR = @LIBDIR@ LIBEXECDIR = @LIBEXECDIR@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCALSTATEDIR = @LOCALSTATEDIR@ LOGPATH = @LOGPATH@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBDIR = @LUA_LIBDIR@ LUA_LIBS = @LUA_LIBS@ LUA_SHAREDIR = @LUA_SHAREDIR@ LUA_VERSION = @LUA_VERSION@ LXCBINHOOKDIR = @LXCBINHOOKDIR@ LXCHOOKDIR = @LXCHOOKDIR@ LXCINITDIR = @LXCINITDIR@ LXCPATH = @LXCPATH@ LXCROOTFSMOUNT = @LXCROOTFSMOUNT@ LXCTEMPLATECONFIG = @LXCTEMPLATECONFIG@ LXCTEMPLATEDIR = @LXCTEMPLATEDIR@ LXC_ABI = @LXC_ABI@ LXC_ABI_MAJOR = @LXC_ABI_MAJOR@ LXC_ABI_MICRO = @LXC_ABI_MICRO@ LXC_ABI_MINOR = @LXC_ABI_MINOR@ LXC_DEFAULT_CONFIG = @LXC_DEFAULT_CONFIG@ LXC_DEVEL = @LXC_DEVEL@ LXC_DISTRO_SYSCONF = @LXC_DISTRO_SYSCONF@ LXC_GENERATE_DATE = @LXC_GENERATE_DATE@ LXC_GLOBAL_CONF = @LXC_GLOBAL_CONF@ LXC_USERNIC_CONF = @LXC_USERNIC_CONF@ LXC_USERNIC_DB = @LXC_USERNIC_DB@ LXC_VERSION = @LXC_VERSION@ LXC_VERSION_BASE = @LXC_VERSION_BASE@ LXC_VERSION_BETA = @LXC_VERSION_BETA@ LXC_VERSION_MAJOR = @LXC_VERSION_MAJOR@ LXC_VERSION_MICRO = @LXC_VERSION_MICRO@ LXC_VERSION_MINOR = @LXC_VERSION_MINOR@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NIH_CFLAGS = @NIH_CFLAGS@ NIH_DBUS_CFLAGS = @NIH_DBUS_CFLAGS@ NIH_DBUS_LIBS = @NIH_DBUS_LIBS@ NIH_LIBS = @NIH_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PREFIX = @PREFIX@ PYTHON = @PYTHON@ PYTHONDEV_CFLAGS = @PYTHONDEV_CFLAGS@ PYTHONDEV_LIBS = @PYTHONDEV_LIBS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RUNTIME_PATH = @RUNTIME_PATH@ SBINDIR = @SBINDIR@ SECCOMP_CFLAGS = @SECCOMP_CFLAGS@ SECCOMP_LIBS = @SECCOMP_LIBS@ SED = @SED@ SELINUX_LIBS = @SELINUX_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SYSCONFDIR = @SYSCONFDIR@ SYSTEMD_UNIT_DIR = @SYSTEMD_UNIT_DIR@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bashcompdir = @bashcompdir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ db2xman = @db2xman@ docdir = @docdir@ docdtd = @docdtd@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = apparmor bash etc init selinux templates yum sysconfig all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu config/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu config/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lxc-2.0.8/config/tls.m40000644061062106075000000000130513105116772011553 00000000000000# See if we have working TLS. We only check to see if it compiles, and that # the resulting program actually runs, not whether the resulting TLS variables # work properly; that check is done at runtime, since we can run binaries # compiled with __thread on systems without TLS. AC_DEFUN([LXC_CHECK_TLS], [ AC_MSG_CHECKING(for TLS) AC_RUN_IFELSE([AC_LANG_SOURCE([[ static __thread int val; int main() { return 0; } ]])],[have_tls=yes],[have_tls=no],[have_tls=no ]) AC_MSG_RESULT($have_tls) if test "$have_tls" = "yes"; then AC_DEFINE([HAVE_TLS],[1],[Define if the compiler supports __thread]) AC_DEFINE([thread_local],[__thread],[Define to the compiler TLS keyword]) fi ]) lxc-2.0.8/config/yum/0000755061062106075000000000000013105117015011371 500000000000000lxc-2.0.8/config/yum/lxc-patch.py0000644061062106075000000000351613105116772013564 00000000000000# Yum plugin to re-patch container rootfs after a yum update is done # # Copyright (C) 2012 Oracle # # Authors: # Dwight Engen # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 # USA # import os from fnmatch import fnmatch from yum.plugins import TYPE_INTERACTIVE from yum.plugins import PluginYumExit requires_api_version = '2.0' plugin_type = (TYPE_INTERACTIVE,) def posttrans_hook(conduit): pkgs = [] patch_required = False # If we aren't root, we can't have updated anything if os.geteuid(): return # See what packages have files that were patched confpkgs = conduit.confString('main', 'packages') if not confpkgs: return tmp = confpkgs.split(",") for confpkg in tmp: pkgs.append(confpkg.strip()) conduit.info(2, "lxc-patch: checking if updated pkgs need patching...") ts = conduit.getTsInfo() for tsmem in ts.getMembers(): for pkg in pkgs: if fnmatch(pkg, tsmem.po.name): patch_required = True if patch_required: conduit.info(2, "lxc-patch: patching container...") os.spawnlp(os.P_WAIT, "lxc-patch", "lxc-patch", "--patch", "/") lxc-2.0.8/config/yum/Makefile.am0000644061062106075000000000014113105116772013352 00000000000000yumpluginsdir=$(datadir)/lxc yumplugins_DATA = \ lxc-patch.py EXTRA_DIST = $(yumplugins_DATA) lxc-2.0.8/config/yum/Makefile.in0000644061062106075000000004047513105116776013405 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = config/yum ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/acinclude.m4 \ $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/tls.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(yumpluginsdir)" DATA = $(yumplugins_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APPARMOR_LIBS = @APPARMOR_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BINDIR = @BINDIR@ CAP_LIBS = @CAP_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CGMANAGER_CFLAGS = @CGMANAGER_CFLAGS@ CGMANAGER_LIBS = @CGMANAGER_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIR = @DATADIR@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFAULT_CGROUP_PATTERN = @DEFAULT_CGROUP_PATTERN@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOCDIR = @DOCDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ HAVE_DOXYGEN = @HAVE_DOXYGEN@ INCLUDEDIR = @INCLUDEDIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDIR = @LIBDIR@ LIBEXECDIR = @LIBEXECDIR@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCALSTATEDIR = @LOCALSTATEDIR@ LOGPATH = @LOGPATH@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBDIR = @LUA_LIBDIR@ LUA_LIBS = @LUA_LIBS@ LUA_SHAREDIR = @LUA_SHAREDIR@ LUA_VERSION = @LUA_VERSION@ LXCBINHOOKDIR = @LXCBINHOOKDIR@ LXCHOOKDIR = @LXCHOOKDIR@ LXCINITDIR = @LXCINITDIR@ LXCPATH = @LXCPATH@ LXCROOTFSMOUNT = @LXCROOTFSMOUNT@ LXCTEMPLATECONFIG = @LXCTEMPLATECONFIG@ LXCTEMPLATEDIR = @LXCTEMPLATEDIR@ LXC_ABI = @LXC_ABI@ LXC_ABI_MAJOR = @LXC_ABI_MAJOR@ LXC_ABI_MICRO = @LXC_ABI_MICRO@ LXC_ABI_MINOR = @LXC_ABI_MINOR@ LXC_DEFAULT_CONFIG = @LXC_DEFAULT_CONFIG@ LXC_DEVEL = @LXC_DEVEL@ LXC_DISTRO_SYSCONF = @LXC_DISTRO_SYSCONF@ LXC_GENERATE_DATE = @LXC_GENERATE_DATE@ LXC_GLOBAL_CONF = @LXC_GLOBAL_CONF@ LXC_USERNIC_CONF = @LXC_USERNIC_CONF@ LXC_USERNIC_DB = @LXC_USERNIC_DB@ LXC_VERSION = @LXC_VERSION@ LXC_VERSION_BASE = @LXC_VERSION_BASE@ LXC_VERSION_BETA = @LXC_VERSION_BETA@ LXC_VERSION_MAJOR = @LXC_VERSION_MAJOR@ LXC_VERSION_MICRO = @LXC_VERSION_MICRO@ LXC_VERSION_MINOR = @LXC_VERSION_MINOR@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NIH_CFLAGS = @NIH_CFLAGS@ NIH_DBUS_CFLAGS = @NIH_DBUS_CFLAGS@ NIH_DBUS_LIBS = @NIH_DBUS_LIBS@ NIH_LIBS = @NIH_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PREFIX = @PREFIX@ PYTHON = @PYTHON@ PYTHONDEV_CFLAGS = @PYTHONDEV_CFLAGS@ PYTHONDEV_LIBS = @PYTHONDEV_LIBS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RUNTIME_PATH = @RUNTIME_PATH@ SBINDIR = @SBINDIR@ SECCOMP_CFLAGS = @SECCOMP_CFLAGS@ SECCOMP_LIBS = @SECCOMP_LIBS@ SED = @SED@ SELINUX_LIBS = @SELINUX_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SYSCONFDIR = @SYSCONFDIR@ SYSTEMD_UNIT_DIR = @SYSTEMD_UNIT_DIR@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bashcompdir = @bashcompdir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ db2xman = @db2xman@ docdir = @docdir@ docdtd = @docdtd@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ yumpluginsdir = $(datadir)/lxc yumplugins_DATA = \ lxc-patch.py EXTRA_DIST = $(yumplugins_DATA) all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu config/yum/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu config/yum/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-yumpluginsDATA: $(yumplugins_DATA) @$(NORMAL_INSTALL) @list='$(yumplugins_DATA)'; test -n "$(yumpluginsdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(yumpluginsdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(yumpluginsdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(yumpluginsdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(yumpluginsdir)" || exit $$?; \ done uninstall-yumpluginsDATA: @$(NORMAL_UNINSTALL) @list='$(yumplugins_DATA)'; test -n "$(yumpluginsdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(yumpluginsdir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(DATA) installdirs: for dir in "$(DESTDIR)$(yumpluginsdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-yumpluginsDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-yumpluginsDATA .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip install-yumpluginsDATA installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am uninstall-yumpluginsDATA .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lxc-2.0.8/templates/0000755061062106075000000000000013105117016011311 500000000000000lxc-2.0.8/templates/lxc-archlinux.in0000644061062106075000000002561513105116772014363 00000000000000#!/bin/bash # # template script for generating Arch Linux container for LXC # # # lxc: linux Container library # Authors: # Alexander Vladimirov # John Lane # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Detect use under userns (unsupported) for arg in "$@"; do [ "$arg" = "--" ] && break if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then echo "This template can't be used for unprivileged containers." 1>&2 echo "You may want to try the \"download\" template instead." 1>&2 exit 1 fi done # Make sure the usual locations are in PATH export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin # defaults arch=$(uname -m) default_path="@LXCPATH@" default_locale="en-US.UTF-8" pacman_config="/etc/pacman.conf" common_config="@LXCTEMPLATECONFIG@/common.conf" shared_config="@LXCTEMPLATECONFIG@/archlinux.common.conf" # by default, install 'base' except the kernel pkg_blacklist="linux" base_packages=() for pkg in $(pacman -Sqg base); do [ "${pkg_blacklist#*$pkg}" = "$pkg_blacklist" ] && base_packages+=($pkg) done declare -a additional_packages # split comma-separated string into an array # ${1} - string to split # ${2} - separator (default is ",") # ${result} - result value on success split_string() { local ifs=${IFS} IFS="${2:-,}" read -a result < <(echo "${1}") IFS=${ifs} return 0 } [ -f /etc/arch-release ] && is_arch=true # Arch-specific preconfiguration for container configure_arch() { # on ArchLinux, read defaults from host systemd configuration if [ "${is_arch}" ]; then cp -p /etc/locale.conf /etc/locale.gen "${rootfs_path}/etc/" else echo "LANG=${default_locale}" > "${rootfs_path}/etc/locale.conf" if [ -e "${rootfs_path}/etc/locale.gen" ]; then sed -i 's@^#\(en_US\.UTF-8\)@\1@' "${rootfs_path}/etc/locale.gen" if [ ! "${default_locale}" = "en_US.UTF-8" ]; then echo "${default_locale} ${default_locale##*.}" >> \ "${rootfs_path}/etc/locale.gen" fi fi fi # hostname and nameservers echo "${name}" > "${rootfs_path}/etc/hostname" # network configuration cat > "${rootfs_path}/etc/systemd/network/eth0.network" << EOF [Match] Name=eth0 [Network] DHCP=ipv4 EOF # chroot and configure system arch-chroot "${rootfs_path}" /bin/bash -s << EOF mkdir /run/lock locale-gen # set default boot target ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target # override getty@.service for container ttys sed -e 's/^ConditionPathExists=/# ConditionPathExists=/' \ -e 's/After=dev-%i.device/After=/' \ < /lib/systemd/system/getty\@.service \ > /etc/systemd/system/getty\@.service # fix systemd-sysctl service sed -e 's/^ConditionPathIsReadWrite=\/proc\/sys\/$/ConditionPathIsReadWrite=\/proc\/sys\/net\//' \ -e 's/^ExecStart=\/usr\/lib\/systemd\/systemd-sysctl$/ExecStart=\/usr\/lib\/systemd\/systemd-sysctl --prefix net/' \ -i /usr/lib/systemd/system/systemd-sysctl.service # initialize pacman keyring pacman-key --init pacman-key --populate archlinux # enable networkd systemctl enable systemd-networkd systemctl enable systemd-resolved ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf EOF # enable getty on active ttys local nttys=$(cat "${config_path}/config" ${shared_config} ${common_config} | grep "^lxc.tty" | head -n1 | cut -d= -f2 | tr -d "[:blank:]") local devttydir=$(cat "${config_path}/config" ${shared_config} ${common_config} | grep "^lxc.devttydir" | head -n1 | cut -d= -f2 | tr -d "[:blank:]") local devtty="" # bind getty instances to /dev//tty* if lxc.devttydir is set [ -n "${devttydir}" ] && devtty="${devttydir}-" if [ ${nttys:-0} -gt 1 ]; then ( cd "${rootfs_path}/etc/systemd/system/getty.target.wants" for i in $(seq 1 $nttys); do ln -sf "../getty@.service" "getty@${devtty}tty${i}.service"; done ) fi # update securetty to allow console login if devttydir is set if [ -n "${devttydir}" ]; then for i in $(seq 1 ${nttys:-1}); do echo "${devttydir}/tty${i}" >> "${rootfs_path}/etc/securetty" done fi [ -n "${devttydir}" ] && echo "${devttydir}/console" >> "${rootfs_path}/etc/securetty" # Arch default configuration allows only tty1-6 for login [ ${nttys:-0} -gt 6 ] && echo \ "You may want to modify container's /etc/securetty \ file to allow root logins on tty7 and higher" return 0 } # write container configuration files copy_configuration() { mkdir -p "${config_path}" local config="${config_path}/config" echo "lxc.utsname = ${name}" >> "${config}" grep -q "^lxc.arch" "${config}" 2>/dev/null \ || echo "lxc.arch = ${arch}" >> "${config}" grep -q "^lxc.rootfs" "${config}" 2>/dev/null \ || echo "lxc.rootfs = ${rootfs_path}" >> "${config}" [ -e "${shared_config}" ] \ && echo "lxc.include = ${shared_config}" >> "${config}" if [ $? -ne 0 ]; then echo "Failed to configure container" return 1 fi return 0 } # install packages within container chroot install_arch() { [ "${arch}" != "$(uname -m)" ] && different_arch=true if [ "${different_arch}" = "true" ]; then container_pacman_config=$(mktemp) container_mirrorlist=$(mktemp) sed -e "s:Architecture =.*:Architecture = ${arch}:g" \ -e "s:/etc/pacman.d/mirrorlist:${container_mirrorlist}:g" \ "${pacman_config}" > "${container_pacman_config}" sed -e "s:\(x86_64\|\$arch\):${arch}:g" \ /etc/pacman.d/mirrorlist > "${container_mirrorlist}" pacman_config="${container_pacman_config}" fi if ! pacstrap -dcGC "${pacman_config}" "${rootfs_path}" \ ${base_packages[@]}; then echo "Failed to install container packages" return 1 fi if [ "${different_arch}" = "true" ]; then sed -i -e "s:Architecture =.*:Architecture = ${arch}:g" \ "${rootfs_path}"/etc/pacman.conf cp "${container_mirrorlist}" "${rootfs_path}"/etc/pacman.d/mirrorlist rm "${container_pacman_config}" "${container_mirrorlist}" fi [ -d "${rootfs_path}/lib/modules" ] && ldconfig -r "${rootfs_path}" return 0 } usage() { cat < [-p|--path=] [-a|--arch=] [-r|--root_password=] [-P|--packages=] [-e|--enable_units=unit1,unit2...] [-d|--disable_units=unit1,unit2...] [-c|--config=] [-h|--help] Mandatory args: -n,--name container name, used to as an identifier for that container from now on Optional args: -p,--path path to where the container rootfs will be created (${default_path}) --rootfs path for actual container rootfs, (${default_path}/rootfs) -P,--packages preinstall additional packages, comma-separated list -e,--enable_units enable systemd services, comma-separated list -d,--disable_units disable systemd services, comma-separated list -c,--config use specified pacman config when installing container packages -a,--arch use specified architecture instead of host's architecture -r,--root_password set container root password -h,--help print this help EOF return 0 } options=$(getopt -o hp:P:e:d:n:c:a:r: -l help,rootfs:,path:,packages:,enable_units:,disable_units:,name:,config:,arch:,root_password: -- "${@}") if [ ${?} -ne 0 ]; then usage $(basename ${0}) exit 1 fi eval set -- "${options}" while true do case "${1}" in -h|--help) usage ${0} && exit 0;; -p|--path) path=${2}; shift 2;; -n|--name) name=${2}; shift 2;; --rootfs) rootfs_path=${2}; shift 2;; -P|--packages) additional_packages=${2}; shift 2;; -e|--enable_units) enable_units=${2}; shift 2;; -d|--disable_units) disable_units=${2}; shift 2;; -c|--config) pacman_config=${2}; shift 2;; -a|--arch) arch=${2}; shift 2;; -r|--root_password) root_passwd=${2}; shift 2;; --) shift 1; break ;; *) break ;; esac done if [ -z "${name}" ]; then echo "missing required 'name' parameter" exit 1 fi type pacman >/dev/null 2>&1 if [ ${?} -ne 0 ]; then echo "'pacman' command is missing, refer to wiki.archlinux.org for information about installing pacman" exit 1 fi if [ -z "${path}" ]; then path="${default_path}/${name}" fi if [ "${EUID}" != "0" ]; then echo "This script should be run as 'root'" exit 1 fi if [ -z "$rootfs_path" ]; then rootfs_path="${path}/rootfs" fi config_path="${path}" revert() { echo "Interrupted, cleaning up" lxc-destroy -n "${name}" rm -rf "${path}/${name}" rm -rf "${default_path}/${name}" exit 1 } trap revert SIGHUP SIGINT SIGTERM copy_configuration if [ ${?} -ne 0 ]; then echo "failed to write configuration file" rm -rf "${config_path}" exit 1 fi if [ ${#additional_packages[@]} -gt 0 ]; then split_string ${additional_packages} base_packages+=(${result[@]}) fi mkdir -p "${rootfs_path}" install_arch if [ ${?} -ne 0 ]; then echo "failed to install Arch Linux" rm -rf "${config_path}" "${path}" exit 1 fi configure_arch if [ ${?} -ne 0 ]; then echo "failed to configure Arch Linux for a container" rm -rf "${config_path}" "${path}" exit 1 fi if [ ${#enable_units[@]} -gt 0 ]; then split_string ${enable_units} for unit in ${result[@]}; do [ "${unit##*.}" = "service" ] || unit="${unit}.service" ln -s "/usr/lib/systemd/system/${unit}" \ "${rootfs_path}/etc/systemd/system/multi-user.target.wants/" done fi if [ ${#disable_units[@]} -gt 0 ]; then split_string ${disable_units} for unit in ${result[@]}; do [ "${unit##*.}" = "service" ] || unit="${unit}.service" ln -s /dev/null "${rootfs_path}/etc/systemd/system/${unit}" done fi if [ -n "${root_passwd}" ]; then echo "root:${root_passwd}" | chroot "${rootfs_path}" chpasswd fi cat << EOF Arch Linux container ${name} is successfully created! The configuration is stored in ${config_path}/config. Please refer to https://wiki.archlinux.org for information about configuring Arch Linux. EOF lxc-2.0.8/templates/lxc-sparclinux.in0000644061062106075000000006407413105116772014560 00000000000000#!/bin/sh # # Template script for generating Linux for SPARC for LXC # based on lxc-fedora, lxc-ubuntu # # Copyright © 2011 Wim Coekaerts # Copyright © 2012 Dwight Engen # Copyright � 2015 Wim Coekaerts # # Modified for Oracle Linux 5 # Wim Coekaerts # # Modified for Oracle Linux 6,7 combined OL4,5,6 into one template script # Dwight Engen # # Modified for Linux for SPARC 1.0 # Wim Coekaerts # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # Detect use under userns (unsupported) for arg in "$@"; do [ "$arg" = "--" ] && break if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then echo "This template can't be used for unprivileged containers." 1>&2 echo "You may want to try the \"download\" template instead." 1>&2 exit 1 fi done # Make sure the usual locations are in PATH export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin die() { echo "failed: $1" exit 1 } is_btrfs_subvolume() { if which btrfs >/dev/null 2>&1 && \ btrfs subvolume list "$1" >/dev/null 2>&1; then return 0 fi return 1 } can_chcon() { if which chcon >/dev/null 2>&1; then selinuxenabled >/dev/null 2>&1 return $? fi return 1 } # fix up the container_rootfs container_rootfs_patch() { echo "Patching container rootfs $container_rootfs for Linux for SPARC $container_release_major.$container_release_minor" # copy ourself into the container to be used to --patch the rootfs when # yum update on certain packages is done. we do this here instead of in # container_rootfs_configure() in case the patching done in this function # is updated in the future, we can inject the updated version of ourself # into older containers. if [ $container_rootfs != "/" ]; then cp -f `readlink -f $0` $container_rootfs/usr/bin/lxc-patch mkdir -p $container_rootfs/usr/share/yum-plugins cp @DATADIR@/lxc/lxc-patch.py $container_rootfs/usr/share/yum-plugins mkdir -p $container_rootfs/etc/yum/pluginconf.d cat < $container_rootfs/etc/yum/pluginconf.d/lxc-patch.conf [main] enabled=1 packages=dbus,initscripts,iptables,openssh-server,setup,selinux-policy,readahead,udev,util-linux,util-linux-ng EOF fi # "disable" selinux in the guest. The policy in the container isn't # likely to match the hosts (unless host == guest exactly) and the # kernel can only be enforcing one policy. # mkdir -p $container_rootfs/selinux echo 0 > $container_rootfs/selinux/enforce if [ -e $container_rootfs/etc/selinux/config ]; then sed -i 's|SELINUX=enforcing|SELINUX=disabled|' $container_rootfs/etc/selinux/config else mkdir -p $container_rootfs/etc/selinux echo "SELINUX=disabled" >$container_rootfs/etc/selinux/config fi sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*close|#session required pam_selinux.so close|' $container_rootfs/etc/pam.d/login sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*open|#session required pam_selinux.so open|' $container_rootfs/etc/pam.d/login sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*close|#session required pam_selinux.so close|' $container_rootfs/etc/pam.d/sshd sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*open|#session required pam_selinux.so open|' $container_rootfs/etc/pam.d/sshd # setting /proc/$$/loginuid doesn't work under user namespace, which # prevents logins from working sed -i 's|session[ \t]*required[ \t]*pam_loginuid.so|#session required pam_loginuid.so|' $container_rootfs/etc/pam.d/sshd sed -i 's|session[ \t]*required[ \t]*pam_loginuid.so|#session required pam_loginuid.so|' $container_rootfs/etc/pam.d/login if [ -f $container_rootfs/usr/sbin/selinuxenabled ]; then mv $container_rootfs/usr/sbin/selinuxenabled $container_rootfs/usr/sbin/selinuxenabled.lxcorig ln -s /bin/false $container_rootfs/usr/sbin/selinuxenabled fi # ensure /dev/ptmx refers to the newinstance devpts of the container, or # pty's will get crossed up with the hosts (https://lkml.org/lkml/2012/1/23/512) rm -f $container_rootfs/dev/ptmx ln -s pts/ptmx $container_rootfs/dev/ptmx # silence error in checking for selinux sed -i 's|cat /proc/self/attr/current|cat /proc/self/attr/current 2>/dev/null|' $container_rootfs/etc/rc.sysinit sed -i 's|cat /proc/self/attr/current|cat /proc/self/attr/current 2>/dev/null|' $container_rootfs/etc/rc.d/rc.sysinit # disable ipv6 rm -f $container_rootfs/etc/sysconfig/network-scripts/init.ipv6-global # remove module stuff for iptables it just shows errors that are not # relevant in a container if [ -f "$container_rootfs/etc/sysconfig/iptables-config" ]; then sed -i 's|IPTABLES_MODULES=".*|IPTABLES_MODULES=""|' $container_rootfs/etc/sysconfig/iptables-config sed -i 's|IPTABLES_MODULES_UNLOAD=".*|IPTABLES_MODULES_UNLOAD="no"|' $container_rootfs/etc/sysconfig/iptables-config fi # disable readahead in the container if [ $container_release_major = "1" -a -e $container_rootfs/etc/sysconfig/readahead ]; then rm -f $container_rootfs/etc/init/readahead-collector.conf rm -f $container_rootfs/etc/init/readahead-disable-services.conf sed -i 's|READAHEAD="yes"|READAHEAD="no"|' $container_rootfs/etc/sysconfig/readahead fi # no need to attempt to mount / sed -i 's|mount -f /$|# LXC mount -f /|' $container_rootfs/etc/rc.sysinit sed -i 's|mount -f /$|# LXC mount -f /|' $container_rootfs/etc/rc.d/rc.sysinit sed -i 's|action \$"Remounting root filesystem|/bin/true # LXC action $"Remounting root filesystem|' $container_rootfs/etc/rc.sysinit sed -i 's|action \$"Remounting root filesystem|/bin/true # LXC action $"Remounting root filesystem|' $container_rootfs/etc/rc.d/rc.sysinit # disable udev in the container sed -i 's|.sbin.start_udev||' $container_rootfs/etc/rc.sysinit sed -i 's|.sbin.start_udev||' $container_rootfs/etc/rc.d/rc.sysinit sed -i 's|\[ -x /sbin/hwclock|\[ 0 -eq 1|' $container_rootfs/etc/rc.d/init.d/halt sed -i 's|^\[ -x /sbin/hwclock|\[ 0 -eq 1|' $container_rootfs/etc/rc.sysinit sed -i 's|^\[ -x /sbin/hwclock|\[ 0 -eq 1|' $container_rootfs/etc/rc.d/rc.sysinit sed -i 's|^/sbin/hwclock|# LXC /sbin/nohwclock|' $container_rootfs/etc/rc.sysinit sed -i 's|^/sbin/hwclock|# LXC /sbin/nohwclock|' $container_rootfs/etc/rc.d/rc.sysinit touch $container_rootfs/.nolvm # fix assumptions that plymouth is available sed -i 's|\[ "$PROMPT" != no \] && plymouth|[ "$PROMPT" != no ] \&\& [ -n "$PLYMOUTH" ] \&\& plymouth|' $container_rootfs/etc/rc.sysinit sed -i 's|\[ "$PROMPT" != no \] && plymouth|[ "$PROMPT" != no ] \&\& [ -n "$PLYMOUTH" ] \&\& plymouth|' $container_rootfs/etc/rc.d/rc.sysinit rm -f $container_rootfs/etc/init/plymouth-shutdown.conf rm -f $container_rootfs/etc/init/quit-plymouth.conf rm -f $container_rootfs/etc/init/splash-manager.conf # dont try to unmount /dev/lxc devices sed -i 's|&& $1 !~ /^\\/dev\\/ram/|\&\& $2 !~ /^\\/dev\\/lxc/ \&\& $1 !~ /^\\/dev\\/ram/|' $container_rootfs/etc/init.d/halt # don't try to unmount swap sed -i 's|\[ -f /proc/swaps \]|# LXC [ -f /proc/swaps ]|' $container_rootfs/etc/init.d/halt sed -i 's|mount -n -o remount /dev/shm >/dev/null 2>&1$|mkdir -p /dev/shm \&\& mount -t tmpfs tmpfs /dev/shm # LXC|' $container_rootfs/etc/rc.sysinit sed -i 's|mount -n -o remount /dev/shm >/dev/null 2>&1$|mkdir -p /dev/shm \&\& mount -t tmpfs tmpfs /dev/shm # LXC|' $container_rootfs/etc/rc.d/rc.sysinit # there might be other services that are useless but the below set is a good start # some of these might not exist in the image, so we silence chkconfig complaining # about the service file not being found for service in \ acpid apmd auditd autofs cpuspeed dund gpm haldaemon hidd \ ip6tables irqbalance iscsi iscsid isdn kdump kudzu \ lm_sensors lvm2-monitor mdmonitor microcode_ctl \ ntpd pcmcia postfix sendmail udev-post xfs ; do chroot $container_rootfs chkconfig 2>/dev/null $service off done for service in rsyslog ; do chroot $container_rootfs chkconfig 2>/dev/null $service on done } container_rootfs_configure() { container_rootfs_patch echo "Configuring container for Linux for SPARC $container_release_major.$container_release_minor" # configure the network to use dhcp. we set DHCP_HOSTNAME so the guest # will report its name and be resolv'able by the hosts dnsmasq cat < $container_rootfs/etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 BOOTPROTO=dhcp ONBOOT=yes HOSTNAME=$name DHCP_HOSTNAME=\`hostname\` NM_CONTROLLED=no TYPE=Ethernet EOF cat < $container_rootfs/etc/sysconfig/network NETWORKING=yes NETWORKING_IPV6=no HOSTNAME=$name EOF # set minimal hosts echo "127.0.0.1 localhost $name" > $container_rootfs/etc/hosts # this file has to exist for libvirt/Virtual machine monitor to boot the container touch $container_rootfs/etc/mtab # setup console and tty[1-4] for login. note that /dev/console and # /dev/tty[1-4] will be symlinks to the ptys /dev/lxc/console and # /dev/lxc/tty[1-4] so that package updates can overwrite the symlinks. # lxc will maintain these links and bind mount ptys over /dev/lxc/* # since lxc.devttydir is specified in the config. # allow root login on console, tty[1-4], and pts/0 for libvirt echo "# LXC (Linux Containers)" >>$container_rootfs/etc/securetty echo "lxc/console" >>$container_rootfs/etc/securetty for i in 1 2 3 4; do echo "lxc/tty$i" >>$container_rootfs/etc/securetty done echo "# For libvirt/Virtual Machine Monitor" >>$container_rootfs/etc/securetty for i in 0 1 2 3 4; do echo "pts/$i" >>$container_rootfs/etc/securetty done # prevent mingetty from calling vhangup(2) since it fails with userns if [ -f $container_rootfs/etc/init/tty.conf ]; then sed -i 's|mingetty|mingetty --nohangup|' $container_rootfs/etc/init/tty.conf fi # create maygetty which only spawns a getty on the console when running # under lxc, not libvirt-lxc which symlinks /dev/console to the same pty # as /dev/tty1 cat <$container_rootfs/sbin/maygetty #!/bin/sh if [ "\$container" = "lxc" ]; then exec /sbin/mingetty \$@ fi exec sleep infinity EOF chmod 755 $container_rootfs/sbin/maygetty cat < $container_rootfs/etc/init/console.conf # console - getty # # This service maintains a getty on the console from the point the system is # started until it is shut down again. start on stopped rc RUNLEVEL=[2345] stop on runlevel [!2345] env container respawn exec /sbin/maygetty --nohangup --noclear /dev/console EOF cat < $container_rootfs/etc/init/power-status-changed.conf # power-status-changed - used to cleanly shut down the container # # This task is run whenever init receives SIGPWR # Used to shut down the machine. start on power-status-changed exec init 0 EOF # start with a clean /var/log/messages rm -f $container_rootfs/var/log/messages # set initial timezone as on host if [ -f /etc/sysconfig/clock ]; then . /etc/sysconfig/clock echo ZONE=$ZONE > $container_rootfs/etc/sysconfig/clock chroot $container_rootfs tzdata-update else echo "Timezone in container is not configured. Adjust it manually." fi # add oracle user chroot $container_rootfs useradd -m -s /bin/bash oracle printf "Added container user:\033[1moracle\033[0m\n" printf "Added container user:\033[1mroot\033[0m\n" } # create the container's lxc config file container_config_create() { echo "Create configuration file $cfg_dir/config" mkdir -p $cfg_dir || die "unable to create config dir $cfg_dir" echo "# Common configuration" >> $cfg_dir/config if [ -e "@LXCTEMPLATECONFIG@/sparclinux.common.conf" ]; then echo "lxc.include = @LXCTEMPLATECONFIG@/sparclinux.common.conf" >> $cfg_dir/config fi cat <> $cfg_dir/config || die "unable to create $cfg_dir/config" # Container configuration for Linux for SPARC $container_release_major.$container_release_minor lxc.arch = $arch lxc.utsname = $name EOF grep -q "^lxc.rootfs" $cfg_dir/config 2>/dev/null || echo "lxc.rootfs = $container_rootfs" >> $cfg_dir/config echo "lxc.cap.drop = sys_resource" >>$cfg_dir/config echo "lxc.cap.drop = setfcap setpcap" >>$cfg_dir/config echo "# Networking" >>$cfg_dir/config # see if the default network settings were already specified lxc_network_type=`grep '^lxc.network.type' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'` if [ -z "$lxc_network_type" ]; then echo "lxc.network.type = veth" >>$cfg_dir/config lxc_network_type=veth fi lxc_network_link=`grep '^lxc.network.link' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'` if [ -z "$lxc_network_link" ]; then echo "lxc.network.link = lxcbr0" >>$cfg_dir/config lxc_network_link=lxcbr0 fi lxc_network_hwaddr=`grep '^lxc.network.hwaddr' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'` if [ -z "$lxc_network_hwaddr" ]; then # generate a hwaddr for the container # see http://sourceforge.net/tracker/?func=detail&aid=3411497&group_id=163076&atid=826303 local hwaddr="00:16:3e:`dd if=/dev/urandom bs=8 count=1 2>/dev/null |od -t x8 | \ head -n1 | awk '{print $2}' | cut -c1-6 | \ sed 's/\(..\)/\1:/g; s/.$//'`" echo "lxc.network.hwaddr = $hwaddr" >>$cfg_dir/config fi lxc_network_flags=`grep '^lxc.network.flags' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'` if [ -z "$lxc_network_flags" ]; then echo "lxc.network.flags = up" >>$cfg_dir/config fi cat <> $cfg_dir/config || die "unable to create $cfg_dir/config" lxc.network.name = eth0 lxc.network.mtu = 1500 EOF } container_rootfs_clone() { if is_btrfs_subvolume $template_rootfs; then # lxc-create already made $container_rootfs a btrfs subvolume, but # in this case we want to snapshot the original subvolume so we we # have to delete the one that lxc-create made btrfs subvolume delete $container_rootfs btrfs subvolume snapshot $template_rootfs $container_rootfs || die "btrfs clone template" else echo "Copying rootfs ..." cp -axT $template_rootfs $container_rootfs || die "copy template" fi } container_rootfs_repo_create() { echo "# LXC generated .repo file" >$1 echo "[$2]" >>$1 echo "name=Linux for SPARC $container_release_major.$container_release_minor ($basearch)" >>$1 echo "baseurl=$3/" >>$1 echo "enabled=1" >>$1 echo "skip_if_unavailable=1" >>$1 if [ "$4" != "" ]; then echo "gpgkey=$yum_url/RPM-GPG-KEY-oracle-ol$container_release_major" >>$1 echo "gpgcheck=1" >>$1 else echo "gpgcheck=0" >>$1 fi } container_rootfs_dev_create() { # create required devices. note that /dev/console will be created by lxc # or libvirt itself to be a symlink to the right pty. # take care to not nuke /dev in case $container_rootfs isn't set dev_path="$container_rootfs/dev" if [ $container_rootfs != "/" -a -d $dev_path ]; then rm -rf $dev_path fi mkdir -p $dev_path if can_chcon; then # ensure symlinks created in /dev have the right context chcon -t device_t $dev_path fi mknod -m 666 $dev_path/null c 1 3 mknod -m 666 $dev_path/zero c 1 5 mknod -m 666 $dev_path/random c 1 8 mknod -m 666 $dev_path/urandom c 1 9 mkdir -m 755 $dev_path/pts mkdir -m 1777 $dev_path/shm mknod -m 666 $dev_path/tty c 5 0 mknod -m 666 $dev_path/tty1 c 4 1 mknod -m 666 $dev_path/tty2 c 4 2 mknod -m 666 $dev_path/tty3 c 4 3 mknod -m 666 $dev_path/tty4 c 4 4 mknod -m 666 $dev_path/full c 1 7 mknod -m 600 $dev_path/initctl p # set selinux labels same as host if can_chcon; then for node in null zero random urandom pts shm \ tty tty0 tty1 tty2 tty3 tty4 full ; do chcon --reference /dev/$node $dev_path/$node 2>/dev/null done fi } container_rootfs_create() { if can_chcon; then chcon --reference / $container_rootfs 2>/dev/null fi cmds="rpm wget yum" for cmd in $cmds; do which $cmd >/dev/null 2>&1 if [ $? -ne 0 ]; then die "The $cmd command is required, please install it" fi done mkdir -p @LOCALSTATEDIR@/lock/subsys ( flock -x 9 if [ $? -ne 0 ]; then die "The template is busy." fi echo "Yum installing release $container_release_major.$container_release_minor for $basearch" if [ -n "$repourl" ]; then yum_url=$repourl else yum_url=http://yum.oracle.com fi if [ -n "$baseurl" ]; then # create .repo pointing at baseurl repo="lxc-install" mkdir -p $container_rootfs/etc/yum.repos.d container_rootfs_repo_create \ $container_rootfs/etc/yum.repos.d/lxc-install.repo $repo $baseurl else # get public-yum repo file if [ $container_release_major = "1" ]; then repofile=yum-linux-sparc64.repo else die "Unsupported release $container_release_major" fi mkdir -p $container_rootfs/etc/yum.repos.d wget -q $yum_url/$repofile -O $container_rootfs/etc/yum.repos.d/$repofile if [ $? -ne 0 ]; then die "Unable to download repo file $yum_url/$repofile, release unavailable" fi # yum will take $basearch from host, so force the arch we want sed -i "s|\$basearch|$basearch|" $container_rootfs/etc/yum.repos.d/$repofile # replace url if they specified one if [ -n "$repourl" ]; then sed -i "s|baseurl=http://yum.oracle.com/|baseurl=$repourl/repo|" $container_rootfs/etc/yum.repos.d/$repofile sed -i "s|gpgkey=http://yum.oracle.com|gpgkey=$repourl|" $container_rootfs/etc/yum.repos.d/$repofile fi # disable all repos, then enable the repo for the version we are installing. if [ $container_release_minor = "latest" ]; then repo="lfs"_$container_release_minor else die "Unsupported release $container_release_major.$container_release_minor" fi sed -i "s|enabled=1|enabled=0|" $container_rootfs/etc/yum.repos.d/$repofile sed -i "/\[$repo\]/,/\[/ s/enabled=0/enabled=1/" $container_rootfs/etc/yum.repos.d/$repofile fi container_rootfs_dev_create # don't put devpts,proc, nor sysfs in here, it will already be mounted for us by lxc/libvirt echo "" >$container_rootfs/etc/fstab # create rpm db, download and yum install minimal packages mkdir -p $container_rootfs/var/lib/rpm rpm --root $container_rootfs --initdb yum_args="--installroot $container_rootfs --disablerepo=* --enablerepo=$repo -y --nogpgcheck" min_pkgs="yum initscripts passwd rsyslog vim-minimal openssh-server openssh-clients dhclient chkconfig rootfiles policycoreutils sparclinux-release" # we unshare the mount namespace because yum installing the ol4 # packages causes $rootfs/proc to be mounted on lxc-unshare -s MOUNT yum -- $yum_args install $min_pkgs $user_pkgs if [ $? -ne 0 ]; then die "Failed to download and install the rootfs, aborting." fi # rsyslog and pam depend on coreutils for some common commands in # their POSTIN scriptlets, but coreutils wasn't installed yet. now # that coreutils is installed, reinstall the packages so their POSTIN # runs right. similarly, libutempter depends on libselinux.so.1 when # it runs /usr/sbin/groupadd, so reinstall it too redo_pkgs="" if [ x"$redo_pkgs" != x ]; then rpm --root $container_rootfs --nodeps -e $redo_pkgs lxc-unshare -s MOUNT yum -- $yum_args install $redo_pkgs if [ $? -ne 0 ]; then die "Unable to reinstall packages" fi fi # these distributions put the rpm database in a place the guest is # not expecting it, so move it if [ $host_distribution = "Ubuntu" -o $host_distribution = "Debian" ]; then mv $container_rootfs/$HOME/.rpmdb/* $container_rootfs/var/lib/rpm fi # if the native rpm created the db with Hash version 9, we need to # downgrade it to Hash version 8 for use with OL5.x db_version=`file $container_rootfs/var/lib/rpm/Packages | \ grep -o 'version [0-9]*' |awk '{print $2}'` # the host rpm may not be the same as the guest, rebuild the db with # the guest rpm version echo "Rebuilding rpm database" rm -f $container_rootfs/var/lib/rpm/__db* chroot $container_rootfs rpm --rebuilddb >/dev/null 2>&1 ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-sparclinux-$name if [ $? -ne 0 ]; then exit 1 fi } container_release_get() { if [ -f $1/etc/sparclinux-release ]; then container_release_version=`cat $1/etc/sparclinux-release |awk '/^Linux/ {print $5}'` container_release_major=`echo $container_release_version |awk -F '.' '{print $1}'` container_release_minor=`echo $container_release_version |awk -F '.' '{print $2}'` else echo "Unable to determine container release version" exit 1 fi } usage() { cat < architecture (sparc64) -R|--release= release to download for the new container --rootfs= rootfs path -r|--rpms= additional rpms to install into container -u|--url= replace yum repo url (ie. Oracle public-yum mirror) --baseurl= use package repository (ie. file:///mnt) arch and release must also be specified -t|--templatefs= copy/clone rootfs at path instead of downloading -P|--patch= only patch the rootfs at path for use as a container -h|--help Release is of the format "major.minor", for example "1.0" or "1.latest" This template supports Linux for SPARC release 1.0 EOF return 0 } options=$(getopt -o hp:n:a:R:r:u:t: -l help,rootfs:,path:,name:,arch:,release:,rpms:,url:,templatefs:,patch:,baseurl: -- "$@") if [ $? -ne 0 ]; then usage $(basename $0) exit 1 fi eval set -- "$options" while true do case "$1" in -h|--help) usage $0 && exit 0;; -p|--path) cfg_dir=$2; shift 2;; --rootfs) container_rootfs=$2; shift 2;; -n|--name) name=$2; shift 2;; -a|--arch) arch=$2; shift 2;; -R|--release) container_release_version=$2; shift 2;; -r|--rpms) user_pkgs=$2; shift 2;; -u|--url) repourl=$2; shift 2;; -t|--templatefs) template_rootfs=$2; shift 2;; --patch) patch_rootfs=$2; shift 2;; --baseurl) baseurl=$2; shift 2;; --) shift 1; break ;; *) break ;; esac done # make sure mandatory args are given and valid if [ "$(id -u)" != "0" ]; then echo "This script should be run as 'root'" exit 1 fi if [ -n "$baseurl" ]; then if [ "$arch" = "" -o "$container_release_version" = "" ]; then echo "The --arch and --release must be specified when using --baseurl" usage exit 1 fi fi if [ "$arch" = "" ]; then arch=$(uname -m) fi if [ -n "$patch_rootfs" ]; then container_rootfs="$patch_rootfs" container_release_get $container_rootfs container_rootfs_patch exit 0 fi if [ -z $name ]; then echo "Container name must be given" usage exit 1 fi if [ -z $cfg_dir ]; then echo "Configuration directory must be given, check lxc-create" usage exit 1 fi basearch=$arch if [ "$arch" != "sparc64" ]; then echo "Bad architecture given, check lxc-create" usage exit 1 fi if [ -f /etc/sparclinux-release ]; then host_distribution="SPARCLinux" host_release_version=`cat /etc/sparclinux-release |awk '{print $5}'` host_release_major=`echo $host_release_version |awk -F '.' '{print $1}'` host_release_minor=`echo $host_release_version |awk -F '.' '{print $2}'` else echo "Unable to determine host distribution" exit 1 fi echo "Host is $host_distribution $host_release_version" if [ -z "$container_rootfs" ]; then container_rootfs="$cfg_dir/rootfs" fi if [ -n "$template_rootfs" ]; then container_release_get $template_rootfs else if [ -z "$container_release_version" ]; then if [ $host_distribution = "SPARCLinux" ]; then container_release_version=$host_release_version else echo "No release specified with -R, defaulting to 1.latest" container_release_version="1.latest" fi fi container_release_major=`echo $container_release_version |awk -F '.' '{print $1}'` container_release_minor=`echo $container_release_version |awk -F '.' '{print $2}'` fi container_config_create if [ -n "$template_rootfs" ]; then container_rootfs_clone else container_rootfs_create fi container_release_get $container_rootfs container_rootfs_configure echo "Container : $container_rootfs" echo "Config : $cfg_dir/config" echo "Network : eth0 ($lxc_network_type) on $lxc_network_link" lxc-2.0.8/templates/lxc-oracle.in0000644061062106075000000012121413105116772013623 00000000000000#!/bin/sh # # Template script for generating Oracle Enterprise Linux container for LXC # based on lxc-fedora, lxc-ubuntu # # Copyright © 2011 Wim Coekaerts # Copyright © 2012 Dwight Engen # # Modified for Oracle Linux 5 # Wim Coekaerts # # Modified for Oracle Linux 6,7 combined OL4,5,6 into one template script # Dwight Engen # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # Detect use under userns (unsupported) for arg in "$@"; do [ "$arg" = "--" ] && break if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then echo "This template can't be used for unprivileged containers." 1>&2 echo "You may want to try the \"download\" template instead." 1>&2 exit 1 fi done # Make sure the usual locations are in PATH export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin die() { echo "failed: $1" exit 1 } is_btrfs_subvolume() { if which btrfs >/dev/null 2>&1 && \ btrfs subvolume list "$1" >/dev/null 2>&1; then return 0 fi return 1 } can_chcon() { if which chcon >/dev/null 2>&1; then selinuxenabled >/dev/null 2>&1 return $? fi return 1 } # fix up the container_rootfs container_rootfs_patch() { echo "Patching container rootfs $container_rootfs for Oracle Linux $container_release_major.$container_release_minor" # copy ourself into the container to be used to --patch the rootfs when # yum update on certain packages is done. we do this here instead of in # container_rootfs_configure() in case the patching done in this function # is updated in the future, we can inject the updated version of ourself # into older containers. if [ $container_rootfs != "/" ]; then cp -f `readlink -f $0` $container_rootfs/usr/bin/lxc-patch if [ $container_release_major -lt "6" ]; then mkdir -p $container_rootfs/usr/lib/yum-plugins cp @DATADIR@/lxc/lxc-patch.py $container_rootfs/usr/lib/yum-plugins fi if [ $container_release_major -ge "6" ]; then mkdir -p $container_rootfs/usr/share/yum-plugins cp @DATADIR@/lxc/lxc-patch.py $container_rootfs/usr/share/yum-plugins fi mkdir -p $container_rootfs/etc/yum/pluginconf.d cat < $container_rootfs/etc/yum/pluginconf.d/lxc-patch.conf [main] enabled=1 packages=dbus,initscripts,iptables,openssh-server,setup,selinux-policy,readahead,udev,util-linux,util-linux-ng EOF fi if [ $container_release_major = "4" ]; then # yum plugin type of TYPE_INTERFACE works in all releases but gives a # deprecation warning on major > 4, so we default to TYPE_INTERACTIVE # and fix it up here sed -i 's|TYPE_INTERACTIVE|TYPE_INTERFACE|' $container_rootfs/usr/lib/yum-plugins/lxc-patch.py if [ -f $container_rootfs/etc/yum.repos.d/ULN-Base.repo ]; then mv $container_rootfs/etc/yum.repos.d/ULN-Base.repo \ $container_rootfs/etc/yum.repos.d/ULN-Base.repo.lxc-disabled fi echo "plugins = 1" >>$container_rootfs/etc/yum.conf fi # "disable" selinux in the guest. The policy in the container isn't # likely to match the hosts (unless host == guest exactly) and the # kernel can only be enforcing one policy. # # The OL 5 init honors /etc/selinux/config, but note that # this doesnt actually disable it if it's enabled in the host, since # libselinux::is_selinux_enabled() in the guest will check # /proc/filesystems and see selinuxfs, thus reporting that it is on # (ie. check the output of sestatus in the guest). We also replace # /usr/sbin/selinuxenabled with a symlink to /bin/false so that init # scripts (ie. mcstransd) that call that think selinux is disabled. mkdir -p $container_rootfs/selinux echo 0 > $container_rootfs/selinux/enforce if [ -e $container_rootfs/etc/selinux/config ]; then sed -i 's|SELINUX=enforcing|SELINUX=disabled|' $container_rootfs/etc/selinux/config else mkdir -p $container_rootfs/etc/selinux echo "SELINUX=disabled" >$container_rootfs/etc/selinux/config fi sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*close|#session required pam_selinux.so close|' $container_rootfs/etc/pam.d/login sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*open|#session required pam_selinux.so open|' $container_rootfs/etc/pam.d/login sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*close|#session required pam_selinux.so close|' $container_rootfs/etc/pam.d/sshd sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*open|#session required pam_selinux.so open|' $container_rootfs/etc/pam.d/sshd # setting /proc/$$/loginuid doesn't work under user namespace, which # prevents logins from working sed -i 's|session[ \t]*required[ \t]*pam_loginuid.so|#session required pam_loginuid.so|' $container_rootfs/etc/pam.d/sshd sed -i 's|session[ \t]*required[ \t]*pam_loginuid.so|#session required pam_loginuid.so|' $container_rootfs/etc/pam.d/login if [ -f $container_rootfs/usr/sbin/selinuxenabled ]; then mv $container_rootfs/usr/sbin/selinuxenabled $container_rootfs/usr/sbin/selinuxenabled.lxcorig ln -s /bin/false $container_rootfs/usr/sbin/selinuxenabled fi # ensure /dev/ptmx refers to the newinstance devpts of the container, or # pty's will get crossed up with the hosts (https://lkml.org/lkml/2012/1/23/512) rm -f $container_rootfs/dev/ptmx ln -s pts/ptmx $container_rootfs/dev/ptmx # OL7 has systemd, no rc.sysinit if [ $container_release_major = "7" ]; then # with newer systemd (OL7.2), getty service include container-getty.service # let that be the one who manage the getty service instead if [ ! -f $container_rootfs/usr/lib/systemd/system/container-getty@.service ]; then # from mhw in the fedora template: We do need to disable the # "ConditionalPathExists=/dev/tty0" line or no gettys are started on # the ttys in the container. Lets do it in an override copy of the # service so it can still pass rpm verifies and not be automatically # updated by a new systemd version. sed -e 's/^ConditionPathExists=/#LXC ConditionPathExists=/' \ < $container_rootfs/usr/lib/systemd/system/getty\@.service \ > $container_rootfs/etc/systemd/system/getty\@.service # Setup getty service on the 4 ttys we are going to allow in the # default config. Number should match lxc.tty ( cd $container_rootfs/etc/systemd/system/getty.target.wants for i in 1 2 3 4 ; do ln -sf ../getty\@.service getty@tty${i}.service; done ) # We only want to spawn a getty on /dev/console in lxc, libvirt-lxc # symlinks /dev/console to /dev/tty1 sed -i '/Before=getty.target/a ConditionVirtualization=lxc' $container_rootfs/usr/lib/systemd/system/console-getty.service fi # disable some systemd services, set default boot, sigpwr target rm -f $container_rootfs/usr/lib/systemd/system/sysinit.target.wants/kmod-static-nodes.service chroot $container_rootfs systemctl -q disable graphical.target chroot $container_rootfs systemctl -q enable multi-user.target # systemd in userns won't be able to set /proc/self/oom_score_adj which # prevents the dbus service from starting sed -i 's|^OOMScoreAdjust|#LXC OOMScoreAdjust|' $container_rootfs/usr/lib/systemd/system/dbus.service return fi # silence error in checking for selinux sed -i 's|cat /proc/self/attr/current|cat /proc/self/attr/current 2>/dev/null|' $container_rootfs/etc/rc.sysinit sed -i 's|cat /proc/self/attr/current|cat /proc/self/attr/current 2>/dev/null|' $container_rootfs/etc/rc.d/rc.sysinit # on ol4 pam_limits prevents logins when using user namespaces if [ $container_release_major = "4" ]; then sed -i 's|session[ \t]*required[ \t]*/lib/security/\$ISA/pam_limits.so|#session required /lib/security/$ISA/pam_limits.so|' $container_rootfs/etc/pam.d/system-auth fi # avoid error in ol5 attempting to copy non-existent resolv.conf if [ $container_release_major = "5" ]; then sed -i 's|resolv.conf.predhclient|resolv.conf.predhclient 2>/dev/null|' $container_rootfs/sbin/dhclient-script fi # disable interactive ovmd asking questions if [ -f $container_rootfs/etc/sysconfig/ovmd ]; then sed -i 's|INITIAL_CONFIG=yes|INITIAL_CONFIG=no|' $container_rootfs/etc/sysconfig/ovmd fi # disable disabling of ipv4 forwarding and defrag on shutdown since # we mount /proc/sys ro if [ $container_release_major = "5" ]; then sed -i 's|-f /proc/sys/net/ipv4/ip_forward|-w /proc/sys/net/ipv4/ip_forward|' $container_rootfs/etc/rc.d/init.d/network sed -i 's|-f /proc/sys/net/ipv4/ip_always_defrag|-w /proc/sys/net/ipv4/ip_always_defrag|' $container_rootfs/etc/rc.d/init.d/network fi # disable ipv6 on ol6 rm -f $container_rootfs/etc/sysconfig/network-scripts/init.ipv6-global # remove module stuff for iptables it just shows errors that are not # relevant in a container if [ -f "$container_rootfs/etc/sysconfig/iptables-config" ]; then sed -i 's|IPTABLES_MODULES=".*|IPTABLES_MODULES=""|' $container_rootfs/etc/sysconfig/iptables-config sed -i 's|IPTABLES_MODULES_UNLOAD=".*|IPTABLES_MODULES_UNLOAD="no"|' $container_rootfs/etc/sysconfig/iptables-config fi # disable readahead in the container if [ $container_release_major = "6" -a -e $container_rootfs/etc/sysconfig/readahead ]; then rm -f $container_rootfs/etc/init/readahead-collector.conf rm -f $container_rootfs/etc/init/readahead-disable-services.conf sed -i 's|READAHEAD="yes"|READAHEAD="no"|' $container_rootfs/etc/sysconfig/readahead fi if [ $container_release_major = "4" ]; then # enable fastboot always sed -i 's|\[ -f /fastboot \]|/bin/true|' $container_rootfs/etc/rc.sysinit sed -i 's|\[ -f /fastboot \]|/bin/true|' $container_rootfs/etc/rc.d/rc.sysinit # dont attempt to set kernel parameters sed -i 's|action $"Configuring kernel parameters|# LXC action $"Configuring kernel parameters|' $container_rootfs/etc/rc.sysinit sed -i 's|action $"Configuring kernel parameters|# LXC action $"Configuring kernel parameters|' $container_rootfs/etc/rc.d/rc.sysinit sed -i 's|action $"Setting network parameters|# LXC action $"Setting network parameters|' $container_rootfs/etc/init.d/network 2>/dev/null sed -i 's|action $"Setting network parameters|# LXC action $"Setting network parameters|' $container_rootfs/etc/init.d/NetworkManager 2>/dev/null fi # no need to attempt to mount / sed -i 's|mount -f /$|# LXC mount -f /|' $container_rootfs/etc/rc.sysinit sed -i 's|mount -f /$|# LXC mount -f /|' $container_rootfs/etc/rc.d/rc.sysinit sed -i 's|action \$"Remounting root filesystem|/bin/true # LXC action $"Remounting root filesystem|' $container_rootfs/etc/rc.sysinit sed -i 's|action \$"Remounting root filesystem|/bin/true # LXC action $"Remounting root filesystem|' $container_rootfs/etc/rc.d/rc.sysinit # disable udev in the container if [ $container_release_major = "4" ]; then sed -i 's|\[ -x /sbin/start_udev \]|# LXC no udev|' $container_rootfs/etc/rc.sysinit sed -i 's|\[ -x /sbin/start_udev \]|# LXC no udev|' $container_rootfs/etc/rc.d/rc.sysinit else sed -i 's|.sbin.start_udev||' $container_rootfs/etc/rc.sysinit sed -i 's|.sbin.start_udev||' $container_rootfs/etc/rc.d/rc.sysinit fi # disable nash raidautorun in the container since no /dev/md* if [ $container_release_major = "4" -o $container_release_major = "5" ]; then sed -i 's|echo "raidautorun /dev/md0"|echo ""|' $container_rootfs/etc/rc.sysinit sed -i 's|echo "raidautorun /dev/md0"|echo ""|' $container_rootfs/etc/rc.d/rc.sysinit fi # prevent rc.sysinit from attempting to loadkeys if [ \( $container_release_major = "4" -o $container_release_major = "5" \) -a -e $container_rootfs/etc/sysconfig/keyboard ]; then rm $container_rootfs/etc/sysconfig/keyboard fi # dont use the hwclock, it messes up the host's time if [ $container_release_major = "4" ]; then sed -i 's|runcmd $"Syncing hardware clock|# LXC no hwclock runcmd $"Syncing hardware clock|' $container_rootfs/etc/rc.d/init.d/halt else sed -i 's|\[ -x /sbin/hwclock|\[ 0 -eq 1|' $container_rootfs/etc/rc.d/init.d/halt fi sed -i 's|^\[ -x /sbin/hwclock|\[ 0 -eq 1|' $container_rootfs/etc/rc.sysinit sed -i 's|^\[ -x /sbin/hwclock|\[ 0 -eq 1|' $container_rootfs/etc/rc.d/rc.sysinit sed -i 's|^/sbin/hwclock|# LXC /sbin/nohwclock|' $container_rootfs/etc/rc.sysinit sed -i 's|^/sbin/hwclock|# LXC /sbin/nohwclock|' $container_rootfs/etc/rc.d/rc.sysinit # dont start lvm if [ $container_release_major -lt "6" -a -f $container_rootfs/sbin/lvm.static ]; then mv $container_rootfs/sbin/lvm.static $container_rootfs/sbin/lvm.static.lxc-disabled fi if [ $container_release_major = "6" ]; then touch $container_rootfs/.nolvm fi # fix assumptions that plymouth is available sed -i 's|\[ "$PROMPT" != no \] && plymouth|[ "$PROMPT" != no ] \&\& [ -n "$PLYMOUTH" ] \&\& plymouth|' $container_rootfs/etc/rc.sysinit sed -i 's|\[ "$PROMPT" != no \] && plymouth|[ "$PROMPT" != no ] \&\& [ -n "$PLYMOUTH" ] \&\& plymouth|' $container_rootfs/etc/rc.d/rc.sysinit rm -f $container_rootfs/etc/init/plymouth-shutdown.conf rm -f $container_rootfs/etc/init/quit-plymouth.conf rm -f $container_rootfs/etc/init/splash-manager.conf # dont try to unmount /dev/lxc devices sed -i 's|&& $1 !~ /^\\/dev\\/ram/|\&\& $2 !~ /^\\/dev\\/lxc/ \&\& $1 !~ /^\\/dev\\/ram/|' $container_rootfs/etc/init.d/halt # don't try to unmount swap sed -i 's|\[ -f /proc/swaps \]|# LXC [ -f /proc/swaps ]|' $container_rootfs/etc/init.d/halt # sem_open(3) checks that /dev/shm is SHMFS_SUPER_MAGIC, so make sure to # mount /dev/shm (normally done by dracut initrd) as tmpfs if [ $container_release_major = "4" -o $container_release_major = "5" ]; then grep -q "mount -t tmpfs tmpfs /dev/shm" $container_rootfs/etc/rc.sysinit if [ $? -eq 1 ]; then echo "mkdir -p /dev/shm && mount -t tmpfs tmpfs /dev/shm" >>$container_rootfs/etc/rc.sysinit echo "mkdir -p /dev/shm && mount -t tmpfs tmpfs /dev/shm" >>$container_rootfs/etc/rc.d/rc.sysinit fi fi if [ $container_release_major = "6" ]; then sed -i 's|mount -n -o remount /dev/shm >/dev/null 2>&1$|mkdir -p /dev/shm \&\& mount -t tmpfs tmpfs /dev/shm # LXC|' $container_rootfs/etc/rc.sysinit sed -i 's|mount -n -o remount /dev/shm >/dev/null 2>&1$|mkdir -p /dev/shm \&\& mount -t tmpfs tmpfs /dev/shm # LXC|' $container_rootfs/etc/rc.d/rc.sysinit fi # there might be other services that are useless but the below set is a good start # some of these might not exist in the image, so we silence chkconfig complaining # about the service file not being found for service in \ acpid apmd auditd autofs cpuspeed dund gpm haldaemon hidd \ ip6tables irqbalance iscsi iscsid isdn kdump kudzu \ lm_sensors lvm2-monitor mdmonitor microcode_ctl \ ntpd pcmcia postfix sendmail udev-post xfs ; do chroot $container_rootfs chkconfig 2>/dev/null $service off done for service in rsyslog ; do chroot $container_rootfs chkconfig 2>/dev/null $service on done } container_rootfs_configure() { container_rootfs_patch echo "Configuring container for Oracle Linux $container_release_major.$container_release_minor" # configure the network to use dhcp. we set DHCP_HOSTNAME so the guest # will report its name and be resolv'able by the hosts dnsmasq cat < $container_rootfs/etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 BOOTPROTO=dhcp ONBOOT=yes HOSTNAME=$name DHCP_HOSTNAME=\`hostname\` NM_CONTROLLED=no TYPE=Ethernet EOF # set the hostname if [ $container_release_major -ge "7" ]; then # systemd honors /etc/hostname echo "$name" >$container_rootfs/etc/hostname fi cat < $container_rootfs/etc/sysconfig/network NETWORKING=yes NETWORKING_IPV6=no HOSTNAME=$name EOF # set minimal hosts echo "127.0.0.1 localhost $name" > $container_rootfs/etc/hosts # this file has to exist for libvirt/Virtual machine monitor to boot the container touch $container_rootfs/etc/mtab # setup console and tty[1-4] for login. note that /dev/console and # /dev/tty[1-4] will be symlinks to the ptys /dev/lxc/console and # /dev/lxc/tty[1-4] so that package updates can overwrite the symlinks. # lxc will maintain these links and bind mount ptys over /dev/lxc/* # since lxc.devttydir is specified in the config. # allow root login on console, tty[1-4], and pts/0 for libvirt echo "# LXC (Linux Containers)" >>$container_rootfs/etc/securetty echo "lxc/console" >>$container_rootfs/etc/securetty for i in 1 2 3 4; do echo "lxc/tty$i" >>$container_rootfs/etc/securetty done echo "# For libvirt/Virtual Machine Monitor" >>$container_rootfs/etc/securetty for i in 0 1 2 3 4; do echo "pts/$i" >>$container_rootfs/etc/securetty done # prevent mingetty from calling vhangup(2) since it fails with userns if [ -f $container_rootfs/etc/init/tty.conf ]; then sed -i 's|mingetty|mingetty --nohangup|' $container_rootfs/etc/init/tty.conf fi # create maygetty which only spawns a getty on the console when running # under lxc, not libvirt-lxc which symlinks /dev/console to the same pty # as /dev/tty1 cat <$container_rootfs/sbin/maygetty #!/bin/sh if [ "\$container" = "lxc" ]; then exec /sbin/mingetty \$@ fi exec sleep infinity EOF chmod 755 $container_rootfs/sbin/maygetty # start a getty on /dev/console, /dev/tty[1-4] if [ $container_release_major = "4" -o $container_release_major = "5" ]; then sed -i 's|mingetty|mingetty --nohangup|' $container_rootfs/etc/inittab sed -i '/1:2345:respawn/i cns:2345:respawn:/sbin/maygetty --nohangup --noclear console' $container_rootfs/etc/inittab sed -i '/5:2345:respawn/d' $container_rootfs/etc/inittab sed -i '/6:2345:respawn/d' $container_rootfs/etc/inittab fi if [ $container_release_major = "6" ]; then cat < $container_rootfs/etc/init/console.conf # console - getty # # This service maintains a getty on the console from the point the system is # started until it is shut down again. start on stopped rc RUNLEVEL=[2345] stop on runlevel [!2345] env container respawn exec /sbin/maygetty --nohangup --noclear /dev/console EOF fi # lxc-shutdown sends SIGPWR to init, OL4 and OL5 have SysVInit, just # make it do shutdown now instead of delaying 2 minutes. OL6 uses # upstart, so we create an upstart job to handle SIGPWR to shut down # cleanly. We use "init 0" instead of shutdown -h now to avoid SELinux # permission denied when upstart's shutdown tries to connect to the # /com/ubuntu/upstart socket. if [ $container_release_major = "4" -o $container_release_major = "5" ]; then sed -i 's|pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; |pf::powerfail:/sbin/shutdown -f -h now "|' $container_rootfs/etc/inittab elif [ $container_release_major = "6" ]; then cat < $container_rootfs/etc/init/power-status-changed.conf # power-status-changed - used to cleanly shut down the container # # This task is run whenever init receives SIGPWR # Used to shut down the machine. start on power-status-changed exec init 0 EOF fi # start with a clean /var/log/messages rm -f $container_rootfs/var/log/messages # set initial timezone as on host if [ -f /etc/sysconfig/clock ]; then . /etc/sysconfig/clock if [ $container_release_major = "5" -o $container_release_major = "6" ]; then echo ZONE=$ZONE > $container_rootfs/etc/sysconfig/clock chroot $container_rootfs tzdata-update else ZONE="${ZONE// /_}" chroot $container_rootfs ln -sf ../usr/share/zoneinfo/$ZONE /etc/localtime fi else ZONE=`readlink /etc/localtime | sed -s "s/\.\.\/usr\/share\/zoneinfo\///g"` if [ "$ZONE" ]; then if [ $container_release_major = "5" -o $container_release_major = "6" ]; then echo ZONE=$ZONE > $container_rootfs/etc/sysconfig/clock chroot $container_rootfs tzdata-update else # if /etc/localtime is a symlink, this should preserve it. cp -a /etc/localtime $container_rootfs/etc/localtime fi else echo "Timezone in container is not configured. Adjust it manually." fi fi # add oracle user chroot $container_rootfs useradd -m -s /bin/bash oracle printf "Added container user:\033[1moracle\033[0m\n" printf "Added container user:\033[1mroot\033[0m\n" } # create the container's lxc config file container_config_create() { echo "Create configuration file $cfg_dir/config" mkdir -p $cfg_dir || die "unable to create config dir $cfg_dir" echo "# Common configuration" >> $cfg_dir/config if [ -e "@LXCTEMPLATECONFIG@/oracle.common.conf" ]; then echo "lxc.include = @LXCTEMPLATECONFIG@/oracle.common.conf" >> $cfg_dir/config fi cat <> $cfg_dir/config || die "unable to create $cfg_dir/config" # Container configuration for Oracle Linux $container_release_major.$container_release_minor lxc.arch = $arch lxc.utsname = $name EOF grep -q "^lxc.rootfs" $cfg_dir/config 2>/dev/null || echo "lxc.rootfs = $container_rootfs" >> $cfg_dir/config if [ $container_release_major != "4" ]; then echo "lxc.cap.drop = sys_resource" >>$cfg_dir/config fi # systemd services like logind and journald need these if [ $container_release_major != "7" ]; then echo "lxc.cap.drop = setfcap setpcap" >>$cfg_dir/config fi echo "# Networking" >>$cfg_dir/config # see if the default network settings were already specified lxc_network_type=`grep '^lxc.network.type' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'` if [ -z "$lxc_network_type" ]; then echo "lxc.network.type = veth" >>$cfg_dir/config lxc_network_type=veth fi lxc_network_link=`grep '^lxc.network.link' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'` if [ -z "$lxc_network_link" ]; then echo "lxc.network.link = lxcbr0" >>$cfg_dir/config lxc_network_link=lxcbr0 fi lxc_network_hwaddr=`grep '^lxc.network.hwaddr' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'` if [ -z "$lxc_network_hwaddr" ]; then # generate a hwaddr for the container # see http://sourceforge.net/tracker/?func=detail&aid=3411497&group_id=163076&atid=826303 local hwaddr="00:16:3e:`dd if=/dev/urandom bs=8 count=1 2>/dev/null |od -t x8 | \ head -n1 | awk '{print $2}' | cut -c1-6 | \ sed 's/\(..\)/\1:/g; s/.$//'`" echo "lxc.network.hwaddr = $hwaddr" >>$cfg_dir/config fi lxc_network_flags=`grep '^lxc.network.flags' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'` if [ -z "$lxc_network_flags" ]; then echo "lxc.network.flags = up" >>$cfg_dir/config fi cat <> $cfg_dir/config || die "unable to create $cfg_dir/config" lxc.network.name = eth0 lxc.network.mtu = 1500 EOF } container_rootfs_clone() { if is_btrfs_subvolume $template_rootfs; then # lxc-create already made $container_rootfs a btrfs subvolume, but # in this case we want to snapshot the original subvolume so we we # have to delete the one that lxc-create made btrfs subvolume delete $container_rootfs btrfs subvolume snapshot $template_rootfs $container_rootfs || die "btrfs clone template" else echo "Copying rootfs ..." cp -axT $template_rootfs $container_rootfs || die "copy template" fi } container_rootfs_repo_create() { echo "# LXC generated .repo file" >$1 echo "[$2]" >>$1 echo "name=Oracle Linux $container_release_major.$container_release_minor ($basearch)" >>$1 echo "baseurl=$3/" >>$1 echo "enabled=1" >>$1 echo "skip_if_unavailable=1" >>$1 if [ "$4" != "" ]; then echo "gpgkey=$yum_url/RPM-GPG-KEY-oracle-ol$container_release_major" >>$1 echo "gpgcheck=1" >>$1 else echo "gpgcheck=0" >>$1 fi } container_rootfs_dev_create() { # create required devices. note that /dev/console will be created by lxc # or libvirt itself to be a symlink to the right pty. # take care to not nuke /dev in case $container_rootfs isn't set dev_path="$container_rootfs/dev" if [ $container_rootfs != "/" -a -d $dev_path ]; then rm -rf $dev_path fi mkdir -p $dev_path if can_chcon; then # ensure symlinks created in /dev have the right context chcon -t device_t $dev_path fi mknod -m 666 $dev_path/null c 1 3 mknod -m 666 $dev_path/zero c 1 5 mknod -m 666 $dev_path/random c 1 8 mknod -m 666 $dev_path/urandom c 1 9 mkdir -m 755 $dev_path/pts mkdir -m 1777 $dev_path/shm mknod -m 666 $dev_path/tty c 5 0 mknod -m 666 $dev_path/tty1 c 4 1 mknod -m 666 $dev_path/tty2 c 4 2 mknod -m 666 $dev_path/tty3 c 4 3 mknod -m 666 $dev_path/tty4 c 4 4 mknod -m 666 $dev_path/full c 1 7 mknod -m 600 $dev_path/initctl p # set selinux labels same as host if can_chcon; then for node in null zero random urandom pts shm \ tty tty0 tty1 tty2 tty3 tty4 full ; do chcon --reference /dev/$node $dev_path/$node 2>/dev/null done fi } container_rootfs_create() { if can_chcon; then chcon --reference / $container_rootfs 2>/dev/null fi cmds="rpm wget yum" if [ $container_release_major -lt "6" ]; then if [ $host_distribution = "Ubuntu" -o $host_distribution = "Debian" ]; then db_dump_cmd="db5.1_dump" fi if [ $host_distribution = "OracleServer" -o \ $host_distribution = "Fedora" ]; then db_dump_cmd="db_dump" fi cmds="$cmds $db_dump_cmd file" fi for cmd in $cmds; do which $cmd >/dev/null 2>&1 if [ $? -ne 0 ]; then die "The $cmd command is required, please install it" fi done mkdir -p @LOCALSTATEDIR@/lock/subsys ( flock -x 9 if [ $? -ne 0 ]; then die "The template is busy." fi echo "Yum installing release $container_release_major.$container_release_minor for $basearch" if [ -n "$repourl" ]; then yum_url=$repourl else yum_url=http://public-yum.oracle.com fi if [ $container_release_major = "4" -o $container_release_major = "5" ]; then latest_L="el" latest_U="EL" else latest_L="ol" latest_U="OL" fi if [ -n "$baseurl" ]; then # create .repo pointing at baseurl repo="lxc-install" mkdir -p $container_rootfs/etc/yum.repos.d container_rootfs_repo_create \ $container_rootfs/etc/yum.repos.d/lxc-install.repo $repo $baseurl else # get public-yum repo file if [ $container_release_major = "4" ]; then repofile=public-yum-el4.repo elif [ $container_release_major = "5" ]; then repofile=public-yum-el5.repo elif [ $container_release_major = "6" ]; then repofile=public-yum-ol6.repo elif [ $container_release_major = "7" ]; then repofile=public-yum-ol7.repo else die "Unsupported release $container_release_major" fi mkdir -p $container_rootfs/etc/yum.repos.d wget -q $yum_url/$repofile -O $container_rootfs/etc/yum.repos.d/$repofile if [ $? -ne 0 ]; then die "Unable to download repo file $yum_url/$repofile, release unavailable" fi # yum will take $basearch from host, so force the arch we want sed -i "s|\$basearch|$basearch|" $container_rootfs/etc/yum.repos.d/$repofile # replace url if they specified one if [ -n "$repourl" ]; then sed -i "s|baseurl=http://public-yum.oracle.com/repo|baseurl=$repourl/repo|" $container_rootfs/etc/yum.repos.d/$repofile sed -i "s|gpgkey=http://public-yum.oracle.com|gpgkey=$repourl|" $container_rootfs/etc/yum.repos.d/$repofile fi # disable all repos, then enable the repo for the version we are installing. if [ $container_release_minor = "latest" ]; then repo=$latest_L""$container_release_major"_"$container_release_minor elif [ $container_release_major = "7" ]; then repo="ol"$container_release_major"_u"$container_release_minor"_base" elif [ $container_release_major = "6" ]; then if [ $container_release_minor = "0" ]; then repo="ol"$container_release_major"_ga_base" else repo="ol"$container_release_major"_u"$container_release_minor"_base" fi elif [ $container_release_major = "5" ]; then if [ $container_release_minor = "0" ]; then repo="el"$container_release_major"_ga_base" elif [ $container_release_minor -lt "6" ]; then repo="el"$container_release_major"_u"$container_release_minor"_base" else repo="ol"$container_release_major"_u"$container_release_minor"_base" fi elif [ $container_release_major = "4" -a $container_release_minor -gt "5" ]; then repo="el"$container_release_major"_u"$container_release_minor"_base" else die "Unsupported release $container_release_major.$container_release_minor" fi sed -i "s|enabled=1|enabled=0|" $container_rootfs/etc/yum.repos.d/$repofile sed -i "/\[$repo\]/,/\[/ s/enabled=0/enabled=1/" $container_rootfs/etc/yum.repos.d/$repofile fi container_rootfs_dev_create # don't put devpts,proc, nor sysfs in here, it will already be mounted for us by lxc/libvirt echo "" >$container_rootfs/etc/fstab # create rpm db, download and yum install minimal packages mkdir -p $container_rootfs/var/lib/rpm rpm --root $container_rootfs --initdb yum_args="--installroot $container_rootfs --disablerepo=* --enablerepo=$repo -y --nogpgcheck" min_pkgs="yum initscripts passwd rsyslog vim-minimal openssh-server openssh-clients dhclient chkconfig rootfiles policycoreutils oraclelinux-release" if [ $container_release_major -lt "6" ]; then min_pkgs="$min_pkgs db4-utils" fi # we unshare the mount namespace because yum installing the ol4 # packages causes $rootfs/proc to be mounted on lxc-unshare -s MOUNT yum -- $yum_args install $min_pkgs $user_pkgs if [ $? -ne 0 ]; then die "Failed to download and install the rootfs, aborting." fi # rsyslog and pam depend on coreutils for some common commands in # their POSTIN scriptlets, but coreutils wasn't installed yet. now # that coreutils is installed, reinstall the packages so their POSTIN # runs right. similarly, libutempter depends on libselinux.so.1 when # it runs /usr/sbin/groupadd, so reinstall it too redo_pkgs="" if [ $container_release_major = "5" ]; then if [ $container_release_minor = "latest" ]; then redo_pkgs="pam rsyslog libutempter" elif [ $container_release_minor -lt 2 ]; then redo_pkgs="pam" elif [ $container_release_minor -lt 6 ]; then redo_pkgs="pam rsyslog" elif [ $container_release_minor -gt 5 ]; then redo_pkgs="pam rsyslog libutempter" fi fi # shadow utils fails on ol4 and ol6.1 if [ $container_release_major = "4" -o \ $container_release_major = "6" -a $container_release_minor = "1" ]; then redo_pkgs="shadow-utils" fi if [ x"$redo_pkgs" != x ]; then rpm --root $container_rootfs --nodeps -e $redo_pkgs lxc-unshare -s MOUNT yum -- $yum_args install $redo_pkgs if [ $? -ne 0 ]; then die "Unable to reinstall packages" fi fi # if installing from a baseurl, create a .repo that the container # can use to update to _latest from http://public-yum.oracle.com if [ -n "$baseurl" ]; then container_rootfs_repo_create \ "$container_rootfs/etc/yum.repos.d/public-yum-"$latestL""$container_release_major".repo" \ $latest_L""$container_release_major"_latest" \ $yum_url"/repo/OracleLinux/"$latest_U""$container_release_major"/latest/$basearch" gpg fi # these distributions put the rpm database in a place the guest is # not expecting it, so move it if [ $host_distribution = "Ubuntu" -o $host_distribution = "Debian" ]; then mv $container_rootfs/$HOME/.rpmdb/* $container_rootfs/var/lib/rpm fi # if the native rpm created the db with Hash version 9, we need to # downgrade it to Hash version 8 for use with OL5.x db_version=`file $container_rootfs/var/lib/rpm/Packages | \ grep -o 'version [0-9]*' |awk '{print $2}'` if [ $container_release_major -lt "6" -a $db_version != "8" ]; then echo "Fixing (downgrading) rpm database from version $db_version" rm -f $container_rootfs/var/lib/rpm/__db* for db in $container_rootfs/var/lib/rpm/* ; do $db_dump_cmd $db |chroot $container_rootfs db_load /var/lib/rpm/`basename $db`.new mv $db.new $db done fi # the host rpm may not be the same as the guest, rebuild the db with # the guest rpm version echo "Rebuilding rpm database" rm -f $container_rootfs/var/lib/rpm/__db* chroot $container_rootfs rpm --rebuilddb >/dev/null 2>&1 ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-oracle-$name if [ $? -ne 0 ]; then exit 1 fi } container_release_get() { if [ -f $1/etc/oracle-release ]; then container_release_version=`cat $1/etc/oracle-release |awk '/^Oracle/ {print $5}'` container_release_major=`echo $container_release_version |awk -F '.' '{print $1}'` container_release_minor=`echo $container_release_version |awk -F '.' '{print $2}'` elif grep -q "Enterprise Linux AS" $1/etc/redhat-release; then container_release_major=`cat $1/etc/redhat-release |awk '{print $7}'` container_release_minor=`cat $1/etc/redhat-release |awk '{print $10}' |tr -d ")"` container_release_version="$container_release_major.$container_release_minor" elif grep -q "Enterprise Linux Server" $1/etc/redhat-release; then container_release_version=`cat $1/etc/redhat-release |awk '{print $7}'` container_release_major=`echo $container_release_version |awk -F '.' '{print $1}'` container_release_minor=`echo $container_release_version |awk -F '.' '{print $2}'` else echo "Unable to determine container release version" exit 1 fi } usage() { cat < architecture (ie. i386, x86_64) -R|--release= release to download for the new container --rootfs= rootfs path -r|--rpms= additional rpms to install into container -u|--url= replace yum repo url (ie. Oracle public-yum mirror) --baseurl= use package repository (ie. file:///mnt) arch and release must also be specified -t|--templatefs= copy/clone rootfs at path instead of downloading -P|--patch= only patch the rootfs at path for use as a container -h|--help Release is of the format "major.minor", for example "5.8", "6.3", or "6.latest" This template supports Oracle Linux releases 4.6 - 7.0 EOF return 0 } options=$(getopt -o hp:n:a:R:r:u:t: -l help,rootfs:,path:,name:,arch:,release:,rpms:,url:,templatefs:,patch:,baseurl: -- "$@") if [ $? -ne 0 ]; then usage $(basename $0) exit 1 fi eval set -- "$options" while true do case "$1" in -h|--help) usage $0 && exit 0;; -p|--path) cfg_dir=$2; shift 2;; --rootfs) container_rootfs=$2; shift 2;; -n|--name) name=$2; shift 2;; -a|--arch) arch=$2; shift 2;; -R|--release) container_release_version=$2; shift 2;; -r|--rpms) user_pkgs=$2; shift 2;; -u|--url) repourl=$2; shift 2;; -t|--templatefs) template_rootfs=$2; shift 2;; --patch) patch_rootfs=$2; shift 2;; --baseurl) baseurl=$2; shift 2;; --) shift 1; break ;; *) break ;; esac done # make sure mandatory args are given and valid if [ "$(id -u)" != "0" ]; then echo "This script should be run as 'root'" exit 1 fi if [ -n "$baseurl" ]; then if [ "$arch" = "" -o "$container_release_version" = "" ]; then echo "The --arch and --release must be specified when using --baseurl" usage exit 1 fi fi if [ "$arch" = "" ]; then arch=$(uname -m) fi if [ -n "$patch_rootfs" ]; then container_rootfs="$patch_rootfs" container_release_get $container_rootfs container_rootfs_patch exit 0 fi if [ -z $name ]; then echo "Container name must be given" usage exit 1 fi if [ -z $cfg_dir ]; then echo "Configuration directory must be given, check lxc-create" usage exit 1 fi basearch=$arch if [ "$arch" = "i686" ]; then basearch="i386" fi if [ "$arch" != "i386" -a "$arch" != "x86_64" ]; then echo "Bad architecture given, check lxc-create" usage exit 1 fi if which lsb_release >/dev/null 2>&1; then host_distribution=`lsb_release --id |awk '{print $3}'` host_release_version=`lsb_release --release |awk '{print $2}'` host_release_major=`echo $host_release_version |awk -F '.' '{print $1}'` host_release_minor=`echo $host_release_version |awk -F '.' '{print $2}'` else if [ -f /etc/fedora-release ]; then host_distribution="Fedora" host_release_version=`cat /etc/fedora-release |awk '{print $3}'` host_release_major=$host_release_version host_release_minor=0 elif [ -f /etc/oracle-release ]; then host_distribution="OracleServer" host_release_version=`cat /etc/oracle-release |awk '{print $5}'` host_release_major=`echo $host_release_version |awk -F '.' '{print $1}'` host_release_minor=`echo $host_release_version |awk -F '.' '{print $2}'` else echo "Unable to determine host distribution, ensure lsb_release is installed" exit 1 fi fi echo "Host is $host_distribution $host_release_version" if [ -z "$container_rootfs" ]; then container_rootfs="$cfg_dir/rootfs" fi if [ -n "$template_rootfs" ]; then container_release_get $template_rootfs else if [ -z "$container_release_version" ]; then if [ $host_distribution = "OracleServer" ]; then container_release_version=$host_release_version else echo "No release specified with -R, defaulting to 6.5" container_release_version="6.5" fi fi container_release_major=`echo $container_release_version |awk -F '.' '{print $1}'` container_release_minor=`echo $container_release_version |awk -F '.' '{print $2}'` fi container_config_create if [ -n "$template_rootfs" ]; then container_rootfs_clone else container_rootfs_create fi container_release_get $container_rootfs container_rootfs_configure echo "Container : $container_rootfs" echo "Config : $cfg_dir/config" echo "Network : eth0 ($lxc_network_type) on $lxc_network_link" lxc-2.0.8/templates/lxc-debian.in0000644061062106075000000004732413105116772013611 00000000000000#!/bin/bash # # lxc: linux Container library # Authors: # Daniel Lezcano # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Detect use under userns (unsupported) for arg in "$@"; do [ "$arg" = "--" ] && break if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then echo "This template can't be used for unprivileged containers." 1>&2 echo "You may want to try the \"download\" template instead." 1>&2 exit 1 fi done # Make sure the usual locations are in PATH export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin export GREP_OPTIONS="" MIRROR=${MIRROR:-http://httpredir.debian.org/debian} SECURITY_MIRROR=${SECURITY_MIRROR:-http://security.debian.org/} LOCALSTATEDIR="@LOCALSTATEDIR@" LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@" # Allows the lxc-cache directory to be set by environment variable LXC_CACHE_PATH=${LXC_CACHE_PATH:-"$LOCALSTATEDIR/cache/lxc"} configure_debian() { rootfs=$1 hostname=$2 num_tty=$3 # squeeze only has /dev/tty and /dev/tty0 by default, # therefore creating missing device nodes for tty1-4. for tty in $(seq 1 "$num_tty"); do if [ ! -e "$rootfs/dev/tty$tty" ]; then mknod "$rootfs/dev/tty$tty" c 4 "$tty" fi done # configure the inittab cat < $rootfs/etc/inittab id:3:initdefault: si::sysinit:/etc/init.d/rcS l0:0:wait:/etc/init.d/rc 0 l1:1:wait:/etc/init.d/rc 1 l2:2:wait:/etc/init.d/rc 2 l3:3:wait:/etc/init.d/rc 3 l4:4:wait:/etc/init.d/rc 4 l5:5:wait:/etc/init.d/rc 5 l6:6:wait:/etc/init.d/rc 6 # Normally not reached, but fallthrough in case of emergency. z6:6:respawn:/sbin/sulogin 1:2345:respawn:/sbin/getty 38400 console $(for tty in $(seq 1 "$num_tty"); do echo "c${tty}:12345:respawn:/sbin/getty 38400 tty${tty} linux" ; done;) p6::ctrlaltdel:/sbin/init 6 p0::powerfail:/sbin/init 0 EOF # symlink mtab [ -e "$rootfs/etc/mtab" ] && rm "$rootfs/etc/mtab" ln -s /proc/self/mounts "$rootfs/etc/mtab" # disable selinux in debian mkdir -p "$rootfs/selinux" echo 0 > "$rootfs/selinux/enforce" # configure the network using the dhcp cat < $rootfs/etc/network/interfaces auto lo iface lo inet loopback auto eth0 iface eth0 inet dhcp EOF # set the hostname cat < $rootfs/etc/hostname $hostname EOF # reconfigure some services # but first reconfigure locales - so we get no noisy perl-warnings if [ -z "$LANG" ]; then cat >> "$rootfs/etc/locale.gen" << EOF en_US.UTF-8 UTF-8 EOF chroot "$rootfs" locale-gen en_US.UTF-8 UTF-8 chroot "$rootfs" update-locale LANG=en_US.UTF-8 else encoding=$(echo "$LANG" | cut -d. -f2) chroot "$rootfs" sed -e "s/^# \(${LANG} ${encoding}\)/\1/" \ -i /etc/locale.gen 2> /dev/null cat >> "$rootfs/etc/locale.gen" << EOF $LANG $encoding EOF chroot "$rootfs" locale-gen "$LANG" "$encoding" chroot "$rootfs" update-locale LANG="$LANG" fi # remove pointless services in a container chroot "$rootfs" /usr/sbin/update-rc.d -f checkroot.sh disable chroot "$rootfs" /usr/sbin/update-rc.d -f umountfs disable chroot "$rootfs" /usr/sbin/update-rc.d -f hwclock.sh disable chroot "$rootfs" /usr/sbin/update-rc.d -f hwclockfirst.sh disable # generate new SSH keys if [ -x "$rootfs/var/lib/dpkg/info/openssh-server.postinst" ]; then cat > "$rootfs/usr/sbin/policy-rc.d" << EOF #!/bin/sh exit 101 EOF chmod +x "$rootfs/usr/sbin/policy-rc.d" if [ -f "$rootfs/etc/init/ssh.conf" ]; then mv "$rootfs/etc/init/ssh.conf" "$rootfs/etc/init/ssh.conf.disabled" fi rm -f "$rootfs/etc/ssh/"ssh_host_*key* DPKG_MAINTSCRIPT_PACKAGE=openssh DPKG_MAINTSCRIPT_NAME=postinst chroot "$rootfs" /var/lib/dpkg/info/openssh-server.postinst configure sed -i "s/root@$(hostname)/root@$hostname/g" "$rootfs/etc/ssh/"ssh_host_*.pub if [ -f "$rootfs/etc/init/ssh.conf.disabled" ]; then mv "$rootfs/etc/init/ssh.conf.disabled" "$rootfs/etc/init/ssh.conf" fi rm -f "$rootfs/usr/sbin/policy-rc.d" fi # set initial timezone as on host if [ -f /etc/timezone ]; then cat /etc/timezone > "$rootfs/etc/timezone" chroot "$rootfs" dpkg-reconfigure -f noninteractive tzdata elif [ -f /etc/sysconfig/clock ]; then . /etc/sysconfig/clock echo "$ZONE" > "$rootfs/etc/timezone" chroot "$rootfs" dpkg-reconfigure -f noninteractive tzdata else echo "Timezone in container is not configured. Adjust it manually." fi return 0 } write_sourceslist() { local rootfs="$1"; shift local release="$1"; shift local arch="$1"; shift local prefix="deb" if [ -n "${arch}" ]; then prefix="deb [arch=${arch}]" fi if [ "$mainonly" = 1 ]; then non_main='' else non_main=' contrib non-free' fi cat >> "${rootfs}/etc/apt/sources.list" << EOF ${prefix} $MIRROR ${release} main${non_main} EOF if [ "$release" != "unstable" -a "$release" != "sid" ]; then cat >> "${rootfs}/etc/apt/sources.list" << EOF ${prefix} $SECURITY_MIRROR ${release}/updates main${non_main} EOF fi } install_packages() { local rootfs="$1"; shift local packages="$*" chroot "${rootfs}" apt-get update if [ -n "${packages}" ]; then chroot "${rootfs}" apt-get install --force-yes -y --no-install-recommends ${packages} fi } configure_debian_systemd() { path=$1 rootfs=$2 config=$3 num_tty=$4 # this only works if we have getty@.service to manipulate if [ -f "${rootfs}/lib/systemd/system/getty@.service" ]; then sed -e 's/^ConditionPathExists=/# ConditionPathExists=/' \ -e 's/After=dev-%i.device/After=/' \ < "${rootfs}/lib/systemd/system/getty@.service" \ > "${rootfs}/etc/systemd/system/getty@.service" fi # just in case systemd is not installed mkdir -p "${rootfs}/lib/systemd/system" mkdir -p "${rootfs}/etc/systemd/system/getty.target.wants" # Fix getty-static-service as debootstrap does not install dbus if [ -e "$rootfs//lib/systemd/system/getty-static.service" ] ; then local tty_services tty_services=$(for i in $(seq 2 "$num_tty"); do echo -n "getty@tty${i}.service "; done; ) sed 's/ getty@tty.*/'" $tty_services "'/g' \ "$rootfs/lib/systemd/system/getty-static.service" | \ sed 's/\(tty2-tty\)[5-9]/\1'"${num_tty}"'/g' > "$rootfs/etc/systemd/system/getty-static.service" fi # This function has been copied and adapted from lxc-fedora rm -f "${rootfs}/etc/systemd/system/default.target" chroot "${rootfs}" ln -s /dev/null /etc/systemd/system/udev.service chroot "${rootfs}" ln -s /dev/null /etc/systemd/system/systemd-udevd.service chroot "${rootfs}" ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target # Setup getty service on the ttys we are going to allow in the # default config. Number should match lxc.tty ( cd "${rootfs}/etc/systemd/system/getty.target.wants" for i in $(seq 1 "$num_tty") ; do ln -sf ../getty\@.service getty@tty"${i}".service; done ) # Since we use static-getty.target; we need to mask container-getty@.service generated by # container-getty-generator, so we don't get multiple instances of agetty running. # See https://github.com/lxc/lxc/issues/520 and https://github.com/lxc/lxc/issues/484 ( cd "${rootfs}/etc/systemd/system/getty.target.wants" for i in $(seq 0 "$num_tty"); do ln -sf /dev/null container-getty\@"${i}".service; done ) return 0 } cleanup() { rm -rf "$cache/partial-$release-$arch" rm -rf "$cache/rootfs-$release-$arch" } download_debian() { case "$release" in wheezy) init=sysvinit ;; *) init=init ;; esac packages=\ $init,\ ifupdown,\ locales,\ dialog,\ isc-dhcp-client,\ netbase,\ net-tools,\ iproute,\ openssh-server cache=$1 arch=$2 release=$3 trap cleanup EXIT SIGHUP SIGINT SIGTERM # Create the cache mkdir -p "$cache" # If debian-archive-keyring isn't installed, fetch GPG keys directly releasekeyring=/usr/share/keyrings/debian-archive-keyring.gpg if [ ! -f $releasekeyring ]; then releasekeyring="$cache/archive-key.gpg" case $release in "wheezy") gpgkeyname="archive-key-7.0" ;; *) gpgkeyname="archive-key-8" ;; esac wget https://ftp-master.debian.org/keys/${gpgkeyname}.asc -O - --quiet \ | gpg --import --no-default-keyring --keyring="${releasekeyring}" fi # check the mini debian was not already downloaded mkdir -p "$cache/partial-$release-$arch" if [ $? -ne 0 ]; then echo "Failed to create '$cache/partial-$release-$arch' directory" return 1 fi # download a mini debian into a cache echo "Downloading debian minimal ..." debootstrap --verbose --variant=minbase --arch="$arch" \ --include="$packages" --keyring="${releasekeyring}" \ "$release" "$cache/partial-$release-$arch" "$MIRROR" if [ $? -ne 0 ]; then echo "Failed to download the rootfs, aborting." return 1 fi mv "$1/partial-$release-$arch" "$1/rootfs-$release-$arch" echo "Download complete." trap EXIT trap SIGINT trap SIGTERM trap SIGHUP return 0 } copy_debian() { cache=$1 arch=$2 rootfs=$3 release=$4 # make a local copy of the minidebian echo -n "Copying rootfs to $rootfs..." mkdir -p "$rootfs" rsync -Ha "$cache/rootfs-$release-$arch"/ "$rootfs"/ || return 1 return 0 } install_debian() { rootfs=$1 release=$2 arch=$3 cache="$4/debian" mkdir -p $LOCALSTATEDIR/lock/subsys/ ( flock -x 9 if [ $? -ne 0 ]; then echo "Cache repository is busy." return 1 fi echo "Checking cache download in $cache/rootfs-$release-$arch ... " if [ ! -e "$cache/rootfs-$release-$arch" ]; then download_debian "$cache" "$arch" "$release" if [ $? -ne 0 ]; then echo "Failed to download 'debian base'" return 1 fi fi copy_debian "$cache" "$arch" "$rootfs" "$release" if [ $? -ne 0 ]; then echo "Failed to copy rootfs" return 1 fi return 0 ) 9>$LOCALSTATEDIR/lock/subsys/lxc-debian return $? } copy_configuration() { path=$1 rootfs=$2 hostname=$3 arch=$4 num_tty=$5 # Generate the configuration file # if there is exactly one veth network entry, make sure it has an # associated hwaddr. nics=$(grep -ce '^lxc\.network\.type[ \t]*=[ \t]*veth' "$path/config") if [ "$nics" -eq 1 ]; then grep -q "^lxc.network.hwaddr" "$path/config" || sed -i -e "/^lxc\.network\.type[ \t]*=[ \t]*veth/a lxc.network.hwaddr = 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')" "$path/config" fi ## Add all the includes echo "" >> "$path/config" echo "# Common configuration" >> "$path/config" if [ -e "${LXC_TEMPLATE_CONFIG}/debian.common.conf" ]; then echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/debian.common.conf" >> "$path/config" fi if [ -e "${LXC_TEMPLATE_CONFIG}/debian.${release}.conf" ]; then echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/debian.${release}.conf" >> "$path/config" fi ## Add the container-specific config echo "" >> "$path/config" echo "# Container specific configuration" >> "$path/config" grep -q "^lxc.rootfs" "$path/config" 2> /dev/null || echo "lxc.rootfs = $rootfs" >> "$path/config" cat <> $path/config lxc.tty = $num_tty lxc.utsname = $hostname lxc.arch = $arch EOF if [ $? -ne 0 ]; then echo "Failed to add configuration" return 1 fi return 0 } post_process() { local rootfs="$1"; shift local release="$1"; shift local arch="$1"; shift local hostarch="$1"; shift local packages="$*" # Disable service startup cat > "${rootfs}/usr/sbin/policy-rc.d" << EOF #!/bin/sh exit 101 EOF chmod +x "${rootfs}/usr/sbin/policy-rc.d" # If the container isn't running a native architecture, setup multiarch if [ "${arch}" != "${hostarch}" ]; then # Test if dpkg supports multiarch if ! chroot "$rootfs" dpkg --print-foreign-architectures 2>&1; then chroot "$rootfs" dpkg --add-architecture "${hostarch}" fi fi # Write a new sources.list containing both native and multiarch entries > "${rootfs}/etc/apt/sources.list" if [ "${arch}" = "${hostarch}" ]; then write_sourceslist "${rootfs}" "${release}" "${arch}" else write_sourceslist "${rootfs}" "${release}" fi # Install Packages in container if [ -n "${packages}" ]; then local pack_list pack_list="${packages//,/ }" echo "Installing packages: ${pack_list}" install_packages "${rootfs}" "${pack_list}" fi # Re-enable service startup rm "${rootfs}/usr/sbin/policy-rc.d" # end } clean() { cache=${LXC_CACHE_PATH:-"$LOCALSTATEDIR/cache/lxc/debian"} if [ ! -e "$cache" ]; then exit 0 fi # lock, so we won't purge while someone is creating a repository ( flock -x 9 if [ $? != 0 ]; then echo "Cache repository is busy." exit 1 fi echo -n "Purging the download cache..." rm --preserve-root --one-file-system -rf "$cache" && echo "Done." || exit 1 exit 0 ) 9>$LOCALSTATEDIR/lock/subsys/lxc-debian } usage() { cat < [-c|--clean] [-a|--arch=] [-r|--release=] [--mirror=] [--security-mirror=] [--package=] Options : -h, --help print this help text -p, --path=PATH directory where config and rootfs of this VM will be kept -a, --arch=ARCH The container architecture. Can be one of: i686, x86_64, amd64, armhf, armel, powerpc. Defaults to host arch. -r, --release=RELEASE Debian release. Can be one of: wheezy, jessie, stretch, sid. Defaults to current stable. --mirror=MIRROR Debian mirror to use during installation. Overrides the MIRROR environment variable (see below). --security-mirror=SECURITY_MIRROR Debian mirror to use for security updates. Overrides the SECURITY_MIRROR environment variable (see below). --packages=PACKAGE_NAME1,PACKAGE_NAME2,... List of additional packages to install. Comma separated, without space. -c, --clean only clean up the cache and terminate --enable-non-free include also Debian's contrib and non-free repositories. Environment variables: MIRROR The Debian package mirror to use. See also the --mirror switch above. Defaults to '$MIRROR' SECURITY_MIRROR The Debian package security mirror to use. See also the --security-mirror switch above. Defaults to '$SECURITY_MIRROR' EOF return 0 } options=$(getopt -o hp:n:a:r:c -l arch:,clean,help,enable-non-free,mirror:,name:,packages:,path:,release:,rootfs:,security-mirror: -- "$@") if [ $? -ne 0 ]; then usage "$(basename "$0")" exit 1 fi eval set -- "$options" littleendian=$(lscpu | grep '^Byte Order' | grep -q Little && echo yes) arch=$(uname -m) if [ "$arch" = "i686" ]; then arch="i386" elif [ "$arch" = "x86_64" ]; then arch="amd64" elif [ "$arch" = "armv7l" ]; then arch="armhf" elif [ "$arch" = "ppc" ]; then arch="powerpc" elif [ "$arch" = "ppc64le" ]; then arch="ppc64el" elif [ "$arch" = "mips" -a "$littleendian" = "yes" ]; then arch="mipsel" elif [ "$arch" = "mips64" -a "$littleendian" = "yes" ]; then arch="mips64el" fi hostarch=$arch mainonly=1 while true do case "$1" in -h|--help) usage "$0" && exit 1;; --) shift 1; break ;; -a|--arch) arch=$2; shift 2;; -c|--clean) clean=1; shift 1;; --enable-non-free) mainonly=0; shift 1;; --mirror) MIRROR=$2; shift 2;; -n|--name) name=$2; shift 2;; --packages) packages=$2; shift 2;; -p|--path) path=$2; shift 2;; -r|--release) release=$2; shift 2;; --rootfs) rootfs=$2; shift 2;; --security-mirror) SECURITY_MIRROR=$2; shift 2;; *) break ;; esac done if [ ! -z "$clean" -a -z "$path" ]; then clean || exit 1 exit 0 fi if [ "$arch" = "i686" ]; then arch=i386 fi if [ "$arch" = "x86_64" ]; then arch=amd64 fi if [ $hostarch = "i386" -a $arch = "amd64" ]; then echo "can't create $arch container on $hostarch" exit 1 fi if [ $hostarch = "armhf" -o $hostarch = "armel" ] && \ [ $arch != "armhf" -a $arch != "armel" ]; then echo "can't create $arch container on $hostarch" exit 1 fi if [ $hostarch = "powerpc" -a $arch != "powerpc" ]; then echo "can't create $arch container on $hostarch" exit 1 fi type debootstrap if [ $? -ne 0 ]; then echo "'debootstrap' command is missing" exit 1 fi if [ -z "$path" ]; then echo "'path' parameter is required" exit 1 fi if [ "$(id -u)" != "0" ]; then echo "This script should be run as 'root'" exit 1 fi current_release=$(wget "${MIRROR}/dists/stable/Release" -O - 2> /dev/null | head |awk '/^Codename: (.*)$/ { print $2; }') release=${release:-${current_release}} valid_releases=('wheezy' 'jessie' 'stretch' 'sid') if [[ ! "${valid_releases[*]}" =~ (^|[^[:alpha:]])$release([^[:alpha:]]|$) ]]; then echo "Invalid release ${release}, valid ones are: ${valid_releases[*]}" exit 1 fi # detect rootfs config="$path/config" if [ -z "$rootfs" ]; then if grep -q '^lxc.rootfs' "$config" 2> /dev/null ; then rootfs=$(awk -F= '/^lxc.rootfs[ \t]+=/{ print $2 }' "$config") else rootfs=$path/rootfs fi fi # determine the number of ttys - default is 4 if grep -q '^lxc.tty' "$config" 2> /dev/null ; then num_tty=$(awk -F= '/^lxc.tty[ \t]+=/{ print $2 }' "$config") else num_tty=4 fi install_debian "$rootfs" "$release" "$arch" "$LXC_CACHE_PATH" if [ $? -ne 0 ]; then echo "failed to install debian" exit 1 fi configure_debian "$rootfs" "$name" $num_tty if [ $? -ne 0 ]; then echo "failed to configure debian for a container" exit 1 fi copy_configuration "$path" "$rootfs" "$name" $arch $num_tty if [ $? -ne 0 ]; then echo "failed write configuration file" exit 1 fi configure_debian_systemd "$path" "$rootfs" "$config" $num_tty post_process "${rootfs}" "${release}" "${arch}" "${hostarch}" "${packages}" if [ ! -z "$clean" ]; then clean || exit 1 exit 0 fi lxc-2.0.8/templates/lxc-opensuse.in0000644061062106075000000003713113105116772014223 00000000000000#!/bin/bash # # template script for generating OpenSUSE container for LXC # # # lxc: linux Container library # Authors: # Daniel Lezcano # Frederic Crozat # Michael H. Warfield # Johannes Kastl # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Detect use under userns (unsupported) for arg in "$@"; do [ "$arg" = "--" ] && break if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then echo "This template can't be used for unprivileged containers." 1>&2 echo "You may want to try the \"download\" template instead." 1>&2 exit 1 fi done # Make sure the usual locations are in PATH export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin if [ -x /usr/bin/obs-build ]; then BUILD=/usr/bin/obs-build export BUILD_DIR=/usr/lib/obs-build else BUILD=/usr/bin/build export BUILD_DIR=/usr/lib/build fi configure_opensuse() { rootfs=$1 hostname=$2 # set first network adapter as dhcp. This is the most common config. cat < $rootfs/etc/sysconfig/network/ifcfg-eth0 STARTMODE='auto' BOOTPROTO='dhcp' EOF # create empty fstab touch $rootfs/etc/fstab # set the hostname cat < $rootfs/etc/HOSTNAME $hostname EOF # ensure /etc/hostname is available too ln -s -f HOSTNAME $rootfs/etc/hostname # do not use hostname from HOSTNAME variable cat <> $rootfs/etc/sysconfig/cron unset HOSTNAME EOF # set minimal hosts cat < $rootfs/etc/hosts 127.0.0.1 localhost $hostname EOF # disable yast->bootloader in container cat < $rootfs/etc/sysconfig/bootloader LOADER_TYPE=none LOADER_LOCATION=none EOF # set /dev/console as securetty cat << EOF >> $rootfs/etc/securetty console EOF cat <> $rootfs/etc/sysconfig/boot # disable root fsck ROOTFS_FSCK="0" ROOTFS_BLKDEV="/dev/null" EOF # remove pointless services in a container ln -s /dev/null $rootfs/etc/systemd/system/proc-sys-fs-binfmt_misc.automount ln -s /dev/null $rootfs/etc/systemd/system/console-shell.service ln -s /dev/null $rootfs/etc/systemd/system/systemd-vconsole-setup.service sed -e 's/ConditionPathExists=.*//' $rootfs/usr/lib/systemd/system/getty@.service > $rootfs/etc/systemd/system/getty@.service ln -s getty@.service $rootfs/etc/systemd/system/getty@tty1.service ln -s ../getty@.service $rootfs/etc/systemd/system/getty.target.wants/getty@console.service ln -s -f ../getty@.service $rootfs/etc/systemd/system/getty.target.wants/getty@tty1.service ln -s ../getty@.service $rootfs/etc/systemd/system/getty.target.wants/getty@tty2.service ln -s ../getty@.service $rootfs/etc/systemd/system/getty.target.wants/getty@tty3.service ln -s ../getty@.service $rootfs/etc/systemd/system/getty.target.wants/getty@tty4.service touch $rootfs/etc/sysconfig/kernel echo "Please change root-password !" return 0 } download_opensuse() { cache=$1 arch=$2 if [ ! -x ${BUILD} ]; then echo "Could not create openSUSE template :" echo "you need to install \"build\" package" return 1 fi # check the mini opensuse was not already downloaded mkdir -p "$cache/partial-$arch" if [ $? -ne 0 ]; then echo "Failed to create '$cache/partial-$arch' directory" return 1 fi # download a mini opensuse into a cache echo "Downloading opensuse minimal ..." mkdir -p "$cache/partial-$arch-packages" zypper --quiet --root $cache/partial-$arch-packages --non-interactive ar http://download.opensuse.org/distribution/$DISTRO/repo/oss/ repo-oss || return 1 # Leap update repos were rearranged if [[ $DISTRO == "leap/4"* ]]; then zypper --quiet --root $cache/partial-$arch-packages --non-interactive ar http://download.opensuse.org/update/$DISTRO/oss/ update || return 1 else zypper --quiet --root $cache/partial-$arch-packages --non-interactive ar http://download.opensuse.org/update/$DISTRO/ update || return 1 fi zypper --quiet --root $cache/partial-$arch-packages --non-interactive --gpg-auto-import-keys update || return 1 zypper --root $cache/partial-$arch-packages --non-interactive in --auto-agree-with-licenses --download-only zypper lxc patterns-openSUSE-base bash iputils sed tar rsyslog || return 1 cat > $cache/partial-$arch-packages/opensuse.conf << EOF Preinstall: aaa_base bash coreutils diffutils Preinstall: filesystem fillup glibc grep insserv-compat perl-base Preinstall: libbz2-1 libncurses5 pam Preinstall: permissions libreadline6 rpm sed tar libz1 libselinux1 Preinstall: liblzma5 libcap2 libacl1 libattr1 Preinstall: libpopt0 libelf1 liblua5_1 Preinstall: libpcre1 RunScripts: aaa_base Support: zypper Support: patterns-openSUSE-base Support: lxc Support: ncurses-utils Support: iputils Support: udev Support: netcfg Support: hwinfo insserv-compat module-init-tools openSUSE-release openssh Support: pwdutils rpcbind sysconfig Ignore: rpm:suse-build-key,build-key Ignore: systemd:systemd-presets-branding EOF if [ $DISTRO = "13.2" ] then echo "Support: python3-base" >> $cache/partial-$arch-packages/opensuse.conf fi # dhcpcd is not in the default repos since Leap 42.1 if [[ $DISTRO != "leap/4"* ]] then echo "Support: dhcpcd" >> $cache/partial-$arch-packages/opensuse.conf fi # Leap doesn't seem to have iproute2 utils installed if [[ $DISTRO == "leap/4"* ]] then echo "Support: net-tools iproute2" >> $cache/partial-$arch-packages/opensuse.conf fi if [ "$arch" = "i686" ]; then mkdir -p $cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/i686/ for i in "$cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/i586/*" ; do ln -s $i $cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/i686/ done mkdir -p $cache/partial-$arch-packages/var/cache/zypp/packages/update/i686 for i in "$cache/partial-$arch-packages/var/cache/zypp/packages/update/i586/*" ; do ln -s $i $cache/partial-$arch-packages/var/cache/zypp/packages/update/i686/ done fi # openSUSE 13.2 has no noarch directory in update [ -d $cache/partial-$arch-packages/var/cache/zypp/packages/update/noarch ] || mkdir -p $cache/partial-$arch-packages/var/cache/zypp/packages/update/noarch CLEAN_BUILD=1 BUILD_ARCH="$arch" BUILD_ROOT="$cache/partial-$arch" BUILD_DIST="$cache/partial-$arch-packages/opensuse.conf" PATH="$PATH:$BUILD_DIR" $BUILD_DIR/init_buildsystem --clean --configdir $BUILD_DIR/configs --cachedir $cache/partial-$arch-cache --repository $cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/$arch --repository $cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/noarch --repository $cache/partial-$arch-packages/var/cache/zypp/packages/update/$arch --repository $cache/partial-$arch-packages/var/cache/zypp/packages/update/noarch || return 1 chroot $cache/partial-$arch /usr/bin/zypper --quiet --non-interactive ar http://download.opensuse.org/distribution/$DISTRO/repo/oss repo-oss || return 1 if [[ $DISTRO == "leap/4"* ]]; then chroot $cache/partial-$arch /usr/bin/zypper --quiet --non-interactive ar http://download.opensuse.org/update/$DISTRO/oss update || return 1 else chroot $cache/partial-$arch /usr/bin/zypper --quiet --non-interactive ar http://download.opensuse.org/update/$DISTRO/ update || return 1 fi # really clean the image rm -fr $cache/partial-$arch/{.build,.guessed_dist,.srcfiles*,installed-pkg} rm -fr $cache/partial-$arch/dev # make sure we have a minimal /dev mkdir -p "$cache/partial-$arch/dev" mknod -m 666 $cache/partial-$arch/dev/null c 1 3 mknod -m 666 $cache/partial-$arch/dev/zero c 1 5 # create mtab symlink rm -f $cache/partial-$arch/etc/mtab ln -sf /proc/self/mounts $cache/partial-$arch/etc/mtab # ensure /var/run and /run are symlinked rm -fr $cache/partial-$arch/var/run ln -s -f ../run $cache/partial-$arch/var/run if [ $? -ne 0 ]; then echo "Failed to download the rootfs, aborting." return 1 fi rm -fr "$cache/partial-$arch-packages" mv "$1/partial-$arch" "$1/rootfs-$arch" echo "Download complete." return 0 } copy_opensuse() { cache=$1 arch=$2 rootfs=$3 # make a local copy of the mini opensuse echo "Copying rootfs to $rootfs ..." mkdir -p $rootfs rsync -Ha $cache/rootfs-$arch/ $rootfs/ || return 1 return 0 } install_opensuse() { # Allow the cache base to be set by environment variable cache="${LXC_CACHE_PATH:-@LOCALSTATEDIR@/cache/lxc/opensuse/$DISTRO}" rootfs=$1 mkdir -p @LOCALSTATEDIR@/lock/subsys/ ( flock -x 9 if [ $? -ne 0 ]; then echo "Cache repository is busy." return 1 fi echo "Checking cache download in $cache/rootfs-$arch ... " if [ ! -e "$cache/rootfs-$arch" ]; then download_opensuse $cache $arch if [ $? -ne 0 ]; then echo "Failed to download 'opensuse base'" return 1 fi fi echo "Copy $cache/rootfs-$arch to $rootfs ... " copy_opensuse $cache $arch $rootfs if [ $? -ne 0 ]; then echo "Failed to copy rootfs" return 1 fi return 0 ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-opensuse return $? } # Generate a random hardware (MAC) address composed of FE followed by # 5 random bytes... create_hwaddr() { openssl rand -hex 5 | sed -e 's/\(..\)/:\1/g; s/^/fe/' } copy_configuration() { path=$1 rootfs=$2 name=$3 grep -q "^lxc.rootfs" $path/config 2>/dev/null || echo " lxc.rootfs = $rootfs_path " >> $path/config # The following code is to create static MAC addresses for each # interface in the container. This code will work for multiple # interfaces in the default config. It will also strip any # hwaddr stanzas out of the default config since we can not share # MAC addresses between containers. # # This code is largely mimiced from the Fedora Template. mv $path/config $path/config.def while read LINE do # This should catch variable expansions from the default config... if expr "${LINE}" : '.*\$' > /dev/null 2>&1 then LINE=$(eval "echo \"${LINE}\"") fi # There is a tab and a space in the regex bracket below! # Seems that \s doesn't work in brackets. KEY=$(expr "${LINE}" : '\s*\([^ ]*\)\s*=') if [[ "${KEY}" != "lxc.network.hwaddr" ]] then echo "${LINE}" >> $path/config if [[ "${KEY}" == "lxc.network.link" ]] then echo "lxc.network.hwaddr = $(create_hwaddr)" >> $path/config fi fi done < $path/config.def rm -f $path/config.def if [ -e "@LXCTEMPLATECONFIG@/opensuse.common.conf" ]; then echo " # Include common configuration lxc.include = @LXCTEMPLATECONFIG@/opensuse.common.conf " >> $path/config fi # Append things which require expansion here... cat <> $path/config lxc.arch = $arch lxc.utsname = $name lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed # When using LXC with apparmor, uncomment the next line to run unconfined: lxc.aa_profile = unconfined # example simple networking setup, uncomment to enable #lxc.network.type = $lxc_network_type #lxc.network.flags = up #lxc.network.link = $lxc_network_link #lxc.network.name = eth0 # Additional example for veth network type # static MAC address, #lxc.network.hwaddr = 00:16:3e:77:52:20 # persistent veth device name on host side # Note: This may potentially collide with other containers of same name! #lxc.network.veth.pair = v-$name-e0 EOF if [ $? -ne 0 ]; then echo "Failed to add configuration" return 1 fi return 0 } clean() { cache="${LXC_CACHE_PATH:-@LOCALSTATEDIR@/cache/lxc/opensuse}" if [ ! -e $cache ]; then exit 0 fi # lock, so we won't purge while someone is creating a repository ( flock -x 9 if [ $? != 0 ]; then echo "Cache repository is busy." exit 1 fi echo -n "Purging the download cache..." rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1 exit 0 ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-opensuse } usage() { cat < -r|--release nn.n --clean Please give the release as 13.1, 13.2 etc. If no release is given, openSUSE Leap 42.2 is installed. EOF return 0 } # Make arch a global. This may become configurable? arch=$(uname -m) options=$(getopt -o hp:n:r:c -l help,rootfs:,path:,name:,release:,clean -- "$@") if [ $? -ne 0 ]; then usage $(basename $0) exit 1 fi eval set -- "$options" while true do case "$1" in -h|--help) usage $0 && exit 0;; -p|--path) path=$2; shift 2;; --rootfs) rootfs=$2; shift 2;; -n|--name) name=$2; shift 2;; -r|--release) DISTRO=$2; shift 2;; -c|--clean) clean=1; shift 1;; --) shift 1; break ;; *) break ;; esac done if [ ! -z "$clean" -a -z "$path" ]; then clean || exit 1 exit 0 fi type zypper > /dev/null if [ $? -ne 0 ]; then echo "'zypper' command is missing" exit 1 fi if [ -z "$path" ]; then echo "'path' parameter is required" exit 1 fi if grep -q Harlequin /etc/os-release || grep -q Tumbleweed /etc/os-release ; then BVER=`rpm -q --qf '%{version}\n' build` if [ $? -ne 0 -o "$BVER" -lt "20141120" ]; then echo "Building openSUSE containers with your version of the build package is broken. Please install the update to version 20141120 or newer." exit 1 fi fi if [ -z "$DISTRO" ]; then echo "" echo "No release selected, using openSUSE Leap 42.2" DISTRO="leap/42.2" else echo "" case "$DISTRO" in 13.1) echo "Selected openSUSE 13.1" ;; 13.2) echo "Selected openSUSE 13.2" ;; 42.1|leap/42.1|leap) echo "Selected openSUSE Leap 42.1" DISTRO="leap/42.1" ;; 42.2|leap/42.2|422) echo "Selected openSUSE Leap 42.2" DISTRO="leap/42.2" ;; *) echo "You have chosen an invalid release, quitting..." exit 1 ;; esac fi if [ "$(id -u)" != "0" ]; then echo "This script should be run as 'root'" exit 1 fi # detect rootfs config="$path/config" if [ -z "$rootfs" ]; then if grep -q '^lxc.rootfs' $config 2>/dev/null ; then rootfs=$(awk -F= '/^lxc.rootfs =/{ print $2 }' $config) else rootfs=$path/rootfs fi fi install_opensuse $rootfs if [ $? -ne 0 ]; then echo "failed to install opensuse" exit 1 fi configure_opensuse $rootfs $name if [ $? -ne 0 ]; then echo "failed to configure opensuse for a container" exit 1 fi copy_configuration $path $rootfs $name if [ $? -ne 0 ]; then echo "failed write configuration file" exit 1 fi if [ ! -z "$clean" ]; then clean || exit 1 exit 0 fi lxc-2.0.8/templates/lxc-fedora.in0000644061062106075000000014107713105116772013627 00000000000000#!/bin/bash # # template script for generating fedora container for LXC # # # lxc: linux Container library # Authors: # Daniel Lezcano # Ramez Hanna # Michael H. Warfield # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #Configurations default_path=@LXCPATH@ # Some combinations of the tuning knobs below do not exactly make sense. # but that's ok. # # If the "root_password" is non-blank, use it, else set a default. # This can be passed to the script as an environment variable and is # set by a shell conditional assignment. Looks weird but it is what it is. # # If the root password contains a ding ($) then try to expand it. # That will pick up things like ${name} and ${RANDOM}. # If the root password contains more than 3 consecutive X's, pass it as # a template to mktemp and take the result. # # If root_display_password = yes, display the temporary root password at exit. # If root_store_password = yes, store it in the configuration directory # If root_prompt_password = yes, invoke "passwd" to force the user to change # the root password after the container is created. # If root_expire_password = yes, you will be prompted to change the root # password at the first login. # # These are conditional assignments... The can be overridden from the # preexisting environment variables... # # Make sure this is in single quotes to defer expansion to later! # :{root_password='Root-${name}-${RANDOM}'} : ${root_password='Root-${name}-XXXXXX'} # Now, it doesn't make much sense to display, store, and force change # together. But, we gotta test, right??? : ${root_display_password='no'} : ${root_store_password='yes'} # Prompting for something interactive has potential for mayhem # with users running under the API... Don't default to "yes" : ${root_prompt_password='no'} # Expire root password? Default to yes, but can be overridden from # the environment variable : ${root_expire_password='yes'} # These are only going into comments in the resulting config... lxc_network_type=veth lxc_network_link=lxcbr0 # is this fedora? # Alow for weird remixes like the Raspberry Pi # # Use the Mitre standard CPE identifier for the release ID if possible... # This may be in /etc/os-release or /etc/system-release-cpe. We # should be able to use EITHER. Give preference to /etc/os-release for now. # Detect use under userns (unsupported) for arg in "$@"; do [ "$arg" = "--" ] && break if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then echo "This template can't be used for unprivileged containers." 1>&2 echo "You may want to try the \"download\" template instead." 1>&2 exit 1 fi done # Make sure the usual locations are in PATH export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin if [ -e /etc/os-release ] then # This is a shell friendly configuration file. We can just source it. # What we're looking for in here is the ID, VERSION_ID and the CPE_NAME . /etc/os-release echo "Host CPE ID from /etc/os-release: ${CPE_NAME}" fi if [ "${CPE_NAME}" = "" -a -e /etc/system-release-cpe ] then CPE_NAME=$(head -n1 /etc/system-release-cpe) CPE_URI=$(expr ${CPE_NAME} : '\([^:]*:[^:]*\)') if [ "${CPE_URI}" != "cpe:/o" ] then CPE_NAME= else echo "Host CPE ID from /etc/system-release-cpe: ${CPE_NAME}" # Probably a better way to do this but sill remain posix # compatible but this works, shrug... # Must be nice and not introduce convenient bashisms here. ID=$(expr ${CPE_NAME} : '[^:]*:[^:]*:[^:]*:\([^:]*\)') VERSION_ID=$(expr ${CPE_NAME} : '[^:]*:[^:]*:[^:]*:[^:]*:\([^:]*\)') fi fi if [ "${CPE_NAME}" != "" -a "${ID}" = "fedora" -a "${VERSION_ID}" != "" ] then fedora_host_ver=${VERSION_ID} is_fedora=true elif [ -e /etc/redhat-release ] then # Only if all other methods fail, try to parse the redhat-release file. fedora_host_ver=$( sed -e '/^Fedora /!d' -e 's/Fedora.*\srelease\s*\([0-9][0-9]*\)\s.*/\1/' < /etc/redhat-release ) if [ "$fedora_host_ver" != "" ] then is_fedora=true fi fi configure_fedora() { # disable selinux in fedora mkdir -p $rootfs_path/selinux echo 0 > $rootfs_path/selinux/enforce # Also kill it in the /etc/selinux/config file if it's there... if [[ -f $rootfs_path/etc/selinux/config ]] then sed -i '/^SELINUX=/s/.*/SELINUX=disabled/' $rootfs_path/etc/selinux/config fi # Nice catch from Dwight Engen in the Oracle template. # Wantonly plagerized here with much appreciation. if [ -f $rootfs_path/usr/sbin/selinuxenabled ]; then mv $rootfs_path/usr/sbin/selinuxenabled $rootfs_path/usr/sbin/selinuxenabled.lxcorig ln -s /bin/false $rootfs_path/usr/sbin/selinuxenabled fi # This is a known problem and documented in RedHat bugzilla as relating # to a problem with auditing enabled. This prevents an error in # the container "Cannot make/remove an entry for the specified session" sed -i '/^session.*pam_loginuid.so/s/^session/# session/' ${rootfs_path}/etc/pam.d/login sed -i '/^session.*pam_loginuid.so/s/^session/# session/' ${rootfs_path}/etc/pam.d/sshd if [ -f ${rootfs_path}/etc/pam.d/crond ] then sed -i '/^session.*pam_loginuid.so/s/^session/# session/' ${rootfs_path}/etc/pam.d/crond fi # In addition to disabling pam_loginuid in the above config files # we'll also disable it by linking it to pam_permit to catch any # we missed or any that get installed after the container is built. # # Catch either or both 32 and 64 bit archs. if [ -f ${rootfs_path}/lib/security/pam_loginuid.so ] then ( cd ${rootfs_path}/lib/security/ mv pam_loginuid.so pam_loginuid.so.disabled ln -s pam_permit.so pam_loginuid.so ) fi if [ -f ${rootfs_path}/lib64/security/pam_loginuid.so ] then ( cd ${rootfs_path}/lib64/security/ mv pam_loginuid.so pam_loginuid.so.disabled ln -s pam_permit.so pam_loginuid.so ) fi # Set default localtime to the host localtime if not set... if [ -e /etc/localtime -a ! -e ${rootfs_path}/etc/localtime ] then # if /etc/localtime is a symlink, this should preserve it. cp -a /etc/localtime ${rootfs_path}/etc/localtime fi # Deal with some dain bramage in the /etc/init.d/halt script. # Trim it and make it our own and link it in before the default # halt script so we can intercept it. This also preventions package # updates from interferring with our interferring with it. # # There's generally not much in the halt script that useful but what's # in there from resetting the hardware clock down is generally very bad. # So we just eliminate the whole bottom half of that script in making # ourselves a copy. That way a major update to the init scripts won't # trash what we've set up. # # This is mostly for legacy distros since any modern systemd Fedora # release will not have this script so we won't try to intercept it. if [ -f ${rootfs_path}/etc/init.d/halt ] then sed -e '/hwclock/,$d' \ < ${rootfs_path}/etc/init.d/halt \ > ${rootfs_path}/etc/init.d/lxc-halt echo '$command -f' >> ${rootfs_path}/etc/init.d/lxc-halt chmod 755 ${rootfs_path}/etc/init.d/lxc-halt # Link them into the rc directories... ( cd ${rootfs_path}/etc/rc.d/rc0.d ln -s ../init.d/lxc-halt S00lxc-halt cd ${rootfs_path}/etc/rc.d/rc6.d ln -s ../init.d/lxc-halt S00lxc-reboot ) fi # configure the network using the dhcp cat < ${rootfs_path}/etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 BOOTPROTO=dhcp ONBOOT=yes HOSTNAME=${utsname} DHCP_HOSTNAME=\`hostname\` NM_CONTROLLED=no TYPE=Ethernet MTU=${MTU} EOF # set the hostname cat < ${rootfs_path}/etc/sysconfig/network NETWORKING=yes HOSTNAME=${utsname} EOF # set hostname on systemd Fedora systems if [ $release -gt 14 ]; then echo "${utsname}" > ${rootfs_path}/etc/hostname fi # set minimal hosts cat < $rootfs_path/etc/hosts 127.0.0.1 localhost.localdomain localhost $utsname ::1 localhost6.localdomain6 localhost6 EOF # These mknod's really don't make any sense with modern releases of # Fedora with systemd, devtmpfs, and autodev enabled. They are left # here for legacy reasons and older releases with upstart and sysv init. dev_path="${rootfs_path}/dev" rm -rf $dev_path mkdir -p $dev_path mknod -m 666 ${dev_path}/null c 1 3 mknod -m 666 ${dev_path}/zero c 1 5 mknod -m 666 ${dev_path}/random c 1 8 mknod -m 666 ${dev_path}/urandom c 1 9 mkdir -m 755 ${dev_path}/pts mkdir -m 1777 ${dev_path}/shm mknod -m 666 ${dev_path}/tty c 5 0 mknod -m 666 ${dev_path}/tty0 c 4 0 mknod -m 666 ${dev_path}/tty1 c 4 1 mknod -m 666 ${dev_path}/tty2 c 4 2 mknod -m 666 ${dev_path}/tty3 c 4 3 mknod -m 666 ${dev_path}/tty4 c 4 4 mknod -m 600 ${dev_path}/console c 5 1 mknod -m 666 ${dev_path}/full c 1 7 mknod -m 600 ${dev_path}/initctl p mknod -m 666 ${dev_path}/ptmx c 5 2 # setup console and tty[1-4] for login. note that /dev/console and # /dev/tty[1-4] will be symlinks to the ptys /dev/lxc/console and # /dev/lxc/tty[1-4] so that package updates can overwrite the symlinks. # lxc will maintain these links and bind mount ptys over /dev/lxc/* # since lxc.devttydir is specified in the config. # allow root login on console, tty[1-4], and pts/0 for libvirt echo "# LXC (Linux Containers)" >>${rootfs_path}/etc/securetty echo "lxc/console" >>${rootfs_path}/etc/securetty echo "lxc/tty1" >>${rootfs_path}/etc/securetty echo "lxc/tty2" >>${rootfs_path}/etc/securetty echo "lxc/tty3" >>${rootfs_path}/etc/securetty echo "lxc/tty4" >>${rootfs_path}/etc/securetty echo "# For libvirt/Virtual Machine Monitor" >>${rootfs_path}/etc/securetty echo "pts/0" >>${rootfs_path}/etc/securetty if [ ${root_display_password} = "yes" ] then echo "Setting root password to '$root_password'" fi if [ ${root_store_password} = "yes" ] then touch ${config_path}/tmp_root_pass chmod 600 ${config_path}/tmp_root_pass echo ${root_password} > ${config_path}/tmp_root_pass echo "Storing root password in '${config_path}/tmp_root_pass'" fi echo "root:$root_password" | chroot $rootfs_path chpasswd if [ ${root_expire_password} = "yes" ] then # Also set this password as expired to force the user to change it! chroot $rootfs_path passwd -e root fi # specifying this in the initial packages doesn't always work. # Even though it should have... echo "installing fedora-release package" mount -o bind /dev ${rootfs_path}/dev mount -t proc proc ${rootfs_path}/proc # Always make sure /etc/resolv.conf is up to date in the target! cp /etc/resolv.conf ${rootfs_path}/etc/ # Rebuild the rpm database based on the target rpm version... rm -f ${rootfs_path}/var/lib/rpm/__db* chroot ${rootfs_path} rpm --rebuilddb chroot ${rootfs_path} yum -y install fedora-release if [[ ! -e ${rootfs_path}/sbin/NetworkManager ]] then # NetworkManager has not been installed. Use the # legacy chkconfig command to enable the network startup # scripts in the container. chroot ${rootfs_path} chkconfig network on fi umount ${rootfs_path}/proc umount ${rootfs_path}/dev # silence some needless startup errors touch ${rootfs_path}/etc/fstab # give us a console on /dev/console sed -i 's/ACTIVE_CONSOLES=.*$/ACTIVE_CONSOLES="\/dev\/console \/dev\/tty[1-4]"/' \ ${rootfs_path}/etc/sysconfig/init return 0 } configure_fedora_init() { sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc/rc.sysinit sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc/rc.d/rc.sysinit # don't mount devpts, for pete's sake sed -i 's/^.*dev.pts.*$/#\0/' ${rootfs_path}/etc/rc.sysinit sed -i 's/^.*dev.pts.*$/#\0/' ${rootfs_path}/etc/rc.d/rc.sysinit chroot ${rootfs_path} chkconfig udev-post off chroot ${rootfs_path} chkconfig network on if [ -d ${rootfs_path}/etc/init ] then # This is to make upstart honor SIGPWR. Should do no harm # on systemd systems and some systems may have both. cat <${rootfs_path}/etc/init/power-status-changed.conf # power-status-changed - shutdown on SIGPWR # start on power-status-changed exec /sbin/shutdown -h now "SIGPWR received" EOF fi } configure_fedora_systemd() { rm -f ${rootfs_path}/etc/systemd/system/default.target touch ${rootfs_path}/etc/fstab chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/udev.service chroot ${rootfs_path} ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target # Make systemd honor SIGPWR chroot ${rootfs_path} ln -s /usr/lib/systemd/system/halt.target /etc/systemd/system/sigpwr.target # if desired, prevent systemd from over-mounting /tmp with tmpfs if [ $masktmp -eq 1 ]; then chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/tmp.mount fi #dependency on a device unit fails it specially that we disabled udev # sed -i 's/After=dev-%i.device/After=/' ${rootfs_path}/lib/systemd/system/getty\@.service # # Actually, the After=dev-%i.device line does not appear in the # Fedora 17 or Fedora 18 systemd getty\@.service file. It may be left # over from an earlier version and it's not doing any harm. We do need # to disable the "ConditionalPathExists=/dev/tty0" line or no gettys are # started on the ttys in the container. Lets do it in an override copy of # the service so it can still pass rpm verifies and not be automatically # updated by a new systemd version. -- mhw /\/\|=mhw=|\/\/ sed -e 's/^ConditionPathExists=/# ConditionPathExists=/' \ -e 's/After=dev-%i.device/After=/' \ < ${rootfs_path}/lib/systemd/system/getty\@.service \ > ${rootfs_path}/etc/systemd/system/getty\@.service # Setup getty service on the 4 ttys we are going to allow in the # default config. Number should match lxc.tty ( cd ${rootfs_path}/etc/systemd/system/getty.target.wants for i in 1 2 3 4 ; do ln -sf ../getty\@.service getty@tty${i}.service; done ) } ### BEGIN Bootstrap Environment Code... Michael H. Warfield /\/\|=mhw=|\/\/ # Ok... Heads up. If you're reading these comments, you're either a # template owner or someone wondering how the hell I did this (or, worse, # someone in the future trying to maintain it). This code is slightly # "evil coding bastard" code with one significant hack / dirty trick # that you would probably miss just reading the code below. I'll mark # it out with comments. # # Because of what this code does, it deserves a lot of comments so people # can understand WHY I did it this way... # # Ultimate Objective - Build a Fedora container on a host system which does # not have a (complete compatible) version of rpm and/or yum. That basically # means damn near any distro other than Fedora and Ubuntu (which has rpm and # yum available). Only requirements for this function are rsync and # squashfs available to the kernel. If you don't have those, why are you # even attempting to build containers? # # Challenge for this function - Bootstrap a Fedora install bootstrap # run time environment which has all the pieces to run rpm and yum and # from which we can build targets containers even where the host system # has no support for rpm, yum, or fedora. # # Steps: # Stage 0 - Download a Fedora LiveOS squashfs core (netinst core). # Stage 1 - Extract filesystem from Stage 0 and update to full rpm & yum # Stage 2 - Use Stage 1 to build a rootfs with python, rpm, and yum. # # Stage 2 becomes our bootstrap file system which can be cached # and then used to build other arbitrary vesions of Fedora of a # given architecture. Note that this only has to run once for # Fedora on a given architecture since rpm and yum can build other # versions. We'll arbitrarily pick Fedora 20 to build this. This # will need to change as time goes on. # Programmers Note... A future fall back may be to download the netinst # iso image instead of the LiveOS squasfs image and work from that. # That may be more general but will introduce another substep # (mounting the iso) to the stage0 setup. # This system is designed to be as autonomous as possible so all whitelists # and controls are self-contained. # Initial testing - Whitelist nobody. Build for everybody... # Initial deployment - Whitelist Fedora. # Long term - Whitelist Fedora, Debian, Ubuntu, CentOs, Scientific, and NST. # List of distros which do not (should not) need a bootstrap (but we will test # for rpm and yum none the less... OS SHOULD be taken from CPE values but # Debian / Ubuntu doesn't support CPE yet. # BOOTSTRAP_WHITE_LIST="" BOOTSTRAP_WHITE_LIST="fedora" # BOOTSTRAP_WHITE_LIST="fedora debian ubuntu centos scientific sl nst" BOOTSTRAP=0 BOOTSTRAP_DIR= BOOTSTRAP_CHROOT= fedora_get_bootstrap() { echo "Bootstrap Environment testing..." WHITE_LISTED=1 # We need rpm. No rpm - not possible to white list... if ! which rpm > /dev/null 2>&1 then WHITE_LISTED=0 fi # We need yum No yum - not possible to white list... if ! which yum > /dev/null 2>&1 then WHITE_LISTED=0 fi if [[ ${WHITE_LISTED} != 0 ]] then for OS in ${BOOTSTRAP_WHITE_LIST} do if [[ ${ID} = ${OS} ]] then echo " OS ${ID} is whitelisted. Installation Bootstrap Environment not required. " return 0; fi done fi echo " Fedora Installation Bootstrap Build..." if ! which rsync > /dev/null 2>&1 then echo " Unable to locate rsync. Cravely bailing out before even attempting to build an Installation Bootstrap Please install rsync and then rerun this process. " return 255 fi [[ -d ${cache_base} ]] || mkdir -p ${cache_base} cd ${cache_base} # We know we don't have a cache directory of this version or we # would have never reached this code to begin with. But we may # have another Fedora cache directory from which we could run... # We'll give a preference for close matches preferring higher over # lower - which makes for really ugly code... # Is this a "bashism" that will need cleaning up???? BOOTSTRAP_LIST="$(( $release + 1 ))/rootfs $(( $release - 1 ))/rootfs \ $(( $release + 2 ))/rootfs $(( $release - 2 ))/rootfs \ $(( $release + 3 ))/rootfs $(( $release - 3 ))/rootfs \ bootstrap" for bootstrap in ${BOOTSTRAP_LIST} do if [[ -d ${bootstrap} ]] then echo " Existing Bootstrap found. Testing..." mount -o bind /dev ${bootstrap}/dev mount -t proc proc ${bootstrap}/proc # Always make sure /etc/resolv.conf is up to date in the target! cp /etc/resolv.conf ${bootstrap}/etc/ rm -f ${bootstrap}/var/lib/rpm/__db* chroot ${bootstrap} rpm --rebuilddb chroot ${bootstrap} yum -y update RC=$? umount ${bootstrap}/proc umount ${bootstrap}/dev if [[ 0 == ${RC} ]] then BOOTSTRAP=1 BOOTSTRAP_DIR="${cache_base}/${bootstrap}" BOOTSTRAP_CHROOT="chroot ${BOOTSTRAP_DIR} " BOOTSTRAP_INSTALL_ROOT=/run/install echo " Functional Installation Bootstrap exists and appears to be completed. Will use existing Bootstrap: ${BOOTSTRAP_DIR} " return 0 fi echo " Installation Bootstrap in ${BOOTSTRAP_DIR} exists but appears to be non-functional. Skipping... It should be removed. " fi done TMP_BOOTSTRAP_DIR=$( mktemp -d --tmpdir=${cache_base} bootstrap_XXXXXX ) cd ${TMP_BOOTSTRAP_DIR} mkdir squashfs stage0 stage1 bootstrap ### Stage 0 setup. # Download the LiveOS squashfs image # mount image to "squashfs" # mount contained LiveOS to stage0 # We're going to use the archives.fedoraproject.org mirror for the initial stages... # 1 - It's generally up to date and complete # 2 - It's has high bandwidth access # 3 - It supports rsync and wildcarding (and we need both) # 4 - Not all the mirrors carry the LiveOS images if [[ ! -f ../LiveOS/squashfs.img ]] then echo " Downloading stage 0 LiveOS squashfs file system from archives.fedoraproject.org... Have a beer or a cup of coffee. This will take a bit (~300MB). " sleep 3 # let him read it... # Right now, we are using Fedora 20 for the inial bootstrap. # We could make this the "current" Fedora rev (F > 15). rsync -av ${mirrorurl}/fedora/linux/releases/20/Fedora/$basearch/os/LiveOS . if [[ 0 == $? ]] then echo "Download of squashfs image complete." mv LiveOS .. else echo " Download of squashfs image failed. " return 255 fi else echo "Using cached stage 0 LiveOS squashfs file system." fi mount -o loop ../LiveOS/squashfs.img squashfs if [[ $? != 0 ]] then echo " Mount of LiveOS squashfs image failed! You mush have squashfs support available to mount image. Unable to continue. Correct and retry process later! LiveOS image not removed. Process may be rerun without penalty of downloading LiveOS again. If LiveOS is corrupt, remove ${cache_base}/LiveOS before rerunning to redownload. " return 255 fi mount -o loop squashfs/LiveOS/rootfs.img stage0 if [[ $? != 0 ]] then echo " Mount of LiveOS stage0 rootfs image failed! LiveOS download may be corrupt. Remove ${cache_base}/LiveOS to force a new download or troubleshoot cached image and then rerun process. " return 255 fi ### Stage 1 setup. # Copy stage0 (which is ro) to stage1 area (rw) for modification. # Unmount stage0 mounts - we're done with stage 0 at this point. # Download our rpm and yum rpm packages. # Force install of rpm and yum into stage1 image (dirty hack!) echo "Stage 0 complete, building Stage 1 image... This will take a couple of minutes. Patience..." echo "Creating Stage 1 r/w copy of r/o Stage 0 squashfs image from LiveOS." rsync -aAHS stage0/. stage1/ umount stage0 umount squashfs cd stage1 # Setup stage1 image with pieces to run installs... mount -o bind /dev dev mount -t proc proc proc # Always make sure /etc/resolv.conf is up to date in the target! cp /etc/resolv.conf etc/ mkdir run/install echo "Updating Stage 1 image with full rpm and yum packages" # Retrieve our 2 rpm packages we need to force down the throat # of this LiveOS image we're camped out on. This is the beginning # of the butt ugly hack. Look close or you may missing it... rsync -av ${mirrorurl}/fedora/linux/releases/20/Fedora/$basearch/os/Packages/r/rpm-[0-9]* \ ${mirrorurl}/fedora/linux/releases/20/Fedora/$basearch/os/Packages/y/yum-[0-9]* . # And here it is... # The --nodeps is STUPID but F15 had a bogus dependency on RawHide?!?! chroot . rpm -ivh --nodeps rpm-* yum-* # Did you catch it? # The LiveOS image contains rpm (but not rpmdb) and yum (but not # yummain.py - What the hell good does yum do with no # yummain.py?!?! - Sigh...). It contains all the supporting # pieces but the rpm database has not be initialized and it # doesn't know all the dependences (seem to) have been met. # So we do a "--nodeps" rpm install in the chrooted environment # to force the installation of the full rpm and yum packages. # # For the purists - Yes, I know the rpm database is wildly out # of whack now. That's why this is a butt ugly hack / dirty trick. # But, this is just the stage1 image that we are going to discard as # soon as the stage2 image is built, so we don't care. All we care # is that the stage2 image ends up with all the pieces it need to # run yum and rpm and that the stage2 rpm database is coherent. # # NOW we can really go to work! ### Stage 2 setup. # Download our Fedora Release rpm packages. # Install fedora-release into bootstrap to initialize fs and databases. # Install rpm, and yum into bootstrap image using yum echo "Stage 1 creation complete. Building stage 2 Installation Bootstrap" mount -o bind ../bootstrap run/install rsync -av ${mirrorurl}/fedora/linux/releases/20/Fedora/$basearch/os/Packages/f/fedora-release-20* . # The --nodeps is STUPID but F15 had a bogus dependency on RawHide?!?! chroot . rpm --root /run/install --nodeps -ivh fedora-release-* # yum will take $basearch from host, so force the arch we want sed -i "s|\$basearch|$basearch|" ./run/install/etc/yum.repos.d/* chroot . yum -y --nogpgcheck --installroot /run/install install python rpm yum umount run/install umount proc umount dev # That's it! We should now have a viable installation BOOTSTRAP in # bootstrap We'll do a yum update in that to verify and then # move it to the cache location before cleaning up. cd ../bootstrap mount -o bind /dev dev mount -t proc proc proc # Always make sure /etc/resolv.conf is up to date in the target! cp /etc/resolv.conf etc/ # yum will take $basearch from host, so force the arch we want sed -i "s|\$basearch|$basearch|" ./etc/yum.repos.d/* chroot . yum -y update RC=$? umount proc umount dev cd .. if [[ ${RC} != 0 ]] then echo " Build of Installation Bootstrap failed. Temp directory not removed so it can be investigated. " return 255 fi # We know have a working run time environment in rootfs... mv bootstrap .. cd .. rm -rf ${TMP_BOOTSTRAP_DIR} echo " Build of Installation Bootstrap complete! We now return you to your normally scheduled template creation. " BOOTSTRAP=1 BOOTSTRAP_DIR="${cache_base}/bootstrap" BOOTSTRAP_CHROOT="chroot ${BOOTSTRAP_DIR} " BOOTSTRAP_INSTALL_ROOT=/run/install return 0 } fedora_bootstrap_mounts() { if [[ ${BOOTSTRAP} -ne 1 ]] then return 0 fi BOOTSTRAP_CHROOT="chroot ${BOOTSTRAP_DIR} " echo "Mounting Bootstrap mount points" [[ -d ${BOOTSTRAP_DIR}/run/install ]] || mkdir -p ${BOOTSTRAP_DIR}/run/install mount -o bind ${INSTALL_ROOT} ${BOOTSTRAP_DIR}/run/install mount -o bind /dev ${BOOTSTRAP_DIR}/dev mount -t proc proc ${BOOTSTRAP_DIR}/proc # Always make sure /etc/resolv.conf is up to date in the target! cp /etc/resolv.conf ${BOOTSTRAP_DIR}/etc/ } fedora_bootstrap_umounts() { if [[ ${BOOTSTRAP} -ne 1 ]] then return 0 fi umount ${BOOTSTRAP_DIR}/proc umount ${BOOTSTRAP_DIR}/dev umount ${BOOTSTRAP_DIR}/run/install } # This is the code to create the initial roofs for Fedora. It may # require a run time environment by calling the routines above... download_fedora() { # check the mini fedora was not already downloaded INSTALL_ROOT=$cache/partial mkdir -p $INSTALL_ROOT if [ $? -ne 0 ]; then echo "Failed to create '$INSTALL_ROOT' directory" return 1 fi # download a mini fedora into a cache echo "Downloading fedora minimal ..." # These will get changed if it's decided that we need a # boostrap environment (can not build natively). These # are the defaults for the non-boostrap (native) mode. BOOTSTRAP_INSTALL_ROOT=${INSTALL_ROOT} BOOTSTRAP_CHROOT= BOOTSTRAP_DIR= PKG_LIST="yum initscripts passwd rsyslog vim-minimal openssh-server openssh-clients dhclient chkconfig rootfiles policycoreutils fedora-release" MIRRORLIST_URL="http://mirrors.fedoraproject.org/mirrorlist?repo=fedora-$release&arch=$basearch" if [[ ${release} -lt 17 ]] then # The reflects the move of db_dump and db_load from db4_utils to # libdb_utils in Fedora 17 and above and it's inclusion as a dep... # Prior to Fedora 11, we need to explicitly include it! PKG_LIST="${PKG_LIST} db4-utils" fi if [[ ${release} -ge 21 ]] then # Since Fedora 21, a separate fedora-repos package is needed. # Before, the information was conained in fedora-release. PKG_LIST="${PKG_LIST} fedora-repos" fi DOWNLOAD_OK=no # We're splitting the old loop into two loops plus a directory retrival. # First loop... Try and retrive a mirror list with retries and a slight # delay between attempts... for trynumber in 1 2 3 4; do [ $trynumber != 1 ] && echo "Trying again..." # This code is mildly "brittle" in that it assumes a certain # page format and parsing HTML. I've done worse. :-P MIRROR_URLS=$(curl -s -S -f "$MIRRORLIST_URL" | sed -e '/^http:/!d' -e '2,6!d') if [ $? -eq 0 ] && [ -n "$MIRROR_URLS" ] then break fi echo "Failed to get a mirror on try $trynumber" sleep 3 done # This will fall through if we didn't get any URLS above for MIRROR_URL in ${MIRROR_URLS} do if [ "$release" -gt "16" ]; then RELEASE_URL="$MIRROR_URL/Packages/f" else RELEASE_URL="$MIRROR_URL/Packages/" fi echo "Fetching release rpm name from $RELEASE_URL..." # This code is mildly "brittle" in that it assumes a certain directory # page format and parsing HTML. I've done worse. :-P RELEASE_RPM=$(curl -L -f "$RELEASE_URL" | sed -e "/fedora-release-${release}-/!d" -e 's/.*.*//' ) if [ $? -ne 0 -o "${RELEASE_RPM}" = "" ]; then echo "Failed to identify fedora release rpm." continue fi echo "Fetching fedora release rpm from ${RELEASE_URL}/${RELEASE_RPM}......" curl -L -f "${RELEASE_URL}/${RELEASE_RPM}" > ${INSTALL_ROOT}/${RELEASE_RPM} if [ $? -ne 0 ]; then echo "Failed to download fedora release rpm ${RELEASE_RPM}." continue fi # F21 and newer need fedora-repos in addition to fedora-release. if [ "$release" -ge "21" ]; then echo "Fetching repos rpm name from $RELEASE_URL..." REPOS_RPM=$(curl -L -f "$RELEASE_URL" | sed -e "/fedora-repos-${release}-/!d" -e 's/.*.*//' ) if [ $? -ne 0 -o "${REPOS_RPM}" = "" ]; then echo "Failed to identify fedora repos rpm." continue fi echo "Fetching fedora repos rpm from ${RELEASE_URL}/${REPOS_RPM}..." curl -L -f "${RELEASE_URL}/${REPOS_RPM}" > ${INSTALL_ROOT}/${REPOS_RPM} if [ $? -ne 0 ]; then echo "Failed to download fedora repos rpm ${RELEASE_RPM}." continue fi fi DOWNLOAD_OK=yes break done if [ $DOWNLOAD_OK != yes ]; then echo "Aborting" return 1 fi mkdir -p ${INSTALL_ROOT}/var/lib/rpm if ! fedora_get_bootstrap then echo "Fedora Bootstrap setup failed" return 1 fi fedora_bootstrap_mounts ${BOOTSTRAP_CHROOT}rpm --root ${BOOTSTRAP_INSTALL_ROOT} --initdb # The --nodeps is STUPID but F15 had a bogus dependency on RawHide?!?! ${BOOTSTRAP_CHROOT}rpm --root ${BOOTSTRAP_INSTALL_ROOT} --nodeps -ivh ${BOOTSTRAP_INSTALL_ROOT}/${RELEASE_RPM} # F21 and newer need fedora-repos in addition to fedora-release... # Note that fedora-release and fedora-system have a mutual dependency. # So installing the reops package after the release package we can # spare one --nodeps. if [ "$release" -ge "21" ]; then ${BOOTSTRAP_CHROOT}rpm --root ${BOOTSTRAP_INSTALL_ROOT} -ivh ${BOOTSTRAP_INSTALL_ROOT}/${REPOS_RPM} fi # yum will take $basearch from host, so force the arch we want sed -i "s|\$basearch|$basearch|" ${BOOTSTRAP_DIR}/${BOOTSTRAP_INSTALL_ROOT}/etc/yum.repos.d/* ${BOOTSTRAP_CHROOT}yum --installroot ${BOOTSTRAP_INSTALL_ROOT} -y --nogpgcheck install ${PKG_LIST} RC=$? if [[ ${BOOTSTRAP} -eq 1 ]] then # Here we have a bit of a sticky problem. We MIGHT have just installed # this template cache using versions of yum and rpm in the bootstrap # chroot that use a different database version than the target version. # That can be a very big problem. Solution is to rebuild the rpmdatabase # with the target database now that we are done building the cache. In the # vast majority of cases, this is a do-not-care with no harm done if we # didn't do it. But it catches several corner cases with older unsupported # releases and it really doesn't cost us a lot of time for a one shot # install that will never be done again for this rev. # # Thanks and appreciation to Dwight Engen and the Oracle template for the # database rewrite hint! echo "Fixing up rpm databases" # Change to our target install directory (if we're not already # there) just to simplify some of the logic to follow... cd ${INSTALL_ROOT} rm -f var/lib/rpm/__db* # Programmers Note (warning): # # Pay careful attention to the following commands! It # crosses TWO chroot boundaries linked by a bind mount! # In the bootstrap case, that's the bind mount of ${INSTALL_ROOT} # to the ${BOOTSTRAP_CHROOT}/run/install directory! This is # a deliberate hack across that bind mount to do a database # translation between two environments, neither of which may # be the host environment! It's ugly and hard to follow but, # if you don't understand it, don't mess with it! The pipe # is in host space between the two chrooted environments! # This is also why we cd'ed into the INSTALL_ROOT directory # in advance of this loop, so everything is relative to the # current working directory and congruent with the same working # space in both chrooted environments. The output into the new # db is also done in INSTALL_ROOT space but works in either host # space or INSTALL_ROOT space for the mv, so we don't care. It's # just not obvious what's happening in the db_dump and db_load # commands... # for db in var/lib/rpm/* ; do ${BOOTSTRAP_CHROOT} db_dump ${BOOTSTRAP_INSTALL_ROOT}/$db | chroot . db_load $db.new mv $db.new $db done # finish up by rebuilding the database... # This should be redundant but we do it for completeness and # any corner cases I may have missed... mount -t proc proc proc mount -o bind /dev dev chroot . rpm --rebuilddb umount dev umount proc fi fedora_bootstrap_umounts if [ ${RC} -ne 0 ]; then echo "Failed to download the rootfs, aborting." return 1 fi mv "$INSTALL_ROOT" "$cache/rootfs" echo "Download complete." return 0 } copy_fedora() { # make a local copy of the minifedora echo -n "Copying rootfs to $rootfs_path ..." #cp -a $cache/rootfs-$basearch $rootfs_path || return 1 # i prefer rsync (no reason really) mkdir -p $rootfs_path rsync -Ha $cache/rootfs/ $rootfs_path/ echo return 0 } update_fedora() { mount -o bind /dev ${cache}/rootfs/dev mount -t proc proc ${cache}/rootfs/proc # Always make sure /etc/resolv.conf is up to date in the target! cp /etc/resolv.conf ${cache}/rootfs/etc/ chroot ${cache}/rootfs yum -y update umount ${cache}/rootfs/proc umount ${cache}/rootfs/dev } install_fedora() { mkdir -p @LOCALSTATEDIR@/lock/subsys/ ( flock -x 9 if [ $? -ne 0 ]; then echo "Cache repository is busy." return 1 fi echo "Checking cache download in $cache/rootfs ... " if [ ! -e "$cache/rootfs" ]; then download_fedora if [ $? -ne 0 ]; then echo "Failed to download 'fedora base'" return 1 fi else echo "Cache found. Updating..." update_fedora if [ $? -ne 0 ]; then echo "Failed to update 'fedora base', continuing with last known good cache" else echo "Update finished" fi fi echo "Copy $cache/rootfs to $rootfs_path ... " copy_fedora if [ $? -ne 0 ]; then echo "Failed to copy rootfs" return 1 fi return 0 ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-fedora return $? } # Generate a random hardware (MAC) address composed of FE followed by # 5 random bytes... create_hwaddr() { openssl rand -hex 5 | sed -e 's/\(..\)/:\1/g; s/^/fe/' } copy_configuration() { mkdir -p $config_path grep -q "^lxc.rootfs" $config_path/config 2>/dev/null || echo " lxc.rootfs = $rootfs_path " >> $config_path/config # The following code is to create static MAC addresses for each # interface in the container. This code will work for multiple # interfaces in the default config. It will also strip any # hwaddr stanzas out of the default config since we can not share # MAC addresses between containers. mv $config_path/config $config_path/config.def while read LINE do # This should catch variable expansions from the default config... if expr "${LINE}" : '.*\$' > /dev/null 2>&1 then LINE=$(eval "echo \"${LINE}\"") fi # There is a tab and a space in the regex bracket below! # Seems that \s doesn't work in brackets. KEY=$(expr "${LINE}" : '\s*\([^ ]*\)\s*=') if [[ "${KEY}" != "lxc.network.hwaddr" ]] then echo "${LINE}" >> $config_path/config if [[ "${KEY}" == "lxc.network.link" ]] then echo "lxc.network.hwaddr = $(create_hwaddr)" >> $config_path/config fi fi done < $config_path/config.def rm -f $config_path/config.def if [ -e "@LXCTEMPLATECONFIG@/fedora.common.conf" ]; then echo " # Include common configuration lxc.include = @LXCTEMPLATECONFIG@/fedora.common.conf " >> $config_path/config fi # Append things which require expansion here... cat <> $config_path/config lxc.arch = $arch lxc.utsname = $utsname # When using LXC with apparmor, uncomment the next line to run unconfined: #lxc.aa_profile = unconfined # example simple networking setup, uncomment to enable #lxc.network.type = $lxc_network_type #lxc.network.flags = up #lxc.network.link = $lxc_network_link #lxc.network.name = eth0 # Additional example for veth network type # static MAC address, #lxc.network.hwaddr = 00:16:3e:77:52:20 # persistent veth device name on host side # Note: This may potentially collide with other containers of same name! #lxc.network.veth.pair = v-$name-e0 EOF if [ $? -ne 0 ]; then echo "Failed to add configuration" return 1 fi return 0 } clean() { if [ ! -e $cache ]; then exit 0 fi # lock, so we won't purge while someone is creating a repository ( flock -x 9 if [ $? != 0 ]; then echo "Cache repository is busy." exit 1 fi echo -n "Purging the download cache for Fedora-$release..." rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1 exit 0 ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-fedora } usage() { cat < [-p|--path=] [-c|--clean] [-R|--release=] [--fqdn=] [-a|--arch=] [--mask-tmp] [-h|--help] Mandatory args: -n,--name container name, used to as an identifier for that container Optional args: -p,--path path to where the container will be created, defaults to @LXCPATH@. --rootfs path for actual rootfs. -c,--clean clean the cache -R,--release Fedora release for the new container. Defaults to host's release if the host is Fedora. --fqdn fully qualified domain name (FQDN) for DNS and system naming -a,--arch Define what arch the container will be [i686,x86_64] --mask-tmp Prevent systemd from over-mounting /tmp with tmpfs. -h,--help print this help EOF return 0 } options=$(getopt -o a:hp:n:cR: -l help,path:,rootfs:,name:,clean,release:,arch:,fqdn:,mask-tmp -- "$@") if [ $? -ne 0 ]; then usage $(basename $0) exit 1 fi arch=$(uname -m) masktmp=0 eval set -- "$options" while true do case "$1" in -h|--help) usage $0 && exit 0;; -p|--path) path=$2; shift 2;; --rootfs) rootfs_path=$2; shift 2;; -n|--name) name=$2; shift 2;; -c|--clean) clean=1; shift 1;; -R|--release) release=$2; shift 2;; -a|--arch) newarch=$2; shift 2;; --fqdn) utsname=$2; shift 2;; --mask-tmp) masktmp=1; shift 1;; --) shift 1; break ;; *) break ;; esac done if [ ! -z "$clean" -a -z "$path" ]; then clean || exit 1 exit 0 fi basearch=${arch} # Map a few architectures to their generic Fedora repository archs. # The two ARM archs are a bit of a guesstimate for the v5 and v6 # archs. V6 should have hardware floating point (Rasberry Pi). # The "arm" arch is safer (no hardware floating point). So # there may be cases where we "get it wrong" for some v6 other # than RPi. case "$arch" in i686) basearch=i386 ;; armv3l|armv4l|armv5l) basearch=arm ;; armv6l|armv7l|armv8l) basearch=armhfp ;; *) ;; esac mirrorurl="archives.fedoraproject.org::fedora-archive" case "$basearch" in ppc64|s390x) mirrorurl="archives.fedoraproject.org::fedora-secondary" ;; *) ;; esac # Somebody wants to specify an arch. This is very limited case. # i386/i586/i686 on i386/x86_64 # - or - # x86_64 on x86_64 if [ "${newarch}" != "" -a "${newarch}" != "${arch}" ] then case "${newarch}" in i386|i586|i686) if [ "${basearch}" = "i386" -o "${basearch}" = "x86_64" ] then # Make the arch a generic x86 32 bit... arch=${newarch} basearch=i386 else basearch=bad fi ;; *) basearch=bad ;; esac if [ "${basearch}" = "bad" ] then echo "You cannot build a ${newarch} Fedora container on a ${arch} host. Sorry!" exit 1 fi fi # Allow the cache base to be set by environment variable cache_base=${LXC_CACHE_PATH:-"@LOCALSTATEDIR@/cache/lxc"}/fedora/$basearch # Let's do something better for the initial root password. # It's not perfect but it will defeat common scanning brute force # attacks in the case where ssh is exposed. It will also be set to # expired, forcing the user to change it at first login. if [ "${root_password}" = "" ] then root_password=Root-${name}-${RANDOM} else # If it's got a ding in it, try and expand it! if [ $(expr "${root_password}" : '.*$.') != 0 ] then root_password=$(eval echo "${root_password}") fi # If it has more than 3 consecutive X's in it, feed it # through mktemp as a template. if [ $(expr "${root_password}" : '.*XXXX') != 0 ] then root_password=$(mktemp -u ${root_password}) fi fi if [ -z "${utsname}" ]; then utsname=${name} fi # This follows a standard "resolver" convention that an FQDN must have # at least two dots or it is considered a local relative host name. # If it doesn't, append the dns domain name of the host system. # # This changes one significant behavior when running # "lxc_create -n Container_Name" without using the # --fqdn option. # # Old behavior: # utsname and hostname = Container_Name # New behavior: # utsname and hostname = Container_Name.Domain_Name if [ $(expr "$utsname" : '.*\..*\.') = 0 ]; then if [[ "$(dnsdomainname)" != "" && "$(dnsdomainname)" != "localdomain" ]]; then utsname=${utsname}.$(dnsdomainname) fi fi needed_pkgs="" type curl >/dev/null 2>&1 if [ $? -ne 0 ]; then needed_pkgs="curl $needed_pkgs" fi type openssl >/dev/null 2>&1 if [ $? -ne 0 ]; then needed_pkgs="openssl $needed_pkgs" fi if [ -n "$needed_pkgs" ]; then echo "Missing commands: $needed_pkgs" echo "Please install these using \"sudo yum install $needed_pkgs\"" exit 1 fi if [ -z "$path" ]; then path=$default_path/$name fi if [ -z "$release" ]; then if [ "$is_fedora" -a "$fedora_host_ver" ]; then release=$fedora_host_ver else echo "This is not a fedora host and release missing, defaulting to 22 use -R|--release to specify release" release=22 fi fi if [ "$(id -u)" != "0" ]; then echo "This script should be run as 'root'" exit 1 fi if [ -z "$rootfs_path" ]; then rootfs_path=$path/rootfs # check for 'lxc.rootfs' passed in through default config by lxc-create if grep -q '^lxc.rootfs' $path/config 2>/dev/null ; then rootfs_path=$(sed -e '/^lxc.rootfs\s*=/!d' -e 's/\s*#.*//' \ -e 's/^lxc.rootfs\s*=\s*//' -e q $path/config) fi fi config_path=$path cache=$cache_base/$release revert() { echo "Interrupted, so cleaning up" lxc-destroy -n $name # maybe was interrupted before copy config rm -rf $path echo "exiting..." exit 1 } trap revert SIGHUP SIGINT SIGTERM copy_configuration if [ $? -ne 0 ]; then echo "failed write configuration file" exit 1 fi install_fedora if [ $? -ne 0 ]; then echo "failed to install fedora" exit 1 fi configure_fedora if [ $? -ne 0 ]; then echo "failed to configure fedora for a container" exit 1 fi # If the systemd configuration directory exists - set it up for what we need. if [ -d ${rootfs_path}/etc/systemd/system ] then configure_fedora_systemd fi # This configuration (rc.sysinit) is not inconsistent with the systemd stuff # above and may actually coexist on some upgraded systems. Let's just make # sure that, if it exists, we update this file, even if it's not used... if [ -f ${rootfs_path}/etc/rc.sysinit ] then configure_fedora_init fi if [ ! -z "$clean" ]; then clean || exit 1 exit 0 fi echo " Container rootfs and config have been created. Edit the config file to check/enable networking setup. " if [[ -d ${cache_base}/bootstrap ]] then echo "You have successfully built a Fedora container and cache. This cache may be used to create future containers of various revisions. The directory ${cache_base}/bootstrap contains a bootstrap which may no longer needed and can be removed. " fi if [[ -e ${cache_base}/LiveOS ]] then echo "A LiveOS directory exists at ${cache_base}/LiveOS. This is only used in the creation of the bootstrap run-time-environment and may be removed. " fi if [ ${root_display_password} = "yes" ] then echo "The temporary password for root is: '$root_password' You may want to note that password down before starting the container. " fi if [ ${root_store_password} = "yes" ] then echo "The temporary root password is stored in: '${config_path}/tmp_root_pass' " fi if [ ${root_prompt_password} = "yes" ] then echo "Invoking the passwd command in the container to set the root password. chroot ${rootfs_path} passwd " chroot ${rootfs_path} passwd else if [ ${root_expire_password} = "yes" ] then if ( mountpoint -q -- "${rootfs_path}" ) then echo "To reset the root password, you can do: lxc-start -n ${name} lxc-attach -n ${name} -- passwd lxc-stop -n ${name} " else echo " The root password is set up as "expired" and will require it to be changed at first login, which you should do as soon as possible. If you lose the root password or wish to change it without starting the container, you can change it from the host by running the following command (which will also reset the expired flag): chroot ${rootfs_path} passwd " fi fi fi lxc-2.0.8/templates/lxc-centos.in0000644061062106075000000007205413105116772013660 00000000000000#!/bin/bash # # template script for generating CentOS container for LXC # # lxc: linux Container library # Authors: # Daniel Lezcano # Ramez Hanna # Fajar A. Nugraha # Michael H. Warfield # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #Configurations default_path=@LXCPATH@ # Some combinations of the tuning knobs below do not exactly make sense. # but that's ok. # # If the "root_password" is non-blank, use it, else set a default. # This can be passed to the script as an environment variable and is # set by a shell conditional assignment. Looks weird but it is what it is. # # If the root password contains a ding ($) then try to expand it. # That will pick up things like ${name} and ${RANDOM}. # If the root password contains more than 3 consecutive X's, pass it as # a template to mktemp and take the result. # # If root_display_password = yes, display the temporary root password at exit. # If root_store_password = yes, store it in the configuration directory # If root_prompt_password = yes, invoke "passwd" to force the user to change # the root password after the container is created. # If root_expire_password = yes, you will be prompted to change the root # password at the first login. # # These are conditional assignments... The can be overridden from the # preexisting environment variables... # # Make sure this is in single quotes to defer expansion to later! # :{root_password='Root-${name}-${RANDOM}'} : ${root_password='Root-${name}-XXXXXX'} # Now, it doesn't make much sense to display, store, and force change # together. But, we gotta test, right??? : ${root_display_password='no'} : ${root_store_password='yes'} # Prompting for something interactive has potential for mayhem # with users running under the API... Don't default to "yes" : ${root_prompt_password='no'} # Expire root password? Default to yes, but can be overridden from # the environment variable : ${root_expire_password='yes'} # These are only going into comments in the resulting config... lxc_network_type=veth lxc_network_link=lxcbr0 # is this CentOS? # Alow for weird remixes like the Raspberry Pi # # Use the Mitre standard CPE identifier for the release ID if possible... # This may be in /etc/os-release or /etc/system-release-cpe. We # should be able to use EITHER. Give preference to /etc/os-release for now. # Detect use under userns (unsupported) for arg in "$@"; do [ "$arg" = "--" ] && break if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then echo "This template can't be used for unprivileged containers." 1>&2 echo "You may want to try the \"download\" template instead." 1>&2 exit 1 fi done # Make sure the usual locations are in PATH export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin if [ -e /etc/os-release ] then # This is a shell friendly configuration file. We can just source it. # What we're looking for in here is the ID, VERSION_ID and the CPE_NAME . /etc/os-release echo "Host CPE ID from /etc/os-release: ${CPE_NAME}" fi if [ "${CPE_NAME}" = "" -a -e /etc/system-release-cpe ] then CPE_NAME=$(head -n1 /etc/system-release-cpe) CPE_URI=$(expr ${CPE_NAME} : '\([^:]*:[^:]*\)') if [ "${CPE_URI}" != "cpe:/o" ] then CPE_NAME= else # Probably a better way to do this but sill remain posix # compatible but this works, shrug... # Must be nice and not introduce convenient bashisms here. # # According to the official registration at Mitre and NIST, # this should have been something like this for CentOS: # cpe:/o:centos:centos:6 # or this: # cpe:/o:centos:centos:6.5 # ID=$(expr ${CPE_NAME} : '[^:]*:[^:]*:[^:]*:\([^:]*\)') # The "enterprise_linux" is a bone toss back to RHEL. # Since CentOS and RHEL are so tightly coupled, we'll # take the RHEL version if we're running on it and do the # equivalent version for CentOS. if [ ${ID} = "linux" -o ${ID} = "enterprise_linux" ] then # Instead we got this: cpe:/o:centos:linux:6 ID=$(expr ${CPE_NAME} : '[^:]*:[^:]*:\([^:]*\)') fi VERSION_ID=$(expr ${CPE_NAME} : '[^:]*:[^:]*:[^:]*:[^:]*:\([^:]*\)') echo "Host CPE ID from /etc/system-release-cpe: ${CPE_NAME}" fi fi if [ "${CPE_NAME}" != "" -a "${ID}" = "centos" -a "${VERSION_ID}" != "" ] then centos_host_ver=${VERSION_ID} is_centos=true elif [ "${CPE_NAME}" != "" -a "${ID}" = "redhat" -o "${ID}" = "rhel" -a "${VERSION_ID}" != "" ] then # RHEL 7+ /etc/os-release ID = 'rhel', which doesn't enter this elif without the added OR statement redhat_host_ver=${VERSION_ID} is_redhat=true elif [ -e /etc/centos-release ] then # Only if all other methods fail, try to parse the redhat-release file. centos_host_ver=$( sed -e '/^CentOS /!d' -e 's/CentOS.*\srelease\s*\([0-9][0-9.]*\)\s.*/\1/' < /etc/centos-release ) if [ "$centos_host_ver" != "" ] then is_centos=true fi fi force_mknod() { # delete a device node if exists, and create a new one rm -f $2 && mknod -m $1 $2 $3 $4 $5 } configure_centos() { # disable selinux in CentOS mkdir -p $rootfs_path/selinux echo 0 > $rootfs_path/selinux/enforce # Also kill it in the /etc/selinux/config file if it's there... if [ -f $rootfs_path/etc/selinux/config ] then sed -i '/^SELINUX=/s/.*/SELINUX=disabled/' $rootfs_path/etc/selinux/config fi # Nice catch from Dwight Engen in the Oracle template. # Wantonly plagerized here with much appreciation. if [ -f $rootfs_path/usr/sbin/selinuxenabled ]; then mv $rootfs_path/usr/sbin/selinuxenabled $rootfs_path/usr/sbin/selinuxenabled.lxcorig ln -s /bin/false $rootfs_path/usr/sbin/selinuxenabled fi # This is a known problem and documented in RedHat bugzilla as relating # to a problem with auditing enabled. This prevents an error in # the container "Cannot make/remove an entry for the specified session" sed -i '/^session.*pam_loginuid.so/s/^session/# session/' ${rootfs_path}/etc/pam.d/login sed -i '/^session.*pam_loginuid.so/s/^session/# session/' ${rootfs_path}/etc/pam.d/sshd if [ -f ${rootfs_path}/etc/pam.d/crond ] then sed -i '/^session.*pam_loginuid.so/s/^session/# session/' ${rootfs_path}/etc/pam.d/crond fi # In addition to disabling pam_loginuid in the above config files # we'll also disable it by linking it to pam_permit to catch any # we missed or any that get installed after the container is built. # # Catch either or both 32 and 64 bit archs. if [ -f ${rootfs_path}/lib/security/pam_loginuid.so ] then ( cd ${rootfs_path}/lib/security/ mv pam_loginuid.so pam_loginuid.so.disabled ln -s pam_permit.so pam_loginuid.so ) fi if [ -f ${rootfs_path}/lib64/security/pam_loginuid.so ] then ( cd ${rootfs_path}/lib64/security/ mv pam_loginuid.so pam_loginuid.so.disabled ln -s pam_permit.so pam_loginuid.so ) fi # Set default localtime to the host localtime if not set... if [ -e /etc/localtime -a ! -e ${rootfs_path}/etc/localtime ] then # if /etc/localtime is a symlink, this should preserve it. cp -a /etc/localtime ${rootfs_path}/etc/localtime fi # Deal with some dain bramage in the /etc/init.d/halt script. # Trim it and make it our own and link it in before the default # halt script so we can intercept it. This also preventions package # updates from interferring with our interferring with it. # # There's generally not much in the halt script that useful but what's # in there from resetting the hardware clock down is generally very bad. # So we just eliminate the whole bottom half of that script in making # ourselves a copy. That way a major update to the init scripts won't # trash what we've set up. if [ -f ${rootfs_path}/etc/init.d/halt ] then sed -e '/hwclock/,$d' \ < ${rootfs_path}/etc/init.d/halt \ > ${rootfs_path}/etc/init.d/lxc-halt echo '$command -f' >> ${rootfs_path}/etc/init.d/lxc-halt chmod 755 ${rootfs_path}/etc/init.d/lxc-halt # Link them into the rc directories... ( cd ${rootfs_path}/etc/rc.d/rc0.d ln -s ../init.d/lxc-halt S00lxc-halt cd ${rootfs_path}/etc/rc.d/rc6.d ln -s ../init.d/lxc-halt S00lxc-reboot ) fi # configure the network using the dhcp cat < ${rootfs_path}/etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 BOOTPROTO=dhcp ONBOOT=yes HOSTNAME=${utsname} NM_CONTROLLED=no TYPE=Ethernet MTU=${MTU} DHCP_HOSTNAME=\`hostname\` EOF # set the hostname cat < ${rootfs_path}/etc/sysconfig/network NETWORKING=yes HOSTNAME=${utsname} EOF # set minimal hosts cat < $rootfs_path/etc/hosts 127.0.0.1 localhost $name EOF # set minimal fstab cat < $rootfs_path/etc/fstab /dev/root / rootfs defaults 0 0 EOF # create lxc compatibility init script if [ "$release" = "6" ]; then cat < $rootfs_path/etc/init/lxc-sysinit.conf start on startup env container pre-start script if [ "x\$container" != "xlxc" -a "x\$container" != "xlibvirt" ]; then stop; fi rm -f /var/lock/subsys/* rm -f /var/run/*.pid [ -e /etc/mtab ] || ln -s /proc/mounts /etc/mtab mkdir -p /dev/shm mount -t tmpfs -o nosuid,nodev tmpfs /dev/shm initctl start tty TTY=console telinit 3 exit 0 end script EOF elif [ "$release" = "5" ]; then cat < $rootfs_path/etc/rc.d/lxc.sysinit #! /bin/bash rm -f /etc/mtab /var/run/*.{pid,lock} /var/lock/subsys/* rm -rf {/,/var}/tmp/* echo "/dev/root / rootfs defaults 0 0" > /etc/mtab exit 0 EOF chmod 755 $rootfs_path/etc/rc.d/lxc.sysinit sed -i 's|si::sysinit:/etc/rc.d/rc.sysinit|si::bootwait:/etc/rc.d/lxc.sysinit|' $rootfs_path/etc/inittab # 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|^1:|co:2345:respawn:/sbin/mingetty --nohangup console\n1:|' $rootfs_path/etc/inittab sed -i 's|^\([56]:\)|#\1|' $rootfs_path/etc/inittab fi dev_path="${rootfs_path}/dev" rm -rf $dev_path mkdir -p $dev_path mknod -m 666 ${dev_path}/null c 1 3 mknod -m 666 ${dev_path}/zero c 1 5 mknod -m 666 ${dev_path}/random c 1 8 mknod -m 666 ${dev_path}/urandom c 1 9 mkdir -m 755 ${dev_path}/pts mkdir -m 1777 ${dev_path}/shm mknod -m 666 ${dev_path}/tty c 5 0 mknod -m 666 ${dev_path}/tty0 c 4 0 mknod -m 666 ${dev_path}/tty1 c 4 1 mknod -m 666 ${dev_path}/tty2 c 4 2 mknod -m 666 ${dev_path}/tty3 c 4 3 mknod -m 666 ${dev_path}/tty4 c 4 4 mknod -m 600 ${dev_path}/console c 5 1 mknod -m 666 ${dev_path}/full c 1 7 mknod -m 600 ${dev_path}/initctl p mknod -m 666 ${dev_path}/ptmx c 5 2 # setup console and tty[1-4] for login. note that /dev/console and # /dev/tty[1-4] will be symlinks to the ptys /dev/lxc/console and # /dev/lxc/tty[1-4] so that package updates can overwrite the symlinks. # lxc will maintain these links and bind mount ptys over /dev/lxc/* # since lxc.devttydir is specified in the config. # allow root login on console, tty[1-4], and pts/0 for libvirt echo "# LXC (Linux Containers)" >>${rootfs_path}/etc/securetty echo "lxc/console" >>${rootfs_path}/etc/securetty echo "lxc/tty1" >>${rootfs_path}/etc/securetty echo "lxc/tty2" >>${rootfs_path}/etc/securetty echo "lxc/tty3" >>${rootfs_path}/etc/securetty echo "lxc/tty4" >>${rootfs_path}/etc/securetty echo "# For libvirt/Virtual Machine Monitor" >>${rootfs_path}/etc/securetty echo "pts/0" >>${rootfs_path}/etc/securetty # 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|' $rootfs_path/etc/init/tty.conf if [ ${root_display_password} = "yes" ] then echo "Setting root password to '$root_password'" fi if [ ${root_store_password} = "yes" ] then touch ${config_path}/tmp_root_pass chmod 600 ${config_path}/tmp_root_pass echo ${root_password} > ${config_path}/tmp_root_pass echo "Storing root password in '${config_path}/tmp_root_pass'" fi echo "root:$root_password" | chroot $rootfs_path chpasswd if [ ${root_expire_password} = "yes" ] then # Also set this password as expired to force the user to change it! chroot $rootfs_path passwd -e root fi # This will need to be enhanced for CentOS 7 when systemd # comes into play... /\/\|=mhw=|\/\/ return 0 } configure_centos_init() { sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc/rc.sysinit sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc/rc.d/rc.sysinit if [ "$release" = "6" ]; then chroot ${rootfs_path} chkconfig udev-post off fi chroot ${rootfs_path} chkconfig network on if [ -d ${rootfs_path}/etc/init ] then # This is to make upstart honor SIGPWR cat <${rootfs_path}/etc/init/power-status-changed.conf # power-status-changed - shutdown on SIGPWR # start on power-status-changed exec /sbin/shutdown -h now "SIGPWR received" EOF fi } download_centos() { # check the mini CentOS was not already downloaded INSTALL_ROOT=$cache/partial mkdir -p $INSTALL_ROOT if [ $? -ne 0 ]; then echo "Failed to create '$INSTALL_ROOT' directory" return 1 fi # download a mini CentOS into a cache echo "Downloading CentOS minimal ..." YUM0="yum --installroot $INSTALL_ROOT -y --nogpgcheck" if yum -h | grep -q 'releasever=RELEASEVER'; then YUM="$YUM0 --releasever=$release" else YUM="$YUM0" fi PKG_LIST="yum initscripts passwd rsyslog vim-minimal openssh-server openssh-clients dhclient chkconfig rootfiles policycoreutils" # use temporary repository definition REPO_FILE=$INSTALL_ROOT/etc/yum.repos.d/lxc-centos-temp.repo mkdir -p $(dirname $REPO_FILE) if [ -n "$repo" ]; then cat < $REPO_FILE [base] name=local repository baseurl="$repo" EOF else cat < $REPO_FILE [base] name=CentOS-$release - Base mirrorlist=http://mirrorlist.centos.org/?release=$release&arch=$basearch&repo=os [updates] name=CentOS-$release - Updates mirrorlist=http://mirrorlist.centos.org/?release=$release&arch=$basearch&repo=updates EOF fi # create minimal device nodes, needed for "yum install" and "yum update" process mkdir -p $INSTALL_ROOT/dev force_mknod 666 $INSTALL_ROOT/dev/null c 1 3 force_mknod 666 $INSTALL_ROOT/dev/urandom c 1 9 $YUM install $PKG_LIST # create symlink for /var/run -> ../run if [ "$release" = "7" ]; then mv $INSTALL_ROOT/var/run/* $INSTALL_ROOT/run/ rmdir $INSTALL_ROOT/var/run ln -sf ../run $INSTALL_ROOT/var/run fi if [ $? -ne 0 ]; then echo "Failed to download the rootfs, aborting." return 1 fi # use same nameservers as hosts, needed for "yum update later" cp /etc/resolv.conf $INSTALL_ROOT/etc/ # check whether rpmdb is under $HOME if [ ! -e $INSTALL_ROOT/var/lib/rpm/Packages -a -e $INSTALL_ROOT/$HOME/.rpmdb/Packages ]; then echo "Fixing rpmdb location ..." mv $INSTALL_ROOT/$HOME/.rpmdb/[A-Z]* $INSTALL_ROOT/var/lib/rpm/ rm -rf $INSTALL_ROOT/$HOME/.rpmdb chroot $INSTALL_ROOT rpm --rebuilddb 2>/dev/null fi # check whether rpmdb version is correct chroot $INSTALL_ROOT rpm --quiet -q yum 2>/dev/null ret=$? # if "rpm -q" doesn't work due to rpmdb version difference, # then we need to redo the process using the newly-installed yum if [ $ret -gt 0 ]; then echo "Reinstalling packages ..." mv $REPO_FILE $REPO_FILE.tmp mkdir $INSTALL_ROOT/etc/yum.repos.disabled mv $INSTALL_ROOT/etc/yum.repos.d/*.repo $INSTALL_ROOT/etc/yum.repos.disabled/ mv $REPO_FILE.tmp $REPO_FILE mkdir -p $INSTALL_ROOT/$INSTALL_ROOT/etc cp /etc/resolv.conf $INSTALL_ROOT/$INSTALL_ROOT/etc/ mkdir -p $INSTALL_ROOT/$INSTALL_ROOT/dev mknod -m 666 $INSTALL_ROOT/$INSTALL_ROOT/dev/null c 1 3 mknod -m 666 $INSTALL_ROOT/$INSTALL_ROOT/dev/urandom c 1 9 mkdir -p $INSTALL_ROOT/$INSTALL_ROOT/var/cache/yum cp -al $INSTALL_ROOT/var/cache/yum/* $INSTALL_ROOT/$INSTALL_ROOT/var/cache/yum/ chroot $INSTALL_ROOT $YUM0 install $PKG_LIST if [ $? -ne 0 ]; then echo "Failed to download the rootfs, aborting." return 1 fi mv $INSTALL_ROOT/$INSTALL_ROOT $INSTALL_ROOT.tmp rm -rf $INSTALL_ROOT mv $INSTALL_ROOT.tmp $INSTALL_ROOT fi rm -f $REPO_FILE rm -rf $INSTALL_ROOT/var/cache/yum/* mv "$INSTALL_ROOT" "$cache/rootfs" echo "Download complete." return 0 } copy_centos() { # make a local copy of the mini CentOS echo -n "Copying rootfs to $rootfs_path ..." #cp -a $cache/rootfs-$arch $rootfs_path || return 1 # i prefer rsync (no reason really) mkdir -p $rootfs_path rsync -a $cache/rootfs/ $rootfs_path/ echo return 0 } update_centos() { YUM="chroot $cache/rootfs yum -y --nogpgcheck" $YUM update if [ $? -ne 0 ]; then return 1 fi $YUM clean packages } install_centos() { mkdir -p /var/lock/subsys/ ( flock -x 9 if [ $? -ne 0 ]; then echo "Cache repository is busy." return 1 fi echo "Checking cache download in $cache/rootfs ... " if [ ! -e "$cache/rootfs" ]; then download_centos if [ $? -ne 0 ]; then echo "Failed to download 'CentOS base'" return 1 fi else echo "Cache found. Updating..." update_centos if [ $? -ne 0 ]; then echo "Failed to update 'CentOS base', continuing with last known good cache" else echo "Update finished" fi fi echo "Copy $cache/rootfs to $rootfs_path ... " copy_centos if [ $? -ne 0 ]; then echo "Failed to copy rootfs" return 1 fi return 0 ) 9>/var/lock/subsys/lxc-centos return $? } create_hwaddr() { openssl rand -hex 5 | sed -e 's/\(..\)/:\1/g; s/^/fe/' } copy_configuration() { mkdir -p $config_path grep -q "^lxc.rootfs" $config_path/config 2>/dev/null || echo " lxc.rootfs = $rootfs_path " >> $config_path/config # The following code is to create static MAC addresses for each # interface in the container. This code will work for multiple # interfaces in the default config. mv $config_path/config $config_path/config.def while read LINE do # This should catch variable expansions from the default config... if expr "${LINE}" : '.*\$' > /dev/null 2>&1 then LINE=$(eval "echo \"${LINE}\"") fi # There is a tab and a space in the regex bracket below! # Seems that \s doesn't work in brackets. KEY=$(expr "${LINE}" : '\s*\([^ ]*\)\s*=') if [[ "${KEY}" != "lxc.network.hwaddr" ]] then echo ${LINE} >> $config_path/config if [[ "${KEY}" == "lxc.network.link" ]] then echo "lxc.network.hwaddr = $(create_hwaddr)" >> $config_path/config fi fi done < $config_path/config.def rm -f $config_path/config.def if [ -e "@LXCTEMPLATECONFIG@/centos.common.conf" ]; then echo " # Include common configuration lxc.include = @LXCTEMPLATECONFIG@/centos.common.conf " >> $config_path/config fi # Append things which require expansion here... cat <> $config_path/config lxc.arch = $arch lxc.utsname = $utsname # When using LXC with apparmor, uncomment the next line to run unconfined: #lxc.aa_profile = unconfined # example simple networking setup, uncomment to enable #lxc.network.type = $lxc_network_type #lxc.network.flags = up #lxc.network.link = $lxc_network_link #lxc.network.name = eth0 # Additional example for veth network type # static MAC address, #lxc.network.hwaddr = 00:16:3e:77:52:20 # persistent veth device name on host side # Note: This may potentially collide with other containers of same name! #lxc.network.veth.pair = v-$name-e0 EOF if [ $? -ne 0 ]; then echo "Failed to add configuration" return 1 fi return 0 } clean() { if [ ! -e $cache ]; then exit 0 fi # lock, so we won't purge while someone is creating a repository ( flock -x 9 if [ $? != 0 ]; then echo "Cache repository is busy." exit 1 fi echo -n "Purging the download cache for CentOS-$release..." rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1 exit 0 ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-centos } usage() { cat < [-p|--path=] [-c|--clean] [-R|--release=] [-a|--arch=] [-h|--help] Mandatory args: -n,--name container name, used to as an identifier for that container from now on Optional args: -p,--path path to where the container rootfs will be created, defaults to /var/lib/lxc/name. -c,--clean clean the cache -R,--release CentOS release for the new container. If the host is CentOS, then it will default to the host's release. --fqdn fully qualified domain name (FQDN) for DNS and system naming --repo repository to use (url) -a,--arch Define what arch the container will be [i686,x86_64] -h,--help print this help EOF return 0 } options=$(getopt -o a:hp:n:cR: -l help,path:,rootfs:,name:,clean,release:,repo:,arch:,fqdn: -- "$@") if [ $? -ne 0 ]; then usage $(basename $0) exit 1 fi arch=$(uname -m) eval set -- "$options" while true do case "$1" in -h|--help) usage $0 && exit 0;; -p|--path) path=$2; shift 2;; --rootfs) rootfs_path=$2; shift 2;; -n|--name) name=$2; shift 2;; -c|--clean) clean=1; shift 1;; -R|--release) release=$2; shift 2;; --repo) repo="$2"; shift 2;; -a|--arch) newarch=$2; shift 2;; --fqdn) utsname=$2; shift 2;; --) shift 1; break ;; *) break ;; esac done if [ ! -z "$clean" -a -z "$path" ]; then clean || exit 1 exit 0 fi basearch=${arch} # Map a few architectures to their generic CentOS repository archs. # The two ARM archs are a bit of a guesstimate for the v5 and v6 # archs. V6 should have hardware floating point (Rasberry Pi). # The "arm" arch is safer (no hardware floating point). So # there may be cases where we "get it wrong" for some v6 other # than RPi. case "$arch" in i686) basearch=i386 ;; armv3l|armv4l|armv5l) basearch=arm ;; armv6l|armv7l|armv8l) basearch=armhfp ;; *) ;; esac # Somebody wants to specify an arch. This is very limited case. # i386/i586/i686 on i386/x86_64 # - or - # x86_64 on x86_64 if [ "${newarch}" != "" -a "${newarch}" != "${arch}" ] then case "${newarch}" in i386|i586|i686) if [ "${basearch}" = "i386" -o "${basearch}" = "x86_64" ] then # Make the arch a generic x86 32 bit... arch=${newarch} basearch=i386 else basearch=bad fi ;; *) basearch=bad ;; esac if [ "${basearch}" = "bad" ] then echo "You cannot build a ${newarch} CentOS container on a ${arch} host. Sorry!" exit 1 fi fi # Allow the cache base to be set by environment variable cache_base=${LXC_CACHE_PATH:-"@LOCALSTATEDIR@/cache/lxc"}/centos/$basearch # Let's do something better for the initial root password. # It's not perfect but it will defeat common scanning brute force # attacks in the case where ssh is exposed. It will also be set to # expired, forcing the user to change it at first login. if [ "${root_password}" = "" ] then root_password=Root-${name}-${RANDOM} else # If it's got a ding in it, try and expand it! if [ $(expr "${root_password}" : '.*$.') != 0 ] then root_password=$(eval echo "${root_password}") fi # If it has more than 3 consecutive X's in it, feed it # through mktemp as a template. if [ $(expr "${root_password}" : '.*XXXX') != 0 ] then root_password=$(mktemp -u ${root_password}) fi fi if [ -z "${utsname}" ]; then utsname=${name} fi # This follows a standard "resolver" convention that an FQDN must have # at least two dots or it is considered a local relative host name. # If it doesn't, append the dns domain name of the host system. # # This changes one significant behavior when running # "lxc_create -n Container_Name" without using the # --fqdn option. # # Old behavior: # utsname and hostname = Container_Name # New behavior: # utsname and hostname = Container_Name.Domain_Name if [ $(expr "$utsname" : '.*\..*\.') = 0 ]; then if [[ "$(dnsdomainname)" != "" && "$(dnsdomainname)" != "localdomain" ]]; then utsname=${utsname}.$(dnsdomainname) fi fi type yum >/dev/null 2>&1 if [ $? -ne 0 ]; then echo "'yum' command is missing" exit 1 fi if [ -z "$path" ]; then path=$default_path/$name fi if [ -z "$release" ]; then if [ "$is_centos" -a "$centos_host_ver" ]; then release=$centos_host_ver elif [ "$is_redhat" -a "$redhat_host_ver" ]; then # This is needed to clean out bullshit like 6workstation and 6server. release=$(expr $redhat_host_ver : '\([0-9.]*\)') else echo "This is not a CentOS or Redhat host and release is missing, defaulting to 6 use -R|--release to specify release" release=6 fi fi if [ "$(id -u)" != "0" ]; then echo "This script should be run as 'root'" exit 1 fi if [ -z "$rootfs_path" ]; then rootfs_path=$path/rootfs # check for 'lxc.rootfs' passed in through default config by lxc-create if grep -q '^lxc.rootfs' $path/config 2>/dev/null ; then rootfs_path=$(sed -e '/^lxc.rootfs\s*=/!d' -e 's/\s*#.*//' \ -e 's/^lxc.rootfs\s*=\s*//' -e q $path/config) fi fi config_path=$path cache=$cache_base/$release revert() { echo "Interrupted, so cleaning up" lxc-destroy -n $name # maybe was interrupted before copy config rm -rf $path echo "exiting..." exit 1 } trap revert SIGHUP SIGINT SIGTERM copy_configuration if [ $? -ne 0 ]; then echo "failed write configuration file" exit 1 fi install_centos if [ $? -ne 0 ]; then echo "failed to install CentOS" exit 1 fi configure_centos if [ $? -ne 0 ]; then echo "failed to configure CentOS for a container" exit 1 fi configure_centos_init if [ ! -z "$clean" ]; then clean || exit 1 exit 0 fi echo " Container rootfs and config have been created. Edit the config file to check/enable networking setup. " if [ ${root_display_password} = "yes" ] then echo "The temporary password for root is: '$root_password' You may want to note that password down before starting the container. " fi if [ ${root_store_password} = "yes" ] then echo "The temporary root password is stored in: '${config_path}/tmp_root_pass' " fi if [ ${root_prompt_password} = "yes" ] then echo "Invoking the passwd command in the container to set the root password. chroot ${rootfs_path} passwd " chroot ${rootfs_path} passwd else if [ ${root_expire_password} = "yes" ] then if ( mountpoint -q -- "${rootfs_path}" ) then echo "To reset the root password, you can do: lxc-start -n ${name} lxc-attach -n ${name} -- passwd lxc-stop -n ${name} " else echo " The root password is set up as "expired" and will require it to be changed at first login, which you should do as soon as possible. If you lose the root password or wish to change it without starting the container, you can change it from the host by running the following command (which will also reset the expired flag): chroot ${rootfs_path} passwd " fi fi fi lxc-2.0.8/templates/lxc-slackware.in0000644061062106075000000004522613105116772014342 00000000000000#!/bin/bash # # lxc: linux Container library # Authors: # Daniel Lezcano # Template for slackware by Matteo Bernardini # some parts are taken from the debian one (used as model) # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Detect use under userns (unsupported) for arg in "$@"; do [ "$arg" = "--" ] && break if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then echo "This template can't be used for unprivileged containers." 1>&2 echo "You may want to try the \"download\" template instead." 1>&2 exit 1 fi done # Add some directories to PATH in case we create containers with sudo export PATH=/sbin:/usr/sbin:$PATH cache=${cache:-/var/cache/lxc/slackware} # Use the primary Slackware site by default, but please consider changing # this to a closer mirror site. MIRROR=${MIRROR:-http://ftp.slackware.com/pub/slackware} if [ -z "$arch" ]; then case "$( uname -m )" in i?86) arch=i486 ;; arm*) arch=arm ;; *) arch=$( uname -m ) ;; esac fi LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@" configure_slackware() { rootfs=$1 hostname=$2 echo "Configuring..." ; echo # The next part contains excerpts taken from SeTconfig (written by # Patrick Volkerding) from the slackware setup disk. # But before pasting them just set a variable to use them as they are T_PX=$rootfs ( cd $T_PX ; chmod 755 ./ ) ( cd $T_PX ; chmod 755 ./var ) if [ -d $T_PX/usr/src/linux ]; then chmod 755 $T_PX/usr/src/linux fi if [ ! -d $T_PX/proc ]; then mkdir $T_PX/proc chown root.root $T_PX/proc fi if [ ! -d $T_PX/sys ]; then mkdir $T_PX/sys chown root.root $T_PX/sys fi chmod 1777 $T_PX/tmp if [ ! -d $T_PX/var/spool/mail ]; then mkdir -p $T_PX/var/spool/mail chmod 755 $T_PX/var/spool chown root.mail $T_PX/var/spool/mail chmod 1777 $T_PX/var/spool/mail fi echo "#!/bin/sh" > $T_PX/etc/rc.d/rc.keymap echo "# Load the keyboard map. More maps are in /usr/share/kbd/keymaps." \ >> $T_PX/etc/rc.d/rc.keymap echo "if [ -x /usr/bin/loadkeys ]; then" >> $T_PX/etc/rc.d/rc.keymap echo " /usr/bin/loadkeys us" >> $T_PX/etc/rc.d/rc.keymap echo "fi" >> $T_PX/etc/rc.d/rc.keymap chmod 755 $T_PX/etc/rc.d/rc.keymap # Network configuration is left to the user, that have to edit # /etc/rc.d/rc.inet1.conf and /etc/resolv.conf of the container # just set the hostname cat < $rootfs/etc/HOSTNAME $hostname.example.net EOF cp $rootfs/etc/HOSTNAME $rootfs/etc/hostname # make needed devices, from Chris Willing's MAKEDEV.sh # http://www.vislab.uq.edu.au/howto/lxc/MAKEDEV.sh DEV=$rootfs/dev mkdir -p ${DEV} mknod -m 666 ${DEV}/null c 1 3 mknod -m 666 ${DEV}/zero c 1 5 mknod -m 666 ${DEV}/random c 1 8 mknod -m 666 ${DEV}/urandom c 1 9 mkdir -m 755 ${DEV}/pts mkdir -m 1777 ${DEV}/shm mknod -m 666 ${DEV}/tty c 5 0 mknod -m 600 ${DEV}/console c 5 1 mknod -m 666 ${DEV}/tty0 c 4 0 mknod -m 666 ${DEV}/tty1 c 4 1 mknod -m 666 ${DEV}/tty2 c 4 2 mknod -m 666 ${DEV}/tty3 c 4 3 mknod -m 666 ${DEV}/tty4 c 4 4 mknod -m 666 ${DEV}/tty5 c 4 5 mknod -m 666 ${DEV}/full c 1 7 mknod -m 600 ${DEV}/initctl p mknod -m 660 ${DEV}/loop0 b 7 0 mknod -m 660 ${DEV}/loop1 b 7 1 ln -s pts/ptmx ${DEV}/ptmx ln -s /proc/self/fd ${DEV}/fd echo "Adding an etc/fstab" cat >$rootfs/etc/fstab <$rootfs/tmp/rcs.patch <<'EOF' --- ./etc/rc.orig/rc.6 2012-08-15 01:03:12.000000000 +0200 +++ ./etc/rc.d/rc.6 2013-02-17 10:26:30.888839354 +0100 @@ -9,6 +9,12 @@ # Author: Miquel van Smoorenburg # Modified by: Patrick J. Volkerding, # +# minor tweaks for an lxc container +# by Matteo Bernardini , +# based also on Chris Willing's modifications +# http://www.vislab.uq.edu.au/howto/lxc/rc.6 +# a check for a container variable is made to jump sections +container="lxc" # Set the path. PATH=/sbin:/etc:/bin:/usr/bin @@ -37,6 +43,9 @@ ;; esac +# lxc container check +if [ ! $container = "lxc" ]; then + # Save the system time to the hardware clock using hwclock --systohc. if [ -x /sbin/hwclock ]; then # Check for a broken motherboard RTC clock (where ioports for rtc are @@ -53,6 +62,8 @@ fi fi +fi # end container check + # Run any local shutdown scripts: if [ -x /etc/rc.d/rc.local_shutdown ]; then /etc/rc.d/rc.local_shutdown stop @@ -148,6 +159,9 @@ sleep 2 fi +# lxc container check +if [ ! $container = "lxc" ]; then + # Shut down PCMCIA devices: if [ -x /etc/rc.d/rc.pcmcia ]; then . /etc/rc.d/rc.pcmcia stop @@ -155,11 +169,16 @@ /bin/sleep 5 fi +fi # end container check + # Turn off process accounting: if [ -x /sbin/accton -a -r /var/log/pacct ]; then /sbin/accton off fi +# lxc container check +if [ ! $container = "lxc" ]; then + # Terminate acpid before syslog: if [ -x /etc/rc.d/rc.acpid -a -r /var/run/acpid.pid ]; then # quit . /etc/rc.d/rc.acpid stop @@ -170,6 +189,8 @@ sh /etc/rc.d/rc.udev force-stop fi +fi # end container check + # Kill all remaining processes. if [ ! "$1" = "fast" ]; then echo "Sending all processes the SIGTERM signal." @@ -179,6 +200,9 @@ /sbin/killall5 -9 fi +# lxc container check +if [ ! $container = "lxc" ]; then + # Try to turn off quota. if /bin/grep -q quota /etc/fstab ; then if [ -x /sbin/quotaoff ]; then @@ -187,6 +211,8 @@ fi fi +fi # end container check + # Carry a random seed between reboots. echo "Saving random seed from /dev/urandom in /etc/random-seed." # Use the pool size from /proc, or 512 bytes: @@ -205,6 +231,9 @@ rm -f /var/lock/subsys/* fi +# lxc container check +if [ ! $container = "lxc" ]; then + # Turn off swap: echo "Turning off swap." /sbin/swapoff -a @@ -216,6 +245,8 @@ echo "Remounting root filesystem read-only." /bin/mount -v -n -o remount,ro / +fi # end container check + # This never hurts: /bin/sync @@ -240,12 +271,17 @@ done fi +# lxc container check +if [ ! $container = "lxc" ]; then + # Deactivate LVM volume groups: if [ -r /etc/lvmtab -o -d /etc/lvm/backup ]; then echo "Deactivating LVM volume groups:" /sbin/vgchange -an --ignorelockingfailure fi +fi # end container check + # This never hurts again (especially since root-on-LVM always fails # to deactivate the / logical volume... but at least it was # remounted as read-only first) @@ -258,6 +294,9 @@ # This is to ensure all processes have completed on SMP machines: wait +# lxc container check +if [ ! $container = "lxc" ]; then + if [ -x /sbin/genpowerd ]; then # See if this is a powerfail situation: if /bin/egrep -q "FAIL|SCRAM" /etc/upsstatus 2> /dev/null ; then @@ -274,6 +313,13 @@ fi fi +else + +# confirm successful shutdown of the container +echo ; echo "* container stopped. *" ; echo + +fi # end container check + # Now halt (poweroff with APM or ACPI enabled kernels) or reboot. if [ "$command" = "reboot" ]; then echo "Rebooting." --- ./etc/rc.orig/rc.S 2012-09-13 21:38:34.000000000 +0200 +++ ./etc/rc.d/rc.S 2013-02-17 09:39:41.579799641 +0100 @@ -4,9 +4,18 @@ # # Mostly written by: Patrick J. Volkerding, # +# minor tweaks for an lxc container +# by Matteo Bernardini , +# based also on Chris Willing's modifications +# http://www.vislab.uq.edu.au/howto/lxc/rc.S +# a check for a container variable is made to jump sections +container="lxc" PATH=/sbin:/usr/sbin:/bin:/usr/bin +# lxc container check +if [ ! $container = "lxc" ]; then + # Try to mount /proc: /sbin/mount -v proc /proc -n -t proc 2> /dev/null @@ -254,10 +263,27 @@ read junk; fi # Done checking root filesystem +else + # We really don't want to start udev in the container + if [ -f /etc/rc.d/rc.udev ]; then + chmod -x /etc/rc.d/rc.udev + fi + # Alsa won't work + if [ -f /etc/rc.d/rc.alsa ]; then + chmod -x /etc/rc.d/rc.alsa + fi + # This too + if [ -f /etc/rc.d/rc.loop ]; then + chmod -x /etc/rc.d/rc.loop + fi +fi # end container check # Any /etc/mtab that exists here is old, so we start with a new one: /bin/rm -f /etc/mtab{,~,.tmp} && /bin/touch /etc/mtab +# lxc container check +if [ ! $container = "lxc" ]; then + # Add entry for / to /etc/mtab: /sbin/mount -f -w / @@ -337,6 +363,8 @@ # mounted read-write. /sbin/swapon -a 2> /dev/null +fi # end container check + # Clean up some temporary files: rm -f /var/run/* /var/run/*/* /var/run/*/*/* /etc/nologin \ /etc/dhcpc/*.pid /etc/forcefsck /etc/fastboot \ @@ -364,7 +392,7 @@ # if the first line of that file begins with the word 'Linux'. # You are free to modify the rest of the file as you see fit. if [ -x /bin/sed ]; then - /bin/sed -i "{1s/^Linux.*/$(/bin/uname -sr)\./}" /etc/motd + /bin/sed -i "{1s/^Linux.*/$(/bin/uname -sr) lxc container\./}" /etc/motd fi # If there are SystemV init scripts for this runlevel, run them. @@ -372,6 +400,9 @@ . /etc/rc.d/rc.sysvinit fi +# lxc container check +if [ ! $container = "lxc" ]; then + # Run serial port setup script: # CAREFUL! This can make some systems hang if the rc.serial script isn't # set up correctly. If this happens, you may have to edit the file from a @@ -380,6 +411,8 @@ sh /etc/rc.d/rc.serial start fi +fi # end container check + # Carry an entropy pool between reboots to improve randomness. if [ -f /etc/random-seed ]; then echo "Using /etc/random-seed to initialize /dev/urandom." --- ./etc/rc.orig/rc.M 2012-09-25 19:47:07.000000000 +0200 +++ ./etc/rc.d/rc.M 2013-02-17 09:39:41.579799641 +0100 @@ -10,6 +10,10 @@ # Author: Fred N. van Kempen, # Heavily modified by Patrick Volkerding # +# minor tweaks for an lxc container +# by Matteo Bernardini : +# a check for a container variable is made to jump sections +container="lxc" # Tell the viewers what's going to happen. echo "Going multiuser..." @@ -20,6 +24,9 @@ /sbin/ldconfig & fi +# lxc container check +if [ ! $container = "lxc" ]; then + # Screen blanks after 15 minutes idle time, and powers down in one hour # if the kernel supports APM or ACPI power management: /bin/setterm -blank 15 -powersave powerdown -powerdown 60 @@ -33,6 +40,8 @@ /bin/hostname darkstar fi +fi # end container check + # Set the permissions on /var/log/dmesg according to whether the kernel # permits non-root users to access kernel dmesg information: if [ -r /proc/sys/kernel/dmesg_restrict ]; then @@ -135,6 +144,9 @@ chmod 755 / 2> /dev/null chmod 1777 /tmp /var/tmp +# lxc container check +if [ ! $container = "lxc" ]; then + # Start APM or ACPI daemon. # If APM is enabled in the kernel, start apmd: if [ -e /proc/apm ]; then @@ -146,6 +158,8 @@ . /etc/rc.d/rc.acpid start fi +fi # end container check + # Update any existing icon cache files: if find /usr/share/icons 2> /dev/null | grep -q icon-theme.cache ; then for theme_dir in /usr/share/icons/* ; do --- ./etc/rc.orig/rc.inet1 2012-08-05 19:13:27.000000000 +0200 +++ ./etc/rc.d/rc.inet1 2013-02-17 09:39:41.579799641 +0100 @@ -3,6 +3,11 @@ # This script is used to bring up the various network interfaces. # # @(#)/etc/rc.d/rc.inet1 10.2 Sun Jul 24 12:45:56 PDT 2005 (pjv) +# +# minor tweaks for an lxc container +# by Matteo Bernardini : +# a check for a container variable is made to jump sections +container="lxc" ############################ # READ NETWORK CONFIG FILE # @@ -105,6 +110,10 @@ [ "${IFNAME[$i]}" = "${1}" ] && break i=$(($i+1)) done + + # lxc container check + if [ ! $container = "lxc" ]; then + # If the interface is a bridge, then create it first: [ -n "${BRNICS[$i]}" ] && br_open $i # If the interface isn't in the kernel yet (but there's an alias for it in @@ -115,6 +124,9 @@ /sbin/modprobe ${1} fi fi + + fi # end container check + if grep `echo ${1}: | cut -f 1 -d :`: /proc/net/dev 1> /dev/null ; then # interface exists if ! /sbin/ifconfig | grep -w "${1}" 1>/dev/null || \ ! /sbin/ifconfig ${1} | grep -w inet 1> /dev/null ; then # interface not up or not configured EOF ( cd $rootfs ; patch -p1 < tmp/rcs.patch ; rm tmp/rcs.patch ) # restart rc.inet1 to have routing for the loop device echo "/etc/rc.d/rc.inet1 restart" >> $rootfs/etc/rc.d/rc.local # reduce the number of local consoles: two should be enough sed -i '/^c3\|^c4\|^c5\|^c6/s/^/# /' $rootfs/etc/inittab # better not use this in a container sed -i 's/.*genpowerfail.*//' $rootfs/etc/inittab # add a message to rc.local that confirms successful container startup echo "echo ; echo \"* container $name started. *\" ; echo" >> $rootfs/etc/rc.d/rc.local # borrow the time configuration from the local machine cp -a /etc/localtime $rootfs/etc/localtime return 0 } copy_slackware() { rootfs=$1 # make a local copy of the installed filesystem echo -n "Copying rootfs to $rootfs..." mkdir -p $rootfs cp -a $cache/rootfs-$release-$arch/* $rootfs/ || exit 1 # fix fstab with the actual path sed -i "s|$cache/rootfs-$release-$arch|$rootfs|" $rootfs/etc/fstab return 0 } install_slackware() { rootfs=$1 mkdir -p /var/lock/subsys/ ( flock -n -x 9 if [ $? -ne 0 ]; then echo "Cache repository is busy." return 1 fi if [ "$arch" == "x86_64" ]; then PKGMAIN=slackware64 elif [ "$arch" == "arm" ]; then PKGMAIN=slackwarearm else PKGMAIN=slackware fi export CONF=$cache/slackpkg-conf export ROOT=$cache/rootfs-$release-$arch mkdir -p $cache/cache-$release-$arch $cache/rootfs-$release-$arch \ $cache/slackpkg-$release-$arch $CONF/templates echo "$MIRROR/$PKGMAIN-$release/" > $CONF/mirrors touch $CONF/blacklist cat < $CONF/slackpkg.conf # v2.8 ARCH=$arch TEMP=$cache/cache-$release-$arch WORKDIR=$cache/slackpkg-$release-$arch DELALL=off CHECKMD5=on CHECKGPG=on CHECKSIZE=off PRIORITY=( patches %PKGMAIN extra pasture testing ) POSTINST=on ONLY_NEW_DOTNEW=off ONOFF=on DOWNLOAD_ALL=on DIALOG=off BATCH=on DEFAULT_ANSWER=y USE_INCLUDES=on SPINNING=off EOF # thanks to Vincent Batts for this list of packages # (that I modified a little :P) # http://connie.slackware.com/~vbatts/minimal/ cat < $CONF/templates/minimal-lxc.template aaa_base aaa_elflibs aaa_terminfo bash bin bzip2 coreutils dhcpcd dialog diffutils e2fsprogs elvis etc findutils gawk glibc-solibs gnupg grep gzip iputils logrotate mpfr net-tools network-scripts ncurses openssh openssl-solibs pkgtools procps-ng sed shadow sharutils slackpkg sysklogd sysvinit sysvinit-functions sysvinit-scripts tar udev util-linux wget which xz EOF TEMPLATE=${TEMPLATE:-minimal-lxc} if [ ! "$TEMPLATE" = "minimal-lxc" ]; then if [ -f /etc/slackpkg/templates/$TEMPLATE.template ]; then cat /etc/slackpkg/templates/$TEMPLATE.template \ > $CONF/templates/$TEMPLATE.template else TEMPLATE="minimal-lxc" fi fi # clean previous installs rm -fR $ROOT/* slackpkg -default_answer=n update slackpkg install-template $TEMPLATE # add a slackpkg default mirror echo "$MIRROR/$PKGMAIN-$release/" >> $ROOT/etc/slackpkg/mirrors # blacklist the devs package (we have to use our premade devices). # do the same with the kernel packages (we use the host's one), # but leave available headers and sources echo "devs" >> $ROOT/etc/slackpkg/blacklist sed -i \ -e "s|^#kernel-|kernel-|" \ -e "s|^kernel-headers|#kernel-headers|" \ -e "s|^kernel-source|#kernel-source|" \ $ROOT/etc/slackpkg/blacklist # force klog to use the system call interface to the kernel message # buffers - needed for unprivileged containers sed -i 's|3\ \-x|3 -x -s|' $ROOT/etc/rc.d/rc.syslog || true return 0 ) 9>/var/lock/subsys/lxc return $? } copy_configuration() { path=$1 rootfs=$2 name=$3 cat <> $path/config lxc.utsname = $name lxc.arch = $arch lxc.mount = $rootfs/etc/fstab lxc.include = ${LXC_TEMPLATE_CONFIG}/slackware.common.conf EOF if [ $? -ne 0 ]; then echo "Failed to add configuration." return 1 fi return 0 } clean() { if [ ! -e $cache ]; then exit 0 fi # lock, so we won't purge while someone is creating a repository ( flock -n -x 9 if [ $? != 0 ]; then echo "Cache repository is busy." exit 1 fi echo -n "Purging the download cache..." rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1 exit 0 ) 9>/var/lock/subsys/lxc } usage() { cat < --clean EOF return 0 } options=$(getopt -o hp:n:a:r:c -l help,rootfs:,path:,name:,arch:,release:,clean -- "$@") if [ $? -ne 0 ]; then usage $(basename $0) exit 1 fi eval set -- "$options" while true do case "$1" in -h|--help) usage $0 && exit 0;; -p|--path) path=$2; shift 2;; --rootfs) rootfs=$2; shift 2;; -a|--arch) arch=$2; shift 2;; -r|--release) release=$2; shift 2;; -n|--name) name=$2; shift 2;; -c|--clean) clean=$2; shift 2;; --) shift 1; break ;; *) break ;; esac done if [ ! -z "$clean" -a -z "$path" ]; then clean || exit 1 exit 0 fi type installpkg if [ $? -ne 0 ]; then echo "'installpkg' command is missing." exit 1 fi type slackpkg if [ $? -ne 0 ]; then echo "'slackpkg' command is missing." exit 1 fi if [ -z "$path" ]; then echo "'path' parameter is required." exit 1 fi if [ "$(id -u)" != "0" ]; then echo "This script should be run as 'root'." exit 1 fi # If no release version was specified, use current release=${release:-current} if [ -z "$name" ]; then # no name given? set a default one name=slackwarecontainer fi # detect rootfs config="$path/config" if [ -z "$rootfs" ]; then if grep -q '^lxc.rootfs' $config 2>/dev/null ; then rootfs=$(awk -F= '/^lxc.rootfs =/{ print $2 }' $config) else rootfs=$path/rootfs fi fi echo set -e install_slackware $rootfs if [ $? -ne 0 ]; then echo "Failed to install slackware." exit 1 fi echo configure_slackware $cache/rootfs-$release-$arch $name if [ $? -ne 0 ]; then echo "Failed to configure slackware for a container." exit 1 fi echo rootfs=$path/rootfs copy_slackware $rootfs if [ $? -ne 0 ]; then echo "Failed to copy rootfs." exit 1 fi echo copy_configuration $path $rootfs $name if [ $? -ne 0 ]; then echo "Failed to write configuration file." exit 1 fi if [ ! -z $clean ]; then clean || exit 1 exit 0 fi lxc-2.0.8/templates/lxc-alpine.in0000644061062106075000000003137313105116772013634 00000000000000#!/bin/sh # vim: set ts=4: # Exit on error and treat unset variables as an error. set -eu # # LXC template for Alpine Linux 3+ # # Note: Do not replace tabs with spaces, it would break heredocs! # Authors: # Jakub Jirutka # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #=========================== Constants ============================# # Make sure the usual locations are in PATH export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin readonly LOCAL_STATE_DIR='@LOCALSTATEDIR@' readonly LXC_TEMPLATE_CONFIG='@LXCTEMPLATECONFIG@' readonly LXC_CACHE_DIR="${LXC_CACHE_PATH:-"$LOCAL_STATE_DIR/cache/lxc"}/alpine" # SHA256 checksums of GPG keys for APK. readonly APK_KEYS_SHA256="\ 9c102bcc376af1498d549b77bdbfa815ae86faa1d2d82f040e616b18ef2df2d4 alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub 2adcf7ce224f476330b5360ca5edb92fd0bf91c92d83292ed028d7c4e26333ab alpine-devel@lists.alpinelinux.org-4d07755e.rsa.pub ebf31683b56410ecc4c00acd9f6e2839e237a3b62b5ae7ef686705c7ba0396a9 alpine-devel@lists.alpinelinux.org-5243ef4b.rsa.pub 1bb2a846c0ea4ca9d0e7862f970863857fc33c32f5506098c636a62a726a847b alpine-devel@lists.alpinelinux.org-524d27bb.rsa.pub 12f899e55a7691225603d6fb3324940fc51cd7f133e7ead788663c2b7eecb00c alpine-devel@lists.alpinelinux.org-5261cecb.rsa.pub" readonly APK_KEYS_URI='http://alpinelinux.org/keys' readonly DEFAULT_MIRROR_URL='http://dl-cdn.alpinelinux.org/alpine' : ${APK_KEYS_DIR:=/etc/apk/keys} if ! ls "$APK_KEYS_DIR"/alpine* >/dev/null 2>&1; then APK_KEYS_DIR="$LXC_CACHE_DIR/bootstrap/keys" fi readonly APK_KEYS_DIR : ${APK:=$(command -v apk || true)} if [ ! -x "$APK" ]; then APK="$LXC_CACHE_DIR/bootstrap/sbin/apk.static" fi readonly APK #======================== Helper Functions ========================# usage() { cat <<-EOF Template specific options can be passed to lxc-create after a '--' like this: lxc-create --name=NAME [lxc-create-options] -- [template-options] [PKG...] PKG Additional APK package(s) to install into the container. Template options: -a ARCH, --arch=ARCH The container architecture (e.g. x86, x86_64); defaults to the host arch. -d, --debug Run this script in a debug mode (set -x and wget w/o -q). -F, --flush-cache Remove cached files before build. -m URL --mirror=URL The Alpine mirror to use; defaults to $DEFAULT_MIRROR_URL. -r VER, --release=VER The Alpine release branch to install; default is the latest stable. Environment variables: APK The apk-tools binary to use when building rootfs. If not set or not executable and apk is not on PATH, then the script will download the latest apk-tools-static. APK_KEYS_DIR Path to directory with GPG keys for APK. If not set and /etc/apk/keys does not contain alpine keys, then the script will download the keys from ${APK_KEYS_URI}. LXC_CACHE_PATH Path to the cache directory where to store bootstrap files and APK packages. EOF } die() { local retval=$1; shift printf 'ERROR: %s\n' "$@" 1>&2 exit $retval } einfo() { printf "\n==> $1\n" } fetch() { if [ "$DEBUG" = 'yes' ]; then wget -T 10 -O - $@ else wget -T 10 -O - -q $@ fi } latest_release_branch() { local arch="$1" local branch=$(fetch "$MIRROR_URL/latest-stable/releases/$arch/latest-releases.yaml" \ | sed -En 's/^[ \t]*branch: (.*)$/\1/p' \ | head -n 1) [ -n "$branch" ] && echo "$branch" } parse_arch() { case "$1" in x86 | i[3-6]86) echo 'x86';; x86_64 | amd64) echo 'x86_64';; aarch64 | arm64) echo 'aarch64';; armv7) echo 'armv7';; arm*) echo 'armhf';; *) return 1;; esac } run_exclusively() { local lock_name="$1" local timeout=$2 shift 2 mkdir -p "$LOCAL_STATE_DIR/lock/subsys" local retval { echo -n "Obtaining an exclusive lock..." if ! flock -x 9; then echo ' failed.' return 1 fi echo ' done' "$@"; retval=$? } 9> "$LOCAL_STATE_DIR/lock/subsys/lxc-alpine-$lock_name" return $retval } #============================ Bootstrap ===========================# bootstrap() { if [ "$FLUSH_CACHE" = 'yes' ] && [ -d "$LXC_CACHE_DIR/bootstrap" ]; then einfo 'Cleaning cached bootstrap files' rm -Rf "$LXC_CACHE_DIR/bootstrap" fi einfo 'Fetching and/or verifying APK keys' fetch_apk_keys "$APK_KEYS_DIR" if [ ! -x "$APK" ]; then einfo 'Fetching apk-tools static binary' local host_arch=$(parse_arch $(uname -m)) fetch_apk_static "$LXC_CACHE_DIR/bootstrap" "$host_arch" fi } fetch_apk_keys() { local dest="$1" local line keyname mkdir -p "$dest" cd "$dest" echo "$APK_KEYS_SHA256" | while read -r line; do keyname="${line##* }" if [ ! -f "$keyname" ]; then fetch "$APK_KEYS_URI/$keyname" > "$keyname" fi echo "$line" | sha256sum -c - done || exit 2 cd - >/dev/null } fetch_apk_static() { local dest="$1" local arch="$2" local pkg_name='apk-tools-static' mkdir -p "$dest" local pkg_ver=$(fetch "$MIRROR_URL/latest-stable/main/$arch/APKINDEX.tar.gz" \ | tar -xzO APKINDEX \ | sed -n "/P:${pkg_name}/,/^$/ s/V:\(.*\)$/\1/p") [ -n "$pkg_ver" ] || die 2 "Cannot find a version of $pkg_name in APKINDEX" fetch "$MIRROR_URL/latest-stable/main/$arch/${pkg_name}-${pkg_ver}.apk" \ | tar -xz -C "$dest" sbin/ # --extract --gzip --directory [ -f "$dest/sbin/apk.static" ] || die 2 'apk.static not found' local keyname=$(echo "$dest"/sbin/apk.static.*.pub | sed 's/.*\.SIGN\.RSA\.//') openssl dgst -sha1 \ -verify "$APK_KEYS_DIR/$keyname" \ -signature "$dest/sbin/apk.static.SIGN.RSA.$keyname" \ "$dest/sbin/apk.static" \ || die 2 'Signature verification for apk.static failed' # Note: apk doesn't return 0 for --version local out="$("$dest"/sbin/apk.static --version)" echo "$out" [ "${out%% *}" = 'apk-tools' ] || die 3 'apk.static --version failed' } #============================ Install ============================# install() { local dest="$1" local arch="$2" local branch="$3" local extra_packages="$4" local apk_cache="$LXC_CACHE_DIR/apk/$arch" local repo_url="$MIRROR_URL/$branch/main" if [ "$FLUSH_CACHE" = 'yes' ] && [ -d "$apk_cache" ]; then einfo "Cleaning cached APK packages for $arch" rm -Rf "$apk_cache" fi mkdir -p "$apk_cache" einfo "Installing Alpine Linux in $dest" cd "$dest" mkdir -p etc/apk ln -s "$apk_cache" etc/apk/cache echo "$repo_url" > etc/apk/repositories install_packages "$arch" "alpine-base $extra_packages" make_dev_nodes setup_inittab setup_hosts setup_network setup_services chroot . /bin/true \ || die 3 'Failed to execute /bin/true in chroot, the builded rootfs is broken!' rm etc/apk/cache cd - >/dev/null } install_packages() { local arch="$1" local packages="$2" $APK --arch="$arch" --root=. --keys-dir="$APK_KEYS_DIR" \ --update-cache --initdb add $packages } make_dev_nodes() { mkdir -p -m 755 dev/pts mkdir -p -m 1777 dev/shm mknod -m 666 dev/zero c 1 5 mknod -m 666 dev/full c 1 7 mknod -m 666 dev/random c 1 8 mknod -m 666 dev/urandom c 1 9 local i; for i in $(seq 0 4); do mknod -m 620 dev/tty$i c 4 $i chown 0:5 dev/tty$i # root:tty done mknod -m 666 dev/tty c 5 0 chown 0:5 dev/tty # root:tty mknod -m 620 dev/console c 5 1 mknod -m 666 dev/ptmx c 5 2 chown 0:5 dev/ptmx # root:tty } setup_inittab() { # Remove unwanted ttys. sed -i '/^tty[5-9]\:\:.*$/d' etc/inittab cat <<-EOF >> etc/inittab # Main LXC console console ::respawn:/sbin/getty 38400 console EOF } setup_hosts() { # This runscript injects localhost entries with the current hostname # into /etc/hosts. cat <<'EOF' > etc/init.d/hosts #!/sbin/openrc-run start() { local start_tag='# begin generated' local end_tag='# end generated' local content=$( cat <<-EOF $start_tag by /etc/init.d/hosts 127.0.0.1 $(hostname).local $(hostname) localhost ::1 $(hostname).local $(hostname) localhost $end_tag EOF ) if grep -q "^${start_tag}" /etc/hosts; then # escape \n, busybox sed doesn't like them content=${content//$'\n'/\\$'\n'} sed -ni "/^${start_tag}/ { a\\${content} # read and discard next line and repeat until $end_tag or EOF :a; n; /^${end_tag}/!ba; n }; p" /etc/hosts else printf "$content" >> /etc/hosts fi } EOF chmod +x etc/init.d/hosts # Wipe it, will be generated by the above runscript. echo -n > etc/hosts } setup_network() { # Note: loopback is automatically started by LXC. cat <<-EOF > etc/network/interfaces auto eth0 iface eth0 inet dhcp hostname \$(hostname) EOF } setup_services() { local svc_name # Specify the LXC subsystem. sed -i 's/^#*rc_sys=.*/rc_sys="lxc"/' etc/rc.conf # boot runlevel for svc_name in bootmisc hosts syslog; do ln -s /etc/init.d/$svc_name etc/runlevels/boot/$svc_name done # default runlevel for svc_name in networking cron crond; do # issue 1164: alpine renamed cron to crond # Use the one that exists. if [ -e etc/init.d/$svc_name ]; then ln -s /etc/init.d/$svc_name etc/runlevels/default/$svc_name fi done } #=========================== Configure ===========================# configure_container() { local config="$1" local hostname="$2" local arch="$3" cat <<-EOF >> "$config" # Specify container architecture. lxc.arch = $arch # Set hostname. lxc.utsname = $hostname # If something doesn't work, try to comment this out. # Dropping sys_admin disables container root from doing a lot of things # that could be bad like re-mounting lxc fstab entries rw for example, # but also disables some useful things like being able to nfs mount, and # things that are already namespaced with ns_capable() kernel checks, like # hostname(1). lxc.cap.drop = sys_admin # Include common configuration. lxc.include = $LXC_TEMPLATE_CONFIG/alpine.common.conf EOF } #============================= Main ==============================# if [ "$(id -u)" != "0" ]; then die 1 "This script must be run as 'root'" fi # Parse command options. options=$(getopt -o a:dFm:n:p:r:h -l arch:,debug,flush-cache,mirror:,name:,\ path:,release:,rootfs:,help,mapped-uid:,mapped-gid: -- "$@") eval set -- "$options" # Clean variables and set defaults. arch="$(uname -m)" debug='no' flush_cache='no' mirror_url= name= path= release= rootfs= # Process command options. while [ $# -gt 0 ]; do case $1 in -a | --arch) arch=$2; shift 2 ;; -d | --debug) debug='yes'; shift 1 ;; -F | --flush-cache) flush_cache='yes'; shift 1 ;; -m | --mirror) mirror_url=$2; shift 2 ;; -n | --name) name=$2; shift 2 ;; -p | --path) path=$2; shift 2 ;; -r | --release) release=$2; shift 2 ;; --rootfs) rootfs=$2; shift 2 ;; -h | --help) usage; exit 0 ;; --) shift; break ;; --mapped-[ug]id) die 1 "This template can't be used for unprivileged containers." \ 'You may want to try the "download" template instead.' ;; *) echo "Unknown option: $1" 1>&2 usage; exit 1 ;; esac done extra_packages="$@" [ "$debug" = 'yes' ] && set -x # Set global variables. readonly DEBUG="$debug" readonly FLUSH_CACHE="$flush_cache" readonly MIRROR_URL="${mirror_url:-$DEFAULT_MIRROR_URL}" # Validate options. [ -n "$name" ] || die 1 'Missing required option --name' [ -n "$path" ] || die 1 'Missing required option --path' if [ -z "$rootfs" ] && [ -f "$path/config" ]; then rootfs="$(sed -nE 's/^lxc.rootfs\s*=\s*(.*)$/\1/p' "$path/config")" fi if [ -z "$rootfs" ]; then rootfs="$path/rootfs" fi arch=$(parse_arch "$arch") \ || die 1 "Unsupported architecture: $arch" if [ -z "$release" ]; then release=$(latest_release_branch "$arch") \ || die 2 'Failed to resolve Alpine last release branch' fi # Here we go! run_exclusively 'bootstrap' 10 bootstrap run_exclusively "$arch" 30 install "$rootfs" "$arch" "$release" "$extra_packages" configure_container "$path/config" "$name" "$arch" einfo "Container's rootfs and config have been created" cat <<-EOF Edit the config file $path/config to check/enable networking setup. The installed system is preconfigured for a loopback and single network interface configured via DHCP. To start the container, run "lxc-start -n $name". The root password is not set; to enter the container run "lxc-attach -n $name". EOF lxc-2.0.8/templates/lxc-ubuntu.in0000644061062106075000000006216013105116772013704 00000000000000#!/bin/bash # # template script for generating ubuntu container for LXC # # This script consolidates and extends the existing lxc ubuntu scripts # # Copyright © 2011 Serge Hallyn # Copyright © 2010 Wilhelm Meier # Author: Wilhelm Meier # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Detect use under userns (unsupported) for arg in "$@"; do [ "$arg" = "--" ] && break if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then echo "This template can't be used for unprivileged containers." 1>&2 echo "You may want to try the \"download\" template instead." 1>&2 exit 1 fi done # Make sure the usual locations are in PATH export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin set -e LOCALSTATEDIR="@LOCALSTATEDIR@" LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@" # Allows the lxc-cache directory to be set by environment variable LXC_CACHE_PATH=${LXC_CACHE_PATH:-"$LOCALSTATEDIR/cache/lxc"} if [ -r /etc/default/lxc ]; then . /etc/default/lxc fi # Check if given path is in a btrfs partition is_btrfs() { [ -e $1 -a $(stat -f -c '%T' $1) = "btrfs" ] } # Check if given path is the root of a btrfs subvolume is_btrfs_subvolume() { [ -d $1 -a $(stat -f -c '%T' $1) = "btrfs" -a $(stat -c '%i' $1) -eq 256 ] } try_mksubvolume() { path=$1 [ -d $path ] && return 0 mkdir -p $(dirname $path) if which btrfs >/dev/null 2>&1 && is_btrfs $(dirname $path); then btrfs subvolume create $path else mkdir -p $path fi } try_rmsubvolume() { path=$1 [ -d $path ] || return 0 if which btrfs >/dev/null 2>&1 && is_btrfs_subvolume $path; then btrfs subvolume delete $path else rm -rf $path fi } configure_ubuntu() { rootfs=$1 hostname=$2 release=$3 user=$4 password=$5 # configure the network using the dhcp cat < $rootfs/etc/network/interfaces # This file describes the network interfaces available on your system # and how to activate them. For more information, see interfaces(5). # The loopback network interface auto lo iface lo inet loopback auto eth0 iface eth0 inet dhcp EOF # set the hostname cat < $rootfs/etc/hostname $hostname EOF # set minimal hosts cat < $rootfs/etc/hosts 127.0.0.1 localhost 127.0.1.1 $hostname # The following lines are desirable for IPv6 capable hosts ::1 ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters EOF if [ ! -f $rootfs/etc/init/container-detect.conf ]; then # suppress log level output for udev sed -i "s/=\"err\"/=0/" $rootfs/etc/udev/udev.conf # remove jobs for consoles 5 and 6 since we only create 4 consoles in # this template rm -f $rootfs/etc/init/tty{5,6}.conf fi if [ -z "$bindhome" ]; then chroot $rootfs useradd --create-home -s /bin/bash $user echo "$user:$password" | chroot $rootfs chpasswd fi # make sure we have the current locale defined in the container if [ -z "$LANG" ] || echo $LANG | grep -E -q "^C(\..+)*$"; then chroot $rootfs locale-gen en_US.UTF-8 || true chroot $rootfs update-locale LANG=en_US.UTF-8 || true else chroot $rootfs locale-gen $LANG || true chroot $rootfs update-locale LANG=$LANG || true fi # generate new SSH keys if [ -x $rootfs/var/lib/dpkg/info/openssh-server.postinst ]; then cat > $rootfs/usr/sbin/policy-rc.d << EOF #!/bin/sh exit 101 EOF chmod +x $rootfs/usr/sbin/policy-rc.d rm -f $rootfs/etc/ssh/ssh_host_*key* mv $rootfs/etc/init/ssh.conf $rootfs/etc/init/ssh.conf.disabled DPKG_MAINTSCRIPT_PACKAGE=openssh DPKG_MAINTSCRIPT_NAME=postinst chroot $rootfs /var/lib/dpkg/info/openssh-server.postinst configure mv $rootfs/etc/init/ssh.conf.disabled $rootfs/etc/init/ssh.conf sed -i "s/root@$(hostname)/root@$hostname/g" $rootfs/etc/ssh/ssh_host_*.pub rm -f $rootfs/usr/sbin/policy-rc.d fi return 0 } # finish setting up the user in the container by injecting ssh key and # adding sudo group membership. # passed-in user is either 'ubuntu' or the user to bind in from host. finalize_user() { user=$1 sudo_version=$(chroot $rootfs dpkg-query -W -f='${Version}' sudo) if chroot $rootfs dpkg --compare-versions $sudo_version gt "1.8.3p1-1"; then groups="sudo" else groups="sudo admin" fi for group in $groups; do chroot $rootfs groupadd --system $group >/dev/null 2>&1 || true chroot $rootfs adduser ${user} $group >/dev/null 2>&1 || true done if [ -n "$auth_key" -a -f "$auth_key" ]; then u_path="/home/${user}/.ssh" root_u_path="$rootfs/$u_path" mkdir -p $root_u_path cp $auth_key "$root_u_path/authorized_keys" chroot $rootfs chown -R ${user}: "$u_path" echo "Inserted SSH public key from $auth_key into /home/${user}/.ssh/authorized_keys" fi return 0 } # A function to try and autodetect squid-deb-proxy servers on the local network # if either the squid-deb-proxy-client package is installed on the host or # a parent container set the 50squid-deb-proxy-client file. squid_deb_proxy_autodetect() { local apt_discover=/usr/share/squid-deb-proxy-client/apt-avahi-discover local proxy_file=/etc/apt/apt.conf.d/50squid-deb-proxy-client squid_proxy_line= # That's a global :/ # Maybe the host is aware of a squid-deb-proxy? if [ -f $apt_discover ]; then echo -n "Discovering squid-deb-proxy..." squid_proxy_line=$($apt_discover) if [ -n "$squid_proxy_line" ]; then echo "found squid-deb-proxy: $squid_proxy_line" else echo "no squid-deb-proxy found" fi fi # Are we in a nested container, and the parent already knows of a proxy? if [ -f $proxy_file ]; then # Extract the squid URL from the file (whatever is between "") squid_proxy_line=`cat $proxy_file | sed "s/.*\"\(.*\)\".*/\1/"` fi } # # Choose proxies for container # http_proxy will be used by debootstrap on the host. # APT_PROXY will be used to set /etc/apt/apt.conf.d/70proxy in the container. # choose_container_proxy() { local rootfs=$1 local arch=$2 if [ -z "$HTTP_PROXY" ]; then HTTP_PROXY="none" fi case "$HTTP_PROXY" in none) squid_deb_proxy_autodetect if [ -n "$squid_proxy_line" ]; then APT_PROXY=$squid_proxy_line export http_proxy=$squid_proxy_line else APT_PROXY= fi ;; apt) RES=`apt-config shell APT_PROXY Acquire::http::Proxy` eval $RES [ -z "$APT_PROXY" ] || export http_proxy=$APT_PROXY ;; *) APT_PROXY=$HTTP_PROXY export http_proxy=$HTTP_PROXY ;; esac } write_sourceslist() { # $1 => path to the partial cache or the rootfs # $2 => architecture we want to add # $3 => whether to use the multi-arch syntax or not if [ -n "$APT_PROXY" ]; then mkdir -p $1/etc/apt/apt.conf.d cat > $1/etc/apt/apt.conf.d/70proxy << EOF Acquire::http::Proxy "$APT_PROXY" ; EOF fi case $2 in amd64|i386) MIRROR=${MIRROR:-http://archive.ubuntu.com/ubuntu} SECURITY_MIRROR=${SECURITY_MIRROR:-http://security.ubuntu.com/ubuntu} ;; *) MIRROR=${MIRROR:-http://ports.ubuntu.com/ubuntu-ports} SECURITY_MIRROR=${SECURITY_MIRROR:-http://ports.ubuntu.com/ubuntu-ports} ;; esac if [ -n "$3" ]; then cat >> "$1/etc/apt/sources.list" << EOF deb [arch=$2] $MIRROR ${release} main restricted universe multiverse deb [arch=$2] $MIRROR ${release}-updates main restricted universe multiverse deb [arch=$2] $SECURITY_MIRROR ${release}-security main restricted universe multiverse EOF else cat >> "$1/etc/apt/sources.list" << EOF deb $MIRROR ${release} main restricted universe multiverse deb $MIRROR ${release}-updates main restricted universe multiverse deb $SECURITY_MIRROR ${release}-security main restricted universe multiverse EOF fi } install_packages() { local rootfs="$1" shift local packages="$*" if [ -z $update ] then chroot $rootfs apt-get update update=true fi if [ -n "${packages}" ] then chroot $rootfs apt-get install --force-yes -y --no-install-recommends ${packages} fi } cleanup() { try_rmsubvolume $cache/partial-$arch try_rmsubvolume $cache/rootfs-$arch } suggest_flush() { echo "Container upgrade failed. The container cache may be out of date," echo "in which case flushing the cache (see -F in the help output) may help." } download_ubuntu() { cache=$1 arch=$2 release=$3 case $2 in amd64|i386) MIRROR=${MIRROR:-http://archive.ubuntu.com/ubuntu} SECURITY_MIRROR=${SECURITY_MIRROR:-http://security.ubuntu.com/ubuntu} ;; *) MIRROR=${MIRROR:-http://ports.ubuntu.com/ubuntu-ports} SECURITY_MIRROR=${SECURITY_MIRROR:-http://ports.ubuntu.com/ubuntu-ports} ;; esac packages_template=${packages_template:-"apt-transport-https,ssh,vim"} debootstrap_parameters= # Try to guess a list of langpacks to install langpacks="language-pack-en" if which dpkg >/dev/null 2>&1; then langpacks=`(echo $langpacks && dpkg -l | grep -E "^ii language-pack-[a-z]* " | cut -d ' ' -f3) | sort -u` fi packages_template="${packages_template},$(echo $langpacks | sed 's/ /,/g')" if [ -n "$variant" ]; then debootstrap_parameters="$debootstrap_parameters --variant=$variant" fi if [ "$variant" = 'minbase' ]; then packages_template="${packages_template},sudo,ifupdown,isc-dhcp-client" fi echo "Installing packages in template: ${packages_template}" trap cleanup EXIT SIGHUP SIGINT SIGTERM # check the mini ubuntu was not already downloaded try_mksubvolume "$cache/partial-$arch" if [ $? -ne 0 ]; then echo "Failed to create '$cache/partial-$arch' directory" return 1 fi choose_container_proxy $cache/partial-$arch/ $arch # download a mini ubuntu into a cache echo "Downloading ubuntu $release minimal ..." if [ -n "$(which qemu-debootstrap)" ]; then qemu-debootstrap --verbose $debootstrap_parameters --components=main,universe --arch=$arch --include=${packages_template} $release $cache/partial-$arch $MIRROR else debootstrap --verbose $debootstrap_parameters --components=main,universe --arch=$arch --include=${packages_template} $release $cache/partial-$arch $MIRROR fi if [ $? -ne 0 ]; then echo "Failed to download the rootfs, aborting." return 1 fi # Serge isn't sure whether we should avoid doing this when # $release == `distro-info -d` echo "Installing updates" > $cache/partial-$arch/etc/apt/sources.list write_sourceslist $cache/partial-$arch/ $arch chroot "$1/partial-${arch}" apt-get update if [ $? -ne 0 ]; then echo "Failed to update the apt cache" return 1 fi cat > "$1/partial-${arch}"/usr/sbin/policy-rc.d << EOF #!/bin/sh exit 101 EOF chmod +x "$1/partial-${arch}"/usr/sbin/policy-rc.d ( cat << EOF mount -t proc proc "${1}/partial-${arch}/proc" chroot "${1}/partial-${arch}" apt-get dist-upgrade -y EOF ) | lxc-unshare -s MOUNT -- sh -eu || (suggest_flush; false) rm -f "$1/partial-${arch}"/usr/sbin/policy-rc.d chroot "$1/partial-${arch}" apt-get clean mv "$1/partial-$arch" "$1/rootfs-$arch" trap EXIT trap SIGINT trap SIGTERM trap SIGHUP echo "Download complete" return 0 } copy_ubuntu() { cache=$1 arch=$2 rootfs=$3 # make a local copy of the miniubuntu echo "Copying rootfs to $rootfs ..." try_mksubvolume $rootfs if which btrfs >/dev/null 2>&1 && is_btrfs_subvolume $cache/rootfs-$arch && is_btrfs_subvolume $rootfs; then realrootfs=$(dirname $config)/rootfs [ "$rootfs" = "$realrootfs" ] || umount $rootfs || return 1 btrfs subvolume delete $realrootfs || return 1 btrfs subvolume snapshot $cache/rootfs-$arch $realrootfs || return 1 [ "$rootfs" = "$realrootfs" ] || mount --bind $realrootfs $rootfs || return 1 else rsync -Ha $cache/rootfs-$arch/ $rootfs/ || return 1 fi return 0 } install_ubuntu() { rootfs=$1 release=$2 flushcache=$3 cache="$4/$release" mkdir -p $LOCALSTATEDIR/lock/subsys/ ( flock -x 9 if [ $? -ne 0 ]; then echo "Cache repository is busy." return 1 fi if [ $flushcache -eq 1 ]; then echo "Flushing cache..." try_rmsubvolume $cache/partial-$arch try_rmsubvolume $cache/rootfs-$arch fi echo "Checking cache download in $cache/rootfs-$arch ... " if [ ! -e "$cache/rootfs-$arch" ]; then download_ubuntu $cache $arch $release if [ $? -ne 0 ]; then echo "Failed to download 'ubuntu $release base'" return 1 fi fi echo "Copy $cache/rootfs-$arch to $rootfs ... " copy_ubuntu $cache $arch $rootfs if [ $? -ne 0 ]; then echo "Failed to copy rootfs" return 1 fi return 0 ) 9>$LOCALSTATEDIR/lock/subsys/lxc-ubuntu$release return $? } copy_configuration() { path=$1 rootfs=$2 name=$3 arch=$4 release=$5 if [ $arch = "i386" ]; then arch="i686" fi # if there is exactly one veth network entry, make sure it has an # associated hwaddr. nics=`grep -e '^lxc\.network\.type[ \t]*=[ \t]*veth' $path/config | wc -l` if [ $nics -eq 1 ]; then grep -q "^lxc.network.hwaddr" $path/config || sed -i -e "/^lxc\.network\.type[ \t]*=[ \t]*veth/a lxc.network.hwaddr = 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')" $path/config fi # Generate the configuration file ## Relocate all the network config entries sed -i -e "/lxc.network/{w ${path}/config-network" -e "d}" $path/config ## Relocate any other config entries sed -i -e "/lxc./{w ${path}/config-auto" -e "d}" $path/config ## Add all the includes echo "" >> $path/config echo "# Common configuration" >> $path/config if [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu.common.conf" ]; then echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu.common.conf" >> $path/config fi if [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu.${release}.conf" ]; then echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu.${release}.conf" >> $path/config fi ## Add the container-specific config echo "" >> $path/config echo "# Container specific configuration" >> $path/config [ -e "$path/config-auto" ] && cat $path/config-auto >> $path/config && rm $path/config-auto grep -q "^lxc.rootfs" $path/config 2>/dev/null || echo "lxc.rootfs = $rootfs" >> $path/config cat <> $path/config lxc.utsname = $name lxc.arch = $arch EOF ## Re-add the previously removed network config echo "" >> $path/config echo "# Network configuration" >> $path/config cat $path/config-network >> $path/config rm $path/config-network if [ $? -ne 0 ]; then echo "Failed to add configuration" return 1 fi return 0 } post_process() { rootfs=$1 release=$2 packages=$3 # Disable service startup cat > $rootfs/usr/sbin/policy-rc.d << EOF #!/bin/sh exit 101 EOF chmod +x $rootfs/usr/sbin/policy-rc.d # If the container isn't running a native architecture, setup multiarch if [ -x "$(ls -1 ${rootfs}/usr/bin/qemu-*-static 2>/dev/null)" ]; then dpkg_version=$(chroot $rootfs dpkg-query -W -f='${Version}' dpkg) if chroot $rootfs dpkg --compare-versions $dpkg_version ge "1.16.2"; then chroot $rootfs dpkg --add-architecture ${hostarch} else mkdir -p ${rootfs}/etc/dpkg/dpkg.cfg.d echo "foreign-architecture ${hostarch}" > ${rootfs}/etc/dpkg/dpkg.cfg.d/lxc-multiarch fi # Save existing value of MIRROR and SECURITY_MIRROR DEFAULT_MIRROR=$MIRROR DEFAULT_SECURITY_MIRROR=$SECURITY_MIRROR # Write a new sources.list containing both native and multiarch entries > ${rootfs}/etc/apt/sources.list write_sourceslist $rootfs $arch "native" MIRROR=$DEFAULT_MIRROR SECURITY_MIRROR=$DEFAULT_SECURITY_MIRROR write_sourceslist $rootfs $hostarch "multiarch" # Finally update the lists and install upstart using the host architecture HOST_PACKAGES="upstart:${hostarch} mountall:${hostarch} isc-dhcp-client:${hostarch}" chroot $rootfs apt-get update if chroot $rootfs dpkg -l iproute2 | grep -q ^ii; then HOST_PACKAGES="$HOST_PACKAGES iproute2:${hostarch}" else HOST_PACKAGES="$HOST_PACKAGES iproute:${hostarch}" fi install_packages $rootfs $HOST_PACKAGES fi # Install Packages in container if [ -n "$packages" ] then local packages="`echo $packages | sed 's/,/ /g'`" echo "Installing packages: ${packages}" install_packages $rootfs $packages fi # Set initial timezone as on host if [ -f /etc/timezone ]; then cat /etc/timezone > $rootfs/etc/timezone chroot $rootfs dpkg-reconfigure -f noninteractive tzdata elif [ -f /etc/sysconfig/clock ]; then . /etc/sysconfig/clock echo $ZONE > $rootfs/etc/timezone chroot $rootfs dpkg-reconfigure -f noninteractive tzdata else echo "Timezone in container is not configured. Adjust it manually." fi # rmdir /dev/shm for containers that have /run/shm # I'm afraid of doing rm -rf $rootfs/dev/shm, in case it did # get bind mounted to the host's /run/shm. So try to rmdir # it, and in case that fails move it out of the way. # NOTE: This can only be removed once 12.04 goes out of support if [ ! -L $rootfs/dev/shm ] && [ -e $rootfs/dev/shm ]; then rmdir $rootfs/dev/shm 2>/dev/null || mv $rootfs/dev/shm $rootfs/dev/shm.bak ln -s /run/shm $rootfs/dev/shm fi # Re-enable service startup rm $rootfs/usr/sbin/policy-rc.d } do_bindhome() { rootfs=$1 user=$2 # copy /etc/passwd, /etc/shadow, and /etc/group entries into container pwd=`getent passwd $user` || { echo "Failed to copy password entry for $user"; false; } echo $pwd >> $rootfs/etc/passwd # make sure user's shell exists in the container shell=`echo $pwd | cut -d: -f 7` if [ ! -x $rootfs/$shell ]; then echo "shell $shell for user $user was not found in the container." pkg=`dpkg -S $(readlink -m $shell) | cut -d ':' -f1` echo "Installing $pkg" install_packages $rootfs $pkg fi shad=`getent shadow $user` echo "$shad" >> $rootfs/etc/shadow # bind-mount the user's path into the container's /home h=`getent passwd $user | cut -d: -f 6` mkdir -p $rootfs/$h # use relative path in container h2=${h#/} while [ ${h2:0:1} = "/" ]; do h2=${h2#/} done echo "lxc.mount.entry = $h $h2 none bind 0 0" >> $path/config # Make sure the group exists in container grp=`echo $pwd | cut -d: -f 4` # group number for $user grpe=`getent group $grp` || return 0 # if host doesn't define grp, ignore in container chroot $rootfs getent group "$grpe" || echo "$grpe" >> $rootfs/etc/group } usage() { cat <] [-d|--debug] [-F | --flush-cache] [-r|--release ] [-v|--variant] [ -S | --auth-key ] [--rootfs ] [--packages ] [-u|--user ] [--password ] [--mirror ] [--security-mirror ] release: the ubuntu release (e.g. xenial): defaults to host release on ubuntu, otherwise uses latest LTS variant: debootstrap variant to use (see debootstrap(8)) bindhome: bind 's home into the container The ubuntu user will not be created, and will have sudo access. arch: the container architecture (e.g. amd64): defaults to host arch auth-key: SSH Public key file to inject into container packages: list of packages to add comma separated mirror,security-mirror: mirror for download and /etc/apt/sources.list EOF return 0 } options=$(getopt -o a:b:hp:r:v:n:FS:du: -l arch:,bindhome:,help,path:,release:,variant:,name:,flush-cache,auth-key:,debug,rootfs:,packages:,user:,password:,mirror:,security-mirror: -- "$@") if [ $? -ne 0 ]; then usage $(basename $0) exit 1 fi eval set -- "$options" release=xenial # Default to the last Ubuntu LTS release for non-Ubuntu systems if [ -f /etc/lsb-release ]; then . /etc/lsb-release if [ "$DISTRIB_ID" = "Ubuntu" ]; then release=$DISTRIB_CODENAME fi fi bindhome= # Code taken from debootstrap if [ -x /usr/bin/dpkg ] && /usr/bin/dpkg --print-architecture >/dev/null 2>&1; then arch=`/usr/bin/dpkg --print-architecture` elif which udpkg >/dev/null 2>&1 && udpkg --print-architecture >/dev/null 2>&1; then arch=`/usr/bin/udpkg --print-architecture` else arch=$(uname -m) if [ "$arch" = "i686" ]; then arch="i386" elif [ "$arch" = "x86_64" ]; then arch="amd64" elif [ "$arch" = "armv7l" ]; then arch="armhf" elif [ "$arch" = "aarch64" ]; then arch="arm64" elif [ "$arch" = "ppc64le" ]; then arch="ppc64el" fi fi debug=0 hostarch=$arch flushcache=0 packages="" user="ubuntu" password="ubuntu" while true do case "$1" in -h|--help) usage $0 && exit 0;; --rootfs) rootfs=$2; shift 2;; -p|--path) path=$2; shift 2;; -n|--name) name=$2; shift 2;; -u|--user) user=$2; shift 2;; --password) password=$2; shift 2;; -F|--flush-cache) flushcache=1; shift 1;; -r|--release) release=$2; shift 2;; -v|--variant) variant=$2; shift 2;; --packages) packages=$2; shift 2;; -b|--bindhome) bindhome=$2; shift 2;; -a|--arch) arch=$2; shift 2;; -S|--auth-key) auth_key=$2; shift 2;; -d|--debug) debug=1; shift 1;; --mirror) MIRROR=$2; shift 2;; --security-mirror) SECURITY_MIRROR=$2; shift 2;; --) shift 1; break ;; *) break ;; esac done if [ $debug -eq 1 ]; then set -x fi if [ -n "$bindhome" ]; then pwd=`getent passwd $bindhome` if [ $? -ne 0 ]; then echo "Error: no password entry found for $bindhome" exit 1 fi fi if [ "$arch" = "i686" ]; then arch=i386 fi if [ $hostarch = "i386" -a $arch = "amd64" ]; then echo "can't create $arch container on $hostarch" exit 1 fi if [ $hostarch = "armhf" -o $hostarch = "armel" -o $hostarch = "arm64" ] && \ [ $arch != "armhf" -a $arch != "armel" -a $arch != "arm64" ]; then echo "can't create $arch container on $hostarch" exit 1 fi if [ $arch = "arm64" ] && [ $hostarch != "arm64" ]; then echo "can't create $arch container on $hostarch" exit 1 fi if [ $hostarch = "powerpc" -a $arch != "powerpc" ]; then echo "can't create $arch container on $hostarch" exit 1 fi which debootstrap >/dev/null 2>&1 || { echo "'debootstrap' command is missing" >&2; false; } if [ -z "$path" ]; then echo "'path' parameter is required" exit 1 fi if [ "$(id -u)" != "0" ]; then echo "This script should be run as 'root'" exit 1 fi # detect rootfs config="$path/config" # if $rootfs exists here, it was passed in with --rootfs if [ -z "$rootfs" ]; then if grep -q '^lxc.rootfs' $config 2>/dev/null ; then rootfs=$(awk -F= '/^lxc.rootfs =/{ print $2 }' $config) else rootfs=$path/rootfs fi fi install_ubuntu $rootfs $release $flushcache $LXC_CACHE_PATH if [ $? -ne 0 ]; then echo "failed to install ubuntu $release" exit 1 fi configure_ubuntu $rootfs $name $release $user $password if [ $? -ne 0 ]; then echo "failed to configure ubuntu $release for a container" exit 1 fi copy_configuration $path $rootfs $name $arch $release if [ $? -ne 0 ]; then echo "failed write configuration file" exit 1 fi post_process $rootfs $release $trim_container $packages if [ -n "$bindhome" ]; then do_bindhome $rootfs $bindhome finalize_user $bindhome else finalize_user $user fi echo "" echo "##" if [ -n "$bindhome" ]; then echo "# Log in as user $bindhome" else echo "# The default user is '$user' with password '$password'!" echo "# Use the 'sudo' command to run tasks as root in the container." fi echo "##" echo "" lxc-2.0.8/templates/lxc-gentoo.in0000644061062106075000000006720213105116772013657 00000000000000#!/bin/bash # # LXC template for gentoo # # Author: Guillaume Zitta # # Widely inspired from lxc-gentoo script at https://github.com/globalcitizen/lxc-gentoo # # this version is reworked with : # - out of the lxc-create compat # - vanilla gentoo config # - ready to use cache # # Detect use under userns (unsupported) for arg in "$@"; do [ "$arg" = "--" ] && break if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then echo "This template can't be used for unprivileged containers." 1>&2 echo "You may want to try the \"download\" template instead." 1>&2 exit 1 fi done # Make sure the usual locations are in PATH export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin # Ensure strict root's umask doesen't render the VM unusable umask 022 LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@" ################################################################################ # Various helper functions ################################################################################ # param: $1: the name of the lock # param: $2: the timeout for the lock # The rest contain the command to execute and its parameters execute_exclusively() { mkdir -p @LOCALSTATEDIR@/lock/subsys/ local lock_name="$1" local timeout="$2" shift 2 { printf "Attempting to obtain an exclusive lock (timeout: %s sec) named \"%s\"...\n" "${timeout}" "$lock_name" flock -x -w "${timeout}" 50 if [[ $? -ne 0 ]]; then printf " => unable to obtain lock, aborting.\n" return 2 else printf " => done.\n" fi printf " => Executing \"%s\"\n" "$*" "$@" retval=$? } 50> "@LOCALSTATEDIR@/lock/subsys/lxc-gentoo-${lock_name}" return $retval } # a die function is always a good idea die() { printf "\n[the last exit code leading to this death was: %s ]\n" "$?" local retval="$1" shift 1 printf "$@" exit "$retval" } # gentoo arch/variant detection set_default_arch() { printf "### set_default_arch: default arch/variant autodetect...\n" arch=$(uname -m) if [[ $arch =~ i.86 ]]; then arch="x86" variant="x86" elif [[ $arch == "x86_64" ]]; then arch="amd64" variant="amd64" elif [[ $arch =~ arm.* ]]; then arch="arm" variant="armv7a" else #who knows, it may work... printf " => warn: unexpected arch:${arch} let me knows if it works :)\n" variant="${arch}" fi printf " => Got: arch=%s variant=%s\n" "${arch}" "${variant}" } store_user_message() { user_message="${user_message}=> $@\n" } ################################################################################ # CACHE Preparation ################################################################################ # during setup cachedir is $cacheroot/partial-$arch-$variant # at the end, it will be $cacheroot/rootfs-$arch-$variant cache_setup(){ partialfs="${cacheroot}/partial-${arch}-${variant}" #if cache exists and flush not needed, return [[ -d "${cachefs}" && -z "${flush_cache}" ]] && return 0 printf "###### cache_setup(): doing cache preparation\n" local retval=1 #clean from failed previous run rm -rf "${partialfs}" mkdir -p "${partialfs}" #let's go cache_precheck && \ cache_stage3 && \ cache_portage && \ cache_inittab && \ cache_net && \ cache_dev && \ cache_openrc && \ cache_locale && \ rm -rf "${cachefs}" && \ mv "${partialfs}" "${cachefs}" && \ printf "###### cache_setup: Cache should be ready\n" return $? } cache_precheck() { printf "### cache_precheck(): doing some pre-start checks ...\n" # never hurts to have a fail-safe. [[ -n "${cacheroot//\/}" ]] \ || die 8 "\$cacheroot (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPARATORS, THIS IS *VERY* BAD!\n" "${cacheroot}" } #get latest stage3 tarball cache_stage3() { printf "### cache_stage3(): stage3 cache deployment...\n" if [ -z "${tarball}" ]; then #variables init local stage3_baseurl="${mirror}/releases/${arch}/autobuilds" # get latest-stage3....txt file for subpath local stage3_pointer="${stage3_baseurl}/latest-stage3-${variant}.txt" printf "Determining path to latest Gentoo %s (%s) stage3 archive...\n" "${arch}" "${variant}" printf " => downloading and processing %s\n" "${stage3_pointer}" local stage3_latest_tarball=$(wget -q -O - "${stage3_pointer}" | tail -n1 | cut -d' ' -f1) \ || die 6 "Error: unable to fetch\n" printf " => Got: %s\n" "${stage3_latest_tarball}" printf "Downloading/untarring the actual stage3 tarball...\n" wget -O - "${stage3_baseurl}/${stage3_latest_tarball}" \ | tar -xjpf - --numeric-owner -C "${partialfs}" \ || die 6 "Error: unable to fetch or untar\n" printf " => extracted to: %s\n" "${partialfs}" else printf "Extracting the stage3 tarball...\n" tar -xpf "${tarball}" --numeric-owner -C "${partialfs}" \ || die 6 "unable to untar ${tarball} to ${partialfs}" fi #check if it chroots printf "chroot test..." chroot ${partialfs} /bin/true || die 1 "Error: chroot %s /bin/true, failed" "${partialfs}" printf " OK\n" printf " => stage3 cache extracted in : %s\n" "${partialfs}" return 0 } cache_portage() { printf "### cache_portage: caching portage tree tarball...\n" [[ -z "${flush_cache}" && -f "${portage_cache}" ]] && return 0 rm -f ${portage_cache} printf "Downloading Gentoo portage (software build database) snapshot...\n" execute_exclusively portage 60 wget -O "${portage_cache}" "${mirror}/snapshots/portage-latest.tar.bz2" \ || die 6 "Error: unable to fetch\n" printf " => done.\n" } # custom inittab cache_inittab() { printf "### cache_inittab: tuning inittab...\n" INITTAB="${partialfs}/etc/inittab" [[ -w "$INITTAB" ]] || die 1 "Error: $INITTAB is not writeable" # create console echo "# Lxc main console" >> "$INITTAB" echo "1:12345:respawn:/sbin/agetty -a root --noclear 115200 console linux" >> "$INITTAB" # finally we add a pf line to enable clean shutdown on SIGPWR (issue 60) echo "# clean container shutdown on SIGPWR" >> "$INITTAB" echo "pf:12345:powerwait:/sbin/halt" >> "$INITTAB" # we also blank out /etc/issue here in order to prevent delays spawning login # caused by attempts to determine domainname on disconnected containers sed -i 's/[\][Oo]//g' "${partialfs}/etc/issue" } cache_net() { printf "### cache_net: doing some useful net tuning...\n" # useful for chroot # /etc/resolv.conf grep -i 'search ' /etc/resolv.conf > "${partialfs}/etc/resolv.conf" grep -i 'nameserver ' /etc/resolv.conf >> "${partialfs}/etc/resolv.conf" # fix boot-time interface config wipe under aggressive cap drop # (openrc 0.9.8.4 ~sep 2012 - https://bugs.gentoo.org/show_bug.cgi?id=436266) # initial warkaround was: sed -i -e 's/^#rc_nostop=""/rc_nostop="net.eth0 net.lo"/' "${partialfs}/etc/rc.conf" # but this one does not depends on interfaces names echo 'rc_keyword="-stop"' >> "${partialfs}/etc/conf.d/net" } cache_dev() { printf "### cache_dev(): /dev tuning...\n" #Wait for https://bugs.gentoo.org/show_bug.cgi?id=496054 mkdir "${partialfs}/dev/pts" mkdir "${partialfs}/dev/shm" mkdir "${partialfs}/dev/mqueue" mkdir -m 755 "${partialfs}/dev/net" mknod -m 666 "${partialfs}/dev/net/tun" c 10 200 return 0 } # fix openrc system cache_openrc() { printf "### cache_openrc(): doing openrc tuning\n" #Wait for https://bugs.gentoo.org/show_bug.cgi?id=496054 chroot "${partialfs}" sed s/-lxc//g -i "/etc/init.d/devfs" return 0 } cache_locale() { printf "### cache_locale(): initiating minimale locale en_US.UTF-8 \n" echo "en_US.UTF-8 UTF-8" >> "${partialfs}/etc/locale.gen" chroot "${partialfs}" locale-gen return 0 } ################################################################################ # CONTAINER Preparation ################################################################################ container_setup() { printf "##### container_setup(): starting container setup\n" #in most cases lxc-create should have provided a copy of default lxc.conf #let's tag where template starts, or just create the files echo '### lxc-gentoo template stuff starts here' >> "$path/config" #Determine rootfs #If backingstore was specified, lxc.rootfs should be present or --rootfs did the rootfs var creation if [ -z "${rootfs}" ]; then rootfs=`awk -F= '$1 ~ /^lxc.rootfs/ { print $2 }' "$path/config" 2>/dev/null` if [ -z "${rootfs}" ]; then #OK it's default rootfs="${path}/rootfs" fi fi store_user_message "rootfs of container is : ${rootfs}" store_user_message "config of container is : ${path}/config" container_precheck && \ container_rootfs && \ container_consoles && \ container_tz && \ container_portage && \ container_net && \ container_hostname && \ container_auth && \ container_sshd && \ container_conf if [ $? -ne 0 ]; then die 1 "container_setup(): one step didn't complete, sorry\n" fi printf "###### container_setup(): container should be ready to start!\n" printf "\n\n" printf "You could now use you container with: lxc-start -n %s\n" "${name}" printf "little things you should know about your container:\n" printf "${user_message}" return 0 } container_precheck() { printf "### container_precheck(): doing some pre-start checks ...\n" # never hurts to have a fail-safe. [[ -n "${name//\/}" ]] \ || die 8 "\$name (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPARATORS, THIS IS *VERY* BAD!\n" "${name}" [[ -n "${rootfs//\/}" ]] \ || die 8 "\$rootfs (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPARATORS, THIS IS *VERY* BAD!\n" "${rootfs}" [[ -n "${cachefs//\/}" ]] \ || die 8 "\$cachefs (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPARATORS, THIS IS *VERY* BAD!\n" "${cachefs}" # check if the rootfs already exists [[ -d "${rootfs}/etc" ]] && die 18 "Error: \$rootfs (%s) already exists!" "${rootfs}" # check cache [[ ! -d "${cachefs}/etc" ]] && die 1 "Error: \$cachefs (%s) not found!" "${cachefs}" return 0 } container_rootfs() { printf "#### container_rootfs(): copying rootfs %s from cache %s ...\n" "${rootfs}" "${cachefs}" tar -c -f - --numeric-owner -C "${cachefs}" . \ | tar -x -p -f - --numeric-owner -C "${rootfs}" \ || die 1 "Error: cache copy to rootfs failed" printf "chroot test..." chroot "${rootfs}" /bin/true || die 1 "Error: 'chroot %s /bin/true' failed" printf " OK\n" printf " => done\n" return 0 } container_consoles() { printf "#### container_consoles(): setting container consoles ...\n" # disable unwanted ttys if [[ ${tty} < 6 ]]; then local mindis=$(( ${tty} + 1 )) sed -i "s/^c[${mindis}-6]/#&/" "${rootfs}/etc/inittab" fi printf " => main console + ${tty} ttys\n" if [[ -z "${autologin}" ]]; then sed 's/agetty -a root/agetty/' -i "${rootfs}/etc/inittab" elif [[ "${user}" != "root" ]]; then sed "s/agetty -a root/agetty -a ${user}/" -i "${rootfs}/etc/inittab" printf " => Autologin on main console for %s enabled\n" "${user}" [[ -z "${forced_password}" ]] && unset password store_user_message "${user} has autologin on main console" else printf " => Autologin on main console for root enabled\n" [[ -z "${forced_password}" ]] && unset password store_user_message "${user} has autologin on main console" fi printf " => done\n" } container_tz() { printf "#### container_tz(): setting container timezone ...\n" #let's try to copy it from host if [ -L "/etc/localtime" ]; then #host has a symlink #let see if we can reproduct symlink target=$(readlink /etc/localtime) if [[ "$target" != "" ]]; then if [ -f "${rootfs}/${target}" ]; then #same target exists in container chroot "${rootfs}" ln -sf "${target}" "/etc/localtime" printf " => host symlink reproducted in container : %s\n" "${target}" store_user_message "timezone copyed from host" return 0 fi fi fi if [ -e /etc/localtime ]; then # duplicate host timezone cat /etc/localtime > "${rootfs}/etc/localtime" printf " => host localtime copyed to container\n" store_user_message "timezone was staticly copyed from host" else # otherwise set up UTC chroot "${rootfs}" ln -sf /usr/share/zoneinfo/UTC /etc/localtime printf " => fallback: fixed to UTC\n" store_user_message "timezone was fixed to UTC" fi } container_portage() { printf "#### container_portage(): setting container portage... \n" #default entry for conf portage_mount="#container set with private portage tree, no mount here" printf "Warnings are normal here, don't worry\n" #container repos detection if chroot ${rootfs} portageq get_repo_path / gentoo > /dev/null ; then portage_container="$(chroot ${rootfs} portageq get_repo_path / gentoo)" else die 1 "Failed to figure out container portage tree location with portageq get_repo_path / gentoo\n" fi if [[ -n "${private_portage}" ]]; then container_private_portage return 0 fi if [ -z "${portage_dir}" ]; then #gentoo host detection printf "trying to guess portage_dir from host...\n" portage_dir="$(portageq get_repo_path / gentoo 2>/dev/null)" if [ ! -d "${portage_dir}/profiles" ]; then printf " => host portage detection failed (not gentoo host), fallback to private portage tree\n" container_private_portage return 0 fi else if [ ! -d "${portage_dir}/profiles" ]; then die 1 "specified portage_dir (%s) does not contains profiles, is it a portage tree ?\n" "${portage_dir}" fi fi printf "trying to guess portage distfiles dir from host ...\n" portage_distfiles_dir="$(portageq distdir 2>/dev/null)" if [ ! -d "${portage_distfiles_dir}" ]; then portage_distfiles_dir="${portage_dir}/distfiles" fi # if we are here, we have shared portage_dir #ensure dir exists chroot "${rootfs}" mkdir ${portage_container} portage_mount="#container set with shared portage lxc.mount.entry=${portage_dir} ${portage_container/\//} none ro,bind 0 0 lxc.mount.entry=${portage_distfiles_dir} ${portage_container/\//}/distfiles none rw,bind 0 0 #If you use eix, you should uncomment this #lxc.mount.entry=/var/cache/eix var/cache/eix none ro,bind 0 0" store_user_message "container has a shared portage from host's ${portage_dir} to ${portage_container/\//}" #Let's propose binary packages cat <<- EOF >> "${rootfs}/etc/portage/make.conf" # enable this to store built binary packages #FEATURES="\$FEATURES buildpkg" # enable this to use built binary packages #EMERGE_DEFAULT_OPTS="\${EMERGE_DEFAULT_OPTS} --usepkg" # enable and *tune* this kind of entry to slot binaries, specialy if you use multiples archs and variants #PKGDIR="\${PKGDIR}/amd64 #or PKGDIR="\${PKGDIR}/hardened" EOF printf " => portage stuff done, see /etc/portage/make.conf for additional tricks\n" } container_private_portage() { #called from container_portage() do not call directly from container_setup printf "# untaring private portage to %s from %s ... \n" "${rootfs}/${portage_container}" "${portage_cache}" mkdir -p "${rootfs}/${portage_container}" execute_exclusively portage 60 \ tar -xp --strip-components 1 -C "${rootfs}/${portage_container}" \ -f "${portage_cache}" --numeric-owner \ || die 2 "Error: unable to extract the portage tree.\n" store_user_message "container has its own portage tree at ${portage_container}" printf "=> done\n" } #helper func for container_genconf_net() nic_write() { #display with gentoo's confd.net format echo "config_${nic_name}=\"${nic_conf}\"" #add to managed list [[ "${nic_conf}" == "dhcp" ]] && nic_managed="${nic_managed} ${nic_name}" [[ "${nic_conf}" == "null" ]] && nic_unmanaged="${nic_unmanaged} ${nic_name}" [[ -z "${nic_hwaddr}" && ${nic_type} == "veth" ]] && nic_wo_hwaddr="${nic_wo_hwaddr} ${nic_name}" nic_writed=1 } #Analyse lxc.conf and print conf.d/net content container_conf_net() { local file=${1} [[ -z "${nic_last}" ]] && nic_last=-1 [[ -z "${nic_named}" ]] && nic_named=0 OLDIFS=$IFS IFS=" " #let's do some drity bash things to parse lxc network conf for line in $( sed -r "s/[ ]*=[ ]*/_real_ugly_sep_42_/" "${file}" ); do key=$(echo "${line}" | sed 's/_real_ugly_sep_42_.*$//') value=$(echo "${line}" | sed 's/^.*_real_ugly_sep_42_//') #new nic ! if [[ "${key}" == "lxc.network.type" ]]; then #we don't know what to do with it. [[ "${value}" == "empty" ]] && continue #write conf from previous loops [[ "${nic_writed}" == "0" ]] && nic_write #init defaults let nic_last=nic_last+1 nic_writed=0 #if 1 named between 2 not named: last is eth1 #=> Number is ID munis number of named NIC before nic_name="eth$(( ${nic_last} - ${nic_named} ))" nic_conf="dhcp" nic_type="${value}" fi if [[ "${key}" == "lxc.network.hwaddr" ]]; then nic_hwaddr=1 fi if [[ "${key}" =~ ^lxc.network.ipv(4|6) ]]; then #tell openrc to not manage this NIC as LXC set there address nic_conf="null" fi if [[ "${key}" =~ ^lxc.network.name ]]; then nic_name="${value}" let nic_named=nic_named+1 fi if [[ "${key}" == "lxc.include" ]]; then #recursive into include container_conf_net "${value}" fi done #write conf from previous loops [[ "${nic_writed}" == "0" ]] && nic_write IFS=$OLDIFS } container_net() { printf "container_net(): setting container network conf... \n" #Analyse network configuration in config container_conf_net "$path/config" >> "${rootfs}/etc/conf.d/net" # found how much nic finally have nic_count=$(( ${nic_last} + 1 )) # unless openrc manage a nic, we now have to force openrc to automatic # provision of the 'net' dep. If we do not, network dependent services # will fail to load if [[ -z "${nic_managed}" ]]; then #tell openrc that lxc already did the work echo 'rc_provide="net"' >> "${rootfs}/etc/rc.conf" fi #No NIC ? if [[ ${nic_count} == 0 ]]; then #If no Nic, no need to continue bridge=$(brctl show | awk 'NR==2 {print $1}') if [[ "${bridge}" != "" ]]; then store_user_message "No network interface for this container It's a pitty, you have bridge, ${bridge}. If it is for Lxc, use it next time by adding this to your default.conf : lxc.network.type = veth lxc.network.link = ${bridge} lxc.network.flags = up lxc.network.hwaddr = fe:xx:xx:xx:xx:xx" return 0 else store_user_message "No network interface for this container" return 0 fi fi #For each openrc managed nic, activate sys_nic_index=1 for nic in ${nic_managed} do chroot "${rootfs}" ln -s net.lo "/etc/init.d/net.${nic}" chroot "${rootfs}" rc-update add net.${nic} default #fake sysfs for openrc, in case settings does not provide it mkdir -p "${rootfs}/sys/class/net/${nic}" echo ${sys_nic_index} > "${rootfs}/sys/class/net/${nic}/ifindex" echo up > "${rootfs}/sys/class/net/${nic}/operstate" let sys_nic_index=sys_nic_index+1 done #Warn about dynamic hwaddr if [[ -n "${nic_wo_hwaddr}" ]]; then store_user_message "Warning, these veth NIC don't have fixed hwaddr : ${nic_wo_hwaddr} see http://lists.linuxcontainers.org/pipermail/lxc-devel/2013-December/006736.html and man lxc.conf" fi printf " => network conf done.\n" } # custom hostname container_hostname() { printf "#### container_hostname(): setting hostname... \n" printf "hostname=\"%s\"\n" "${name}" > "${rootfs}/etc/conf.d/hostname" printf " => done.\n" } container_auth() { printf "#### container_auth(): setting authentification... \n" if [[ "${user}" != "root" ]]; then printf " non root user requested, creating... \n" chroot "${rootfs}" useradd --create-home -s /bin/bash "${user}" || die 1 "failed to create user ${user}" printf " => user %s created\n" "${user}" fi store_user_message "Connection user is ${user}" #Home of user auth_home=$(chroot "${rootfs}" getent passwd "${user}" | cut -d : -f 6) if [[ -r "${auth_key}" ]]; then printf " deploying auth_key %s for user %s ...\n" "${auth_key}" "${user}" mkdir -p "${rootfs}/${auth_home}/.ssh" cat "${auth_key}" >> "${rootfs}/${auth_home}/.ssh/authorized_keys" chroot "${rootfs}" chown "${user}:" "${auth_home}/.ssh/authorized_keys" printf " => inserted public key in %s/.ssh/authorized_keys\n" "${auth_home}" [[ -z "${forced_password}" ]] && unset password store_user_message "${user} has the ssh key you gave us" fi if [[ -n "${password}" ]]; then printf " setting password for %s ...\n" "${user}" echo "${user}:${password}" | chroot "${rootfs}" chpasswd || die 1 "failed to change password" printf " => done. if you didn't specify , default is 'toor'\n" if [[ -n "${forced_password}" ]]; then store_user_message "${user} has the password you give for him" fi fi printf " => done.\n" } container_sshd() { printf "#### container_sshd(): enabling sshd... \n" chroot "${rootfs}" rc-update add sshd || die 1 "failed to enable sshd\n" printf " => done.\n" } ################################################################################ # lxc configuration files ################################################################################ container_conf() { printf "container_configuration(): making lxc configuration file... \n" #at this point if there conf_file="${path}/config" # if there is exactly one veth network entry, make sure it has an # associated hwaddr. nics=`grep -e '^lxc\.network\.type[ \t]*=[ \t]*veth' ${conf_file} | wc -l` if [ $nics -eq 1 ]; then grep -q "^lxc.network.hwaddr" ${conf_file} || sed -i -e "/^lxc\.network\.type[ \t]*=[ \t]*veth/a lxc.network.hwaddr = 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')" ${conf_file} fi if grep -q "^lxc.rootfs" "${conf_file}" ; then #lxc-create already provided one conf_rootfs_line="" else conf_rootfs_line="lxc.rootfs = $(readlink -f "${rootfs}")" fi if [[ "${arch}" == "x86" || "${arch}" == "amd64" ]]; then local conf_arch_line="lxc.arch = ${arch}" else local conf_arch_line="# lxc.arch = ${arch}" fi cat <<- EOF >> "${conf_file}" # sets container architecture # If desired architecture != amd64 or x86, then we leave it unset as # LXC does not oficially support anything other than x86 or amd64. ${conf_arch_line} # set the hostname lxc.utsname = ${name} lxc.tty = ${tty} ${conf_rootfs_line} ${portage_mount} ${conf_sysfs} ${conf_mounts} lxc.include = ${LXC_TEMPLATE_CONFIG}/gentoo.${settings}.conf EOF printf " => done.\n" } usage() { cat <] [-v|--variant ] [-P|--private-portage] [--portage-dir ] [-t|--tarball ] [-F|--flush-cache] [-c|--cache-only] [-u|--user ] [-w|--password ] [--autologin] [-S|--auth-key ] [-s|--settings ] [-m|--mirror ] [--tty ] arch: the container architecture (e.g. amd64): defaults to host arch (currently: '${arch}') If you choose one that needs emulation tested: amd64, x86 You could try any other gentoo arch, why not... variant: gentoo's Architecture variant as of dec 2013 : (currently: '${variant}') for amd64 arch: amd64 (default), amd64-hardened+nomultilib, amd64-hardened, amd64-nomultilib, x32 for x86 arch: i686 (default), i486, i686-hardened for arm arch: armv7a (default), armv7a_hardfp, armv6j, armv6j_hardfp, armv5tel, armv4tl private-portage: by default, /usr/portage is mount-binded with host one if exists (currently: '${private_portage}') this force container to have his own copy portage-dir: portage dir used for shared portage by default the host on if any (currently: '${portage_dir}') tarball: force usage of local stage3 archive (currently: '${arch}') If empty, latest will be downloaded flush-cache: do like there is no previous cache cache-only: just ensure cache is present if cache exists and "flush-cache" not specified, does nothing user: user used in auth oriented options (currently: '${user}') password: password for user (currently: '${password}') if default, usage of auth-key will disable password setting autologin: enable autologin for user (currently: '${autologin}') This unset default password setting auth-key: SSH Public key file to inject into container for user (currently: '${auth_key}') This unset default password setting settings: choose common configuration (currently: '${settings}') see ${LXC_TEMPLATE_CONFIG}/gentoo.*.conf Available settings: $(ls -1 ${LXC_TEMPLATE_CONFIG}/gentoo.*.conf | xargs basename -a -s .conf | sed 's/^gentoo.//') mirror: gentoo mirror for download (currently: '${mirror}') tty: number of tty (6 max) (currently: '${tty}') EOF exit 0 } #some overridable defaults set_default_arch mirror="http://distfiles.gentoo.org" user="root" tty=1 settings="common" options=$(getopt -o hp:n:a:FcPv:t:S:u:w:s:m: -l help,rootfs:,path:,name:,arch:,flush-cache,cache-only,private-portage,variant:,portage-dir:,tarball:,auth-key:,user:,autologin,password:,settings:,mirror:,tty: -- "$@") eval set -- "$options" while true do case "$1" in -h|--help) usage $0 && exit 0;; --rootfs) rootfs=$2; shift 2;; -p|--path) path=$2; shift 2;; -n|--name) name=$2; shift 2;; -a|--arch) arch=$2; shift 2;; -F|--flush-cache) flush_cache=1; shift 1;; -c|--cache-only) cache_only=1; shift 1;; -P|--private-portage) private_portage=1; shift 1;; -v|--variant) variant=$2; shift 2;; --portage-dir) portage_dir=$2; shift 2;; -t|--tarball) tarball=$2; shift 2;; -S|--auth-key) auth_key=$2; shift 2;; -u|--user) user=$2; shift 2;; -w|--password) forced_password=1; password=$2; shift 2;; -s|--settings) settings=$2; shift 2;; -m|--mirror) mirror=$2; shift 2;; --container-cache) containercache=$2; shift 2;; --tty) [[ $2 -lt 6 ]] && tty=$2; shift 2;; --autologin) autologin=1; shift 1;; --) shift 1; break ;; *) break ;; esac done # Allow the cache path to be set by environment variable cacheroot="${LXC_CACHE_PATH:-"@LOCALSTATEDIR@/cache/lxc"}/gentoo" portage_cache="${cacheroot}/portage.tbz" cachefs="${cacheroot}/rootfs-${arch}-${variant}" alias wget="wget --timeout=8 --read-timeout=15 -c -t10 -nd" do_all() { cache_setup if [ -z "${cache_only}" ]; then container_setup fi } execute_exclusively "cache-${arch}-${variant}" 60 do_all lxc-2.0.8/templates/lxc-altlinux.in0000644061062106075000000003271413105116772014224 00000000000000#!/bin/bash # # template script for generating altlinux container for LXC # # # lxc: linux Container library # Authors: # Alexey Shabalin # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Detect use under userns (unsupported) for arg in "$@"; do [ "$arg" = "--" ] && break if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then echo "This template can't be used for unprivileged containers." 1>&2 echo "You may want to try the \"download\" template instead." 1>&2 exit 1 fi done # Make sure the usual locations are in PATH export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin #Configurations arch=$(uname -m) cache_base=@LOCALSTATEDIR@/cache/lxc/altlinux/$arch default_path=@LXCPATH@ default_profile=default profile_dir=/etc/lxc/profiles lxc_network_type=veth lxc_network_link=virbr0 # is this altlinux? [ -f /etc/altlinux-release ] && is_altlinux=true configure_altlinux() { # disable selinux in altlinux mkdir -p $rootfs_path/selinux echo 0 > $rootfs_path/selinux/enforce mkdir -p ${rootfs_path}/etc/net/ifaces/eth0 cat < ${rootfs_path}/etc/net/ifaces/eth0/options BOOTPROTO=${BOOTPROTO} ONBOOT=yes NM_CONTROLLED=yes TYPE=eth EOF if [ ${BOOTPROTO} != "dhcp" ]; then # ip address cat < ${rootfs_path}/etc/net/ifaces/eth0/ipv4address ${ipv4} EOF cat < ${rootfs_path}/etc/net/ifaces/eth0/ipv4route ${gw} EOF cat < ${rootfs_path}/etc/net/ifaces/eth0/resolv.conf nameserver ${dns} EOF cat < ${rootfs_path}/etc/net/ifaces/eth0/ipv6address ${ipv6} EOF cat < ${rootfs_path}/etc/net/ifaces/eth0/ipv6route ${gw6} EOF fi # set the hostname cat < ${rootfs_path}/etc/sysconfig/network NETWORKING=yes CONFMETHOD=etcnet HOSTNAME=${UTSNAME} RESOLV_MODS=yes EOF # set minimal hosts cat < $rootfs_path/etc/hosts 127.0.0.1 localhost.localdomain localhost $name EOF # Allow to login at virsh console. loginuid.so doen't work in the absence of auditd. # sed -i 's/^.*loginuid.so.*$/\#&/' ${rootfs_path}/etc/pam.d/common-login # Allow root to login at virsh console echo "pts/0" >> ${rootfs_path}/etc/securetty echo "console" >> ${rootfs_path}/etc/securetty # Enable services for service in network syslogd random NetworkManager do chroot ${rootfs_path} chkconfig $service --list &>/dev/null && chroot ${rootfs_path} chkconfig $service on || true # For systemd chroot ${rootfs_path} systemctl -q enable $service &>/dev/null|| true done # Disable services for service in rawdevices fbsetfont do chroot ${rootfs_path} chkconfig $service --list &>/dev/null && chroot ${rootfs_path} chkconfig $service off || true chroot ${rootfs_path} systemctl -q disable $service &>/dev/null || true done subst 's/^\([3-9]\+:[0-9]\+:respawn:\/sbin\/mingetty.*\)/#\1/' ${rootfs_path}/etc/inittab echo "c1:2345:respawn:/sbin/mingetty --noclear console" >> ${rootfs_path}/etc/inittab [ -f "${rootfs_path}/etc/syslog.conf" ] && \ subst 's,\/dev\/tty12,/var/log/syslog/console,' ${rootfs_path}/etc/syslog.conf dev_path="${rootfs_path}/dev" rm -rf ${dev_path} mkdir -p ${dev_path} mknod -m 666 ${dev_path}/null c 1 3 mknod -m 666 ${dev_path}/zero c 1 5 mknod -m 644 ${dev_path}/random c 1 8 mknod -m 644 ${dev_path}/urandom c 1 9 mkdir -m 755 ${dev_path}/pts mkdir -m 1777 ${dev_path}/shm mknod -m 666 ${dev_path}/tty c 5 0 chown root:tty ${dev_path}/tty mknod -m 600 ${dev_path}/tty0 c 4 0 mknod -m 600 ${dev_path}/tty1 c 4 1 mknod -m 600 ${dev_path}/tty2 c 4 2 mknod -m 600 ${dev_path}/tty3 c 4 3 mknod -m 600 ${dev_path}/tty4 c 4 4 mknod -m 600 ${dev_path}/console c 5 1 mknod -m 666 ${dev_path}/full c 1 7 mknod -m 600 ${dev_path}/initctl p mknod -m 666 ${dev_path}/ptmx c 5 2 chown root:tty ${dev_path}/ptmx ln -s /proc/self/fd ${dev_path}/fd ln -s /proc/kcore ${dev_path}/core mkdir -m 755 ${dev_path}/mapper mknod -m 600 ${dev_path}/mapper/control c 10 236 mkdir -m 755 ${dev_path}/net mknod -m 666 ${dev_path}/net/tun c 10 200 if [ -n "${root_password}" ]; then echo "setting root passwd to $root_password" echo "root:$root_password" | chroot $rootfs_path chpasswd fi return 0 } download_altlinux() { # check the mini altlinux was not already downloaded INSTALL_ROOT=$cache/partial mkdir -p $INSTALL_ROOT if [ $? -ne 0 ]; then echo "Failed to create '$INSTALL_ROOT' directory" return 1 fi # download a mini altlinux into a cache echo "Downloading altlinux minimal ..." APT_GET="apt-get -o RPM::RootDir=$INSTALL_ROOT -y" PKG_LIST="$(grep -hs '^[^#]' "$profile_dir/$profile")" # if no configuration file $profile -- fall back to default list of packages [ -z "$PKG_LIST" ] && PKG_LIST="interactivesystem apt apt-conf etcnet-full openssh-server systemd-sysvinit systemd-units systemd NetworkManager-daemon" mkdir -p $INSTALL_ROOT/var/lib/rpm rpm --root $INSTALL_ROOT --initdb # some scripts want to have /dev/null at least dev_path="$INSTALL_ROOT/dev" if [ ! -c "${dev_path}/null" ]; then mkdir -p "${dev_path}" mknod -m 666 "${dev_path}/null" c 1 3 fi $APT_GET install $PKG_LIST if [ $? -ne 0 ]; then echo "Failed to download the rootfs, aborting." return 1 fi mv "$INSTALL_ROOT" "$cache/rootfs" echo "Download complete." return 0 } copy_altlinux() { # make a local copy of the minialtlinux echo -n "Copying rootfs to $rootfs_path ..." #cp -a $cache/rootfs-$arch $rootfs_path || return 1 # i prefer rsync (no reason really) mkdir -p $rootfs_path rsync -Ha $cache/rootfs/ $rootfs_path/ return 0 } update_altlinux() { chroot $cache/rootfs apt-get update chroot $cache/rootfs apt-get -y dist-upgrade } install_altlinux() { mkdir -p @LOCALSTATEDIR@/lock/subsys/ ( flock -x 9 if [ $? -ne 0 ]; then echo "Cache repository is busy." return 1 fi echo "Checking cache download in $cache/rootfs ... " if [ ! -e "$cache/rootfs" ]; then download_altlinux if [ $? -ne 0 ]; then echo "Failed to download 'altlinux base'" return 1 fi else echo "Cache found. Updating..." update_altlinux if [ $? -ne 0 ]; then echo "Failed to update 'altlinux base', continuing with last known good cache" else echo "Update finished" fi fi echo "Copy $cache/rootfs to $rootfs_path ... " copy_altlinux if [ $? -ne 0 ]; then echo "Failed to copy rootfs" return 1 fi return 0 ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-altlinux return $? } copy_configuration() { mkdir -p $config_path grep -q "^lxc.rootfs" $config_path/config 2>/dev/null || echo "lxc.rootfs = $rootfs_path" >> $config_path/config cat <> $config_path/config lxc.utsname = $name lxc.tty = 4 lxc.pts = 1024 lxc.cap.drop = sys_module mac_admin mac_override sys_time # When using LXC with apparmor, uncomment the next line to run unconfined: #lxc.aa_profile = unconfined #networking #lxc.network.type = $lxc_network_type #lxc.network.flags = up #lxc.network.link = $lxc_network_link #lxc.network.name = veth0 #lxc.network.mtu = 1500 EOF if [ ! -z ${ipv4} ]; then cat <> $config_path/config lxc.network.ipv4 = $ipv4 EOF fi if [ ! -z ${gw} ]; then cat <> $config_path/config lxc.network.ipv4.gateway = $gw EOF fi if [ ! -z ${ipv6} ]; then cat <> $config_path/config lxc.network.ipv6 = $ipv6 EOF fi if [ ! -z ${gw6} ]; then cat <> $config_path/config lxc.network.ipv6.gateway = $gw6 EOF fi cat <> $config_path/config #cgroups lxc.cgroup.devices.deny = a # /dev/null and zero lxc.cgroup.devices.allow = c 1:3 rwm lxc.cgroup.devices.allow = c 1:5 rwm # consoles lxc.cgroup.devices.allow = c 5:1 rwm lxc.cgroup.devices.allow = c 5:0 rwm lxc.cgroup.devices.allow = c 4:0 rwm lxc.cgroup.devices.allow = c 4:1 rwm # /dev/{,u}random lxc.cgroup.devices.allow = c 1:9 rwm lxc.cgroup.devices.allow = c 1:8 rwm lxc.cgroup.devices.allow = c 136:* rwm lxc.cgroup.devices.allow = c 5:2 rwm # rtc lxc.cgroup.devices.allow = c 10:135 rwm lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed EOF if [ $? -ne 0 ]; then echo "Failed to add configuration" return 1 fi return 0 } clean() { if [ ! -e $cache ]; then exit 0 fi # lock, so we won't purge while someone is creating a repository ( flock -x 9 if [ $? != 0 ]; then echo "Cache repository is busy." exit 1 fi echo -n "Purging the download cache for ALTLinux-$release..." rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1 exit 0 ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-altlinux } usage() { cat < [-p|--path=] [-c|--clean] [-R|--release=] [-4|--ipv4=] [-6|--ipv6=] [-g|--gw=] [-d|--dns=] [-P|--profile=] [--rootfs=] [-A|--arch=] [-h|--help] Mandatory args: -n,--name container name, used to as an identifier for that container from now on Optional args: -p,--path path to where the container rootfs will be created, defaults to @LXCPATH@. The container config will go under @LXCPATH@ in that case -c,--clean clean the cache -R,--release ALTLinux release for the new container. if the host is ALTLinux, then it will defaultto the host's release. -4,--ipv4 specify the ipv4 address to assign to the virtualized interface, eg. 192.168.1.123/24 -6,--ipv6 specify the ipv6 address to assign to the virtualized interface, eg. 2003:db8:1:0:214:1234:fe0b:3596/64 -g,--gw specify the default gw, eg. 192.168.1.1 -G,--gw6 specify the default gw, eg. 2003:db8:1:0:214:1234:fe0b:3596 -d,--dns specify the DNS server, eg. 192.168.1.2 -P,--profile Profile name is the file name in /etc/lxc/profiles contained packages name for install to cache. -A,--arch NOT USED YET. Define what arch the container will be [i686,x86_64] ---rootfs rootfs path -h,--help print this help EOF return 0 } options=$(getopt -o hp:n:P:cR:4:6:g:d: -l help,rootfs:,path:,name:,profile:,clean,release:,ipv4:,ipv6:,gw:,dns: -- "$@") if [ $? -ne 0 ]; then usage $(basename $0) exit 1 fi eval set -- "$options" while true do case "$1" in -h|--help) usage $0 && exit 0;; -p|--path) path=$2; shift 2;; --rootfs) rootfs_path=$2; shift 2;; -n|--name) name=$2; shift 2;; -P|--profile) profile=$2; shift 2;; -c|--clean) clean=1; shift 1;; -R|--release) release=$2; shift 2;; -4|--ipv4) ipv4=$2; shift 2;; -6|--ipv6) ipv6=$2; shift 2;; -g|--gw) gw=$2; shift 2;; -d|--dns) dns=$2; shift 2;; --) shift 1; break ;; *) break ;; esac done if [ ! -z "$clean" -a -z "$path" ]; then clean || exit 1 exit 0 fi type apt-get >/dev/null 2>&1 if [ $? -ne 0 ]; then echo "'apt-get' command is missing" exit 1 fi if [ -z "$path" ]; then path=$default_path fi if [ -z "$profile" ]; then profile=$default_profile fi if [ -z "$release" ]; then if [ "$is_altlinux" ]; then release=$(cat /etc/altlinux-release |awk '/^ALT/ {print $3}') else echo "This is not a ALTLinux host and release missing, use -R|--release to specify release" exit 1 fi fi if [ -z "$ipv4" -a -z "$ipv6" ]; then BOOTPROTO="dhcp" else BOOTPROTO="static" fi if [ "$(id -u)" != "0" ]; then echo "This script should be run as 'root'" exit 1 fi # check for 'lxc.rootfs' passed in through default config by lxc-create if [ -z "$rootfs_path" ]; then if grep -q '^lxc.rootfs' $path/config 2>/dev/null ; then rootfs_path=$(awk -F= '/^lxc.rootfs =/{ print $2 }' $path/config) else rootfs_path=$path/rootfs fi fi config_path=$default_path/$name cache=$cache_base/$release/$profile install_altlinux if [ $? -ne 0 ]; then echo "failed to install altlinux" exit 1 fi configure_altlinux if [ $? -ne 0 ]; then echo "failed to configure altlinux for a container" exit 1 fi copy_configuration if [ $? -ne 0 ]; then echo "failed write configuration file" exit 1 fi if [ ! -z "$clean" ]; then clean || exit 1 exit 0 fi echo "container rootfs and config created" echo "network configured as $lxc_network_type in the $lxc_network_link" lxc-2.0.8/templates/lxc-download.in0000644061062106075000000004342613105116772014175 00000000000000#!/bin/sh # Client script for LXC container images. # # Copyright © 2014 Stéphane Graber # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 # USA set -eu LOCALSTATEDIR="@LOCALSTATEDIR@" LXC_HOOK_DIR="@LXCHOOKDIR@" LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@" # Defaults DOWNLOAD_ARCH= DOWNLOAD_BUILD= DOWNLOAD_COMPAT_LEVEL=3 DOWNLOAD_DIST= DOWNLOAD_FLUSH_CACHE="false" DOWNLOAD_FORCE_CACHE="false" DOWNLOAD_INTERACTIVE="false" DOWNLOAD_KEYID="0xE7FB0CAEC8173D669066514CBAEFF88C22F6E216" DOWNLOAD_LIST_IMAGES="false" DOWNLOAD_MODE="system" DOWNLOAD_READY_GPG="false" DOWNLOAD_RELEASE= DOWNLOAD_SERVER="images.linuxcontainers.org" DOWNLOAD_SHOW_GPG_WARNING="true" DOWNLOAD_SHOW_HTTP_WARNING="true" DOWNLOAD_TARGET="system" DOWNLOAD_URL= DOWNLOAD_USE_CACHE="false" DOWNLOAD_VALIDATE="true" DOWNLOAD_VARIANT="default" LXC_MAPPED_GID= LXC_MAPPED_UID= LXC_NAME= LXC_PATH= LXC_ROOTFS= if [ -z "${DOWNLOAD_KEYSERVER:-}" ]; then DOWNLOAD_KEYSERVER="hkp://pool.sks-keyservers.net" # Deal with GPG over http proxy if [ -n "${http_proxy:-}" ]; then DOWNLOAD_KEYSERVER="hkp://p80.pool.sks-keyservers.net:80" fi fi # Make sure the usual locations are in PATH export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin # Some useful functions cleanup() { if [ -d "$DOWNLOAD_TEMP" ]; then rm -Rf $DOWNLOAD_TEMP fi } wget_wrapper() { for i in $(seq 3); do if wget $@; then return 0 fi done return 1 } download_file() { if ! wget_wrapper -T 30 -q https://${DOWNLOAD_SERVER}/$1 -O $2 >/dev/null 2>&1; then if ! wget_wrapper -T 30 -q http://${DOWNLOAD_SERVER}/$1 -O $2 >/dev/null 2>&1; then if [ "$3" = "noexit" ]; then return 1 else echo "ERROR: Failed to download http://${DOWNLOAD_SERVER}/$1" 1>&2 exit 1 fi elif [ "$DOWNLOAD_SHOW_HTTP_WARNING" = "true" ]; then DOWNLOAD_SHOW_HTTP_WARNING="false" echo "WARNING: Failed to download the file over HTTPs." 1>&2 echo -n " The file was instead download over HTTP. " 1>&2 echo "A server replay attack may be possible!" 1>&2 fi fi } download_sig() { if ! download_file $1 $2 noexit; then if [ "$DOWNLOAD_VALIDATE" = "true" ]; then if [ "$3" = "normal" ]; then echo "ERROR: Failed to download http://${DOWNLOAD_SERVER}/$1" 1>&2 exit 1 else return 1 fi else return 0 fi fi } gpg_setup() { if [ "$DOWNLOAD_VALIDATE" = "false" ]; then return fi if [ "$DOWNLOAD_READY_GPG" = "true" ]; then return fi echo "Setting up the GPG keyring" mkdir -p "$DOWNLOAD_TEMP/gpg" chmod 700 "$DOWNLOAD_TEMP/gpg" export GNUPGHOME="$DOWNLOAD_TEMP/gpg" success= for i in $(seq 3); do if gpg --keyserver $DOWNLOAD_KEYSERVER \ --recv-keys ${DOWNLOAD_KEYID} >/dev/null 2>&1; then success=1 break fi done if [ -z "$success" ]; then echo "ERROR: Unable to fetch GPG key from keyserver." exit 1 fi DOWNLOAD_READY_GPG="true" } gpg_validate() { if [ "$DOWNLOAD_VALIDATE" = "false" ]; then if [ "$DOWNLOAD_SHOW_GPG_WARNING" = "true" ]; then echo "WARNING: Running without gpg validation!" 1>&2 fi DOWNLOAD_SHOW_GPG_WARNING="false" return 0 fi if ! gpg --verify $1 >/dev/zero 2>&1; then echo "ERROR: Invalid signature for $1" 1>&2 exit 1 fi } in_userns() { [ -e /proc/self/uid_map ] || { echo no; return; } while read line; do fields=$(echo $line | awk '{ print $1 " " $2 " " $3 }') [ "$fields" = "0 0 4294967295" ] && { echo no; return; } || true echo $fields | grep -q " 0 1$" && { echo userns-root; return; } || true done < /proc/self/uid_map [ "$(cat /proc/self/uid_map)" = "$(cat /proc/1/uid_map)" ] && \ { echo userns-root; return; } echo yes } relevant_file() { FILE_PATH="${LXC_CACHE_PATH}/$1" if [ -e "${FILE_PATH}-${DOWNLOAD_MODE}" ]; then FILE_PATH="${FILE_PATH}-${DOWNLOAD_MODE}" fi if [ -e "$FILE_PATH.${DOWNLOAD_COMPAT_LEVEL}" ]; then FILE_PATH="${FILE_PATH}.${DOWNLOAD_COMPAT_LEVEL}" fi echo $FILE_PATH } usage() { cat < ]: The name of the distribution [ -r | --release ]: Release name/version [ -a | --arch ]: Architecture of the container Optional arguments: [ --variant ]: Variant of the image (default: "default") [ --server ]: Image server (default: "images.linuxcontainers.org") [ --keyid ]: GPG keyid (default: 0x...) [ --keyserver ]: GPG keyserver to use. Environment variable: DOWNLOAD_KEYSERVER [ --no-validate ]: Disable GPG validation (not recommended) [ --flush-cache ]: Flush the local copy (if present) [ --force-cache ]: Force the use of the local copy even if expired LXC internal arguments (do not pass manually!): [ --name ]: The container name [ --path ]: The path to the container [ --rootfs ]: The path to the container's rootfs [ --mapped-uid ]: A uid map (user namespaces) [ --mapped-gid ]: A gid map (user namespaces) Environment Variables: DOWNLOAD_KEYSERVER : The URL of the key server to use, instead of the default. Can be further overridden by using optional argument --keyserver EOF return 0 } options=$(getopt -o d:r:a:hl -l dist:,release:,arch:,help,list,variant:,\ server:,keyid:,keyserver:,no-validate,flush-cache,force-cache,name:,path:,\ rootfs:,mapped-uid:,mapped-gid: -- "$@") if [ $? -ne 0 ]; then usage exit 1 fi eval set -- "$options" while :; do case "$1" in -h|--help) usage && exit 1;; -l|--list) DOWNLOAD_LIST_IMAGES="true"; shift 1;; -d|--dist) DOWNLOAD_DIST=$2; shift 2;; -r|--release) DOWNLOAD_RELEASE=$2; shift 2;; -a|--arch) DOWNLOAD_ARCH=$2; shift 2;; --variant) DOWNLOAD_VARIANT=$2; shift 2;; --server) DOWNLOAD_SERVER=$2; shift 2;; --keyid) DOWNLOAD_KEYID=$2; shift 2;; --keyserver) DOWNLOAD_KEYSERVER=$2; shift 2;; --no-validate) DOWNLOAD_VALIDATE="false"; shift 1;; --flush-cache) DOWNLOAD_FLUSH_CACHE="true"; shift 1;; --force-cache) DOWNLOAD_FORCE_CACHE="true"; shift 1;; --name) LXC_NAME=$2; shift 2;; --path) LXC_PATH=$2; shift 2;; --rootfs) LXC_ROOTFS=$2; shift 2;; --mapped-uid) LXC_MAPPED_UID=$2; shift 2;; --mapped-gid) LXC_MAPPED_GID=$2; shift 2;; *) break;; esac done # Check for required binaries for bin in tar xz wget; do if ! type $bin >/dev/null 2>&1; then echo "ERROR: Missing required tool: $bin" 1>&2 exit 1 fi done # Check for GPG if [ "$DOWNLOAD_VALIDATE" = "true" ]; then if ! type gpg >/dev/null 2>&1; then echo "ERROR: Missing recommended tool: gpg" 1>&2 echo "You can workaround this by using --no-validate." 1>&2 exit 1 fi fi # Check that we have all variables we need if [ -z "$LXC_NAME" ] || [ -z "$LXC_PATH" ] || [ -z "$LXC_ROOTFS" ]; then if [ "$DOWNLOAD_LIST_IMAGES" != "true" ]; then echo "ERROR: Not running through LXC." 1>&2 exit 1 fi fi USERNS=$(in_userns) if [ "$USERNS" != "no" ]; then if [ "$USERNS" = "yes" ]; then if [ -z "$LXC_MAPPED_UID" ] || [ "$LXC_MAPPED_UID" = "-1" ]; then echo "ERROR: In a user namespace without a map." 1>&2 exit 1 fi DOWNLOAD_MODE="user" DOWNLOAD_TARGET="user" else DOWNLOAD_MODE="user" DOWNLOAD_TARGET="system" fi fi if [ -z "$DOWNLOAD_DIST" ] || [ -z "$DOWNLOAD_RELEASE" ] || \ [ -z "$DOWNLOAD_ARCH" ]; then DOWNLOAD_INTERACTIVE="true" fi # Trap all exit signals trap cleanup EXIT HUP INT TERM if ! type mktemp >/dev/null 2>&1; then DOWNLOAD_TEMP=/tmp/lxc-download.$$ mkdir -p $DOWNLOAD_TEMP else DOWNLOAD_TEMP=$(mktemp -d) fi # Simply list images if [ "$DOWNLOAD_LIST_IMAGES" = "true" ] || \ [ "$DOWNLOAD_INTERACTIVE" = "true" ]; then # Initialize GPG gpg_setup # Grab the index DOWNLOAD_INDEX_PATH=/meta/1.0/index-${DOWNLOAD_MODE} echo "Downloading the image index" if ! download_file ${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL} \ ${DOWNLOAD_TEMP}/index noexit || ! download_sig ${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL}.asc \ ${DOWNLOAD_TEMP}/index.asc noexit; then download_file ${DOWNLOAD_INDEX_PATH} ${DOWNLOAD_TEMP}/index normal download_sig ${DOWNLOAD_INDEX_PATH}.asc \ ${DOWNLOAD_TEMP}/index.asc normal fi gpg_validate ${DOWNLOAD_TEMP}/index.asc # Parse it echo "" echo "---" printf "DIST\tRELEASE\tARCH\tVARIANT\tBUILD\n" echo "---" while read line; do # Basic CSV parser OLD_IFS=$IFS IFS=";" set -- $line IFS=$OLD_IFS [ -n "$DOWNLOAD_DIST" ] && [ "$1" != "$DOWNLOAD_DIST" ] && continue [ -n "$DOWNLOAD_RELEASE" ] && [ "$2" != "$DOWNLOAD_RELEASE" ] && continue [ -n "$DOWNLOAD_ARCH" ] && [ "$3" != "$DOWNLOAD_ARCH" ] && continue [ -n "$DOWNLOAD_VARIANT" ] && [ "$4" != "$DOWNLOAD_VARIANT" ] && continue [ -z "$5" ] || [ -z "$6" ] && continue printf "$1\t$2\t$3\t$4\t$5\n" done < ${DOWNLOAD_TEMP}/index echo "---" if [ "$DOWNLOAD_LIST_IMAGES" = "true" ]; then exit 1 fi # Interactive mode echo "" if [ -z "$DOWNLOAD_DIST" ]; then echo -n "Distribution: " read DOWNLOAD_DIST fi if [ -z "$DOWNLOAD_RELEASE" ]; then echo -n "Release: " read DOWNLOAD_RELEASE fi if [ -z "$DOWNLOAD_ARCH" ]; then echo -n "Architecture: " read DOWNLOAD_ARCH fi echo "" fi # Setup the cache if [ "$DOWNLOAD_TARGET" = "system" ]; then LXC_CACHE_BASE="$LOCALSTATEDIR/cache/lxc/" else LXC_CACHE_BASE="$HOME/.cache/lxc/" fi # Allow the setting of the LXC_CACHE_PATH with the usage of environment variables. LXC_CACHE_PATH=${LXC_CACHE_PATH:-"$LXC_CACHE_BASE"} LXC_CACHE_PATH=$LXC_CACHE_PATH/download/$DOWNLOAD_DIST LXC_CACHE_PATH="$LXC_CACHE_PATH/$DOWNLOAD_RELEASE/$DOWNLOAD_ARCH/" LXC_CACHE_PATH="$LXC_CACHE_PATH/$DOWNLOAD_VARIANT" if [ -d "$LXC_CACHE_PATH" ]; then if [ "$DOWNLOAD_FLUSH_CACHE" = "true" ]; then echo "Flushing the cache..." rm -Rf $LXC_CACHE_PATH elif [ "$DOWNLOAD_FORCE_CACHE" = "true" ]; then DOWNLOAD_USE_CACHE="true" else DOWNLOAD_USE_CACHE="true" if [ -e "$(relevant_file expiry)" ]; then if [ "$(cat $(relevant_file expiry))" -lt $(date +%s) ]; then echo "The cached copy has expired, re-downloading..." DOWNLOAD_USE_CACHE="false" fi fi fi fi # Download what's needed if [ "$DOWNLOAD_USE_CACHE" = "false" ]; then # Initialize GPG gpg_setup # Grab the index DOWNLOAD_INDEX_PATH=/meta/1.0/index-${DOWNLOAD_MODE} echo "Downloading the image index" if ! download_file ${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL} \ ${DOWNLOAD_TEMP}/index noexit || ! download_sig ${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL}.asc \ ${DOWNLOAD_TEMP}/index.asc noexit; then download_file ${DOWNLOAD_INDEX_PATH} ${DOWNLOAD_TEMP}/index normal download_sig ${DOWNLOAD_INDEX_PATH}.asc \ ${DOWNLOAD_TEMP}/index.asc normal fi gpg_validate ${DOWNLOAD_TEMP}/index.asc # Parse it while read line; do # Basic CSV parser OLD_IFS=$IFS IFS=";" set -- $line IFS=$OLD_IFS if [ "$1" != "$DOWNLOAD_DIST" ] || \ [ "$2" != "$DOWNLOAD_RELEASE" ] || \ [ "$3" != "$DOWNLOAD_ARCH" ] || \ [ "$4" != "$DOWNLOAD_VARIANT" ] || \ [ -z "$6" ]; then continue fi DOWNLOAD_BUILD=$5 DOWNLOAD_URL=$6 break done < ${DOWNLOAD_TEMP}/index if [ -z "$DOWNLOAD_URL" ]; then echo "ERROR: Couldn't find a matching image." 1>&1 exit 1 fi if [ -d "$LXC_CACHE_PATH" ] && [ -f "$LXC_CACHE_PATH/build_id" ] && \ [ "$(cat $LXC_CACHE_PATH/build_id)" = "$DOWNLOAD_BUILD" ]; then echo "The cache is already up to date." echo "Using image from local cache" else # Download the actual files echo "Downloading the rootfs" download_file $DOWNLOAD_URL/rootfs.tar.xz \ ${DOWNLOAD_TEMP}/rootfs.tar.xz normal download_sig $DOWNLOAD_URL/rootfs.tar.xz.asc \ ${DOWNLOAD_TEMP}/rootfs.tar.xz.asc normal gpg_validate ${DOWNLOAD_TEMP}/rootfs.tar.xz.asc echo "Downloading the metadata" download_file $DOWNLOAD_URL/meta.tar.xz \ ${DOWNLOAD_TEMP}/meta.tar.xz normal download_sig $DOWNLOAD_URL/meta.tar.xz.asc \ ${DOWNLOAD_TEMP}/meta.tar.xz.asc normal gpg_validate ${DOWNLOAD_TEMP}/meta.tar.xz.asc if [ -d $LXC_CACHE_PATH ]; then rm -Rf $LXC_CACHE_PATH fi mkdir -p $LXC_CACHE_PATH mv ${DOWNLOAD_TEMP}/rootfs.tar.xz $LXC_CACHE_PATH if ! tar Jxf ${DOWNLOAD_TEMP}/meta.tar.xz -C $LXC_CACHE_PATH; then echo "ERROR: Invalid rootfs tarball." 2>&1 exit 1 fi echo $DOWNLOAD_BUILD > $LXC_CACHE_PATH/build_id if [ -n "$LXC_MAPPED_UID" ] && [ "$LXC_MAPPED_UID" != "-1" ]; then chown -R $LXC_MAPPED_UID $LXC_CACHE_BASE >/dev/null 2>&1 || true fi if [ -n "$LXC_MAPPED_GID" ] && [ "$LXC_MAPPED_GID" != "-1" ]; then chgrp -R $LXC_MAPPED_GID $LXC_CACHE_BASE >/dev/null 2>&1 || true fi echo "The image cache is now ready" fi else echo "Using image from local cache" fi # Unpack the rootfs echo "Unpacking the rootfs" EXCLUDES="" excludelist=$(relevant_file excludes) if [ -f "${excludelist}" ]; then while read line; do EXCLUDES="$EXCLUDES --exclude=$line" done < $excludelist fi tar --anchored ${EXCLUDES} --numeric-owner -xpJf \ ${LXC_CACHE_PATH}/rootfs.tar.xz -C ${LXC_ROOTFS} mkdir -p ${LXC_ROOTFS}/dev/pts/ # Setup the configuration configfile=$(relevant_file config) fstab=$(relevant_file fstab) if [ ! -e $configfile ]; then echo "ERROR: meta tarball is missing the configuration file" 1>&2 exit 1 fi ## Extract all the network config entries sed -i -e "/lxc.network/{w ${LXC_PATH}/config-network" -e "d}" \ ${LXC_PATH}/config ## Extract any other config entry sed -i -e "/lxc./{w ${LXC_PATH}/config-auto" -e "d}" ${LXC_PATH}/config ## Append the defaults echo "" >> ${LXC_PATH}/config echo "# Distribution configuration" >> ${LXC_PATH}/config cat $configfile >> ${LXC_PATH}/config ## Add the container-specific config echo "" >> ${LXC_PATH}/config echo "# Container specific configuration" >> ${LXC_PATH}/config if [ -e "${LXC_PATH}/config-auto" ]; then cat ${LXC_PATH}/config-auto >> ${LXC_PATH}/config rm ${LXC_PATH}/config-auto fi if [ -e "$fstab" ]; then echo "lxc.mount = ${LXC_PATH}/fstab" >> ${LXC_PATH}/config fi echo "lxc.utsname = ${LXC_NAME}" >> ${LXC_PATH}/config ## Re-add the previously removed network config if [ -e "${LXC_PATH}/config-network" ]; then echo "" >> ${LXC_PATH}/config echo "# Network configuration" >> ${LXC_PATH}/config cat ${LXC_PATH}/config-network >> ${LXC_PATH}/config rm ${LXC_PATH}/config-network fi TEMPLATE_FILES="${LXC_PATH}/config" # Setup the fstab if [ -e $fstab ]; then cp ${fstab} ${LXC_PATH}/fstab TEMPLATE_FILES="$TEMPLATE_FILES ${LXC_PATH}/fstab" fi # Look for extra templates if [ -e "$(relevant_file templates)" ]; then while read line; do fullpath=${LXC_ROOTFS}/$line [ ! -e "$fullpath" ] && continue TEMPLATE_FILES="$TEMPLATE_FILES $fullpath" done < $(relevant_file templates) fi # Replace variables in all templates for file in $TEMPLATE_FILES; do [ ! -f "$file" ] && continue sed -i "s#LXC_NAME#$LXC_NAME#g" $file sed -i "s#LXC_PATH#$LXC_PATH#g" $file sed -i "s#LXC_ROOTFS#$LXC_ROOTFS#g" $file sed -i "s#LXC_TEMPLATE_CONFIG#$LXC_TEMPLATE_CONFIG#g" $file sed -i "s#LXC_HOOK_DIR#$LXC_HOOK_DIR#g" $file done # prevent mingetty from calling vhangup(2) since it fails with userns on CentOS / Oracle if [ -f ${LXC_ROOTFS}/etc/init/tty.conf ]; then sed -i 's|mingetty|mingetty --nohangup|' ${LXC_ROOTFS}/etc/init/tty.conf fi if [ -n "$LXC_MAPPED_UID" ] && [ "$LXC_MAPPED_UID" != "-1" ]; then chown $LXC_MAPPED_UID $LXC_PATH/config $LXC_PATH/fstab >/dev/null 2>&1 || true fi if [ -n "$LXC_MAPPED_GID" ] && [ "$LXC_MAPPED_GID" != "-1" ]; then chgrp $LXC_MAPPED_GID $LXC_PATH/config $LXC_PATH/fstab >/dev/null 2>&1 || true fi if [ -e "$(relevant_file create-message)" ]; then echo "" echo "---" cat "$(relevant_file create-message)" fi exit 0 lxc-2.0.8/templates/lxc-busybox.in0000644061062106075000000002660113105116772014055 00000000000000#!/bin/bash # # lxc: linux Container library # Authors: # Daniel Lezcano # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA LXC_MAPPED_UID= LXC_MAPPED_GID= SSH= # Make sure the usual locations are in PATH export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin am_in_userns() { [ -e /proc/self/uid_map ] || { echo no; return; } [ "$(wc -l /proc/self/uid_map | awk '{ print $1 }')" -eq 1 ] || { echo yes; return; } line=$(awk '{ print $1 " " $2 " " $3 }' /proc/self/uid_map) [ "$line" = "0 0 4294967295" ] && { echo no; return; } echo yes } in_userns=0 [ $(am_in_userns) = "yes" ] && in_userns=1 copy_binary() { binary_path=`which $1` if [ $? -ne 0 ]; then echo "Unable to find $1 binary on the system" return 1 fi dir_path="${binary_path%/*}" echo /{,usr/}{,s}bin | grep $dir_path >/dev/null 2>&1 if [ $? -ne 0 ]; then echo "Binary $1 is located at $binary_path and will not be copied" echo "($dir_path not supported)" return 1 fi cp $binary_path $rootfs/$binary_path if [ $? -ne 0 ]; then echo "Failed to copy $binary_path to rootfs" return 1 fi return 0 } install_busybox() { rootfs=$1 name=$2 res=0 tree="\ $rootfs/selinux \ $rootfs/dev \ $rootfs/home \ $rootfs/root \ $rootfs/etc \ $rootfs/etc/init.d \ $rootfs/bin \ $rootfs/usr/bin \ $rootfs/sbin \ $rootfs/usr/sbin \ $rootfs/proc \ $rootfs/sys \ $rootfs/mnt \ $rootfs/tmp \ $rootfs/var/log \ $rootfs/usr/share/udhcpc \ $rootfs/dev/pts \ $rootfs/dev/shm \ $rootfs/lib \ $rootfs/usr/lib \ $rootfs/lib64 \ $rootfs/usr/lib64" mkdir -p $tree || return 1 chmod 755 $tree || return 1 pushd $rootfs/dev > /dev/null || return 1 # minimal devices needed for busybox if [ $in_userns -eq 1 ]; then for dev in tty console tty0 tty1 ram0 null urandom; do echo "lxc.mount.entry = /dev/$dev dev/$dev none bind,optional,create=file 0 0" >> $path/config done else mknod -m 666 tty c 5 0 || res=1 mknod -m 666 console c 5 1 || res=1 mknod -m 666 tty0 c 4 0 || res=1 mknod -m 666 tty1 c 4 0 || res=1 mknod -m 666 tty5 c 4 0 || res=1 mknod -m 600 ram0 b 1 0 || res=1 mknod -m 666 null c 1 3 || res=1 mknod -m 666 zero c 1 5 || res=1 mknod -m 666 urandom c 1 9 || res=1 fi popd > /dev/null # root user defined cat <> $rootfs/etc/passwd root:x:0:0:root:/root:/bin/sh EOF cat <> $rootfs/etc/group root:x:0:root EOF # mount everything cat <> $rootfs/etc/init.d/rcS #!/bin/sh /bin/syslogd /bin/mount -a /bin/udhcpc EOF # executable chmod 744 $rootfs/etc/init.d/rcS || return 1 # launch rcS first then make a console available # and propose a shell on the tty, the last one is # not needed cat <> $rootfs/etc/inittab ::sysinit:/etc/init.d/rcS tty1::respawn:/bin/getty -L tty1 115200 vt100 console::askfirst:/bin/sh EOF # writable and readable for other chmod 644 $rootfs/etc/inittab || return 1 cat <> $rootfs/usr/share/udhcpc/default.script #!/bin/sh case "\$1" in deconfig) ip addr flush dev \$interface ;; renew|bound) # flush all the routes if [ -n "\$router" ]; then ip route del default 2> /dev/null fi # check broadcast if [ -n "\$broadcast" ]; then broadcast="broadcast \$broadcast" fi # add a new ip address ip addr add \$ip/\$mask \$broadcast dev \$interface if [ -n "\$router" ]; then ip route add default via \$router dev \$interface fi [ -n "\$domain" ] && echo search \$domain > /etc/resolv.conf for i in \$dns ; do echo nameserver \$i >> /etc/resolv.conf done ;; esac exit 0 EOF chmod 744 $rootfs/usr/share/udhcpc/default.script return $res } install_dropbear() { # copy dropbear binary copy_binary dropbear || return 1 # make symlinks to various ssh utilities utils="\ $rootfs/usr/bin/dbclient \ $rootfs/usr/bin/scp \ $rootfs/usr/bin/ssh \ $rootfs/usr/sbin/dropbearkey \ $rootfs/usr/sbin/dropbearconvert \ " echo $utils | xargs -n1 ln -s /usr/sbin/dropbear # add necessary config files mkdir $rootfs/etc/dropbear dropbearkey -t rsa -f $rootfs/etc/dropbear/dropbear_rsa_host_key > /dev/null 2>&1 dropbearkey -t dss -f $rootfs/etc/dropbear/dropbear_dss_host_key > /dev/null 2>&1 echo "'dropbear' ssh utility installed" return 0 } install_openssh() { # tools to be installed server_utils="sshd" client_utils="\ ssh \ scp \ " client_optional_utils="\ sftp \ ssh-add \ ssh-agent \ ssh-keygen \ ssh-keyscan \ ssh-argv0 \ ssh-copy-id \ " # new folders used by ssh ssh_tree="\ $rootfs/etc/ssh \ $rootfs/var/empty/sshd \ $rootfs/var/lib/empty/sshd \ $rootfs/var/run/sshd \ " # create folder structure mkdir -p $ssh_tree if [ $? -ne 0 ]; then return 1 fi # copy binaries for bin in $server_utils $client_utils; do copy_binary $bin || return 1 done for bin in $client_optional_utils; do tool_path=`which $bin` && copy_binary $bin done # add user and group cat <> $rootfs/etc/passwd sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin EOF cat <> $rootfs/etc/group sshd:x:74: EOF # generate container keys ssh-keygen -t rsa -N "" -f $rootfs/etc/ssh/ssh_host_rsa_key >/dev/null 2>&1 ssh-keygen -t dsa -N "" -f $rootfs/etc/ssh/ssh_host_dsa_key >/dev/null 2>&1 # by default setup root password with no password cat < $rootfs/etc/ssh/sshd_config Port 22 Protocol 2 HostKey /etc/ssh/ssh_host_rsa_key HostKey /etc/ssh/ssh_host_dsa_key UsePrivilegeSeparation yes KeyRegenerationInterval 3600 ServerKeyBits 768 SyslogFacility AUTH LogLevel INFO LoginGraceTime 120 PermitRootLogin yes StrictModes yes RSAAuthentication yes PubkeyAuthentication yes IgnoreRhosts yes RhostsRSAAuthentication no HostbasedAuthentication no PermitEmptyPasswords yes ChallengeResponseAuthentication no EOF echo "'OpenSSH' utility installed" return 0 } configure_busybox() { rootfs=$1 which busybox >/dev/null 2>&1 if [ $? -ne 0 ]; then echo "busybox executable is not accessible" return 1 fi # copy busybox in the rootfs cp $(which busybox) $rootfs/bin if [ $? -ne 0 ]; then echo "failed to copy busybox in the rootfs" return 1 fi # symlink busybox for the commands it supports # it would be nice to just use "chroot $rootfs busybox --install -s /bin" # but that only works right in a chroot with busybox >= 1.19.0 pushd $rootfs/bin > /dev/null || return 1 ./busybox --help | grep 'Currently defined functions:' -A300 | \ grep -v 'Currently defined functions:' | tr , '\n' | \ xargs -n1 ln -s busybox popd > /dev/null # relink /sbin/init ln $rootfs/bin/busybox $rootfs/sbin/init # /etc/fstab must exist for "mount -a" touch $rootfs/etc/fstab # passwd exec must be setuid chmod +s $rootfs/bin/passwd touch $rootfs/etc/shadow return 0 } copy_configuration() { path=$1 rootfs=$2 name=$3 grep -q "^lxc.rootfs" $path/config 2>/dev/null || echo "lxc.rootfs = $rootfs" >> $path/config cat <> $path/config lxc.haltsignal = SIGUSR1 lxc.rebootsignal = SIGTERM lxc.utsname = $name lxc.tty = 1 lxc.pts = 1 lxc.cap.drop = sys_module mac_admin mac_override sys_time # When using LXC with apparmor, uncomment the next line to run unconfined: #lxc.aa_profile = unconfined lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed lxc.mount.entry = shm /dev/shm tmpfs defaults 0 0 EOF libdirs="\ lib \ usr/lib \ lib64 \ usr/lib64" for dir in $libdirs; do if [ -d "/$dir" ] && [ -d "$rootfs/$dir" ]; then echo "lxc.mount.entry = /$dir $dir none ro,bind 0 0" >> $path/config fi done echo "lxc.mount.entry = /sys/kernel/security sys/kernel/security none ro,bind,optional 0 0" >>$path/config } remap_userns() { path=$1 if [ -n "$LXC_MAPPED_UID" ] && [ "$LXC_MAPPED_UID" != "-1" ]; then chown $LXC_MAPPED_UID $path/config >/dev/null 2>&1 chown -R root $path/rootfs >/dev/null 2>&1 fi if [ -n "$LXC_MAPPED_GID" ] && [ "$LXC_MAPPED_GID" != "-1" ]; then chgrp $LXC_MAPPED_GID $path/config >/dev/null 2>&1 chgrp -R root $path/rootfs >/dev/null 2>&1 fi } usage() { cat < -s|--ssh={dropbear,openssh} EOF return 0 } options=$(getopt -o hp:n:s: -l help,rootfs:,path:,name:,mapped-uid:,mapped-gid:,ssh: -- "$@") if [ $? -ne 0 ]; then usage $(basename $0) exit 1 fi eval set -- "$options" while true do case "$1" in -h|--help) usage $0 && exit 0;; -p|--path) path=$2; shift 2;; --rootfs) rootfs=$2; shift 2;; -n|--name) name=$2; shift 2;; --mapped-uid) LXC_MAPPED_UID=$2; shift 2;; --mapped-gid) LXC_MAPPED_GID=$2; shift 2;; -s|--ssh) SSH=$2; shift 2;; --) shift 1; break ;; *) break ;; esac done if [ "$(id -u)" != "0" ]; then echo "This script should be run as 'root'" exit 1 fi if [ -z "$path" ]; then echo "'path' parameter is required" exit 1 fi # detect rootfs config="$path/config" if [ -z "$rootfs" ]; then if grep -q '^lxc.rootfs' $config 2>/dev/null ; then rootfs=$(awk -F= '/^lxc.rootfs =/{ print $2 }' $config) else rootfs=$path/rootfs fi fi install_busybox $rootfs $name if [ $? -ne 0 ]; then echo "failed to install busybox's rootfs" exit 1 fi configure_busybox $rootfs if [ $? -ne 0 ]; then echo "failed to configure busybox template" exit 1 fi copy_configuration $path $rootfs $name if [ $? -ne 0 ]; then echo "failed to write configuration file" exit 1 fi remap_userns $path if [ $? -ne 0 ]; then echo "failed to remap files to user" exit 1 fi if [ -n "$SSH" ]; then case "$SSH" in "dropbear") install_dropbear if [ $? -ne 0 ]; then echo "Unable to install 'dropbear' ssh utility" exit 1 fi ;; "openssh") install_openssh if [ $? -ne 0 ]; then echo "Unable to install 'OpenSSH' utility" exit 1 fi ;; *) echo "$SSH: unrecognized ssh utility" exit 1 esac else which dropbear >/dev/null 2>&1 if [ $? -eq 0 ]; then install_dropbear fi fi lxc-2.0.8/templates/lxc-plamo.in0000644061062106075000000002635713105116772013502 00000000000000#!/bin/bash -eu # # template script for generating Plamo Linux container for LXC # # # lxc: linux Container library # Authors: # KATOH Yasufumi # TAMUKI Shoichi # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # ref. https://github.com/Ponce/lxc-slackware/blob/master/lxc-slackware # lxc-ubuntu script # Detect use under userns (unsupported) for arg in "$@"; do [ "$arg" = "--" ] && break if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then echo "This template can't be used for unprivileged containers." 1>&2 echo "You may want to try the \"download\" template instead." 1>&2 exit 1 fi done # Make sure the usual locations are in PATH export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin [ -r /etc/default/lxc ] && . /etc/default/lxc DLSCHEME=${DLSCHEME:-"http"} MIRRORSRV=${MIRRORSRV:-"repository.plamolinux.org"} MIRRORPATH=${MIRRORPATH:-"/pub/linux/Plamo"} CATEGORIES=${CATEGORIES-"00_base 01_minimum"} EXTRACTGRS=${EXTRACTGRS-""} IGNOREPKGS=${IGNOREPKGS-"grub kernel lilo linux_firmware microcode_ctl cpufreqd cpufrequtils gpm ntp kmod"} ADDONPKGS=${ADDONPKGS-"`echo contrib/Hamradio/{morse,qrq}`"} download_plamo() { # check the mini plamo was not already downloaded if ! mkdir -p $ptcache ; then echo "Failed to create '$ptcache' directory." return 1 fi # download a mini plamo into a cache echo "Downloading Plamo-$release minimal..." cd $ptcache case $DLSCHEME in http) depth=2 ;; ftp) depth=3 ;; esac rej=${IGNOREPKGS%% *} ; [ -n "$rej" ] && rej="$rej-*" if [ `echo $IGNOREPKGS | wc -w` -gt 1 ] ; then for p in ${IGNOREPKGS#* } ; do rej="$rej,$p-*" ; done fi for i in $CATEGORIES ; do wget -nv -e robots=off -r -l $depth -nd -A .tgz,.txz -R "$rej" \ -I $MIRRORPATH/Plamo-$release/$arch/plamo/$i \ -X $MIRRORPATH/Plamo-$release/$arch/plamo/$i/old \ $DLSCHEME://$MIRRORSRV$MIRRORPATH/Plamo-$release/$arch/plamo/$i if [ $? -ne 0 ] ; then echo "Failed to download the rootfs, aborting." return 1 fi done for i in $EXTRACTGRS ; do wget -nv -e robots=off -r -l $depth -nd -A .tgz,.txz -R "$rej" \ -I $MIRRORPATH/Plamo-$release/$arch/contrib/$i \ -X $MIRRORPATH/Plamo-$release/$arch/contrib/$i/old \ $DLSCHEME://$MIRRORSRV$MIRRORPATH/Plamo-$release/$arch/contrib/$i if [ $? -ne 0 ] ; then echo "Failed to download the rootfs, aborting." return 1 fi done for p in $ADDONPKGS ; do wget -nv -e robots=off -r -l $depth -nd -A "`basename $p`-*" \ -I $MIRRORPATH/Plamo-$release/$arch/`dirname $p` \ -X $MIRRORPATH/Plamo-$release/$arch/`dirname $p`/old \ $DLSCHEME://$MIRRORSRV$MIRRORPATH/Plamo-$release/$arch/`dirname $p` if [ $? -ne 0 ] ; then echo "Failed to download the rootfs, aborting." return 1 fi done mv $ptcache $dlcache echo "Download complete." return 0 } copy_plamo() { # make a local copy of the mini plamo echo "Copying $rtcache to $rootfs..." mkdir -p $rootfs find $rtcache -mindepth 1 -maxdepth 1 -exec cp -a {} $rootfs \; || return 1 return 0 } install_plamo() { mkdir -p @LOCALSTATEDIR@/lock/subsys ( if ! flock -n 9 ; then echo "Cache repository is busy." return 1 fi echo "Checking cache download in $dlcache..." if [ ! -d $dlcache ] ; then if ! download_plamo ; then echo "Failed to download plamo $release base packages." return 1 fi fi # install "installpkg" command temporarily with static linked tar # command into the lxc cache directory to keep the original uid/ # gid of files/directories. echo "Installing 'installpkg' command into $dlcache/sbin..." ( cd $dlcache ; tar xpJf hdsetup-*.txz ; rm -rf tmp usr var ) sed -i "/ldconfig/!s@/sbin@$dlcache&@g" $dlcache/sbin/installpkg* PATH=$dlcache/sbin:$PATH echo "Installing packages to $rtcache..." if [ ! -d $rtcache ] ; then mkdir -p $rtcache for p in `ls -cr $dlcache/*.t?z` ; do installpkg -root $rtcache -priority ADD $p done fi echo "Copy $rtcache to $rootfs..." if ! copy_plamo ; then echo "Failed to copy rootfs." return 1 fi return 0 ) 9> @LOCALSTATEDIR@/lock/subsys/lxc-plamo } configure_plamo() { # suppress log level output for udev sed -i 's/="err"/=0/' $rootfs/etc/udev/udev.conf # /etc/fstab cat <<- "EOF" > $rootfs/etc/fstab none /proc proc defaults 0 0 none /sys sysfs defaults 0 0 none /dev tmpfs defaults 0 0 none /tmp tmpfs defaults 0 0 none /dev/pts devpts gid=5,mode=620 0 0 none /proc/bus/usb usbfs noauto 0 0 none /var/lib/nfs/rpc_pipefs rpc_pipefs defaults 0 0 EOF # /etc/inittab cat <<- "EOF" | patch $rootfs/etc/inittab 32,33c32,33 < # What to do when power fails (shutdown to single user). < pf::powerfail:/sbin/shutdown -f +5 "THE POWER IS FAILING" --- > # What to do when power fails (shutdown). > pf::powerfail:/sbin/shutdown -h +0 "THE POWER IS FAILING" 47a48 > 1:1235:respawn:/sbin/agetty 38400 console 52,53d52 < c5:1235:respawn:/sbin/agetty 38400 tty5 linux < c6:12345:respawn:/sbin/agetty 38400 tty6 linux EOF # set the hostname echo "$name" > $rootfs/etc/HOSTNAME # set minimal hosts echo "127.0.0.1 localhost $name" > $rootfs/etc/hosts # configure the network using the dhcp echo "DHCP" > $rootfs/var/run/inet1-scheme # localtime (JST) ln -s ../usr/share/zoneinfo/Asia/Tokyo $rootfs/etc/localtime # disable pam_loginuid.so in /etc/pam.d/login (for libvirt's lxc driver) sed -i '/pam_loginuid/s/^/#/' $rootfs/etc/pam.d/login # glibc configure mv $rootfs/etc/ld.so.conf{.new,} chroot $rootfs ldconfig echo "Please change root password!" ed - $rootfs/etc/rc.d/rc.S <<- "EOF" /^mount -w -n -t proc/;/^mkdir \/dev\/shm/-1d /^mknod \/dev\/null/;/^# Clean \/etc\/mtab/-2d /^# copy the rules/;/^# Set the hostname/-1d /^# Check the integrity/;/^# Clean up temporary/-1d w EOF # /etc/rc.d/rc.M ed - $rootfs/etc/rc.d/rc.M <<- "EOF" /^# Screen blanks/;/^# Initialize ip6tables/-1d /^# Initialize sysctl/;/^echo "Starting services/-1d /^sync/;/^# All done/-1d w EOF # /etc/rc.d/rc.inet1.tradnet head -n-93 $rootfs/sbin/netconfig.tradnet > /tmp/netconfig.rconly cat <<- EOF >> /tmp/netconfig.rconly PCMCIA=n RC=$rootfs/etc/rc.d/rc.inet1.tradnet IFCONFIG=sbin/ifconfig ROUTE=sbin/route INET1SCHEME=var/run/inet1-scheme IPADDR=127.0.0.1 NETWORK=127.0.0.0 DHCPCD=usr/sbin/dhclient LOOPBACK=y make_config_file EOF rm -f $rootfs/etc/rc.d/rc.inet1.tradnet sh /tmp/netconfig.rconly rm -f /tmp/netconfig.rconly sed -i '/cmdline/s/if/& false \&\&/' $rootfs/etc/rc.d/rc.inet1.tradnet # /etc/rc.d/rc.inet2 sed -i '/rpc.mountd/s/^/#/' $rootfs/etc/rc.d/rc.inet2 sed -i '/modprobe/s/^/#/' $rootfs/etc/rc.d/rc.inet2 # configure to start only the minimum of service chmod 644 $rootfs/etc/rc.d/init.d/saslauthd chmod 644 $rootfs/etc/rc.d/init.d/open-iscsi rm -f $rootfs/etc/rc.d/init.d/postfix rm -f $rootfs/var/log/initpkg/shadow return 0 } copy_configuration() { ret=0 cat <<- EOF >> $path/config || let ret++ lxc.utsname = $name lxc.arch = $arch EOF if [ -f "@LXCTEMPLATECONFIG@/plamo.common.conf" ] ; then cat <<- "EOF" >> $path/config || let ret++ lxc.include = @LXCTEMPLATECONFIG@/plamo.common.conf EOF fi if [ $ret -ne 0 ] ; then echo "Failed to add configuration." return 1 fi return 0 } post_process() { # nothing do in Plamo Linux true } do_bindhome() { # bind-mount the user's path into the container's /home h=`getent passwd $bindhome | cut -d: -f6` mkdir -p $rootfs/$h echo "lxc.mount.entry = $h $rootfs/$h none bind 0 0" >> $path/config # copy /etc/passwd, /etc/shadow, and /etc/group entries into container if ! pwd=`getent passwd $bindhome` ; then echo "Warning: failed to copy password entry for $bindhome." else echo $pwd >> $rootfs/etc/passwd fi echo `getent shadow $bindhome` >> $rootfs/etc/shadow } cleanup() { [ -d $dlcache -a -d $rtcache ] || return 0 # lock, so we won't purge while someone is creating a repository ( if ! flock -n 9 ; then echo "Cache repository is busy." return 1 fi echo "Purging the download cache..." rm -rf --one-file-system $dlcache $rtcache || return 1 echo "Done." return 0 ) 9> @LOCALSTATEDIR@/lock/subsys/lxc-plamo } usage() { cat <<- EOF $prog [-h|--help] -p|--path= -n|--name= --rootfs= [-c|--clean] [-r|--release=] [-a|--arch=] [-b|--bindhome=] release: $release arch: x86 or x86_64: defaults to host arch bindhome: bind 's home into the container EOF } prog=`basename $0` path="" ; name="" ; rootfs="" clean=0 release=${release:-6.x} arch=`uname -m | sed 's/i.86/x86/'` ; hostarch=$arch bindhome="" sopts=hp:n:cr:a:b: lopts=help,path:,name:,rootfs:,clean,release:,arch:,bindhome: if ! options=`getopt -o $sopts -l $lopts -- "$@"` ; then usage exit 1 fi eval set -- "$options" while true ; do case "$1" in -h|--help) usage && exit 0 ;; -p|--path) path=$2 ; shift 2 ;; -n|--name) name=$2 ; shift 2 ;; --rootfs) rootfs=$2 ; shift 2 ;; -c|--clean) clean=1 ; shift 1 ;; -r|--release) release=$2 ; shift 2 ;; -a|--arch) arch=$2 ; shift 2 ;; -b|--bindhome) bindhome=$2 ; shift 2 ;; --) shift 1 ; break ;; *) break ;; esac done if [ $clean -eq 1 -a -z "$path" ] ; then cleanup || exit 1 exit 0 fi if [ $hostarch == "x86" -a $arch == "x86_64" ] ; then echo "Can't create x86_64 container on x86." exit 1 fi if [ -z "$path" ] ; then echo "'path' parameter is required." exit 1 fi if [ -z "$name" ] ; then echo "'name' parameter is required." exit 1 fi if [ `id -u` -ne 0 ] ; then echo "This script should be run as 'root'." exit 1 fi cache="${LXC_CACHE_PATH:-@LOCALSTATEDIR@/cache/lxc}" ptcache=$cache/partial-${prog##*-}-$release-$arch dlcache=$cache/cache-${prog##*-}-$release-$arch rtcache=$cache/rootfs-${prog##*-}-$release-$arch if [ -z "$rootfs" ] ; then if grep -q "^lxc.rootfs" $path/config ; then rootfs=`awk -F= '/^lxc.rootfs =/{ print $2 }' $path/config` else rootfs=$path/rootfs fi fi if ! install_plamo ; then echo "Failed to install plamo $release." exit 1 fi if ! configure_plamo ; then echo "Failed to configure plamo $release for a container." exit 1 fi if ! copy_configuration ; then echo "Failed to write configuration file." exit 1 fi post_process if [ -n "$bindhome" ] ; then do_bindhome fi if [ $clean -eq 1 ] ; then cleanup || exit 1 exit 0 fi lxc-2.0.8/templates/Makefile.in0000644061062106075000000005056613105116776013326 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = templates ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/acinclude.m4 \ $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/tls.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h CONFIG_CLEAN_FILES = lxc-alpine lxc-altlinux lxc-archlinux lxc-busybox \ lxc-centos lxc-cirros lxc-debian lxc-download lxc-fedora \ lxc-gentoo lxc-openmandriva lxc-opensuse lxc-oracle lxc-plamo \ lxc-slackware lxc-sshd lxc-ubuntu lxc-ubuntu-cloud \ lxc-sparclinux CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(templatesdir)" SCRIPTS = $(templates_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/lxc-alpine.in \ $(srcdir)/lxc-altlinux.in $(srcdir)/lxc-archlinux.in \ $(srcdir)/lxc-busybox.in $(srcdir)/lxc-centos.in \ $(srcdir)/lxc-cirros.in $(srcdir)/lxc-debian.in \ $(srcdir)/lxc-download.in $(srcdir)/lxc-fedora.in \ $(srcdir)/lxc-gentoo.in $(srcdir)/lxc-openmandriva.in \ $(srcdir)/lxc-opensuse.in $(srcdir)/lxc-oracle.in \ $(srcdir)/lxc-plamo.in $(srcdir)/lxc-slackware.in \ $(srcdir)/lxc-sparclinux.in $(srcdir)/lxc-sshd.in \ $(srcdir)/lxc-ubuntu-cloud.in $(srcdir)/lxc-ubuntu.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APPARMOR_LIBS = @APPARMOR_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BINDIR = @BINDIR@ CAP_LIBS = @CAP_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CGMANAGER_CFLAGS = @CGMANAGER_CFLAGS@ CGMANAGER_LIBS = @CGMANAGER_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIR = @DATADIR@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFAULT_CGROUP_PATTERN = @DEFAULT_CGROUP_PATTERN@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOCDIR = @DOCDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ HAVE_DOXYGEN = @HAVE_DOXYGEN@ INCLUDEDIR = @INCLUDEDIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDIR = @LIBDIR@ LIBEXECDIR = @LIBEXECDIR@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCALSTATEDIR = @LOCALSTATEDIR@ LOGPATH = @LOGPATH@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBDIR = @LUA_LIBDIR@ LUA_LIBS = @LUA_LIBS@ LUA_SHAREDIR = @LUA_SHAREDIR@ LUA_VERSION = @LUA_VERSION@ LXCBINHOOKDIR = @LXCBINHOOKDIR@ LXCHOOKDIR = @LXCHOOKDIR@ LXCINITDIR = @LXCINITDIR@ LXCPATH = @LXCPATH@ LXCROOTFSMOUNT = @LXCROOTFSMOUNT@ LXCTEMPLATECONFIG = @LXCTEMPLATECONFIG@ LXCTEMPLATEDIR = @LXCTEMPLATEDIR@ LXC_ABI = @LXC_ABI@ LXC_ABI_MAJOR = @LXC_ABI_MAJOR@ LXC_ABI_MICRO = @LXC_ABI_MICRO@ LXC_ABI_MINOR = @LXC_ABI_MINOR@ LXC_DEFAULT_CONFIG = @LXC_DEFAULT_CONFIG@ LXC_DEVEL = @LXC_DEVEL@ LXC_DISTRO_SYSCONF = @LXC_DISTRO_SYSCONF@ LXC_GENERATE_DATE = @LXC_GENERATE_DATE@ LXC_GLOBAL_CONF = @LXC_GLOBAL_CONF@ LXC_USERNIC_CONF = @LXC_USERNIC_CONF@ LXC_USERNIC_DB = @LXC_USERNIC_DB@ LXC_VERSION = @LXC_VERSION@ LXC_VERSION_BASE = @LXC_VERSION_BASE@ LXC_VERSION_BETA = @LXC_VERSION_BETA@ LXC_VERSION_MAJOR = @LXC_VERSION_MAJOR@ LXC_VERSION_MICRO = @LXC_VERSION_MICRO@ LXC_VERSION_MINOR = @LXC_VERSION_MINOR@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NIH_CFLAGS = @NIH_CFLAGS@ NIH_DBUS_CFLAGS = @NIH_DBUS_CFLAGS@ NIH_DBUS_LIBS = @NIH_DBUS_LIBS@ NIH_LIBS = @NIH_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PREFIX = @PREFIX@ PYTHON = @PYTHON@ PYTHONDEV_CFLAGS = @PYTHONDEV_CFLAGS@ PYTHONDEV_LIBS = @PYTHONDEV_LIBS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RUNTIME_PATH = @RUNTIME_PATH@ SBINDIR = @SBINDIR@ SECCOMP_CFLAGS = @SECCOMP_CFLAGS@ SECCOMP_LIBS = @SECCOMP_LIBS@ SED = @SED@ SELINUX_LIBS = @SELINUX_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SYSCONFDIR = @SYSCONFDIR@ SYSTEMD_UNIT_DIR = @SYSTEMD_UNIT_DIR@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bashcompdir = @bashcompdir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ db2xman = @db2xman@ docdir = @docdir@ docdtd = @docdtd@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ templatesdir = @LXCTEMPLATEDIR@ templates_SCRIPTS = \ lxc-alpine \ lxc-altlinux \ lxc-archlinux \ lxc-busybox \ lxc-centos \ lxc-cirros \ lxc-debian \ lxc-download \ lxc-fedora \ lxc-gentoo \ lxc-openmandriva \ lxc-opensuse \ lxc-oracle \ lxc-plamo \ lxc-slackware \ lxc-sshd \ lxc-ubuntu \ lxc-ubuntu-cloud \ lxc-sparclinux all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu templates/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu templates/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): lxc-alpine: $(top_builddir)/config.status $(srcdir)/lxc-alpine.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ lxc-altlinux: $(top_builddir)/config.status $(srcdir)/lxc-altlinux.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ lxc-archlinux: $(top_builddir)/config.status $(srcdir)/lxc-archlinux.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ lxc-busybox: $(top_builddir)/config.status $(srcdir)/lxc-busybox.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ lxc-centos: $(top_builddir)/config.status $(srcdir)/lxc-centos.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ lxc-cirros: $(top_builddir)/config.status $(srcdir)/lxc-cirros.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ lxc-debian: $(top_builddir)/config.status $(srcdir)/lxc-debian.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ lxc-download: $(top_builddir)/config.status $(srcdir)/lxc-download.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ lxc-fedora: $(top_builddir)/config.status $(srcdir)/lxc-fedora.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ lxc-gentoo: $(top_builddir)/config.status $(srcdir)/lxc-gentoo.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ lxc-openmandriva: $(top_builddir)/config.status $(srcdir)/lxc-openmandriva.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ lxc-opensuse: $(top_builddir)/config.status $(srcdir)/lxc-opensuse.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ lxc-oracle: $(top_builddir)/config.status $(srcdir)/lxc-oracle.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ lxc-plamo: $(top_builddir)/config.status $(srcdir)/lxc-plamo.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ lxc-slackware: $(top_builddir)/config.status $(srcdir)/lxc-slackware.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ lxc-sshd: $(top_builddir)/config.status $(srcdir)/lxc-sshd.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ lxc-ubuntu: $(top_builddir)/config.status $(srcdir)/lxc-ubuntu.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ lxc-ubuntu-cloud: $(top_builddir)/config.status $(srcdir)/lxc-ubuntu-cloud.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ lxc-sparclinux: $(top_builddir)/config.status $(srcdir)/lxc-sparclinux.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-templatesSCRIPTS: $(templates_SCRIPTS) @$(NORMAL_INSTALL) @list='$(templates_SCRIPTS)'; test -n "$(templatesdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(templatesdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(templatesdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(templatesdir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(templatesdir)$$dir" || exit $$?; \ } \ ; done uninstall-templatesSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(templates_SCRIPTS)'; test -n "$(templatesdir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(templatesdir)'; $(am__uninstall_files_from_dir) mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(SCRIPTS) installdirs: for dir in "$(DESTDIR)$(templatesdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-templatesSCRIPTS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-templatesSCRIPTS .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip install-templatesSCRIPTS installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am uninstall-templatesSCRIPTS .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lxc-2.0.8/templates/lxc-openmandriva.in0000644061062106075000000003307413105116772015047 00000000000000#!/bin/bash # # template script for generating openmandriva container for LXC # # # lxc: linux Container library # Authors: # Alexander Khryukin # Vokhmin Alexey V # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # # Detect use under userns (unsupported) for arg in "$@"; do [ "$arg" = "--" ] && break if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then echo "This template can't be used for unprivileged containers." 1>&2 echo "You may want to try the \"download\" template instead." 1>&2 exit 1 fi done # Make sure the usual locations are in PATH export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin #Configurations #distro=cooker hostarch=$(uname -m) # Allow the cache base to be set by environment variable cache_base="${LXC_CACHE_PATH:-@LOCALSTATEDIR@/cache/lxc/openmandriva/$arch}" default_path=@LXCPATH@ default_profile=default lxc_network_type=veth lxc_network_link=br0 # is this openmandriva? [ -f /etc/mandriva-release ] && is_openmandriva=true configure_openmandriva() { mkdir -p ${rootfs_path}/etc/sysconfig/network-scripts/ # configure the network using the dhcp cat < ${rootfs_path}/etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 ONBOOT=yes BOOTPROTO=dhcp NM_CONTROLLED=no HOSTNAME=${utsname} EOF # set the hostname cat < ${rootfs_path}/etc/sysconfig/network NETWORKING=yes HOSTNAME=${utsname} EOF echo "${utsname}" > ${rootfs_path}/etc/hostname # set minimal hosts cat < $rootfs_path/etc/hosts 127.0.0.1 localhost.localdomain localhost $utsname ::1 localhost6.localdomain6 localhost6 EOF } populate_dev() { echo -n "Create devices in /dev/" dev_path="${rootfs_path}/dev" rm -rf $dev_path mkdir -p $dev_path mknod -m 666 ${dev_path}/null c 1 3 mknod -m 666 ${dev_path}/zero c 1 5 mknod -m 666 ${dev_path}/random c 1 8 mknod -m 666 ${dev_path}/urandom c 1 9 mkdir -m 755 ${dev_path}/pts mkdir -m 1777 ${dev_path}/shm mknod -m 666 ${dev_path}/tty c 5 0 mknod -m 666 ${dev_path}/tty0 c 4 0 mknod -m 666 ${dev_path}/tty1 c 4 1 mknod -m 666 ${dev_path}/tty2 c 4 2 mknod -m 666 ${dev_path}/tty3 c 4 3 mknod -m 666 ${dev_path}/tty4 c 4 4 mknod -m 600 ${dev_path}/console c 5 1 mknod -m 666 ${dev_path}/full c 1 7 mknod -m 600 ${dev_path}/initctl p mknod -m 666 ${dev_path}/ptmx c 5 2 mkdir -m 755 ${dev_path}/net mknod -m 666 ${dev_path}/net/tun c 10 200 } set_guest_root_password() { [ -z "$root_password" ] && return # pass is empty, abort echo " - setting guest root password.." echo "root passwd is: $root_password" echo "root:$root_password" | chroot "$rootfs_path" chpasswd echo "done." } create_chroot_openmandriva() { # check the mini openmandriva was not already downloaded INSTALL_ROOT=$cache/cache mkdir -p $INSTALL_ROOT if [ $? -ne 0 ]; then echo "Failed to create '$INSTALL_ROOT' directory" return 1 fi # package list to install PKG_LIST="basesystem-minimal locales locales-en initscripts urpmi cronie dhcp-client kbd" # download a mini openmandriva into a cache echo "Downloading openmandriva minimal ..." URPMI="/usr/sbin/urpmi.addmedia --urpmi-root $INSTALL_ROOT main http://abf.rosalinux.ru/downloads/$release/repository/$arch/main/release" echo $URPMI URPMI_BASE="/usr/sbin/urpmi --no-suggests --no-verify-rpm --ignorearch --root $INSTALL_ROOT --urpmi-root $INSTALL_ROOT --auto $PKG_LIST" $URPMI $URPMI_BASE # We're splitting the old loop into two loops plus a directory retrival. # First loop... Try and retrive a mirror list with retries and a slight # delay between attempts... if [ $? -ne 0 ]; then echo "Failed to download the rootfs, aborting." return 1 fi mv "$INSTALL_ROOT" "$cache/rootfs" echo "Download complete." return 0 } copy_openmandriva() { echo -n "Copying rootfs to $rootfs_path ..." mkdir -p $rootfs_path rsync -Ha $cache/rootfs/ $rootfs_path/ return 0 } update_openmandriva() { echo "automated update in progress..." urpmi --root $cache/rootfs --urpmi-root $cache/rootfs --auto --auto-update --ignorearch } configure_openmandriva_systemd() { chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/proc-sys-fs-binfmt_misc.automount chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/systemd-udevd.service chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/systemd-udevd-control.socket chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/systemd-udevd-kernel.socket # remove numlock service # KDGKBLED: Inappropriate ioctl for device rm -f ${rootfs_path}/etc/systemd/system/getty@.service.d/enable-numlock.conf unlink ${rootfs_path}/etc/systemd/system/default.target chroot ${rootfs_path} ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target sed -i 's!ConditionPathExists=/dev/tty0!ConditionPathExists=|/dev/tty0\nConditionVirtualization=|lxc!' \ ${rootfs_path}/lib/systemd/system/getty\@.service } install_openmandriva() { mkdir -p @LOCALSTATEDIR@/lock/subsys/ ( flock -x 9 if [ $? -ne 0 ]; then echo "Cache repository is busy." return 1 fi echo "Checking cache download in $cache/rootfs ... " if [ ! -e "$cache/rootfs" ]; then echo $cache/rootfs create_chroot_openmandriva if [ $? -ne 0 ]; then echo "Failed to download 'openmandriva basesystem-minimal'" return 1 fi else echo "Cache found. Updating..." update_openmandriva if [ $? -ne 0 ]; then echo "Failed to update 'openmandriva base', continuing with last known good cache" else echo "Update finished" fi fi echo "Copy $cache/rootfs to $rootfs_path ... " copy_openmandriva if [ $? -ne 0 ]; then echo "Failed to copy rootfs" return 1 fi return 0 ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-openmandriva return $? } copy_configuration() { mkdir -p $config_path grep -q "^lxc.rootfs" $config_path/config 2>/dev/null || echo "lxc.rootfs = $rootfs_path" >> $config_path/config cat <> $config_path/config lxc.utsname = $name lxc.tty = 4 lxc.pts = 1024 lxc.cap.drop = sys_module mac_admin mac_override sys_time lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed # When using LXC with apparmor, uncomment the next line to run unconfined: #lxc.aa_profile = unconfined #networking lxc.network.type = $lxc_network_type lxc.network.flags = up lxc.network.link = $lxc_network_link lxc.network.name = eth0 lxc.network.mtu = 1500 EOF if [ ! -z ${ipv4} ]; then cat <> $config_path/config lxc.network.ipv4 = $ipv4 EOF fi if [ ! -z ${gw} ]; then cat <> $config_path/config lxc.network.ipv4.gateway = $gw EOF fi if [ ! -z ${ipv6} ]; then cat <> $config_path/config lxc.network.ipv6 = $ipv6 EOF fi if [ ! -z ${gw6} ]; then cat <> $config_path/config lxc.network.ipv6.gateway = $gw6 EOF fi cat <> $config_path/config #cgroups lxc.cgroup.devices.deny = a # /dev/null and zero lxc.cgroup.devices.allow = c 1:3 rwm lxc.cgroup.devices.allow = c 1:5 rwm # consoles lxc.cgroup.devices.allow = c 5:1 rwm lxc.cgroup.devices.allow = c 5:0 rwm lxc.cgroup.devices.allow = c 4:0 rwm lxc.cgroup.devices.allow = c 4:1 rwm # /dev/{,u}random lxc.cgroup.devices.allow = c 1:9 rwm lxc.cgroup.devices.allow = c 1:8 rwm lxc.cgroup.devices.allow = c 136:* rwm lxc.cgroup.devices.allow = c 5:2 rwm # rtc lxc.cgroup.devices.allow = c 10:135 rwm EOF if [ $? -ne 0 ]; then echo "Failed to add configuration" return 1 fi return 0 } clean() { if [ ! -e $cache ]; then exit 0 fi # lock, so we won't purge while someone is creating a repository ( flock -x 9 if [ $? != 0 ]; then echo "Cache repository is busy." exit 1 fi echo -n "Purging the download cache for OpenMandriva-$release..." rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1 exit 0 ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-openmandriva } usage() { cat < [-p|--path=] [-c|--clean] [-R|--release=] [-4|--ipv4=] [-6|--ipv6=] [-g|--gw=] [-d|--dns=] [-P|--profile=] [--rootfs=] [-A|--arch=] [-h|--help] Mandatory args: -n,--name container name, used to as an identifier for that container from now on Optional args: -p,--path path to where the container rootfs will be created, defaults to @LXCPATH@. The container config will go under @LXCPATH@ in that case -c,--clean clean the cache -R,--release openmandriva2013.0/cooker/rosa2012.1 release for the new container. if the host is OpenMandriva, then it will default to the host's release. -4,--ipv4 specify the ipv4 address to assign to the virtualized interface, eg. 192.168.1.123/24 -6,--ipv6 specify the ipv6 address to assign to the virtualized interface, eg. 2003:db8:1:0:214:1234:fe0b:3596/64 -g,--gw specify the default gw, eg. 192.168.1.1 -G,--gw6 specify the default gw, eg. 2003:db8:1:0:214:1234:fe0b:3596 -d,--dns specify the DNS server, eg. 192.168.1.2 -P,--profile Profile name is the file name in /etc/lxc/profiles contained packages name for install to cache. -A,--arch Define what arch the container will be [i586,x86_64,armv7l,armv7hl] ---rootfs rootfs path -h,--help print this help EOF return 0 } options=$(getopt -o hp:n:P:cR:4:6:g:d:A -l help,rootfs:,path:,name:,profile:,clean:,release:,ipv4:,ipv6:,gw:,dns:,arch: -- "$@") if [ $? -ne 0 ]; then usage $(basename $0) exit 1 fi eval set -- "$options" release=${release:-"cooker"} if [ -f /etc/lsb-release ]; then . /etc/lsb-release if [ "$DISTRIB_ID" = "OpenMandrivaLinux" ]; then release=openmandriva2013.0 elif [ "$DISTRIB_ID" = "RosaDesktop.Fresh" ]; then release=rosa2012.1 else echo "This is not an OpenMandriva or ROSA release" exit 1 fi fi while true do case "$1" in -h|--help) usage $0 && exit 0;; -p|--path) path=$2; shift 2;; --rootfs) rootfs_path=$2; shift 2;; -n|--name) name=$2; shift 2;; -P|--profile) profile=$2; shift 2;; -c|--clean) clean=1; shift 1;; -R|--release) release=$2; shift 2;; -A|--arch) arch=$2; shift 2;; -4|--ipv4) ipv4=$2; shift 2;; -6|--ipv6) ipv6=$2; shift 2;; -g|--gw) gw=$2; shift 2;; -d|--dns) dns=$2; shift 2;; --) shift 1; break ;; *) break ;; esac done arch=${arch:-$hostarch} if [ ! -z "$clean" -a -z "$path" ]; then clean || exit 1 exit 0 fi if [ -z "${utsname}" ]; then utsname=${name} fi type urpmi >/dev/null 2>&1 if [ $? -ne 0 ]; then echo "'urpmi' command is missing" exit 1 fi if [ -z "$path" ]; then path=$default_path fi if [ -z "$profile" ]; then profile=$default_profile fi if [ $hostarch = "i586" -a $arch = "x86_64" ]; then echo "can't create x86_64 container on i586" exit 1 fi if [ -z "$ipv4" -a -z "$ipv6" ]; then BOOTPROTO="dhcp" else BOOTPROTO="static" fi if [ "$(id -u)" != "0" ]; then echo "This script should be run as 'root'" exit 1 fi # check for 'lxc.rootfs' passed in through default config by lxc-create if [ -z "$rootfs_path" ]; then if grep -q '^lxc.rootfs' $path/config 2>/dev/null ; then rootfs_path=$(awk -F= '/^lxc.rootfs =/{ print $2 }' $path/config) else rootfs_path=$path/$name/rootfs fi fi config_path=$default_path/$name cache=$cache_base/$release/$arch/$profile if [ ! -f $config_path/config ]; then echo "A container with that name exists, chose a different name" exit 1 fi install_openmandriva if [ $? -ne 0 ]; then echo "failed to install openmandriva" exit 1 fi configure_openmandriva if [ $? -ne 0 ]; then echo "failed to configure openmandriva for a container" exit 1 fi # If the systemd configuration directory exists - set it up for what we need. if [ -d ${rootfs_path}/etc/systemd/system ] then configure_openmandriva_systemd fi populate_dev if [ $? -ne 0 ]; then echo "failed to populated /dev/ devices" exit 1 fi set_guest_root_password if [ $? -ne 0 ]; then echo "failed to configure password for chroot" exit 1 fi copy_configuration if [ $? -ne 0 ]; then echo "failed write configuration file" exit 1 fi if [ ! -z "$clean" ]; then clean || exit 1 exit 0 fi echo "container rootfs and config created" lxc-2.0.8/templates/lxc-ubuntu-cloud.in0000644061062106075000000002672713105116772015021 00000000000000#!/bin/bash # template script for generating ubuntu container for LXC based on released # cloud images. # # Copyright © 2012 Serge Hallyn # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA set -e STATE_DIR="@LOCALSTATEDIR@" HOOK_DIR="@LXCHOOKDIR@" CLONE_HOOK_FN="$HOOK_DIR/ubuntu-cloud-prep" LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@" KNOWN_RELEASES="precise trusty xenial yakkety zesty" skip_arch_check=${UCTEMPLATE_SKIP_ARCH_CHECK:-0} # Make sure the usual locations are in PATH export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin if [ -r /etc/default/lxc ]; then . /etc/default/lxc fi am_in_userns() { [ -e /proc/self/uid_map ] || { echo no; return; } [ "$(wc -l /proc/self/uid_map | awk '{ print $1 }')" -eq 1 ] || { echo yes; return; } line=$(awk '{ print $1 " " $2 " " $3 }' /proc/self/uid_map) [ "$line" = "0 0 4294967295" ] && { echo no; return; } echo yes } in_userns=0 [ $(am_in_userns) = "yes" ] && in_userns=1 copy_configuration() { path=$1 rootfs=$2 name=$3 arch=$4 release=$5 if [ $arch = "i386" ]; then arch="i686" fi # if there is exactly one veth network entry, make sure it has an # associated hwaddr. nics=`grep -e '^lxc\.network\.type[ \t]*=[ \t]*veth' $path/config | wc -l` if [ $nics -eq 1 ]; then grep -q "^lxc.network.hwaddr" $path/config || sed -i -e "/^lxc\.network\.type[ \t]*=[ \t]*veth/a lxc.network.hwaddr = 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')" $path/config fi # Generate the configuration file ## Relocate all the network config entries sed -i -e "/lxc.network/{w ${path}/config-network" -e "d}" $path/config ## Relocate any other config entries sed -i -e "/lxc./{w ${path}/config-auto" -e "d}" $path/config ## Add all the includes echo "" >> $path/config echo "# Common configuration" >> $path/config if [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.common.conf" ]; then echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.common.conf" >> $path/config fi if [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.${release}.conf" ]; then echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.${release}.conf" >> $path/config fi if [ $in_userns -eq 1 ] && [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.userns.conf" ]; then echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.userns.conf" >> $path/config fi ## Add the container-specific config echo "" >> $path/config echo "# Container specific configuration" >> $path/config [ -e "$path/config-auto" ] && cat $path/config-auto >> $path/config && rm $path/config-auto grep -q "^lxc.rootfs" $path/config 2>/dev/null || echo "lxc.rootfs = $rootfs" >> $path/config cat <> $path/config lxc.utsname = $name lxc.arch = $arch EOF ## Re-add the previously removed network config echo "" >> $path/config echo "# Network configuration" >> $path/config cat $path/config-network >> $path/config rm $path/config-network # Set initial timezone as on host if [ -f /etc/timezone ]; then cat /etc/timezone > $rootfs/etc/timezone chroot $rootfs dpkg-reconfigure -f noninteractive tzdata elif [ -f /etc/sysconfig/clock ]; then . /etc/sysconfig/clock echo $ZONE > $rootfs/etc/timezone chroot $rootfs dpkg-reconfigure -f noninteractive tzdata else echo "Timezone in container is not configured. Adjust it manually." fi # rmdir /dev/shm for containers that have /run/shm # I'm afraid of doing rm -rf $rootfs/dev/shm, in case it did # get bind mounted to the host's /run/shm. So try to rmdir # it, and in case that fails move it out of the way. # NOTE: This can only be removed once 12.04 goes out of support if [ ! -L $rootfs/dev/shm ] && [ -e $rootfs/dev/shm ]; then rmdir $rootfs/dev/shm 2>/dev/null || mv $rootfs/dev/shm $rootfs/dev/shm.bak ln -s /run/shm $rootfs/dev/shm fi return 0 } usage() { cat < ]: Release name of container, defaults to host [ --rootfs ]: Path in which rootfs will be placed [ -a | --arch ]: Architecture of container, defaults to host architecture [ -T | --tarball ]: Location of tarball [ -d | --debug ]: Run with 'set -x' to debug errors [ -s | --stream]: Use specified stream rather than 'tryreleased' Additionally, clone hooks can be passed through (ie, --userdata). For those, see: $CLONE_HOOK_FN --help EOF return 0 } options=$(getopt -o a:hp:r:n:Fi:CLS:T:ds:u: -l arch:,help,rootfs:,path:,release:,name:,flush-cache,hostid:,auth-key:,cloud,no_locales,tarball:,debug,stream:,userdata:,vendordata:,mapped-uid:,mapped-gid: -- "$@") if [ $? -ne 0 ]; then usage $(basename $0) exit 1 fi eval set -- "$options" mapped_uid=-1 mapped_gid=-1 # default release is trusty, or the systems release if recognized release=trusty if [ -f /etc/lsb-release ]; then . /etc/lsb-release rels=$(ubuntu-distro-info --supported 2>/dev/null) || rels="$KNOWN_RELEASES" for r in $rels; do [ "$DISTRIB_CODENAME" = "$r" ] && release="$r" done fi # Code taken from debootstrap if [ -x /usr/bin/dpkg ] && /usr/bin/dpkg --print-architecture >/dev/null 2>&1; then arch=`/usr/bin/dpkg --print-architecture` elif type udpkg >/dev/null 2>&1 && udpkg --print-architecture >/dev/null 2>&1; then arch=`/usr/bin/udpkg --print-architecture` else arch=$(uname -m) if [ "$arch" = "i686" ]; then arch="i386" elif [ "$arch" = "x86_64" ]; then arch="amd64" elif [ "$arch" = "armv7l" ]; then # note: arm images don't exist before oneiric; are called armhf in # trusty and later; and are not supported by the query, so we don't actually # support them yet (see check later on). When Query2 is available, # we'll use that to enable arm images. arch="armhf" elif [ "$arch" = "aarch64" ]; then arch="arm64" elif [ "$arch" = "ppc64le" ]; then arch="ppc64el" fi fi debug=0 hostarch=$arch cloud=0 locales=1 flushcache=0 stream="tryreleased" cloneargs=() while true do case "$1" in -h|--help) usage $0 && exit 1;; -p|--path) path=$2; shift 2;; -n|--name) name=$2; shift 2;; -F|--flush-cache) flushcache=1; shift 1;; -r|--release) release=$2; shift 2;; -a|--arch) arch=$2; shift 2;; -T|--tarball) tarball=$2; shift 2;; -d|--debug) debug=1; shift 1;; -s|--stream) stream=$2; shift 2;; --rootfs) rootfs=$2; shift 2;; -L|--no?locales) cloneargs[${#cloneargs[@]}]="--no-locales"; shift 1;; -i|--hostid) cloneargs[${#cloneargs[@]}]="--hostid=$2"; shift 2;; -u|--userdata) cloneargs[${#cloneargs[@]}]="--userdata=$2"; shift 2;; -V|--vendordata) cloneargs[${#cloneargs[@]}]="--vendordata=$2"; shift 2;; -C|--cloud) cloneargs[${#cloneargs[@]}]="--cloud"; shift 1;; -S|--auth-key) cloneargs[${#cloneargs[@]}]="--auth-key=$2"; shift 2;; --mapped-uid) mapped_uid=$2; shift 2;; --mapped-gid) mapped_gid=$2; shift 2;; --) shift 1; break ;; *) break ;; esac done cloneargs=( "--name=$name" "${cloneargs[@]}" ) if [ $debug -eq 1 ]; then set -x fi if [ "$arch" = "i686" ]; then arch=i386 fi if [ "$skip_arch_check" = "0" ]; then case "$hostarch:$arch" in $arch:$arch) : ;; # the host == container amd64:i386) :;; # supported "cross" arm64:arm*) :;; # supported "cross" armel:armhf) :;; # supported "cross" armhf:armel) :;; # supported "cross" *) echo "cannot create '$arch' container on hostarch '$hostarch'"; exit 1;; esac fi if [ "$stream" != "daily" -a "$stream" != "released" -a "$stream" != "tryreleased" ]; then echo "Only 'daily' and 'released' and 'tryreleased' streams are supported" exit 1 fi if [ -z "$path" ]; then echo "'path' parameter is required" exit 1 fi if [ "$(id -u)" != "0" ]; then echo "This script should be run as 'root'" exit 1 fi # detect rootfs config="$path/config" if [ -z "$rootfs" ]; then if grep -q '^lxc.rootfs' $config 2>/dev/null ; then rootfs=$(awk -F= '/^lxc.rootfs =/{ print $2 }' $config) else rootfs=$path/rootfs fi fi type ubuntu-cloudimg-query type wget # determine the url, tarball, and directory names # download if needed # Allow the cache base to be set by environment variable cache=${LXC_CACHE_PATH:-"$STATE_DIR/cache/lxc"}/cloud-$release if [ $in_userns -eq 1 ]; then STATE_DIR="$HOME/.cache/lxc" cache=${LXC_CACHE_PATH:-"$STATE_DIR"}/cloud-$release fi mkdir -p $cache if [ "$stream" = "tryreleased" ]; then stream=released ubuntu-cloudimg-query $release $stream $arch 1>/dev/null 2>/dev/null || stream=daily fi if [ -n "$tarball" ]; then url2="$tarball" else if ! url1=`ubuntu-cloudimg-query $release $stream $arch --format "%{url}\n"`; then echo "There is no download available for release=$release, stream=$stream, arch=$arch" [ "$stream" = "daily" ] || echo "You may try with '--stream=daily'" exit 1 fi if [ "$release" = "precise" ] || [ "$release" = "trusty" ]; then url2=`echo $url1 | sed -e 's/.tar.gz/-root\0/' -e 's/.tar.gz/.tar.xz/'` else url2=`echo $url1 | sed -e 's/.tar.gz/.squashfs/'` fi fi filename=`basename $url2` wgetcleanup() { rm -f $filename } do_extract_rootfs() { cd $cache if [ $flushcache -eq 1 ]; then echo "Clearing the cached images" rm -f $filename fi trap wgetcleanup EXIT SIGHUP SIGINT SIGTERM if [ ! -f $filename ]; then wget $url2 fi trap EXIT trap SIGHUP trap SIGINT trap SIGTERM echo "Extracting container rootfs" mkdir -p $rootfs cd $rootfs if [ "${filename##*.}" = "squashfs" ]; then unsquashfs -n -f -d "$rootfs" "$cache/$filename" else if [ $in_userns -eq 1 ]; then tar --anchored --exclude="dev/*" --numeric-owner -xpf "$cache/$filename" mkdir -p $rootfs/dev/pts/ else tar --numeric-owner -xpf "$cache/$filename" fi fi } if [ -n "$tarball" ]; then do_extract_rootfs else mkdir -p "$STATE_DIR/lock/subsys/" ( flock -x 9 do_extract_rootfs ) 9>"$STATE_DIR/lock/subsys/lxc-ubuntu-cloud" fi copy_configuration $path $rootfs $name $arch $release "$CLONE_HOOK_FN" "${cloneargs[@]}" "$rootfs" if [ $mapped_uid -ne -1 ]; then chown $mapped_uid $path/config chown -R $mapped_uid $STATE_DIR chown -R $mapped_uid $cache fi if [ $mapped_gid -ne -1 ]; then chgrp $mapped_gid $path/config chgrp -R $mapped_gid $STATE_DIR chgrp -R $mapped_gid $cache fi echo "Container $name created." exit 0 # vi: ts=4 expandtab lxc-2.0.8/templates/lxc-sshd.in0000644061062106075000000001523613105116772013325 00000000000000#!/bin/bash # # lxc: linux Container library # Authors: # Daniel Lezcano # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Detect use under userns (unsupported) for arg in "$@"; do [ "$arg" = "--" ] && break if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then echo "This template can't be used for unprivileged containers." 1>&2 echo "You may want to try the \"download\" template instead." 1>&2 exit 1 fi done # Make sure the usual locations are in PATH export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin install_sshd() { rootfs=$1 tree="\ $rootfs/var/empty/sshd \ $rootfs/var/lib/empty/sshd \ $rootfs/etc/init.d \ $rootfs/etc/rc.d \ $rootfs/etc/ssh \ $rootfs/etc/sysconfig/network-scripts \ $rootfs/dev/shm \ $rootfs/run/sshd \ $rootfs/proc \ $rootfs/sys \ $rootfs/bin \ $rootfs/sbin \ $rootfs/usr \ $rootfs/tmp \ $rootfs/home \ $rootfs/root \ $rootfs/lib \ $rootfs/lib64" mkdir -p $tree if [ $? -ne 0 ]; then return 1 fi ln -s /run $rootfs/var/run if [ $? -ne 0 ]; then return 1 fi return 0 } configure_sshd() { rootfs=$1 cat < $rootfs/etc/passwd root:x:0:0:root:/root:/bin/bash sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin EOF cat < $rootfs/etc/group root:x:0:root sshd:x:74: EOF ssh-keygen -t rsa -N "" -f $rootfs/etc/ssh/ssh_host_rsa_key ssh-keygen -t dsa -N "" -f $rootfs/etc/ssh/ssh_host_dsa_key # by default setup root password with no password cat < $rootfs/etc/ssh/sshd_config Port 22 Protocol 2 HostKey /etc/ssh/ssh_host_rsa_key HostKey /etc/ssh/ssh_host_dsa_key UsePrivilegeSeparation yes SyslogFacility AUTH LogLevel INFO LoginGraceTime 120 PermitRootLogin yes StrictModes yes PubkeyAuthentication yes IgnoreRhosts yes HostbasedAuthentication no PermitEmptyPasswords yes ChallengeResponseAuthentication no EOF if [ -n "$auth_key" -a -f "$auth_key" ]; then u_path="/root/.ssh" root_u_path="$rootfs/$u_path" mkdir -p $root_u_path cp $auth_key "$root_u_path/authorized_keys" chown -R 0:0 "$rootfs/$u_path" chmod 700 "$rootfs/$u_path" echo "Inserted SSH public key from $auth_key into $rootfs/$u_path" fi return 0 } copy_configuration() { path=$1 rootfs=$2 name=$3 init_path=$(realpath --relative-to=/ $(readlink -f /sbin/init)) grep -q "^lxc.rootfs" $path/config 2>/dev/null || echo "lxc.rootfs = $rootfs" >> $path/config cat <> $path/config lxc.utsname = $name lxc.pts = 1024 lxc.cap.drop = sys_module mac_admin mac_override sys_time # When using LXC with apparmor, uncomment the next line to run unconfined: #lxc.aa_profile = unconfined lxc.mount.entry = /dev dev none ro,bind 0 0 lxc.mount.entry = /lib lib none ro,bind 0 0 lxc.mount.entry = /bin bin none ro,bind 0 0 lxc.mount.entry = /usr usr none ro,bind 0 0 lxc.mount.entry = /sbin sbin none ro,bind 0 0 lxc.mount.entry = tmpfs run/sshd tmpfs mode=0644 0 0 lxc.mount.entry = @LXCTEMPLATEDIR@/lxc-sshd $init_path none ro,bind 0 0 lxc.mount.entry = /etc/init.d etc/init.d none ro,bind 0 0 lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed EOF # Oracle Linux and Fedora need the following two bind mounted if [ -d /etc/sysconfig/network-scripts ]; then cat <> $path/config lxc.mount.entry = /etc/sysconfig/network-scripts etc/sysconfig/network-scripts none ro,bind 0 0 EOF fi if [ -d /etc/rc.d ]; then cat <> $path/config lxc.mount.entry = /etc/rc.d etc/rc.d none ro,bind 0 0 EOF fi # if no .ipv4 section in config, then have the container run dhcp grep -q "^lxc.network.ipv4" $path/config || touch $rootfs/run-dhcp if [ "$(uname -m)" = "x86_64" ]; then cat <> $path/config lxc.mount.entry = /lib64 lib64 none ro,bind 0 0 EOF fi } usage() { cat < [--rootfs=] EOF return 0 } check_for_cmd() { cmd_path=`type $1` if [ $? -ne 0 ]; then echo "The command '$1' $cmd_path is not accessible on the system" exit 1 fi # we use cut instead of awk because awk is alternatives symlink on ubuntu # and /etc/alternatives isn't bind mounted cmd_path=`echo $cmd_path |cut -d ' ' -f 3` } options=$(getopt -o hp:n:S: -l help,rootfs:,path:,name:,auth-key: -- "$@") if [ $? -ne 0 ]; then usage $(basename $0) exit 1 fi eval set -- "$options" while true do case "$1" in -h|--help) usage $0 && exit 0;; -p|--path) path=$2; shift 2;; --rootfs) rootfs=$2; shift 2;; -n|--name) name=$2; shift 2;; -S|--auth-key) auth_key=$2; shift 2;; --) shift 1; break ;; *) break ;; esac done if [ "$(id -u)" != "0" ]; then echo "This script should be run as 'root'" exit 1 fi if [ $0 = "/sbin/init" ]; then PATH="$PATH:/bin:/sbin:/usr/sbin" check_for_cmd @SBINDIR@/init.lxc check_for_cmd sshd sshd_path=$cmd_path # run dhcp? if [ -f /run-dhcp ]; then check_for_cmd dhclient check_for_cmd ifconfig touch /etc/fstab rm -f /dhclient.conf cat > /dhclient.conf << EOF send host-name = gethostname(); EOF ifconfig eth0 up dhclient eth0 -cf /dhclient.conf echo "Container IP address:" ifconfig eth0 |grep inet fi exec @SBINDIR@/init.lxc -- $sshd_path exit 1 fi if [ -z "$path" ]; then echo "'path' parameter is required" exit 1 fi # detect rootfs config="$path/config" if [ -z "$rootfs" ]; then if grep -q '^lxc.rootfs' $config 2>/dev/null ; then rootfs=$(awk -F= '/^lxc.rootfs =/{ print $2 }' $config) else rootfs=$path/rootfs fi fi install_sshd $rootfs if [ $? -ne 0 ]; then echo "failed to install sshd's rootfs" exit 1 fi configure_sshd $rootfs if [ $? -ne 0 ]; then echo "failed to configure sshd template" exit 1 fi copy_configuration $path $rootfs $name if [ $? -ne 0 ]; then echo "failed to write configuration file" exit 1 fi lxc-2.0.8/templates/lxc-cirros.in0000644061062106075000000002421713105116772013664 00000000000000#!/bin/bash # template script for generating ubuntu container for LXC # # This script consolidates and extends the existing lxc ubuntu scripts # # Copyright © 2013 Canonical Ltd. # Author: Scott Moser # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2, as # published by the Free Software Foundation. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # Detect use under userns (unsupported) # Make sure the usual locations are in PATH export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin VERBOSITY=0 DOWNLOAD_URL="http://download.cirros-cloud.net/" UNAME_M=$(uname -m) ARCHES=( i386 x86_64 amd64 arm ) STREAMS=( released devel ) SOURCES=( nocloud none ) BUILD="standard" LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@" LXC_MAPPED_GID= LXC_MAPPED_UID= DEF_VERSION="released" DEF_SOURCE="nocloud" case "${UNAME_M}" in i?86) DEF_ARCH="i386";; x86_64) DEF_ARCH="x86_64";; arm*) DEF_ARCH="arm";; *) DEF_ARCH="i386";; esac am_in_userns() { [ -e /proc/self/uid_map ] || { echo no; return; } [ "$(wc -l /proc/self/uid_map | awk '{ print $1 }')" -eq 1 ] || { echo yes; return; } line=$(awk '{ print $1 " " $2 " " $3 }' /proc/self/uid_map) [ "$line" = "0 0 4294967295" ] && { echo no; return; } echo yes } in_userns=0 [ $(am_in_userns) = "yes" ] && in_userns=1 # Allow the cache base to be set by environment variable if [ $(id -u) -eq 0 ]; then CACHE_D=${LXC_CACHE_PATH:-"@LOCALSTATEDIR@/cache/lxc/cirros"} else CACHE_D=${LXC_CACHE_PATH:-"$HOME/.cache/lxc/cirros"} fi error() { echo "$@" 1>&2; } inargs() { local needle="$1" x="" shift for x in "$@"; do [ "$needle" = "$x" ] && return 0 done return 1 } Usage() { cat <&2; [ $# -eq 0 ] || error "$@"; return 1; } debug() { local level=${1}; shift; [ "${level}" -gt "${VERBOSITY}" ] && return error "${@}" } jsondict() { local k="" v="" ret="{" for arg in "$@"; do k="${arg%%=*}" v="${arg#*=}" ret="${ret} \"${k}\": \"$v\"," done ret="${ret%,} }" echo "$ret" } copy_configuration() { local path=$1 rootfs=$2 name=$3 arch=$4 release=$5 cat >> "$path/config" <> $path/config fi } insert_ds_nocloud() { local root_d="$1" authkey="$2" udfile="$3" local sdir="$root_d/var/lib/cloud/seed/nocloud" mkdir -p "$sdir" || { error "failed to make datasource dir $sdir"; return 1; } rm -f "$sdir/meta-data" "$sdir/user-data" || { error "failed to clean old data from $sdir"; return 1; } iid="iid-local01" jsondict "instance-id=$iid" \ ${authkeys:+"public-keys=${authkeys}"} > "$sdir/meta-data" || { error "failed to write metadata to $sdir/meta-data"; return 1; } if [ -n "$udfile" ]; then cat "$udfile" > "$sdir/user-data" || { error "failed to write user-data to $sdir"; return 1; } else rm -f "$sdir/user-data" fi } insert_ds() { local dstype="$1" root_d="$2" authkey="$3" udfile="$4" case "$dstype" in nocloud) insert_ds_nocloud "$root_d" "$authkey" "$udfile" esac } extract_rootfs() { local tarball="$1" rootfs_d="$2" mkdir -p "${rootfs_d}" || { error "failed to make rootfs dir ${rootfs_d}"; return 1; } if [ $in_userns -eq 1 ]; then tar -C "${rootfs_d}" --anchored --exclude="dev/*" -Sxzf "${tarball}" || { error "failed to populate ${rootfs_d}"; return 1; } else tar -C "${rootfs_d}" -Sxzf "${tarball}" || { error "failed to populate ${rootfs_d}"; return 1; } fi return 0 } download_tarball() { local arch="$1" ver="$2" cached="$3" baseurl="$4" local out="" outd="" file="" dlpath="" file="cirros-$ver-$arch-lxc.tar.gz" dlpath="$ver/$file" outd="${cached}/${dlpath%/*}" if [ -f "$cached/$dlpath" ]; then _RET="$cached/$dlpath" return 0 fi mkdir -p "${outd}" || { error "failed to create ${outd}"; return 1; } debug 1 "downloading ${baseurl%/}/$dlpath" to "${cached}/$dlpath" wget "${baseurl%/}/$dlpath" -O "$cached/${dlpath}.$$" && mv "$cached/$dlpath.$$" "$cached/$dlpath" || { rm -f "$cached/$dlpath.$$"; error "failed to download $dlpath"; return 1; } _RET="$cached/$dlpath" } create_main() { local short_opts="a:hn:p:S:uvV" local long_opts="arch:,auth-key:,name:,path:,tarball:,userdata:,verbose,version:,rootfs:,mapped-uid:,mapped-gid:" local getopt_out="" getopt_out=$(getopt --name "${0##*/}" \ --options "${short_opts}" --long "${long_opts}" -- "$@") && eval set -- "${getopt_out}" || { bad_Usage; return; } local arch="${DEF_ARCH}" dsource="${DEF_SOURCE}" version="${DEF_VERSION}" local authkey_f="" authkeys="" userdata_f="" path="" tarball="" local cur="" next="" local rootfs_d="" while [ $# -ne 0 ]; do cur=$1; next=$2; case "$cur" in -a|--arch) arch="$next"; shift;; -h|--help) Usage ; return 0;; -n|--name) name="$next"; shift;; -v|--verbose) VERBOSITY=$((${VERBOSITY}+1));; -S|--auth-key) authkey_f="$next"; shift;; -p|--path) path=$next; shift;; -v|--version) version=$next; shift;; -u|--userdata) userdata_f="$next"; shift;; --tarball) tarball="$next"; shift;; --source) dsource="$next"; shift;; --rootfs) rootfs_d="$next"; shift;; --mapped-uid) LXC_MAPPED_UID=$next; shift;; --mapped-gid) LXC_MAPPED_GID=$next; shift;; --) shift; break;; esac shift; done [ -n "$rootfs_d" ] || rootfs_d="$path/rootfs" [ $# -eq 0 ] || { bad_Usage "unexpected arguments: $*"; return; } [ -n "$path" ] || { error "'path' parameter is required"; return 1; } if [ "$(id -u)" != "0" ]; then { error "must be run as root"; return 1; } fi case "$arch" in i?86) arch="i386";; amd64) arch="x86_64";; esac inargs "$arch" "${ARCHES[@]}" || { error "bad arch '$arch'. allowed: ${ARCHES[*]}"; return 1; } inargs "$dsource" "${SOURCES[@]}" || { error "bad source '$dsource'. allowed: ${SOURCES[*]}"; return 1; } if [ "$dsource" = "none" ] && [ -n "$userdata_f" -o -n "$authkey_f" ]; then error "userdata and authkey are incompatible with --source=none"; return 1; fi if [ -n "$authkey_f" ]; then if [ ! -f "$authkey_f" ]; then error "--auth-key=${authkey_f} must reference a file" return 1 fi authkeys=$(cat "$authkey_f") || { error "failed to read ${authkey_f}"; return 1; } fi if [ -n "$userdata_f" -a ! -f "${userdata_f}" ]; then error "${userdata_f}: --userdata arg not a file" return 1 fi if [ -z "$tarball" ]; then if inargs "$version" "${STREAMS[@]}"; then out=$(wget -O - -q "${DOWNLOAD_URL%/}/version/$version") || { error "failed to convert 'version=$version'"; return 1; } version="$out" fi download_tarball "$arch" "$version" "${CACHE_D}" "${DOWNLOAD_URL}" || return tarball="$_RET" fi extract_rootfs "${tarball}" "${rootfs_d}" || return if [ "$version" = "0.3.2~pre1" ]; then debug 1 "fixing console for lxc and '$version'" sed -i 's,^\(#console.* 115200 \)# /dev/console,\1 console,g' \ "$rootfs_d/etc/inittab" || { error "failed to fix console entry for $version"; return 1; } fi if [ "$dsource" != "none" ]; then insert_ds "$dsource" "$path/rootfs" "$authkeys" "$userdata_f" || { error "failed to insert userdata to $path/rootfs" return 1 } fi copy_configuration "$path" "$path/rootfs" "$name" "$arch" "$release" return } create_main "$@" # vi: ts=4 expandtab lxc-2.0.8/templates/Makefile.am0000644061062106075000000000052713105116772013301 00000000000000templatesdir=@LXCTEMPLATEDIR@ templates_SCRIPTS = \ lxc-alpine \ lxc-altlinux \ lxc-archlinux \ lxc-busybox \ lxc-centos \ lxc-cirros \ lxc-debian \ lxc-download \ lxc-fedora \ lxc-gentoo \ lxc-openmandriva \ lxc-opensuse \ lxc-oracle \ lxc-plamo \ lxc-slackware \ lxc-sshd \ lxc-ubuntu \ lxc-ubuntu-cloud \ lxc-sparclinux lxc-2.0.8/configure.ac0000644061062106075000000007341513105116772011543 00000000000000# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. m4_define([lxc_devel], 0) m4_define([lxc_version_major], 2) m4_define([lxc_version_minor], 0) m4_define([lxc_version_micro], 8) m4_define([lxc_version_beta], []) m4_define([lxc_abi_major], 1) m4_define([lxc_abi_minor], 2) m4_define([lxc_abi_micro], 0) m4_define([lxc_abi], [lxc_abi_major.lxc_abi_minor.lxc_abi_micro]) m4_define([lxc_version_base], [lxc_version_major.lxc_version_minor.lxc_version_micro]) m4_define([lxc_version], [ifelse(lxc_version_beta, [], [lxc_version_base], [lxc_version_base.lxc_version_beta])]) AC_INIT([lxc], [lxc_version]) # We need pkg-config PKG_PROG_PKG_CONFIG AC_SUBST(LXC_VERSION_BASE, lxc_version_base) AC_SUBST(LXC_VERSION_BETA, lxc_version_beta) AC_SUBST([LXC_VERSION_MAJOR], [lxc_version_major]) AC_SUBST([LXC_VERSION_MINOR], [lxc_version_minor]) AC_SUBST([LXC_VERSION_MICRO], [lxc_version_micro]) AC_SUBST([LXC_VERSION], [lxc_version]) AC_SUBST([LXC_DEVEL], [lxc_devel]) AC_SUBST([LXC_ABI_MAJOR], [lxc_abi_major]) AC_SUBST([LXC_ABI_MINOR], [lxc_abi_minor]) AC_SUBST([LXC_ABI_MICRO], [lxc_abi_micro]) AC_SUBST([LXC_ABI], [lxc_abi]) AC_CONFIG_SRCDIR([configure.ac]) AC_CONFIG_AUX_DIR([config]) AC_CONFIG_HEADERS([src/config.h]) AM_INIT_AUTOMAKE([-Wall -Werror -Wno-portability subdir-objects]) AC_CANONICAL_HOST AM_PROG_CC_C_O AC_GNU_SOURCE # libtool LT_INIT AC_SUBST([LIBTOOL_DEPS]) # Detect the distribution. This is used for the default configuration and # for some distro-specific build options. AC_MSG_CHECKING([host distribution]) AC_ARG_WITH(distro, AS_HELP_STRING([--with-distro=DISTRO], [Specify the Linux distribution to target: One of redhat, oracle, centos, fedora, suse, gentoo, debian, arch, slackware, plamo, paldo, openmandriva, pardus, sparclinux, altlinux.])) if type lsb_release >/dev/null 2>&1 && test "z$with_distro" = "z"; then with_distro=`lsb_release -is` fi if test "z$with_distro" = "z"; then AC_CHECK_FILE(/etc/redhat-release,with_distro="redhat") AC_CHECK_FILE(/etc/oracle-release,with_distro="oracle") AC_CHECK_FILE(/etc/sparclinux-release,with_distro="sparclinux") AC_CHECK_FILE(/etc/centos-release,with_distro="centos") AC_CHECK_FILE(/etc/fedora-release,with_distro="fedora") AC_CHECK_FILE(/etc/SuSE-release,with_distro="suse") AC_CHECK_FILE(/etc/gentoo-release,with_distro="gentoo") AC_CHECK_FILE(/etc/debian_version,with_distro="debian") AC_CHECK_FILE(/etc/arch-release,with_distro="arch") AC_CHECK_FILE(/etc/slackware-version,with_distro="slackware") AC_CHECK_FILE(/etc/plamo-version,with_distro="plamo") AC_CHECK_FILE(/etc/frugalware-release,with_distro="frugalware") AC_CHECK_FILE(/etc/mandrakelinux-release, with_distro="openmandriva") AC_CHECK_FILE(/etc/mandriva-release,with_distro="openmandriva") AC_CHECK_FILE(/etc/pardus-release,with_distro="pardus") AC_CHECK_FILE(/etc/altlinux-release,with_distro="altlinux") fi with_distro=`echo ${with_distro} | tr '[[:upper:]]' '[[:lower:]]'` if test "z$with_distro" = "zforsparc"; then with_distro="sparclinux" fi if test "z$with_distro" = "z"; then with_distro="unknown" fi case $with_distro in ubuntu|raspbian) distroconf=default.conf.lxcbr distrosysconf="$sysconfdir/default" ;; redhat|centos|fedora|oracle|oracleserver|sparclinux|altlinux|suse|opensuse*|plamo) distroconf=default.conf.lxcbr distrosysconf="$sysconfdir/sysconfig" ;; *) distroconf=default.conf.unknown distrosysconf="$sysconfdir/default" ;; esac AC_MSG_RESULT([$with_distro]) AM_CONDITIONAL([HAVE_DEBIAN], [test x"$with_distro" = "xdebian" -o x"$with_distro" = "xubuntu" -o x"$with_distro" = "xraspbian"]) AM_CONDITIONAL([DISTRO_UBUNTU], [test "x$with_distro" = "xubuntu"]) AC_CONFIG_LINKS([config/etc/default.conf:config/etc/${distroconf}]) # Check for init system type AC_MSG_CHECKING([for init system type]) AC_ARG_WITH([init-script], [AC_HELP_STRING([--with-init-script@<:@=TYPE@<:@,TYPE,...@:>@@:>@], [Type(s) of init script to install: sysvinit, systemd, upstart, distro @<:@default=distro@:>@])],[],[with_init_script=distro]) case "$with_init_script" in distro) case $with_distro in fedora|altlinux|opensuse*) init_script=systemd ;; redhat|oracle|oracleserver|sparclinux|plamo) init_script=sysvinit ;; centos) init_script=sysvinit,systemd ;; debian|raspbian|ubuntu) init_script=upstart,systemd ;; *) echo -n "Linux distribution init system unknown." init_script= ;; esac ;; *) init_script=$with_init_script ;; esac # Check valid init systems were given, run in subshell so we don't mess up IFS (IFS="," ; for init_sys in $init_script; do case "$init_sys" in none|sysvinit|systemd|upstart) ;; *) exit 1 ;; esac done) || AC_MSG_ERROR([Unknown init system type in $init_script]) AM_CONDITIONAL([INIT_SCRIPT_SYSV], [echo "$init_script" |grep -q "sysvinit"]) AM_CONDITIONAL([INIT_SCRIPT_SYSTEMD], [echo "$init_script" |grep -q "systemd"]) AM_CONDITIONAL([INIT_SCRIPT_UPSTART], [echo "$init_script" |grep -q "upstart"]) AC_MSG_RESULT($init_script) # systemd unit dir AC_ARG_WITH([systemdsystemunitdir], AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]), [], [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)]) if test -z "$with_systemdsystemunitdir"; then with_systemdsystemunitdir=/lib/systemd/system fi if test "x$with_systemdsystemunitdir" != "xno"; then AC_SUBST([SYSTEMD_UNIT_DIR], [$with_systemdsystemunitdir]) fi AC_ARG_ENABLE([werror], [AC_HELP_STRING([--disable-werror], [do not treat warnings as errors])], [], [enable_werror=yes]) # Allow enabling deprecated executables AC_ARG_ENABLE([deprecated], [AC_HELP_STRING([--enable-deprecated], [enable deprecated executables [default=no]])], [], [enable_deprecated=false]) AM_CONDITIONAL([ENABLE_DEPRECATED], [test "x$enable_deprecated" = "xyes"]) # Allow disabling rpath AC_ARG_ENABLE([rpath], [AC_HELP_STRING([--enable-rpath], [set rpath in executables [default=no]])], [], [enable_rpath=no]) AM_CONDITIONAL([ENABLE_RPATH], [test "x$enable_rpath" = "xyes"]) # Documentation (manpages) AC_ARG_ENABLE([doc], [AC_HELP_STRING([--enable-doc], [make man pages [default=auto]])], [], [enable_doc=auto]) if test "x$enable_doc" = "xyes" -o "x$enable_doc" = "xauto"; then db2xman="" dbparsers="docbook2x-man db2x_docbook2man docbook2man docbook-to-man" AC_MSG_CHECKING(for docbook2x-man) for name in ${dbparsers}; do if "$name" --help >/dev/null 2>&1; then db2xman="$name" break; fi done if test -n "${db2xman}"; then AC_MSG_RESULT([${db2xman}]) enable_doc="yes" else AC_MSG_RESULT([no]) if test "x$enable_doc" = "xyes"; then AC_MSG_ERROR([docbook2x-man is required, but could not be found]) fi enable_doc="no" fi AC_SUBST(db2xman) fi AM_CONDITIONAL([ENABLE_DOCBOOK], [test "x$db2xman" != "x"]) AM_CONDITIONAL([USE_DOCBOOK2X], [test "x$db2xman" != "xdocbook2man"]) if test "x$db2xman" = "xdocbook2man"; then docdtd="\"-//Davenport//DTD DocBook V3.0//EN\"" else docdtd="\"-//OASIS//DTD DocBook XML\" \"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd\"" fi AC_SUBST(docdtd) # Documentation (API) AC_ARG_ENABLE([api-docs], [AC_HELP_STRING([--enable-api-docs], [make API documentation [default=auto]])], [], [enable_api_docs=auto]) if test "x$enable_api_docs" = "xyes" -o "x$enable_api_docs" = "xauto"; then AC_CHECK_PROGS([HAVE_DOXYGEN],[doxygen]) AC_SUBST([HAVE_DOXYGEN]) if test "x$HAVE_DOXYGEN" != "x"; then enable_api_docs="yes" else if test "x$enable_api_docs" = "xyes"; then AC_MSG_ERROR([doxygen is required, but could not be found]) fi enable_api_docs="no" fi fi AM_CONDITIONAL([ENABLE_API_DOCS], [test "x$HAVE_DOXYGEN" != "x"]) # Apparmor AC_ARG_ENABLE([apparmor], [AC_HELP_STRING([--enable-apparmor], [enable apparmor support [default=auto]])], [], [enable_apparmor=auto]) if test "$enable_apparmor" = "auto" ; then AC_CHECK_LIB([apparmor],[aa_change_profile],[enable_apparmor=yes], [enable_apparmor=no]) fi AM_CONDITIONAL([ENABLE_APPARMOR], [test "x$enable_apparmor" = "xyes"]) AM_COND_IF([ENABLE_APPARMOR], [AC_CHECK_HEADER([sys/apparmor.h],[],[AC_MSG_ERROR([You must install the AppArmor development package in order to compile lxc])]) AC_CHECK_LIB([apparmor], [aa_change_profile],[],[AC_MSG_ERROR([You must install the AppArmor development package in order to compile lxc])]) AC_SUBST([APPARMOR_LIBS], [-lapparmor])]) # GnuTLS AC_ARG_ENABLE([gnutls], [AC_HELP_STRING([--enable-gnutls], [enable GnuTLS support [default=auto]])], [], [enable_gnutls=auto]) if test "$enable_gnutls" = "auto" ; then AC_CHECK_LIB([gnutls], [gnutls_hash_fast], [enable_gnutls=yes], [enable_gnutls=no]) fi AM_CONDITIONAL([ENABLE_GNUTLS], [test "x$enable_gnutls" = "xyes"]) AM_COND_IF([ENABLE_GNUTLS], [AC_CHECK_HEADER([gnutls/gnutls.h],[],[AC_MSG_ERROR([You must install the GnuTLS development package in order to compile lxc])]) AC_CHECK_LIB([gnutls], [gnutls_hash_fast],[],[AC_MSG_ERROR([You must install the GnuTLS development package in order to compile lxc])]) AC_SUBST([GNUTLS_LIBS], [-lgnutls])]) # SELinux AC_ARG_ENABLE([selinux], [AC_HELP_STRING([--enable-selinux], [enable SELinux support [default=auto]])], [], [enable_selinux=auto]) if test "x$enable_selinux" = xauto; then AC_CHECK_LIB([selinux],[setexeccon_raw],[enable_selinux=yes],[enable_selinux=no]) fi AM_CONDITIONAL([ENABLE_SELINUX], [test "x$enable_selinux" = "xyes"]) AM_COND_IF([ENABLE_SELINUX], [AC_CHECK_HEADER([selinux/selinux.h],[],[AC_MSG_ERROR([You must install the SELinux development package in order to compile lxc])]) AC_CHECK_LIB([selinux], [setexeccon_raw],[true],[AC_MSG_ERROR([You must install the SELinux development package in order to compile lxc])]) AC_SUBST([SELINUX_LIBS], [-lselinux])]) # Seccomp syscall filter AC_ARG_ENABLE([seccomp], [AC_HELP_STRING([--enable-seccomp], [enable seccomp support [default=auto]])], [], [enable_seccomp=auto]) if test "x$enable_seccomp" = "xauto" ; then AC_CHECK_LIB([seccomp],[seccomp_init],[enable_seccomp=yes],[enable_seccomp=no]) fi AM_CONDITIONAL([ENABLE_SECCOMP], [test "x$enable_seccomp" = "xyes"]) AM_COND_IF([ENABLE_SECCOMP], [PKG_CHECK_MODULES([SECCOMP],[libseccomp],[],[ AC_CHECK_HEADER([seccomp.h],[],[AC_MSG_ERROR([You must install the seccomp development package in order to compile lxc])]) AC_CHECK_LIB([seccomp], [seccomp_init],[],[AC_MSG_ERROR([You must install the seccomp development package in order to compile lxc])]) AC_SUBST([SECCOMP_LIBS], [-lseccomp]) ]) ]) # cgmanager AC_ARG_ENABLE([cgmanager], [AC_HELP_STRING([--enable-cgmanager], [enable cgmanager support [default=auto]])], [], [enable_cgmanager=auto]) if test "x$enable_cgmanager" = "xauto" ; then AC_CHECK_LIB([cgmanager],[cgmanager_create],[enable_cgmanager=yes],[enable_cgmanager=no],[-lnih -lnih-dbus -ldbus-1]) fi AM_CONDITIONAL([ENABLE_CGMANAGER], [test "x$enable_cgmanager" = "xyes"]) AM_COND_IF([ENABLE_CGMANAGER], [PKG_CHECK_MODULES([CGMANAGER], [libcgmanager]) PKG_CHECK_MODULES([NIH], [libnih >= 1.0.2]) PKG_CHECK_MODULES([NIH_DBUS], [libnih-dbus >= 1.0.0]) PKG_CHECK_MODULES([DBUS], [dbus-1 >= 1.2.16]) ]) AC_MSG_CHECKING(for get_pid_cgroup_abs_sync) save_LIBS=$LIBS AC_SEARCH_LIBS([cgmanager_get_pid_cgroup_abs_sync], [cgmanager], [have_abs_cgroups=yes], [have_abs_cgroups=no], [-lnih -lnih-dbus -ldbus-1]) LIBS=$save_LIBS if test "x$have_abs_cgroups" = "xyes"; then AC_DEFINE([HAVE_CGMANAGER_GET_PID_CGROUP_ABS_SYNC], 1, [Have cgmanager_get_pid_cgroup_abs_sync]) AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi AC_MSG_CHECKING(for cgmanager_list_controllers) save_LIBS=$LIBS AC_SEARCH_LIBS([cgmanager_list_controllers_sync], [cgmanager], [have_list_controllers=yes], [have_list_controllers=no], [-lnih -lnih-dbus -ldbus-1]) LIBS=$save_LIBS if test "x$have_list_controllers" = "xyes"; then AC_DEFINE([HAVE_CGMANAGER_LIST_CONTROLLERS], 1, [Have cgmanager_list_controllers]) AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi # Check for static libcap, make sure the function checked for differs from the # the one checked below so the cache doesn't give a wrong answer OLD_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -static" AC_CHECK_LIB([cap],[cap_init],[have_static_libcap=yes],[have_static_libcap=no]) AM_CONDITIONAL([HAVE_STATIC_LIBCAP], [test "x$have_static_libcap" = "xyes"]) if test "x$have_static_libcap" = "xyes"; then AC_DEFINE([HAVE_STATIC_LIBCAP], 1, [Have static libcap]) fi CFLAGS="$OLD_CFLAGS" # Linux capabilities AC_ARG_ENABLE([capabilities], [AC_HELP_STRING([--enable-capabilities], [enable kernel capabilities support [default=auto]])], [], [enable_capabilities=auto]) if test "x$enable_capabilities" = "xauto"; then AC_CHECK_LIB([cap],[cap_set_proc],[enable_capabilities=yes],[enable_capabilities=no]) fi AM_CONDITIONAL([ENABLE_CAP], [test "x$enable_capabilities" = "xyes"]) AM_COND_IF([ENABLE_CAP], [AC_CHECK_HEADER([sys/capability.h],[],[AC_MSG_ERROR([You must install the libcap development package in order to compile lxc])]) AC_CHECK_LIB(cap,cap_set_proc,[],[AC_MSG_ERROR([You must install the libcap development package in order to compile lxc])]) # Test whether we support getting file capabilities via cap_get_file(). AC_CHECK_LIB(cap,cap_get_file, AC_DEFINE(LIBCAP_SUPPORTS_FILE_CAPABILITIES,1,[Have cap_get_file]),[],[]) AC_SUBST([CAP_LIBS], [-lcap])]) # HAVE_SCMP_FILTER_CTX=1 will tell us we have libseccomp api >= 1.0.0 OLD_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $SECCOMP_CFLAGS" AC_CHECK_TYPES([scmp_filter_ctx], [], [], [[#include ]]) AC_CHECK_DECLS([seccomp_syscall_resolve_name_arch], [], [], [[#include ]]) CFLAGS="$OLD_CFLAGS" # Configuration examples AC_ARG_ENABLE([examples], [AC_HELP_STRING([--enable-examples], [install examples [default=yes]])], [], [enable_examples=yes]) AM_CONDITIONAL([ENABLE_EXAMPLES], [test "x$enable_examples" = "xyes"]) # Python3 module and scripts AC_ARG_ENABLE([python], [AC_HELP_STRING([--enable-python], [enable python binding [default=auto]])], [], [enable_python=auto]) if test "x$enable_python" = "xauto"; then PKG_CHECK_MODULES([PYTHONDEV], [python3 >= 3.2],[enable_python=yes],[enable_python=no]) if test "$CC" = "clang"; then enable_python=no fi fi if test "x$enable_python" = "xyes" && test "$CC" = "clang"; then AC_MSG_ERROR([Python3 is incompatible with the clang compiler]) fi AM_CONDITIONAL([ENABLE_PYTHON], [test "x$enable_python" = "xyes"]) AM_COND_IF([ENABLE_PYTHON], [AM_PATH_PYTHON([3.2], [], [AC_MSG_ERROR([You must install python3])]) PKG_CHECK_MODULES([PYTHONDEV], [python3 >= 3.2],[],[AC_MSG_ERROR([You must install python3-dev])]) AC_DEFINE_UNQUOTED([ENABLE_PYTHON], 1, [Python3 is available])]) # Enable dumping stack traces AC_ARG_ENABLE([mutex-debugging], [AC_HELP_STRING([--enable-mutex-debugging], [Makes mutexes to report error and provide stack trace [default=no]])], [], [enable_mutex_debugging=no]) AM_CONDITIONAL([MUTEX_DEBUGGING], [test "x$enable_mutex_debugging" = "xyes"]) AM_COND_IF([MUTEX_DEBUGGING], AC_DEFINE_UNQUOTED([MUTEX_DEBUGGING], 1, [Enabling mutex debugging])) # Not in older autoconf versions # AS_VAR_COPY(DEST, SOURCE) # ------------------------- # Set the polymorphic shell variable DEST to the contents of the polymorphic # shell variable SOURCE. m4_ifdef([AS_VAR_COPY], [], [AC_DEFUN([AS_VAR_COPY], [AS_LITERAL_IF([$1[]$2], [$1=$$2], [eval $1=\$$2])]) ]) dnl PKG_CHECK_VAR was introduced with pkg-config 0.28 m4_ifdef([PKG_CHECK_VAR], [], [AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl _PKG_CONFIG([$1], [variable="][$3]["], [$2]) AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl ])# PKG_CHECK_VAR ]) # Lua module and scripts AC_ARG_ENABLE([lua], [AC_HELP_STRING([--enable-lua], [enable lua binding [default=auto]])], [], [enable_lua=auto]) AC_ARG_WITH([lua-pc], [AS_HELP_STRING( [--with-lua-pc=PKG], [Specify pkg-config package name for lua] )], [], [with_lua_pc=no]) if test "x$enable_lua" = "xyes" -a "x$with_lua_pc" != "xno"; then # exit with error if not found PKG_CHECK_MODULES([LUA], [$with_lua_pc], [LUAPKGCONFIG=$with_lua_pc]) fi if test "x$enable_lua" = "xauto" -a "x$with_lua_pc" != "xno"; then PKG_CHECK_MODULES([LUA], [$with_lua_pc], [LUAPKGCONFIG=$with_lua_pc enable_lua=yes], [enable_lua=no]) fi if test "x$enable_lua" != "xno"; then PKG_CHECK_MODULES([LUA], [lua], [LUAPKGCONFIG=lua], [PKG_CHECK_MODULES([LUA], [lua5.2], [LUAPKGCONFIG=lua5.2], [PKG_CHECK_MODULES([LUA], [lua5.1], [LUAPKGCONFIG=lua5.1], [AS_IF([test "x$enable_lua" = "xyes"], [AC_MSG_ERROR([Lua not found. Please use --with-lua-pc=PKG])], [enable_lua=no])] )] )]) AS_IF([test "x$LUAPKGCONFIG" != "x"], [enable_lua=yes]) fi AM_CONDITIONAL([ENABLE_LUA], [test "x$enable_lua" = "xyes"]) AM_COND_IF([ENABLE_LUA], [AC_MSG_CHECKING([Lua version]) PKG_CHECK_VAR([LUA_VERSION], [$LUAPKGCONFIG], [V],, [PKG_CHECK_VAR([LUA_VERSION], [$LUAPKGCONFIG], [major_version])]) AC_MSG_RESULT([$LUA_VERSION]) AC_SUBST([LUA_LIBDIR], [$libdir/lua/$LUA_VERSION]) AC_SUBST([LUA_SHAREDIR], [$datadir/lua/$LUA_VERSION]) ]) # Optional bash integration AC_ARG_ENABLE([bash], [AC_HELP_STRING([--enable-bash], [build bash integration [default=yes]])], [], [enable_bash=yes]) AM_CONDITIONAL([ENABLE_BASH], [test "x$enable_bash" = "xyes"]) AM_COND_IF([ENABLE_BASH], [AC_MSG_CHECKING([bash completion directory]) PKG_CHECK_VAR(bashcompdir, [bash-completion], [completionsdir], , bashcompdir="${sysconfdir}/bash_completion.d") AC_MSG_RESULT([$bashcompdir]) AC_SUBST(bashcompdir) ]) # Optional test binaries AC_ARG_ENABLE([tests], [AC_HELP_STRING([--enable-tests], [build test/example binaries [default=no]])], [], [enable_tests=no]) AM_CONDITIONAL([ENABLE_TESTS], [test "x$enable_tests" = "xyes"]) # Allow overriding the default runtime dir (/run) AC_ARG_WITH([runtime-path], [AC_HELP_STRING( [--with-runtime-path=dir], [runtime directory (default: /run)] )], [], [with_runtime_path=['/run']]) # LXC container path, where the containers are actually stored # This is overridden by an entry in the file called LXCCONF # (i.e. /etc/lxc/lxc.conf) AC_ARG_WITH([config-path], [AC_HELP_STRING( [--with-config-path=dir], [lxc configuration repository path] )], [], [with_config_path=['${localstatedir}/lib/lxc']]) # The path of the global lxc configuration file. AC_ARG_WITH([global-conf], [AC_HELP_STRING( [--with-global-conf=dir], [global lxc configuration file] )], [], [with_global_conf=['${sysconfdir}/lxc/lxc.conf']]) # The path of the userns network configuration file AC_ARG_WITH([usernic-conf], [AC_HELP_STRING( [--with-usernic-conf], [user network interface configuration file] )], [], [with_usernic_conf=['${sysconfdir}/lxc/lxc-usernet']]) # The path of the runtime usernic database AC_ARG_WITH([usernic-db], [AC_HELP_STRING( [--with-usernic-db], [lxc user nic database] )], [], [with_usernic_db=['${with_runtime_path}/lxc/nics']]) # Rootfs path, where the container mount structure is assembled AC_ARG_WITH([rootfs-path], [AC_HELP_STRING( [--with-rootfs-path=dir], [lxc rootfs mount point] )], [], [with_rootfs_path=['${libdir}/lxc/rootfs']]) # cgroup pattern specification AC_ARG_WITH([cgroup-pattern], [AC_HELP_STRING( [--with-cgroup-pattern=pattern], [pattern for container cgroups] )], [], [with_cgroup_pattern=['/lxc/%n']]) # Container log path. By default, use $lxcpath. AC_MSG_CHECKING([Whether to place logfiles in container config path]) AC_ARG_ENABLE([configpath-log], [AC_HELP_STRING([--enable-configpath-log], [use logfiles in config path [default=no]])], [], [enable_configpath_log=no]) AC_MSG_RESULT([$enable_configpath_log]) AM_CONDITIONAL([USE_CONFIGPATH_LOGS], [test "$enable_configpath_log" = "yes"]) if test "$enable_configpath_log" = "yes"; then default_log_path="${with_config_path}" else default_log_path="${localstatedir}/log/lxc" fi AC_ARG_WITH([log-path], [AC_HELP_STRING( [--with-log-path=dir], [per container log path] )], [], [with_log_path=['${default_log_path}']]) # Expand some useful variables AS_AC_EXPAND(PREFIX, "$prefix") AS_AC_EXPAND(LIBDIR, "$libdir") AS_AC_EXPAND(BINDIR, "$bindir") AS_AC_EXPAND(SBINDIR, "$sbindir") AS_AC_EXPAND(LIBEXECDIR, "$libexecdir") AS_AC_EXPAND(INCLUDEDIR, "$includedir") AS_AC_EXPAND(SYSCONFDIR, "$sysconfdir") AS_AC_EXPAND(LXC_DEFAULT_CONFIG, "$sysconfdir/lxc/default.conf") AS_AC_EXPAND(DATADIR, "$datadir") AS_AC_EXPAND(LOCALSTATEDIR, "$localstatedir") AS_AC_EXPAND(DOCDIR, "$docdir") AS_AC_EXPAND(LXC_GENERATE_DATE, "$(date --utc --date=@${SOURCE_DATE_EPOCH:-$(date +%s)} '+%Y-%m-%d')") AS_AC_EXPAND(LXCPATH, "$with_config_path") AS_AC_EXPAND(LXC_GLOBAL_CONF, "$with_global_conf") AS_AC_EXPAND(LXC_USERNIC_CONF, "$with_usernic_conf") AS_AC_EXPAND(LXC_USERNIC_DB, "$with_usernic_db") AS_AC_EXPAND(LXC_DISTRO_SYSCONF, "$distrosysconf") AS_AC_EXPAND(LXCROOTFSMOUNT, "$with_rootfs_path") AS_AC_EXPAND(LXCTEMPLATEDIR, "$datadir/lxc/templates") AS_AC_EXPAND(LXCTEMPLATECONFIG, "$datadir/lxc/config") AS_AC_EXPAND(LXCHOOKDIR, "$datadir/lxc/hooks") AS_AC_EXPAND(LXCBINHOOKDIR, "$libexecdir/lxc/hooks") AS_AC_EXPAND(LXCINITDIR, "$libexecdir") AS_AC_EXPAND(LOGPATH, "$with_log_path") AS_AC_EXPAND(RUNTIME_PATH, "$with_runtime_path") AC_SUBST(DEFAULT_CGROUP_PATTERN, ["$with_cgroup_pattern"]) # We need the install path so criu knows where to reference the hook scripts. AC_DEFINE_UNQUOTED([DATADIR], "$DATADIR", ["Prefix for shared files."]) # Check for some standard kernel headers AC_CHECK_HEADERS([linux/unistd.h linux/netlink.h linux/genetlink.h], [], AC_MSG_ERROR([Please install the Linux kernel headers.]), [#include ]) # Check for alternate C libraries AC_MSG_CHECKING(for bionic libc) AC_COMPILE_IFELSE([AC_LANG_PROGRAM( [[#ifndef __ANDROID__ error: Not bionic! #endif]])], [is_bionic=yes], [is_bionic=no]) if test "x$is_bionic" = "xyes"; then AC_DEFINE([IS_BIONIC], 1, [bionic libc]) AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi AM_CONDITIONAL([IS_BIONIC], [test "x$is_bionic" = "xyes"]) # Some systems lack PR_CAPBSET_DROP definition => HAVE_DECL_PR_CAPBSET_DROP AC_CHECK_DECLS([PR_CAPBSET_DROP], [], [], [#include ]) # Check for some headers AC_CHECK_HEADERS([sys/signalfd.h pty.h ifaddrs.h sys/memfd.h sys/personality.h utmpx.h sys/timerfd.h]) # lookup major()/minor()/makedev() AC_HEADER_MAJOR # Check for some syscalls functions AC_CHECK_FUNCS([setns pivot_root sethostname unshare rand_r confstr faccessat gettid memfd_create]) # Check for some functions AC_CHECK_LIB(pthread, main) AC_CHECK_FUNCS(pthread_atfork) AC_CHECK_FUNCS(statvfs) AC_CHECK_LIB(util, openpty) AC_CHECK_FUNCS([openpty hasmntopt setmntent endmntent utmpxname]) AC_CHECK_FUNCS([getline], AM_CONDITIONAL(HAVE_GETLINE, true) AC_DEFINE(HAVE_GETLINE,1,[Have getline]), AM_CONDITIONAL(HAVE_GETLINE, false)) AC_CHECK_FUNCS([getsubopt], AM_CONDITIONAL(HAVE_GETSUBOPT, true) AC_DEFINE(HAVE_GETSUBOPT,1,[Have getsubopt]), AM_CONDITIONAL(HAVE_GETSUBOPT, false)) AC_CHECK_FUNCS([fgetln], AM_CONDITIONAL(HAVE_FGETLN, true) AC_DEFINE(HAVE_FGETLN,1,[Have fgetln]), AM_CONDITIONAL(HAVE_FGETLN, false)) # Check for some libraries AC_SEARCH_LIBS(sem_open, [rt pthread]) AC_SEARCH_LIBS(clock_gettime, [rt]) # Check for some standard binaries AC_PROG_GCC_TRADITIONAL AC_PROG_SED # See if we support thread-local storage. LXC_CHECK_TLS if test "x$GCC" = "xyes"; then CFLAGS="$CFLAGS -Wall" if test "x$enable_werror" = "xyes"; then CFLAGS="$CFLAGS -Werror" fi fi # Files requiring some variable expansion AC_CONFIG_FILES([ Makefile lxc.pc lxc.spec config/Makefile config/apparmor/Makefile config/selinux/Makefile config/bash/Makefile config/bash/lxc config/init/Makefile config/init/common/Makefile config/init/common/lxc-containers config/init/common/lxc-net config/init/systemd/Makefile config/init/systemd/lxc.service config/init/systemd/lxc@.service config/init/systemd/lxc-net.service config/init/sysvinit/Makefile config/init/sysvinit/lxc-containers config/init/sysvinit/lxc-net config/init/upstart/lxc.conf config/init/upstart/lxc-net.conf config/init/upstart/Makefile config/etc/Makefile config/templates/Makefile config/templates/alpine.common.conf config/templates/alpine.userns.conf config/templates/archlinux.common.conf config/templates/archlinux.userns.conf config/templates/centos.common.conf config/templates/centos.userns.conf config/templates/common.conf config/templates/common.conf.d/Makefile config/templates/debian.common.conf config/templates/debian.userns.conf config/templates/fedora.common.conf config/templates/fedora.userns.conf config/templates/gentoo.common.conf config/templates/gentoo.moresecure.conf config/templates/gentoo.userns.conf config/templates/nesting.conf config/templates/opensuse.common.conf config/templates/opensuse.userns.conf config/templates/oracle.common.conf config/templates/oracle.userns.conf config/templates/plamo.common.conf config/templates/plamo.userns.conf config/templates/slackware.common.conf config/templates/slackware.userns.conf config/templates/ubuntu-cloud.common.conf config/templates/ubuntu-cloud.lucid.conf config/templates/ubuntu-cloud.userns.conf config/templates/ubuntu.common.conf config/templates/ubuntu.lucid.conf config/templates/ubuntu.userns.conf config/templates/openwrt.common.conf config/templates/sparclinux.common.conf config/templates/sparclinux.userns.conf config/templates/userns.conf config/yum/Makefile config/sysconfig/Makefile config/sysconfig/lxc doc/Makefile doc/api/Makefile doc/lxc-attach.sgml doc/lxc-autostart.sgml doc/lxc-cgroup.sgml doc/lxc-checkconfig.sgml doc/lxc-checkpoint.sgml doc/lxc-clone.sgml doc/lxc-config.sgml doc/lxc-console.sgml doc/lxc-copy.sgml doc/lxc-create.sgml doc/lxc-destroy.sgml doc/lxc-device.sgml doc/lxc-execute.sgml doc/lxc-freeze.sgml doc/lxc-info.sgml doc/lxc-ls.sgml doc/lxc-monitor.sgml doc/lxc-snapshot.sgml doc/lxc-start-ephemeral.sgml doc/lxc-start.sgml doc/lxc-stop.sgml doc/lxc-top.sgml doc/lxc-unfreeze.sgml doc/lxc-unshare.sgml doc/lxc-user-nic.sgml doc/lxc-usernsexec.sgml doc/lxc-wait.sgml doc/lxc.conf.sgml doc/lxc.container.conf.sgml doc/lxc.system.conf.sgml doc/lxc-usernet.sgml doc/lxc.sgml doc/common_options.sgml doc/see_also.sgml doc/rootfs/Makefile doc/examples/Makefile doc/examples/lxc-macvlan.conf doc/examples/lxc-vlan.conf doc/examples/lxc-no-netns.conf doc/examples/lxc-empty-netns.conf doc/examples/lxc-phys.conf doc/examples/lxc-veth.conf doc/examples/lxc-complex.conf doc/ja/Makefile doc/ja/lxc-attach.sgml doc/ja/lxc-autostart.sgml doc/ja/lxc-cgroup.sgml doc/ja/lxc-checkconfig.sgml doc/ja/lxc-checkpoint.sgml doc/ja/lxc-clone.sgml doc/ja/lxc-config.sgml doc/ja/lxc-console.sgml doc/ja/lxc-copy.sgml doc/ja/lxc-create.sgml doc/ja/lxc-destroy.sgml doc/ja/lxc-device.sgml doc/ja/lxc-execute.sgml doc/ja/lxc-freeze.sgml doc/ja/lxc-info.sgml doc/ja/lxc-ls.sgml doc/ja/lxc-monitor.sgml doc/ja/lxc-snapshot.sgml doc/ja/lxc-start-ephemeral.sgml doc/ja/lxc-start.sgml doc/ja/lxc-stop.sgml doc/ja/lxc-top.sgml doc/ja/lxc-unfreeze.sgml doc/ja/lxc-unshare.sgml doc/ja/lxc-user-nic.sgml doc/ja/lxc-usernsexec.sgml doc/ja/lxc-wait.sgml doc/ja/lxc.conf.sgml doc/ja/lxc.container.conf.sgml doc/ja/lxc.system.conf.sgml doc/ja/lxc-usernet.sgml doc/ja/lxc.sgml doc/ja/common_options.sgml doc/ja/see_also.sgml doc/ko/Makefile doc/ko/lxc-attach.sgml doc/ko/lxc-autostart.sgml doc/ko/lxc-cgroup.sgml doc/ko/lxc-checkconfig.sgml doc/ko/lxc-checkpoint.sgml doc/ko/lxc-clone.sgml doc/ko/lxc-config.sgml doc/ko/lxc-console.sgml doc/ko/lxc-copy.sgml doc/ko/lxc-create.sgml doc/ko/lxc-destroy.sgml doc/ko/lxc-device.sgml doc/ko/lxc-execute.sgml doc/ko/lxc-freeze.sgml doc/ko/lxc-info.sgml doc/ko/lxc-ls.sgml doc/ko/lxc-monitor.sgml doc/ko/lxc-snapshot.sgml doc/ko/lxc-start-ephemeral.sgml doc/ko/lxc-start.sgml doc/ko/lxc-stop.sgml doc/ko/lxc-top.sgml doc/ko/lxc-unfreeze.sgml doc/ko/lxc-unshare.sgml doc/ko/lxc-user-nic.sgml doc/ko/lxc-usernsexec.sgml doc/ko/lxc-wait.sgml doc/ko/lxc.conf.sgml doc/ko/lxc.container.conf.sgml doc/ko/lxc.system.conf.sgml doc/ko/lxc-usernet.sgml doc/ko/lxc.sgml doc/ko/common_options.sgml doc/ko/see_also.sgml hooks/Makefile templates/Makefile templates/lxc-alpine templates/lxc-altlinux templates/lxc-archlinux templates/lxc-busybox templates/lxc-centos templates/lxc-cirros templates/lxc-debian templates/lxc-download templates/lxc-fedora templates/lxc-gentoo templates/lxc-openmandriva templates/lxc-opensuse templates/lxc-oracle templates/lxc-plamo templates/lxc-slackware templates/lxc-sshd templates/lxc-ubuntu templates/lxc-ubuntu-cloud templates/lxc-sparclinux src/Makefile src/lxc/Makefile src/lxc/lxc.functions src/lxc/tools/lxc-checkconfig src/lxc/tools/lxc-start-ephemeral src/lxc/version.h src/python-lxc/Makefile src/python-lxc/setup.py src/lua-lxc/Makefile src/tests/Makefile src/tests/lxc-test-usernic ]) AC_CONFIG_COMMANDS([default],[[]],[[]]) AC_OUTPUT # Configuration overview cat << EOF ---------------------------- Environment: - compiler: $CC - distribution: $with_distro - init script type(s): $init_script - rpath: $enable_rpath - GnuTLS: $enable_gnutls - Bash integration: $enable_bash Security features: - Apparmor: $enable_apparmor - Linux capabilities: $enable_capabilities - seccomp: $enable_seccomp - SELinux: $enable_selinux - cgmanager: $enable_cgmanager Bindings: - lua: $enable_lua - python3: $enable_python Documentation: - examples: $enable_examples - API documentation: $enable_api_docs - user documentation: $enable_doc Debugging: - tests: $enable_tests - mutex debugging: $enable_mutex_debugging Paths: - Logs in configpath: $enable_configpath_log EOF if test "x$ac_cv_func_pthread_atfork" = "xno" ; then cat << EOF WARNING: Threading not supported on your platform You are compiling LXC for bionic target which lacks certain threading related functionality used by LXC API (like pthread_atfork). Please note that, because of the missing functionality, multithreaded usage of LXC API cause some problems. EOF fi lxc-2.0.8/README0000644061062106075000000000655013105116772010131 00000000000000Please see the COPYING file for details on copying and usage. Please refer to the INSTALL file for instructions on how to build. What is lxc: The container technology is actively being pushed into the mainstream linux kernel. It provides the resource management through the control groups aka process containers and resource isolation through the namespaces. 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 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- tinue working on the Checkpoint/Restart new features. The lxc is small enough to easily manage a container with simple command lines and complete enough to be used for other purposes. Using lxc: Refer the lxc* man pages (generated from doc/* files) Downloading the current source code: Source for the latest released version can always be downloaded from http://linuxcontainers.org/downloads/ You can browse the up to the minute source code and change history online. http://github.com/lxc/lxc For detailed build instruction refer to INSTALL and man lxc man page but a short command line should work: ./autogen.sh && ./configure && make && sudo make install preceded by ./autogen.sh if configure do not exist yet. Troubleshooting: If you get an error message at the autogen.sh or configure stage, make sure you have, autoconf, automake, pkg-config, make and gcc installed on your machine. The configure script will usually give you hints as to what you are missing, looking for those in your package manager will usually give you the package that you need to install. Also pay a close attention to the feature summary showed at the end of the configure run, features are automatically enabled/disabled based on whether the needed development packages are installed on your machine. If you want a feature but don't know what to install, force it with --enable- and look at the error message from configure. Getting help: when you find you need help, you can check out one of the two lxc mailing list archives and register if interested: http://lists.linuxcontainers.org/listinfo/lxc-devel http://lists.linuxcontainers.org/listinfo/lxc-users Portability: lxc is developed and tested on Linux since kernel mainline version 2.6.27 (without network) and 2.6.29 with network isolation. It's compiled with gcc, and should work on most architectures as long as the required kernel features are available. This includes (but isn't limited to): i686, x86_64, ppc, ppc64, S390, armel and armhf. AUTHOR Daniel Lezcano Seccomp with LXC ---------------- To restrict a container with seccomp, you must specify a profile which is basically a whitelist of system calls it may execute. In the container config file, add a line like lxc.seccomp = /var/lib/lxc/q1/seccomp.full I created a usable (but basically worthless) seccomp.full file using cat > seccomp.full << EOF 1 whitelist EOF for i in `seq 0 300`; do echo $i >> seccomp.full done for i in `seq 1024 1079`; do echo $i >> seccomp.full done -- Serge Hallyn Fri, 27 Jul 2012 15:47:02 +0600 lxc-2.0.8/Makefile.in0000644061062106075000000007433213105116775011324 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Makefile.am VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @ENABLE_LUA_TRUE@am__append_1 = --with lua @ENABLE_PYTHON_TRUE@am__append_2 = --with python subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/acinclude.m4 \ $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/tls.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ $(am__configure_deps) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h CONFIG_CLEAN_FILES = lxc.pc lxc.spec src/lxc/tools/lxc-checkconfig \ src/lxc/tools/lxc-start-ephemeral CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(pcdatadir)" DATA = $(pcdata_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ cscope distdir dist dist-all distcheck am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags CSCOPE = cscope am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/lxc.pc.in \ $(srcdir)/lxc.spec.in $(top_srcdir)/config/compile \ $(top_srcdir)/config/config.guess \ $(top_srcdir)/config/config.sub \ $(top_srcdir)/config/install-sh $(top_srcdir)/config/ltmain.sh \ $(top_srcdir)/config/missing \ $(top_srcdir)/src/lxc/tools/lxc-checkconfig.in \ $(top_srcdir)/src/lxc/tools/lxc-start-ephemeral.in AUTHORS \ COPYING ChangeLog INSTALL NEWS README DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APPARMOR_LIBS = @APPARMOR_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BINDIR = @BINDIR@ CAP_LIBS = @CAP_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CGMANAGER_CFLAGS = @CGMANAGER_CFLAGS@ CGMANAGER_LIBS = @CGMANAGER_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIR = @DATADIR@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFAULT_CGROUP_PATTERN = @DEFAULT_CGROUP_PATTERN@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOCDIR = @DOCDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ HAVE_DOXYGEN = @HAVE_DOXYGEN@ INCLUDEDIR = @INCLUDEDIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDIR = @LIBDIR@ LIBEXECDIR = @LIBEXECDIR@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCALSTATEDIR = @LOCALSTATEDIR@ LOGPATH = @LOGPATH@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBDIR = @LUA_LIBDIR@ LUA_LIBS = @LUA_LIBS@ LUA_SHAREDIR = @LUA_SHAREDIR@ LUA_VERSION = @LUA_VERSION@ LXCBINHOOKDIR = @LXCBINHOOKDIR@ LXCHOOKDIR = @LXCHOOKDIR@ LXCINITDIR = @LXCINITDIR@ LXCPATH = @LXCPATH@ LXCROOTFSMOUNT = @LXCROOTFSMOUNT@ LXCTEMPLATECONFIG = @LXCTEMPLATECONFIG@ LXCTEMPLATEDIR = @LXCTEMPLATEDIR@ LXC_ABI = @LXC_ABI@ LXC_ABI_MAJOR = @LXC_ABI_MAJOR@ LXC_ABI_MICRO = @LXC_ABI_MICRO@ LXC_ABI_MINOR = @LXC_ABI_MINOR@ LXC_DEFAULT_CONFIG = @LXC_DEFAULT_CONFIG@ LXC_DEVEL = @LXC_DEVEL@ LXC_DISTRO_SYSCONF = @LXC_DISTRO_SYSCONF@ LXC_GENERATE_DATE = @LXC_GENERATE_DATE@ LXC_GLOBAL_CONF = @LXC_GLOBAL_CONF@ LXC_USERNIC_CONF = @LXC_USERNIC_CONF@ LXC_USERNIC_DB = @LXC_USERNIC_DB@ LXC_VERSION = @LXC_VERSION@ LXC_VERSION_BASE = @LXC_VERSION_BASE@ LXC_VERSION_BETA = @LXC_VERSION_BETA@ LXC_VERSION_MAJOR = @LXC_VERSION_MAJOR@ LXC_VERSION_MICRO = @LXC_VERSION_MICRO@ LXC_VERSION_MINOR = @LXC_VERSION_MINOR@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NIH_CFLAGS = @NIH_CFLAGS@ NIH_DBUS_CFLAGS = @NIH_DBUS_CFLAGS@ NIH_DBUS_LIBS = @NIH_DBUS_LIBS@ NIH_LIBS = @NIH_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PREFIX = @PREFIX@ PYTHON = @PYTHON@ PYTHONDEV_CFLAGS = @PYTHONDEV_CFLAGS@ PYTHONDEV_LIBS = @PYTHONDEV_LIBS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RUNTIME_PATH = @RUNTIME_PATH@ SBINDIR = @SBINDIR@ SECCOMP_CFLAGS = @SECCOMP_CFLAGS@ SECCOMP_LIBS = @SECCOMP_LIBS@ SED = @SED@ SELINUX_LIBS = @SELINUX_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SYSCONFDIR = @SYSCONFDIR@ SYSTEMD_UNIT_DIR = @SYSTEMD_UNIT_DIR@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bashcompdir = @bashcompdir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ db2xman = @db2xman@ docdir = @docdir@ docdtd = @docdtd@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ ACLOCAL_AMFLAGS = -I config SUBDIRS = config src templates doc hooks DIST_SUBDIRS = config src templates doc hooks EXTRA_DIST = \ autogen.sh \ lxc.spec \ CONTRIBUTING \ MAINTAINERS RPMARGS = $(am__append_1) $(am__append_2) pcdatadir = $(libdir)/pkgconfig pcdata_DATA = lxc.pc all: all-recursive .SUFFIXES: am--refresh: Makefile @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): lxc.pc: $(top_builddir)/config.status $(srcdir)/lxc.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ lxc.spec: $(top_builddir)/config.status $(srcdir)/lxc.spec.in cd $(top_builddir) && $(SHELL) ./config.status $@ src/lxc/tools/lxc-checkconfig: $(top_builddir)/config.status $(top_srcdir)/src/lxc/tools/lxc-checkconfig.in cd $(top_builddir) && $(SHELL) ./config.status $@ src/lxc/tools/lxc-start-ephemeral: $(top_builddir)/config.status $(top_srcdir)/src/lxc/tools/lxc-start-ephemeral.in cd $(top_builddir) && $(SHELL) ./config.status $@ mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool config.lt install-pcdataDATA: $(pcdata_DATA) @$(NORMAL_INSTALL) @list='$(pcdata_DATA)'; test -n "$(pcdatadir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pcdatadir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pcdatadir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pcdatadir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pcdatadir)" || exit $$?; \ done uninstall-pcdataDATA: @$(NORMAL_UNINSTALL) @list='$(pcdata_DATA)'; test -n "$(pcdatadir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pcdatadir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files distdir: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-tarZ: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build/sub \ && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile $(DATA) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(pcdatadir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-libtool \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-data-local install-pcdataDATA install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-pcdataDATA .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--refresh check check-am clean clean-cscope clean-generic \ clean-libtool cscope cscopelist-am ctags ctags-am dist \ dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \ dist-xz dist-zip distcheck distclean distclean-generic \ distclean-libtool distclean-tags distcleancheck distdir \ distuninstallcheck dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am \ install-data-local install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pcdataDATA install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-pcdataDATA .PRECIOUS: Makefile libtool: $(LIBTOOL_DEPS) $(SHELL) ./config.status libtool install-data-local: $(MKDIR_P) $(DESTDIR)$(LXCPATH) $(MKDIR_P) $(DESTDIR)$(localstatedir)/cache/lxc ChangeLog:: @touch ChangeLog rpm: dist rpmbuild --clean -ta ${distdir}.tar.gz $(RPMARGS) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lxc-2.0.8/src/0000755061062106075000000000000013105117016010102 500000000000000lxc-2.0.8/src/lua-lxc/0000755061062106075000000000000013105117016011447 500000000000000lxc-2.0.8/src/lua-lxc/test/0000755061062106075000000000000013105117016012426 500000000000000lxc-2.0.8/src/lua-lxc/test/apitest.lua0000755061062106075000000002401113105116772014533 00000000000000#!/usr/bin/env lua -- -- test the lxc lua api -- -- Copyright © 2012 Oracle. -- -- Authors: -- Dwight Engen -- -- This library is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 2, as -- published by the Free Software Foundation. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along -- with this program; if not, write to the Free Software Foundation, Inc., -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -- local lxc = require("lxc") local lfs = require("lfs") local getopt = require("alt_getopt") local LXC_PATH = lxc.default_config_path_get() local container local cfg_containers = {} local optarg = {} local optind = {} function printf(...) local function wrapper(...) io.write(string.format(...)) end local status, result = pcall(wrapper, ...) if not status then error(result, 2) end end function log(level, ...) if (optarg["v"] >= level) then printf(os.date("%Y-%m-%d %T ")) printf(...) printf("\n") end end function die(...) printf(...) os.exit(1) end function test_global_info() local cfg_containers local run_containers log(0, "%-20s %s", "LXC version:", lxc.version_get()) log(0, "%-20s %s", "Container name:", optarg["n"]) if (optarg["c"]) then log(0, "%-20s %s", "Creating container:", "yes") log(0, "%-20s %s", "With template:", optarg["t"]) end log(0, "%-20s %s", "Containers path:", LXC_PATH) cfg_containers = lxc.containers_configured() log(0, "%-20s", "Containers configured:") for _,v in ipairs(cfg_containers) do log(0, " %s", v) end run_containers = lxc.containers_running(true) log(0, "%-20s", "Containers running:") for _,v in ipairs(run_containers) do log(0, " %s", v) end end function test_container_new() container = lxc.container:new(optarg["n"]) assert(container ~= nil) assert(container:config_file_name() == string.format("%s/%s/config", LXC_PATH, optarg["n"])) end function test_container_config_path() local cfgcontainer local cfgpath = "/tmp/" .. optarg["n"] local cfgname = cfgpath .. "/config" log(0, "Test container config path...") -- create a config file in the new location from container's config assert(lfs.mkdir(cfgpath)) assert(container:save_config(cfgname)) cfgcontainer = lxc.container:new(optarg["n"], "/tmp") assert(cfgcontainer ~= nil) log(0, "cfgname:%s cfgpath:%s", cfgcontainer:config_file_name(), cfgcontainer:get_config_path()) assert(cfgcontainer:config_file_name() == cfgname) assert(cfgcontainer:get_config_path() == "/tmp") assert(cfgcontainer:set_config_path(LXC_PATH)) assert(cfgcontainer:get_config_path() == LXC_PATH) assert(os.remove(cfgname)) assert(lfs.rmdir(cfgpath)) end function test_container_create() if (optarg["c"]) then log(0, "%-20s %s", "Destroy existing container:", optarg["n"]) container:destroy() assert(container:defined() == false) else local cfg_containers = lxc.containers_configured() if (cfg_containers[optarg["n"]]) then log(0, "%-20s %s", "Use existing container:", optarg["n"]) return end end log(0, "%-20s %s", "Creating rootfs using:", optarg["t"]) assert(container:create(optarg["t"]) == true) assert(container:defined() == true) assert(container:name() == optarg["n"]) end function test_container_started() local now_running log(2, "state:%s pid:%d\n", container:state(), container:init_pid()) assert(container:init_pid() > 1) assert(container:running() == true) assert(container:state() == "RUNNING") now_running = lxc.containers_running(true) assert(now_running[optarg["n"]] ~= nil) log(1, "%-20s %s", "Running, init pid:", container:init_pid()) end function test_container_stopped() local now_running assert(container:init_pid() == -1) assert(container:running() == false) assert(container:state() == "STOPPED") now_running = lxc.containers_running(true) assert(now_running[optarg["n"]] == nil) end function test_container_frozen() local now_running assert(container:init_pid() > 1) assert(container:running() == true) assert(container:state() == "FROZEN") now_running = lxc.containers_running(true) assert(now_running[optarg["n"]] ~= nil) end function test_container_start() log(0, "Starting...") if (not container:start()) then log(1, "Start returned failure, waiting another 10 seconds...") container:wait("RUNNING", 10) end container:wait("RUNNING", 1) end function test_container_stop() log(0, "Stopping...") if (not container:stop()) then log(1, "Stop returned failure, waiting another 10 seconds...") container:wait("STOPPED", 10) end container:wait("STOPPED", 1) end function test_container_freeze() log(0, "Freezing...") if (not container:freeze()) then log(1, "Freeze returned failure, waiting another 10 seconds...") container:wait("FROZEN", 10) end end function test_container_unfreeze() log(0, "Unfreezing...") if (not container:unfreeze()) then log(1, "Unfreeze returned failure, waiting another 10 seconds...") container:wait("RUNNING", 10) end end function test_container_shutdown() log(0, "Shutting down...") container:shutdown(5) if (container:running()) then test_container_stop() end end function test_container_in_cfglist(should_find) local cfg_containers = lxc.containers_configured() if (should_find) then assert(cfg_containers[container:name()] ~= nil) else assert(cfg_containers[container:name()] == nil) end end function test_container_attach() log(0, "Test attach...") assert(container:running() == true) assert(container:attach("/bin/ps") == true) end function test_container_cgroup() log(0, "Test get/set cgroup items...") max_mem = container:get_cgroup_item("memory.max_usage_in_bytes") saved_limit = container:get_cgroup_item("memory.limit_in_bytes") assert(saved_limit ~= max_mem) assert(container:set_cgroup_item("memory.limit_in_bytes", max_mem)) assert(container:get_cgroup_item("memory.limit_in_bytes") ~= saved_limit) assert(container:set_cgroup_item("memory.limit_in_bytes", "-1")) end function test_container_cmd() log(0, "Test get config from running container...") veth_pair = lxc.cmd_get_config_item(optarg["n"], "lxc.network.0.veth.pair") log(0, " veth.pair:%s", veth_pair) end function test_config_items() log(0, "Test set/clear configuration items...") -- test setting a 'single type' item assert(container:get_config_item("lxc.utsname") == optarg["n"]) container:set_config_item("lxc.utsname", "foobar") assert(container:get_config_item("lxc.utsname") == "foobar") container:set_config_item("lxc.utsname", optarg["n"]) assert(container:get_config_item("lxc.utsname") == optarg["n"]) -- test clearing/setting a 'list type' item container:clear_config_item("lxc.cap.drop") container:set_config_item("lxc.cap.drop", "new_cap1") container:set_config_item("lxc.cap.drop", "new_cap2") local cap_drop = container:get_config_item("lxc.cap.drop") assert(cap_drop["new_cap1"] ~= nil) assert(cap_drop["new_cap2"] ~= nil) -- note: clear_config_item only works on list type items container:clear_config_item("lxc.cap.drop") assert(container:get_config_item("lxc.cap.drop") == nil) local altname = "/tmp/" .. optarg["n"] .. ".altconfig" log(0, "Test saving to an alternate (%s) config file...", altname) assert(container:save_config(altname)) assert(os.remove(altname)) end function test_config_mount_entries() local mntents -- mount entries are a list type item mntents = container:get_config_item("lxc.mount.entry") log(0, "Mount entries:") for _,v in ipairs(mntents) do log(0, " %s", v) end end function test_config_keys() local keys keys = container:get_keys() log(0, "Top level keys:") for k,v in pairs(keys) do log(0, " %s = %s", k, v or "") end end function test_config_network(net_nr) log(0, "Test network %d config...", net_nr) local netcfg netcfg = container:get_keys("lxc.network." .. net_nr) if (netcfg == nil) then return end for k,v in pairs(netcfg) do log(0, " %s = %s", k, v or "") end assert(netcfg["flags"] == "up") assert(container:get_config_item("lxc.network."..net_nr..".type") == "veth") end function usage() die("Usage: apitest \n" .. " -v|--verbose increase verbosity with each -v\n" .. " -h|--help print help message\n" .. " -n|--name name of container to use for testing\n" .. " -c|--create create the test container anew\n" .. " -l|--login do interactive login test\n" .. " -t|--template template to use when creating test container\n" ) end local long_opts = { verbose = "v", help = "h", name = "n", create = "c", template = "t", } optarg,optind = alt_getopt.get_opts (arg, "hvn:ct:", long_opts) optarg["v"] = tonumber(optarg["v"]) or 0 optarg["n"] = optarg["n"] or "lua-apitest" optarg["c"] = optarg["c"] or nil optarg["t"] = optarg["t"] or "busybox" if (optarg["h"] ~= nil) then usage() end test_global_info() test_container_new() test_container_create() test_container_stopped() test_container_in_cfglist(true) test_container_config_path() test_config_items() test_config_keys() test_config_mount_entries() test_config_network(0) test_container_start() test_container_started() test_container_attach() test_container_cgroup() test_container_cmd() test_container_freeze() test_container_frozen() test_container_unfreeze() test_container_started() test_container_shutdown() test_container_stopped() container:destroy() test_container_in_cfglist(false) log(0, "All tests passed") lxc-2.0.8/src/lua-lxc/core.c0000644061062106075000000003572213105116772012504 00000000000000/* * lua-lxc: lua bindings for lxc * * Copyright © 2012 Oracle. * * Authors: * Dwight Engen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define LUA_LIB #define _GNU_SOURCE #include #include #include #include #include #include #include #include "lxc/commands.h" #if LUA_VERSION_NUM < 502 #define luaL_newlib(L,l) (lua_newtable(L), luaL_register(L,NULL,l)) #define luaL_setfuncs(L,l,n) (assert(n==0), luaL_register(L,NULL,l)) #define luaL_checkunsigned(L,n) luaL_checknumber(L,n) #endif #if LUA_VERSION_NUM >= 503 #ifndef luaL_checkunsigned #define luaL_checkunsigned(L,n) ((lua_Unsigned)luaL_checkinteger(L,n)) #endif #endif #ifdef NO_CHECK_UDATA #define checkudata(L,i,tname) lua_touserdata(L, i) #else #define checkudata(L,i,tname) luaL_checkudata(L, i, tname) #endif #define lua_boxpointer(L,u) \ (*(void **) (lua_newuserdata(L, sizeof(void *))) = (u)) #define lua_unboxpointer(L,i,tname) \ (*(void **) (checkudata(L, i, tname))) #define CONTAINER_TYPENAME "lxc.container" /* Max Lua arguments for function */ #define MAXVARS 200 static int container_new(lua_State *L) { struct lxc_container *c; const char *name = luaL_checkstring(L, 1); const char *configpath = NULL; int argc = lua_gettop(L); if (argc > 1) configpath = luaL_checkstring(L, 2); c = lxc_container_new(name, configpath); if (c) { lua_boxpointer(L, c); luaL_getmetatable(L, CONTAINER_TYPENAME); lua_setmetatable(L, -2); } else { lua_pushnil(L); } return 1; } static int container_gc(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); /* XXX what to do if this fails? */ lxc_container_put(c); return 0; } static int container_config_file_name(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); char *config_file_name; config_file_name = c->config_file_name(c); lua_pushstring(L, config_file_name); free(config_file_name); return 1; } static int container_defined(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); lua_pushboolean(L, !!c->is_defined(c)); return 1; } static int container_name(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); lua_pushstring(L, c->name); return 1; } static int container_create(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); char *template_name = strdupa(luaL_checkstring(L, 2)); int argc = lua_gettop(L); char **argv; int i; argv = alloca((argc+1) * sizeof(char *)); for (i = 0; i < argc-2; i++) argv[i] = strdupa(luaL_checkstring(L, i+3)); argv[i] = NULL; lua_pushboolean(L, !!c->create(c, template_name, NULL, NULL, 0, argv)); return 1; } static int container_destroy(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); lua_pushboolean(L, !!c->destroy(c)); return 1; } /* container state */ static int container_start(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); int argc = lua_gettop(L); char **argv = NULL; int i,j; int useinit = 0; if (argc > 1) { argv = alloca((argc+1) * sizeof(char *)); for (i = 0, j = 0; i < argc-1; i++) { const char *arg = luaL_checkstring(L, i+2); if (!strcmp(arg, "useinit")) useinit = 1; else argv[j++] = strdupa(arg); } argv[j] = NULL; } c->want_daemonize(c, true); lua_pushboolean(L, !!c->start(c, useinit, argv)); return 1; } static int container_stop(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); lua_pushboolean(L, !!c->stop(c)); return 1; } static int container_shutdown(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); int timeout = luaL_checkinteger(L, 2); lua_pushboolean(L, !!c->shutdown(c, timeout)); return 1; } static int container_wait(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); const char *state = luaL_checkstring(L, 2); int timeout = luaL_checkinteger(L, 3); lua_pushboolean(L, !!c->wait(c, state, timeout)); return 1; } static int container_rename(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); const char *new_name; int argc = lua_gettop(L); if (argc > 1) { new_name = luaL_checkstring(L, 2); lua_pushboolean(L, !!c->rename(c, new_name)); } else lua_pushnil(L); return 1; } static int container_freeze(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); lua_pushboolean(L, !!c->freeze(c)); return 1; } static int container_unfreeze(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); lua_pushboolean(L, !!c->unfreeze(c)); return 1; } static int container_running(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); lua_pushboolean(L, !!c->is_running(c)); return 1; } static int container_state(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); lua_pushstring(L, c->state(c)); return 1; } static int container_init_pid(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); lua_pushinteger(L, c->init_pid(c)); return 1; } /* configuration file methods */ static int container_load_config(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); int arg_cnt = lua_gettop(L); const char *alt_path = NULL; if (arg_cnt > 1) alt_path = luaL_checkstring(L, 2); lua_pushboolean(L, !!c->load_config(c, alt_path)); return 1; } static int container_save_config(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); int arg_cnt = lua_gettop(L); const char *alt_path = NULL; if (arg_cnt > 1) alt_path = luaL_checkstring(L, 2); lua_pushboolean(L, !!c->save_config(c, alt_path)); return 1; } static int container_get_config_path(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); const char *config_path; config_path = c->get_config_path(c); lua_pushstring(L, config_path); return 1; } static int container_set_config_path(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); const char *config_path = luaL_checkstring(L, 2); lua_pushboolean(L, !!c->set_config_path(c, config_path)); return 1; } static int container_clear_config_item(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); const char *key = luaL_checkstring(L, 2); lua_pushboolean(L, !!c->clear_config_item(c, key)); return 1; } static int container_get_cgroup_item(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); const char *key = luaL_checkstring(L, 2); int len; char *value; len = c->get_cgroup_item(c, key, NULL, 0); if (len <= 0) goto not_found; value = alloca(sizeof(char)*len + 1); if (c->get_cgroup_item(c, key, value, len + 1) != len) goto not_found; lua_pushstring(L, value); return 1; not_found: lua_pushnil(L); return 1; } static int container_get_config_item(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); const char *key = luaL_checkstring(L, 2); int len; char *value; len = c->get_config_item(c, key, NULL, 0); if (len <= 0) goto not_found; value = alloca(sizeof(char)*len + 1); if (c->get_config_item(c, key, value, len + 1) != len) goto not_found; lua_pushstring(L, value); return 1; not_found: lua_pushnil(L); return 1; } static int container_set_cgroup_item(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); const char *key = luaL_checkstring(L, 2); const char *value = luaL_checkstring(L, 3); lua_pushboolean(L, !!c->set_cgroup_item(c, key, value)); return 1; } static int container_set_config_item(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); const char *key = luaL_checkstring(L, 2); const char *value = luaL_checkstring(L, 3); lua_pushboolean(L, !!c->set_config_item(c, key, value)); return 1; } static int container_get_keys(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); const char *key = NULL; int len; char *value; int arg_cnt = lua_gettop(L); if (arg_cnt > 1) key = luaL_checkstring(L, 2); len = c->get_keys(c, key, NULL, 0); if (len <= 0) goto not_found; value = alloca(sizeof(char)*len + 1); if (c->get_keys(c, key, value, len + 1) != len) goto not_found; lua_pushstring(L, value); return 1; not_found: lua_pushnil(L); return 1; } static int container_attach(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); int argc = lua_gettop(L); char **argv = NULL; int i; if (argc > 1) { argv = alloca((argc+1) * sizeof(char *)); for (i = 0; i < argc-1; i++) { const char *arg = luaL_checkstring(L, i+2); argv[i] = strdupa(arg); } argv[i] = NULL; } else { lua_pushnil(L); return 1; } lua_pushboolean(L, !(c->attach_run_wait(c, NULL, argv[0], (const char**)argv))); return 1; } static int container_get_interfaces(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); char **ifaces; int i; ifaces = c->get_interfaces(c); if (!ifaces){ lua_pushnil(L); return 1; } for (i = 0; ifaces[i]; i++); /* protect LUA stack form overflow */ if (i > MAXVARS || !lua_checkstack(L, i)){ for (i = 0; ifaces[i]; i++) free(ifaces[i]); lua_pushnil(L); return 1; } for (i = 0; ifaces[i]; i++){ lua_pushstring(L, ifaces[i]); free(ifaces[i]); } return i; } static int container_get_ips(lua_State *L) { struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME); int argc = lua_gettop(L); char **addresses; char *iface = NULL, *family = NULL; int i, scope = 0; if (argc > 1) iface = (char *)luaL_checkstring(L, 2); if (argc > 2) family = (char *)luaL_checkstring(L, 3); if (argc > 3) scope = luaL_checkinteger(L, 4); addresses = c->get_ips(c, iface, family, scope); if (!addresses){ lua_pushnil(L); return 1; } for (i = 0; addresses[i]; i++); /* protect LUA stack form overflow */ if (i > MAXVARS || !lua_checkstack(L, i)){ for (i = 0; addresses[i]; i++) free(addresses[i]); lua_pushnil(L); return 1; } for (i = 0; addresses[i]; i++){ lua_pushstring(L, addresses[i]); free(addresses[i]); } return i; } static luaL_Reg lxc_container_methods[] = { {"attach", container_attach}, {"create", container_create}, {"defined", container_defined}, {"destroy", container_destroy}, {"init_pid", container_init_pid}, {"name", container_name}, {"running", container_running}, {"state", container_state}, {"freeze", container_freeze}, {"unfreeze", container_unfreeze}, {"start", container_start}, {"stop", container_stop}, {"shutdown", container_shutdown}, {"wait", container_wait}, {"rename", container_rename}, {"config_file_name", container_config_file_name}, {"load_config", container_load_config}, {"save_config", container_save_config}, {"get_cgroup_item", container_get_cgroup_item}, {"set_cgroup_item", container_set_cgroup_item}, {"get_config_path", container_get_config_path}, {"set_config_path", container_set_config_path}, {"get_config_item", container_get_config_item}, {"set_config_item", container_set_config_item}, {"clear_config_item", container_clear_config_item}, {"get_keys", container_get_keys}, {"get_interfaces", container_get_interfaces}, {"get_ips", container_get_ips}, {NULL, NULL} }; static int lxc_version_get(lua_State *L) { lua_pushstring(L, VERSION); return 1; } static int lxc_default_config_path_get(lua_State *L) { const char *lxcpath = lxc_get_global_config_item("lxc.lxcpath"); lua_pushstring(L, lxcpath); return 1; } static int cmd_get_config_item(lua_State *L) { int arg_cnt = lua_gettop(L); const char *name = luaL_checkstring(L, 1); const char *key = luaL_checkstring(L, 2); const char *lxcpath = NULL; char *value; if (arg_cnt > 2) lxcpath = luaL_checkstring(L, 3); value = lxc_cmd_get_config_item(name, key, lxcpath); if (!value) goto not_found; lua_pushstring(L, value); return 1; not_found: lua_pushnil(L); return 1; } /* utility functions */ static int lxc_util_usleep(lua_State *L) { usleep((useconds_t)luaL_checkunsigned(L, 1)); return 0; } static int lxc_util_dirname(lua_State *L) { char *path = strdupa(luaL_checkstring(L, 1)); lua_pushstring(L, dirname(path)); return 1; } static luaL_Reg lxc_lib_methods[] = { {"version_get", lxc_version_get}, {"default_config_path_get", lxc_default_config_path_get}, {"cmd_get_config_item", cmd_get_config_item}, {"container_new", container_new}, {"usleep", lxc_util_usleep}, {"dirname", lxc_util_dirname}, {NULL, NULL} }; static int lxc_lib_uninit(lua_State *L) { (void) L; /* this is where we would fini liblxc.so if we needed to */ return 0; } LUALIB_API int luaopen_lxc_core(lua_State *L) { /* this is where we would initialize liblxc.so if we needed to */ luaL_newlib(L, lxc_lib_methods); lua_newuserdata(L, 0); lua_newtable(L); /* metatable */ lua_pushvalue(L, -1); lua_pushliteral(L, "__gc"); lua_pushcfunction(L, lxc_lib_uninit); lua_rawset(L, -3); lua_setmetatable(L, -3); lua_rawset(L, -3); luaL_newmetatable(L, CONTAINER_TYPENAME); luaL_setfuncs(L, lxc_container_methods, 0); lua_pushvalue(L, -1); /* push metatable */ lua_pushstring(L, "__gc"); lua_pushcfunction(L, container_gc); lua_settable(L, -3); lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ lua_pop(L, 1); return 1; } lxc-2.0.8/src/lua-lxc/Makefile.in0000644061062106075000000006241613105116776013461 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/lua-lxc ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/acinclude.m4 \ $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/tls.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(luadir)" LTLIBRARIES = $(lib_LTLIBRARIES) libcore_la_DEPENDENCIES = am__libcore_la_SOURCES_DIST = core.c @ENABLE_LUA_TRUE@am_libcore_la_OBJECTS = libcore_la-core.lo libcore_la_OBJECTS = $(am_libcore_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libcore_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libcore_la_CFLAGS) \ $(CFLAGS) $(libcore_la_LDFLAGS) $(LDFLAGS) -o $@ @ENABLE_LUA_TRUE@am_libcore_la_rpath = -rpath $(libdir) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src depcomp = $(SHELL) $(top_srcdir)/config/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libcore_la_SOURCES) DIST_SOURCES = $(am__libcore_la_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(lua_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/config/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APPARMOR_LIBS = @APPARMOR_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BINDIR = @BINDIR@ CAP_LIBS = @CAP_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CGMANAGER_CFLAGS = @CGMANAGER_CFLAGS@ CGMANAGER_LIBS = @CGMANAGER_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIR = @DATADIR@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFAULT_CGROUP_PATTERN = @DEFAULT_CGROUP_PATTERN@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOCDIR = @DOCDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ HAVE_DOXYGEN = @HAVE_DOXYGEN@ INCLUDEDIR = @INCLUDEDIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDIR = @LIBDIR@ LIBEXECDIR = @LIBEXECDIR@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCALSTATEDIR = @LOCALSTATEDIR@ LOGPATH = @LOGPATH@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBDIR = @LUA_LIBDIR@ LUA_LIBS = @LUA_LIBS@ LUA_SHAREDIR = @LUA_SHAREDIR@ LUA_VERSION = @LUA_VERSION@ LXCBINHOOKDIR = @LXCBINHOOKDIR@ LXCHOOKDIR = @LXCHOOKDIR@ LXCINITDIR = @LXCINITDIR@ LXCPATH = @LXCPATH@ LXCROOTFSMOUNT = @LXCROOTFSMOUNT@ LXCTEMPLATECONFIG = @LXCTEMPLATECONFIG@ LXCTEMPLATEDIR = @LXCTEMPLATEDIR@ LXC_ABI = @LXC_ABI@ LXC_ABI_MAJOR = @LXC_ABI_MAJOR@ LXC_ABI_MICRO = @LXC_ABI_MICRO@ LXC_ABI_MINOR = @LXC_ABI_MINOR@ LXC_DEFAULT_CONFIG = @LXC_DEFAULT_CONFIG@ LXC_DEVEL = @LXC_DEVEL@ LXC_DISTRO_SYSCONF = @LXC_DISTRO_SYSCONF@ LXC_GENERATE_DATE = @LXC_GENERATE_DATE@ LXC_GLOBAL_CONF = @LXC_GLOBAL_CONF@ LXC_USERNIC_CONF = @LXC_USERNIC_CONF@ LXC_USERNIC_DB = @LXC_USERNIC_DB@ LXC_VERSION = @LXC_VERSION@ LXC_VERSION_BASE = @LXC_VERSION_BASE@ LXC_VERSION_BETA = @LXC_VERSION_BETA@ LXC_VERSION_MAJOR = @LXC_VERSION_MAJOR@ LXC_VERSION_MICRO = @LXC_VERSION_MICRO@ LXC_VERSION_MINOR = @LXC_VERSION_MINOR@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NIH_CFLAGS = @NIH_CFLAGS@ NIH_DBUS_CFLAGS = @NIH_DBUS_CFLAGS@ NIH_DBUS_LIBS = @NIH_DBUS_LIBS@ NIH_LIBS = @NIH_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PREFIX = @PREFIX@ PYTHON = @PYTHON@ PYTHONDEV_CFLAGS = @PYTHONDEV_CFLAGS@ PYTHONDEV_LIBS = @PYTHONDEV_LIBS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RUNTIME_PATH = @RUNTIME_PATH@ SBINDIR = @SBINDIR@ SECCOMP_CFLAGS = @SECCOMP_CFLAGS@ SECCOMP_LIBS = @SECCOMP_LIBS@ SED = @SED@ SELINUX_LIBS = @SELINUX_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SYSCONFDIR = @SYSCONFDIR@ SYSTEMD_UNIT_DIR = @SYSTEMD_UNIT_DIR@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bashcompdir = @bashcompdir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ db2xman = @db2xman@ docdir = @docdir@ docdtd = @docdtd@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ @ENABLE_LUA_TRUE@luasharedir = $(LUA_SHAREDIR) @ENABLE_LUA_TRUE@lualibdir = $(LUA_LIBDIR) @ENABLE_LUA_TRUE@luadir = $(luasharedir) @ENABLE_LUA_TRUE@sodir = $(lualibdir)/lxc @ENABLE_LUA_TRUE@lua_DATA = lxc.lua @ENABLE_LUA_TRUE@lib_LTLIBRARIES = libcore.la @ENABLE_LUA_TRUE@libcore_la_SOURCES = core.c @ENABLE_LUA_TRUE@AM_CFLAGS = -I$(top_builddir)/src -I$(top_srcdir)/src $(LUA_CFLAGS) -DVERSION=\"$(VERSION)\" -DLXCPATH=\"$(LXCPATH)\" @ENABLE_LUA_TRUE@libcore_la_CFLAGS = -fPIC -DPIC $(AM_CFLAGS) @ENABLE_LUA_TRUE@libcore_la_LDFLAGS = \ @ENABLE_LUA_TRUE@ -shared \ @ENABLE_LUA_TRUE@ -L$(top_builddir)/src/lxc \ @ENABLE_LUA_TRUE@ -Wl,-soname,core.so.$(firstword $(subst ., ,$(VERSION))) @ENABLE_LUA_TRUE@libcore_la_LIBADD = -llxc EXTRA_DIST = \ lxc.lua \ test/apitest.lua all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/lua-lxc/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/lua-lxc/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libcore.la: $(libcore_la_OBJECTS) $(libcore_la_DEPENDENCIES) $(EXTRA_libcore_la_DEPENDENCIES) $(AM_V_CCLD)$(libcore_la_LINK) $(am_libcore_la_rpath) $(libcore_la_OBJECTS) $(libcore_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcore_la-core.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libcore_la-core.lo: core.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcore_la_CFLAGS) $(CFLAGS) -MT libcore_la-core.lo -MD -MP -MF $(DEPDIR)/libcore_la-core.Tpo -c -o libcore_la-core.lo `test -f 'core.c' || echo '$(srcdir)/'`core.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcore_la-core.Tpo $(DEPDIR)/libcore_la-core.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='core.c' object='libcore_la-core.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcore_la_CFLAGS) $(CFLAGS) -c -o libcore_la-core.lo `test -f 'core.c' || echo '$(srcdir)/'`core.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-luaDATA: $(lua_DATA) @$(NORMAL_INSTALL) @list='$(lua_DATA)'; test -n "$(luadir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(luadir)'"; \ $(MKDIR_P) "$(DESTDIR)$(luadir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(luadir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(luadir)" || exit $$?; \ done uninstall-luaDATA: @$(NORMAL_UNINSTALL) @list='$(lua_DATA)'; test -n "$(luadir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(luadir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(DATA) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(luadir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." @ENABLE_LUA_FALSE@uninstall-local: @ENABLE_LUA_FALSE@install-exec-local: clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-luaDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-exec-local install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES uninstall-local \ uninstall-luaDATA .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-exec-local install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-luaDATA install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES \ uninstall-local uninstall-luaDATA .PRECIOUS: Makefile @ENABLE_LUA_TRUE@install-exec-local: install-libLTLIBRARIES @ENABLE_LUA_TRUE@ mkdir -p $(DESTDIR)$(lualibdir)/lxc/ @ENABLE_LUA_TRUE@ mv $(DESTDIR)$(libdir)/libcore.so.0.0.0 $(DESTDIR)$(lualibdir)/lxc/core.so @ENABLE_LUA_TRUE@ rm $(DESTDIR)$(libdir)/libcore.* @ENABLE_LUA_TRUE@uninstall-local: @ENABLE_LUA_TRUE@ $(RM) $(DESTDIR)$(lualibdir)/lxc/core.so* @ENABLE_LUA_TRUE@lxc.lua: # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lxc-2.0.8/src/lua-lxc/lxc.lua0000755061062106075000000002434013105116772012676 00000000000000-- -- lua lxc module -- -- Copyright © 2012 Oracle. -- -- Authors: -- Dwight Engen -- -- This library is free software; you can redistribute it and/or -- modify it under the terms of the GNU Lesser General Public -- License as published by the Free Software Foundation; either -- version 2.1 of the License, or (at your option) any later version. -- -- This library is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public -- License along with this library; if not, write to the Free Software -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -- local core = require("lxc.core") local lfs = require("lfs") local table = require("table") local string = require("string") local io = require("io") module("lxc", package.seeall) local lxc_path local log_level = 3 -- lua 5.1 compat if table.unpack == nil then table.unpack = unpack end -- the following two functions can be useful for debugging function printf(...) local function wrapper(...) io.write(string.format(...)) end local status, result = pcall(wrapper, ...) if not status then error(result, 2) end end function log(level, ...) if (log_level >= level) then printf(os.date("%Y-%m-%d %T ")) printf(...) end end function string:split(delim, max_cols) local cols = {} local start = 1 local nextc repeat nextc = string.find(self, delim, start) if (nextc and #cols ~= max_cols - 1) then table.insert(cols, string.sub(self, start, nextc-1)) start = nextc + #delim else table.insert(cols, string.sub(self, start, string.len(self))) nextc = nil end until nextc == nil or start > #self return cols end -- container class container = {} container_mt = {} container_mt.__index = container function container:new(lname, config) local lcore local lnetcfg = {} local lstats = {} if lname then if config then lcore = core.container_new(lname, config) else lcore = core.container_new(lname) end end return setmetatable({ctname = lname, core = lcore, netcfg = lnetcfg, stats = lstats}, container_mt) end -- methods interfacing to core functionality function container:attach(what, ...) return self.core:attach(what, ...) end function container:config_file_name() return self.core:config_file_name() end function container:defined() return self.core:defined() end function container:init_pid() return self.core:init_pid() end function container:name() return self.core:name() end function container:start() return self.core:start() end function container:stop() return self.core:stop() end function container:shutdown(timeout) return self.core:shutdown(timeout) end function container:wait(state, timeout) return self.core:wait(state, timeout) end function container:freeze() return self.core:freeze() end function container:unfreeze() return self.core:unfreeze() end function container:running() return self.core:running() end function container:state() return self.core:state() end function container:create(template, ...) return self.core:create(template, ...) end function container:destroy() return self.core:destroy() end -- return nil if name missing function container:rename(name) return self.core:rename(name) end function container:get_config_path() return self.core:get_config_path() end function container:set_config_path(path) return self.core:set_config_path(path) end function container:append_config_item(key, value) return self.core:set_config_item(key, value) end function container:clear_config_item(key) return self.core:clear_config_item(key) end function container:get_cgroup_item(key) return self.core:get_cgroup_item(key) end function container:get_config_item(key) local value local vals = {} value = self.core:get_config_item(key) -- check if it is a single item if (not value or not string.find(value, "\n")) then return value end -- it must be a list type item, make a table of it vals = value:split("\n", 1000) -- make it a "mixed" table, ie both dictionary and list for ease of use for _,v in ipairs(vals) do vals[v] = true end return vals end function container:set_cgroup_item(key, value) return self.core:set_cgroup_item(key, value) end function container:set_config_item(key, value) return self.core:set_config_item(key, value) end function container:get_keys(base) local ktab = {} local keys if (base) then keys = self.core:get_keys(base) base = base .. "." else keys = self.core:get_keys() base = "" end if (keys == nil) then return nil end keys = keys:split("\n", 1000) for _,v in ipairs(keys) do local config_item = base .. v ktab[v] = self.core:get_config_item(config_item) end return ktab end -- return nil or more args function container:get_interfaces() return self.core:get_interfaces() end -- return nil or more args function container:get_ips(...) return self.core:get_ips(...) end function container:load_config(alt_path) if (alt_path) then return self.core:load_config(alt_path) else return self.core:load_config() end end function container:save_config(alt_path) if (alt_path) then return self.core:save_config(alt_path) else return self.core:save_config() end end -- methods for stats collection from various cgroup files -- read integers at given coordinates from a cgroup file function container:stat_get_ints(item, coords) local lines = {} local result = {} local flines = self:get_cgroup_item(item) if (flines == nil) then for k,c in ipairs(coords) do table.insert(result, 0) end else for line in flines:gmatch("[^\r\n]+") do table.insert(lines, line) end for k,c in ipairs(coords) do local col col = lines[c[1]]:split(" ", 80) local val = tonumber(col[c[2]]) table.insert(result, val) end end return table.unpack(result) end -- read an integer from a cgroup file function container:stat_get_int(item) local line = self:get_cgroup_item(item) -- if line is nil (on an error like Operation not supported because -- CONFIG_MEMCG_SWAP_ENABLED isn't enabled) return 0 return tonumber(line) or 0 end function container:stat_match_get_int(item, match, column) local val local lines = self:get_cgroup_item(item) if (lines == nil) then return 0 end for line in lines:gmatch("[^\r\n]+") do if (string.find(line, match)) then local col col = line:split(" ", 80) val = tonumber(col[column]) or 0 end end return val end function container:stats_get(total) local stat = {} stat.mem_used = self:stat_get_int("memory.usage_in_bytes") stat.mem_limit = self:stat_get_int("memory.limit_in_bytes") stat.memsw_used = self:stat_get_int("memory.memsw.usage_in_bytes") stat.memsw_limit = self:stat_get_int("memory.memsw.limit_in_bytes") stat.kmem_used = self:stat_get_int("memory.kmem.usage_in_bytes") stat.kmem_limit = self:stat_get_int("memory.kmem.limit_in_bytes") stat.cpu_use_nanos = self:stat_get_int("cpuacct.usage") stat.cpu_use_user, stat.cpu_use_sys = self:stat_get_ints("cpuacct.stat", {{1, 2}, {2, 2}}) stat.blkio = self:stat_match_get_int("blkio.throttle.io_service_bytes", "Total", 2) if (total) then total.mem_used = total.mem_used + stat.mem_used total.mem_limit = total.mem_limit + stat.mem_limit total.memsw_used = total.memsw_used + stat.memsw_used total.memsw_limit = total.memsw_limit + stat.memsw_limit total.kmem_used = total.kmem_used + stat.kmem_used total.kmem_limit = total.kmem_limit + stat.kmem_limit total.cpu_use_nanos = total.cpu_use_nanos + stat.cpu_use_nanos total.cpu_use_user = total.cpu_use_user + stat.cpu_use_user total.cpu_use_sys = total.cpu_use_sys + stat.cpu_use_sys total.blkio = total.blkio + stat.blkio end return stat end local M = { container = container } function M.stats_clear(stat) stat.mem_used = 0 stat.mem_limit = 0 stat.memsw_used = 0 stat.memsw_limit = 0 stat.kmem_used = 0 stat.kmem_limit = 0 stat.cpu_use_nanos = 0 stat.cpu_use_user = 0 stat.cpu_use_sys = 0 stat.blkio = 0 end -- return configured containers found in LXC_PATH directory function M.containers_configured(names_only) local containers = {} for dir in lfs.dir(lxc_path) do if (dir ~= "." and dir ~= "..") then local cfgfile = lxc_path .. "/" .. dir .. "/config" local cfgattr = lfs.attributes(cfgfile) if (cfgattr and cfgattr.mode == "file") then if (names_only) then -- note, this is a "mixed" table, ie both dictionary and list containers[dir] = true table.insert(containers, dir) else local ct = container:new(dir) -- note, this is a "mixed" table, ie both dictionary and list containers[dir] = ct table.insert(containers, dir) end end end end table.sort(containers, function (a,b) return (a < b) end) return containers end -- return running containers found in cgroup fs function M.containers_running(names_only) local containers = {} local names = M.containers_configured(true) for _,name in ipairs(names) do local ct = container:new(name) if ct:running() then -- note, this is a "mixed" table, ie both dictionary and list table.insert(containers, name) if (names_only) then containers[name] = true ct = nil else containers[name] = ct end end end table.sort(containers, function (a,b) return (a < b) end) return containers end function M.version_get() return core.version_get() end function M.default_config_path_get() return core.default_config_path_get() end function M.cmd_get_config_item(name, item, lxcpath) if (lxcpath) then return core.cmd_get_config_item(name, item, lxcpath) else return core.cmd_get_config_item(name, item) end end lxc_path = core.default_config_path_get() return M lxc-2.0.8/src/lua-lxc/Makefile.am0000644061062106075000000000145613105116772013441 00000000000000if ENABLE_LUA luasharedir=$(LUA_SHAREDIR) lualibdir=$(LUA_LIBDIR) luadir=$(luasharedir) sodir=$(lualibdir)/lxc lua_DATA=lxc.lua lib_LTLIBRARIES = libcore.la libcore_la_SOURCES = core.c AM_CFLAGS=-I$(top_builddir)/src -I$(top_srcdir)/src $(LUA_CFLAGS) -DVERSION=\"$(VERSION)\" -DLXCPATH=\"$(LXCPATH)\" libcore_la_CFLAGS = -fPIC -DPIC $(AM_CFLAGS) libcore_la_LDFLAGS = \ -shared \ -L$(top_builddir)/src/lxc \ -Wl,-soname,core.so.$(firstword $(subst ., ,$(VERSION))) libcore_la_LIBADD = -llxc install-exec-local: install-libLTLIBRARIES mkdir -p $(DESTDIR)$(lualibdir)/lxc/ mv $(DESTDIR)$(libdir)/libcore.so.0.0.0 $(DESTDIR)$(lualibdir)/lxc/core.so rm $(DESTDIR)$(libdir)/libcore.* uninstall-local: $(RM) $(DESTDIR)$(lualibdir)/lxc/core.so* lxc.lua: endif EXTRA_DIST= \ lxc.lua \ test/apitest.lua lxc-2.0.8/src/tests/0000755061062106075000000000000013105117016011244 500000000000000lxc-2.0.8/src/tests/lxc-test-cloneconfig0000755061062106075000000000657413105116772015165 00000000000000#!/bin/bash # lxc: linux Container library # Authors: # Serge Hallyn # # This is a test script for the lxc-user-nic program # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA set -e s=`mktemp -d /tmp/lxctest-XXXXXX` DONE=0 verify_unchanged_number() { key=$1 desc=$2 n1=`grep ^$key $CONTAINER_PATH/config | wc -l` n2=`grep ^$key $CONTAINER2_PATH/config | wc -l` if [ $n1 -ne $n2 ]; then echo "Test $testnum failed" echo "unequal number of $desc" echo "Original has $n1, clone has $n2" false fi } cleanup() { lxc-destroy -n lxctestb || true lxc-destroy -n lxctestb2 || true rm -rf $s [ $DONE -eq 1 ] && echo "PASS" || echo "FAIL" } verify_numnics() { verify_unchanged_number lxc.network.type "network defs" } verify_hwaddr() { verify_unchanged_number lxc.network.hwaddr "hwaddr defs" grep ^lxc.network.hwaddr $CONTAINER_PATH/config | while read line; do addr=`echo $line | awk -F= { print $2 }` echo "looking for $addr in $CONTAINER2_PATH/config" if grep -q $addr $CONTAINER2_PATH/config; then echo "Test $testnum failed" echo "hwaddr $addr was not changed" false fi done } verify_hooks() { verify_unchanged_number lxc.hook "hooks" grep ^lxc.hook $CONTAINER_PATH/config | while read line; do nline=${line/$CONTAINER_PATH/$CONTAINER2_PATH} if ! grep -q "$nline" $CONTAINER2_PATH/config; then echo "Test $testnum failed" echo "Failed to find $nline in:" cat $CONTAINER2_PATH/config fi done } trap cleanup EXIT # Simple nic cat > $s/1.conf << EOF lxc.network.type = veth lxc.network.link = lxcbr0 EOF # Simple nic with hwaddr; verify hwaddr changed cat > $s/2.conf << EOF lxc.network.type = veth lxc.network.link = lxcbr0 EOF # No nics, but nic from include cat > $s/1.include << EOF lxc.network.type = veth lxc.network.link = lxcbr0 lxc.hook.start = /bin/bash EOF cat > $s/3.conf << EOF lxc.include = $s/1.include EOF # No nics, one clone hook in /bin cat > $s/4.conf << EOF lxc.hook.start = /bin/bash EOF # Figure out container dirname # We need this in 5.conf lxc-destroy -n lxctestb || true lxc-create -t busybox -n lxctestb CONTAINER_PATH=$(dirname $(lxc-info -n lxctestb -c lxc.rootfs -H)) lxc-destroy -n lxctestb # No nics, one clone hook in $container cat > $s/5.conf << EOF lxc.hook.start = $CONTAINER_PATH/x1 EOF CONTAINER2_PATH="${CONTAINER_PATH}2" testnum=1 for f in $s/*.conf; do echo "Test $testnum starting ($f)" lxc-create -t busybox -f $f -n lxctestb touch $CONTAINER_PATH/x1 lxc-copy -s -n lxctestb -N lxctestb2 # verify that # nics did not change verify_numnics # verify hwaddr, if any changed verify_hwaddr # verify hooks are correct verify_hooks lxc-destroy -n lxctestb2 || true lxc-destroy -n lxctestb || true testnum=$((testnum+1)) done DONE=1 lxc-2.0.8/src/tests/aa.c0000644061062106075000000001101513105116772011717 00000000000000/* liblxcapi * * Copyright 2014 Serge Hallyn . * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* Test apparmor rules */ #include #include "lxc/utils.h" #include #include #include #define MYNAME "test-aa" static void try_to_remove(void) { struct lxc_container *c; c = lxc_container_new(MYNAME, NULL); if (c) { if (c->is_defined(c)) c->destroy(c); lxc_container_put(c); } } static int test_attach_write_file(void* payload) { char *fnam = payload; FILE *f; f = fopen(fnam, "w"); if (f) { printf("yes\n"); fclose(f); fflush(NULL); return 1; } printf("no\n"); fflush(NULL); return 0; } /* * try opening a file attached to a container. Return 0 on open fail. Return * 1 if the file open succeeded. Return -1 if attach itself failed - perhas an * older kernel. */ static int do_test_file_open(struct lxc_container *c, char *fnam) { int fret = -1; int ret; pid_t pid; int pipefd[2]; char result[1024]; lxc_attach_options_t attach_options = LXC_ATTACH_OPTIONS_DEFAULT; ret = pipe(pipefd); if (ret < 0) { fprintf(stderr, "pipe failed %d\n", ret); return fret; } attach_options.stdout_fd = pipefd[1]; attach_options.attach_flags &= ~(LXC_ATTACH_LSM_EXEC|LXC_ATTACH_DROP_CAPABILITIES); attach_options.attach_flags |= LXC_ATTACH_LSM_NOW; ret = c->attach(c, test_attach_write_file, fnam, &attach_options, &pid); if (ret < 0) { fprintf(stderr, "attach failed\n"); goto err1; } ret = read(pipefd[0], result, sizeof(result)-1); if (ret < 0) { fprintf(stderr, "read failed %d\n", ret); goto err2; } fret = 1; if (strncmp(result, "no", 2) == 0) fret = 0; err2: wait_for_pid(pid); err1: close(pipefd[0]); close(pipefd[1]); return fret; } char *files_to_allow[] = { "/sys/class/net/lo/ifalias", "/proc/sys/kernel/shmmax", NULL }; char *files_to_deny[] = { "/proc/mem", "/proc/kmem", "/sys/kernel/uevent_helper", "/proc/sys/fs/file-nr", "/sys/kernel/mm/ksm/pages_to_scan", "/proc/sys/kernel/sysrq", NULL }; static bool test_aa_policy(struct lxc_container *c) { int i, ret; for (i = 0; files_to_deny[i]; i++) { ret = do_test_file_open(c, files_to_deny[i]); if (ret < 0) { fprintf(stderr, "attach failed; skipping test\n"); return true; } if (ret > 0) { fprintf(stderr, "failed - opened %s\n", files_to_deny[i]); return false; } fprintf(stderr, "passed with %s\n", files_to_deny[i]); } for (i = 0; files_to_allow[i]; i++) { ret = do_test_file_open(c, files_to_allow[i]); if (ret < 0) { fprintf(stderr, "attach failed; skipping test\n"); return true; } if (ret == 0) { fprintf(stderr, "failed - could not open %s\n", files_to_allow[i]); return false; } fprintf(stderr, "passed with %s\n", files_to_allow[i]); } return true; } int main(int argc, char *argv[]) { struct lxc_container *c; try_to_remove(); c = lxc_container_new(MYNAME, NULL); if (!c) { fprintf(stderr, "%s: %d: failed to load first container\n", __FILE__, __LINE__); exit(1); } if (c->is_defined(c)) { fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME); goto err; } if (!c->set_config_item(c, "lxc.network.type", "empty")) { fprintf(stderr, "%s: %d: failed to set network type\n", __FILE__, __LINE__); goto err; } c->save_config(c, NULL); if (!c->createl(c, "busybox", NULL, NULL, 0, NULL)) { fprintf(stderr, "%s: %d: failed to create container\n", __FILE__, __LINE__); goto err; } c->clear_config_item(c, "lxc.mount.auto"); c->set_config_item(c, "lxc.mount.entry", "proc proc proc"); c->set_config_item(c, "lxc.mount.entry", "sysfs sys sysfs"); c->save_config(c, NULL); c->want_daemonize(c, true); if (!c->startl(c, 0, NULL)) { fprintf(stderr, "Error starting container\n"); goto err; } if (!test_aa_policy(c)) { c->stop(c); goto err; } c->stop(c); try_to_remove(); exit(0); err: try_to_remove(); exit(1); } lxc-2.0.8/src/tests/lxctest.h0000644061062106075000000000400213105116772013027 00000000000000/* * lxc: linux Container library * * Copyright © 2016 Canonical Ltd. * * Authors: * Christian Brauner * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_TEST_H_ #define __LXC_TEST_H_ #include #include #include #define lxc_debug_stream(stream, format, ...) \ do { \ fprintf(stream, "%s: %d: %s: " format, __FILE__, __LINE__, \ __func__, __VA_ARGS__); \ } while (false) #define lxc_error(format, ...) lxc_debug_stream(stderr, format, __VA_ARGS__) #define lxc_debug(format, ...) lxc_debug_stream(stdout, format, __VA_ARGS__) #define lxc_test_assert_stringify(expression, stringify_expression) \ do { \ if (!(expression)) { \ fprintf(stderr, "%s: %s: %d: %s\n", __FILE__, \ __func__, __LINE__, stringify_expression); \ abort(); \ } \ } while (false) #define lxc_test_assert_abort(expression) lxc_test_assert_stringify(expression, #expression) #endif /* __LXC_TEST_H */ lxc-2.0.8/src/tests/lxc-test-snapdeps0000644061062106075000000000403113105116772014473 00000000000000#!/bin/bash # lxc: linux Container library # Authors: # Serge Hallyn # # This is a test for dependency between snapshots # # When container c2 is created as an overlayfs clone of c1, then # we record it as such, because c1 cannot be deleted until c2 is # deleted. Once c2 is deleted, c1 should be delete-able. # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # This test assumes an Ubuntu host set -e if ! grep -q overlay /proc/filesystems; then echo "Not running this test as overlay is not available" exit 0 fi cleanup() { for i in `seq 1 20`; do lxc-destroy -n snapdeptest$i > /dev/null 2>&1 || true done lxc-destroy -n snapdeptest > /dev/null 2>&1 || true } verify_deps() { n=$1 m=`wc -l /var/lib/lxc/snapdeptest/lxc_snapshots | awk '{ print $1 }'` [ $((n*2)) -eq $m ] } cleanup trap cleanup EXIT SIGHUP SIGINT SIGTERM lxc-create -t busybox -n snapdeptest lxc-copy -s -n snapdeptest -N snapdeptest1 fail=0 lxc-destroy -n snapdeptest || fail=1 if [ $fail -eq 0 ]; then echo "FAIL: clone did not prevent deletion" false fi for i in `seq 2 20`; do lxc-copy -s -n snapdeptest -N snapdeptest$i done verify_deps 20 lxc-destroy -n snapdeptest1 verify_deps 19 lxc-destroy -n snapdeptest20 verify_deps 18 for i in `seq 2 19`; do lxc-destroy -n snapdeptest$i done lxc-destroy -n snapdeptest echo "Snapshot clone dependency test passed" exit 0 lxc-2.0.8/src/tests/startone.c0000644061062106075000000001434113105116772013202 00000000000000/* liblxcapi * * Copyright © 2012 Serge Hallyn . * Copyright © 2012 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include #include #include #include #define MYNAME "lxctest1" static int destroy_container(void) { int status, ret; pid_t pid = fork(); if (pid < 0) { perror("fork"); return -1; } if (pid == 0) { ret = execlp("lxc-destroy", "lxc-destroy", "-f", "-n", MYNAME, NULL); // Should not return perror("execl"); exit(1); } again: ret = waitpid(pid, &status, 0); if (ret == -1) { if (errno == EINTR) goto again; perror("waitpid"); return -1; } if (ret != pid) goto again; if (!WIFEXITED(status)) { // did not exit normally fprintf(stderr, "%d: lxc-create exited abnormally\n", __LINE__); return -1; } return WEXITSTATUS(status); } static int create_container(void) { int status, ret; pid_t pid = fork(); if (pid < 0) { perror("fork"); return -1; } if (pid == 0) { ret = execlp("lxc-create", "lxc-create", "-t", "busybox", "-n", MYNAME, NULL); // Should not return perror("execl"); exit(1); } again: ret = waitpid(pid, &status, 0); if (ret == -1) { if (errno == EINTR) goto again; perror("waitpid"); return -1; } if (ret != pid) goto again; if (!WIFEXITED(status)) { // did not exit normally fprintf(stderr, "%d: lxc-create exited abnormally\n", __LINE__); return -1; } return WEXITSTATUS(status); } int main(int argc, char *argv[]) { struct lxc_container *c; int ret = 0; const char *s; bool b; char buf[201]; int len; ret = 1; /* test a real container */ c = lxc_container_new(MYNAME, NULL); if (!c) { fprintf(stderr, "%d: error creating lxc_container %s\n", __LINE__, MYNAME); ret = 1; goto out; } if (c->is_defined(c)) { fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME); goto out; } ret = create_container(); if (ret) { fprintf(stderr, "%d: failed to create a container\n", __LINE__); goto out; } b = c->is_defined(c); if (!b) { fprintf(stderr, "%d: %s thought it was not defined\n", __LINE__, MYNAME); goto out; } len = c->get_cgroup_item(c, "cpuset.cpus", buf, 200); if (len >= 0) { fprintf(stderr, "%d: %s not running but had cgroup settings\n", __LINE__, MYNAME); goto out; } sprintf(buf, "0"); b = c->set_cgroup_item(c, "cpuset.cpus", buf); if (b) { fprintf(stderr, "%d: %s not running but coudl set cgroup settings\n", __LINE__, MYNAME); goto out; } s = c->state(c); if (!s || strcmp(s, "STOPPED")) { fprintf(stderr, "%d: %s is in state %s, not in STOPPED.\n", __LINE__, c->name, s ? s : "undefined"); goto out; } b = c->load_config(c, NULL); if (!b) { fprintf(stderr, "%d: %s failed to read its config\n", __LINE__, c->name); goto out; } if (!c->set_config_item(c, "lxc.utsname", "bobo")) { fprintf(stderr, "%d: failed setting lxc.utsname\n", __LINE__); goto out; } if (!lxc_container_get(c)) { fprintf(stderr, "%d: failed to get extra ref to container\n", __LINE__); exit(1); } c->want_daemonize(c, true); if (!c->startl(c, 0, NULL)) { fprintf(stderr, "%d: %s failed to start\n", __LINE__, c->name); exit(1); } sleep(3); s = c->state(c); if (!s || strcmp(s, "RUNNING")) { fprintf(stderr, "%d: %s is in state %s, not in RUNNING.\n", __LINE__, c->name, s ? s : "undefined"); goto out; } len = c->get_cgroup_item(c, "cpuset.cpus", buf, 0); if (len <= 0) { fprintf(stderr, "%d: not able to get length of cpuset.cpus (ret %d)\n", __LINE__, len); goto out; } len = c->get_cgroup_item(c, "cpuset.cpus", buf, 200); if (len <= 0 || strncmp(buf, "0", 1)) { fprintf(stderr, "%d: not able to get cpuset.cpus (len %d buf %s)\n", __LINE__, len, buf); goto out; } sprintf(buf, "FROZEN"); b = c->set_cgroup_item(c, "freezer.state", buf); if (!b) { fprintf(stderr, "%d: not able to set freezer.state.\n", __LINE__); goto out; } sprintf(buf, "XXX"); len = c->get_cgroup_item(c, "freezer.state", buf, 200); if (len <= 0 || (strcmp(buf, "FREEZING\n") && strcmp(buf, "FROZEN\n"))) { fprintf(stderr, "%d: not able to get freezer.state (len %d buf %s)\n", __LINE__, len, buf); goto out; } c->set_cgroup_item(c, "freezer.state", "THAWED"); c->stop(c); /* feh - multilib has moved the lxc-init crap */ #if 0 goto ok; ret = system("mkdir -p " LXCPATH "/lxctest1/rootfs//usr/local/libexec/lxc"); if (!ret) ret = system("mkdir -p " LXCPATH "/lxctest1/rootfs/usr/lib/lxc/"); if (!ret) ret = system("cp src/lxc/lxc-init " LXCPATH "/lxctest1/rootfs//usr/local/libexec/lxc"); if (!ret) ret = system("cp src/lxc/liblxc.so " LXCPATH "/lxctest1/rootfs/usr/lib/lxc"); if (!ret) ret = system("cp src/lxc/liblxc.so " LXCPATH "/lxctest1/rootfs/usr/lib/lxc/liblxc.so.0"); if (!ret) ret = system("cp src/lxc/liblxc.so " LXCPATH "/lxctest1/rootfs/usr/lib"); if (!ret) ret = system("mkdir -p " LXCPATH "/lxctest1/rootfs/dev/shm"); if (!ret) ret = system("chroot " LXCPATH "/lxctest1/rootfs apt-get install --no-install-recommends lxc"); if (ret) { fprintf(stderr, "%d: failed to installing lxc-init in container\n", __LINE__); goto out; } // next write out the config file; does it match? if (!c->startl(c, 1, "/bin/hostname", NULL)) { fprintf(stderr, "%d: failed to lxc-execute /bin/hostname\n", __LINE__); goto out; } // auto-check result? ('bobo' is printed on stdout) ok: #endif fprintf(stderr, "all lxc_container tests passed for %s\n", c->name); ret = 0; out: if (c) { c->stop(c); destroy_container(); } lxc_container_put(c); exit(ret); } lxc-2.0.8/src/tests/lxc-test-automount0000644061062106075000000001537413105116772014725 00000000000000#!/bin/bash # lxc: linux Container library # Authors: # Serge Hallyn # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # At the moment this only tests cgroup automount. Testing proc and # sys automounts would be worthwhile. [ -f /proc/self/ns/cgroup ] && exit 0 # cgmanager doesn't do the same cgroup filesystem mounting cgm ping && exit 0 set -ex cleanup() { set +e rmdir /sys/fs/cgroup/freezer/xx lxc-destroy -n lxc-test-automount -f if [ $PHASE != "done" ]; then echo "automount test failed at $PHASE" exit 1 fi echo "automount test passed" exit 0 } PHASE=setup trap cleanup EXIT rmdir /sys/fs/cgroup/freezer/xx || true lxc-destroy -n lxc-test-automount -f || true lxc-create -t busybox -n lxc-test-automount PHASE=no-cgroup echo "Starting phase $PHASE" config=/var/lib/lxc/lxc-test-automount/config sed -i '/lxc.mount.auto/d' $config echo "lxc.mount.auto = proc:mixed sys:mixed" >> $config lxc-start -n lxc-test-automount pid=`lxc-info -n lxc-test-automount -p -H` cg=`awk -F: '/freezer/ { print $3 }' /proc/$pid/cgroup` notfound=0 stat /proc/$pid/root/sys/fs/cgroup/freezer || notfound=1 [ $notfound -ne 0 ] # Tests are as follows: # 1. check that freezer controller is mounted # 2. check that it is cgroupfs for cgroup-full (/cgroup.procs exists) or # tmpfs for cgroup # 3. check that root cgroup dir is readonly or not (try mkdir) # 4. check that the container's cgroup dir is readonly or not # 5. check that the container's cgroup dir is cgroupfs (/cgroup.procs exists) lxc-stop -n lxc-test-automount -k PHASE=cgroup:mixed echo "Starting phase $PHASE" sed -i '/lxc.mount.auto/d' $config echo "lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed" >> $config lxc-start -n lxc-test-automount pid=`lxc-info -n lxc-test-automount -p -H` notfound=0 stat /proc/$pid/root/sys/fs/cgroup/freezer || notfound=1 [ $notfound -ne 1 ] notfound=0 stat /proc/$pid/root/sys/fs/cgroup/freezer/cgroup.procs || notfound=1 [ $notfound -ne 0 ] ro=0 mkdir /proc/$pid/root/sys/fs/cgroup/freezer/xx || ro=1 [ $ro -ne 0 ] ro=0 mkdir /proc/$pid/root/sys/fs/cgroup/freezer/$cg/xx || ro=1 [ $ro -ne 1 ] notfound=0 stat /proc/$pid/root/sys/fs/cgroup/freezer/$cg/cgroup.procs || notfound=1 [ $notfound -ne 1 ] lxc-stop -n lxc-test-automount -k PHASE=cgroup:ro echo "Starting phase $PHASE" sed -i '/lxc.mount.auto/d' $config echo "lxc.mount.auto = cgroup:ro proc:mixed sys:mixed" >> $config lxc-start -n lxc-test-automount pid=`lxc-info -n lxc-test-automount -p -H` cg=`awk -F: '/freezer/ { print $3 }' /proc/$pid/cgroup` notfound=0 stat /proc/$pid/root/sys/fs/cgroup/freezer || notfound=1 [ $notfound -ne 1 ] notfound=0 stat /proc/$pid/root/sys/fs/cgroup/freezer/cgroup.procs || notfound=1 [ $notfound -ne 0 ] ro=0 mkdir /proc/$pid/root/sys/fs/cgroup/freezer/xx || ro=1 [ $ro -ne 0 ] ro=0 mkdir /proc/$pid/root/sys/fs/cgroup/freezer/$cg/xx || ro=1 [ $ro -ne 1 ] notfound=0 stat /proc/$pid/root/sys/fs/cgroup/freezer/$cg/cgroup.procs || notfound=1 [ $notfound -ne 1 ] lxc-stop -n lxc-test-automount -k PHASE=cgroup:rw echo "Starting phase $PHASE" sed -i '/lxc.mount.auto/d' $config echo "lxc.mount.auto = cgroup:rw proc:mixed sys:mixed" >> $config lxc-start -n lxc-test-automount pid=`lxc-info -n lxc-test-automount -p -H` cg=`awk -F: '/freezer/ { print $3 }' /proc/$pid/cgroup` notfound=0 stat /proc/$pid/root/sys/fs/cgroup/freezer || notfound=1 [ $notfound -ne 1 ] notfound=0 stat /proc/$pid/root/sys/fs/cgroup/freezer/cgroup.procs || notfound=1 [ $notfound -ne 0 ] ro=0 mkdir /proc/$pid/root/sys/fs/cgroup/freezer/xx || ro=1 [ $ro -ne 1 ] rmdir /proc/$pid/root/sys/fs/cgroup/freezer/xx ro=0 mkdir /proc/$pid/root/sys/fs/cgroup/freezer/$cg/xx || ro=1 [ $ro -ne 1 ] notfound=0 stat /proc/$pid/root/sys/fs/cgroup/freezer/$cg/cgroup.procs || notfound=1 [ $notfound -ne 1 ] # cgroup-full lxc-stop -n lxc-test-automount -k PHASE=cgroup-full:mixed echo "Starting phase $PHASE" sed -i '/lxc.mount.auto/d' $config echo "lxc.mount.auto = cgroup-full:mixed proc:mixed sys:mixed" >> $config lxc-start -n lxc-test-automount pid=`lxc-info -n lxc-test-automount -p -H` cg=`awk -F: '/freezer/ { print $3 }' /proc/$pid/cgroup` notfound=0 stat /proc/$pid/root/sys/fs/cgroup/freezer || notfound=1 [ $notfound -ne 1 ] notfound=0 stat /proc/$pid/root/sys/fs/cgroup/freezer/cgroup.procs || notfound=1 [ $notfound -ne 1 ] ro=0 mkdir /proc/$pid/root/sys/fs/cgroup/freezer/xx || ro=1 [ $ro -ne 0 ] ro=0 mkdir /proc/$pid/root/sys/fs/cgroup/freezer/$cg/xx || ro=1 [ $ro -ne 1 ] rmdir /proc/$pid/root/sys/fs/cgroup/freezer/$cg/xx notfound=0 stat /proc/$pid/root/sys/fs/cgroup/freezer/$cg/cgroup.procs || notfound=1 [ $notfound -ne 1 ] lxc-stop -n lxc-test-automount -k PHASE=cgroup-full:ro echo "Starting phase $PHASE" sed -i '/lxc.mount.auto/d' $config echo "lxc.mount.auto = cgroup-full:ro proc:mixed sys:mixed" >> $config lxc-start -n lxc-test-automount pid=`lxc-info -n lxc-test-automount -p -H` cg=`awk -F: '/freezer/ { print $3 }' /proc/$pid/cgroup` notfound=0 stat /proc/$pid/root/sys/fs/cgroup/freezer || notfound=1 [ $notfound -ne 1 ] notfound=0 stat /proc/$pid/root/sys/fs/cgroup/freezer/cgroup.procs || notfound=1 [ $notfound -ne 1 ] ro=0 mkdir /proc/$pid/root/sys/fs/cgroup/freezer/xx || ro=1 [ $ro -ne 0 ] ro=0 mkdir /proc/$pid/root/sys/fs/cgroup/freezer/$cg/xy || ro=1 [ $ro -ne 0 ] notfound=0 stat /proc/$pid/root/sys/fs/cgroup/freezer/$cg/cgroup.procs || notfound=1 [ $notfound -ne 1 ] lxc-stop -n lxc-test-automount -k PHASE=cgroup-full:rw echo "Starting phase $PHASE" sed -i '/lxc.mount.auto/d' $config echo "lxc.mount.auto = cgroup-full:rw proc:mixed sys:mixed" >> $config lxc-start -n lxc-test-automount pid=`lxc-info -n lxc-test-automount -p -H` cg=`awk -F: '/freezer/ { print $3 }' /proc/$pid/cgroup` notfound=0 stat /proc/$pid/root/sys/fs/cgroup/freezer || notfound=1 [ $notfound -ne 1 ] notfound=0 stat /proc/$pid/root/sys/fs/cgroup/freezer/cgroup.procs || notfound=1 [ $notfound -ne 1 ] ro=0 mkdir /proc/$pid/root/sys/fs/cgroup/freezer/xx || ro=1 [ $ro -ne 1 ] rmdir /proc/$pid/root/sys/fs/cgroup/freezer/xx ro=0 mkdir /proc/$pid/root/sys/fs/cgroup/freezer/$cg/xx || ro=1 [ $ro -ne 1 ] notfound=0 /proc/$pid/root/sys/fs/cgroup/freezer/$cg/cgroup.procs || notfound=1 [ $notfound -eq 1 ] PHASE=done lxc-2.0.8/src/tests/concurrent.c0000644061062106075000000001763613105116772013537 00000000000000/* concurrent.c * * Copyright © 2013 S.Çağlar Onur * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include static int nthreads = 5; static int iterations = 1; static int debug = 0; static int quiet = 0; static int delay = 0; static const char *template = "busybox"; static const struct option options[] = { { "threads", required_argument, NULL, 'j' }, { "iterations", required_argument, NULL, 'i' }, { "template", required_argument, NULL, 't' }, { "delay", required_argument, NULL, 'd' }, { "modes", required_argument, NULL, 'm' }, { "quiet", no_argument, NULL, 'q' }, { "debug", no_argument, NULL, 'D' }, { "help", no_argument, NULL, '?' }, { 0, 0, 0, 0 }, }; static void usage(void) { fprintf(stderr, "Usage: lxc-test-concurrent [OPTION]...\n\n" "Common options :\n" " -j, --threads=N Threads to run concurrently\n" " (default: 5, use 1 for no threading)\n" " -i, --iterations=N Number times to run the test (default: 1)\n" " -t, --template=t Template to use (default: busybox)\n" " -d, --delay=N Delay in seconds between start and stop\n" " -m, --modes= Modes to run (create, start, stop, destroy)\n" " -q, --quiet Don't produce any output\n" " -D, --debug Create a debug log\n" " -?, --help Give this help list\n" "\n" "Mandatory or optional arguments to long options are also mandatory or optional\n" "for any corresponding short options.\n\n"); } struct thread_args { int thread_id; int return_code; const char *mode; }; static void do_function(void *arguments) { char name[NAME_MAX+1]; struct thread_args *args = arguments; struct lxc_container *c; sprintf(name, "lxc-test-concurrent-%d", args->thread_id); args->return_code = 1; c = lxc_container_new(name, NULL); if (!c) { fprintf(stderr, "Unable to instantiate container (%s)\n", name); return; } if (debug) { c->set_config_item(c, "lxc.loglevel", "DEBUG"); c->set_config_item(c, "lxc.logfile", name); } if (strcmp(args->mode, "create") == 0) { if (!c->is_defined(c)) { if (!c->create(c, template, NULL, NULL, 1, NULL)) { fprintf(stderr, "Creating the container (%s) failed...\n", name); goto out; } } } else if(strcmp(args->mode, "start") == 0) { if (c->is_defined(c) && !c->is_running(c)) { c->want_daemonize(c, true); if (!c->start(c, false, NULL)) { fprintf(stderr, "Starting the container (%s) failed...\n", name); goto out; } if (!c->wait(c, "RUNNING", 15)) { fprintf(stderr, "Waiting the container (%s) to start failed...\n", name); goto out; } sleep(delay); } } else if(strcmp(args->mode, "stop") == 0) { if (c->is_defined(c) && c->is_running(c)) { if (!c->stop(c)) { fprintf(stderr, "Stopping the container (%s) failed...\n", name); goto out; } if (!c->wait(c, "STOPPED", 15)) { fprintf(stderr, "Waiting the container (%s) to stop failed...\n", name); goto out; } } } else if(strcmp(args->mode, "destroy") == 0) { if (c->is_defined(c) && !c->is_running(c)) { if (!c->destroy(c)) { fprintf(stderr, "Destroying the container (%s) failed...\n", name); goto out; } } } args->return_code = 0; out: lxc_container_put(c); if (debug) lxc_log_close(); } static void *concurrent(void *arguments) { do_function(arguments); pthread_exit(NULL); return NULL; } int main(int argc, char *argv[]) { int i, j, iter, opt; pthread_attr_t attr; pthread_t *threads; struct thread_args *args; char *modes_default[] = {"create", "start", "stop", "destroy", NULL}; char **modes = modes_default; pthread_attr_init(&attr); while ((opt = getopt_long(argc, argv, "j:i:t:d:m:qD", options, NULL)) != -1) { switch(opt) { case 'j': nthreads = atoi(optarg); break; case 'i': iterations = atoi(optarg); break; case 't': template = optarg; break; case 'd': delay = atoi(optarg); break; case 'q': quiet = 1; break; case 'D': debug = 1; break; case 'm': { char *mode_tok, *tok, *saveptr = NULL; modes = NULL; for (i = 0, mode_tok = optarg; (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; break; } default: /* '?' */ usage(); exit(EXIT_FAILURE); } } threads = malloc(sizeof(*threads) * nthreads); args = malloc(sizeof(*args) * nthreads); if (threads == NULL || args == NULL) { fprintf(stderr, "Unable malloc enough memory for %d threads\n", nthreads); exit(EXIT_FAILURE); } for (iter = 1; iter <= iterations; iter++) { int fd; fd = open("/", O_RDONLY); if (fd < 0) { fprintf(stderr, "Failed to open /\n"); continue; } if (!quiet) printf("\nIteration %d/%d maxfd:%d\n", iter, iterations, fd); close(fd); for (i = 0; modes[i];i++) { if (!quiet) printf("Executing (%s) for %d containers...\n", modes[i], nthreads); for (j = 0; j < nthreads; j++) { args[j].thread_id = j; args[j].mode = modes[i]; if (nthreads > 1) { if (pthread_create(&threads[j], &attr, concurrent, (void *) &args[j]) != 0) { perror("pthread_create() error"); exit(EXIT_FAILURE); } } else { do_function(&args[j]); } } for (j = 0; j < nthreads; j++) { if (nthreads > 1) { if (pthread_join(threads[j], NULL) != 0) { perror("pthread_join() error"); exit(EXIT_FAILURE); } } if (args[j].return_code) { fprintf(stderr, "thread returned error %d\n", args[j].return_code); exit(EXIT_FAILURE); } } } } free(args); free(threads); pthread_attr_destroy(&attr); exit(EXIT_SUCCESS); } lxc-2.0.8/src/tests/lxc-test-usernic.in0000755061062106075000000001421113105116772014737 00000000000000#!/bin/bash # lxc: linux Container library # Authors: # Serge Hallyn # # This is a test script for the lxc-user-nic program # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # This test assumes an Ubuntu host DONE=0 KNOWN_RELEASES="precise trusty xenial yakkety zesty" LXC_USER_NIC="@LIBEXECDIR@/lxc/lxc-user-nic" cleanup() { set +e ( lxc-stop -n usernic-c1 -k lxc-destroy -n usernic-c1 sed -i '/usernic-user/d' /run/lxc/nics /etc/lxc/lxc-usernet ifconfig usernic-br0 down ifconfig usernic-br1 down brctl delbr usernic-br0 brctl delbr usernic-br1 run_cmd "lxc-stop -n b1 -k" pkill -u $(id -u usernic-user) -9 rm -rf /tmp/usernic-test /home/usernic-user /run/user/$(id -u usernic-user) deluser usernic-user ) >/dev/null 2>&1 if [ "$DONE" = "1" ]; then echo "PASS" exit 0 fi echo "FAIL" exit 1 } run_cmd() { sudo -i -u usernic-user \ env http_proxy=${http_proxy:-} https_proxy=${https_proxy:-} \ XDG_RUNTIME_DIR=/run/user/$(id -u usernic-user) $* } ARCH=i386 if type dpkg >/dev/null 2>&1; then ARCH=$(dpkg --print-architecture) fi set -eu trap cleanup EXIT SIGHUP SIGINT SIGTERM # create a test user deluser usernic-user || true useradd usernic-user sudo mkdir -p /home/usernic-user sudo chown usernic-user: /home/usernic-user usermod -v 910000-919999 -w 910000-919999 usernic-user mkdir -p /home/usernic-user/.config/lxc/ cat > /home/usernic-user/.config/lxc/default.conf << EOF lxc.network.type = empty lxc.id_map = u 0 910000 10000 lxc.id_map = g 0 910000 10000 EOF if which cgm >/dev/null 2>&1; then cgm create all usernic-user cgm chown all usernic-user $(id -u usernic-user) $(id -g usernic-user) cgm movepid all usernic-user $$ elif [ -e /sys/fs/cgroup/cgmanager/sock ]; then for d in $(cut -d : -f 2 /proc/self/cgroup); do dbus-send --print-reply --address=unix:path=/sys/fs/cgroup/cgmanager/sock \ --type=method_call /org/linuxcontainers/cgmanager org.linuxcontainers.cgmanager0_0.Create \ string:$d string:usernic-user >/dev/null dbus-send --print-reply --address=unix:path=/sys/fs/cgroup/cgmanager/sock \ --type=method_call /org/linuxcontainers/cgmanager org.linuxcontainers.cgmanager0_0.Chown \ string:$d string:usernic-user int32:$(id -u usernic-user) int32:$(id -g usernic-user) >/dev/null dbus-send --print-reply --address=unix:path=/sys/fs/cgroup/cgmanager/sock \ --type=method_call /org/linuxcontainers/cgmanager org.linuxcontainers.cgmanager0_0.MovePid \ string:$d string:usernic-user int32:$$ >/dev/null done else for d in /sys/fs/cgroup/*; do [ -f $d/cgroup.clone_children ] && echo 1 > $d/cgroup.clone_children [ ! -d $d/lxctest ] && mkdir $d/lxctest chown -R usernic-user: $d/lxctest echo $$ > $d/lxctest/tasks done fi mkdir -p /run/user/$(id -u usernic-user) chown -R usernic-user: /run/user/$(id -u usernic-user) /home/usernic-user # Copy the download template cache if available run_cmd "mkdir -p /home/usernic-user/.cache/lxc" [ -d /var/cache/lxc/download ] && \ cp -R /var/cache/lxc/download /home/usernic-user/.cache/lxc && \ chown -R usernic-user: /home/usernic-user/.cache/lxc # Create two test bridges brctl addbr usernic-br0 brctl addbr usernic-br1 ifconfig usernic-br0 0.0.0.0 up ifconfig usernic-br1 0.0.0.0 up ARCH=i386 if type dpkg >/dev/null 2>&1; then ARCH=$(dpkg --print-architecture) fi # default release is trusty, or the systems release if recognized release=trusty if [ -f /etc/lsb-release ]; then . /etc/lsb-release rels=$(ubuntu-distro-info --supported 2>/dev/null) || rels="$KNOWN_RELEASES" for r in $rels; do [ "$DISTRIB_CODENAME" = "$r" ] && release="$r" done fi # Create three containers run_cmd "lxc-create -t download -n b1 -- -d ubuntu -r $release -a $ARCH" run_cmd "lxc-start -n b1 -d" p1=$(run_cmd "lxc-info -n b1 -p -H") lxcpath=/home/usernic-user/.local/share/lxc lxcname=b1 # Assign one veth, should fail as no allowed entries yet if run_cmd "$LXC_USER_NIC $lxcpath $lxcname $p1 veth usernic-br0 xx1"; then echo "FAIL: able to create nic with no entries" exit 1 fi # Give him a quota of two touch /etc/lxc/lxc-usernet sed -i '/^usernic-user/d' /etc/lxc/lxc-usernet echo "usernic-user veth usernic-br0 2" >> /etc/lxc/lxc-usernet # Assign one veth to second bridge, should fail if run_cmd "$LXC_USER_NIC $lxcpath $lxcname $p1 veth usernic-br1 xx1"; then echo "FAIL: able to create nic with no entries" exit 1 fi # Assign two veths, should succeed if ! run_cmd "$LXC_USER_NIC $lxcpath $lxcname $p1 veth usernic-br0 xx2"; then echo "FAIL: unable to create first nic" exit 1 fi if ! run_cmd "$LXC_USER_NIC $lxcpath $lxcname $p1 veth usernic-br0 xx3"; then echo "FAIL: unable to create second nic" exit 1 fi # Assign one more veth, should fail. if run_cmd "$LXC_USER_NIC $lxcpath $lxcname $p1 veth usernic-br0 xx4"; then echo "FAIL: able to create third nic" exit 1 fi # Shut down and restart the container, should be able to assign more nics run_cmd "lxc-stop -n b1 -k" run_cmd "lxc-start -n b1 -d" p1=$(run_cmd "lxc-info -n b1 -p -H") if ! run_cmd "$LXC_USER_NIC $lxcpath $lxcname $p1 veth usernic-br0 xx5"; then echo "FAIL: unable to create nic after destroying the old" cleanup 1 fi run_cmd "lxc-stop -n b1 -k" # Create a root-owned ns lxc-create -t busybox -n usernic-c1 lxc-start -n usernic-c1 -d p2=$(lxc-info -n usernic-c1 -p -H) # assign veth to it - should fail if run_cmd "$LXC_USER_NIC $lxcpath $lxcname $p2 veth usernic-br0 xx6"; then echo "FAIL: able to attach nic to root-owned container" cleanup 1 fi echo "All tests passed" DONE=1 lxc-2.0.8/src/tests/saveconfig.c0000644061062106075000000000547413105116772013476 00000000000000/* liblxcapi * * Copyright © 2012 Serge Hallyn . * Copyright © 2012 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include #include #define MYNAME "lxctest1" static int create_container(void) { int status, ret; pid_t pid = fork(); if (pid < 0) { perror("fork"); return -1; } if (pid == 0) { ret = execlp("lxc-create", "lxc-create", "-t", "busybox", "-n", MYNAME, NULL); // Should not return perror("execl"); exit(1); } again: ret = waitpid(pid, &status, 0); if (ret == -1) { if (errno == EINTR) goto again; perror("waitpid"); return -1; } if (ret != pid) goto again; if (!WIFEXITED(status)) { // did not exit normally fprintf(stderr, "%d: lxc-create exited abnormally\n", __LINE__); return -1; } return WEXITSTATUS(status); } int main(int argc, char *argv[]) { struct lxc_container *c; int ret = 1; if ((c = lxc_container_new(MYNAME, NULL)) == NULL) { fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME); ret = 1; goto out; } if (c->is_defined(c)) { fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME); goto out; } if (create_container()) { fprintf(stderr, "%d: failed to create a container\n", __LINE__); goto out; } if (!c->is_defined(c)) { fprintf(stderr, "%d: %s thought it was not defined\n", __LINE__, MYNAME); goto out; } c->load_config(c, NULL); unlink("/tmp/lxctest1"); if (!c->save_config(c, "/tmp/lxctest1")) { fprintf(stderr, "%d: failed writing config file /tmp/lxctest1\n", __LINE__); goto out; } rename(LXCPATH "/" MYNAME "/config", LXCPATH "/" MYNAME "/config.bak"); if (!c->save_config(c, NULL)) { fprintf(stderr, "%d: failed writing config file\n", __LINE__); goto out; } if (!c->destroy(c)) { fprintf(stderr, "%d: error deleting %s\n", __LINE__, MYNAME); goto out; } if (c->is_defined(c)) { fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME); goto out; } fprintf(stderr, "all lxc_container tests passed for %s\n", c->name); ret = 0; out: lxc_container_put(c); exit(ret); } lxc-2.0.8/src/tests/Makefile.in0000644061062106075000000012710113105116776013247 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @ENABLE_APPARMOR_TRUE@@ENABLE_TESTS_TRUE@am__append_1 = -DHAVE_APPARMOR @ENABLE_SELINUX_TRUE@@ENABLE_TESTS_TRUE@am__append_2 = -DHAVE_SELINUX @ENABLE_TESTS_TRUE@bin_PROGRAMS = lxc-test-containertests$(EXEEXT) \ @ENABLE_TESTS_TRUE@ lxc-test-locktests$(EXEEXT) \ @ENABLE_TESTS_TRUE@ lxc-test-startone$(EXEEXT) \ @ENABLE_TESTS_TRUE@ lxc-test-destroytest$(EXEEXT) \ @ENABLE_TESTS_TRUE@ lxc-test-saveconfig$(EXEEXT) \ @ENABLE_TESTS_TRUE@ lxc-test-createtest$(EXEEXT) \ @ENABLE_TESTS_TRUE@ lxc-test-shutdowntest$(EXEEXT) \ @ENABLE_TESTS_TRUE@ lxc-test-get_item$(EXEEXT) \ @ENABLE_TESTS_TRUE@ lxc-test-getkeys$(EXEEXT) \ @ENABLE_TESTS_TRUE@ lxc-test-lxcpath$(EXEEXT) \ @ENABLE_TESTS_TRUE@ lxc-test-cgpath$(EXEEXT) \ @ENABLE_TESTS_TRUE@ lxc-test-clonetest$(EXEEXT) \ @ENABLE_TESTS_TRUE@ lxc-test-console$(EXEEXT) \ @ENABLE_TESTS_TRUE@ lxc-test-snapshot$(EXEEXT) \ @ENABLE_TESTS_TRUE@ lxc-test-concurrent$(EXEEXT) \ @ENABLE_TESTS_TRUE@ lxc-test-may-control$(EXEEXT) \ @ENABLE_TESTS_TRUE@ lxc-test-reboot$(EXEEXT) \ @ENABLE_TESTS_TRUE@ lxc-test-list$(EXEEXT) \ @ENABLE_TESTS_TRUE@ lxc-test-attach$(EXEEXT) \ @ENABLE_TESTS_TRUE@ lxc-test-device-add-remove$(EXEEXT) \ @ENABLE_TESTS_TRUE@ lxc-test-apparmor$(EXEEXT) \ @ENABLE_TESTS_TRUE@ lxc-test-utils$(EXEEXT) @DISTRO_UBUNTU_TRUE@@ENABLE_TESTS_TRUE@am__append_3 = \ @DISTRO_UBUNTU_TRUE@@ENABLE_TESTS_TRUE@ lxc-test-lxc-attach \ @DISTRO_UBUNTU_TRUE@@ENABLE_TESTS_TRUE@ lxc-test-apparmor-mount \ @DISTRO_UBUNTU_TRUE@@ENABLE_TESTS_TRUE@ lxc-test-checkpoint-restore \ @DISTRO_UBUNTU_TRUE@@ENABLE_TESTS_TRUE@ lxc-test-snapdeps \ @DISTRO_UBUNTU_TRUE@@ENABLE_TESTS_TRUE@ lxc-test-symlink \ @DISTRO_UBUNTU_TRUE@@ENABLE_TESTS_TRUE@ lxc-test-ubuntu \ @DISTRO_UBUNTU_TRUE@@ENABLE_TESTS_TRUE@ lxc-test-unpriv \ @DISTRO_UBUNTU_TRUE@@ENABLE_TESTS_TRUE@ lxc-test-usernic subdir = src/tests ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/acinclude.m4 \ $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/tls.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h CONFIG_CLEAN_FILES = lxc-test-usernic CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am__lxc_test_apparmor_SOURCES_DIST = aa.c @ENABLE_TESTS_TRUE@am_lxc_test_apparmor_OBJECTS = aa.$(OBJEXT) lxc_test_apparmor_OBJECTS = $(am_lxc_test_apparmor_OBJECTS) lxc_test_apparmor_LDADD = $(LDADD) @ENABLE_TESTS_TRUE@lxc_test_apparmor_DEPENDENCIES = ../lxc/liblxc.la AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am__lxc_test_attach_SOURCES_DIST = attach.c @ENABLE_TESTS_TRUE@am_lxc_test_attach_OBJECTS = attach.$(OBJEXT) lxc_test_attach_OBJECTS = $(am_lxc_test_attach_OBJECTS) lxc_test_attach_LDADD = $(LDADD) @ENABLE_TESTS_TRUE@lxc_test_attach_DEPENDENCIES = ../lxc/liblxc.la am__lxc_test_cgpath_SOURCES_DIST = cgpath.c @ENABLE_TESTS_TRUE@am_lxc_test_cgpath_OBJECTS = cgpath.$(OBJEXT) lxc_test_cgpath_OBJECTS = $(am_lxc_test_cgpath_OBJECTS) lxc_test_cgpath_LDADD = $(LDADD) @ENABLE_TESTS_TRUE@lxc_test_cgpath_DEPENDENCIES = ../lxc/liblxc.la am__lxc_test_clonetest_SOURCES_DIST = clonetest.c @ENABLE_TESTS_TRUE@am_lxc_test_clonetest_OBJECTS = \ @ENABLE_TESTS_TRUE@ clonetest.$(OBJEXT) lxc_test_clonetest_OBJECTS = $(am_lxc_test_clonetest_OBJECTS) lxc_test_clonetest_LDADD = $(LDADD) @ENABLE_TESTS_TRUE@lxc_test_clonetest_DEPENDENCIES = ../lxc/liblxc.la am__lxc_test_concurrent_SOURCES_DIST = concurrent.c @ENABLE_TESTS_TRUE@am_lxc_test_concurrent_OBJECTS = \ @ENABLE_TESTS_TRUE@ concurrent.$(OBJEXT) lxc_test_concurrent_OBJECTS = $(am_lxc_test_concurrent_OBJECTS) lxc_test_concurrent_LDADD = $(LDADD) @ENABLE_TESTS_TRUE@lxc_test_concurrent_DEPENDENCIES = \ @ENABLE_TESTS_TRUE@ ../lxc/liblxc.la am__lxc_test_console_SOURCES_DIST = console.c @ENABLE_TESTS_TRUE@am_lxc_test_console_OBJECTS = console.$(OBJEXT) lxc_test_console_OBJECTS = $(am_lxc_test_console_OBJECTS) lxc_test_console_LDADD = $(LDADD) @ENABLE_TESTS_TRUE@lxc_test_console_DEPENDENCIES = ../lxc/liblxc.la am__lxc_test_containertests_SOURCES_DIST = containertests.c @ENABLE_TESTS_TRUE@am_lxc_test_containertests_OBJECTS = \ @ENABLE_TESTS_TRUE@ containertests.$(OBJEXT) lxc_test_containertests_OBJECTS = \ $(am_lxc_test_containertests_OBJECTS) lxc_test_containertests_LDADD = $(LDADD) @ENABLE_TESTS_TRUE@lxc_test_containertests_DEPENDENCIES = \ @ENABLE_TESTS_TRUE@ ../lxc/liblxc.la am__lxc_test_createtest_SOURCES_DIST = createtest.c @ENABLE_TESTS_TRUE@am_lxc_test_createtest_OBJECTS = \ @ENABLE_TESTS_TRUE@ createtest.$(OBJEXT) lxc_test_createtest_OBJECTS = $(am_lxc_test_createtest_OBJECTS) lxc_test_createtest_LDADD = $(LDADD) @ENABLE_TESTS_TRUE@lxc_test_createtest_DEPENDENCIES = \ @ENABLE_TESTS_TRUE@ ../lxc/liblxc.la am__lxc_test_destroytest_SOURCES_DIST = destroytest.c @ENABLE_TESTS_TRUE@am_lxc_test_destroytest_OBJECTS = \ @ENABLE_TESTS_TRUE@ destroytest.$(OBJEXT) lxc_test_destroytest_OBJECTS = $(am_lxc_test_destroytest_OBJECTS) lxc_test_destroytest_LDADD = $(LDADD) @ENABLE_TESTS_TRUE@lxc_test_destroytest_DEPENDENCIES = \ @ENABLE_TESTS_TRUE@ ../lxc/liblxc.la am__lxc_test_device_add_remove_SOURCES_DIST = device_add_remove.c @ENABLE_TESTS_TRUE@am_lxc_test_device_add_remove_OBJECTS = \ @ENABLE_TESTS_TRUE@ device_add_remove.$(OBJEXT) lxc_test_device_add_remove_OBJECTS = \ $(am_lxc_test_device_add_remove_OBJECTS) lxc_test_device_add_remove_LDADD = $(LDADD) @ENABLE_TESTS_TRUE@lxc_test_device_add_remove_DEPENDENCIES = \ @ENABLE_TESTS_TRUE@ ../lxc/liblxc.la am__lxc_test_get_item_SOURCES_DIST = get_item.c @ENABLE_TESTS_TRUE@am_lxc_test_get_item_OBJECTS = get_item.$(OBJEXT) lxc_test_get_item_OBJECTS = $(am_lxc_test_get_item_OBJECTS) lxc_test_get_item_LDADD = $(LDADD) @ENABLE_TESTS_TRUE@lxc_test_get_item_DEPENDENCIES = ../lxc/liblxc.la am__lxc_test_getkeys_SOURCES_DIST = getkeys.c @ENABLE_TESTS_TRUE@am_lxc_test_getkeys_OBJECTS = getkeys.$(OBJEXT) lxc_test_getkeys_OBJECTS = $(am_lxc_test_getkeys_OBJECTS) lxc_test_getkeys_LDADD = $(LDADD) @ENABLE_TESTS_TRUE@lxc_test_getkeys_DEPENDENCIES = ../lxc/liblxc.la am__lxc_test_list_SOURCES_DIST = list.c @ENABLE_TESTS_TRUE@am_lxc_test_list_OBJECTS = list.$(OBJEXT) lxc_test_list_OBJECTS = $(am_lxc_test_list_OBJECTS) lxc_test_list_LDADD = $(LDADD) @ENABLE_TESTS_TRUE@lxc_test_list_DEPENDENCIES = ../lxc/liblxc.la am__lxc_test_locktests_SOURCES_DIST = locktests.c @ENABLE_TESTS_TRUE@am_lxc_test_locktests_OBJECTS = \ @ENABLE_TESTS_TRUE@ locktests.$(OBJEXT) lxc_test_locktests_OBJECTS = $(am_lxc_test_locktests_OBJECTS) lxc_test_locktests_LDADD = $(LDADD) @ENABLE_TESTS_TRUE@lxc_test_locktests_DEPENDENCIES = ../lxc/liblxc.la am__lxc_test_lxcpath_SOURCES_DIST = lxcpath.c @ENABLE_TESTS_TRUE@am_lxc_test_lxcpath_OBJECTS = lxcpath.$(OBJEXT) lxc_test_lxcpath_OBJECTS = $(am_lxc_test_lxcpath_OBJECTS) lxc_test_lxcpath_LDADD = $(LDADD) @ENABLE_TESTS_TRUE@lxc_test_lxcpath_DEPENDENCIES = ../lxc/liblxc.la am__lxc_test_may_control_SOURCES_DIST = may_control.c @ENABLE_TESTS_TRUE@am_lxc_test_may_control_OBJECTS = \ @ENABLE_TESTS_TRUE@ may_control.$(OBJEXT) lxc_test_may_control_OBJECTS = $(am_lxc_test_may_control_OBJECTS) lxc_test_may_control_LDADD = $(LDADD) @ENABLE_TESTS_TRUE@lxc_test_may_control_DEPENDENCIES = \ @ENABLE_TESTS_TRUE@ ../lxc/liblxc.la am__lxc_test_reboot_SOURCES_DIST = reboot.c @ENABLE_TESTS_TRUE@am_lxc_test_reboot_OBJECTS = reboot.$(OBJEXT) lxc_test_reboot_OBJECTS = $(am_lxc_test_reboot_OBJECTS) lxc_test_reboot_LDADD = $(LDADD) @ENABLE_TESTS_TRUE@lxc_test_reboot_DEPENDENCIES = ../lxc/liblxc.la am__lxc_test_saveconfig_SOURCES_DIST = saveconfig.c @ENABLE_TESTS_TRUE@am_lxc_test_saveconfig_OBJECTS = \ @ENABLE_TESTS_TRUE@ saveconfig.$(OBJEXT) lxc_test_saveconfig_OBJECTS = $(am_lxc_test_saveconfig_OBJECTS) lxc_test_saveconfig_LDADD = $(LDADD) @ENABLE_TESTS_TRUE@lxc_test_saveconfig_DEPENDENCIES = \ @ENABLE_TESTS_TRUE@ ../lxc/liblxc.la am__lxc_test_shutdowntest_SOURCES_DIST = shutdowntest.c @ENABLE_TESTS_TRUE@am_lxc_test_shutdowntest_OBJECTS = \ @ENABLE_TESTS_TRUE@ shutdowntest.$(OBJEXT) lxc_test_shutdowntest_OBJECTS = $(am_lxc_test_shutdowntest_OBJECTS) lxc_test_shutdowntest_LDADD = $(LDADD) @ENABLE_TESTS_TRUE@lxc_test_shutdowntest_DEPENDENCIES = \ @ENABLE_TESTS_TRUE@ ../lxc/liblxc.la am__lxc_test_snapshot_SOURCES_DIST = snapshot.c @ENABLE_TESTS_TRUE@am_lxc_test_snapshot_OBJECTS = snapshot.$(OBJEXT) lxc_test_snapshot_OBJECTS = $(am_lxc_test_snapshot_OBJECTS) lxc_test_snapshot_LDADD = $(LDADD) @ENABLE_TESTS_TRUE@lxc_test_snapshot_DEPENDENCIES = ../lxc/liblxc.la am__lxc_test_startone_SOURCES_DIST = startone.c @ENABLE_TESTS_TRUE@am_lxc_test_startone_OBJECTS = startone.$(OBJEXT) lxc_test_startone_OBJECTS = $(am_lxc_test_startone_OBJECTS) lxc_test_startone_LDADD = $(LDADD) @ENABLE_TESTS_TRUE@lxc_test_startone_DEPENDENCIES = ../lxc/liblxc.la am__lxc_test_utils_SOURCES_DIST = lxc-test-utils.c lxctest.h @ENABLE_TESTS_TRUE@am_lxc_test_utils_OBJECTS = \ @ENABLE_TESTS_TRUE@ lxc-test-utils.$(OBJEXT) lxc_test_utils_OBJECTS = $(am_lxc_test_utils_OBJECTS) lxc_test_utils_LDADD = $(LDADD) @ENABLE_TESTS_TRUE@lxc_test_utils_DEPENDENCIES = ../lxc/liblxc.la am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } SCRIPTS = $(bin_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src depcomp = $(SHELL) $(top_srcdir)/config/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(lxc_test_apparmor_SOURCES) $(lxc_test_attach_SOURCES) \ $(lxc_test_cgpath_SOURCES) $(lxc_test_clonetest_SOURCES) \ $(lxc_test_concurrent_SOURCES) $(lxc_test_console_SOURCES) \ $(lxc_test_containertests_SOURCES) \ $(lxc_test_createtest_SOURCES) $(lxc_test_destroytest_SOURCES) \ $(lxc_test_device_add_remove_SOURCES) \ $(lxc_test_get_item_SOURCES) $(lxc_test_getkeys_SOURCES) \ $(lxc_test_list_SOURCES) $(lxc_test_locktests_SOURCES) \ $(lxc_test_lxcpath_SOURCES) $(lxc_test_may_control_SOURCES) \ $(lxc_test_reboot_SOURCES) $(lxc_test_saveconfig_SOURCES) \ $(lxc_test_shutdowntest_SOURCES) $(lxc_test_snapshot_SOURCES) \ $(lxc_test_startone_SOURCES) $(lxc_test_utils_SOURCES) DIST_SOURCES = $(am__lxc_test_apparmor_SOURCES_DIST) \ $(am__lxc_test_attach_SOURCES_DIST) \ $(am__lxc_test_cgpath_SOURCES_DIST) \ $(am__lxc_test_clonetest_SOURCES_DIST) \ $(am__lxc_test_concurrent_SOURCES_DIST) \ $(am__lxc_test_console_SOURCES_DIST) \ $(am__lxc_test_containertests_SOURCES_DIST) \ $(am__lxc_test_createtest_SOURCES_DIST) \ $(am__lxc_test_destroytest_SOURCES_DIST) \ $(am__lxc_test_device_add_remove_SOURCES_DIST) \ $(am__lxc_test_get_item_SOURCES_DIST) \ $(am__lxc_test_getkeys_SOURCES_DIST) \ $(am__lxc_test_list_SOURCES_DIST) \ $(am__lxc_test_locktests_SOURCES_DIST) \ $(am__lxc_test_lxcpath_SOURCES_DIST) \ $(am__lxc_test_may_control_SOURCES_DIST) \ $(am__lxc_test_reboot_SOURCES_DIST) \ $(am__lxc_test_saveconfig_SOURCES_DIST) \ $(am__lxc_test_shutdowntest_SOURCES_DIST) \ $(am__lxc_test_snapshot_SOURCES_DIST) \ $(am__lxc_test_startone_SOURCES_DIST) \ $(am__lxc_test_utils_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/lxc-test-usernic.in \ $(top_srcdir)/config/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APPARMOR_LIBS = @APPARMOR_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BINDIR = @BINDIR@ CAP_LIBS = @CAP_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CGMANAGER_CFLAGS = @CGMANAGER_CFLAGS@ CGMANAGER_LIBS = @CGMANAGER_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIR = @DATADIR@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFAULT_CGROUP_PATTERN = @DEFAULT_CGROUP_PATTERN@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOCDIR = @DOCDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ HAVE_DOXYGEN = @HAVE_DOXYGEN@ INCLUDEDIR = @INCLUDEDIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDIR = @LIBDIR@ LIBEXECDIR = @LIBEXECDIR@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCALSTATEDIR = @LOCALSTATEDIR@ LOGPATH = @LOGPATH@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBDIR = @LUA_LIBDIR@ LUA_LIBS = @LUA_LIBS@ LUA_SHAREDIR = @LUA_SHAREDIR@ LUA_VERSION = @LUA_VERSION@ LXCBINHOOKDIR = @LXCBINHOOKDIR@ LXCHOOKDIR = @LXCHOOKDIR@ LXCINITDIR = @LXCINITDIR@ LXCPATH = @LXCPATH@ LXCROOTFSMOUNT = @LXCROOTFSMOUNT@ LXCTEMPLATECONFIG = @LXCTEMPLATECONFIG@ LXCTEMPLATEDIR = @LXCTEMPLATEDIR@ LXC_ABI = @LXC_ABI@ LXC_ABI_MAJOR = @LXC_ABI_MAJOR@ LXC_ABI_MICRO = @LXC_ABI_MICRO@ LXC_ABI_MINOR = @LXC_ABI_MINOR@ LXC_DEFAULT_CONFIG = @LXC_DEFAULT_CONFIG@ LXC_DEVEL = @LXC_DEVEL@ LXC_DISTRO_SYSCONF = @LXC_DISTRO_SYSCONF@ LXC_GENERATE_DATE = @LXC_GENERATE_DATE@ LXC_GLOBAL_CONF = @LXC_GLOBAL_CONF@ LXC_USERNIC_CONF = @LXC_USERNIC_CONF@ LXC_USERNIC_DB = @LXC_USERNIC_DB@ LXC_VERSION = @LXC_VERSION@ LXC_VERSION_BASE = @LXC_VERSION_BASE@ LXC_VERSION_BETA = @LXC_VERSION_BETA@ LXC_VERSION_MAJOR = @LXC_VERSION_MAJOR@ LXC_VERSION_MICRO = @LXC_VERSION_MICRO@ LXC_VERSION_MINOR = @LXC_VERSION_MINOR@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NIH_CFLAGS = @NIH_CFLAGS@ NIH_DBUS_CFLAGS = @NIH_DBUS_CFLAGS@ NIH_DBUS_LIBS = @NIH_DBUS_LIBS@ NIH_LIBS = @NIH_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PREFIX = @PREFIX@ PYTHON = @PYTHON@ PYTHONDEV_CFLAGS = @PYTHONDEV_CFLAGS@ PYTHONDEV_LIBS = @PYTHONDEV_LIBS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RUNTIME_PATH = @RUNTIME_PATH@ SBINDIR = @SBINDIR@ SECCOMP_CFLAGS = @SECCOMP_CFLAGS@ SECCOMP_LIBS = @SECCOMP_LIBS@ SED = @SED@ SELINUX_LIBS = @SELINUX_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SYSCONFDIR = @SYSCONFDIR@ SYSTEMD_UNIT_DIR = @SYSTEMD_UNIT_DIR@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bashcompdir = @bashcompdir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ db2xman = @db2xman@ docdir = @docdir@ docdtd = @docdtd@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ @ENABLE_TESTS_TRUE@LDADD = ../lxc/liblxc.la @ENABLE_TESTS_TRUE@lxc_test_containertests_SOURCES = containertests.c @ENABLE_TESTS_TRUE@lxc_test_locktests_SOURCES = locktests.c @ENABLE_TESTS_TRUE@lxc_test_startone_SOURCES = startone.c @ENABLE_TESTS_TRUE@lxc_test_destroytest_SOURCES = destroytest.c @ENABLE_TESTS_TRUE@lxc_test_saveconfig_SOURCES = saveconfig.c @ENABLE_TESTS_TRUE@lxc_test_createtest_SOURCES = createtest.c @ENABLE_TESTS_TRUE@lxc_test_shutdowntest_SOURCES = shutdowntest.c @ENABLE_TESTS_TRUE@lxc_test_get_item_SOURCES = get_item.c @ENABLE_TESTS_TRUE@lxc_test_getkeys_SOURCES = getkeys.c @ENABLE_TESTS_TRUE@lxc_test_lxcpath_SOURCES = lxcpath.c @ENABLE_TESTS_TRUE@lxc_test_cgpath_SOURCES = cgpath.c @ENABLE_TESTS_TRUE@lxc_test_clonetest_SOURCES = clonetest.c @ENABLE_TESTS_TRUE@lxc_test_console_SOURCES = console.c @ENABLE_TESTS_TRUE@lxc_test_snapshot_SOURCES = snapshot.c @ENABLE_TESTS_TRUE@lxc_test_concurrent_SOURCES = concurrent.c @ENABLE_TESTS_TRUE@lxc_test_may_control_SOURCES = may_control.c @ENABLE_TESTS_TRUE@lxc_test_reboot_SOURCES = reboot.c @ENABLE_TESTS_TRUE@lxc_test_list_SOURCES = list.c @ENABLE_TESTS_TRUE@lxc_test_attach_SOURCES = attach.c @ENABLE_TESTS_TRUE@lxc_test_device_add_remove_SOURCES = device_add_remove.c @ENABLE_TESTS_TRUE@lxc_test_apparmor_SOURCES = aa.c @ENABLE_TESTS_TRUE@lxc_test_utils_SOURCES = lxc-test-utils.c lxctest.h @ENABLE_TESTS_TRUE@AM_CFLAGS = -DLXCROOTFSMOUNT=\"$(LXCROOTFSMOUNT)\" \ @ENABLE_TESTS_TRUE@ -DLXCPATH=\"$(LXCPATH)\" \ @ENABLE_TESTS_TRUE@ -DLXC_GLOBAL_CONF=\"$(LXC_GLOBAL_CONF)\" \ @ENABLE_TESTS_TRUE@ -DLXCINITDIR=\"$(LXCINITDIR)\" \ @ENABLE_TESTS_TRUE@ -DLXC_DEFAULT_CONFIG=\"$(LXC_DEFAULT_CONFIG)\" \ @ENABLE_TESTS_TRUE@ -DRUNTIME_PATH=\"$(RUNTIME_PATH)\" -I \ @ENABLE_TESTS_TRUE@ $(top_srcdir)/src -I $(top_srcdir)/src/lxc \ @ENABLE_TESTS_TRUE@ -I $(top_srcdir)/src/lxc/bdev -I \ @ENABLE_TESTS_TRUE@ $(top_srcdir)/src/lxc/cgroups -I \ @ENABLE_TESTS_TRUE@ $(top_srcdir)/src/lxc/tools $(am__append_1) \ @ENABLE_TESTS_TRUE@ $(am__append_2) @ENABLE_TESTS_TRUE@bin_SCRIPTS = lxc-test-automount lxc-test-autostart \ @ENABLE_TESTS_TRUE@ lxc-test-cloneconfig lxc-test-createconfig \ @ENABLE_TESTS_TRUE@ $(am__append_3) EXTRA_DIST = \ cgpath.c \ clonetest.c \ concurrent.c \ console.c \ containertests.c \ createtest.c \ destroytest.c \ device_add_remove.c \ get_item.c \ getkeys.c \ list.c \ locktests.c \ lxcpath.c \ lxc-test-lxc-attach \ lxc-test-automount \ lxc-test-autostart \ lxc-test-apparmor-mount \ lxc-test-checkpoint-restore \ lxc-test-cloneconfig \ lxc-test-createconfig \ lxc-test-snapdeps \ lxc-test-symlink \ lxc-test-ubuntu \ lxc-test-unpriv \ lxc-test-utils.c \ may_control.c \ saveconfig.c \ shutdowntest.c \ snapshot.c \ startone.c all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/tests/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/tests/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): lxc-test-usernic: $(top_builddir)/config.status $(srcdir)/lxc-test-usernic.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list lxc-test-apparmor$(EXEEXT): $(lxc_test_apparmor_OBJECTS) $(lxc_test_apparmor_DEPENDENCIES) $(EXTRA_lxc_test_apparmor_DEPENDENCIES) @rm -f lxc-test-apparmor$(EXEEXT) $(AM_V_CCLD)$(LINK) $(lxc_test_apparmor_OBJECTS) $(lxc_test_apparmor_LDADD) $(LIBS) lxc-test-attach$(EXEEXT): $(lxc_test_attach_OBJECTS) $(lxc_test_attach_DEPENDENCIES) $(EXTRA_lxc_test_attach_DEPENDENCIES) @rm -f lxc-test-attach$(EXEEXT) $(AM_V_CCLD)$(LINK) $(lxc_test_attach_OBJECTS) $(lxc_test_attach_LDADD) $(LIBS) lxc-test-cgpath$(EXEEXT): $(lxc_test_cgpath_OBJECTS) $(lxc_test_cgpath_DEPENDENCIES) $(EXTRA_lxc_test_cgpath_DEPENDENCIES) @rm -f lxc-test-cgpath$(EXEEXT) $(AM_V_CCLD)$(LINK) $(lxc_test_cgpath_OBJECTS) $(lxc_test_cgpath_LDADD) $(LIBS) lxc-test-clonetest$(EXEEXT): $(lxc_test_clonetest_OBJECTS) $(lxc_test_clonetest_DEPENDENCIES) $(EXTRA_lxc_test_clonetest_DEPENDENCIES) @rm -f lxc-test-clonetest$(EXEEXT) $(AM_V_CCLD)$(LINK) $(lxc_test_clonetest_OBJECTS) $(lxc_test_clonetest_LDADD) $(LIBS) lxc-test-concurrent$(EXEEXT): $(lxc_test_concurrent_OBJECTS) $(lxc_test_concurrent_DEPENDENCIES) $(EXTRA_lxc_test_concurrent_DEPENDENCIES) @rm -f lxc-test-concurrent$(EXEEXT) $(AM_V_CCLD)$(LINK) $(lxc_test_concurrent_OBJECTS) $(lxc_test_concurrent_LDADD) $(LIBS) lxc-test-console$(EXEEXT): $(lxc_test_console_OBJECTS) $(lxc_test_console_DEPENDENCIES) $(EXTRA_lxc_test_console_DEPENDENCIES) @rm -f lxc-test-console$(EXEEXT) $(AM_V_CCLD)$(LINK) $(lxc_test_console_OBJECTS) $(lxc_test_console_LDADD) $(LIBS) lxc-test-containertests$(EXEEXT): $(lxc_test_containertests_OBJECTS) $(lxc_test_containertests_DEPENDENCIES) $(EXTRA_lxc_test_containertests_DEPENDENCIES) @rm -f lxc-test-containertests$(EXEEXT) $(AM_V_CCLD)$(LINK) $(lxc_test_containertests_OBJECTS) $(lxc_test_containertests_LDADD) $(LIBS) lxc-test-createtest$(EXEEXT): $(lxc_test_createtest_OBJECTS) $(lxc_test_createtest_DEPENDENCIES) $(EXTRA_lxc_test_createtest_DEPENDENCIES) @rm -f lxc-test-createtest$(EXEEXT) $(AM_V_CCLD)$(LINK) $(lxc_test_createtest_OBJECTS) $(lxc_test_createtest_LDADD) $(LIBS) lxc-test-destroytest$(EXEEXT): $(lxc_test_destroytest_OBJECTS) $(lxc_test_destroytest_DEPENDENCIES) $(EXTRA_lxc_test_destroytest_DEPENDENCIES) @rm -f lxc-test-destroytest$(EXEEXT) $(AM_V_CCLD)$(LINK) $(lxc_test_destroytest_OBJECTS) $(lxc_test_destroytest_LDADD) $(LIBS) lxc-test-device-add-remove$(EXEEXT): $(lxc_test_device_add_remove_OBJECTS) $(lxc_test_device_add_remove_DEPENDENCIES) $(EXTRA_lxc_test_device_add_remove_DEPENDENCIES) @rm -f lxc-test-device-add-remove$(EXEEXT) $(AM_V_CCLD)$(LINK) $(lxc_test_device_add_remove_OBJECTS) $(lxc_test_device_add_remove_LDADD) $(LIBS) lxc-test-get_item$(EXEEXT): $(lxc_test_get_item_OBJECTS) $(lxc_test_get_item_DEPENDENCIES) $(EXTRA_lxc_test_get_item_DEPENDENCIES) @rm -f lxc-test-get_item$(EXEEXT) $(AM_V_CCLD)$(LINK) $(lxc_test_get_item_OBJECTS) $(lxc_test_get_item_LDADD) $(LIBS) lxc-test-getkeys$(EXEEXT): $(lxc_test_getkeys_OBJECTS) $(lxc_test_getkeys_DEPENDENCIES) $(EXTRA_lxc_test_getkeys_DEPENDENCIES) @rm -f lxc-test-getkeys$(EXEEXT) $(AM_V_CCLD)$(LINK) $(lxc_test_getkeys_OBJECTS) $(lxc_test_getkeys_LDADD) $(LIBS) lxc-test-list$(EXEEXT): $(lxc_test_list_OBJECTS) $(lxc_test_list_DEPENDENCIES) $(EXTRA_lxc_test_list_DEPENDENCIES) @rm -f lxc-test-list$(EXEEXT) $(AM_V_CCLD)$(LINK) $(lxc_test_list_OBJECTS) $(lxc_test_list_LDADD) $(LIBS) lxc-test-locktests$(EXEEXT): $(lxc_test_locktests_OBJECTS) $(lxc_test_locktests_DEPENDENCIES) $(EXTRA_lxc_test_locktests_DEPENDENCIES) @rm -f lxc-test-locktests$(EXEEXT) $(AM_V_CCLD)$(LINK) $(lxc_test_locktests_OBJECTS) $(lxc_test_locktests_LDADD) $(LIBS) lxc-test-lxcpath$(EXEEXT): $(lxc_test_lxcpath_OBJECTS) $(lxc_test_lxcpath_DEPENDENCIES) $(EXTRA_lxc_test_lxcpath_DEPENDENCIES) @rm -f lxc-test-lxcpath$(EXEEXT) $(AM_V_CCLD)$(LINK) $(lxc_test_lxcpath_OBJECTS) $(lxc_test_lxcpath_LDADD) $(LIBS) lxc-test-may-control$(EXEEXT): $(lxc_test_may_control_OBJECTS) $(lxc_test_may_control_DEPENDENCIES) $(EXTRA_lxc_test_may_control_DEPENDENCIES) @rm -f lxc-test-may-control$(EXEEXT) $(AM_V_CCLD)$(LINK) $(lxc_test_may_control_OBJECTS) $(lxc_test_may_control_LDADD) $(LIBS) lxc-test-reboot$(EXEEXT): $(lxc_test_reboot_OBJECTS) $(lxc_test_reboot_DEPENDENCIES) $(EXTRA_lxc_test_reboot_DEPENDENCIES) @rm -f lxc-test-reboot$(EXEEXT) $(AM_V_CCLD)$(LINK) $(lxc_test_reboot_OBJECTS) $(lxc_test_reboot_LDADD) $(LIBS) lxc-test-saveconfig$(EXEEXT): $(lxc_test_saveconfig_OBJECTS) $(lxc_test_saveconfig_DEPENDENCIES) $(EXTRA_lxc_test_saveconfig_DEPENDENCIES) @rm -f lxc-test-saveconfig$(EXEEXT) $(AM_V_CCLD)$(LINK) $(lxc_test_saveconfig_OBJECTS) $(lxc_test_saveconfig_LDADD) $(LIBS) lxc-test-shutdowntest$(EXEEXT): $(lxc_test_shutdowntest_OBJECTS) $(lxc_test_shutdowntest_DEPENDENCIES) $(EXTRA_lxc_test_shutdowntest_DEPENDENCIES) @rm -f lxc-test-shutdowntest$(EXEEXT) $(AM_V_CCLD)$(LINK) $(lxc_test_shutdowntest_OBJECTS) $(lxc_test_shutdowntest_LDADD) $(LIBS) lxc-test-snapshot$(EXEEXT): $(lxc_test_snapshot_OBJECTS) $(lxc_test_snapshot_DEPENDENCIES) $(EXTRA_lxc_test_snapshot_DEPENDENCIES) @rm -f lxc-test-snapshot$(EXEEXT) $(AM_V_CCLD)$(LINK) $(lxc_test_snapshot_OBJECTS) $(lxc_test_snapshot_LDADD) $(LIBS) lxc-test-startone$(EXEEXT): $(lxc_test_startone_OBJECTS) $(lxc_test_startone_DEPENDENCIES) $(EXTRA_lxc_test_startone_DEPENDENCIES) @rm -f lxc-test-startone$(EXEEXT) $(AM_V_CCLD)$(LINK) $(lxc_test_startone_OBJECTS) $(lxc_test_startone_LDADD) $(LIBS) lxc-test-utils$(EXEEXT): $(lxc_test_utils_OBJECTS) $(lxc_test_utils_DEPENDENCIES) $(EXTRA_lxc_test_utils_DEPENDENCIES) @rm -f lxc-test-utils$(EXEEXT) $(AM_V_CCLD)$(LINK) $(lxc_test_utils_OBJECTS) $(lxc_test_utils_LDADD) $(LIBS) install-binSCRIPTS: $(bin_SCRIPTS) @$(NORMAL_INSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aa.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/attach.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cgpath.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clonetest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/concurrent.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/console.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/containertests.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/createtest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/destroytest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/device_add_remove.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/get_item.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getkeys.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/locktests.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxc-test-utils.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxcpath.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/may_control.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reboot.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/saveconfig.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shutdowntest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snapshot.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/startone.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(SCRIPTS) installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool clean-local \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-binSCRIPTS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ clean-binPROGRAMS clean-generic clean-libtool clean-local \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-binPROGRAMS install-binSCRIPTS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-binSCRIPTS .PRECIOUS: Makefile clean-local: rm -f lxc-test-utils-* # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lxc-2.0.8/src/tests/reboot.c0000644061062106075000000000637413105116772012644 00000000000000/* * Copyright © 2012 Serge Hallyn . * Copyright © 2012 Canonical Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include "lxc/namespace.h" #include #include #include int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...); static int do_reboot(void *arg) { int *cmd = arg; if (reboot(*cmd)) printf("failed to reboot(%d): %m\n", *cmd); return 0; } static int test_reboot(int cmd, int sig) { long stack_size = 4096; void *stack = alloca(stack_size) + stack_size; int status; pid_t ret; ret = clone(do_reboot, stack, CLONE_NEWPID | SIGCHLD, &cmd); if (ret < 0) { printf("failed to clone: %m\n"); return -1; } if (wait(&status) < 0) { printf("unexpected wait error: %m\n"); return -1; } if (!WIFSIGNALED(status)) { if (sig != -1) printf("child process exited but was not signaled\n"); return -1; } if (WTERMSIG(status) != sig) { printf("signal termination is not the one expected\n"); return -1; } return 0; } static int have_reboot_patch(void) { FILE *f = fopen("/proc/sys/kernel/ctrl-alt-del", "r"); int ret; int v; if (!f) return 0; ret = fscanf(f, "%d", &v); fclose(f); if (ret != 1) return 0; ret = reboot(v ? LINUX_REBOOT_CMD_CAD_ON : LINUX_REBOOT_CMD_CAD_OFF); if (ret != -1) return 0; return 1; } int main(int argc, char *argv[]) { int status; if (getuid() != 0) { printf("Must run as root.\n"); return 1; } status = have_reboot_patch(); if (status != 0) { printf("Your kernel does not have the container reboot patch\n"); return 1; } status = test_reboot(LINUX_REBOOT_CMD_CAD_ON, -1); if (status >= 0) { printf("reboot(LINUX_REBOOT_CMD_CAD_ON) should have failed\n"); return 1; } printf("reboot(LINUX_REBOOT_CMD_CAD_ON) has failed as expected\n"); status = test_reboot(LINUX_REBOOT_CMD_RESTART, SIGHUP); if (status < 0) return 1; printf("reboot(LINUX_REBOOT_CMD_RESTART) succeed\n"); status = test_reboot(LINUX_REBOOT_CMD_RESTART2, SIGHUP); if (status < 0) return 1; printf("reboot(LINUX_REBOOT_CMD_RESTART2) succeed\n"); status = test_reboot(LINUX_REBOOT_CMD_HALT, SIGINT); if (status < 0) return 1; printf("reboot(LINUX_REBOOT_CMD_HALT) succeed\n"); status = test_reboot(LINUX_REBOOT_CMD_POWER_OFF, SIGINT); if (status < 0) return 1; printf("reboot(LINUX_REBOOT_CMD_POWERR_OFF) succeed\n"); printf("All tests passed\n"); return 0; } lxc-2.0.8/src/tests/cgpath.c0000644061062106075000000001200213105116772012601 00000000000000/* liblxcapi * * Copyright © 2012 Serge Hallyn . * Copyright © 2012 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include #include #include #include #include #include "cgroup.h" #include "lxc.h" #include "commands.h" #define MYNAME "lxctest1" #define TSTERR(fmt, ...) do { \ fprintf(stderr, "%s:%d " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \ } while (0) /* * test_running_container: test cgroup functions against a running container * * @group : name of the container group or NULL for default "lxc" * @name : name of the container */ static int test_running_container(const char *lxcpath, const char *group, const char *name) { int ret = -1; struct lxc_container *c = NULL; char *cgrelpath; char relpath[PATH_MAX+1]; char value[NAME_MAX], value_save[NAME_MAX]; sprintf(relpath, "%s/%s", group ? group : "lxc", name); if ((c = lxc_container_new(name, lxcpath)) == NULL) { TSTERR("container %s couldn't instantiate", name); goto err1; } if (!c->is_defined(c)) { TSTERR("container %s does not exist", name); goto err2; } cgrelpath = lxc_cmd_get_cgroup_path(c->name, c->config_path, "freezer"); if (!cgrelpath) { TSTERR("lxc_cmd_get_cgroup_path returned NULL"); goto err2; } if (!strstr(cgrelpath, relpath)) { TSTERR("lxc_cmd_get_cgroup_path %s not in %s", relpath, cgrelpath); goto err3; } /* test get/set value using memory.soft_limit_in_bytes file */ ret = lxc_cgroup_get("memory.soft_limit_in_bytes", value, sizeof(value), c->name, c->config_path); if (ret < 0) { TSTERR("lxc_cgroup_get failed"); goto err3; } strcpy(value_save, value); ret = lxc_cgroup_set("memory.soft_limit_in_bytes", "512M", c->name, c->config_path); if (ret < 0) { TSTERR("lxc_cgroup_set failed %d %d", ret, errno); goto err3; } ret = lxc_cgroup_get("memory.soft_limit_in_bytes", value, sizeof(value), c->name, c->config_path); if (ret < 0) { TSTERR("lxc_cgroup_get failed"); goto err3; } if (strcmp(value, "536870912\n")) { TSTERR("lxc_cgroup_set_bypath failed to set value >%s<", value); goto err3; } /* restore original value */ ret = lxc_cgroup_set("memory.soft_limit_in_bytes", value_save, c->name, c->config_path); if (ret < 0) { TSTERR("lxc_cgroup_set failed"); goto err3; } ret = 0; err3: free(cgrelpath); err2: lxc_container_put(c); err1: return ret; } static int test_container(const char *lxcpath, const char *group, const char *name, const char *template) { int ret; struct lxc_container *c = NULL; if (lxcpath) { ret = mkdir(lxcpath, 0755); if (ret < 0 && errno != EEXIST) { TSTERR("failed to mkdir %s %s", lxcpath, strerror(errno)); goto out1; } } ret = -1; if ((c = lxc_container_new(name, lxcpath)) == NULL) { TSTERR("instantiating container %s", name); goto out1; } if (c->is_defined(c)) { c->stop(c); c->destroy(c); c = lxc_container_new(name, lxcpath); } c->set_config_item(c, "lxc.network.type", "empty"); if (!c->createl(c, template, NULL, NULL, 0, NULL)) { TSTERR("creating container %s", name); goto out2; } c->load_config(c, NULL); c->want_daemonize(c, true); if (!c->startl(c, 0, NULL)) { TSTERR("starting container %s", name); goto out3; } ret = test_running_container(lxcpath, group, name); c->stop(c); out3: c->destroy(c); out2: lxc_container_put(c); out1: return ret; } int main() { int ret = EXIT_FAILURE; /* won't require privilege necessarily once users are classified by * pam_cgroup */ if (geteuid() != 0) { TSTERR("requires privilege"); exit(0); } #if TEST_ALREADY_RUNNING_CT /* * This is useful for running with valgrind to test for memory * leaks. The container should already be running, we can't start * the container ourselves because valgrind gets confused by lxc's * internal calls to clone. */ if (test_running_container(NULL, NULL, "bb01") < 0) goto out; printf("Running container cgroup tests...Passed\n"); #else if (test_container(NULL, NULL, MYNAME, "busybox") < 0) goto out; printf("Container creation tests...Passed\n"); if (test_container("/var/lib/lxctest2", NULL, MYNAME, "busybox") < 0) goto out; printf("Container creation with LXCPATH tests...Passed\n"); #endif ret = EXIT_SUCCESS; out: return ret; } lxc-2.0.8/src/tests/lxcpath.c0000644061062106075000000000413313105116772013004 00000000000000/* liblxcapi * * Copyright © 2012 Serge Hallyn . * Copyright © 2012 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include #include #include #define MYNAME "lxctest1" #define TSTERR(x) do { \ fprintf(stderr, "%d: %s\n", __LINE__, x); \ } while (0) int main() { struct lxc_container *c; const char *p1, *p2; int retval = -1; c = lxc_container_new(MYNAME, NULL); if (!c) { TSTERR("create using default path"); goto err; } p1 = c->get_config_path(c); p2 = c->config_file_name(c); if (!p1 || !p2 || strncmp(p1, p2, strlen(p1))) { TSTERR("Bad result for path names"); goto err; } #define CPATH "/boo" #define FPATH "/boo/lxctest1/config" if (!c->set_config_path(c, "/boo")) { TSTERR("Error setting custom path"); goto err; } p1 = c->get_config_path(c); p2 = c->config_file_name(c); if (strcmp(p1, CPATH) || strcmp(p2, FPATH)) { TSTERR("Bad result for path names after set_config_path()"); goto err; } lxc_container_put(c); c = lxc_container_new(MYNAME, CPATH); if (!c) { TSTERR("create using custom path"); goto err; } p1 = c->get_config_path(c); p2 = c->config_file_name(c); if (strcmp(p1, CPATH) || strcmp(p2, FPATH)) { TSTERR("Bad result for path names after create with custom path"); goto err; } retval = 0; err: lxc_container_put(c); return retval; } lxc-2.0.8/src/tests/console.c0000644061062106075000000001040513105116772013002 00000000000000/* liblxcapi * * Copyright © 2013 Oracle. * * Authors: * Dwight Engen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #define TTYCNT 4 #define TTYCNT_STR "4" #define TSTNAME "lxcconsoletest" #define MAXCONSOLES 512 #define TSTERR(fmt, ...) do { \ fprintf(stderr, "%s:%d " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \ } while (0) static void test_console_close_all(int ttyfd[MAXCONSOLES], int masterfd[MAXCONSOLES]) { int i; for (i = 0; i < MAXCONSOLES; i++) { if (masterfd[i] != -1) { close(masterfd[i]); masterfd[i] = -1; } if (ttyfd[i] != -1) { close(ttyfd[i]); ttyfd[i] = -1; } } } static int test_console_running_container(struct lxc_container *c) { int nrconsoles, i, ret = -1; int ttynum [MAXCONSOLES]; int ttyfd [MAXCONSOLES]; int masterfd[MAXCONSOLES]; for (i = 0; i < MAXCONSOLES; i++) ttynum[i] = ttyfd[i] = masterfd[i] = -1; ttynum[0] = 1; ret = c->console_getfd(c, &ttynum[0], &masterfd[0]); if (ret < 0) { TSTERR("console allocate failed"); goto err1; } ttyfd[0] = ret; if (ttynum[0] != 1) { TSTERR("console allocate got bad ttynum %d", ttynum[0]); goto err2; } /* attempt to alloc same ttynum */ ret = c->console_getfd(c, &ttynum[0], &masterfd[1]); if (ret != -1) { TSTERR("console allocate should fail for allocated ttynum %d", ttynum[0]); goto err2; } close(masterfd[0]); masterfd[0] = -1; close(ttyfd[0]); ttyfd[0] = -1; /* ensure we can allocate all consoles, we do this a few times to * show that the closes are freeing up the allocated slots */ for (i = 0; i < 10; i++) { for (nrconsoles = 0; nrconsoles < MAXCONSOLES; nrconsoles++) { ret = c->console_getfd(c, &ttynum[nrconsoles], &masterfd[nrconsoles]); if (ret < 0) break; ttyfd[nrconsoles] = ret; } if (nrconsoles != TTYCNT) { TSTERR("didn't allocate all consoles %d != %d", nrconsoles, TTYCNT); goto err2; } test_console_close_all(ttyfd, masterfd); } ret = 0; err2: test_console_close_all(ttyfd, masterfd); err1: return ret; } /* test_container: test console function * * @lxcpath : the lxcpath in which to create the container * @group : name of the container group or NULL for default "lxc" * @name : name of the container * @template : template to use when creating the container */ static int test_console(const char *lxcpath, const char *group, const char *name, const char *template) { int ret; struct lxc_container *c = NULL; if (lxcpath) { ret = mkdir(lxcpath, 0755); if (ret < 0 && errno != EEXIST) { TSTERR("failed to mkdir %s %s", lxcpath, strerror(errno)); goto out1; } } ret = -1; if ((c = lxc_container_new(name, lxcpath)) == NULL) { TSTERR("instantiating container %s", name); goto out1; } if (c->is_defined(c)) { c->stop(c); c->destroy(c); c = lxc_container_new(name, lxcpath); } if (!c->createl(c, template, NULL, NULL, 0, NULL)) { TSTERR("creating container %s", name); goto out2; } c->load_config(c, NULL); c->set_config_item(c, "lxc.tty", TTYCNT_STR); c->save_config(c, NULL); c->want_daemonize(c, true); if (!c->startl(c, 0, NULL)) { TSTERR("starting container %s", name); goto out3; } ret = test_console_running_container(c); c->stop(c); out3: c->destroy(c); out2: lxc_container_put(c); out1: return ret; } int main(int argc, char *argv[]) { int ret; ret = test_console(NULL, NULL, TSTNAME, "busybox"); if (ret < 0) goto err1; ret = test_console("/var/lib/lxctest2", NULL, TSTNAME, "busybox"); if (ret < 0) goto err1; printf("All tests passed\n"); err1: return ret; } lxc-2.0.8/src/tests/lxc-test-createconfig0000644061062106075000000000233013105116772015307 00000000000000#!/bin/bash # lxc: linux Container library # Authors: # Serge Hallyn # # This is a test script for the lxc-user-nic program # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA set -e s=`mktemp -d /tmp/lxctest-XXXXXX` f="$s/in.conf" cleanup() { lxc-destroy -n lxctestc || true rm -rf $s } trap cleanup EXIT cat > $f << EOF lxc.network.type = veth lxc.network.hwaddr = 00:16:3e:xx:xx:xx EOF lxc-create -t busybox -f $f -n lxctestc grep -q "xx:xx" /var/lib/lxc/lxctestc/config && { echo "hwaddr not expanded"; exit 1; } echo "Success" lxc-2.0.8/src/tests/getkeys.c0000644061062106075000000000361713105116772013022 00000000000000/* liblxcapi * * Copyright © 2012 Serge Hallyn . * Copyright © 2012 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include #include #include "lxc/state.h" #define MYNAME "lxctest1" int main(int argc, char *argv[]) { struct lxc_container *c; int len, ret; char v3[2048]; if ((c = lxc_container_new(MYNAME, NULL)) == NULL) { fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME); ret = 1; goto out; } c->set_config_item(c, "lxc.network.type", "veth"); len = c->get_keys(c, NULL, NULL, 0); if (len < 0) { fprintf(stderr, "%d: failed to get length of all keys (%d)\n", __LINE__, len); ret = 1; goto out; } ret = c->get_keys(c, NULL, v3, len+1); if (ret != len) { fprintf(stderr, "%d: failed to get keys (%d)\n", __LINE__, ret); ret = 1; goto out; } printf("get_keys returned %d\n%s", ret, v3); ret = c->get_keys(c, "lxc.network.0", v3, 2000); if (ret < 0) { fprintf(stderr, "%d: failed to get nic 0 keys(%d)\n", __LINE__, ret); ret = 1; goto out; } printf("get_keys for nic 1 returned %d\n%s", ret, v3); ret = 0; out: lxc_container_put(c); exit(ret); } lxc-2.0.8/src/tests/lxc-test-utils.c0000644061062106075000000003161313105116772014245 00000000000000/* * lxc: linux Container library * * Copyright © 2016 Canonical Ltd. * * Authors: * Christian Brauner * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #define __STDC_FORMAT_MACROS #include #include #include #include #include #include #include #include #include #include #include #include #include "lxctest.h" #include "utils.h" void test_lxc_deslashify(void) { char *s = strdup("/A///B//C/D/E/"); if (!s) exit(EXIT_FAILURE); lxc_test_assert_abort(lxc_deslashify(&s)); lxc_test_assert_abort(strcmp(s, "/A/B/C/D/E") == 0); free(s); s = strdup("/A"); if (!s) exit(EXIT_FAILURE); lxc_test_assert_abort(lxc_deslashify(&s)); lxc_test_assert_abort(strcmp(s, "/A") == 0); free(s); s = strdup(""); if (!s) exit(EXIT_FAILURE); lxc_test_assert_abort(lxc_deslashify(&s)); lxc_test_assert_abort(strcmp(s, "") == 0); free(s); s = strdup("//"); if (!s) exit(EXIT_FAILURE); lxc_test_assert_abort(lxc_deslashify(&s)); lxc_test_assert_abort(strcmp(s, "/") == 0); free(s); } /* /proc/int_as_str/ns/mnt\0 = (5 + 21 + 7 + 1) */ #define __MNTNS_LEN (5 + (LXC_NUMSTRLEN64) + 7 + 1) void test_detect_ramfs_rootfs(void) { size_t i; int ret; int fret = EXIT_FAILURE; char path[__MNTNS_LEN]; int init_ns = -1; char tmpf1[] = "lxc-test-utils-XXXXXX"; char tmpf2[] = "lxc-test-utils-XXXXXX"; int fd1 = -1, fd2 = -1; FILE *fp1 = NULL, *fp2 = NULL; char *mountinfo[] = { "18 24 0:17 / /sys rw,nosuid,nodev,noexec,relatime shared:7 - sysfs sysfs rw", "19 24 0:4 / /proc rw,nosuid,nodev,noexec,relatime shared:13 - proc proc rw", "20 24 0:6 / /dev rw,nosuid,relatime shared:2 - devtmpfs udev rw,size=4019884k,nr_inodes=1004971,mode=755", "21 20 0:14 / /dev/pts rw,nosuid,noexec,relatime shared:3 - devpts devpts rw,gid=5,mode=620,ptmxmode=000", "22 24 0:18 / /run rw,nosuid,noexec,relatime shared:5 - tmpfs tmpfs rw,size=807912k,mode=755", /* This is what we care about. */ "24 0 8:2 / / rw - rootfs rootfs rw,size=1004396k,nr_inodes=251099", "25 18 0:12 / /sys/kernel/security rw,nosuid,nodev,noexec,relatime shared:8 - securityfs securityfs rw", "26 20 0:20 / /dev/shm rw,nosuid,nodev shared:4 - tmpfs tmpfs rw", "27 22 0:21 / /run/lock rw,nosuid,nodev,noexec,relatime shared:6 - tmpfs tmpfs rw,size=5120k", "28 18 0:22 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:9 - tmpfs tmpfs ro,mode=755", "29 28 0:23 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:10 - cgroup cgroup rw,xattr,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd", "30 18 0:24 / /sys/fs/pstore rw,nosuid,nodev,noexec,relatime shared:11 - pstore pstore rw", "31 18 0:25 / /sys/firmware/efi/efivars rw,nosuid,nodev,noexec,relatime shared:12 - efivarfs efivarfs rw", "32 28 0:26 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:14 - cgroup cgroup rw,cpu,cpuacct", "33 28 0:27 / /sys/fs/cgroup/net_cls,net_prio rw,nosuid,nodev,noexec,relatime shared:15 - cgroup cgroup rw,net_cls,net_prio", "34 28 0:28 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,blkio", "35 28 0:29 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:17 - cgroup cgroup rw,freezer", "36 28 0:30 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:18 - cgroup cgroup rw,memory", "37 28 0:31 / /sys/fs/cgroup/hugetlb rw,nosuid,nodev,noexec,relatime shared:19 - cgroup cgroup rw,hugetlb", "38 28 0:32 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:20 - cgroup cgroup rw,cpuset", "39 28 0:33 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:21 - cgroup cgroup rw,devices", "40 28 0:34 / /sys/fs/cgroup/pids rw,nosuid,nodev,noexec,relatime shared:22 - cgroup cgroup rw,pids", "41 28 0:35 / /sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:23 - cgroup cgroup rw,perf_event", "42 19 0:36 / /proc/sys/fs/binfmt_misc rw,relatime shared:24 - autofs systemd-1 rw,fd=32,pgrp=1,timeout=0,minproto=5,maxproto=5,direct", "43 18 0:7 / /sys/kernel/debug rw,relatime shared:25 - debugfs debugfs rw", "44 20 0:37 / /dev/hugepages rw,relatime shared:26 - hugetlbfs hugetlbfs rw", "45 20 0:16 / /dev/mqueue rw,relatime shared:27 - mqueue mqueue rw", "46 43 0:9 / /sys/kernel/debug/tracing rw,relatime shared:28 - tracefs tracefs rw", "76 18 0:38 / /sys/fs/fuse/connections rw,relatime shared:29 - fusectl fusectl rw", "78 24 8:1 / /boot/efi rw,relatime shared:30 - vfat /dev/sda1 rw,fmask=0077,dmask=0077,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro", }; ret = snprintf(path, __MNTNS_LEN, "/proc/self/ns/mnt"); if (ret < 0 || (size_t)ret >= __MNTNS_LEN) { lxc_error("%s\n", "Failed to create path with snprintf()."); goto non_test_error; } init_ns = open(path, O_RDONLY | O_CLOEXEC); if (init_ns < 0) { lxc_error("%s\n", "Failed to open initial mount namespace."); goto non_test_error; } if (unshare(CLONE_NEWNS) < 0) { lxc_error("%s\n", "Could not unshare mount namespace."); close(init_ns); init_ns = -1; goto non_test_error; } if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0) < 0) { lxc_error("Failed to remount / private: %s.\n", strerror(errno)); goto non_test_error; } fd1 = mkstemp(tmpf1); if (fd1 < 0) { lxc_error("%s\n", "Could not create temporary file."); goto non_test_error; } fd2 = mkstemp(tmpf2); if (fd2 < 0) { lxc_error("%s\n", "Could not create temporary file."); goto non_test_error; } fp1 = fdopen(fd1, "r+"); if (!fp1) { lxc_error("%s\n", "Could not fdopen() temporary file."); goto non_test_error; } fp2 = fdopen(fd2, "r+"); if (!fp2) { lxc_error("%s\n", "Could not fdopen() temporary file."); goto non_test_error; } /* Test if it correctly detects - rootfs rootfs */ for (i = 0; i < sizeof(mountinfo) / sizeof(mountinfo[0]); i++) { if (fprintf(fp1, "%s\n", mountinfo[i]) < 0) { lxc_error("Could not write \"%s\" to temporary file.", mountinfo[i]); goto non_test_error; } } fclose(fp1); fp1 = NULL; /* Test if it correctly fails to detect when no - rootfs rootfs */ for (i = 0; i < sizeof(mountinfo) / sizeof(mountinfo[0]); i++) { if (strcmp(mountinfo[i], "24 0 8:2 / / rw - rootfs rootfs rw,size=1004396k,nr_inodes=251099") == 0) continue; if (fprintf(fp2, "%s\n", mountinfo[i]) < 0) { lxc_error("Could not write \"%s\" to temporary file.", mountinfo[i]); goto non_test_error; } } fclose(fp2); fp2 = NULL; if (mount(tmpf1, "/proc/self/mountinfo", NULL, MS_BIND, 0) < 0) { lxc_error("%s\n", "Could not overmount \"/proc/self/mountinfo\"."); goto non_test_error; } lxc_test_assert_abort(detect_ramfs_rootfs()); if (mount(tmpf2, "/proc/self/mountinfo", NULL, MS_BIND, 0) < 0) { lxc_error("%s\n", "Could not overmount \"/proc/self/mountinfo\"."); goto non_test_error; } lxc_test_assert_abort(!detect_ramfs_rootfs()); fret = EXIT_SUCCESS; non_test_error: if (fp1) fclose(fp1); else if (fd1 > 0) close(fd1); if (fp2) fclose(fp2); else if (fd2 > 0) close(fd2); if (init_ns > 0) { if (setns(init_ns, 0) < 0) { lxc_error("Failed to switch back to initial mount namespace: %s.\n", strerror(errno)); fret = EXIT_FAILURE; } close(init_ns); } if (fret == EXIT_SUCCESS) return; exit(fret); } void test_lxc_safe_uint(void) { unsigned int n; lxc_test_assert_abort((0 == lxc_safe_uint("1234345", &n)) && n == 1234345); lxc_test_assert_abort((0 == lxc_safe_uint(" 345", &n)) && n == 345); lxc_test_assert_abort((-EINVAL == lxc_safe_uint(" g345", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_uint(" 3g45", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_uint(" 345g", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_uint("g345", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_uint("3g45", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_uint("345g", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_uint("g345 ", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_uint("3g45 ", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_uint("345g ", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_uint("g", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_uint(" g345", &n))); } void test_lxc_safe_int(void) { signed int n; lxc_test_assert_abort((0 == lxc_safe_int("1234345", &n)) && n == 1234345); lxc_test_assert_abort((0 == lxc_safe_int(" 345", &n)) && n == 345); lxc_test_assert_abort((0 == lxc_safe_int("-1234345", &n)) && n == -1234345); lxc_test_assert_abort((0 == lxc_safe_int(" -345", &n)) && n == -345); lxc_test_assert_abort((-EINVAL == lxc_safe_int(" g345", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_int(" 3g45", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_int(" 345g", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_int("g345", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_int("3g45", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_int("345g", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_int("g345 ", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_int("3g45 ", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_int("345g ", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_int("g", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_int(" g345", &n))); } void test_lxc_safe_long(void) { signed long int n; lxc_test_assert_abort((0 == lxc_safe_long("1234345", &n)) && n == 1234345); lxc_test_assert_abort((0 == lxc_safe_long(" 345", &n)) && n == 345); lxc_test_assert_abort((0 == lxc_safe_long("-1234345", &n)) && n == -1234345); lxc_test_assert_abort((0 == lxc_safe_long(" -345", &n)) && n == -345); lxc_test_assert_abort((-EINVAL == lxc_safe_long(" g345", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_long(" 3g45", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_long(" 345g", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_long("g345", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_long("3g45", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_long("345g", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_long("g345 ", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_long("3g45 ", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_long("345g ", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_long("g", &n))); lxc_test_assert_abort((-EINVAL == lxc_safe_long(" g345", &n))); } void test_lxc_string_replace(void) { char *s; s = lxc_string_replace("A", "A", "A"); lxc_test_assert_abort(strcmp(s, "A") == 0); free(s); s = lxc_string_replace("A", "AA", "A"); lxc_test_assert_abort(strcmp(s, "AA") == 0); free(s); s = lxc_string_replace("A", "AA", "BA"); lxc_test_assert_abort(strcmp(s, "BAA") == 0); free(s); s = lxc_string_replace("A", "AA", "BAB"); lxc_test_assert_abort(strcmp(s, "BAAB") == 0); free(s); s = lxc_string_replace("AA", "A", "AA"); lxc_test_assert_abort(strcmp(s, "A") == 0); free(s); s = lxc_string_replace("AA", "A", "BAA"); lxc_test_assert_abort(strcmp(s, "BA") == 0); free(s); s = lxc_string_replace("AA", "A", "BAAB"); lxc_test_assert_abort(strcmp(s, "BAB") == 0); free(s); s = lxc_string_replace("\"A\"A", "\"A\"", "B\"A\"AB"); lxc_test_assert_abort(strcmp(s, "B\"A\"B") == 0); free(s); } void test_lxc_string_in_array(void) { lxc_test_assert_abort(lxc_string_in_array("", (const char *[]){"", NULL})); lxc_test_assert_abort(!lxc_string_in_array("A", (const char *[]){"", NULL})); lxc_test_assert_abort(!lxc_string_in_array("AAA", (const char *[]){"", "3472", "jshH", NULL})); lxc_test_assert_abort(lxc_string_in_array("A", (const char *[]){"A", NULL})); lxc_test_assert_abort(lxc_string_in_array("A", (const char *[]){"A", "B", "C", NULL})); lxc_test_assert_abort(lxc_string_in_array("A", (const char *[]){"B", "A", "C", NULL})); lxc_test_assert_abort(lxc_string_in_array("ABC", (const char *[]){"ASD", "ATR", "ABC", NULL})); lxc_test_assert_abort(lxc_string_in_array("GHJ", (const char *[]){"AZIU", "WRT567B", "879C", "GHJ", "IUZ89", NULL})); lxc_test_assert_abort(lxc_string_in_array("XYZ", (const char *[]){"BERTA", "ARQWE(9", "C8Zhkd", "7U", "XYZ", "UOIZ9", "=)()", NULL})); } int main(int argc, char *argv[]) { test_lxc_string_replace(); test_lxc_string_in_array(); test_lxc_deslashify(); test_detect_ramfs_rootfs(); test_lxc_safe_uint(); test_lxc_safe_int(); test_lxc_safe_long(); exit(EXIT_SUCCESS); } lxc-2.0.8/src/tests/device_add_remove.c0000644061062106075000000000362613105116772014773 00000000000000/* DEVICE_add_remove.c * * Copyright © 2014 S.Çağlar Onur * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #define NAME "device_add_remove_test" #define DEVICE "/dev/network_latency" int main(int argc, char *argv[]) { int ret = 1; struct lxc_container *c; c = lxc_container_new(NAME, NULL); if (!c) { fprintf(stderr, "Unable to instantiate container (%s)...\n", NAME); goto out; } if (!c->create(c, "busybox", NULL, NULL, 1, NULL)) { fprintf(stderr, "Creating the container (%s) failed...\n", NAME); goto out; } c->want_daemonize(c, true); if (!c->start(c, false, NULL)) { fprintf(stderr, "Starting the container (%s) failed...\n", NAME); goto out; } if (!c->add_device_node(c, DEVICE, DEVICE)) { fprintf(stderr, "Adding %s to the container (%s) failed...\n", DEVICE, NAME); goto out; } if (!c->remove_device_node(c, DEVICE, DEVICE)) { fprintf(stderr, "Removing %s from the container (%s) failed...\n", DEVICE, NAME); goto out; } if (!c->stop(c)) { fprintf(stderr, "Stopping the container (%s) failed...\n", NAME); goto out; } if (!c->destroy(c)) { fprintf(stderr, "Destroying the container (%s) failed...\n", NAME); goto out; } ret = 0; out: lxc_container_put(c); return ret; } lxc-2.0.8/src/tests/Makefile.am0000644061062106075000000000541413105116772013234 00000000000000if ENABLE_TESTS LDADD = ../lxc/liblxc.la lxc_test_containertests_SOURCES = containertests.c lxc_test_locktests_SOURCES = locktests.c lxc_test_startone_SOURCES = startone.c lxc_test_destroytest_SOURCES = destroytest.c lxc_test_saveconfig_SOURCES = saveconfig.c lxc_test_createtest_SOURCES = createtest.c lxc_test_shutdowntest_SOURCES = shutdowntest.c lxc_test_get_item_SOURCES = get_item.c lxc_test_getkeys_SOURCES = getkeys.c lxc_test_lxcpath_SOURCES = lxcpath.c lxc_test_cgpath_SOURCES = cgpath.c lxc_test_clonetest_SOURCES = clonetest.c lxc_test_console_SOURCES = console.c lxc_test_snapshot_SOURCES = snapshot.c lxc_test_concurrent_SOURCES = concurrent.c lxc_test_may_control_SOURCES = may_control.c lxc_test_reboot_SOURCES = reboot.c lxc_test_list_SOURCES = list.c lxc_test_attach_SOURCES = attach.c lxc_test_device_add_remove_SOURCES = device_add_remove.c lxc_test_apparmor_SOURCES = aa.c lxc_test_utils_SOURCES = lxc-test-utils.c lxctest.h AM_CFLAGS=-DLXCROOTFSMOUNT=\"$(LXCROOTFSMOUNT)\" \ -DLXCPATH=\"$(LXCPATH)\" \ -DLXC_GLOBAL_CONF=\"$(LXC_GLOBAL_CONF)\" \ -DLXCINITDIR=\"$(LXCINITDIR)\" \ -DLXC_DEFAULT_CONFIG=\"$(LXC_DEFAULT_CONFIG)\" \ -DRUNTIME_PATH=\"$(RUNTIME_PATH)\" \ -I $(top_srcdir)/src \ -I $(top_srcdir)/src/lxc \ -I $(top_srcdir)/src/lxc/bdev \ -I $(top_srcdir)/src/lxc/cgroups \ -I $(top_srcdir)/src/lxc/tools if ENABLE_APPARMOR AM_CFLAGS += -DHAVE_APPARMOR endif if ENABLE_SELINUX AM_CFLAGS += -DHAVE_SELINUX endif bin_PROGRAMS = lxc-test-containertests lxc-test-locktests lxc-test-startone \ lxc-test-destroytest lxc-test-saveconfig lxc-test-createtest \ lxc-test-shutdowntest lxc-test-get_item lxc-test-getkeys lxc-test-lxcpath \ lxc-test-cgpath lxc-test-clonetest lxc-test-console \ lxc-test-snapshot lxc-test-concurrent lxc-test-may-control \ lxc-test-reboot lxc-test-list lxc-test-attach lxc-test-device-add-remove \ lxc-test-apparmor lxc-test-utils bin_SCRIPTS = lxc-test-automount lxc-test-autostart lxc-test-cloneconfig \ lxc-test-createconfig if DISTRO_UBUNTU bin_SCRIPTS += \ lxc-test-lxc-attach \ lxc-test-apparmor-mount \ lxc-test-checkpoint-restore \ lxc-test-snapdeps \ lxc-test-symlink \ lxc-test-ubuntu \ lxc-test-unpriv \ lxc-test-usernic endif endif EXTRA_DIST = \ cgpath.c \ clonetest.c \ concurrent.c \ console.c \ containertests.c \ createtest.c \ destroytest.c \ device_add_remove.c \ get_item.c \ getkeys.c \ list.c \ locktests.c \ lxcpath.c \ lxc-test-lxc-attach \ lxc-test-automount \ lxc-test-autostart \ lxc-test-apparmor-mount \ lxc-test-checkpoint-restore \ lxc-test-cloneconfig \ lxc-test-createconfig \ lxc-test-snapdeps \ lxc-test-symlink \ lxc-test-ubuntu \ lxc-test-unpriv \ lxc-test-utils.c \ may_control.c \ saveconfig.c \ shutdowntest.c \ snapshot.c \ startone.c clean-local: rm -f lxc-test-utils-* lxc-2.0.8/src/tests/clonetest.c0000644061062106075000000001047413105116772013346 00000000000000/* liblxcapi * * Copyright © 2012 Serge Hallyn . * Copyright © 2012 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include #include #define MYNAME "clonetest1" #define MYNAME2 "clonetest2" int main(int argc, char *argv[]) { struct lxc_container *c = NULL, *c2 = NULL, *c3 = NULL; int ret = 1; c = lxc_container_new(MYNAME, NULL); c2 = lxc_container_new(MYNAME2, NULL); if (c) { c->destroy(c); lxc_container_put(c); c = NULL; } if (c2) { c2->destroy(c2); lxc_container_put(c2); c2 = NULL; } if ((c = lxc_container_new(MYNAME, NULL)) == NULL) { fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME); ret = 1; goto out; } c->save_config(c, NULL); if (!c->createl(c, "busybox", NULL, NULL, 0, NULL)) { fprintf(stderr, "%d: failed to create a container\n", __LINE__); goto out; } c->load_config(c, NULL); if (!c->is_defined(c)) { fprintf(stderr, "%d: %s thought it was not defined\n", __LINE__, MYNAME); goto out; } c2 = c->clone(c, MYNAME2, NULL, 0, NULL, NULL, 0, NULL); if (!c2) { fprintf(stderr, "%d: %s clone returned NULL\n", __LINE__, MYNAME2); goto out; } if (!c2->is_defined(c2)) { fprintf(stderr, "%d: %s not defined after clone\n", __LINE__, MYNAME2); goto out; } fprintf(stderr, "directory backing store tests passed\n"); // now test with lvm // Only do this if clonetestlvm1 exists - user has to set this up // in advance c2->destroy(c2); lxc_container_put(c2); c->destroy(c); lxc_container_put(c); c = NULL; c2 = lxc_container_new("clonetestlvm2", NULL); if (c2) { if (c2->is_defined(c2)) c2->destroy(c2); lxc_container_put(c2); } c2 = lxc_container_new("clonetest-o1", NULL); if (c2) { if (c2->is_defined(c2)) c2->destroy(c2); lxc_container_put(c2); } c2 = lxc_container_new("clonetest-o2", NULL); if (c2) { if (c2->is_defined(c2)) c2->destroy(c2); lxc_container_put(c2); } c2 = NULL; // lvm-copied c = lxc_container_new("clonetestlvm1", NULL); if (!c) { fprintf(stderr, "failed loading clonetestlvm1\n"); goto out; } if (!c->is_defined(c)) { fprintf(stderr, "clonetestlvm1 does not exist, skipping lvm tests\n"); ret = 0; goto out; } if ((c2 = c->clone(c, "clonetestlvm2", NULL, 0, NULL, NULL, 0, NULL)) == NULL) { fprintf(stderr, "lvm clone failed\n"); goto out; } lxc_container_put(c2); // lvm-snapshot c2 = lxc_container_new("clonetestlvm3", NULL); if (c2) { if (c2->is_defined(c2)) c2->destroy(c2); lxc_container_put(c2); c2 = NULL; } if ((c2 = c->clone(c, "clonetestlvm3", NULL, LXC_CLONE_SNAPSHOT, NULL, NULL, 0, NULL)) == NULL) { fprintf(stderr, "lvm clone failed\n"); goto out; } lxc_container_put(c2); lxc_container_put(c); c = c2 = NULL; if ((c = lxc_container_new(MYNAME, NULL)) == NULL) { fprintf(stderr, "error opening original container for overlay test\n"); goto out; } // Now create an overlayfs clone of a dir-backed container if ((c2 = c->clone(c, "clonetest-o1", NULL, LXC_CLONE_SNAPSHOT, "overlayfs", NULL, 0, NULL)) == NULL) { fprintf(stderr, "overlayfs clone of dir failed\n"); goto out; } // Now create an overlayfs clone of the overlayfs clone if ((c3 = c2->clone(c2, "clonetest-o2", NULL, LXC_CLONE_SNAPSHOT, "overlayfs", NULL, 0, NULL)) == NULL) { fprintf(stderr, "overlayfs clone of overlayfs failed\n"); goto out; } fprintf(stderr, "all clone tests passed for %s\n", c->name); ret = 0; out: if (c3) { lxc_container_put(c3); } if (c2) { c2->destroy(c2); lxc_container_put(c2); } if (c) { c->destroy(c); lxc_container_put(c); } exit(ret); } lxc-2.0.8/src/tests/createtest.c0000644061062106075000000000462713105116772013514 00000000000000/* liblxcapi * * Copyright © 2012 Serge Hallyn . * Copyright © 2012 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include #include #define MYNAME "lxctest1" int main(int argc, char *argv[]) { struct lxc_container *c; int ret = 1; if ((c = lxc_container_new(MYNAME, NULL)) == NULL) { fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME); ret = 1; goto out; } if (c->is_defined(c)) { fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME); goto out; } if (!c->set_config_item(c, "lxc.network.type", "veth")) { fprintf(stderr, "%d: failed to set network type\n", __LINE__); goto out; } c->set_config_item(c, "lxc.network.link", "lxcbr0"); c->set_config_item(c, "lxc.network.flags", "up"); if (!c->createl(c, "busybox", NULL, NULL, 0, NULL)) { fprintf(stderr, "%d: failed to create a trusty container\n", __LINE__); goto out; } if (!c->is_defined(c)) { fprintf(stderr, "%d: %s thought it was not defined\n", __LINE__, MYNAME); goto out; } c->clear_config(c); c->load_config(c, NULL); c->want_daemonize(c, true); if (!c->startl(c, 0, NULL)) { fprintf(stderr, "%d: failed to start %s\n", __LINE__, MYNAME); goto out; } if (!c->stop(c)) { fprintf(stderr, "%d: failed to stop %s\n", __LINE__, MYNAME); goto out; } if (!c->destroy(c)) { fprintf(stderr, "%d: error deleting %s\n", __LINE__, MYNAME); goto out; } if (c->is_defined(c)) { fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME); goto out; } fprintf(stderr, "all lxc_container tests passed for %s\n", c->name); ret = 0; out: lxc_container_put(c); exit(ret); } lxc-2.0.8/src/tests/attach.c0000644061062106075000000002223713105116772012612 00000000000000/* liblxcapi * * Copyright © 2013 Oracle. * * Authors: * Dwight Engen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include "lxc/utils.h" #include "lxc/lsm/lsm.h" #include #include #include #include #include #define TSTNAME "lxc-attach-test" #define TSTOUT(fmt, ...) do { \ fprintf(stdout, fmt, ##__VA_ARGS__); fflush(NULL); \ } while (0) #define TSTERR(fmt, ...) do { \ fprintf(stderr, "%s:%d " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); fflush(NULL); \ } while (0) static const char *lsm_config_key = NULL; static const char *lsm_label = NULL; bool file_exists(const char *f) { struct stat statbuf; return stat(f, &statbuf) == 0; } static void test_lsm_detect(void) { if (lsm_enabled()) { if (!strcmp(lsm_name(), "SELinux")) { lsm_config_key = "lxc.se_context"; lsm_label = "unconfined_u:unconfined_r:lxc_t:s0-s0:c0.c1023"; } else if (!strcmp(lsm_name(), "AppArmor")) { lsm_config_key = "lxc.aa_profile"; if (file_exists("/proc/self/ns/cgroup")) lsm_label = "lxc-container-default-cgns"; else lsm_label = "lxc-container-default"; } else { TSTERR("unknown lsm %s enabled, add test code here", lsm_name()); exit(EXIT_FAILURE); } } } #if HAVE_APPARMOR || HAVE_SELINUX static void test_attach_lsm_set_config(struct lxc_container *ct) { ct->load_config(ct, NULL); ct->set_config_item(ct, lsm_config_key, lsm_label); ct->save_config(ct, NULL); } static int test_attach_lsm_func_func(void* payload) { TSTOUT("%s", lsm_process_label_get(getpid())); return 0; } static int test_attach_lsm_func(struct lxc_container *ct) { int ret; pid_t pid; int pipefd[2]; char result[1024]; lxc_attach_options_t attach_options = LXC_ATTACH_OPTIONS_DEFAULT; TSTOUT("Testing attach lsm label with func...\n"); ret = pipe(pipefd); if (ret < 0) { TSTERR("pipe failed %d", ret); return ret; } attach_options.stdout_fd = pipefd[1]; attach_options.attach_flags &= ~(LXC_ATTACH_LSM_EXEC|LXC_ATTACH_DROP_CAPABILITIES); attach_options.attach_flags |= LXC_ATTACH_LSM_NOW; ret = ct->attach(ct, test_attach_lsm_func_func, NULL, &attach_options, &pid); if (ret < 0) { TSTERR("attach failed"); goto err1; } ret = read(pipefd[0], result, sizeof(result)-1); if (ret < 0) { TSTERR("read failed %d", ret); goto err2; } result[ret] = '\0'; if (strcmp(lsm_label, result)) { TSTERR("LSM label mismatch expected:%s got:%s", lsm_label, result); ret = -1; goto err2; } ret = 0; err2: wait_for_pid(pid); err1: close(pipefd[0]); close(pipefd[1]); return ret; } static int test_attach_lsm_cmd(struct lxc_container *ct) { int ret; pid_t pid; int pipefd[2]; char result[1024]; char *space; char *argv[] = {"cat", "/proc/self/attr/current", NULL}; lxc_attach_command_t command = {"cat", argv}; lxc_attach_options_t attach_options = LXC_ATTACH_OPTIONS_DEFAULT; TSTOUT("Testing attach lsm label with cmd...\n"); ret = pipe(pipefd); if (ret < 0) { TSTERR("pipe failed %d", ret); return ret; } attach_options.stdout_fd = pipefd[1]; ret = ct->attach(ct, lxc_attach_run_command, &command, &attach_options, &pid); if (ret < 0) { TSTERR("attach failed"); goto err1; } ret = read(pipefd[0], result, sizeof(result)-1); if (ret < 0) { TSTERR("read failed %d", ret); goto err2; } result[ret] = '\0'; space = strchr(result, '\n'); if (space) *space = '\0'; space = strchr(result, ' '); if (space) *space = '\0'; ret = -1; if (strcmp(lsm_label, result)) { TSTERR("LSM label mismatch expected:%s got:%s", lsm_label, result); goto err2; } ret = 0; err2: wait_for_pid(pid); err1: close(pipefd[0]); close(pipefd[1]); return ret; } #else static void test_attach_lsm_set_config(struct lxc_container *ct) {} static int test_attach_lsm_func(struct lxc_container *ct) { return 0; } static int test_attach_lsm_cmd(struct lxc_container *ct) { return 0; } #endif /* HAVE_APPARMOR || HAVE_SELINUX */ static int test_attach_func_func(void* payload) { TSTOUT("%d", getpid()); return 0; } static int test_attach_func(struct lxc_container *ct) { int ret; pid_t pid,nspid; int pipefd[2]; char result[1024]; lxc_attach_options_t attach_options = LXC_ATTACH_OPTIONS_DEFAULT; TSTOUT("Testing attach with func...\n"); /* XXX: We can't just use &nspid and have test_attach_func_func fill * it in because the function doesn't run in our process context but * in a fork()ed from us context. We read the result through a pipe. */ ret = pipe(pipefd); if (ret < 0) { TSTERR("pipe failed %d", ret); return ret; } attach_options.stdout_fd = pipefd[1]; ret = ct->attach(ct, test_attach_func_func, NULL, &attach_options, &pid); if (ret < 0) { TSTERR("attach failed"); goto err1; } ret = read(pipefd[0], result, sizeof(result)-1); if (ret < 0) { TSTERR("read failed %d", ret); goto err2; } result[ret] = '\0'; /* There is a small chance the pid is reused inside the NS, so we * just print it and don't actually do this check * * if (pid == nspid) TSTERR(...) */ nspid = atoi(result); TSTOUT("Pid:%d in NS:%d\n", pid, nspid); ret = 0; err2: wait_for_pid(pid); err1: close(pipefd[0]); close(pipefd[1]); return ret; } static int test_attach_cmd(struct lxc_container *ct) { int ret; pid_t pid; char *argv[] = {"cmp", "-s", "/sbin/init", "/bin/busybox", NULL}; lxc_attach_command_t command = {"cmp", argv}; lxc_attach_options_t attach_options = LXC_ATTACH_OPTIONS_DEFAULT; TSTOUT("Testing attach with success command...\n"); ret = ct->attach(ct, lxc_attach_run_command, &command, &attach_options, &pid); if (ret < 0) { TSTERR("attach failed"); return ret; } ret = wait_for_pid(pid); if (ret < 0) { TSTERR("attach success command got bad return %d", ret); return ret; } TSTOUT("Testing attach with failure command...\n"); argv[2] = "/etc/fstab"; ret = ct->attach(ct, lxc_attach_run_command, &command, &attach_options, &pid); if (ret < 0) { TSTERR("attach failed"); return ret; } ret = wait_for_pid(pid); if (ret == 0) { TSTERR("attach failure command got bad return %d", ret); return -1; } return 0; } /* test_ct_destroy: stop and destroy the test container * * @ct : the container */ static void test_ct_destroy(struct lxc_container *ct) { ct->stop(ct); ct->destroy(ct); lxc_container_put(ct); } /* test_ct_create: create and start test container * * @lxcpath : the lxcpath in which to create the container * @group : name of the container group or NULL for default "lxc" * @name : name of the container * @template : template to use when creating the container */ static struct lxc_container *test_ct_create(const char *lxcpath, const char *group, const char *name, const char *template) { int ret; struct lxc_container *ct = NULL; if (lxcpath) { ret = mkdir(lxcpath, 0755); if (ret < 0 && errno != EEXIST) { TSTERR("failed to mkdir %s %s", lxcpath, strerror(errno)); goto out1; } } if ((ct = lxc_container_new(name, lxcpath)) == NULL) { TSTERR("instantiating container %s", name); goto out1; } if (ct->is_defined(ct)) { ct->stop(ct); ct->destroy(ct); ct = lxc_container_new(name, lxcpath); } if (!ct->createl(ct, template, NULL, NULL, 0, NULL)) { TSTERR("creating container %s", name); goto out2; } if (lsm_enabled()) test_attach_lsm_set_config(ct); ct->want_daemonize(ct, true); if (!ct->startl(ct, 0, NULL)) { TSTERR("starting container %s", name); goto out2; } return ct; out2: test_ct_destroy(ct); ct = NULL; out1: return ct; } static int test_attach(const char *lxcpath, const char *name, const char *template) { int ret = -1; struct lxc_container *ct; TSTOUT("Testing attach with on lxcpath:%s\n", lxcpath ? lxcpath : ""); ct = test_ct_create(lxcpath, NULL, name, template); if (!ct) goto err1; ret = test_attach_cmd(ct); if (ret < 0) { TSTERR("attach cmd test failed"); goto err2; } ret = test_attach_func(ct); if (ret < 0) { TSTERR("attach func test failed"); goto err2; } if (lsm_enabled()) { ret = test_attach_lsm_cmd(ct); if (ret < 0) { TSTERR("attach lsm cmd test failed"); goto err2; } ret = test_attach_lsm_func(ct); if (ret < 0) { TSTERR("attach lsm func test failed"); goto err2; } } ret = 0; err2: test_ct_destroy(ct); err1: return ret; } int main(int argc, char *argv[]) { int ret; test_lsm_detect(); ret = test_attach(NULL, TSTNAME, "busybox"); if (ret < 0) return EXIT_FAILURE; TSTOUT("\n"); ret = test_attach(LXCPATH "/alternate-path-test", TSTNAME, "busybox"); if (ret < 0) return EXIT_FAILURE; TSTOUT("All tests passed\n"); return EXIT_SUCCESS; } lxc-2.0.8/src/tests/may_control.c0000644061062106075000000000240513105116772013667 00000000000000/* control.c * * Copyright © 2013 Canonical, Inc * Author: Serge Hallyn * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include static void usage(const char *me) { printf("Usage: %s name [lxcpath]\n", me); exit(0); } int main(int argc, char *argv[]) { const char *lxcpath = NULL, *name; bool may = false; struct lxc_container *c; if (argc < 2) usage(argv[0]); name = argv[1]; if (argc == 3) lxcpath = argv[2]; c = lxc_container_new(name, lxcpath); if (c) may = c->may_control(c); printf("You may%s control %s\n", may ? "" : " not", name); exit(may ? 0 : 1); } lxc-2.0.8/src/tests/lxc-test-unpriv0000755061062106075000000001427313105116772014215 00000000000000#!/bin/bash # lxc: linux Container library # Authors: # Serge Hallyn # # This is a test script for unprivileged containers # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # This test assumes an Ubuntu host if [ $(id -u) -ne 0 ]; then echo "ERROR: Must run as root." exit 1 fi # Test if we're using an overlayfs module that handles symlinks correctly. If # not, we skip these tests since overlay clones will not work correctly. if modprobe -q overlayfs; then TMPDIR=$(mktemp -d) MOUNTDIR="${TMPDIR}/ovl_symlink_test" mkdir ${MOUNTDIR} mount -t tmpfs none ${MOUNTDIR} mkdir "${MOUNTDIR}/lowerdir" "${MOUNTDIR}/upperdir" "${MOUNTDIR}/overlayfs" mount -t overlayfs -o lowerdir="${MOUNTDIR}/lowerdir",upperdir="${MOUNTDIR}/upperdir" none "${MOUNTDIR}/overlayfs" CORRECT_LINK_TARGET="${MOUNTDIR}/overlayfs/dummy_file" exec 9> "${CORRECT_LINK_TARGET}" DETECTED_LINK_TARGET=$(readlink -q /proc/$$/fd/9) # cleanup exec 9>&- umount "${MOUNTDIR}/overlayfs" umount ${MOUNTDIR} rmdir ${MOUNTDIR} # This overlay module does not correctly handle symlinks, so skip the # tests. if [ "${DETECTED_LINK_TARGET}" != "${CORRECT_LINK_TARGET}" ]; then exit 0 fi fi which newuidmap >/dev/null 2>&1 || { echo "'newuidmap' command is missing" >&2; exit 1; } DONE=0 KNOWN_RELEASES="precise trusty xenial yakkety zesty" cleanup() { cd / run_cmd lxc-stop -n c2 -k || true run_cmd lxc-stop -n c1 -k || true pkill -u $(id -u $TUSER) -9 sed -i '/lxcunpriv/d' /run/lxc/nics /etc/lxc/lxc-usernet sed -i '/^lxcunpriv:/d' /etc/subuid /etc/subgid rm -Rf $HDIR /run/user/$(id -u $TUSER) deluser $TUSER if [ $DONE -eq 0 ]; then echo "FAIL" exit 1 fi echo "PASS" } run_cmd() { sudo -i -u $TUSER \ env http_proxy=${http_proxy:-} https_proxy=${https_proxy:-} \ XDG_RUNTIME_DIR=/run/user/$(id -u $TUSER) $* } # create a test user TUSER=lxcunpriv HDIR=/home/$TUSER ARCH=i386 if type dpkg >/dev/null 2>&1; then ARCH=$(dpkg --print-architecture) fi trap cleanup EXIT SIGHUP SIGINT SIGTERM set -eu deluser $TUSER && rm -Rf $HDIR || true useradd $TUSER mkdir -p $HDIR echo "$TUSER veth lxcbr0 2" >> /etc/lxc/lxc-usernet sed -i '/^lxcunpriv:/d' /etc/subuid /etc/subgid usermod -v 910000-919999 -w 910000-919999 $TUSER mkdir -p $HDIR/.config/lxc/ cat > $HDIR/.config/lxc/default.conf << EOF lxc.network.type = veth lxc.network.link = lxcbr0 lxc.id_map = u 0 910000 9999 lxc.id_map = g 0 910000 9999 EOF chown -R $TUSER: $HDIR mkdir -p /run/user/$(id -u $TUSER) chown -R $TUSER: /run/user/$(id -u $TUSER) cd $HDIR if which cgm >/dev/null 2>&1; then cgm create all $TUSER cgm chown all $TUSER $(id -u $TUSER) $(id -g $TUSER) cgm movepid all $TUSER $$ elif [ -e /sys/fs/cgroup/cgmanager/sock ]; then for d in $(cut -d : -f 2 /proc/self/cgroup); do dbus-send --print-reply --address=unix:path=/sys/fs/cgroup/cgmanager/sock \ --type=method_call /org/linuxcontainers/cgmanager org.linuxcontainers.cgmanager0_0.Create \ string:$d string:$TUSER >/dev/null dbus-send --print-reply --address=unix:path=/sys/fs/cgroup/cgmanager/sock \ --type=method_call /org/linuxcontainers/cgmanager org.linuxcontainers.cgmanager0_0.Chown \ string:$d string:$TUSER int32:$(id -u $TUSER) int32:$(id -g $TUSER) >/dev/null dbus-send --print-reply --address=unix:path=/sys/fs/cgroup/cgmanager/sock \ --type=method_call /org/linuxcontainers/cgmanager org.linuxcontainers.cgmanager0_0.MovePid \ string:$d string:$TUSER int32:$$ >/dev/null done else for d in /sys/fs/cgroup/*; do [ -f $d/cgroup.clone_children ] && echo 1 > $d/cgroup.clone_children [ ! -d $d/lxctest ] && mkdir $d/lxctest chown -R $TUSER: $d/lxctest echo $$ > $d/lxctest/tasks done fi # default release is trusty, or the systems release if recognized release=trusty if [ -f /etc/lsb-release ]; then . /etc/lsb-release rels=$(ubuntu-distro-info --supported 2>/dev/null) || rels="$KNOWN_RELEASES" for r in $rels; do [ "$DISTRIB_CODENAME" = "$r" ] && release="$r" done fi # Copy the download template cache if available run_cmd mkdir -p $HDIR/.cache/lxc [ -d /var/cache/lxc/download ] && \ cp -R /var/cache/lxc/download $HDIR/.cache/lxc && \ chown -R $TUSER: $HDIR/.cache/lxc run_cmd lxc-create -t download -n c1 -- -d ubuntu -r $release -a $ARCH # Make sure we can start it - twice for count in `seq 1 2`; do run_cmd lxc-start -n c1 -d p1=$(run_cmd lxc-info -n c1 -p -H) [ "$p1" != "-1" ] || { echo "Failed to start container c1 (run $count)"; false; } run_cmd lxc-info -n c1 run_cmd lxc-attach -n c1 -- /bin/true run_cmd lxc-stop -n c1 -k done run_cmd lxc-copy -s -n c1 -N c2 run_cmd lxc-start -n c2 -d p1=$(run_cmd lxc-info -n c2 -p -H) [ "$p1" != "-1" ] || { echo "Failed to start container c2"; false; } run_cmd lxc-stop -n c2 -k if which cgm >/dev/null 2>&1; then echo "Testing containers under different cgroups per subsystem" run_cmd cgm create freezer x1/x2 cgm movepid freezer x1 $$ run_cmd lxc-start -n c1 -d p1=$(run_cmd lxc-info -n c1 -p -H) [ "$p1" != "-1" ] || { echo "Failed to start container c1"; false; } run_cmd lxc-info -n c1 run_cmd lxc-attach -n c1 -- /bin/true run_cmd lxc-cgroup -n c1 freezer.state echo "Testing lxc-attach and lxc-cgroup from different cgroup" cgm movepid freezer x2 $$ run_cmd lxc-attach -n c1 -- /bin/true run_cmd lxc-cgroup -n c1 freezer.state run_cmd lxc-cgroup -n c1 memory.limit_in_bytes fi DONE=1 lxc-2.0.8/src/tests/lxc-test-symlink0000755061062106075000000000477613105116772014367 00000000000000#!/bin/bash set -ex # lxc: linux Container library # Authors: # Serge Hallyn # # This is a regression test for symbolic links dirname=`mktemp -d` fname=`mktemp` fname2=`mktemp` lxcpath=/var/lib/lxcsym1 cleanup() { lxc-destroy -P $lxcpath -f -n symtest1 || true rm -f $lxcpath rmdir $dirname || true rm -f $fname || true rm -f $fname2 || true } trap cleanup EXIT SIGHUP SIGINT SIGTERM testrun() { expected=$1 run=$2 pass="pass" lxc-start -P $lxcpath -n symtest1 -l trace -o $lxcpath/log || pass="fail" [ $pass = "pass" ] && lxc-wait -P $lxcpath -n symtest1 -t 10 -s RUNNING || pass="fail" if [ "$pass" != "$expected" ]; then echo "Test $run: expected $expected but container did not. Start log:" cat $lxcpath/log echo "FAIL: Test $run: expected $expected but container did not." false fi lxc-stop -P $lxcpath -n symtest1 -k || true } # make lxcpath a symlink - this should NOT cause failure ln -s /var/lib/lxc $lxcpath lxc-destroy -P $lxcpath -f -n symtest1 || true lxc-create -P $lxcpath -t busybox -n symtest1 cat >> /var/lib/lxc/symtest1/config << EOF lxc.mount.entry = $dirname opt/xxx/dir none bind,create=dir lxc.mount.entry = $fname opt/xxx/file none bind,create=file lxc.mount.entry = $fname2 opt/xxx/file2 none bind lxc.mount.entry = $dirname /var/lib/lxc/symtest1/rootfs/opt/xxx/dir2 none bind,create=dir EOF # Regular - should succeed mkdir -p /var/lib/lxc/symtest1/rootfs/opt/xxx touch /var/lib/lxc/symtest1/rootfs/opt/xxx/file2 testrun pass 1 # symlink - should fail rm -rf /var/lib/lxc/symtest1/rootfs/opt/xxx mkdir -p /var/lib/lxc/symtest1/rootfs/opt/xxx2 ln -s /var/lib/lxc/symtest1/rootfs/opt/xxx2 /var/lib/lxc/symtest1/rootfs/opt/xxx touch /var/lib/lxc/symtest1/rootfs/opt/xxx/file2 testrun fail 2 # final final symlink - should fail rm -rf $lxcpath/symtest1/rootfs/opt/xxx mkdir -p $lxcpath/symtest1/rootfs/opt/xxx mkdir -p $lxcpath/symtest1/rootfs/opt/xxx/dir touch $lxcpath/symtest1/rootfs/opt/xxx/file touch $lxcpath/symtest1/rootfs/opt/xxx/file2src ln -s $lxcpath/symtest1/rootfs/opt/xxx/file2src $lxcpath/symtest1/rootfs/opt/xxx/file2 testrun fail 3 # Ideally we'd also try a loop device, but that won't work in nested containers # anyway - TODO # what about /proc itself rm -rf $lxcpath/symtest1/rootfs/opt/xxx mkdir -p $lxcpath/symtest1/rootfs/opt/xxx touch $lxcpath/symtest1/rootfs/opt/xxx/file2 mv $lxcpath/symtest1/rootfs/proc $lxcpath/symtest1/rootfs/proc1 ln -s $lxcpath/symtest1/rootfs/proc1 $lxcpath/symtest1/rootfs/proc testrun fail 4 echo "all tests passed" lxc-2.0.8/src/tests/lxc-test-lxc-attach0000755061062106075000000001622613105116772014722 00000000000000#!/bin/sh # lxc: linux Container library # Authors: # Christian Brauner # # This is a test script for the lxc-attach program. It tests whether I/O # redirection and pty allocation works correctly. # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA set -e # NOTE: # lxc-attach allocates a pty on the host and attaches any standard file # descriptors that refer to a pty to it. Standard file descriptors which do not # refer to a pty are not attached. In order to determine whether lxc-attach # works correctly we test various methods of redirection on the host. E.g.: # # lxc-attach -n busy -- hostname < /dev/null # # This is done to check whether the file descriptor that gets redirected to # /dev/null is (a) left alone and (b) that lxc-attach does not fail. When # lxc-attach fails we know that it's behavior has been altered, e.g. by trying # to attach a standard file descriptor that does not refer to a pty. # The small table preceeding each test case show which standard file descriptors # we expect to be attached to a pty and which we expect to be redirected. E.g. # # stdin --> attached to pty # stdout --> attached to pty # stderr --> attached to pty allocate_pty="nopty" FAIL() { echo -n "Failed " >&2 echo "$*" >&2 lxc-destroy -n busy -f exit 1 } # Create a container, start it and wait for it to be in running state. lxc-create -t busybox -n busy || FAIL "creating busybox container" lxc-start -n busy -d || FAIL "starting busybox container" lxc-wait -n busy -s RUNNING || FAIL "waiting for busybox container to run" if [ -t 0 ] && [ -t 1 ] && [ -t 2 ]; then allocate_pty="pty" echo "All standard file descriptors refer to a pty." echo "Tests for lxc-attach pty allocation and I/O redirection" echo "will be performed correctly." fi # stdin --> attached to pty # stdout --> attached to pty # stderr --> attached to pty for i in `seq 1 100`; do attach=$(lxc-attach -n busy -- hostname || FAIL "to allocate or setup pty") if [ "$attach" != "busy" ]; then FAIL "lxc-attach -n busy -- hostname" fi done # stdin --> /dev/null # stdout --> attached to pty # stderr --> attached to pty attach=$(lxc-attach -n busy -- hostname < /dev/null || FAIL "to allocate or setup pty") if [ "$attach" != "busy" ]; then FAIL "lxc-attach -n busy -- hostname < /dev/null" fi # stdin --> attached to pty # stdout --> /dev/null # stderr --> attached to pty attach=$(lxc-attach -n busy -- hostname > /dev/null || FAIL "to allocate or setup pty") if [ -n "$attach" ]; then FAIL "lxc-attach -n busy -- hostname > /dev/null" fi # stdin --> attached to pty # stdout --> attached to pty # stderr --> /dev/null attach=$(lxc-attach -n busy -- hostname 2> /dev/null || FAIL "to allocate or setup pty") if [ "$attach" != "busy" ]; then FAIL "lxc-attach -n busy -- hostname 2> /dev/null < /dev/null" fi # stdin --> /dev/null # stdout --> attached to pty # stderr --> /dev/null attach=$(lxc-attach -n busy -- hostname 2> /dev/null < /dev/null || FAIL "to allocate or setup pty") if [ "$attach" != "busy" ]; then FAIL "lxc-attach -n busy -- hostname 2> /dev/null < /dev/null" fi # Use a synthetic reproducer in container to produce output on stderr. stdout on # the host gets redirect to /dev/null. We should still be able to receive # containers output on stderr on the host. (The command is run in a subshell. # This allows us to redirect stderr to stdout for the subshell and capture the # output in the attach variable.) # stdin --> attached to pty # stdout --> /dev/null # stderr --> attached to pty attach=$( ( lxc-attach -n busy -- sh -c 'hostname >&2' > /dev/null ) 2>&1 || FAIL "to allocate or setup pty") if [ "$attach" != "busy" ]; then FAIL "lxc-attach -n busy -- sh -c 'hostname >&2' > /dev/null" fi # Use a synthetic reproducer in container to produce output on stderr. stderr on # the host gets redirect to /dev/null. We should not receive output on stderr on # the host. (The command is run in a subshell. This allows us to redirect stderr # to stdout for the subshell and capture the output in the attach variable.) # stdin --> attached to pty # stdout --> attach to pty # stderr --> /dev/null attach=$( ( lxc-attach -n busy -- sh -c 'hostname >&2' 2> /dev/null ) 2>&1 || FAIL "to allocate or setup pty") if [ -n "$attach" ]; then FAIL "lxc-attach -n busy -- sh -c 'hostname >&2' 2> /dev/null" fi # stdin --> attached to pty # stdout --> /dev/null # stderr --> attached to pty # (As we expect the exit code of the command to be 1 we ignore it.) attach=$(lxc-attach -n busy -- sh -c 'rm 2>&1' > /dev/null || true) if [ -n "$attach" ]; then FAIL "lxc-attach -n busy -- sh -c 'rm 2>&1' > /dev/null" fi # - stdin --> attached to pty # - stdout --> attached to pty # - stderr --> /dev/null # (As we expect the exit code of the command to be 1 we ignore it.) attach=$(lxc-attach -n busy -- sh -c 'rm 2>&1' 2> /dev/null || true) if [ -z "$attach" ]; then FAIL "lxc-attach -n busy -- sh -c 'rm 2>&1' 2> /dev/null" fi # stdin --> $in # stdout --> attached to pty # stderr --> attached to pty attach=$(echo hostname | lxc-attach -n busy -- || FAIL "to allocate or setup pty") if [ "$attach" != "busy" ]; then FAIL "echo hostname | lxc-attach -n busy --" fi # stdin --> attached to pty # stdout --> $out # stderr --> $err out=$(mktemp /tmp/out_XXXX) err=$(mktemp /tmp/err_XXXX) trap "rm -f $out $err" EXIT INT QUIT PIPE lxc-attach -n busy -- sh -c 'echo OUT; echo ERR >&2' > $out 2> $err || FAIL "to allocate or setup pty" outcontent=$(cat $out) errcontent=$(cat $err) if [ "$outcontent" != "OUT" ] || [ "$errcontent" != "ERR" ]; then FAIL "lxc-attach -n busy -- sh -c 'echo OUT; echo ERR >&2' > $out 2> $err" fi rm -f $out $err # stdin --> $in # stdout --> $out # stderr --> $err # (As we expect the exit code of the command to be 1 we ignore it.) out=$(mktemp /tmp/out_XXXX) err=$(mktemp /tmp/err_XXXX) trap "rm -f $out $err" EXIT INT QUIT PIPE echo "hostname; rm" | lxc-attach -n busy > $out 2> $err || true outcontent=$(cat $out) errcontent=$(cat $err) if [ "$outcontent" != "busy" ] || [ -z "$errcontent" ]; then FAIL "echo 'hostname; rm' | lxc-attach -n busy > $out 2> $err" fi rm -f $out $err if [ $allocate_pty = "pty" ]; then # Test whether logging pty output to a file works. trap "rm -f /tmp/ptylog" EXIT INT QUIT PIPE lxc-attach -n busy -L /tmp/ptylog -- hostname || FAIL "to allocate or setup pty" if [ ! -s /tmp/ptylog ]; then FAIL "lxc-attach -n busy -L /tmp/ptylog -- hostname" fi rm -f /tmp/ptylog fi lxc-destroy -n busy -f exit 0 lxc-2.0.8/src/tests/destroytest.c0000644061062106075000000000470313105116772013735 00000000000000/* liblxcapi * * Copyright © 2012 Serge Hallyn . * Copyright © 2012 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include #include #define MYNAME "lxctest1" static int create_container(void) { int status, ret; pid_t pid = fork(); if (pid < 0) { perror("fork"); return -1; } if (pid == 0) { ret = execlp("lxc-create", "lxc-create", "-t", "busybox", "-n", MYNAME, NULL); // Should not return perror("execl"); exit(1); } again: ret = waitpid(pid, &status, 0); if (ret == -1) { if (errno == EINTR) goto again; perror("waitpid"); return -1; } if (ret != pid) goto again; if (!WIFEXITED(status)) { // did not exit normally fprintf(stderr, "%d: lxc-create exited abnormally\n", __LINE__); return -1; } return WEXITSTATUS(status); } int main(int argc, char *argv[]) { struct lxc_container *c; int ret = 1; if ((c = lxc_container_new(MYNAME, NULL)) == NULL) { fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME); ret = 1; goto out; } if (c->is_defined(c)) { fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME); goto out; } if (create_container()) { fprintf(stderr, "%d: failed to create a container\n", __LINE__); goto out; } if (!c->is_defined(c)) { fprintf(stderr, "%d: %s thought it was not defined\n", __LINE__, MYNAME); goto out; } if (!c->destroy(c)) { fprintf(stderr, "%d: error deleting %s\n", __LINE__, MYNAME); goto out; } if (c->is_defined(c)) { fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME); goto out; } fprintf(stderr, "all lxc_container tests passed for %s\n", c->name); ret = 0; out: lxc_container_put(c); exit(ret); } lxc-2.0.8/src/tests/lxc-test-checkpoint-restore0000755061062106075000000000224713105116772016500 00000000000000#!/bin/sh # Do an end to end checkpoint and restore with criu. set -e FAIL() { echo -n "Failed " >&2 echo "$*" >&2 exit 1 } if [ "$(id -u)" != "0" ]; then echo "ERROR: Must run as root." exit 1 fi verlte() { ! [ "$1" = "$(printf "$1\n$2" | sort -V | tail -n1)" ] } criu_version="$(criu --version | head -n1 | cut -d' ' -f 2)" if verlte "$criu_version" "1.3.1"; then echo "SKIP: skipping test because no (or wrong) criu installed." exit 0 fi name=lxc-test-criu lxc-create -t ubuntu -n $name || FAIL "creating container" cat >> "$(lxc-config lxc.lxcpath)/$name/config" <&2 echo "$*" >&2 exit 1 } run_cmd() { sudo -i -u $TUSER \ env http_proxy=${http_proxy:-} https_proxy=${https_proxy:-} \ XDG_RUNTIME_DIR=/run/user/$(id -u $TUSER) $* } DONE=0 KNOWN_RELEASES="precise trusty xenial yakkety zesty" MOUNTSR=/sys/kernel/security/apparmor/features/mount dnam=`mktemp -d` cname=`basename $dnam` cleanup() { run_cmd lxc-destroy -f -n $cname || true umount -l $MOUNTSR || true rmdir $dnam || true pkill -u $(id -u $TUSER) -9 sed -i '/lxcunpriv/d' /run/lxc/nics /etc/lxc/lxc-usernet sed -i '/^lxcunpriv:/d' /etc/subuid /etc/subgid rm -Rf $HDIR /run/user/$(id -u $TUSER) deluser $TUSER if [ $DONE -eq 0 ]; then echo "FAIL" exit 1 fi echo "PASS" } trap cleanup exit # Only run on a normally configured ubuntu lxc system if [ ! -d /sys/class/net/lxcbr0 ]; then echo "lxcbr0 is not configured." exit 1 fi if [ "$(id -u)" != "0" ]; then echo "ERROR: Must run as root." exit 1 fi # This would be much simpler if we could run it as # root. However, in order to not have the bind mount # of an empty directory over the securitfs 'mount' directory # be removed, we need to do this as non-root. which newuidmap >/dev/null 2>&1 || { echo "'newuidmap' command is missing" >&2; exit 1; } # create a test user TUSER=lxcunpriv HDIR=/home/$TUSER ARCH=i386 if type dpkg >/dev/null 2>&1; then ARCH=$(dpkg --print-architecture) fi deluser $TUSER && rm -Rf $HDIR || true useradd $TUSER mkdir -p $HDIR echo "$TUSER veth lxcbr0 2" >> /etc/lxc/lxc-usernet sed -i '/^lxcunpriv:/d' /etc/subuid /etc/subgid usermod -v 910000-919999 -w 910000-919999 $TUSER mkdir -p $HDIR/.config/lxc/ cat > $HDIR/.config/lxc/default.conf << EOF lxc.network.type = veth lxc.network.link = lxcbr0 lxc.id_map = u 0 910000 9999 lxc.id_map = g 0 910000 9999 EOF chown -R $TUSER: $HDIR mkdir -p /run/user/$(id -u $TUSER) chown -R $TUSER: /run/user/$(id -u $TUSER) cd $HDIR if which cgm >/dev/null 2>&1; then cgm create all $TUSER cgm chown all $TUSER $(id -u $TUSER) $(id -g $TUSER) cgm movepid all $TUSER $$ elif [ -e /sys/fs/cgroup/cgmanager/sock ]; then for d in $(cut -d : -f 2 /proc/self/cgroup); do dbus-send --print-reply --address=unix:path=/sys/fs/cgroup/cgmanager/sock \ --type=method_call /org/linuxcontainers/cgmanager org.linuxcontainers.cgmanager0_0.Create \ string:$d string:$TUSER >/dev/null dbus-send --print-reply --address=unix:path=/sys/fs/cgroup/cgmanager/sock \ --type=method_call /org/linuxcontainers/cgmanager org.linuxcontainers.cgmanager0_0.Chown \ string:$d string:$TUSER int32:$(id -u $TUSER) int32:$(id -g $TUSER) >/dev/null dbus-send --print-reply --address=unix:path=/sys/fs/cgroup/cgmanager/sock \ --type=method_call /org/linuxcontainers/cgmanager org.linuxcontainers.cgmanager0_0.MovePid \ string:$d string:$TUSER int32:$$ >/dev/null done else for d in /sys/fs/cgroup/*; do [ -f $d/cgroup.clone_children ] && echo 1 > $d/cgroup.clone_children [ ! -d $d/lxctest ] && mkdir $d/lxctest chown -R $TUSER: $d/lxctest echo $$ > $d/lxctest/tasks done fi run_cmd mkdir -p $HDIR/.cache/lxc [ -d /var/cache/lxc/download ] && \ cp -R /var/cache/lxc/download $HDIR/.cache/lxc && \ chown -R $TUSER: $HDIR/.cache/lxc # default release is trusty, or the systems release if recognized release=trusty if [ -f /etc/lsb-release ]; then . /etc/lsb-release rels=$(ubuntu-distro-info --supported 2>/dev/null) || rels="$KNOWN_RELEASES" for r in $rels; do [ "$DISTRIB_CODENAME" = "$r" ] && release="$r" done fi run_cmd lxc-create -t download -n $cname -- -d ubuntu -r $release -a $ARCH echo "test default confined container" run_cmd lxc-start -n $cname -d run_cmd lxc-wait -n $cname -s RUNNING pid=`run_cmd lxc-info -p -H -n $cname` profile=`cat /proc/$pid/attr/current` if [ "x$profile" != "x${default_profile}" ]; then echo "FAIL: confined container was in profile $profile" exit 1 fi run_cmd lxc-stop -n $cname -k echo "test regular unconfined container" echo "lxc.aa_profile = unconfined" >> $HDIR/.local/share/lxc/$cname/config run_cmd lxc-start -n $cname -d run_cmd lxc-wait -n $cname -s RUNNING pid=`run_cmd lxc-info -p -H -n $cname` profile=`cat /proc/$pid/attr/current` if [ "x$profile" != "xunconfined" ]; then echo "FAIL: unconfined container was in profile $profile" exit 1 fi run_cmd lxc-stop -n $cname -k echo "masking $MOUNTSR" mount --bind $dnam $MOUNTSR echo "test default confined container" sed -i '/aa_profile/d' $HDIR/.local/share/lxc/$cname/config run_cmd lxc-start -n $cname -d || true sleep 3 pid=`run_cmd lxc-info -p -H -n $cname` || true if [ -n "$pid" -a "$pid" != "-1" ]; then echo "FAIL: confined container started without mount restrictions" echo "pid was $pid" exit 1 fi echo "test regular unconfined container" echo "lxc.aa_profile = unconfined" >> $HDIR/.local/share/lxc/$cname/config run_cmd lxc-start -n $cname -d run_cmd lxc-wait -n $cname -s RUNNING pid=`run_cmd lxc-info -p -H -n $cname` if [ "$pid" = "-1" ]; then echo "FAIL: unconfined container failed to start without mount restrictions" exit 1 fi profile=`cat /proc/$pid/attr/current` if [ "x$profile" != "xunconfined" ]; then echo "FAIL: confined container was in profile $profile" exit 1 fi run_cmd lxc-stop -n $cname -k echo "testing override" sed -i '/aa_profile/d' $HDIR/.local/share/lxc/$cname/config echo "lxc.aa_allow_incomplete = 1" >> $HDIR/.local/share/lxc/$cname/config run_cmd lxc-start -n $cname -d run_cmd lxc-wait -n $cname -s RUNNING pid=`run_cmd lxc-info -p -H -n $cname` if [ "$pid" = "-1" ]; then echo "FAIL: excepted container failed to start without mount restrictions" exit 1 fi profile=`cat /proc/$pid/attr/current` if [ "x$profile" != "x${default_profile}" ]; then echo "FAIL: confined container was in profile $profile" exit 1 fi run_cmd lxc-stop -n $cname -k DONE=1 lxc-2.0.8/src/tests/containertests.c0000644061062106075000000001411613105116772014410 00000000000000/* liblxcapi * * Copyright © 2012 Serge Hallyn . * Copyright © 2012 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include #include #include #include "lxc/state.h" #define MYNAME "lxctest1" static int destroy_busybox(void) { int status, ret; pid_t pid = fork(); if (pid < 0) { perror("fork"); return -1; } if (pid == 0) { ret = execlp("lxc-destroy", "lxc-destroy", "-f", "-n", MYNAME, NULL); // Should not return perror("execl"); exit(1); } again: ret = waitpid(pid, &status, 0); if (ret == -1) { if (errno == EINTR) goto again; perror("waitpid"); return -1; } if (ret != pid) goto again; if (!WIFEXITED(status)) { // did not exit normally fprintf(stderr, "%d: lxc-create exited abnormally\n", __LINE__); return -1; } return WEXITSTATUS(status); } static int create_busybox(void) { int status, ret; pid_t pid = fork(); if (pid < 0) { perror("fork"); return -1; } if (pid == 0) { ret = execlp("lxc-create", "lxc-create", "-t", "busybox", "-n", MYNAME, NULL); // Should not return perror("execl"); exit(1); } again: ret = waitpid(pid, &status, 0); if (ret == -1) { if (errno == EINTR) goto again; perror("waitpid"); return -1; } if (ret != pid) goto again; if (!WIFEXITED(status)) { // did not exit normally fprintf(stderr, "%d: lxc-create exited abnormally\n", __LINE__); return -1; } return WEXITSTATUS(status); } int main(int argc, char *argv[]) { struct lxc_container *c; int ret = 0; const char *s; bool b; char *str; ret = 1; /* test refcounting */ c = lxc_container_new(MYNAME, NULL); if (!c) { fprintf(stderr, "%d: error creating lxc_container %s\n", __LINE__, MYNAME); goto out; } if (!lxc_container_get(c)) { fprintf(stderr, "%d: error getting refcount\n", __LINE__); goto out; } /* peek in, inappropriately, make sure refcount is a we'd like */ if (c->numthreads != 2) { fprintf(stderr, "%d: refcount is %d, not %d\n", __LINE__, c->numthreads, 2); goto out; } if (strcmp(c->name, MYNAME) != 0) { fprintf(stderr, "%d: container has wrong name (%s not %s)\n", __LINE__, c->name, MYNAME); goto out; } str = c->config_file_name(c); #define CONFIGFNAM LXCPATH "/" MYNAME "/config" if (!str || strcmp(str, CONFIGFNAM)) { fprintf(stderr, "%d: got wrong config file name (%s, not %s)\n", __LINE__, str, CONFIGFNAM); goto out; } free(str); free(c->configfile); c->configfile = NULL; str = c->config_file_name(c); if (str) { fprintf(stderr, "%d: config file name was not NULL as it should have been\n", __LINE__); goto out; } if (lxc_container_put(c) != 0) { fprintf(stderr, "%d: c was freed on non-final put\n", __LINE__); goto out; } if (c->numthreads != 1) { fprintf(stderr, "%d: refcount is %d, not %d\n", __LINE__, c->numthreads, 1); goto out; } if (lxc_container_put(c) != 1) { fprintf(stderr, "%d: c was not freed on final put\n", __LINE__); goto out; } /* test a real container */ c = lxc_container_new(MYNAME, NULL); if (!c) { fprintf(stderr, "%d: error creating lxc_container %s\n", __LINE__, MYNAME); ret = 1; goto out; } b = c->is_defined(c); if (b) { fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME); goto out; } s = c->state(c); if (s && strcmp(s, "STOPPED") != 0) { // liblxc says a container is STOPPED if it doesn't exist. That's because // the container may be an application container - it's not wrong, just // sometimes unintuitive. fprintf(stderr, "%d: %s thinks it is in state %s\n", __LINE__, c->name, s); goto out; } // create a container // the liblxc api does not support creation - it probably will eventually, // but not yet. // So we just call out to lxc-create. We'll create a busybox container. ret = create_busybox(); if (ret) { fprintf(stderr, "%d: failed to create a busybox container\n", __LINE__); goto out; } b = c->is_defined(c); if (!b) { fprintf(stderr, "%d: %s thought it was not defined\n", __LINE__, MYNAME); goto out; } s = c->state(c); if (!s || strcmp(s, "STOPPED")) { fprintf(stderr, "%d: %s is in state %s, not in STOPPED.\n", __LINE__, c->name, s ? s : "undefined"); goto out; } b = c->load_config(c, NULL); if (!b) { fprintf(stderr, "%d: %s failed to read its config\n", __LINE__, c->name); goto out; } // test wait states int numstates = lxc_get_wait_states(NULL); if (numstates != MAX_STATE) { fprintf(stderr, "%d: lxc_get_wait_states gave %d not %d\n", __LINE__, numstates, MAX_STATE); goto out; } const char **sstr = malloc(numstates * sizeof(const char *)); numstates = lxc_get_wait_states(sstr); int i; for (i=0; iwant_daemonize(c, true); if (!c->startl(c, 0, NULL, NULL)) { fprintf(stderr, "%d: %s failed to start daemonized\n", __LINE__, c->name); goto out; } if (!c->wait(c, "RUNNING", -1)) { fprintf(stderr, "%d: failed waiting for state RUNNING\n", __LINE__); goto out; } sleep(3); s = c->state(c); if (!s || strcmp(s, "RUNNING")) { fprintf(stderr, "%d: %s is in state %s, not in RUNNING.\n", __LINE__, c->name, s ? s : "undefined"); goto out; } fprintf(stderr, "all lxc_container tests passed for %s\n", c->name); ret = 0; out: if (c) { c->stop(c); destroy_busybox(); } lxc_container_put(c); exit(ret); } lxc-2.0.8/src/tests/snapshot.c0000644061062106075000000001117713105116772013206 00000000000000/* liblxcapi * * Copyright © 2013 Serge Hallyn . * Copyright © 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include "lxc/lxc.h" #define MYNAME "snapxxx1" #define MYNAME2 "snapxxx3" #define RESTNAME "snapxxx2" static void try_to_remove(void) { struct lxc_container *c; c = lxc_container_new(RESTNAME, NULL); if (c) { c->snapshot_destroy_all(c); if (c->is_defined(c)) c->destroy(c); lxc_container_put(c); } c = lxc_container_new(MYNAME2, NULL); if (c) { c->destroy_with_snapshots(c); lxc_container_put(c); } c = lxc_container_new(MYNAME, NULL); if (c) { c->snapshot_destroy_all(c); if (c->is_defined(c)) c->destroy(c); lxc_container_put(c); } } int main(int argc, char *argv[]) { struct lxc_container *c, *c2 = NULL; char *template = "busybox"; if (argc > 1) template = argv[1]; try_to_remove(); c = lxc_container_new(MYNAME, NULL); if (!c) { fprintf(stderr, "%s: %d: failed to load first container\n", __FILE__, __LINE__); exit(1); } if (c->is_defined(c)) { fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME); (void) c->destroy_with_snapshots(c); } if (!c->set_config_item(c, "lxc.network.type", "empty")) { fprintf(stderr, "%s: %d: failed to set network type\n", __FILE__, __LINE__); goto err; } c->save_config(c, NULL); if (!c->createl(c, template, NULL, NULL, 0, NULL)) { fprintf(stderr, "%s: %d: failed to create %s container\n", __FILE__, __LINE__, template); goto err; } c->load_config(c, NULL); if (c->snapshot(c, NULL) != 0) { fprintf(stderr, "%s: %d: failed to create snapshot\n", __FILE__, __LINE__); goto err; } // rootfs should be ${lxcpath}${lxcname}/snaps/snap0/rootfs struct stat sb; int ret; char path[1024]; snprintf(path, 1024, "%s/%s/snaps/snap0/rootfs", lxc_get_global_config_item("lxc.lxcpath"), MYNAME); ret = stat(path, &sb); if (ret != 0) { fprintf(stderr, "%s: %d: snapshot was not actually created\n", __FILE__, __LINE__); goto err; } struct lxc_snapshot *s; int i, n; n = c->snapshot_list(c, &s); if (n < 1) { fprintf(stderr, "%s: %d: failed listing containers\n", __FILE__, __LINE__); goto err; } if (strcmp(s->name, "snap0") != 0) { fprintf(stderr, "%s: %d: snapshot had bad name\n", __FILE__, __LINE__); goto err; } for (i=0; isnapshot_restore(c, "snap0", RESTNAME)) { fprintf(stderr, "%s: %d: failed to restore snapshot\n", __FILE__, __LINE__); goto err; } if (!c->snapshot_destroy(c, "snap0")) { fprintf(stderr, "%s: %d: failed to destroy snapshot\n", __FILE__, __LINE__); goto err; } c2 = lxc_container_new(RESTNAME, NULL); if (!c2 || !c2->is_defined(c2)) { fprintf(stderr, "%s: %d: external snapshot restore failed\n", __FILE__, __LINE__); goto err; } lxc_container_put(c2); c2 = c->clone(c, MYNAME2, NULL, LXC_CLONE_SNAPSHOT, "overlayfs", NULL, 0, NULL); if (!c2) { fprintf(stderr, "%d: %s overlayfs clone failed\n", __LINE__, MYNAME2); goto good; } if (c2->snapshot(c2, NULL) != 0) { fprintf(stderr, "%s: %d: failed to create snapshot\n", __FILE__, __LINE__); goto err; } n = c2->snapshot_list(c2, &s); if (n < 1) { fprintf(stderr, "%s: %d: failed listing containers\n", __FILE__, __LINE__); goto err; } if (strcmp(s->name, "snap0") != 0) { fprintf(stderr, "%s: %d: snapshot had bad name\n", __FILE__, __LINE__); goto err; } for (i=0; isnapshot_restore(c2, "snap0", NULL)) { fprintf(stderr, "%s: %d: failed to restore overlayfs snapshot\n", __FILE__, __LINE__); goto err; } if (!c2->snapshot_destroy(c2, "snap0")) { fprintf(stderr, "%s: %d: failed to destroy overlayfs snapshot\n", __FILE__, __LINE__); goto err; } good: lxc_container_put(c); try_to_remove(); printf("All tests passed\n"); exit(0); err: lxc_container_put(c); try_to_remove(); fprintf(stderr, "Exiting on error\n"); exit(1); } lxc-2.0.8/src/tests/lxc-test-autostart0000755061062106075000000000633513105116772014720 00000000000000#!/bin/sh # lxc: linux Container library # Authors: # Stéphane Graber # # This is a test script for lxc-autostart # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA DONE=0 KNOWN_RELEASES="precise trusty xenial yakkety zesty" cleanup() { lxc-destroy -n $CONTAINER_NAME >/dev/null 2>&1 || true if [ $DONE -eq 0 ]; then echo "FAIL" exit 1 fi echo "PASS" } ARCH=i386 if type dpkg >/dev/null 2>&1; then ARCH=$(dpkg --print-architecture) fi trap cleanup EXIT HUP INT TERM set -eu # Create a container CONTAINER_NAME=lxc-test-auto # default release is trusty, or the systems release if recognized release=trusty if [ -f /etc/lsb-release ]; then . /etc/lsb-release rels=$(ubuntu-distro-info --supported 2>/dev/null) || rels="$KNOWN_RELEASES" for r in $rels; do [ "$DISTRIB_CODENAME" = "$r" ] && release="$r" done fi lxc-create -t download -n $CONTAINER_NAME -- -d ubuntu -r $release -a $ARCH CONTAINER_PATH=$(dirname $(lxc-info -n $CONTAINER_NAME -c lxc.rootfs -H)) cp $CONTAINER_PATH/config $CONTAINER_PATH/config.bak # Ensure it's not in lxc-autostart lxc-autostart -L | grep -q $CONTAINER_NAME && \ (echo "Container shouldn't be auto-started" && exit 1) # Mark it as auto-started and re-check echo "lxc.start.auto = 1" >> $CONTAINER_PATH/config lxc-autostart -L | grep -q $CONTAINER_NAME || \ (echo "Container should be auto-started" && exit 1) # Put it in a test group and set a delay echo "lxc.group = lxc-auto-test" >> $CONTAINER_PATH/config echo "lxc.start.delay = 5" >> $CONTAINER_PATH/config # Check that everything looks good if [ "$(lxc-autostart -L -g lxc-auto-test | grep $CONTAINER_NAME)" != "$CONTAINER_NAME 5" ]; then echo "Invalid autostart setting" && exit 1 fi # Start it lxc-autostart -g lxc-auto-test lxc-wait -n $CONTAINER_NAME -t 5 -s RUNNING || (echo "Container didn't start" && exit 1) sleep 5 # Restart it lxc-autostart -g lxc-auto-test -r lxc-wait -n $CONTAINER_NAME -t 5 -s RUNNING || (echo "Container didn't restart" && exit 1) sleep 5 # When shutting down, the container calls sync. If the machine running # the test has a massive backlog, it can take minutes for the sync call to # finish, causing a test failure. # So try to reduce that by flushing everything to disk before we attempt # a container shutdown. sync # Shut it down lxc-autostart -g lxc-auto-test -s -t 120 lxc-wait -n $CONTAINER_NAME -t 120 -s STOPPED || (echo "Container didn't stop" && exit 1) # Kill it lxc-autostart -g lxc-auto-test -k lxc-wait -n $CONTAINER_NAME -t 60 -s STOPPED || (echo "Container didn't die" && exit 1) DONE=1 lxc-2.0.8/src/tests/lxc-test-ubuntu0000755061062106075000000000500513105116772014205 00000000000000#!/bin/sh # lxc-test-ubuntu: some tests of ubuntu-specific features of lxc. # Some features of lxc - networking and LSM configuration for instance - # are generally configured by the distro packages. This program # tests the Ubuntu configuration. # These require the ubuntu lxc package to be installed. # General lxc functionality testing does not belong here. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA set -e FAIL() { echo -n "Failed " >&2 echo "$*" >&2 exit 1 } # Only run on a normally configured ubuntu lxc system if [ ! -d /sys/class/net/lxcbr0 ]; then echo "lxcbr0 is not configured." exit 1 fi if [ "$(id -u)" != "0" ]; then echo "ERROR: Must run as root." exit 1 fi for template in ubuntu ubuntu-cloud; do # need a different name for each container so dnsmasq doesn't # mess us up with its caching if which uuidgen 2>&1 > /dev/null; then name=$(uuidgen) else name=lxc-test-$template fi lxc-create -t $template -n $name || FAIL "creating $template container" lxc-start -n $name -d || FAIL "starting $template container" lxc-wait -n $name -s RUNNING || FAIL "waiting for $template container to run" for tries in `seq 1 20`; do lxcip=$(lxc-info -i -n $name -H | head -n 1) [ -z "$lxcip" ] || break sleep 1 done [ -n "$lxcip" ] || FAIL "to start networking in $template container" if echo "${lxcip}" | grep -q ":"; then ping6 -c 1 $lxcip || FAIL "to ping $template container" else ping -c 1 $lxcip || FAIL "to ping $template container" fi # Check apparmor lxcpid=`lxc-info -n $name -p -H` aa=`cat /proc/$lxcpid/attr/current` if [ "$aa" != "lxc-container-default-with-nesting (enforce)" -a \ "$aa" != "lxc-container-default-cgns (enforce)" -a \ "$aa" != "lxc-container-default (enforce)" ]; then FAIL " to correctly set apparmor profile (profile is \"$aa\")" fi lxc-stop -n $name -k lxc-destroy -n $name done exit 0 lxc-2.0.8/src/tests/get_item.c0000644061062106075000000002377013105116772013146 00000000000000/* liblxcapi * * Copyright © 2012 Serge Hallyn . * Copyright © 2012 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include #include #include #include "lxc/state.h" #define MYNAME "lxctest1" int main(int argc, char *argv[]) { int ret = EXIT_FAILURE; struct lxc_container *c; char v1[2], v2[256], v3[2048]; if ((c = lxc_container_new("testxyz", NULL)) == NULL) { fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME); exit(EXIT_FAILURE); } if (!c->set_config_item(c, "lxc.hook.pre-start", "hi there")) { fprintf(stderr, "%d: failed to set hook.pre-start\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.hook.pre-start", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.hook.pre-start) returned %d\n", __LINE__, ret); goto out; } fprintf(stderr, "lxc.hook.pre-start returned %d %s\n", ret, v2); ret = c->get_config_item(c, "lxc.network", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item returned %d\n", __LINE__, ret); goto out; } fprintf(stderr, "%d: get_config_item(lxc.network) returned %d %s\n", __LINE__, ret, v2); if (!c->set_config_item(c, "lxc.tty", "4")) { fprintf(stderr, "%d: failed to set tty\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.tty", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.tty) returned %d\n", __LINE__, ret); goto out; } fprintf(stderr, "lxc.tty returned %d %s\n", ret, v2); if (!c->set_config_item(c, "lxc.arch", "x86")) { fprintf(stderr, "%d: failed to set arch\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.arch", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.arch) returned %d\n", __LINE__, ret); goto out; } printf("lxc.arch returned %d %s\n", ret, v2); if (!c->set_config_item(c, "lxc.init_uid", "100")) { fprintf(stderr, "%d: failed to set init_uid\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.init_uid", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.init_uid) returned %d\n", __LINE__, ret); goto out; } printf("lxc.init_uid returned %d %s\n", ret, v2); if (!c->set_config_item(c, "lxc.init_gid", "100")) { fprintf(stderr, "%d: failed to set init_gid\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.init_gid", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.init_gid) returned %d\n", __LINE__, ret); goto out; } printf("lxc.init_gid returned %d %s\n", ret, v2); #define HNAME "hostname1" // demonstrate proper usage: char *alloced; if (!c->set_config_item(c, "lxc.utsname", HNAME)) { fprintf(stderr, "%d: failed to set utsname\n", __LINE__); goto out; } int len; len = c->get_config_item(c, "lxc.utsname", NULL, 0); // query the size of the string if (len < 0) { fprintf(stderr, "%d: get_config_item(lxc.utsname) returned %d\n", __LINE__, len); goto out; } printf("lxc.utsname returned %d\n", len); // allocate the length of string + 1 for trailing \0 alloced = malloc(len+1); if (!alloced) { fprintf(stderr, "%d: failed to allocate %d bytes for utsname\n", __LINE__, len); goto out; } // now pass in the malloc'd array, and pass in length of string + 1: again // because we need room for the trailing \0 ret = c->get_config_item(c, "lxc.utsname", alloced, len+1); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.utsname) returned %d\n", __LINE__, ret); goto out; } if (strcmp(alloced, HNAME) != 0 || ret != len) { fprintf(stderr, "lxc.utsname returned wrong value: %d %s not %d %s\n", ret, alloced, len, HNAME); goto out; } printf("lxc.utsname returned %d %s\n", len, alloced); free(alloced); if (!c->set_config_item(c, "lxc.mount.entry", "hi there")) { fprintf(stderr, "%d: failed to set mount.entry\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.mount.entry", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.mount.entry) returned %d\n", __LINE__, ret); goto out; } printf("lxc.mount.entry returned %d %s\n", ret, v2); if (!c->set_config_item(c, "lxc.aa_profile", "unconfined")) { fprintf(stderr, "%d: failed to set aa_profile\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.aa_profile", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.aa_profile) returned %d\n", __LINE__, ret); goto out; } printf("lxc.aa_profile returned %d %s\n", ret, v2); lxc_container_put(c); // new test with real container if ((c = lxc_container_new(MYNAME, NULL)) == NULL) { fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME); goto out; } c->destroy(c); lxc_container_put(c); if ((c = lxc_container_new(MYNAME, NULL)) == NULL) { fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME); goto out; } if (!c->createl(c, "busybox", NULL, NULL, 0, NULL)) { fprintf(stderr, "%d: failed to create a trusty container\n", __LINE__); goto out; } lxc_container_put(c); /* XXX TODO load_config needs to clear out any old config first */ if ((c = lxc_container_new(MYNAME, NULL)) == NULL) { fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME); goto out; } ret = c->get_config_item(c, "lxc.cap.drop", NULL, 300); if (ret < 5 || ret > 255) { fprintf(stderr, "%d: get_config_item(lxc.cap.drop) with NULL returned %d\n", __LINE__, ret); goto out; } ret = c->get_config_item(c, "lxc.cap.drop", v1, 1); if (ret < 5 || ret > 255) { fprintf(stderr, "%d: get_config_item(lxc.cap.drop) returned %d\n", __LINE__, ret); goto out; } ret = c->get_config_item(c, "lxc.cap.drop", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.cap.drop) returned %d %s\n", __LINE__, ret, v2); goto out; } printf("%d: get_config_item(lxc.cap.drop) returned %d %s\n", __LINE__, ret, v2); ret = c->get_config_item(c, "lxc.network", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item returned %d\n", __LINE__, ret); goto out; } printf("%d: get_config_item(lxc.network) returned %d %s\n", __LINE__, ret, v2); if (!c->set_config_item(c, "lxc.network.ipv4", "10.2.3.4")) { fprintf(stderr, "%d: failed to set ipv4\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.network.0.ipv4", v2, 255); if (ret <= 0) { fprintf(stderr, "%d: lxc.network.0.ipv4 returned %d\n", __LINE__, ret); goto out; } if (!c->clear_config_item(c, "lxc.network.0.ipv4")) { fprintf(stderr, "%d: failed clearing all ipv4 entries\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.network.0.ipv4", v2, 255); if (ret != 0) { fprintf(stderr, "%d: after clearing ipv4 entries get_item(lxc.network.0.ipv4 returned %d\n", __LINE__, ret); goto out; } if (!c->set_config_item(c, "lxc.network.ipv4.gateway", "10.2.3.254")) { fprintf(stderr, "%d: failed to set ipv4.gateway\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.network.0.ipv4.gateway", v2, 255); if (ret <= 0) { fprintf(stderr, "%d: lxc.network.0.ipv4.gateway returned %d\n", __LINE__, ret); goto out; } if (!c->set_config_item(c, "lxc.network.0.ipv4.gateway", "")) { fprintf(stderr, "%d: failed clearing ipv4.gateway\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.network.0.ipv4.gateway", v2, 255); if (ret != 0) { fprintf(stderr, "%d: after clearing ipv4.gateway get_item(lxc.network.0.ipv4.gateway returned %d\n", __LINE__, ret); goto out; } ret = c->get_config_item(c, "lxc.network.0.link", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item returned %d\n", __LINE__, ret); goto out; } printf("%d: get_config_item (link) returned %d %s\n", __LINE__, ret, v2); ret = c->get_config_item(c, "lxc.network.0.name", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item returned %d\n", __LINE__, ret); goto out; } printf("%d: get_config_item (name) returned %d %s\n", __LINE__, ret, v2); if (!c->clear_config_item(c, "lxc.network")) { fprintf(stderr, "%d: clear_config_item failed\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.network", v2, 255); if (ret != 0) { fprintf(stderr, "%d: network was not actually cleared (get_network returned %d)\n", __LINE__, ret); goto out; } ret = c->get_config_item(c, "lxc.cgroup", v3, 2047); if (ret < 0) { fprintf(stderr, "%d: get_config_item(cgroup.devices) returned %d\n", __LINE__, ret); goto out; } printf("%d: get_config_item (cgroup.devices) returned %d %s\n", __LINE__, ret, v3); ret = c->get_config_item(c, "lxc.cgroup.devices.allow", v3, 2047); if (ret < 0) { fprintf(stderr, "%d: get_config_item(cgroup.devices.devices.allow) returned %d\n", __LINE__, ret); goto out; } printf("%d: get_config_item (cgroup.devices.devices.allow) returned %d %s\n", __LINE__, ret, v3); if (!c->clear_config_item(c, "lxc.cgroup")) { fprintf(stderr, "%d: failed clearing lxc.cgroup\n", __LINE__); goto out; } if (!c->clear_config_item(c, "lxc.cap.drop")) { fprintf(stderr, "%d: failed clearing lxc.cap.drop\n", __LINE__); goto out; } if (!c->clear_config_item(c, "lxc.mount.entry")) { fprintf(stderr, "%d: failed clearing lxc.mount.entry\n", __LINE__); goto out; } if (!c->clear_config_item(c, "lxc.hook")) { fprintf(stderr, "%d: failed clearing lxc.hook\n", __LINE__); goto out; } printf("All get_item tests passed\n"); ret = EXIT_SUCCESS; out: c->destroy(c); lxc_container_put(c); exit(ret); } lxc-2.0.8/src/tests/locktests.c0000644061062106075000000000625313105116772013361 00000000000000/* liblxcapi * * Copyright © 2012 Serge Hallyn . * Copyright © 2012 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "lxc/lxclock.h" #include "config.h" #include #include #include #include #include #include #define mycontainername "lxctest.sem" #define TIMEOUT_SECS 3 static void test_two_locks(void) { struct lxc_lock *l; pid_t pid; int ret, status; int p[2]; char c; if (pipe(p) < 0) exit(1); if ((pid = fork()) < 0) exit(1); if (pid == 0) { if (read(p[0], &c, 1) < 0) { perror("read"); exit(1); } l = lxc_newlock("/tmp", "lxctest-sem"); if (!l) { fprintf(stderr, "%d: child: failed to create lock\n", __LINE__); exit(1); } if (lxclock(l, 0) < 0) { fprintf(stderr, "%d: child: failed to grab lock\n", __LINE__); exit(1); } fprintf(stderr, "%d: child: grabbed lock\n", __LINE__); exit(0); } l = lxc_newlock("/tmp", "lxctest-sem"); if (!l) { fprintf(stderr, "%d: failed to create lock\n", __LINE__); exit(1); } if (lxclock(l, 0) < 0) { fprintf(stderr, "%d; failed to get lock\n", __LINE__); exit(1); } if (write(p[1], "a", 1) < 0) { perror("write"); exit(1); } sleep(3); ret = waitpid(pid, &status, WNOHANG); if (ret == pid) { // task exited if (WIFEXITED(status)) { printf("%d exited normally with exit code %d\n", pid, WEXITSTATUS(status)); if (WEXITSTATUS(status) == 0) exit(1); } else printf("%d did not exit normally\n", pid); return; } else if (ret < 0) { perror("waitpid"); exit(1); } kill(pid, SIGKILL); wait(&status); close(p[1]); close(p[0]); lxcunlock(l); lxc_putlock(l); } int main(int argc, char *argv[]) { int ret; struct lxc_lock *lock; lock = lxc_newlock(NULL, NULL); if (!lock) { fprintf(stderr, "%d: failed to get unnamed lock\n", __LINE__); exit(1); } ret = lxclock(lock, 0); if (ret) { fprintf(stderr, "%d: failed to take unnamed lock (%d)\n", __LINE__, ret); exit(1); } ret = lxcunlock(lock); if (ret) { fprintf(stderr, "%d: failed to put unnamed lock (%d)\n", __LINE__, ret); exit(1); } lxc_putlock(lock); lock = lxc_newlock("/var/lib/lxc", mycontainername); if (!lock) { fprintf(stderr, "%d: failed to get lock\n", __LINE__); exit(1); } struct stat sb; char *pathname = RUNTIME_PATH "/lxc/lock/var/lib/lxc/"; ret = stat(pathname, &sb); if (ret != 0) { fprintf(stderr, "%d: filename %s not created\n", __LINE__, pathname); exit(1); } lxc_putlock(lock); test_two_locks(); fprintf(stderr, "all tests passed\n"); exit(ret); } lxc-2.0.8/src/tests/list.c0000644061062106075000000000515513105116772012321 00000000000000/* list.c * * Copyright © 2013 Canonical, Inc * Author: Serge Hallyn * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include static void test_list_func(const char *lxcpath, const char *type, int (*func)(const char *path, char ***names, struct lxc_container ***cret)) { int i, n, n2; struct lxc_container **clist; char **names; printf("%-10s Counting containers\n", type); n = func(lxcpath, NULL, NULL); printf("%-10s Counted %d containers\n", type, n); printf("%-10s Get container struct only\n", type); n2 = func(lxcpath, NULL, &clist); if (n2 != n) printf("Warning: first call returned %d, second %d\n", n, n2); for (i = 0; i < n2; i++) { struct lxc_container *c = clist[i]; printf("%-10s Got container struct %s\n", type, c->name); lxc_container_put(c); } if (n2 > 0) { free(clist); clist = NULL; } printf("%-10s Get names only\n", type); n2 = func(lxcpath, &names, NULL); if (n2 != n) printf("Warning: first call returned %d, second %d\n", n, n2); for (i = 0; i < n2; i++) { printf("%-10s Got container name %s\n", type, names[i]); free(names[i]); } if (n2 > 0) { free(names); names = NULL; } printf("%-10s Get names and containers\n", type); n2 = func(lxcpath, &names, &clist); if (n2 != n) printf("Warning: first call returned %d, second %d\n", n, n2); for (i = 0; i < n2; i++) { struct lxc_container *c = clist[i]; printf("%-10s Got container struct %s, name %s\n", type, c->name, names[i]); if (strcmp(c->name, names[i])) fprintf(stderr, "ERROR: name mismatch!\n"); free(names[i]); lxc_container_put(c); } if (n2 > 0) { free(names); free(clist); } } int main(int argc, char *argv[]) { const char *lxcpath = NULL; if (argc > 1) lxcpath = argv[1]; test_list_func(lxcpath, "Defined:", list_defined_containers); test_list_func(lxcpath, "Active:", list_active_containers); test_list_func(lxcpath, "All:", list_all_containers); exit(0); } lxc-2.0.8/src/tests/shutdowntest.c0000644061062106075000000000514513105116772014120 00000000000000 /* liblxcapi * * Copyright © 2012 Serge Hallyn . * Copyright © 2012 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include #include #define MYNAME "lxctest1" int main(int argc, char *argv[]) { struct lxc_container *c; int ret = 1; if ((c = lxc_container_new(MYNAME, NULL)) == NULL) { fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME); ret = 1; goto out; } if (c->is_defined(c)) { fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME); goto out; } if (!c->set_config_item(c, "lxc.network.type", "veth")) { fprintf(stderr, "%d: failed to set network type\n", __LINE__); goto out; } c->set_config_item(c, "lxc.network.link", "lxcbr0"); c->set_config_item(c, "lxc.network.flags", "up"); if (!c->createl(c, "busybox", NULL, NULL, 0, NULL)) { fprintf(stderr, "%d: failed to create a container\n", __LINE__); goto out; } if (!c->is_defined(c)) { fprintf(stderr, "%d: %s thought it was not defined\n", __LINE__, MYNAME); goto out; } c->clear_config(c); c->load_config(c, NULL); c->want_daemonize(c, true); if (!c->startl(c, 0, NULL)) { fprintf(stderr, "%d: failed to start %s\n", __LINE__, MYNAME); goto out; } /* Wait for init to be ready for SIGPWR */ sleep(20); if (!c->shutdown(c, 120)) { fprintf(stderr, "%d: failed to shut down %s\n", __LINE__, MYNAME); if (!c->stop(c)) { fprintf(stderr, "%d: failed to kill %s\n", __LINE__, MYNAME); } goto out; } if (!c->destroy(c)) { fprintf(stderr, "%d: error deleting %s\n", __LINE__, MYNAME); goto out; } if (c->is_defined(c)) { fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME); goto out; } fprintf(stderr, "all lxc_container tests passed for %s\n", c->name); ret = 0; out: if (c && c->is_defined(c)) { c->destroy(c); } lxc_container_put(c); exit(ret); } lxc-2.0.8/src/Makefile.am0000644061062106075000000000004713105116772012067 00000000000000SUBDIRS = lxc tests python-lxc lua-lxc lxc-2.0.8/src/Makefile.in0000644061062106075000000005131513105116776012110 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/acinclude.m4 \ $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/tls.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ $(LISP)config.h.in # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APPARMOR_LIBS = @APPARMOR_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BINDIR = @BINDIR@ CAP_LIBS = @CAP_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CGMANAGER_CFLAGS = @CGMANAGER_CFLAGS@ CGMANAGER_LIBS = @CGMANAGER_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIR = @DATADIR@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFAULT_CGROUP_PATTERN = @DEFAULT_CGROUP_PATTERN@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOCDIR = @DOCDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ HAVE_DOXYGEN = @HAVE_DOXYGEN@ INCLUDEDIR = @INCLUDEDIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBDIR = @LIBDIR@ LIBEXECDIR = @LIBEXECDIR@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCALSTATEDIR = @LOCALSTATEDIR@ LOGPATH = @LOGPATH@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBDIR = @LUA_LIBDIR@ LUA_LIBS = @LUA_LIBS@ LUA_SHAREDIR = @LUA_SHAREDIR@ LUA_VERSION = @LUA_VERSION@ LXCBINHOOKDIR = @LXCBINHOOKDIR@ LXCHOOKDIR = @LXCHOOKDIR@ LXCINITDIR = @LXCINITDIR@ LXCPATH = @LXCPATH@ LXCROOTFSMOUNT = @LXCROOTFSMOUNT@ LXCTEMPLATECONFIG = @LXCTEMPLATECONFIG@ LXCTEMPLATEDIR = @LXCTEMPLATEDIR@ LXC_ABI = @LXC_ABI@ LXC_ABI_MAJOR = @LXC_ABI_MAJOR@ LXC_ABI_MICRO = @LXC_ABI_MICRO@ LXC_ABI_MINOR = @LXC_ABI_MINOR@ LXC_DEFAULT_CONFIG = @LXC_DEFAULT_CONFIG@ LXC_DEVEL = @LXC_DEVEL@ LXC_DISTRO_SYSCONF = @LXC_DISTRO_SYSCONF@ LXC_GENERATE_DATE = @LXC_GENERATE_DATE@ LXC_GLOBAL_CONF = @LXC_GLOBAL_CONF@ LXC_USERNIC_CONF = @LXC_USERNIC_CONF@ LXC_USERNIC_DB = @LXC_USERNIC_DB@ LXC_VERSION = @LXC_VERSION@ LXC_VERSION_BASE = @LXC_VERSION_BASE@ LXC_VERSION_BETA = @LXC_VERSION_BETA@ LXC_VERSION_MAJOR = @LXC_VERSION_MAJOR@ LXC_VERSION_MICRO = @LXC_VERSION_MICRO@ LXC_VERSION_MINOR = @LXC_VERSION_MINOR@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NIH_CFLAGS = @NIH_CFLAGS@ NIH_DBUS_CFLAGS = @NIH_DBUS_CFLAGS@ NIH_DBUS_LIBS = @NIH_DBUS_LIBS@ NIH_LIBS = @NIH_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PREFIX = @PREFIX@ PYTHON = @PYTHON@ PYTHONDEV_CFLAGS = @PYTHONDEV_CFLAGS@ PYTHONDEV_LIBS = @PYTHONDEV_LIBS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RUNTIME_PATH = @RUNTIME_PATH@ SBINDIR = @SBINDIR@ SECCOMP_CFLAGS = @SECCOMP_CFLAGS@ SECCOMP_LIBS = @SECCOMP_LIBS@ SED = @SED@ SELINUX_LIBS = @SELINUX_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SYSCONFDIR = @SYSCONFDIR@ SYSTEMD_UNIT_DIR = @SYSTEMD_UNIT_DIR@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bashcompdir = @bashcompdir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ db2xman = @db2xman@ docdir = @docdir@ docdtd = @docdtd@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = lxc tests python-lxc lua-lxc all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): config.h: stamp-h1 @test -f $@ || rm -f stamp-h1 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status src/config.h $(srcdir)/config.h.in: $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile config.h installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-hdr distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) all install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-generic distclean-hdr \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: lxc-2.0.8/src/include/0000755061062106075000000000000013105117015011524 500000000000000lxc-2.0.8/src/include/lxcmntent.h0000644061062106075000000000306413105116772013645 00000000000000/* Utilities for reading/writing fstab, mtab, etc. Copyright (C) 1995-2000, 2001, 2002, 2003, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _lxcmntent_h #define _lxcmntent_h #if IS_BIONIC struct mntent { char* mnt_fsname; char* mnt_dir; char* mnt_type; char* mnt_opts; int mnt_freq; int mnt_passno; }; extern struct mntent *getmntent (FILE *stream); extern struct mntent *getmntent_r (FILE *stream, struct mntent *mp, char *buffer, int bufsiz); #endif #if !defined(HAVE_SETMNTENT) || IS_BIONIC FILE *setmntent (const char *file, const char *mode); #endif #if !defined(HAVE_ENDMNTENT) || IS_BIONIC int endmntent (FILE *stream); #endif #if !defined(HAVE_HASMNTOPT) || IS_BIONIC extern char *hasmntopt (const struct mntent *mnt, const char *opt); #endif #endif lxc-2.0.8/src/include/openpty.c0000644061062106075000000000366413105116772013330 00000000000000 /* * openpty: glibc implementation * * Copyright (C) 1998, 1999, 2004 Free Software Foundation, Inc. * * Authors: * Zack Weinberg , 1998. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _XOPEN_SOURCE /* See feature_test_macros(7) */ #include #include #include #include #include #include #include #include #include #define _PATH_DEVPTMX "/dev/ptmx" int openpty (int *amaster, int *aslave, char *name, struct termios *termp, struct winsize *winp) { char buf[PATH_MAX]; int master, slave; master = open(_PATH_DEVPTMX, O_RDWR); if (master == -1) return -1; if (grantpt(master)) goto fail; if (unlockpt(master)) goto fail; if (ptsname_r(master, buf, sizeof buf)) goto fail; slave = open(buf, O_RDWR | O_NOCTTY); if (slave == -1) goto fail; /* XXX Should we ignore errors here? */ if (termp) tcsetattr(slave, TCSAFLUSH, termp); if (winp) ioctl(slave, TIOCSWINSZ, winp); *amaster = master; *aslave = slave; if (name != NULL) strcpy(name, buf); return 0; fail: close(master); return -1; } lxc-2.0.8/src/include/getsubopt.c0000644061062106075000000000515513105116772013643 00000000000000/* * Android c-library does not have getsubopt, * so code lifted from uClibc * http://git.uclibc.org/uClibc/tree/libc/unistd/getsubopt.c */ /* Parse comma separate list into words. Copyright (C) 1996, 1997, 1999, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1996. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include #include char *strchrnul(const char *s, int c) { char *result; result = strchr( s, c ); if( !result ) { result = (char *)s + strlen( s ); } return( result ); } /* Parse comma separated suboption from *OPTIONP and match against strings in TOKENS. If found return index and set *VALUEP to optional value introduced by an equal sign. If the suboption is not part of TOKENS return in *VALUEP beginning of unknown suboption. On exit *OPTIONP is set to the beginning of the next token or at the terminating NUL character. */ int getsubopt (char **optionp, char *const *tokens, char **valuep) { char *endp, *vstart; int cnt; if (**optionp == '\0') return -1; /* Find end of next token. */ endp = strchrnul (*optionp, ','); /* Find start of value. */ vstart = memchr (*optionp, '=', endp - *optionp); if (vstart == NULL) vstart = endp; /* Try to match the characters between *OPTIONP and VSTART against one of the TOKENS. */ for (cnt = 0; tokens[cnt] != NULL; ++cnt) if (strncmp (*optionp, tokens[cnt], vstart - *optionp) == 0 && tokens[cnt][vstart - *optionp] == '\0') { /* We found the current option in TOKENS. */ *valuep = vstart != endp ? vstart + 1 : NULL; if (*endp != '\0') *endp++ = '\0'; *optionp = endp; return cnt; } /* The current suboption does not match any option. */ *valuep = *optionp; if (*endp != '\0') *endp++ = '\0'; *optionp = endp; return -1; } lxc-2.0.8/src/include/getline.c0000644061062106075000000000415213105116772013252 00000000000000/* * Copyright (c) 2006 SPARTA, Inc. * All rights reserved. * * This software was developed by SPARTA ISSO under SPAWAR contract * N66001-04-C-6019 ("SEFOS"). * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include /* * Emulate glibc getline() via BSD fgetln(). * Note that outsize is not changed unless memory is allocated. */ ssize_t getline(char **outbuf, size_t *outsize, FILE *fp) { size_t len; char *buf; buf = fgetln(fp, &len); if (buf == NULL) return (-1); /* Assumes realloc() accepts NULL for ptr (C99) */ if (*outbuf == NULL || *outsize < len + 1) { void *tmp = realloc(*outbuf, len + 1); if (tmp == NULL) return (-1); *outbuf = tmp; *outsize = len + 1; } memcpy(*outbuf, buf, len); (*outbuf)[len] = '\0'; return (len); } lxc-2.0.8/src/include/ifaddrs.c0000644061062106075000000004373513105116772013251 00000000000000/* Copyright (c) 2013, Kenneth MacKay All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "ifaddrs.h" #include #include #include #include #include #include #include #include #include typedef struct NetlinkList { struct NetlinkList *m_next; struct nlmsghdr *m_data; unsigned int m_size; } NetlinkList; static int netlink_socket(void) { int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if(l_socket < 0) { return -1; } struct sockaddr_nl l_addr; memset(&l_addr, 0, sizeof(l_addr)); l_addr.nl_family = AF_NETLINK; if(bind(l_socket, (struct sockaddr *)&l_addr, sizeof(l_addr)) < 0) { close(l_socket); return -1; } return l_socket; } static int netlink_send(int p_socket, int p_request) { char l_buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))]; memset(l_buffer, 0, sizeof(l_buffer)); struct nlmsghdr *l_hdr = (struct nlmsghdr *)l_buffer; struct rtgenmsg *l_msg = (struct rtgenmsg *)NLMSG_DATA(l_hdr); l_hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*l_msg)); l_hdr->nlmsg_type = p_request; l_hdr->nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; l_hdr->nlmsg_pid = 0; l_hdr->nlmsg_seq = p_socket; l_msg->rtgen_family = AF_UNSPEC; struct sockaddr_nl l_addr; memset(&l_addr, 0, sizeof(l_addr)); l_addr.nl_family = AF_NETLINK; return (sendto(p_socket, l_hdr, l_hdr->nlmsg_len, 0, (struct sockaddr *)&l_addr, sizeof(l_addr))); } static int netlink_recv(int p_socket, void *p_buffer, size_t p_len) { struct msghdr l_msg; struct iovec l_iov = { p_buffer, p_len }; struct sockaddr_nl l_addr; for(;;) { l_msg.msg_name = (void *)&l_addr; l_msg.msg_namelen = sizeof(l_addr); l_msg.msg_iov = &l_iov; l_msg.msg_iovlen = 1; l_msg.msg_control = NULL; l_msg.msg_controllen = 0; l_msg.msg_flags = 0; int l_result = recvmsg(p_socket, &l_msg, 0); if(l_result < 0) { if(errno == EINTR) { continue; } return -2; } if(l_msg.msg_flags & MSG_TRUNC) { // buffer was too small return -1; } return l_result; } } static struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int *p_done) { size_t l_size = 4096; void *l_buffer = NULL; for(;;) { free(l_buffer); l_buffer = malloc(l_size); int l_read = netlink_recv(p_socket, l_buffer, l_size); *p_size = l_read; if(l_read == -2) { free(l_buffer); return NULL; } if(l_read >= 0) { pid_t l_pid = getpid(); struct nlmsghdr *l_hdr; for(l_hdr = (struct nlmsghdr *)l_buffer; NLMSG_OK(l_hdr, (unsigned int)l_read); l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read)) { if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) { continue; } if(l_hdr->nlmsg_type == NLMSG_DONE) { *p_done = 1; break; } if(l_hdr->nlmsg_type == NLMSG_ERROR) { free(l_buffer); return NULL; } } return l_buffer; } l_size *= 2; } } static NetlinkList *newListItem(struct nlmsghdr *p_data, unsigned int p_size) { NetlinkList *l_item = malloc(sizeof(NetlinkList)); l_item->m_next = NULL; l_item->m_data = p_data; l_item->m_size = p_size; return l_item; } static void freeResultList(NetlinkList *p_list) { NetlinkList *l_cur; while(p_list) { l_cur = p_list; p_list = p_list->m_next; free(l_cur->m_data); free(l_cur); } } static NetlinkList *getResultList(int p_socket, int p_request) { if(netlink_send(p_socket, p_request) < 0) { return NULL; } NetlinkList *l_list = NULL; NetlinkList *l_end = NULL; int l_size; int l_done = 0; while(!l_done) { struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, &l_size, &l_done); if(!l_hdr) { // error freeResultList(l_list); return NULL; } NetlinkList *l_item = newListItem(l_hdr, l_size); if(!l_list) { l_list = l_item; } else { l_end->m_next = l_item; } l_end = l_item; } return l_list; } static size_t maxSize(size_t a, size_t b) { return (a > b ? a : b); } static size_t calcAddrLen(sa_family_t p_family, int p_dataSize) { switch(p_family) { case AF_INET: return sizeof(struct sockaddr_in); case AF_INET6: return sizeof(struct sockaddr_in6); case AF_PACKET: return maxSize(sizeof(struct sockaddr_ll), offsetof(struct sockaddr_ll, sll_addr) + p_dataSize); default: return maxSize(sizeof(struct sockaddr), offsetof(struct sockaddr, sa_data) + p_dataSize); } } static void makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void *p_data, size_t p_size) { switch(p_family) { case AF_INET: memcpy(&((struct sockaddr_in*)p_dest)->sin_addr, p_data, p_size); break; case AF_INET6: memcpy(&((struct sockaddr_in6*)p_dest)->sin6_addr, p_data, p_size); break; case AF_PACKET: memcpy(((struct sockaddr_ll*)p_dest)->sll_addr, p_data, p_size); ((struct sockaddr_ll*)p_dest)->sll_halen = p_size; break; default: memcpy(p_dest->sa_data, p_data, p_size); break; } p_dest->sa_family = p_family; } static void addToEnd(struct ifaddrs **p_resultList, struct ifaddrs *p_entry) { if(!*p_resultList) { *p_resultList = p_entry; } else { struct ifaddrs *l_cur = *p_resultList; while(l_cur->ifa_next) { l_cur = l_cur->ifa_next; } l_cur->ifa_next = p_entry; } } static void interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_links, struct ifaddrs **p_resultList) { struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(p_hdr); size_t l_nameSize = 0; size_t l_addrSize = 0; size_t l_dataSize = 0; size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg)); struct rtattr *l_rta; for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifinfomsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) { size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); switch(l_rta->rta_type) { case IFLA_ADDRESS: case IFLA_BROADCAST: l_addrSize += NLMSG_ALIGN(calcAddrLen(AF_PACKET, l_rtaDataSize)); break; case IFLA_IFNAME: l_nameSize += NLMSG_ALIGN(l_rtaSize + 1); break; case IFLA_STATS: l_dataSize += NLMSG_ALIGN(l_rtaSize); break; default: break; } } struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize + l_dataSize); memset(l_entry, 0, sizeof(struct ifaddrs)); l_entry->ifa_name = ""; char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs); char *l_addr = l_name + l_nameSize; char *l_data = l_addr + l_addrSize; l_entry->ifa_flags = l_info->ifi_flags; l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg)); for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifinfomsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) { void *l_rtaData = RTA_DATA(l_rta); size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); switch(l_rta->rta_type) { case IFLA_ADDRESS: case IFLA_BROADCAST: { size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize); makeSockaddr(AF_PACKET, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize); ((struct sockaddr_ll *)l_addr)->sll_ifindex = l_info->ifi_index; ((struct sockaddr_ll *)l_addr)->sll_hatype = l_info->ifi_type; if(l_rta->rta_type == IFLA_ADDRESS) { l_entry->ifa_addr = (struct sockaddr *)l_addr; } else { l_entry->ifa_broadaddr = (struct sockaddr *)l_addr; } l_addr += NLMSG_ALIGN(l_addrLen); break; } case IFLA_IFNAME: strncpy(l_name, l_rtaData, l_rtaDataSize); l_name[l_rtaDataSize] = '\0'; l_entry->ifa_name = l_name; break; case IFLA_STATS: memcpy(l_data, l_rtaData, l_rtaDataSize); l_entry->ifa_data = l_data; break; default: break; } } addToEnd(p_resultList, l_entry); p_links[l_info->ifi_index - 1] = l_entry; } static void interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_links, struct ifaddrs **p_resultList) { struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr); size_t l_nameSize = 0; size_t l_addrSize = 0; int l_addedNetmask = 0; size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg)); struct rtattr *l_rta; for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) { size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); if(l_info->ifa_family == AF_PACKET) { continue; } switch(l_rta->rta_type) { case IFA_ADDRESS: case IFA_LOCAL: if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask) { // make room for netmask l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize)); l_addedNetmask = 1; } case IFA_BROADCAST: l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize)); break; case IFA_LABEL: l_nameSize += NLMSG_ALIGN(l_rtaSize + 1); break; default: break; } } struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize); memset(l_entry, 0, sizeof(struct ifaddrs)); l_entry->ifa_name = p_links[l_info->ifa_index - 1]->ifa_name; char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs); char *l_addr = l_name + l_nameSize; l_entry->ifa_flags = l_info->ifa_flags | p_links[l_info->ifa_index - 1]->ifa_flags; l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg)); for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) { void *l_rtaData = RTA_DATA(l_rta); size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); switch(l_rta->rta_type) { case IFA_ADDRESS: case IFA_BROADCAST: case IFA_LOCAL: { size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize); makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize); if(l_info->ifa_family == AF_INET6) { if(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)l_rtaData) || IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr *)l_rtaData)) { ((struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index; } } if(l_rta->rta_type == IFA_ADDRESS) { // apparently in a point-to-point network IFA_ADDRESS contains the dest address and IFA_LOCAL contains the local address if(l_entry->ifa_addr) { l_entry->ifa_dstaddr = (struct sockaddr *)l_addr; } else { l_entry->ifa_addr = (struct sockaddr *)l_addr; } } else if(l_rta->rta_type == IFA_LOCAL) { if(l_entry->ifa_addr) { l_entry->ifa_dstaddr = l_entry->ifa_addr; } l_entry->ifa_addr = (struct sockaddr *)l_addr; } else { l_entry->ifa_broadaddr = (struct sockaddr *)l_addr; } l_addr += NLMSG_ALIGN(l_addrLen); break; } case IFA_LABEL: strncpy(l_name, l_rtaData, l_rtaDataSize); l_name[l_rtaDataSize] = '\0'; l_entry->ifa_name = l_name; break; default: break; } } if(l_entry->ifa_addr && (l_entry->ifa_addr->sa_family == AF_INET || l_entry->ifa_addr->sa_family == AF_INET6)) { unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128); unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen); char l_mask[16] = {0}; unsigned i; for(i=0; i<(l_prefix/8); ++i) { l_mask[i] = 0xff; } if (l_prefix % 8) { l_mask[i] = 0xff << (8 - (l_prefix % 8)); } makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr *)l_addr, l_mask, l_maxPrefix / 8); l_entry->ifa_netmask = (struct sockaddr *)l_addr; } addToEnd(p_resultList, l_entry); } static void interpret(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_links, struct ifaddrs **p_resultList) { pid_t l_pid = getpid(); for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next) { unsigned int l_nlsize = p_netlinkList->m_size; struct nlmsghdr *l_hdr; for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize)) { if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) { continue; } if(l_hdr->nlmsg_type == NLMSG_DONE) { break; } if(l_hdr->nlmsg_type == RTM_NEWLINK) { interpretLink(l_hdr, p_links, p_resultList); } else if(l_hdr->nlmsg_type == RTM_NEWADDR) { interpretAddr(l_hdr, p_links, p_resultList); } } } } static unsigned countLinks(int p_socket, NetlinkList *p_netlinkList) { unsigned l_links = 0; pid_t l_pid = getpid(); for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next) { unsigned int l_nlsize = p_netlinkList->m_size; struct nlmsghdr *l_hdr; for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize)) { if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) { continue; } if(l_hdr->nlmsg_type == NLMSG_DONE) { break; } if(l_hdr->nlmsg_type == RTM_NEWLINK) { ++l_links; } } } return l_links; } int getifaddrs(struct ifaddrs **ifap) { if(!ifap) { return -1; } *ifap = NULL; int l_socket = netlink_socket(); if(l_socket < 0) { return -1; } NetlinkList *l_linkResults = getResultList(l_socket, RTM_GETLINK); if(!l_linkResults) { close(l_socket); return -1; } NetlinkList *l_addrResults = getResultList(l_socket, RTM_GETADDR); if(!l_addrResults) { close(l_socket); freeResultList(l_linkResults); return -1; } unsigned l_numLinks = countLinks(l_socket, l_linkResults) + countLinks(l_socket, l_addrResults); struct ifaddrs *l_links[l_numLinks]; memset(l_links, 0, l_numLinks * sizeof(struct ifaddrs *)); interpret(l_socket, l_linkResults, l_links, ifap); interpret(l_socket, l_addrResults, l_links, ifap); freeResultList(l_linkResults); freeResultList(l_addrResults); close(l_socket); return 0; } void freeifaddrs(struct ifaddrs *ifa) { struct ifaddrs *l_cur; while(ifa) { l_cur = ifa; ifa = ifa->ifa_next; free(l_cur); } } lxc-2.0.8/src/include/getline.h0000644061062106075000000000306513105116772013261 00000000000000/* * Copyright (c) 2006 SPARTA, Inc. * All rights reserved. * * This software was developed by SPARTA ISSO under SPAWAR contract * N66001-04-C-6019 ("SEFOS"). * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef _getline_h #define _getline_h #include extern ssize_t getline(char **outbuf, size_t *outsize, FILE *fp); #endif lxc-2.0.8/src/include/openpty.h0000644061062106075000000000246313105116772013331 00000000000000/* * openpty: glibc implementation * * Copyright (C) 1998, 1999, 2004 Free Software Foundation, Inc. * * Authors: * Zack Weinberg , 1998. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _openpty_h #define _openpty_h #include #include /* Create pseudo tty master slave pair with NAME and set terminal attributes according to TERMP and WINP and return handles for both ends in AMASTER and ASLAVE. */ extern int openpty (int *__amaster, int *__aslave, char *__name, const struct termios *__termp, const struct winsize *__winp); #endif lxc-2.0.8/src/include/getsubopt.h0000644061062106075000000000016513105116772013644 00000000000000#ifndef _getsubopt_h #define _getsubopt_h int getsubopt (char **optionp, char *const *tokens, char **valuep); #endif lxc-2.0.8/src/include/lxcmntent.c0000644061062106075000000001263613105116772013645 00000000000000/* Utilities for reading/writing fstab, mtab, etc. Copyright (C) 1995-2000, 2001, 2002, 2003, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include /* Since the values in a line are separated by spaces, a name cannot contain a space. Therefore some programs encode spaces in names by the strings "\040". We undo the encoding when reading an entry. The decoding happens in place. */ static char * decode_name (char *buf) { char *rp = buf; char *wp = buf; do if (rp[0] == '\\' && rp[1] == '0' && rp[2] == '4' && rp[3] == '0') { /* \040 is a SPACE. */ *wp++ = ' '; rp += 3; } else if (rp[0] == '\\' && rp[1] == '0' && rp[2] == '1' && rp[3] == '1') { /* \011 is a TAB. */ *wp++ = '\t'; rp += 3; } else if (rp[0] == '\\' && rp[1] == '0' && rp[2] == '1' && rp[3] == '2') { /* \012 is a NEWLINE. */ *wp++ = '\n'; rp += 3; } else if (rp[0] == '\\' && rp[1] == '\\') { /* We have to escape \\ to be able to represent all characters. */ *wp++ = '\\'; rp += 1; } else if (rp[0] == '\\' && rp[1] == '1' && rp[2] == '3' && rp[3] == '4') { /* \134 is also \\. */ *wp++ = '\\'; rp += 3; } else *wp++ = *rp; while (*rp++ != '\0'); return buf; } /* Read one mount table entry from STREAM. Returns a pointer to storage reused on the next call, or null for EOF or error (use feof/ferror to check). */ struct mntent *getmntent_r (FILE *stream, struct mntent *mp, char *buffer, int bufsiz) { char *cp; char *head; do { char *end_ptr; if (fgets (buffer, bufsiz, stream) == NULL) { return NULL; } end_ptr = strchr (buffer, '\n'); if (end_ptr != NULL) /* chop newline */ *end_ptr = '\0'; else { /* Not the whole line was read. Do it now but forget it. */ char tmp[1024]; while (fgets (tmp, sizeof tmp, stream) != NULL) if (strchr (tmp, '\n') != NULL) break; } head = buffer + strspn (buffer, " \t"); /* skip empty lines and comment lines: */ } while (head[0] == '\0' || head[0] == '#'); cp = strsep (&head, " \t"); mp->mnt_fsname = cp != NULL ? decode_name (cp) : (char *) ""; if (head) head += strspn (head, " \t"); cp = strsep (&head, " \t"); mp->mnt_dir = cp != NULL ? decode_name (cp) : (char *) ""; if (head) head += strspn (head, " \t"); cp = strsep (&head, " \t"); mp->mnt_type = cp != NULL ? decode_name (cp) : (char *) ""; if (head) head += strspn (head, " \t"); cp = strsep (&head, " \t"); mp->mnt_opts = cp != NULL ? decode_name (cp) : (char *) ""; switch (head ? sscanf (head, " %d %d ", &mp->mnt_freq, &mp->mnt_passno) : 0) { case 0: mp->mnt_freq = 0; case 1: mp->mnt_passno = 0; case 2: break; } return mp; } struct mntent *getmntent (FILE *stream) { static struct mntent m; static char *getmntent_buffer; #define BUFFER_SIZE 4096 if (getmntent_buffer == NULL) { getmntent_buffer = (char *) malloc (BUFFER_SIZE); } return getmntent_r (stream, &m, getmntent_buffer, BUFFER_SIZE); #undef BUFFER_SIZE } /* Prepare to begin reading and/or writing mount table entries from the beginning of FILE. MODE is as for `fopen'. */ FILE *setmntent (const char *file, const char *mode) { /* Extend the mode parameter with "c" to disable cancellation in the I/O functions and "e" to set FD_CLOEXEC. */ size_t modelen = strlen (mode); char newmode[modelen + 3]; memcpy (newmode, mode, modelen); memcpy (newmode + modelen, "ce", 3); FILE *result = fopen (file, newmode); return result; } /* Close a stream opened with `setmntent'. */ int endmntent (FILE *stream) { if (stream) /* SunOS 4.x allows for NULL stream */ fclose (stream); return 1; /* SunOS 4.x says to always return 1 */ } /* Search MNT->mnt_opts for an option matching OPT. Returns the address of the substring, or null if none found. */ char *hasmntopt (const struct mntent *mnt, const char *opt) { const size_t optlen = strlen (opt); char *rest = mnt->mnt_opts, *p; while ((p = strstr (rest, opt)) != NULL) { if ((p == rest || p[-1] == ',') && (p[optlen] == '\0' || p[optlen] == '=' || p[optlen] == ',')) return p; rest = strchr (p, ','); if (rest == NULL) break; ++rest; } return NULL; } lxc-2.0.8/src/include/ifaddrs.h0000644061062106075000000000347513105116772013253 00000000000000/* * Copyright (c) 1995, 1999 * Berkeley Software Design, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp */ #ifndef _IFADDRS_H_ #define _IFADDRS_H_ struct ifaddrs { struct ifaddrs *ifa_next; char *ifa_name; unsigned int ifa_flags; struct sockaddr *ifa_addr; struct sockaddr *ifa_netmask; struct sockaddr *ifa_dstaddr; void *ifa_data; }; /* * This may have been defined in . Note that if is * to be included it must be included before this header file. */ #ifndef ifa_broadaddr #define ifa_broadaddr ifa_dstaddr /* broadcast address interface */ #endif #include __BEGIN_DECLS extern int getifaddrs(struct ifaddrs **ifap); extern void freeifaddrs(struct ifaddrs *ifa); __END_DECLS #endif lxc-2.0.8/src/lxc/0000755061062106075000000000000013105117015010667 500000000000000lxc-2.0.8/src/lxc/cgroups/0000755061062106075000000000000013105117015012351 500000000000000lxc-2.0.8/src/lxc/cgroups/cgroup.c0000644061062106075000000001252513105116772013752 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include "cgroup.h" #include "conf.h" #include "log.h" #include "start.h" lxc_log_define(lxc_cgroup, lxc); static struct cgroup_ops *ops = NULL; extern struct cgroup_ops *cgfs_ops_init(void); extern struct cgroup_ops *cgfsng_ops_init(void); extern struct cgroup_ops *cgm_ops_init(void); __attribute__((constructor)) void cgroup_ops_init(void) { if (ops) { INFO("cgroup driver %s", ops->name); return; } DEBUG("cgroup_init"); #if HAVE_CGMANAGER ops = cgm_ops_init(); #endif if (!ops) ops = cgfsng_ops_init(); if (!ops) ops = cgfs_ops_init(); if (ops) INFO("Initialized cgroup driver %s", ops->name); } bool cgroup_init(struct lxc_handler *handler) { if (handler->cgroup_data) { ERROR("cgroup_init called on already inited handler"); return true; } if (ops) { INFO("cgroup driver %s initing for %s", ops->name, handler->name); handler->cgroup_data = ops->init(handler->name); } return handler->cgroup_data != NULL; } void cgroup_destroy(struct lxc_handler *handler) { if (ops) { ops->destroy(handler->cgroup_data, handler->conf); handler->cgroup_data = NULL; } } /* Create the container cgroups for all requested controllers */ bool cgroup_create(struct lxc_handler *handler) { if (ops) return ops->create(handler->cgroup_data); return false; } /* * Enter the container init into its new cgroups for all * requested controllers */ bool cgroup_enter(struct lxc_handler *handler) { if (ops) return ops->enter(handler->cgroup_data, handler->pid); return false; } bool cgroup_create_legacy(struct lxc_handler *handler) { if (ops && ops->create_legacy) return ops->create_legacy(handler->cgroup_data, handler->pid); return true; } const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem) { if (ops) return ops->get_cgroup(handler->cgroup_data, subsystem); return NULL; } bool cgroup_escape(struct lxc_handler *handler) { if (ops) return ops->escape(handler->cgroup_data); return false; } int cgroup_num_hierarchies(void) { if (!ops) return -1; return ops->num_hierarchies(); } bool cgroup_get_hierarchies(int n, char ***out) { if (!ops) return false; return ops->get_hierarchies(n, out); } bool cgroup_unfreeze(struct lxc_handler *handler) { if (ops) return ops->unfreeze(handler->cgroup_data); return false; } bool cgroup_setup_limits(struct lxc_handler *handler, bool with_devices) { if (ops) return ops->setup_limits(handler->cgroup_data, &handler->conf->cgroup, with_devices); return false; } bool cgroup_chown(struct lxc_handler *handler) { if (ops && ops->chown) return ops->chown(handler->cgroup_data, handler->conf); return true; } bool cgroup_mount(const char *root, struct lxc_handler *handler, int type) { if (ops) { return ops->mount_cgroup(handler->cgroup_data, root, type); } return false; } int cgroup_nrtasks(struct lxc_handler *handler) { if (ops) { if (ops->nrtasks) return ops->nrtasks(handler->cgroup_data); else WARN("CGROUP driver %s doesn't implement nrtasks", ops->name); } return -1; } bool cgroup_attach(const char *name, const char *lxcpath, pid_t pid) { if (ops) return ops->attach(name, lxcpath, pid); return false; } int lxc_cgroup_set(const char *filename, const char *value, const char *name, const char *lxcpath) { if (ops) return ops->set(filename, value, name, lxcpath); return -1; } int lxc_cgroup_get(const char *filename, char *value, size_t len, const char *name, const char *lxcpath) { if (ops) return ops->get(filename, value, len, name, lxcpath); return -1; } void cgroup_disconnect(void) { if (ops && ops->disconnect) ops->disconnect(); } cgroup_driver_t cgroup_driver(void) { return ops->driver; } #define INIT_SCOPE "/init.scope" void prune_init_scope(char *cg) { char *point; if (!cg) return; point = cg + strlen(cg) - strlen(INIT_SCOPE); if (point < cg) return; if (strcmp(point, INIT_SCOPE) == 0) { if (point == cg) *(point+1) = '\0'; else *point = '\0'; } } /* * Return true if this is a subsystem which we cannot do * without. * * systemd is questionable here. The way callers currently * use this, if systemd is not mounted then it will be ignored. * But if systemd is mounted, then it must be setup so that lxc * can create cgroups in it, else containers will fail. */ bool is_crucial_cgroup_subsystem(const char *s) { if (strcmp(s, "systemd") == 0) return true; if (strcmp(s, "name=systemd") == 0) return true; if (strcmp(s, "freezer") == 0) return true; return false; } lxc-2.0.8/src/lxc/cgroups/cgmanager.c0000644061062106075000000011557613105116772014411 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "bdev.h" #include "error.h" #include "commands.h" #include "list.h" #include "conf.h" #include "utils.h" #include "log.h" #include "cgroup.h" #include "start.h" #include "state.h" #define CGM_SUPPORTS_GET_ABS 3 #define CGM_SUPPORTS_NAMED 4 #define CGM_SUPPORTS_MULT_CONTROLLERS 10 #ifdef HAVE_CGMANAGER lxc_log_define(lxc_cgmanager, lxc); #include #include #include #include #include struct cgm_data { char *name; char *cgroup_path; const char *cgroup_pattern; }; static pthread_mutex_t cgm_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 cgm_lock(void) { lock_mutex(&cgm_mutex); } void cgm_unlock(void) { unlock_mutex(&cgm_mutex); } #ifdef HAVE_PTHREAD_ATFORK __attribute__((constructor)) static void process_lock_setup_atfork(void) { pthread_atfork(cgm_lock, cgm_unlock, cgm_unlock); } #endif static NihDBusProxy *cgroup_manager = NULL; static int32_t api_version; static struct cgroup_ops cgmanager_ops; static int nr_subsystems; static char **subsystems, **subsystems_inone; static bool dbus_threads_initialized = false; static void cull_user_controllers(void); static void cgm_dbus_disconnect(void) { if (cgroup_manager) { dbus_connection_flush(cgroup_manager->connection); dbus_connection_close(cgroup_manager->connection); nih_free(cgroup_manager); } cgroup_manager = NULL; cgm_unlock(); } #define CGMANAGER_DBUS_SOCK "unix:path=/sys/fs/cgroup/cgmanager/sock" static bool cgm_dbus_connect(void) { DBusError dbus_error; static DBusConnection *connection; cgm_lock(); if (!dbus_threads_initialized) { // tell dbus to do struct locking for thread safety dbus_threads_init_default(); dbus_threads_initialized = true; } dbus_error_init(&dbus_error); connection = dbus_connection_open_private(CGMANAGER_DBUS_SOCK, &dbus_error); if (!connection) { DEBUG("Failed opening dbus connection: %s: %s", dbus_error.name, dbus_error.message); dbus_error_free(&dbus_error); cgm_unlock(); return false; } dbus_connection_set_exit_on_disconnect(connection, FALSE); dbus_error_free(&dbus_error); cgroup_manager = nih_dbus_proxy_new(NULL, connection, NULL /* p2p */, "/org/linuxcontainers/cgmanager", NULL, NULL); dbus_connection_unref(connection); if (!cgroup_manager) { NihError *nerr; nerr = nih_error_get(); ERROR("Error opening cgmanager proxy: %s", nerr->message); nih_free(nerr); cgm_dbus_disconnect(); return false; } // get the api version if (cgmanager_get_api_version_sync(NULL, cgroup_manager, &api_version) != 0) { NihError *nerr; nerr = nih_error_get(); ERROR("Error cgroup manager api version: %s", nerr->message); nih_free(nerr); cgm_dbus_disconnect(); return false; } if (api_version < CGM_SUPPORTS_NAMED) cull_user_controllers(); return true; } static bool cgm_all_controllers_same; /* * Check whether we can use "all" when talking to cgmanager. * We check two things: * 1. whether cgmanager is new enough to support this. * 2. whether the task we are interested in is in the same * cgroup for all controllers. * In cgm_init (before an lxc-start) we care about our own * cgroup. In cgm_attach, we care about the target task's * cgroup. */ static void check_supports_multiple_controllers(pid_t pid) { FILE *f; char *line = NULL, *prevpath = NULL; size_t sz = 0; char path[100]; cgm_all_controllers_same = false; if (pid == -1) sprintf(path, "/proc/self/cgroup"); else sprintf(path, "/proc/%d/cgroup", pid); f = fopen(path, "r"); if (!f) return; cgm_all_controllers_same = true; while (getline(&line, &sz, f) != -1) { /* file format: hierarchy:subsystems:group */ char *colon; if (!line[0]) continue; colon = strchr(line, ':'); if (!colon) continue; colon = strchr(colon+1, ':'); if (!colon) continue; colon++; if (!prevpath) { prevpath = alloca(strlen(colon)+1); strcpy(prevpath, colon); continue; } if (strcmp(prevpath, colon) != 0) { cgm_all_controllers_same = false; break; } } fclose(f); free(line); } static int send_creds(int sock, int rpid, int ruid, int rgid) { struct msghdr msg = { 0 }; struct iovec iov; struct cmsghdr *cmsg; struct ucred cred = { .pid = rpid, .uid = ruid, .gid = rgid, }; char cmsgbuf[CMSG_SPACE(sizeof(cred))]; char buf[1]; buf[0] = 'p'; msg.msg_control = cmsgbuf; msg.msg_controllen = sizeof(cmsgbuf); cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred)); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_CREDENTIALS; memcpy(CMSG_DATA(cmsg), &cred, sizeof(cred)); msg.msg_name = NULL; msg.msg_namelen = 0; iov.iov_base = buf; iov.iov_len = sizeof(buf); msg.msg_iov = &iov; msg.msg_iovlen = 1; if (sendmsg(sock, &msg, 0) < 0) return -1; return 0; } static bool lxc_cgmanager_create(const char *controller, const char *cgroup_path, int32_t *existed) { bool ret = true; if ( cgmanager_create_sync(NULL, cgroup_manager, controller, cgroup_path, existed) != 0) { NihError *nerr; nerr = nih_error_get(); ERROR("call to cgmanager_create_sync failed: %s", nerr->message); nih_free(nerr); ERROR("Failed to create %s:%s", controller, cgroup_path); ret = false; } return ret; } /* * Escape to the root cgroup if we are root, so that the container will * be in "/lxc/c1" rather than "/user/..../c1" * called internally with connection already open */ static bool cgm_escape(void *hdata) { bool ret = true, cgm_needs_disconnect = false; pid_t me = getpid(); char **slist = subsystems; int i; if (!cgroup_manager) { if (!cgm_dbus_connect()) { ERROR("Error connecting to cgroup manager"); return false; } cgm_needs_disconnect = true; } if (cgm_all_controllers_same) slist = subsystems_inone; for (i = 0; slist[i]; i++) { if (cgmanager_move_pid_abs_sync(NULL, cgroup_manager, slist[i], "/", me) != 0) { NihError *nerr; nerr = nih_error_get(); ERROR("call to cgmanager_move_pid_abs_sync(%s) failed: %s", slist[i], nerr->message); nih_free(nerr); ret = false; break; } } if (cgm_needs_disconnect) cgm_dbus_disconnect(); return ret; } static int cgm_num_hierarchies(void) { /* not implemented */ return -1; } static bool cgm_get_hierarchies(int i, char ***out) { /* not implemented */ return false; } struct chown_data { const char *cgroup_path; uid_t origuid; }; static int do_chown_cgroup(const char *controller, const char *cgroup_path, uid_t newuid) { int sv[2] = {-1, -1}, optval = 1, ret = -1; char buf[1]; struct pollfd fds; if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sv) < 0) { SYSERROR("Error creating socketpair"); goto out; } if (setsockopt(sv[1], SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) == -1) { SYSERROR("setsockopt failed"); goto out; } if (setsockopt(sv[0], SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) == -1) { SYSERROR("setsockopt failed"); goto out; } if ( cgmanager_chown_scm_sync(NULL, cgroup_manager, controller, cgroup_path, sv[1]) != 0) { NihError *nerr; nerr = nih_error_get(); ERROR("call to cgmanager_chown_scm_sync failed: %s", nerr->message); nih_free(nerr); goto out; } /* now send credentials */ fds.fd = sv[0]; fds.events = POLLIN; fds.revents = 0; if (poll(&fds, 1, -1) <= 0) { ERROR("Error getting go-ahead from server: %s", strerror(errno)); goto out; } if (read(sv[0], &buf, 1) != 1) { ERROR("Error getting reply from server over socketpair"); goto out; } if (send_creds(sv[0], getpid(), getuid(), getgid())) { SYSERROR("%s: Error sending pid over SCM_CREDENTIAL", __func__); goto out; } fds.fd = sv[0]; fds.events = POLLIN; fds.revents = 0; if (poll(&fds, 1, -1) <= 0) { ERROR("Error getting go-ahead from server: %s", strerror(errno)); goto out; } if (read(sv[0], &buf, 1) != 1) { ERROR("Error getting reply from server over socketpair"); goto out; } if (send_creds(sv[0], getpid(), newuid, 0)) { SYSERROR("%s: Error sending pid over SCM_CREDENTIAL", __func__); goto out; } fds.fd = sv[0]; fds.events = POLLIN; fds.revents = 0; if (poll(&fds, 1, -1) <= 0) { ERROR("Error getting go-ahead from server: %s", strerror(errno)); goto out; } ret = read(sv[0], buf, 1); out: close(sv[0]); close(sv[1]); if (ret == 1 && *buf == '1') return 0; return -1; } static int chown_cgroup_wrapper(void *data) { struct chown_data *arg = data; char **slist = subsystems; int i, ret = -1; uid_t destuid; if (setresgid(0,0,0) < 0) SYSERROR("Failed to setgid to 0"); if (setresuid(0,0,0) < 0) SYSERROR("Failed to setuid to 0"); if (setgroups(0, NULL) < 0) SYSERROR("Failed to clear groups"); cgm_dbus_disconnect(); if (!cgm_dbus_connect()) { ERROR("Error connecting to cgroup manager"); return -1; } destuid = get_ns_uid(arg->origuid); if (cgm_all_controllers_same) slist = subsystems_inone; for (i = 0; slist[i]; i++) { if (do_chown_cgroup(slist[i], arg->cgroup_path, destuid) < 0) { ERROR("Failed to chown %s:%s to container root", slist[i], arg->cgroup_path); goto fail; } } ret = 0; fail: cgm_dbus_disconnect(); return ret; } /* Internal helper. Must be called with the cgmanager dbus socket open */ static bool lxc_cgmanager_chmod(const char *controller, const char *cgroup_path, const char *file, int mode) { if (cgmanager_chmod_sync(NULL, cgroup_manager, controller, cgroup_path, file, mode) != 0) { NihError *nerr; nerr = nih_error_get(); ERROR("call to cgmanager_chmod_sync failed: %s", nerr->message); nih_free(nerr); return false; } return true; } /* Internal helper. Must be called with the cgmanager dbus socket open */ static bool chown_cgroup(const char *cgroup_path, struct lxc_conf *conf) { struct chown_data data; char **slist = subsystems; int i; if (lxc_list_empty(&conf->id_map)) /* If there's no mapping then we don't need to chown */ return true; data.cgroup_path = cgroup_path; data.origuid = geteuid(); /* Unpriv users can't chown it themselves, so chown from * a child namespace mapping both our own and the target uid */ if (userns_exec_1(conf, chown_cgroup_wrapper, &data) < 0) { ERROR("Error requesting cgroup chown in new namespace"); return false; } /* * Now chmod 775 the directory else the container cannot create cgroups. * This can't be done in the child namespace because it only group-owns * the cgroup */ if (cgm_all_controllers_same) slist = subsystems_inone; for (i = 0; slist[i]; i++) { if (!lxc_cgmanager_chmod(slist[i], cgroup_path, "", 0775)) return false; if (!lxc_cgmanager_chmod(slist[i], cgroup_path, "tasks", 0664)) return false; if (!lxc_cgmanager_chmod(slist[i], cgroup_path, "cgroup.procs", 0664)) return false; } return true; } #define CG_REMOVE_RECURSIVE 1 /* Internal helper. Must be called with the cgmanager dbus socket open */ static void cgm_remove_cgroup(const char *controller, const char *path) { int existed; if ( cgmanager_remove_sync(NULL, cgroup_manager, controller, path, CG_REMOVE_RECURSIVE, &existed) != 0) { NihError *nerr; nerr = nih_error_get(); ERROR("call to cgmanager_remove_sync failed: %s", nerr->message); nih_free(nerr); ERROR("Error removing %s:%s", controller, path); } if (existed == -1) INFO("cgroup removal attempt: %s:%s did not exist", controller, path); } static void *cgm_init(const char *name) { struct cgm_data *d; d = malloc(sizeof(*d)); if (!d) return NULL; if (!cgm_dbus_connect()) { ERROR("Error connecting to cgroup manager"); goto err1; } memset(d, 0, sizeof(*d)); d->name = strdup(name); if (!d->name) { cgm_dbus_disconnect(); goto err1; } d->cgroup_pattern = lxc_global_config_value("lxc.cgroup.pattern"); // cgm_create immediately gets called so keep the connection open return d; err1: free(d); return NULL; } /* Called after a failed container startup */ static void cgm_destroy(void *hdata, struct lxc_conf *conf) { struct cgm_data *d = hdata; char **slist = subsystems; int i; if (!d || !d->cgroup_path) return; if (!cgm_dbus_connect()) { ERROR("Error connecting to cgroup manager"); return; } if (cgm_all_controllers_same) slist = subsystems_inone; for (i = 0; slist[i]; i++) cgm_remove_cgroup(slist[i], d->cgroup_path); free(d->name); free(d->cgroup_path); free(d); cgm_dbus_disconnect(); } /* * remove all the cgroups created * called internally with dbus connection open */ static inline void cleanup_cgroups(char *path) { int i; char **slist = subsystems; if (cgm_all_controllers_same) slist = subsystems_inone; for (i = 0; slist[i]; i++) cgm_remove_cgroup(slist[i], path); } static inline bool cgm_create(void *hdata) { struct cgm_data *d = hdata; char **slist = subsystems; int i, index=0, baselen, ret; int32_t existed; char result[MAXPATHLEN], *tmp, *cgroup_path; if (!d) return false; // XXX we should send a hint to the cgmanager that when these // cgroups become empty they should be deleted. Requires a cgmanager // extension memset(result, 0, MAXPATHLEN); tmp = lxc_string_replace("%n", d->name, d->cgroup_pattern); if (!tmp) goto bad; if (strlen(tmp) >= MAXPATHLEN) { free(tmp); goto bad; } strcpy(result, tmp); baselen = strlen(result); free(tmp); tmp = result; while (*tmp == '/') tmp++; again: if (index == 100) { // turn this into a warn later ERROR("cgroup error? 100 cgroups with this name already running"); goto bad; } if (index) { ret = snprintf(result+baselen, MAXPATHLEN-baselen, "-%d", index); if (ret < 0 || ret >= MAXPATHLEN-baselen) goto bad; } existed = 0; if (cgm_all_controllers_same) slist = subsystems_inone; for (i = 0; slist[i]; i++) { if (!lxc_cgmanager_create(slist[i], tmp, &existed)) { ERROR("Error creating cgroup %s:%s", slist[i], result); cleanup_cgroups(tmp); goto bad; } if (existed == 1) goto next; } // success cgroup_path = strdup(tmp); if (!cgroup_path) { cleanup_cgroups(tmp); goto bad; } d->cgroup_path = cgroup_path; cgm_dbus_disconnect(); return true; next: index++; goto again; bad: cgm_dbus_disconnect(); return false; } /* * Use the cgmanager to move a task into a cgroup for a particular * hierarchy. * All the subsystems in this hierarchy are co-mounted, so we only * need to transition the task into one of the cgroups * * Internal helper, must be called with cgmanager dbus socket open */ static bool lxc_cgmanager_enter(pid_t pid, const char *controller, const char *cgroup_path, bool abs) { int ret; if (abs) ret = cgmanager_move_pid_abs_sync(NULL, cgroup_manager, controller, cgroup_path, pid); else ret = cgmanager_move_pid_sync(NULL, cgroup_manager, controller, cgroup_path, pid); if (ret != 0) { NihError *nerr; nerr = nih_error_get(); WARN("call to cgmanager_move_pid_%ssync failed: %s", abs ? "abs_" : "", nerr->message); nih_free(nerr); return false; } return true; } static inline bool cgm_enter(void *hdata, pid_t pid) { struct cgm_data *d = hdata; char **slist = subsystems; bool ret = false; int i; if (!d || !d->cgroup_path) return false; if (!cgm_dbus_connect()) { ERROR("Error connecting to cgroup manager"); return false; } if (cgm_all_controllers_same) slist = subsystems_inone; for (i = 0; slist[i]; i++) { if (!lxc_cgmanager_enter(pid, slist[i], d->cgroup_path, false)) goto out; } ret = true; out: cgm_dbus_disconnect(); return ret; } static const char *cgm_get_cgroup(void *hdata, const char *subsystem) { struct cgm_data *d = hdata; if (!d || !d->cgroup_path) return NULL; return d->cgroup_path; } #if HAVE_CGMANAGER_GET_PID_CGROUP_ABS_SYNC static inline bool abs_cgroup_supported(void) { return api_version >= CGM_SUPPORTS_GET_ABS; } #else static inline bool abs_cgroup_supported(void) { return false; } #define cgmanager_get_pid_cgroup_abs_sync(...) -1 #endif static char *try_get_abs_cgroup(const char *name, const char *lxcpath, const char *controller) { char *cgroup = NULL; if (abs_cgroup_supported()) { /* get the container init pid and ask for its abs cgroup */ pid_t pid = lxc_cmd_get_init_pid(name, lxcpath); if (pid < 0) return NULL; if (cgmanager_get_pid_cgroup_abs_sync(NULL, cgroup_manager, controller, pid, &cgroup) != 0) { cgroup = NULL; NihError *nerr; nerr = nih_error_get(); nih_free(nerr); } else prune_init_scope(cgroup); return cgroup; } /* use the command interface to look for the cgroup */ return lxc_cmd_get_cgroup_path(name, lxcpath, controller); } /* * nrtasks is called by the utmp helper by the container monitor. * cgmanager socket was closed after cgroup setup was complete, so we need * to reopen here. * * Return -1 on error. */ static int cgm_get_nrtasks(void *hdata) { struct cgm_data *d = hdata; int32_t *pids; size_t pids_len; if (!d || !d->cgroup_path) return -1; if (!cgm_dbus_connect()) { ERROR("Error connecting to cgroup manager"); return -1; } if (cgmanager_get_tasks_sync(NULL, cgroup_manager, subsystems[0], d->cgroup_path, &pids, &pids_len) != 0) { NihError *nerr; nerr = nih_error_get(); ERROR("call to cgmanager_get_tasks_sync failed: %s", nerr->message); nih_free(nerr); pids_len = -1; goto out; } nih_free(pids); out: cgm_dbus_disconnect(); return pids_len; } #if HAVE_CGMANAGER_LIST_CONTROLLERS static bool lxc_list_controllers(char ***list) { if (!cgm_dbus_connect()) { ERROR("Error connecting to cgroup manager"); return false; } if (cgmanager_list_controllers_sync(NULL, cgroup_manager, list) != 0) { NihError *nerr; nerr = nih_error_get(); ERROR("call to cgmanager_list_controllers_sync failed: %s", nerr->message); nih_free(nerr); cgm_dbus_disconnect(); return false; } cgm_dbus_disconnect(); return true; } #else static bool lxc_list_controllers(char ***list) { return false; } #endif static inline void free_abs_cgroup(char *cgroup) { if (!cgroup) return; if (abs_cgroup_supported()) nih_free(cgroup); else free(cgroup); } static void do_cgm_get(const char *name, const char *lxcpath, const char *filename, int outp, bool sendvalue) { char *controller, *key, *cgroup = NULL, *cglast; int len = -1; int ret; nih_local char *result = NULL; controller = alloca(strlen(filename)+1); strcpy(controller, filename); key = strchr(controller, '.'); if (!key) { ret = write(outp, &len, sizeof(len)); if (ret != sizeof(len)) WARN("Failed to warn cgm_get of error; parent may hang"); exit(1); } *key = '\0'; if (!cgm_dbus_connect()) { ERROR("Error connecting to cgroup manager"); ret = write(outp, &len, sizeof(len)); if (ret != sizeof(len)) WARN("Failed to warn cgm_get of error; parent may hang"); exit(1); } cgroup = try_get_abs_cgroup(name, lxcpath, controller); if (!cgroup) { cgm_dbus_disconnect(); ret = write(outp, &len, sizeof(len)); if (ret != sizeof(len)) WARN("Failed to warn cgm_get of error; parent may hang"); exit(1); } cglast = strrchr(cgroup, '/'); if (!cglast) { cgm_dbus_disconnect(); free_abs_cgroup(cgroup); ret = write(outp, &len, sizeof(len)); if (ret != sizeof(len)) WARN("Failed to warn cgm_get of error; parent may hang"); exit(1); } *cglast = '\0'; if (!lxc_cgmanager_enter(getpid(), controller, cgroup, abs_cgroup_supported())) { WARN("Failed to enter container cgroup %s:%s", controller, cgroup); ret = write(outp, &len, sizeof(len)); if (ret != sizeof(len)) WARN("Failed to warn cgm_get of error; parent may hang"); cgm_dbus_disconnect(); free_abs_cgroup(cgroup); exit(1); } if (cgmanager_get_value_sync(NULL, cgroup_manager, controller, cglast+1, filename, &result) != 0) { NihError *nerr; nerr = nih_error_get(); nih_free(nerr); free_abs_cgroup(cgroup); cgm_dbus_disconnect(); ret = write(outp, &len, sizeof(len)); if (ret != sizeof(len)) WARN("Failed to warn cgm_get of error; parent may hang"); exit(1); } free_abs_cgroup(cgroup); cgm_dbus_disconnect(); len = strlen(result); ret = write(outp, &len, sizeof(len)); if (ret != sizeof(len)) { WARN("Failed to send length to parent"); exit(1); } if (!len || !sendvalue) { exit(0); } ret = write(outp, result, len); if (ret < 0) exit(1); exit(0); } /* cgm_get is called to get container cgroup settings, not during startup */ static int cgm_get(const char *filename, char *value, size_t len, const char *name, const char *lxcpath) { pid_t pid; int p[2], ret, newlen, readlen; if (pipe(p) < 0) return -1; if ((pid = fork()) < 0) { close(p[0]); close(p[1]); return -1; } if (!pid) // do_cgm_get exits do_cgm_get(name, lxcpath, filename, p[1], len && value); close(p[1]); ret = read(p[0], &newlen, sizeof(newlen)); if (ret != sizeof(newlen)) { close(p[0]); ret = -1; goto out; } if (!len || !value) { close(p[0]); ret = newlen; goto out; } memset(value, 0, len); if (newlen < 0) { // child is reporting an error close(p[0]); ret = -1; goto out; } if (newlen == 0) { // empty read close(p[0]); ret = 0; goto out; } readlen = newlen > len ? len : newlen; ret = read(p[0], value, readlen); close(p[0]); if (ret != readlen) { ret = -1; goto out; } if (newlen >= len) { value[len-1] = '\0'; newlen = len-1; } else if (newlen+1 < len) { // cgmanager doesn't add eol to last entry value[newlen++] = '\n'; value[newlen] = '\0'; } ret = newlen; out: if (wait_for_pid(pid)) WARN("do_cgm_get exited with error"); return ret; } static void do_cgm_set(const char *name, const char *lxcpath, const char *filename, const char *value, int outp) { char *controller, *key, *cgroup = NULL; int retval = 0; // value we are sending to the parent over outp int ret; char *cglast; controller = alloca(strlen(filename)+1); strcpy(controller, filename); key = strchr(controller, '.'); if (!key) { ret = write(outp, &retval, sizeof(retval)); if (ret != sizeof(retval)) WARN("Failed to warn cgm_set of error; parent may hang"); exit(1); } *key = '\0'; if (!cgm_dbus_connect()) { ERROR("Error connecting to cgroup manager"); ret = write(outp, &retval, sizeof(retval)); if (ret != sizeof(retval)) WARN("Failed to warn cgm_set of error; parent may hang"); exit(1); } cgroup = try_get_abs_cgroup(name, lxcpath, controller); if (!cgroup) { cgm_dbus_disconnect(); ret = write(outp, &retval, sizeof(retval)); if (ret != sizeof(retval)) WARN("Failed to warn cgm_set of error; parent may hang"); exit(1); } cglast = strrchr(cgroup, '/'); if (!cglast) { cgm_dbus_disconnect(); free_abs_cgroup(cgroup); ret = write(outp, &retval, sizeof(retval)); if (ret != sizeof(retval)) WARN("Failed to warn cgm_set of error; parent may hang"); exit(1); } *cglast = '\0'; if (!lxc_cgmanager_enter(getpid(), controller, cgroup, abs_cgroup_supported())) { ERROR("Failed to enter container cgroup %s:%s", controller, cgroup); ret = write(outp, &retval, sizeof(retval)); if (ret != sizeof(retval)) WARN("Failed to warn cgm_set of error; parent may hang"); cgm_dbus_disconnect(); free_abs_cgroup(cgroup); exit(1); } if (cgmanager_set_value_sync(NULL, cgroup_manager, controller, cglast+1, filename, value) != 0) { NihError *nerr; nerr = nih_error_get(); ERROR("Error setting cgroup value %s for %s:%s", filename, controller, cgroup); ERROR("call to cgmanager_set_value_sync failed: %s", nerr->message); nih_free(nerr); free_abs_cgroup(cgroup); cgm_dbus_disconnect(); ret = write(outp, &retval, sizeof(retval)); if (ret != sizeof(retval)) WARN("Failed to warn cgm_set of error; parent may hang"); exit(1); } free_abs_cgroup(cgroup); cgm_dbus_disconnect(); /* tell parent that we are done */ retval = 1; ret = write(outp, &retval, sizeof(retval)); if (ret != sizeof(retval)) { exit(1); } exit(0); } /* cgm_set is called to change cgroup settings, not during startup */ static int cgm_set(const char *filename, const char *value, const char *name, const char *lxcpath) { pid_t pid; int p[2], ret, v; if (pipe(p) < 0) return -1; if ((pid = fork()) < 0) { close(p[1]); close(p[0]); return -1; } if (!pid) // do_cgm_set exits do_cgm_set(name, lxcpath, filename, value, p[1]); close(p[1]); ret = read(p[0], &v, sizeof(v)); close(p[0]); if (wait_for_pid(pid)) WARN("do_cgm_set exited with error"); if (ret != sizeof(v) || !v) return -1; return 0; } static void free_subsystems(void) { int i; for (i = 0; i < nr_subsystems; i++) free(subsystems[i]); free(subsystems); subsystems = NULL; nr_subsystems = 0; } static void cull_user_controllers(void) { int i, j; for (i = 0; i < nr_subsystems; i++) { if (strncmp(subsystems[i], "name=", 5) != 0) continue; for (j = i; j < nr_subsystems-1; j++) subsystems[j] = subsystems[j+1]; nr_subsystems--; } } /* * return true if inword is in the comma-delimited list cgroup_use */ static bool in_comma_list(const char *inword, const char *cgroup_use) { char *e; size_t inlen = strlen(inword), len; do { e = strchr(cgroup_use, ','); len = e ? e - cgroup_use : strlen(cgroup_use); if (len == inlen && strncmp(inword, cgroup_use, len) == 0) return true; cgroup_use = e + 1; } while (e); return false; } /* * inlist is a comma-delimited list of cgroups; so is checklist. Return * true if any member of inlist is in checklist. */ static bool any_in_comma_list(const char *inlist, const char *checklist) { char *tmp = alloca(strlen(inlist) + 1), *tok, *saveptr = NULL; strcpy(tmp, inlist); for (tok = strtok_r(tmp, ",", &saveptr); tok; tok = strtok_r(NULL, ",", &saveptr)) { if (in_comma_list(tok, checklist)) return true; } return false; } static bool in_subsystem_list(const char *c) { int i; for (i = 0; i < nr_subsystems; i++) { if (strcmp(c, subsystems[i]) == 0) return true; } return false; } /* * If /etc/lxc/lxc.conf specifies lxc.cgroup.use = "freezer,memory", * then clear out any other subsystems, and make sure that freezer * and memory are both enabled */ static bool verify_and_prune(const char *cgroup_use) { const char *p; char *e; int i, j; for (p = cgroup_use; p && *p; p = e + 1) { e = strchr(p, ','); if (e) *e = '\0'; if (!in_subsystem_list(p)) { ERROR("Controller %s required by lxc.cgroup.use but not available\n", p); return false; } if (e) *e = ','; if (!e) break; } for (i = 0; i < nr_subsystems;) { if (in_comma_list(subsystems[i], cgroup_use)) { i++; continue; } free(subsystems[i]); for (j = i; j < nr_subsystems-1; j++) subsystems[j] = subsystems[j+1]; subsystems[nr_subsystems-1] = NULL; nr_subsystems--; } return true; } static void drop_subsystem(int which) { int i; if (which < 0 || which >= nr_subsystems) { ERROR("code error: dropping invalid subsystem index\n"); exit(1); } free(subsystems[which]); /* note - we have nr_subsystems+1 entries, last one a NULL */ for (i = which; i < nr_subsystems; i++) subsystems[i] = subsystems[i+1]; nr_subsystems -= 1; } /* * Check whether we can create the cgroups we would want */ static bool subsys_is_writeable(const char *controller, const char *probe) { int32_t existed; bool ret = true; if ( cgmanager_create_sync(NULL, cgroup_manager, controller, probe, &existed) != 0) { NihError *nerr; nerr = nih_error_get(); ERROR("call to cgmanager_create_sync failed: %s", nerr->message); nih_free(nerr); ERROR("Failed to create %s:%s", controller, probe); ret = false; } return ret; } static char *get_last_controller_in_list(char *list) { char *p; while ((p = strchr(list, ',')) != NULL) list = p + 1; return list; } /* * Make sure that all the controllers are writeable. * If any are not, then * - if they are listed in lxc.cgroup.use, refuse to start * - else if they are crucial subsystems, refuse to start * - else warn and do not use them */ static bool verify_final_subsystems(const char *cgroup_use) { int i; bool dropped_any = false; bool bret = false; const char *cgroup_pattern; char tmpnam[50], *probe; if (!cgm_dbus_connect()) { ERROR("Error connecting to cgroup manager"); return false; } cgroup_pattern = lxc_global_config_value("lxc.cgroup.pattern"); i = snprintf(tmpnam, 50, "lxcprobe-%d", getpid()); if (i < 0 || i >= 50) { ERROR("Attack - format string modified?"); return false; } probe = lxc_string_replace("%n", tmpnam, cgroup_pattern); if (!probe) goto out; i = 0; while (i < nr_subsystems) { char *p = get_last_controller_in_list(subsystems[i]); if (!subsys_is_writeable(p, probe)) { if (is_crucial_cgroup_subsystem(p)) { ERROR("Cannot write to crucial subsystem %s\n", subsystems[i]); goto out; } if (cgroup_use && any_in_comma_list(subsystems[i], cgroup_use)) { ERROR("Cannot write to subsystem %s which is requested in lxc.cgroup.use\n", subsystems[i]); goto out; } WARN("Cannot write to subsystem %s, continuing with out it\n", subsystems[i]); dropped_any = true; drop_subsystem(i); } else { cgm_remove_cgroup(subsystems[i], probe); i++; } } if (dropped_any) cgm_all_controllers_same = false; bret = true; out: free(probe); cgm_dbus_disconnect(); return bret; } static bool collect_subsystems(void) { char *line = NULL; nih_local char **cgm_subsys_list = NULL; size_t sz = 0; FILE *f = NULL; if (subsystems) // already initialized return true; subsystems_inone = malloc(2 * sizeof(char *)); if (!subsystems_inone) return false; subsystems_inone[0] = "all"; subsystems_inone[1] = NULL; if (lxc_list_controllers(&cgm_subsys_list)) { while (cgm_subsys_list[nr_subsystems]) { char **tmp = NIH_MUST( realloc(subsystems, (nr_subsystems+2)*sizeof(char *)) ); tmp[nr_subsystems] = NIH_MUST( strdup(cgm_subsys_list[nr_subsystems++]) ); subsystems = tmp; } if (nr_subsystems) subsystems[nr_subsystems] = NULL; goto collected; } INFO("cgmanager_list_controllers failed, falling back to /proc/self/cgroups"); f = fopen_cloexec("/proc/self/cgroup", "r"); if (!f) { f = fopen_cloexec("/proc/1/cgroup", "r"); if (!f) return false; } while (getline(&line, &sz, f) != -1) { /* file format: hierarchy:subsystems:group, * with multiple subsystems being ,-separated */ char *slist, *end, *p, *saveptr = NULL, **tmp; if (!line[0]) continue; slist = strchr(line, ':'); if (!slist) continue; slist++; end = strchr(slist, ':'); if (!end) continue; *end = '\0'; for (p = strtok_r(slist, ",", &saveptr); p; p = strtok_r(NULL, ",", &saveptr)) { tmp = realloc(subsystems, (nr_subsystems+2)*sizeof(char *)); if (!tmp) goto out_free; subsystems = tmp; tmp[nr_subsystems] = strdup(p); tmp[nr_subsystems+1] = NULL; if (!tmp[nr_subsystems]) goto out_free; nr_subsystems++; } } fclose(f); f = NULL; free(line); line = NULL; collected: if (!nr_subsystems) { ERROR("No cgroup subsystems found"); return false; } /* make sure that cgroup.use can be and is honored */ const char *cgroup_use = lxc_global_config_value("lxc.cgroup.use"); if (!cgroup_use && errno != 0) goto final_verify; if (cgroup_use) { if (!verify_and_prune(cgroup_use)) { free_subsystems(); return false; } subsystems_inone[0] = NIH_MUST( strdup(cgroup_use) ); cgm_all_controllers_same = false; } final_verify: return verify_final_subsystems(cgroup_use); out_free: free(line); if (f) fclose(f); free_subsystems(); return false; } /* * called during cgroup.c:cgroup_ops_init(), at startup. No threads. * We check whether we can talk to cgmanager, escape to root cgroup if * we are root, then close the connection. */ struct cgroup_ops *cgm_ops_init(void) { check_supports_multiple_controllers(-1); if (!collect_subsystems()) return NULL; if (api_version < CGM_SUPPORTS_MULT_CONTROLLERS) cgm_all_controllers_same = false; // if root, try to escape to root cgroup if (geteuid() == 0 && !cgm_escape(NULL)) { free_subsystems(); return NULL; } return &cgmanager_ops; } /* unfreeze is called by the command api after killing a container. */ static bool cgm_unfreeze(void *hdata) { struct cgm_data *d = hdata; bool ret = true; if (!d || !d->cgroup_path) return false; if (!cgm_dbus_connect()) { ERROR("Error connecting to cgroup manager"); return false; } if (cgmanager_set_value_sync(NULL, cgroup_manager, "freezer", d->cgroup_path, "freezer.state", "THAWED") != 0) { NihError *nerr; nerr = nih_error_get(); ERROR("call to cgmanager_set_value_sync failed: %s", nerr->message); nih_free(nerr); ERROR("Error unfreezing %s", d->cgroup_path); ret = false; } cgm_dbus_disconnect(); return ret; } static bool cgm_setup_limits(void *hdata, struct lxc_list *cgroup_settings, bool do_devices) { struct cgm_data *d = hdata; struct lxc_list *iterator, *sorted_cgroup_settings, *next; struct lxc_cgroup *cg; bool ret = false; if (lxc_list_empty(cgroup_settings)) return true; if (!d || !d->cgroup_path) return false; if (!cgm_dbus_connect()) { ERROR("Error connecting to cgroup manager"); return false; } sorted_cgroup_settings = sort_cgroup_settings(cgroup_settings); if (!sorted_cgroup_settings) { return false; } lxc_list_for_each(iterator, sorted_cgroup_settings) { char controller[100], *p; cg = iterator->elem; if (do_devices != !strncmp("devices", cg->subsystem, 7)) continue; if (strlen(cg->subsystem) > 100) // i smell a rat goto out; strcpy(controller, cg->subsystem); p = strchr(controller, '.'); if (p) *p = '\0'; if (cgmanager_set_value_sync(NULL, cgroup_manager, controller, d->cgroup_path, cg->subsystem, cg->value) != 0) { NihError *nerr; nerr = nih_error_get(); if (do_devices) { WARN("call to cgmanager_set_value_sync failed: %s", nerr->message); nih_free(nerr); WARN("Error setting cgroup %s:%s limit type %s", controller, d->cgroup_path, cg->subsystem); continue; } ERROR("call to cgmanager_set_value_sync failed: %s", nerr->message); nih_free(nerr); ERROR("Error setting cgroup %s:%s limit type %s", controller, d->cgroup_path, cg->subsystem); goto out; } DEBUG("cgroup '%s' set to '%s'", cg->subsystem, cg->value); } ret = true; INFO("cgroup limits have been setup"); out: lxc_list_for_each_safe(iterator, sorted_cgroup_settings, next) { lxc_list_del(iterator); free(iterator); } free(sorted_cgroup_settings); cgm_dbus_disconnect(); return ret; } static bool cgm_chown(void *hdata, struct lxc_conf *conf) { struct cgm_data *d = hdata; if (!d || !d->cgroup_path) return false; if (!cgm_dbus_connect()) { ERROR("Error connecting to cgroup manager"); return false; } if (!chown_cgroup(d->cgroup_path, conf)) WARN("Failed to chown %s to container root", d->cgroup_path); cgm_dbus_disconnect(); return true; } /* * TODO: this should be re-written to use the get_config_item("lxc.id_map") * cmd api instead of getting the idmap from c->lxc_conf. The reason is * that the id_maps may be different if the container was started with a * -f or -s argument. * The reason I'm punting on that is because we'll need to parse the * idmap results. */ static bool cgm_attach(const char *name, const char *lxcpath, pid_t pid) { bool pass = true; char *cgroup = NULL; char **slist = subsystems; int i; if (!cgm_dbus_connect()) { ERROR("Error connecting to cgroup manager"); return false; } for (i = 0; slist[i]; i++) { cgroup = try_get_abs_cgroup(name, lxcpath, slist[i]); if (!cgroup) { ERROR("Failed to get cgroup for controller %s", slist[i]); cgm_dbus_disconnect(); return false; } if (!lxc_cgmanager_enter(pid, slist[i], cgroup, abs_cgroup_supported())) { pass = false; break; } } cgm_dbus_disconnect(); if (!pass) ERROR("Failed to enter group %s", cgroup); free_abs_cgroup(cgroup); return pass; } static bool cgm_bind_dir(const char *root, const char *dirname) { nih_local char *cgpath = NULL; /* /sys should have been mounted by now */ cgpath = NIH_MUST( nih_strdup(NULL, root) ); NIH_MUST( nih_strcat(&cgpath, NULL, "/sys/fs/cgroup") ); if (!dir_exists(cgpath)) { ERROR("%s does not exist", cgpath); return false; } /* mount a tmpfs there so we can create subdirs */ if (safe_mount("cgroup", cgpath, "tmpfs", 0, "size=10000,mode=755", root)) { SYSERROR("Failed to mount tmpfs at %s", cgpath); return false; } NIH_MUST( nih_strcat(&cgpath, NULL, "/cgmanager") ); if (mkdir(cgpath, 0755) < 0) { SYSERROR("Failed to create %s", cgpath); return false; } if (safe_mount(dirname, cgpath, "none", MS_BIND, 0, root)) { SYSERROR("Failed to bind mount %s to %s", dirname, cgpath); return false; } return true; } /* * cgm_mount_cgroup: * If /sys/fs/cgroup/cgmanager.lower/ exists, bind mount that to * /sys/fs/cgroup/cgmanager/ in the container. * Otherwise, if /sys/fs/cgroup/cgmanager exists, bind mount that. * Else do nothing */ #define CGMANAGER_LOWER_SOCK "/sys/fs/cgroup/cgmanager.lower" #define CGMANAGER_UPPER_SOCK "/sys/fs/cgroup/cgmanager" static bool cgm_mount_cgroup(void *hdata, const char *root, int type) { if (dir_exists(CGMANAGER_LOWER_SOCK)) return cgm_bind_dir(root, CGMANAGER_LOWER_SOCK); if (dir_exists(CGMANAGER_UPPER_SOCK)) return cgm_bind_dir(root, CGMANAGER_UPPER_SOCK); // Host doesn't have cgmanager running? Then how did we get here? return false; } static struct cgroup_ops cgmanager_ops = { .init = cgm_init, .destroy = cgm_destroy, .create = cgm_create, .enter = cgm_enter, .create_legacy = NULL, .get_cgroup = cgm_get_cgroup, .escape = cgm_escape, .num_hierarchies = cgm_num_hierarchies, .get_hierarchies = cgm_get_hierarchies, .get = cgm_get, .set = cgm_set, .unfreeze = cgm_unfreeze, .setup_limits = cgm_setup_limits, .name = "cgmanager", .chown = cgm_chown, .attach = cgm_attach, .mount_cgroup = cgm_mount_cgroup, .nrtasks = cgm_get_nrtasks, .disconnect = NULL, .driver = CGMANAGER, }; #endif lxc-2.0.8/src/lxc/cgroups/cgfs.c0000644061062106075000000021610613105116772013376 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "bdev.h" #include "error.h" #include "commands.h" #include "list.h" #include "conf.h" #include "utils.h" #include "log.h" #include "cgroup.h" #include "start.h" #include "state.h" #if IS_BIONIC #include <../include/lxcmntent.h> #else #include #endif struct cgroup_hierarchy; struct cgroup_meta_data; struct cgroup_mount_point; /* * cgroup_meta_data: the metadata about the cgroup infrastructure on this * host */ struct cgroup_meta_data { ptrdiff_t ref; /* simple refcount */ struct cgroup_hierarchy **hierarchies; struct cgroup_mount_point **mount_points; int maximum_hierarchy; }; /* * cgroup_hierarchy: describes a single cgroup hierarchy * (may have multiple mount points) */ struct cgroup_hierarchy { int index; bool used; /* false if the hierarchy should be ignored by lxc */ char **subsystems; struct cgroup_mount_point *rw_absolute_mount_point; struct cgroup_mount_point *ro_absolute_mount_point; struct cgroup_mount_point **all_mount_points; size_t all_mount_point_capacity; }; /* * cgroup_mount_point: a mount point to where a hierarchy * is mounted to */ struct cgroup_mount_point { struct cgroup_hierarchy *hierarchy; char *mount_point; char *mount_prefix; bool read_only; bool need_cpuset_init; }; /* * cgroup_process_info: describes the membership of a * process to the different cgroup * hierarchies * * Note this is the per-process info tracked by the cgfs_ops. * This is not used with cgmanager. */ struct cgroup_process_info { struct cgroup_process_info *next; struct cgroup_meta_data *meta_ref; struct cgroup_hierarchy *hierarchy; char *cgroup_path; char *cgroup_path_sub; char **created_paths; size_t created_paths_capacity; size_t created_paths_count; struct cgroup_mount_point *designated_mount_point; }; struct cgfs_data { char *name; const char *cgroup_pattern; struct cgroup_meta_data *meta; struct cgroup_process_info *info; }; lxc_log_define(lxc_cgfs, lxc); static struct cgroup_process_info *lxc_cgroup_process_info_getx(const char *proc_pid_cgroup_str, struct cgroup_meta_data *meta); static char **subsystems_from_mount_options(const char *mount_options, char **kernel_list); static void lxc_cgroup_mount_point_free(struct cgroup_mount_point *mp); static void lxc_cgroup_hierarchy_free(struct cgroup_hierarchy *h); static bool is_valid_cgroup(const char *name); static int create_cgroup(struct cgroup_mount_point *mp, const char *path); static int remove_cgroup(struct cgroup_mount_point *mp, const char *path, bool recurse, struct lxc_conf *conf); static char *cgroup_to_absolute_path(struct cgroup_mount_point *mp, const char *path, const char *suffix); static struct cgroup_process_info *find_info_for_subsystem(struct cgroup_process_info *info, const char *subsystem); static int do_cgroup_get(const char *cgroup_path, const char *sub_filename, char *value, size_t len); static int do_cgroup_set(const char *cgroup_path, const char *sub_filename, const char *value); static bool cgroup_devices_has_allow_or_deny(struct cgfs_data *d, char *v, bool for_allow); static int do_setup_cgroup_limits(struct cgfs_data *d, struct lxc_list *cgroup_settings, bool do_devices); static int cgroup_recursive_task_count(const char *cgroup_path); static int handle_cgroup_settings(struct cgroup_mount_point *mp, char *cgroup_path); static bool init_cpuset_if_needed(struct cgroup_mount_point *mp, const char *path); static struct cgroup_meta_data *lxc_cgroup_load_meta2(const char **subsystem_whitelist); static struct cgroup_meta_data *lxc_cgroup_get_meta(struct cgroup_meta_data *meta_data); static struct cgroup_meta_data *lxc_cgroup_put_meta(struct cgroup_meta_data *meta_data); /* free process membership information */ static void lxc_cgroup_process_info_free(struct cgroup_process_info *info); static void lxc_cgroup_process_info_free_and_remove(struct cgroup_process_info *info, struct lxc_conf *conf); static struct cgroup_ops cgfs_ops; static int cgroup_rmdir(char *dirname) { struct dirent *direntp; int saved_errno = 0; DIR *dir; int ret, failed=0; char pathname[MAXPATHLEN]; dir = opendir(dirname); if (!dir) { ERROR("%s: failed to open %s", __func__, dirname); return -1; } while ((direntp = readdir(dir))) { struct stat mystat; int rc; if (!direntp) break; if (!strcmp(direntp->d_name, ".") || !strcmp(direntp->d_name, "..")) continue; rc = snprintf(pathname, MAXPATHLEN, "%s/%s", dirname, direntp->d_name); if (rc < 0 || rc >= MAXPATHLEN) { ERROR("pathname too long"); failed=1; if (!saved_errno) saved_errno = -ENOMEM; continue; } ret = lstat(pathname, &mystat); if (ret) { SYSERROR("%s: failed to stat %s", __func__, pathname); failed=1; if (!saved_errno) saved_errno = errno; continue; } if (S_ISDIR(mystat.st_mode)) { if (cgroup_rmdir(pathname) < 0) { if (!saved_errno) saved_errno = errno; failed=1; } } } if (rmdir(dirname) < 0) { SYSERROR("%s: failed to delete %s", __func__, dirname); if (!saved_errno) saved_errno = errno; failed=1; } ret = closedir(dir); if (ret) { SYSERROR("%s: failed to close directory %s", __func__, dirname); if (!saved_errno) saved_errno = errno; failed=1; } errno = saved_errno; return failed ? -1 : 0; } static int rmdir_wrapper(void *data) { char *path = data; if (setresgid(0,0,0) < 0) SYSERROR("Failed to setgid to 0"); if (setresuid(0,0,0) < 0) SYSERROR("Failed to setuid to 0"); if (setgroups(0, NULL) < 0) SYSERROR("Failed to clear groups"); return cgroup_rmdir(path); } static struct cgroup_meta_data *lxc_cgroup_load_meta() { const char *cgroup_use = NULL; char **cgroup_use_list = NULL; struct cgroup_meta_data *md = NULL; int saved_errno; errno = 0; cgroup_use = lxc_global_config_value("lxc.cgroup.use"); if (!cgroup_use && errno != 0) return NULL; if (cgroup_use) { cgroup_use_list = lxc_string_split_and_trim(cgroup_use, ','); if (!cgroup_use_list) return NULL; } md = lxc_cgroup_load_meta2((const char **)cgroup_use_list); saved_errno = errno; lxc_free_array((void **)cgroup_use_list, free); errno = saved_errno; return md; } /* Step 1: determine all kernel subsystems */ static bool find_cgroup_subsystems(char ***kernel_subsystems) { FILE *proc_cgroups; bool bret = false; char *line = NULL; size_t sz = 0; size_t kernel_subsystems_count = 0; size_t kernel_subsystems_capacity = 0; int r; proc_cgroups = fopen_cloexec("/proc/cgroups", "r"); if (!proc_cgroups) return false; while (getline(&line, &sz, proc_cgroups) != -1) { char *tab1; char *tab2; int hierarchy_number; if (line[0] == '#') continue; if (!line[0]) continue; tab1 = strchr(line, '\t'); if (!tab1) continue; *tab1++ = '\0'; tab2 = strchr(tab1, '\t'); if (!tab2) continue; *tab2 = '\0'; tab2 = NULL; hierarchy_number = strtoul(tab1, &tab2, 10); if (!tab2 || *tab2) continue; (void)hierarchy_number; r = lxc_grow_array((void ***)kernel_subsystems, &kernel_subsystems_capacity, kernel_subsystems_count + 1, 12); if (r < 0) goto out; (*kernel_subsystems)[kernel_subsystems_count] = strdup(line); if (!(*kernel_subsystems)[kernel_subsystems_count]) goto out; kernel_subsystems_count++; } bret = true; out: fclose(proc_cgroups); free(line); return bret; } /* Step 2: determine all hierarchies (by reading /proc/self/cgroup), * since mount points don't specify hierarchy number and * /proc/cgroups does not contain named hierarchies */ static bool find_cgroup_hierarchies(struct cgroup_meta_data *meta_data, bool all_kernel_subsystems, bool all_named_subsystems, const char **subsystem_whitelist) { FILE *proc_self_cgroup; char *line = NULL; size_t sz = 0; int r; bool bret = false; size_t hierarchy_capacity = 0; proc_self_cgroup = fopen_cloexec("/proc/self/cgroup", "r"); /* if for some reason (because of setns() and pid namespace for example), * /proc/self is not valid, we try /proc/1/cgroup... */ if (!proc_self_cgroup) proc_self_cgroup = fopen_cloexec("/proc/1/cgroup", "r"); if (!proc_self_cgroup) return false; while (getline(&line, &sz, proc_self_cgroup) != -1) { /* file format: hierarchy:subsystems:group, * we only extract hierarchy and subsystems * here */ char *colon1; char *colon2; int hierarchy_number; struct cgroup_hierarchy *h = NULL; char **p; if (!line[0]) continue; colon1 = strchr(line, ':'); if (!colon1) continue; *colon1++ = '\0'; colon2 = strchr(colon1, ':'); if (!colon2) continue; *colon2 = '\0'; colon2 = NULL; /* With cgroupv2 /proc/self/cgroup can contain entries of the * form: 0::/ * These entries need to be skipped. */ if (!strcmp(colon1, "")) continue; hierarchy_number = strtoul(line, &colon2, 10); if (!colon2 || *colon2) continue; if (hierarchy_number > meta_data->maximum_hierarchy) { /* lxc_grow_array will never shrink, so even if we find a lower * hierarchy number here, the array will never be smaller */ r = lxc_grow_array((void ***)&meta_data->hierarchies, &hierarchy_capacity, hierarchy_number + 1, 12); if (r < 0) goto out; meta_data->maximum_hierarchy = hierarchy_number; } /* this shouldn't happen, we had this already */ if (meta_data->hierarchies[hierarchy_number]) goto out; h = calloc(1, sizeof(struct cgroup_hierarchy)); if (!h) goto out; meta_data->hierarchies[hierarchy_number] = h; h->index = hierarchy_number; h->subsystems = lxc_string_split_and_trim(colon1, ','); if (!h->subsystems) goto out; /* see if this hierarchy should be considered */ if (!all_kernel_subsystems || !all_named_subsystems) { for (p = h->subsystems; *p; p++) { if (!strncmp(*p, "name=", 5)) { if (all_named_subsystems || (subsystem_whitelist && lxc_string_in_array(*p, subsystem_whitelist))) { h->used = true; break; } } else { if (all_kernel_subsystems || (subsystem_whitelist && lxc_string_in_array(*p, subsystem_whitelist))) { h->used = true; break; } } } } else { /* we want all hierarchy anyway */ h->used = true; } } bret = true; out: fclose(proc_self_cgroup); free(line); return bret; } /* Step 3: determine all mount points of each hierarchy */ static bool find_hierarchy_mountpts( struct cgroup_meta_data *meta_data, char **kernel_subsystems) { bool bret = false; FILE *proc_self_mountinfo; char *line = NULL; size_t sz = 0; char **tokens = NULL; size_t mount_point_count = 0; size_t mount_point_capacity = 0; size_t token_capacity = 0; int r; bool is_cgns = cgns_supported(); proc_self_mountinfo = fopen_cloexec("/proc/self/mountinfo", "r"); /* if for some reason (because of setns() and pid namespace for example), * /proc/self is not valid, we try /proc/1/cgroup... */ if (!proc_self_mountinfo) proc_self_mountinfo = fopen_cloexec("/proc/1/mountinfo", "r"); if (!proc_self_mountinfo) return false; while (getline(&line, &sz, proc_self_mountinfo) != -1) { char *token, *line_tok, *saveptr = NULL; size_t i, j, k; struct cgroup_mount_point *mount_point; struct cgroup_hierarchy *h; char **subsystems; bool is_lxcfs = false; if (line[0] && line[strlen(line) - 1] == '\n') line[strlen(line) - 1] = '\0'; for (i = 0, line_tok = line; (token = strtok_r(line_tok, " ", &saveptr)); line_tok = NULL) { r = lxc_grow_array((void ***)&tokens, &token_capacity, i + 1, 64); if (r < 0) goto out; tokens[i++] = token; } /* layout of /proc/self/mountinfo: * 0: id * 1: parent id * 2: device major:minor * 3: mount prefix * 4: mount point * 5: per-mount options * [optional X]: additional data * X+7: "-" * X+8: type * X+9: source * X+10: per-superblock options */ for (j = 6; j < i && tokens[j]; j++) if (!strcmp(tokens[j], "-")) break; /* could not find separator */ if (j >= i || !tokens[j]) continue; /* there should be exactly three fields after * the separator */ if (i != j + 4) continue; /* not a cgroup filesystem */ if (strcmp(tokens[j + 1], "cgroup") != 0) { if (strcmp(tokens[j + 1], "fuse.lxcfs") != 0) continue; if (strncmp(tokens[4], "/sys/fs/cgroup/", 15) != 0) continue; is_lxcfs = true; char *curtok = tokens[4] + 15; subsystems = subsystems_from_mount_options(curtok, kernel_subsystems); } else subsystems = subsystems_from_mount_options(tokens[j + 3], kernel_subsystems); if (!subsystems) goto out; h = NULL; for (k = 0; k <= meta_data->maximum_hierarchy; k++) { if (meta_data->hierarchies[k] && meta_data->hierarchies[k]->subsystems[0] && lxc_string_in_array(meta_data->hierarchies[k]->subsystems[0], (const char **)subsystems)) { /* TODO: we could also check if the lists really match completely, * just to have an additional sanity check */ h = meta_data->hierarchies[k]; break; } } lxc_free_array((void **)subsystems, free); r = lxc_grow_array((void ***)&meta_data->mount_points, &mount_point_capacity, mount_point_count + 1, 12); if (r < 0) goto out; /* create mount point object */ mount_point = calloc(1, sizeof(*mount_point)); if (!mount_point) goto out; meta_data->mount_points[mount_point_count++] = mount_point; mount_point->hierarchy = h; if (is_lxcfs || is_cgns) mount_point->mount_prefix = strdup("/"); else mount_point->mount_prefix = strdup(tokens[3]); mount_point->mount_point = strdup(tokens[4]); if (!mount_point->mount_point || !mount_point->mount_prefix) goto out; mount_point->read_only = !lxc_string_in_list("rw", tokens[5], ','); if (!strcmp(mount_point->mount_prefix, "/")) { if (mount_point->read_only) { if (!h->ro_absolute_mount_point) h->ro_absolute_mount_point = mount_point; } else { if (!h->rw_absolute_mount_point) h->rw_absolute_mount_point = mount_point; } } k = lxc_array_len((void **)h->all_mount_points); r = lxc_grow_array((void ***)&h->all_mount_points, &h->all_mount_point_capacity, k + 1, 4); if (r < 0) goto out; h->all_mount_points[k] = mount_point; } bret = true; out: fclose(proc_self_mountinfo); free(tokens); free(line); return bret; } static struct cgroup_meta_data *lxc_cgroup_load_meta2(const char **subsystem_whitelist) { bool all_kernel_subsystems = true; bool all_named_subsystems = false; struct cgroup_meta_data *meta_data = NULL; char **kernel_subsystems = NULL; int saved_errno = 0; /* if the subsystem whitelist is not specified, include all * hierarchies that contain kernel subsystems by default but * no hierarchies that only contain named subsystems * * if it is specified, the specifier @all will select all * hierarchies, @kernel will select all hierarchies with * kernel subsystems and @named will select all named * hierarchies */ all_kernel_subsystems = subsystem_whitelist ? (lxc_string_in_array("@kernel", subsystem_whitelist) || lxc_string_in_array("@all", subsystem_whitelist)) : true; all_named_subsystems = subsystem_whitelist ? (lxc_string_in_array("@named", subsystem_whitelist) || lxc_string_in_array("@all", subsystem_whitelist)) : true; meta_data = calloc(1, sizeof(struct cgroup_meta_data)); if (!meta_data) return NULL; meta_data->ref = 1; if (!find_cgroup_subsystems(&kernel_subsystems)) goto out_error; if (!find_cgroup_hierarchies(meta_data, all_kernel_subsystems, all_named_subsystems, subsystem_whitelist)) goto out_error; if (!find_hierarchy_mountpts(meta_data, kernel_subsystems)) goto out_error; /* oops, we couldn't find anything */ if (!meta_data->hierarchies || !meta_data->mount_points) { errno = EINVAL; goto out_error; } lxc_free_array((void **)kernel_subsystems, free); return meta_data; out_error: saved_errno = errno; lxc_free_array((void **)kernel_subsystems, free); lxc_cgroup_put_meta(meta_data); errno = saved_errno; return NULL; } static struct cgroup_meta_data *lxc_cgroup_get_meta(struct cgroup_meta_data *meta_data) { meta_data->ref++; return meta_data; } static struct cgroup_meta_data *lxc_cgroup_put_meta(struct cgroup_meta_data *meta_data) { size_t i; if (!meta_data) return NULL; if (--meta_data->ref > 0) return meta_data; lxc_free_array((void **)meta_data->mount_points, (lxc_free_fn)lxc_cgroup_mount_point_free); if (meta_data->hierarchies) for (i = 0; i <= meta_data->maximum_hierarchy; i++) if (meta_data->hierarchies[i]) lxc_cgroup_hierarchy_free(meta_data->hierarchies[i]); free(meta_data->hierarchies); free(meta_data); return NULL; } static struct cgroup_hierarchy *lxc_cgroup_find_hierarchy(struct cgroup_meta_data *meta_data, const char *subsystem) { size_t i; for (i = 0; i <= meta_data->maximum_hierarchy; i++) { struct cgroup_hierarchy *h = meta_data->hierarchies[i]; if (!h) continue; if (h && lxc_string_in_array(subsystem, (const char **)h->subsystems)) return h; } return NULL; } static bool mountpoint_is_accessible(struct cgroup_mount_point *mp) { return mp && access(mp->mount_point, F_OK) == 0; } static struct cgroup_mount_point *lxc_cgroup_find_mount_point(struct cgroup_hierarchy *hierarchy, const char *group, bool should_be_writable) { struct cgroup_mount_point **mps; struct cgroup_mount_point *current_result = NULL; ssize_t quality = -1; /* trivial case */ if (mountpoint_is_accessible(hierarchy->rw_absolute_mount_point)) return hierarchy->rw_absolute_mount_point; if (!should_be_writable && mountpoint_is_accessible(hierarchy->ro_absolute_mount_point)) return hierarchy->ro_absolute_mount_point; for (mps = hierarchy->all_mount_points; mps && *mps; mps++) { struct cgroup_mount_point *mp = *mps; size_t prefix_len = mp->mount_prefix ? strlen(mp->mount_prefix) : 0; if (prefix_len == 1 && mp->mount_prefix[0] == '/') prefix_len = 0; if (!mountpoint_is_accessible(mp)) continue; if (should_be_writable && mp->read_only) continue; if (!prefix_len || (strncmp(group, mp->mount_prefix, prefix_len) == 0 && (group[prefix_len] == '\0' || group[prefix_len] == '/'))) { /* search for the best quality match, i.e. the match with the * shortest prefix where this group is still contained */ if (quality == -1 || prefix_len < quality) { current_result = mp; quality = prefix_len; } } } if (!current_result) errno = ENOENT; return current_result; } static char *lxc_cgroup_find_abs_path(const char *subsystem, const char *group, bool should_be_writable, const char *suffix) { struct cgroup_meta_data *meta_data; struct cgroup_hierarchy *h; struct cgroup_mount_point *mp; char *result; int saved_errno; meta_data = lxc_cgroup_load_meta(); if (!meta_data) return NULL; h = lxc_cgroup_find_hierarchy(meta_data, subsystem); if (!h) goto out_error; mp = lxc_cgroup_find_mount_point(h, group, should_be_writable); if (!mp) goto out_error; result = cgroup_to_absolute_path(mp, group, suffix); if (!result) goto out_error; lxc_cgroup_put_meta(meta_data); return result; out_error: saved_errno = errno; lxc_cgroup_put_meta(meta_data); errno = saved_errno; return NULL; } static struct cgroup_process_info *lxc_cgroup_process_info_get(pid_t pid, struct cgroup_meta_data *meta) { char pid_buf[32]; snprintf(pid_buf, 32, "/proc/%lu/cgroup", (unsigned long)pid); return lxc_cgroup_process_info_getx(pid_buf, meta); } static struct cgroup_process_info *lxc_cgroup_process_info_get_init(struct cgroup_meta_data *meta) { return lxc_cgroup_process_info_get(1, meta); } static struct cgroup_process_info *lxc_cgroup_process_info_get_self(struct cgroup_meta_data *meta) { struct cgroup_process_info *i; i = lxc_cgroup_process_info_getx("/proc/self/cgroup", meta); if (!i) i = lxc_cgroup_process_info_get(getpid(), meta); return i; } /* * If a controller has ns cgroup mounted, then in that cgroup the handler->pid * is already in a new cgroup named after the pid. 'mnt' is passed in as * the full current cgroup. Say that is /sys/fs/cgroup/lxc/2975 and the container * name is c1. . We want to rename the cgroup directory to /sys/fs/cgroup/lxc/c1, * and return the string /sys/fs/cgroup/lxc/c1. */ static char *cgroup_rename_nsgroup(const char *mountpath, const char *oldname, pid_t pid, const char *name) { char *dir, *fulloldpath; char *newname, *fullnewpath; int len, newlen, ret; /* * if cgroup is mounted at /cgroup and task is in cgroup /ab/, pid 2375 and * name is c1, * dir: /ab * fulloldpath = /cgroup/ab/2375 * fullnewpath = /cgroup/ab/c1 * newname = /ab/c1 */ dir = alloca(strlen(oldname) + 1); strcpy(dir, oldname); len = strlen(oldname) + strlen(mountpath) + 22; fulloldpath = alloca(len); ret = snprintf(fulloldpath, len, "%s/%s/%ld", mountpath, oldname, (unsigned long)pid); if (ret < 0 || ret >= len) return NULL; len = strlen(dir) + strlen(name) + 2; newname = malloc(len); if (!newname) { SYSERROR("Out of memory"); return NULL; } ret = snprintf(newname, len, "%s/%s", dir, name); if (ret < 0 || ret >= len) { free(newname); return NULL; } newlen = strlen(mountpath) + len + 2; fullnewpath = alloca(newlen); ret = snprintf(fullnewpath, newlen, "%s/%s", mountpath, newname); if (ret < 0 || ret >= newlen) { free(newname); return NULL; } if (access(fullnewpath, F_OK) == 0) { if (rmdir(fullnewpath) != 0) { SYSERROR("container cgroup %s already exists.", fullnewpath); free(newname); return NULL; } } if (rename(fulloldpath, fullnewpath)) { SYSERROR("failed to rename cgroup %s->%s", fulloldpath, fullnewpath); free(newname); return NULL; } DEBUG("'%s' renamed to '%s'", oldname, newname); return newname; } static bool is_crucial_hierarchy(struct cgroup_hierarchy *h) { char **p; for (p = h->subsystems; *p; p++) { if (is_crucial_cgroup_subsystem(*p)) return true; } return false; } /* create a new cgroup */ static struct cgroup_process_info *lxc_cgroupfs_create(const char *name, const char *path_pattern, struct cgroup_meta_data *meta_data, const char *sub_pattern) { char **cgroup_path_components = NULL; char **p = NULL; char *path_so_far = NULL; char **new_cgroup_paths = NULL; char **new_cgroup_paths_sub = NULL; struct cgroup_mount_point *mp; struct cgroup_hierarchy *h; struct cgroup_process_info *base_info = NULL; struct cgroup_process_info *info_ptr; int saved_errno; int r; unsigned suffix = 0; bool had_sub_pattern = false; size_t i; if (!is_valid_cgroup(name)) { ERROR("Invalid cgroup name: '%s'", name); errno = EINVAL; return NULL; } if (!strstr(path_pattern, "%n")) { ERROR("Invalid cgroup path pattern: '%s'; contains no %%n for specifying container name", path_pattern); errno = EINVAL; return NULL; } /* we will modify the result of this operation directly, * so we don't have to copy the data structure */ base_info = (path_pattern[0] == '/') ? lxc_cgroup_process_info_get_init(meta_data) : lxc_cgroup_process_info_get_self(meta_data); if (!base_info) return NULL; new_cgroup_paths = calloc(meta_data->maximum_hierarchy + 1, sizeof(char *)); if (!new_cgroup_paths) goto out_initial_error; new_cgroup_paths_sub = calloc(meta_data->maximum_hierarchy + 1, sizeof(char *)); if (!new_cgroup_paths_sub) goto out_initial_error; /* find mount points we can use */ for (info_ptr = base_info; info_ptr; info_ptr = info_ptr->next) { h = info_ptr->hierarchy; if (!h) continue; mp = lxc_cgroup_find_mount_point(h, info_ptr->cgroup_path, true); if (!mp) { ERROR("Could not find writable mount point for cgroup hierarchy %d while trying to create cgroup.", h->index); goto out_initial_error; } info_ptr->designated_mount_point = mp; if (lxc_string_in_array("ns", (const char **)h->subsystems)) continue; if (handle_cgroup_settings(mp, info_ptr->cgroup_path) < 0) { ERROR("Could not set clone_children to 1 for cpuset hierarchy in parent cgroup."); goto out_initial_error; } } /* normalize the path */ cgroup_path_components = lxc_normalize_path(path_pattern); if (!cgroup_path_components) goto out_initial_error; /* go through the path components to see if we can create them */ for (p = cgroup_path_components; *p || (sub_pattern && !had_sub_pattern); p++) { /* we only want to create the same component with -1, -2, etc. * if the component contains the container name itself, otherwise * it's not an error if it already exists */ char *p_eff = *p ? *p : (char *)sub_pattern; bool contains_name = strstr(p_eff, "%n"); char *current_component = NULL; char *current_subpath = NULL; char *current_entire_path = NULL; char *parts[3]; size_t j = 0; i = 0; /* if we are processing the subpattern, we want to make sure * loop is ended the next time around */ if (!*p) { had_sub_pattern = true; p--; } goto find_name_on_this_level; cleanup_name_on_this_level: /* This is reached if we found a name clash. * In that case, remove the cgroup from all previous hierarchies */ for (j = 0, info_ptr = base_info; j < i && info_ptr; info_ptr = info_ptr->next, j++) { if (info_ptr->created_paths_count < 1) continue; r = remove_cgroup(info_ptr->designated_mount_point, info_ptr->created_paths[info_ptr->created_paths_count - 1], false, NULL); if (r < 0) WARN("could not clean up cgroup we created when trying to create container"); free(info_ptr->created_paths[info_ptr->created_paths_count - 1]); info_ptr->created_paths[--info_ptr->created_paths_count] = NULL; } if (current_component != current_subpath) free(current_subpath); if (current_component != p_eff) free(current_component); current_component = current_subpath = NULL; /* try again with another suffix */ ++suffix; find_name_on_this_level: /* determine name of the path component we should create */ if (contains_name && suffix > 0) { char *buf = calloc(strlen(name) + 32, 1); if (!buf) goto out_initial_error; snprintf(buf, strlen(name) + 32, "%s-%u", name, suffix); current_component = lxc_string_replace("%n", buf, p_eff); free(buf); } else { current_component = contains_name ? lxc_string_replace("%n", name, p_eff) : p_eff; } parts[0] = path_so_far; parts[1] = current_component; parts[2] = NULL; current_subpath = path_so_far ? lxc_string_join("/", (const char **)parts, false) : current_component; /* Now go through each hierarchy and try to create the * corresponding cgroup */ for (i = 0, info_ptr = base_info; info_ptr; info_ptr = info_ptr->next, i++) { char *parts2[3]; if (!info_ptr->hierarchy) continue; if (lxc_string_in_array("ns", (const char **)info_ptr->hierarchy->subsystems)) continue; current_entire_path = NULL; parts2[0] = !strcmp(info_ptr->cgroup_path, "/") ? "" : info_ptr->cgroup_path; parts2[1] = current_subpath; parts2[2] = NULL; current_entire_path = lxc_string_join("/", (const char **)parts2, false); if (!*p) { /* we are processing the subpath, so only update that one */ free(new_cgroup_paths_sub[i]); new_cgroup_paths_sub[i] = strdup(current_entire_path); if (!new_cgroup_paths_sub[i]) goto cleanup_from_error; } else { /* remember which path was used on this controller */ free(new_cgroup_paths[i]); new_cgroup_paths[i] = strdup(current_entire_path); if (!new_cgroup_paths[i]) goto cleanup_from_error; } r = create_cgroup(info_ptr->designated_mount_point, current_entire_path); if (r < 0 && errno == EEXIST && contains_name) { /* name clash => try new name with new suffix */ free(current_entire_path); current_entire_path = NULL; goto cleanup_name_on_this_level; } else if (r < 0 && errno != EEXIST) { if (is_crucial_hierarchy(info_ptr->hierarchy)) { SYSERROR("Could not create cgroup '%s' in '%s'.", current_entire_path, info_ptr->designated_mount_point->mount_point); goto cleanup_from_error; } goto skip; } else if (r == 0) { /* successfully created */ r = lxc_grow_array((void ***)&info_ptr->created_paths, &info_ptr->created_paths_capacity, info_ptr->created_paths_count + 1, 8); if (r < 0) goto cleanup_from_error; if (!init_cpuset_if_needed(info_ptr->designated_mount_point, current_entire_path)) { ERROR("Failed to initialize cpuset for '%s' in '%s'.", current_entire_path, info_ptr->designated_mount_point->mount_point); goto cleanup_from_error; } info_ptr->created_paths[info_ptr->created_paths_count++] = current_entire_path; } else { /* if we didn't create the cgroup, then we have to make sure that * further cgroups will be created properly */ if (handle_cgroup_settings(info_ptr->designated_mount_point, info_ptr->cgroup_path) < 0) { ERROR("Could not set clone_children to 1 for cpuset hierarchy in pre-existing cgroup."); goto cleanup_from_error; } if (!init_cpuset_if_needed(info_ptr->designated_mount_point, info_ptr->cgroup_path)) { ERROR("Failed to initialize cpuset in pre-existing '%s'.", info_ptr->cgroup_path); goto cleanup_from_error; } skip: /* already existed but path component of pattern didn't contain '%n', * so this is not an error; but then we don't need current_entire_path * anymore... */ free(current_entire_path); current_entire_path = NULL; } } /* save path so far */ free(path_so_far); path_so_far = strdup(current_subpath); if (!path_so_far) goto cleanup_from_error; /* cleanup */ if (current_component != current_subpath) free(current_subpath); if (current_component != p_eff) free(current_component); current_component = current_subpath = NULL; continue; cleanup_from_error: /* called if an error occurred in the loop, so we * do some additional cleanup here */ saved_errno = errno; if (current_component != current_subpath) free(current_subpath); if (current_component != p_eff) free(current_component); free(current_entire_path); errno = saved_errno; goto out_initial_error; } /* we're done, now update the paths */ for (i = 0, info_ptr = base_info; info_ptr; info_ptr = info_ptr->next, i++) { if (!info_ptr->hierarchy) continue; /* ignore legacy 'ns' subsystem here, lxc_cgroup_create_legacy * will take care of it * Since we do a continue in above loop, new_cgroup_paths[i] is * unset anyway, as is new_cgroup_paths_sub[i] */ if (lxc_string_in_array("ns", (const char **)info_ptr->hierarchy->subsystems)) continue; free(info_ptr->cgroup_path); info_ptr->cgroup_path = new_cgroup_paths[i]; info_ptr->cgroup_path_sub = new_cgroup_paths_sub[i]; } /* don't use lxc_free_array since we used the array members * to store them in our result... */ free(new_cgroup_paths); free(new_cgroup_paths_sub); free(path_so_far); lxc_free_array((void **)cgroup_path_components, free); return base_info; out_initial_error: saved_errno = errno; free(path_so_far); lxc_cgroup_process_info_free_and_remove(base_info, NULL); lxc_free_array((void **)new_cgroup_paths, free); lxc_free_array((void **)new_cgroup_paths_sub, free); lxc_free_array((void **)cgroup_path_components, free); errno = saved_errno; return NULL; } static int lxc_cgroup_create_legacy(struct cgroup_process_info *base_info, const char *name, pid_t pid) { struct cgroup_process_info *info_ptr; int r; for (info_ptr = base_info; info_ptr; info_ptr = info_ptr->next) { if (!info_ptr->hierarchy) continue; if (!lxc_string_in_array("ns", (const char **)info_ptr->hierarchy->subsystems)) continue; /* * For any path which has ns cgroup mounted, handler->pid is already * moved into a container called '%d % (handler->pid)'. Rename it to * the cgroup name and record that. */ char *tmp = cgroup_rename_nsgroup((const char *)info_ptr->designated_mount_point->mount_point, info_ptr->cgroup_path, pid, name); if (!tmp) return -1; free(info_ptr->cgroup_path); info_ptr->cgroup_path = tmp; r = lxc_grow_array((void ***)&info_ptr->created_paths, &info_ptr->created_paths_capacity, info_ptr->created_paths_count + 1, 8); if (r < 0) return -1; tmp = strdup(tmp); if (!tmp) return -1; info_ptr->created_paths[info_ptr->created_paths_count++] = tmp; } return 0; } /* get the cgroup membership of a given container */ static struct cgroup_process_info *lxc_cgroup_get_container_info(const char *name, const char *lxcpath, struct cgroup_meta_data *meta_data) { struct cgroup_process_info *result = NULL; int saved_errno = 0; size_t i; struct cgroup_process_info **cptr = &result; struct cgroup_process_info *entry = NULL; char *path = NULL; for (i = 0; i <= meta_data->maximum_hierarchy; i++) { struct cgroup_hierarchy *h = meta_data->hierarchies[i]; if (!h || !h->used) continue; /* use the command interface to look for the cgroup */ path = lxc_cmd_get_cgroup_path(name, lxcpath, h->subsystems[0]); if (!path) { h->used = false; continue; } entry = calloc(1, sizeof(struct cgroup_process_info)); if (!entry) goto out_error; entry->meta_ref = lxc_cgroup_get_meta(meta_data); entry->hierarchy = h; entry->cgroup_path = path; path = NULL; /* it is not an error if we don't find anything here, * it is up to the caller to decide what to do in that * case */ entry->designated_mount_point = lxc_cgroup_find_mount_point(h, entry->cgroup_path, true); *cptr = entry; cptr = &entry->next; entry = NULL; } return result; out_error: saved_errno = errno; free(path); lxc_cgroup_process_info_free(result); lxc_cgroup_process_info_free(entry); errno = saved_errno; return NULL; } /* move a processs to the cgroups specified by the membership */ static int lxc_cgroupfs_enter(struct cgroup_process_info *info, pid_t pid, bool enter_sub) { char pid_buf[32]; char *cgroup_tasks_fn; int r; struct cgroup_process_info *info_ptr; snprintf(pid_buf, 32, "%lu", (unsigned long)pid); for (info_ptr = info; info_ptr; info_ptr = info_ptr->next) { if (!info_ptr->hierarchy) continue; char *cgroup_path = (enter_sub && info_ptr->cgroup_path_sub) ? info_ptr->cgroup_path_sub : info_ptr->cgroup_path; if (!info_ptr->designated_mount_point) { info_ptr->designated_mount_point = lxc_cgroup_find_mount_point(info_ptr->hierarchy, cgroup_path, true); if (!info_ptr->designated_mount_point) { SYSERROR("Could not add pid %lu to cgroup %s: internal error (couldn't find any writable mountpoint to cgroup filesystem)", (unsigned long)pid, cgroup_path); return -1; } } cgroup_tasks_fn = cgroup_to_absolute_path(info_ptr->designated_mount_point, cgroup_path, "/tasks"); if (!cgroup_tasks_fn) { SYSERROR("Could not add pid %lu to cgroup %s: internal error", (unsigned long)pid, cgroup_path); return -1; } r = lxc_write_to_file(cgroup_tasks_fn, pid_buf, strlen(pid_buf), false); free(cgroup_tasks_fn); if (r < 0 && is_crucial_hierarchy(info_ptr->hierarchy)) { SYSERROR("Could not add pid %lu to cgroup %s: internal error", (unsigned long)pid, cgroup_path); return -1; } } return 0; } /* free process membership information */ void lxc_cgroup_process_info_free(struct cgroup_process_info *info) { struct cgroup_process_info *next; if (!info) return; next = info->next; lxc_cgroup_put_meta(info->meta_ref); free(info->cgroup_path); free(info->cgroup_path_sub); lxc_free_array((void **)info->created_paths, free); free(info); lxc_cgroup_process_info_free(next); } /* free process membership information and remove cgroups that were created */ void lxc_cgroup_process_info_free_and_remove(struct cgroup_process_info *info, struct lxc_conf *conf) { struct cgroup_process_info *next; char **pp; if (!info) return; next = info->next; { struct cgroup_mount_point *mp = info->designated_mount_point; if (!mp) mp = lxc_cgroup_find_mount_point(info->hierarchy, info->cgroup_path, true); if (mp) /* ignore return value here, perhaps we created the * '/lxc' cgroup in this container but another container * is still running (for example) */ (void)remove_cgroup(mp, info->cgroup_path, true, conf); } for (pp = info->created_paths; pp && *pp; pp++); for ((void)(pp && --pp); info->created_paths && pp >= info->created_paths; --pp) { free(*pp); } free(info->created_paths); lxc_cgroup_put_meta(info->meta_ref); free(info->cgroup_path); free(info->cgroup_path_sub); free(info); lxc_cgroup_process_info_free_and_remove(next, conf); } static char *lxc_cgroup_get_hierarchy_path_data(const char *subsystem, struct cgfs_data *d) { struct cgroup_process_info *info = d->info; info = find_info_for_subsystem(info, subsystem); if (!info) return NULL; prune_init_scope(info->cgroup_path); return info->cgroup_path; } static char *lxc_cgroup_get_hierarchy_abs_path_data(const char *subsystem, struct cgfs_data *d) { struct cgroup_process_info *info = d->info; struct cgroup_mount_point *mp = NULL; info = find_info_for_subsystem(info, subsystem); if (!info) return NULL; if (info->designated_mount_point) { mp = info->designated_mount_point; } else { mp = lxc_cgroup_find_mount_point(info->hierarchy, info->cgroup_path, true); if (!mp) return NULL; } return cgroup_to_absolute_path(mp, info->cgroup_path, NULL); } static char *lxc_cgroup_get_hierarchy_abs_path(const char *subsystem, const char *name, const char *lxcpath) { struct cgroup_meta_data *meta; struct cgroup_process_info *base_info, *info; struct cgroup_mount_point *mp; char *result = NULL; meta = lxc_cgroup_load_meta(); if (!meta) return NULL; base_info = lxc_cgroup_get_container_info(name, lxcpath, meta); if (!base_info) goto out1; info = find_info_for_subsystem(base_info, subsystem); if (!info) goto out2; if (info->designated_mount_point) { mp = info->designated_mount_point; } else { mp = lxc_cgroup_find_mount_point(info->hierarchy, info->cgroup_path, true); if (!mp) goto out3; } result = cgroup_to_absolute_path(mp, info->cgroup_path, NULL); out3: out2: lxc_cgroup_process_info_free(base_info); out1: lxc_cgroup_put_meta(meta); return result; } static int lxc_cgroup_set_data(const char *filename, const char *value, struct cgfs_data *d) { char *subsystem = NULL, *p, *path; int ret = -1; subsystem = alloca(strlen(filename) + 1); strcpy(subsystem, filename); if ((p = strchr(subsystem, '.')) != NULL) *p = '\0'; errno = ENOENT; path = lxc_cgroup_get_hierarchy_abs_path_data(subsystem, d); if (path) { ret = do_cgroup_set(path, filename, value); int saved_errno = errno; free(path); errno = saved_errno; } return ret; } static int lxc_cgroupfs_set(const char *filename, const char *value, const char *name, const char *lxcpath) { char *subsystem = NULL, *p, *path; int ret = -1; subsystem = alloca(strlen(filename) + 1); strcpy(subsystem, filename); if ((p = strchr(subsystem, '.')) != NULL) *p = '\0'; path = lxc_cgroup_get_hierarchy_abs_path(subsystem, name, lxcpath); if (path) { ret = do_cgroup_set(path, filename, value); free(path); } return ret; } static int lxc_cgroupfs_get(const char *filename, char *value, size_t len, const char *name, const char *lxcpath) { char *subsystem = NULL, *p, *path; int ret = -1; subsystem = alloca(strlen(filename) + 1); strcpy(subsystem, filename); if ((p = strchr(subsystem, '.')) != NULL) *p = '\0'; path = lxc_cgroup_get_hierarchy_abs_path(subsystem, name, lxcpath); if (path) { ret = do_cgroup_get(path, filename, value, len); free(path); } return ret; } static bool cgroupfs_mount_cgroup(void *hdata, const char *root, int type) { size_t bufsz = strlen(root) + sizeof("/sys/fs/cgroup"); char *path = NULL; char **parts = NULL; char *dirname = NULL; char *abs_path = NULL; char *abs_path2 = NULL; struct cgfs_data *cgfs_d; struct cgroup_process_info *info, *base_info; int r, saved_errno = 0; if (cgns_supported()) return true; cgfs_d = hdata; if (!cgfs_d) return false; base_info = cgfs_d->info; /* If we get passed the _NOSPEC types, we default to _MIXED, since we don't * have access to the lxc_conf object at this point. It really should be up * to the caller to fix this, but this doesn't really hurt. */ if (type == LXC_AUTO_CGROUP_FULL_NOSPEC) type = LXC_AUTO_CGROUP_FULL_MIXED; else if (type == LXC_AUTO_CGROUP_NOSPEC) type = LXC_AUTO_CGROUP_MIXED; if (type < LXC_AUTO_CGROUP_RO || type > LXC_AUTO_CGROUP_FULL_MIXED) { ERROR("could not mount cgroups into container: invalid type specified internally"); errno = EINVAL; return false; } path = calloc(1, bufsz); if (!path) return false; snprintf(path, bufsz, "%s/sys/fs/cgroup", root); r = safe_mount("cgroup_root", path, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_RELATIME, "size=10240k,mode=755", root); if (r < 0) { SYSERROR("could not mount tmpfs to /sys/fs/cgroup in the container"); return false; } /* now mount all the hierarchies we care about */ for (info = base_info; info; info = info->next) { size_t subsystem_count, i; struct cgroup_mount_point *mp = info->designated_mount_point; if (!info->hierarchy) continue; if (!mountpoint_is_accessible(mp)) mp = lxc_cgroup_find_mount_point(info->hierarchy, info->cgroup_path, true); if (!mp) { SYSERROR("could not find original mount point for cgroup hierarchy while trying to mount cgroup filesystem"); goto out_error; } subsystem_count = lxc_array_len((void **)info->hierarchy->subsystems); parts = calloc(subsystem_count + 1, sizeof(char *)); if (!parts) goto out_error; for (i = 0; i < subsystem_count; i++) { if (!strncmp(info->hierarchy->subsystems[i], "name=", 5)) parts[i] = info->hierarchy->subsystems[i] + 5; else parts[i] = info->hierarchy->subsystems[i]; } dirname = lxc_string_join(",", (const char **)parts, false); if (!dirname) goto out_error; /* create subsystem directory */ abs_path = lxc_append_paths(path, dirname); if (!abs_path) goto out_error; r = mkdir_p(abs_path, 0755); if (r < 0 && errno != EEXIST) { SYSERROR("could not create cgroup subsystem directory /sys/fs/cgroup/%s", dirname); goto out_error; } abs_path2 = lxc_append_paths(abs_path, info->cgroup_path); if (!abs_path2) goto out_error; if (type == LXC_AUTO_CGROUP_FULL_RO || type == LXC_AUTO_CGROUP_FULL_RW || type == LXC_AUTO_CGROUP_FULL_MIXED) { /* bind-mount the cgroup entire filesystem there */ if (strcmp(mp->mount_prefix, "/") != 0) { /* FIXME: maybe we should just try to remount the entire hierarchy * with a regular mount command? may that works? */ ERROR("could not automatically mount cgroup-full to /sys/fs/cgroup/%s: host has no mount point for this cgroup filesystem that has access to the root cgroup", dirname); goto out_error; } r = mount(mp->mount_point, abs_path, "none", MS_BIND, 0); if (r < 0) { SYSERROR("error bind-mounting %s to %s", mp->mount_point, abs_path); goto out_error; } /* main cgroup path should be read-only */ if (type == LXC_AUTO_CGROUP_FULL_RO || type == LXC_AUTO_CGROUP_FULL_MIXED) { r = mount(NULL, abs_path, NULL, MS_REMOUNT|MS_BIND|MS_RDONLY, NULL); if (r < 0) { SYSERROR("error re-mounting %s readonly", abs_path); goto out_error; } } /* own cgroup should be read-write */ if (type == LXC_AUTO_CGROUP_FULL_MIXED) { r = mount(abs_path2, abs_path2, NULL, MS_BIND, NULL); if (r < 0) { SYSERROR("error bind-mounting %s onto itself", abs_path2); goto out_error; } r = mount(NULL, abs_path2, NULL, MS_REMOUNT|MS_BIND, NULL); if (r < 0) { SYSERROR("error re-mounting %s readwrite", abs_path2); goto out_error; } } } else { /* create path for container's cgroup */ r = mkdir_p(abs_path2, 0755); if (r < 0 && errno != EEXIST) { SYSERROR("could not create cgroup directory /sys/fs/cgroup/%s%s", dirname, info->cgroup_path); goto out_error; } /* for read-only and mixed cases, we have to bind-mount the tmpfs directory * that points to the hierarchy itself (i.e. /sys/fs/cgroup/cpu etc.) onto * itself and then bind-mount it read-only, since we keep the tmpfs itself * read-write (see comment below) */ if (type == LXC_AUTO_CGROUP_MIXED || type == LXC_AUTO_CGROUP_RO) { r = mount(abs_path, abs_path, NULL, MS_BIND, NULL); if (r < 0) { SYSERROR("error bind-mounting %s onto itself", abs_path); goto out_error; } r = mount(NULL, abs_path, NULL, MS_REMOUNT|MS_BIND|MS_RDONLY, NULL); if (r < 0) { SYSERROR("error re-mounting %s readonly", abs_path); goto out_error; } } free(abs_path); abs_path = NULL; /* bind-mount container's cgroup to that directory */ abs_path = cgroup_to_absolute_path(mp, info->cgroup_path, NULL); if (!abs_path) goto out_error; r = mount(abs_path, abs_path2, "none", MS_BIND, 0); if (r < 0 && is_crucial_hierarchy(info->hierarchy)) { SYSERROR("error bind-mounting %s to %s", abs_path, abs_path2); goto out_error; } if (type == LXC_AUTO_CGROUP_RO) { r = mount(NULL, abs_path2, NULL, MS_REMOUNT|MS_BIND|MS_RDONLY, NULL); if (r < 0) { SYSERROR("error re-mounting %s readonly", abs_path2); goto out_error; } } } free(abs_path); free(abs_path2); abs_path = NULL; abs_path2 = NULL; /* add symlinks for every single subsystem */ if (subsystem_count > 1) { for (i = 0; i < subsystem_count; i++) { abs_path = lxc_append_paths(path, parts[i]); if (!abs_path) goto out_error; r = symlink(dirname, abs_path); if (r < 0) WARN("could not create symlink %s -> %s in /sys/fs/cgroup of container", parts[i], dirname); free(abs_path); abs_path = NULL; } } free(dirname); free(parts); dirname = NULL; parts = NULL; } /* We used to remount the entire tmpfs readonly if any :ro or * :mixed mode was specified. However, Ubuntu's mountall has the * unfortunate behavior to block bootup if /sys/fs/cgroup is * mounted read-only and cannot be remounted read-write. * (mountall reads /lib/init/fstab and tries to (re-)mount all of * these if they are not already mounted with the right options; * it contains an entry for /sys/fs/cgroup. In case it can't do * that, it prompts for the user to either manually fix it or * boot anyway. But without user input, booting of the container * hangs.) * * Instead of remounting the entire tmpfs readonly, we only * remount the paths readonly that are part of the cgroup * hierarchy. */ free(path); return true; out_error: saved_errno = errno; free(path); free(dirname); free(parts); free(abs_path); free(abs_path2); errno = saved_errno; return false; } static int cgfs_nrtasks(void *hdata) { struct cgfs_data *d = hdata; struct cgroup_process_info *info; struct cgroup_mount_point *mp = NULL; char *abs_path = NULL; int ret; if (!d) { errno = ENOENT; return -1; } info = d->info; if (!info) { errno = ENOENT; return -1; } if (info->designated_mount_point) { mp = info->designated_mount_point; } else { mp = lxc_cgroup_find_mount_point(info->hierarchy, info->cgroup_path, false); if (!mp) return -1; } abs_path = cgroup_to_absolute_path(mp, info->cgroup_path, NULL); if (!abs_path) return -1; ret = cgroup_recursive_task_count(abs_path); free(abs_path); return ret; } static struct cgroup_process_info * lxc_cgroup_process_info_getx(const char *proc_pid_cgroup_str, struct cgroup_meta_data *meta) { struct cgroup_process_info *result = NULL; FILE *proc_pid_cgroup = NULL; char *line = NULL; size_t sz = 0; int saved_errno = 0; struct cgroup_process_info **cptr = &result; struct cgroup_process_info *entry = NULL; proc_pid_cgroup = fopen_cloexec(proc_pid_cgroup_str, "r"); if (!proc_pid_cgroup) return NULL; while (getline(&line, &sz, proc_pid_cgroup) != -1) { /* file format: hierarchy:subsystems:group */ char *colon1; char *colon2; char *endptr; int hierarchy_number; struct cgroup_hierarchy *h = NULL; if (!line[0]) continue; if (line[strlen(line) - 1] == '\n') line[strlen(line) - 1] = '\0'; colon1 = strchr(line, ':'); if (!colon1) continue; *colon1++ = '\0'; colon2 = strchr(colon1, ':'); if (!colon2) continue; *colon2++ = '\0'; endptr = NULL; /* With cgroupv2 /proc/self/cgroup can contain entries of the * form: 0::/ * These entries need to be skipped. */ if (!strcmp(colon1, "")) continue; hierarchy_number = strtoul(line, &endptr, 10); if (!endptr || *endptr) continue; if (hierarchy_number > meta->maximum_hierarchy) { /* we encountered a hierarchy we didn't have before, * so probably somebody remounted some stuff in the * mean time... */ errno = EAGAIN; goto out_error; } h = meta->hierarchies[hierarchy_number]; if (!h) { /* we encountered a hierarchy that was thought to be * dead before, so probably somebody remounted some * stuff in the mean time... */ errno = EAGAIN; goto out_error; } /* we are told that we should ignore this hierarchy */ if (!h->used) continue; entry = calloc(1, sizeof(struct cgroup_process_info)); if (!entry) goto out_error; entry->meta_ref = lxc_cgroup_get_meta(meta); entry->hierarchy = h; entry->cgroup_path = strdup(colon2); if (!entry->cgroup_path) goto out_error; prune_init_scope(entry->cgroup_path); *cptr = entry; cptr = &entry->next; entry = NULL; } fclose(proc_pid_cgroup); free(line); return result; out_error: saved_errno = errno; if (proc_pid_cgroup) fclose(proc_pid_cgroup); lxc_cgroup_process_info_free(result); lxc_cgroup_process_info_free(entry); free(line); errno = saved_errno; return NULL; } static char **subsystems_from_mount_options(const char *mount_options, char **kernel_list) { char *token, *str, *saveptr = NULL; char **result = NULL; size_t result_capacity = 0; size_t result_count = 0; int saved_errno; int r; str = alloca(strlen(mount_options)+1); strcpy(str, mount_options); for (; (token = strtok_r(str, ",", &saveptr)); str = NULL) { /* we have a subsystem if it's either in the list of * subsystems provided by the kernel OR if it starts * with name= for named hierarchies */ r = lxc_grow_array((void ***)&result, &result_capacity, result_count + 1, 12); if (r < 0) goto out_free; result[result_count + 1] = NULL; if (strncmp(token, "name=", 5) && !lxc_string_in_array(token, (const char **)kernel_list)) { // this is eg 'systemd' but the mount will be 'name=systemd' result[result_count] = malloc(strlen(token) + 6); if (result[result_count]) sprintf(result[result_count], "name=%s", token); } else result[result_count] = strdup(token); if (!result[result_count]) goto out_free; result_count++; } return result; out_free: saved_errno = errno; lxc_free_array((void**)result, free); errno = saved_errno; return NULL; } static void lxc_cgroup_mount_point_free(struct cgroup_mount_point *mp) { if (!mp) return; free(mp->mount_point); free(mp->mount_prefix); free(mp); } static void lxc_cgroup_hierarchy_free(struct cgroup_hierarchy *h) { if (!h) return; if (h->subsystems) { lxc_free_array((void **)h->subsystems, free); h->subsystems = NULL; } if (h->all_mount_points) { free(h->all_mount_points); h->all_mount_points = NULL; } free(h); h = NULL; } static bool is_valid_cgroup(const char *name) { const char *p; for (p = name; *p; p++) { /* Use the ASCII printable characters range(32 - 127) * is reasonable, we kick out 32(SPACE) because it'll * break legacy lxc-ls */ if (*p <= 32 || *p >= 127 || *p == '/') return false; } return strcmp(name, ".") != 0 && strcmp(name, "..") != 0; } static int create_or_remove_cgroup(bool do_remove, struct cgroup_mount_point *mp, const char *path, int recurse, struct lxc_conf *conf) { int r, saved_errno = 0; char *buf = cgroup_to_absolute_path(mp, path, NULL); if (!buf) return -1; /* create or remove directory */ if (do_remove) { if (!dir_exists(buf)) return 0; if (recurse) { if (conf && !lxc_list_empty(&conf->id_map)) r = userns_exec_1(conf, rmdir_wrapper, buf); else r = cgroup_rmdir(buf); } else r = rmdir(buf); } else r = mkdir_p(buf, 0777); saved_errno = errno; free(buf); errno = saved_errno; return r; } static int create_cgroup(struct cgroup_mount_point *mp, const char *path) { return create_or_remove_cgroup(false, mp, path, false, NULL); } static int remove_cgroup(struct cgroup_mount_point *mp, const char *path, bool recurse, struct lxc_conf *conf) { return create_or_remove_cgroup(true, mp, path, recurse, conf); } static char *cgroup_to_absolute_path(struct cgroup_mount_point *mp, const char *path, const char *suffix) { /* first we have to make sure we subtract the mount point's prefix */ char *prefix = mp->mount_prefix; char *buf; ssize_t len, rv; /* we want to make sure only absolute paths to cgroups are passed to us */ if (path[0] != '/') { errno = EINVAL; return NULL; } if (prefix && !strcmp(prefix, "/")) prefix = NULL; /* prefix doesn't match */ if (prefix && strncmp(prefix, path, strlen(prefix)) != 0) { errno = EINVAL; return NULL; } /* if prefix is /foo and path is /foobar */ if (prefix && path[strlen(prefix)] != '/' && path[strlen(prefix)] != '\0') { errno = EINVAL; return NULL; } /* remove prefix from path */ path += prefix ? strlen(prefix) : 0; len = strlen(mp->mount_point) + strlen(path) + (suffix ? strlen(suffix) : 0); buf = calloc(len + 1, 1); if (!buf) return NULL; rv = snprintf(buf, len + 1, "%s%s%s", mp->mount_point, path, suffix ? suffix : ""); if (rv > len) { free(buf); errno = ENOMEM; return NULL; } return buf; } static struct cgroup_process_info * find_info_for_subsystem(struct cgroup_process_info *info, const char *subsystem) { struct cgroup_process_info *info_ptr; for (info_ptr = info; info_ptr; info_ptr = info_ptr->next) { struct cgroup_hierarchy *h = info_ptr->hierarchy; if (!h) continue; if (lxc_string_in_array(subsystem, (const char **)h->subsystems)) return info_ptr; } errno = ENOENT; return NULL; } static int do_cgroup_get(const char *cgroup_path, const char *sub_filename, char *value, size_t len) { const char *parts[3] = { cgroup_path, sub_filename, NULL }; char *filename; int ret, saved_errno; filename = lxc_string_join("/", parts, false); if (!filename) return -1; ret = lxc_read_from_file(filename, value, len); saved_errno = errno; free(filename); errno = saved_errno; return ret; } static int do_cgroup_set(const char *cgroup_path, const char *sub_filename, const char *value) { const char *parts[3] = { cgroup_path, sub_filename, NULL }; char *filename; int ret, saved_errno; filename = lxc_string_join("/", parts, false); if (!filename) return -1; ret = lxc_write_to_file(filename, value, strlen(value), false); saved_errno = errno; free(filename); errno = saved_errno; return ret; } static int do_setup_cgroup_limits(struct cgfs_data *d, struct lxc_list *cgroup_settings, bool do_devices) { struct lxc_list *iterator, *sorted_cgroup_settings, *next; struct lxc_cgroup *cg; int ret = -1; if (lxc_list_empty(cgroup_settings)) return 0; sorted_cgroup_settings = sort_cgroup_settings(cgroup_settings); if (!sorted_cgroup_settings) { return -1; } lxc_list_for_each(iterator, sorted_cgroup_settings) { cg = iterator->elem; if (do_devices == !strncmp("devices", cg->subsystem, 7)) { if (strcmp(cg->subsystem, "devices.deny") == 0 && cgroup_devices_has_allow_or_deny(d, cg->value, false)) continue; if (strcmp(cg->subsystem, "devices.allow") == 0 && cgroup_devices_has_allow_or_deny(d, cg->value, true)) continue; if (lxc_cgroup_set_data(cg->subsystem, cg->value, d)) { if (do_devices && (errno == EACCES || errno == EPERM)) { WARN("Error setting %s to %s for %s", cg->subsystem, cg->value, d->name); continue; } SYSERROR("Error setting %s to %s for %s", cg->subsystem, cg->value, d->name); goto out; } } DEBUG("cgroup '%s' set to '%s'", cg->subsystem, cg->value); } ret = 0; INFO("cgroup has been setup"); out: lxc_list_for_each_safe(iterator, sorted_cgroup_settings, next) { lxc_list_del(iterator); free(iterator); } free(sorted_cgroup_settings); return ret; } static bool cgroup_devices_has_allow_or_deny(struct cgfs_data *d, char *v, bool for_allow) { char *path; FILE *devices_list; char *line = NULL; size_t sz = 0; bool ret = !for_allow; const char *parts[3] = { NULL, "devices.list", NULL }; // XXX FIXME if users could use something other than 'lxc.devices.deny = a'. // not sure they ever do, but they *could* // right now, I'm assuming they do NOT if (!for_allow && strcmp(v, "a") != 0 && strcmp(v, "a *:* rwm") != 0) return false; parts[0] = (const char *)lxc_cgroup_get_hierarchy_abs_path_data("devices", d); if (!parts[0]) return false; path = lxc_string_join("/", parts, false); if (!path) { free((void *)parts[0]); return false; } devices_list = fopen_cloexec(path, "r"); if (!devices_list) { free(path); return false; } while (getline(&line, &sz, devices_list) != -1) { size_t len = strlen(line); if (len > 0 && line[len-1] == '\n') line[len-1] = '\0'; if (strcmp(line, "a *:* rwm") == 0) { ret = for_allow; goto out; } else if (for_allow && strcmp(line, v) == 0) { ret = true; goto out; } } out: fclose(devices_list); free(line); free(path); return ret; } static int cgroup_recursive_task_count(const char *cgroup_path) { DIR *d; struct dirent *dent; int n = 0, r; d = opendir(cgroup_path); if (!d) return 0; while ((dent = readdir(d))) { const char *parts[3] = { cgroup_path, dent->d_name, NULL }; char *sub_path; struct stat st; if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) continue; sub_path = lxc_string_join("/", parts, false); if (!sub_path) { closedir(d); return -1; } r = stat(sub_path, &st); if (r < 0) { closedir(d); free(sub_path); return -1; } if (S_ISDIR(st.st_mode)) { r = cgroup_recursive_task_count(sub_path); if (r >= 0) n += r; } else if (!strcmp(dent->d_name, "tasks")) { r = lxc_count_file_lines(sub_path); if (r >= 0) n += r; } free(sub_path); } closedir(d); return n; } static int handle_cgroup_settings(struct cgroup_mount_point *mp, char *cgroup_path) { int r, saved_errno = 0; char buf[2]; mp->need_cpuset_init = false; /* If this is the memory cgroup, we want to enforce hierarchy. * But don't fail if for some reason we can't. */ if (lxc_string_in_array("memory", (const char **)mp->hierarchy->subsystems)) { char *cc_path = cgroup_to_absolute_path(mp, cgroup_path, "/memory.use_hierarchy"); if (cc_path) { r = lxc_read_from_file(cc_path, buf, 1); if (r < 1 || buf[0] != '1') { r = lxc_write_to_file(cc_path, "1", 1, false); if (r < 0) SYSERROR("failed to set memory.use_hierarchy to 1; continuing"); } free(cc_path); } } /* if this is a cpuset hierarchy, we have to set cgroup.clone_children in * the base cgroup, otherwise containers will start with an empty cpuset.mems * and cpuset.cpus and then */ if (lxc_string_in_array("cpuset", (const char **)mp->hierarchy->subsystems)) { char *cc_path = cgroup_to_absolute_path(mp, cgroup_path, "/cgroup.clone_children"); struct stat sb; if (!cc_path) return -1; /* cgroup.clone_children is not available when running under * older kernel versions; in this case, we'll initialize * cpuset.cpus and cpuset.mems later, after the new cgroup * was created */ if (stat(cc_path, &sb) != 0 && errno == ENOENT) { mp->need_cpuset_init = true; free(cc_path); return 0; } r = lxc_read_from_file(cc_path, buf, 1); if (r == 1 && buf[0] == '1') { free(cc_path); return 0; } r = lxc_write_to_file(cc_path, "1", 1, false); saved_errno = errno; free(cc_path); errno = saved_errno; return r < 0 ? -1 : 0; } return 0; } static int cgroup_read_from_file(const char *fn, char buf[], size_t bufsize) { int ret = lxc_read_from_file(fn, buf, bufsize); if (ret < 0) { SYSERROR("failed to read %s", fn); return ret; } if (ret == bufsize) { if (bufsize > 0) { /* obviously this wasn't empty */ buf[bufsize-1] = '\0'; return ret; } /* Callers don't do this, but regression/sanity check */ ERROR("%s: was not expecting 0 bufsize", __func__); return -1; } buf[ret] = '\0'; return ret; } static bool do_init_cpuset_file(struct cgroup_mount_point *mp, const char *path, const char *name) { char value[1024]; char *childfile, *parentfile = NULL, *tmp; int ret; bool ok = false; childfile = cgroup_to_absolute_path(mp, path, name); if (!childfile) return false; /* don't overwrite a non-empty value in the file */ ret = cgroup_read_from_file(childfile, value, sizeof(value)); if (ret < 0) goto out; if (value[0] != '\0' && value[0] != '\n') { ok = true; goto out; } /* path to the same name in the parent cgroup */ parentfile = strdup(path); if (!parentfile) goto out; tmp = strrchr(parentfile, '/'); if (!tmp) goto out; if (tmp == parentfile) tmp++; /* keep the '/' at the start */ *tmp = '\0'; tmp = parentfile; parentfile = cgroup_to_absolute_path(mp, tmp, name); free(tmp); if (!parentfile) goto out; /* copy from parent to child cgroup */ ret = cgroup_read_from_file(parentfile, value, sizeof(value)); if (ret < 0) goto out; if (ret == sizeof(value)) { /* If anyone actually sees this error, we can address it */ ERROR("parent cpuset value too long"); goto out; } ok = (lxc_write_to_file(childfile, value, strlen(value), false) >= 0); if (!ok) SYSERROR("failed writing %s", childfile); out: free(parentfile); free(childfile); return ok; } static bool init_cpuset_if_needed(struct cgroup_mount_point *mp, const char *path) { /* the files we have to handle here are only in cpuset hierarchies */ if (!lxc_string_in_array("cpuset", (const char **)mp->hierarchy->subsystems)) return true; if (!mp->need_cpuset_init) return true; return (do_init_cpuset_file(mp, path, "/cpuset.cpus") && do_init_cpuset_file(mp, path, "/cpuset.mems") ); } static void print_cgfs_init_debuginfo(struct cgfs_data *d) { int i; if (!getenv("LXC_DEBUG_CGFS")) return; DEBUG("Cgroup information:"); DEBUG(" container name: %s", d->name); if (!d->meta || !d->meta->hierarchies) { DEBUG(" No hierarchies found."); return; } DEBUG(" Controllers:"); for (i = 0; i <= d->meta->maximum_hierarchy; i++) { char **p; struct cgroup_hierarchy *h = d->meta->hierarchies[i]; if (!h) { DEBUG(" Empty hierarchy number %d.", i); continue; } for (p = h->subsystems; p && *p; p++) { DEBUG(" %2d: %s", i, *p); } } } struct cgroup_ops *cgfs_ops_init(void) { return &cgfs_ops; } static void *cgfs_init(const char *name) { struct cgfs_data *d; d = malloc(sizeof(*d)); if (!d) return NULL; memset(d, 0, sizeof(*d)); d->name = strdup(name); if (!d->name) goto err1; d->cgroup_pattern = lxc_global_config_value("lxc.cgroup.pattern"); d->meta = lxc_cgroup_load_meta(); if (!d->meta) { ERROR("cgroupfs failed to detect cgroup metadata"); goto err2; } print_cgfs_init_debuginfo(d); return d; err2: free(d->name); err1: free(d); return NULL; } static void cgfs_destroy(void *hdata, struct lxc_conf *conf) { struct cgfs_data *d = hdata; if (!d) return; free(d->name); lxc_cgroup_process_info_free_and_remove(d->info, conf); lxc_cgroup_put_meta(d->meta); free(d); } static inline bool cgfs_create(void *hdata) { struct cgfs_data *d = hdata; struct cgroup_process_info *i; struct cgroup_meta_data *md; if (!d) return false; md = d->meta; i = lxc_cgroupfs_create(d->name, d->cgroup_pattern, md, NULL); if (!i) return false; d->info = i; return true; } static inline bool cgfs_enter(void *hdata, pid_t pid) { struct cgfs_data *d = hdata; struct cgroup_process_info *i; int ret; if (!d) return false; i = d->info; ret = lxc_cgroupfs_enter(i, pid, false); return ret == 0; } static inline bool cgfs_create_legacy(void *hdata, pid_t pid) { struct cgfs_data *d = hdata; struct cgroup_process_info *i; if (!d) return false; i = d->info; if (lxc_cgroup_create_legacy(i, d->name, pid) < 0) { ERROR("failed to create legacy ns cgroups for '%s'", d->name); return false; } return true; } static const char *cgfs_get_cgroup(void *hdata, const char *subsystem) { struct cgfs_data *d = hdata; if (!d) return NULL; return lxc_cgroup_get_hierarchy_path_data(subsystem, d); } static bool cgfs_escape(void *hdata) { struct cgroup_meta_data *md; int i; bool ret = false; md = lxc_cgroup_load_meta(); if (!md) return false; for (i = 0; i <= md->maximum_hierarchy; i++) { struct cgroup_hierarchy *h = md->hierarchies[i]; struct cgroup_mount_point *mp; char *tasks; FILE *f; int written; if (!h) { WARN("not escaping hierarchy %d", i); continue; } mp = lxc_cgroup_find_mount_point(h, "/", true); if (!mp) goto out; tasks = cgroup_to_absolute_path(mp, "/", "tasks"); if (!tasks) goto out; f = fopen(tasks, "a"); free(tasks); if (!f) goto out; written = fprintf(f, "%d\n", getpid()); fclose(f); if (written < 0) { SYSERROR("writing tasks failed\n"); goto out; } } ret = true; out: lxc_cgroup_put_meta(md); return ret; } static int cgfs_num_hierarchies(void) { /* not implemented */ return -1; } static bool cgfs_get_hierarchies(int i, char ***out) { /* not implemented */ return false; } static bool cgfs_unfreeze(void *hdata) { struct cgfs_data *d = hdata; char *cgabspath, *cgrelpath; int ret; if (!d) return false; cgrelpath = lxc_cgroup_get_hierarchy_path_data("freezer", d); cgabspath = lxc_cgroup_find_abs_path("freezer", cgrelpath, true, NULL); if (!cgabspath) return false; ret = do_cgroup_set(cgabspath, "freezer.state", "THAWED"); free(cgabspath); return ret == 0; } static bool cgroupfs_setup_limits(void *hdata, struct lxc_list *cgroup_conf, bool with_devices) { struct cgfs_data *d = hdata; if (!d) return false; return do_setup_cgroup_limits(d, cgroup_conf, with_devices) == 0; } static bool lxc_cgroupfs_attach(const char *name, const char *lxcpath, pid_t pid) { struct cgroup_meta_data *meta_data; struct cgroup_process_info *container_info; int ret; meta_data = lxc_cgroup_load_meta(); if (!meta_data) { ERROR("could not move attached process %d to cgroup of container", pid); return false; } container_info = lxc_cgroup_get_container_info(name, lxcpath, meta_data); lxc_cgroup_put_meta(meta_data); if (!container_info) { ERROR("could not move attached process %d to cgroup of container", pid); return false; } ret = lxc_cgroupfs_enter(container_info, pid, false); lxc_cgroup_process_info_free(container_info); if (ret < 0) { ERROR("could not move attached process %d to cgroup of container", pid); return false; } return true; } struct chown_data { const char *cgroup_path; uid_t origuid; }; /* * TODO - someone should refactor this to unshare once passing all the paths * to be chowned in one go */ static int chown_cgroup_wrapper(void *data) { struct chown_data *arg = data; uid_t destuid; char *fpath; if (setresgid(0,0,0) < 0) SYSERROR("Failed to setgid to 0"); if (setresuid(0,0,0) < 0) SYSERROR("Failed to setuid to 0"); if (setgroups(0, NULL) < 0) SYSERROR("Failed to clear groups"); destuid = get_ns_uid(arg->origuid); if (chown(arg->cgroup_path, destuid, 0) < 0) SYSERROR("Failed chowning %s to %d", arg->cgroup_path, (int)destuid); fpath = lxc_append_paths(arg->cgroup_path, "tasks"); if (!fpath) return -1; if (chown(fpath, destuid, 0) < 0) SYSERROR("Error chowning %s\n", fpath); free(fpath); fpath = lxc_append_paths(arg->cgroup_path, "cgroup.procs"); if (!fpath) return -1; if (chown(fpath, destuid, 0) < 0) SYSERROR("Error chowning %s", fpath); free(fpath); return 0; } static bool do_cgfs_chown(char *cgroup_path, struct lxc_conf *conf) { struct chown_data data; char *fpath; if (!dir_exists(cgroup_path)) return true; if (lxc_list_empty(&conf->id_map)) /* If there's no mapping then we don't need to chown */ return true; data.cgroup_path = cgroup_path; data.origuid = geteuid(); /* Unpriv users can't chown it themselves, so chown from * a child namespace mapping both our own and the target uid */ if (userns_exec_1(conf, chown_cgroup_wrapper, &data) < 0) { ERROR("Error requesting cgroup chown in new namespace"); return false; } /* * Now chmod 775 the directory else the container cannot create cgroups. * This can't be done in the child namespace because it only group-owns * the cgroup */ if (chmod(cgroup_path, 0775) < 0) { SYSERROR("Error chmoding %s\n", cgroup_path); return false; } fpath = lxc_append_paths(cgroup_path, "tasks"); if (!fpath) return false; if (chmod(fpath, 0664) < 0) SYSERROR("Error chmoding %s\n", fpath); free(fpath); fpath = lxc_append_paths(cgroup_path, "cgroup.procs"); if (!fpath) return false; if (chmod(fpath, 0664) < 0) SYSERROR("Error chmoding %s\n", fpath); free(fpath); return true; } static bool cgfs_chown(void *hdata, struct lxc_conf *conf) { struct cgfs_data *d = hdata; struct cgroup_process_info *info_ptr; char *cgpath; bool r = true; if (!d) return false; for (info_ptr = d->info; info_ptr; info_ptr = info_ptr->next) { if (!info_ptr->hierarchy) continue; if (!info_ptr->designated_mount_point) { info_ptr->designated_mount_point = lxc_cgroup_find_mount_point(info_ptr->hierarchy, info_ptr->cgroup_path, true); if (!info_ptr->designated_mount_point) { SYSERROR("Could not chown cgroup %s: internal error (couldn't find any writable mountpoint to cgroup filesystem)", info_ptr->cgroup_path); return false; } } cgpath = cgroup_to_absolute_path(info_ptr->designated_mount_point, info_ptr->cgroup_path, NULL); if (!cgpath) { SYSERROR("Could not chown cgroup %s: internal error", info_ptr->cgroup_path); continue; } r = do_cgfs_chown(cgpath, conf); if (!r && is_crucial_hierarchy(info_ptr->hierarchy)) { ERROR("Failed chowning %s\n", cgpath); free(cgpath); return false; } free(cgpath); } return true; } static struct cgroup_ops cgfs_ops = { .init = cgfs_init, .destroy = cgfs_destroy, .create = cgfs_create, .enter = cgfs_enter, .create_legacy = cgfs_create_legacy, .get_cgroup = cgfs_get_cgroup, .escape = cgfs_escape, .num_hierarchies = cgfs_num_hierarchies, .get_hierarchies = cgfs_get_hierarchies, .get = lxc_cgroupfs_get, .set = lxc_cgroupfs_set, .unfreeze = cgfs_unfreeze, .setup_limits = cgroupfs_setup_limits, .name = "cgroupfs", .attach = lxc_cgroupfs_attach, .chown = cgfs_chown, .mount_cgroup = cgroupfs_mount_cgroup, .nrtasks = cgfs_nrtasks, .driver = CGFS, }; lxc-2.0.8/src/lxc/cgroups/cgfsng.c0000644061062106075000000013443213105116772013724 00000000000000/* * lxc: linux Container library * * Copyright © 2016 Canonical Ltd. * * Authors: * Serge Hallyn * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* * cgfs-ng.c: this is a new, simplified implementation of a filesystem * cgroup backend. The original cgfs.c was designed to be as flexible * as possible. It would try to find cgroup filesystems no matter where * or how you had them mounted, and deduce the most usable mount for * each controller. It also was not designed for unprivileged use, as * that was reserved for cgmanager. * * This new implementation assumes that cgroup filesystems are mounted * under /sys/fs/cgroup/clist where clist is either the controller, or * a comman-separated list of controllers. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include "bdev.h" #include "cgroup.h" #include "commands.h" #include "log.h" #include "utils.h" lxc_log_define(lxc_cgfsng, lxc); static struct cgroup_ops cgfsng_ops; /* * A descriptor for a mounted hierarchy * @controllers: either NULL, or a null-terminated list of all * the co-mounted controllers * @mountpoint: the mountpoint we will use. It will be either * /sys/fs/cgroup/controller or /sys/fs/cgroup/controllerlist * @base_cgroup: the cgroup under which the container cgroup path is created. This will be either the caller's cgroup (if not root), or init's cgroup (if root). */ struct hierarchy { char **controllers; char *mountpoint; char *base_cgroup; char *fullcgpath; }; /* * The cgroup data which is attached to the lxc_handler. * @cgroup_pattern - a copy of the lxc.cgroup.pattern * @container_cgroup - if not null, the cgroup which was created for * the container. For each hierarchy, it is created under the * @hierarchy->base_cgroup directory. Relative to the base_cgroup * it is the same for all hierarchies. * @name - the container name */ struct cgfsng_handler_data { char *cgroup_pattern; char *container_cgroup; // cgroup we created for the container char *name; // container name }; /* * @hierarchies - a NULL-terminated array of struct hierarchy, one per * hierarchy. No duplicates. First sufficient, writeable mounted * hierarchy wins */ struct hierarchy **hierarchies; /* * @cgroup_use - a copy of the lxc.cgroup.use */ char *cgroup_use; /* * @lxc_cgfsng_debug - whether to print debug info to stdout for the cgfsng * driver */ static bool lxc_cgfsng_debug; static void free_string_list(char **clist) { if (clist) { int i; for (i = 0; clist[i]; i++) free(clist[i]); free(clist); } } /* Re-alllocate a pointer, do not fail */ static void *must_realloc(void *orig, size_t sz) { void *ret; do { ret = realloc(orig, sz); } while (!ret); return ret; } /* Allocate a pointer, do not fail */ static void *must_alloc(size_t sz) { return must_realloc(NULL, sz); } /* return copy of string @entry; do not fail. */ static char *must_copy_string(const char *entry) { char *ret; if (!entry) return NULL; do { ret = strdup(entry); } while (!ret); return ret; } /* * This is a special case - return a copy of @entry * prepending 'name='. I.e. turn systemd into name=systemd. * Do not fail. */ static char *must_prefix_named(char *entry) { char *ret; size_t len = strlen(entry); ret = must_alloc(len + 6); snprintf(ret, len + 6, "name=%s", entry); return ret; } /* * Given a pointer to a null-terminated array of pointers, realloc to * add one entry, and point the new entry to NULL. Do not fail. Return * the index to the second-to-last entry - that is, the one which is * now available for use (keeping the list null-terminated). */ static int append_null_to_list(void ***list) { int newentry = 0; if (*list) for (; (*list)[newentry]; newentry++); *list = must_realloc(*list, (newentry + 2) * sizeof(void **)); (*list)[newentry + 1] = NULL; return newentry; } /* * Given a null-terminated array of strings, check whether @entry * is one of the strings */ static bool string_in_list(char **list, const char *entry) { int i; if (!list) return false; for (i = 0; list[i]; i++) if (strcmp(list[i], entry) == 0) return true; return false; } /* * append an entry to the clist. Do not fail. * *clist must be NULL the first time we are called. * * We also handle named subsystems here. Any controller which is not a * kernel subsystem, we prefix 'name='. Any which is both a kernel and * named subsystem, we refuse to use because we're not sure which we * have here. (TODO - we could work around this in some cases by just * remounting to be unambiguous, or by comparing mountpoint contents * with current cgroup) * * The last entry will always be NULL. */ static void must_append_controller(char **klist, char **nlist, char ***clist, char *entry) { int newentry; char *copy; if (string_in_list(klist, entry) && string_in_list(nlist, entry)) { ERROR("Refusing to use ambiguous controller '%s'", entry); ERROR("It is both a named and kernel subsystem"); return; } newentry = append_null_to_list((void ***)clist); if (strncmp(entry, "name=", 5) == 0) copy = must_copy_string(entry); else if (string_in_list(klist, entry)) copy = must_copy_string(entry); else copy = must_prefix_named(entry); (*clist)[newentry] = copy; } static void free_handler_data(struct cgfsng_handler_data *d) { free(d->cgroup_pattern); free(d->container_cgroup); free(d->name); free(d); } /* * Given a handler's cgroup data, return the struct hierarchy for the * controller @c, or NULL if there is none. */ struct hierarchy *get_hierarchy(const char *c) { int i; if (!hierarchies) return NULL; for (i = 0; hierarchies[i]; i++) { if (string_in_list(hierarchies[i]->controllers, c)) return hierarchies[i]; } return NULL; } static char *must_make_path(const char *first, ...) __attribute__((sentinel)); #define BATCH_SIZE 50 static void batch_realloc(char **mem, size_t oldlen, size_t newlen) { int newbatches = (newlen / BATCH_SIZE) + 1; int oldbatches = (oldlen / BATCH_SIZE) + 1; if (!*mem || newbatches > oldbatches) { *mem = must_realloc(*mem, newbatches * BATCH_SIZE); } } static void append_line(char **dest, size_t oldlen, char *new, size_t newlen) { size_t full = oldlen + newlen; batch_realloc(dest, oldlen, full + 1); memcpy(*dest + oldlen, new, newlen + 1); } /* Slurp in a whole file */ static char *read_file(char *fnam) { FILE *f; char *line = NULL, *buf = NULL; size_t len = 0, fulllen = 0; int linelen; f = fopen(fnam, "r"); if (!f) return NULL; while ((linelen = getline(&line, &len, f)) != -1) { append_line(&buf, fulllen, line, linelen); fulllen += linelen; } fclose(f); free(line); return buf; } /* Taken over modified from the kernel sources. */ #define NBITS 32 /* bits in uint32_t */ #define DIV_ROUND_UP(n, d) (((n) + (d)-1) / (d)) #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, NBITS) static void set_bit(unsigned bit, uint32_t *bitarr) { bitarr[bit / NBITS] |= (1 << (bit % NBITS)); } static void clear_bit(unsigned bit, uint32_t *bitarr) { bitarr[bit / NBITS] &= ~(1 << (bit % NBITS)); } static bool is_set(unsigned bit, uint32_t *bitarr) { return (bitarr[bit / NBITS] & (1 << (bit % NBITS))) != 0; } /* Create cpumask from cpulist aka turn: * * 0,2-3 * * into bit array * * 1 0 1 1 */ static uint32_t *lxc_cpumask(char *buf, size_t nbits) { char *token; char *saveptr = NULL; size_t arrlen = BITS_TO_LONGS(nbits); uint32_t *bitarr = calloc(arrlen, sizeof(uint32_t)); if (!bitarr) return NULL; for (; (token = strtok_r(buf, ",", &saveptr)); buf = NULL) { errno = 0; unsigned start = strtoul(token, NULL, 0); unsigned end = start; char *range = strchr(token, '-'); if (range) end = strtoul(range + 1, NULL, 0); if (!(start <= end)) { free(bitarr); return NULL; } if (end >= nbits) { free(bitarr); return NULL; } while (start <= end) set_bit(start++, bitarr); } return bitarr; } /* Turn cpumask into simple, comma-separated cpulist. */ static char *lxc_cpumask_to_cpulist(uint32_t *bitarr, size_t nbits) { size_t i; int ret; char numstr[LXC_NUMSTRLEN64] = {0}; char **cpulist = NULL; for (i = 0; i <= nbits; i++) { if (is_set(i, bitarr)) { ret = snprintf(numstr, LXC_NUMSTRLEN64, "%zu", i); if (ret < 0 || (size_t)ret >= LXC_NUMSTRLEN64) { lxc_free_array((void **)cpulist, free); return NULL; } if (lxc_append_string(&cpulist, numstr) < 0) { lxc_free_array((void **)cpulist, free); return NULL; } } } return lxc_string_join(",", (const char **)cpulist, false); } static ssize_t get_max_cpus(char *cpulist) { char *c1, *c2; char *maxcpus = cpulist; size_t cpus = 0; c1 = strrchr(maxcpus, ','); if (c1) c1++; c2 = strrchr(maxcpus, '-'); if (c2) c2++; if (!c1 && !c2) c1 = maxcpus; else if (c1 > c2) c2 = c1; else if (c1 < c2) c1 = c2; else if (!c1 && c2) // The reverse case is obvs. not needed. c1 = c2; /* If the above logic is correct, c1 should always hold a valid string * here. */ errno = 0; cpus = strtoul(c1, NULL, 0); if (errno != 0) return -1; return cpus; } #define __ISOL_CPUS "/sys/devices/system/cpu/isolated" static bool filter_and_set_cpus(char *path, bool am_initialized) { char *lastslash, *fpath, oldv; int ret; ssize_t i; ssize_t maxposs = 0, maxisol = 0; char *cpulist = NULL, *posscpus = NULL, *isolcpus = NULL; uint32_t *possmask = NULL, *isolmask = NULL; bool bret = false, flipped_bit = false; lastslash = strrchr(path, '/'); if (!lastslash) { // bug... this shouldn't be possible ERROR("Invalid path: %s.", path); return bret; } oldv = *lastslash; *lastslash = '\0'; fpath = must_make_path(path, "cpuset.cpus", NULL); posscpus = read_file(fpath); if (!posscpus) { SYSERROR("Could not read file: %s.\n", fpath); goto on_error; } /* Get maximum number of cpus found in possible cpuset. */ maxposs = get_max_cpus(posscpus); if (maxposs < 0) goto on_error; if (!file_exists(__ISOL_CPUS)) { /* This system doesn't expose isolated cpus. */ DEBUG("Path: "__ISOL_CPUS" to read isolated cpus from does not exist.\n"); cpulist = posscpus; /* No isolated cpus but we weren't already initialized by * someone. We should simply copy the parents cpuset.cpus * values. */ if (!am_initialized) { DEBUG("Copying cpuset of parent cgroup."); goto copy_parent; } /* No isolated cpus but we were already initialized by someone. * Nothing more to do for us. */ goto on_success; } isolcpus = read_file(__ISOL_CPUS); if (!isolcpus) { SYSERROR("Could not read file "__ISOL_CPUS); goto on_error; } if (!isdigit(isolcpus[0])) { DEBUG("No isolated cpus detected."); cpulist = posscpus; /* No isolated cpus but we weren't already initialized by * someone. We should simply copy the parents cpuset.cpus * values. */ if (!am_initialized) { DEBUG("Copying cpuset of parent cgroup."); goto copy_parent; } /* No isolated cpus but we were already initialized by someone. * Nothing more to do for us. */ goto on_success; } /* Get maximum number of cpus found in isolated cpuset. */ maxisol = get_max_cpus(isolcpus); if (maxisol < 0) goto on_error; if (maxposs < maxisol) maxposs = maxisol; maxposs++; possmask = lxc_cpumask(posscpus, maxposs); if (!possmask) { ERROR("Could not create cpumask for all possible cpus.\n"); goto on_error; } isolmask = lxc_cpumask(isolcpus, maxposs); if (!isolmask) { ERROR("Could not create cpumask for all isolated cpus.\n"); goto on_error; } for (i = 0; i <= maxposs; i++) { if (is_set(i, isolmask) && is_set(i, possmask)) { flipped_bit = true; clear_bit(i, possmask); } } if (!flipped_bit) { DEBUG("No isolated cpus present in cpuset."); goto on_success; } DEBUG("Removed isolated cpus from cpuset."); cpulist = lxc_cpumask_to_cpulist(possmask, maxposs); if (!cpulist) { ERROR("Could not create cpu list.\n"); goto on_error; } copy_parent: *lastslash = oldv; fpath = must_make_path(path, "cpuset.cpus", NULL); ret = lxc_write_to_file(fpath, cpulist, strlen(cpulist), false); if (ret < 0) { SYSERROR("Could not write cpu list to: %s.\n", fpath); goto on_error; } on_success: bret = true; on_error: free(fpath); free(isolcpus); free(isolmask); if (posscpus != cpulist) free(posscpus); free(possmask); free(cpulist); return bret; } /* Copy contents of parent(@path)/@file to @path/@file */ static bool copy_parent_file(char *path, char *file) { char *lastslash, *value = NULL, *fpath, oldv; int len = 0; int ret; lastslash = strrchr(path, '/'); if (!lastslash) { // bug... this shouldn't be possible ERROR("cgfsng:copy_parent_file: bad path %s", path); return false; } oldv = *lastslash; *lastslash = '\0'; fpath = must_make_path(path, file, NULL); len = lxc_read_from_file(fpath, NULL, 0); if (len <= 0) goto bad; value = must_alloc(len + 1); if (lxc_read_from_file(fpath, value, len) != len) goto bad; free(fpath); *lastslash = oldv; fpath = must_make_path(path, file, NULL); ret = lxc_write_to_file(fpath, value, len, false); if (ret < 0) SYSERROR("Unable to write %s to %s", value, fpath); free(fpath); free(value); return ret >= 0; bad: SYSERROR("Error reading '%s'", fpath); free(fpath); free(value); return false; } /* * Initialize the cpuset hierarchy in first directory of @gname and * set cgroup.clone_children so that children inherit settings. * Since the h->base_path is populated by init or ourselves, we know * it is already initialized. */ static bool handle_cpuset_hierarchy(struct hierarchy *h, char *cgname) { char *cgpath, *clonechildrenpath, v, *slash; if (!string_in_list(h->controllers, "cpuset")) return true; if (*cgname == '/') cgname++; slash = strchr(cgname, '/'); if (slash) *slash = '\0'; cgpath = must_make_path(h->mountpoint, h->base_cgroup, cgname, NULL); if (slash) *slash = '/'; if (mkdir(cgpath, 0755) < 0 && errno != EEXIST) { SYSERROR("Failed to create '%s'", cgpath); free(cgpath); return false; } clonechildrenpath = must_make_path(cgpath, "cgroup.clone_children", NULL); if (!file_exists(clonechildrenpath)) { /* unified hierarchy doesn't have clone_children */ free(clonechildrenpath); free(cgpath); return true; } if (lxc_read_from_file(clonechildrenpath, &v, 1) < 0) { SYSERROR("Failed to read '%s'", clonechildrenpath); free(clonechildrenpath); free(cgpath); return false; } /* Make sure any isolated cpus are removed from cpuset.cpus. */ if (!filter_and_set_cpus(cgpath, v == '1')) { SYSERROR("Failed to remove isolated cpus."); free(clonechildrenpath); free(cgpath); return false; } if (v == '1') { /* already set for us by someone else */ DEBUG("\"cgroup.clone_children\" was already set to \"1\"."); free(clonechildrenpath); free(cgpath); return true; } /* copy parent's settings */ if (!copy_parent_file(cgpath, "cpuset.mems")) { SYSERROR("Failed to copy \"cpuset.mems\" settings."); free(cgpath); free(clonechildrenpath); return false; } free(cgpath); if (lxc_write_to_file(clonechildrenpath, "1", 1, false) < 0) { /* Set clone_children so children inherit our settings */ SYSERROR("Failed to write 1 to %s", clonechildrenpath); free(clonechildrenpath); return false; } free(clonechildrenpath); return true; } /* * Given two null-terminated lists of strings, return true if any string * is in both. */ static bool controller_lists_intersect(char **l1, char **l2) { int i; if (!l1 || !l2) return false; for (i = 0; l1[i]; i++) { if (string_in_list(l2, l1[i])) return true; } return false; } /* * For a null-terminated list of controllers @clist, return true if any of * those controllers is already listed the null-terminated list of * hierarchies @hlist. Realistically, if one is present, all must be present. */ static bool controller_list_is_dup(struct hierarchy **hlist, char **clist) { int i; if (!hlist) return false; for (i = 0; hlist[i]; i++) if (controller_lists_intersect(hlist[i]->controllers, clist)) return true; return false; } /* * Return true if the controller @entry is found in the null-terminated * list of hierarchies @hlist */ static bool controller_found(struct hierarchy **hlist, char *entry) { int i; if (!hlist) return false; for (i = 0; hlist[i]; i++) if (string_in_list(hlist[i]->controllers, entry)) return true; return false; } /* * Return true if all of the controllers which we require have been found. * The required list is freezer and anything in * lxc.cgroup.use. */ static bool all_controllers_found(void) { char *p, *saveptr = NULL; struct hierarchy ** hlist = hierarchies; if (!controller_found(hlist, "freezer")) { ERROR("no freezer controller mountpoint found"); return false; } if (!cgroup_use) return true; for (p = strtok_r(cgroup_use, ",", &saveptr); p; p = strtok_r(NULL, ",", &saveptr)) { if (!controller_found(hlist, p)) { ERROR("no %s controller mountpoint found", p); return false; } } return true; } /* Return true if the fs type is fuse.lxcfs */ static bool is_lxcfs(const char *line) { char *p = strstr(line, " - "); if (!p) return false; return strncmp(p, " - fuse.lxcfs ", 14) == 0; } /* * Get the controllers from a mountinfo line * There are other ways we could get this info. For lxcfs, field 3 * is /cgroup/controller-list. For cgroupfs, we could parse the mount * options. But we simply assume that the mountpoint must be * /sys/fs/cgroup/controller-list */ static char **get_controllers(char **klist, char **nlist, char *line) { // the fourth field is /sys/fs/cgroup/comma-delimited-controller-list int i; char *p = line, *p2, *tok, *saveptr = NULL; char **aret = NULL; for (i = 0; i < 4; i++) { p = strchr(p, ' '); if (!p) return NULL; p++; } if (!p) return NULL; /* note - if we change how mountinfo works, then our caller * will need to verify /sys/fs/cgroup/ in this field */ if (strncmp(p, "/sys/fs/cgroup/", 15) != 0) return NULL; p += 15; p2 = strchr(p, ' '); if (!p2) { ERROR("corrupt mountinfo"); return NULL; } *p2 = '\0'; for (tok = strtok_r(p, ",", &saveptr); tok; tok = strtok_r(NULL, ",", &saveptr)) { must_append_controller(klist, nlist, &aret, tok); } return aret; } /* return true if the fstype is cgroup */ static bool is_cgroupfs(char *line) { char *p = strstr(line, " - "); if (!p) return false; return strncmp(p, " - cgroup ", 10) == 0; } /* Add a controller to our list of hierarchies */ static void add_controller(char **clist, char *mountpoint, char *base_cgroup) { struct hierarchy *new; int newentry; new = must_alloc(sizeof(*new)); new->controllers = clist; new->mountpoint = mountpoint; new->base_cgroup = base_cgroup; new->fullcgpath = NULL; newentry = append_null_to_list((void ***)&hierarchies); hierarchies[newentry] = new; } /* * Get a copy of the mountpoint from @line, which is a line from * /proc/self/mountinfo */ static char *get_mountpoint(char *line) { int i; char *p = line, *sret; size_t len; for (i = 0; i < 4; i++) { p = strchr(p, ' '); if (!p) return NULL; p++; } /* we've already stuck a \0 after the mountpoint */ len = strlen(p); sret = must_alloc(len + 1); memcpy(sret, p, len); sret[len] = '\0'; return sret; } /* * Given a multi-line string, return a null-terminated copy of the * current line. */ static char *copy_to_eol(char *p) { char *p2 = strchr(p, '\n'), *sret; size_t len; if (!p2) return NULL; len = p2 - p; sret = must_alloc(len + 1); memcpy(sret, p, len); sret[len] = '\0'; return sret; } /* * cgline: pointer to character after the first ':' in a line in a * \n-terminated /proc/self/cgroup file. Check whether * controller c is * present. */ static bool controller_in_clist(char *cgline, char *c) { char *tok, *saveptr = NULL, *eol, *tmp; size_t len; eol = strchr(cgline, ':'); if (!eol) return false; len = eol - cgline; tmp = alloca(len + 1); memcpy(tmp, cgline, len); tmp[len] = '\0'; for (tok = strtok_r(tmp, ",", &saveptr); tok; tok = strtok_r(NULL, ",", &saveptr)) { if (strcmp(tok, c) == 0) return true; } return false; } /* * @basecginfo is a copy of /proc/$$/cgroup. Return the current * cgroup for @controller */ static char *get_current_cgroup(char *basecginfo, char *controller) { char *p = basecginfo; while (1) { p = strchr(p, ':'); if (!p) return NULL; p++; if (controller_in_clist(p, controller)) { p = strchr(p, ':'); if (!p) return NULL; p++; return copy_to_eol(p); } p = strchr(p, '\n'); if (!p) return NULL; p++; } } /* * Given a hierarchy @mountpoint and base @path, verify that we can create * directories underneath it. */ static bool test_writeable(char *mountpoint, char *path) { char *fullpath = must_make_path(mountpoint, path, NULL); int ret; ret = access(fullpath, W_OK); free(fullpath); return ret == 0; } static void must_append_string(char ***list, char *entry) { int newentry = append_null_to_list((void ***)list); char *copy; copy = must_copy_string(entry); (*list)[newentry] = copy; } static void get_existing_subsystems(char ***klist, char ***nlist) { FILE *f; char *line = NULL; size_t len = 0; if ((f = fopen("/proc/self/cgroup", "r")) == NULL) return; while (getline(&line, &len, f) != -1) { char *p, *p2, *tok, *saveptr = NULL; p = strchr(line, ':'); if (!p) continue; p++; p2 = strchr(p, ':'); if (!p2) continue; *p2 = '\0'; /* If we have a mixture between cgroup v1 and cgroup v2 * hierarchies, then /proc/self/cgroup contains entries of the * form: * * 0::/some/path * * We need to skip those. */ if ((p2 - p) == 0) continue; for (tok = strtok_r(p, ",", &saveptr); tok; tok = strtok_r(NULL, ",", &saveptr)) { if (strncmp(tok, "name=", 5) == 0) must_append_string(nlist, tok); else must_append_string(klist, tok); } } free(line); fclose(f); } static void trim(char *s) { size_t len = strlen(s); while ((len > 1) && (s[len - 1] == '\n')) s[--len] = '\0'; } static void lxc_cgfsng_print_handler_data(const struct cgfsng_handler_data *d) { printf("Cgroup information:\n"); printf(" container name: %s\n", d->name ? d->name : "(null)"); printf(" lxc.cgroup.use: %s\n", cgroup_use ? cgroup_use : "(null)"); printf(" lxc.cgroup.pattern: %s\n", d->cgroup_pattern ? d->cgroup_pattern : "(null)"); printf(" cgroup: %s\n", d->container_cgroup ? d->container_cgroup : "(null)"); } static void lxc_cgfsng_print_hierarchies() { struct hierarchy **it; int i; if (!hierarchies) { printf(" No hierarchies found."); return; } printf(" Hierarchies:\n"); for (i = 0, it = hierarchies; it && *it; it++, i++) { char **cit; int j; printf(" %d: base_cgroup %s\n", i, (*it)->base_cgroup ? (*it)->base_cgroup : "(null)"); printf(" mountpoint %s\n", (*it)->mountpoint ? (*it)->mountpoint : "(null)"); printf(" controllers:\n"); for (j = 0, cit = (*it)->controllers; cit && *cit; cit++, j++) printf(" %d: %s\n", j, *cit); } } static void lxc_cgfsng_print_basecg_debuginfo(char *basecginfo, char **klist, char **nlist) { int k; char **it; printf("basecginfo is:\n"); printf("%s\n", basecginfo); for (k = 0, it = klist; it && *it; it++, k++) printf("kernel subsystem %d: %s\n", k, *it); for (k = 0, it = nlist; it && *it; it++, k++) printf("named subsystem %d: %s\n", k, *it); } static void lxc_cgfsng_print_debuginfo(const struct cgfsng_handler_data *d) { lxc_cgfsng_print_handler_data(d); lxc_cgfsng_print_hierarchies(); } /* * At startup, parse_hierarchies finds all the info we need about * cgroup mountpoints and current cgroups, and stores it in @d. */ static bool parse_hierarchies(void) { FILE *f; char * line = NULL, *basecginfo; char **klist = NULL, **nlist = NULL; size_t len = 0; /* * Root spawned containers escape the current cgroup, so use init's * cgroups as our base in that case. */ if (geteuid()) basecginfo = read_file("/proc/self/cgroup"); else basecginfo = read_file("/proc/1/cgroup"); if (!basecginfo) return false; if ((f = fopen("/proc/self/mountinfo", "r")) == NULL) { SYSERROR("Failed opening /proc/self/mountinfo"); return false; } get_existing_subsystems(&klist, &nlist); if (lxc_cgfsng_debug) lxc_cgfsng_print_basecg_debuginfo(basecginfo, klist, nlist); /* we support simple cgroup mounts and lxcfs mounts */ while (getline(&line, &len, f) != -1) { char **controller_list = NULL; char *mountpoint, *base_cgroup; if (!is_lxcfs(line) && !is_cgroupfs(line)) continue; controller_list = get_controllers(klist, nlist, line); if (!controller_list) continue; if (controller_list_is_dup(hierarchies, controller_list)) { free(controller_list); continue; } mountpoint = get_mountpoint(line); if (!mountpoint) { ERROR("Error reading mountinfo: bad line '%s'", line); free_string_list(controller_list); continue; } base_cgroup = get_current_cgroup(basecginfo, controller_list[0]); if (!base_cgroup) { ERROR("Failed to find current cgroup for controller '%s'", controller_list[0]); free_string_list(controller_list); free(mountpoint); continue; } trim(base_cgroup); prune_init_scope(base_cgroup); if (!test_writeable(mountpoint, base_cgroup)) { free_string_list(controller_list); free(mountpoint); free(base_cgroup); continue; } add_controller(controller_list, mountpoint, base_cgroup); } free_string_list(klist); free_string_list(nlist); free(basecginfo); fclose(f); free(line); if (lxc_cgfsng_debug) { printf("writeable subsystems:\n"); lxc_cgfsng_print_hierarchies(); } /* verify that all controllers in cgroup.use and all crucial * controllers are accounted for */ if (!all_controllers_found()) return false; return true; } static bool collect_hierarchy_info(void) { const char *tmp; errno = 0; tmp = lxc_global_config_value("lxc.cgroup.use"); if (!cgroup_use && errno != 0) { // lxc.cgroup.use can be NULL SYSERROR("cgfsng: error reading list of cgroups to use"); return false; } cgroup_use = must_copy_string(tmp); return parse_hierarchies(); } static void *cgfsng_init(const char *name) { struct cgfsng_handler_data *d; const char *cgroup_pattern; d = must_alloc(sizeof(*d)); memset(d, 0, sizeof(*d)); d->name = must_copy_string(name); cgroup_pattern = lxc_global_config_value("lxc.cgroup.pattern"); if (!cgroup_pattern) { // lxc.cgroup.pattern is only NULL on error ERROR("Error getting cgroup pattern"); goto out_free; } d->cgroup_pattern = must_copy_string(cgroup_pattern); if (lxc_cgfsng_debug) lxc_cgfsng_print_debuginfo(d); return d; out_free: free_handler_data(d); return NULL; } /* * Concatenate all passed-in strings into one path. Do not fail. If any piece is * not prefixed with '/', add a '/'. */ static char *must_make_path(const char *first, ...) { va_list args; char *cur, *dest; size_t full_len = strlen(first); dest = must_copy_string(first); va_start(args, first); while ((cur = va_arg(args, char *)) != NULL) { full_len += strlen(cur); if (cur[0] != '/') full_len++; dest = must_realloc(dest, full_len + 1); if (cur[0] != '/') strcat(dest, "/"); strcat(dest, cur); } va_end(args); return dest; } static int cgroup_rmdir(char *dirname) { struct dirent *direntp; DIR *dir; int r = 0; dir = opendir(dirname); if (!dir) return -1; while ((direntp = readdir(dir))) { struct stat mystat; char *pathname; if (!direntp) break; if (!strcmp(direntp->d_name, ".") || !strcmp(direntp->d_name, "..")) continue; pathname = must_make_path(dirname, direntp->d_name, NULL); if (lstat(pathname, &mystat)) { if (!r) WARN("failed to stat %s", pathname); r = -1; goto next; } if (!S_ISDIR(mystat.st_mode)) goto next; if (cgroup_rmdir(pathname) < 0) r = -1; next: free(pathname); } if (rmdir(dirname) < 0) { if (!r) WARN("%s: failed to delete %s: %m", __func__, dirname); r = -1; } if (closedir(dir) < 0) { if (!r) WARN("%s: failed to delete %s: %m", __func__, dirname); r = -1; } return r; } static int rmdir_wrapper(void *data) { char *path = data; if (setresgid(0,0,0) < 0) SYSERROR("Failed to setgid to 0"); if (setresuid(0,0,0) < 0) SYSERROR("Failed to setuid to 0"); if (setgroups(0, NULL) < 0) SYSERROR("Failed to clear groups"); return cgroup_rmdir(path); } void recursive_destroy(char *path, struct lxc_conf *conf) { int r; if (conf && !lxc_list_empty(&conf->id_map)) r = userns_exec_1(conf, rmdir_wrapper, path); else r = cgroup_rmdir(path); if (r < 0) ERROR("Error destroying %s", path); } static void cgfsng_destroy(void *hdata, struct lxc_conf *conf) { struct cgfsng_handler_data *d = hdata; if (!d) return; if (d->container_cgroup && hierarchies) { int i; for (i = 0; hierarchies[i]; i++) { struct hierarchy *h = hierarchies[i]; if (h->fullcgpath) { recursive_destroy(h->fullcgpath, conf); free(h->fullcgpath); h->fullcgpath = NULL; } } } free_handler_data(d); } struct cgroup_ops *cgfsng_ops_init(void) { if (getenv("LXC_DEBUG_CGFSNG")) lxc_cgfsng_debug = true; if (!collect_hierarchy_info()) return NULL; return &cgfsng_ops; } static bool create_path_for_hierarchy(struct hierarchy *h, char *cgname) { h->fullcgpath = must_make_path(h->mountpoint, h->base_cgroup, cgname, NULL); if (dir_exists(h->fullcgpath)) { // it must not already exist ERROR("Path \"%s\" already existed.", h->fullcgpath); return false; } if (!handle_cpuset_hierarchy(h, cgname)) { ERROR("Failed to handle cgroupfs v1 cpuset controller."); return false; } return mkdir_p(h->fullcgpath, 0755) == 0; } static void remove_path_for_hierarchy(struct hierarchy *h, char *cgname) { if (rmdir(h->fullcgpath) < 0) SYSERROR("Failed to clean up cgroup %s from failed creation attempt", h->fullcgpath); free(h->fullcgpath); h->fullcgpath = NULL; } /* * Try to create the same cgroup in all hierarchies. * Start with cgroup_pattern; next cgroup_pattern-1, -2, ..., -999 */ static inline bool cgfsng_create(void *hdata) { struct cgfsng_handler_data *d = hdata; char *tmp, *cgname, *offset; int i, idx = 0; size_t len; if (!d) return false; if (d->container_cgroup) { WARN("cgfsng_create called a second time"); return false; } tmp = lxc_string_replace("%n", d->name, d->cgroup_pattern); if (!tmp) { ERROR("Failed expanding cgroup name pattern"); return false; } len = strlen(tmp) + 5; // leave room for -NNN\0 cgname = must_alloc(len); strcpy(cgname, tmp); free(tmp); offset = cgname + len - 5; again: if (idx == 1000) { ERROR("Too many conflicting cgroup names"); goto out_free; } if (idx) snprintf(offset, 5, "-%d", idx); for (i = 0; hierarchies[i]; i++) { if (!create_path_for_hierarchy(hierarchies[i], cgname)) { int j; SYSERROR("Failed to create %s: %s", hierarchies[i]->fullcgpath, strerror(errno)); free(hierarchies[i]->fullcgpath); hierarchies[i]->fullcgpath = NULL; for (j = 0; j < i; j++) remove_path_for_hierarchy(hierarchies[j], cgname); idx++; goto again; } } /* Done */ d->container_cgroup = cgname; return true; out_free: free(cgname); return false; } static bool cgfsng_enter(void *hdata, pid_t pid) { char pidstr[25]; int i, len; len = snprintf(pidstr, 25, "%d", pid); if (len < 0 || len > 25) return false; for (i = 0; hierarchies[i]; i++) { char *fullpath = must_make_path(hierarchies[i]->fullcgpath, "cgroup.procs", NULL); if (lxc_write_to_file(fullpath, pidstr, len, false) != 0) { SYSERROR("Failed to enter %s", fullpath); free(fullpath); return false; } free(fullpath); } return true; } struct chown_data { struct cgfsng_handler_data *d; uid_t origuid; // target uid in parent namespace }; /* * chgrp the container cgroups to container group. We leave * the container owner as cgroup owner. So we must make the * directories 775 so that the container can create sub-cgroups. * * Also chown the tasks and cgroup.procs files. Those may not * exist depending on kernel version. */ static int chown_cgroup_wrapper(void *data) { struct chown_data *arg = data; uid_t destuid; int i; if (setresgid(0,0,0) < 0) SYSERROR("Failed to setgid to 0"); if (setresuid(0,0,0) < 0) SYSERROR("Failed to setuid to 0"); if (setgroups(0, NULL) < 0) SYSERROR("Failed to clear groups"); destuid = get_ns_uid(arg->origuid); for (i = 0; hierarchies[i]; i++) { char *fullpath, *path = hierarchies[i]->fullcgpath; if (chown(path, destuid, 0) < 0) { SYSERROR("Error chowning %s to %d", path, (int) destuid); return -1; } if (chmod(path, 0775) < 0) { SYSERROR("Error chmoding %s", path); return -1; } /* * Failures to chown these are inconvenient but not detrimental * We leave these owned by the container launcher, so that container * root can write to the files to attach. We chmod them 664 so that * container systemd can write to the files (which systemd in wily * insists on doing) */ fullpath = must_make_path(path, "tasks", NULL); if (chown(fullpath, destuid, 0) < 0 && errno != ENOENT) WARN("Failed chowning %s to %d: %m", fullpath, (int) destuid); if (chmod(fullpath, 0664) < 0) WARN("Error chmoding %s: %m", path); free(fullpath); fullpath = must_make_path(path, "cgroup.procs", NULL); if (chown(fullpath, destuid, 0) < 0 && errno != ENOENT) WARN("Failed chowning %s to %d: %m", fullpath, (int) destuid); if (chmod(fullpath, 0664) < 0) WARN("Error chmoding %s: %m", path); free(fullpath); } return 0; } static bool cgfsns_chown(void *hdata, struct lxc_conf *conf) { struct cgfsng_handler_data *d = hdata; struct chown_data wrap; if (!d) return false; if (lxc_list_empty(&conf->id_map)) return true; wrap.d = d; wrap.origuid = geteuid(); if (userns_exec_1(conf, chown_cgroup_wrapper, &wrap) < 0) { ERROR("Error requesting cgroup chown in new namespace"); return false; } return true; } /* * We've safe-mounted a tmpfs as parent, so we don't need to protect against * symlinks any more - just use mount */ /* mount cgroup-full if requested */ static int mount_cgroup_full(int type, struct hierarchy *h, char *dest, char *container_cgroup) { if (type < LXC_AUTO_CGROUP_FULL_RO || type > LXC_AUTO_CGROUP_FULL_MIXED) return 0; if (mount(h->mountpoint, dest, "cgroup", MS_BIND, NULL) < 0) { SYSERROR("Error bind-mounting %s cgroup onto %s", h->mountpoint, dest); return -1; } if (type != LXC_AUTO_CGROUP_FULL_RW) { unsigned long flags = MS_BIND | MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_REMOUNT | MS_RDONLY; if (mount(NULL, dest, "cgroup", flags, NULL) < 0) { SYSERROR("Error remounting %s readonly", dest); return -1; } } INFO("Bind mounted %s onto %s", h->mountpoint, dest); if (type != LXC_AUTO_CGROUP_FULL_MIXED) return 0; /* mount just the container path rw */ char *source = must_make_path(h->mountpoint, h->base_cgroup, container_cgroup, NULL); char *rwpath = must_make_path(dest, h->base_cgroup, container_cgroup, NULL); if (mount(source, rwpath, "cgroup", MS_BIND, NULL) < 0) WARN("Failed to mount %s read-write: %m", rwpath); INFO("Made %s read-write", rwpath); free(rwpath); free(source); return 0; } /* cgroup-full:* is done, no need to create subdirs */ static bool cg_mount_needs_subdirs(int type) { if (type >= LXC_AUTO_CGROUP_FULL_RO) return false; return true; } /* * After $rootfs/sys/fs/container/controller/the/cg/path has been * created, remount controller ro if needed and bindmount the * cgroupfs onto controll/the/cg/path */ static int do_secondstage_mounts_if_needed(int type, struct hierarchy *h, char *controllerpath, char *cgpath, const char *container_cgroup) { if (type == LXC_AUTO_CGROUP_RO || type == LXC_AUTO_CGROUP_MIXED) { if (mount(controllerpath, controllerpath, "cgroup", MS_BIND, NULL) < 0) { SYSERROR("Error bind-mounting %s", controllerpath); return -1; } if (mount(controllerpath, controllerpath, "cgroup", MS_REMOUNT | MS_BIND | MS_RDONLY, NULL) < 0) { SYSERROR("Error remounting %s read-only", controllerpath); return -1; } INFO("Remounted %s read-only", controllerpath); } char *sourcepath = must_make_path(h->mountpoint, h->base_cgroup, container_cgroup, NULL); int flags = MS_BIND; if (type == LXC_AUTO_CGROUP_RO) flags |= MS_RDONLY; INFO("Mounting %s onto %s", sourcepath, cgpath); if (mount(sourcepath, cgpath, "cgroup", flags, NULL) < 0) { free(sourcepath); SYSERROR("Error mounting cgroup %s onto %s", h->controllers[0], cgpath); return -1; } free(sourcepath); INFO("Completed second stage cgroup automounts for %s", cgpath); return 0; } static bool cgfsng_mount(void *hdata, const char *root, int type) { struct cgfsng_handler_data *d = hdata; char *tmpfspath = NULL; bool retval = false; int i; if ((type & LXC_AUTO_CGROUP_MASK) == 0) return true; if (cgns_supported()) return true; tmpfspath = must_make_path(root, "/sys/fs/cgroup", NULL); if (type == LXC_AUTO_CGROUP_NOSPEC) type = LXC_AUTO_CGROUP_MIXED; else if (type == LXC_AUTO_CGROUP_FULL_NOSPEC) type = LXC_AUTO_CGROUP_FULL_MIXED; /* Mount tmpfs */ if (safe_mount("cgroup_root", tmpfspath, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_RELATIME, "size=10240k,mode=755", root) < 0) goto bad; for (i = 0; hierarchies[i]; i++) { char *controllerpath, *path2; struct hierarchy *h = hierarchies[i]; char *controller = strrchr(h->mountpoint, '/'); int r; if (!controller) continue; controller++; controllerpath = must_make_path(tmpfspath, controller, NULL); if (dir_exists(controllerpath)) { free(controllerpath); continue; } if (mkdir(controllerpath, 0755) < 0) { SYSERROR("Error creating cgroup path: %s", controllerpath); free(controllerpath); goto bad; } if (mount_cgroup_full(type, h, controllerpath, d->container_cgroup) < 0) { free(controllerpath); goto bad; } if (!cg_mount_needs_subdirs(type)) { free(controllerpath); continue; } path2 = must_make_path(controllerpath, h->base_cgroup, d->container_cgroup, NULL); if (mkdir_p(path2, 0755) < 0) { free(controllerpath); goto bad; } r = do_secondstage_mounts_if_needed(type, h, controllerpath, path2, d->container_cgroup); free(controllerpath); free(path2); if (r < 0) goto bad; } retval = true; bad: free(tmpfspath); return retval; } static int recursive_count_nrtasks(char *dirname) { struct dirent *direntp; DIR *dir; int count = 0, ret; char *path; dir = opendir(dirname); if (!dir) return 0; while ((direntp = readdir(dir))) { struct stat mystat; if (!direntp) break; if (!strcmp(direntp->d_name, ".") || !strcmp(direntp->d_name, "..")) continue; path = must_make_path(dirname, direntp->d_name, NULL); if (lstat(path, &mystat)) goto next; if (!S_ISDIR(mystat.st_mode)) goto next; count += recursive_count_nrtasks(path); next: free(path); } path = must_make_path(dirname, "cgroup.procs", NULL); ret = lxc_count_file_lines(path); if (ret != -1) count += ret; free(path); (void) closedir(dir); return count; } static int cgfsng_nrtasks(void *hdata) { struct cgfsng_handler_data *d = hdata; char *path; int count; if (!d || !d->container_cgroup || !hierarchies) return -1; path = must_make_path(hierarchies[0]->fullcgpath, NULL); count = recursive_count_nrtasks(path); free(path); return count; } /* Only root needs to escape to the cgroup of its init */ static bool cgfsng_escape() { int i; if (geteuid()) return true; for (i = 0; hierarchies[i]; i++) { char *fullpath = must_make_path(hierarchies[i]->mountpoint, hierarchies[i]->base_cgroup, "cgroup.procs", NULL); if (lxc_write_to_file(fullpath, "0", 2, false) != 0) { SYSERROR("Failed to escape to %s", fullpath); free(fullpath); return false; } free(fullpath); } return true; } static int cgfsng_num_hierarchies(void) { int i; for (i = 0; hierarchies[i]; i++) ; return i; } static bool cgfsng_get_hierarchies(int n, char ***out) { int i; /* sanity check n */ for (i = 0; i < n; i++) { if (!hierarchies[i]) return false; } *out = hierarchies[i]->controllers; return true; } #define THAWED "THAWED" #define THAWED_LEN (strlen(THAWED)) static bool cgfsng_unfreeze(void *hdata) { char *fullpath; struct hierarchy *h = get_hierarchy("freezer"); if (!h) return false; fullpath = must_make_path(h->fullcgpath, "freezer.state", NULL); if (lxc_write_to_file(fullpath, THAWED, THAWED_LEN, false) != 0) { free(fullpath); return false; } free(fullpath); return true; } static const char *cgfsng_get_cgroup(void *hdata, const char *subsystem) { struct hierarchy *h = get_hierarchy(subsystem); if (!h) return NULL; return h->fullcgpath ? h->fullcgpath + strlen(h->mountpoint) : NULL; } /* * Given a cgroup path returned from lxc_cmd_get_cgroup_path, build a * full path, which must be freed by the caller. */ static char *build_full_cgpath_from_monitorpath(struct hierarchy *h, const char *inpath, const char *filename) { /* * XXX Remove this case after 2.0 release. It's for dealing with * containers spawned under the old buggy cgfsng which wasn't around * for long. */ if (strncmp(inpath, "/sys/fs/cgroup/", 15) == 0) return must_make_path(inpath, filename, NULL); return must_make_path(h->mountpoint, inpath, filename, NULL); } static bool cgfsng_attach(const char *name, const char *lxcpath, pid_t pid) { char pidstr[25]; int i, len; len = snprintf(pidstr, 25, "%d", pid); if (len < 0 || len > 25) return false; for (i = 0; hierarchies[i]; i++) { char *path, *fullpath; struct hierarchy *h = hierarchies[i]; path = lxc_cmd_get_cgroup_path(name, lxcpath, h->controllers[0]); if (!path) // not running continue; fullpath = build_full_cgpath_from_monitorpath(h, path, "cgroup.procs"); free(path); if (lxc_write_to_file(fullpath, pidstr, len, false) != 0) { SYSERROR("Failed to attach %d to %s", (int)pid, fullpath); free(fullpath); return false; } free(fullpath); } return true; } /* * Called externally (i.e. from 'lxc-cgroup') to query cgroup limits. * Here we don't have a cgroup_data set up, so we ask the running * container through the commands API for the cgroup path */ static int cgfsng_get(const char *filename, char *value, size_t len, const char *name, const char *lxcpath) { char *subsystem, *p, *path; struct hierarchy *h; int ret = -1; subsystem = alloca(strlen(filename) + 1); strcpy(subsystem, filename); if ((p = strchr(subsystem, '.')) != NULL) *p = '\0'; path = lxc_cmd_get_cgroup_path(name, lxcpath, subsystem); if (!path) // not running return -1; h = get_hierarchy(subsystem); if (h) { char *fullpath = build_full_cgpath_from_monitorpath(h, path, filename); ret = lxc_read_from_file(fullpath, value, len); free(fullpath); } free(path); return ret; } /* * Called externally (i.e. from 'lxc-cgroup') to set new cgroup limits. * Here we don't have a cgroup_data set up, so we ask the running * container through the commands API for the cgroup path */ static int cgfsng_set(const char *filename, const char *value, const char *name, const char *lxcpath) { char *subsystem, *p, *path; struct hierarchy *h; int ret = -1; subsystem = alloca(strlen(filename) + 1); strcpy(subsystem, filename); if ((p = strchr(subsystem, '.')) != NULL) *p = '\0'; path = lxc_cmd_get_cgroup_path(name, lxcpath, subsystem); if (!path) // not running return -1; h = get_hierarchy(subsystem); if (h) { char *fullpath = build_full_cgpath_from_monitorpath(h, path, filename); ret = lxc_write_to_file(fullpath, value, strlen(value), false); free(fullpath); } free(path); return ret; } /* * Called from setup_limits - here we have the container's cgroup_data because * we created the cgroups */ static int lxc_cgroup_set_data(const char *filename, const char *value, struct cgfsng_handler_data *d) { char *subsystem = NULL, *p; int ret = -1; struct hierarchy *h; subsystem = alloca(strlen(filename) + 1); strcpy(subsystem, filename); if ((p = strchr(subsystem, '.')) != NULL) *p = '\0'; h = get_hierarchy(subsystem); if (h) { char *fullpath = must_make_path(h->fullcgpath, filename, NULL); ret = lxc_write_to_file(fullpath, value, strlen(value), false); free(fullpath); } return ret; } static bool cgfsng_setup_limits(void *hdata, struct lxc_list *cgroup_settings, bool do_devices) { struct cgfsng_handler_data *d = hdata; struct lxc_list *iterator, *sorted_cgroup_settings, *next; struct lxc_cgroup *cg; bool ret = false; if (lxc_list_empty(cgroup_settings)) return true; sorted_cgroup_settings = sort_cgroup_settings(cgroup_settings); if (!sorted_cgroup_settings) { return false; } lxc_list_for_each(iterator, sorted_cgroup_settings) { cg = iterator->elem; if (do_devices == !strncmp("devices", cg->subsystem, 7)) { if (lxc_cgroup_set_data(cg->subsystem, cg->value, d)) { if (do_devices && (errno == EACCES || errno == EPERM)) { WARN("Error setting %s to %s for %s", cg->subsystem, cg->value, d->name); continue; } SYSERROR("Error setting %s to %s for %s", cg->subsystem, cg->value, d->name); goto out; } } DEBUG("cgroup '%s' set to '%s'", cg->subsystem, cg->value); } ret = true; INFO("cgroup has been setup"); out: lxc_list_for_each_safe(iterator, sorted_cgroup_settings, next) { lxc_list_del(iterator); free(iterator); } free(sorted_cgroup_settings); return ret; } static struct cgroup_ops cgfsng_ops = { .init = cgfsng_init, .destroy = cgfsng_destroy, .create = cgfsng_create, .enter = cgfsng_enter, .escape = cgfsng_escape, .num_hierarchies = cgfsng_num_hierarchies, .get_hierarchies = cgfsng_get_hierarchies, .get_cgroup = cgfsng_get_cgroup, .get = cgfsng_get, .set = cgfsng_set, .unfreeze = cgfsng_unfreeze, .setup_limits = cgfsng_setup_limits, .name = "cgroupfs-ng", .attach = cgfsng_attach, .chown = cgfsns_chown, .mount_cgroup = cgfsng_mount, .nrtasks = cgfsng_nrtasks, .driver = CGFSNG, /* unsupported */ .create_legacy = NULL, }; lxc-2.0.8/src/lxc/cgroups/cgroup.h0000644061062106075000000000625413105116772013761 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_CGROUP_H #define __LXC_CGROUP_H #include #include #include struct lxc_handler; struct lxc_conf; struct lxc_list; typedef enum { CGFS, CGMANAGER, CGFSNG, } cgroup_driver_t; struct cgroup_ops { const char *name; void *(*init)(const char *name); void (*destroy)(void *hdata, struct lxc_conf *conf); bool (*create)(void *hdata); bool (*enter)(void *hdata, pid_t pid); bool (*create_legacy)(void *hdata, pid_t pid); const char *(*get_cgroup)(void *hdata, const char *subsystem); bool (*escape)(); int (*num_hierarchies)(); bool (*get_hierarchies)(int n, char ***out); int (*set)(const char *filename, const char *value, const char *name, const char *lxcpath); int (*get)(const char *filename, char *value, size_t len, const char *name, const char *lxcpath); bool (*unfreeze)(void *hdata); bool (*setup_limits)(void *hdata, struct lxc_list *cgroup_conf, bool with_devices); bool (*chown)(void *hdata, struct lxc_conf *conf); bool (*attach)(const char *name, const char *lxcpath, pid_t pid); 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); extern bool cgroup_mount(const char *root, struct lxc_handler *handler, int type); extern void cgroup_destroy(struct lxc_handler *handler); extern bool cgroup_init(struct lxc_handler *handler); extern bool cgroup_create(struct lxc_handler *handler); extern bool cgroup_setup_limits(struct lxc_handler *handler, bool with_devices); extern bool cgroup_chown(struct lxc_handler *handler); extern bool cgroup_enter(struct lxc_handler *handler); extern void cgroup_cleanup(struct lxc_handler *handler); extern bool cgroup_create_legacy(struct lxc_handler *handler); extern int cgroup_nrtasks(struct lxc_handler *handler); extern const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem); extern bool cgroup_escape(); extern int cgroup_num_hierarchies(); extern bool cgroup_get_hierarchies(int i, char ***out); extern bool cgroup_unfreeze(struct lxc_handler *handler); extern void cgroup_disconnect(void); extern cgroup_driver_t cgroup_driver(void); extern void prune_init_scope(char *cg); extern bool is_crucial_cgroup_subsystem(const char *s); #endif lxc-2.0.8/src/lxc/lxccontainer.h0000644061062106075000000007672113105116772013477 00000000000000/*! \file * * liblxcapi * * Copyright © 2012 Serge Hallyn . * Copyright © 2012 Canonical Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_CONTAINER_H #define __LXC_CONTAINER_H #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif #define LXC_CLONE_KEEPNAME (1 << 0) /*!< Do not edit the rootfs to change the hostname */ #define LXC_CLONE_KEEPMACADDR (1 << 1) /*!< Do not change the MAC address on network interfaces */ #define LXC_CLONE_SNAPSHOT (1 << 2) /*!< Snapshot the original filesystem(s) */ #define LXC_CLONE_KEEPBDEVTYPE (1 << 3) /*!< Use the same bdev type */ #define LXC_CLONE_MAYBE_SNAPSHOT (1 << 4) /*!< Snapshot only if bdev supports it, else copy */ #define LXC_CLONE_MAXFLAGS (1 << 5) /*!< Number of \c LXC_CLONE_* flags */ #define LXC_CREATE_QUIET (1 << 0) /*!< Redirect \c stdin to \c /dev/zero and \c stdout and \c stderr to \c /dev/null */ #define LXC_CREATE_MAXFLAGS (1 << 1) /*!< Number of \c LXC_CREATE* flags */ struct bdev_specs; struct lxc_snapshot; struct lxc_lock; struct migrate_opts; /*! * An LXC container. * * Note that changing the order of struct members is an API change, as callers * will end up having the wrong offset when calling a function. So when making * changes, whenever possible stick to simply appending new members. */ struct lxc_container { // private fields /*! * \private * Name of container. */ char *name; /*! * \private * Full path to configuration file. */ char *configfile; /*! * \private * File to store pid. */ char *pidfile; /*! * \private * Container semaphore lock. */ struct lxc_lock *slock; /*! * \private * Container private lock. */ struct lxc_lock *privlock; /*! * \private * Number of references to this container. * \note protected by privlock. */ int numthreads; /*! * \private * Container configuration. * * \internal FIXME: do we want the whole lxc_handler? */ struct lxc_conf *lxc_conf; // public fields /*! Human-readable string representing last error */ char *error_string; /*! Last error number */ int error_num; /*! Whether container wishes to be daemonized */ bool daemonize; /*! Full path to configuration file */ char *config_path; /*! * \brief Determine if \c /var/lib/lxc/$name/config exists. * * \param c Container. * * \return \c true if container is defined, else \c false. */ bool (*is_defined)(struct lxc_container *c); /*! * \brief Determine state of container. * * \param c Container. * * \return Static upper-case string representing state of container. * * \note Returned string must not be freed. */ const char *(*state)(struct lxc_container *c); /*! * \brief Determine if container is running. * * \param c Container. * * \return \c true on success, else \c false. */ bool (*is_running)(struct lxc_container *c); /*! * \brief Freeze running container. * * \param c Container. * * \return \c true on success, else \c false. */ bool (*freeze)(struct lxc_container *c); /*! * \brief Thaw a frozen container. * * \param c Container. * * \return \c true on success, else \c false. */ bool (*unfreeze)(struct lxc_container *c); /*! * \brief Determine process ID of the containers init process. * * \param c Container. * * \return pid of init process as seen from outside the * container. */ pid_t (*init_pid)(struct lxc_container *c); /*! * \brief Load the specified configuration for the container. * * \param c Container. * \param alt_file Full path to alternate configuration file, or * \c NULL to use the default configuration file. * * \return \c true on success, else \c false. */ bool (*load_config)(struct lxc_container *c, const char *alt_file); /*! * \brief Start the container. * * \param c Container. * \param useinit Use lxcinit rather than \c /sbin/init. * \param argv Array of arguments to pass to init. * * \return \c true on success, else \c false. */ bool (*start)(struct lxc_container *c, int useinit, char * const argv[]); /*! * \brief Start the container (list variant). * * \param c Container. * \param useinit Use lxcinit rather than \c /sbin/init. * \param ... Command-line to pass to init (must end in \c NULL). * * \return \c true on success, else \c false. * * \note Identical to \ref start except that that the init * arguments are specified via a list rather than an array of * pointers. */ bool (*startl)(struct lxc_container *c, int useinit, ...); /*! * \brief Stop the container. * * \param c Container. * * \return \c true on success, else \c false. */ bool (*stop)(struct lxc_container *c); /*! * \brief Change whether the container wants to run disconnected * from the terminal. * * \param c Container. * \param state Value for the daemonize bit (0 or 1). * * \return \c true on success, else \c false. */ bool (*want_daemonize)(struct lxc_container *c, bool state); /*! * \brief Change whether the container wishes all file descriptors * to be closed on startup. * * \param c Container. * \param state Value for the close_all_fds bit (0 or 1). * * \return \c true on success, else \c false. */ bool (*want_close_all_fds)(struct lxc_container *c, bool state); /*! * \brief Return current config file name. * * \param c Container. * * \return config file name, or \c NULL on error. * * \note The result is allocated, so the caller must free the result. */ char *(*config_file_name)(struct lxc_container *c); /*! * \brief Wait for container to reach a particular state. * * \param c Container. * \param state State to wait for. * \param timeout Timeout in seconds. * * \return \c true if state reached within \p timeout, else \c false. * * \note A \p timeout of \c -1 means wait forever. A \p timeout * of \c 0 means do not wait. */ bool (*wait)(struct lxc_container *c, const char *state, int timeout); /*! * \brief Set a key/value configuration option. * * \param c Container. * \param key Name of option to set. * \param value Value of \p name to set. * * \return \c true on success, else \c false. */ bool (*set_config_item)(struct lxc_container *c, const char *key, const char *value); /*! * \brief Delete the container. * * \param c Container. * * \return \c true on success, else \c false. * * \note Container must be stopped and have no dependent snapshots. */ bool (*destroy)(struct lxc_container *c); /*! * \brief Save configuaration to a file. * * \param c Container. * \param alt_file Full path to file to save configuration in. * * \return \c true on success, else \c false. */ bool (*save_config)(struct lxc_container *c, const char *alt_file); /*! * \brief Create a container. * * \param c Container (with lxcpath, name and a starting * configuration set). * \param t Template to execute to instantiate the root * filesystem and adjust the configuration. * \param bdevtype Backing store type to use (if \c NULL, \c dir will be used). * \param specs Additional parameters for the backing store (for * example LVM volume group to use). * \param flags \c LXC_CREATE_* options (currently only \ref * LXC_CREATE_QUIET is supported). * \param argv Arguments to pass to the template, terminated by \c NULL (if no * arguments are required, just pass \c NULL). * * \return \c true on success, else \c false. */ bool (*create)(struct lxc_container *c, const char *t, const char *bdevtype, struct bdev_specs *specs, int flags, char *const argv[]); /*! * \brief Create a container (list variant). * * \param c Container (with lxcpath, name and a starting * configuration set). * \param t Template to execute to instantiate the root * filesystem and adjust the configuration. * \param bdevtype Backing store type to use (if \c NULL, \c dir will be used). * \param specs Additional parameters for the backing store (for * example LVM volume group to use). * \param flags \c LXC_CREATE_* options (currently only \ref * LXC_CREATE_QUIET is supported). * \param ... Command-line to pass to init (must end in \c NULL). * * \return \c true on success, else \c false. * * \note Identical to \ref create except that the template * arguments are specified as a list rather than an array of * pointers. */ bool (*createl)(struct lxc_container *c, const char *t, const char *bdevtype, struct bdev_specs *specs, int flags, ...); /*! * \brief Rename a container * * \param c Container. * \param newname New name to be used for the container. * * \return \c true on success, else \c false. */ bool (*rename)(struct lxc_container *c, const char *newname); /*! * \brief Request the container reboot by sending it \c SIGINT. * * \param c Container. * * \return \c true if reboot request successful, else \c false. */ bool (*reboot)(struct lxc_container *c); /*! * \brief Request the container shutdown by sending it \c * SIGPWR. * * \param c Container. * \param timeout Seconds to wait before returning false. * (-1 to wait forever, 0 to avoid waiting). * * \return \c true if the container was shutdown successfully, else \c false. */ bool (*shutdown)(struct lxc_container *c, int timeout); /*! * \brief Completely clear the containers in-memory configuration. * * \param c Container. */ void (*clear_config)(struct lxc_container *c); /*! * \brief Clear a configuration item. * * \param c Container. * \param key Name of option to clear. * * \return \c true on success, else \c false. * * \note Analog of \ref set_config_item. */ bool (*clear_config_item)(struct lxc_container *c, const char *key); /*! * \brief Retrieve the value of a config item. * * \param c Container. * \param key Name of option to get. * \param[out] retv Caller-allocated buffer to write value of \p key * into (or \c NULL to determine length of value). * \param inlen Length of \p retv (may be zero). * * \return Length of config items value, or < 0 on error. * * \note The caller can (and should) determine how large a buffer to allocate for * \p retv by initially passing its value as \c NULL and considering the return value. * This function can then be called again passing a newly-allocated suitably-sized buffer. * \note If \p retv is NULL, \p inlen is ignored. * \note If \p inlen is smaller than required, the value written * to \p retv will be truncated. */ int (*get_config_item)(struct lxc_container *c, const char *key, char *retv, int inlen); /*! * \brief Retrieve the value of a config item from running container. * * \param c Container. * \param key Name of option to get. * * \return the item or NULL on error. * * \note Returned string must be freed by the caller. */ char* (*get_running_config_item)(struct lxc_container *c, const char *key); /*! * \brief Retrieve a list of config item keys given a key * prefix. * * \param c Container. * \param key Name of option to get. * \param[out] retv Caller-allocated buffer to write list of keys to * (or \c NULL to determine overall length of keys list). * \param inlen Length of \p retv (may be zero). * * \return Length of keys list, or < 0 on error. * * \note The list values written to \p retv are separated by * a newline character ('\\n'). * \note The caller can (and should) determine how large a buffer to allocate for * \p retv by initially passing its value as \c NULL and considering the return value. * This function can then be called again passing a newly-allocated suitably-sized buffer. * \note If \p retv is NULL, \p inlen is ignored. * \note If \p inlen is smaller than required, the value written * to \p retv will be truncated. */ int (*get_keys)(struct lxc_container *c, const char *key, char *retv, int inlen); /*! * \brief Obtain a list of network interfaces. * \param c Container. * * \return Newly-allocated array of network interfaces, or \c * NULL on error. * * \note The returned array is allocated, so the caller must free it. * \note The returned array is terminated with a \c NULL entry. */ char** (*get_interfaces)(struct lxc_container *c); /*! * \brief Determine the list of container IP addresses. * * \param c Container. * \param interface Network interface name to consider. * \param family Network family (for example "inet", "inet6"). * \param scope IPv6 scope id (ignored if \p family is not "inet6"). * * \return Newly-allocated array of network interfaces, or \c * NULL on error. * * \note The returned array is allocated, so the caller must free it. * \note The returned array is terminated with a \c NULL entry. */ char** (*get_ips)(struct lxc_container *c, const char* interface, const char* family, int scope); /*! * \brief Retrieve the specified cgroup subsystem value for the container. * * \param c Container. * \param subsys cgroup subsystem to retrieve. * \param[out] retv Caller-allocated buffer to write value of \p * subsys into (or \c NULL to determine length of value). * \param inlen length of \p retv (may be zero). * * \return Length of \p subsys value, or < 0 on error. * * \note If \p retv is \c NULL, \p inlen is ignored. * \note If \p inlen is smaller than required, the value written * to \p retv will be truncated. */ int (*get_cgroup_item)(struct lxc_container *c, const char *subsys, char *retv, int inlen); /*! * \brief Set the specified cgroup subsystem value for the container. * * \param c Container. * \param subsys cgroup subsystem to consider. * \param value Value to set for \p subsys. * * \return \c true on success, else \c false. */ bool (*set_cgroup_item)(struct lxc_container *c, const char *subsys, const char *value); /*! * \brief Determine full path to the containers configuration file. * Each container can have a custom configuration path. However * by default it will be set to either the \c LXCPATH configure * variable, or the lxcpath value in the \c LXC_GLOBAL_CONF configuration * file (i.e. \c /etc/lxc/lxc.conf). * The value for a specific container can be changed using * \ref set_config_path. There is no other way to specify this in general at the moment. * * \param c Container. * * \return Static string representing full path to configuration * file. * * \note Returned string must not be freed. */ const char *(*get_config_path)(struct lxc_container *c); /*! * \brief Set the full path to the containers configuration * file. * * \param c Container. * \param path Full path to configuration file. * * \return \c true on success, else \c false. */ bool (*set_config_path)(struct lxc_container *c, const char *path); /*! * \brief Copy a stopped container. * * \param c Original container. * \param newname New name for the container. If \c NULL, the same * name is used and a new lxcpath MUST be specified. * \param lxcpath lxcpath in which to create the new container. If * \c NULL, the original container's lxcpath will be used. * (XXX: should we use the default instead?) * \param flags Additional \c LXC_CLONE* flags to change the cloning behaviour: * - \ref LXC_CLONE_KEEPNAME * - \ref LXC_CLONE_KEEPMACADDR * - \ref LXC_CLONE_SNAPSHOT * \param bdevtype Optionally force the cloned bdevtype to a specified plugin. * By default the original is used (subject to snapshot requirements). * \param bdevdata Information about how to create the new storage * (i.e. fstype and fsdata). * \param newsize In case of a block device backing store, an * optional size. If \c 0, the original backing store's size will * be used if possible. Note this only applies to the rootfs. For * any other filesystems, the original size will be duplicated. * \param hookargs Additional arguments to pass to the clone hook script. * * \return Newly-allocated copy of container \p c, or \p NULL on * error. * * \note If devtype was not specified, and \p flags contains \ref * LXC_CLONE_SNAPSHOT then use the native \p bdevtype if possible, * else use an overlayfs. */ struct lxc_container *(*clone)(struct lxc_container *c, const char *newname, const char *lxcpath, int flags, const char *bdevtype, const char *bdevdata, uint64_t newsize, char **hookargs); /*! * \brief Allocate a console tty for the container. * * \param c Container. * \param[in,out] ttynum Terminal number to attempt to allocate, * or \c -1 to allocate the first available tty. * \param[out] masterfd File descriptor referring to the master side of the pty. * * \return tty file descriptor number on success, or \c -1 on * failure. * * \note On successful return, \p ttynum will contain the tty number * that was allocated. * \note The returned file descriptor is used to keep the tty * allocated. The caller should call close(2) on the returned file * descriptor when no longer required so that it may be allocated * by another caller. */ int (*console_getfd)(struct lxc_container *c, int *ttynum, int *masterfd); /*! * \brief Allocate and run a console tty. * * \param c Container. * \param ttynum Terminal number to attempt to allocate, \c -1 to * allocate the first available tty or \c 0 to allocate the * console. * \param stdinfd File descriptor to read input from. * \param stdoutfd File descriptor to write output to. * \param stderrfd File descriptor to write error output to. * \param escape The escape character (1 == 'a', 2 == 'b', ...). * * \return \c 0 on success, \c -1 on failure. * * \note This function will not return until the console has been * exited by the user. */ int (*console)(struct lxc_container *c, int ttynum, int stdinfd, int stdoutfd, int stderrfd, int escape); /*! * \brief Create a sub-process attached to a container and run * a function inside it. * * \param c Container. * \param exec_function Function to run. * \param exec_payload Data to pass to \p exec_function. * \param options \ref lxc_attach_options_t. * \param[out] attached_process Process ID of process running inside * container \p c that is running \p exec_function. * * \return \c 0 on success, \c -1 on error. */ int (*attach)(struct lxc_container *c, lxc_attach_exec_t exec_function, void *exec_payload, lxc_attach_options_t *options, pid_t *attached_process); /*! * \brief Run a program inside a container and wait for it to exit. * * \param c Container. * \param options See \ref attach options. * \param program Full path inside container of program to run. * \param argv Array of arguments to pass to \p program. * * \return \c waitpid(2) status of exited process that ran \p * program, or \c -1 on error. */ int (*attach_run_wait)(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char * const argv[]); /*! * \brief Run a program inside a container and wait for it to exit (list variant). * * \param c Container. * \param options See \ref attach options. * \param program Full path inside container of program to run. * \param ... Command-line to pass to \p program (must end in \c NULL). * * \return \c waitpid(2) status of exited process that ran \p * program, or \c -1 on error. */ int (*attach_run_waitl)(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char *arg, ...); /*! * \brief Create a container snapshot. * * Assuming default paths, snapshots will be created as * \c /var/lib/lxc/\/snaps/snap\ * where \c \ represents the container name and \c \ * represents the zero-based snapshot number. * * \param c Container. * \param commentfile Full path to file containing a description * of the snapshot. * * \return -1 on error, or zero-based snapshot number. * * \note \p commentfile may be \c NULL but this is discouraged. */ int (*snapshot)(struct lxc_container *c, const char *commentfile); /*! * \brief Obtain a list of container snapshots. * * \param c Container. * \param[out] snapshots Dynamically-allocated Array of lxc_snapshot's. * * \return Number of snapshots. * * \note The array returned in \p snapshots is allocated, so the caller must free it. * \note To free an individual snapshot as returned in \p * snapshots, call the snapshots \c free function (see \c src/tests/snapshot.c for an example). */ int (*snapshot_list)(struct lxc_container *c, struct lxc_snapshot **snapshots); /*! * \brief Create a new container based on a snapshot. * * The restored container will be a copy (not snapshot) of the snapshot, * and restored in the lxcpath of the original container. * \param c Container. * \param snapname Name of snapshot. * \param newname Name to be used for the restored snapshot. * \return \c true on success, else \c false. * \warning If \p newname is the same as the current container * name, the container will be destroyed. However, this will * fail if the snapshot is overlay-based, since the snapshots * will pin the original container. * \note As an example, if the container exists as \c /var/lib/lxc/c1, snapname might be \c 'snap0' * (representing \c /var/lib/lxc/c1/snaps/snap0). If \p newname is \p c2, * then \c snap0 will be copied to \c /var/lib/lxc/c2. */ bool (*snapshot_restore)(struct lxc_container *c, const char *snapname, const char *newname); /*! * \brief Destroy the specified snapshot. * * \param c Container. * \param snapname Name of snapshot. * * \return \c true on success, else \c false. */ bool (*snapshot_destroy)(struct lxc_container *c, const char *snapname); /*! * \brief Determine if the caller may control the container. * * \param c Container. * * \return \c false if there is a control socket for the * container monitor and the caller may not access it, otherwise * returns \c true. */ bool (*may_control)(struct lxc_container *c); /*! * \brief Add specified device to the container. * * \param c Container. * \param src_path Full path of the device. * \param dest_path Alternate path in the container (or \p NULL * to use \p src_path). * * \return \c true on success, else \c false. */ bool (*add_device_node)(struct lxc_container *c, const char *src_path, const char *dest_path); /*! * \brief Remove specified device from the container. * * \param c Container. * \param src_path Full path of the device. * \param dest_path Alternate path in the container (or \p NULL * to use \p src_path). * * \return \c true on success, else \c false. */ bool (*remove_device_node)(struct lxc_container *c, const char *src_path, const char *dest_path); /* Post LXC-1.0 additions */ /*! * \brief Add specified netdev to the container. * * \param c Container. * \param dev name of net device. * * \return \c true on success, else \c false. */ bool (*attach_interface)(struct lxc_container *c, const char *dev, const char *dst_dev); /*! * \brief Remove specified netdev from the container. * * \param c Container. * \param dev name of net device. * * \return \c true on success, else \c false. */ bool (*detach_interface)(struct lxc_container *c, const char *dev, const char *dst_dev); /*! * \brief Checkpoint a container. * * \param c Container. * \param directory The directory to dump the container to. * \param stop Whether or not to stop the container after checkpointing. * \param verbose Enable criu's verbose logs. * * \return \c true on success, else \c false. * present at compile time). */ bool (*checkpoint)(struct lxc_container *c, char *directory, bool stop, bool verbose); /*! * \brief Restore a container from a checkpoint. * * \param c Container. * \param directory The directory to restore the container from. * \param verbose Enable criu's verbose logs. * * \return \c true on success, else \c false. * */ bool (*restore)(struct lxc_container *c, char *directory, bool verbose); /*! * \brief Delete the container and all its snapshots. * * \param c Container. * * \return \c true on success, else \c false. * * \note Container must be stopped. */ bool (*destroy_with_snapshots)(struct lxc_container *c); /*! * \brief Destroy all the container's snapshot. * * \param c Container. * * \return \c true on success, else \c false. */ bool (*snapshot_destroy_all)(struct lxc_container *c); /* Post LXC-1.1 additions */ /*! * \brief An API call to perform various migration operations * * \param cmd One of the MIGRATE_ contstants. * \param opts A migrate_opts struct filled with relevant options. * \param size The size of the migrate_opts struct, i.e. sizeof(struct migrate_opts). * * \return \c 0 on success, nonzero on failure. */ int (*migrate)(struct lxc_container *c, unsigned int cmd, struct migrate_opts *opts, unsigned int size); }; /*! * \brief An LXC container snapshot. */ struct lxc_snapshot { char *name; /*!< Name of snapshot */ char *comment_pathname; /*!< Full path to snapshots comment file (may be \c NULL) */ char *timestamp; /*!< Time snapshot was created */ char *lxcpath; /*!< Full path to LXCPATH for snapshot */ /*! * \brief De-allocate the snapshot. * \param s snapshot. */ void (*free)(struct lxc_snapshot *s); }; /*! * \brief Specifications for how to create a new backing store */ struct bdev_specs { char *fstype; /*!< Filesystem type */ uint64_t fssize; /*!< Filesystem size in bytes */ struct { char *zfsroot; /*!< ZFS root path */ } zfs; struct { char *vg; /*!< LVM Volume Group name */ char *lv; /*!< LVM Logical Volume name */ char *thinpool; /*!< LVM thin pool to use, if any */ } lvm; char *dir; /*!< Directory path */ struct { char *rbdname; /*!< RBD image name */ char *rbdpool; /*!< Ceph pool name */ } rbd; }; /*! * \brief Commands for the migrate API call. */ enum { MIGRATE_PRE_DUMP, MIGRATE_DUMP, MIGRATE_RESTORE, }; /*! * \brief Options for the migrate API call. */ struct migrate_opts { /* new members should be added at the end */ char *directory; bool verbose; bool stop; /* stop the container after dump? */ char *predump_dir; /* relative to directory above */ char *pageserver_address; /* where should memory pages be send? */ char *pageserver_port; /* This flag indicates whether or not the container's rootfs will have * the same inodes on checkpoint and restore. In the case of e.g. zfs * send or btrfs send, or an LVM snapshot, this will be true, but it * won't if e.g. you rsync the filesystems between two machines. */ bool preserves_inodes; /* Path to an executable script that will be registered as a criu * "action script" */ char *action_script; /* If CRIU >= 2.4 is detected the option to skip in-flight connections * will be enabled by default. The flag 'disable_skip_in_flight' will * unconditionally disable this feature. In-flight connections are * not fully established TCP connections: SYN, SYN-ACK */ bool disable_skip_in_flight; /* This is the maximum file size for deleted files (which CRIU calls * "ghost" files) that will be handled. 0 indicates the CRIU default, * which at this time is 1MB. */ uint64_t ghost_limit; }; /*! * \brief Create a new container. * * \param name Name to use for container. * \param configpath Full path to configuration file to use. * * \return Newly-allocated container, or \c NULL on error. */ struct lxc_container *lxc_container_new(const char *name, const char *configpath); /*! * \brief Add a reference to the specified container. * * \param c Container. * * \return \c true on success, \c false on error. */ int lxc_container_get(struct lxc_container *c); /*! * \brief Drop a reference to the specified container. * * \param c Container. * * \return \c 0 on success, \c 1 if reference was successfully dropped * and container has been freed, and \c -1 on error. * * \warning If \c 1 is returned, \p c is no longer valid. */ int lxc_container_put(struct lxc_container *c); /*! * \brief Obtain a list of all container states. * \param[out] states Caller-allocated array to hold all states (may be \c NULL). * * \return Number of container states. * * \note Passing \c NULL for \p states allows the caller to first * calculate how many states there are before calling the function again, the second time * providing a suitably-sized array to store the static string pointers * in. * \note The \p states array should be freed by the caller, but not the strings the elements point to. */ int lxc_get_wait_states(const char **states); /*! * \brief Get the value for a global config key * * \param key The name of the config key * * \return String representing the current value for the key. */ const char *lxc_get_global_config_item(const char *key); /*! * \brief Determine version of LXC. * \return Static string representing version of LXC in use. * * \note Returned string must not be freed. */ const char *lxc_get_version(void); /*! * \brief Get a list of defined containers in a lxcpath. * * \param lxcpath lxcpath under which to look. * \param names If not \c NULL, then a list of container names will be returned here. * \param cret If not \c NULL, then a list of lxc_containers will be returned here. * * \return Number of containers found, or \c -1 on error. * * \note Values returned in \p cret are sorted by container name. */ int list_defined_containers(const char *lxcpath, char ***names, struct lxc_container ***cret); /*! * \brief Get a list of active containers for a given lxcpath. * * \param lxcpath Full \c LXCPATH path to consider. * \param[out] names Dynamically-allocated array of container names. * \param[out] cret Dynamically-allocated list of containers. * * \return Number of containers found, or -1 on error. * * \note Some of the containers may not be "defined". * \note Values returned in \p cret are sorted by container name. * \note \p names and \p cret may both (or either) be specified as \c NULL. * \note \p names and \p cret must be freed by the caller. */ int list_active_containers(const char *lxcpath, char ***names, struct lxc_container ***cret); /*! * \brief Get a complete list of all containers for a given lxcpath. * * \param lxcpath Full \c LXCPATH path to consider. * \param[out] names Dynamically-allocated array of container name. * \param[out] cret Dynamically-allocated list of containers. * * \return Number of containers, or -1 on error. * * \note Some of the containers may not be "defined". * \note Values returned in \p cret are sorted by container name. * \note \p names and \p cret may both (or either) be specified as \c NULL. * \note \p names and \p cret must be freed by the caller. */ int list_all_containers(const char *lxcpath, char ***names, struct lxc_container ***cret); /*! * \brief Close log file. */ void lxc_log_close(void); #ifdef __cplusplus } #endif #endif lxc-2.0.8/src/lxc/conf.c0000644061062106075000000034644013105116772011724 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* makedev() */ #ifdef MAJOR_IN_MKDEV # include #endif #ifdef HAVE_STATVFS #include #endif #if HAVE_PTY_H #include #else #include <../include/openpty.h> #endif #ifdef HAVE_LINUX_MEMFD_H #include #endif #include "af_unix.h" #include "bdev.h" #include "caps.h" /* for lxc_caps_last_cap() */ #include "cgroup.h" #include "conf.h" #include "error.h" #include "log.h" #include "lxcaufs.h" #include "lxclock.h" #include "lxcoverlay.h" #include "lxcseccomp.h" #include "namespace.h" #include "network.h" #include "parse.h" #include "utils.h" #include "lsm/lsm.h" #if HAVE_LIBCAP #include #endif #if HAVE_SYS_PERSONALITY_H #include #endif #if IS_BIONIC #include <../include/lxcmntent.h> #else #include #endif lxc_log_define(lxc_conf, lxc); #if HAVE_LIBCAP #ifndef CAP_SETFCAP #define CAP_SETFCAP 31 #endif #ifndef CAP_MAC_OVERRIDE #define CAP_MAC_OVERRIDE 32 #endif #ifndef CAP_MAC_ADMIN #define CAP_MAC_ADMIN 33 #endif #endif #ifndef PR_CAPBSET_DROP #define PR_CAPBSET_DROP 24 #endif #ifndef LO_FLAGS_AUTOCLEAR #define LO_FLAGS_AUTOCLEAR 4 #endif /* needed for cgroup automount checks, regardless of whether we * have included linux/capability.h or not */ #ifndef CAP_SYS_ADMIN #define CAP_SYS_ADMIN 21 #endif /* Define pivot_root() if missing from the C library */ #ifndef HAVE_PIVOT_ROOT static int pivot_root(const char * new_root, const char * put_old) { #ifdef __NR_pivot_root return syscall(__NR_pivot_root, new_root, put_old); #else errno = ENOSYS; return -1; #endif } #else extern int pivot_root(const char * new_root, const char * put_old); #endif /* Define sethostname() if missing from the C library */ #ifndef HAVE_SETHOSTNAME static int sethostname(const char * name, size_t len) { #ifdef __NR_sethostname return syscall(__NR_sethostname, name, len); #else errno = ENOSYS; return -1; #endif } #endif /* Define __S_ISTYPE if missing from the C library */ #ifndef __S_ISTYPE #define __S_ISTYPE(mode, mask) (((mode) & S_IFMT) == (mask)) #endif #ifndef MS_PRIVATE #define MS_PRIVATE (1<<18) #endif #ifndef MS_LAZYTIME #define MS_LAZYTIME (1<<25) #endif /* memfd_create() */ #ifndef MFD_CLOEXEC #define MFD_CLOEXEC 0x0001U #endif #ifndef MFD_ALLOW_SEALING #define MFD_ALLOW_SEALING 0x0002U #endif #ifndef HAVE_MEMFD_CREATE static int memfd_create(const char *name, unsigned int flags) { #ifndef __NR_memfd_create #if defined __i386__ #define __NR_memfd_create 356 #elif defined __x86_64__ #define __NR_memfd_create 319 #elif defined __arm__ #define __NR_memfd_create 385 #elif defined __aarch64__ #define __NR_memfd_create 279 #elif defined __s390__ #define __NR_memfd_create 350 #elif defined __powerpc__ #define __NR_memfd_create 360 #elif defined __sparc__ #define __NR_memfd_create 348 #elif defined __blackfin__ #define __NR_memfd_create 390 #elif defined __ia64__ #define __NR_memfd_create 1340 #elif defined _MIPS_SIM #if _MIPS_SIM == _MIPS_SIM_ABI32 #define __NR_memfd_create 4354 #endif #if _MIPS_SIM == _MIPS_SIM_NABI32 #define __NR_memfd_create 6318 #endif #if _MIPS_SIM == _MIPS_SIM_ABI64 #define __NR_memfd_create 5314 #endif #endif #endif #ifdef __NR_memfd_create return syscall(__NR_memfd_create, name, flags); #else errno = ENOSYS; return -1; #endif } #else extern int memfd_create(const char *name, unsigned int flags); #endif char *lxchook_names[NUM_LXC_HOOKS] = { "pre-start", "pre-mount", "mount", "autodev", "start", "stop", "post-stop", "clone", "destroy" }; typedef int (*instantiate_cb)(struct lxc_handler *, struct lxc_netdev *); struct mount_opt { char *name; int clear; int flag; }; struct caps_opt { char *name; 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); static int instantiate_veth(struct lxc_handler *, struct lxc_netdev *); static int instantiate_macvlan(struct lxc_handler *, struct lxc_netdev *); static int instantiate_vlan(struct lxc_handler *, struct lxc_netdev *); static int instantiate_phys(struct lxc_handler *, struct lxc_netdev *); static int instantiate_empty(struct lxc_handler *, struct lxc_netdev *); static int instantiate_none(struct lxc_handler *, struct lxc_netdev *); static instantiate_cb netdev_conf[LXC_NET_MAXCONFTYPE + 1] = { [LXC_NET_VETH] = instantiate_veth, [LXC_NET_MACVLAN] = instantiate_macvlan, [LXC_NET_VLAN] = instantiate_vlan, [LXC_NET_PHYS] = instantiate_phys, [LXC_NET_EMPTY] = instantiate_empty, [LXC_NET_NONE] = instantiate_none, }; static int shutdown_veth(struct lxc_handler *, struct lxc_netdev *); static int shutdown_macvlan(struct lxc_handler *, struct lxc_netdev *); static int shutdown_vlan(struct lxc_handler *, struct lxc_netdev *); static int shutdown_phys(struct lxc_handler *, struct lxc_netdev *); static int shutdown_empty(struct lxc_handler *, struct lxc_netdev *); static int shutdown_none(struct lxc_handler *, struct lxc_netdev *); static instantiate_cb netdev_deconf[LXC_NET_MAXCONFTYPE + 1] = { [LXC_NET_VETH] = shutdown_veth, [LXC_NET_MACVLAN] = shutdown_macvlan, [LXC_NET_VLAN] = shutdown_vlan, [LXC_NET_PHYS] = shutdown_phys, [LXC_NET_EMPTY] = shutdown_empty, [LXC_NET_NONE] = shutdown_none, }; static struct mount_opt mount_opt[] = { { "async", 1, MS_SYNCHRONOUS }, { "atime", 1, MS_NOATIME }, { "bind", 0, MS_BIND }, { "defaults", 0, 0 }, { "dev", 1, MS_NODEV }, { "diratime", 1, MS_NODIRATIME }, { "dirsync", 0, MS_DIRSYNC }, { "exec", 1, MS_NOEXEC }, { "lazytime", 0, MS_LAZYTIME }, { "mand", 0, MS_MANDLOCK }, { "noatime", 0, MS_NOATIME }, { "nodev", 0, MS_NODEV }, { "nodiratime", 0, MS_NODIRATIME }, { "noexec", 0, MS_NOEXEC }, { "nomand", 1, MS_MANDLOCK }, { "norelatime", 1, MS_RELATIME }, { "nostrictatime", 1, MS_STRICTATIME }, { "nosuid", 0, MS_NOSUID }, { "rbind", 0, MS_BIND|MS_REC }, { "relatime", 0, MS_RELATIME }, { "remount", 0, MS_REMOUNT }, { "ro", 0, MS_RDONLY }, { "rw", 1, MS_RDONLY }, { "strictatime", 0, MS_STRICTATIME }, { "suid", 1, MS_NOSUID }, { "sync", 0, MS_SYNCHRONOUS }, { NULL, 0, 0 }, }; #if HAVE_LIBCAP static struct caps_opt caps_opt[] = { { "chown", CAP_CHOWN }, { "dac_override", CAP_DAC_OVERRIDE }, { "dac_read_search", CAP_DAC_READ_SEARCH }, { "fowner", CAP_FOWNER }, { "fsetid", CAP_FSETID }, { "kill", CAP_KILL }, { "setgid", CAP_SETGID }, { "setuid", CAP_SETUID }, { "setpcap", CAP_SETPCAP }, { "linux_immutable", CAP_LINUX_IMMUTABLE }, { "net_bind_service", CAP_NET_BIND_SERVICE }, { "net_broadcast", CAP_NET_BROADCAST }, { "net_admin", CAP_NET_ADMIN }, { "net_raw", CAP_NET_RAW }, { "ipc_lock", CAP_IPC_LOCK }, { "ipc_owner", CAP_IPC_OWNER }, { "sys_module", CAP_SYS_MODULE }, { "sys_rawio", CAP_SYS_RAWIO }, { "sys_chroot", CAP_SYS_CHROOT }, { "sys_ptrace", CAP_SYS_PTRACE }, { "sys_pacct", CAP_SYS_PACCT }, { "sys_admin", CAP_SYS_ADMIN }, { "sys_boot", CAP_SYS_BOOT }, { "sys_nice", CAP_SYS_NICE }, { "sys_resource", CAP_SYS_RESOURCE }, { "sys_time", CAP_SYS_TIME }, { "sys_tty_config", CAP_SYS_TTY_CONFIG }, { "mknod", CAP_MKNOD }, { "lease", CAP_LEASE }, #ifdef CAP_AUDIT_READ { "audit_read", CAP_AUDIT_READ }, #endif #ifdef CAP_AUDIT_WRITE { "audit_write", CAP_AUDIT_WRITE }, #endif #ifdef CAP_AUDIT_CONTROL { "audit_control", CAP_AUDIT_CONTROL }, #endif { "setfcap", CAP_SETFCAP }, { "mac_override", CAP_MAC_OVERRIDE }, { "mac_admin", CAP_MAC_ADMIN }, #ifdef CAP_SYSLOG { "syslog", CAP_SYSLOG }, #endif #ifdef CAP_WAKE_ALARM { "wake_alarm", CAP_WAKE_ALARM }, #endif #ifdef CAP_BLOCK_SUSPEND { "block_suspend", CAP_BLOCK_SUSPEND }, #endif }; #else static struct caps_opt caps_opt[] = {}; #endif static int run_buffer(char *buffer) { struct lxc_popen_FILE *f; char *output; int ret; f = lxc_popen(buffer); if (!f) { SYSERROR("Failed to popen() %s.", buffer); return -1; } output = malloc(LXC_LOG_BUFFER_SIZE); if (!output) { ERROR("Failed to allocate memory for %s.", buffer); lxc_pclose(f); return -1; } while (fgets(output, LXC_LOG_BUFFER_SIZE, f->f)) DEBUG("Script %s with output: %s.", buffer, output); free(output); ret = lxc_pclose(f); if (ret == -1) { SYSERROR("Script exited with error."); return -1; } else if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0) { ERROR("Script exited with status %d.", WEXITSTATUS(ret)); return -1; } else if (WIFSIGNALED(ret)) { ERROR("Script terminated by signal %d.", WTERMSIG(ret)); return -1; } return 0; } static int run_script_argv(const char *name, const char *section, const char *script, const char *hook, const char *lxcpath, char **argsin) { int ret, i; char *buffer; size_t size = 0; INFO("Executing script \"%s\" for container \"%s\", config section \"%s\".", script, name, section); for (i = 0; argsin && argsin[i]; i++) size += strlen(argsin[i]) + 1; size += strlen(hook) + 1; size += strlen(script); size += strlen(name); size += strlen(section); size += 3; if (size > INT_MAX) return -1; buffer = alloca(size); if (!buffer) { ERROR("Failed to allocate memory."); return -1; } ret = snprintf(buffer, size, "%s %s %s %s", script, name, section, hook); if (ret < 0 || (size_t)ret >= size) { ERROR("Script name too long."); return -1; } for (i = 0; argsin && argsin[i]; i++) { int len = size - ret; int rc; rc = snprintf(buffer + ret, len, " %s", argsin[i]); if (rc < 0 || rc >= len) { ERROR("Script args too long."); return -1; } ret += rc; } return run_buffer(buffer); } static int run_script(const char *name, const char *section, const char *script, ...) { int ret; char *buffer, *p; size_t size = 0; va_list ap; INFO("Executing script \"%s\" for container \"%s\", config section \"%s\".", script, name, section); va_start(ap, script); while ((p = va_arg(ap, char *))) size += strlen(p) + 1; va_end(ap); size += strlen(script); size += strlen(name); size += strlen(section); size += 3; if (size > INT_MAX) return -1; buffer = alloca(size); if (!buffer) { ERROR("Failed to allocate memory."); return -1; } ret = snprintf(buffer, size, "%s %s %s", script, name, section); if (ret < 0 || ret >= size) { ERROR("Script name too long."); return -1; } va_start(ap, script); while ((p = va_arg(ap, char *))) { int len = size - ret; int rc; rc = snprintf(buffer + ret, len, " %s", p); if (rc < 0 || rc >= len) { ERROR("Script args too long."); return -1; } ret += rc; } va_end(ap); return run_buffer(buffer); } static int mount_rootfs_dir(const char *rootfs, const char *target, const char *options) { unsigned long mntflags; char *mntdata; int ret; if (parse_mntopts(options, &mntflags, &mntdata) < 0) { free(mntdata); return -1; } ret = mount(rootfs, target, "none", MS_BIND | MS_REC | mntflags, mntdata); free(mntdata); return ret; } static int lxc_mount_rootfs_file(const char *rootfs, const char *target, const char *options) { int ret, loopfd; char path[MAXPATHLEN]; loopfd = lxc_prepare_loop_dev(rootfs, path, LO_FLAGS_AUTOCLEAR); if (loopfd < 0) return -1; DEBUG("prepared loop device \"%s\"", path); ret = mount_unknown_fs(path, target, options); close(loopfd); DEBUG("mounted rootfs \"%s\" on loop device \"%s\" via loop device \"%s\"", rootfs, target, path); return ret; } static int mount_rootfs_block(const char *rootfs, const char *target, const char *options) { return mount_unknown_fs(rootfs, target, options); } /* * pin_rootfs * if rootfs is a directory, then open ${rootfs}/lxc.hold for writing for * the duration of the container run, to prevent the container from marking * the underlying fs readonly on shutdown. unlink the file immediately so * no name pollution is happens * return -1 on error. * return -2 if nothing needed to be pinned. * return an open fd (>=0) if we pinned it. */ int pin_rootfs(const char *rootfs) { char absrootfs[MAXPATHLEN]; char absrootfspin[MAXPATHLEN]; struct stat s; int ret, fd; if (rootfs == NULL || strlen(rootfs) == 0) return -2; if (!realpath(rootfs, absrootfs)) return -2; if (access(absrootfs, F_OK)) return -1; if (stat(absrootfs, &s)) return -1; if (!S_ISDIR(s.st_mode)) return -2; ret = snprintf(absrootfspin, MAXPATHLEN, "%s/lxc.hold", absrootfs); if (ret >= MAXPATHLEN) return -1; fd = open(absrootfspin, O_CREAT | O_RDWR, S_IWUSR|S_IRUSR); if (fd < 0) return fd; (void)unlink(absrootfspin); return fd; } /* * If we are asking to remount something, make sure that any * NOEXEC etc are honored. */ static unsigned long add_required_remount_flags(const char *s, const char *d, unsigned long flags) { #ifdef HAVE_STATVFS struct statvfs sb; unsigned long required_flags = 0; if (!(flags & MS_REMOUNT)) return flags; if (!s) s = d; if (!s) return flags; if (statvfs(s, &sb) < 0) return flags; if (sb.f_flag & MS_NOSUID) required_flags |= MS_NOSUID; if (sb.f_flag & MS_NODEV) required_flags |= MS_NODEV; if (sb.f_flag & MS_RDONLY) required_flags |= MS_RDONLY; if (sb.f_flag & MS_NOEXEC) required_flags |= MS_NOEXEC; return flags | required_flags; #else return flags; #endif } static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_handler *handler) { int r; int i; static struct { int match_mask; int match_flag; const char *source; const char *destination; const char *fstype; unsigned long flags; const char *options; } default_mounts[] = { /* Read-only bind-mounting... In older kernels, doing that required * to do one MS_BIND mount and then MS_REMOUNT|MS_RDONLY the same * one. According to mount(2) manpage, MS_BIND honors MS_RDONLY from * kernel 2.6.26 onwards. However, this apparently does not work on * kernel 3.8. Unfortunately, on that very same kernel, doing the * same trick as above doesn't seem to work either, there one needs * to ALSO specify MS_BIND for the remount, otherwise the entire * fs is remounted read-only or the mount fails because it's busy... * MS_REMOUNT|MS_BIND|MS_RDONLY seems to work for kernels as low as * 2.6.32... */ { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, "proc", "%r/proc", "proc", MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL }, /* proc/tty is used as a temporary placeholder for proc/sys/net which we'll move back in a few steps */ { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, "%r/proc/sys/net", "%r/proc/tty", NULL, MS_BIND, NULL }, { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, "%r/proc/sys", "%r/proc/sys", NULL, MS_BIND, NULL }, { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, NULL, "%r/proc/sys", NULL, MS_REMOUNT|MS_BIND|MS_RDONLY, NULL }, { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, "%r/proc/tty", "%r/proc/sys/net", NULL, MS_MOVE, NULL }, { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, "%r/proc/sysrq-trigger", "%r/proc/sysrq-trigger", NULL, MS_BIND, NULL }, { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED, NULL, "%r/proc/sysrq-trigger", NULL, MS_REMOUNT|MS_BIND|MS_RDONLY, NULL }, { LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_RW, "proc", "%r/proc", "proc", MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL }, { LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RW, "sysfs", "%r/sys", "sysfs", 0, NULL }, { LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RO, "sysfs", "%r/sys", "sysfs", MS_RDONLY, NULL }, { LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED, "sysfs", "%r/sys", "sysfs", MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL }, { LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED, "%r/sys", "%r/sys", NULL, MS_BIND, NULL }, { LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED, NULL, "%r/sys", NULL, MS_REMOUNT|MS_BIND|MS_RDONLY, NULL }, { LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED, "sysfs", "%r/sys/devices/virtual/net", "sysfs", 0, NULL }, { LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED, "%r/sys/devices/virtual/net/devices/virtual/net", "%r/sys/devices/virtual/net", NULL, MS_BIND, NULL }, { LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED, NULL, "%r/sys/devices/virtual/net", NULL, MS_REMOUNT|MS_BIND|MS_NOSUID|MS_NODEV|MS_NOEXEC, NULL }, { 0, 0, NULL, NULL, NULL, 0, NULL } }; for (i = 0; default_mounts[i].match_mask; i++) { if ((flags & default_mounts[i].match_mask) == default_mounts[i].match_flag) { char *source = NULL; char *destination = NULL; int saved_errno; unsigned long mflags; if (default_mounts[i].source) { /* will act like strdup if %r is not present */ source = lxc_string_replace("%r", conf->rootfs.path ? conf->rootfs.mount : "", default_mounts[i].source); if (!source) { SYSERROR("memory allocation error"); return -1; } } if (!default_mounts[i].destination) { ERROR("BUG: auto mounts destination %d was NULL", i); free(source); return -1; } /* will act like strdup if %r is not present */ destination = lxc_string_replace("%r", conf->rootfs.path ? conf->rootfs.mount : "", default_mounts[i].destination); if (!destination) { saved_errno = errno; SYSERROR("memory allocation error"); free(source); errno = saved_errno; return -1; } mflags = add_required_remount_flags(source, destination, default_mounts[i].flags); r = safe_mount(source, destination, default_mounts[i].fstype, mflags, default_mounts[i].options, conf->rootfs.path ? conf->rootfs.mount : NULL); saved_errno = errno; if (r < 0 && errno == ENOENT) { INFO("Mount source or target for %s on %s doesn't exist. Skipping.", source, destination); r = 0; } else if (r < 0) SYSERROR("error mounting %s on %s flags %lu", source, destination, mflags); free(source); free(destination); if (r < 0) { errno = saved_errno; return -1; } } } if (flags & LXC_AUTO_CGROUP_MASK) { int cg_flags; cg_flags = flags & LXC_AUTO_CGROUP_MASK; /* If the type of cgroup mount was not specified, it depends on the * container's capabilities as to what makes sense: if we have * CAP_SYS_ADMIN, the read-only part can be remounted read-write * anyway, so we may as well default to read-write; then the admin * will not be given a false sense of security. (And if they really * want mixed r/o r/w, then they can explicitly specify :mixed.) * OTOH, if the container lacks CAP_SYS_ADMIN, do only default to * :mixed, because then the container can't remount it read-write. */ if (cg_flags == LXC_AUTO_CGROUP_NOSPEC || cg_flags == LXC_AUTO_CGROUP_FULL_NOSPEC) { int has_sys_admin = 0; if (!lxc_list_empty(&conf->keepcaps)) { has_sys_admin = in_caplist(CAP_SYS_ADMIN, &conf->keepcaps); } else { has_sys_admin = !in_caplist(CAP_SYS_ADMIN, &conf->caps); } if (cg_flags == LXC_AUTO_CGROUP_NOSPEC) { cg_flags = has_sys_admin ? LXC_AUTO_CGROUP_RW : LXC_AUTO_CGROUP_MIXED; } else { cg_flags = has_sys_admin ? LXC_AUTO_CGROUP_FULL_RW : LXC_AUTO_CGROUP_FULL_MIXED; } } if (!cgroup_mount(conf->rootfs.path ? conf->rootfs.mount : "", handler, cg_flags)) { SYSERROR("error mounting /sys/fs/cgroup"); return -1; } } return 0; } static int mount_rootfs(const char *rootfs, const char *target, const char *options) { char absrootfs[MAXPATHLEN]; struct stat s; int i; typedef int (*rootfs_cb)(const char *, const char *, const char *); struct rootfs_type { int type; rootfs_cb cb; } rtfs_type[] = { { S_IFDIR, mount_rootfs_dir }, { S_IFBLK, mount_rootfs_block }, { S_IFREG, lxc_mount_rootfs_file }, }; if (!realpath(rootfs, absrootfs)) { SYSERROR("Failed to get real path for \"%s\".", rootfs); return -1; } if (access(absrootfs, F_OK)) { SYSERROR("The rootfs \"%s\" is not accessible.", absrootfs); return -1; } if (stat(absrootfs, &s)) { SYSERROR("Failed to stat the rootfs \"%s\".", absrootfs); return -1; } for (i = 0; i < sizeof(rtfs_type)/sizeof(rtfs_type[0]); i++) { if (!__S_ISTYPE(s.st_mode, rtfs_type[i].type)) continue; return rtfs_type[i].cb(absrootfs, target, options); } ERROR("Unsupported rootfs type for rootfs \"%s\".", absrootfs); return -1; } static int setup_utsname(struct utsname *utsname) { if (!utsname) return 0; if (sethostname(utsname->nodename, strlen(utsname->nodename))) { SYSERROR("failed to set the hostname to '%s'", utsname->nodename); return -1; } INFO("'%s' hostname has been setup", utsname->nodename); return 0; } struct dev_symlinks { const char *oldpath; const char *name; }; static const struct dev_symlinks dev_symlinks[] = { {"/proc/self/fd", "fd"}, {"/proc/self/fd/0", "stdin"}, {"/proc/self/fd/1", "stdout"}, {"/proc/self/fd/2", "stderr"}, }; static int setup_dev_symlinks(const struct lxc_rootfs *rootfs) { char path[MAXPATHLEN]; int ret,i; struct stat s; for (i = 0; i < sizeof(dev_symlinks) / sizeof(dev_symlinks[0]); i++) { const struct dev_symlinks *d = &dev_symlinks[i]; ret = snprintf(path, sizeof(path), "%s/dev/%s", rootfs->path ? rootfs->mount : "", d->name); if (ret < 0 || ret >= MAXPATHLEN) return -1; /* * Stat the path first. If we don't get an error * accept it as is and don't try to create it */ if (!stat(path, &s)) { continue; } ret = symlink(d->oldpath, path); if (ret && errno != EEXIST) { if ( errno == EROFS ) { WARN("Warning: Read Only file system while creating %s", path); } else { SYSERROR("Error creating %s", path); return -1; } } } return 0; } /* * Build a space-separate list of ptys to pass to systemd. */ static bool append_ptyname(char **pp, char *name) { char *p; if (!*pp) { *pp = malloc(strlen(name) + strlen("container_ttys=") + 1); if (!*pp) return false; sprintf(*pp, "container_ttys=%s", name); return true; } p = realloc(*pp, strlen(*pp) + strlen(name) + 2); if (!p) return false; *pp = p; strcat(p, " "); strcat(p, name); return true; } static int setup_tty(struct lxc_conf *conf) { const struct lxc_tty_info *tty_info = &conf->tty_info; char *ttydir = conf->ttydir; char path[MAXPATHLEN], lxcpath[MAXPATHLEN]; int i, ret; if (!conf->rootfs.path) return 0; for (i = 0; i < tty_info->nbtty; i++) { struct lxc_pty_info *pty_info = &tty_info->pty_info[i]; ret = snprintf(path, sizeof(path), "/dev/tty%d", i + 1); if (ret >= sizeof(path)) { ERROR("pathname too long for ttys"); return -1; } if (ttydir) { /* create dev/lxc/tty%d" */ ret = snprintf(lxcpath, sizeof(lxcpath), "/dev/%s/tty%d", ttydir, i + 1); if (ret >= sizeof(lxcpath)) { ERROR("pathname too long for ttys"); return -1; } ret = creat(lxcpath, 0660); if (ret==-1 && errno != EEXIST) { SYSERROR("error creating %s", lxcpath); return -1; } if (ret >= 0) close(ret); ret = unlink(path); if (ret && errno != ENOENT) { SYSERROR("error unlinking %s", path); return -1; } if (mount(pty_info->name, lxcpath, "none", MS_BIND, 0)) { WARN("failed to mount '%s'->'%s'", pty_info->name, path); continue; } ret = snprintf(lxcpath, sizeof(lxcpath), "%s/tty%d", ttydir, i+1); if (ret >= sizeof(lxcpath)) { ERROR("tty pathname too long"); return -1; } ret = symlink(lxcpath, path); if (ret) { SYSERROR("failed to create symlink for tty %d", i+1); return -1; } } else { /* If we populated /dev, then we need to create /dev/ttyN */ if (access(path, F_OK)) { ret = creat(path, 0660); if (ret==-1) { SYSERROR("error creating %s", path); /* this isn't fatal, continue */ } else { close(ret); } } if (mount(pty_info->name, path, "none", MS_BIND, 0)) { SYSERROR("failed to mount '%s'->'%s'", pty_info->name, path); continue; } } if (!append_ptyname(&conf->pty_names, pty_info->name)) { ERROR("Error setting up container_ttys string"); return -1; } } INFO("%d tty(s) has been setup", tty_info->nbtty); return 0; } static int setup_rootfs_pivot_root(const char *rootfs) { int oldroot = -1, newroot = -1; oldroot = open("/", O_DIRECTORY | O_RDONLY); if (oldroot < 0) { SYSERROR("Error opening old-/ for fchdir"); return -1; } newroot = open(rootfs, O_DIRECTORY | O_RDONLY); if (newroot < 0) { SYSERROR("Error opening new-/ for fchdir"); goto fail; } /* change into new root fs */ if (fchdir(newroot)) { SYSERROR("can't chdir to new rootfs '%s'", rootfs); goto fail; } /* pivot_root into our new root fs */ if (pivot_root(".", ".")) { SYSERROR("pivot_root syscall failed"); goto fail; } /* * at this point the old-root is mounted on top of our new-root * To unmounted it we must not be chdir'd into it, so escape back * to old-root */ if (fchdir(oldroot) < 0) { SYSERROR("Error entering oldroot"); goto fail; } if (umount2(".", MNT_DETACH) < 0) { SYSERROR("Error detaching old root"); goto fail; } if (fchdir(newroot) < 0) { SYSERROR("Error re-entering newroot"); goto fail; } close(oldroot); close(newroot); DEBUG("pivot_root syscall to '%s' successful", rootfs); return 0; fail: if (oldroot != -1) close(oldroot); if (newroot != -1) close(newroot); return -1; } /* * Just create a path for /dev under $lxcpath/$name and in rootfs * If we hit an error, log it but don't fail yet. */ static int mount_autodev(const char *name, const struct lxc_rootfs *rootfs, const char *lxcpath) { int ret; size_t clen; char *path; INFO("Mounting container /dev"); /* $(rootfs->mount) + "/dev/pts" + '\0' */ clen = (rootfs->path ? strlen(rootfs->mount) : 0) + 9; path = alloca(clen); ret = snprintf(path, clen, "%s/dev", rootfs->path ? rootfs->mount : ""); if (ret < 0 || ret >= clen) return -1; if (!dir_exists(path)) { WARN("No /dev in container."); WARN("Proceeding without autodev setup"); return 0; } ret = safe_mount("none", path, "tmpfs", 0, "size=500000,mode=755", rootfs->path ? rootfs->mount : NULL); if (ret != 0) { SYSERROR("Failed mounting tmpfs onto %s\n", path); return -1; } INFO("Mounted tmpfs onto %s", path); ret = snprintf(path, clen, "%s/dev/pts", rootfs->path ? rootfs->mount : ""); if (ret < 0 || ret >= clen) return -1; /* * If we are running on a devtmpfs mapping, dev/pts may already exist. * If not, then create it and exit if that fails... */ if (!dir_exists(path)) { ret = mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); if (ret) { SYSERROR("Failed to create /dev/pts in container"); return -1; } } INFO("Mounted container /dev"); return 0; } struct lxc_devs { const char *name; mode_t mode; int maj; int min; }; static const struct lxc_devs lxc_devs[] = { { "null", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 3 }, { "zero", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 5 }, { "full", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 7 }, { "urandom", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 9 }, { "random", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 8 }, { "tty", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 5, 0 }, }; static int lxc_fill_autodev(const struct lxc_rootfs *rootfs) { int ret; char path[MAXPATHLEN]; int i; mode_t cmask; ret = snprintf(path, MAXPATHLEN, "%s/dev", rootfs->path ? rootfs->mount : ""); if (ret < 0 || ret >= MAXPATHLEN) { ERROR("Error calculating container /dev location"); return -1; } /* ignore, just don't try to fill in */ if (!dir_exists(path)) return 0; INFO("populating container /dev"); cmask = umask(S_IXUSR | S_IXGRP | S_IXOTH); for (i = 0; i < sizeof(lxc_devs) / sizeof(lxc_devs[0]); i++) { const struct lxc_devs *d = &lxc_devs[i]; ret = snprintf(path, MAXPATHLEN, "%s/dev/%s", rootfs->path ? rootfs->mount : "", d->name); if (ret < 0 || ret >= MAXPATHLEN) return -1; ret = mknod(path, d->mode, makedev(d->maj, d->min)); if (ret < 0) { char hostpath[MAXPATHLEN]; FILE *pathfile; if (errno == EEXIST) { DEBUG("\"%s\" device already existed", path); continue; } /* Unprivileged containers cannot create devices, so * bind mount the device from the host. */ ret = snprintf(hostpath, MAXPATHLEN, "/dev/%s", d->name); if (ret < 0 || ret >= MAXPATHLEN) return -1; pathfile = fopen(path, "wb"); if (!pathfile) { SYSERROR("Failed to create device mount target '%s'", path); return -1; } fclose(pathfile); if (safe_mount(hostpath, path, 0, MS_BIND, NULL, rootfs->path ? rootfs->mount : NULL) != 0) { SYSERROR("Failed bind mounting device %s from host into container", d->name); return -1; } DEBUG("bind mounted \"%s\" onto \"%s\"", hostpath, path); } else { DEBUG("created device node \"%s\"", path); } } umask(cmask); INFO("populated container /dev"); return 0; } static int setup_rootfs(struct lxc_conf *conf) { struct bdev *bdev; const struct lxc_rootfs *rootfs; rootfs = &conf->rootfs; if (!rootfs->path) { if (mount("", "/", NULL, MS_SLAVE | MS_REC, 0)) { SYSERROR("Failed to make / rslave."); return -1; } return 0; } if (access(rootfs->mount, F_OK)) { SYSERROR("Failed to access to \"%s\". Check it is present.", rootfs->mount); return -1; } /* First try mounting rootfs using a bdev. */ bdev = bdev_init(conf, rootfs->path, rootfs->mount, rootfs->options); if (bdev && !bdev->ops->mount(bdev)) { bdev_put(bdev); DEBUG("Mounted rootfs \"%s\" onto \"%s\" with options \"%s\".", rootfs->path, rootfs->mount, rootfs->options ? rootfs->options : "(null)"); return 0; } if (bdev) bdev_put(bdev); if (mount_rootfs(rootfs->path, rootfs->mount, rootfs->options)) { ERROR("Failed to mount rootfs \"%s\" onto \"%s\" with options \"%s\".", rootfs->path, rootfs->mount, rootfs->options ? rootfs->options : "(null)"); return -1; } DEBUG("Mounted rootfs \"%s\" onto \"%s\" with options \"%s\".", rootfs->path, rootfs->mount, rootfs->options ? rootfs->options : "(null)"); return 0; } int prepare_ramfs_root(char *root) { char buf[LXC_LINELEN], *p; char nroot[PATH_MAX]; FILE *f; int i; char *p2; if (realpath(root, nroot) == NULL) return -errno; if (chdir("/") == -1) return -errno; /* * We could use here MS_MOVE, but in userns this mount is * locked and can't be moved. */ if (mount(root, "/", NULL, MS_REC | MS_BIND, NULL) < 0) { SYSERROR("Failed to move %s into /", root); return -errno; } if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL) < 0) { SYSERROR("Failed to make . rprivate"); return -errno; } /* * The following code cleans up inhereted mounts which are not * required for CT. * * The mountinfo file shows not all mounts, if a few points have been * unmounted between read operations from the mountinfo. So we need to * read mountinfo a few times. * * This loop can be skipped if a container uses unserns, because all * inherited mounts are locked and we should live with all this trash. */ while (1) { int progress = 0; f = fopen("./proc/self/mountinfo", "r"); if (!f) { SYSERROR("Unable to open /proc/self/mountinfo"); return -1; } while (fgets(buf, LXC_LINELEN, f)) { for (p = buf, i=0; p && i < 4; i++) p = strchr(p+1, ' '); if (!p) continue; p2 = strchr(p+1, ' '); if (!p2) continue; *p2 = '\0'; *p = '.'; if (strcmp(p + 1, "/") == 0) continue; if (strcmp(p + 1, "/proc") == 0) continue; if (umount2(p, MNT_DETACH) == 0) progress++; } fclose(f); if (!progress) break; } /* This also can be skipped if a container uses unserns */ umount2("./proc", MNT_DETACH); /* It is weird, but chdir("..") moves us in a new root */ if (chdir("..") == -1) { SYSERROR("Unable to change working directory"); return -1; } if (chroot(".") == -1) { SYSERROR("Unable to chroot"); return -1; } return 0; } static int setup_pivot_root(const struct lxc_rootfs *rootfs) { if (!rootfs->path) { DEBUG("container does not have a rootfs, so not doing pivot root"); return 0; } if (detect_ramfs_rootfs()) { DEBUG("detected that container is on ramfs"); if (prepare_ramfs_root(rootfs->mount)) { ERROR("failed to prepare minimal ramfs root"); return -1; } DEBUG("prepared ramfs root for container"); return 0; } if (setup_rootfs_pivot_root(rootfs->mount) < 0) { ERROR("failed to pivot root"); return -1; } DEBUG("finished pivot root"); return 0; } static int lxc_setup_devpts(int num_pts) { int ret; const char *devpts_mntopts = "newinstance,ptmxmode=0666,mode=0620,gid=5"; if (!num_pts) { DEBUG("no new devpts instance will be mounted since no pts " "devices are requested"); return 0; } /* Unmount old devpts instance. */ ret = access("/dev/pts/ptmx", F_OK); if (!ret) { ret = umount("/dev/pts"); if (ret < 0) { SYSERROR("failed to unmount old devpts instance"); return -1; } DEBUG("unmounted old /dev/pts instance"); } /* Create mountpoint for devpts instance. */ ret = mkdir("/dev/pts", 0755); if (ret < 0 && errno != EEXIST) { SYSERROR("failed to create the \"/dev/pts\" directory"); return -1; } /* Mount new devpts instance. */ ret = mount("devpts", "/dev/pts", "devpts", MS_MGC_VAL, devpts_mntopts); if (ret < 0) { SYSERROR("failed to mount new devpts instance"); return -1; } /* Remove any pre-existing /dev/ptmx file. */ ret = access("/dev/ptmx", F_OK); if (!ret) { ret = remove("/dev/ptmx"); if (ret < 0) { SYSERROR("failed to remove existing \"/dev/ptmx\""); return -1; } DEBUG("removed existing \"/dev/ptmx\""); } /* Create dummy /dev/ptmx file as bind mountpoint for /dev/pts/ptmx. */ ret = open("/dev/ptmx", O_CREAT, 0666); if (ret < 0) { SYSERROR("failed to create dummy \"/dev/ptmx\" file as bind mount target"); return -1; } close(ret); DEBUG("created dummy \"/dev/ptmx\" file as bind mount target"); /* Fallback option: create symlink /dev/ptmx -> /dev/pts/ptmx */ ret = mount("/dev/pts/ptmx", "/dev/ptmx", NULL, MS_BIND, NULL); if (!ret) { DEBUG("bind mounted \"/dev/pts/ptmx\" to \"/dev/ptmx\""); return 0; } else { /* Fallthrough and try to create a symlink. */ ERROR("failed to bind mount \"/dev/pts/ptmx\" to \"/dev/ptmx\""); } /* Remove the dummy /dev/ptmx file we created above. */ ret = remove("/dev/ptmx"); if (ret < 0) { SYSERROR("failed to remove existing \"/dev/ptmx\""); return -1; } /* Fallback option: Create symlink /dev/ptmx -> /dev/pts/ptmx. */ ret = symlink("/dev/pts/ptmx", "/dev/ptmx"); if (ret < 0) { SYSERROR("failed to create symlink \"/dev/ptmx\" -> \"/dev/pts/ptmx\""); return -1; } DEBUG("created symlink \"/dev/ptmx\" -> \"/dev/pts/ptmx\""); return 0; } static int setup_personality(int persona) { #if HAVE_SYS_PERSONALITY_H if (persona == -1) return 0; if (personality(persona) < 0) { SYSERROR("failed to set personality to '0x%x'", persona); return -1; } INFO("set personality to '0x%x'", persona); #endif return 0; } static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs, const struct lxc_console *console) { char path[MAXPATHLEN]; int ret, fd; if (console->path && !strcmp(console->path, "none")) return 0; ret = snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount); if (ret < 0 || (size_t)ret >= sizeof(path)) return -1; /* When we are asked to setup a console we remove any previous * /dev/console bind-mounts. */ if (file_exists(path)) { ret = lxc_unstack_mountpoint(path, false); if (ret < 0) { ERROR("failed to unmount \"%s\": %s", path, strerror(errno)); return -ret; } else { DEBUG("cleared all (%d) mounts from \"%s\"", ret, path); } ret = unlink(path); if (ret < 0) { SYSERROR("error unlinking %s", path); return -errno; } } /* For unprivileged containers autodev or automounts will already have * taken care of creating /dev/console. */ fd = open(path, O_CREAT | O_EXCL, S_IXUSR | S_IXGRP | S_IXOTH); if (fd < 0) { if (errno != EEXIST) { SYSERROR("failed to create console"); return -errno; } } else { close(fd); } if (chmod(console->name, S_IXUSR | S_IXGRP | S_IXOTH)) { SYSERROR("failed to set mode '0%o' to '%s'", S_IXUSR | S_IXGRP | S_IXOTH, console->name); return -errno; } if (safe_mount(console->name, path, "none", MS_BIND, 0, rootfs->mount) < 0) { ERROR("failed to mount '%s' on '%s'", console->name, path); return -1; } DEBUG("mounted pts device \"%s\" onto \"%s\"", console->name, path); return 0; } static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs, const struct lxc_console *console, char *ttydir) { int ret; char path[MAXPATHLEN], lxcpath[MAXPATHLEN]; /* create rootfs/dev/ directory */ ret = snprintf(path, sizeof(path), "%s/dev/%s", rootfs->mount, ttydir); if (ret < 0 || (size_t)ret >= sizeof(path)) return -1; ret = mkdir(path, 0755); if (ret && errno != EEXIST) { SYSERROR("failed with errno %d to create %s", errno, path); return -errno; } DEBUG("created directory for console and tty devices at \%s\"", path); ret = snprintf(lxcpath, sizeof(lxcpath), "%s/dev/%s/console", rootfs->mount, ttydir); if (ret < 0 || (size_t)ret >= sizeof(lxcpath)) return -1; ret = creat(lxcpath, 0660); if (ret == -1 && errno != EEXIST) { SYSERROR("error %d creating %s", errno, lxcpath); return -errno; } if (ret >= 0) close(ret); ret = snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount); if (ret < 0 || (size_t)ret >= sizeof(lxcpath)) return -1; /* When we are asked to setup a console we remove any previous * /dev/console bind-mounts. */ if (console->path && !strcmp(console->path, "none")) { struct stat st; ret = stat(path, &st); if (ret < 0) { if (errno == ENOENT) return 0; SYSERROR("failed stat() \"%s\"", path); return -errno; } /* /dev/console must be character device with major number 5 and * minor number 1. If not, give benefit of the doubt and assume * the user has mounted something else right there on purpose. */ if (((st.st_mode & S_IFMT) != S_IFCHR) || major(st.st_rdev) != 5 || minor(st.st_rdev) != 1) return 0; /* In case the user requested a bind-mount for /dev/console and * requests a ttydir we move the mount to the * /dev/mount); if (ret < 0) { if (errno != EINVAL) { ERROR("failed to MS_MOVE \"%s\" to \"%s\": %s", path, lxcpath, strerror(errno)); return -errno; } /* path was not a mountpoint */ ret = rename(path, lxcpath); if (ret < 0) { ERROR("failed to rename \"%s\" to \"%s\": %s", path, lxcpath, strerror(errno)); return -errno; } DEBUG("renamed \"%s\" to \"%s\"", path, lxcpath); } else { DEBUG("moved mount \"%s\" to \"%s\"", path, lxcpath); } /* Clear all remaining bind-mounts. */ ret = lxc_unstack_mountpoint(path, false); if (ret < 0) { ERROR("failed to unmount \"%s\": %s", path, strerror(errno)); return -ret; } else { DEBUG("cleared all (%d) mounts from \"%s\"", ret, path); } } else { if (file_exists(path)) { ret = lxc_unstack_mountpoint(path, false); if (ret < 0) { ERROR("failed to unmount \"%s\": %s", path, strerror(errno)); return -ret; } else { DEBUG("cleared all (%d) mounts from \"%s\"", ret, path); } } if (safe_mount(console->name, lxcpath, "none", MS_BIND, 0, rootfs->mount) < 0) { ERROR("failed to mount '%s' on '%s'", console->name, lxcpath); return -1; } DEBUG("mounted \"%s\" onto \"%s\"", console->name, lxcpath); } /* create symlink from rootfs /dev/console to '/console' */ ret = snprintf(lxcpath, sizeof(lxcpath), "%s/console", ttydir); if (ret < 0 || (size_t)ret >= sizeof(lxcpath)) return -1; ret = unlink(path); if (ret && errno != ENOENT) { SYSERROR("error unlinking %s", path); return -errno; } ret = symlink(lxcpath, path); if (ret < 0) { SYSERROR("failed to create symlink for console from \"%s\" to \"%s\"", lxcpath, path); return -1; } DEBUG("console has been setup under \"%s\" and symlinked to \"%s\"", lxcpath, path); return 0; } static int lxc_setup_console(const struct lxc_rootfs *rootfs, const struct lxc_console *console, char *ttydir) { /* We don't have a rootfs, /dev/console will be shared. */ if (!rootfs->path) { DEBUG("/dev/console will be shared with the host"); return 0; } if (!ttydir) return lxc_setup_dev_console(rootfs, console); return lxc_setup_ttydir_console(rootfs, console, ttydir); } static int setup_kmsg(const struct lxc_rootfs *rootfs, const struct lxc_console *console) { char kpath[MAXPATHLEN]; int ret; if (!rootfs->path) return 0; ret = snprintf(kpath, sizeof(kpath), "%s/dev/kmsg", rootfs->mount); if (ret < 0 || ret >= sizeof(kpath)) return -1; ret = unlink(kpath); if (ret && errno != ENOENT) { SYSERROR("error unlinking %s", kpath); return -1; } ret = symlink("console", kpath); if (ret) { SYSERROR("failed to create symlink for kmsg"); return -1; } return 0; } static void parse_mntopt(char *opt, unsigned long *flags, char **data) { struct mount_opt *mo; /* If opt is found in mount_opt, set or clear flags. * Otherwise append it to data. */ for (mo = &mount_opt[0]; mo->name != NULL; mo++) { if (!strncmp(opt, mo->name, strlen(mo->name))) { if (mo->clear) *flags &= ~mo->flag; else *flags |= mo->flag; return; } } if (strlen(*data)) strcat(*data, ","); strcat(*data, opt); } int parse_mntopts(const char *mntopts, unsigned long *mntflags, char **mntdata) { char *s, *data; char *p, *saveptr = NULL; *mntdata = NULL; *mntflags = 0L; if (!mntopts) return 0; s = strdup(mntopts); if (!s) { SYSERROR("failed to allocate memory"); return -1; } data = malloc(strlen(s) + 1); if (!data) { SYSERROR("failed to allocate memory"); free(s); return -1; } *data = 0; for (p = strtok_r(s, ",", &saveptr); p != NULL; p = strtok_r(NULL, ",", &saveptr)) parse_mntopt(p, mntflags, &data); if (*data) *mntdata = data; else free(data); free(s); return 0; } static void null_endofword(char *word) { while (*word && *word != ' ' && *word != '\t') word++; *word = '\0'; } /* * skip @nfields spaces in @src */ static char *get_field(char *src, int nfields) { char *p = src; int i; for (i = 0; i < nfields; i++) { while (*p && *p != ' ' && *p != '\t') p++; if (!*p) break; p++; } return p; } static int mount_entry(const char *fsname, const char *target, const char *fstype, unsigned long mountflags, const char *data, int optional, int dev, const char *rootfs) { #ifdef HAVE_STATVFS struct statvfs sb; #endif if (safe_mount(fsname, target, fstype, mountflags & ~MS_REMOUNT, data, rootfs)) { if (optional) { INFO("failed to mount '%s' on '%s' (optional): %s", fsname, target, strerror(errno)); return 0; } else { SYSERROR("failed to mount '%s' on '%s'", fsname, target); return -1; } } if ((mountflags & MS_REMOUNT) || (mountflags & MS_BIND)) { DEBUG("remounting %s on %s to respect bind or remount options", fsname ? fsname : "(none)", target ? target : "(none)"); unsigned long rqd_flags = 0; if (mountflags & MS_RDONLY) rqd_flags |= MS_RDONLY; #ifdef HAVE_STATVFS if (statvfs(fsname, &sb) == 0) { unsigned long required_flags = rqd_flags; if (sb.f_flag & MS_NOSUID) required_flags |= MS_NOSUID; if (sb.f_flag & MS_NODEV && !dev) required_flags |= MS_NODEV; if (sb.f_flag & MS_RDONLY) required_flags |= MS_RDONLY; if (sb.f_flag & MS_NOEXEC) required_flags |= MS_NOEXEC; DEBUG("(at remount) flags for %s was %lu, required extra flags are %lu", fsname, sb.f_flag, required_flags); /* * If this was a bind mount request, and required_flags * does not have any flags which are not already in * mountflags, then skip the remount */ if (!(mountflags & MS_REMOUNT)) { if (!(required_flags & ~mountflags) && rqd_flags == 0) { DEBUG("mountflags already was %lu, skipping remount", mountflags); goto skipremount; } } mountflags |= required_flags; } #endif if (mount(fsname, target, fstype, mountflags | MS_REMOUNT, data) < 0) { if (optional) { INFO("failed to mount '%s' on '%s' (optional): %s", fsname, target, strerror(errno)); return 0; } else { SYSERROR("failed to mount '%s' on '%s'", fsname, target); return -1; } } } #ifdef HAVE_STATVFS skipremount: #endif DEBUG("mounted '%s' on '%s', type '%s'", fsname, target, fstype); return 0; } /* * Remove 'optional', 'create=dir', and 'create=file' from mntopt */ static void cull_mntent_opt(struct mntent *mntent) { int i; char *p, *p2; char *list[] = {"create=dir", "create=file", "optional", NULL }; for (i=0; list[i]; i++) { if (!(p = strstr(mntent->mnt_opts, list[i]))) continue; p2 = strchr(p, ','); if (!p2) { /* no more mntopts, so just chop it here */ *p = '\0'; continue; } memmove(p, p2+1, strlen(p2+1)+1); } } static int mount_entry_create_dir_file(const struct mntent *mntent, const char* path, const struct lxc_rootfs *rootfs, const char *lxc_name, const char *lxc_path) { char *pathdirname = NULL; int ret = 0; FILE *pathfile = NULL; if (strncmp(mntent->mnt_type, "overlay", 7) == 0) { if (ovl_mkdir(mntent, rootfs, lxc_name, lxc_path) < 0) return -1; } else if (strncmp(mntent->mnt_type, "aufs", 4) == 0) { if (aufs_mkdir(mntent, rootfs, lxc_name, lxc_path) < 0) return -1; } if (hasmntopt(mntent, "create=dir")) { if (mkdir_p(path, 0755) < 0) { WARN("Failed to create mount target '%s'", path); ret = -1; } } if (hasmntopt(mntent, "create=file") && access(path, F_OK)) { pathdirname = strdup(path); pathdirname = dirname(pathdirname); if (mkdir_p(pathdirname, 0755) < 0) { WARN("Failed to create target directory"); } pathfile = fopen(path, "wb"); if (!pathfile) { WARN("Failed to create mount target '%s'", path); ret = -1; } else { fclose(pathfile); } } free(pathdirname); return ret; } /* rootfs, lxc_name, and lxc_path can be NULL when the container is created * without a rootfs. */ static inline int mount_entry_on_generic(struct mntent *mntent, const char* path, const struct lxc_rootfs *rootfs, const char *lxc_name, const char *lxc_path) { unsigned long mntflags; char *mntdata; int ret; bool optional = hasmntopt(mntent, "optional") != NULL; bool dev = hasmntopt(mntent, "dev") != NULL; char *rootfs_path = NULL; if (rootfs && rootfs->path) rootfs_path = rootfs->mount; ret = mount_entry_create_dir_file(mntent, path, rootfs, lxc_name, lxc_path); if (ret < 0) return optional ? 0 : -1; cull_mntent_opt(mntent); if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) { free(mntdata); return -1; } ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type, mntflags, mntdata, optional, dev, rootfs_path); free(mntdata); return ret; } static inline int mount_entry_on_systemfs(struct mntent *mntent) { char path[MAXPATHLEN]; int ret; /* For containers created without a rootfs all mounts are treated as * absolute paths starting at / on the host. */ if (mntent->mnt_dir[0] != '/') ret = snprintf(path, sizeof(path), "/%s", mntent->mnt_dir); else ret = snprintf(path, sizeof(path), "%s", mntent->mnt_dir); if (ret < 0 || ret >= sizeof(path)) { ERROR("path name too long"); return -1; } return mount_entry_on_generic(mntent, path, NULL, NULL, NULL); } static int mount_entry_on_absolute_rootfs(struct mntent *mntent, const struct lxc_rootfs *rootfs, const char *lxc_name, const char *lxc_path) { char *aux; char path[MAXPATHLEN]; int r, ret = 0, offset; const char *lxcpath; lxcpath = lxc_global_config_value("lxc.lxcpath"); if (!lxcpath) { ERROR("Out of memory"); return -1; } /* if rootfs->path is a blockdev path, allow container fstab to * use $lxcpath/CN/rootfs as the target prefix */ r = snprintf(path, MAXPATHLEN, "%s/%s/rootfs", lxcpath, lxc_name); if (r < 0 || r >= MAXPATHLEN) goto skipvarlib; aux = strstr(mntent->mnt_dir, path); if (aux) { offset = strlen(path); goto skipabs; } skipvarlib: aux = strstr(mntent->mnt_dir, rootfs->path); if (!aux) { WARN("ignoring mount point '%s'", mntent->mnt_dir); return ret; } offset = strlen(rootfs->path); skipabs: r = snprintf(path, MAXPATHLEN, "%s/%s", rootfs->mount, aux + offset); if (r < 0 || r >= MAXPATHLEN) { WARN("pathnme too long for '%s'", mntent->mnt_dir); return -1; } return mount_entry_on_generic(mntent, path, rootfs, lxc_name, lxc_path); } static int mount_entry_on_relative_rootfs(struct mntent *mntent, const struct lxc_rootfs *rootfs, const char *lxc_name, const char *lxc_path) { char path[MAXPATHLEN]; int ret; /* relative to root mount point */ ret = snprintf(path, sizeof(path), "%s/%s", rootfs->mount, mntent->mnt_dir); if (ret < 0 || ret >= sizeof(path)) { ERROR("path name too long"); return -1; } return mount_entry_on_generic(mntent, path, rootfs, lxc_name, lxc_path); } static int mount_file_entries(const struct lxc_rootfs *rootfs, FILE *file, const char *lxc_name, const char *lxc_path) { struct mntent mntent; char buf[4096]; int ret = -1; while (getmntent_r(file, &mntent, buf, sizeof(buf))) { if (!rootfs->path) { if (mount_entry_on_systemfs(&mntent)) goto out; continue; } /* We have a separate root, mounts are relative to it */ if (mntent.mnt_dir[0] != '/') { if (mount_entry_on_relative_rootfs(&mntent, rootfs, lxc_name, lxc_path)) goto out; continue; } if (mount_entry_on_absolute_rootfs(&mntent, rootfs, lxc_name, lxc_path)) goto out; } ret = 0; INFO("mount points have been setup"); out: return ret; } static int setup_mount(const struct lxc_rootfs *rootfs, const char *fstab, const char *lxc_name, const char *lxc_path) { FILE *file; int ret; if (!fstab) return 0; file = setmntent(fstab, "r"); if (!file) { SYSERROR("failed to use '%s'", fstab); return -1; } ret = mount_file_entries(rootfs, file, lxc_name, lxc_path); endmntent(file); return ret; } FILE *make_anonymous_mount_file(struct lxc_list *mount) { int ret; char *mount_entry; struct lxc_list *iterator; FILE *file; int fd = -1; fd = memfd_create("lxc_mount_file", MFD_CLOEXEC); if (fd < 0) { if (errno != ENOSYS) return NULL; file = tmpfile(); } else { file = fdopen(fd, "r+"); } if (!file) { int saved_errno = errno; if (fd != -1) close(fd); ERROR("Could not create mount entry file: %s.", strerror(saved_errno)); return NULL; } lxc_list_for_each(iterator, mount) { mount_entry = iterator->elem; ret = fprintf(file, "%s\n", mount_entry); if (ret < strlen(mount_entry)) WARN("Could not write mount entry to anonymous mount file."); } if (fseek(file, 0, SEEK_SET) < 0) { fclose(file); return NULL; } return file; } static int setup_mount_entries(const struct lxc_rootfs *rootfs, struct lxc_list *mount, const char *lxc_name, const char *lxc_path) { FILE *file; int ret; file = make_anonymous_mount_file(mount); if (!file) return -1; ret = mount_file_entries(rootfs, file, lxc_name, lxc_path); fclose(file); return ret; } static int parse_cap(const char *cap) { char *ptr = NULL; size_t i; int capid = -1; if (!strcmp(cap, "none")) return -2; for (i = 0; i < sizeof(caps_opt)/sizeof(caps_opt[0]); i++) { if (strcmp(cap, caps_opt[i].name)) continue; capid = caps_opt[i].value; break; } if (capid < 0) { /* try to see if it's numeric, so the user may specify * capabilities that the running kernel knows about but * we don't */ errno = 0; capid = strtol(cap, &ptr, 10); if (!ptr || *ptr != '\0' || errno != 0) /* not a valid number */ capid = -1; else if (capid > lxc_caps_last_cap()) /* we have a number but it's not a valid * capability */ capid = -1; } return capid; } int in_caplist(int cap, struct lxc_list *caps) { struct lxc_list *iterator; int capid; lxc_list_for_each(iterator, caps) { capid = parse_cap(iterator->elem); if (capid == cap) return 1; } return 0; } static int setup_caps(struct lxc_list *caps) { struct lxc_list *iterator; char *drop_entry; int capid; lxc_list_for_each(iterator, caps) { drop_entry = iterator->elem; capid = parse_cap(drop_entry); if (capid < 0) { ERROR("unknown capability %s", drop_entry); return -1; } DEBUG("drop capability '%s' (%d)", drop_entry, capid); if (prctl(PR_CAPBSET_DROP, capid, 0, 0, 0)) { SYSERROR("failed to remove %s capability", drop_entry); return -1; } } DEBUG("capabilities have been setup"); return 0; } static int dropcaps_except(struct lxc_list *caps) { struct lxc_list *iterator; char *keep_entry; int i, capid; int numcaps = lxc_caps_last_cap() + 1; INFO("found %d capabilities", numcaps); if (numcaps <= 0 || numcaps > 200) return -1; // caplist[i] is 1 if we keep capability i int *caplist = alloca(numcaps * sizeof(int)); memset(caplist, 0, numcaps * sizeof(int)); lxc_list_for_each(iterator, caps) { keep_entry = iterator->elem; capid = parse_cap(keep_entry); if (capid == -2) continue; if (capid < 0) { ERROR("unknown capability %s", keep_entry); return -1; } DEBUG("keep capability '%s' (%d)", keep_entry, capid); caplist[capid] = 1; } for (i=0; ielem; err = lxc_ipv4_addr_add(ifindex, &inetdev->addr, &inetdev->bcast, inetdev->prefix); if (err) { ERROR("failed to setup_ipv4_addr ifindex %d : %s", ifindex, strerror(-err)); return -1; } } return 0; } static int setup_ipv6_addr(struct lxc_list *ip, int ifindex) { struct lxc_list *iterator; struct lxc_inet6dev *inet6dev; int err; lxc_list_for_each(iterator, ip) { inet6dev = iterator->elem; err = lxc_ipv6_addr_add(ifindex, &inet6dev->addr, &inet6dev->mcast, &inet6dev->acast, inet6dev->prefix); if (err) { ERROR("failed to setup_ipv6_addr ifindex %d : %s", ifindex, strerror(-err)); return -1; } } return 0; } static int setup_netdev(struct lxc_netdev *netdev) { char ifname[IFNAMSIZ]; char *current_ifname = ifname; int err; /* empty network namespace */ if (!netdev->ifindex) { if (netdev->flags & IFF_UP) { err = lxc_netdev_up("lo"); if (err) { ERROR("failed to set the loopback up : %s", strerror(-err)); return -1; } } if (netdev->type != LXC_NET_VETH) return 0; netdev->ifindex = if_nametoindex(netdev->name); } /* get the new ifindex in case of physical netdev */ if (netdev->type == LXC_NET_PHYS) { if (!(netdev->ifindex = if_nametoindex(netdev->link))) { ERROR("failed to get ifindex for %s", netdev->link); return -1; } } /* retrieve the name of the interface */ if (!if_indextoname(netdev->ifindex, current_ifname)) { ERROR("no interface corresponding to index '%d'", netdev->ifindex); return -1; } /* default: let the system to choose one interface name */ if (!netdev->name) netdev->name = netdev->type == LXC_NET_PHYS ? netdev->link : "eth%d"; /* rename the interface name */ if (strcmp(ifname, netdev->name) != 0) { err = lxc_netdev_rename_by_name(ifname, netdev->name); if (err) { ERROR("failed to rename %s->%s : %s", ifname, netdev->name, strerror(-err)); return -1; } } /* Re-read the name of the interface because its name has changed * and would be automatically allocated by the system */ if (!if_indextoname(netdev->ifindex, current_ifname)) { ERROR("no interface corresponding to index '%d'", netdev->ifindex); return -1; } /* set a mac address */ if (netdev->hwaddr) { if (setup_hw_addr(netdev->hwaddr, current_ifname)) { ERROR("failed to setup hw address for '%s'", current_ifname); return -1; } } /* setup ipv4 addresses on the interface */ if (setup_ipv4_addr(&netdev->ipv4, netdev->ifindex)) { ERROR("failed to setup ip addresses for '%s'", ifname); return -1; } /* setup ipv6 addresses on the interface */ if (setup_ipv6_addr(&netdev->ipv6, netdev->ifindex)) { ERROR("failed to setup ipv6 addresses for '%s'", ifname); return -1; } /* set the network device up */ if (netdev->flags & IFF_UP) { int err; err = lxc_netdev_up(current_ifname); if (err) { ERROR("failed to set '%s' up : %s", current_ifname, strerror(-err)); return -1; } /* the network is up, make the loopback up too */ err = lxc_netdev_up("lo"); if (err) { ERROR("failed to set the loopback up : %s", strerror(-err)); return -1; } } /* We can only set up the default routes after bringing * up the interface, sine bringing up the interface adds * the link-local routes and we can't add a default * route if the gateway is not reachable. */ /* setup ipv4 gateway on the interface */ if (netdev->ipv4_gateway) { if (!(netdev->flags & IFF_UP)) { ERROR("Cannot add ipv4 gateway for %s when not bringing up the interface", ifname); return -1; } if (lxc_list_empty(&netdev->ipv4)) { ERROR("Cannot add ipv4 gateway for %s when not assigning an address", ifname); return -1; } err = lxc_ipv4_gateway_add(netdev->ifindex, netdev->ipv4_gateway); if (err) { err = lxc_ipv4_dest_add(netdev->ifindex, netdev->ipv4_gateway); if (err) { ERROR("failed to add ipv4 dest for '%s': %s", ifname, strerror(-err)); } err = lxc_ipv4_gateway_add(netdev->ifindex, netdev->ipv4_gateway); if (err) { ERROR("failed to setup ipv4 gateway for '%s': %s", ifname, strerror(-err)); if (netdev->ipv4_gateway_auto) { char buf[INET_ADDRSTRLEN]; inet_ntop(AF_INET, netdev->ipv4_gateway, buf, sizeof(buf)); ERROR("tried to set autodetected ipv4 gateway '%s'", buf); } return -1; } } } /* setup ipv6 gateway on the interface */ if (netdev->ipv6_gateway) { if (!(netdev->flags & IFF_UP)) { ERROR("Cannot add ipv6 gateway for %s when not bringing up the interface", ifname); return -1; } if (lxc_list_empty(&netdev->ipv6) && !IN6_IS_ADDR_LINKLOCAL(netdev->ipv6_gateway)) { ERROR("Cannot add ipv6 gateway for %s when not assigning an address", ifname); return -1; } err = lxc_ipv6_gateway_add(netdev->ifindex, netdev->ipv6_gateway); if (err) { err = lxc_ipv6_dest_add(netdev->ifindex, netdev->ipv6_gateway); if (err) { ERROR("failed to add ipv6 dest for '%s': %s", ifname, strerror(-err)); } err = lxc_ipv6_gateway_add(netdev->ifindex, netdev->ipv6_gateway); if (err) { ERROR("failed to setup ipv6 gateway for '%s': %s", ifname, strerror(-err)); if (netdev->ipv6_gateway_auto) { char buf[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, netdev->ipv6_gateway, buf, sizeof(buf)); ERROR("tried to set autodetected ipv6 gateway '%s'", buf); } return -1; } } } DEBUG("'%s' has been setup", current_ifname); return 0; } static int setup_network(struct lxc_list *network) { struct lxc_list *iterator; struct lxc_netdev *netdev; lxc_list_for_each(iterator, network) { netdev = iterator->elem; if (setup_netdev(netdev)) { ERROR("failed to setup netdev"); return -1; } } if (!lxc_list_empty(network)) INFO("network has been setup"); return 0; } /* try to move physical nics to the init netns */ void lxc_restore_phys_nics_to_netns(int netnsfd, struct lxc_conf *conf) { int i, oldfd; char ifname[IFNAMSIZ]; if (netnsfd < 0 || conf->num_savednics == 0) return; INFO("Running to reset %d nic names.", conf->num_savednics); oldfd = lxc_preserve_ns(getpid(), "net"); if (oldfd < 0) { SYSERROR("Failed to open monitor netns fd."); return; } if (setns(netnsfd, 0) != 0) { SYSERROR("Failed to enter container netns to reset nics"); close(oldfd); return; } for (i=0; inum_savednics; i++) { struct saved_nic *s = &conf->saved_nics[i]; /* retrieve the name of the interface */ if (!if_indextoname(s->ifindex, ifname)) { WARN("no interface corresponding to index '%d'", s->ifindex); continue; } if (lxc_netdev_move_by_name(ifname, 1, s->orig_name)) WARN("Error moving nic name:%s back to host netns", ifname); free(s->orig_name); } conf->num_savednics = 0; if (setns(oldfd, 0) != 0) SYSERROR("Failed to re-enter monitor's netns"); close(oldfd); } static char *default_rootfs_mount = LXCROOTFSMOUNT; struct lxc_conf *lxc_conf_init(void) { struct lxc_conf *new; int i; new = malloc(sizeof(*new)); if (!new) { ERROR("lxc_conf_init : %m"); return NULL; } memset(new, 0, sizeof(*new)); new->loglevel = LXC_LOG_PRIORITY_NOTSET; new->personality = -1; new->autodev = 1; new->console.log_path = NULL; new->console.log_fd = -1; new->console.path = NULL; new->console.peer = -1; new->console.peerpty.busy = -1; new->console.peerpty.master = -1; new->console.peerpty.slave = -1; new->console.master = -1; new->console.slave = -1; new->console.name[0] = '\0'; new->maincmd_fd = -1; new->nbd_idx = -1; new->rootfs.mount = strdup(default_rootfs_mount); if (!new->rootfs.mount) { ERROR("lxc_conf_init : %m"); free(new); return NULL; } new->kmsg = 0; new->logfd = -1; lxc_list_init(&new->cgroup); lxc_list_init(&new->network); lxc_list_init(&new->mount_list); lxc_list_init(&new->caps); lxc_list_init(&new->keepcaps); lxc_list_init(&new->id_map); lxc_list_init(&new->includes); lxc_list_init(&new->aliens); lxc_list_init(&new->environment); for (i=0; ihooks[i]); lxc_list_init(&new->groups); new->lsm_aa_profile = NULL; new->lsm_se_context = NULL; new->tmp_umount_proc = 0; for (i = 0; i < LXC_NS_MAX; i++) new->inherit_ns_fd[i] = -1; /* if running in a new user namespace, init and COMMAND * default to running as UID/GID 0 when using lxc-execute */ new->init_uid = 0; new->init_gid = 0; return new; } static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netdev) { char veth1buf[IFNAMSIZ], *veth1; char veth2buf[IFNAMSIZ], *veth2; int bridge_index, err; unsigned int mtu = 0; if (netdev->priv.veth_attr.pair) { veth1 = netdev->priv.veth_attr.pair; if (handler->conf->reboot) lxc_netdev_delete_by_name(veth1); } else { err = snprintf(veth1buf, sizeof(veth1buf), "vethXXXXXX"); if (err >= sizeof(veth1buf)) { /* can't *really* happen, but... */ ERROR("veth1 name too long"); return -1; } veth1 = lxc_mkifname(veth1buf); if (!veth1) { ERROR("failed to allocate a temporary name"); return -1; } /* store away for deconf */ memcpy(netdev->priv.veth_attr.veth1, veth1, IFNAMSIZ); } snprintf(veth2buf, sizeof(veth2buf), "vethXXXXXX"); veth2 = lxc_mkifname(veth2buf); if (!veth2) { ERROR("failed to allocate a temporary name"); goto out_delete; } err = lxc_veth_create(veth1, veth2); if (err) { ERROR("failed to create veth pair (%s and %s): %s", veth1, veth2, strerror(-err)); goto out_delete; } /* changing the high byte of the mac address to 0xfe, the bridge interface * will always keep the host's mac address and not take the mac address * of a container */ err = setup_private_host_hw_addr(veth1); if (err) { ERROR("failed to change mac address of host interface '%s': %s", veth1, strerror(-err)); goto out_delete; } netdev->ifindex = if_nametoindex(veth2); if (!netdev->ifindex) { ERROR("failed to retrieve the index for %s", veth2); goto out_delete; } if (netdev->mtu) { if (lxc_safe_uint(netdev->mtu, &mtu) < 0) WARN("Failed to parse mtu from."); else INFO("Retrieved mtu %d", mtu); } else if (netdev->link) { bridge_index = if_nametoindex(netdev->link); if (bridge_index) { mtu = netdev_get_mtu(bridge_index); INFO("Retrieved mtu %d from %s", mtu, netdev->link); } else { mtu = netdev_get_mtu(netdev->ifindex); INFO("Retrieved mtu %d from %s", mtu, veth2); } } if (mtu) { err = lxc_netdev_set_mtu(veth1, mtu); if (!err) err = lxc_netdev_set_mtu(veth2, mtu); if (err) { ERROR("failed to set mtu '%i' for veth pair (%s and %s): %s", mtu, veth1, veth2, strerror(-err)); goto out_delete; } } if (netdev->link) { err = lxc_bridge_attach(handler->lxcpath, handler->name, netdev->link, veth1); if (err) { ERROR("failed to attach '%s' to the bridge '%s': %s", veth1, netdev->link, strerror(-err)); goto out_delete; } INFO("Attached '%s': to the bridge '%s': ", veth1, netdev->link); } err = lxc_netdev_up(veth1); if (err) { ERROR("failed to set %s up : %s", veth1, strerror(-err)); goto out_delete; } if (netdev->upscript) { err = run_script(handler->name, "net", netdev->upscript, "up", "veth", veth1, (char*) NULL); if (err) goto out_delete; } DEBUG("instantiated veth '%s/%s', index is '%d'", veth1, veth2, netdev->ifindex); return 0; out_delete: lxc_netdev_delete_by_name(veth1); if (!netdev->priv.veth_attr.pair) free(veth1); free(veth2); return -1; } static int shutdown_veth(struct lxc_handler *handler, struct lxc_netdev *netdev) { char *veth1; int err; if (netdev->priv.veth_attr.pair) veth1 = netdev->priv.veth_attr.pair; else veth1 = netdev->priv.veth_attr.veth1; if (netdev->downscript) { err = run_script(handler->name, "net", netdev->downscript, "down", "veth", veth1, (char*) NULL); if (err) return -1; } return 0; } static int instantiate_macvlan(struct lxc_handler *handler, struct lxc_netdev *netdev) { char peerbuf[IFNAMSIZ], *peer; int err; if (!netdev->link) { ERROR("no link specified for macvlan netdev"); return -1; } err = snprintf(peerbuf, sizeof(peerbuf), "mcXXXXXX"); if (err >= sizeof(peerbuf)) return -1; peer = lxc_mkifname(peerbuf); if (!peer) { ERROR("failed to make a temporary name"); return -1; } err = lxc_macvlan_create(netdev->link, peer, netdev->priv.macvlan_attr.mode); if (err) { ERROR("failed to create macvlan interface '%s' on '%s' : %s", peer, netdev->link, strerror(-err)); goto out; } netdev->ifindex = if_nametoindex(peer); if (!netdev->ifindex) { ERROR("failed to retrieve the index for %s", peer); goto out; } if (netdev->upscript) { err = run_script(handler->name, "net", netdev->upscript, "up", "macvlan", netdev->link, (char*) NULL); if (err) goto out; } DEBUG("instantiated macvlan '%s', index is '%d' and mode '%d'", peer, netdev->ifindex, netdev->priv.macvlan_attr.mode); return 0; out: lxc_netdev_delete_by_name(peer); free(peer); return -1; } static int shutdown_macvlan(struct lxc_handler *handler, struct lxc_netdev *netdev) { int err; if (netdev->downscript) { err = run_script(handler->name, "net", netdev->downscript, "down", "macvlan", netdev->link, (char*) NULL); if (err) return -1; } return 0; } /* XXX: merge with instantiate_macvlan */ static int instantiate_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev) { char peer[IFNAMSIZ]; int err; static uint16_t vlan_cntr = 0; unsigned int mtu = 0; if (!netdev->link) { ERROR("no link specified for vlan netdev"); return -1; } err = snprintf(peer, sizeof(peer), "vlan%d-%d", netdev->priv.vlan_attr.vid, vlan_cntr++); if (err >= sizeof(peer)) { ERROR("peer name too long"); return -1; } err = lxc_vlan_create(netdev->link, peer, netdev->priv.vlan_attr.vid); if (err) { ERROR("failed to create vlan interface '%s' on '%s' : %s", peer, netdev->link, strerror(-err)); return -1; } netdev->ifindex = if_nametoindex(peer); if (!netdev->ifindex) { ERROR("failed to retrieve the ifindex for %s", peer); lxc_netdev_delete_by_name(peer); return -1; } DEBUG("instantiated vlan '%s', ifindex is '%d'", " vlan1000", netdev->ifindex); if (netdev->mtu) { if (lxc_safe_uint(netdev->mtu, &mtu) < 0) { ERROR("Failed to retrieve mtu from: '%d'/'%s'.", netdev->ifindex, netdev->name); return -1; } err = lxc_netdev_set_mtu(peer, mtu); if (err) { ERROR("failed to set mtu '%s' for %s : %s", netdev->mtu, peer, strerror(-err)); lxc_netdev_delete_by_name(peer); return -1; } } return 0; } static int shutdown_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev) { return 0; } static int instantiate_phys(struct lxc_handler *handler, struct lxc_netdev *netdev) { if (!netdev->link) { ERROR("no link specified for the physical interface"); return -1; } netdev->ifindex = if_nametoindex(netdev->link); if (!netdev->ifindex) { ERROR("failed to retrieve the index for %s", netdev->link); return -1; } if (netdev->upscript) { int err; err = run_script(handler->name, "net", netdev->upscript, "up", "phys", netdev->link, (char*) NULL); if (err) return -1; } return 0; } static int shutdown_phys(struct lxc_handler *handler, struct lxc_netdev *netdev) { int err; if (netdev->downscript) { err = run_script(handler->name, "net", netdev->downscript, "down", "phys", netdev->link, (char*) NULL); if (err) return -1; } return 0; } static int instantiate_none(struct lxc_handler *handler, struct lxc_netdev *netdev) { netdev->ifindex = 0; return 0; } static int instantiate_empty(struct lxc_handler *handler, struct lxc_netdev *netdev) { netdev->ifindex = 0; if (netdev->upscript) { int err; err = run_script(handler->name, "net", netdev->upscript, "up", "empty", (char*) NULL); if (err) return -1; } return 0; } static int shutdown_empty(struct lxc_handler *handler, struct lxc_netdev *netdev) { int err; if (netdev->downscript) { err = run_script(handler->name, "net", netdev->downscript, "down", "empty", (char*) NULL); if (err) return -1; } return 0; } static int shutdown_none(struct lxc_handler *handler, struct lxc_netdev *netdev) { return 0; } int lxc_requests_empty_network(struct lxc_handler *handler) { struct lxc_list *network = &handler->conf->network; struct lxc_list *iterator; struct lxc_netdev *netdev; bool found_none = false, found_nic = false; if (lxc_list_empty(network)) return 0; lxc_list_for_each(iterator, network) { netdev = iterator->elem; if (netdev->type == LXC_NET_NONE) found_none = true; else found_nic = true; } if (found_none && !found_nic) return 1; return 0; } int lxc_create_network(struct lxc_handler *handler) { struct lxc_list *network = &handler->conf->network; struct lxc_list *iterator; struct lxc_netdev *netdev; int am_root = (getuid() == 0); if (!am_root) return 0; lxc_list_for_each(iterator, network) { netdev = iterator->elem; if (netdev->type < 0 || netdev->type > LXC_NET_MAXCONFTYPE) { ERROR("invalid network configuration type '%d'", netdev->type); return -1; } if (netdev_conf[netdev->type](handler, netdev)) { ERROR("failed to create netdev"); return -1; } } return 0; } bool lxc_delete_network(struct lxc_handler *handler) { int ret; struct lxc_list *network = &handler->conf->network; struct lxc_list *iterator; struct lxc_netdev *netdev; bool deleted_all = true; lxc_list_for_each(iterator, network) { netdev = iterator->elem; if (netdev->ifindex != 0 && netdev->type == LXC_NET_PHYS) { if (lxc_netdev_rename_by_index(netdev->ifindex, netdev->link)) WARN("Failed to rename interface with index %d " "to its initial name \"%s\".", netdev->ifindex, netdev->link); continue; } if (netdev_deconf[netdev->type](handler, netdev)) { WARN("Failed to destroy netdev"); } /* Recent kernel remove the virtual interfaces when the network * namespace is destroyed but in case we did not moved the * interface to the network namespace, we have to destroy it */ if (netdev->ifindex != 0) { ret = lxc_netdev_delete_by_index(netdev->ifindex); if (-ret == ENODEV) { INFO("Interface \"%s\" with index %d already " "deleted or existing in different network " "namespace.", netdev->name ? netdev->name : "(null)", netdev->ifindex); } else if (ret < 0) { deleted_all = false; WARN("Failed to remove interface \"%s\" with " "index %d: %s.", netdev->name ? netdev->name : "(null)", netdev->ifindex, strerror(-ret)); } else { INFO("Removed interface \"%s\" with index %d.", netdev->name ? netdev->name : "(null)", netdev->ifindex); } } /* Explicitly delete host veth device to prevent lingering * devices. We had issues in LXD around this. */ if (netdev->type == LXC_NET_VETH && !am_unpriv()) { char *hostveth; if (netdev->priv.veth_attr.pair) { hostveth = netdev->priv.veth_attr.pair; ret = lxc_netdev_delete_by_name(hostveth); if (ret < 0) { WARN("Failed to remove interface \"%s\" from host: %s.", hostveth, strerror(-ret)); } else { INFO("Removed interface \"%s\" from host.", hostveth); } } else if (strlen(netdev->priv.veth_attr.veth1) > 0) { hostveth = netdev->priv.veth_attr.veth1; ret = lxc_netdev_delete_by_name(hostveth); if (ret < 0) { WARN("Failed to remove \"%s\" from host: %s.", hostveth, strerror(-ret)); } else { INFO("Removed interface \"%s\" from host.", hostveth); memset((void *)&netdev->priv.veth_attr.veth1, 0, sizeof(netdev->priv.veth_attr.veth1)); } } } } return deleted_all; } #define LXC_USERNIC_PATH LIBEXECDIR "/lxc/lxc-user-nic" /* lxc-user-nic returns "interface_name:interface_name\n" */ #define MAX_BUFFER_SIZE IFNAMSIZ * 2 + 2 static int unpriv_assign_nic(const char *lxcpath, char *lxcname, struct lxc_netdev *netdev, pid_t pid) { pid_t child; int bytes, pipefd[2]; char *token, *saveptr = NULL; char buffer[MAX_BUFFER_SIZE]; char netdev_link[IFNAMSIZ + 1]; if (netdev->type != LXC_NET_VETH) { ERROR("nic type %d not support for unprivileged use", netdev->type); return -1; } if (pipe(pipefd) < 0) { SYSERROR("pipe failed"); return -1; } child = fork(); if (child < 0) { SYSERROR("fork"); close(pipefd[0]); close(pipefd[1]); return -1; } if (child == 0) { // child /* Call lxc-user-nic pid type bridge. */ int ret; char pidstr[LXC_NUMSTRLEN64]; close(pipefd[0]); /* Close the read-end of the pipe. */ /* Redirect stdout to write-end of the pipe. */ ret = dup2(pipefd[1], STDOUT_FILENO); close(pipefd[1]); /* Close the write-end of the pipe. */ if (ret < 0) { SYSERROR("Failed to dup2() to redirect stdout to pipe file descriptor."); exit(EXIT_FAILURE); } if (netdev->link) strncpy(netdev_link, netdev->link, IFNAMSIZ); else strncpy(netdev_link, "none", IFNAMSIZ); ret = snprintf(pidstr, LXC_NUMSTRLEN64, "%d", pid); if (ret < 0 || ret >= LXC_NUMSTRLEN64) exit(EXIT_FAILURE); pidstr[LXC_NUMSTRLEN64 - 1] = '\0'; INFO("Execing lxc-user-nic %s %s %s veth %s %s", lxcpath, lxcname, pidstr, netdev_link, netdev->name); execlp(LXC_USERNIC_PATH, LXC_USERNIC_PATH, lxcpath, lxcname, pidstr, "veth", netdev_link, netdev->name, NULL); SYSERROR("Failed to exec lxc-user-nic."); exit(EXIT_FAILURE); } /* close the write-end of the pipe */ close(pipefd[1]); bytes = read(pipefd[0], &buffer, MAX_BUFFER_SIZE); if (bytes < 0) SYSERROR("Failed to read from pipe file descriptor."); buffer[bytes - 1] = '\0'; if (wait_for_pid(child) != 0) { close(pipefd[0]); return -1; } /* close the read-end of the pipe */ close(pipefd[0]); /* fill netdev->name field */ token = strtok_r(buffer, ":", &saveptr); if (!token) return -1; netdev->name = malloc(IFNAMSIZ + 1); if (!netdev->name) { SYSERROR("Failed to allocate memory."); return -1; } memset(netdev->name, 0, IFNAMSIZ + 1); strncpy(netdev->name, token, IFNAMSIZ); /* fill netdev->veth_attr.pair field */ token = strtok_r(NULL, ":", &saveptr); if (!token) return -1; netdev->priv.veth_attr.pair = strdup(token); if (!netdev->priv.veth_attr.pair) { ERROR("Failed to allocate memory."); return -1; } return 0; } int lxc_assign_network(const char *lxcpath, char *lxcname, struct lxc_list *network, pid_t pid) { struct lxc_list *iterator; struct lxc_netdev *netdev; char ifname[IFNAMSIZ]; int am_root = (getuid() == 0); int err; lxc_list_for_each(iterator, network) { netdev = iterator->elem; if (netdev->type == LXC_NET_VETH && !am_root) { if (unpriv_assign_nic(lxcpath, lxcname, netdev, pid)) return -1; // lxc-user-nic has moved the nic to the new ns. // unpriv_assign_nic() fills in netdev->name. // netdev->ifindex will be filed in at setup_netdev. continue; } /* empty network namespace, nothing to move */ if (!netdev->ifindex) continue; /* retrieve the name of the interface */ if (!if_indextoname(netdev->ifindex, ifname)) { ERROR("no interface corresponding to index '%d'", netdev->ifindex); return -1; } err = lxc_netdev_move_by_name(ifname, pid, NULL); if (err) { ERROR("failed to move '%s' to the container : %s", netdev->link, strerror(-err)); return -1; } DEBUG("move '%s'/'%s' to '%d': .", ifname, netdev->name, pid); } return 0; } static int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf, size_t buf_size) { char path[PATH_MAX]; int ret, closeret; FILE *f; ret = snprintf(path, PATH_MAX, "/proc/%d/%cid_map", pid, idtype == ID_TYPE_UID ? 'u' : 'g'); if (ret < 0 || ret >= PATH_MAX) { fprintf(stderr, "%s: path name too long\n", __func__); return -E2BIG; } f = fopen(path, "w"); if (!f) { perror("open"); return -EINVAL; } ret = fwrite(buf, buf_size, 1, f); if (ret < 0) SYSERROR("writing id mapping"); closeret = fclose(f); if (closeret) SYSERROR("writing id mapping"); return ret < 0 ? ret : closeret; } /* Check whether a binary exist and has either CAP_SETUID, CAP_SETGID or both. */ static int idmaptool_on_path_and_privileged(const char *binary, cap_value_t cap) { char *path; int ret; struct stat st; int fret = 0; path = on_path(binary, NULL); if (!path) return -ENOENT; ret = stat(path, &st); if (ret < 0) { fret = -errno; goto cleanup; } /* Check if the binary is setuid. */ if (st.st_mode & S_ISUID) { DEBUG("The binary \"%s\" does have the setuid bit set.", path); fret = 1; goto cleanup; } #if HAVE_LIBCAP && LIBCAP_SUPPORTS_FILE_CAPABILITIES /* Check if it has the CAP_SETUID capability. */ if ((cap & CAP_SETUID) && lxc_file_cap_is_set(path, CAP_SETUID, CAP_EFFECTIVE) && lxc_file_cap_is_set(path, CAP_SETUID, CAP_PERMITTED)) { DEBUG("The binary \"%s\" has CAP_SETUID in its CAP_EFFECTIVE " "and CAP_PERMITTED sets.", path); fret = 1; goto cleanup; } /* Check if it has the CAP_SETGID capability. */ if ((cap & CAP_SETGID) && lxc_file_cap_is_set(path, CAP_SETGID, CAP_EFFECTIVE) && lxc_file_cap_is_set(path, CAP_SETGID, CAP_PERMITTED)) { DEBUG("The binary \"%s\" has CAP_SETGID in its CAP_EFFECTIVE " "and CAP_PERMITTED sets.", path); fret = 1; goto cleanup; } #else /* If we cannot check for file capabilities we need to give the benefit * of the doubt. Otherwise we might fail even though all the necessary * file capabilities are set. */ DEBUG("Cannot check for file capabilites as full capability support is " "missing. Manual intervention needed."); fret = 1; #endif cleanup: free(path); return fret; } int lxc_map_ids(struct lxc_list *idmap, pid_t pid) { struct id_map *map; struct lxc_list *iterator; enum idtype type; char *pos; int euid; int ret = 0, use_shadow = 0; int uidmap = 0, gidmap = 0; char *buf = NULL; euid = geteuid(); /* If new{g,u}idmap exists, that is, if shadow is handing out subuid * ranges, then insist that root also reserve ranges in subuid. This * will protected it by preventing another user from being handed the * range by shadow. */ uidmap = idmaptool_on_path_and_privileged("newuidmap", CAP_SETUID); gidmap = idmaptool_on_path_and_privileged("newgidmap", CAP_SETGID); if (uidmap > 0 && gidmap > 0) { DEBUG("Functional newuidmap and newgidmap binary found."); use_shadow = true; } else if (uidmap == -ENOENT && gidmap == -ENOENT && !euid) { DEBUG("No newuidmap and newgidmap binary found. Trying to " "write directly with euid 0."); use_shadow = false; } else { DEBUG("Either one or both of the newuidmap and newgidmap " "binaries do not exist or are missing necessary " "privilege."); return -1; } for (type = ID_TYPE_UID; type <= ID_TYPE_GID; type++) { int left, fill; bool had_entry = false; if (!buf) { buf = pos = malloc(LXC_IDMAPLEN); if (!buf) return -ENOMEM; } pos = buf; if (use_shadow) pos += sprintf(buf, "new%cidmap %d", type == ID_TYPE_UID ? 'u' : 'g', pid); lxc_list_for_each(iterator, idmap) { /* The kernel only takes <= 4k for writes to * /proc//[ug]id_map */ map = iterator->elem; if (map->idtype != type) continue; had_entry = true; left = LXC_IDMAPLEN - (pos - buf); fill = snprintf(pos, left, "%s%lu %lu %lu%s", use_shadow ? " " : "", map->nsid, map->hostid, map->range, use_shadow ? "" : "\n"); if (fill <= 0 || fill >= left) SYSERROR("Too many {g,u}id mappings defined."); pos += fill; } if (!had_entry) continue; if (!use_shadow) { ret = write_id_mapping(type, pid, buf, pos - buf); } else { left = LXC_IDMAPLEN - (pos - buf); fill = snprintf(pos, left, "\n"); if (fill <= 0 || fill >= left) SYSERROR("Too many {g,u}id mappings defined."); pos += fill; ret = system(buf); } if (ret) break; } free(buf); return ret; } /* * return the host uid/gid to which the container root is mapped in * *val. * Return true if id was found, false otherwise. */ bool get_mapped_rootid(struct lxc_conf *conf, enum idtype idtype, unsigned long *val) { struct lxc_list *it; struct id_map *map; lxc_list_for_each(it, &conf->id_map) { map = it->elem; if (map->idtype != idtype) continue; if (map->nsid != 0) continue; *val = map->hostid; return true; } return false; } int mapped_hostid(unsigned id, struct lxc_conf *conf, enum idtype idtype) { struct lxc_list *it; struct id_map *map; lxc_list_for_each(it, &conf->id_map) { map = it->elem; if (map->idtype != idtype) continue; if (id >= map->hostid && id < map->hostid + map->range) return (id - map->hostid) + map->nsid; } return -1; } int find_unmapped_nsuid(struct lxc_conf *conf, enum idtype idtype) { struct lxc_list *it; struct id_map *map; unsigned int freeid = 0; again: lxc_list_for_each(it, &conf->id_map) { map = it->elem; if (map->idtype != idtype) continue; if (freeid >= map->nsid && freeid < map->nsid + map->range) { freeid = map->nsid + map->range; goto again; } } return freeid; } int lxc_find_gateway_addresses(struct lxc_handler *handler) { struct lxc_list *network = &handler->conf->network; struct lxc_list *iterator; struct lxc_netdev *netdev; int link_index; lxc_list_for_each(iterator, network) { netdev = iterator->elem; if (!netdev->ipv4_gateway_auto && !netdev->ipv6_gateway_auto) continue; if (netdev->type != LXC_NET_VETH && netdev->type != LXC_NET_MACVLAN) { ERROR("gateway = auto only supported for " "veth and macvlan"); return -1; } if (!netdev->link) { ERROR("gateway = auto needs a link interface"); return -1; } link_index = if_nametoindex(netdev->link); if (!link_index) return -EINVAL; if (netdev->ipv4_gateway_auto) { if (lxc_ipv4_addr_get(link_index, &netdev->ipv4_gateway)) { ERROR("failed to automatically find ipv4 gateway " "address from link interface '%s'", netdev->link); return -1; } } if (netdev->ipv6_gateway_auto) { if (lxc_ipv6_addr_get(link_index, &netdev->ipv6_gateway)) { ERROR("failed to automatically find ipv6 gateway " "address from link interface '%s'", netdev->link); return -1; } } } return 0; } int lxc_create_tty(const char *name, struct lxc_conf *conf) { struct lxc_tty_info *tty_info = &conf->tty_info; int i, ret; /* no tty in the configuration */ if (!conf->tty) return 0; tty_info->pty_info = malloc(sizeof(*tty_info->pty_info)*conf->tty); if (!tty_info->pty_info) { SYSERROR("failed to allocate pty_info"); return -1; } for (i = 0; i < conf->tty; i++) { struct lxc_pty_info *pty_info = &tty_info->pty_info[i]; process_lock(); ret = openpty(&pty_info->master, &pty_info->slave, pty_info->name, NULL, NULL); process_unlock(); if (ret) { SYSERROR("failed to create pty #%d", i); tty_info->nbtty = i; lxc_delete_tty(tty_info); return -1; } DEBUG("allocated pty '%s' (%d/%d)", pty_info->name, pty_info->master, pty_info->slave); /* Prevent leaking the file descriptors to the container */ fcntl(pty_info->master, F_SETFD, FD_CLOEXEC); fcntl(pty_info->slave, F_SETFD, FD_CLOEXEC); pty_info->busy = 0; } tty_info->nbtty = conf->tty; INFO("tty's configured"); return 0; } void lxc_delete_tty(struct lxc_tty_info *tty_info) { int i; for (i = 0; i < tty_info->nbtty; i++) { struct lxc_pty_info *pty_info = &tty_info->pty_info[i]; close(pty_info->master); close(pty_info->slave); } free(tty_info->pty_info); tty_info->pty_info = NULL; tty_info->nbtty = 0; } /* * chown_mapped_root: for an unprivileged user with uid/gid X to * chown a dir to subuid/subgid Y, he needs to run chown as root * in a userns where nsid 0 is mapped to hostuid/hostgid Y, and * nsid Y is mapped to hostuid/hostgid X. That way, the container * root is privileged with respect to hostuid/hostgid X, allowing * him to do the chown. */ int chown_mapped_root(char *path, struct lxc_conf *conf) { uid_t rootuid; gid_t rootgid; pid_t pid; unsigned long val; char *chownpath = path; if (!get_mapped_rootid(conf, ID_TYPE_UID, &val)) { ERROR("No mapping for container root"); return -1; } rootuid = (uid_t) val; if (!get_mapped_rootid(conf, ID_TYPE_GID, &val)) { ERROR("No mapping for container root"); return -1; } rootgid = (gid_t) val; /* * In case of overlay, we want only the writeable layer * to be chowned */ if (strncmp(path, "overlayfs:", 10) == 0 || strncmp(path, "aufs:", 5) == 0) { chownpath = strchr(path, ':'); if (!chownpath) { ERROR("Bad overlay path: %s", path); return -1; } chownpath = strchr(chownpath+1, ':'); if (!chownpath) { ERROR("Bad overlay path: %s", path); return -1; } chownpath++; } path = chownpath; if (geteuid() == 0) { if (chown(path, rootuid, rootgid) < 0) { ERROR("Error chowning %s", path); return -1; } return 0; } if (rootuid == geteuid()) { // nothing to do INFO("%s: container root is our uid; no need to chown" ,__func__); return 0; } pid = fork(); if (pid < 0) { SYSERROR("Failed forking"); return -1; } if (!pid) { int hostuid = geteuid(), hostgid = getegid(), ret; struct stat sb; char map1[100], map2[100], map3[100], map4[100], map5[100]; char ugid[100]; char *args1[] = { "lxc-usernsexec", "-m", map1, "-m", map2, "-m", map3, "-m", map5, "--", "chown", ugid, path, NULL }; char *args2[] = { "lxc-usernsexec", "-m", map1, "-m", map2, "-m", map3, "-m", map4, "-m", map5, "--", "chown", ugid, path, NULL }; // save the current gid of "path" if (stat(path, &sb) < 0) { ERROR("Error stat %s", path); return -1; } /* * A file has to be group-owned by a gid mapped into the * container, or the container won't be privileged over it. */ if (sb.st_uid == geteuid() && mapped_hostid(sb.st_gid, conf, ID_TYPE_GID) < 0 && chown(path, -1, hostgid) < 0) { ERROR("Failed chgrping %s", path); return -1; } // "u:0:rootuid:1" ret = snprintf(map1, 100, "u:0:%d:1", rootuid); if (ret < 0 || ret >= 100) { ERROR("Error uid printing map string"); return -1; } // "u:hostuid:hostuid:1" ret = snprintf(map2, 100, "u:%d:%d:1", hostuid, hostuid); if (ret < 0 || ret >= 100) { ERROR("Error uid printing map string"); return -1; } // "g:0:rootgid:1" ret = snprintf(map3, 100, "g:0:%d:1", rootgid); if (ret < 0 || ret >= 100) { ERROR("Error gid printing map string"); return -1; } // "g:pathgid:rootgid+pathgid:1" ret = snprintf(map4, 100, "g:%d:%d:1", (gid_t)sb.st_gid, rootgid + (gid_t)sb.st_gid); if (ret < 0 || ret >= 100) { ERROR("Error gid printing map string"); return -1; } // "g:hostgid:hostgid:1" ret = snprintf(map5, 100, "g:%d:%d:1", hostgid, hostgid); if (ret < 0 || ret >= 100) { ERROR("Error gid printing map string"); return -1; } // "0:pathgid" (chown) ret = snprintf(ugid, 100, "0:%d", (gid_t)sb.st_gid); if (ret < 0 || ret >= 100) { ERROR("Error owner printing format string for chown"); return -1; } if (hostgid == sb.st_gid) ret = execvp("lxc-usernsexec", args1); else ret = execvp("lxc-usernsexec", args2); SYSERROR("Failed executing usernsexec"); exit(1); } return wait_for_pid(pid); } int ttys_shift_ids(struct lxc_conf *c) { if (lxc_list_empty(&c->id_map)) return 0; if (strcmp(c->console.name, "") !=0 && chown_mapped_root(c->console.name, c) < 0) { ERROR("Failed to chown %s", c->console.name); return -1; } return 0; } /* NOTE: Must not be called from inside the container namespace! */ int lxc_create_tmp_proc_mount(struct lxc_conf *conf) { int mounted; mounted = lxc_mount_proc_if_needed(conf->rootfs.path ? conf->rootfs.mount : ""); if (mounted == -1) { SYSERROR("failed to mount /proc in the container"); /* continue only if there is no rootfs */ if (conf->rootfs.path) return -1; } else if (mounted == 1) { conf->tmp_umount_proc = 1; } return 0; } void tmp_proc_unmount(struct lxc_conf *lxc_conf) { if (lxc_conf->tmp_umount_proc == 1) { umount("/proc"); lxc_conf->tmp_umount_proc = 0; } } void remount_all_slave(void) { /* walk /proc/mounts and change any shared entries to slave */ FILE *f = fopen("/proc/self/mountinfo", "r"); char *line = NULL; size_t len = 0; if (!f) { SYSERROR("Failed to open /proc/self/mountinfo to mark all shared"); ERROR("Continuing container startup..."); return; } while (getline(&line, &len, f) != -1) { char *target, *opts; target = get_field(line, 4); if (!target) continue; opts = get_field(target, 2); if (!opts) continue; null_endofword(opts); if (!strstr(opts, "shared")) continue; null_endofword(target); if (mount(NULL, target, NULL, MS_SLAVE, NULL)) { SYSERROR("Failed to make %s rslave", target); ERROR("Continuing..."); } } fclose(f); free(line); } void lxc_execute_bind_init(struct lxc_conf *conf) { int ret; char path[PATH_MAX], destpath[PATH_MAX], *p; /* If init exists in the container, don't bind mount a static one */ p = choose_init(conf->rootfs.mount); if (p) { free(p); return; } ret = snprintf(path, PATH_MAX, SBINDIR "/init.lxc.static"); if (ret < 0 || ret >= PATH_MAX) { WARN("Path name too long searching for lxc.init.static"); return; } if (!file_exists(path)) { INFO("%s does not exist on host", path); return; } ret = snprintf(destpath, PATH_MAX, "%s%s", conf->rootfs.mount, "/init.lxc.static"); if (ret < 0 || ret >= PATH_MAX) { WARN("Path name too long for container's lxc.init.static"); return; } if (!file_exists(destpath)) { FILE * pathfile = fopen(destpath, "wb"); if (!pathfile) { SYSERROR("Failed to create mount target '%s'", destpath); return; } fclose(pathfile); } ret = safe_mount(path, destpath, "none", MS_BIND, NULL, conf->rootfs.mount); if (ret < 0) SYSERROR("Failed to bind lxc.init.static into container"); INFO("lxc.init.static bound into container at %s", path); } /* * This does the work of remounting / if it is shared, calling the * container pre-mount hooks, and mounting the rootfs. */ int do_rootfs_setup(struct lxc_conf *conf, const char *name, const char *lxcpath) { if (conf->rootfs_setup) { /* * rootfs was set up in another namespace. bind-mount it * to give us a mount in our own ns so we can pivot_root to it */ const char *path = conf->rootfs.mount; if (mount(path, path, "rootfs", MS_BIND, NULL) < 0) { ERROR("Failed to bind-mount container / onto itself"); return -1; } return 0; } remount_all_slave(); if (run_lxc_hooks(name, "pre-mount", conf, lxcpath, NULL)) { ERROR("failed to run pre-mount hooks for container '%s'.", name); return -1; } if (setup_rootfs(conf)) { ERROR("failed to setup rootfs for '%s'", name); return -1; } conf->rootfs_setup = true; return 0; } static bool verify_start_hooks(struct lxc_conf *conf) { struct lxc_list *it; char path[MAXPATHLEN]; lxc_list_for_each(it, &conf->hooks[LXCHOOK_START]) { char *hookname = it->elem; struct stat st; int ret; ret = snprintf(path, MAXPATHLEN, "%s%s", conf->rootfs.path ? conf->rootfs.mount : "", hookname); if (ret < 0 || ret >= MAXPATHLEN) return false; ret = stat(path, &st); if (ret) { SYSERROR("Start hook %s not found in container", hookname); return false; } return true; } return true; } static int send_fd(int sock, int fd) { int ret = lxc_abstract_unix_send_fd(sock, fd, NULL, 0); if (ret < 0) { SYSERROR("Error sending tty fd to parent"); return -1; } return 0; } static int send_ttys_to_parent(struct lxc_handler *handler) { struct lxc_conf *conf = handler->conf; const struct lxc_tty_info *tty_info = &conf->tty_info; int i; int sock = handler->ttysock[0]; for (i = 0; i < tty_info->nbtty; i++) { struct lxc_pty_info *pty_info = &tty_info->pty_info[i]; if (send_fd(sock, pty_info->slave) < 0) goto bad; close(pty_info->slave); pty_info->slave = -1; if (send_fd(sock, pty_info->master) < 0) goto bad; close(pty_info->master); pty_info->master = -1; } close(handler->ttysock[0]); close(handler->ttysock[1]); return 0; bad: ERROR("Error writing tty fd to parent"); return -1; } int lxc_setup(struct lxc_handler *handler) { const char *name = handler->name; struct lxc_conf *lxc_conf = handler->conf; const char *lxcpath = handler->lxcpath; if (do_rootfs_setup(lxc_conf, name, lxcpath) < 0) { ERROR("Error setting up rootfs mount after spawn"); return -1; } if (lxc_conf->inherit_ns_fd[LXC_NS_UTS] == -1) { if (setup_utsname(lxc_conf->utsname)) { ERROR("failed to setup the utsname for '%s'", name); return -1; } } if (setup_network(&lxc_conf->network)) { ERROR("failed to setup the network for '%s'", name); return -1; } if (lxc_conf->autodev > 0) { if (mount_autodev(name, &lxc_conf->rootfs, lxcpath)) { ERROR("failed to mount /dev in the container"); return -1; } } /* do automatic mounts (mainly /proc and /sys), but exclude * those that need to wait until other stuff has finished */ if (lxc_mount_auto_mounts(lxc_conf, lxc_conf->auto_mounts & ~LXC_AUTO_CGROUP_MASK, handler) < 0) { ERROR("failed to setup the automatic mounts for '%s'", name); return -1; } if (setup_mount(&lxc_conf->rootfs, lxc_conf->fstab, name, lxcpath)) { ERROR("failed to setup the mounts for '%s'", name); return -1; } if (!lxc_list_empty(&lxc_conf->mount_list) && setup_mount_entries(&lxc_conf->rootfs, &lxc_conf->mount_list, name, lxcpath)) { ERROR("failed to setup the mount entries for '%s'", name); return -1; } /* Make sure any start hooks are in the container */ if (!verify_start_hooks(lxc_conf)) return -1; if (lxc_conf->is_execute) lxc_execute_bind_init(lxc_conf); /* now mount only cgroup, if wanted; * before, /sys could not have been mounted * (is either mounted automatically or via fstab entries) */ if (lxc_mount_auto_mounts(lxc_conf, lxc_conf->auto_mounts & LXC_AUTO_CGROUP_MASK, handler) < 0) { ERROR("failed to setup the automatic mounts for '%s'", name); return -1; } if (run_lxc_hooks(name, "mount", lxc_conf, lxcpath, NULL)) { ERROR("failed to run mount hooks for container '%s'.", name); return -1; } if (lxc_conf->autodev > 0) { if (run_lxc_hooks(name, "autodev", lxc_conf, lxcpath, NULL)) { ERROR("failed to run autodev hooks for container '%s'.", name); return -1; } if (lxc_fill_autodev(&lxc_conf->rootfs)) { ERROR("failed to populate /dev in the container"); return -1; } } if (!lxc_conf->is_execute && lxc_setup_console(&lxc_conf->rootfs, &lxc_conf->console, lxc_conf->ttydir)) { ERROR("failed to setup the console for '%s'", name); return -1; } if (lxc_conf->kmsg) { if (setup_kmsg(&lxc_conf->rootfs, &lxc_conf->console)) // don't fail ERROR("failed to setup kmsg for '%s'", name); } if (!lxc_conf->is_execute && setup_dev_symlinks(&lxc_conf->rootfs)) { ERROR("failed to setup /dev symlinks for '%s'", name); return -1; } /* mount /proc if it's not already there */ if (lxc_create_tmp_proc_mount(lxc_conf) < 0) { ERROR("failed to LSM mount proc for '%s'", name); return -1; } if (setup_pivot_root(&lxc_conf->rootfs)) { ERROR("failed to set rootfs for '%s'", name); return -1; } if (lxc_setup_devpts(lxc_conf->pts)) { ERROR("failed to setup the new pts instance"); return -1; } if (lxc_create_tty(name, lxc_conf)) { ERROR("failed to create the ttys"); return -1; } if (send_ttys_to_parent(handler) < 0) { ERROR("failure sending console info to parent"); return -1; } if (!lxc_conf->is_execute && setup_tty(lxc_conf)) { ERROR("failed to setup the ttys for '%s'", name); return -1; } if (lxc_conf->pty_names && setenv("container_ttys", lxc_conf->pty_names, 1)) SYSERROR("failed to set environment variable for container ptys"); if (setup_personality(lxc_conf->personality)) { ERROR("failed to setup personality"); return -1; } if (!lxc_list_empty(&lxc_conf->keepcaps)) { if (!lxc_list_empty(&lxc_conf->caps)) { ERROR("Container requests lxc.cap.drop and lxc.cap.keep: either use lxc.cap.drop or lxc.cap.keep, not both."); return -1; } if (dropcaps_except(&lxc_conf->keepcaps)) { ERROR("failed to keep requested caps"); return -1; } } else if (setup_caps(&lxc_conf->caps)) { ERROR("failed to drop capabilities"); return -1; } NOTICE("'%s' is setup.", name); return 0; } int run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf, const char *lxcpath, char *argv[]) { int which = -1; struct lxc_list *it; if (strcmp(hook, "pre-start") == 0) which = LXCHOOK_PRESTART; else if (strcmp(hook, "pre-mount") == 0) which = LXCHOOK_PREMOUNT; else if (strcmp(hook, "mount") == 0) which = LXCHOOK_MOUNT; else if (strcmp(hook, "autodev") == 0) which = LXCHOOK_AUTODEV; else if (strcmp(hook, "start") == 0) which = LXCHOOK_START; else if (strcmp(hook, "stop") == 0) which = LXCHOOK_STOP; else if (strcmp(hook, "post-stop") == 0) which = LXCHOOK_POSTSTOP; else if (strcmp(hook, "clone") == 0) which = LXCHOOK_CLONE; else if (strcmp(hook, "destroy") == 0) which = LXCHOOK_DESTROY; else return -1; lxc_list_for_each(it, &conf->hooks[which]) { int ret; char *hookname = it->elem; ret = run_script_argv(name, "lxc", hookname, hook, lxcpath, argv); if (ret) return ret; } return 0; } static void lxc_remove_nic(struct lxc_list *it) { struct lxc_netdev *netdev = it->elem; struct lxc_list *it2,*next; lxc_list_del(it); free(netdev->link); free(netdev->name); if (netdev->type == LXC_NET_VETH) free(netdev->priv.veth_attr.pair); free(netdev->upscript); free(netdev->hwaddr); free(netdev->mtu); free(netdev->ipv4_gateway); free(netdev->ipv6_gateway); lxc_list_for_each_safe(it2, &netdev->ipv4, next) { lxc_list_del(it2); free(it2->elem); free(it2); } lxc_list_for_each_safe(it2, &netdev->ipv6, next) { lxc_list_del(it2); free(it2->elem); free(it2); } free(netdev); free(it); } /* we get passed in something like '0', '0.ipv4' or '1.ipv6' */ int lxc_clear_nic(struct lxc_conf *c, const char *key) { char *p1; int ret, idx, i; struct lxc_list *it; struct lxc_netdev *netdev; p1 = strchr(key, '.'); if (!p1 || *(p1+1) == '\0') p1 = NULL; ret = sscanf(key, "%d", &idx); if (ret != 1) return -1; if (idx < 0) return -1; i = 0; lxc_list_for_each(it, &c->network) { if (i == idx) break; i++; } if (i < idx) // we don't have that many nics defined return -1; if (!it || !it->elem) return -1; netdev = it->elem; if (!p1) { lxc_remove_nic(it); } else if (strcmp(p1, ".ipv4") == 0) { struct lxc_list *it2,*next; lxc_list_for_each_safe(it2, &netdev->ipv4, next) { lxc_list_del(it2); free(it2->elem); free(it2); } } else if (strcmp(p1, ".ipv6") == 0) { struct lxc_list *it2,*next; lxc_list_for_each_safe(it2, &netdev->ipv6, next) { lxc_list_del(it2); free(it2->elem); free(it2); } } else return -1; return 0; } int lxc_clear_config_network(struct lxc_conf *c) { struct lxc_list *it,*next; lxc_list_for_each_safe(it, &c->network, next) { lxc_remove_nic(it); } return 0; } int lxc_clear_config_caps(struct lxc_conf *c) { struct lxc_list *it,*next; lxc_list_for_each_safe(it, &c->caps, next) { lxc_list_del(it); free(it->elem); free(it); } return 0; } static int lxc_free_idmap(struct lxc_list *id_map) { struct lxc_list *it, *next; lxc_list_for_each_safe(it, id_map, next) { lxc_list_del(it); free(it->elem); free(it); } return 0; } int lxc_clear_idmaps(struct lxc_conf *c) { return lxc_free_idmap(&c->id_map); } int lxc_clear_config_keepcaps(struct lxc_conf *c) { struct lxc_list *it,*next; lxc_list_for_each_safe(it, &c->keepcaps, next) { lxc_list_del(it); free(it->elem); free(it); } return 0; } int lxc_clear_cgroups(struct lxc_conf *c, const char *key) { struct lxc_list *it,*next; bool all = false; const char *k = NULL; if (strcmp(key, "lxc.cgroup") == 0) all = true; else if (strncmp(key, "lxc.cgroup.", sizeof("lxc.cgroup.")-1) == 0) k = key + sizeof("lxc.cgroup.")-1; else return -1; lxc_list_for_each_safe(it, &c->cgroup, next) { struct lxc_cgroup *cg = it->elem; if (!all && strcmp(cg->subsystem, k) != 0) continue; lxc_list_del(it); free(cg->subsystem); free(cg->value); free(cg); free(it); } return 0; } int lxc_clear_groups(struct lxc_conf *c) { struct lxc_list *it,*next; lxc_list_for_each_safe(it, &c->groups, next) { lxc_list_del(it); free(it->elem); free(it); } return 0; } int lxc_clear_environment(struct lxc_conf *c) { struct lxc_list *it,*next; lxc_list_for_each_safe(it, &c->environment, next) { lxc_list_del(it); free(it->elem); free(it); } return 0; } int lxc_clear_mount_entries(struct lxc_conf *c) { struct lxc_list *it,*next; lxc_list_for_each_safe(it, &c->mount_list, next) { lxc_list_del(it); free(it->elem); free(it); } return 0; } int lxc_clear_automounts(struct lxc_conf *c) { c->auto_mounts = 0; return 0; } int lxc_clear_hooks(struct lxc_conf *c, const char *key) { struct lxc_list *it,*next; bool all = false, done = false; const char *k = NULL; int i; if (strcmp(key, "lxc.hook") == 0) all = true; else if (strncmp(key, "lxc.hook.", sizeof("lxc.hook.")-1) == 0) k = key + sizeof("lxc.hook.")-1; else return -1; for (i=0; ihooks[i], next) { lxc_list_del(it); free(it->elem); free(it); } done = true; } } if (!done) { ERROR("Invalid hook key: %s", key); return -1; } return 0; } static void lxc_clear_saved_nics(struct lxc_conf *conf) { int i; if (!conf->saved_nics) return; for (i=0; i < conf->num_savednics; i++) free(conf->saved_nics[i].orig_name); free(conf->saved_nics); } static inline void lxc_clear_aliens(struct lxc_conf *conf) { struct lxc_list *it,*next; lxc_list_for_each_safe(it, &conf->aliens, next) { lxc_list_del(it); free(it->elem); free(it); } } static inline void lxc_clear_includes(struct lxc_conf *conf) { struct lxc_list *it,*next; lxc_list_for_each_safe(it, &conf->includes, next) { lxc_list_del(it); free(it->elem); free(it); } } void lxc_conf_free(struct lxc_conf *conf) { if (!conf) return; if (current_config == conf) current_config = NULL; free(conf->console.log_path); free(conf->console.path); free(conf->rootfs.mount); free(conf->rootfs.bdev_type); free(conf->rootfs.options); free(conf->rootfs.path); free(conf->logfile); if (conf->logfd != -1) close(conf->logfd); free(conf->utsname); free(conf->ttydir); free(conf->fstab); free(conf->rcfile); free(conf->init_cmd); free(conf->unexpanded_config); free(conf->pty_names); lxc_clear_config_network(conf); free(conf->lsm_aa_profile); free(conf->lsm_se_context); lxc_seccomp_free(conf); lxc_clear_config_caps(conf); lxc_clear_config_keepcaps(conf); lxc_clear_cgroups(conf, "lxc.cgroup"); lxc_clear_hooks(conf, "lxc.hook"); lxc_clear_mount_entries(conf); lxc_clear_saved_nics(conf); lxc_clear_idmaps(conf); lxc_clear_groups(conf); lxc_clear_includes(conf); lxc_clear_aliens(conf); lxc_clear_environment(conf); free(conf); } struct userns_fn_data { int (*fn)(void *); void *arg; int p[2]; }; static int run_userns_fn(void *data) { struct userns_fn_data *d = data; char c; // we're not sharing with the parent any more, if it was a thread close(d->p[1]); if (read(d->p[0], &c, 1) != 1) return -1; close(d->p[0]); return d->fn(d->arg); } /* * Add ID_TYPE_UID/ID_TYPE_GID entries to an existing lxc_conf, * if they are not already there. */ static struct lxc_list *idmap_add_id(struct lxc_conf *conf, uid_t uid, gid_t gid) { int hostuid_mapped = mapped_hostid(uid, conf, ID_TYPE_UID); int hostgid_mapped = mapped_hostid(gid, conf, ID_TYPE_GID); struct lxc_list *new = NULL, *tmp, *it, *next; struct id_map *entry; new = malloc(sizeof(*new)); if (!new) { ERROR("Out of memory building id map"); return NULL; } lxc_list_init(new); if (hostuid_mapped < 0) { hostuid_mapped = find_unmapped_nsuid(conf, ID_TYPE_UID); if (hostuid_mapped < 0) goto err; tmp = malloc(sizeof(*tmp)); if (!tmp) goto err; entry = malloc(sizeof(*entry)); if (!entry) { free(tmp); goto err; } tmp->elem = entry; entry->idtype = ID_TYPE_UID; entry->nsid = hostuid_mapped; entry->hostid = (unsigned long) uid; entry->range = 1; lxc_list_add_tail(new, tmp); } if (hostgid_mapped < 0) { hostgid_mapped = find_unmapped_nsuid(conf, ID_TYPE_GID); if (hostgid_mapped < 0) goto err; tmp = malloc(sizeof(*tmp)); if (!tmp) goto err; entry = malloc(sizeof(*entry)); if (!entry) { free(tmp); goto err; } tmp->elem = entry; entry->idtype = ID_TYPE_GID; entry->nsid = hostgid_mapped; entry->hostid = (unsigned long) gid; entry->range = 1; lxc_list_add_tail(new, tmp); } lxc_list_for_each_safe(it, &conf->id_map, next) { tmp = malloc(sizeof(*tmp)); if (!tmp) goto err; entry = malloc(sizeof(*entry)); if (!entry) { free(tmp); goto err; } memset(entry, 0, sizeof(*entry)); memcpy(entry, it->elem, sizeof(*entry)); tmp->elem = entry; lxc_list_add_tail(new, tmp); } return new; err: ERROR("Out of memory building a new uid/gid map"); if (new) lxc_free_idmap(new); free(new); return NULL; } /* * Run a function in a new user namespace. * The caller's euid/egid will be mapped in if it is not already. */ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data) { int ret, pid; struct userns_fn_data d; char c = '1'; int p[2]; struct lxc_list *idmap; ret = pipe(p); if (ret < 0) { SYSERROR("opening pipe"); return -1; } d.fn = fn; d.arg = data; d.p[0] = p[0]; d.p[1] = p[1]; pid = lxc_clone(run_userns_fn, &d, CLONE_NEWUSER); if (pid < 0) goto err; close(p[0]); p[0] = -1; if ((idmap = idmap_add_id(conf, geteuid(), getegid())) == NULL) { ERROR("Error adding self to container uid/gid map"); goto err; } ret = lxc_map_ids(idmap, pid); lxc_free_idmap(idmap); free(idmap); if (ret) { ERROR("Error setting up child mappings"); goto err; } // kick the child if (write(p[1], &c, 1) != 1) { SYSERROR("writing to pipe to child"); goto err; } ret = wait_for_pid(pid); close(p[1]); return ret; err: if (p[0] != -1) close(p[0]); close(p[1]); return -1; } /* not thread-safe, do not use from api without first forking */ static char* getuname(void) { struct passwd *result; result = getpwuid(geteuid()); if (!result) return NULL; return strdup(result->pw_name); } /* not thread-safe, do not use from api without first forking */ static char *getgname(void) { struct group *result; result = getgrgid(getegid()); if (!result) return NULL; return strdup(result->gr_name); } /* not thread-safe, do not use from api without first forking */ void suggest_default_idmap(void) { FILE *f; unsigned int uid = 0, urange = 0, gid = 0, grange = 0; char *line = NULL; char *uname, *gname; size_t len = 0; if (!(uname = getuname())) return; if (!(gname = getgname())) { free(uname); return; } f = fopen(subuidfile, "r"); if (!f) { ERROR("Your system is not configured with subuids"); free(gname); free(uname); return; } while (getline(&line, &len, f) != -1) { size_t no_newline = 0; char *p = strchr(line, ':'), *p2; if (*line == '#') continue; if (!p) continue; *p = '\0'; p++; if (strcmp(line, uname)) continue; p2 = strchr(p, ':'); if (!p2) continue; *p2 = '\0'; p2++; if (!*p2) continue; no_newline = strcspn(p2, "\n"); p2[no_newline] = '\0'; if (lxc_safe_uint(p, &uid) < 0) WARN("Could not parse UID."); if (lxc_safe_uint(p2, &urange) < 0) WARN("Could not parse UID range."); } fclose(f); f = fopen(subgidfile, "r"); if (!f) { ERROR("Your system is not configured with subgids"); free(gname); free(uname); return; } while (getline(&line, &len, f) != -1) { size_t no_newline = 0; char *p = strchr(line, ':'), *p2; if (*line == '#') continue; if (!p) continue; *p = '\0'; p++; if (strcmp(line, uname)) continue; p2 = strchr(p, ':'); if (!p2) continue; *p2 = '\0'; p2++; if (!*p2) continue; no_newline = strcspn(p2, "\n"); p2[no_newline] = '\0'; if (lxc_safe_uint(p, &gid) < 0) WARN("Could not parse GID."); if (lxc_safe_uint(p2, &grange) < 0) WARN("Could not parse GID range."); } fclose(f); free(line); if (!urange || !grange) { ERROR("You do not have subuids or subgids allocated"); ERROR("Unprivileged containers require subuids and subgids"); return; } ERROR("You must either run as root, or define uid mappings"); ERROR("To pass uid mappings to lxc-create, you could create"); ERROR("~/.config/lxc/default.conf:"); ERROR("lxc.include = %s", LXC_DEFAULT_CONFIG); ERROR("lxc.id_map = u 0 %u %u", uid, urange); ERROR("lxc.id_map = g 0 %u %u", gid, grange); free(gname); free(uname); } static void free_cgroup_settings(struct lxc_list *result) { struct lxc_list *iterator, *next; lxc_list_for_each_safe(iterator, result, next) { lxc_list_del(iterator); free(iterator); } free(result); } /* * Return the list of cgroup_settings sorted according to the following rules * 1. Put memory.limit_in_bytes before memory.memsw.limit_in_bytes */ struct lxc_list *sort_cgroup_settings(struct lxc_list* cgroup_settings) { struct lxc_list *result; struct lxc_list *memsw_limit = NULL; struct lxc_list *it = NULL; struct lxc_cgroup *cg = NULL; struct lxc_list *item = NULL; result = malloc(sizeof(*result)); if (!result) { ERROR("failed to allocate memory to sort cgroup settings"); return NULL; } lxc_list_init(result); /*Iterate over the cgroup settings and copy them to the output list*/ lxc_list_for_each(it, cgroup_settings) { item = malloc(sizeof(*item)); if (!item) { ERROR("failed to allocate memory to sort cgroup settings"); free_cgroup_settings(result); return NULL; } item->elem = it->elem; cg = it->elem; if (strcmp(cg->subsystem, "memory.memsw.limit_in_bytes") == 0) { /* Store the memsw_limit location */ memsw_limit = item; } else if (strcmp(cg->subsystem, "memory.limit_in_bytes") == 0 && memsw_limit != NULL) { /* lxc.cgroup.memory.memsw.limit_in_bytes is found before * lxc.cgroup.memory.limit_in_bytes, swap these two items */ item->elem = memsw_limit->elem; memsw_limit->elem = it->elem; } lxc_list_add_tail(result, item); } return result; } lxc-2.0.8/src/lxc/lxcutmp.c0000644061062106075000000002615413105116772012470 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_TIMERFD_H #include #else #include #ifndef TFD_NONBLOCK #define TFD_NONBLOCK O_NONBLOCK #endif #ifndef TFD_CLOEXEC #define TFD_CLOEXEC O_CLOEXEC #endif static int timerfd_create (clockid_t __clock_id, int __flags) { return syscall(__NR_timerfd_create, __clock_id, __flags); } static int timerfd_settime (int __ufd, int __flags, const struct itimerspec *__utmr, struct itimerspec *__otmr) { return syscall(__NR_timerfd_settime, __ufd, __flags, __utmr, __otmr); } #endif #include "conf.h" #include "cgroup.h" #include "start.h" #include "mainloop.h" #include "lxc.h" #include "log.h" #ifndef __USE_GNU #define __USE_GNU #endif #ifdef HAVE_UTMPX_H #include #ifndef HAVE_UTMPXNAME #include #endif #else #include #ifndef RUN_LVL #define RUN_LVL 1 #endif static void setutxent(void) { return setutent(); } static struct utmp * getutxent (void) { return (struct utmp *) getutent(); } static void endutxent (void) { #ifdef IS_BIONIC /* bionic isn't exporting endutend */ return; #else return endutent(); #endif } #endif #ifndef HAVE_UTMPXNAME static int utmpxname(const char *file) { int result; result = utmpname(file); #ifdef IS_BIONIC /* Yeah bionic is that weird */ result = result - 1; #endif return result; } #endif #undef __USE_GNU /* This file watches the /var/run/utmp file in the container * (that should probably be configurable) * We use inotify to put a watch on the /var/run directory for * create and modify events. These can trigger a read of the * utmp file looking for runlevel changes. If a runlevel change * to reboot or halt states is detected, we set up an itimer to * regularly check for the container shutdown, and reboot or halt * as appropriate when we get down to 1 task remaining. */ lxc_log_define(lxc_utmp, lxc); struct lxc_utmp { struct lxc_handler *handler; #define CONTAINER_STARTING 0 #define CONTAINER_REBOOTING 1 #define CONTAINER_HALTING 2 #define CONTAINER_RUNNING 4 char container_state; int timer_fd; int prev_runlevel, curr_runlevel; }; typedef void (*lxc_mainloop_timer_t) (void *data); static int utmp_get_runlevel(struct lxc_utmp *utmp_data); static int utmp_get_ntasks(struct lxc_handler *handler); static int utmp_shutdown_handler(int fd, uint32_t events, void *data, struct lxc_epoll_descr *descr); static int lxc_utmp_add_timer(struct lxc_epoll_descr *descr, lxc_mainloop_callback_t callback, void *data); static int lxc_utmp_del_timer(struct lxc_epoll_descr *descr, struct lxc_utmp *utmp_data); static int utmp_handler(int fd, uint32_t events, void *data, struct lxc_epoll_descr *descr) { struct inotify_event *ie; int size, ret, length; struct lxc_utmp *utmp_data = (struct lxc_utmp *)data; /* * we're monitoring a directory. ie->name is not included in * sizeof(struct inotify_event) if we don't read it all at once, * read gives us EINVAL, so we read and cast to struct ie */ char buffer[MAXPATHLEN]; if (ioctl(fd, FIONREAD, &size) < 0) { SYSERROR("cannot determine the size of this notification"); return -1; } if (read(fd, buffer, size) < size) { SYSERROR("failed to read notification"); return -1; } ie = (struct inotify_event *)buffer; if (ie->len <= 0) { if (ie->mask & IN_UNMOUNT) { DEBUG("watched directory removed"); goto out; } SYSERROR("inotify event with no name (mask %d)", ie->mask); return -1; } ret = 0; DEBUG("got inotify event %d for %s", ie->mask, ie->name); length = (4 < ie->len) ? 4 : ie->len; /* only care about utmp */ if (strncmp(ie->name, "utmp", length)) return 0; if (ie->mask & (IN_MODIFY | IN_CREATE)) ret = utmp_get_runlevel(utmp_data); if (ret < 0) goto out; /* container halting, from running or starting state */ if (utmp_data->curr_runlevel == '0' && ((utmp_data->container_state == CONTAINER_RUNNING) || (utmp_data->container_state == CONTAINER_STARTING))) { utmp_data->container_state = CONTAINER_HALTING; if (utmp_data->timer_fd == -1) lxc_utmp_add_timer(descr, utmp_shutdown_handler, data); DEBUG("Container halting"); goto out; } /* container rebooting, from running or starting state */ if (utmp_data->curr_runlevel == '6' && ((utmp_data->container_state == CONTAINER_RUNNING) || (utmp_data->container_state == CONTAINER_STARTING))) { utmp_data->container_state = CONTAINER_REBOOTING; if (utmp_data->timer_fd == -1) lxc_utmp_add_timer(descr, utmp_shutdown_handler, data); DEBUG("Container rebooting"); goto out; } /* normal operation, running, from starting state. */ if (utmp_data->curr_runlevel > '0' && utmp_data->curr_runlevel < '6') { utmp_data->container_state = CONTAINER_RUNNING; if (utmp_data->timer_fd > 0) lxc_utmp_del_timer(descr, utmp_data); DEBUG("Container running"); goto out; } out: return 0; } static int utmp_get_runlevel(struct lxc_utmp *utmp_data) { #if HAVE_UTMPX_H struct utmpx *utmpx; #else struct utmp *utmpx; #endif char path[MAXPATHLEN]; struct lxc_handler *handler = utmp_data->handler; if (snprintf(path, MAXPATHLEN, "/proc/%d/root/run/utmp", handler->pid) > MAXPATHLEN) { ERROR("path is too long"); return -1; } if (!access(path, F_OK) && !utmpxname(path)) goto utmp_ok; if (snprintf(path, MAXPATHLEN, "/proc/%d/root/var/run/utmp", handler->pid) > MAXPATHLEN) { ERROR("path is too long"); return -1; } if (utmpxname(path)) { SYSERROR("failed to 'utmpxname'"); return -1; } utmp_ok: setutxent(); while ((utmpx = getutxent())) { if (utmpx->ut_type == RUN_LVL) { utmp_data->prev_runlevel = utmpx->ut_pid / 256; utmp_data->curr_runlevel = utmpx->ut_pid % 256; DEBUG("utmp handler - run level is %c/%c", utmp_data->prev_runlevel, utmp_data->curr_runlevel); } } endutxent(); return 0; } static int utmp_get_ntasks(struct lxc_handler *handler) { int ntasks; ntasks = cgroup_nrtasks(handler); if (ntasks < 0) { ERROR("failed to get the number of tasks"); return -1; } DEBUG("there are %d tasks running", ntasks); return ntasks; } int lxc_utmp_mainloop_add(struct lxc_epoll_descr *descr, struct lxc_handler *handler) { char path[MAXPATHLEN]; char path2[MAXPATHLEN]; int fd, wd; struct lxc_utmp *utmp_data; /* We set up a watch for the /var/run directory. We're only interested * in utmp at the moment, but want to watch for delete and create * events as well. */ if (snprintf(path, MAXPATHLEN, "/proc/%d/root/run", handler->pid) > MAXPATHLEN) { ERROR("path is too long"); return -1; } if (snprintf(path2, MAXPATHLEN, "/proc/%d/root/run/utmp", handler->pid) > MAXPATHLEN) { ERROR("path is too long"); return -1; } if (!access(path2, F_OK)) goto run_ok; if (snprintf(path, MAXPATHLEN, "/proc/%d/root/var/run", handler->pid) > MAXPATHLEN) { ERROR("path is too long"); return -1; } if (access(path, F_OK)) { WARN("'%s' not found", path); return 0; } run_ok: utmp_data = (struct lxc_utmp *)malloc(sizeof(struct lxc_utmp)); if (NULL == utmp_data) { SYSERROR("failed to malloc handler utmp_data"); return -1; } memset(utmp_data, 0, sizeof(struct lxc_utmp)); fd = inotify_init(); if (fd < 0) { SYSERROR("failed to inotify_init"); goto out; } if (fcntl(fd, F_SETFD, FD_CLOEXEC)) { SYSERROR("failed to set inotify fd to close-on-exec"); goto out_close; } wd = inotify_add_watch(fd, path, IN_MODIFY | IN_CREATE); if (wd < 0) { SYSERROR("failed to add watch for '%s'", path); goto out_close; } utmp_data->handler = handler; utmp_data->container_state = CONTAINER_STARTING; utmp_data->timer_fd = -1; utmp_data->prev_runlevel = 'N'; utmp_data->curr_runlevel = 'N'; if (lxc_mainloop_add_handler (descr, fd, utmp_handler, (void *)utmp_data)) { SYSERROR("failed to add mainloop"); goto out_close; } DEBUG("Added '%s' to inotifywatch", path); return 0; out_close: close(fd); out: free(utmp_data); return -1; } static int utmp_shutdown_handler(int fd, uint32_t events, void *data, struct lxc_epoll_descr *descr) { int ntasks; ssize_t nread; struct lxc_utmp *utmp_data = (struct lxc_utmp *)data; struct lxc_handler *handler = utmp_data->handler; struct lxc_conf *conf = handler->conf; uint64_t expirations; /* read and clear notifications */ nread = read(fd, &expirations, sizeof(expirations)); if (nread < 0) SYSERROR("Failed to read timer notification"); ntasks = utmp_get_ntasks(handler); if (ntasks == 1 && (utmp_data->container_state == CONTAINER_HALTING)) { INFO("container has shutdown"); /* shutdown timer */ lxc_utmp_del_timer(descr, utmp_data); kill(handler->pid, SIGKILL); } if (ntasks == 1 && (utmp_data->container_state == CONTAINER_REBOOTING)) { INFO("container has rebooted"); conf->reboot = 1; /* shutdown timer */ lxc_utmp_del_timer(descr, utmp_data); /* this seems a bit rough. */ kill(handler->pid, SIGKILL); } return 0; } int lxc_utmp_add_timer(struct lxc_epoll_descr *descr, lxc_mainloop_callback_t callback, void *data) { int fd, result; struct itimerspec timeout; struct lxc_utmp *utmp_data = (struct lxc_utmp *)data; fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); if (fd < 0) { SYSERROR("failed to create timer"); return -1; } DEBUG("Setting up utmp shutdown timer"); /* set a one second timeout. Repeated. */ timeout.it_value.tv_sec = 1; timeout.it_value.tv_nsec = 0; timeout.it_interval.tv_sec = 1; timeout.it_interval.tv_nsec = 0; result = timerfd_settime(fd, 0, &timeout, NULL); if (result < 0) { SYSERROR("timerfd_settime:"); return -1; } if (lxc_mainloop_add_handler(descr, fd, callback, utmp_data)) { SYSERROR("failed to add utmp timer to mainloop"); close(fd); return -1; } utmp_data->timer_fd = fd; return 0; } int lxc_utmp_del_timer(struct lxc_epoll_descr *descr, struct lxc_utmp *utmp_data) { int result; DEBUG("Clearing utmp shutdown timer"); result = lxc_mainloop_del_handler(descr, utmp_data->timer_fd); if (result < 0) SYSERROR("failed to del utmp timer from mainloop"); /* shutdown timer_fd */ close(utmp_data->timer_fd); utmp_data->timer_fd = -1; if (result < 0) return -1; else return 0; } lxc-2.0.8/src/lxc/utils.h0000644061062106075000000002703313105116772012136 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_UTILS_H #define __LXC_UTILS_H /* Properly support loop devices on 32bit systems. */ #define _FILE_OFFSET_BITS 64 #include "config.h" #include #include #include #include #include #include #include #include #include "initutils.h" /* Useful macros */ /* Maximum number for 64 bit integer is a string with 21 digits: 2^64 - 1 = 21 */ #define LXC_NUMSTRLEN64 21 #define LXC_LINELEN 4096 #define LXC_IDMAPLEN 4096 /* returns 1 on success, 0 if there were any failures */ extern int lxc_rmdir_onedev(char *path, const char *exclude); extern int get_u16(unsigned short *val, const char *arg, int base); extern int mkdir_p(const char *dir, mode_t mode); extern char *get_rundir(void); /* Define getline() if missing from the C library */ #ifndef HAVE_GETLINE #ifdef HAVE_FGETLN #include <../include/getline.h> #endif #endif /* Define setns() if missing from the C library */ #ifndef HAVE_SETNS static inline int setns(int fd, int nstype) { #ifdef __NR_setns return syscall(__NR_setns, fd, nstype); #elif defined(__NR_set_ns) return syscall(__NR_set_ns, fd, nstype); #else errno = ENOSYS; return -1; #endif } #endif /* Define unshare() if missing from the C library */ #ifndef HAVE_UNSHARE static inline int unshare(int flags) { #ifdef __NR_unshare return syscall(__NR_unshare, flags); #else errno = ENOSYS; return -1; #endif } #else int unshare(int); #endif /* Define signalfd() if missing from the C library */ #ifdef HAVE_SYS_SIGNALFD_H # include #else /* assume kernel headers are too old */ #include struct signalfd_siginfo { uint32_t ssi_signo; int32_t ssi_errno; int32_t ssi_code; uint32_t ssi_pid; uint32_t ssi_uid; int32_t ssi_fd; uint32_t ssi_tid; uint32_t ssi_band; uint32_t ssi_overrun; uint32_t ssi_trapno; int32_t ssi_status; int32_t ssi_int; uint64_t ssi_ptr; uint64_t ssi_utime; uint64_t ssi_stime; uint64_t ssi_addr; uint8_t __pad[48]; }; # ifndef __NR_signalfd4 /* assume kernel headers are too old */ # if __i386__ # define __NR_signalfd4 327 # elif __x86_64__ # define __NR_signalfd4 289 # elif __powerpc__ # define __NR_signalfd4 313 # elif __s390x__ # define __NR_signalfd4 322 # elif __arm__ # define __NR_signalfd4 355 # elif __mips__ && _MIPS_SIM == _ABIO32 # define __NR_signalfd4 4324 # elif __mips__ && _MIPS_SIM == _ABI64 # define __NR_signalfd4 5283 # elif __mips__ && _MIPS_SIM == _ABIN32 # define __NR_signalfd4 6287 # endif #endif # ifndef __NR_signalfd /* assume kernel headers are too old */ # if __i386__ # define __NR_signalfd 321 # elif __x86_64__ # define __NR_signalfd 282 # elif __powerpc__ # define __NR_signalfd 305 # elif __s390x__ # define __NR_signalfd 316 # elif __arm__ # define __NR_signalfd 349 # elif __mips__ && _MIPS_SIM == _ABIO32 # define __NR_signalfd 4317 # elif __mips__ && _MIPS_SIM == _ABI64 # define __NR_signalfd 5276 # elif __mips__ && _MIPS_SIM == _ABIN32 # define __NR_signalfd 6280 # endif #endif static inline int signalfd(int fd, const sigset_t *mask, int flags) { int retval; retval = syscall (__NR_signalfd4, fd, mask, _NSIG / 8, flags); if (errno == ENOSYS && flags == 0) retval = syscall (__NR_signalfd, fd, mask, _NSIG / 8); return retval; } #endif /* loop devices */ #ifndef LO_FLAGS_AUTOCLEAR #define LO_FLAGS_AUTOCLEAR 4 #endif #ifndef LOOP_CTL_GET_FREE #define LOOP_CTL_GET_FREE 0x4C82 #endif /* Struct to carry child pid from lxc_popen() to lxc_pclose(). * Not an opaque struct to allow direct access to the underlying FILE * * (i.e., struct lxc_popen_FILE *file; fgets(buf, sizeof(buf), file->f)) * without additional wrappers. */ struct lxc_popen_FILE { FILE *f; pid_t child_pid; }; /* popen(command, "re") replacement that restores default signal mask * via sigprocmask(2) (unblocks all signals) after fork(2) but prior to calling exec(3). * In short, popen(command, "re") does pipe() + fork() + exec() * while lxc_popen(command) does pipe() + fork() + sigprocmask() + exec(). * Returns pointer to struct lxc_popen_FILE, that should be freed with lxc_pclose(). * On error returns NULL. */ extern struct lxc_popen_FILE *lxc_popen(const char *command); /* pclose() replacement to be used on struct lxc_popen_FILE *, * returned by lxc_popen(). * Waits for associated process to terminate, returns its exit status and * frees resources, pointed to by struct lxc_popen_FILE *. */ extern int lxc_pclose(struct lxc_popen_FILE *fp); /** * BUILD_BUG_ON - break compile if a condition is true. * @condition: the condition which the compiler should know is false. * * If you have some code which relies on certain constants being equal, or * other compile-time-evaluated condition, you should use BUILD_BUG_ON to * detect if someone changes it. * * The implementation uses gcc's reluctance to create a negative array, but * gcc (as of 4.4) only emits that error for obvious cases (eg. not arguments * to inline functions). So as a fallback we use the optimizer; if it can't * prove the condition is false, it will cause a link error on the undefined * "__build_bug_on_failed". This error message can be harder to track down * though, hence the two different methods. */ #ifndef __OPTIMIZE__ #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) #else extern int __build_bug_on_failed; #define BUILD_BUG_ON(condition) \ do { \ ((void)sizeof(char[1 - 2*!!(condition)])); \ if (condition) __build_bug_on_failed = 1; \ } while(0) #endif /* * wait on a child we forked */ extern int wait_for_pid(pid_t pid); extern int lxc_wait_for_pid_status(pid_t pid); /* send and receive buffers completely */ extern ssize_t lxc_write_nointr(int fd, const void* buf, size_t count); extern ssize_t lxc_read_nointr(int fd, void* buf, size_t count); extern ssize_t lxc_read_nointr_expect(int fd, void* buf, size_t count, const void* expected_buf); #if HAVE_LIBGNUTLS #define SHA_DIGEST_LENGTH 20 extern int sha1sum_file(char *fnam, unsigned char *md_value); #endif /* read and write whole files */ extern int lxc_write_to_file(const char *filename, const void* buf, size_t count, bool add_newline); extern int lxc_read_from_file(const char *filename, void* buf, size_t count); /* convert variadic argument lists to arrays (for execl type argument lists) */ extern char** lxc_va_arg_list_to_argv(va_list ap, size_t skip, int do_strdup); extern const char** lxc_va_arg_list_to_argv_const(va_list ap, size_t skip); /* Some simple string functions; if they return pointers, they are allocated buffers. */ extern char *lxc_string_replace(const char *needle, const char *replacement, const char *haystack); extern bool lxc_string_in_array(const char *needle, const char **haystack); extern char *lxc_string_join(const char *sep, const char **parts, bool use_as_prefix); /* Normalize and split path: Leading and trailing / are removed, multiple * / are compactified, .. and . are resolved (.. on the top level is considered * identical to .). * Examples: * / -> { NULL } * foo/../bar -> { bar, NULL } * ../../ -> { NULL } * ./bar/baz/.. -> { bar, NULL } * foo//bar -> { foo, bar, NULL } */ extern char **lxc_normalize_path(const char *path); /* remove multiple slashes from the path, e.g. ///foo//bar -> /foo/bar */ extern bool lxc_deslashify(char **path); extern char *lxc_append_paths(const char *first, const char *second); /* Note: the following two functions use strtok(), so they will never * consider an empty element, even if two delimiters are next to * each other. */ extern bool lxc_string_in_list(const char *needle, const char *haystack, char sep); extern char **lxc_string_split(const char *string, char sep); extern char **lxc_string_split_and_trim(const char *string, char sep); /* Append string to NULL-terminated string array. */ extern int lxc_append_string(char ***list, char *entry); /* some simple array manipulation utilities */ typedef void (*lxc_free_fn)(void *); typedef void *(*lxc_dup_fn)(void *); extern int lxc_grow_array(void ***array, size_t* capacity, size_t new_size, size_t capacity_increment); extern void lxc_free_array(void **array, lxc_free_fn element_free_fn); extern size_t lxc_array_len(void **array); extern void **lxc_append_null_to_array(void **array, size_t count); /* mmap() wrapper. lxc_strmmap() will take care to \0-terminate files so that * normal string-handling functions can be used on the buffer. */ extern void *lxc_strmmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); /* munmap() wrapper. Use it to free memory mmap()ed with lxc_strmmap(). */ extern int lxc_strmunmap(void *addr, size_t length); //initialize rand with urandom extern int randseed(bool); inline static bool am_unpriv(void) { return geteuid() != 0; } /* * parse /proc/self/uid_map to find what @orig maps to */ extern uid_t get_ns_uid(uid_t orig); extern bool dir_exists(const char *path); #define FNV1A_64_INIT ((uint64_t)0xcbf29ce484222325ULL) uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval); int detect_shared_rootfs(void); bool detect_ramfs_rootfs(void); char *on_path(const char *cmd, const char *rootfs); bool file_exists(const char *f); bool cgns_supported(void); char *choose_init(const char *rootfs); int print_to_file(const char *file, const char *content); bool switch_to_ns(pid_t pid, const char *ns); int is_dir(const char *path); char *get_template_path(const char *t); int setproctitle(char *title); int safe_mount(const char *src, const char *dest, const char *fstype, unsigned long flags, const void *data, const char *rootfs); int lxc_mount_proc_if_needed(const char *rootfs); int open_devnull(void); int set_stdfds(int fd); int null_stdfds(void); int lxc_count_file_lines(const char *fn); int lxc_preserve_ns(const int pid, const char *ns); /* Check whether a signal is blocked by a process. */ bool task_blocking_signal(pid_t pid, int signal); /* Helper functions to parse numbers. */ int lxc_safe_uint(const char *numstr, unsigned int *converted); int lxc_safe_int(const char *numstr, int *converted); int lxc_safe_long(const char *numstr, long int *converted); /* Switch to a new uid and gid. */ int lxc_switch_uid_gid(uid_t uid, gid_t gid); int lxc_setgroups(int size, gid_t list[]); /* Find an unused loop device and associate it with source. */ int lxc_prepare_loop_dev(const char *source, char *loop_dev, int flags); /* Clear all mounts on a given node. * >= 0 successfully cleared. The number returned is the number of umounts * performed. * < 0 error umounting. Return -errno. */ int lxc_unstack_mountpoint(const char *path, bool lazy); #endif /* __LXC_UTILS_H */ lxc-2.0.8/src/lxc/list.h0000644061062106075000000001015313105116772011744 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_LIST_H #define __LXC_LIST_H struct lxc_list { void *elem; struct lxc_list *next; struct lxc_list *prev; }; #define lxc_init_list(l) { .next = l, .prev = l } /* * Iterate through an lxc list. An example for an idiom would be: * * struct lxc_list *iterator; * type *tmp; // where "type" can be an int, char * etc. * lxc_list_for_each(iterator, list) { * tmp = iterator->elem; * // Do stuff with tmp. * } * free(iterator); */ #define lxc_list_for_each(__iterator, __list) \ for (__iterator = (__list)->next; \ __iterator != __list; \ __iterator = __iterator->next) /* * Iterate safely through an lxc list. An example for an appropriate use case * would be: * * struct lxc_list *iterator; * lxc_list_for_each_safe(iterator, list, list->next) { * tmp = iterator->elem; * // Do stuff with tmp. * } * free(iterator); */ #define lxc_list_for_each_safe(__iterator, __list, __next) \ for (__iterator = (__list)->next, __next = __iterator->next; \ __iterator != __list; \ __iterator = __next, __next = __next->next) /* Initalize list. */ static inline void lxc_list_init(struct lxc_list *list) { list->elem = NULL; list->next = list->prev = list; } /* Add an element to a list. See lxc_list_add() and lxc_list_add_tail() for an * idiom. */ static inline void lxc_list_add_elem(struct lxc_list *list, void *elem) { list->elem = elem; } /* Retrieve first element of list. */ static inline void *lxc_list_first_elem(struct lxc_list *list) { return list->next->elem; } /* Retrieve last element of list. */ static inline void *lxc_list_last_elem(struct lxc_list *list) { return list->prev->elem; } /* Determine if list is empty. */ static inline int lxc_list_empty(struct lxc_list *list) { return list == list->next; } /* Workhorse to be called from lxc_list_add() and lxc_list_add_tail(). */ static inline void __lxc_list_add(struct lxc_list *new, struct lxc_list *prev, struct lxc_list *next) { next->prev = new; new->next = next; new->prev = prev; prev->next = new; } /* * Idiom to add an element to the beginning of an lxc list: * * struct lxc_list *tmp = malloc(sizeof(*tmp)); * if (tmp == NULL) * return 1; * lxc_list_add_elem(tmp, elem); * lxc_list_add(list, tmp); */ static inline void lxc_list_add(struct lxc_list *head, struct lxc_list *list) { __lxc_list_add(list, head, head->next); } /* * Idiom to add an element to the end of an lxc list: * * struct lxc_list *tmp = malloc(sizeof(*tmp)); * if (tmp == NULL) * return 1; * lxc_list_add_elem(tmp, elem); * lxc_list_add_tail(list, tmp); */ static inline void lxc_list_add_tail(struct lxc_list *head, struct lxc_list *list) { __lxc_list_add(list, head->prev, head); } /* * Idiom to free an lxc list: * * lxc_list_for_each_safe(iterator, list, list->next) { * lxc_list_del(iterator); * free(iterator); * } * free(iterator); */ static inline void lxc_list_del(struct lxc_list *list) { struct lxc_list *next, *prev; next = list->next; prev = list->prev; next->prev = prev; prev->next = next; } /* Return length of the list. */ static inline size_t lxc_list_len(struct lxc_list *list) { size_t i = 0; struct lxc_list *iter; lxc_list_for_each(iter, list) { i++; } return i; } #endif lxc-2.0.8/src/lxc/confile.c0000644061062106075000000022452513105116772012415 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "bdev.h" #include "parse.h" #include "config.h" #include "confile.h" #include "utils.h" #include "log.h" #include "conf.h" #include "network.h" #include "lxcseccomp.h" #if HAVE_SYS_PERSONALITY_H #include #endif lxc_log_define(lxc_confile, lxc); static int config_personality(const char *, const char *, struct lxc_conf *); static int config_pts(const char *, const char *, struct lxc_conf *); static int config_tty(const char *, const char *, struct lxc_conf *); static int config_ttydir(const char *, const char *, struct lxc_conf *); static int config_kmsg(const char *, const char *, struct lxc_conf *); static int config_lsm_aa_profile(const char *, const char *, struct lxc_conf *); static int config_lsm_aa_incomplete(const char *, const char *, struct lxc_conf *); static int config_lsm_se_context(const char *, const char *, struct lxc_conf *); static int config_cgroup(const char *, const char *, struct lxc_conf *); static int config_idmap(const char *, const char *, struct lxc_conf *); static int config_loglevel(const char *, const char *, struct lxc_conf *); static int config_logfile(const char *, const char *, struct lxc_conf *); static int config_mount(const char *, const char *, struct lxc_conf *); static int config_mount_auto(const char *, const char *, struct lxc_conf *); static int config_fstab(const char *, const char *, struct lxc_conf *); static int config_rootfs(const char *, const char *, struct lxc_conf *); static int config_rootfs_mount(const char *, const char *, struct lxc_conf *); static int config_rootfs_options(const char *, const char *, struct lxc_conf *); static int config_rootfs_backend(const char *, const char *, struct lxc_conf *); static int config_pivotdir(const char *, const char *, struct lxc_conf *); static int config_utsname(const char *, const char *, struct lxc_conf *); static int config_hook(const char *, const char *, struct lxc_conf *lxc_conf); static int config_network(const char *, const char *, struct lxc_conf *); static int config_network_type(const char *, const char *, struct lxc_conf *); static int config_network_flags(const char *, const char *, struct lxc_conf *); static int config_network_link(const char *, const char *, struct lxc_conf *); static int config_network_name(const char *, const char *, struct lxc_conf *); static int config_network_veth_pair(const char *, const char *, struct lxc_conf *); static int config_network_macvlan_mode(const char *, const char *, struct lxc_conf *); static int config_network_hwaddr(const char *, const char *, struct lxc_conf *); static int config_network_vlan_id(const char *, const char *, struct lxc_conf *); static int config_network_mtu(const char *, const char *, struct lxc_conf *); static int config_network_ipv4(const char *, const char *, struct lxc_conf *); static int config_network_ipv4_gateway(const char *, const char *, struct lxc_conf *); static int config_network_script_up(const char *, const char *, struct lxc_conf *); static int config_network_script_down(const char *, const char *, struct lxc_conf *); static int config_network_ipv6(const char *, const char *, struct lxc_conf *); static int config_network_ipv6_gateway(const char *, const char *, struct lxc_conf *); static int config_cap_drop(const char *, const char *, struct lxc_conf *); static int config_cap_keep(const char *, const char *, struct lxc_conf *); static int config_console(const char *, const char *, struct lxc_conf *); static int config_console_logfile(const char *, const char *, struct lxc_conf *); static int config_seccomp(const char *, const char *, struct lxc_conf *); static int config_includefile(const char *, const char *, struct lxc_conf *); static int config_network_nic(const char *, const char *, struct lxc_conf *); static int config_autodev(const char *, const char *, struct lxc_conf *); static int config_haltsignal(const char *, const char *, struct lxc_conf *); static int config_rebootsignal(const char *, const char *, struct lxc_conf *); static int config_stopsignal(const char *, const char *, struct lxc_conf *); static int config_start(const char *, const char *, struct lxc_conf *); static int config_monitor(const char *, const char *, struct lxc_conf *); static int config_group(const char *, const char *, struct lxc_conf *); static int config_environment(const char *, const char *, struct lxc_conf *); static int config_init_cmd(const char *, const char *, struct lxc_conf *); static int config_init_uid(const char *, const char *, struct lxc_conf *); static int config_init_gid(const char *, const char *, struct lxc_conf *); static int config_ephemeral(const char *, const char *, struct lxc_conf *); static struct lxc_config_t config[] = { { "lxc.arch", config_personality }, { "lxc.pts", config_pts }, { "lxc.tty", config_tty }, { "lxc.devttydir", config_ttydir }, { "lxc.kmsg", config_kmsg }, { "lxc.aa_profile", config_lsm_aa_profile }, { "lxc.aa_allow_incomplete", config_lsm_aa_incomplete }, { "lxc.se_context", config_lsm_se_context }, { "lxc.cgroup", config_cgroup }, { "lxc.id_map", config_idmap }, { "lxc.loglevel", config_loglevel }, { "lxc.logfile", config_logfile }, { "lxc.mount.entry", config_mount }, { "lxc.mount.auto", config_mount_auto }, { "lxc.mount", config_fstab }, { "lxc.rootfs.mount", config_rootfs_mount }, { "lxc.rootfs.options", config_rootfs_options }, { "lxc.rootfs.backend", config_rootfs_backend }, { "lxc.rootfs", config_rootfs }, { "lxc.pivotdir", config_pivotdir }, { "lxc.utsname", config_utsname }, { "lxc.hook.pre-start", config_hook }, { "lxc.hook.pre-mount", config_hook }, { "lxc.hook.mount", config_hook }, { "lxc.hook.autodev", config_hook }, { "lxc.hook.start", config_hook }, { "lxc.hook.stop", config_hook }, { "lxc.hook.post-stop", config_hook }, { "lxc.hook.clone", config_hook }, { "lxc.hook.destroy", config_hook }, { "lxc.hook", config_hook }, { "lxc.network.type", config_network_type }, { "lxc.network.flags", config_network_flags }, { "lxc.network.link", config_network_link }, { "lxc.network.name", config_network_name }, { "lxc.network.macvlan.mode", config_network_macvlan_mode }, { "lxc.network.veth.pair", config_network_veth_pair }, { "lxc.network.script.up", config_network_script_up }, { "lxc.network.script.down", config_network_script_down }, { "lxc.network.hwaddr", config_network_hwaddr }, { "lxc.network.mtu", config_network_mtu }, { "lxc.network.vlan.id", config_network_vlan_id }, { "lxc.network.ipv4.gateway", config_network_ipv4_gateway }, { "lxc.network.ipv4", config_network_ipv4 }, { "lxc.network.ipv6.gateway", config_network_ipv6_gateway }, { "lxc.network.ipv6", config_network_ipv6 }, /* config_network_nic must come after all other 'lxc.network.*' entries */ { "lxc.network.", config_network_nic }, { "lxc.network", config_network }, { "lxc.cap.drop", config_cap_drop }, { "lxc.cap.keep", config_cap_keep }, { "lxc.console.logfile", config_console_logfile }, { "lxc.console", config_console }, { "lxc.seccomp", config_seccomp }, { "lxc.include", config_includefile }, { "lxc.autodev", config_autodev }, { "lxc.haltsignal", config_haltsignal }, { "lxc.rebootsignal", config_rebootsignal }, { "lxc.stopsignal", config_stopsignal }, { "lxc.start.auto", config_start }, { "lxc.start.delay", config_start }, { "lxc.start.order", config_start }, { "lxc.monitor.unshare", config_monitor }, { "lxc.group", config_group }, { "lxc.environment", config_environment }, { "lxc.init_cmd", config_init_cmd }, { "lxc.init_uid", config_init_uid }, { "lxc.init_gid", config_init_gid }, { "lxc.ephemeral", config_ephemeral }, }; struct signame { int num; const char *name; }; static const struct signame signames[] = { { SIGHUP, "HUP" }, { SIGINT, "INT" }, { SIGQUIT, "QUIT" }, { SIGILL, "ILL" }, { SIGABRT, "ABRT" }, { SIGFPE, "FPE" }, { SIGKILL, "KILL" }, { SIGSEGV, "SEGV" }, { SIGPIPE, "PIPE" }, { SIGALRM, "ALRM" }, { SIGTERM, "TERM" }, { SIGUSR1, "USR1" }, { SIGUSR2, "USR2" }, { SIGCHLD, "CHLD" }, { SIGCONT, "CONT" }, { SIGSTOP, "STOP" }, { SIGTSTP, "TSTP" }, { SIGTTIN, "TTIN" }, { SIGTTOU, "TTOU" }, #ifdef SIGTRAP { SIGTRAP, "TRAP" }, #endif #ifdef SIGIOT { SIGIOT, "IOT" }, #endif #ifdef SIGEMT { SIGEMT, "EMT" }, #endif #ifdef SIGBUS { SIGBUS, "BUS" }, #endif #ifdef SIGSTKFLT { SIGSTKFLT, "STKFLT" }, #endif #ifdef SIGCLD { SIGCLD, "CLD" }, #endif #ifdef SIGURG { SIGURG, "URG" }, #endif #ifdef SIGXCPU { SIGXCPU, "XCPU" }, #endif #ifdef SIGXFSZ { SIGXFSZ, "XFSZ" }, #endif #ifdef SIGVTALRM { SIGVTALRM, "VTALRM" }, #endif #ifdef SIGPROF { SIGPROF, "PROF" }, #endif #ifdef SIGWINCH { SIGWINCH, "WINCH" }, #endif #ifdef SIGIO { SIGIO, "IO" }, #endif #ifdef SIGPOLL { SIGPOLL, "POLL" }, #endif #ifdef SIGINFO { SIGINFO, "INFO" }, #endif #ifdef SIGLOST { SIGLOST, "LOST" }, #endif #ifdef SIGPWR { SIGPWR, "PWR" }, #endif #ifdef SIGUNUSED { SIGUNUSED, "UNUSED" }, #endif #ifdef SIGSYS { SIGSYS, "SYS" }, #endif }; static const size_t config_size = sizeof(config)/sizeof(struct lxc_config_t); extern struct lxc_config_t *lxc_getconfig(const char *key) { size_t i; for (i = 0; i < config_size; i++) if (!strncmp(config[i].name, key, strlen(config[i].name))) return &config[i]; return NULL; } #define strprint(str, inlen, ...) \ do { \ len = snprintf(str, inlen, ##__VA_ARGS__); \ if (len < 0) { SYSERROR("snprintf"); return -1; }; \ fulllen += len; \ if (inlen > 0) { \ if (str) str += len; \ inlen -= len; \ if (inlen < 0) inlen = 0; \ } \ } while (0); int lxc_listconfigs(char *retv, int inlen) { size_t i; int fulllen = 0, len; if (!retv) inlen = 0; else memset(retv, 0, inlen); for (i = 0; i < config_size; i++) { char *s = config[i].name; if (s[strlen(s)-1] == '.') continue; strprint(retv, inlen, "%s\n", s); } return fulllen; } static int config_string_item(char **conf_item, const char *value) { char *new_value; if (!value || strlen(value) == 0) { free(*conf_item); *conf_item = NULL; return 0; } new_value = strdup(value); if (!new_value) { SYSERROR("failed to strdup '%s': %m", value); return -1; } free(*conf_item); *conf_item = new_value; return 0; } static int config_string_item_max(char **conf_item, const char *value, size_t max) { if (strlen(value) >= max) { ERROR("%s is too long (>= %lu)", value, (unsigned long)max); return -1; } return config_string_item(conf_item, value); } static int config_path_item(char **conf_item, const char *value) { return config_string_item_max(conf_item, value, PATH_MAX); } /* * config entry is something like "lxc.network.0.ipv4" * the key 'lxc.network.' was found. So we make sure next * comes an integer, find the right callback (by rewriting * the key), and call it. */ static int config_network_nic(const char *key, const char *value, struct lxc_conf *lxc_conf) { char *copy = strdup(key), *p; int ret = -1; struct lxc_config_t *config; if (!copy) { SYSERROR("failed to allocate memory"); return -1; } /* * ok we know that to get here we've got "lxc.network." * and it isn't any of the other network entries. So * after the second . should come an integer (# of defined * nic) followed by a valid entry. */ if (*(key+12) < '0' || *(key+12) > '9') goto out; p = strchr(key+12, '.'); if (!p) goto out; strcpy(copy+12, p+1); config = lxc_getconfig(copy); if (!config) { ERROR("unknown key %s", key); goto out; } ret = config->cb(key, value, lxc_conf); out: free(copy); return ret; } static int config_network(const char *key, const char *value, struct lxc_conf *lxc_conf) { if (value && strlen(value)) { ERROR("lxc.network must not have a value"); return -1; } return lxc_clear_config_network(lxc_conf); } static int macvlan_mode(int *valuep, const char *value); static int config_network_type(const char *key, const char *value, struct lxc_conf *lxc_conf) { struct lxc_list *network = &lxc_conf->network; struct lxc_netdev *netdev; struct lxc_list *list; if (!value || strlen(value) == 0) return lxc_clear_config_network(lxc_conf); netdev = malloc(sizeof(*netdev)); if (!netdev) { SYSERROR("failed to allocate memory"); return -1; } memset(netdev, 0, sizeof(*netdev)); lxc_list_init(&netdev->ipv4); lxc_list_init(&netdev->ipv6); list = malloc(sizeof(*list)); if (!list) { SYSERROR("failed to allocate memory"); free(netdev); return -1; } lxc_list_init(list); list->elem = netdev; lxc_list_add_tail(network, list); if (!strcmp(value, "veth")) netdev->type = LXC_NET_VETH; else if (!strcmp(value, "macvlan")) { netdev->type = LXC_NET_MACVLAN; macvlan_mode(&netdev->priv.macvlan_attr.mode, "private"); } else if (!strcmp(value, "vlan")) netdev->type = LXC_NET_VLAN; else if (!strcmp(value, "phys")) netdev->type = LXC_NET_PHYS; else if (!strcmp(value, "empty")) netdev->type = LXC_NET_EMPTY; else if (!strcmp(value, "none")) netdev->type = LXC_NET_NONE; else { ERROR("invalid network type %s", value); return -1; } return 0; } static int config_ip_prefix(struct in_addr *addr) { if (IN_CLASSA(addr->s_addr)) return 32 - IN_CLASSA_NSHIFT; if (IN_CLASSB(addr->s_addr)) return 32 - IN_CLASSB_NSHIFT; if (IN_CLASSC(addr->s_addr)) return 32 - IN_CLASSC_NSHIFT; return 0; } /* * if you have p="lxc.network.0.link", pass it p+12 * to get back '0' (the index of the nic) */ static int get_network_netdev_idx(const char *key) { int ret, idx; if (*key < '0' || *key > '9') return -1; ret = sscanf(key, "%d", &idx); if (ret != 1) return -1; return idx; } /* * if you have p="lxc.network.0", pass this p+12 and it will return * the netdev of the first configured nic */ static struct lxc_netdev *get_netdev_from_key(const char *key, struct lxc_list *network) { int i = 0, idx = get_network_netdev_idx(key); struct lxc_netdev *netdev = NULL; struct lxc_list *it; if (idx == -1) return NULL; lxc_list_for_each(it, network) { if (idx == i++) { netdev = it->elem; break; } } return netdev; } extern int lxc_list_nicconfigs(struct lxc_conf *c, const char *key, char *retv, int inlen) { struct lxc_netdev *netdev; int fulllen = 0, len; netdev = get_netdev_from_key(key+12, &c->network); if (!netdev) return -1; if (!retv) inlen = 0; else memset(retv, 0, inlen); strprint(retv, inlen, "type\n"); strprint(retv, inlen, "script.up\n"); strprint(retv, inlen, "script.down\n"); if (netdev->type != LXC_NET_EMPTY) { strprint(retv, inlen, "flags\n"); strprint(retv, inlen, "link\n"); strprint(retv, inlen, "name\n"); strprint(retv, inlen, "hwaddr\n"); strprint(retv, inlen, "mtu\n"); strprint(retv, inlen, "ipv6\n"); strprint(retv, inlen, "ipv6.gateway\n"); strprint(retv, inlen, "ipv4\n"); strprint(retv, inlen, "ipv4.gateway\n"); } switch(netdev->type) { case LXC_NET_VETH: strprint(retv, inlen, "veth.pair\n"); break; case LXC_NET_MACVLAN: strprint(retv, inlen, "macvlan.mode\n"); break; case LXC_NET_VLAN: strprint(retv, inlen, "vlan.id\n"); break; case LXC_NET_PHYS: break; } return fulllen; } static struct lxc_netdev *network_netdev(const char *key, const char *value, struct lxc_list *network) { struct lxc_netdev *netdev = NULL; if (lxc_list_empty(network)) { ERROR("network is not created for '%s' = '%s' option", key, value); return NULL; } if (get_network_netdev_idx(key+12) == -1) netdev = lxc_list_last_elem(network); else netdev = get_netdev_from_key(key+12, network); if (!netdev) { ERROR("no network device defined for '%s' = '%s' option", key, value); return NULL; } return netdev; } static int network_ifname(char **valuep, const char *value) { return config_string_item_max(valuep, value, IFNAMSIZ); } #ifndef MACVLAN_MODE_PRIVATE # define MACVLAN_MODE_PRIVATE 1 #endif #ifndef MACVLAN_MODE_VEPA # define MACVLAN_MODE_VEPA 2 #endif #ifndef MACVLAN_MODE_BRIDGE # define MACVLAN_MODE_BRIDGE 4 #endif #ifndef MACVLAN_MODE_PASSTHRU # define MACVLAN_MODE_PASSTHRU 8 #endif static int macvlan_mode(int *valuep, const char *value) { struct mc_mode { char *name; int mode; } m[] = { { "private", MACVLAN_MODE_PRIVATE }, { "vepa", MACVLAN_MODE_VEPA }, { "bridge", MACVLAN_MODE_BRIDGE }, { "passthru", MACVLAN_MODE_PASSTHRU }, }; size_t i; for (i = 0; i < sizeof(m)/sizeof(m[0]); i++) { if (strcmp(m[i].name, value)) continue; *valuep = m[i].mode; return 0; } return -1; } static int rand_complete_hwaddr(char *hwaddr) { const char hex[] = "0123456789abcdef"; char *curs = hwaddr; #ifndef HAVE_RAND_R randseed(true); #else unsigned int seed=randseed(false); #endif while (*curs != '\0' && *curs != '\n') { if ( *curs == 'x' || *curs == 'X' ) { if (curs - hwaddr == 1) { //ensure address is unicast #ifdef HAVE_RAND_R *curs = hex[rand_r(&seed) & 0x0E]; } else { *curs = hex[rand_r(&seed) & 0x0F]; #else *curs = hex[rand() & 0x0E]; } else { *curs = hex[rand() & 0x0F]; #endif } } curs++; } return 0; } static int config_network_flags(const char *key, const char *value, struct lxc_conf *lxc_conf) { struct lxc_netdev *netdev; netdev = network_netdev(key, value, &lxc_conf->network); if (!netdev) return -1; netdev->flags |= IFF_UP; return 0; } static int config_network_link(const char *key, const char *value, struct lxc_conf *lxc_conf) { struct lxc_netdev *netdev; netdev = network_netdev(key, value, &lxc_conf->network); if (!netdev) return -1; return network_ifname(&netdev->link, value); } static int config_network_name(const char *key, const char *value, struct lxc_conf *lxc_conf) { struct lxc_netdev *netdev; netdev = network_netdev(key, value, &lxc_conf->network); if (!netdev) return -1; return network_ifname(&netdev->name, value); } static int config_network_veth_pair(const char *key, const char *value, struct lxc_conf *lxc_conf) { struct lxc_netdev *netdev; netdev = network_netdev(key, value, &lxc_conf->network); if (!netdev) return -1; if (netdev->type != LXC_NET_VETH) { ERROR("Invalid veth pair for a non-veth netdev"); return -1; } return network_ifname(&netdev->priv.veth_attr.pair, value); } static int config_network_macvlan_mode(const char *key, const char *value, struct lxc_conf *lxc_conf) { struct lxc_netdev *netdev; netdev = network_netdev(key, value, &lxc_conf->network); if (!netdev) return -1; if (netdev->type != LXC_NET_MACVLAN) { ERROR("Invalid macvlan.mode for a non-macvlan netdev"); return -1; } return macvlan_mode(&netdev->priv.macvlan_attr.mode, value); } static int config_network_hwaddr(const char *key, const char *value, struct lxc_conf *lxc_conf) { struct lxc_netdev *netdev; char *new_value = strdup(value); if (!new_value) { SYSERROR("failed to strdup '%s': %m", value); return -1; } rand_complete_hwaddr(new_value); netdev = network_netdev(key, new_value, &lxc_conf->network); if (!netdev) { free(new_value); return -1; }; if (!new_value || strlen(new_value) == 0) { free(new_value); netdev->hwaddr = NULL; return 0; } netdev->hwaddr = new_value; return 0; } static int config_network_vlan_id(const char *key, const char *value, struct lxc_conf *lxc_conf) { struct lxc_netdev *netdev; netdev = network_netdev(key, value, &lxc_conf->network); if (!netdev) return -1; if (netdev->type != LXC_NET_VLAN) { ERROR("Invalid vlan.id for a non-macvlan netdev"); return -1; } if (get_u16(&netdev->priv.vlan_attr.vid, value, 0)) return -1; return 0; } static int config_network_mtu(const char *key, const char *value, struct lxc_conf *lxc_conf) { struct lxc_netdev *netdev; netdev = network_netdev(key, value, &lxc_conf->network); if (!netdev) return -1; return config_string_item(&netdev->mtu, value); } static int config_network_ipv4(const char *key, const char *value, struct lxc_conf *lxc_conf) { struct lxc_netdev *netdev; struct lxc_inetdev *inetdev; struct lxc_list *list; char *cursor, *slash, *addr = NULL, *bcast = NULL, *prefix = NULL; if (!value || !strlen(value)) return lxc_clear_config_item(lxc_conf, key); netdev = network_netdev(key, value, &lxc_conf->network); if (!netdev) return -1; inetdev = malloc(sizeof(*inetdev)); if (!inetdev) { SYSERROR("failed to allocate ipv4 address"); return -1; } memset(inetdev, 0, sizeof(*inetdev)); list = malloc(sizeof(*list)); if (!list) { SYSERROR("failed to allocate memory"); free(inetdev); return -1; } lxc_list_init(list); list->elem = inetdev; addr = strdup(value); if (!addr) { ERROR("no address specified"); free(inetdev); free(list); return -1; } cursor = strstr(addr, " "); if (cursor) { *cursor = '\0'; bcast = cursor + 1; } slash = strstr(addr, "/"); if (slash) { *slash = '\0'; prefix = slash + 1; } if (!inet_pton(AF_INET, addr, &inetdev->addr)) { SYSERROR("invalid ipv4 address: %s", value); free(inetdev); free(addr); free(list); return -1; } if (bcast && !inet_pton(AF_INET, bcast, &inetdev->bcast)) { SYSERROR("invalid ipv4 broadcast address: %s", value); free(inetdev); free(list); free(addr); return -1; } /* no prefix specified, determine it from the network class */ if (prefix) { if (lxc_safe_uint(prefix, &inetdev->prefix) < 0) return -1; } else { inetdev->prefix = config_ip_prefix(&inetdev->addr); } /* if no broadcast address, let compute one from the * prefix and address */ if (!bcast) { inetdev->bcast.s_addr = inetdev->addr.s_addr; inetdev->bcast.s_addr |= htonl(INADDR_BROADCAST >> inetdev->prefix); } lxc_list_add_tail(&netdev->ipv4, list); free(addr); return 0; } static int config_network_ipv4_gateway(const char *key, const char *value, struct lxc_conf *lxc_conf) { struct lxc_netdev *netdev; netdev = network_netdev(key, value, &lxc_conf->network); if (!netdev) return -1; free(netdev->ipv4_gateway); if (!value || strlen(value) == 0) { netdev->ipv4_gateway = NULL; } else if (!strcmp(value, "auto")) { netdev->ipv4_gateway = NULL; netdev->ipv4_gateway_auto = true; } else { struct in_addr *gw; gw = malloc(sizeof(*gw)); if (!gw) { SYSERROR("failed to allocate ipv4 gateway address"); return -1; } if (!inet_pton(AF_INET, value, gw)) { SYSERROR("invalid ipv4 gateway address: %s", value); free(gw); return -1; } netdev->ipv4_gateway = gw; netdev->ipv4_gateway_auto = false; } return 0; } static int config_network_ipv6(const char *key, const char *value, struct lxc_conf *lxc_conf) { struct lxc_netdev *netdev; struct lxc_inet6dev *inet6dev; struct lxc_list *list; char *slash,*valdup; char *netmask; if (!value || !strlen(value)) return lxc_clear_config_item(lxc_conf, key); netdev = network_netdev(key, value, &lxc_conf->network); if (!netdev) return -1; inet6dev = malloc(sizeof(*inet6dev)); if (!inet6dev) { SYSERROR("failed to allocate ipv6 address"); return -1; } memset(inet6dev, 0, sizeof(*inet6dev)); list = malloc(sizeof(*list)); if (!list) { SYSERROR("failed to allocate memory"); free(inet6dev); return -1; } lxc_list_init(list); list->elem = inet6dev; valdup = strdup(value); if (!valdup) { ERROR("no address specified"); free(list); free(inet6dev); return -1; } inet6dev->prefix = 64; slash = strstr(valdup, "/"); if (slash) { *slash = '\0'; netmask = slash + 1; if (lxc_safe_uint(netmask, &inet6dev->prefix) < 0) return -1; } if (!inet_pton(AF_INET6, valdup, &inet6dev->addr)) { SYSERROR("invalid ipv6 address: %s", valdup); free(list); free(inet6dev); free(valdup); return -1; } lxc_list_add_tail(&netdev->ipv6, list); free(valdup); return 0; } static int config_network_ipv6_gateway(const char *key, const char *value, struct lxc_conf *lxc_conf) { struct lxc_netdev *netdev; netdev = network_netdev(key, value, &lxc_conf->network); if (!netdev) return -1; free(netdev->ipv6_gateway); if (!value || strlen(value) == 0) { netdev->ipv6_gateway = NULL; } else if (!strcmp(value, "auto")) { netdev->ipv6_gateway = NULL; netdev->ipv6_gateway_auto = true; } else { struct in6_addr *gw; gw = malloc(sizeof(*gw)); if (!gw) { SYSERROR("failed to allocate ipv6 gateway address"); return -1; } if (!inet_pton(AF_INET6, value, gw)) { SYSERROR("invalid ipv6 gateway address: %s", value); free(gw); return -1; } netdev->ipv6_gateway = gw; netdev->ipv6_gateway_auto = false; } return 0; } static int config_network_script_up(const char *key, const char *value, struct lxc_conf *lxc_conf) { struct lxc_netdev *netdev; netdev = network_netdev(key, value, &lxc_conf->network); if (!netdev) return -1; return config_string_item(&netdev->upscript, value); } static int config_network_script_down(const char *key, const char *value, struct lxc_conf *lxc_conf) { struct lxc_netdev *netdev; netdev = network_netdev(key, value, &lxc_conf->network); if (!netdev) return -1; return config_string_item(&netdev->downscript, value); } static int add_hook(struct lxc_conf *lxc_conf, int which, char *hook) { struct lxc_list *hooklist; hooklist = malloc(sizeof(*hooklist)); if (!hooklist) { free(hook); return -1; } hooklist->elem = hook; lxc_list_add_tail(&lxc_conf->hooks[which], hooklist); return 0; } static int config_seccomp(const char *key, const char *value, struct lxc_conf *lxc_conf) { return config_path_item(&lxc_conf->seccomp, value); } static int config_init_cmd(const char *key, const char *value, struct lxc_conf *lxc_conf) { return config_path_item(&lxc_conf->init_cmd, value); } static int config_init_uid(const char *key, const char *value, struct lxc_conf *lxc_conf) { unsigned int init_uid; if (lxc_safe_uint(value, &init_uid) < 0) return -1; lxc_conf->init_uid = init_uid; return 0; } static int config_init_gid(const char *key, const char *value, struct lxc_conf *lxc_conf) { unsigned int init_gid; if (lxc_safe_uint(value, &init_gid) < 0) return -1; lxc_conf->init_gid = init_gid; return 0; } static int config_hook(const char *key, const char *value, struct lxc_conf *lxc_conf) { char *copy; if (!value || strlen(value) == 0) return lxc_clear_hooks(lxc_conf, key); if (strcmp(key, "lxc.hook") == 0) { ERROR("lxc.hook cannot take a value"); return -1; } copy = strdup(value); if (!copy) { SYSERROR("failed to dup string '%s'", value); return -1; } if (strcmp(key, "lxc.hook.pre-start") == 0) return add_hook(lxc_conf, LXCHOOK_PRESTART, copy); else if (strcmp(key, "lxc.hook.pre-mount") == 0) return add_hook(lxc_conf, LXCHOOK_PREMOUNT, copy); else if (strcmp(key, "lxc.hook.autodev") == 0) return add_hook(lxc_conf, LXCHOOK_AUTODEV, copy); else if (strcmp(key, "lxc.hook.mount") == 0) return add_hook(lxc_conf, LXCHOOK_MOUNT, copy); else if (strcmp(key, "lxc.hook.start") == 0) return add_hook(lxc_conf, LXCHOOK_START, copy); else if (strcmp(key, "lxc.hook.stop") == 0) return add_hook(lxc_conf, LXCHOOK_STOP, copy); else if (strcmp(key, "lxc.hook.post-stop") == 0) return add_hook(lxc_conf, LXCHOOK_POSTSTOP, copy); else if (strcmp(key, "lxc.hook.clone") == 0) return add_hook(lxc_conf, LXCHOOK_CLONE, copy); else if (strcmp(key, "lxc.hook.destroy") == 0) return add_hook(lxc_conf, LXCHOOK_DESTROY, copy); SYSERROR("Unknown key: %s", key); free(copy); return -1; } static int config_personality(const char *key, const char *value, struct lxc_conf *lxc_conf) { signed long personality = lxc_config_parse_arch(value); if (personality >= 0) lxc_conf->personality = personality; else WARN("unsupported personality '%s'", value); return 0; } static int config_pts(const char *key, const char *value, struct lxc_conf *lxc_conf) { if (lxc_safe_uint(value, &lxc_conf->pts) < 0) return -1; return 0; } static int config_start(const char *key, const char *value, struct lxc_conf *lxc_conf) { if(strcmp(key, "lxc.start.auto") == 0) { if (lxc_safe_uint(value, &lxc_conf->start_auto) < 0) return -1; if (lxc_conf->start_auto > 1) return -1; return 0; } else if (strcmp(key, "lxc.start.delay") == 0) { if (lxc_safe_uint(value, &lxc_conf->start_delay) < 0) return -1; return 0; } else if (strcmp(key, "lxc.start.order") == 0) { if (lxc_safe_int(value, &lxc_conf->start_order) < 0) return -1; return 0; } SYSERROR("Unknown key: %s", key); return -1; } static int config_monitor(const char *key, const char *value, struct lxc_conf *lxc_conf) { if(strcmp(key, "lxc.monitor.unshare") == 0) { if (lxc_safe_uint(value, &lxc_conf->monitor_unshare) < 0) return -1; return 0; } SYSERROR("Unknown key: %s", key); return -1; } static int config_group(const char *key, const char *value, struct lxc_conf *lxc_conf) { char *groups, *groupptr, *sptr, *token; struct lxc_list *grouplist; int ret = -1; if (!strlen(value)) return lxc_clear_groups(lxc_conf); groups = strdup(value); if (!groups) { SYSERROR("failed to dup '%s'", value); return -1; } /* in case several groups are specified in a single line * split these groups in a single element for the list */ for (groupptr = groups;;groupptr = NULL) { token = strtok_r(groupptr, " \t", &sptr); if (!token) { ret = 0; break; } grouplist = malloc(sizeof(*grouplist)); if (!grouplist) { SYSERROR("failed to allocate groups list"); break; } grouplist->elem = strdup(token); if (!grouplist->elem) { SYSERROR("failed to dup '%s'", token); free(grouplist); break; } lxc_list_add_tail(&lxc_conf->groups, grouplist); } free(groups); return ret; } static int config_environment(const char *key, const char *value, struct lxc_conf *lxc_conf) { struct lxc_list *list_item = NULL; if (!strlen(value)) return lxc_clear_environment(lxc_conf); list_item = malloc(sizeof(*list_item)); if (!list_item) goto freak_out; list_item->elem = strdup(value); if (!list_item->elem) goto freak_out; lxc_list_add_tail(&lxc_conf->environment, list_item); return 0; freak_out: free(list_item); return -1; } static int config_tty(const char *key, const char *value, struct lxc_conf *lxc_conf) { if (lxc_safe_uint(value, &lxc_conf->tty) < 0) return -1; return 0; } static int config_ttydir(const char *key, const char *value, struct lxc_conf *lxc_conf) { return config_string_item_max(&lxc_conf->ttydir, value, NAME_MAX+1); } static int config_kmsg(const char *key, const char *value, struct lxc_conf *lxc_conf) { if (lxc_safe_uint(value, &lxc_conf->kmsg) < 0) return -1; if (lxc_conf->kmsg > 1) return -1; return 0; } static int config_lsm_aa_profile(const char *key, const char *value, struct lxc_conf *lxc_conf) { return config_string_item(&lxc_conf->lsm_aa_profile, value); } static int config_lsm_aa_incomplete(const char *key, const char *value, struct lxc_conf *lxc_conf) { if (lxc_safe_uint(value, &lxc_conf->lsm_aa_allow_incomplete) < 0) return -1; if (lxc_conf->lsm_aa_allow_incomplete > 1) { ERROR("Wrong value for lxc.lsm_aa_allow_incomplete. Can only be set to 0 or 1"); return -1; } return 0; } static int config_lsm_se_context(const char *key, const char *value, struct lxc_conf *lxc_conf) { return config_string_item(&lxc_conf->lsm_se_context, value); } static int config_logfile(const char *key, const char *value, 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(&c->logfile, value); if (ret == 0) ret = lxc_log_set_file(&c->logfd, c->logfile); return ret; } static int config_loglevel(const char *key, const char *value, struct lxc_conf *lxc_conf) { int newlevel; if (!value || strlen(value) == 0) return 0; if (value[0] >= '0' && value[0] <= '9') { if (lxc_safe_int(value, &newlevel) < 0) return -1; } else { newlevel = lxc_log_priority_to_int(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(&lxc_conf->loglevel, newlevel); } static int config_autodev(const char *key, const char *value, struct lxc_conf *lxc_conf) { if (lxc_safe_uint(value, &lxc_conf->autodev) < 0) return -1; if (lxc_conf->autodev > 1) { ERROR("Wrong value for lxc.autodev. Can only be set to 0 or 1"); return -1; } return 0; } static int sig_num(const char *sig) { int n; char *endp = NULL; errno = 0; n = strtol(sig, &endp, 10); if (sig == endp || n < 0 || errno != 0) return -1; return n; } static int rt_sig_num(const char *signame) { int sig_n = 0; int rtmax = 0; if (strncasecmp(signame, "max-", 4) == 0) { rtmax = 1; } signame += 4; if (!isdigit(*signame)) return -1; sig_n = sig_num(signame); sig_n = rtmax ? SIGRTMAX - sig_n : SIGRTMIN + sig_n; if (sig_n > SIGRTMAX || sig_n < SIGRTMIN) return -1; return sig_n; } static int sig_parse(const char *signame) { size_t n; if (isdigit(*signame)) { return sig_num(signame); } else if (strncasecmp(signame, "sig", 3) == 0) { signame += 3; if (strncasecmp(signame, "rt", 2) == 0) return rt_sig_num(signame + 2); for (n = 0; n < sizeof(signames) / sizeof((signames)[0]); n++) { if (strcasecmp (signames[n].name, signame) == 0) return signames[n].num; } } return -1; } static int config_haltsignal(const char *key, const char *value, struct lxc_conf *lxc_conf) { int sig_n = sig_parse(value); if (sig_n < 0) return -1; lxc_conf->haltsignal = sig_n; return 0; } static int config_rebootsignal(const char *key, const char *value, struct lxc_conf *lxc_conf) { int sig_n = sig_parse(value); if (sig_n < 0) return -1; lxc_conf->rebootsignal = sig_n; return 0; } static int config_stopsignal(const char *key, const char *value, struct lxc_conf *lxc_conf) { int sig_n = sig_parse(value); if (sig_n < 0) return -1; lxc_conf->stopsignal = sig_n; return 0; } static int config_cgroup(const char *key, const char *value, struct lxc_conf *lxc_conf) { char *token = "lxc.cgroup."; char *subkey; struct lxc_list *cglist = NULL; struct lxc_cgroup *cgelem = NULL; if (!value || strlen(value) == 0) return lxc_clear_cgroups(lxc_conf, key); subkey = strstr(key, token); if (!subkey) return -1; if (!strlen(subkey)) return -1; if (strlen(subkey) == strlen(token)) return -1; subkey += strlen(token); cglist = malloc(sizeof(*cglist)); if (!cglist) goto out; cgelem = malloc(sizeof(*cgelem)); if (!cgelem) goto out; memset(cgelem, 0, sizeof(*cgelem)); cgelem->subsystem = strdup(subkey); cgelem->value = strdup(value); if (!cgelem->subsystem || !cgelem->value) goto out; cglist->elem = cgelem; lxc_list_add_tail(&lxc_conf->cgroup, cglist); return 0; out: free(cglist); if (cgelem) { free(cgelem->subsystem); free(cgelem->value); free(cgelem); } return -1; } static int config_idmap(const char *key, const char *value, struct lxc_conf *lxc_conf) { char *token = "lxc.id_map"; char *subkey; struct lxc_list *idmaplist = NULL; struct id_map *idmap = NULL; unsigned long hostid, nsid, range; char type; int ret; if (!value || strlen(value) == 0) return lxc_clear_idmaps(lxc_conf); subkey = strstr(key, token); if (!subkey) return -1; if (!strlen(subkey)) return -1; idmaplist = malloc(sizeof(*idmaplist)); if (!idmaplist) goto out; idmap = malloc(sizeof(*idmap)); if (!idmap) goto out; memset(idmap, 0, sizeof(*idmap)); ret = sscanf(value, "%c %lu %lu %lu", &type, &nsid, &hostid, &range); if (ret != 4) goto out; INFO("read uid map: type %c nsid %lu hostid %lu range %lu", type, nsid, hostid, range); if (type == 'u') idmap->idtype = ID_TYPE_UID; else if (type == 'g') idmap->idtype = ID_TYPE_GID; else goto out; idmap->hostid = hostid; idmap->nsid = nsid; idmap->range = range; idmaplist->elem = idmap; lxc_list_add_tail(&lxc_conf->id_map, idmaplist); return 0; out: free(idmaplist); if (idmap) { free(idmap); } return -1; } static int config_fstab(const char *key, const char *value, struct lxc_conf *lxc_conf) { if (!value || strlen(value) == 0) return -1; return config_path_item(&lxc_conf->fstab, value); } static int config_mount_auto(const char *key, const char *value, struct lxc_conf *lxc_conf) { char *autos, *autoptr, *sptr, *token; static struct { const char *token; int mask; int flag; } allowed_auto_mounts[] = { { "proc", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED }, { "proc:mixed", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_MIXED }, { "proc:rw", LXC_AUTO_PROC_MASK, LXC_AUTO_PROC_RW }, { "sys", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED }, { "sys:ro", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RO }, { "sys:mixed", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_MIXED }, { "sys:rw", LXC_AUTO_SYS_MASK, LXC_AUTO_SYS_RW }, { "cgroup", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_NOSPEC }, { "cgroup:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_MIXED }, { "cgroup:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RO }, { "cgroup:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_RW }, { "cgroup-full", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_NOSPEC }, { "cgroup-full:mixed", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_MIXED }, { "cgroup-full:ro", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RO }, { "cgroup-full:rw", LXC_AUTO_CGROUP_MASK, LXC_AUTO_CGROUP_FULL_RW }, /* NB: For adding anything that is just a single on/off, but has * no options: keep mask and flag identical and just define the * enum value as an unused bit so far */ { NULL, 0 } }; int i; int ret = -1; if (!value || strlen(value) == 0) { lxc_conf->auto_mounts = 0; return 0; } autos = strdup(value); if (!autos) { SYSERROR("failed to dup '%s'", value); return -1; } for (autoptr = autos; ; autoptr = NULL) { token = strtok_r(autoptr, " \t", &sptr); if (!token) { ret = 0; break; } for (i = 0; allowed_auto_mounts[i].token; i++) { if (!strcmp(allowed_auto_mounts[i].token, token)) break; } if (!allowed_auto_mounts[i].token) { ERROR("Invalid filesystem to automount: %s", token); break; } lxc_conf->auto_mounts &= ~allowed_auto_mounts[i].mask; lxc_conf->auto_mounts |= allowed_auto_mounts[i].flag; } free(autos); return ret; } static int config_mount(const char *key, const char *value, struct lxc_conf *lxc_conf) { char *mntelem; struct lxc_list *mntlist; if (!value || strlen(value) == 0) return lxc_clear_mount_entries(lxc_conf); mntlist = malloc(sizeof(*mntlist)); if (!mntlist) return -1; mntelem = strdup(value); if (!mntelem) { free(mntlist); return -1; } mntlist->elem = mntelem; lxc_list_add_tail(&lxc_conf->mount_list, mntlist); return 0; } static int config_cap_keep(const char *key, const char *value, struct lxc_conf *lxc_conf) { char *keepcaps, *keepptr, *sptr, *token; struct lxc_list *keeplist; int ret = -1; if (!strlen(value)) return lxc_clear_config_keepcaps(lxc_conf); keepcaps = strdup(value); if (!keepcaps) { SYSERROR("failed to dup '%s'", value); return -1; } /* in case several capability keep is specified in a single line * split these caps in a single element for the list */ for (keepptr = keepcaps;;keepptr = NULL) { token = strtok_r(keepptr, " \t", &sptr); if (!token) { ret = 0; break; } if (!strcmp(token, "none")) lxc_clear_config_keepcaps(lxc_conf); keeplist = malloc(sizeof(*keeplist)); if (!keeplist) { SYSERROR("failed to allocate keepcap list"); break; } keeplist->elem = strdup(token); if (!keeplist->elem) { SYSERROR("failed to dup '%s'", token); free(keeplist); break; } lxc_list_add_tail(&lxc_conf->keepcaps, keeplist); } free(keepcaps); return ret; } static int config_cap_drop(const char *key, const char *value, struct lxc_conf *lxc_conf) { char *dropcaps, *dropptr, *sptr, *token; struct lxc_list *droplist; int ret = -1; if (!strlen(value)) return lxc_clear_config_caps(lxc_conf); dropcaps = strdup(value); if (!dropcaps) { SYSERROR("failed to dup '%s'", value); return -1; } /* in case several capability drop is specified in a single line * split these caps in a single element for the list */ for (dropptr = dropcaps;;dropptr = NULL) { token = strtok_r(dropptr, " \t", &sptr); if (!token) { ret = 0; break; } droplist = malloc(sizeof(*droplist)); if (!droplist) { SYSERROR("failed to allocate drop list"); break; } droplist->elem = strdup(token); if (!droplist->elem) { SYSERROR("failed to dup '%s'", token); free(droplist); break; } lxc_list_add_tail(&lxc_conf->caps, droplist); } free(dropcaps); return ret; } static int config_console(const char *key, const char *value, struct lxc_conf *lxc_conf) { return config_path_item(&lxc_conf->console.path, value); } static int config_console_logfile(const char *key, const char *value, struct lxc_conf *lxc_conf) { return config_path_item(&lxc_conf->console.log_path, value); } /* * If we find a lxc.network.hwaddr in the original config file, * we expand it in the unexpanded_config, so that after a save_config * we store the hwaddr for re-use. * This is only called when reading the config file, not when executing * a lxc.include. * 'x' and 'X' are substituted in-place. */ static void update_hwaddr(const char *line) { char *p; line += lxc_char_left_gc(line, strlen(line)); if (line[0] == '#') return; if (strncmp(line, "lxc.network.hwaddr", 18) != 0) return; p = strchr(line, '='); if (!p) return; // let config_network_hwaddr raise the error p++; while (isblank(*p)) p++; if (!*p) return; rand_complete_hwaddr(p); } int append_unexp_config_line(const char *line, struct lxc_conf *conf) { size_t len = conf->unexpanded_len, linelen = strlen(line); update_hwaddr(line); while (conf->unexpanded_alloced <= len + linelen + 2) { char *tmp = realloc(conf->unexpanded_config, conf->unexpanded_alloced + 1024); if (!tmp) return -1; if (!conf->unexpanded_config) *tmp = '\0'; conf->unexpanded_config = tmp; conf->unexpanded_alloced += 1024; } strcat(conf->unexpanded_config, line); conf->unexpanded_len += linelen; if (line[linelen-1] != '\n') { strcat(conf->unexpanded_config, "\n"); conf->unexpanded_len++; } return 0; } static int do_includedir(const char *dirp, struct lxc_conf *lxc_conf) { struct dirent *direntp; DIR *dir; char path[MAXPATHLEN]; int ret = -1, len; dir = opendir(dirp); if (!dir) { SYSERROR("failed to open '%s'", dirp); return -1; } while ((direntp = readdir(dir))) { const char *fnam; if (!direntp) break; fnam = direntp->d_name; if (!strcmp(fnam, ".")) continue; if (!strcmp(fnam, "..")) continue; len = strlen(fnam); if (len < 6 || strncmp(fnam+len-5, ".conf", 5) != 0) continue; len = snprintf(path, MAXPATHLEN, "%s/%s", dirp, fnam); if (len < 0 || len >= MAXPATHLEN) { ERROR("lxc.include filename too long under '%s'", dirp); ret = -1; goto out; } ret = lxc_config_read(path, lxc_conf, true); if (ret < 0) goto out; } ret = 0; out: if (closedir(dir)) WARN("lxc.include dir: failed to close directory"); return ret; } static int config_includefile(const char *key, const char *value, struct lxc_conf *lxc_conf) { if (is_dir(value)) return do_includedir(value, lxc_conf); return lxc_config_read(value, lxc_conf, true); } static int config_rootfs(const char *key, const char *value, struct lxc_conf *lxc_conf) { return config_path_item(&lxc_conf->rootfs.path, value); } static int config_rootfs_mount(const char *key, const char *value, struct lxc_conf *lxc_conf) { return config_path_item(&lxc_conf->rootfs.mount, value); } static int config_rootfs_options(const char *key, const char *value, struct lxc_conf *lxc_conf) { return config_string_item(&lxc_conf->rootfs.options, value); } static int config_rootfs_backend(const char *key, const char *value, struct lxc_conf *lxc_conf) { if (strlen(value) == 0) { free(lxc_conf->rootfs.bdev_type); lxc_conf->rootfs.bdev_type = NULL; } if (!is_valid_bdev_type(value)) { ERROR("Bad rootfs.backend: '%s'", value); return -1; } return config_string_item(&lxc_conf->rootfs.bdev_type, value); } static int config_pivotdir(const char *key, const char *value, struct lxc_conf *lxc_conf) { WARN("lxc.pivotdir is ignored. It will soon become an error."); return 0; } static int config_utsname(const char *key, const char *value, struct lxc_conf *lxc_conf) { struct utsname *utsname; utsname = malloc(sizeof(*utsname)); if (!utsname) { SYSERROR("failed to allocate memory"); return -1; } if (strlen(value) >= sizeof(utsname->nodename)) { ERROR("node name '%s' is too long", value); free(utsname); return -1; } strcpy(utsname->nodename, value); free(lxc_conf->utsname); lxc_conf->utsname = utsname; return 0; } struct parse_line_conf { struct lxc_conf *conf; bool from_include; }; static int parse_line(char *buffer, void *data) { struct lxc_config_t *config; char *line, *linep; char *dot; char *key; char *value; int ret = 0; struct parse_line_conf *plc = data; if (lxc_is_line_empty(buffer)) return 0; /* we have to dup the buffer otherwise, at the re-exec for * reboot we modified the original string on the stack by * replacing '=' by '\0' below */ linep = line = strdup(buffer); if (!line) { SYSERROR("failed to allocate memory for '%s'", buffer); return -1; } if (!plc->from_include) if ((ret = append_unexp_config_line(line, plc->conf))) goto out; line += lxc_char_left_gc(line, strlen(line)); /* ignore comments */ if (line[0] == '#') goto out; /* martian option - don't add it to the config itself */ if (strncmp(line, "lxc.", 4)) goto out; ret = -1; dot = strstr(line, "="); if (!dot) { ERROR("invalid configuration line: %s", line); goto out; } *dot = '\0'; value = dot + 1; key = line; key[lxc_char_right_gc(key, strlen(key))] = '\0'; value += lxc_char_left_gc(value, strlen(value)); value[lxc_char_right_gc(value, strlen(value))] = '\0'; if (*value == '\'' || *value == '\"') { size_t len = strlen(value); if (len > 1 && value[len-1] == *value) { value[len-1] = '\0'; value++; } } config = lxc_getconfig(key); if (!config) { ERROR("unknown key %s", key); goto out; } ret = config->cb(key, value, plc->conf); out: free(linep); return ret; } static int lxc_config_readline(char *buffer, struct lxc_conf *conf) { struct parse_line_conf c; c.conf = conf; c.from_include = false; return parse_line(buffer, &c); } int lxc_config_read(const char *file, struct lxc_conf *conf, bool from_include) { struct parse_line_conf c; c.conf = conf; c.from_include = from_include; if( access(file, R_OK) == -1 ) { return -1; } /* Catch only the top level config file name in the structure */ if( ! conf->rcfile ) conf->rcfile = strdup( file ); return lxc_file_for_each_line(file, parse_line, &c); } int lxc_config_define_add(struct lxc_list *defines, char* arg) { struct lxc_list *dent; dent = malloc(sizeof(struct lxc_list)); if (!dent) return -1; dent->elem = arg; lxc_list_add_tail(defines, dent); return 0; } int lxc_config_define_load(struct lxc_list *defines, struct lxc_conf *conf) { struct lxc_list *it,*next; int ret = 0; lxc_list_for_each(it, defines) { ret = lxc_config_readline(it->elem, conf); if (ret) break; } lxc_list_for_each_safe(it, defines, next) { lxc_list_del(it); free(it); } return ret; } signed long lxc_config_parse_arch(const char *arch) { #if HAVE_SYS_PERSONALITY_H struct per_name { char *name; unsigned long per; } pername[] = { { "x86", PER_LINUX32 }, { "linux32", PER_LINUX32 }, { "i386", PER_LINUX32 }, { "i486", PER_LINUX32 }, { "i586", PER_LINUX32 }, { "i686", PER_LINUX32 }, { "athlon", PER_LINUX32 }, { "mips", PER_LINUX32 }, { "mipsel", PER_LINUX32 }, { "ppc", PER_LINUX32 }, { "arm", PER_LINUX32 }, { "armv7l", PER_LINUX32 }, { "armhf", PER_LINUX32 }, { "armel", PER_LINUX32 }, { "powerpc", PER_LINUX32 }, { "linux64", PER_LINUX }, { "x86_64", PER_LINUX }, { "amd64", PER_LINUX }, { "mips64", PER_LINUX }, { "mips64el", PER_LINUX }, { "ppc64", PER_LINUX }, { "ppc64le", PER_LINUX }, { "ppc64el", PER_LINUX }, { "powerpc64", PER_LINUX }, { "s390x", PER_LINUX }, { "aarch64", PER_LINUX }, { "arm64", PER_LINUX }, }; size_t len = sizeof(pername) / sizeof(pername[0]); size_t i; for (i = 0; i < len; i++) { if (!strcmp(pername[i].name, arch)) return pername[i].per; } #endif return -1; } int lxc_fill_elevated_privileges(char *flaglist, int *flags) { char *token, *saveptr = NULL; int i, aflag; struct { const char *token; int flag; } all_privs[] = { { "CGROUP", LXC_ATTACH_MOVE_TO_CGROUP }, { "CAP", LXC_ATTACH_DROP_CAPABILITIES }, { "LSM", LXC_ATTACH_LSM_EXEC }, { NULL, 0 } }; if (!flaglist) { /* for the sake of backward compatibility, drop all privileges if none is specified */ for (i = 0; all_privs[i].token; i++) { *flags |= all_privs[i].flag; } return 0; } token = strtok_r(flaglist, "|", &saveptr); while (token) { aflag = -1; for (i = 0; all_privs[i].token; i++) { if (!strcmp(all_privs[i].token, token)) aflag = all_privs[i].flag; } if (aflag < 0) return -1; *flags |= aflag; token = strtok_r(NULL, "|", &saveptr); } return 0; } static int lxc_get_conf_int(struct lxc_conf *c, char *retv, int inlen, int v) { if (!retv) inlen = 0; else memset(retv, 0, inlen); return snprintf(retv, inlen, "%d", v); } static int lxc_get_arch_entry(struct lxc_conf *c, char *retv, int inlen) { int fulllen = 0; if (!retv) inlen = 0; else memset(retv, 0, inlen); #if HAVE_SYS_PERSONALITY_H int len = 0; switch(c->personality) { case PER_LINUX32: strprint(retv, inlen, "i686"); break; case PER_LINUX: strprint(retv, inlen, "x86_64"); break; default: break; } #endif return fulllen; } /* * If you ask for a specific cgroup value, i.e. lxc.cgroup.devices.list, * then just the value(s) will be printed. Since there still could be * more than one, it is newline-separated. * (Maybe that's ambigous, since some values, i.e. devices.list, will * already have newlines?) * If you ask for 'lxc.cgroup", then all cgroup entries will be printed, * in 'lxc.cgroup.subsystem.key = value' format. */ static int lxc_get_cgroup_entry(struct lxc_conf *c, char *retv, int inlen, const char *key) { int fulllen = 0, len; int all = 0; struct lxc_list *it; if (!retv) inlen = 0; else memset(retv, 0, inlen); if (strcmp(key, "all") == 0) all = 1; lxc_list_for_each(it, &c->cgroup) { struct lxc_cgroup *cg = it->elem; if (all) { strprint(retv, inlen, "lxc.cgroup.%s = %s\n", cg->subsystem, cg->value); } else if (strcmp(cg->subsystem, key) == 0) { strprint(retv, inlen, "%s\n", cg->value); } } return fulllen; } static int lxc_get_item_hooks(struct lxc_conf *c, char *retv, int inlen, const char *key) { char *subkey; int len, fulllen = 0, found = -1; struct lxc_list *it; int i; /* "lxc.hook.mount" */ subkey = strchr(key, '.'); if (subkey) subkey = strchr(subkey+1, '.'); if (!subkey) return -1; subkey++; if (!*subkey) return -1; for (i=0; ihooks[found]) { strprint(retv, inlen, "%s\n", (char *)it->elem); } return fulllen; } static int lxc_get_item_groups(struct lxc_conf *c, char *retv, int inlen) { int len, fulllen = 0; struct lxc_list *it; if (!retv) inlen = 0; else memset(retv, 0, inlen); lxc_list_for_each(it, &c->groups) { strprint(retv, inlen, "%s\n", (char *)it->elem); } return fulllen; } static int lxc_get_item_environment(struct lxc_conf *c, char *retv, int inlen) { int len, fulllen = 0; struct lxc_list *it; if (!retv) inlen = 0; else memset(retv, 0, inlen); lxc_list_for_each(it, &c->environment) { strprint(retv, inlen, "%s\n", (char *)it->elem); } return fulllen; } static int lxc_get_item_cap_drop(struct lxc_conf *c, char *retv, int inlen) { int len, fulllen = 0; struct lxc_list *it; if (!retv) inlen = 0; else memset(retv, 0, inlen); lxc_list_for_each(it, &c->caps) { strprint(retv, inlen, "%s\n", (char *)it->elem); } return fulllen; } static int lxc_get_item_cap_keep(struct lxc_conf *c, char *retv, int inlen) { int len, fulllen = 0; struct lxc_list *it; if (!retv) inlen = 0; else memset(retv, 0, inlen); lxc_list_for_each(it, &c->keepcaps) { strprint(retv, inlen, "%s\n", (char *)it->elem); } return fulllen; } static int lxc_get_mount_entries(struct lxc_conf *c, char *retv, int inlen) { int len, fulllen = 0; struct lxc_list *it; if (!retv) inlen = 0; else memset(retv, 0, inlen); lxc_list_for_each(it, &c->mount_list) { strprint(retv, inlen, "%s\n", (char *)it->elem); } return fulllen; } static int lxc_get_auto_mounts(struct lxc_conf *c, char *retv, int inlen) { int len, fulllen = 0; const char *sep = ""; if (!retv) inlen = 0; else memset(retv, 0, inlen); if (!(c->auto_mounts & LXC_AUTO_ALL_MASK)) return 0; switch (c->auto_mounts & LXC_AUTO_PROC_MASK) { case LXC_AUTO_PROC_MIXED: strprint(retv, inlen, "%sproc:mixed", sep); sep = " "; break; case LXC_AUTO_PROC_RW: strprint(retv, inlen, "%sproc:rw", sep); sep = " "; break; default: break; } switch (c->auto_mounts & LXC_AUTO_SYS_MASK) { case LXC_AUTO_SYS_RO: strprint(retv, inlen, "%ssys:ro", sep); sep = " "; break; case LXC_AUTO_SYS_RW: strprint(retv, inlen, "%ssys:rw", sep); sep = " "; break; case LXC_AUTO_SYS_MIXED: strprint(retv, inlen, "%ssys:mixed", sep); sep = " "; break; default: break; } switch (c->auto_mounts & LXC_AUTO_CGROUP_MASK) { case LXC_AUTO_CGROUP_NOSPEC: strprint(retv, inlen, "%scgroup", sep); sep = " "; break; case LXC_AUTO_CGROUP_MIXED: strprint(retv, inlen, "%scgroup:mixed", sep); sep = " "; break; case LXC_AUTO_CGROUP_RO: strprint(retv, inlen, "%scgroup:ro", sep); sep = " "; break; case LXC_AUTO_CGROUP_RW: strprint(retv, inlen, "%scgroup:rw", sep); sep = " "; break; case LXC_AUTO_CGROUP_FULL_NOSPEC: strprint(retv, inlen, "%scgroup-full", sep); sep = " "; break; case LXC_AUTO_CGROUP_FULL_MIXED: strprint(retv, inlen, "%scgroup-full:mixed", sep); sep = " "; break; case LXC_AUTO_CGROUP_FULL_RO: strprint(retv, inlen, "%scgroup-full:ro", sep); sep = " "; break; case LXC_AUTO_CGROUP_FULL_RW: strprint(retv, inlen, "%scgroup-full:rw", sep); sep = " "; break; default: break; } return fulllen; } /* * lxc.network.0.XXX, where XXX can be: name, type, link, flags, type, * macvlan.mode, veth.pair, vlan, ipv4, ipv6, script.up, hwaddr, mtu, * ipv4.gateway, ipv6.gateway. ipvX.gateway can return 'auto' instead * of an address. ipv4 and ipv6 return lists (newline-separated). * things like veth.pair return '' if invalid (i.e. if called for vlan * type). */ static int lxc_get_item_nic(struct lxc_conf *c, char *retv, int inlen, const char *key) { char *p1; int len, fulllen = 0; struct lxc_netdev *netdev; if (!retv) inlen = 0; else memset(retv, 0, inlen); p1 = strchr(key, '.'); if (!p1 || *(p1+1) == '\0') return -1; p1++; netdev = get_netdev_from_key(key, &c->network); if (!netdev) return -1; if (strcmp(p1, "name") == 0) { if (netdev->name) strprint(retv, inlen, "%s", netdev->name); } else if (strcmp(p1, "type") == 0) { strprint(retv, inlen, "%s", lxc_net_type_to_str(netdev->type)); } else if (strcmp(p1, "link") == 0) { if (netdev->link) strprint(retv, inlen, "%s", netdev->link); } else if (strcmp(p1, "flags") == 0) { if (netdev->flags & IFF_UP) strprint(retv, inlen, "up"); } else if (strcmp(p1, "script.up") == 0) { if (netdev->upscript) strprint(retv, inlen, "%s", netdev->upscript); } else if (strcmp(p1, "script.down") == 0) { if (netdev->downscript) strprint(retv, inlen, "%s", netdev->downscript); } else if (strcmp(p1, "hwaddr") == 0) { if (netdev->hwaddr) strprint(retv, inlen, "%s", netdev->hwaddr); } else if (strcmp(p1, "mtu") == 0) { if (netdev->mtu) strprint(retv, inlen, "%s", netdev->mtu); } else if (strcmp(p1, "macvlan.mode") == 0) { if (netdev->type == LXC_NET_MACVLAN) { const char *mode; switch (netdev->priv.macvlan_attr.mode) { case MACVLAN_MODE_PRIVATE: mode = "private"; break; case MACVLAN_MODE_VEPA: mode = "vepa"; break; case MACVLAN_MODE_BRIDGE: mode = "bridge"; break; case MACVLAN_MODE_PASSTHRU: mode = "passthru"; break; default: mode = "(invalid)"; break; } strprint(retv, inlen, "%s", mode); } } else if (strcmp(p1, "veth.pair") == 0) { if (netdev->type == LXC_NET_VETH) { strprint(retv, inlen, "%s", netdev->priv.veth_attr.pair ? netdev->priv.veth_attr.pair : netdev->priv.veth_attr.veth1); } } else if (strcmp(p1, "vlan") == 0) { if (netdev->type == LXC_NET_VLAN) { strprint(retv, inlen, "%d", netdev->priv.vlan_attr.vid); } } else if (strcmp(p1, "ipv4.gateway") == 0) { if (netdev->ipv4_gateway_auto) { strprint(retv, inlen, "auto"); } else if (netdev->ipv4_gateway) { char buf[INET_ADDRSTRLEN]; inet_ntop(AF_INET, netdev->ipv4_gateway, buf, sizeof(buf)); strprint(retv, inlen, "%s", buf); } } else if (strcmp(p1, "ipv4") == 0) { struct lxc_list *it2; lxc_list_for_each(it2, &netdev->ipv4) { struct lxc_inetdev *i = it2->elem; char buf[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &i->addr, buf, sizeof(buf)); strprint(retv, inlen, "%s/%d\n", buf, i->prefix); } } else if (strcmp(p1, "ipv6.gateway") == 0) { if (netdev->ipv6_gateway_auto) { strprint(retv, inlen, "auto"); } else if (netdev->ipv6_gateway) { char buf[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, netdev->ipv6_gateway, buf, sizeof(buf)); strprint(retv, inlen, "%s", buf); } } else if (strcmp(p1, "ipv6") == 0) { struct lxc_list *it2; lxc_list_for_each(it2, &netdev->ipv6) { struct lxc_inet6dev *i = it2->elem; char buf[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, &i->addr, buf, sizeof(buf)); strprint(retv, inlen, "%s/%d\n", buf, i->prefix); } } return fulllen; } static int lxc_get_item_network(struct lxc_conf *c, char *retv, int inlen) { int len, fulllen = 0; struct lxc_list *it; if (!retv) inlen = 0; else memset(retv, 0, inlen); lxc_list_for_each(it, &c->network) { struct lxc_netdev *n = it->elem; const char *t = lxc_net_type_to_str(n->type); strprint(retv, inlen, "%s\n", t ? t : "(invalid)"); } return fulllen; } int lxc_get_config_item(struct lxc_conf *c, const char *key, char *retv, int inlen) { const char *v = NULL; if (strcmp(key, "lxc.mount.entry") == 0) return lxc_get_mount_entries(c, retv, inlen); else if (strcmp(key, "lxc.mount.auto") == 0) return lxc_get_auto_mounts(c, retv, inlen); else if (strcmp(key, "lxc.mount") == 0) v = c->fstab; else if (strcmp(key, "lxc.tty") == 0) return lxc_get_conf_int(c, retv, inlen, c->tty); else if (strcmp(key, "lxc.pts") == 0) return lxc_get_conf_int(c, retv, inlen, c->pts); else if (strcmp(key, "lxc.devttydir") == 0) v = c->ttydir; else if (strcmp(key, "lxc.arch") == 0) return lxc_get_arch_entry(c, retv, inlen); else if (strcmp(key, "lxc.aa_profile") == 0) v = c->lsm_aa_profile; else if (strcmp(key, "lxc.aa_allow_incomplete") == 0) return lxc_get_conf_int(c, retv, inlen, c->lsm_aa_allow_incomplete); else if (strcmp(key, "lxc.se_context") == 0) v = c->lsm_se_context; else if (strcmp(key, "lxc.logfile") == 0) v = c->logfile; else if (strcmp(key, "lxc.loglevel") == 0) 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 return lxc_get_cgroup_entry(c, retv, inlen, key + 11); else if (strcmp(key, "lxc.utsname") == 0) v = c->utsname ? c->utsname->nodename : NULL; else if (strcmp(key, "lxc.console.logfile") == 0) v = c->console.log_path; else if (strcmp(key, "lxc.console") == 0) v = c->console.path; else if (strcmp(key, "lxc.rootfs.mount") == 0) v = c->rootfs.mount; else if (strcmp(key, "lxc.rootfs.backend") == 0) v = c->rootfs.bdev_type; else if (strcmp(key, "lxc.rootfs.options") == 0) v = c->rootfs.options; else if (strcmp(key, "lxc.rootfs") == 0) v = c->rootfs.path; else if (strcmp(key, "lxc.cap.drop") == 0) return lxc_get_item_cap_drop(c, retv, inlen); else if (strcmp(key, "lxc.cap.keep") == 0) return lxc_get_item_cap_keep(c, retv, inlen); else if (strncmp(key, "lxc.hook", 8) == 0) return lxc_get_item_hooks(c, retv, inlen, key); else if (strcmp(key, "lxc.network") == 0) return lxc_get_item_network(c, retv, inlen); else if (strncmp(key, "lxc.network.", 12) == 0) return lxc_get_item_nic(c, retv, inlen, key + 12); else if (strcmp(key, "lxc.start.auto") == 0) return lxc_get_conf_int(c, retv, inlen, c->start_auto); else if (strcmp(key, "lxc.start.delay") == 0) return lxc_get_conf_int(c, retv, inlen, c->start_delay); else if (strcmp(key, "lxc.start.order") == 0) return lxc_get_conf_int(c, retv, inlen, c->start_order); else if (strcmp(key, "lxc.monitor.unshare") == 0) return lxc_get_conf_int(c, retv, inlen, c->monitor_unshare); else if (strcmp(key, "lxc.group") == 0) return lxc_get_item_groups(c, retv, inlen); else if (strcmp(key, "lxc.seccomp") == 0) v = c->seccomp; else if (strcmp(key, "lxc.environment") == 0) return lxc_get_item_environment(c, retv, inlen); else if (strcmp(key, "lxc.init_cmd") == 0) v = c->init_cmd; else if (strcmp(key, "lxc.init_uid") == 0) return lxc_get_conf_int(c, retv, inlen, c->init_uid); else if (strcmp(key, "lxc.init_gid") == 0) return lxc_get_conf_int(c, retv, inlen, c->init_gid); else if (strcmp(key, "lxc.ephemeral") == 0) return lxc_get_conf_int(c, retv, inlen, c->ephemeral); else return -1; if (!v) return 0; if (retv && inlen >= strlen(v) + 1) strncpy(retv, v, strlen(v)+1); return strlen(v); } int lxc_clear_config_item(struct lxc_conf *c, const char *key) { if (strcmp(key, "lxc.network") == 0) return lxc_clear_config_network(c); else if (strncmp(key, "lxc.network.", 12) == 0) return lxc_clear_nic(c, key + 12); else if (strcmp(key, "lxc.cap.drop") == 0) return lxc_clear_config_caps(c); else if (strcmp(key, "lxc.cap.keep") == 0) return lxc_clear_config_keepcaps(c); else if (strncmp(key, "lxc.cgroup", 10) == 0) return lxc_clear_cgroups(c, key); else if (strcmp(key, "lxc.mount.entry") == 0) return lxc_clear_mount_entries(c); else if (strcmp(key, "lxc.mount.auto") == 0) return lxc_clear_automounts(c); else if (strncmp(key, "lxc.hook", 8) == 0) return lxc_clear_hooks(c, key); else if (strncmp(key, "lxc.group", 9) == 0) return lxc_clear_groups(c); else if (strncmp(key, "lxc.environment", 15) == 0) return lxc_clear_environment(c); else if (strncmp(key, "lxc.id_map", 10) == 0) return lxc_clear_idmaps(c); return -1; } /* * writing out a confile. */ void write_config(FILE *fout, struct lxc_conf *c) { size_t len = c->unexpanded_len; int ret; if (!len) return; ret = fwrite(c->unexpanded_config, 1, len, fout); if (ret != len) SYSERROR("Error writing configuration file"); } bool do_append_unexp_config_line(struct lxc_conf *conf, const char *key, const char *v) { int ret; size_t len = strlen(key) + strlen(v) + 4; char *tmp = alloca(len); ret = snprintf(tmp, len, "%s = %s", key, v); if (ret < 0 || ret >= len) return false; /* Save the line verbatim into unexpanded_conf */ if (append_unexp_config_line(tmp, conf)) return false; return true; } void clear_unexp_config_line(struct lxc_conf *conf, const char *key, bool rm_subkeys) { char *lstart = conf->unexpanded_config, *lend; if (!conf->unexpanded_config) return; while (*lstart) { lend = strchr(lstart, '\n'); char v; if (!lend) lend = lstart + strlen(lstart); else lend++; if (strncmp(lstart, key, strlen(key)) != 0) { lstart = lend; continue; } if (!rm_subkeys) { v = lstart[strlen(key)]; if (!isspace(v) && v != '=') { lstart = lend; continue; } } conf->unexpanded_len -= (lend - lstart); if (*lend == '\0') { *lstart = '\0'; return; } memmove(lstart, lend, strlen(lend)+1); } } bool clone_update_unexp_ovl_paths(struct lxc_conf *conf, const char *oldpath, const char *newpath, const char *oldname, const char *newname, const char *ovldir) { const char *key = "lxc.mount.entry"; int ret; char *lstart = conf->unexpanded_config; char *lend; char *p; char *q; size_t newdirlen = strlen(ovldir) + strlen(newpath) + strlen(newname) + 2; size_t olddirlen = strlen(ovldir) + strlen(oldpath) + strlen(oldname) + 2; char *olddir = alloca(olddirlen + 1); char *newdir = alloca(newdirlen + 1); ret = snprintf(olddir, olddirlen + 1, "%s=%s/%s", ovldir, oldpath, oldname); if (ret < 0 || ret >= olddirlen + 1) { ERROR("Bug in %s", __func__); return false; } ret = snprintf(newdir, newdirlen + 1, "%s=%s/%s", ovldir, newpath, newname); if (ret < 0 || ret >= newdirlen + 1) { ERROR("Bug in %s", __func__); return false; } if (!conf->unexpanded_config) return true; while (*lstart) { lend = strchr(lstart, '\n'); if (!lend) lend = lstart + strlen(lstart); else lend++; if (strncmp(lstart, key, strlen(key)) != 0) goto next; p = strchr(lstart + strlen(key), '='); if (!p) goto next; p++; while (isblank(*p)) p++; if (p >= lend) goto next; /* Whenever an lxc.mount.entry entry is found in a line we check * if the substring " overlay" or the substring " aufs" is * present before doing any further work. We check for " * overlay" and " aufs" since both substrings need to have at * least one space before them in a valid overlay * lxc.mount.entry (/A B overlay). When the space before is * missing it is very likely that these substrings are part of a * path or something else. (Checking q >= lend ensures that we * only count matches in the current line.) */ if ((!(q = strstr(p, " overlay")) || q >= lend) && (!(q = strstr(p, " aufs")) || q >= lend)) goto next; if (!(q = strstr(p, olddir)) || (q >= lend)) goto next; /* replace the olddir with newdir */ if (olddirlen >= newdirlen) { size_t diff = olddirlen - newdirlen; memcpy(q, newdir, newdirlen); if (olddirlen != newdirlen) { memmove(q + newdirlen, q + newdirlen + diff, strlen(q) - newdirlen - diff + 1); lend -= diff; conf->unexpanded_len -= diff; } } else { char *new; size_t diff = newdirlen - olddirlen; size_t oldlen = conf->unexpanded_len; size_t newlen = oldlen + diff; size_t poffset = q - conf->unexpanded_config; new = realloc(conf->unexpanded_config, newlen + 1); if (!new) { ERROR("Out of memory"); return false; } conf->unexpanded_len = newlen; conf->unexpanded_alloced = newlen + 1; new[newlen - 1] = '\0'; lend = new + (lend - conf->unexpanded_config); /* move over the remainder to make room for the newdir */ memmove(new + poffset + newdirlen, new + poffset + olddirlen, oldlen - poffset - olddirlen + 1); conf->unexpanded_config = new; memcpy(new + poffset, newdir, newdirlen); lend += diff; } next: lstart = lend; } return true; } bool clone_update_unexp_hooks(struct lxc_conf *conf, const char *oldpath, const char *newpath, const char *oldname, const char *newname) { const char *key = "lxc.hook"; int ret; char *lstart = conf->unexpanded_config, *lend, *p; size_t newdirlen = strlen(newpath) + strlen(newname) + 1; size_t olddirlen = strlen(oldpath) + strlen(oldname) + 1; char *olddir = alloca(olddirlen + 1); char *newdir = alloca(newdirlen + 1); ret = snprintf(olddir, olddirlen + 1, "%s/%s", oldpath, oldname); if (ret < 0 || ret >= olddirlen + 1) { ERROR("Bug in %s", __func__); return false; } ret = snprintf(newdir, newdirlen + 1, "%s/%s", newpath, newname); if (ret < 0 || ret >= newdirlen + 1) { ERROR("Bug in %s", __func__); return false; } if (!conf->unexpanded_config) return true; while (*lstart) { lend = strchr(lstart, '\n'); if (!lend) lend = lstart + strlen(lstart); else lend++; if (strncmp(lstart, key, strlen(key)) != 0) goto next; p = strchr(lstart + strlen(key), '='); if (!p) goto next; p++; while (isblank(*p)) p++; if (p >= lend) goto next; if (strncmp(p, olddir, strlen(olddir)) != 0) goto next; /* replace the olddir with newdir */ if (olddirlen >= newdirlen) { size_t diff = olddirlen - newdirlen; memcpy(p, newdir, newdirlen); if (olddirlen != newdirlen) { memmove(p + newdirlen, p + newdirlen + diff, strlen(p) - newdirlen - diff + 1); lend -= diff; conf->unexpanded_len -= diff; } } else { char *new; size_t diff = newdirlen - olddirlen; size_t oldlen = conf->unexpanded_len; size_t newlen = oldlen + diff; size_t poffset = p - conf->unexpanded_config; new = realloc(conf->unexpanded_config, newlen + 1); if (!new) { ERROR("Out of memory"); return false; } conf->unexpanded_len = newlen; conf->unexpanded_alloced = newlen + 1; new[newlen - 1] = '\0'; lend = new + (lend - conf->unexpanded_config); /* move over the remainder to make room for the newdir */ memmove(new + poffset + newdirlen, new + poffset + olddirlen, oldlen - poffset - olddirlen + 1); conf->unexpanded_config = new; memcpy(new + poffset, newdir, newdirlen); lend += diff; } next: lstart = lend; } return true; } #define DO(cmd) { \ if (!(cmd)) { \ ERROR("Error writing to new config"); \ return false; \ } \ } static bool new_hwaddr(char *hwaddr) { int ret; /* COMMENT(brauner): Initialize random number generator. */ (void)randseed(true); ret = snprintf(hwaddr, 18, "00:16:3e:%02x:%02x:%02x", rand() % 255, rand() % 255, rand() % 255); if (ret < 0 || ret >= 18) { SYSERROR("Failed to call snprintf()."); return false; } return true; } /* * This is called only from clone. * We wish to update all hwaddrs in the unexpanded config file. We * can't/don't want to update any which come from lxc.includes (there * shouldn't be any). * We can't just walk the c->lxc-conf->network list because that includes * netifs from the include files. So we update the ones which we find in * the unexp config file, then find the original macaddr in the * conf->network, and update that to the same value. */ bool network_new_hwaddrs(struct lxc_conf *conf) { struct lxc_list *it; const char *key = "lxc.network.hwaddr"; char *lstart = conf->unexpanded_config, *lend, *p, *p2; if (!conf->unexpanded_config) return true; while (*lstart) { char newhwaddr[18], oldhwaddr[17]; lend = strchr(lstart, '\n'); if (!lend) lend = lstart + strlen(lstart); else lend++; if (strncmp(lstart, key, strlen(key)) != 0) { lstart = lend; continue; } p = strchr(lstart+strlen(key), '='); if (!p) { lstart = lend; continue; } p++; while (isblank(*p)) p++; if (!*p) return true; p2 = p; while (*p2 && !isblank(*p2) && *p2 != '\n') p2++; if (p2-p != 17) { WARN("Bad hwaddr entry"); lstart = lend; continue; } memcpy(oldhwaddr, p, 17); if (!new_hwaddr(newhwaddr)) return false; memcpy(p, newhwaddr, 17); lxc_list_for_each(it, &conf->network) { struct lxc_netdev *n = it->elem; if (n->hwaddr && memcmp(oldhwaddr, n->hwaddr, 17) == 0) memcpy(n->hwaddr, newhwaddr, 17); } lstart = lend; } return true; } static int config_ephemeral(const char *key, const char *value, struct lxc_conf *lxc_conf) { if (lxc_safe_uint(value, &lxc_conf->ephemeral) < 0) return -1; if (lxc_conf->ephemeral > 1) { ERROR("Wrong value for lxc.ephemeral. Can only be set to 0 or 1"); return -1; } return 0; } lxc-2.0.8/src/lxc/rtnl.c0000644061062106075000000000413613105116772011747 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include "nl.h" #include "rtnl.h" extern int rtnetlink_open(struct rtnl_handler *handler) { return netlink_open(&handler->nlh, NETLINK_ROUTE); } extern int rtnetlink_close(struct rtnl_handler *handler) { return netlink_close(&handler->nlh); } extern int rtnetlink_rcv(struct rtnl_handler *handler, struct rtnlmsg *rtnlmsg) { return netlink_rcv(&handler->nlh, (struct nlmsg *)&rtnlmsg->nlmsghdr); } extern int rtnetlink_send(struct rtnl_handler *handler, struct rtnlmsg *rtnlmsg) { return netlink_send(&handler->nlh, (struct nlmsg *)&rtnlmsg->nlmsghdr); } extern int rtnetlink_transaction(struct rtnl_handler *handler, struct rtnlmsg *request, struct rtnlmsg *answer) { return netlink_transaction(&handler->nlh, (struct nlmsg *)&request->nlmsghdr, (struct nlmsg *)&answer->nlmsghdr); } extern struct rtnlmsg *rtnlmsg_alloc(size_t size) { /* size_t len = NLMSG_LENGTH(NLMSG_ALIGN(sizeof(struct rtnlmsghdr))) + size; */ /* return (struct rtnlmsg *)nlmsg_alloc(len); */ return NULL; } extern void rtnlmsg_free(struct rtnlmsg *rtnlmsg) { free(rtnlmsg); } lxc-2.0.8/src/lxc/log.h0000644061062106075000000002210613105116772011553 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * Cedric Le Goater * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_LOG_H #define __LXC_LOG_H #include "config.h" #include #include #include #include #include #include #include #include "conf.h" #ifndef O_CLOEXEC #define O_CLOEXEC 02000000 #endif #ifndef F_DUPFD_CLOEXEC #define F_DUPFD_CLOEXEC 1030 #endif #define LXC_LOG_PREFIX_SIZE 32 #define LXC_LOG_BUFFER_SIZE 4096 /* This attribute is required to silence clang warnings */ #if defined(__GNUC__) #define ATTR_UNUSED __attribute__ ((unused)) #else #define ATTR_UNUSED #endif /* predefined priorities. */ enum lxc_loglevel { LXC_LOG_PRIORITY_TRACE, LXC_LOG_PRIORITY_DEBUG, LXC_LOG_PRIORITY_INFO, LXC_LOG_PRIORITY_NOTICE, LXC_LOG_PRIORITY_WARN, LXC_LOG_PRIORITY_ERROR, LXC_LOG_PRIORITY_CRIT, LXC_LOG_PRIORITY_ALERT, LXC_LOG_PRIORITY_FATAL, LXC_LOG_PRIORITY_NOTSET, }; /* location information of the logging event */ struct lxc_log_locinfo { const char *file; const char *func; int line; }; #define LXC_LOG_LOCINFO_INIT \ { .file = __FILE__, .func = __func__, .line = __LINE__ } /* brief logging event object */ struct lxc_log_event { const char* category; int priority; struct timespec timestamp; struct lxc_log_locinfo *locinfo; const char *fmt; va_list *vap; }; /* log appender object */ struct lxc_log_appender { const char* name; int (*append)(const struct lxc_log_appender *, struct lxc_log_event *); /* * appenders can be stacked */ struct lxc_log_appender *next; }; /* log category object */ struct lxc_log_category { const char *name; int priority; struct lxc_log_appender *appender; 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. */ static inline int lxc_log_priority_is_enabled(const struct lxc_log_category* category, int priority) { while (category->priority == LXC_LOG_PRIORITY_NOTSET && category->parent) category = category->parent; 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; } /* * converts a priority to a literal string */ static inline const char* lxc_log_priority_to_string(int priority) { switch (priority) { case LXC_LOG_PRIORITY_TRACE: return "TRACE"; case LXC_LOG_PRIORITY_DEBUG: return "DEBUG"; case LXC_LOG_PRIORITY_INFO: return "INFO"; case LXC_LOG_PRIORITY_NOTICE: return "NOTICE"; case LXC_LOG_PRIORITY_WARN: return "WARN"; case LXC_LOG_PRIORITY_ERROR: return "ERROR"; case LXC_LOG_PRIORITY_CRIT: return "CRIT"; case LXC_LOG_PRIORITY_ALERT: return "ALERT"; case LXC_LOG_PRIORITY_FATAL: return "FATAL"; default: return "NOTSET"; } } /* * converts a literal priority to an int */ static inline int lxc_log_priority_to_int(const char* name) { if (!strcasecmp("TRACE", name)) return LXC_LOG_PRIORITY_TRACE; if (!strcasecmp("DEBUG", name)) return LXC_LOG_PRIORITY_DEBUG; if (!strcasecmp("INFO", name)) return LXC_LOG_PRIORITY_INFO; if (!strcasecmp("NOTICE", name)) return LXC_LOG_PRIORITY_NOTICE; if (!strcasecmp("WARN", name)) return LXC_LOG_PRIORITY_WARN; if (!strcasecmp("ERROR", name)) return LXC_LOG_PRIORITY_ERROR; if (!strcasecmp("CRIT", name)) return LXC_LOG_PRIORITY_CRIT; if (!strcasecmp("ALERT", name)) return LXC_LOG_PRIORITY_ALERT; if (!strcasecmp("FATAL", name)) return LXC_LOG_PRIORITY_FATAL; return LXC_LOG_PRIORITY_NOTSET; } static inline void __lxc_log_append(const struct lxc_log_appender *appender, struct lxc_log_event* event) { va_list va, *va_keep; va_keep = event->vap; while (appender) { va_copy(va, *va_keep); event->vap = &va; appender->append(appender, event); appender = appender->next; va_end(va); } } static inline void __lxc_log(const struct lxc_log_category* category, struct lxc_log_event* event) { while (category) { __lxc_log_append(category->appender, event); category = category->parent; } } /* * Helper macro to define log functions. */ #define lxc_log_priority_define(acategory, PRIORITY) \ \ ATTR_UNUSED static inline void LXC_##PRIORITY(struct lxc_log_locinfo *, \ const char *, ...) __attribute__ ((format (printf, 2, 3))); \ \ ATTR_UNUSED static inline void LXC_##PRIORITY(struct lxc_log_locinfo* locinfo, \ const char* format, ...) \ { \ if (lxc_log_priority_is_enabled(acategory, \ LXC_LOG_PRIORITY_##PRIORITY)) { \ struct lxc_log_event evt = { \ .category = (acategory)->name, \ .priority = LXC_LOG_PRIORITY_##PRIORITY, \ .fmt = format, \ .locinfo = locinfo \ }; \ va_list va_ref; \ \ /* clock_gettime() is explicitly marked as MT-Safe \ * without restrictions. So let's use it for our \ * logging stamps. */ \ clock_gettime(CLOCK_REALTIME, &evt.timestamp); \ \ va_start(va_ref, format); \ evt.vap = &va_ref; \ __lxc_log(acategory, &evt); \ va_end(va_ref); \ } \ } /* * Helper macro to define and use static categories. */ #define lxc_log_category_define(name, parent) \ extern struct lxc_log_category lxc_log_category_##parent; \ struct lxc_log_category lxc_log_category_##name = { \ #name, \ LXC_LOG_PRIORITY_NOTSET, \ NULL, \ &lxc_log_category_##parent \ }; #define lxc_log_define(name, parent) \ lxc_log_category_define(name, parent) \ \ lxc_log_priority_define(&lxc_log_category_##name, TRACE) \ lxc_log_priority_define(&lxc_log_category_##name, DEBUG) \ lxc_log_priority_define(&lxc_log_category_##name, INFO) \ lxc_log_priority_define(&lxc_log_category_##name, NOTICE) \ lxc_log_priority_define(&lxc_log_category_##name, WARN) \ lxc_log_priority_define(&lxc_log_category_##name, ERROR) \ lxc_log_priority_define(&lxc_log_category_##name, CRIT) \ lxc_log_priority_define(&lxc_log_category_##name, ALERT) \ lxc_log_priority_define(&lxc_log_category_##name, FATAL) #define lxc_log_category_priority(name) \ (lxc_log_priority_to_string(lxc_log_category_##name.priority)) /* * top categories */ #define TRACE(format, ...) do { \ struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \ LXC_TRACE(&locinfo, format, ##__VA_ARGS__); \ } while (0) #define DEBUG(format, ...) do { \ struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \ LXC_DEBUG(&locinfo, format, ##__VA_ARGS__); \ } while (0) #define INFO(format, ...) do { \ struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \ LXC_INFO(&locinfo, format, ##__VA_ARGS__); \ } while (0) #define NOTICE(format, ...) do { \ struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \ LXC_NOTICE(&locinfo, format, ##__VA_ARGS__); \ } while (0) #define WARN(format, ...) do { \ struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \ LXC_WARN(&locinfo, format, ##__VA_ARGS__); \ } while (0) #define ERROR(format, ...) do { \ struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \ LXC_ERROR(&locinfo, format, ##__VA_ARGS__); \ } while (0) #define CRIT(format, ...) do { \ struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \ LXC_CRIT(&locinfo, format, ##__VA_ARGS__); \ } while (0) #define ALERT(format, ...) do { \ struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \ LXC_ALERT(&locinfo, format, ##__VA_ARGS__); \ } while (0) #define FATAL(format, ...) do { \ struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \ LXC_FATAL(&locinfo, format, ##__VA_ARGS__); \ } while (0) #define SYSERROR(format, ...) do { \ ERROR("%s - " format, strerror(errno), ##__VA_ARGS__); \ } while (0) extern int lxc_log_fd; 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(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); extern bool lxc_log_has_valid_level(void); extern const char *lxc_log_get_prefix(void); extern void lxc_log_options_no_override(); #endif lxc-2.0.8/src/lxc/parse.h0000644061062106075000000000252213105116772012104 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_PARSE_H #define __LXC_PARSE_H typedef int (*lxc_dir_cb)(const char *name, const char *directory, const char *file, void *data); typedef int (*lxc_file_cb)(char *buffer, void *data); extern int lxc_file_for_each_line(const char *file, lxc_file_cb callback, void* data); extern int lxc_char_left_gc(const char *buffer, size_t len); extern int lxc_char_right_gc(const char *buffer, size_t len); extern int lxc_is_line_empty(const char *line); #endif lxc-2.0.8/src/lxc/attach.c0000644061062106075000000010341513105116772012234 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if !HAVE_DECL_PR_CAPBSET_DROP #define PR_CAPBSET_DROP 24 #endif #include "af_unix.h" #include "attach.h" #include "caps.h" #include "cgroup.h" #include "commands.h" #include "conf.h" #include "config.h" #include "confile.h" #include "log.h" #include "lsm/lsm.h" #include "lxclock.h" #include "lxcseccomp.h" #include "namespace.h" #include "utils.h" #include #if HAVE_SYS_PERSONALITY_H #include #endif #ifndef SOCK_CLOEXEC # define SOCK_CLOEXEC 02000000 #endif #ifndef MS_REC #define MS_REC 16384 #endif #ifndef MS_SLAVE #define MS_SLAVE (1<<19) #endif lxc_log_define(lxc_attach, lxc); /* /proc/pid-to-str/current\0 = (5 + 21 + 7 + 1) */ #define __LSMATTRLEN (5 + (LXC_NUMSTRLEN64) + 7 + 1) static int lsm_openat(int procfd, pid_t pid, int on_exec) { int ret = -1; int labelfd = -1; const char *name; char path[__LSMATTRLEN]; name = lsm_name(); if (strcmp(name, "nop") == 0) return 0; if (strcmp(name, "none") == 0) return 0; /* We don't support on-exec with AppArmor */ if (strcmp(name, "AppArmor") == 0) on_exec = 0; if (on_exec) ret = snprintf(path, __LSMATTRLEN, "%d/attr/exec", pid); else ret = snprintf(path, __LSMATTRLEN, "%d/attr/current", pid); if (ret < 0 || ret >= __LSMATTRLEN) return -1; labelfd = openat(procfd, path, O_RDWR); if (labelfd < 0) { SYSERROR("Unable to open file descriptor to set LSM label."); return -1; } return labelfd; } static int lsm_set_label_at(int lsm_labelfd, int on_exec, char *lsm_label) { int fret = -1; const char* name; char *command = NULL; name = lsm_name(); if (strcmp(name, "nop") == 0) return 0; if (strcmp(name, "none") == 0) return 0; /* We don't support on-exec with AppArmor */ if (strcmp(name, "AppArmor") == 0) on_exec = 0; if (strcmp(name, "AppArmor") == 0) { int size; command = malloc(strlen(lsm_label) + strlen("changeprofile ") + 1); if (!command) { SYSERROR("Failed to write apparmor profile."); goto out; } size = sprintf(command, "changeprofile %s", lsm_label); if (size < 0) { SYSERROR("Failed to write apparmor profile."); goto out; } if (write(lsm_labelfd, command, size + 1) < 0) { SYSERROR("Unable to set LSM label: %s.", command); goto out; } INFO("Set LSM label to: %s.", command); } else if (strcmp(name, "SELinux") == 0) { if (write(lsm_labelfd, lsm_label, strlen(lsm_label) + 1) < 0) { SYSERROR("Unable to set LSM label: %s.", lsm_label); goto out; } INFO("Set LSM label to: %s.", lsm_label); } else { ERROR("Unable to restore label for unknown LSM: %s.", name); goto out; } fret = 0; out: free(command); if (lsm_labelfd != -1) close(lsm_labelfd); return fret; } /* /proc/pid-to-str/status\0 = (5 + 21 + 7 + 1) */ #define __PROC_STATUS_LEN (5 + 21 + 7 + 1) static struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid) { FILE *proc_file; char proc_fn[__PROC_STATUS_LEN]; bool found; int ret; char *line = NULL; size_t line_bufsz = 0; struct lxc_proc_context_info *info = NULL; /* Read capabilities. */ ret = snprintf(proc_fn, __PROC_STATUS_LEN, "/proc/%d/status", pid); if (ret < 0 || ret >= __PROC_STATUS_LEN) goto on_error; proc_file = fopen(proc_fn, "r"); if (!proc_file) { SYSERROR("Could not open %s.", proc_fn); goto on_error; } info = calloc(1, sizeof(*info)); if (!info) { SYSERROR("Could not allocate memory."); return NULL; } found = false; while (getline(&line, &line_bufsz, proc_file) != -1) { ret = sscanf(line, "CapBnd: %llx", &info->capability_mask); if (ret != EOF && ret == 1) { found = true; break; } } free(line); fclose(proc_file); if (!found) { SYSERROR("Could not read capability bounding set from %s.", proc_fn); errno = ENOENT; goto on_error; } info->lsm_label = lsm_process_label_get(pid); return info; on_error: free(info); return NULL; } static void lxc_proc_put_context_info(struct lxc_proc_context_info *ctx) { free(ctx->lsm_label); if (ctx->container) lxc_container_put(ctx->container); free(ctx); } static int lxc_attach_to_ns(pid_t pid, int which) { int fd[LXC_NS_MAX]; int i, j, saved_errno; if (access("/proc/self/ns", X_OK)) { ERROR("Does this kernel version support namespaces?"); return -1; } for (i = 0; i < LXC_NS_MAX; i++) { /* Ignore if we are not supposed to attach to that namespace. */ if (which != -1 && !(which & ns_info[i].clone_flag)) { fd[i] = -1; continue; } fd[i] = lxc_preserve_ns(pid, ns_info[i].proc_name); if (fd[i] < 0) { saved_errno = errno; /* Close all already opened file descriptors before we * return an error, so we don't leak them. */ for (j = 0; j < i; j++) close(fd[j]); errno = saved_errno; SYSERROR("Failed to open namespace: \"%s\".", ns_info[i].proc_name); return -1; } } for (i = 0; i < LXC_NS_MAX; i++) { if (fd[i] < 0) continue; if (setns(fd[i], 0) < 0) { saved_errno = errno; for (j = i; j < LXC_NS_MAX; j++) close(fd[j]); errno = saved_errno; SYSERROR("Failed to attach to namespace \"%s\".", ns_info[i].proc_name); return -1; } DEBUG("Attached to namespace \"%s\".", ns_info[i].proc_name); close(fd[i]); } return 0; } static int lxc_attach_remount_sys_proc(void) { int ret; ret = unshare(CLONE_NEWNS); if (ret < 0) { SYSERROR("Failed to unshare mount namespace."); return -1; } if (detect_shared_rootfs()) { if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) { SYSERROR("Failed to make / rslave."); ERROR("Continuing..."); } } /* Assume /proc is always mounted, so remount it. */ ret = umount2("/proc", MNT_DETACH); if (ret < 0) { SYSERROR("Failed to unmount /proc."); return -1; } ret = mount("none", "/proc", "proc", 0, NULL); if (ret < 0) { SYSERROR("Failed to remount /proc."); return -1; } /* Try to umount /sys. If it's not a mount point, we'll get EINVAL, then * we ignore it because it may not have been mounted in the first place. */ ret = umount2("/sys", MNT_DETACH); if (ret < 0 && errno != EINVAL) { SYSERROR("Failed to unmount /sys."); return -1; } else if (ret == 0) { /* Remount it. */ ret = mount("none", "/sys", "sysfs", 0, NULL); if (ret < 0) { SYSERROR("Failed to remount /sys."); return -1; } } return 0; } static int lxc_attach_drop_privs(struct lxc_proc_context_info *ctx) { int last_cap = lxc_caps_last_cap(); int cap; for (cap = 0; cap <= last_cap; cap++) { if (ctx->capability_mask & (1LL << cap)) continue; if (prctl(PR_CAPBSET_DROP, cap, 0, 0, 0)) { SYSERROR("Failed to remove capability id %d.", cap); return -1; } } return 0; } static int lxc_attach_set_environment(enum lxc_attach_env_policy_t policy, char** extra_env, char** extra_keep) { if (policy == LXC_ATTACH_CLEAR_ENV) { char **extra_keep_store = NULL; int path_kept = 0; if (extra_keep) { size_t count, i; for (count = 0; extra_keep[count]; count++); extra_keep_store = calloc(count, sizeof(char *)); if (!extra_keep_store) { SYSERROR("Failed to allocate memory for storing current " "environment variable values that will be kept."); return -1; } for (i = 0; i < count; i++) { char *v = getenv(extra_keep[i]); if (v) { extra_keep_store[i] = strdup(v); if (!extra_keep_store[i]) { SYSERROR("Failed to allocate memory for storing current " "environment variable values that will be kept."); while (i > 0) free(extra_keep_store[--i]); free(extra_keep_store); return -1; } if (strcmp(extra_keep[i], "PATH") == 0) path_kept = 1; } /* Calloc sets entire array to zero, so we don't * need an else. */ } } if (clearenv()) { char **p; SYSERROR("Failed to clear environment."); if (extra_keep_store) { for (p = extra_keep_store; *p; p++) free(*p); free(extra_keep_store); } return -1; } if (extra_keep_store) { size_t i; for (i = 0; extra_keep[i]; i++) { if (extra_keep_store[i]) { if (setenv(extra_keep[i], extra_keep_store[i], 1) < 0) SYSERROR("Unable to set environment variable."); } free(extra_keep_store[i]); } free(extra_keep_store); } /* Always set a default path; shells and execlp tend to be fine * without it, but there is a disturbing number of C programs * out there that just assume that getenv("PATH") is never NULL * and then die a painful segfault death. */ if (!path_kept) setenv("PATH", "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 1); } if (putenv("container=lxc")) { SYSERROR("Failed to set environment variable."); return -1; } /* Set extra environment variables. */ if (extra_env) { for (; *extra_env; extra_env++) { /* Duplicate the string, just to be on the safe side, * because putenv does not do it for us. */ char *p = strdup(*extra_env); /* We just assume the user knows what they are doing, so * we don't do any checks. */ if (!p) { SYSERROR("Failed to allocate memory for additional environment " "variables."); return -1; } putenv(p); } } return 0; } static char *lxc_attach_getpwshell(uid_t uid) { pid_t pid; int pipes[2]; int ret; int fd; char *result = NULL; /* We need to fork off a process that runs the getent program, and we * need to capture its output, so we use a pipe for that purpose. */ ret = pipe(pipes); if (ret < 0) return NULL; pid = fork(); if (pid < 0) { close(pipes[0]); close(pipes[1]); return NULL; } if (pid) { FILE *pipe_f; char *line = NULL; size_t line_bufsz = 0; int found = 0; int status; close(pipes[1]); pipe_f = fdopen(pipes[0], "r"); while (getline(&line, &line_bufsz, pipe_f) != -1) { char *token; char *saveptr = NULL; long value; char *endptr = NULL; int i; /* If we already found something, just continue to read * until the pipe doesn't deliver any more data, but * don't modify the existing data structure. */ if (found) continue; /* Trim line on the right hand side. */ for (i = strlen(line); i > 0 && (line[i - 1] == '\n' || line[i - 1] == '\r'); --i) line[i - 1] = '\0'; /* Split into tokens: first: user name. */ token = strtok_r(line, ":", &saveptr); if (!token) continue; /* next: dummy password field */ token = strtok_r(NULL, ":", &saveptr); if (!token) continue; /* next: user id */ token = strtok_r(NULL, ":", &saveptr); value = token ? strtol(token, &endptr, 10) : 0; if (!token || !endptr || *endptr || value == LONG_MIN || value == LONG_MAX) continue; /* dummy sanity check: user id matches */ if ((uid_t) value != uid) continue; /* skip fields: gid, gecos, dir, go to next field 'shell' */ for (i = 0; i < 4; i++) { token = strtok_r(NULL, ":", &saveptr); if (!token) break; } if (!token) continue; free(result); result = strdup(token); /* Sanity check that there are no fields after that. */ token = strtok_r(NULL, ":", &saveptr); if (token) continue; found = 1; } free(line); fclose(pipe_f); again: if (waitpid(pid, &status, 0) < 0) { if (errno == EINTR) goto again; return NULL; } /* Some sanity checks. If anything even hinted at going wrong, * we can't be sure we have a valid result, so we assume we * don't. */ if (!WIFEXITED(status)) return NULL; if (WEXITSTATUS(status) != 0) return NULL; if (!found) return NULL; return result; } else { char uid_buf[32]; char *arguments[] = { "getent", "passwd", uid_buf, NULL }; close(pipes[0]); /* We want to capture stdout. */ dup2(pipes[1], 1); close(pipes[1]); /* Get rid of stdin/stderr, so we try to associate it with * /dev/null. */ fd = open("/dev/null", O_RDWR); if (fd < 0) { close(0); close(2); } else { dup2(fd, 0); dup2(fd, 2); close(fd); } /* Finish argument list. */ ret = snprintf(uid_buf, sizeof(uid_buf), "%ld", (long) uid); if (ret <= 0) exit(-1); /* Try to run getent program. */ (void) execvp("getent", arguments); exit(-1); } } static void lxc_attach_get_init_uidgid(uid_t* init_uid, gid_t* init_gid) { FILE *proc_file; char proc_fn[__PROC_STATUS_LEN]; int ret; char *line = NULL; size_t line_bufsz = 0; long value = -1; uid_t uid = (uid_t)-1; gid_t gid = (gid_t)-1; /* Read capabilities. */ snprintf(proc_fn, __PROC_STATUS_LEN, "/proc/%d/status", 1); proc_file = fopen(proc_fn, "r"); if (!proc_file) return; while (getline(&line, &line_bufsz, proc_file) != -1) { /* Format is: real, effective, saved set user, fs we only care * about real uid. */ ret = sscanf(line, "Uid: %ld", &value); if (ret != EOF && ret == 1) { uid = (uid_t) value; } else { ret = sscanf(line, "Gid: %ld", &value); if (ret != EOF && ret == 1) gid = (gid_t) value; } if (uid != (uid_t)-1 && gid != (gid_t)-1) break; } fclose(proc_file); free(line); /* Only override arguments if we found something. */ if (uid != (uid_t)-1) *init_uid = uid; if (gid != (gid_t)-1) *init_gid = gid; /* TODO: we should also parse supplementary groups and use * setgroups() to set them. */ } struct attach_clone_payload { int ipc_socket; lxc_attach_options_t* options; struct lxc_proc_context_info* init_ctx; lxc_attach_exec_t exec_function; void* exec_payload; }; static int attach_child_main(void* data); /* Help the optimizer along if it doesn't know that exit always exits. */ #define rexit(c) do { int __c = (c); _exit(__c); return __c; } while(0) /* Define default options if no options are supplied by the user. */ static lxc_attach_options_t attach_static_default_options = LXC_ATTACH_OPTIONS_DEFAULT; static bool fetch_seccomp(const char *name, const char *lxcpath, struct lxc_proc_context_info *i, lxc_attach_options_t *options) { struct lxc_container *c; char *path; if (!(options->namespaces & CLONE_NEWNS) || !(options->attach_flags & LXC_ATTACH_LSM)) return true; c = lxc_container_new(name, lxcpath); if (!c) return false; i->container = c; /* Initialize an empty lxc_conf */ if (!c->set_config_item(c, "lxc.seccomp", "")) { return false; } /* Fetch the current profile path over the cmd interface. */ path = c->get_running_config_item(c, "lxc.seccomp"); if (!path) { return true; } /* Copy the value into the new lxc_conf. */ if (!c->set_config_item(c, "lxc.seccomp", path)) { free(path); return false; } free(path); /* Attempt to parse the resulting config. */ if (lxc_read_seccomp_config(c->lxc_conf) < 0) { ERROR("Error reading seccomp policy."); return false; } return true; } static signed long get_personality(const char *name, const char *lxcpath) { char *p = lxc_cmd_get_config_item(name, "lxc.arch", lxcpath); signed long ret; if (!p) return -1; ret = lxc_config_parse_arch(p); free(p); return ret; } int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_function, void* exec_payload, lxc_attach_options_t* options, pid_t* attached_process) { int ret, status; pid_t init_pid, pid, attached_pid, expected; struct lxc_proc_context_info *init_ctx; char* cwd; char* new_cwd; int ipc_sockets[2]; signed long personality; if (!options) options = &attach_static_default_options; init_pid = lxc_cmd_get_init_pid(name, lxcpath); if (init_pid < 0) { ERROR("Failed to get init pid."); return -1; } init_ctx = lxc_proc_get_context_info(init_pid); if (!init_ctx) { ERROR("Failed to get context of init process: %ld.", (long)init_pid); return -1; } personality = get_personality(name, lxcpath); if (init_ctx->personality < 0) { ERROR("Failed to get personality of the container."); lxc_proc_put_context_info(init_ctx); return -1; } init_ctx->personality = personality; if (!fetch_seccomp(name, lxcpath, init_ctx, options)) WARN("Failed to get seccomp policy."); cwd = getcwd(NULL, 0); /* Determine which namespaces the container was created with * by asking lxc-start, if necessary. */ if (options->namespaces == -1) { options->namespaces = lxc_cmd_get_clone_flags(name, lxcpath); /* call failed */ if (options->namespaces == -1) { ERROR("Failed to automatically determine the " "namespaces which the container uses."); free(cwd); lxc_proc_put_context_info(init_ctx); return -1; } } /* Create a socket pair for IPC communication; set SOCK_CLOEXEC in order * to make sure we don't irritate other threads that want to fork+exec * away * * IMPORTANT: if the initial process is multithreaded and another call * just fork()s away without exec'ing directly after, the socket fd will * exist in the forked process from the other thread and any close() in * our own child process will not really cause the socket to close * properly, potentiall causing the parent to hang. * * For this reason, while IPC is still active, we have to use shutdown() * if the child exits prematurely in order to signal that the socket is * closed and cannot assume that the child exiting will automatically do * that. * * IPC mechanism: (X is receiver) * initial process intermediate attached * X <--- send pid of * attached proc, * then exit * send 0 ------------------------------------> X * [do initialization] * X <------------------------------------ send 1 * [add to cgroup, ...] * send 2 ------------------------------------> X * [set LXC_ATTACH_NO_NEW_PRIVS] * X <------------------------------------ send 3 * [open LSM label fd] * send 4 ------------------------------------> X * [set LSM label] * close socket close socket * run program */ ret = socketpair(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); if (ret < 0) { SYSERROR("Could not set up required IPC mechanism for attaching."); free(cwd); lxc_proc_put_context_info(init_ctx); return -1; } /* Create intermediate subprocess, three reasons: * 1. Runs all pthread_atfork handlers and the child will no * longer be threaded (we can't properly setns() in a threaded * process). * 2. We can't setns() in the child itself, since we want to make * sure we are properly attached to the pidns. * 3. Also, the initial thread has to put the attached process * into the cgroup, which we can only do if we didn't already * setns() (otherwise, user namespaces will hate us). */ pid = fork(); if (pid < 0) { SYSERROR("Failed to create first subprocess."); free(cwd); lxc_proc_put_context_info(init_ctx); return -1; } if (pid) { int procfd = -1; pid_t to_cleanup_pid = pid; /* Initial thread, we close the socket that is for the * subprocesses. */ close(ipc_sockets[1]); free(cwd); /* Attach to cgroup, if requested. */ if (options->attach_flags & LXC_ATTACH_MOVE_TO_CGROUP) { if (!cgroup_attach(name, lxcpath, pid)) goto on_error; } /* Open /proc before setns() to the containers namespace so we * don't rely on any information from inside the container. */ procfd = open("/proc", O_DIRECTORY | O_RDONLY | O_CLOEXEC); if (procfd < 0) { SYSERROR("Unable to open /proc."); goto on_error; } /* Let the child process know to go ahead. */ status = 0; ret = lxc_write_nointr(ipc_sockets[0], &status, sizeof(status)); if (ret <= 0) { ERROR("Intended to send sequence number 0: %s.", strerror(errno)); goto on_error; } /* Get pid of attached process from intermediate process. */ ret = lxc_read_nointr_expect(ipc_sockets[0], &attached_pid, sizeof(attached_pid), NULL); if (ret <= 0) { if (ret != 0) ERROR("Expected to receive pid: %s.", strerror(errno)); goto on_error; } /* Ignore SIGKILL (CTRL-C) and SIGQUIT (CTRL-\) - issue #313. */ if (options->stdin_fd == 0) { signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); } /* Reap intermediate process. */ ret = wait_for_pid(pid); if (ret < 0) goto on_error; /* We will always have to reap the attached process now. */ to_cleanup_pid = attached_pid; /* Tell attached process it may start initializing. */ status = 0; ret = lxc_write_nointr(ipc_sockets[0], &status, sizeof(status)); if (ret <= 0) { ERROR("Intended to send sequence number 0: %s.", strerror(errno)); goto on_error; } /* Wait for the attached process to finish initializing. */ expected = 1; ret = lxc_read_nointr_expect(ipc_sockets[0], &status, sizeof(status), &expected); if (ret <= 0) { if (ret != 0) ERROR("Expected to receive sequence number 1: %s.", strerror(errno)); goto on_error; } /* Tell attached process we're done. */ status = 2; ret = lxc_write_nointr(ipc_sockets[0], &status, sizeof(status)); if (ret <= 0) { ERROR("Intended to send sequence number 2: %s.", strerror(errno)); goto on_error; } /* Wait for the (grand)child to tell us that it's ready to set * up its LSM labels. */ expected = 3; ret = lxc_read_nointr_expect(ipc_sockets[0], &status, sizeof(status), &expected); if (ret <= 0) { ERROR("Expected to receive sequence number 3: %s.", strerror(errno)); goto on_error; } /* Open LSM fd and send it to child. */ if ((options->namespaces & CLONE_NEWNS) && (options->attach_flags & LXC_ATTACH_LSM) && init_ctx->lsm_label) { int on_exec, saved_errno; int labelfd = -1; on_exec = options->attach_flags & LXC_ATTACH_LSM_EXEC ? 1 : 0; /* Open fd for the LSM security module. */ labelfd = lsm_openat(procfd, attached_pid, on_exec); if (labelfd < 0) goto on_error; /* Send child fd of the LSM security module to write to. */ ret = lxc_abstract_unix_send_fd(ipc_sockets[0], labelfd, NULL, 0); saved_errno = errno; close(labelfd); if (ret <= 0) { ERROR("Intended to send file descriptor %d: %s.", labelfd, strerror(saved_errno)); goto on_error; } } if (procfd >= 0) close(procfd); /* Now shut down communication with child, we're done. */ shutdown(ipc_sockets[0], SHUT_RDWR); close(ipc_sockets[0]); lxc_proc_put_context_info(init_ctx); /* We're done, the child process should now execute whatever it * is that the user requested. The parent can now track it with * waitpid() or similar. */ *attached_process = attached_pid; return 0; on_error: /* First shut down the socket, then wait for the pid, otherwise * the pid we're waiting for may never exit. */ if (procfd >= 0) close(procfd); shutdown(ipc_sockets[0], SHUT_RDWR); close(ipc_sockets[0]); if (to_cleanup_pid) (void) wait_for_pid(to_cleanup_pid); lxc_proc_put_context_info(init_ctx); return -1; } /* First subprocess begins here, we close the socket that is for the * initial thread. */ close(ipc_sockets[0]); /* Wait for the parent to have setup cgroups. */ expected = 0; status = -1; ret = lxc_read_nointr_expect(ipc_sockets[1], &status, sizeof(status), &expected); if (ret <= 0) { ERROR("Expected to receive sequence number 0: %s.", strerror(errno)); shutdown(ipc_sockets[1], SHUT_RDWR); rexit(-1); } if ((options->attach_flags & LXC_ATTACH_MOVE_TO_CGROUP) && cgns_supported()) options->namespaces |= CLONE_NEWCGROUP; /* Attach now, create another subprocess later, since pid namespaces * only really affect the children of the current process. */ ret = lxc_attach_to_ns(init_pid, options->namespaces); if (ret < 0) { ERROR("Failed to enter namespaces."); shutdown(ipc_sockets[1], SHUT_RDWR); rexit(-1); } /* Attach succeeded, try to cwd. */ if (options->initial_cwd) new_cwd = options->initial_cwd; else new_cwd = cwd; ret = chdir(new_cwd); if (ret < 0) WARN("Could not change directory to \"%s\".", new_cwd); free(cwd); /* Now create the real child process. */ { struct attach_clone_payload payload = { .ipc_socket = ipc_sockets[1], .options = options, .init_ctx = init_ctx, .exec_function = exec_function, .exec_payload = exec_payload }; /* We use clone_parent here to make this subprocess a direct * child of the initial process. Then this intermediate process * can exit and the parent can directly track the attached * process. */ pid = lxc_clone(attach_child_main, &payload, CLONE_PARENT); } /* Shouldn't happen, clone() should always return positive pid. */ if (pid <= 0) { SYSERROR("Failed to create subprocess."); shutdown(ipc_sockets[1], SHUT_RDWR); rexit(-1); } /* Tell grandparent the pid of the pid of the newly created child. */ ret = lxc_write_nointr(ipc_sockets[1], &pid, sizeof(pid)); if (ret != sizeof(pid)) { /* If this really happens here, this is very unfortunate, since * the parent will not know the pid of the attached process and * will not be able to wait for it (and we won't either due to * CLONE_PARENT) so the parent won't be able to reap it and the * attached process will remain a zombie. */ ERROR("Intended to send pid %d: %s.", pid, strerror(errno)); shutdown(ipc_sockets[1], SHUT_RDWR); rexit(-1); } /* The rest is in the hands of the initial and the attached process. */ rexit(0); } static int attach_child_main(void* data) { struct attach_clone_payload* payload = (struct attach_clone_payload*)data; int ipc_socket = payload->ipc_socket; lxc_attach_options_t* options = payload->options; struct lxc_proc_context_info* init_ctx = payload->init_ctx; #if HAVE_SYS_PERSONALITY_H long new_personality; #endif int ret; int status; int expected; long flags; int fd; int lsm_labelfd; uid_t new_uid; gid_t new_gid; /* Wait for the initial thread to signal us that it's ready for us to * start initializing. */ expected = 0; status = -1; ret = lxc_read_nointr_expect(ipc_socket, &status, sizeof(status), &expected); if (ret <= 0) { ERROR("Expected to receive sequence number 0: %s.", strerror(errno)); shutdown(ipc_socket, SHUT_RDWR); rexit(-1); } /* A description of the purpose of this functionality is provided in the * lxc-attach(1) manual page. We have to remount here and not in the * parent process, otherwise /proc may not properly reflect the new pid * namespace. */ if (!(options->namespaces & CLONE_NEWNS) && (options->attach_flags & LXC_ATTACH_REMOUNT_PROC_SYS)) { ret = lxc_attach_remount_sys_proc(); if (ret < 0) { shutdown(ipc_socket, SHUT_RDWR); rexit(-1); } } /* Now perform additional attachments. */ #if HAVE_SYS_PERSONALITY_H if (options->personality < 0) new_personality = init_ctx->personality; else new_personality = options->personality; if (options->attach_flags & LXC_ATTACH_SET_PERSONALITY) { ret = personality(new_personality); if (ret < 0) { SYSERROR("Could not ensure correct architecture."); shutdown(ipc_socket, SHUT_RDWR); rexit(-1); } } #endif if (options->attach_flags & LXC_ATTACH_DROP_CAPABILITIES) { ret = lxc_attach_drop_privs(init_ctx); if (ret < 0) { ERROR("Could not drop privileges."); shutdown(ipc_socket, SHUT_RDWR); rexit(-1); } } /* Always set the environment (specify (LXC_ATTACH_KEEP_ENV, NULL, NULL) * if you want this to be a no-op). */ ret = lxc_attach_set_environment(options->env_policy, options->extra_env_vars, options->extra_keep_env); if (ret < 0) { ERROR("Could not set initial environment for attached process."); shutdown(ipc_socket, SHUT_RDWR); rexit(-1); } /* Set {u,g}id. */ new_uid = 0; new_gid = 0; /* Ignore errors, we will fall back to root in that case (/proc was not * mounted etc.). */ if (options->namespaces & CLONE_NEWUSER) lxc_attach_get_init_uidgid(&new_uid, &new_gid); if (options->uid != (uid_t)-1) new_uid = options->uid; if (options->gid != (gid_t)-1) new_gid = options->gid; /* Setup the controlling tty. */ if (options->stdin_fd && isatty(options->stdin_fd)) { if (setsid() < 0) { SYSERROR("Unable to setsid."); shutdown(ipc_socket, SHUT_RDWR); rexit(-1); } if (ioctl(options->stdin_fd, TIOCSCTTY, (char *)NULL) < 0) { SYSERROR("Unable to set TIOCSTTY."); shutdown(ipc_socket, SHUT_RDWR); rexit(-1); } } /* Try to set the {u,g}id combination. */ if ((new_gid != 0 || options->namespaces & CLONE_NEWUSER)) { if (setgid(new_gid) || setgroups(0, NULL)) { SYSERROR("Switching to container gid."); shutdown(ipc_socket, SHUT_RDWR); rexit(-1); } } if ((new_uid != 0 || options->namespaces & CLONE_NEWUSER) && setuid(new_uid)) { SYSERROR("Switching to container uid."); shutdown(ipc_socket, SHUT_RDWR); rexit(-1); } /* Tell initial process it may now put us into cgroups. */ status = 1; ret = lxc_write_nointr(ipc_socket, &status, sizeof(status)); if (ret != sizeof(status)) { ERROR("Intended to send sequence number 1: %s.", strerror(errno)); shutdown(ipc_socket, SHUT_RDWR); rexit(-1); } /* Wait for the initial thread to signal us that it has done everything * for us when it comes to cgroups etc. */ expected = 2; status = -1; ret = lxc_read_nointr_expect(ipc_socket, &status, sizeof(status), &expected); if (ret <= 0) { ERROR("Expected to receive sequence number 2: %s", strerror(errno)); shutdown(ipc_socket, SHUT_RDWR); rexit(-1); } /* Tell the (grand)parent to send us LSM label fd. */ status = 3; ret = lxc_write_nointr(ipc_socket, &status, sizeof(status)); if (ret <= 0) { ERROR("Intended to send sequence number 3: %s.", strerror(errno)); shutdown(ipc_socket, SHUT_RDWR); rexit(-1); } if ((options->namespaces & CLONE_NEWNS) && (options->attach_flags & LXC_ATTACH_LSM) && init_ctx->lsm_label) { int on_exec; /* Receive fd for LSM security module. */ ret = lxc_abstract_unix_recv_fd(ipc_socket, &lsm_labelfd, NULL, 0); if (ret <= 0) { ERROR("Expected to receive file descriptor: %s.", strerror(errno)); shutdown(ipc_socket, SHUT_RDWR); rexit(-1); } /* Change into our new LSM profile. */ on_exec = options->attach_flags & LXC_ATTACH_LSM_EXEC ? 1 : 0; if (lsm_set_label_at(lsm_labelfd, on_exec, init_ctx->lsm_label) < 0) { SYSERROR("Failed to set LSM label."); shutdown(ipc_socket, SHUT_RDWR); close(lsm_labelfd); rexit(-1); } close(lsm_labelfd); } if (init_ctx->container && init_ctx->container->lxc_conf && lxc_seccomp_load(init_ctx->container->lxc_conf) != 0) { ERROR("Failed to load seccomp policy."); shutdown(ipc_socket, SHUT_RDWR); rexit(-1); } shutdown(ipc_socket, SHUT_RDWR); close(ipc_socket); lxc_proc_put_context_info(init_ctx); /* The following is done after the communication socket is shut down. * That way, all errors that might (though unlikely) occur up until this * point will have their messages printed to the original stderr (if * logging is so configured) and not the fd the user supplied, if any. */ /* Fd handling for stdin, stdout and stderr; ignore errors here, user * may want to make sure the fds are closed, for example. */ if (options->stdin_fd >= 0 && options->stdin_fd != 0) dup2(options->stdin_fd, 0); if (options->stdout_fd >= 0 && options->stdout_fd != 1) dup2(options->stdout_fd, 1); if (options->stderr_fd >= 0 && options->stderr_fd != 2) dup2(options->stderr_fd, 2); /* close the old fds */ if (options->stdin_fd > 2) close(options->stdin_fd); if (options->stdout_fd > 2) close(options->stdout_fd); if (options->stderr_fd > 2) close(options->stderr_fd); /* Try to remove FD_CLOEXEC flag from stdin/stdout/stderr, but also * here, ignore errors. */ for (fd = 0; fd <= 2; fd++) { flags = fcntl(fd, F_GETFL); if (flags < 0) continue; if (flags & FD_CLOEXEC) if (fcntl(fd, F_SETFL, flags & ~FD_CLOEXEC) < 0) SYSERROR("Unable to clear FD_CLOEXEC from file descriptor."); } /* We're done, so we can now do whatever the user intended us to do. */ rexit(payload->exec_function(payload->exec_payload)); } int lxc_attach_run_command(void* payload) { lxc_attach_command_t* cmd = (lxc_attach_command_t*)payload; execvp(cmd->program, cmd->argv); SYSERROR("Failed to exec \"%s\".", cmd->program); return -1; } int lxc_attach_run_shell(void* payload) { uid_t uid; struct passwd *passwd; char *user_shell; /* Ignore payload parameter. */ (void)payload; uid = getuid(); passwd = getpwuid(uid); /* This probably happens because of incompatible nss implementations in * host and container (remember, this code is still using the host's * glibc but our mount namespace is in the container) we may try to get * the information by spawning a [getent passwd uid] process and parsing * the result. */ if (!passwd) user_shell = lxc_attach_getpwshell(uid); else user_shell = passwd->pw_shell; if (user_shell) execlp(user_shell, user_shell, (char *)NULL); /* Executed if either no passwd entry or execvp fails, we will fall back * on /bin/sh as a default shell. */ execlp("/bin/sh", "/bin/sh", (char *)NULL); SYSERROR("Failed to exec shell."); return -1; } lxc-2.0.8/src/lxc/criu.h0000644061062106075000000000227213105116772011736 00000000000000/* * lxc: linux Container library * * Copyright © 2014-2015 Canonical Ltd. * * Authors: * Tycho Andersen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_CRIU_H #define __LXC_CRIU_H #include #include bool __criu_pre_dump(struct lxc_container *c, struct migrate_opts *opts); bool __criu_dump(struct lxc_container *c, struct migrate_opts *opts); bool __criu_restore(struct lxc_container *c, struct migrate_opts *opts); #endif lxc-2.0.8/src/lxc/arguments.h0000644061062106075000000000752313105116772013005 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * Michel Normand * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_ARGUMENTS_H #define __LXC_ARGUMENTS_H #include #include #include #include struct lxc_arguments; typedef int (*lxc_arguments_parser_t) (struct lxc_arguments *, int, char*); typedef int (*lxc_arguments_checker_t) (const struct lxc_arguments *); struct lxc_arguments { const char *help; void(*helpfn)(const struct lxc_arguments *); const char *progname; const struct option* options; lxc_arguments_parser_t parser; lxc_arguments_checker_t checker; const char *name; char *log_file; char *log_priority; int quiet; int daemonize; const char *rcfile; const char *console; const char *console_log; const char *pidfile; const char **lxcpath; int lxcpath_cnt; /* set to 0 to accept only 1 lxcpath, -1 for unlimited */ int lxcpath_additional; /* for lxc-start */ const char *share_ns[32]; // size must be greater than LXC_NS_MAX /* for lxc-console */ unsigned int ttynum; char escape; /* for lxc-wait */ char *states; long timeout; /* for lxc-autostart */ int shutdown; /* for lxc-stop */ int hardstop; int nokill; int nolock; int nowait; int reboot; /* for lxc-destroy */ int force; /* close fds from parent? */ int close_all_fds; /* lxc-create */ char *bdevtype, *configfile, *template; char *fstype; uint64_t fssize; char *lvname, *vgname, *thinpool; char *rbdname, *rbdpool; char *zfsroot, *lowerdir, *dir; /* lxc-execute */ uid_t uid; gid_t gid; /* auto-start */ int all; int ignore_auto; int list; char *groups; /* also used by lxc-ls */ /* lxc-snapshot and lxc-copy */ enum task { CLONE, DESTROY, LIST, RESTORE, SNAP, RENAME, } task; int print_comments; char *commentfile; char *newname; char *newpath; char *snapname; int keepdata; int keepname; int keepmac; /* lxc-ls */ char *ls_fancy_format; char *ls_filter; unsigned int ls_nesting; /* maximum allowed nesting level */ bool ls_active; bool ls_fancy; bool ls_frozen; bool ls_line; bool ls_running; bool ls_stopped; /* remaining arguments */ char *const *argv; int argc; /* private arguments */ void *data; }; #define LXC_COMMON_OPTIONS \ {"name", required_argument, 0, 'n'}, \ {"help", no_argument, 0, 'h'}, \ {"usage", no_argument, 0, OPT_USAGE}, \ {"version", no_argument, 0, OPT_VERSION}, \ {"quiet", no_argument, 0, 'q'}, \ {"logfile", required_argument, 0, 'o'}, \ {"logpriority", required_argument, 0, 'l'}, \ {"lxcpath", required_argument, 0, 'P'}, \ {"rcfile", required_argument, 0, OPT_RCFILE}, \ {0, 0, 0, 0} /* option keys for long only options */ #define OPT_USAGE 0x1000 #define OPT_VERSION OPT_USAGE-1 #define OPT_RCFILE OPT_USAGE-2 extern int lxc_arguments_parse(struct lxc_arguments *args, int argc, char *const argv[]); extern int lxc_arguments_str_to_int(struct lxc_arguments *args, const char *str); #define lxc_error(arg, fmt, args...) if (!(arg)->quiet) \ fprintf(stderr, "%s: " fmt "\n", (arg)->progname, ## args) #endif lxc-2.0.8/src/lxc/error.h0000644061062106075000000000174013105116772012124 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_ERROR_H #define __LXC_ERROR_H extern int lxc_error_set_and_log(int pid, int status); #endif lxc-2.0.8/src/lxc/initutils.h0000644061062106075000000000305013105116772013013 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_INITUTILS_H #define __LXC_INITUTILS_H #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #define DEFAULT_VG "lxc" #define DEFAULT_THIN_POOL "lxc" #define DEFAULT_ZFSROOT "lxc" #define DEFAULT_RBDPOOL "lxc" extern void lxc_setup_fs(void); extern const char *lxc_global_config_value(const char *option_name); /* open a file with O_CLOEXEC */ extern void remove_trailing_slashes(char *p); FILE *fopen_cloexec(const char *path, const char *mode); #endif /* __LXC_INITUTILS_H */ lxc-2.0.8/src/lxc/tools/0000755061062106075000000000000013105117015012027 500000000000000lxc-2.0.8/src/lxc/tools/lxc_clone.c0000644061062106075000000001412113105116772014071 00000000000000/* * * Copyright © 2013 Serge Hallyn . * Copyright © 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include #include #include #include #include #include "log.h" #include "config.h" #include "lxc.h" #include "conf.h" #include "state.h" lxc_log_define(lxc_clone_ui, lxc); /* we pass fssize in bytes */ static uint64_t get_fssize(char *s) { uint64_t ret; char *end; ret = strtoull(s, &end, 0); if (end == s) { fprintf(stderr, "Invalid blockdev size '%s', using default size\n", s); return 0; } while (isblank(*end)) end++; if (*end == '\0') ret *= 1024ULL * 1024ULL; // MB by default else if (*end == 'b' || *end == 'B') ret *= 1ULL; else if (*end == 'k' || *end == 'K') ret *= 1024ULL; else if (*end == 'm' || *end == 'M') ret *= 1024ULL * 1024ULL; else if (*end == 'g' || *end == 'G') ret *= 1024ULL * 1024ULL * 1024ULL; else if (*end == 't' || *end == 'T') ret *= 1024ULL * 1024ULL * 1024ULL * 1024ULL; else { fprintf(stderr, "Invalid blockdev unit size '%c' in '%s', using default size\n", *end, s); return 0; } return ret; } static void usage(const char *me) { printf("Usage: %s [-s] [-B backingstore] [-L size[unit]] [-K] [-M] [-H]\n", me); printf(" [-p lxcpath] [-P newlxcpath] orig new\n"); printf("\n"); printf(" -s: snapshot rather than copy\n"); printf(" -B: use specified new backingstore. Default is the same as\n"); printf(" the original. Options include aufs, btrfs, lvm, overlayfs, \n"); printf(" dir and loop\n"); printf(" -L: for blockdev-backed backingstore, use specified size * specified\n"); printf(" unit. Default size is the size of the source blockdev, default\n"); printf(" unit is MB\n"); printf(" -K: Keep name - do not change the container name\n"); printf(" -M: Keep macaddr - do not choose a random new mac address\n"); printf(" -p: use container orig from custom lxcpath\n"); printf(" -P: create container new in custom lxcpath\n"); printf(" -R: rename existing container\n"); exit(EXIT_SUCCESS); } static struct option options[] = { { "snapshot", no_argument, 0, 's'}, { "backingstore", required_argument, 0, 'B'}, { "size", required_argument, 0, 'L'}, { "orig", required_argument, 0, 'o'}, { "new", required_argument, 0, 'n'}, { "vgname", required_argument, 0, 'v'}, { "rename", no_argument, 0, 'R'}, { "keepname", no_argument, 0, 'K'}, { "keepmac", no_argument, 0, 'M'}, { "lxcpath", required_argument, 0, 'p'}, { "newpath", required_argument, 0, 'P'}, { "fstype", required_argument, 0, 't'}, { "help", no_argument, 0, 'h'}, { 0, 0, 0, 0 }, }; int main(int argc, char *argv[]) { struct lxc_container *c1 = NULL, *c2 = NULL; int snapshot = 0, keepname = 0, keepmac = 0, rename = 0; int flags = 0, option_index; uint64_t newsize = 0; char *bdevtype = NULL, *lxcpath = NULL, *newpath = NULL, *fstype = NULL; char *orig = NULL, *new = NULL, *vgname = NULL; char **args = NULL; int c; bool ret; fprintf(stderr, "lxc-clone is deprecated in favor of lxc-copy.\n\n"); if (argc < 3) usage(argv[0]); while (1) { c = getopt_long(argc, argv, "sB:L:o:n:v:KMHp:P:Rt:h", options, &option_index); if (c == -1) break; switch (c) { case 's': snapshot = 1; break; case 'B': bdevtype = optarg; break; case 'L': newsize = get_fssize(optarg); break; case 'o': orig = optarg; break; case 'n': new = optarg; break; case 'v': vgname = optarg; break; case 'K': keepname = 1; break; case 'M': keepmac = 1; break; case 'p': lxcpath = optarg; break; case 'P': newpath = optarg; break; case 'R': rename = 1; break; case 't': fstype = optarg; break; case 'h': usage(argv[0]); default: break; } } if (optind < argc && !orig) orig = argv[optind++]; if (optind < argc && !new) new = argv[optind++]; if (optind < argc) /* arguments for the clone hook */ args = &argv[optind]; if (!new || !orig) { printf("Error: you must provide orig and new names\n"); usage(argv[0]); } if (snapshot) flags |= LXC_CLONE_SNAPSHOT; if (keepname) flags |= LXC_CLONE_KEEPNAME; if (keepmac) flags |= LXC_CLONE_KEEPMACADDR; // vgname and fstype could be supported by sending them through the // bdevdata. However, they currently are not yet. I'm not convinced // they are worthwhile. if (vgname) { printf("Error: vgname not supported\n"); usage(argv[0]); } if (fstype) { printf("Error: fstype not supported\n"); usage(argv[0]); } c1 = lxc_container_new(orig, lxcpath); if (!c1) exit(EXIT_FAILURE); if (!c1->may_control(c1)) { fprintf(stderr, "Insufficent privileges to control %s\n", orig); lxc_container_put(c1); exit(EXIT_FAILURE); } if (!c1->is_defined(c1)) { fprintf(stderr, "Error: container %s is not defined\n", orig); lxc_container_put(c1); exit(EXIT_FAILURE); } if (rename) { ret = c1->rename(c1, new); if (!ret) { fprintf(stderr, "Error: Renaming container %s to %s failed\n", c1->name, new); lxc_container_put(c1); exit(EXIT_FAILURE); } } else { c2 = c1->clone(c1, new, newpath, flags, bdevtype, NULL, newsize, args); if (c2 == NULL) { lxc_container_put(c1); fprintf(stderr, "clone failed\n"); exit(EXIT_FAILURE); } printf("Created container %s as %s of %s\n", new, snapshot ? "snapshot" : "copy", orig); lxc_container_put(c2); } lxc_container_put(c1); exit(EXIT_SUCCESS); } lxc-2.0.8/src/lxc/tools/lxc_config.c0000644061062106075000000000414213105116772014240 00000000000000/* lxc_config * * Copyright © 2012 Serge Hallyn . * Copyright © 2012 Canonical Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include "config.h" struct lxc_config_items { char *name; }; static struct lxc_config_items items[] = { { .name = "lxc.default_config", }, { .name = "lxc.lxcpath", }, { .name = "lxc.bdev.lvm.vg", }, { .name = "lxc.bdev.lvm.thin_pool", }, { .name = "lxc.bdev.zfs.root", }, { .name = "lxc.cgroup.use", }, { .name = "lxc.cgroup.pattern", }, { .name = NULL, }, }; static void usage(char *me) { printf("Usage: %s -l: list all available configuration items\n", me); printf(" %s item: print configuration item\n", me); exit(EXIT_SUCCESS); } static void list_config_items(void) { struct lxc_config_items *i; for (i = &items[0]; i->name; i++) printf("%s\n", i->name); exit(EXIT_SUCCESS); } int main(int argc, char *argv[]) { struct lxc_config_items *i; const char *value; if (argc < 2) usage(argv[0]); if (strcmp(argv[1], "-l") == 0) list_config_items(); for (i = &items[0]; i->name; i++) { if (strcmp(argv[1], i->name) == 0) { value = lxc_get_global_config_item(i->name); if (value) printf("%s\n", value); else printf("%s is not set.\n", argv[1]); exit(EXIT_SUCCESS); } } printf("Unknown configuration item: %s\n", argv[1]); exit(EXIT_FAILURE); } lxc-2.0.8/src/lxc/tools/lxc_stop.c0000644061062106075000000001420213105116772013756 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include "lxc.h" #include "log.h" #include "arguments.h" #include "commands.h" #include "utils.h" #define OPT_NO_LOCK OPT_USAGE + 1 #define OPT_NO_KILL OPT_USAGE + 2 lxc_log_define(lxc_stop_ui, lxc); static int my_parser(struct lxc_arguments *args, int c, char *arg) { switch (c) { case 'r': args->reboot = 1; break; case 'W': args->nowait = 1; break; case 't': if (lxc_safe_long(arg, &args->timeout) < 0) return -1; break; case 'k': args->hardstop = 1; break; case OPT_NO_LOCK: args->nolock = 1; break; case OPT_NO_KILL: args->nokill = 1; break; } return 0; } static const struct option my_longopts[] = { {"reboot", no_argument, 0, 'r'}, {"nowait", no_argument, 0, 'W'}, {"timeout", required_argument, 0, 't'}, {"kill", no_argument, 0, 'k'}, {"nokill", no_argument, 0, OPT_NO_KILL}, {"nolock", no_argument, 0, OPT_NO_LOCK}, LXC_COMMON_OPTIONS }; static struct lxc_arguments my_args = { .progname = "lxc-stop", .help = "\ --name=NAME\n\ \n\ lxc-stop stops a container with the identifier NAME\n\ \n\ Options :\n\ -n, --name=NAME NAME of the container\n\ -r, --reboot reboot the container\n\ -W, --nowait don't wait for shutdown or reboot to complete\n\ -t, --timeout=T wait T seconds before hard-stopping\n\ -k, --kill kill container rather than request clean shutdown\n\ --nolock Avoid using API locks\n\ --nokill Only request clean shutdown, don't force kill after timeout\n\ --rcfile=FILE Load configuration file FILE\n", .options = my_longopts, .parser = my_parser, .checker = NULL, .timeout = -2, }; /* returns -1 on failure, 0 on success */ static int do_reboot_and_check(struct lxc_arguments *a, struct lxc_container *c) { int ret; pid_t pid; pid_t newpid; int timeout = a->timeout; pid = c->init_pid(c); if (pid == -1) return -1; if (!c->reboot(c)) return -1; if (a->nowait) return 0; if (timeout == 0) goto out; for (;;) { /* can we use c-> wait for this, assuming it will * re-enter RUNNING? For now just sleep */ int elapsed_time, curtime = 0; struct timeval tv; newpid = c->init_pid(c); if (newpid != -1 && newpid != pid) return 0; if (timeout != -1) { ret = gettimeofday(&tv, NULL); if (ret) break; curtime = tv.tv_sec; } sleep(1); if (timeout != -1) { ret = gettimeofday(&tv, NULL); if (ret) break; elapsed_time = tv.tv_sec - curtime; if (timeout - elapsed_time <= 0) break; timeout -= elapsed_time; } } out: newpid = c->init_pid(c); if (newpid == -1 || newpid == pid) { printf("Reboot did not complete before timeout\n"); return -1; } return 0; } int main(int argc, char *argv[]) { struct lxc_container *c; bool s; int ret = EXIT_FAILURE; if (lxc_arguments_parse(&my_args, argc, argv)) exit(ret); if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority, my_args.progname, my_args.quiet, my_args.lxcpath[0])) exit(ret); lxc_log_options_no_override(); /* Set default timeout */ if (my_args.timeout == -2) { if (my_args.hardstop) my_args.timeout = 0; else my_args.timeout = 60; } if (my_args.nowait) my_args.timeout = 0; /* some checks */ if (!my_args.hardstop && my_args.timeout < -1) { fprintf(stderr, "invalid timeout\n"); exit(ret); } if (my_args.hardstop && my_args.nokill) { fprintf(stderr, "-k can't be used with --nokill\n"); exit(ret); } if (my_args.hardstop && my_args.reboot) { fprintf(stderr, "-k can't be used with -r\n"); exit(ret); } if (my_args.hardstop && my_args.timeout) { fprintf(stderr, "-k doesn't allow timeouts\n"); exit(ret); } if (my_args.nolock && !my_args.hardstop) { fprintf(stderr, "--nolock may only be used with -k\n"); exit(ret); } /* shortcut - if locking is bogus, we should be able to kill * containers at least */ if (my_args.nolock) { ret = lxc_cmd_stop(my_args.name, my_args.lxcpath[0]); exit(ret); } c = lxc_container_new(my_args.name, my_args.lxcpath[0]); if (!c) { fprintf(stderr, "Error opening container\n"); goto out; } if (my_args.rcfile) { c->clear_config(c); if (!c->load_config(c, my_args.rcfile)) { fprintf(stderr, "Failed to load rcfile\n"); goto out; } c->configfile = strdup(my_args.rcfile); if (!c->configfile) { fprintf(stderr, "Out of memory setting new config filename\n"); goto out; } } if (!c->may_control(c)) { fprintf(stderr, "Insufficent privileges to control %s\n", c->name); goto out; } if (!c->is_running(c)) { fprintf(stderr, "%s is not running\n", c->name); /* Per our manpage we need to exit with exit code: * 2: The specified container exists but was not running. */ ret = 2; goto out; } /* kill */ if (my_args.hardstop) { ret = c->stop(c) ? EXIT_SUCCESS : EXIT_FAILURE; goto out; } /* reboot */ if (my_args.reboot) { ret = do_reboot_and_check(&my_args, c) < 0 ? EXIT_SUCCESS : EXIT_FAILURE; goto out; } /* shutdown */ s = c->shutdown(c, my_args.timeout); if (!s) { if (my_args.timeout == 0) ret = EXIT_SUCCESS; else if (my_args.nokill) ret = EXIT_FAILURE; else ret = c->stop(c) ? EXIT_SUCCESS : EXIT_FAILURE; } else { ret = EXIT_SUCCESS; } out: lxc_container_put(c); exit(ret); } lxc-2.0.8/src/lxc/tools/lxc_checkpoint.c0000644061062106075000000001317613105116772015131 00000000000000/* * * Copyright © 2014 Tycho Andersen . * Copyright © 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include "log.h" #include "config.h" #include "lxc.h" #include "arguments.h" #include "utils.h" static char *checkpoint_dir = NULL; static bool stop = false; static bool verbose = false; static bool do_restore = false; static bool daemonize_set = false; static const struct option my_longopts[] = { {"checkpoint-dir", required_argument, 0, 'D'}, {"stop", no_argument, 0, 's'}, {"verbose", no_argument, 0, 'v'}, {"restore", no_argument, 0, 'r'}, {"daemon", no_argument, 0, 'd'}, {"foreground", no_argument, 0, 'F'}, LXC_COMMON_OPTIONS }; static int my_checker(const struct lxc_arguments *args) { if (do_restore && stop) { lxc_error(args, "-s not compatible with -r."); return -1; } else if (!do_restore && daemonize_set) { lxc_error(args, "-d/-F not compatible with -r."); return -1; } if (checkpoint_dir == NULL) { lxc_error(args, "-D is required."); return -1; } return 0; } static int my_parser(struct lxc_arguments *args, int c, char *arg) { switch (c) { case 'D': checkpoint_dir = strdup(arg); if (!checkpoint_dir) return -1; break; case 's': stop = true; break; case 'v': verbose = true; break; case 'r': do_restore = true; break; case 'd': args->daemonize = 1; daemonize_set = true; break; case 'F': args->daemonize = 0; daemonize_set = true; break; } return 0; } static struct lxc_arguments my_args = { .progname = "lxc-checkpoint", .help = "\ --name=NAME\n\ \n\ lxc-checkpoint checkpoints and restores a container\n\ Serializes a container's running state to disk to allow restoring it in\n\ its running state at a later time.\n\ \n\ Options :\n\ -n, --name=NAME NAME of the container\n\ -r, --restore Restore container\n\ -D, --checkpoint-dir=DIR directory to save the checkpoint in\n\ -v, --verbose Enable verbose criu logs\n\ Checkpoint options:\n\ -s, --stop Stop the container after checkpointing.\n\ Restore options:\n\ -d, --daemon Daemonize the container (default)\n\ -F, --foreground Start with the current tty attached to /dev/console\n\ --rcfile=FILE Load configuration file FILE\n\ ", .options = my_longopts, .parser = my_parser, .daemonize = 1, .checker = my_checker, }; static bool checkpoint(struct lxc_container *c) { bool ret; if (!c->is_running(c)) { fprintf(stderr, "%s not running, not checkpointing.\n", my_args.name); lxc_container_put(c); return false; } ret = c->checkpoint(c, checkpoint_dir, stop, verbose); lxc_container_put(c); if (!ret) { fprintf(stderr, "Checkpointing %s failed.\n", my_args.name); return false; } return true; } static bool restore_finalize(struct lxc_container *c) { 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; } static 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) { pid_t pid; pid = fork(); if (pid < 0) { perror("fork"); return false; } if (pid == 0) { close(0); close(1); exit(!restore_finalize(c)); } else { return wait_for_pid(pid) == 0; } } else { int status; if (!restore_finalize(c)) return false; if (waitpid(-1, &status, 0) < 0) return false; return WIFEXITED(status) && WEXITSTATUS(status) == 0; } } int main(int argc, char *argv[]) { struct lxc_container *c; bool ret; if (lxc_arguments_parse(&my_args, argc, argv)) exit(EXIT_FAILURE); if (!my_args.log_file) my_args.log_file = "none"; if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority, my_args.progname, my_args.quiet, my_args.lxcpath[0])) exit(EXIT_FAILURE); lxc_log_options_no_override(); c = lxc_container_new(my_args.name, my_args.lxcpath[0]); if (!c) { fprintf(stderr, "System error loading %s\n", my_args.name); exit(EXIT_FAILURE); } if (my_args.rcfile) { c->clear_config(c); if (!c->load_config(c, my_args.rcfile)) { fprintf(stderr, "Failed to load rcfile\n"); lxc_container_put(c); exit(EXIT_FAILURE); } c->configfile = strdup(my_args.rcfile); if (!c->configfile) { fprintf(stderr, "Out of memory setting new config filename\n"); lxc_container_put(c); exit(EXIT_FAILURE); } } if (!c->may_control(c)) { fprintf(stderr, "Insufficent privileges to control %s\n", my_args.name); lxc_container_put(c); exit(EXIT_FAILURE); } if (!c->is_defined(c)) { fprintf(stderr, "%s is not defined\n", my_args.name); lxc_container_put(c); exit(EXIT_FAILURE); } if (do_restore) ret = restore(c); else ret = checkpoint(c); if (!ret) exit(EXIT_FAILURE); exit(EXIT_SUCCESS); } lxc-2.0.8/src/lxc/tools/lxc_info.c0000644061062106075000000002344413105116772013734 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include "lxc.h" #include "log.h" #include "utils.h" #include "commands.h" #include "arguments.h" lxc_log_define(lxc_info_ui, lxc); static bool ips; static bool state; static bool pid; static bool stats; static bool humanize = true; static char **key = NULL; static int keys = 0; static int filter_count = 0; static int my_parser(struct lxc_arguments* args, int c, char* arg) { char **newk; switch (c) { case 'c': newk = realloc(key, (keys + 1) * sizeof(key[0])); if (!newk) return -1; key = newk; key[keys] = arg; keys++; break; case 'i': ips = true; filter_count += 1; break; case 's': state = true; filter_count += 1; break; case 'p': pid = true; filter_count += 1; break; case 'S': stats = true; filter_count += 5; break; case 'H': humanize = false; break; } return 0; } static const struct option my_longopts[] = { {"config", required_argument, 0, 'c'}, {"ips", no_argument, 0, 'i'}, {"state", no_argument, 0, 's'}, {"pid", no_argument, 0, 'p'}, {"stats", no_argument, 0, 'S'}, {"no-humanize", no_argument, 0, 'H'}, LXC_COMMON_OPTIONS, }; static struct lxc_arguments my_args = { .progname = "lxc-info", .help = "\ --name=NAME\n\ \n\ lxc-info display some information about a container with the identifier NAME\n\ \n\ Options :\n\ -n, --name=NAME NAME of the container\n\ -c, --config=KEY show configuration variable KEY from running container\n\ -i, --ips shows the IP addresses\n\ -p, --pid shows the process id of the init container\n\ -S, --stats shows usage stats\n\ -H, --no-humanize shows stats as raw numbers, not humanized\n\ -s, --state shows the state of the container\n\ --rcfile=FILE Load configuration file FILE\n", .name = NULL, .options = my_longopts, .parser = my_parser, .checker = NULL, }; static void str_chomp(char *buf) { char *ch; /* remove trailing whitespace from buf */ for(ch = &buf[strlen(buf)-1]; ch >= buf && (*ch == '\t' || *ch == '\n' || *ch == ' '); ch--) *ch = '\0'; } static void size_humanize(unsigned long long val, char *buf, size_t bufsz) { if (val > 1 << 30) { snprintf(buf, bufsz, "%u.%2.2u GiB", (int)(val >> 30), (int)(val & ((1 << 30) - 1)) / 10737419); } else if (val > 1 << 20) { int x = val + 5243; /* for rounding */ snprintf(buf, bufsz, "%u.%2.2u MiB", x >> 20, ((x & ((1 << 20) - 1)) * 100) >> 20); } else if (val > 1 << 10) { int x = val + 5; /* for rounding */ snprintf(buf, bufsz, "%u.%2.2u KiB", x >> 10, ((x & ((1 << 10) - 1)) * 100) >> 10); } else { snprintf(buf, bufsz, "%u bytes", (int)val); } } static unsigned long long str_size_humanize(char *iobuf, size_t iobufsz) { unsigned long long val; char *end = NULL; val = strtoull(iobuf, &end, 0); if (humanize) { if (*end == '\0' || *end == '\n') size_humanize(val, iobuf, iobufsz); else *iobuf = '\0'; } return val; } static void print_net_stats(struct lxc_container *c) { int rc,netnr; unsigned long long rx_bytes = 0, tx_bytes = 0; char *ifname, *type; char path[PATH_MAX]; char buf[256]; for(netnr = 0; ;netnr++) { sprintf(buf, "lxc.network.%d.type", netnr); type = c->get_running_config_item(c, buf); if (!type) break; if (!strcmp(type, "veth")) { sprintf(buf, "lxc.network.%d.veth.pair", netnr); } else { sprintf(buf, "lxc.network.%d.link", netnr); } free(type); ifname = c->get_running_config_item(c, buf); if (!ifname) return; printf("%-15s %s\n", "Link:", ifname); fflush(stdout); /* XXX: tx and rx are reversed from the host vs container * perspective, print them from the container perspective */ snprintf(path, sizeof(path), "/sys/class/net/%s/statistics/rx_bytes", ifname); rc = lxc_read_from_file(path, buf, sizeof(buf)); if (rc > 0) { str_chomp(buf); rx_bytes = str_size_humanize(buf, sizeof(buf)); printf("%-15s %s\n", " TX bytes:", buf); fflush(stdout); } snprintf(path, sizeof(path), "/sys/class/net/%s/statistics/tx_bytes", ifname); rc = lxc_read_from_file(path, buf, sizeof(buf)); if (rc > 0) { str_chomp(buf); tx_bytes = str_size_humanize(buf, sizeof(buf)); printf("%-15s %s\n", " RX bytes:", buf); fflush(stdout); } sprintf(buf, "%llu", rx_bytes + tx_bytes); str_size_humanize(buf, sizeof(buf)); printf("%-15s %s\n", " Total bytes:", buf); fflush(stdout); free(ifname); } } static void print_stats(struct lxc_container *c) { int i, ret; char buf[4096]; ret = c->get_cgroup_item(c, "cpuacct.usage", buf, sizeof(buf)); if (ret > 0 && ret < sizeof(buf)) { str_chomp(buf); if (humanize) { float seconds = strtof(buf, NULL) / 1000000000.0; printf("%-15s %.2f seconds\n", "CPU use:", seconds); } else { printf("%-15s %s\n", "CPU use:", buf); } fflush(stdout); } ret = c->get_cgroup_item(c, "blkio.throttle.io_service_bytes", buf, sizeof(buf)); if (ret > 0 && ret < sizeof(buf)) { char *ch; /* put ch on last "Total" line */ str_chomp(buf); for(ch = &buf[strlen(buf)-1]; ch > buf && *ch != '\n'; ch--) ; if (*ch == '\n') ch++; if (strncmp(ch, "Total", 5) == 0) { ch += 6; memmove(buf, ch, strlen(ch)+1); str_size_humanize(buf, sizeof(buf)); printf("%-15s %s\n", "BlkIO use:", buf); } fflush(stdout); } static const struct { const char *name; const char *file; } lxstat[] = { { "Memory use:", "memory.usage_in_bytes" }, { "KMem use:", "memory.kmem.usage_in_bytes" }, { NULL, NULL }, }; for (i = 0; lxstat[i].name; i++) { ret = c->get_cgroup_item(c, lxstat[i].file, buf, sizeof(buf)); if (ret > 0 && ret < sizeof(buf)) { str_chomp(buf); str_size_humanize(buf, sizeof(buf)); printf("%-15s %s\n", lxstat[i].name, buf); fflush(stdout); } } } static void print_info_msg_int(const char *key, int value) { if (humanize) printf("%-15s %d\n", key, value); else { if (filter_count == 1) printf("%d\n", value); else printf("%-15s %d\n", key, value); } fflush(stdout); } static void print_info_msg_str(const char *key, const char *value) { if (humanize) printf("%-15s %s\n", key, value); else { if (filter_count == 1) printf("%s\n", value); else printf("%-15s %s\n", key, value); } fflush(stdout); } static int print_info(const char *name, const char *lxcpath) { int i; struct lxc_container *c; c = lxc_container_new(name, lxcpath); if (!c) { fprintf(stderr, "Failure to retrieve information on %s:%s\n", lxcpath ? lxcpath : "null", name ? name : "null"); return -1; } if (my_args.rcfile) { c->clear_config(c); if (!c->load_config(c, my_args.rcfile)) { fprintf(stderr, "Failed to load rcfile\n"); lxc_container_put(c); return -1; } c->configfile = strdup(my_args.rcfile); if (!c->configfile) { fprintf(stderr, "Out of memory setting new config filename\n"); lxc_container_put(c); return -1; } } if (!c->may_control(c)) { fprintf(stderr, "Insufficent privileges to control %s\n", c->name); lxc_container_put(c); return -1; } if (!c->is_running(c) && !c->is_defined(c)) { fprintf(stderr, "%s doesn't exist\n", c->name); lxc_container_put(c); return -1; } if (!state && !pid && !ips && !stats && keys <= 0) { state = pid = ips = stats = true; print_info_msg_str("Name:", c->name); } if (state) { print_info_msg_str("State:", c->state(c)); } if (c->is_running(c)) { if (pid) { pid_t initpid; initpid = c->init_pid(c); if (initpid >= 0) print_info_msg_int("PID:", initpid); } if (ips) { fflush(stdout); char **addresses = c->get_ips(c, NULL, NULL, 0); if (addresses) { char *address; i = 0; while (addresses[i]) { address = addresses[i]; print_info_msg_str("IP:", address); i++; } } } } if (stats) { print_stats(c); print_net_stats(c); } for(i = 0; i < keys; i++) { int len = c->get_config_item(c, key[i], NULL, 0); if (len > 0) { char *val = (char*) malloc(sizeof(char)*len + 1); if (c->get_config_item(c, key[i], val, len + 1) != len) { fprintf(stderr, "unable to read %s from configuration\n", key[i]); } else { if (!humanize && keys == 1) printf("%s\n", val); else printf("%s = %s\n", key[i], val); } free(val); } else if (len == 0) { if (!humanize && keys == 1) printf("\n"); else printf("%s =\n", key[i]); } else { fprintf(stderr, "%s invalid\n", key[i]); } fflush(stdout); } lxc_container_put(c); return 0; } int main(int argc, char *argv[]) { int ret = EXIT_FAILURE; if (lxc_arguments_parse(&my_args, argc, argv)) exit(ret); if (!my_args.log_file) my_args.log_file = "none"; if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority, my_args.progname, my_args.quiet, my_args.lxcpath[0])) exit(ret); lxc_log_options_no_override(); if (print_info(my_args.name, my_args.lxcpath[0]) == 0) ret = EXIT_SUCCESS; exit(ret); } lxc-2.0.8/src/lxc/tools/lxc-top.lua0000755061062106075000000001643513105116772014065 00000000000000#!/usr/bin/env lua -- -- top(1) like monitor for lxc containers -- -- Copyright © 2012 Oracle. -- -- Authors: -- Dwight Engen -- -- This library is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 2, as -- published by the Free Software Foundation. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along -- with this program; if not, write to the Free Software Foundation, Inc., -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -- local lxc = require("lxc") local core = require("lxc.core") local getopt = require("alt_getopt") local USER_HZ = 100 local ESC = string.format("%c", 27) local TERMCLEAR = ESC.."[H"..ESC.."[J" local TERMNORM = ESC.."[0m" local TERMBOLD = ESC.."[1m" local TERMRVRS = ESC.."[7m" local containers = {} local stats = {} local stats_total = {} local max_containers function printf(...) local function wrapper(...) io.write(string.format(...)) end local status, result = pcall(wrapper, ...) if not status then error(result, 2) end end function string:split(delim, max_cols) local cols = {} local start = 1 local nextc repeat nextc = string.find(self, delim, start) if (nextc and #cols ~= max_cols - 1) then table.insert(cols, string.sub(self, start, nextc-1)) start = nextc + #delim else table.insert(cols, string.sub(self, start, string.len(self))) nextc = nil end until nextc == nil or start > #self return cols end function strsisize(size, width) local KiB = 1024 local MiB = 1048576 local GiB = 1073741824 local TiB = 1099511627776 local PiB = 1125899906842624 local EiB = 1152921504606846976 local ZiB = 1180591620717411303424 if (size >= ZiB) then return string.format("%d.%2.2d ZB", size / ZiB, (math.floor(size % ZiB) * 100) / ZiB) end if (size >= EiB) then return string.format("%d.%2.2d EB", size / EiB, (math.floor(size % EiB) * 100) / EiB) end if (size >= PiB) then return string.format("%d.%2.2d PB", size / PiB, (math.floor(size % PiB) * 100) / PiB) end if (size >= TiB) then return string.format("%d.%2.2d TB", size / TiB, (math.floor(size % TiB) * 100) / TiB) end if (size >= GiB) then return string.format("%d.%2.2d GB", size / GiB, (math.floor(size % GiB) * 100) / GiB) end if (size >= MiB) then return string.format("%d.%2.2d MB", size / MiB, (math.floor(size % MiB) * 1000) / (MiB * 10)) end if (size >= KiB) then return string.format("%d.%2.2d KB", size / KiB, (math.floor(size % KiB) * 1000) / (KiB * 10)) end return string.format("%3d.00 ", size) end function tty_lines() local rows = 25 local f = assert(io.popen("stty -a | head -n 1")) for line in f:lines() do local stty_rows _,_,stty_rows = string.find(line, "rows (%d+)") if (stty_rows ~= nil) then rows = stty_rows break end end f:close() return rows end function container_sort(a, b) if (optarg["r"]) then if (optarg["s"] == "n") then return (a > b) elseif (optarg["s"] == "c") then return (stats[a].cpu_use_nanos < stats[b].cpu_use_nanos) elseif (optarg["s"] == "d") then return (stats[a].blkio < stats[b].blkio) elseif (optarg["s"] == "m") then return (stats[a].mem_used < stats[b].mem_used) elseif (optarg["s"] == "k") then return (stats[a].kmem_used < stats[b].kmem_used) end else if (optarg["s"] == "n") then return (a < b) elseif (optarg["s"] == "c") then return (stats[a].cpu_use_nanos > stats[b].cpu_use_nanos) elseif (optarg["s"] == "d") then return (stats[a].blkio > stats[b].blkio) elseif (optarg["s"] == "m") then return (stats[a].mem_used > stats[b].mem_used) elseif (optarg["s"] == "k") then return (stats[a].kmem_used > stats[b].kmem_used) end end end function container_list_update() local now_running now_running = lxc.containers_running(true) -- check for newly started containers for _,v in ipairs(now_running) do if (containers[v] == nil) then local ct = lxc.container:new(v) -- note, this is a "mixed" table, ie both dictionary and list containers[v] = ct table.insert(containers, v) end end -- check for newly stopped containers local indx = 1 while (indx <= #containers) do local ctname = containers[indx] if (now_running[ctname] == nil) then containers[ctname] = nil stats[ctname] = nil table.remove(containers, indx) else indx = indx + 1 end end -- get stats for all current containers and resort the list lxc.stats_clear(stats_total) for _,ctname in ipairs(containers) do stats[ctname] = containers[ctname]:stats_get(stats_total) end table.sort(containers, container_sort) end function stats_print_header(stats_total) printf(TERMRVRS .. TERMBOLD) printf("%-15s %8s %8s %8s %10s %10s", "Container", "CPU", "CPU", "CPU", "BlkIO", "Mem") if (stats_total.kmem_used > 0) then printf(" %10s", "KMem") end printf("\n") printf("%-15s %8s %8s %8s %10s %10s", "Name", "Used", "Sys", "User", "Total", "Used") if (stats_total.kmem_used > 0) then printf(" %10s", "Used") end printf("\n") printf(TERMNORM) end function stats_print(name, stats, stats_total) printf("%-15s %8.2f %8.2f %8.2f %10s %10s", name, stats.cpu_use_nanos / 1000000000, stats.cpu_use_sys / USER_HZ, stats.cpu_use_user / USER_HZ, strsisize(stats.blkio), strsisize(stats.mem_used)) if (stats_total.kmem_used > 0) then printf(" %10s", strsisize(stats.kmem_used)) end end function usage() printf("Usage: lxc-top [options]\n" .. " -h|--help print this help message\n" .. " -m|--max display maximum number of containers\n" .. " -d|--delay delay in seconds between refreshes (default: 3.0)\n" .. " -s|--sort sort by [n,c,d,m] (default: n) where\n" .. " n = Name\n" .. " c = CPU use\n" .. " d = Disk I/O use\n" .. " m = Memory use\n" .. " k = Kernel memory use\n" .. " -r|--reverse sort in reverse (descending) order\n" ) os.exit(1) end local long_opts = { help = "h", delay = "d", max = "m", reverse = "r", sort = "s", } optarg,optind = alt_getopt.get_opts (arg, "hd:m:rs:", long_opts) optarg["d"] = tonumber(optarg["d"]) or 3.0 optarg["m"] = tonumber(optarg["m"]) or tonumber(tty_lines() - 3) optarg["r"] = optarg["r"] or false optarg["s"] = optarg["s"] or "n" if (optarg["h"] ~= nil) then usage() end while true do container_list_update() -- if some terminal we care about doesn't support the simple escapes, we -- may fall back to this, or ncurses. ug. --os.execute("tput clear") printf(TERMCLEAR) stats_print_header(stats_total) for index,ctname in ipairs(containers) do stats_print(ctname, stats[ctname], stats_total) printf("\n") if (index >= optarg["m"]) then break end end stats_print(string.format("TOTAL (%-2d)", #containers), stats_total, stats_total) io.flush() core.usleep(optarg["d"] * 1000000) end lxc-2.0.8/src/lxc/tools/lxc_top.c0000644061062106075000000003007613105116772013602 00000000000000/* * lxc: linux Container library * * Copyright © 2014 Oracle. * * Authors: * Dwight Engen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include "arguments.h" #include "log.h" #include "lxc.h" #include "mainloop.h" #include "utils.h" lxc_log_define(lxc_top_ui, lxc); #define USER_HZ 100 #define ESC "\033" #define TERMCLEAR ESC "[H" ESC "[J" #define TERMNORM ESC "[0m" #define TERMBOLD ESC "[1m" #define TERMRVRS ESC "[7m" struct stats { uint64_t mem_used; uint64_t mem_limit; uint64_t kmem_used; uint64_t kmem_limit; uint64_t cpu_use_nanos; uint64_t cpu_use_user; uint64_t cpu_use_sys; uint64_t blkio; }; struct ct { struct lxc_container *c; struct stats *stats; }; static int delay = 3; static char sort_by = 'n'; static int sort_reverse = 0; static struct termios oldtios; static struct ct *ct = NULL; static int ct_alloc_cnt = 0; static int my_parser(struct lxc_arguments* args, int c, char* arg) { switch (c) { case 'd': if (lxc_safe_int(arg, &delay) < 0) return -1; break; case 's': sort_by = arg[0]; break; case 'r': sort_reverse = 1; break; } return 0; } static const struct option my_longopts[] = { {"delay", required_argument, 0, 'd'}, {"sort", required_argument, 0, 's'}, {"reverse", no_argument, 0, 'r'}, LXC_COMMON_OPTIONS }; static struct lxc_arguments my_args = { .progname = "lxc-top", .help = "\ \n\ \n\ lxc-top monitors the state of the active containers\n\ \n\ Options :\n\ -d, --delay delay in seconds between refreshes (default: 3.0)\n\ -s, --sort sort by [n,c,b,m] (default: n) where\n\ n = Name\n\ c = CPU use\n\ b = Block I/O use\n\ m = Memory use\n\ k = Kernel memory use\n\ -r, --reverse sort in reverse (descending) order\n", .name = ".*", .options = my_longopts, .parser = my_parser, .checker = NULL, .lxcpath_additional = -1, }; static void stdin_tios_restore(void) { tcsetattr(0, TCSAFLUSH, &oldtios); fprintf(stderr, "\n"); } static int stdin_tios_setup(void) { struct termios newtios; if (!isatty(0)) { ERROR("stdin is not a tty"); return -1; } if (tcgetattr(0, &oldtios)) { SYSERROR("failed to get current terminal settings"); return -1; } newtios = oldtios; /* turn off echo and line buffering */ newtios.c_iflag &= ~IGNBRK; newtios.c_iflag &= BRKINT; newtios.c_lflag &= ~(ECHO|ICANON); newtios.c_cc[VMIN] = 1; newtios.c_cc[VTIME] = 0; if (tcsetattr(0, TCSAFLUSH, &newtios)) { ERROR("failed to set new terminal settings"); return -1; } return 0; } static int stdin_tios_rows(void) { struct winsize wsz; if (isatty(0) && ioctl(0, TIOCGWINSZ, &wsz) == 0) return wsz.ws_row; return 25; } static int stdin_handler(int fd, uint32_t events, void *data, struct lxc_epoll_descr *descr) { char *in_char = data; if (events & EPOLLIN) { int rc; rc = read(fd, in_char, sizeof(*in_char)); if (rc <= 0) *in_char = '\0'; } if (events & EPOLLHUP) *in_char = 'q'; return 1; } static void sig_handler(int sig) { exit(EXIT_SUCCESS); } static void size_humanize(unsigned long long val, char *buf, size_t bufsz) { if (val > 1 << 30) { snprintf(buf, bufsz, "%u.%2.2u GB", (int)(val >> 30), (int)(val & ((1 << 30) - 1)) / 10737419); } else if (val > 1 << 20) { int x = val + 5243; /* for rounding */ snprintf(buf, bufsz, "%u.%2.2u MB", x >> 20, ((x & ((1 << 20) - 1)) * 100) >> 20); } else if (val > 1 << 10) { int x = val + 5; /* for rounding */ snprintf(buf, bufsz, "%u.%2.2u KB", x >> 10, ((x & ((1 << 10) - 1)) * 100) >> 10); } else { snprintf(buf, bufsz, "%3u.00 ", (int)val); } } static uint64_t stat_get_int(struct lxc_container *c, const char *item) { char buf[80]; int len; uint64_t val; len = c->get_cgroup_item(c, item, buf, sizeof(buf)); if (len <= 0) { ERROR("unable to read cgroup item %s", item); return 0; } val = strtoull(buf, NULL, 0); return val; } static uint64_t stat_match_get_int(struct lxc_container *c, const char *item, const char *match, int column) { char buf[4096]; int i,j,len; uint64_t val = 0; char **lines, **cols; size_t matchlen; len = c->get_cgroup_item(c, item, buf, sizeof(buf)); if (len <= 0) { ERROR("unable to read cgroup item %s", item); goto out; } lines = lxc_string_split_and_trim(buf, '\n'); if (!lines) goto out; matchlen = strlen(match); for (i = 0; lines[i]; i++) { if (strncmp(lines[i], match, matchlen) == 0) { cols = lxc_string_split_and_trim(lines[i], ' '); if (!cols) goto err1; for (j = 0; cols[j]; j++) { if (j == column) { val = strtoull(cols[j], NULL, 0); break; } } lxc_free_array((void **)cols, free); break; } } err1: lxc_free_array((void **)lines, free); out: return val; } static void stats_get(struct lxc_container *c, struct ct *ct, struct stats *total) { ct->c = c; ct->stats->mem_used = stat_get_int(c, "memory.usage_in_bytes"); ct->stats->mem_limit = stat_get_int(c, "memory.limit_in_bytes"); ct->stats->kmem_used = stat_get_int(c, "memory.kmem.usage_in_bytes"); ct->stats->kmem_limit = stat_get_int(c, "memory.kmem.limit_in_bytes"); ct->stats->cpu_use_nanos = stat_get_int(c, "cpuacct.usage"); ct->stats->cpu_use_user = stat_match_get_int(c, "cpuacct.stat", "user", 1); ct->stats->cpu_use_sys = stat_match_get_int(c, "cpuacct.stat", "system", 1); ct->stats->blkio = stat_match_get_int(c, "blkio.throttle.io_service_bytes", "Total", 1); if (total) { total->mem_used = total->mem_used + ct->stats->mem_used; total->mem_limit = total->mem_limit + ct->stats->mem_limit; total->kmem_used = total->kmem_used + ct->stats->kmem_used; total->kmem_limit = total->kmem_limit + ct->stats->kmem_limit; total->cpu_use_nanos = total->cpu_use_nanos + ct->stats->cpu_use_nanos; total->cpu_use_user = total->cpu_use_user + ct->stats->cpu_use_user; total->cpu_use_sys = total->cpu_use_sys + ct->stats->cpu_use_sys; total->blkio = total->blkio + ct->stats->blkio; } } static void stats_print_header(struct stats *stats) { printf(TERMRVRS TERMBOLD); printf("%-18s %12s %12s %12s %14s %10s", "Container", "CPU", "CPU", "CPU", "BlkIO", "Mem"); if (stats->kmem_used > 0) printf(" %10s", "KMem"); printf("\n"); printf("%-18s %12s %12s %12s %14s %10s", "Name", "Used", "Sys", "User", "Total", "Used"); if (stats->kmem_used > 0) printf(" %10s", "Used"); printf("\n"); printf(TERMNORM); } static void stats_print(const char *name, const struct stats *stats, const struct stats *total) { char blkio_str[20]; char mem_used_str[20]; char kmem_used_str[20]; size_humanize(stats->blkio, blkio_str, sizeof(blkio_str)); size_humanize(stats->mem_used, mem_used_str, sizeof(mem_used_str)); printf("%-18.18s %12.2f %12.2f %12.2f %14s %10s", name, (float)stats->cpu_use_nanos / 1000000000, (float)stats->cpu_use_sys / USER_HZ, (float)stats->cpu_use_user / USER_HZ, blkio_str, mem_used_str); if (total->kmem_used > 0) { size_humanize(stats->kmem_used, kmem_used_str, sizeof(kmem_used_str)); printf(" %10s", kmem_used_str); } } static int cmp_name(const void *sct1, const void *sct2) { const struct ct *ct1 = sct1; const struct ct *ct2 = sct2; if (sort_reverse) return strcmp(ct2->c->name, ct1->c->name); return strcmp(ct1->c->name, ct2->c->name); } static int cmp_cpuuse(const void *sct1, const void *sct2) { const struct ct *ct1 = sct1; const struct ct *ct2 = sct2; if (sort_reverse) return ct2->stats->cpu_use_nanos < ct1->stats->cpu_use_nanos; return ct1->stats->cpu_use_nanos < ct2->stats->cpu_use_nanos; } static int cmp_blkio(const void *sct1, const void *sct2) { const struct ct *ct1 = sct1; const struct ct *ct2 = sct2; if (sort_reverse) return ct2->stats->blkio < ct1->stats->blkio; return ct1->stats->blkio < ct2->stats->blkio; } static int cmp_memory(const void *sct1, const void *sct2) { const struct ct *ct1 = sct1; const struct ct *ct2 = sct2; if (sort_reverse) return ct2->stats->mem_used < ct1->stats->mem_used; return ct1->stats->mem_used < ct2->stats->mem_used; } static int cmp_kmemory(const void *sct1, const void *sct2) { const struct ct *ct1 = sct1; const struct ct *ct2 = sct2; if (sort_reverse) return ct2->stats->kmem_used < ct1->stats->kmem_used; return ct1->stats->kmem_used < ct2->stats->kmem_used; } static void ct_sort(int active) { int (*cmp_func)(const void *, const void *); switch(sort_by) { default: case 'n': cmp_func = cmp_name; break; case 'c': cmp_func = cmp_cpuuse; break; case 'b': cmp_func = cmp_blkio; break; case 'm': cmp_func = cmp_memory; break; case 'k': cmp_func = cmp_kmemory; break; } qsort(ct, active, sizeof(*ct), (int (*)(const void *,const void *))cmp_func); } static void ct_free(void) { int i; for (i = 0; i < ct_alloc_cnt; i++) { if (ct[i].c) { lxc_container_put(ct[i].c); ct[i].c = NULL; } free(ct[i].stats); ct[i].stats = NULL; } } static void ct_realloc(int active_cnt) { int i; if (active_cnt > ct_alloc_cnt) { ct_free(); ct = realloc(ct, sizeof(*ct) * active_cnt); if (!ct) { ERROR("cannot alloc mem"); exit(EXIT_FAILURE); } for (i = 0; i < active_cnt; i++) { ct[i].stats = malloc(sizeof(*ct[0].stats)); if (!ct[i].stats) { ERROR("cannot alloc mem"); exit(EXIT_FAILURE); } } ct_alloc_cnt = active_cnt; } } int main(int argc, char *argv[]) { struct lxc_epoll_descr descr; int ret, ct_print_cnt; char in_char; ret = EXIT_FAILURE; if (lxc_arguments_parse(&my_args, argc, argv)) goto out; ct_print_cnt = stdin_tios_rows() - 3; /* 3 -> header and total */ if (stdin_tios_setup() < 0) { ERROR("failed to setup terminal"); goto out; } /* ensure the terminal gets restored */ atexit(stdin_tios_restore); signal(SIGINT, sig_handler); signal(SIGQUIT, sig_handler); if (lxc_mainloop_open(&descr)) { ERROR("failed to create mainloop"); goto out; } ret = lxc_mainloop_add_handler(&descr, 0, stdin_handler, &in_char); if (ret) { ERROR("failed to add stdin handler"); ret = EXIT_FAILURE; goto err1; } for(;;) { struct lxc_container **active; int i, active_cnt; struct stats total; char total_name[30]; active_cnt = list_active_containers(my_args.lxcpath[0], NULL, &active); ct_realloc(active_cnt); memset(&total, 0, sizeof(total)); for (i = 0; i < active_cnt; i++) stats_get(active[i], &ct[i], &total); ct_sort(active_cnt); printf(TERMCLEAR); stats_print_header(&total); for (i = 0; i < active_cnt && i < ct_print_cnt; i++) { stats_print(ct[i].c->name, ct[i].stats, &total); printf("\n"); } sprintf(total_name, "TOTAL %d of %d", i, active_cnt); stats_print(total_name, &total, &total); fflush(stdout); for (i = 0; i < active_cnt; i++) { lxc_container_put(ct[i].c); ct[i].c = NULL; } in_char = '\0'; ret = lxc_mainloop(&descr, 1000 * delay); if (ret != 0 || in_char == 'q') break; switch(in_char) { case 'r': sort_reverse ^= 1; break; case 'n': case 'c': case 'b': case 'm': case 'k': if (sort_by == in_char) sort_reverse ^= 1; else sort_reverse = 0; sort_by = in_char; } } ret = EXIT_SUCCESS; err1: lxc_mainloop_close(&descr); out: exit(ret); } lxc-2.0.8/src/lxc/tools/lxc-start-ephemeral.in0000644061062106075000000003467513105116772016210 00000000000000#!/usr/bin/env python3 # # lxc-start-ephemeral: Start a copy of a container using an overlay # # This python implementation is based on the work done in the original # shell implementation done by Serge Hallyn in Ubuntu (and other contributors) # # (C) Copyright Canonical Ltd. 2012 # # Authors: # Stéphane Graber # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # import argparse import gettext import lxc import locale import os import sys import subprocess import tempfile _ = gettext.gettext gettext.textdomain("lxc-start-ephemeral") # Other functions def printstderr(*args): print("lxc-start-ephemeral is deprecated in favor of lxc-copy\n", *args, file=sys.stderr) def randomMAC(): import random mac = [0x00, 0x16, 0x3e, random.randint(0x00, 0x7f), random.randint(0x00, 0xff), random.randint(0x00, 0xff)] return ':'.join(map(lambda x: "%02x" % x, mac)) def get_rundir(): if os.geteuid() == 0: return "@RUNTIME_PATH@" if "XDG_RUNTIME_DIR" in os.environ: return os.environ["XDG_RUNTIME_DIR"] if "HOME" in os.environ: return "%s/.cache/lxc/run/" % os.environ["HOME"] raise Exception("Unable to find a runtime directory") # Inform that lxc-start-ephemeral is deprecated printstderr() # Begin parsing the command line parser = argparse.ArgumentParser(description=_( "LXC: Start an ephemeral container"), formatter_class=argparse.RawTextHelpFormatter, epilog=_("If a COMMAND is given, then the " """container will run only as long as the command runs. If no COMMAND is given, this command will attach to tty1 and stop the container when exiting (with ctrl-a-q). If no COMMAND is given and -d is used, the name and IP addresses of the container will be printed to the console.""")) parser.add_argument("--lxcpath", "-P", dest="lxcpath", metavar="PATH", help=_("Use specified container path"), default=None) parser.add_argument("--orig", "-o", type=str, required=True, help=_("name of the original container")) parser.add_argument("--name", "-n", type=str, help=_("name of the target container")) parser.add_argument("--bdir", "-b", type=str, action="append", default=[], help=_("directory to bind mount into container, " "either --bdir=/src-path or --bdir=/src-path:/dst-path")) parser.add_argument("--cdir", "-c", type=str, action="append", default=[], help=_("directory to cow mount into container")) parser.add_argument("--user", "-u", type=str, help=_("the user to run the command as")) parser.add_argument("--key", "-S", type=str, help=_("the path to the key to use to connect " "(when using ssh)")) parser.add_argument("--daemon", "-d", action="store_true", help=_("run in the background")) parser.add_argument("--storage-type", "-s", type=str, default=None, choices=("tmpfs", "dir"), help=("type of storage use by the container")) parser.add_argument("--union-type", "-U", type=str, default="overlayfs", choices=("overlayfs", "aufs"), help=_("type of union (overlayfs or aufs), " "defaults to overlayfs.")) parser.add_argument("--keep-data", "-k", action="store_true", help=_("don't wipe everything clean at the end")) parser.add_argument("command", metavar='CMD', type=str, nargs="*", help=_("Run specific command in container " "(command as argument)")) parser.add_argument("--version", action="version", version=lxc.version) args = parser.parse_args() # Check that -d and CMD aren't used at the same time if args.command and args.daemon: parser.error(_("You can't use -d and a command at the same time.")) # Check that -k isn't used with -s tmpfs if not args.storage_type: if args.keep_data: args.storage_type = "dir" else: args.storage_type = "tmpfs" if args.keep_data and args.storage_type == "tmpfs": parser.error(_("You can't use -k with the tmpfs storage type.")) # Load the orig container orig = lxc.Container(args.orig, args.lxcpath) if not orig.defined: parser.error(_("Source container '%s' doesn't exist." % args.orig)) # Create the new container paths if not args.lxcpath: lxc_path = lxc.default_config_path else: lxc_path = args.lxcpath if args.name: if os.path.exists("%s/%s" % (lxc_path, args.name)): parser.error(_("A container named '%s' already exists." % args.name)) dest_path = "%s/%s" % (lxc_path, args.name) os.mkdir(dest_path) else: dest_path = tempfile.mkdtemp(prefix="%s-" % args.orig, dir=lxc_path) os.mkdir(os.path.join(dest_path, "rootfs")) os.chmod(dest_path, 0o770) # Setup the new container's configuration dest = lxc.Container(os.path.basename(dest_path), args.lxcpath) dest.load_config(orig.config_file_name) dest.set_config_item("lxc.utsname", dest.name) dest.set_config_item("lxc.rootfs", os.path.join(dest_path, "rootfs")) print("setting rootfs to .%s.", os.path.join(dest_path, "rootfs")) for nic in dest.network: if hasattr(nic, 'hwaddr'): nic.hwaddr = randomMAC() overlay_dirs = [(orig.get_config_item("lxc.rootfs"), "%s/rootfs/" % dest_path)] # Generate a new fstab if orig.get_config_item("lxc.mount"): dest.set_config_item("lxc.mount", os.path.join(dest_path, "fstab")) with open(orig.get_config_item("lxc.mount"), "r") as orig_fd: with open(dest.get_config_item("lxc.mount"), "w+") as dest_fd: for line in orig_fd.read().split("\n"): # Start by replacing any reference to the container rootfs line.replace(orig.get_config_item("lxc.rootfs"), dest.get_config_item("lxc.rootfs")) fields = line.split() # Skip invalid entries if len(fields) < 4: continue # Non-bind mounts are kept as-is if "bind" not in fields[3]: dest_fd.write("%s\n" % line) continue # Bind mounts of virtual filesystems are also kept as-is src_path = fields[0].split("/") if len(src_path) > 1 and src_path[1] in ("proc", "sys"): dest_fd.write("%s\n" % line) continue # Skip invalid mount points dest_mount = os.path.abspath(os.path.join("%s/rootfs/" % ( dest_path), fields[1])) if "%s/rootfs/" % dest_path not in dest_mount: print(_("Skipping mount entry '%s' as it's outside " "of the container rootfs.") % line) # Setup an overlay for anything remaining overlay_dirs += [(fields[0], dest_mount)] for entry in args.cdir: if not os.path.exists(entry): print(_("Path '%s' doesn't exist, won't be cow-mounted.") % entry) else: src_path = os.path.abspath(entry) dst_path = "%s/rootfs/%s" % (dest_path, src_path) overlay_dirs += [(src_path, dst_path)] # do we have the new overlay fs which requires workdir, or the older # overlayfs which does not? have_new_overlay = False with open("/proc/filesystems", "r") as fd: for line in fd: if line == "nodev\toverlay\n": have_new_overlay = True # Generate pre-mount script with open(os.path.join(dest_path, "pre-mount"), "w+") as fd: os.fchmod(fd.fileno(), 0o755) fd.write("""#!/bin/sh LXC_DIR="%s" LXC_BASE="%s" LXC_NAME="%s" """ % (dest_path, orig.name, dest.name)) 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) 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" % (entry[0], entry[1])) if args.union_type == "overlayfs": if have_new_overlay: fd.write("mount -n -t overlay" " -oupperdir=%s,lowerdir=%s,workdir=%s none %s\n" % ( deltdir, entry[0], workdir, entry[1])) else: fd.write("mount -n -t overlayfs" " -oupperdir=%s,lowerdir=%s none %s\n" % ( deltdir, entry[0], entry[1])) elif args.union_type == "aufs": xino_path = "/dev/shm/aufs.xino" if not os.path.exists(os.path.basename(xino_path)): os.makedirs(os.path.basename(xino_path)) fd.write("mount -n -t aufs " "-o br=%s=rw:%s=ro,noplink,xino=%s none %s\n" % ( deltdir, entry[0], xino_path, entry[1])) count += 1 for entry in args.bdir: if ':' in entry: src_path, dst_path = entry.split(":") else: src_path = entry dst_path = os.path.abspath(entry) if not os.path.exists(src_path): print(_("Path '%s' doesn't exist, won't be bind-mounted.") % src_path) else: src_path = os.path.abspath(src_path) dst_path = "%s/rootfs/%s" % (dest_path, dst_path) fd.write("mkdir -p %s\nmount -n --bind %s %s\n" % ( dst_path, src_path, dst_path)) fd.write(""" [ -e $LXC_DIR/configured ] && exit 0 for file in $LXC_DIR/rootfs/etc/hostname \\ $LXC_DIR/rootfs/etc/hosts \\ $LXC_DIR/rootfs/etc/sysconfig/network \\ $LXC_DIR/rootfs/etc/sysconfig/network-scripts/ifcfg-eth0; do [ -f "$file" ] && sed -i -e "s/$LXC_BASE/$LXC_NAME/" $file done touch $LXC_DIR/configured """) dest.set_config_item("lxc.hook.pre-mount", os.path.join(dest_path, "pre-mount")) if not args.keep_data: dest.set_config_item("lxc.ephemeral", "1") dest.save_config() # Start the container if not dest.start() or not dest.wait("RUNNING", timeout=5): print(_("The container '%s' failed to start.") % dest.name) dest.stop() if dest.defined: dest.destroy() sys.exit(1) # Deal with the case where we just attach to the container's console if not args.command and not args.daemon: dest.console() if not dest.shutdown(timeout=5): dest.stop() sys.exit(0) # Try to get the IP addresses ips = dest.get_ips(timeout=10) # Deal with the case where we just print info about the container if args.daemon: print(_("""The ephemeral container is now started. You can enter it from the command line with: lxc-console -n %s The following IP addresses have be found in the container: %s""") % (dest.name, "\n".join([" - %s" % entry for entry in ips] or [" - %s" % _("No address could be found")]))) sys.exit(0) # Now deal with the case where we want to run a command in the container if not ips: print(_("Failed to get an IP for container '%s'.") % dest.name) dest.stop() if dest.defined: dest.destroy() sys.exit(1) if os.path.exists("/proc/self/ns/pid"): def attach_as_user(command): try: username = "root" if args.user: username = args.user # This should really just use universal_newlines=True, but we do # the decoding by hand instead for compatibility with Python # 3.2; that used locale.getpreferredencoding() internally rather # than locale.getpreferredencoding(False), and the former breaks # here because we can't reload codecs at this point unless the # container has the same version of Python installed. line = subprocess.check_output(["getent", "passwd", username]) line = line.decode(locale.getpreferredencoding(False)).rstrip("\n") _, _, pw_uid, pw_gid, _, pw_dir, _ = line.split(":", 6) pw_uid = int(pw_uid) pw_gid = int(pw_gid) os.setgid(pw_gid) os.initgroups(username, pw_gid) os.setuid(pw_uid) os.chdir(pw_dir) os.environ['HOME'] = pw_dir except: print(_("Unable to switch to user: %s" % username)) sys.exit(1) return lxc.attach_run_command(command) retval = dest.attach_wait(attach_as_user, args.command, env_policy=lxc.LXC_ATTACH_CLEAR_ENV) else: cmd = ["ssh", "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null"] if args.user: cmd += ["-l", args.user] if args.key: cmd += ["-i", args.key] for ip in ips: ssh_cmd = cmd + [ip] + args.command retval = subprocess.call(ssh_cmd, universal_newlines=True) if retval == 255: print(_("SSH failed to connect, trying next IP address.")) continue if retval != 0: print(_("Command returned with non-zero return code: %s") % retval) break # Shutdown the container if not dest.shutdown(timeout=5): dest.stop() sys.exit(retval) lxc-2.0.8/src/lxc/tools/lxc_destroy.c0000644061062106075000000001476713105116772014502 00000000000000/* * * Copyright © 2013 Serge Hallyn . * Copyright © 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #define _GNU_SOURCE #include "config.h" #include #include #include #include #include #include "arguments.h" #include "log.h" #include "lxc.h" #include "utils.h" lxc_log_define(lxc_destroy_ui, lxc); static int my_parser(struct lxc_arguments* args, int c, char* arg); static bool quiet; static const struct option my_longopts[] = { {"force", no_argument, 0, 'f'}, {"snapshots", no_argument, 0, 's'}, LXC_COMMON_OPTIONS }; static struct lxc_arguments my_args = { .progname = "lxc-destroy", .help = "\ --name=NAME [-f] [-P lxcpath]\n\ \n\ lxc-destroy destroys a container with the identifier NAME\n\ \n\ Options :\n\ -n, --name=NAME NAME of the container\n\ -s, --snapshots destroy including all snapshots\n\ -f, --force wait for the container to shut down\n\ --rcfile=FILE Load configuration file FILE\n", .options = my_longopts, .parser = my_parser, .checker = NULL, .task = DESTROY, }; static bool do_destroy(struct lxc_container *c); static bool do_destroy_with_snapshots(struct lxc_container *c); int main(int argc, char *argv[]) { struct lxc_container *c; bool bret; if (lxc_arguments_parse(&my_args, argc, argv)) exit(EXIT_FAILURE); if (!my_args.log_file) my_args.log_file = "none"; if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority, my_args.progname, my_args.quiet, my_args.lxcpath[0])) exit(EXIT_FAILURE); lxc_log_options_no_override(); if (my_args.quiet) quiet = true; c = lxc_container_new(my_args.name, my_args.lxcpath[0]); if (!c) { if (!quiet) fprintf(stderr, "System error loading container\n"); exit(EXIT_FAILURE); } if (my_args.rcfile) { c->clear_config(c); if (!c->load_config(c, my_args.rcfile)) { fprintf(stderr, "Failed to load rcfile\n"); lxc_container_put(c); exit(EXIT_FAILURE); } c->configfile = strdup(my_args.rcfile); if (!c->configfile) { fprintf(stderr, "Out of memory setting new config filename\n"); lxc_container_put(c); exit(EXIT_FAILURE); } } if (!c->may_control(c)) { if (!quiet) fprintf(stderr, "Insufficent privileges to control %s\n", my_args.name); lxc_container_put(c); exit(EXIT_FAILURE); } if (!c->is_defined(c)) { if (!quiet) fprintf(stderr, "Container is not defined\n"); lxc_container_put(c); exit(EXIT_FAILURE); } if (my_args.task == SNAP) { bret = do_destroy_with_snapshots(c); if (bret && !quiet) printf("Destroyed container %s including snapshots \n", my_args.name); } else { bret = do_destroy(c); if (bret && !quiet) printf("Destroyed container %s\n", my_args.name); } lxc_container_put(c); if (bret) exit(EXIT_SUCCESS); exit(EXIT_FAILURE); } static int my_parser(struct lxc_arguments *args, int c, char *arg) { switch (c) { case 'f': args->force = 1; break; case 's': args->task = SNAP; break; } return 0; } static bool do_destroy(struct lxc_container *c) { bool bret = true; char path[MAXPATHLEN]; /* First check whether the container has dependent clones or snapshots. */ int ret = snprintf(path, MAXPATHLEN, "%s/%s/lxc_snapshots", c->config_path, c->name); if (ret < 0 || ret >= MAXPATHLEN) return false; if (file_exists(path)) { if (!quiet) fprintf(stdout, "Destroying %s failed: %s has clones.\n", c->name, c->name); return false; } ret = snprintf(path, MAXPATHLEN, "%s/%s/snaps", c->config_path, c->name); if (ret < 0 || ret >= MAXPATHLEN) return false; if (dir_exists(path)) { if (!quiet) fprintf(stdout, "Destroying %s failed: %s has snapshots.\n", c->name, c->name); return false; } if (c->is_running(c)) { if (!my_args.force && !quiet) { fprintf(stderr, "%s is running\n", my_args.name); return false; } /* If the container was ephemeral it will be removed on shutdown. */ c->stop(c); } /* If the container was ephemeral we have already removed it when we * stopped it. */ if (c->is_defined(c) && !c->lxc_conf->ephemeral) bret = c->destroy(c); if (!bret) { if (!quiet) fprintf(stderr, "Destroying %s failed\n", my_args.name); return false; } return true; } static bool do_destroy_with_snapshots(struct lxc_container *c) { struct lxc_container *c1; struct stat fbuf; bool bret = false; char path[MAXPATHLEN]; char *buf = NULL; char *lxcpath = NULL; char *lxcname = NULL; char *scratch = NULL; int fd; int ret; int counter = 0; /* Destroy clones. */ ret = snprintf(path, MAXPATHLEN, "%s/%s/lxc_snapshots", c->config_path, c->name); if (ret < 0 || ret >= MAXPATHLEN) return false; fd = open(path, O_RDONLY | O_CLOEXEC); if (fd >= 0) { ret = fstat(fd, &fbuf); if (ret < 0) { close(fd); return false; } /* Make sure that the string is \0 terminated. */ buf = calloc(fbuf.st_size + 1, sizeof(char)); if (!buf) { SYSERROR("failed to allocate memory"); close(fd); return false; } ret = read(fd, buf, fbuf.st_size); if (ret < 0) { ERROR("could not read %s", path); close(fd); free(buf); return false; } close(fd); while ((lxcpath = strtok_r(!counter ? buf : NULL, "\n", &scratch))) { if (!(lxcname = strtok_r(NULL, "\n", &scratch))) break; c1 = lxc_container_new(lxcname, lxcpath); if (!c1) { counter++; continue; } /* We do not destroy recursively. If a clone of a clone * has clones or snapshots the user should remove it * explicitly. */ if (!do_destroy(c1)) { lxc_container_put(c1); free(buf); return false; } lxc_container_put(c1); counter++; } free(buf); } /* Destroy snapshots located in the containers snap/ folder. */ ret = snprintf(path, MAXPATHLEN, "%s/%s/snaps", c->config_path, c->name); if (ret < 0 || ret >= MAXPATHLEN) return false; if (dir_exists(path)) bret = c->destroy_with_snapshots(c); else bret = do_destroy(c); return bret; } lxc-2.0.8/src/lxc/tools/lxc_freeze.c0000644061062106075000000000532613105116772014260 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include "lxc.h" #include "log.h" #include "arguments.h" lxc_log_define(lxc_freeze_ui, lxc); static const struct option my_longopts[] = { LXC_COMMON_OPTIONS }; static struct lxc_arguments my_args = { .progname = "lxc-freeze", .help = "\ --name=NAME\n\ \n\ lxc-freeze freezes a container with the identifier NAME\n\ \n\ Options :\n\ -n, --name=NAME NAME of the container\n\ --rcfile=FILE Load configuration file FILE\n", .options = my_longopts, .parser = NULL, .checker = NULL, }; int main(int argc, char *argv[]) { struct lxc_container *c; if (lxc_arguments_parse(&my_args, argc, argv)) exit(EXIT_FAILURE); if (!my_args.log_file) my_args.log_file = "none"; if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority, my_args.progname, my_args.quiet, my_args.lxcpath[0])) exit(EXIT_FAILURE); lxc_log_options_no_override(); c = lxc_container_new(my_args.name, my_args.lxcpath[0]); if (!c) { ERROR("No such container: %s:%s", my_args.lxcpath[0], my_args.name); exit(EXIT_FAILURE); } if (my_args.rcfile) { c->clear_config(c); if (!c->load_config(c, my_args.rcfile)) { ERROR("Failed to load rcfile"); lxc_container_put(c); exit(EXIT_FAILURE); } c->configfile = strdup(my_args.rcfile); if (!c->configfile) { ERROR("Out of memory setting new config filename"); lxc_container_put(c); exit(EXIT_FAILURE); } } if (!c->may_control(c)) { ERROR("Insufficent privileges to control %s:%s", my_args.lxcpath[0], my_args.name); lxc_container_put(c); exit(EXIT_FAILURE); } if (!c->freeze(c)) { ERROR("Failed to freeze %s:%s", my_args.lxcpath[0], my_args.name); lxc_container_put(c); exit(EXIT_FAILURE); } lxc_container_put(c); exit(EXIT_SUCCESS); } lxc-2.0.8/src/lxc/tools/lxc_snapshot.c0000644061062106075000000001536213105116772014640 00000000000000/* * * Copyright © 2013 Serge Hallyn . * Copyright © 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "confile.h" #include #include #include #include #include #include #include #include "bdev.h" #include "lxc.h" #include "log.h" #include "arguments.h" #include "utils.h" lxc_log_define(lxc_snapshot_ui, lxc); static int my_parser(struct lxc_arguments *args, int c, char *arg); static const struct option my_longopts[] = { {"list", no_argument, 0, 'L'}, {"restore", required_argument, 0, 'r'}, {"newname", required_argument, 0, 'N'}, {"destroy", required_argument, 0, 'd'}, {"comment", required_argument, 0, 'c'}, {"showcomments", no_argument, 0, 'C'}, LXC_COMMON_OPTIONS }; static struct lxc_arguments my_args = { .progname = "lxc-snapshot", .help = "\ --name=NAME [-P lxcpath] [-L [-C]] [-c commentfile] [-r snapname [-N newname]]\n\ \n\ lxc-snapshot snapshots a container\n\ \n\ Options :\n\ -n, --name=NAME NAME of the container\n\ -L, --list list all snapshots\n\ -r, --restore=NAME restore snapshot NAME, e.g. 'snap0'\n\ -N, --newname=NEWNAME NEWNAME for the restored container\n\ -d, --destroy=NAME destroy snapshot NAME, e.g. 'snap0'\n\ use ALL to destroy all snapshots\n\ -c, --comment=FILE add FILE as a comment\n\ -C, --showcomments show snapshot comments\n\ --rcfile=FILE Load configuration file FILE\n", .options = my_longopts, .parser = my_parser, .checker = NULL, .task = SNAP, }; static int do_snapshot(struct lxc_container *c, char *commentfile); static int do_snapshot_destroy(struct lxc_container *c, char *snapname); static int do_snapshot_list(struct lxc_container *c, int print_comments); static int do_snapshot_restore(struct lxc_container *c, struct lxc_arguments *args); static int do_snapshot_task(struct lxc_container *c, enum task task); static void print_file(char *path); int main(int argc, char *argv[]) { struct lxc_container *c; int ret; if (lxc_arguments_parse(&my_args, argc, argv)) exit(EXIT_FAILURE); if (!my_args.log_file) my_args.log_file = "none"; if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority, my_args.progname, my_args.quiet, my_args.lxcpath[0])) exit(EXIT_FAILURE); lxc_log_options_no_override(); if (geteuid()) { if (access(my_args.lxcpath[0], O_RDONLY) < 0) { fprintf(stderr, "You lack access to %s\n", my_args.lxcpath[0]); exit(EXIT_FAILURE); } } c = lxc_container_new(my_args.name, my_args.lxcpath[0]); if (!c) { fprintf(stderr, "System error loading container\n"); exit(EXIT_FAILURE); } if (my_args.rcfile) { c->clear_config(c); if (!c->load_config(c, my_args.rcfile)) { fprintf(stderr, "Failed to load rcfile\n"); lxc_container_put(c); exit(EXIT_FAILURE); } c->configfile = strdup(my_args.rcfile); if (!c->configfile) { fprintf(stderr, "Out of memory setting new config filename\n"); lxc_container_put(c); exit(EXIT_FAILURE); } } if (!c->may_control(c)) { fprintf(stderr, "Insufficent privileges to control %s\n", my_args.name); lxc_container_put(c); exit(EXIT_FAILURE); } ret = do_snapshot_task(c, my_args.task); lxc_container_put(c); if (ret == 0) exit(EXIT_SUCCESS); exit(EXIT_FAILURE); } static int do_snapshot_task(struct lxc_container *c, enum task task) { int ret = 0; switch (task) { case DESTROY: ret = do_snapshot_destroy(c, my_args.snapname); break; case LIST: ret = do_snapshot_list(c, my_args.print_comments); break; case RESTORE: ret = do_snapshot_restore(c, &my_args); break; case SNAP: ret = do_snapshot(c, my_args.commentfile); break; default: ret = 0; break; } return ret; } static int my_parser(struct lxc_arguments *args, int c, char *arg) { switch (c) { case 'L': args->task = LIST; break; case 'r': args->task = RESTORE; args->snapname = arg; break; case 'N': args->newname = arg; break; case 'd': args->task = DESTROY; args->snapname = arg; break; case 'c': args->commentfile = arg; break; case 'C': args->print_comments = 1; break; } return 0; } static int do_snapshot(struct lxc_container *c, char *commentfile) { int ret; ret = c->snapshot(c, commentfile); if (ret < 0) { ERROR("Error creating a snapshot"); return -1; } INFO("Created snapshot snap%d", ret); return 0; } static int do_snapshot_destroy(struct lxc_container *c, char *snapname) { bool ret; if (strcmp(snapname, "ALL") == 0) ret = c->snapshot_destroy_all(c); else ret = c->snapshot_destroy(c, snapname); if (!ret) { ERROR("Error destroying snapshot %s", snapname); return -1; } return 0; } static int do_snapshot_list(struct lxc_container *c, int print_comments) { struct lxc_snapshot *s; int i, n; n = c->snapshot_list(c, &s); if (n < 0) { ERROR("Error listing snapshots"); return -1; } if (n == 0) { printf("No snapshots\n"); return 0; } for (i = 0; i < n; i++) { printf("%s (%s) %s\n", s[i].name, s[i].lxcpath, s[i].timestamp); if (print_comments) print_file(s[i].comment_pathname); s[i].free(&s[i]); } free(s); return 0; } static int do_snapshot_restore(struct lxc_container *c, struct lxc_arguments *args) { int bret; /* When restoring a snapshot, the last optional argument if not given * explicitly via the corresponding command line option is the name to * use for the restored container. If no name is given, then the * original container will be destroyed and the restored container will * take its place. */ if ((!args->newname) && (args->argc > 1)) { lxc_error(args, "Too many arguments"); return -1; } if ((!args->newname) && (args->argc == 1)) args->newname = args->argv[0]; bret = c->snapshot_restore(c, args->snapname, args->newname); if (!bret) { ERROR("Error restoring snapshot %s", args->snapname); return -1; } return 0; } static void print_file(char *path) { if (!path) return; FILE *f = fopen(path, "r"); char *line = NULL; size_t sz = 0; if (!f) return; while (getline(&line, &sz, f) != -1) { printf("%s", line); } free(line); fclose(f); } lxc-2.0.8/src/lxc/tools/lxc_cgroup.c0000644061062106075000000000700613105116772014274 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include "lxc.h" #include "log.h" #include "arguments.h" lxc_log_define(lxc_cgroup_ui, lxc); static int my_checker(const struct lxc_arguments* args) { if (!args->argc) { lxc_error(args, "missing state object"); return -1; } return 0; } static const struct option my_longopts[] = { LXC_COMMON_OPTIONS }; static struct lxc_arguments my_args = { .progname = "lxc-cgroup", .help = "\ --name=NAME state-object [value]\n\ \n\ Get or set the value of a state object (for example, 'cpuset.cpus')\n\ in the container's cgroup for the corresponding subsystem.\n\ \n\ Options :\n\ -n, --name=NAME NAME of the container\n\ --rcfile=FILE Load configuration file FILE\n", .options = my_longopts, .parser = NULL, .checker = my_checker, }; int main(int argc, char *argv[]) { char *state_object = NULL, *value = NULL; struct lxc_container *c; if (lxc_arguments_parse(&my_args, argc, argv)) exit(EXIT_FAILURE); if (!my_args.log_file) my_args.log_file = "none"; if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority, my_args.progname, my_args.quiet, my_args.lxcpath[0])) exit(EXIT_FAILURE); lxc_log_options_no_override(); state_object = my_args.argv[0]; c = lxc_container_new(my_args.name, my_args.lxcpath[0]); if (!c) exit(EXIT_FAILURE); if (my_args.rcfile) { c->clear_config(c); if (!c->load_config(c, my_args.rcfile)) { ERROR("Failed to load rcfile"); lxc_container_put(c); exit(EXIT_FAILURE); } c->configfile = strdup(my_args.rcfile); if (!c->configfile) { ERROR("Out of memory setting new config filename"); lxc_container_put(c); exit(EXIT_FAILURE); } } if (!c->may_control(c)) { ERROR("Insufficent privileges to control %s:%s", my_args.lxcpath[0], my_args.name); lxc_container_put(c); exit(EXIT_FAILURE); } if (!c->is_running(c)) { ERROR("'%s:%s' is not running", my_args.lxcpath[0], my_args.name); lxc_container_put(c); exit(EXIT_FAILURE); } if ((my_args.argc) > 1) { value = my_args.argv[1]; if (!c->set_cgroup_item(c, state_object, value)) { ERROR("failed to assign '%s' value to '%s' for '%s'", value, state_object, my_args.name); lxc_container_put(c); exit(EXIT_FAILURE); } } else { char buffer[MAXPATHLEN]; int ret = c->get_cgroup_item(c, state_object, buffer, MAXPATHLEN); if (ret < 0) { ERROR("failed to retrieve value of '%s' for '%s:%s'", state_object, my_args.lxcpath[0], my_args.name); lxc_container_put(c); exit(EXIT_FAILURE); } printf("%*s", ret, buffer); } lxc_container_put(c); exit(EXIT_SUCCESS); } lxc-2.0.8/src/lxc/tools/lxc_monitor.c0000644061062106075000000001064113105116772014463 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include "lxc.h" #include "log.h" #include "monitor.h" #include "arguments.h" lxc_log_define(lxc_monitor_ui, lxc); static bool quit_monitord; static int my_parser(struct lxc_arguments* args, int c, char* arg) { switch (c) { case 'Q': quit_monitord = true; break; } return 0; } static const struct option my_longopts[] = { {"quit", no_argument, 0, 'Q'}, LXC_COMMON_OPTIONS }; static struct lxc_arguments my_args = { .progname = "lxc-monitor", .help = "\ [--name=NAME]\n\ \n\ lxc-monitor monitors the state of the NAME container\n\ \n\ Options :\n\ -n, --name=NAME NAME of the container\n\ NAME may be a regular expression\n\ -Q, --quit tell lxc-monitord to quit\n", .name = ".*", .options = my_longopts, .parser = my_parser, .checker = NULL, .lxcpath_additional = -1, }; static void close_fds(struct pollfd *fds, nfds_t nfds) { nfds_t i; if (nfds < 1) return; for (i = 0; i < nfds; ++i) { close(fds[i].fd); } } int main(int argc, char *argv[]) { char *regexp; struct lxc_msg msg; regex_t preg; struct pollfd *fds; nfds_t nfds; int len, rc_main, rc_snp, i; rc_main = EXIT_FAILURE; if (lxc_arguments_parse(&my_args, argc, argv)) exit(rc_main); if (!my_args.log_file) my_args.log_file = "none"; if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority, my_args.progname, my_args.quiet, my_args.lxcpath[0])) exit(rc_main); lxc_log_options_no_override(); if (quit_monitord) { int ret = EXIT_SUCCESS; for (i = 0; i < my_args.lxcpath_cnt; i++) { int fd; fd = lxc_monitor_open(my_args.lxcpath[i]); if (fd < 0) { ERROR("Unable to open monitor on path: %s", my_args.lxcpath[i]); ret = EXIT_FAILURE; continue; } if (write(fd, "quit", 4) < 0) { SYSERROR("Unable to close monitor on path: %s", my_args.lxcpath[i]); ret = EXIT_FAILURE; close(fd); continue; } close(fd); } exit(ret); } len = strlen(my_args.name) + 3; regexp = malloc(len + 3); if (!regexp) { ERROR("failed to allocate memory"); exit(rc_main); } rc_snp = snprintf(regexp, len, "^%s$", my_args.name); if (rc_snp < 0 || rc_snp >= len) { ERROR("Name too long"); goto error; } if (regcomp(&preg, regexp, REG_NOSUB|REG_EXTENDED)) { ERROR("failed to compile the regex '%s'", my_args.name); goto error; } fds = malloc(my_args.lxcpath_cnt * sizeof(struct pollfd)); if (!fds) { SYSERROR("out of memory"); goto cleanup; } nfds = my_args.lxcpath_cnt; for (i = 0; i < nfds; i++) { int fd; lxc_monitord_spawn(my_args.lxcpath[i]); fd = lxc_monitor_open(my_args.lxcpath[i]); if (fd < 0) { close_fds(fds, i); goto cleanup; } fds[i].fd = fd; fds[i].events = POLLIN; fds[i].revents = 0; } setlinebuf(stdout); for (;;) { if (lxc_monitor_read_fdset(fds, nfds, &msg, -1) < 0) { goto close_and_clean; } msg.name[sizeof(msg.name)-1] = '\0'; if (regexec(&preg, msg.name, 0, NULL, 0)) continue; switch (msg.type) { case lxc_msg_state: printf("'%s' changed state to [%s]\n", msg.name, lxc_state2str(msg.value)); break; case lxc_msg_exit_code: printf("'%s' exited with status [%d]\n", msg.name, WEXITSTATUS(msg.value)); break; default: /* ignore garbage */ break; } } rc_main = 0; close_and_clean: close_fds(fds, nfds); cleanup: regfree(&preg); free(fds); error: free(regexp); exit(rc_main); } lxc-2.0.8/src/lxc/tools/lxc_init.c0000644061062106075000000001353013105116772013737 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include "log.h" #include "caps.h" #include "error.h" #include "initutils.h" lxc_log_define(lxc_init, lxc); static int quiet; static const struct option options[] = { { "name", required_argument, NULL, 'n' }, { "logpriority", required_argument, NULL, 'l' }, { "quiet", no_argument, NULL, 'q' }, { "lxcpath", required_argument, NULL, 'P' }, { 0, 0, 0, 0 }, }; static sig_atomic_t was_interrupted = 0; static void interrupt_handler(int sig) { if (!was_interrupted) was_interrupted = sig; } static void usage(void) { fprintf(stderr, "Usage: lxc-init [OPTION]...\n\n" "Common options :\n" " -n, --name=NAME NAME of the container\n" " -l, --logpriority=LEVEL Set log priority to LEVEL\n" " -q, --quiet Don't produce any output\n" " -P, --lxcpath=PATH Use specified container path\n" " -?, --help Give this help list\n" "\n" "Mandatory or optional arguments to long options are also mandatory or optional\n" "for any corresponding short options.\n" "\n" "NOTE: lxc-init is intended for use by lxc internally\n" " and does not need to be run by hand\n\n"); } int main(int argc, char *argv[]) { pid_t pid; int err; char **aargv; sigset_t mask, omask; int i, have_status = 0, shutdown = 0; int opt; char *lxcpath = NULL, *name = NULL, *logpriority = NULL; while ((opt = getopt_long(argc, argv, "n:l:qP:", options, NULL)) != -1) { switch(opt) { case 'n': name = optarg; break; case 'l': logpriority = optarg; break; case 'q': quiet = 1; break; case 'P': lxcpath = optarg; break; default: /* '?' */ usage(); exit(EXIT_FAILURE); } } err = lxc_log_init(name, name ? NULL : "none", logpriority, basename(argv[0]), quiet, lxcpath); if (err < 0) exit(EXIT_FAILURE); lxc_log_options_no_override(); if (!argv[optind]) { ERROR("missing command to launch"); exit(EXIT_FAILURE); } aargv = &argv[optind]; /* * mask all the signals so we are safe to install a * signal handler and to fork */ if (sigfillset(&mask) || sigdelset(&mask, SIGILL) || sigdelset(&mask, SIGSEGV) || sigdelset(&mask, SIGBUS) || sigprocmask(SIG_SETMASK, &mask, &omask)) { SYSERROR("failed to set signal mask"); exit(EXIT_FAILURE); } for (i = 1; i < NSIG; i++) { struct sigaction act; /* Exclude some signals: ILL, SEGV and BUS are likely to * reveal a bug and we want a core. STOP and KILL cannot be * handled anyway: they're here for documentation. */ if (i == SIGILL || i == SIGSEGV || i == SIGBUS || i == SIGSTOP || i == SIGKILL || i == 32 || i == 33) continue; if (sigfillset(&act.sa_mask) || sigdelset(&act.sa_mask, SIGILL) || sigdelset(&act.sa_mask, SIGSEGV) || sigdelset(&act.sa_mask, SIGBUS) || sigdelset(&act.sa_mask, SIGSTOP) || sigdelset(&act.sa_mask, SIGKILL)) { ERROR("failed to set signal"); exit(EXIT_FAILURE); } act.sa_flags = 0; act.sa_handler = interrupt_handler; if (sigaction(i, &act, NULL) && errno != EINVAL) { SYSERROR("failed to sigaction"); exit(EXIT_FAILURE); } } lxc_setup_fs(); pid = fork(); if (pid < 0) exit(EXIT_FAILURE); if (!pid) { /* restore default signal handlers */ for (i = 1; i < NSIG; i++) signal(i, SIG_DFL); if (sigprocmask(SIG_SETMASK, &omask, NULL)) { SYSERROR("failed to set signal mask"); exit(EXIT_FAILURE); } NOTICE("about to exec '%s'", aargv[0]); execvp(aargv[0], aargv); ERROR("failed to exec: '%s' : %m", aargv[0]); exit(err); } /* let's process the signals now */ if (sigdelset(&omask, SIGALRM) || sigprocmask(SIG_SETMASK, &omask, NULL)) { SYSERROR("failed to set signal mask"); exit(EXIT_FAILURE); } /* no need of other inherited fds but stderr */ close(fileno(stdin)); close(fileno(stdout)); err = EXIT_SUCCESS; for (;;) { int status; pid_t waited_pid; switch (was_interrupted) { case 0: break; case SIGPWR: case SIGTERM: if (!shutdown) { shutdown = 1; kill(-1, SIGTERM); alarm(1); } break; case SIGALRM: kill(-1, SIGKILL); break; default: kill(pid, was_interrupted); break; } was_interrupted = 0; waited_pid = wait(&status); if (waited_pid < 0) { if (errno == ECHILD) goto out; if (errno == EINTR) continue; ERROR("failed to wait child : %s", strerror(errno)); goto out; } /* reset timer each time a process exited */ if (shutdown) alarm(1); /* * keep the exit code of started application * (not wrapped pid) and continue to wait for * the end of the orphan group. */ if (waited_pid == pid && !have_status) { err = lxc_error_set_and_log(waited_pid, status); have_status = 1; } } out: if (err < 0) exit(EXIT_FAILURE); exit(err); } lxc-2.0.8/src/lxc/tools/lxc_ls.c0000644061062106075000000010025313105116772013411 00000000000000/* * * Copyright © 2016 Christian Brauner . * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "arguments.h" #include "conf.h" #include "confile.h" #include "log.h" #include "lxc.h" #include "utils.h" lxc_log_define(lxc_ls, lxc); /* Per default we only allow five levels of recursion to protect the stack at * least a little bit. */ #define MAX_NESTLVL 5 #define LS_FROZEN 1 #define LS_STOPPED 2 #define LS_ACTIVE 3 #define LS_RUNNING 4 #define LS_NESTING 5 #define LS_FILTER 6 #ifndef SOCK_CLOEXEC # define SOCK_CLOEXEC 02000000 #endif /* Store container info. */ struct ls { char *name; char *state; char *groups; char *interface; char *ipv4; char *ipv6; unsigned int nestlvl; pid_t init; double ram; double swap; bool autostart; bool running; }; /* Keep track of field widths for printing. */ struct lengths { unsigned int name_length; unsigned int state_length; unsigned int groups_length; unsigned int interface_length; unsigned int ipv4_length; unsigned int ipv6_length; unsigned int init_length; unsigned int ram_length; unsigned int swap_length; unsigned int autostart_length; }; static int ls_deserialize(int rpipefd, struct ls **m, size_t *len); static void ls_field_width(const struct ls *l, const size_t size, struct lengths *lht); static void ls_free(struct ls *l, size_t size); static void ls_free_arr(char **arr, size_t size); static int ls_get(struct ls **m, size_t *size, const struct lxc_arguments *args, const char *basepath, const char *parent, unsigned int lvl, char **lockpath, size_t len_lockpath, char **grps_must, size_t grps_must_len); static char *ls_get_cgroup_item(struct lxc_container *c, const char *item); static char *ls_get_config_item(struct lxc_container *c, const char *item, bool running); static char *ls_get_groups(struct lxc_container *c, bool running); static char *ls_get_ips(struct lxc_container *c, const char *inet); static int ls_recv_str(int fd, char **buf); static int ls_send_str(int fd, const char *buf); struct wrapargs { const struct lxc_arguments *args; char **grps_must; size_t grps_must_len; int pipefd[2]; size_t *size; const char *parent; unsigned int nestlvl; }; /* * Takes struct wrapargs as argument. */ static int ls_get_wrapper(void *wrap); /* * To calculate swap usage we should not simply check memory.usage_in_bytes and * memory.memsw.usage_in_bytes and then do: * swap = memory.memsw.usage_in_bytes - memory.usage_in_bytes; * because we might receive an incorrect/negative value. * Instead we check memory.stat and check the "swap" value. */ static double ls_get_swap(struct lxc_container *c); static unsigned int ls_get_term_width(void); static char *ls_get_interface(struct lxc_container *c); static bool ls_has_all_grps(const char *has, char **must, size_t must_len); static struct ls *ls_new(struct ls **ls, size_t *size); /* * Print user-specified fancy format. */ static void ls_print_fancy_format(struct ls *l, struct lengths *lht, size_t size, const char *fancy_fmt); /* * Only print names of containers. */ static void ls_print_names(struct ls *l, struct lengths *lht, size_t ls_arr, size_t termwidth, bool list); /* * Print default fancy format. */ static void ls_print_table(struct ls *l, struct lengths *lht, size_t size); /* * id can only be 79 + \0 chars long. */ static int ls_remove_lock(const char *path, const char *name, char **lockpath, size_t *len_lockpath, bool recalc); static int ls_serialize(int wpipefd, struct ls *n); static int my_parser(struct lxc_arguments *args, int c, char *arg); static const struct option my_longopts[] = { {"line", no_argument, 0, '1'}, {"fancy", no_argument, 0, 'f'}, {"fancy-format", required_argument, 0, 'F'}, {"active", no_argument, 0, LS_ACTIVE}, {"running", no_argument, 0, LS_RUNNING}, {"frozen", no_argument, 0, LS_FROZEN}, {"stopped", no_argument, 0, LS_STOPPED}, {"nesting", optional_argument, 0, LS_NESTING}, {"groups", required_argument, 0, 'g'}, {"filter", required_argument, 0, LS_FILTER}, LXC_COMMON_OPTIONS }; static struct lxc_arguments my_args = { .progname = "lxc-ls", .help = "\n\ [-P lxcpath] [--active] [--running] [--frozen] [--stopped] [--nesting] [-g groups] [--filter regex]\n\ [-1] [-P lxcpath] [--active] [--running] [--frozen] [--stopped] [--nesting] [-g groups] [--filter regex]\n\ [-f] [-P lxcpath] [--active] [--running] [--frozen] [--stopped] [--nesting] [-g groups] [--filter regex]\n\ \n\ lxc-ls list containers\n\ \n\ Options :\n\ -1, --line show one entry per line\n\ -f, --fancy use a fancy, column-based output\n\ -F, --fancy-format comma separated list of columns to show in the fancy output\n\ valid columns are: NAME, STATE, PID, RAM, SWAP, AUTOSTART,\n\ GROUPS, INTERFACE, IPV4 and IPV6\n\ --active list only active containers\n\ --running list only running containers\n\ --frozen list only frozen containers\n\ --stopped list only stopped containers\n\ --nesting=NUM list nested containers up to NUM (default is 5) levels of nesting\n\ --filter=REGEX filter container names by regular expression\n\ -g --groups comma separated list of groups a container must have to be displayed\n", .options = my_longopts, .parser = my_parser, .ls_nesting = 0, }; int main(int argc, char *argv[]) { int ret = EXIT_FAILURE; /* * The lxc parser requires that my_args.name is set. So let's satisfy * that condition by setting a dummy name which is never used. */ my_args.name = ""; if (lxc_arguments_parse(&my_args, argc, argv)) exit(EXIT_FAILURE); if (!my_args.log_file) my_args.log_file = "none"; /* * We set the first argument that usually takes my_args.name to NULL so * that the log is only used when the user specifies a file. */ if (lxc_log_init(NULL, my_args.log_file, my_args.log_priority, my_args.progname, my_args.quiet, my_args.lxcpath[0])) exit(EXIT_FAILURE); lxc_log_options_no_override(); struct lengths max_len = { /* default header length */ .name_length = 4, /* NAME */ .state_length = 5, /* STATE */ .groups_length = 6, /* GROUPS */ .interface_length = 9, /* INTERFACE */ .ipv4_length = 4, /* IPV4 */ .ipv6_length = 4, /* IPV6 */ .init_length = 3, /* PID */ .ram_length = 3, /* RAM */ .swap_length = 4, /* SWAP */ .autostart_length = 9, /* AUTOSTART */ }; char **grps = NULL; size_t ngrps = 0; if (my_args.groups) { grps = lxc_string_split_and_trim(my_args.groups, ','); ngrps = lxc_array_len((void **)grps); } struct ls *ls_arr = NULL; size_t ls_size = 0; /* &(char *){NULL} is no magic. It's just a compound literal which * avoids having a pointless variable in main() that serves no purpose * here. */ int status = ls_get(&ls_arr, &ls_size, &my_args, "", NULL, 0, &(char *){NULL}, 0, grps, ngrps); if (!ls_arr && status == 0) /* We did not fail. There was just nothing to do. */ exit(EXIT_SUCCESS); else if (!ls_arr || status == -1) goto out; ls_field_width(ls_arr, ls_size, &max_len); if (my_args.ls_fancy && !my_args.ls_fancy_format) { ls_print_table(ls_arr, &max_len, ls_size); } else if (my_args.ls_fancy && my_args.ls_fancy_format) { ls_print_fancy_format(ls_arr, &max_len, ls_size, my_args.ls_fancy_format); } else { unsigned int cols = 0; if (!my_args.ls_line) cols = ls_get_term_width(); ls_print_names(ls_arr, &max_len, ls_size, cols, my_args.ls_line); } ret = EXIT_SUCCESS; out: ls_free(ls_arr, ls_size); lxc_free_array((void **)grps, free); exit(ret); } static void ls_free(struct ls *l, size_t size) { size_t i; struct ls *m = NULL; for (i = 0, m = l; i < size; i++, m++) { free(m->groups); free(m->interface); free(m->ipv4); free(m->ipv6); free(m->name); free(m->state); } free(l); } static char *ls_get_config_item(struct lxc_container *c, const char *item, bool running) { if (running) return c->get_running_config_item(c, item); size_t len = c->get_config_item(c, item, NULL, 0); if (len <= 0) return NULL; char *val = malloc((len + 1) * sizeof(*val)); if (!val) return NULL; if ((size_t)c->get_config_item(c, item, val, len + 1) != len) { free(val); val = NULL; } return val; } static void ls_free_arr(char **arr, size_t size) { size_t i; for (i = 0; i < size; i++) free(arr[i]); free(arr); } static int ls_get(struct ls **m, size_t *size, const struct lxc_arguments *args, const char *basepath, const char *parent, unsigned int lvl, char **lockpath, size_t len_lockpath, char **grps_must, size_t grps_must_len) { /* As ls_get() is non-tail recursive we face the inherent danger of * blowing up the stack at some level of nesting. To have at least some * security we define MAX_NESTLVL to be 5. That should be sufficient for * most users. The argument lvl can be used to keep track of the level * of nesting we are at. If lvl is greater than the allowed default * level or the level the user specified on the command line we return * and unwind the stack. */ if (lvl > args->ls_nesting) return 0; int num = 0, ret = -1; char **containers = NULL; /* If we, at some level of nesting, encounter a stopped container but * want to retrieve nested containers we need to build an absolute path * beginning from it. Initially, at nesting level 0, basepath will * simply be the empty string and path will simply be whatever the * default lxcpath or the path the user gave us is. Basepath will also * be the empty string in case we encounter a running container since we * can simply attach to its namespace to retrieve nested containers. */ char *path = lxc_append_paths(basepath, args->lxcpath[0]); if (!path) goto out; if (!dir_exists(path)) { ret = 0; goto out; } /* Do not do more work than is necessary right from the start. */ if (args->ls_active || args->ls_frozen) num = list_active_containers(path, &containers, NULL); else num = list_all_containers(path, &containers, NULL); if (num == -1) { num = 0; goto out; } char *tmp = NULL; int check; struct ls *l = NULL; struct lxc_container *c = NULL; size_t i; for (i = 0; i < (size_t)num; i++) { char *name = containers[i]; /* Filter container names by regex the user gave us. */ if (args->ls_filter || args->argc == 1) { regex_t preg; tmp = args->ls_filter ? args->ls_filter : args->argv[0]; check = regcomp(&preg, tmp, REG_NOSUB | REG_EXTENDED); if (check == REG_ESPACE) /* we're out of memory */ goto out; else if (check != 0) continue; check = regexec(&preg, name, 0, NULL, 0); regfree(&preg); if (check != 0) continue; } errno = 0; c = lxc_container_new(name, path); if ((errno == ENOMEM) && !c) goto out; else if (!c) continue; if (!c->is_defined(c)) goto put_and_next; /* This does not allocate memory so no worries about freeing it * when we goto next or out. */ const char *state_tmp = c->state(c); if (!state_tmp) state_tmp = "UNKNOWN"; if (args->ls_running && !c->is_running(c)) goto put_and_next; if (args->ls_frozen && !args->ls_active && strcmp(state_tmp, "FROZEN")) goto put_and_next; if (args->ls_stopped && strcmp(state_tmp, "STOPPED")) goto put_and_next; bool running = c->is_running(c); char *grp_tmp = ls_get_groups(c, running); if (!ls_has_all_grps(grp_tmp, grps_must, grps_must_len)) { free(grp_tmp); goto put_and_next; } /* Now it makes sense to allocate memory. */ l = ls_new(m, size); if (!l) { free(grp_tmp); goto put_and_next; } /* How deeply nested are we? */ l->nestlvl = lvl; l->groups = grp_tmp; l->running = running; if (parent && args->ls_nesting && (args->ls_line || !args->ls_fancy)) /* Prepend the name of the container with all its parents when * the user requests it. */ l->name = lxc_append_paths(parent, name); else /* Otherwise simply record the name. */ l->name = strdup(name); if (!l->name) goto put_and_next; /* Do not record stuff the user did not explictly request. */ if (args->ls_fancy) { /* Maybe we should even consider the name sensitive and * hide it when you're not allowed to control the * container. */ if (!c->may_control(c)) goto put_and_next; l->state = strdup(state_tmp); if (!l->state) goto put_and_next; tmp = ls_get_config_item(c, "lxc.start.auto", running); if (tmp) { unsigned int astart = 0; if (lxc_safe_uint(tmp, &astart) < 0) WARN("Could not parse value for 'lxc.start.auto'."); if (astart > 1) DEBUG("Wrong value for 'lxc.start.auto = %d'.", astart); l->autostart = astart == 1 ? true : false; } free(tmp); if (running) { l->init = c->init_pid(c); l->interface = ls_get_interface(c); l->ipv4 = ls_get_ips(c, "inet"); l->ipv6 = ls_get_ips(c, "inet6"); tmp = ls_get_cgroup_item(c, "memory.usage_in_bytes"); if (tmp) { l->ram = strtoull(tmp, NULL, 0); l->ram = l->ram / 1024 /1024; free(tmp); } l->swap = ls_get_swap(c); } } /* Get nested containers: Only do this after we have gathered * all other information we need. */ if (args->ls_nesting && running) { struct wrapargs wargs = (struct wrapargs){.args = NULL}; /* Open a socket so that the child can communicate with us. */ check = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, wargs.pipefd); if (check == -1) goto put_and_next; /* Set the next nesting level. */ wargs.nestlvl = lvl + 1; /* Send in the parent for the next nesting level. */ wargs.parent = l->name; wargs.args = args; wargs.grps_must = grps_must; wargs.grps_must_len = grps_must_len; pid_t out; lxc_attach_options_t aopt = LXC_ATTACH_OPTIONS_DEFAULT; aopt.env_policy = LXC_ATTACH_CLEAR_ENV; /* fork(): Attach to the namespace of the container and * run ls_get() in it which is called in ls_get_wrapper(). */ check = c->attach(c, ls_get_wrapper, &wargs, &aopt, &out); /* close the socket */ close(wargs.pipefd[1]); /* Retrieve all information we want from the child. */ if (check == 0) if (ls_deserialize(wargs.pipefd[0], m, size) == -1) goto put_and_next; /* Wait for the child to finish. */ wait_for_pid(out); /* We've done all the communication we need so shutdown * the socket and close it. */ shutdown(wargs.pipefd[0], SHUT_RDWR); close(wargs.pipefd[0]); } else if (args->ls_nesting && !running) { /* This way of extracting the rootfs is not safe since * it will return very different things depending on the * storage backend that is used for the container. We * need a path-extractor function. We face the same * problem with the ovl_mkdir() function in * lxcoverlay.{c,h}. */ char *curr_path = ls_get_config_item(c, "lxc.rootfs", running); if (!curr_path) goto put_and_next; /* Since the container is not running and we cannot * attach to it we need another strategy to retrieve * nested containers. What we do is simply create a * growing path which will lead us into the rootfs of * the next container where it stores its containers. */ char *newpath = lxc_append_paths(basepath, curr_path); free(curr_path); if (!newpath) goto put_and_next; /* We want to remove all locks we create under * /run/lxc/lock so we create a string pointing us to * the lock path for the current container. */ if (ls_remove_lock(path, name, lockpath, &len_lockpath, true) == -1) goto put_and_next; ls_get(m, size, args, newpath, l->name, lvl + 1, lockpath, len_lockpath, grps_must, grps_must_len); free(newpath); /* Remove the lock. No need to check for failure here. */ ls_remove_lock(path, name, lockpath, &len_lockpath, false); } put_and_next: lxc_container_put(c); } ret = 0; out: ls_free_arr(containers, num); free(path); /* lockpath is shared amongst all non-fork()ing recursive calls to * ls_get() so only free it on the uppermost level. */ if (lvl == 0) free(*lockpath); return ret; } static char *ls_get_cgroup_item(struct lxc_container *c, const char *item) { size_t len = c->get_cgroup_item(c, item, NULL, 0); if (len <= 0) return NULL; char *val = malloc((len + 1) * sizeof(*val)); if (!val) return NULL; if ((size_t)c->get_cgroup_item(c, item, val, len + 1) != len) { free(val); val = NULL; } return val; } static char *ls_get_groups(struct lxc_container *c, bool running) { size_t len = 0; char *val = NULL; if (running) val = c->get_running_config_item(c, "lxc.group"); else len = c->get_config_item(c, "lxc.group", NULL, 0); if (!val && (len > 0)) { val = malloc((len + 1) * sizeof(*val)); if ((size_t)c->get_config_item(c, "lxc.group", val, len + 1) != len) { free(val); return NULL; } } if (val) { char *tmp; if ((tmp = strrchr(val, '\n'))) *tmp = '\0'; tmp = lxc_string_replace("\n", ", ", val); free(val); val = tmp; } return val; } static char *ls_get_ips(struct lxc_container *c, const char *inet) { char *ips = NULL; char **iptmp = c->get_ips(c, NULL, inet, 0); if (iptmp) ips = lxc_string_join(", ", (const char **)iptmp, false); lxc_free_array((void **)iptmp, free); return ips; } static char *ls_get_interface(struct lxc_container *c) { char **interfaces = c->get_interfaces(c); if (!interfaces) return NULL; char *interface = lxc_string_join(", ", (const char **)interfaces, false); lxc_free_array((void **)interfaces, free); return interface; } /* * To calculate swap usage we should not simply check memory.usage_in_bytes and * memory.memsw.usage_in_bytes and then do: * swap = memory.memsw.usage_in_bytes - memory.usage_in_bytes; * because we might receive an incorrect/negative value. * Instead we check memory.stat and check the "swap" value. */ static double ls_get_swap(struct lxc_container *c) { unsigned long long int num = 0; char *stat = ls_get_cgroup_item(c, "memory.stat"); if (!stat) goto out; char *swap = strstr(stat, "\nswap"); if (!swap) goto out; swap = 1 + swap + 4 + 1; // start_of_swap_value = '\n' + strlen(swap) + ' ' char *tmp = strchr(swap, '\n'); // find end of swap value if (!tmp) goto out; *tmp = '\0'; num = strtoull(swap, NULL, 0); num = num / 1024 / 1024; out: free(stat); return num; } static unsigned int ls_get_term_width(void) { struct winsize ws; if (((ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1) && (ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == -1) && (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1)) || (ws.ws_col == 0)) return 0; return ws.ws_col; } static bool ls_has_all_grps(const char *has, char **must, size_t must_len) { bool bret = false; if (!has && must) return false; else if (!must) return true; char **tmp_has = lxc_string_split_and_trim(has, ','); size_t tmp_has_len = lxc_array_len((void **)tmp_has); /* Don't do any unnecessary work. */ if (must_len > tmp_has_len) goto out; size_t i, j; for (i = 0; i < must_len; i++) { for (j = 0; j < tmp_has_len; j++) if (strcmp(must[i], tmp_has[j]) == 0) break; if (j == tmp_has_len) break; } if (i == must_len) bret = true; out: lxc_free_array((void **)tmp_has, free); return bret; } static struct ls *ls_new(struct ls **ls, size_t *size) { struct ls *m, *n; n = realloc(*ls, (*size + 1) * sizeof(struct ls)); if (!n) return NULL; *ls = n; m = *ls + *size; (*size)++; *m = (struct ls){.name = NULL, .init = -1}; return m; } static void ls_print_names(struct ls *l, struct lengths *lht, size_t size, size_t termwidth, bool list) { /* If list is empty do nothing. */ if (size == 0) return; size_t i, len = 0; struct ls *m = NULL; for (i = 0, m = l; i < size; i++, m++) { if (list) { printf("%s\n", m->name ? m->name : "-"); } else { printf("%-*s", lht->name_length, m->name ? m->name : "-"); len += lht->name_length; if ((len + lht->name_length) >= termwidth) { printf("\n"); len = 0; } else { printf(" "); len++; } } } if (len > 0) printf("\n"); } static void ls_print_fancy_format(struct ls *l, struct lengths *lht, size_t size, const char *fancy_fmt) { /* If list is empty do nothing. */ if (size == 0) return; char **tmp = lxc_string_split_and_trim(fancy_fmt, ','); if (!tmp) return; char **s; /* Check for invalid keys. */ for (s = tmp; s && *s; s++) { if (strcasecmp(*s, "NAME") && strcasecmp(*s, "STATE") && strcasecmp(*s, "PID") && strcasecmp(*s, "RAM") && strcasecmp(*s, "SWAP") && strcasecmp(*s, "AUTOSTART") && strcasecmp(*s, "GROUPS") && strcasecmp(*s, "INTERFACE") && strcasecmp(*s, "IPV4") && strcasecmp(*s, "IPV6")) { fprintf(stderr, "Invalid key: %s\n", *s); return; } } /* print header */ for (s = tmp; s && *s; s++) { if (strcasecmp(*s, "NAME") == 0) printf("%-*s ", lht->name_length, "NAME"); else if (strcasecmp(*s, "STATE") == 0) printf("%-*s ", lht->state_length, "STATE"); else if (strcasecmp(*s, "PID") == 0) printf("%-*s ", lht->init_length, "PID"); else if (strcasecmp(*s, "RAM") == 0) printf("%-*s ", lht->ram_length + 2, "RAM"); else if (strcasecmp(*s, "SWAP") == 0) printf("%-*s ", lht->swap_length + 2, "SWAP"); else if (strcasecmp(*s, "AUTOSTART") == 0) printf("%-*s ", lht->autostart_length, "AUTOSTART"); else if (strcasecmp(*s, "GROUPS") == 0) printf("%-*s ", lht->groups_length, "GROUPS"); else if (strcasecmp(*s, "INTERFACE") == 0) printf("%-*s ", lht->interface_length, "INTERFACE"); else if (strcasecmp(*s, "IPV4") == 0) printf("%-*s ", lht->ipv4_length, "IPV4"); else if (strcasecmp(*s, "IPV6") == 0) printf("%-*s ", lht->ipv6_length, "IPV6"); } printf("\n"); struct ls *m = NULL; size_t i; for (i = 0, m = l; i < size; i++, m++) { for (s = tmp; s && *s; s++) { if (strcasecmp(*s, "NAME") == 0) { if (m->nestlvl > 0) { printf("%*s", m->nestlvl, "\\"); printf("%-*s ", lht->name_length - m->nestlvl, m->name ? m->name : "-"); } else { printf("%-*s ", lht->name_length, m->name ? m->name : "-"); } } else if (strcasecmp(*s, "STATE") == 0) { printf("%-*s ", lht->state_length, m->state ? m->state : "-"); } else if (strcasecmp(*s, "PID") == 0) { if (m->init > 0) printf("%-*d ", lht->init_length, m->init); else printf("%-*s ", lht->init_length, "-"); } else if (strcasecmp(*s, "RAM") == 0) { if ((m->ram >= 0) && m->running) printf("%*.2fMB ", lht->ram_length, m->ram); else printf("%-*s ", lht->ram_length, "-"); } else if (strcasecmp(*s, "SWAP") == 0) { if ((m->swap >= 0) && m->running) printf("%*.2fMB ", lht->swap_length, m->swap); else printf("%-*s ", lht->swap_length, "-"); } else if (strcasecmp(*s, "AUTOSTART") == 0) { printf("%-*d ", lht->autostart_length, m->autostart); } else if (strcasecmp(*s, "GROUPS") == 0) { printf("%-*s ", lht->groups_length, m->groups ? m->groups : "-"); } else if (strcasecmp(*s, "INTERFACE") == 0) { printf("%-*s ", lht->interface_length, m->interface ? m->interface : "-"); } else if (strcasecmp(*s, "IPV4") == 0) { printf("%-*s ", lht->ipv4_length, m->ipv4 ? m->ipv4 : "-"); } else if (strcasecmp(*s, "IPV6") == 0) { printf("%-*s ", lht->ipv6_length, m->ipv6 ? m->ipv6 : "-"); } } printf("\n"); } } static void ls_print_table(struct ls *l, struct lengths *lht, size_t size) { /* If list is empty do nothing. */ if (size == 0) return; struct ls *m = NULL; /* print header */ printf("%-*s ", lht->name_length, "NAME"); printf("%-*s ", lht->state_length, "STATE"); printf("%-*s ", lht->autostart_length, "AUTOSTART"); printf("%-*s ", lht->groups_length, "GROUPS"); printf("%-*s ", lht->ipv4_length, "IPV4"); printf("%-*s ", lht->ipv6_length, "IPV6"); printf("\n"); size_t i; for (i = 0, m = l; i < size; i++, m++) { if (m->nestlvl > 0) { printf("%*s", m->nestlvl, "\\"); printf("%-*s ", lht->name_length - m->nestlvl, m->name ? m->name : "-"); } else { printf("%-*s ", lht->name_length, m->name ? m->name : "-"); } printf("%-*s ", lht->state_length, m->state ? m->state : "-"); printf("%-*d ", lht->autostart_length, m->autostart); printf("%-*s ", lht->groups_length, m->groups ? m->groups : "-"); printf("%-*s ", lht->ipv4_length, m->ipv4 ? m->ipv4 : "-"); printf("%-*s ", lht->ipv6_length, m->ipv6 ? m->ipv6 : "-"); printf("\n"); } } static int my_parser(struct lxc_arguments *args, int c, char *arg) { char *invalid; unsigned long int m, n = MAX_NESTLVL; switch (c) { case '1': args->ls_line = true; break; case 'f': args->ls_fancy = true; break; case LS_ACTIVE: args->ls_active = true; break; case LS_FROZEN: args->ls_frozen = true; break; case LS_RUNNING: args->ls_running = true; break; case LS_STOPPED: args->ls_stopped = true; break; case LS_NESTING: /* In case strtoul() receives a string that represents a * negative number it will return ULONG_MAX - the number that * the string represents if the number the string represents is * < ULONG_MAX and ULONG_MAX otherwise. But it will consider * this valid input and not set errno. So we check manually if * the first character of num_string == '-'. Otherwise the * default level remains set. */ if (arg && !(*arg == '-')) { errno = 0; m = strtoul(arg, &invalid, 0); /* ls_nesting has type unsigned int. */ if (!errno && (*invalid == '\0') && (m <= UINT_MAX)) n = m; } args->ls_nesting = n; break; case 'g': args->groups = arg; break; case LS_FILTER: args->ls_filter = arg; break; case 'F': args->ls_fancy_format = arg; break; } return 0; } static int ls_get_wrapper(void *wrap) { int ret = -1; size_t len = 0; struct wrapargs *wargs = (struct wrapargs *)wrap; struct ls *m = NULL, *n = NULL; /* close pipe */ close(wargs->pipefd[0]); /* &(char *){NULL} is no magic. It's just a compound literal which * allows us to avoid keeping a pointless variable around. */ ls_get(&m, &len, wargs->args, "", wargs->parent, wargs->nestlvl, &(char *){NULL}, 0, wargs->grps_must, wargs->grps_must_len); if (!m) goto out; /* send length */ if (lxc_write_nointr(wargs->pipefd[1], &len, sizeof(len)) <= 0) goto out; size_t i; for (i = 0, n = m; i < len; i++, n++) { if (ls_serialize(wargs->pipefd[1], n) == -1) goto out; } ret = 0; out: shutdown(wargs->pipefd[1], SHUT_RDWR); close(wargs->pipefd[1]); ls_free(m, len); return ret; } static int ls_remove_lock(const char *path, const char *name, char **lockpath, size_t *len_lockpath, bool recalc) { int ret = -1; char *rundir; /* lockfile will be: * "/run" + "/lxc/lock/$lxcpath/$lxcname + '\0' if root * or * $XDG_RUNTIME_DIR + "/lxc/lock/$lxcpath/$lxcname + '\0' if non-root */ rundir = get_rundir(); if (!rundir) goto out; /* Avoid doing unnecessary work if we can. */ if (recalc) { size_t newlen = strlen(path) + strlen(name) + strlen(rundir) + /* / + lxc + / + lock + / + / = */ 11 + 1; if (newlen > *len_lockpath) { char *tmp = realloc(*lockpath, newlen * 2); if (!tmp) goto out; *lockpath = tmp; *len_lockpath = newlen * 2; } } int check = snprintf(*lockpath, *len_lockpath, "%s/lxc/lock/%s/%s", rundir, path, name); if (check < 0 || (size_t)check >= *len_lockpath) goto out; lxc_rmdir_onedev(*lockpath, NULL); ret = 0; out: free(rundir); return ret; } static int ls_send_str(int fd, const char *buf) { size_t slen = 0; if (buf) slen = strlen(buf); if (lxc_write_nointr(fd, &slen, sizeof(slen)) != sizeof(slen)) return -1; if (slen > 0) { if (lxc_write_nointr(fd, buf, slen) != (ssize_t)slen) return -1; } return 0; } static int ls_serialize(int wpipefd, struct ls *n) { ssize_t nbytes = sizeof(n->ram); if (lxc_write_nointr(wpipefd, &n->ram, (size_t)nbytes) != nbytes) return -1; nbytes = sizeof(n->swap); if (lxc_write_nointr(wpipefd, &n->swap, (size_t)nbytes) != nbytes) return -1; nbytes = sizeof(n->init); if (lxc_write_nointr(wpipefd, &n->init, (size_t)nbytes) != nbytes) return -1; nbytes = sizeof(n->autostart); if (lxc_write_nointr(wpipefd, &n->autostart, (size_t)nbytes) != nbytes) return -1; nbytes = sizeof(n->running); if (lxc_write_nointr(wpipefd, &n->running, (size_t)nbytes) != nbytes) return -1; nbytes = sizeof(n->nestlvl); if (lxc_write_nointr(wpipefd, &n->nestlvl, (size_t)nbytes) != nbytes) return -1; /* NAME */ if (ls_send_str(wpipefd, n->name) < 0) return -1; /* STATE */ if (ls_send_str(wpipefd, n->state) < 0) return -1; /* GROUPS */ if (ls_send_str(wpipefd, n->groups) < 0) return -1; /* INTERFACE */ if (ls_send_str(wpipefd, n->interface) < 0) return -1; /* IPV4 */ if (ls_send_str(wpipefd, n->ipv4) < 0) return -1; /* IPV6 */ if (ls_send_str(wpipefd, n->ipv6) < 0) return -1; return 0; } static int ls_recv_str(int fd, char **buf) { size_t slen = 0; if (lxc_read_nointr(fd, &slen, sizeof(slen)) != sizeof(slen)) return -1; if (slen > 0) { *buf = malloc(sizeof(char) * (slen + 1)); if (!*buf) return -1; if (lxc_read_nointr(fd, *buf, slen) != (ssize_t)slen) return -1; (*buf)[slen] = '\0'; } return 0; } static int ls_deserialize(int rpipefd, struct ls **m, size_t *len) { struct ls *n; size_t sublen = 0; ssize_t nbytes = 0; /* get length */ nbytes = sizeof(sublen); if (lxc_read_nointr(rpipefd, &sublen, (size_t)nbytes) != nbytes) return -1; while (sublen-- > 0) { n = ls_new(m, len); if (!n) return -1; nbytes = sizeof(n->ram); if (lxc_read_nointr(rpipefd, &n->ram, (size_t)nbytes) != nbytes) return -1; nbytes = sizeof(n->swap); if (lxc_read_nointr(rpipefd, &n->swap, (size_t)nbytes) != nbytes) return -1; nbytes = sizeof(n->init); if (lxc_read_nointr(rpipefd, &n->init, (size_t)nbytes) != nbytes) return -1; nbytes = sizeof(n->autostart); if (lxc_read_nointr(rpipefd, &n->autostart, (size_t)nbytes) != nbytes) return -1; nbytes = sizeof(n->running); if (lxc_read_nointr(rpipefd, &n->running, (size_t)nbytes) != nbytes) return -1; nbytes = sizeof(n->nestlvl); if (lxc_read_nointr(rpipefd, &n->nestlvl, (size_t)nbytes) != nbytes) return -1; /* NAME */ if (ls_recv_str(rpipefd, &n->name) < 0) return -1; /* STATE */ if (ls_recv_str(rpipefd, &n->state) < 0) return -1; /* GROUPS */ if (ls_recv_str(rpipefd, &n->groups) < 0) return -1; /* INTERFACE */ if (ls_recv_str(rpipefd, &n->interface) < 0) return -1; /* IPV4 */ if (ls_recv_str(rpipefd, &n->ipv4) < 0) return -1; /* IPV6 */ if (ls_recv_str(rpipefd, &n->ipv6) < 0) return -1; } return 0; } static void ls_field_width(const struct ls *l, const size_t size, struct lengths *lht) { const struct ls *m; size_t i, len = 0; for (i = 0, m = l; i < size; i++, m++) { if (m->name) { len = strlen(m->name) + m->nestlvl; if (len > lht->name_length) lht->name_length = len; } if (m->state) { len = strlen(m->state); if (len > lht->state_length) lht->state_length = len; } if (m->interface) { len = strlen(m->interface); if (len > lht->interface_length) lht->interface_length = len; } if (m->groups) { len = strlen(m->groups); if (len > lht->groups_length) lht->groups_length = len; } if (m->ipv4) { len = strlen(m->ipv4); if (len > lht->ipv4_length) lht->ipv4_length = len; } if (m->ipv6) { len = strlen(m->ipv6); if (len > lht->ipv6_length) lht->ipv6_length = len; } if ((len = snprintf(NULL, 0, "%.2f", m->ram)) > lht->ram_length) lht->ram_length = len; if ((len = snprintf(NULL, 0, "%.2f", m->swap)) > lht->swap_length) lht->swap_length = len; if (m->init != -1) { if ((len = snprintf(NULL, 0, "%d", m->init)) > lht->init_length) lht->init_length = len; } } } lxc-2.0.8/src/lxc/tools/lxc_console.c0000644061062106075000000000737113105116772014444 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "arguments.h" #include "commands.h" #include "error.h" #include "log.h" #include "lxc.h" #include "mainloop.h" #include "utils.h" lxc_log_define(lxc_console_ui, lxc); static char etoc(const char *expr) { /* returns "control code" of given expression */ char c = expr[0] == '^' ? expr[1] : expr[0]; return 1 + ((c > 'Z') ? (c - 'a') : (c - 'Z')); } static int my_parser(struct lxc_arguments* args, int c, char* arg) { switch (c) { case 't': if (lxc_safe_uint(arg, &args->ttynum) < 0) return -1; break; case 'e': args->escape = etoc(arg); break; } return 0; } static const struct option my_longopts[] = { {"tty", required_argument, 0, 't'}, {"escape", required_argument, 0, 'e'}, LXC_COMMON_OPTIONS }; static struct lxc_arguments my_args = { .progname = "lxc-console", .help = "\ --name=NAME [--tty NUMBER]\n\ \n\ lxc-console logs on the container with the identifier NAME\n\ \n\ Options :\n\ -n, --name=NAME NAME of the container\n\ -t, --tty=NUMBER console tty number\n\ -e, --escape=PREFIX prefix for escape command\n\ --rcfile=FILE Load configuration file FILE\n", .options = my_longopts, .parser = my_parser, .checker = NULL, .ttynum = -1, .escape = 1, }; int main(int argc, char *argv[]) { int ret; struct lxc_container *c; ret = lxc_arguments_parse(&my_args, argc, argv); if (ret) return EXIT_FAILURE; if (!my_args.log_file) my_args.log_file = "none"; ret = lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority, my_args.progname, my_args.quiet, my_args.lxcpath[0]); if (ret) return EXIT_FAILURE; lxc_log_options_no_override(); c = lxc_container_new(my_args.name, my_args.lxcpath[0]); if (!c) { fprintf(stderr, "System error loading container\n"); exit(EXIT_FAILURE); } if (my_args.rcfile) { c->clear_config(c); if (!c->load_config(c, my_args.rcfile)) { fprintf(stderr, "Failed to load rcfile\n"); lxc_container_put(c); exit(EXIT_FAILURE); } c->configfile = strdup(my_args.rcfile); if (!c->configfile) { fprintf(stderr, "Out of memory setting new config filename\n"); lxc_container_put(c); exit(EXIT_FAILURE); } } if (!c->may_control(c)) { fprintf(stderr, "Insufficent privileges to control %s\n", my_args.name); lxc_container_put(c); exit(EXIT_FAILURE); } if (!c->is_running(c)) { fprintf(stderr, "%s is not running\n", my_args.name); lxc_container_put(c); exit(EXIT_FAILURE); } ret = c->console(c, my_args.ttynum, 0, 1, 2, my_args.escape); if (ret < 0) { lxc_container_put(c); exit(EXIT_FAILURE); } lxc_container_put(c); exit(EXIT_SUCCESS); } lxc-2.0.8/src/lxc/tools/lxc_unfreeze.c0000644061062106075000000000530713105116772014622 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include "lxc.h" #include "log.h" #include "arguments.h" lxc_log_define(lxc_unfreeze_ui, lxc); static const struct option my_longopts[] = { LXC_COMMON_OPTIONS }; static struct lxc_arguments my_args = { .progname = "lxc-unfreeze", .help = "\ --name=NAME\n\ \n\ lxc-unfreeze unfreezes a container with the identifier NAME\n\ \n\ Options :\n\ -n, --name=NAME NAME of the container\n\ --rcfile=FILE Load configuration file FILE\n", .options = my_longopts, .parser = NULL, .checker = NULL, }; int main(int argc, char *argv[]) { struct lxc_container *c; if (lxc_arguments_parse(&my_args, argc, argv)) exit(EXIT_FAILURE); if (!my_args.log_file) my_args.log_file = "none"; if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority, my_args.progname, my_args.quiet, my_args.lxcpath[0])) exit(EXIT_FAILURE); lxc_log_options_no_override(); c = lxc_container_new(my_args.name, my_args.lxcpath[0]); if (!c) { ERROR("No such container: %s:%s", my_args.lxcpath[0], my_args.name); exit(EXIT_FAILURE); } if (!c->may_control(c)) { ERROR("Insufficent privileges to control %s:%s", my_args.lxcpath[0], my_args.name); lxc_container_put(c); exit(EXIT_FAILURE); } if (my_args.rcfile) { c->clear_config(c); if (!c->load_config(c, my_args.rcfile)) { ERROR("Failed to load rcfile"); lxc_container_put(c); exit(EXIT_FAILURE); } c->configfile = strdup(my_args.rcfile); if (!c->configfile) { ERROR("Out of memory setting new config filename"); lxc_container_put(c); exit(EXIT_FAILURE); } } if (!c->unfreeze(c)) { ERROR("Failed to unfreeze %s:%s", my_args.lxcpath[0], my_args.name); lxc_container_put(c); exit(EXIT_FAILURE); } lxc_container_put(c); exit(EXIT_SUCCESS); } lxc-2.0.8/src/lxc/tools/lxc_create.c0000644061062106075000000002221313105116772014235 00000000000000/* * * Copyright © 2013 Serge Hallyn . * Copyright © 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include #include #include "arguments.h" #include "bdev.h" #include "log.h" #include "lxc.h" #include "utils.h" lxc_log_define(lxc_create_ui, lxc); static uint64_t get_fssize(char *s) { uint64_t ret; char *end; ret = strtoull(s, &end, 0); if (end == s) { fprintf(stderr, "Invalid blockdev size '%s', using default size\n", s); return 0; } while (isblank(*end)) end++; if (*end == '\0') ret *= 1024ULL * 1024ULL; // MB by default else if (*end == 'b' || *end == 'B') ret *= 1ULL; else if (*end == 'k' || *end == 'K') ret *= 1024ULL; else if (*end == 'm' || *end == 'M') ret *= 1024ULL * 1024ULL; else if (*end == 'g' || *end == 'G') ret *= 1024ULL * 1024ULL * 1024ULL; else if (*end == 't' || *end == 'T') ret *= 1024ULL * 1024ULL * 1024ULL * 1024ULL; else { fprintf(stderr, "Invalid blockdev unit size '%c' in '%s', using default size\n", *end, s); return 0; } return ret; } static int my_parser(struct lxc_arguments* args, int c, char* arg) { switch (c) { case 'B': args->bdevtype = arg; break; case 'f': args->configfile = arg; break; case 't': args->template = arg; break; case '0': args->lvname = arg; break; case '1': args->vgname = arg; break; case '2': args->thinpool = arg; break; case '3': args->fstype = arg; break; case '4': args->fssize = get_fssize(arg); break; case '5': args->zfsroot = arg; break; case '6': args->dir = arg; break; case '7': args->rbdname = arg; break; case '8': args->rbdpool = arg; break; } return 0; } static const struct option my_longopts[] = { {"bdev", required_argument, 0, 'B'}, {"config", required_argument, 0, 'f'}, {"template", required_argument, 0, 't'}, {"lvname", required_argument, 0, '0'}, {"vgname", required_argument, 0, '1'}, {"thinpool", required_argument, 0, '2'}, {"fstype", required_argument, 0, '3'}, {"fssize", required_argument, 0, '4'}, {"zfsroot", required_argument, 0, '5'}, {"dir", required_argument, 0, '6'}, {"rbdname", required_argument, 0, '7'}, {"rbdpool", required_argument, 0, '8'}, LXC_COMMON_OPTIONS }; static void create_helpfn(const struct lxc_arguments *args) { char *argv[3], *path; pid_t pid; if (!args->template) return; pid = fork(); if (pid) { wait_for_pid(pid); return; } path = get_template_path(args->template); argv[0] = path; argv[1] = "-h"; argv[2] = NULL; execv(path, argv); ERROR("Error executing %s -h", path); exit(EXIT_FAILURE); } static struct lxc_arguments my_args = { .progname = "lxc-create", .helpfn = create_helpfn, .help = "\ --name=NAME --template=TEMPLATE [OPTION...]\n\ \n\ lxc-create creates a container\n\ \n\ Options :\n\ -n, --name=NAME NAME of the container\n\ -f, --config=CONFIG Initial configuration file\n\ -t, --template=TEMPLATE Template to use to setup container\n\ -B, --bdev=BDEV Backing store type to use\n\ --dir=DIR Place rootfs directory under DIR\n\ \n\ BDEV options for LVM (with -B/--bdev lvm):\n\ --lvname=LVNAME Use LVM lv name LVNAME\n\ (Default: container name)\n\ --vgname=VG Use LVM vg called VG\n\ (Default: lxc)\n\ --thinpool=TP Use LVM thin pool called TP\n\ (Default: lxc)\n\ \n\ BDEV options for Ceph RBD (with -B/--bdev rbd) :\n\ --rbdname=RBDNAME Use Ceph RBD name RBDNAME\n\ (Default: container name)\n\ --rbdpool=POOL Use Ceph RBD pool name POOL\n\ (Default: lxc)\n\ \n\ BDEV option for ZFS (with -B/--bdev zfs) :\n\ --zfsroot=PATH Create zfs under given zfsroot\n\ (Default: tank/lxc)\n\ \n\ BDEV options for LVM or Loop (with -B/--bdev lvm/loop) :\n\ --fstype=TYPE Create fstype TYPE\n\ (Default: ext3)\n\ --fssize=SIZE[U] Create filesystem of\n\ size SIZE * unit U (bBkKmMgGtT)\n\ (Default: 1G, default unit: M)\n", .options = my_longopts, .parser = my_parser, .checker = NULL, }; static bool validate_bdev_args(struct lxc_arguments *a) { if (strcmp(a->bdevtype, "best") != 0) { if (a->fstype || a->fssize) { if (strcmp(a->bdevtype, "lvm") != 0 && strcmp(a->bdevtype, "loop") != 0 && strcmp(a->bdevtype, "rbd") != 0) { fprintf(stderr, "filesystem type and size are only valid with block devices\n"); return false; } } if (strcmp(a->bdevtype, "lvm") != 0) { if (a->lvname || a->vgname || a->thinpool) { fprintf(stderr, "--lvname, --vgname and --thinpool are only valid with -B lvm\n"); return false; } } if (strcmp(a->bdevtype, "rbd") != 0) { if (a->rbdname || a->rbdpool) { fprintf(stderr, "--rbdname and --rbdpool are only valid with -B rbd\n"); return false; } } if (strcmp(a->bdevtype, "zfs") != 0) { if (a->zfsroot) { fprintf(stderr, "zfsroot is only valid with -B zfs\n"); return false; } } } return true; } int main(int argc, char *argv[]) { struct lxc_container *c; struct bdev_specs spec; int flags = 0; if (lxc_arguments_parse(&my_args, argc, argv)) exit(EXIT_FAILURE); if (!my_args.log_file) my_args.log_file = "none"; if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority, my_args.progname, my_args.quiet, my_args.lxcpath[0])) exit(EXIT_FAILURE); lxc_log_options_no_override(); if (!my_args.template) { fprintf(stderr, "A template must be specified.\n"); fprintf(stderr, "Use \"none\" if you really want a container without a rootfs.\n"); exit(EXIT_FAILURE); } if (strcmp(my_args.template, "none") == 0) my_args.template = NULL; memset(&spec, 0, sizeof(spec)); if (!my_args.bdevtype) my_args.bdevtype = "_unset"; if (!validate_bdev_args(&my_args)) exit(EXIT_FAILURE); if (strcmp(my_args.bdevtype, "none") == 0) my_args.bdevtype = "dir"; // Final check whether the user gave use a valid bdev type. if (strcmp(my_args.bdevtype, "best") && strcmp(my_args.bdevtype, "_unset") && !is_valid_bdev_type(my_args.bdevtype)) { fprintf(stderr, "%s is not a valid backing storage type.\n", my_args.bdevtype); exit(EXIT_FAILURE); } if (geteuid()) { if (mkdir_p(my_args.lxcpath[0], 0755)) { exit(EXIT_FAILURE); } if (access(my_args.lxcpath[0], O_RDONLY) < 0) { fprintf(stderr, "You lack access to %s\n", my_args.lxcpath[0]); exit(EXIT_FAILURE); } if (strcmp(my_args.bdevtype, "dir") && strcmp(my_args.bdevtype, "_unset") && strcmp(my_args.bdevtype, "btrfs")) { fprintf(stderr, "Unprivileged users cannot create %s containers.\n", my_args.bdevtype); exit(EXIT_FAILURE); } } c = lxc_container_new(my_args.name, my_args.lxcpath[0]); if (!c) { fprintf(stderr, "Failed to create lxc container.\n"); exit(EXIT_FAILURE); } if (c->is_defined(c)) { lxc_container_put(c); fprintf(stderr, "Container already exists\n"); exit(EXIT_FAILURE); } if (my_args.configfile) c->load_config(c, my_args.configfile); else c->load_config(c, lxc_global_config_value("lxc.default_config")); if (my_args.fstype) spec.fstype = my_args.fstype; if (my_args.fssize) spec.fssize = my_args.fssize; if ((strcmp(my_args.bdevtype, "zfs") == 0) || (strcmp(my_args.bdevtype, "best") == 0)) { if (my_args.zfsroot) spec.zfs.zfsroot = my_args.zfsroot; } if ((strcmp(my_args.bdevtype, "lvm") == 0) || (strcmp(my_args.bdevtype, "best") == 0)) { if (my_args.lvname) spec.lvm.lv = my_args.lvname; if (my_args.vgname) spec.lvm.vg = my_args.vgname; if (my_args.thinpool) spec.lvm.thinpool = my_args.thinpool; } if ((strcmp(my_args.bdevtype, "rbd") == 0) || (strcmp(my_args.bdevtype, "best") == 0)) { if (my_args.rbdname) spec.rbd.rbdname = my_args.rbdname; if (my_args.rbdpool) spec.rbd.rbdpool = my_args.rbdpool; } if (my_args.dir) spec.dir = my_args.dir; if (strcmp(my_args.bdevtype, "_unset") == 0) my_args.bdevtype = NULL; if (my_args.quiet) flags = LXC_CREATE_QUIET; if (!c->create(c, my_args.template, my_args.bdevtype, &spec, flags, &argv[optind])) { ERROR("Error creating container %s", c->name); lxc_container_put(c); exit(EXIT_FAILURE); } lxc_container_put(c); INFO("container %s created", c->name); exit(EXIT_SUCCESS); } lxc-2.0.8/src/lxc/tools/lxc_wait.c0000644061062106075000000000645213105116772013745 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include "lxc.h" #include "log.h" #include "arguments.h" lxc_log_define(lxc_wait_ui, lxc); static int my_checker(const struct lxc_arguments* args) { if (!args->states) { lxc_error(args, "missing state option to wait for."); return -1; } return 0; } static int my_parser(struct lxc_arguments* args, int c, char* arg) { switch (c) { case 's': args->states = optarg; break; case 't': args->timeout = atol(optarg); break; } return 0; } static const struct option my_longopts[] = { {"state", required_argument, 0, 's'}, {"timeout", required_argument, 0, 't'}, LXC_COMMON_OPTIONS }; static struct lxc_arguments my_args = { .progname = "lxc-wait", .help = "\ --name=NAME --state=STATE\n\ \n\ lxc-wait waits for NAME container state to reach STATE\n\ \n\ Options :\n\ -n, --name=NAME NAME of the container\n\ -s, --state=STATE ORed states to wait for\n\ STOPPED, STARTING, RUNNING, STOPPING,\n\ ABORTING, FREEZING, FROZEN, THAWED\n\ -t, --timeout=TMO Seconds to wait for state changes\n\ --rcfile=FILE Load configuration file FILE\n", .options = my_longopts, .parser = my_parser, .checker = my_checker, .timeout = -1, }; int main(int argc, char *argv[]) { struct lxc_container *c; if (lxc_arguments_parse(&my_args, argc, argv)) exit(EXIT_FAILURE); if (!my_args.log_file) my_args.log_file = "none"; if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority, my_args.progname, my_args.quiet, my_args.lxcpath[0])) exit(EXIT_FAILURE); lxc_log_options_no_override(); c = lxc_container_new(my_args.name, my_args.lxcpath[0]); if (!c) exit(EXIT_FAILURE); if (!c->may_control(c)) { fprintf(stderr, "Insufficent privileges to control %s\n", c->name); lxc_container_put(c); exit(EXIT_FAILURE); } if (my_args.rcfile) { c->clear_config(c); if (!c->load_config(c, my_args.rcfile)) { fprintf(stderr, "Failed to load rcfile\n"); lxc_container_put(c); exit(EXIT_FAILURE); } c->configfile = strdup(my_args.rcfile); if (!c->configfile) { fprintf(stderr, "Out of memory setting new config filename\n"); lxc_container_put(c); exit(EXIT_FAILURE); } } if (!c->wait(c, my_args.states, my_args.timeout)) { lxc_container_put(c); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); } lxc-2.0.8/src/lxc/tools/lxc-checkconfig.in0000644061062106075000000001420013105116772015334 00000000000000#!/bin/sh # Allow environment variables to override config : ${CONFIG:=/proc/config.gz} : ${MODNAME:=configs} CAT="cat" if [ -t 1 ]; then SETCOLOR_SUCCESS="printf \\033[1;32m" SETCOLOR_FAILURE="printf \\033[1;31m" SETCOLOR_WARNING="printf \\033[1;33m" SETCOLOR_NORMAL="printf \\033[0;39m" else SETCOLOR_SUCCESS=":" SETCOLOR_FAILURE=":" SETCOLOR_WARNING=":" SETCOLOR_NORMAL=":" fi is_set() { $CAT $CONFIG | grep "$1=[y|m]" > /dev/null return $? } is_enabled() { mandatory=$2 is_set $1 RES=$? if [ $RES -eq 0 ]; then $SETCOLOR_SUCCESS && echo "enabled" && $SETCOLOR_NORMAL else if [ ! -z "$mandatory" ] && [ "$mandatory" = yes ]; then $SETCOLOR_FAILURE && echo "required" && $SETCOLOR_NORMAL else $SETCOLOR_WARNING && echo "missing" && $SETCOLOR_NORMAL fi fi } if [ ! -f $CONFIG ]; then echo "Kernel configuration not found at $CONFIG; searching..." KVER="`uname -r`" HEADERS_CONFIG="/lib/modules/$KVER/build/.config" BOOT_CONFIG="/boot/config-$KVER" [ -f "${HEADERS_CONFIG}" ] && CONFIG=${HEADERS_CONFIG} [ -f "${BOOT_CONFIG}" ] && CONFIG=${BOOT_CONFIG} if [ ! -f "$CONFIG" ]; then MODULEFILE=$(modinfo -k $KVER -n $MODNAME 2> /dev/null) # don't want to modprobe, so give user a hint # although scripts/extract-ikconfig could be used to extract contents without loading kernel module # http://svn.pld-linux.org/trac/svn/browser/geninitrd/trunk/geninitrd?rev=12696#L327 fi if [ ! -f $CONFIG ]; then echo "$(basename $0): unable to retrieve kernel configuration" >&2 echo >&2 if [ -f "$MODULEFILE" ]; then echo "Try modprobe $MODNAME module, or" >&2 fi echo "Try recompiling with IKCONFIG_PROC, installing the kernel headers," >&2 echo "or specifying the kernel configuration path with:" >&2 echo " CONFIG= $(basename $0)" >&2 exit 1 else echo "Kernel configuration found at $CONFIG" fi fi if gunzip -tq < $CONFIG 2>/dev/null; then CAT="zcat" fi KVER_MAJOR=$($CAT $CONFIG | grep '^# Linux.*Kernel Configuration' | \ sed -r 's/.* ([0-9])\.[0-9]{1,2}\.[0-9]{1,3}.*/\1/') if [ "$KVER_MAJOR" = "2" ]; then KVER_MINOR=$($CAT $CONFIG | grep '^# Linux.*Kernel Configuration' | \ sed -r 's/.* 2.6.([0-9]{2}).*/\1/') else KVER_MINOR=$($CAT $CONFIG | grep '^# Linux.*Kernel Configuration' | \ sed -r 's/.* [0-9]\.([0-9]{1,3})\.[0-9]{1,3}.*/\1/') fi echo "--- Namespaces ---" echo -n "Namespaces: " && is_enabled CONFIG_NAMESPACES yes echo -n "Utsname namespace: " && is_enabled CONFIG_UTS_NS echo -n "Ipc namespace: " && is_enabled CONFIG_IPC_NS yes echo -n "Pid namespace: " && is_enabled CONFIG_PID_NS yes echo -n "User namespace: " && is_enabled CONFIG_USER_NS if is_set CONFIG_USER_NS; then if type newuidmap > /dev/null 2>&1; then f=`type -P newuidmap` if [ ! -u "${f}" ]; then echo "Warning: newuidmap is not setuid-root" fi else echo "newuidmap is not installed" fi if type newgidmap > /dev/null 2>&1; then f=`type -P newgidmap` if [ ! -u "${f}" ]; then echo "Warning: newgidmap is not setuid-root" fi else echo "newgidmap is not installed" fi fi echo -n "Network namespace: " && is_enabled CONFIG_NET_NS if ([ $KVER_MAJOR -lt 4 ]) || ([ $KVER_MAJOR -eq 4 ] && [ $KVER_MINOR -lt 7 ]); then echo -n "Multiple /dev/pts instances: " && is_enabled DEVPTS_MULTIPLE_INSTANCES fi echo echo "--- Control groups ---" print_cgroups() { # print all mountpoints for cgroup filesystems awk '$1 !~ /#/ && $3 == mp { print $2; } ; END { exit(0); } ' "mp=$1" "$2" ; } CGROUP_MNT_PATH=`print_cgroups cgroup /proc/self/mounts | head -n 1` echo -n "Cgroup: " && is_enabled CONFIG_CGROUPS yes if [ -f $CGROUP_MNT_PATH/cgroup.clone_children ]; then echo -n "Cgroup clone_children flag: " && $SETCOLOR_SUCCESS && echo "enabled" && $SETCOLOR_NORMAL else echo -n "Cgroup namespace: " && is_enabled CONFIG_CGROUP_NS yes fi echo -n "Cgroup device: " && is_enabled CONFIG_CGROUP_DEVICE echo -n "Cgroup sched: " && is_enabled CONFIG_CGROUP_SCHED echo -n "Cgroup cpu account: " && is_enabled CONFIG_CGROUP_CPUACCT echo -n "Cgroup memory controller: " if ([ $KVER_MAJOR -ge 3 ] && [ $KVER_MINOR -ge 6 ]) || ([ $KVER_MAJOR -gt 3 ]); then is_enabled CONFIG_MEMCG else is_enabled CONFIG_CGROUP_MEM_RES_CTLR fi is_set CONFIG_SMP && echo -n "Cgroup cpuset: " && is_enabled CONFIG_CPUSETS echo echo "--- Misc ---" echo -n "Veth pair device: " && is_enabled CONFIG_VETH echo -n "Macvlan: " && is_enabled CONFIG_MACVLAN echo -n "Vlan: " && is_enabled CONFIG_VLAN_8021Q echo -n "Bridges: " && is_enabled CONFIG_BRIDGE echo -n "Advanced netfilter: " && is_enabled CONFIG_NETFILTER_ADVANCED echo -n "CONFIG_NF_NAT_IPV4: " && is_enabled CONFIG_NF_NAT_IPV4 echo -n "CONFIG_NF_NAT_IPV6: " && is_enabled CONFIG_NF_NAT_IPV6 echo -n "CONFIG_IP_NF_TARGET_MASQUERADE: " && is_enabled CONFIG_IP_NF_TARGET_MASQUERADE echo -n "CONFIG_IP6_NF_TARGET_MASQUERADE: " && is_enabled CONFIG_IP6_NF_TARGET_MASQUERADE echo -n "CONFIG_NETFILTER_XT_TARGET_CHECKSUM: " && is_enabled CONFIG_NETFILTER_XT_TARGET_CHECKSUM echo -n "FUSE (for use with lxcfs): " && is_enabled CONFIG_FUSE_FS echo echo "--- Checkpoint/Restore ---" echo -n "checkpoint restore: " && is_enabled CONFIG_CHECKPOINT_RESTORE echo -n "CONFIG_FHANDLE: " && is_enabled CONFIG_FHANDLE echo -n "CONFIG_EVENTFD: " && is_enabled CONFIG_EVENTFD echo -n "CONFIG_EPOLL: " && is_enabled CONFIG_EPOLL echo -n "CONFIG_UNIX_DIAG: " && is_enabled CONFIG_UNIX_DIAG echo -n "CONFIG_INET_DIAG: " && is_enabled CONFIG_INET_DIAG echo -n "CONFIG_PACKET_DIAG: " && is_enabled CONFIG_PACKET_DIAG echo -n "CONFIG_NETLINK_DIAG: " && is_enabled CONFIG_NETLINK_DIAG echo -n "File capabilities: " && \ ( [ "${KVER_MAJOR}" = 2 ] && [ ${KVER_MINOR} -lt 33 ] && \ is_enabled CONFIG_SECURITY_FILE_CAPABILITIES ) || \ ( ( [ "${KVER_MAJOR}" = "2" ] && [ ${KVER_MINOR} -gt 32 ] ) || \ [ ${KVER_MAJOR} -gt 2 ] && $SETCOLOR_SUCCESS && \ echo "enabled" && $SETCOLOR_NORMAL ) echo echo "Note : Before booting a new kernel, you can check its configuration" echo "usage : CONFIG=/path/to/config $0" echo lxc-2.0.8/src/lxc/tools/lxc_autostart.c0000644061062106075000000003112213105116772015017 00000000000000/* lxc_autostart * * Copyright © 2013 Stéphane Graber * Copyright © 2013 Canonical Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include "arguments.h" #include "list.h" #include "log.h" #include "utils.h" lxc_log_define(lxc_autostart_ui, lxc); static struct lxc_list *accumulate_list(char *input, char *delimiter, struct lxc_list *str_list); struct lxc_list *cmd_groups_list = NULL; static int my_parser(struct lxc_arguments* args, int c, char* arg) { switch (c) { case 'k': args->hardstop = 1; break; case 'L': args->list = 1; break; case 'r': args->reboot = 1; break; case 's': args->shutdown = 1; break; case 'a': args->all = 1; break; case 'A': args->ignore_auto = 1; break; case 'g': cmd_groups_list = accumulate_list(arg, ",", cmd_groups_list); break; case 't': if (lxc_safe_long(arg, &args->timeout) < 0) return -1; break; } return 0; } static const struct option my_longopts[] = { {"kill", no_argument, 0, 'k'}, {"list", no_argument, 0, 'L'}, {"reboot", no_argument, 0, 'r'}, {"shutdown", no_argument, 0, 's'}, {"all", no_argument, 0, 'a'}, {"ignore-auto", no_argument, 0, 'A'}, {"groups", required_argument, 0, 'g'}, {"timeout", required_argument, 0, 't'}, {"help", no_argument, 0, 'h'}, LXC_COMMON_OPTIONS }; static struct lxc_arguments my_args = { .progname = "lxc-autostart", .help = "\ \n\ lxc-autostart managed auto-started containers\n\ \n\ Options:\n\ -k, --kill kill the containers instead of starting them\n\ -L, --list list all affected containers and wait delay\n\ -r, --reboot reboot the containers instead of starting them\n\ -s, --shutdown shutdown the containers instead of starting them\n\ \n\ -a, --all list all auto-started containers (ignore groups)\n\ -A, --ignore-auto ignore lxc.start.auto and select all matching containers\n\ -g, --groups list of groups (comma separated) to select\n\ -t, --timeout=T wait T seconds before hard-stopping\n", .options = my_longopts, .parser = my_parser, .checker = NULL, .timeout = 60, }; int list_contains_entry( char *str_ptr, struct lxc_list *p1 ) { struct lxc_list *it1; /* * If the entry is NULL or the empty string and the list * is NULL, we have a match */ if (! p1 && ! str_ptr) return 1; if (! p1 && ! *str_ptr) return 1; if (!p1) return 0; lxc_list_for_each(it1, p1) { if (strcmp(it1->elem, str_ptr) == 0) return 1; } return 0; } int lists_contain_common_entry(struct lxc_list *p1, struct lxc_list *p2) { struct lxc_list *it1; struct lxc_list *it2; if (!p1 && !p2) return 1; if (!p1) return 0; if (!p2) return 0; lxc_list_for_each(it1, p1) { lxc_list_for_each(it2, p2) { if (strcmp(it1->elem, it2->elem) == 0) return 1; } } return 0; } /* * This is a variation of get_list below it. * This version allows two additional features. * If a list is passed to it, it adds to it. * It allows for empty entries (i.e. "group1,,group2") generating * and empty list entry. */ static struct lxc_list *accumulate_list(char *input, char *delimiter, struct lxc_list *str_list) { char *workstr = NULL; char *workptr = NULL; char *next_ptr = NULL; struct lxc_list *worklist; struct lxc_list *workstr_list; workstr = strdup(input); if (!workstr) { return NULL; } workstr_list = str_list; if ( ! workstr_list ) { workstr_list = malloc(sizeof(*workstr_list)); lxc_list_init(workstr_list); } for (workptr = workstr; workptr; workptr = next_ptr) { /* * We can't use strtok_r here because it collapses * multiple delimiters into 1 making empty fields * impossible... */ /* token = strtok_r(workptr, delimiter, &sptr); */ next_ptr = strchr( workptr, *delimiter ); if( next_ptr ) { *next_ptr++ = '\0'; } /* * At this point, we'd like to check to see if this * group is already contained in the list and ignore * it if it is... This also helps us with any * corner cases where a string begins or ends with a * delimiter. */ if ( list_contains_entry( workptr, workstr_list ) ) { if ( *workptr ) { fprintf(stderr, "Duplicate group \"%s\" in list - ignoring\n", workptr ); fflush(stderr); } else { fprintf(stderr, "Duplicate NULL group in list - ignoring\n" ); fflush(stderr); } } else { worklist = malloc(sizeof(*worklist)); if (!worklist) break; worklist->elem = strdup(workptr); if (!worklist->elem) { free(worklist); break; } lxc_list_add_tail(workstr_list, worklist); } } free(workstr); return workstr_list; } static struct lxc_list *get_list(char *input, char *delimiter) { char *workstr = NULL; char *workptr = NULL; char *sptr = NULL; char *token = NULL; struct lxc_list *worklist; struct lxc_list *workstr_list; workstr_list = malloc(sizeof(*workstr_list)); lxc_list_init(workstr_list); workstr = strdup(input); if (!workstr) { free(workstr_list); return NULL; } for (workptr = workstr;;workptr = NULL) { token = strtok_r(workptr, delimiter, &sptr); if (!token) { break; } worklist = malloc(sizeof(*worklist)); if (!worklist) break; worklist->elem = strdup(token); if (!worklist->elem) { free(worklist); break; } lxc_list_add_tail(workstr_list, worklist); } free(workstr); return workstr_list; } static struct lxc_list *get_config_list(struct lxc_container *c, char *key) { int len = 0; char* value = NULL; struct lxc_list *config_list = NULL; len = c->get_config_item(c, key, NULL, 0); if (len < 0) return NULL; value = (char*) malloc(sizeof(char)*len + 1); if (value == NULL) return NULL; if (c->get_config_item(c, key, value, len + 1) != len) { free(value); return NULL; } if (strlen(value) == 0) { free(value); return NULL; } config_list = get_list(value, "\n"); free(value); return config_list; } static int get_config_integer(struct lxc_container *c, char *key) { int len = 0; int ret = 0; char* value = NULL; len = c->get_config_item(c, key, NULL, 0); if (len < 0) return 0; value = (char*) malloc(sizeof(char)*len + 1); if (value == NULL) return 0; if (c->get_config_item(c, key, value, len + 1) != len) { free(value); return 0; } if (lxc_safe_int(value, &ret) < 0) DEBUG("Could not parse config item."); free(value); return ret; } static int cmporder(const void *p1, const void *p2) { struct lxc_container *c1 = *(struct lxc_container **)p1; struct lxc_container *c2 = *(struct lxc_container **)p2; int c1_order = get_config_integer(c1, "lxc.start.order"); int c2_order = get_config_integer(c2, "lxc.start.order"); if (c1_order == c2_order) return strcmp(c1->name, c2->name); else return (c1_order - c2_order); } static int toss_list( struct lxc_list *c_groups_list ) { struct lxc_list *it, *next; if (c_groups_list) { lxc_list_for_each_safe(it, c_groups_list, next) { lxc_list_del(it); free(it->elem); free(it); } free(c_groups_list); } return 1; } int main(int argc, char *argv[]) { int count = 0; int i = 0; int ret = 0; struct lxc_container **containers = NULL; struct lxc_list **c_groups_lists = NULL; struct lxc_list *cmd_group; if (lxc_arguments_parse(&my_args, argc, argv)) exit(EXIT_FAILURE); if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority, my_args.progname, my_args.quiet, my_args.lxcpath[0])) exit(EXIT_FAILURE); lxc_log_options_no_override(); count = list_defined_containers(my_args.lxcpath[0], NULL, &containers); if (count < 0) exit(EXIT_FAILURE); if (!my_args.all) { /* Allocate an array for our container group lists */ c_groups_lists = calloc( count, sizeof( struct lxc_list * ) ); } qsort(&containers[0], count, sizeof(struct lxc_container *), cmporder); if (cmd_groups_list && my_args.all) { fprintf(stderr, "Specifying -a (all) with -g (groups) doesn't make sense. All option overrides.\n"); fflush(stderr); } if (!cmd_groups_list) { /* * We need a default cmd_groups_list even for the -a * case in order to force a pass through the loop for * the NULL group. This, someday, could be taken from * a config file somewhere... */ cmd_groups_list = accumulate_list( "" , ",", NULL ); } lxc_list_for_each(cmd_group, cmd_groups_list) { /* * Prograpmmers Note: * Because we may take several passes through the container list * We'll switch on if the container pointer is NULL and if we process a * container (run it or decide to ignore it) and call lxc_container_put * then we'll NULL it out and not check it again. */ for (i = 0; i < count; i++) { struct lxc_container *c = containers[i]; if (!c) /* Skip - must have been already processed */ continue; /* * We haven't loaded the container groups yet so * these next two checks don't need to free them * if they fail. They'll fail on the first pass. */ if (!c->may_control(c)) { /* We're done with this container */ if ( lxc_container_put(c) > 0 ) containers[i] = NULL; continue; } if (!my_args.ignore_auto && get_config_integer(c, "lxc.start.auto") != 1) { /* We're done with this container */ if ( lxc_container_put(c) > 0 ) containers[i] = NULL; continue; } if (!my_args.all) { /* Filter by group */ if( ! c_groups_lists[i] ) { /* Now we're loading up a container's groups */ c_groups_lists[i] = get_config_list(c, "lxc.group"); } ret = list_contains_entry(cmd_group->elem, c_groups_lists[i]); if ( ret == 0 ) { /* Not in the target group this pass */ /* Leave in the list for subsequent passes */ continue; } } /* We have a candidate continer to process */ c->want_daemonize(c, 1); if (my_args.shutdown) { /* Shutdown the container */ if (c->is_running(c)) { if (my_args.list) { printf("%s\n", c->name); fflush(stdout); } else { if (!c->shutdown(c, my_args.timeout)) { if (!c->stop(c)) { fprintf(stderr, "Error shutting down container: %s\n", c->name); fflush(stderr); } } } } } else if (my_args.hardstop) { /* Kill the container */ if (c->is_running(c)) { if (my_args.list) { printf("%s\n", c->name); fflush(stdout); } else { if (!c->stop(c)) { fprintf(stderr, "Error killing container: %s\n", c->name); fflush(stderr); } } } } else if (my_args.reboot) { /* Reboot the container */ if (c->is_running(c)) { if (my_args.list) { printf("%s %d\n", c->name, get_config_integer(c, "lxc.start.delay")); fflush(stdout); } else { if (!c->reboot(c)) { fprintf(stderr, "Error rebooting container: %s\n", c->name); fflush(stderr); } else sleep(get_config_integer(c, "lxc.start.delay")); } } } else { /* Start the container */ if (!c->is_running(c)) { if (my_args.list) { printf("%s %d\n", c->name, get_config_integer(c, "lxc.start.delay")); fflush(stdout); } else { if (!c->start(c, 0, NULL)) { fprintf(stderr, "Error starting container: %s\n", c->name); fflush(stderr); } else sleep(get_config_integer(c, "lxc.start.delay")); } } } /* * If we get this far and we haven't hit any skip "continue" * then we're done with this container... We can dump any * c_groups_list and the container itself. */ if ( lxc_container_put(c) > 0 ) { containers[i] = NULL; } if ( c_groups_lists ) { toss_list(c_groups_lists[i]); c_groups_lists[i] = NULL; } } } /* clean up any lingering detritus */ for (i = 0; i < count; i++) { if ( containers[i] ) { lxc_container_put(containers[i]); } if ( c_groups_lists && c_groups_lists[i] ) { toss_list(c_groups_lists[i]); } } free(c_groups_lists); toss_list( cmd_groups_list ); free(containers); exit(EXIT_SUCCESS); } lxc-2.0.8/src/lxc/tools/lxc_copy.c0000644061062106075000000004527513105116772013761 00000000000000/* * * Copyright © 2015 Christian Brauner . * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #define _GNU_SOURCE #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "attach.h" #include "bdev.h" #include "log.h" #include "confile.h" #include "arguments.h" #include "lxc.h" #include "conf.h" #include "state.h" #include "utils.h" #ifndef HAVE_GETSUBOPT #include <../include/getsubopt.h> #endif lxc_log_define(lxc_copy_ui, lxc); enum mnttype { LXC_MNT_BIND, LXC_MNT_AUFS, LXC_MNT_OVL, }; struct mnts { enum mnttype mnt_type; char *src; char *dest; char *options; char *upper; char *workdir; char *lower; }; static unsigned int mnt_table_size = 0; static struct mnts *mnt_table = NULL; static int my_parser(struct lxc_arguments *args, int c, char *arg); static const struct option my_longopts[] = { { "newname", required_argument, 0, 'N'}, { "newpath", required_argument, 0, 'p'}, { "rename", no_argument, 0, 'R'}, { "snapshot", no_argument, 0, 's'}, { "foreground", no_argument, 0, 'F'}, { "daemon", no_argument, 0, 'd'}, { "ephemeral", no_argument, 0, 'e'}, { "mount", required_argument, 0, 'm'}, { "backingstorage", required_argument, 0, 'B'}, { "fssize", required_argument, 0, 'L'}, { "keepdata", no_argument, 0, 'D'}, { "keepname", no_argument, 0, 'K'}, { "keepmac", no_argument, 0, 'M'}, LXC_COMMON_OPTIONS }; /* mount keys */ static char *const keys[] = { [LXC_MNT_BIND] = "bind", [LXC_MNT_AUFS] = "aufs", [LXC_MNT_OVL] = "overlay", NULL }; static struct lxc_arguments my_args = { .progname = "lxc-copy", .help = "\n\ --name=NAME [-P lxcpath] -N newname [-p newpath] [-B backingstorage] [-s] [-K] [-M] [-L size [unit]] -- hook options\n\ --name=NAME [-P lxcpath] [-N newname] [-p newpath] [-B backingstorage] -e [-d] [-D] [-K] [-M] [-m {bind,aufs,overlay}=/src:/dest] -- hook options\n\ --name=NAME [-P lxcpath] -N newname -R\n\ \n\ lxc-copy clone a container\n\ \n\ Options :\n\ -n, --name=NAME NAME of the container\n\ -N, --newname=NEWNAME NEWNAME for the restored container\n\ -p, --newpath=NEWPATH NEWPATH for the container to be stored\n\ -R, --rename rename container\n\ -s, --snapshot create snapshot instead of clone\n\ -F, --foreground start with current tty attached to /dev/console\n\ -d, --daemon daemonize the container (default)\n\ -e, --ephemeral start ephemeral container\n\ -m, --mount directory to mount into container, either \n\ {bind,aufs,overlay}=/src-path or {bind,aufs,overlay}=/src-path:/dst-path\n\ -B, --backingstorage=TYPE backingstorage type for the container\n\ -L, --fssize size of the new block device for block device containers\n\ -D, --keedata pass together with -e start a persistent snapshot \n\ -K, --keepname keep the hostname of the original container\n\ -- hook options arguments passed to the hook program\n\ -M, --keepmac keep the MAC address of the original container\n\ --rcfile=FILE Load configuration file FILE\n", .options = my_longopts, .parser = my_parser, .task = CLONE, .daemonize = 1, .quiet = false, }; static struct mnts *add_mnt(struct mnts **mnts, unsigned int *num, enum mnttype type); static int mk_rand_ovl_dirs(struct mnts *mnts, unsigned int num, struct lxc_arguments *arg); static char *construct_path(char *path, bool as_prefix); static char *set_mnt_entry(struct mnts *m); static int do_clone(struct lxc_container *c, char *newname, char *newpath, int flags, char *bdevtype, uint64_t fssize, enum task task, char **args); static int do_clone_ephemeral(struct lxc_container *c, struct lxc_arguments *arg, char **args, int flags); static int do_clone_rename(struct lxc_container *c, char *newname); static int do_clone_task(struct lxc_container *c, enum task task, int flags, char **args); static void free_mnts(void); static uint64_t get_fssize(char *s); static int parse_mntsubopts(char *subopts, char *const *keys, char *mntparameters); static int parse_aufs_mnt(char *mntstring, enum mnttype type); static int parse_bind_mnt(char *mntstring, enum mnttype type); static int parse_ovl_mnt(char *mntstring, enum mnttype type); int main(int argc, char *argv[]) { struct lxc_container *c; int flags = 0; int ret = EXIT_FAILURE; if (lxc_arguments_parse(&my_args, argc, argv)) exit(ret); if (!my_args.log_file) my_args.log_file = "none"; if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority, my_args.progname, my_args.quiet, my_args.lxcpath[0])) exit(ret); lxc_log_options_no_override(); if (geteuid()) { if (access(my_args.lxcpath[0], O_RDONLY) < 0) { if (!my_args.quiet) fprintf(stderr, "You lack access to %s\n", my_args.lxcpath[0]); exit(ret); } } if (!my_args.newname && !(my_args.task == DESTROY)) { if (!my_args.quiet) printf("Error: You must provide a NEWNAME for the clone.\n"); exit(ret); } if (my_args.task == SNAP || my_args.task == DESTROY) flags |= LXC_CLONE_SNAPSHOT; if (my_args.keepname) flags |= LXC_CLONE_KEEPNAME; if (my_args.keepmac) flags |= LXC_CLONE_KEEPMACADDR; if (!my_args.newpath) my_args.newpath = (char *)my_args.lxcpath[0]; c = lxc_container_new(my_args.name, my_args.lxcpath[0]); if (!c) exit(ret); if (my_args.rcfile) { c->clear_config(c); if (!c->load_config(c, my_args.rcfile)) { fprintf(stderr, "Failed to load rcfile\n"); goto out; } c->configfile = strdup(my_args.rcfile); if (!c->configfile) { fprintf(stderr, "Out of memory setting new config filename\n"); goto out; } } if (!c->may_control(c)) { if (!my_args.quiet) fprintf(stderr, "Insufficent privileges to control %s\n", c->name); goto out; } if (!c->is_defined(c)) { if (!my_args.quiet) fprintf(stderr, "Error: container %s is not defined\n", c->name); goto out; } ret = do_clone_task(c, my_args.task, flags, &argv[optind]); out: lxc_container_put(c); if (ret == 0) exit(EXIT_SUCCESS); exit(EXIT_FAILURE); } static struct mnts *add_mnt(struct mnts **mnts, unsigned int *num, enum mnttype type) { struct mnts *m, *n; n = realloc(*mnts, (*num + 1) * sizeof(struct mnts)); if (!n) return NULL; *mnts = n; m = *mnts + *num; (*num)++; *m = (struct mnts) {.mnt_type = type}; return m; } static int mk_rand_ovl_dirs(struct mnts *mnts, unsigned int num, struct lxc_arguments *arg) { char upperdir[MAXPATHLEN]; char workdir[MAXPATHLEN]; unsigned int i; int ret; struct mnts *m = NULL; for (i = 0, m = mnts; i < num; i++, m++) { if ((m->mnt_type == LXC_MNT_OVL) || (m->mnt_type == LXC_MNT_AUFS)) { ret = snprintf(upperdir, MAXPATHLEN, "%s/%s/delta#XXXXXX", arg->newpath, arg->newname); if (ret < 0 || ret >= MAXPATHLEN) return -1; if (!mkdtemp(upperdir)) return -1; m->upper = strdup(upperdir); if (!m->upper) return -1; } if (m->mnt_type == LXC_MNT_OVL) { ret = snprintf(workdir, MAXPATHLEN, "%s/%s/work#XXXXXX", arg->newpath, arg->newname); if (ret < 0 || ret >= MAXPATHLEN) return -1; if (!mkdtemp(workdir)) return -1; m->workdir = strdup(workdir); if (!m->workdir) return -1; } } return 0; } static char *construct_path(char *path, bool as_prefix) { char **components = NULL; char *cleanpath = NULL; components = lxc_normalize_path(path); if (!components) return NULL; cleanpath = lxc_string_join("/", (const char **)components, as_prefix); lxc_free_array((void **)components, free); return cleanpath; } static char *set_mnt_entry(struct mnts *m) { char *mntentry = NULL; int ret = 0; size_t len = 0; if (m->mnt_type == LXC_MNT_AUFS) { len = strlen(" aufs br==rw:=ro,xino=,create=dir") + 2 * strlen(m->src) + strlen(m->dest) + strlen(m->upper) + strlen(m->workdir) + 1; mntentry = malloc(len); if (!mntentry) goto err; ret = snprintf(mntentry, len, "%s %s aufs br=%s=rw:%s=ro,xino=%s,create=dir", m->src, m->dest, m->upper, m->src, m->workdir); if (ret < 0 || (size_t)ret >= len) goto err; } else if (m->mnt_type == LXC_MNT_OVL) { len = strlen(" overlay lowerdir=,upperdir=,workdir=,create=dir") + 2 * strlen(m->src) + strlen(m->dest) + strlen(m->upper) + strlen(m->workdir) + 1; mntentry = malloc(len); if (!mntentry) goto err; ret = snprintf(mntentry, len, "%s %s overlay lowerdir=%s,upperdir=%s,workdir=%s,create=dir", m->src, m->dest, m->src, m->upper, m->workdir); if (ret < 0 || (size_t)ret >= len) goto err; } else if (m->mnt_type == LXC_MNT_BIND) { len = strlen(" none bind,optional,, 0 0") + strlen(is_dir(m->src) ? "create=dir" : "create=file") + strlen(m->src) + strlen(m->dest) + strlen(m->options) + 1; mntentry = malloc(len); if (!mntentry) goto err; ret = snprintf(mntentry, len, "%s %s none bind,optional,%s,%s 0 0", m->src, m->dest, m->options, is_dir(m->src) ? "create=dir" : "create=file"); if (ret < 0 || (size_t)ret >= len) goto err; } return mntentry; err: free(mntentry); return NULL; } static int do_clone(struct lxc_container *c, char *newname, char *newpath, int flags, char *bdevtype, uint64_t fssize, enum task task, char **args) { struct lxc_container *clone; clone = c->clone(c, newname, newpath, flags, bdevtype, NULL, fssize, args); if (!clone) { if (!my_args.quiet) fprintf(stderr, "clone failed\n"); return -1; } INFO("Created %s as %s of %s\n", newname, task ? "snapshot" : "copy", c->name); lxc_container_put(clone); return 0; } static int do_clone_ephemeral(struct lxc_container *c, struct lxc_arguments *arg, char **args, int flags) { char randname[MAXPATHLEN]; unsigned int i; int ret = 0; bool bret = true, started = false; struct lxc_container *clone; lxc_attach_options_t attach_options = LXC_ATTACH_OPTIONS_DEFAULT; attach_options.env_policy = LXC_ATTACH_CLEAR_ENV; if (!arg->newname) { ret = snprintf(randname, MAXPATHLEN, "%s/%s_XXXXXX", arg->newpath, arg->name); if (ret < 0 || ret >= MAXPATHLEN) return -1; if (!mkdtemp(randname)) return -1; if (chmod(randname, 0770) < 0) { remove(randname); return -1; } arg->newname = randname + strlen(arg->newpath) + 1; } clone = c->clone(c, arg->newname, arg->newpath, flags, arg->bdevtype, NULL, arg->fssize, args); if (!clone) return -1; if (!arg->keepdata) if (!clone->set_config_item(clone, "lxc.ephemeral", "1")) goto destroy_and_put; /* allocate and create random upper- and workdirs for overlay mounts */ if (mk_rand_ovl_dirs(mnt_table, mnt_table_size, arg) < 0) goto destroy_and_put; /* allocate and set mount entries */ struct mnts *n = NULL; for (i = 0, n = mnt_table; i < mnt_table_size; i++, n++) { char *mntentry = NULL; mntentry = set_mnt_entry(n); if (!mntentry) goto destroy_and_put; bret = clone->set_config_item(clone, "lxc.mount.entry", mntentry); free(mntentry); if (!bret) goto destroy_and_put; } if (!clone->save_config(clone, NULL)) goto destroy_and_put; if (!my_args.quiet) printf("Created %s as clone of %s\n", arg->newname, arg->name); if (!arg->daemonize && arg->argc) { clone->want_daemonize(clone, true); arg->daemonize = 1; } else if (!arg->daemonize) { clone->want_daemonize(clone, false); } started = clone->start(clone, 0, NULL); if (!started) goto destroy_and_put; if (arg->daemonize && arg->argc) { ret = clone->attach_run_wait(clone, &attach_options, arg->argv[0], (const char *const *)arg->argv); if (ret < 0) goto destroy_and_put; clone->shutdown(clone, -1); } free_mnts(); lxc_container_put(clone); return 0; destroy_and_put: if (started) clone->shutdown(clone, -1); if (!started || clone->lxc_conf->ephemeral != 1) clone->destroy(clone); free_mnts(); lxc_container_put(clone); return -1; } static int do_clone_rename(struct lxc_container *c, char *newname) { if (!c->rename(c, newname)) { ERROR("Error: Renaming container %s to %s failed\n", c->name, newname); return -1; } INFO("Renamed container %s to %s\n", c->name, newname); return 0; } static int do_clone_task(struct lxc_container *c, enum task task, int flags, char **args) { int ret = 0; switch (task) { case DESTROY: ret = do_clone_ephemeral(c, &my_args, args, flags); break; case RENAME: ret = do_clone_rename(c, my_args.newname); break; default: ret = do_clone(c, my_args.newname, my_args.newpath, flags, my_args.bdevtype, my_args.fssize, my_args.task, args); break; } return ret; } static void free_mnts() { unsigned int i; struct mnts *n = NULL; for (i = 0, n = mnt_table; i < mnt_table_size; i++, n++) { free(n->src); free(n->dest); free(n->options); free(n->upper); free(n->workdir); } free(mnt_table); mnt_table = NULL; mnt_table_size = 0; } /* we pass fssize in bytes */ static uint64_t get_fssize(char *s) { uint64_t ret; char *end; ret = strtoull(s, &end, 0); if (end == s) { if (!my_args.quiet) fprintf(stderr, "Invalid blockdev size '%s', using default size\n", s); return 0; } while (isblank(*end)) end++; if (*end == '\0') { ret *= 1024ULL * 1024ULL; // MB by default } else if (*end == 'b' || *end == 'B') { ret *= 1ULL; } else if (*end == 'k' || *end == 'K') { ret *= 1024ULL; } else if (*end == 'm' || *end == 'M') { ret *= 1024ULL * 1024ULL; } else if (*end == 'g' || *end == 'G') { ret *= 1024ULL * 1024ULL * 1024ULL; } else if (*end == 't' || *end == 'T') { ret *= 1024ULL * 1024ULL * 1024ULL * 1024ULL; } else { if (!my_args.quiet) fprintf(stderr, "Invalid blockdev unit size '%c' in '%s', " "using default size\n", *end, s); return 0; } return ret; } static int my_parser(struct lxc_arguments *args, int c, char *arg) { char *subopts = NULL; char *mntparameters = NULL; switch (c) { case 'N': args->newname = arg; break; case 'p': args->newpath = arg; break; case 'R': args->task = RENAME; break; case 's': args->task = SNAP; break; case 'F': args->daemonize = 0; break; case 'd': args->daemonize = 1; break; case 'e': args->task = DESTROY; break; case 'm': subopts = optarg; if (parse_mntsubopts(subopts, keys, mntparameters) < 0) return -1; break; case 'B': if (strcmp(arg, "overlay") == 0) arg = "overlayfs"; args->bdevtype = arg; break; case 'L': args->fssize = get_fssize(optarg); break; case 'D': args->keepdata = 1; break; case 'K': args->keepname = 1; break; case 'M': args->keepmac = 1; break; } return 0; } static int parse_aufs_mnt(char *mntstring, enum mnttype type) { int len = 0; const char *xinopath = "/dev/shm/aufs.xino"; char **mntarray = NULL; struct mnts *m = NULL; m = add_mnt(&mnt_table, &mnt_table_size, type); if (!m) goto err; mntarray = lxc_string_split(mntstring, ':'); if (!mntarray) goto err; m->src = construct_path(mntarray[0], true); if (!m->src) goto err; len = lxc_array_len((void **)mntarray); if (len == 1) /* aufs=src */ m->dest = construct_path(mntarray[0], false); else if (len == 2) /* aufs=src:dest */ m->dest = construct_path(mntarray[1], false); else INFO("Excess elements in mount specification"); if (!m->dest) goto err; m->workdir = strdup(xinopath); if (!m->workdir) goto err; lxc_free_array((void **)mntarray, free); return 0; err: free_mnts(); lxc_free_array((void **)mntarray, free); return -1; } static int parse_bind_mnt(char *mntstring, enum mnttype type) { int len = 0; char **mntarray = NULL; struct mnts *m = NULL; m = add_mnt(&mnt_table, &mnt_table_size, type); if (!m) goto err; mntarray = lxc_string_split(mntstring, ':'); if (!mntarray) goto err; m->src = construct_path(mntarray[0], true); if (!m->src) goto err; len = lxc_array_len((void **)mntarray); if (len == 1) { /* bind=src */ m->dest = construct_path(mntarray[0], false); } else if (len == 2) { /* bind=src:option or bind=src:dest */ if (strncmp(mntarray[1], "rw", strlen(mntarray[1])) == 0) m->options = strdup("rw"); if (strncmp(mntarray[1], "ro", strlen(mntarray[1])) == 0) m->options = strdup("ro"); if (m->options) m->dest = construct_path(mntarray[0], false); else m->dest = construct_path(mntarray[1], false); } else if (len == 3) { /* bind=src:dest:option */ m->dest = construct_path(mntarray[1], false); m->options = strdup(mntarray[2]); } else { INFO("Excess elements in mount specification"); } if (!m->dest) goto err; if (!m->options) m->options = strdup("rw"); if (!m->options || (strncmp(m->options, "rw", strlen(m->options)) && strncmp(m->options, "ro", strlen(m->options)))) goto err; lxc_free_array((void **)mntarray, free); return 0; err: free_mnts(); lxc_free_array((void **)mntarray, free); return -1; } static int parse_mntsubopts(char *subopts, char *const *keys, char *mntparameters) { while (*subopts != '\0') { switch (getsubopt(&subopts, keys, &mntparameters)) { case LXC_MNT_BIND: if (parse_bind_mnt(mntparameters, LXC_MNT_BIND) < 0) return -1; break; case LXC_MNT_OVL: if (parse_ovl_mnt(mntparameters, LXC_MNT_OVL) < 0) return -1; break; case LXC_MNT_AUFS: if (parse_aufs_mnt(mntparameters, LXC_MNT_AUFS) < 0) return -1; break; default: break; } } return 0; } static int parse_ovl_mnt(char *mntstring, enum mnttype type) { int len = 0; char **mntarray = NULL; struct mnts *m; m = add_mnt(&mnt_table, &mnt_table_size, type); if (!m) goto err; mntarray = lxc_string_split(mntstring, ':'); if (!mntarray) goto err; m->src = construct_path(mntarray[0], true); if (!m->src) goto err; len = lxc_array_len((void **)mntarray); if (len == 1) /* overlay=src */ m->dest = construct_path(mntarray[0], false); else if (len == 2) /* overlay=src:dest */ m->dest = construct_path(mntarray[1], false); else INFO("Excess elements in mount specification"); if (!m->dest) goto err; lxc_free_array((void **)mntarray, free); return 0; err: free_mnts(); lxc_free_array((void **)mntarray, free); return -1; } lxc-2.0.8/src/lxc/tools/lxc_start.c0000644061062106075000000002310713105116772014132 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "log.h" #include "caps.h" #include "lxc.h" #include "conf.h" #include "cgroup.h" #include "utils.h" #include "confile.h" #include "arguments.h" #define OPT_SHARE_NET OPT_USAGE + 1 #define OPT_SHARE_IPC OPT_USAGE + 2 #define OPT_SHARE_UTS OPT_USAGE + 3 lxc_log_define(lxc_start_ui, lxc); static struct lxc_list defines; static int ensure_path(char **confpath, const char *path) { int err = -1, fd; char *fullpath = NULL; if (path) { if (access(path, W_OK)) { fd = creat(path, 0600); if (fd < 0 && errno != EEXIST) { SYSERROR("failed to create '%s'", path); goto err; } if (fd >= 0) close(fd); } fullpath = realpath(path, NULL); if (!fullpath) { SYSERROR("failed to get the real path of '%s'", path); goto err; } *confpath = strdup(fullpath); if (!*confpath) { ERROR("failed to dup string '%s'", fullpath); goto err; } } err = EXIT_SUCCESS; err: free(fullpath); return err; } static int pid_from_lxcname(const char *lxcname_or_pid, const char *lxcpath) { char *eptr; int pid = strtol(lxcname_or_pid, &eptr, 10); if (*eptr != '\0' || pid < 1) { struct lxc_container *s; s = lxc_container_new(lxcname_or_pid, lxcpath); if (!s) { SYSERROR("'%s' is not a valid pid nor a container name", lxcname_or_pid); return -1; } if (!s->may_control(s)) { SYSERROR("Insufficient privileges to control container '%s'", s->name); lxc_container_put(s); return -1; } pid = s->init_pid(s); if (pid < 1) { SYSERROR("Is container '%s' running?", s->name); lxc_container_put(s); return -1; } lxc_container_put(s); } if (kill(pid, 0) < 0) { SYSERROR("Can't send signal to pid %d", pid); return -1; } return pid; } static int open_ns(int pid, const char *ns_proc_name) { int fd; char path[MAXPATHLEN]; snprintf(path, MAXPATHLEN, "/proc/%d/ns/%s", pid, ns_proc_name); fd = open(path, O_RDONLY); if (fd < 0) { SYSERROR("failed to open %s", path); return -1; } return fd; } static int my_parser(struct lxc_arguments* args, int c, char* arg) { switch (c) { case 'c': args->console = arg; break; case 'L': args->console_log = arg; break; case 'd': args->daemonize = 1; break; case 'F': args->daemonize = 0; break; case 'f': args->rcfile = arg; break; case 'C': args->close_all_fds = 1; break; case 's': return lxc_config_define_add(&defines, arg); case 'p': args->pidfile = arg; break; case OPT_SHARE_NET: args->share_ns[LXC_NS_NET] = arg; break; case OPT_SHARE_IPC: args->share_ns[LXC_NS_IPC] = arg; break; case OPT_SHARE_UTS: args->share_ns[LXC_NS_UTS] = arg; break; } return 0; } static const struct option my_longopts[] = { {"daemon", no_argument, 0, 'd'}, {"foreground", no_argument, 0, 'F'}, {"rcfile", required_argument, 0, 'f'}, {"define", required_argument, 0, 's'}, {"console", required_argument, 0, 'c'}, {"console-log", required_argument, 0, 'L'}, {"close-all-fds", no_argument, 0, 'C'}, {"pidfile", required_argument, 0, 'p'}, {"share-net", required_argument, 0, OPT_SHARE_NET}, {"share-ipc", required_argument, 0, OPT_SHARE_IPC}, {"share-uts", required_argument, 0, OPT_SHARE_UTS}, LXC_COMMON_OPTIONS }; static struct lxc_arguments my_args = { .progname = "lxc-start", .help = "\ --name=NAME -- COMMAND\n\ \n\ lxc-start start COMMAND in specified container NAME\n\ \n\ Options :\n\ -n, --name=NAME NAME of the container\n\ -d, --daemon Daemonize the container (default)\n\ -F, --foreground Start with the current tty attached to /dev/console\n\ -p, --pidfile=FILE Create a file with the process id\n\ -f, --rcfile=FILE Load configuration file FILE\n\ -c, --console=FILE Use specified FILE for the container console\n\ -L, --console-log=FILE Log container console output to FILE\n\ -C, --close-all-fds If any fds are inherited, close them\n\ If not specified, exit with failure instead\n\ Note: --daemon implies --close-all-fds\n\ -s, --define KEY=VAL Assign VAL to configuration variable KEY\n\ --share-[net|ipc|uts]=NAME Share a namespace with another container or pid\n\ ", .options = my_longopts, .parser = my_parser, .checker = NULL, .daemonize = 1, .pidfile = NULL, }; int main(int argc, char *argv[]) { int err = EXIT_FAILURE; struct lxc_conf *conf; char *const *args; char *rcfile = NULL; char *const default_args[] = { "/sbin/init", NULL, }; struct lxc_container *c; lxc_list_init(&defines); if (lxc_caps_init()) exit(err); if (lxc_arguments_parse(&my_args, argc, argv)) exit(err); if (!my_args.argc) args = default_args; else args = my_args.argv; if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority, my_args.progname, my_args.quiet, my_args.lxcpath[0])) exit(err); lxc_log_options_no_override(); if (access(my_args.lxcpath[0], O_RDONLY) < 0) { if (!my_args.quiet) fprintf(stderr, "You lack access to %s\n", my_args.lxcpath[0]); exit(err); } const char *lxcpath = my_args.lxcpath[0]; /* * rcfile possibilities: * 1. rcfile from random path specified in cli option * 2. rcfile not specified, use $lxcpath/$lxcname/config * 3. rcfile not specified and does not exist. */ /* rcfile is specified in the cli option */ if (my_args.rcfile) { rcfile = (char *)my_args.rcfile; c = lxc_container_new(my_args.name, lxcpath); if (!c) { ERROR("Failed to create lxc_container"); exit(err); } c->clear_config(c); if (!c->load_config(c, rcfile)) { ERROR("Failed to load rcfile"); lxc_container_put(c); exit(err); } c->configfile = strdup(my_args.rcfile); if (!c->configfile) { ERROR("Out of memory setting new config filename"); goto out; } } else { int rc; rc = asprintf(&rcfile, "%s/%s/config", lxcpath, my_args.name); if (rc == -1) { SYSERROR("failed to allocate memory"); exit(err); } INFO("using rcfile %s", rcfile); /* container configuration does not exist */ if (access(rcfile, F_OK)) { free(rcfile); rcfile = NULL; } c = lxc_container_new(my_args.name, lxcpath); if (!c) { ERROR("Failed to create lxc_container"); exit(err); } } /* We do not check here whether the container is defined, because we * support volatile containers. Which means the container does not need * to be created for it to be started. You can just pass a configuration * file as argument and start the container right away. */ if (!c->may_control(c)) { fprintf(stderr, "Insufficent privileges to control %s\n", c->name); goto out; } if (c->is_running(c)) { ERROR("Container is already running."); err = EXIT_SUCCESS; goto out; } /* * We should use set_config_item() over &defines, which would handle * unset c->lxc_conf for us and let us not use lxc_config_define_load() */ if (!c->lxc_conf) c->lxc_conf = lxc_conf_init(); conf = c->lxc_conf; if (lxc_config_define_load(&defines, conf)) goto out; if (!rcfile && !strcmp("/sbin/init", args[0])) { ERROR("Executing '/sbin/init' with no configuration file may crash the host"); goto out; } if (ensure_path(&conf->console.path, my_args.console) < 0) { ERROR("failed to ensure console path '%s'", my_args.console); goto out; } if (ensure_path(&conf->console.log_path, my_args.console_log) < 0) { ERROR("failed to ensure console log '%s'", my_args.console_log); goto out; } if (my_args.pidfile != NULL) { if (ensure_path(&c->pidfile, my_args.pidfile) < 0) { ERROR("failed to ensure pidfile '%s'", my_args.pidfile); goto out; } } int i; for (i = 0; i < LXC_NS_MAX; i++) { if (my_args.share_ns[i] == NULL) continue; int pid = pid_from_lxcname(my_args.share_ns[i], lxcpath); if (pid < 1) goto out; int fd = open_ns(pid, ns_info[i].proc_name); if (fd < 0) goto out; conf->inherit_ns_fd[i] = fd; } if (!my_args.daemonize) { c->want_daemonize(c, false); } if (my_args.close_all_fds) c->want_close_all_fds(c, true); if (args == default_args) err = c->start(c, 0, NULL) ? EXIT_SUCCESS : EXIT_FAILURE; else err = c->start(c, 0, args) ? EXIT_SUCCESS : EXIT_FAILURE; if (err) { ERROR("The container failed to start."); if (my_args.daemonize) ERROR("To get more details, run the container in foreground mode."); ERROR("Additional information can be obtained by setting the " "--logfile and --logpriority options."); err = c->error_num; lxc_container_put(c); exit(err); } out: lxc_container_put(c); exit(err); } lxc-2.0.8/src/lxc/tools/lxc_unshare.c0000644061062106075000000001604113105116772014441 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "caps.h" #include "cgroup.h" #include "error.h" #include "log.h" #include "namespace.h" #include "network.h" #include "utils.h" /* Define sethostname() if missing from the C library */ #ifndef HAVE_SETHOSTNAME static int sethostname(const char * name, size_t len) { #ifdef __NR_sethostname return syscall(__NR_sethostname, name, len); #else errno = ENOSYS; return -1; #endif } #endif lxc_log_define(lxc_unshare_ui, lxc); struct my_iflist { char *mi_ifname; struct my_iflist *mi_next; }; static void usage(char *cmd) { fprintf(stderr, "%s command [command_arguments]\n", basename(cmd)); fprintf(stderr, "Options are:\n"); fprintf(stderr, "\t -s flags : ORed list of flags to unshare:\n" \ "\t MOUNT, PID, UTSNAME, IPC, USER, NETWORK\n"); fprintf(stderr, "\t -u : new id to be set if -s USER is specified\n"); fprintf(stderr, "\t -i : Interface name to be moved into container (presumably with NETWORK unsharing set)\n"); fprintf(stderr, "\t -H : Set the hostname in the container\n"); fprintf(stderr, "\t -d : Daemonize (do not wait for container to exit)\n"); fprintf(stderr, "\t -M : Remount default fs inside container (/proc /dev/shm /dev/mqueue)\n"); _exit(EXIT_SUCCESS); } static bool lookup_user(const char *optarg, uid_t *uid) { char name[MAXPATHLEN]; struct passwd *pwent = NULL; if (!optarg || (optarg[0] == '\0')) return false; if (sscanf(optarg, "%u", uid) < 1) { /* not a uid -- perhaps a username */ if (sscanf(optarg, "%s", name) < 1) return false; pwent = getpwnam(name); if (!pwent) { ERROR("invalid username %s", name); return false; } *uid = pwent->pw_uid; } else { pwent = getpwuid(*uid); if (!pwent) { ERROR("invalid uid %u", *uid); return false; } } return true; } struct start_arg { char ***args; int *flags; uid_t *uid; bool setuid; int want_default_mounts; const char *want_hostname; }; static int do_start(void *arg) { struct start_arg *start_arg = arg; char **args = *start_arg->args; int flags = *start_arg->flags; uid_t uid = *start_arg->uid; int want_default_mounts = start_arg->want_default_mounts; const char *want_hostname = start_arg->want_hostname; if ((flags & CLONE_NEWNS) && want_default_mounts) lxc_setup_fs(); if ((flags & CLONE_NEWUTS) && want_hostname) if (sethostname(want_hostname, strlen(want_hostname)) < 0) { ERROR("failed to set hostname %s: %s", want_hostname, strerror(errno)); exit(EXIT_FAILURE); } // Setuid is useful even without a new user id space if (start_arg->setuid && setuid(uid)) { ERROR("failed to set uid %d: %s", uid, strerror(errno)); exit(EXIT_FAILURE); } execvp(args[0], args); ERROR("failed to exec: '%s': %s", args[0], strerror(errno)); return 1; } int main(int argc, char *argv[]) { char *del; char **it, **args; int opt, status; int ret; char *namespaces = NULL; int flags = 0, daemonize = 0; uid_t uid = 0; /* valid only if (flags & CLONE_NEWUSER) */ pid_t pid; struct my_iflist *tmpif, *my_iflist = NULL; struct start_arg start_arg = { .args = &args, .uid = &uid, .setuid = false, .flags = &flags, .want_hostname = NULL, .want_default_mounts = 0, }; while ((opt = getopt(argc, argv, "s:u:hH:i:dM")) != -1) { switch (opt) { case 's': namespaces = optarg; break; case 'i': if (!(tmpif = malloc(sizeof(*tmpif)))) { perror("malloc"); exit(EXIT_FAILURE); } tmpif->mi_ifname = optarg; tmpif->mi_next = my_iflist; my_iflist = tmpif; break; case 'd': daemonize = 1; break; case 'M': start_arg.want_default_mounts = 1; break; case 'H': start_arg.want_hostname = optarg; break; case 'h': usage(argv[0]); break; case 'u': if (!lookup_user(optarg, &uid)) exit(EXIT_FAILURE); start_arg.setuid = true; } } if (argv[optind] == NULL) { ERROR("a command to execute in the new namespace is required"); exit(EXIT_FAILURE); } args = &argv[optind]; ret = lxc_caps_init(); if (ret) exit(EXIT_FAILURE); /* The identifiers for namespaces used with lxc-unshare as given on the * manpage do not align with the standard identifiers. This affects * network, mount, and uts namespaces. The standard identifiers are: * "mnt", "uts", and "net" whereas lxc-unshare uses "MOUNT", "UTSNAME", * and "NETWORK". So let's use some cheap memmove()s to replace them by * their standard identifiers. Let's illustrate this with an example: * Assume the string: * * "IPC|MOUNT|PID" * * then we memmove() * * dest: del + 1 == OUNT|PID * src: del + 3 == NT|PID */ while ((del = strstr(namespaces, "MOUNT"))) memmove(del + 1, del + 3, strlen(del) - 2); for (it = (char *[]){"NETWORK", "UTSNAME", NULL}; it && *it; it++) while ((del = strstr(namespaces, *it))) memmove(del + 3, del + 7, strlen(del) - 6); ret = lxc_fill_namespace_flags(namespaces, &flags); if (ret) usage(argv[0]); if (!(flags & CLONE_NEWNET) && my_iflist) { ERROR("-i needs -s NETWORK option"); exit(EXIT_FAILURE); } if (!(flags & CLONE_NEWUTS) && start_arg.want_hostname) { ERROR("-H needs -s UTSNAME option"); exit(EXIT_FAILURE); } if (!(flags & CLONE_NEWNS) && start_arg.want_default_mounts) { ERROR("-M needs -s MOUNT option"); exit(EXIT_FAILURE); } pid = lxc_clone(do_start, &start_arg, flags); if (pid < 0) { ERROR("failed to clone"); exit(EXIT_FAILURE); } if (my_iflist) { for (tmpif = my_iflist; tmpif; tmpif = tmpif->mi_next) { if (lxc_netdev_move_by_name(tmpif->mi_ifname, pid, NULL) < 0) fprintf(stderr,"Could not move interface %s into container %d: %s\n", tmpif->mi_ifname, pid, strerror(errno)); } } if (daemonize) exit(EXIT_SUCCESS); if (waitpid(pid, &status, 0) < 0) { ERROR("failed to wait for '%d'", pid); exit(EXIT_FAILURE); } /* Call exit() directly on this function because it retuns an exit code. */ exit(lxc_error_set_and_log(pid, status)); } lxc-2.0.8/src/lxc/tools/lxc_attach.c0000644061062106075000000003223213105116772014240 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2010 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include "attach.h" #include "arguments.h" #include "caps.h" #include "confile.h" #include "console.h" #include "log.h" #include "list.h" #include "mainloop.h" #include "utils.h" #if HAVE_PTY_H #include #else #include <../include/openpty.h> #endif lxc_log_define(lxc_attach_ui, lxc); static const struct option my_longopts[] = { {"elevated-privileges", optional_argument, 0, 'e'}, {"arch", required_argument, 0, 'a'}, {"namespaces", required_argument, 0, 's'}, {"remount-sys-proc", no_argument, 0, 'R'}, /* TODO: decide upon short option names */ {"clear-env", no_argument, 0, 500}, {"keep-env", no_argument, 0, 501}, {"keep-var", required_argument, 0, 502}, {"set-var", required_argument, 0, 'v'}, {"pty-log", required_argument, 0, 'L'}, {"rcfile", required_argument, 0, 'f'}, LXC_COMMON_OPTIONS }; static int elevated_privileges = 0; static signed long new_personality = -1; static int namespace_flags = -1; static int remount_sys_proc = 0; static lxc_attach_env_policy_t env_policy = LXC_ATTACH_KEEP_ENV; static char **extra_env = NULL; static ssize_t extra_env_size = 0; static char **extra_keep = NULL; static ssize_t extra_keep_size = 0; static int add_to_simple_array(char ***array, ssize_t *capacity, char *value) { ssize_t count = 0; if (!array) return -1; if (*array) for (; (*array)[count]; count++); /* we have to reallocate */ if (count >= *capacity - 1) { ssize_t new_capacity = ((count + 1) / 32 + 1) * 32; char **new_array = realloc((void*)*array, sizeof(char *) * new_capacity); if (!new_array) return -1; memset(&new_array[count], 0, sizeof(char*)*(new_capacity - count)); *array = new_array; *capacity = new_capacity; } if (!(*array)) return -1; (*array)[count] = value; return 0; } static int my_parser(struct lxc_arguments* args, int c, char* arg) { char **it; char *del; int ret; switch (c) { case 'e': ret = lxc_fill_elevated_privileges(arg, &elevated_privileges); if (ret) return -1; break; case 'R': remount_sys_proc = 1; break; case 'a': new_personality = lxc_config_parse_arch(arg); if (new_personality < 0) { lxc_error(args, "invalid architecture specified: %s", arg); return -1; } break; case 's': namespace_flags = 0; /* The identifiers for namespaces used with lxc-attach as given * on the manpage do not align with the standard identifiers. * This affects network, mount, and uts namespaces. The standard * identifiers are: "mnt", "uts", and "net" whereas lxc-attach * uses "MOUNT", "UTSNAME", and "NETWORK". So let's use some * cheap memmove()s to replace them by their standard * identifiers. Let's illustrate this with an example: * Assume the string: * * "IPC|MOUNT|PID" * * then we memmove() * * dest: del + 1 == OUNT|PID * src: del + 3 == NT|PID */ while ((del = strstr(arg, "MOUNT"))) memmove(del + 1, del + 3, strlen(del) - 2); for (it = (char *[]){"NETWORK", "UTSNAME", NULL}; it && *it; it++) while ((del = strstr(arg, *it))) memmove(del + 3, del + 7, strlen(del) - 6); ret = lxc_fill_namespace_flags(arg, &namespace_flags); if (ret) return -1; /* -s implies -e */ lxc_fill_elevated_privileges(NULL, &elevated_privileges); break; case 500: /* clear-env */ env_policy = LXC_ATTACH_CLEAR_ENV; break; case 501: /* keep-env */ env_policy = LXC_ATTACH_KEEP_ENV; break; case 502: /* keep-var */ ret = add_to_simple_array(&extra_keep, &extra_keep_size, arg); if (ret < 0) { lxc_error(args, "memory allocation error"); return -1; } break; case 'v': ret = add_to_simple_array(&extra_env, &extra_env_size, arg); if (ret < 0) { lxc_error(args, "memory allocation error"); return -1; } break; case 'L': args->console_log = arg; break; case 'f': args->rcfile = arg; break; } return 0; } static struct lxc_arguments my_args = { .progname = "lxc-attach", .help = "\ --name=NAME [-- COMMAND]\n\ \n\ Execute the specified COMMAND - enter the container NAME\n\ \n\ Options :\n\ -n, --name=NAME NAME of the container\n\ -e, --elevated-privileges=PRIVILEGES\n\ Use elevated privileges instead of those of the\n\ container. If you don't specify privileges to be\n\ elevated as OR'd list: CAP, CGROUP and LSM (capabilities,\n\ cgroup and restrictions, respectively) then all of them\n\ will be elevated.\n\ WARNING: This may leak privileges into the container.\n\ Use with care.\n\ -a, --arch=ARCH Use ARCH for program instead of container's own\n\ architecture.\n\ -s, --namespaces=FLAGS\n\ Don't attach to all the namespaces of the container\n\ but just to the following OR'd list of flags:\n\ MOUNT, PID, UTSNAME, IPC, USER or NETWORK.\n\ WARNING: Using -s implies -e with all privileges\n\ elevated, it may therefore leak privileges into the\n\ container. Use with care.\n\ -R, --remount-sys-proc\n\ Remount /sys and /proc if not attaching to the\n\ mount namespace when using -s in order to properly\n\ reflect the correct namespace context. See the\n\ lxc-attach(1) manual page for details.\n\ --clear-env Clear all environment variables before attaching.\n\ The attached shell/program will start with only\n\ container=lxc set.\n\ --keep-env Keep all current environment variables. This\n\ is the current default behaviour, but is likely to\n\ change in the future.\n\ -L, --pty-log=FILE\n\ Log pty output to FILE\n\ -v, --set-var Set an additional variable that is seen by the\n\ attached program in the container. May be specified\n\ multiple times.\n\ --keep-var Keep an additional environment variable. Only\n\ applicable if --clear-env is specified. May be used\n\ multiple times.\n\ -f, --rcfile=FILE\n\ Load configuration file FILE\n\ ", .options = my_longopts, .parser = my_parser, .checker = NULL, }; struct wrapargs { lxc_attach_options_t *options; lxc_attach_command_t *command; struct lxc_console *console; int ptyfd; }; /* Minimalistic login_tty() implementation. */ static int login_pty(int fd) { setsid(); if (ioctl(fd, TIOCSCTTY, NULL) < 0) return -1; if (lxc_console_set_stdfds(fd) < 0) return -1; if (fd > STDERR_FILENO) close(fd); return 0; } static int get_pty_on_host_callback(void *p) { struct wrapargs *wrap = p; close(wrap->console->master); if (login_pty(wrap->console->slave) < 0) return -1; if (wrap->command->program) lxc_attach_run_command(wrap->command); else lxc_attach_run_shell(NULL); return -1; } static int get_pty_on_host(struct lxc_container *c, struct wrapargs *wrap, int *pid) { int ret = -1; struct wrapargs *args = wrap; struct lxc_epoll_descr descr; struct lxc_conf *conf; struct lxc_tty_state *ts; INFO("Trying to allocate a pty on the host"); if (!isatty(args->ptyfd)) { ERROR("Standard file descriptor does not refer to a pty\n."); return -1; } conf = c->lxc_conf; free(conf->console.log_path); if (my_args.console_log) conf->console.log_path = strdup(my_args.console_log); else conf->console.log_path = NULL; /* In the case of lxc-attach our peer pty will always be the current * controlling terminal. We clear whatever was set by the user for * lxc.console.path here and set it to "/dev/tty". Doing this will (a) * prevent segfaults when the container has been setup with * lxc.console = none and (b) provide an easy way to ensure that we * always do the correct thing. strdup() must be used since console.path * is free()ed when we call lxc_container_put(). */ free(conf->console.path); conf->console.path = strdup("/dev/tty"); if (!conf->console.path) return -1; /* Create pty on the host. */ if (lxc_console_create(conf) < 0) return -1; ts = conf->console.tty_state; conf->console.descr = &descr; /* Shift ttys to container. */ if (ttys_shift_ids(conf) < 0) { ERROR("Failed to shift tty into container"); goto err1; } /* Send wrapper function on its way. */ wrap->console = &conf->console; if (c->attach(c, get_pty_on_host_callback, wrap, wrap->options, pid) < 0) goto err1; close(conf->console.slave); /* Close slave side. */ ret = lxc_mainloop_open(&descr); if (ret) { ERROR("failed to create mainloop"); goto err2; } if (lxc_console_mainloop_add(&descr, conf) < 0) { ERROR("Failed to add handlers to lxc mainloop."); goto err3; } ret = lxc_mainloop(&descr, -1); if (ret) { ERROR("mainloop returned an error"); goto err3; } ret = 0; err3: lxc_mainloop_close(&descr); err2: if (ts && ts->sigfd != -1) lxc_console_sigwinch_fini(ts); err1: lxc_console_delete(&conf->console); return ret; } static int stdfd_is_pty(void) { if (isatty(STDIN_FILENO)) return STDIN_FILENO; if (isatty(STDOUT_FILENO)) return STDOUT_FILENO; if (isatty(STDERR_FILENO)) return STDERR_FILENO; return -1; } int main(int argc, char *argv[]) { int ret = -1, r; int wexit = 0; pid_t pid; lxc_attach_options_t attach_options = LXC_ATTACH_OPTIONS_DEFAULT; lxc_attach_command_t command = (lxc_attach_command_t){.program = NULL}; r = lxc_caps_init(); if (r) exit(EXIT_FAILURE); r = lxc_arguments_parse(&my_args, argc, argv); if (r) exit(EXIT_FAILURE); if (!my_args.log_file) my_args.log_file = "none"; r = lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority, my_args.progname, my_args.quiet, my_args.lxcpath[0]); if (r) exit(EXIT_FAILURE); lxc_log_options_no_override(); if (geteuid()) { if (access(my_args.lxcpath[0], O_RDONLY) < 0) { if (!my_args.quiet) fprintf(stderr, "You lack access to %s\n", my_args.lxcpath[0]); exit(EXIT_FAILURE); } } struct lxc_container *c = lxc_container_new(my_args.name, my_args.lxcpath[0]); if (!c) exit(EXIT_FAILURE); if (my_args.rcfile) { c->clear_config(c); if (!c->load_config(c, my_args.rcfile)) { ERROR("Failed to load rcfile"); lxc_container_put(c); exit(EXIT_FAILURE); } c->configfile = strdup(my_args.rcfile); if (!c->configfile) { ERROR("Out of memory setting new config filename"); lxc_container_put(c); exit(EXIT_FAILURE); } } if (!c->may_control(c)) { fprintf(stderr, "Insufficent privileges to control %s\n", c->name); lxc_container_put(c); exit(EXIT_FAILURE); } if (!c->is_defined(c)) { fprintf(stderr, "Error: container %s is not defined\n", c->name); lxc_container_put(c); exit(EXIT_FAILURE); } if (remount_sys_proc) attach_options.attach_flags |= LXC_ATTACH_REMOUNT_PROC_SYS; if (elevated_privileges) attach_options.attach_flags &= ~(elevated_privileges); attach_options.namespaces = namespace_flags; attach_options.personality = new_personality; attach_options.env_policy = env_policy; attach_options.extra_env_vars = extra_env; attach_options.extra_keep_env = extra_keep; if (my_args.argc > 0) { command.program = my_args.argv[0]; command.argv = (char**)my_args.argv; } struct wrapargs wrap = (struct wrapargs){ .command = &command, .options = &attach_options }; wrap.ptyfd = stdfd_is_pty(); if (wrap.ptyfd >= 0) { if ((!isatty(STDOUT_FILENO) || !isatty(STDERR_FILENO)) && my_args.console_log) { fprintf(stderr, "-L/--pty-log can only be used when stdout and stderr refer to a pty.\n"); goto out; } ret = get_pty_on_host(c, &wrap, &pid); } else { if (my_args.console_log) { fprintf(stderr, "-L/--pty-log can only be used when stdout and stderr refer to a pty.\n"); goto out; } if (command.program) ret = c->attach(c, lxc_attach_run_command, &command, &attach_options, &pid); else ret = c->attach(c, lxc_attach_run_shell, NULL, &attach_options, &pid); } if (ret < 0) goto out; ret = lxc_wait_for_pid_status(pid); if (ret < 0) goto out; if (WIFEXITED(ret)) wexit = WEXITSTATUS(ret); out: lxc_container_put(c); if (ret >= 0) exit(wexit); exit(EXIT_FAILURE); } lxc-2.0.8/src/lxc/tools/lxc_usernsexec.c0000644061062106075000000002067313105116772015166 00000000000000/* * (C) Copyright IBM Corp. 2008 * (C) Copyright Canonical, Inc 2010-2013 * * Authors: * Serge Hallyn * (Once upon a time, this was based on nsexec from the IBM * container tools) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "conf.h" #include "namespace.h" #include "utils.h" #ifndef MS_REC #define MS_REC 16384 #endif #ifndef MS_SLAVE #define MS_SLAVE (1 << 19) #endif int unshare(int flags); static void usage(const char *name) { printf("usage: %s [-h] [-m ] -- [command [arg ..]]\n", name); printf("\n"); printf(" -h this message\n"); printf("\n"); printf(" -m uid maps to use\n"); printf("\n"); printf(" uid-maps: [u|g|b]:ns_id:host_id:range\n"); printf(" [u|g|b]: map user id, group id, or both\n"); printf(" ns_id: the base id in the new namespace\n"); printf(" host_id: the base id in the parent namespace\n"); printf(" range: how many ids to map\n"); printf(" Note: This program uses newuidmap(2) and newgidmap(2).\n"); printf(" As such, /etc/subuid and /etc/subgid must grant the\n"); printf(" calling user permission to use the mapped ranges\n"); exit(EXIT_SUCCESS); } static void opentty(const char * tty, int which) { int fd, flags; if (tty[0] == '\0') return; fd = open(tty, O_RDWR | O_NONBLOCK); if (fd == -1) { printf("WARN: could not reopen tty: %s\n", strerror(errno)); return; } flags = fcntl(fd, F_GETFL); flags &= ~O_NONBLOCK; if (fcntl(fd, F_SETFL, flags) < 0) { printf("WARN: could not set fd flags: %s\n", strerror(errno)); return; } close(which); if (fd != which) { dup2(fd, which); close(fd); } } // Code copy end static int do_child(void *vargv) { char **argv = (char **)vargv; // Assume we want to become root if (setgid(0) < 0) { perror("setgid"); return -1; } if (setuid(0) < 0) { perror("setuid"); return -1; } if (setgroups(0, NULL) < 0) { perror("setgroups"); return -1; } if (unshare(CLONE_NEWNS) < 0) { perror("unshare CLONE_NEWNS"); return -1; } if (detect_shared_rootfs()) { if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) { printf("Failed to make / rslave"); return -1; } } execvp(argv[0], argv); perror("execvpe"); return -1; } static struct lxc_list active_map; /* * given a string like "b:0:100000:10", map both uids and gids * 0-10 to 100000 to 100010 */ static int parse_map(char *map) { struct id_map *newmap; struct lxc_list *tmp = NULL; int ret; int i; char types[2] = {'u', 'g'}; char which; long host_id, ns_id, range; if (!map) return -1; ret = sscanf(map, "%c:%ld:%ld:%ld", &which, &ns_id, &host_id, &range); if (ret != 4) return -1; if (which != 'b' && which != 'u' && which != 'g') return -1; for (i = 0; i < 2; i++) { if (which != types[i] && which != 'b') continue; newmap = malloc(sizeof(*newmap)); if (!newmap) return -1; newmap->hostid = host_id; newmap->nsid = ns_id; newmap->range = range; if (types[i] == 'u') newmap->idtype = ID_TYPE_UID; else newmap->idtype = ID_TYPE_GID; tmp = malloc(sizeof(*tmp)); if (!tmp) { free(newmap); return -1; } tmp->elem = newmap; lxc_list_add_tail(&active_map, tmp); } return 0; } /* * This is called if the user did not pass any uid ranges in * through -m flags. It's called once to get the default uid * map, and once for the default gid map. * Go through /etc/subuids and /etc/subgids to find this user's * allowed map. We only use the first one for each of uid and * gid, because otherwise we're not sure which entries the user * wanted. */ static int read_default_map(char *fnam, int which, char *username) { FILE *fin; char *line = NULL; size_t sz = 0; struct id_map *newmap; struct lxc_list *tmp = NULL; char *p1, *p2; fin = fopen(fnam, "r"); if (!fin) return -1; while (getline(&line, &sz, fin) != -1) { if (sz <= strlen(username) || strncmp(line, username, strlen(username)) != 0 || line[strlen(username)] != ':') continue; p1 = strchr(line, ':'); if (!p1) continue; p2 = strchr(p1+1, ':'); if (!p2) continue; newmap = malloc(sizeof(*newmap)); if (!newmap) { fclose(fin); free(line); return -1; } newmap->hostid = atol(p1+1); newmap->range = atol(p2+1); newmap->nsid = 0; newmap->idtype = which; tmp = malloc(sizeof(*tmp)); if (!tmp) { fclose(fin); free(line); free(newmap); return -1; } tmp->elem = newmap; lxc_list_add_tail(&active_map, tmp); break; } free(line); fclose(fin); return 0; } static int find_default_map(void) { struct passwd *p = getpwuid(getuid()); if (!p) return -1; if (read_default_map(subuidfile, ID_TYPE_UID, p->pw_name) < 0) return -1; if (read_default_map(subgidfile, ID_TYPE_GID, p->pw_name) < 0) return -1; return 0; } int main(int argc, char *argv[]) { int c; unsigned long flags = CLONE_NEWUSER | CLONE_NEWNS; char ttyname0[256], ttyname1[256], ttyname2[256]; int status; int ret; int pid; char *default_args[] = {"/bin/sh", NULL}; char buf[1]; int pipe1[2], // child tells parent it has unshared pipe2[2]; // parent tells child it is mapped and may proceed memset(ttyname0, '\0', sizeof(ttyname0)); memset(ttyname1, '\0', sizeof(ttyname1)); memset(ttyname2, '\0', sizeof(ttyname2)); if (isatty(0)) { ret = readlink("/proc/self/fd/0", ttyname0, sizeof(ttyname0)); if (ret < 0) { perror("unable to open stdin."); exit(EXIT_FAILURE); } ret = readlink("/proc/self/fd/1", ttyname1, sizeof(ttyname1)); if (ret < 0) { printf("Warning: unable to open stdout, continuing."); memset(ttyname1, '\0', sizeof(ttyname1)); } ret = readlink("/proc/self/fd/2", ttyname2, sizeof(ttyname2)); if (ret < 0) { printf("Warning: unable to open stderr, continuing."); memset(ttyname2, '\0', sizeof(ttyname2)); } } lxc_list_init(&active_map); while ((c = getopt(argc, argv, "m:h")) != EOF) { switch (c) { case 'm': if (parse_map(optarg)) usage(argv[0]); break; case 'h': default: usage(argv[0]); } }; if (lxc_list_empty(&active_map)) { if (find_default_map()) { fprintf(stderr, "You have no allocated subuids or subgids\n"); exit(EXIT_FAILURE); } } argv = &argv[optind]; argc = argc - optind; if (argc < 1) { argv = default_args; argc = 1; } if (pipe(pipe1) < 0 || pipe(pipe2) < 0) { perror("pipe"); exit(EXIT_FAILURE); } if ((pid = fork()) == 0) { // Child. close(pipe1[0]); close(pipe2[1]); opentty(ttyname0, 0); opentty(ttyname1, 1); opentty(ttyname2, 2); ret = unshare(flags); if (ret < 0) { perror("unshare"); return 1; } buf[0] = '1'; if (write(pipe1[1], buf, 1) < 1) { perror("write pipe"); exit(EXIT_FAILURE); } if (read(pipe2[0], buf, 1) < 1) { perror("read pipe"); exit(EXIT_FAILURE); } if (buf[0] != '1') { fprintf(stderr, "parent had an error, child exiting\n"); exit(EXIT_FAILURE); } close(pipe1[1]); close(pipe2[0]); return do_child((void*)argv); } close(pipe1[1]); close(pipe2[0]); if (read(pipe1[0], buf, 1) < 1) { perror("read pipe"); exit(EXIT_FAILURE); } buf[0] = '1'; if (lxc_map_ids(&active_map, pid)) { fprintf(stderr, "error mapping child\n"); ret = 0; } if (write(pipe2[1], buf, 1) < 0) { perror("write to pipe"); exit(EXIT_FAILURE); } if ((ret = waitpid(pid, &status, __WALL)) < 0) { printf("waitpid() returns %d, errno %d\n", ret, errno); exit(EXIT_FAILURE); } exit(WEXITSTATUS(status)); } lxc-2.0.8/src/lxc/tools/lxc_device.c0000644061062106075000000001063113105116772014232 00000000000000/* * lxc: linux Container library * * Authors: * Dongsheng Yang * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include "utils.h" #include "lxc.h" #include "log.h" #include "arguments.h" #if HAVE_IFADDRS_H #include #else #include <../include/ifaddrs.h> #endif lxc_log_define(lxc_device, lxc); static const struct option my_longopts[] = { LXC_COMMON_OPTIONS }; static struct lxc_arguments my_args = { .progname = "lxc-device", .help = "\ --name=NAME -- add|del DEV\n\ \n\ lxc-device attach or detach DEV to or from container.\n\ \n\ Options :\n\ -n, --name=NAME NAME of the container\n\ --rcfile=FILE Load configuration file FILE\n", .options = my_longopts, .parser = NULL, .checker = NULL, }; static bool is_interface(const char* dev_name, pid_t pid) { pid_t p = fork(); if (p < 0) { SYSERROR("failed to fork task."); exit(EXIT_FAILURE); } if (p == 0) { struct ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL; if (!switch_to_ns(pid, "net")) { ERROR("failed to enter netns of container."); exit(-1); } /* Grab the list of interfaces */ if (getifaddrs(&interfaceArray)) { ERROR("failed to get interfaces list"); exit(-1); } /* Iterate through the interfaces */ for (tempIfAddr = interfaceArray; tempIfAddr != NULL; tempIfAddr = tempIfAddr->ifa_next) { if (strcmp(tempIfAddr->ifa_name, dev_name) == 0) { exit(EXIT_SUCCESS); } } exit(EXIT_FAILURE); } if (wait_for_pid(p) == 0) { return true; } return false; } int main(int argc, char *argv[]) { struct lxc_container *c; char *cmd, *dev_name, *dst_name; bool ret = false; if (geteuid() != 0) { ERROR("%s must be run as root", argv[0]); exit(EXIT_FAILURE); } if (lxc_arguments_parse(&my_args, argc, argv)) goto err; if (!my_args.log_file) my_args.log_file = "none"; if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority, my_args.progname, my_args.quiet, my_args.lxcpath[0])) goto err; lxc_log_options_no_override(); c = lxc_container_new(my_args.name, my_args.lxcpath[0]); if (!c) { ERROR("%s doesn't exist", my_args.name); goto err; } if (my_args.rcfile) { c->clear_config(c); if (!c->load_config(c, my_args.rcfile)) { ERROR("Failed to load rcfile"); goto err1; } c->configfile = strdup(my_args.rcfile); if (!c->configfile) { ERROR("Out of memory setting new config filename"); goto err1; } } if (!c->is_running(c)) { ERROR("Container %s is not running.", c->name); goto err1; } if (my_args.argc < 2) { ERROR("Error: no command given (Please see --help output)"); goto err1; } cmd = my_args.argv[0]; dev_name = my_args.argv[1]; if (my_args.argc < 3) dst_name = dev_name; else dst_name = my_args.argv[2]; if (strcmp(cmd, "add") == 0) { if (is_interface(dev_name, 1)) { ret = c->attach_interface(c, dev_name, dst_name); } else { ret = c->add_device_node(c, dev_name, dst_name); } if (ret != true) { ERROR("Failed to add %s to %s.", dev_name, c->name); goto err1; } INFO("Add %s to %s.", dev_name, c->name); } else if (strcmp(cmd, "del") == 0) { if (is_interface(dev_name, c->init_pid(c))) { ret = c->detach_interface(c, dev_name, dst_name); } else { ret = c->remove_device_node(c, dev_name, dst_name); } if (ret != true) { ERROR("Failed to del %s from %s.", dev_name, c->name); goto err1; } INFO("Delete %s from %s.", dev_name, c->name); } else { ERROR("Error: Please use add or del (Please see --help output)"); goto err1; } exit(EXIT_SUCCESS); err1: lxc_container_put(c); err: exit(EXIT_FAILURE); } lxc-2.0.8/src/lxc/tools/lxc_execute.c0000644061062106075000000000777313105116772014452 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "caps.h" #include "lxc.h" #include "log.h" #include "conf.h" #include "confile.h" #include "arguments.h" #include "config.h" #include "start.h" #include "utils.h" lxc_log_define(lxc_execute_ui, lxc); static struct lxc_list defines; static int my_checker(const struct lxc_arguments* args) { if (!args->argc) { lxc_error(args, "missing command to execute !"); return -1; } return 0; } static int my_parser(struct lxc_arguments* args, int c, char* arg) { switch (c) { case 'f': args->rcfile = arg; break; case 's': return lxc_config_define_add(&defines, arg); break; case 'u': if (lxc_safe_uint(arg, &args->uid) < 0) return -1; break; case 'g': if (lxc_safe_uint(arg, &args->gid) < 0) return -1; } return 0; } static const struct option my_longopts[] = { {"rcfile", required_argument, 0, 'f'}, {"define", required_argument, 0, 's'}, {"uid", required_argument, 0, 'u'}, {"gid", required_argument, 0, 'g'}, LXC_COMMON_OPTIONS }; static struct lxc_arguments my_args = { .progname = "lxc-execute", .help = "\ --name=NAME -- COMMAND\n\ \n\ lxc-execute creates a container with the identifier NAME\n\ and execs COMMAND into this container.\n\ \n\ Options :\n\ -n, --name=NAME NAME of the container\n\ -f, --rcfile=FILE Load configuration file FILE\n\ -s, --define KEY=VAL Assign VAL to configuration variable KEY\n\ -u, --uid=UID Execute COMMAND with UID inside the container\n\ -g, --gid=GID Execute COMMAND with GID inside the container\n", .options = my_longopts, .parser = my_parser, .checker = my_checker, }; int main(int argc, char *argv[]) { char *rcfile; struct lxc_conf *conf; int ret; lxc_list_init(&defines); if (lxc_caps_init()) exit(EXIT_FAILURE); if (lxc_arguments_parse(&my_args, argc, argv)) exit(EXIT_FAILURE); if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority, my_args.progname, my_args.quiet, my_args.lxcpath[0])) exit(EXIT_FAILURE); lxc_log_options_no_override(); /* rcfile is specified in the cli option */ if (my_args.rcfile) rcfile = (char *)my_args.rcfile; else { int rc; rc = asprintf(&rcfile, "%s/%s/config", my_args.lxcpath[0], my_args.name); if (rc == -1) { SYSERROR("failed to allocate memory"); exit(EXIT_FAILURE); } /* container configuration does not exist */ if (access(rcfile, F_OK)) { free(rcfile); rcfile = NULL; } } conf = lxc_conf_init(); if (!conf) { ERROR("failed to initialize configuration"); exit(EXIT_FAILURE); } if (rcfile && lxc_config_read(rcfile, conf, NULL)) { ERROR("failed to read configuration file"); exit(EXIT_FAILURE); } if (lxc_config_define_load(&defines, conf)) exit(EXIT_FAILURE); if (my_args.uid) conf->init_uid = my_args.uid; if (my_args.gid) conf->init_gid = my_args.gid; ret = lxc_execute(my_args.name, my_args.argv, my_args.quiet, conf, my_args.lxcpath[0], false); lxc_conf_free(conf); if (ret < 0) exit(EXIT_FAILURE); exit(ret); } lxc-2.0.8/src/lxc/caps.h0000644061062106075000000000461613105116772011726 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include #ifndef __LXC_CAPS_H #define __LXC_CAPS_H #if HAVE_LIBCAP #include extern int lxc_caps_down(void); extern int lxc_caps_up(void); extern int lxc_caps_init(void); extern int lxc_caps_last_cap(void); extern bool lxc_proc_cap_is_set(cap_value_t cap, cap_flag_t flag); extern bool lxc_file_cap_is_set(const char *path, cap_value_t cap, cap_flag_t flag); #else static inline int lxc_caps_down(void) { return 0; } static inline int lxc_caps_up(void) { return 0; } static inline int lxc_caps_init(void) { return 0; } static inline int lxc_caps_last_cap(void) { return 0; } typedef int cap_value_t; typedef int cap_flag_t; static inline bool lxc_proc_cap_is_set(cap_value_t cap, cap_flag_t flag) { return false; } static inline bool lxc_file_cap_is_set(const char *path, cap_value_t cap, cap_flag_t flag) { return false; } #endif #define lxc_priv(__lxc_function) \ ({ \ __label__ out; \ int __ret, __ret2, ___errno = 0; \ __ret = lxc_caps_up(); \ if (__ret) \ goto out; \ __ret = __lxc_function; \ if (__ret) \ ___errno = errno; \ __ret2 = lxc_caps_down(); \ out: __ret ? errno = ___errno,__ret : __ret2; \ }) #define lxc_unpriv(__lxc_function) \ ({ \ __label__ out; \ int __ret, __ret2, ___errno = 0; \ __ret = lxc_caps_down(); \ if (__ret) \ goto out; \ __ret = __lxc_function; \ if (__ret) \ ___errno = errno; \ __ret2 = lxc_caps_up(); \ out: __ret ? errno = ___errno,__ret : __ret2; \ }) #endif lxc-2.0.8/src/lxc/lxclock.c0000644061062106075000000001674613105116772012441 00000000000000/* liblxcapi * * Copyright © 2012 Serge Hallyn . * Copyright © 2012 Canonical Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #include "lxclock.h" #include #include #include #include #include #include #include #include #include "utils.h" #include "log.h" #ifdef MUTEX_DEBUGGING #include #endif #define MAX_STACKDEPTH 25 #define OFLAG (O_CREAT | O_RDWR) #define SEMMODE 0660 #define SEMVALUE 1 #define SEMVALUE_LOCKED 0 lxc_log_define(lxc_lock, lxc); #ifdef MUTEX_DEBUGGING static pthread_mutex_t thread_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; static inline void dump_stacktrace(void) { void *array[MAX_STACKDEPTH]; size_t size; char **strings; size_t i; size = backtrace(array, MAX_STACKDEPTH); strings = backtrace_symbols(array, size); // Using fprintf here as our logging module is not thread safe fprintf(stderr, "\tObtained %zd stack frames.\n", size); for (i = 0; i < size; i++) fprintf(stderr, "\t\t%s\n", strings[i]); free (strings); } #else static pthread_mutex_t thread_mutex = PTHREAD_MUTEX_INITIALIZER; static inline void dump_stacktrace(void) {;} #endif 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)); dump_stacktrace(); 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)); dump_stacktrace(); exit(1); } } static char *lxclock_name(const char *p, const char *n) { int ret; int len; char *dest; char *rundir; /* lockfile will be: * "/run" + "/lxc/lock/$lxcpath/$lxcname + '\0' if root * or * $XDG_RUNTIME_DIR + "/lxc/lock/$lxcpath/$lxcname + '\0' if non-root */ /* length of "/lxc/lock/" + $lxcpath + "/" + "." + $lxcname + '\0' */ len = strlen("/lxc/lock/") + strlen(n) + strlen(p) + 3; rundir = get_rundir(); if (!rundir) return NULL; len += strlen(rundir); if ((dest = malloc(len)) == NULL) { free(rundir); return NULL; } ret = snprintf(dest, len, "%s/lxc/lock/%s", rundir, p); if (ret < 0 || ret >= len) { free(dest); free(rundir); return NULL; } ret = mkdir_p(dest, 0755); if (ret < 0) { free(dest); free(rundir); return NULL; } ret = snprintf(dest, len, "%s/lxc/lock/%s/.%s", rundir, p, n); free(rundir); if (ret < 0 || ret >= len) { free(dest); return NULL; } return dest; } static sem_t *lxc_new_unnamed_sem(void) { sem_t *s; int ret; s = malloc(sizeof(*s)); if (!s) return NULL; ret = sem_init(s, 0, 1); if (ret) { free(s); return NULL; } return s; } struct lxc_lock *lxc_newlock(const char *lxcpath, const char *name) { struct lxc_lock *l; l = malloc(sizeof(*l)); if (!l) goto out; if (!name) { l->type = LXC_LOCK_ANON_SEM; l->u.sem = lxc_new_unnamed_sem(); if (!l->u.sem) { free(l); l = NULL; } goto out; } l->type = LXC_LOCK_FLOCK; l->u.f.fname = lxclock_name(lxcpath, name); if (!l->u.f.fname) { free(l); l = NULL; goto out; } l->u.f.fd = -1; out: return l; } int lxclock(struct lxc_lock *l, int timeout) { int ret = -1, saved_errno = errno; struct flock lk; switch(l->type) { case LXC_LOCK_ANON_SEM: if (!timeout) { ret = sem_wait(l->u.sem); if (ret == -1) saved_errno = errno; } else { struct timespec ts; if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { ret = -2; goto out; } ts.tv_sec += timeout; ret = sem_timedwait(l->u.sem, &ts); if (ret == -1) saved_errno = errno; } break; case LXC_LOCK_FLOCK: ret = -2; if (timeout) { ERROR("Error: timeout not supported with flock"); ret = -2; goto out; } if (!l->u.f.fname) { ERROR("Error: filename not set for flock"); ret = -2; goto out; } if (l->u.f.fd == -1) { l->u.f.fd = open(l->u.f.fname, O_RDWR|O_CREAT, S_IWUSR | S_IRUSR); if (l->u.f.fd == -1) { ERROR("Error opening %s", l->u.f.fname); goto out; } } lk.l_type = F_WRLCK; lk.l_whence = SEEK_SET; lk.l_start = 0; lk.l_len = 0; ret = fcntl(l->u.f.fd, F_SETLKW, &lk); if (ret == -1) saved_errno = errno; break; } out: errno = saved_errno; return ret; } int lxcunlock(struct lxc_lock *l) { int ret = 0, saved_errno = errno; struct flock lk; switch(l->type) { case LXC_LOCK_ANON_SEM: if (!l->u.sem) ret = -2; else { ret = sem_post(l->u.sem); saved_errno = errno; } break; case LXC_LOCK_FLOCK: if (l->u.f.fd != -1) { lk.l_type = F_UNLCK; lk.l_whence = SEEK_SET; lk.l_start = 0; lk.l_len = 0; ret = fcntl(l->u.f.fd, F_SETLK, &lk); if (ret < 0) saved_errno = errno; close(l->u.f.fd); l->u.f.fd = -1; } else ret = -2; break; } errno = saved_errno; return ret; } /* * lxc_putlock() is only called when a container_new() fails, * or during container_put(), which is already guaranteed to * only be done by one task. * So the only exclusion we need to provide here is for regular * thread safety (i.e. file descriptor table changes). */ void lxc_putlock(struct lxc_lock *l) { if (!l) return; switch(l->type) { case LXC_LOCK_ANON_SEM: if (l->u.sem) { sem_destroy(l->u.sem); free(l->u.sem); l->u.sem = NULL; } break; case LXC_LOCK_FLOCK: if (l->u.f.fd != -1) { close(l->u.f.fd); l->u.f.fd = -1; } free(l->u.f.fname); l->u.f.fname = NULL; break; } free(l); } void process_lock(void) { lock_mutex(&thread_mutex); } void process_unlock(void) { unlock_mutex(&thread_mutex); } /* One thread can do fork() while another one is holding a mutex. * There is only one thread in child just after the fork(), so no one will ever release that mutex. * We setup a "child" fork handler to unlock the mutex just after the fork(). * For several mutex types, unlocking an unlocked mutex can lead to undefined behavior. * One way to deal with it is to setup "prepare" fork handler * to lock the mutex before fork() and both "parent" and "child" fork handlers * to unlock the mutex. * This forbids doing fork() while explicitly holding the lock. */ #ifdef HAVE_PTHREAD_ATFORK __attribute__((constructor)) static void process_lock_setup_atfork(void) { pthread_atfork(process_lock, process_unlock, process_unlock); } #endif int container_mem_lock(struct lxc_container *c) { return lxclock(c->privlock, 0); } void container_mem_unlock(struct lxc_container *c) { lxcunlock(c->privlock); } int container_disk_lock(struct lxc_container *c) { int ret; if ((ret = lxclock(c->privlock, 0))) return ret; if ((ret = lxclock(c->slock, 0))) { lxcunlock(c->privlock); return ret; } return 0; } void container_disk_unlock(struct lxc_container *c) { lxcunlock(c->slock); lxcunlock(c->privlock); } lxc-2.0.8/src/lxc/genl.h0000644061062106075000000000721213105116772011720 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_GENL_H #define __LXC_GENL_H /* * Use this as a good size to allocate generic netlink messages */ #define GENLMSG_GOOD_SIZE NLMSG_GOOD_SIZE #define GENLMSG_DATA(glh) ((void *)(NLMSG_DATA(glh) + GENL_HDRLEN)) /* * struct genl_handler : the structure which store the netlink handler * and the family number resulting of the auto-generating id family * for the generic netlink protocol * * @nlh: the netlink socket handler * @family: the generic netlink family assigned number */ struct genl_handler { struct nl_handler nlh; int family; }; /* * struct genlmsg : the struct containing the generic netlink message * format * * @nlmsghdr: a netlink message header * @genlmsghdr: a generic netlink message header pointer * */ /* __attribute__ ((aligned(4))); */ struct genlmsg { struct nlmsghdr nlmsghdr; struct genlmsghdr genlmsghdr; }; static inline int genetlink_len(const struct genlmsg *genlmsg) { return ((genlmsg->nlmsghdr.nlmsg_len) - GENL_HDRLEN - NLMSG_HDRLEN); } /* * genetlink_open : resolve family number id and open a generic netlink socket * * @handler: a struct genl_handler pointer * @family: the family name of the generic netlink protocol * * Returns 0 on success, < 0 otherwise */ int genetlink_open(struct genl_handler *handler, const char *family); /* * genetlink_close : close a generic netlink socket * * @handler: the handler of the socket to be closed * * Returns 0 on success, < 0 otherwise */ int genetlink_close(struct genl_handler *handler); /* * genetlink_rcv : receive a generic netlink socket, it is up * to the caller to manage the allocation of the generic netlink message * * @handler: the handler of the generic netlink socket * @genlmsg: the pointer to a generic netlink message pre-allocated * * Returns 0 on success, < 0 otherwise */ int genetlink_rcv(struct genl_handler *handler, struct genlmsg *genlmsg); /* * genetlink_send : send a generic netlink socket, it is up * to the caller to manage the allocation of the generic netlink message * * @handler: the handler of the generic netlink socket * @genlmsg: the pointer to a generic netlink message pre-allocated * * Returns 0 on success, < 0 otherwise */ int genetlink_send(struct genl_handler *handler, struct genlmsg *genlmsg); struct genlmsg *genlmsg_alloc(size_t size); void genlmsg_free(struct genlmsg *genlmsg); /* * genetlink_transaction : send and receive a generic netlink message in one shot * * @handler: the handler of the generic netlink socket * @request: a generic netlink message containing the request to be sent * @answer: a pre-allocated generic netlink message to receive the response * * Returns 0 on success, < 0 otherwise */ int genetlink_transaction(struct genl_handler *handler, struct genlmsg *request, struct genlmsg *answer); #endif lxc-2.0.8/src/lxc/console.c0000644061062106075000000004073513105116772012437 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include "af_unix.h" #include "caps.h" #include "commands.h" #include "conf.h" #include "config.h" #include "console.h" #include "log.h" #include "lxclock.h" #include "mainloop.h" #include "start.h" /* for struct lxc_handler */ #include "utils.h" #if HAVE_PTY_H #include #else #include <../include/openpty.h> #endif lxc_log_define(console, lxc); static struct lxc_list lxc_ttys; typedef void (*sighandler_t)(int); __attribute__((constructor)) void lxc_console_init(void) { lxc_list_init(&lxc_ttys); } void lxc_console_winsz(int srcfd, int dstfd) { struct winsize wsz; if (isatty(srcfd) && ioctl(srcfd, TIOCGWINSZ, &wsz) == 0) { DEBUG("set winsz dstfd:%d cols:%d rows:%d", dstfd, wsz.ws_col, wsz.ws_row); ioctl(dstfd, TIOCSWINSZ, &wsz); } } static void lxc_console_winch(struct lxc_tty_state *ts) { lxc_console_winsz(ts->stdinfd, ts->masterfd); if (ts->winch_proxy) lxc_cmd_console_winch(ts->winch_proxy, ts->winch_proxy_lxcpath); } void lxc_console_sigwinch(int sig) { struct lxc_list *it; struct lxc_tty_state *ts; lxc_list_for_each(it, &lxc_ttys) { ts = it->elem; lxc_console_winch(ts); } } int lxc_console_cb_sigwinch_fd(int fd, uint32_t events, void *cbdata, struct lxc_epoll_descr *descr) { struct signalfd_siginfo siginfo; struct lxc_tty_state *ts = cbdata; ssize_t ret = read(fd, &siginfo, sizeof(siginfo)); if (ret < 0 || (size_t)ret < sizeof(siginfo)) { ERROR("failed to read signal info"); return -1; } lxc_console_winch(ts); return 0; } struct lxc_tty_state *lxc_console_sigwinch_init(int srcfd, int dstfd) { sigset_t mask; struct lxc_tty_state *ts; ts = malloc(sizeof(*ts)); if (!ts) return NULL; memset(ts, 0, sizeof(*ts)); ts->stdinfd = srcfd; ts->masterfd = dstfd; ts->sigfd = -1; /* add tty to list to be scanned at SIGWINCH time */ lxc_list_add_elem(&ts->node, ts); lxc_list_add_tail(&lxc_ttys, &ts->node); sigemptyset(&mask); sigaddset(&mask, SIGWINCH); if (sigprocmask(SIG_BLOCK, &mask, &ts->oldmask)) { SYSERROR("failed to block SIGWINCH."); ts->sigfd = -1; return ts; } ts->sigfd = signalfd(-1, &mask, 0); if (ts->sigfd < 0) { SYSERROR("failed to get signalfd."); sigprocmask(SIG_SETMASK, &ts->oldmask, NULL); ts->sigfd = -1; return ts; } DEBUG("%d got SIGWINCH fd %d", getpid(), ts->sigfd); return ts; } void lxc_console_sigwinch_fini(struct lxc_tty_state *ts) { if (ts->sigfd >= 0) close(ts->sigfd); lxc_list_del(&ts->node); sigprocmask(SIG_SETMASK, &ts->oldmask, NULL); free(ts); } static int lxc_console_cb_con(int fd, uint32_t events, void *data, struct lxc_epoll_descr *descr) { struct lxc_console *console = (struct lxc_console *)data; char buf[1024]; int r, w; w = r = lxc_read_nointr(fd, buf, sizeof(buf)); if (r <= 0) { INFO("console client on fd %d has exited", fd); lxc_mainloop_del_handler(descr, fd); close(fd); return 1; } if (fd == console->peer) w = lxc_write_nointr(console->master, buf, r); if (fd == console->master) { if (console->log_fd >= 0) w = lxc_write_nointr(console->log_fd, buf, r); if (console->peer >= 0) w = lxc_write_nointr(console->peer, buf, r); } if (w != r) WARN("console short write r:%d w:%d", r, w); return 0; } static void lxc_console_mainloop_add_peer(struct lxc_console *console) { if (console->peer >= 0) { if (lxc_mainloop_add_handler(console->descr, console->peer, lxc_console_cb_con, console)) WARN("console peer not added to mainloop"); } if (console->tty_state && console->tty_state->sigfd != -1) { if (lxc_mainloop_add_handler(console->descr, console->tty_state->sigfd, lxc_console_cb_sigwinch_fd, console->tty_state)) { WARN("failed to add to mainloop SIGWINCH handler for '%d'", console->tty_state->sigfd); } } } extern int lxc_console_mainloop_add(struct lxc_epoll_descr *descr, struct lxc_conf *conf) { struct lxc_console *console = &conf->console; if (conf->is_execute) { INFO("no console for lxc-execute."); return 0; } if (!conf->rootfs.path) { INFO("no rootfs, no console."); return 0; } if (console->master < 0) { INFO("no console"); return 0; } if (lxc_mainloop_add_handler(descr, console->master, lxc_console_cb_con, console)) { ERROR("failed to add to mainloop console handler for '%d'", console->master); return -1; } /* we cache the descr so that we can add an fd to it when someone * does attach to it in lxc_console_allocate() */ console->descr = descr; lxc_console_mainloop_add_peer(console); return 0; } int lxc_setup_tios(int fd, struct termios *oldtios) { struct termios newtios; if (!isatty(fd)) { ERROR("'%d' is not a tty", fd); return -1; } /* Get current termios */ if (tcgetattr(fd, oldtios)) { SYSERROR("failed to get current terminal settings"); return -1; } /* ensure we don't end up in an endless loop: * The kernel might fire SIGTTOU while an * ioctl() in tcsetattr() is executed. When the ioctl() * is resumed and retries, the signal handler interrupts it again. */ signal (SIGTTIN, SIG_IGN); signal (SIGTTOU, SIG_IGN); newtios = *oldtios; /* We use the same settings that ssh does. */ newtios.c_iflag |= IGNPAR; newtios.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF); #ifdef IUCLC newtios.c_iflag &= ~IUCLC; #endif newtios.c_lflag &= ~(TOSTOP | ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL); #ifdef IEXTEN newtios.c_lflag &= ~IEXTEN; #endif newtios.c_oflag &= ~OPOST; newtios.c_cc[VMIN] = 1; newtios.c_cc[VTIME] = 0; /* Set new attributes. */ if (tcsetattr(fd, TCSAFLUSH, &newtios)) { ERROR("failed to set new terminal settings"); return -1; } return 0; } static void lxc_console_peer_proxy_free(struct lxc_console *console) { if (console->tty_state && console->tty_state->sigfd != -1) { lxc_console_sigwinch_fini(console->tty_state); console->tty_state = NULL; } close(console->peerpty.master); close(console->peerpty.slave); console->peerpty.master = -1; console->peerpty.slave = -1; console->peerpty.busy = -1; console->peerpty.name[0] = '\0'; console->peer = -1; } static int lxc_console_peer_proxy_alloc(struct lxc_console *console, int sockfd) { struct termios oldtermio; struct lxc_tty_state *ts; int ret; if (console->master < 0) { ERROR("console not set up"); return -1; } if (console->peerpty.busy != -1 || console->peer != -1) { NOTICE("console already in use"); return -1; } if (console->tty_state) { ERROR("console already has tty_state"); return -1; } /* this is the proxy pty that will be given to the client, and that * the real pty master will send to / recv from */ process_lock(); ret = openpty(&console->peerpty.master, &console->peerpty.slave, console->peerpty.name, NULL, NULL); process_unlock(); if (ret) { SYSERROR("failed to create proxy pty"); return -1; } if (lxc_setup_tios(console->peerpty.slave, &oldtermio) < 0) goto err1; ts = lxc_console_sigwinch_init(console->peerpty.master, console->master); if (!ts) goto err1; console->tty_state = ts; console->peer = console->peerpty.slave; console->peerpty.busy = sockfd; lxc_console_mainloop_add_peer(console); DEBUG("%d %s peermaster:%d sockfd:%d", getpid(), __FUNCTION__, console->peerpty.master, sockfd); return 0; err1: lxc_console_peer_proxy_free(console); return -1; } int lxc_console_allocate(struct lxc_conf *conf, int sockfd, int *ttyreq) { int masterfd = -1, ttynum; struct lxc_tty_info *tty_info = &conf->tty_info; struct lxc_console *console = &conf->console; if (*ttyreq == 0) { if (lxc_console_peer_proxy_alloc(console, sockfd) < 0) goto out; masterfd = console->peerpty.master; goto out; } if (*ttyreq > 0) { if (*ttyreq > tty_info->nbtty) goto out; if (tty_info->pty_info[*ttyreq - 1].busy) goto out; /* the requested tty is available */ ttynum = *ttyreq; goto out_tty; } /* search for next available tty, fixup index tty1 => [0] */ for (ttynum = 1; ttynum <= tty_info->nbtty && tty_info->pty_info[ttynum - 1].busy; ttynum++) ; /* we didn't find any available slot for tty */ if (ttynum > tty_info->nbtty) goto out; *ttyreq = ttynum; out_tty: tty_info->pty_info[ttynum - 1].busy = sockfd; masterfd = tty_info->pty_info[ttynum - 1].master; out: return masterfd; } void lxc_console_free(struct lxc_conf *conf, int fd) { int i; struct lxc_tty_info *tty_info = &conf->tty_info; struct lxc_console *console = &conf->console; for (i = 0; i < tty_info->nbtty; i++) { if (tty_info->pty_info[i].busy == fd) tty_info->pty_info[i].busy = 0; } if (console->peerpty.busy == fd) { lxc_mainloop_del_handler(console->descr, console->peerpty.slave); lxc_console_peer_proxy_free(console); } } static int lxc_console_peer_default(struct lxc_console *console) { struct lxc_tty_state *ts; const char *path = console->path; int fd; int ret = 0; /* If no console was given, try current controlling terminal, there * won't be one if we were started as a daemon (-d). */ if (!path && !access("/dev/tty", F_OK)) { fd = open("/dev/tty", O_RDWR); if (fd >= 0) { close(fd); path = "/dev/tty"; } } if (!path) { errno = ENOTTY; DEBUG("process does not have a controlling terminal"); goto out; } console->peer = lxc_unpriv(open(path, O_CLOEXEC | O_RDWR | O_CREAT | O_APPEND, 0600)); if (console->peer < 0) { ERROR("failed to open \"%s\"", path); return -ENOTTY; } DEBUG("using \"%s\" as peer tty device", path); if (!isatty(console->peer)) { ERROR("file descriptor for file \"%s\" does not refer to a tty device", path); goto on_error1; } ts = lxc_console_sigwinch_init(console->peer, console->master); console->tty_state = ts; if (!ts) { WARN("unable to install SIGWINCH handler"); goto on_error1; } lxc_console_winsz(console->peer, console->master); console->tios = malloc(sizeof(*console->tios)); if (!console->tios) { SYSERROR("failed to allocate memory"); ret = -ENOMEM; goto on_error1; } if (lxc_setup_tios(console->peer, console->tios) < 0) goto on_error2; else goto out; on_error2: free(console->tios); console->tios = NULL; ret = -ENOTTY; on_error1: close(console->peer); console->peer = -1; ret = -ENOTTY; out: return ret; } void lxc_console_delete(struct lxc_console *console) { if (console->tios && console->peer >= 0 && tcsetattr(console->peer, TCSAFLUSH, console->tios)) WARN("failed to set old terminal settings"); free(console->tios); console->tios = NULL; close(console->peer); close(console->master); close(console->slave); if (console->log_fd >= 0) close(console->log_fd); console->peer = -1; console->master = -1; console->slave = -1; console->log_fd = -1; } int lxc_console_create(struct lxc_conf *conf) { struct lxc_console *console = &conf->console; int ret; if (conf->is_execute) { INFO("not allocating a console device for lxc-execute."); return 0; } if (!conf->rootfs.path) { INFO("container does not have a rootfs, console device will be shared with the host"); return 0; } if (console->path && !strcmp(console->path, "none")) { INFO("no console requested"); return 0; } process_lock(); ret = openpty(&console->master, &console->slave, console->name, NULL, NULL); process_unlock(); if (ret < 0) { SYSERROR("failed to allocate a pty"); return -1; } if (fcntl(console->master, F_SETFD, FD_CLOEXEC)) { SYSERROR("failed to set console master to close-on-exec"); goto err; } if (fcntl(console->slave, F_SETFD, FD_CLOEXEC)) { SYSERROR("failed to set console slave to close-on-exec"); goto err; } ret = lxc_console_peer_default(console); if (ret < 0) { ERROR("failed to allocate peer tty device"); goto err; } if (console->log_path) { console->log_fd = lxc_unpriv(open(console->log_path, O_CLOEXEC | O_RDWR | O_CREAT | O_APPEND, 0600)); if (console->log_fd < 0) { SYSERROR("failed to open console log file \"%s\"", console->log_path); goto err; } DEBUG("using \"%s\" as console log file", console->log_path); } return 0; err: lxc_console_delete(console); return -1; } int lxc_console_set_stdfds(int fd) { if (fd < 0) return 0; if (isatty(STDIN_FILENO)) if (dup2(fd, STDIN_FILENO) < 0) { SYSERROR("failed to duplicate stdin."); return -1; } if (isatty(STDOUT_FILENO)) if (dup2(fd, STDOUT_FILENO) < 0) { SYSERROR("failed to duplicate stdout."); return -1; } if (isatty(STDERR_FILENO)) if (dup2(fd, STDERR_FILENO) < 0) { SYSERROR("failed to duplicate stderr."); return -1; } return 0; } int lxc_console_cb_tty_stdin(int fd, uint32_t events, void *cbdata, struct lxc_epoll_descr *descr) { struct lxc_tty_state *ts = cbdata; char c; if (fd != ts->stdinfd) return 1; if (lxc_read_nointr(ts->stdinfd, &c, 1) <= 0) return 1; if (ts->escape != -1) { /* we want to exit the console with Ctrl+a q */ if (c == ts->escape && !ts->saw_escape) { ts->saw_escape = 1; return 0; } if (c == 'q' && ts->saw_escape) return 1; ts->saw_escape = 0; } if (lxc_write_nointr(ts->masterfd, &c, 1) <= 0) return 1; return 0; } int lxc_console_cb_tty_master(int fd, uint32_t events, void *cbdata, struct lxc_epoll_descr *descr) { struct lxc_tty_state *ts = cbdata; char buf[1024]; int r, w; if (fd != ts->masterfd) return 1; r = lxc_read_nointr(fd, buf, sizeof(buf)); if (r <= 0) return 1; w = lxc_write_nointr(ts->stdoutfd, buf, r); if (w <= 0) { return 1; } else if (w != r) { SYSERROR("failed to write"); return 1; } return 0; } int lxc_console_getfd(struct lxc_container *c, int *ttynum, int *masterfd) { return lxc_cmd_console(c->name, ttynum, masterfd, c->config_path); } int lxc_console(struct lxc_container *c, int ttynum, int stdinfd, int stdoutfd, int stderrfd, int escape) { int ret, ttyfd, masterfd; struct lxc_epoll_descr descr; struct termios oldtios; struct lxc_tty_state *ts; if (!isatty(stdinfd)) { ERROR("stdin is not a tty"); return -1; } ret = lxc_setup_tios(stdinfd, &oldtios); if (ret) { ERROR("failed to setup tios"); return -1; } ttyfd = lxc_cmd_console(c->name, &ttynum, &masterfd, c->config_path); if (ttyfd < 0) { ret = ttyfd; goto err1; } fprintf(stderr, "\n" "Connected to tty %1$d\n" "Type to exit the console, " " to enter Ctrl+%2$c itself\n", ttynum, 'a' + escape - 1); ret = setsid(); if (ret) INFO("already group leader"); ts = lxc_console_sigwinch_init(stdinfd, masterfd); if (!ts) { ret = -1; goto err2; } ts->escape = escape; ts->winch_proxy = c->name; ts->winch_proxy_lxcpath = c->config_path; lxc_console_winsz(stdinfd, masterfd); lxc_cmd_console_winch(ts->winch_proxy, ts->winch_proxy_lxcpath); ret = lxc_mainloop_open(&descr); if (ret) { ERROR("failed to create mainloop"); goto err3; } if (ts->sigfd != -1) { ret = lxc_mainloop_add_handler(&descr, ts->sigfd, lxc_console_cb_sigwinch_fd, ts); if (ret) { ERROR("failed to add handler for SIGWINCH fd"); goto err4; } } ret = lxc_mainloop_add_handler(&descr, ts->stdinfd, lxc_console_cb_tty_stdin, ts); if (ret) { ERROR("failed to add handler for stdinfd"); goto err4; } ret = lxc_mainloop_add_handler(&descr, ts->masterfd, lxc_console_cb_tty_master, ts); if (ret) { ERROR("failed to add handler for masterfd"); goto err4; } ret = lxc_mainloop(&descr, -1); if (ret) { ERROR("mainloop returned an error"); goto err4; } ret = 0; err4: lxc_mainloop_close(&descr); err3: if (ts->sigfd != -1) lxc_console_sigwinch_fini(ts); err2: close(masterfd); close(ttyfd); err1: tcsetattr(stdinfd, TCSAFLUSH, &oldtios); return ret; } lxc-2.0.8/src/lxc/mainloop.h0000644061062106075000000000305513105116772012612 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_MAINLOOP_H #define __LXC_MAINLOOP_H #include #include "list.h" struct lxc_epoll_descr { int epfd; struct lxc_list handlers; }; typedef int (*lxc_mainloop_callback_t)(int fd, uint32_t event, void *data, struct lxc_epoll_descr *descr); extern int lxc_mainloop(struct lxc_epoll_descr *descr, int timeout_ms); extern int lxc_mainloop_add_handler(struct lxc_epoll_descr *descr, int fd, lxc_mainloop_callback_t callback, void *data); extern int lxc_mainloop_del_handler(struct lxc_epoll_descr *descr, int fd); extern int lxc_mainloop_open(struct lxc_epoll_descr *descr); extern int lxc_mainloop_close(struct lxc_epoll_descr *descr); #endif lxc-2.0.8/src/lxc/nl.c0000644061062106075000000001553713105116772011410 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include "nl.h" #define NLMSG_TAIL(nmsg) \ ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) extern size_t nlmsg_len(const struct nlmsg *nlmsg) { return nlmsg->nlmsghdr->nlmsg_len - NLMSG_HDRLEN; } extern void *nlmsg_data(struct nlmsg *nlmsg) { char *data = ((char *)nlmsg) + NLMSG_HDRLEN; if (!nlmsg_len(nlmsg)) return NULL; return data; } static int nla_put(struct nlmsg *nlmsg, int attr, const void *data, size_t len) { struct rtattr *rta; size_t rtalen = RTA_LENGTH(len); size_t tlen = NLMSG_ALIGN(nlmsg->nlmsghdr->nlmsg_len) + RTA_ALIGN(rtalen); if (tlen > nlmsg->cap) return -ENOMEM; rta = NLMSG_TAIL(nlmsg->nlmsghdr); rta->rta_type = attr; rta->rta_len = rtalen; memcpy(RTA_DATA(rta), data, len); nlmsg->nlmsghdr->nlmsg_len = tlen; return 0; } extern int nla_put_buffer(struct nlmsg *nlmsg, int attr, const void *data, size_t size) { return nla_put(nlmsg, attr, data, size); } extern int nla_put_string(struct nlmsg *nlmsg, int attr, const char *string) { return nla_put(nlmsg, attr, string, strlen(string) + 1); } extern int nla_put_u32(struct nlmsg *nlmsg, int attr, int value) { return nla_put(nlmsg, attr, &value, sizeof(value)); } extern int nla_put_u16(struct nlmsg *nlmsg, int attr, unsigned short value) { return nla_put(nlmsg, attr, &value, 2); } extern int nla_put_attr(struct nlmsg *nlmsg, int attr) { return nla_put(nlmsg, attr, NULL, 0); } struct rtattr *nla_begin_nested(struct nlmsg *nlmsg, int attr) { struct rtattr *rtattr = NLMSG_TAIL(nlmsg->nlmsghdr); if (nla_put_attr(nlmsg, attr)) return NULL; return rtattr; } void nla_end_nested(struct nlmsg *nlmsg, struct rtattr *attr) { attr->rta_len = (void *)NLMSG_TAIL(nlmsg->nlmsghdr) - (void *)attr; } extern struct nlmsg *nlmsg_alloc(size_t size) { struct nlmsg *nlmsg; size_t len = NLMSG_HDRLEN + NLMSG_ALIGN(size); nlmsg = (struct nlmsg *)malloc(sizeof(struct nlmsg)); if (!nlmsg) return NULL; nlmsg->nlmsghdr = (struct nlmsghdr *)malloc(len); if (!nlmsg->nlmsghdr) goto errout; memset(nlmsg->nlmsghdr, 0, len); nlmsg->cap = len; nlmsg->nlmsghdr->nlmsg_len = NLMSG_HDRLEN; return nlmsg; errout: free(nlmsg); return NULL; } extern void *nlmsg_reserve(struct nlmsg *nlmsg, size_t len) { void *buf; size_t nlmsg_len = nlmsg->nlmsghdr->nlmsg_len; size_t tlen = NLMSG_ALIGN(len); if (nlmsg_len + tlen > nlmsg->cap) return NULL; buf = ((char *)(nlmsg->nlmsghdr)) + nlmsg_len; nlmsg->nlmsghdr->nlmsg_len += tlen; if (tlen > len) memset(buf + len, 0, tlen - len); return buf; } extern struct nlmsg *nlmsg_alloc_reserve(size_t size) { struct nlmsg *nlmsg; nlmsg = nlmsg_alloc(size); if (!nlmsg) return NULL; // just set message length to cap directly nlmsg->nlmsghdr->nlmsg_len = nlmsg->cap; return nlmsg; } extern void nlmsg_free(struct nlmsg *nlmsg) { if (!nlmsg) return; free(nlmsg->nlmsghdr); free(nlmsg); } extern int netlink_rcv(struct nl_handler *handler, struct nlmsg *answer) { int ret; struct sockaddr_nl nladdr; struct iovec iov = { .iov_base = answer->nlmsghdr, .iov_len = answer->nlmsghdr->nlmsg_len, }; struct msghdr msg = { .msg_name = &nladdr, .msg_namelen = sizeof(nladdr), .msg_iov = &iov, .msg_iovlen = 1, }; memset(&nladdr, 0, sizeof(nladdr)); nladdr.nl_family = AF_NETLINK; nladdr.nl_pid = 0; nladdr.nl_groups = 0; again: ret = recvmsg(handler->fd, &msg, 0); if (ret < 0) { if (errno == EINTR) goto again; return -errno; } if (!ret) return 0; if (msg.msg_flags & MSG_TRUNC && ret == answer->nlmsghdr->nlmsg_len) return -EMSGSIZE; return ret; } extern int netlink_send(struct nl_handler *handler, struct nlmsg *nlmsg) { struct sockaddr_nl nladdr; struct iovec iov = { .iov_base = nlmsg->nlmsghdr, .iov_len = nlmsg->nlmsghdr->nlmsg_len, }; struct msghdr msg = { .msg_name = &nladdr, .msg_namelen = sizeof(nladdr), .msg_iov = &iov, .msg_iovlen = 1, }; int ret; memset(&nladdr, 0, sizeof(nladdr)); nladdr.nl_family = AF_NETLINK; nladdr.nl_pid = 0; nladdr.nl_groups = 0; ret = sendmsg(handler->fd, &msg, 0); if (ret < 0) return -errno; return ret; } #ifndef NLMSG_ERROR #define NLMSG_ERROR 0x2 #endif extern int netlink_transaction(struct nl_handler *handler, struct nlmsg *request, struct nlmsg *answer) { int ret; ret = netlink_send(handler, request); if (ret < 0) return ret; ret = netlink_rcv(handler, answer); if (ret < 0) return ret; if (answer->nlmsghdr->nlmsg_type == NLMSG_ERROR) { struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(answer->nlmsghdr); return err->error; } return 0; } extern int netlink_open(struct nl_handler *handler, int protocol) { socklen_t socklen; int sndbuf = 32768; int rcvbuf = 32768; int err; memset(handler, 0, sizeof(*handler)); handler->fd = socket(AF_NETLINK, SOCK_RAW, protocol); if (handler->fd < 0) return -errno; if (setsockopt(handler->fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) < 0) goto err_with_errno; if (setsockopt(handler->fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf,sizeof(rcvbuf)) < 0) goto err_with_errno; memset(&handler->local, 0, sizeof(handler->local)); handler->local.nl_family = AF_NETLINK; handler->local.nl_groups = 0; if (bind(handler->fd, (struct sockaddr*)&handler->local, sizeof(handler->local)) < 0) goto err_with_errno; socklen = sizeof(handler->local); if (getsockname(handler->fd, (struct sockaddr*)&handler->local, &socklen) < 0) goto err_with_errno; if (socklen != sizeof(handler->local)) { err = -EINVAL; goto errclose; } if (handler->local.nl_family != AF_NETLINK) { err = -EINVAL; goto errclose; } handler->seq = time(NULL); return 0; err_with_errno: err = -errno; errclose: close(handler->fd); return err; } extern int netlink_close(struct nl_handler *handler) { close(handler->fd); handler->fd = -1; return 0; } lxc-2.0.8/src/lxc/af_unix.c0000644061062106075000000001421513105116772012420 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include #include #include #include #include #include #include #include "log.h" lxc_log_define(lxc_af_unix, lxc); int lxc_abstract_unix_open(const char *path, int type, int flags) { int fd; size_t len; struct sockaddr_un addr; if (flags & O_TRUNC) unlink(path); fd = socket(PF_UNIX, type, 0); if (fd < 0) return -1; /* Clear address structure */ memset(&addr, 0, sizeof(addr)); if (!path) return fd; addr.sun_family = AF_UNIX; len = strlen(&path[1]); /* do not enforce \0-termination */ if (len >= sizeof(addr.sun_path)) { close(fd); errno = ENAMETOOLONG; return -1; } /* addr.sun_path[0] has already been set to 0 by memset() */ strncpy(&addr.sun_path[1], &path[1], strlen(&path[1])); if (bind(fd, (struct sockaddr *)&addr, offsetof(struct sockaddr_un, sun_path) + len + 1)) { int tmp = errno; close(fd); errno = tmp; return -1; } if (type == SOCK_STREAM && listen(fd, 100)) { int tmp = errno; close(fd); errno = tmp; return -1; } return fd; } int lxc_abstract_unix_close(int fd) { struct sockaddr_un addr; socklen_t addrlen = sizeof(addr); if (!getsockname(fd, (struct sockaddr *)&addr, &addrlen) && addr.sun_path[0]) unlink(addr.sun_path); close(fd); return 0; } int lxc_abstract_unix_connect(const char *path) { int fd; size_t len; struct sockaddr_un addr; fd = socket(PF_UNIX, SOCK_STREAM, 0); if (fd < 0) return -1; memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; len = strlen(&path[1]); /* do not enforce \0-termination */ if (len >= sizeof(addr.sun_path)) { close(fd); errno = ENAMETOOLONG; return -1; } /* addr.sun_path[0] has already been set to 0 by memset() */ strncpy(&addr.sun_path[1], &path[1], strlen(&path[1])); if (connect(fd, (struct sockaddr *)&addr, offsetof(struct sockaddr_un, sun_path) + len + 1)) { int tmp = errno; /* special case to connect to older containers */ if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == 0) return fd; close(fd); errno = tmp; return -1; } return fd; } int lxc_abstract_unix_send_fd(int fd, int sendfd, void *data, size_t size) { struct msghdr msg = { 0 }; struct iovec iov; struct cmsghdr *cmsg; char cmsgbuf[CMSG_SPACE(sizeof(int))] = {0}; char buf[1] = {0}; int *val; msg.msg_control = cmsgbuf; msg.msg_controllen = sizeof(cmsgbuf); cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_len = CMSG_LEN(sizeof(int)); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; val = (int *)(CMSG_DATA(cmsg)); *val = sendfd; msg.msg_name = NULL; msg.msg_namelen = 0; iov.iov_base = data ? data : buf; iov.iov_len = data ? size : sizeof(buf); msg.msg_iov = &iov; msg.msg_iovlen = 1; return sendmsg(fd, &msg, MSG_NOSIGNAL); } int lxc_abstract_unix_recv_fd(int fd, int *recvfd, void *data, size_t size) { struct msghdr msg = { 0 }; struct iovec iov; struct cmsghdr *cmsg; int ret, *val; char cmsgbuf[CMSG_SPACE(sizeof(int))] = {0}; char buf[1] = {0}; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_control = cmsgbuf; msg.msg_controllen = sizeof(cmsgbuf); iov.iov_base = data ? data : buf; iov.iov_len = data ? size : sizeof(buf); msg.msg_iov = &iov; msg.msg_iovlen = 1; ret = recvmsg(fd, &msg, 0); if (ret <= 0) goto out; cmsg = CMSG_FIRSTHDR(&msg); /* if the message is wrong the variable will not be * filled and the peer will notified about a problem */ *recvfd = -1; if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(int)) && cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { val = (int *) CMSG_DATA(cmsg); *recvfd = *val; } out: return ret; } int lxc_abstract_unix_send_credential(int fd, void *data, size_t size) { struct msghdr msg = { 0 }; struct iovec iov; struct cmsghdr *cmsg; struct ucred cred = { .pid = getpid(), .uid = getuid(), .gid = getgid(), }; char cmsgbuf[CMSG_SPACE(sizeof(cred))] = {0}; char buf[1] = {0}; msg.msg_control = cmsgbuf; msg.msg_controllen = sizeof(cmsgbuf); cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred)); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_CREDENTIALS; memcpy(CMSG_DATA(cmsg), &cred, sizeof(cred)); msg.msg_name = NULL; msg.msg_namelen = 0; iov.iov_base = data ? data : buf; iov.iov_len = data ? size : sizeof(buf); msg.msg_iov = &iov; msg.msg_iovlen = 1; return sendmsg(fd, &msg, MSG_NOSIGNAL); } int lxc_abstract_unix_rcv_credential(int fd, void *data, size_t size) { struct msghdr msg = { 0 }; struct iovec iov; struct cmsghdr *cmsg; struct ucred cred; int ret; char cmsgbuf[CMSG_SPACE(sizeof(cred))] = {0}; char buf[1] = {0}; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_control = cmsgbuf; msg.msg_controllen = sizeof(cmsgbuf); iov.iov_base = data ? data : buf; iov.iov_len = data ? size : sizeof(buf); msg.msg_iov = &iov; msg.msg_iovlen = 1; ret = recvmsg(fd, &msg, 0); if (ret <= 0) goto out; cmsg = CMSG_FIRSTHDR(&msg); if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)) && cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS) { memcpy(&cred, CMSG_DATA(cmsg), sizeof(cred)); if (cred.uid && (cred.uid != getuid() || cred.gid != getgid())) { INFO("message denied for '%d/%d'", cred.uid, cred.gid); return -EACCES; } } out: return ret; } lxc-2.0.8/src/lxc/lxc.functions.in0000644061062106075000000000210013105116772013736 00000000000000# # lxc: linux Container library # Authors: # Serge Hallyn # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # This file contains helpers for the various lxc shell scripts globalconf=@LXC_GLOBAL_CONF@ bindir=@BINDIR@ templatedir=@LXCTEMPLATEDIR@ lxcinitdir=@LXCINITDIR@ lxc_path=`lxc-config lxc.lxcpath` lxc_vg=`lxc-config lxc.bdev.lvm.vg` lxc_zfsroot=`lxc-config lxc.bdev.zfs.root` lxc-2.0.8/src/lxc/state.h0000644061062106075000000000253313105116772012114 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_STATE_H #define __LXC_STATE_H typedef enum { STOPPED, STARTING, RUNNING, STOPPING, ABORTING, FREEZING, FROZEN, THAWED, MAX_STATE, } lxc_state_t; extern int lxc_rmstate(const char *name); extern lxc_state_t lxc_getstate(const char *name, const char *lxcpath); extern lxc_state_t lxc_str2state(const char *state); extern const char *lxc_state2str(lxc_state_t state); extern int lxc_wait(const char *lxcname, const char *states, int timeout, const char *lxcpath); #endif lxc-2.0.8/src/lxc/namespace.h0000644061062106075000000000442413105116772012731 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2009 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_NAMESPACE_H #define __LXC_NAMESPACE_H #include #include #include "config.h" #ifndef CLONE_FS # define CLONE_FS 0x00000200 #endif #ifndef CLONE_NEWNS # define CLONE_NEWNS 0x00020000 #endif #ifndef CLONE_NEWCGROUP # define CLONE_NEWCGROUP 0x02000000 #endif #ifndef CLONE_NEWUTS # define CLONE_NEWUTS 0x04000000 #endif #ifndef CLONE_NEWIPC # define CLONE_NEWIPC 0x08000000 #endif #ifndef CLONE_NEWUSER # define CLONE_NEWUSER 0x10000000 #endif #ifndef CLONE_NEWPID # define CLONE_NEWPID 0x20000000 #endif #ifndef CLONE_NEWNET # define CLONE_NEWNET 0x40000000 #endif enum { LXC_NS_USER, LXC_NS_MNT, LXC_NS_PID, LXC_NS_UTS, LXC_NS_IPC, LXC_NS_NET, LXC_NS_CGROUP, LXC_NS_MAX }; extern const struct ns_info { const char *proc_name; int clone_flag; const char *flag_name; } ns_info[LXC_NS_MAX]; #if defined(__ia64__) int __clone2(int (*__fn) (void *__arg), void *__child_stack_base, size_t __child_stack_size, int __flags, void *__arg, ...); #else int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ... /* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ ); #endif extern pid_t lxc_clone(int (*fn)(void *), void *arg, int flags); extern int lxc_namespace_2_cloneflag(char *namespace); extern int lxc_fill_namespace_flags(char *flaglist, int *flags); #endif lxc-2.0.8/src/lxc/commands.h0000644061062106075000000000563013105116772012576 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2009 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_COMMANDS_H #define __LXC_COMMANDS_H #include "state.h" #define LXC_CMD_DATA_MAX (MAXPATHLEN * 2) /* https://developer.gnome.org/glib/2.28/glib-Type-Conversion-Macros.html */ #define INT_TO_PTR(n) ((void *)(long)(n)) #define PTR_TO_INT(p) ((int)(long)(p)) typedef enum { LXC_CMD_CONSOLE, LXC_CMD_CONSOLE_WINCH, LXC_CMD_STOP, LXC_CMD_GET_STATE, LXC_CMD_GET_INIT_PID, LXC_CMD_GET_CLONE_FLAGS, LXC_CMD_GET_CGROUP, LXC_CMD_GET_CONFIG_ITEM, LXC_CMD_GET_NAME, LXC_CMD_GET_LXCPATH, LXC_CMD_MAX, } lxc_cmd_t; struct lxc_cmd_req { lxc_cmd_t cmd; int datalen; const void *data; }; struct lxc_cmd_rsp { int ret; /* 0 on success, -errno on failure */ int datalen; void *data; }; struct lxc_cmd_rr { struct lxc_cmd_req req; struct lxc_cmd_rsp rsp; }; struct lxc_cmd_console_rsp_data { int masterfd; int ttynum; }; extern int lxc_cmd_console_winch(const char *name, const char *lxcpath); extern int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath); /* * Get the 'real' cgroup path (as seen in /proc/self/cgroup) for a container * for a particular subsystem */ extern char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath, const char *subsystem); extern int lxc_cmd_get_clone_flags(const char *name, const char *lxcpath); extern char *lxc_cmd_get_config_item(const char *name, const char *item, const char *lxcpath); extern char *lxc_cmd_get_name(const char *hashed_sock); extern char *lxc_cmd_get_lxcpath(const char *hashed_sock); extern pid_t lxc_cmd_get_init_pid(const char *name, const char *lxcpath); extern lxc_state_t lxc_cmd_get_state(const char *name, const char *lxcpath); extern int lxc_cmd_stop(const char *name, const char *lxcpath); struct lxc_epoll_descr; struct lxc_handler; extern int lxc_cmd_init(const char *name, struct lxc_handler *handler, const char *lxcpath); extern int lxc_cmd_mainloop_add(const char *name, struct lxc_epoll_descr *descr, struct lxc_handler *handler); extern int lxc_try_cmd(const char *name, const char *lxcpath); #endif /* __commands_h */ lxc-2.0.8/src/lxc/sync.c0000644061062106075000000000657113105116772011751 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include "sync.h" #include "log.h" #include "start.h" lxc_log_define(lxc_sync, lxc); static int __sync_wait(int fd, int sequence) { int sync = -1; ssize_t ret; ret = read(fd, &sync, sizeof(sync)); if (ret < 0) { ERROR("sync wait failure : %m"); return -1; } if (!ret) return 0; if ((size_t)ret != sizeof(sync)) { ERROR("unexpected sync size: %zu expected %zu", (size_t)ret, sizeof(sync)); return -1; } if (sync == LXC_SYNC_ERROR) { ERROR("An error occurred in another process " "(expected sequence number %d)", sequence); return -1; } if (sync != sequence) { ERROR("invalid sequence number %d. expected %d", sync, sequence); return -1; } return 0; } static int __sync_wake(int fd, int sequence) { int sync = sequence; if (write(fd, &sync, sizeof(sync)) < 0) { ERROR("sync wake failure : %m"); return -1; } return 0; } static int __sync_barrier(int fd, int sequence) { if (__sync_wake(fd, sequence)) return -1; return __sync_wait(fd, sequence+1); } int lxc_sync_barrier_parent(struct lxc_handler *handler, int sequence) { return __sync_barrier(handler->sv[0], sequence); } int lxc_sync_barrier_child(struct lxc_handler *handler, int sequence) { return __sync_barrier(handler->sv[1], sequence); } int lxc_sync_wake_parent(struct lxc_handler *handler, int sequence) { return __sync_wake(handler->sv[0], sequence); } int lxc_sync_wait_parent(struct lxc_handler *handler, int sequence) { return __sync_wait(handler->sv[0], sequence); } int lxc_sync_wait_child(struct lxc_handler *handler, int sequence) { return __sync_wait(handler->sv[1], sequence); } int lxc_sync_wake_child(struct lxc_handler *handler, int sequence) { return __sync_wake(handler->sv[1], sequence); } int lxc_sync_init(struct lxc_handler *handler) { int ret; ret = socketpair(AF_LOCAL, SOCK_STREAM, 0, handler->sv); if (ret) { SYSERROR("failed to create synchronization socketpair"); return -1; } /* Be sure we don't inherit this after the exec */ fcntl(handler->sv[0], F_SETFD, FD_CLOEXEC); return 0; } void lxc_sync_fini_child(struct lxc_handler *handler) { if (handler->sv[0] != -1) { close(handler->sv[0]); handler->sv[0] = -1; } } void lxc_sync_fini_parent(struct lxc_handler *handler) { if (handler->sv[1] != -1) { close(handler->sv[1]); handler->sv[1] = -1; } } void lxc_sync_fini(struct lxc_handler *handler) { lxc_sync_fini_child(handler); lxc_sync_fini_parent(handler); } lxc-2.0.8/src/lxc/bdev/0000755061062106075000000000000013105117015011607 500000000000000lxc-2.0.8/src/lxc/bdev/lxcaufs.c0000644061062106075000000002445513105116772013363 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #include #include #include #include #include #include "bdev.h" #include "log.h" #include "lxcaufs.h" #include "lxcrsync.h" #include "utils.h" lxc_log_define(lxcaufs, lxc); /* the bulk of this needs to become a common helper */ extern char *dir_new_path(char *src, const char *oldname, const char *name, const char *oldpath, const char *lxcpath); int aufs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, int snap, uint64_t newsize, struct lxc_conf *conf) { if (!snap) { ERROR("aufs is only for snapshot clones"); return -22; } if (!orig->src || !orig->dest) return -1; new->dest = dir_new_path(orig->dest, oldname, cname, oldpath, lxcpath); if (!new->dest) return -1; if (mkdir_p(new->dest, 0755) < 0) return -1; if (am_unpriv() && chown_mapped_root(new->dest, conf) < 0) WARN("Failed to update ownership of %s", new->dest); if (strcmp(orig->type, "dir") == 0) { char *delta, *lastslash; int ret, len, lastslashidx; // if we have /var/lib/lxc/c2/rootfs, then delta will be // /var/lib/lxc/c2/delta0 lastslash = strrchr(new->dest, '/'); if (!lastslash) return -22; if (strlen(lastslash) < 7) return -22; lastslash++; lastslashidx = lastslash - new->dest; delta = malloc(lastslashidx + 7); if (!delta) return -1; strncpy(delta, new->dest, lastslashidx+1); strcpy(delta+lastslashidx, "delta0"); if ((ret = mkdir(delta, 0755)) < 0) { SYSERROR("error: mkdir %s", delta); free(delta); return -1; } if (am_unpriv() && chown_mapped_root(delta, conf) < 0) WARN("Failed to update ownership of %s", delta); // the src will be 'aufs:lowerdir:upperdir' len = strlen(delta) + strlen(orig->src) + 12; new->src = malloc(len); if (!new->src) { free(delta); return -ENOMEM; } ret = snprintf(new->src, len, "aufs:%s:%s", orig->src, delta); free(delta); if (ret < 0 || ret >= len) return -ENOMEM; } else if (strcmp(orig->type, "aufs") == 0) { // What exactly do we want to do here? // I think we want to use the original lowerdir, with a // private delta which is originally rsynced from the // original delta char *osrc, *odelta, *nsrc, *ndelta; int len, ret; if (!(osrc = strdup(orig->src))) return -22; nsrc = strchr(osrc, ':') + 1; if (nsrc != osrc + 5 || (odelta = strchr(nsrc, ':')) == NULL) { free(osrc); return -22; } *odelta = '\0'; odelta++; ndelta = dir_new_path(odelta, oldname, cname, oldpath, lxcpath); if (!ndelta) { free(osrc); return -ENOMEM; } if ((ret = mkdir(ndelta, 0755)) < 0 && errno != EEXIST) { SYSERROR("error: mkdir %s", ndelta); free(osrc); free(ndelta); return -1; } if (am_unpriv() && chown_mapped_root(ndelta, conf) < 0) WARN("Failed to update ownership of %s", ndelta); struct rsync_data_char rdata; rdata.src = odelta; rdata.dest = ndelta; if (am_unpriv()) ret = userns_exec_1(conf, rsync_delta_wrapper, &rdata); else ret = rsync_delta(&rdata); if (ret) { free(osrc); free(ndelta); ERROR("copying aufs delta"); return -1; } len = strlen(nsrc) + strlen(ndelta) + 12; new->src = malloc(len); if (!new->src) { free(osrc); free(ndelta); return -ENOMEM; } ret = snprintf(new->src, len, "aufs:%s:%s", nsrc, ndelta); free(osrc); free(ndelta); if (ret < 0 || ret >= len) return -ENOMEM; } else { ERROR("aufs clone of %s container is not yet supported", orig->type); // Note, supporting this will require aufs_mount supporting // mounting of the underlay. No big deal, just needs to be done. return -1; } return 0; } /* * to say 'lxc-create -t ubuntu -n o1 -B aufs' means you want * $lxcpath/$lxcname/rootfs to have the created container, while all * changes after starting the container are written to * $lxcpath/$lxcname/delta0 */ int aufs_create(struct bdev *bdev, const char *dest, const char *n, struct bdev_specs *specs) { char *delta; int ret, len = strlen(dest), newlen; if (len < 8 || strcmp(dest+len-7, "/rootfs") != 0) return -1; if (!(bdev->dest = strdup(dest))) { ERROR("Out of memory"); return -1; } delta = alloca(strlen(dest)+1); strcpy(delta, dest); strcpy(delta+len-6, "delta0"); if (mkdir_p(delta, 0755) < 0) { ERROR("Error creating %s", delta); return -1; } /* aufs:lower:upper */ newlen = (2 * len) + strlen("aufs:") + 2; bdev->src = malloc(newlen); if (!bdev->src) { ERROR("Out of memory"); return -1; } ret = snprintf(bdev->src, newlen, "aufs:%s:%s", dest, delta); if (ret < 0 || ret >= newlen) return -1; if (mkdir_p(bdev->dest, 0755) < 0) { ERROR("Error creating %s", bdev->dest); return -1; } return 0; } int aufs_destroy(struct bdev *orig) { char *upper; if (strncmp(orig->src, "aufs:", 5) != 0) return -22; upper = strchr(orig->src + 5, ':'); if (!upper) return -22; upper++; return lxc_rmdir_onedev(upper, NULL); } int aufs_detect(const char *path) { if (strncmp(path, "aufs:", 5) == 0) return 1; // take their word for it return 0; } int aufs_mount(struct bdev *bdev) { char *tmp, *options, *dup, *lower, *upper; int len; unsigned long mntflags; char *mntdata; int ret; const char *xinopath = "/dev/shm/aufs.xino"; if (strcmp(bdev->type, "aufs")) return -22; if (!bdev->src || !bdev->dest) return -22; // separately mount it first // mount -t aufs -obr=${upper}=rw:${lower}=ro lower dest dup = alloca(strlen(bdev->src)+1); strcpy(dup, bdev->src); /* support multiple lower layers */ if (!(lower = strstr(dup, ":/"))) return -22; lower++; upper = lower; while ((tmp = strstr(++upper, ":/"))) { upper = tmp; } if (--upper == lower) return -22; *upper = '\0'; upper++; if (parse_mntopts(bdev->mntopts, &mntflags, &mntdata) < 0) { free(mntdata); return -22; } // TODO We should check whether bdev->src is a blockdev, and if so // but for now, only support aufs of a basic directory // AUFS does not work on top of certain filesystems like (XFS or Btrfs) // so add xino=/dev/shm/aufs.xino parameter to mount options. // The same xino option can be specified to multiple aufs mounts, and // a xino file is not shared among multiple aufs mounts. // // see http://www.mail-archive.com/aufs-users@lists.sourceforge.net/msg02587.html // http://www.mail-archive.com/aufs-users@lists.sourceforge.net/msg05126.html if (mntdata) { len = strlen(lower) + strlen(upper) + strlen(xinopath) + strlen("br==rw:=ro,,xino=") + strlen(mntdata) + 1; options = alloca(len); ret = snprintf(options, len, "br=%s=rw:%s=ro,%s,xino=%s", upper, lower, mntdata, xinopath); } else { len = strlen(lower) + strlen(upper) + strlen(xinopath) + strlen("br==rw:=ro,xino=") + 1; options = alloca(len); ret = snprintf(options, len, "br=%s=rw:%s=ro,xino=%s", upper, lower, xinopath); } if (ret < 0 || ret >= len) { free(mntdata); return -1; } ret = mount(lower, bdev->dest, "aufs", MS_MGC_VAL | mntflags, options); if (ret < 0) SYSERROR("aufs: error mounting %s onto %s options %s", lower, bdev->dest, options); else INFO("aufs: mounted %s onto %s options %s", lower, bdev->dest, options); return ret; } int aufs_umount(struct bdev *bdev) { if (strcmp(bdev->type, "aufs")) return -22; if (!bdev->src || !bdev->dest) return -22; return umount(bdev->dest); } char *aufs_get_rootfs(const char *rootfs_path, size_t *rootfslen) { char *rootfsdir = NULL; char *s1 = NULL; char *s2 = NULL; char *s3 = NULL; if (!rootfs_path || !rootfslen) return NULL; s1 = strdup(rootfs_path); if (!s1) return NULL; if ((s2 = strstr(s1, ":/"))) { s2 = s2 + 1; if ((s3 = strstr(s2, ":/"))) *s3 = '\0'; rootfsdir = strdup(s2); if (!rootfsdir) { free(s1); return NULL; } } if (!rootfsdir) rootfsdir = s1; else free(s1); *rootfslen = strlen(rootfsdir); return rootfsdir; } int aufs_mkdir(const struct mntent *mntent, const struct lxc_rootfs *rootfs, const char *lxc_name, const char *lxc_path) { char lxcpath[MAXPATHLEN]; char *rootfs_path = NULL; char *rootfsdir = NULL; char *scratch = NULL; char *tmp = NULL; char *upperdir = NULL; char **opts = NULL; int fret = -1; int ret = 0; size_t arrlen = 0; size_t i; size_t len = 0; size_t rootfslen = 0; /* When rootfs == NULL we have a container without a rootfs. */ if (rootfs && rootfs->path) rootfs_path = rootfs->path; opts = lxc_string_split(mntent->mnt_opts, ','); if (opts) arrlen = lxc_array_len((void **)opts); else goto err; for (i = 0; i < arrlen; i++) { if (strstr(opts[i], "br=") && (strlen(opts[i]) > (len = strlen("br=")))) tmp = opts[i] + len; } if (!tmp) goto err; upperdir = strtok_r(tmp, ":=", &scratch); if (!upperdir) goto err; if (rootfs_path) { ret = snprintf(lxcpath, MAXPATHLEN, "%s/%s", lxc_path, lxc_name); if (ret < 0 || ret >= MAXPATHLEN) goto err; rootfsdir = aufs_get_rootfs(rootfs->path, &rootfslen); if (!rootfsdir) goto err; } /* * We neither allow users to create upperdirs and workdirs outside the * containerdir nor inside the rootfs. The latter might be debatable. * When we have a container without a rootfs we skip the checks. */ ret = 0; if (!rootfs_path) ret = mkdir_p(upperdir, 0755); else if ((strncmp(upperdir, lxcpath, strlen(lxcpath)) == 0) && (strncmp(upperdir, rootfsdir, rootfslen) != 0)) ret = mkdir_p(upperdir, 0755); if (ret < 0) WARN("Failed to create upperdir"); fret = 0; err: free(rootfsdir); lxc_free_array((void **)opts, free); return fret; } lxc-2.0.8/src/lxc/bdev/lxcloop.h0000644061062106075000000000311613105116772013372 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_LOOP_H #define __LXC_LOOP_H #define _GNU_SOURCE #include /* defined in bdev.h */ struct bdev; /* defined in lxccontainer.h */ struct bdev_specs; /* defined conf.h */ struct lxc_conf; /* * functions associated with a loop bdev struct */ int loop_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, int snap, uint64_t newsize, struct lxc_conf *conf); int loop_create(struct bdev *bdev, const char *dest, const char *n, struct bdev_specs *specs); int loop_destroy(struct bdev *orig); int loop_detect(const char *path); int loop_mount(struct bdev *bdev); int loop_umount(struct bdev *bdev); #endif /* __LXC_LOOP_H */ lxc-2.0.8/src/lxc/bdev/lxczfs.h0000644061062106075000000000367613105116772013236 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_ZFS_H #define __LXC_ZFS_H #define _GNU_SOURCE #include #include /* defined in bdev.h */ struct bdev; /* defined in lxccontainer.h */ struct bdev_specs; /* defined conf.h */ struct lxc_conf; /* * Functions associated with an zfs bdev struct. */ int zfs_clone(const char *opath, const char *npath, const char *oname, const char *nname, const char *lxcpath, int snapshot); int zfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, int snap, uint64_t newsize, struct lxc_conf *conf); int zfs_create(struct bdev *bdev, const char *dest, const char *n, struct bdev_specs *specs); /* * TODO: detect whether this was a clone, and if so then also delete the * snapshot it was based on, so that we don't hold the original * container busy. */ int zfs_destroy(struct bdev *orig); int zfs_detect(const char *path); int zfs_list_entry(const char *path, char *output, size_t inlen); int zfs_mount(struct bdev *bdev); int zfs_umount(struct bdev *bdev); #endif /* __LXC_ZFS_H */ lxc-2.0.8/src/lxc/bdev/lxcrsync.h0000644061062106075000000000245513105116772013564 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_RSYNC_H #define __LXC_RSYNC_H #define _GNU_SOURCE #include struct rsync_data { struct bdev *orig; struct bdev *new; }; struct rsync_data_char { char *src; char *dest; }; int do_rsync(const char *src, const char *dest); int rsync_delta_wrapper(void *data); int rsync_delta(struct rsync_data_char *data); int rsync_rootfs(struct rsync_data *data); int rsync_rootfs_wrapper(void *data); #endif // __LXC_RSYNC_H lxc-2.0.8/src/lxc/bdev/lxclvm.c0000644061062106075000000002333313105116772013215 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */ #include /* Required for PRIu64 to work. */ #include #include #include #include #include #include #include #include "bdev.h" #include "config.h" #include "log.h" #include "lxclvm.h" #include "utils.h" /* major()/minor() */ #ifdef MAJOR_IN_MKDEV # include #endif lxc_log_define(lxclvm, lxc); extern char *dir_new_path(char *src, const char *oldname, const char *name, const char *oldpath, const char *lxcpath); /* * LVM ops */ /* * path must be '/dev/$vg/$lv', $vg must be an existing VG, and $lv must not * yet exist. This function will attempt to create /dev/$vg/$lv of size * $size. If thinpool is specified, we'll check for it's existence and if * it's * a valid thin pool, and if so, we'll create the requested lv from that * thin * pool. */ static int do_lvm_create(const char *path, uint64_t size, const char *thinpool) { int ret, pid, len; char sz[24], *pathdup, *vg, *lv, *tp = NULL; if ((pid = fork()) < 0) { SYSERROR("failed fork"); return -1; } if (pid > 0) return wait_for_pid(pid); // specify bytes to lvcreate ret = snprintf(sz, 24, "%"PRIu64"b", size); if (ret < 0 || ret >= 24) exit(EXIT_FAILURE); pathdup = strdup(path); if (!pathdup) exit(EXIT_FAILURE); lv = strrchr(pathdup, '/'); if (!lv) exit(EXIT_FAILURE); *lv = '\0'; lv++; vg = strrchr(pathdup, '/'); if (!vg) exit(EXIT_FAILURE); vg++; if (thinpool) { len = strlen(pathdup) + strlen(thinpool) + 2; tp = alloca(len); ret = snprintf(tp, len, "%s/%s", pathdup, thinpool); if (ret < 0 || ret >= len) exit(EXIT_FAILURE); ret = lvm_is_thin_pool(tp); INFO("got %d for thin pool at path: %s", ret, tp); if (ret < 0) exit(EXIT_FAILURE); if (!ret) tp = NULL; } (void)setenv("LVM_SUPPRESS_FD_WARNINGS", "1", 1); if (!tp) execlp("lvcreate", "lvcreate", "-L", sz, vg, "-n", lv, (char *)NULL); else execlp("lvcreate", "lvcreate", "--thinpool", tp, "-V", sz, vg, "-n", lv, (char *)NULL); SYSERROR("execlp"); exit(EXIT_FAILURE); } /* * Look at /sys/dev/block/maj:min/dm/uuid. If it contains the hardcoded LVM * prefix "LVM-", then this is an lvm2 LV */ int lvm_detect(const char *path) { char devp[MAXPATHLEN], buf[4]; FILE *fout; int ret; struct stat statbuf; if (strncmp(path, "lvm:", 4) == 0) return 1; // take their word for it ret = stat(path, &statbuf); if (ret != 0) return 0; if (!S_ISBLK(statbuf.st_mode)) return 0; ret = snprintf(devp, MAXPATHLEN, "/sys/dev/block/%d:%d/dm/uuid", major(statbuf.st_rdev), minor(statbuf.st_rdev)); if (ret < 0 || ret >= MAXPATHLEN) { ERROR("lvm uuid pathname too long"); return 0; } fout = fopen(devp, "r"); if (!fout) return 0; ret = fread(buf, 1, 4, fout); fclose(fout); if (ret != 4 || strncmp(buf, "LVM-", 4) != 0) return 0; return 1; } int lvm_mount(struct bdev *bdev) { if (strcmp(bdev->type, "lvm")) return -22; if (!bdev->src || !bdev->dest) return -22; /* if we might pass in data sometime, then we'll have to enrich * mount_unknown_fs */ return mount_unknown_fs(bdev->src, bdev->dest, bdev->mntopts); } int lvm_umount(struct bdev *bdev) { if (strcmp(bdev->type, "lvm")) return -22; if (!bdev->src || !bdev->dest) return -22; return umount(bdev->dest); } int lvm_compare_lv_attr(const char *path, int pos, const char expected) { struct lxc_popen_FILE *f; int ret, len, status, start=0; char *cmd, output[12]; const char *lvscmd = "lvs --unbuffered --noheadings -o lv_attr %s 2>/dev/null"; len = strlen(lvscmd) + strlen(path) - 1; cmd = alloca(len); ret = snprintf(cmd, len, lvscmd, path); if (ret < 0 || ret >= len) return -1; f = lxc_popen(cmd); if (f == NULL) { SYSERROR("popen failed"); return -1; } ret = fgets(output, 12, f->f) == NULL; status = lxc_pclose(f); if (ret || WEXITSTATUS(status)) // Assume either vg or lvs do not exist, default // comparison to false. return 0; len = strlen(output); while(start < len && output[start] == ' ') start++; if (start + pos < len && output[start + pos] == expected) return 1; return 0; } int lvm_is_thin_volume(const char *path) { return lvm_compare_lv_attr(path, 6, 't'); } int lvm_is_thin_pool(const char *path) { return lvm_compare_lv_attr(path, 0, 't'); } int lvm_snapshot(const char *orig, const char *path, uint64_t size) { int ret, pid; char sz[24], *pathdup, *lv; if ((pid = fork()) < 0) { SYSERROR("failed fork"); return -1; } if (pid > 0) return wait_for_pid(pid); // specify bytes to lvcreate ret = snprintf(sz, 24, "%"PRIu64"b", size); if (ret < 0 || ret >= 24) exit(EXIT_FAILURE); pathdup = strdup(path); if (!pathdup) exit(EXIT_FAILURE); lv = strrchr(pathdup, '/'); if (!lv) { free(pathdup); exit(EXIT_FAILURE); } *lv = '\0'; lv++; // check if the original lv is backed by a thin pool, in which case we // cannot specify a size that's different from the original size. ret = lvm_is_thin_volume(orig); if (ret == -1) { free(pathdup); return -1; } (void)setenv("LVM_SUPPRESS_FD_WARNINGS", "1", 1); if (!ret) { ret = execlp("lvcreate", "lvcreate", "-s", "-L", sz, "-n", lv, orig, (char *)NULL); } else { ret = execlp("lvcreate", "lvcreate", "-s", "-n", lv, orig, (char *)NULL); } free(pathdup); exit(EXIT_FAILURE); } int lvm_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, int snap, uint64_t newsize, struct lxc_conf *conf) { char fstype[100]; uint64_t size = newsize; int len, ret; if (!orig->src || !orig->dest) return -1; if (strcmp(orig->type, "lvm")) { const char *vg; if (snap) { ERROR("LVM snapshot from %s backing store is not supported", orig->type); return -1; } vg = lxc_global_config_value("lxc.bdev.lvm.vg"); len = strlen("/dev/") + strlen(vg) + strlen(cname) + 2; if ((new->src = malloc(len)) == NULL) return -1; ret = snprintf(new->src, len, "/dev/%s/%s", vg, cname); if (ret < 0 || ret >= len) return -1; } else { new->src = dir_new_path(orig->src, oldname, cname, oldpath, lxcpath); if (!new->src) return -1; } if (orig->mntopts) { new->mntopts = strdup(orig->mntopts); if (!new->mntopts) return -1; } len = strlen(lxcpath) + strlen(cname) + strlen("rootfs") + 3; new->dest = malloc(len); if (!new->dest) return -1; ret = snprintf(new->dest, len, "%s/%s/rootfs", lxcpath, cname); if (ret < 0 || ret >= len) return -1; if (mkdir_p(new->dest, 0755) < 0) return -1; if (is_blktype(orig)) { if (!newsize && blk_getsize(orig, &size) < 0) { ERROR("Error getting size of %s", orig->src); return -1; } if (detect_fs(orig, fstype, 100) < 0) { INFO("could not find fstype for %s, using ext3", orig->src); return -1; } } else { sprintf(fstype, "ext3"); if (!newsize) size = DEFAULT_FS_SIZE; } if (snap) { if (lvm_snapshot(orig->src, new->src, size) < 0) { ERROR("could not create %s snapshot of %s", new->src, orig->src); return -1; } } else { if (do_lvm_create(new->src, size, lxc_global_config_value("lxc.bdev.lvm.thin_pool")) < 0) { ERROR("Error creating new lvm blockdev"); return -1; } if (do_mkfs(new->src, fstype) < 0) { ERROR("Error creating filesystem type %s on %s", fstype, new->src); return -1; } } return 0; } int lvm_destroy(struct bdev *orig) { pid_t pid; if ((pid = fork()) < 0) return -1; if (!pid) { (void)setenv("LVM_SUPPRESS_FD_WARNINGS", "1", 1); execlp("lvremove", "lvremove", "-f", orig->src, (char *)NULL); exit(EXIT_FAILURE); } return wait_for_pid(pid); } int lvm_create(struct bdev *bdev, const char *dest, const char *n, struct bdev_specs *specs) { const char *vg, *thinpool, *fstype, *lv = n; uint64_t sz; int ret, len; if (!specs) return -1; vg = specs->lvm.vg; if (!vg) vg = lxc_global_config_value("lxc.bdev.lvm.vg"); thinpool = specs->lvm.thinpool; if (!thinpool) thinpool = lxc_global_config_value("lxc.bdev.lvm.thin_pool"); /* /dev/$vg/$lv */ if (specs->lvm.lv) lv = specs->lvm.lv; len = strlen(vg) + strlen(lv) + 7; bdev->src = malloc(len); if (!bdev->src) return -1; ret = snprintf(bdev->src, len, "/dev/%s/%s", vg, lv); if (ret < 0 || ret >= len) return -1; // fssize is in bytes. sz = specs->fssize; if (!sz) sz = DEFAULT_FS_SIZE; if (do_lvm_create(bdev->src, sz, thinpool) < 0) { ERROR("Error creating new lvm blockdev %s size %"PRIu64" bytes", bdev->src, sz); return -1; } fstype = specs->fstype; if (!fstype) fstype = DEFAULT_FSTYPE; if (do_mkfs(bdev->src, fstype) < 0) { ERROR("Error creating filesystem type %s on %s", fstype, bdev->src); return -1; } if (!(bdev->dest = strdup(dest))) return -1; if (mkdir_p(bdev->dest, 0755) < 0) { ERROR("Error creating %s", bdev->dest); return -1; } return 0; } lxc-2.0.8/src/lxc/bdev/lxcdir.h0000644061062106075000000000310513105116772013175 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_DIR_H #define __LXC_DIR_H #define _GNU_SOURCE #include /* defined in bdev.h */ struct bdev; /* defined in lxccontainer.h */ struct bdev_specs; /* defined conf.h */ struct lxc_conf; /* * Functions associated with a dir bdev struct. */ int dir_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, int snap, uint64_t newsize, struct lxc_conf *conf); int dir_create(struct bdev *bdev, const char *dest, const char *n, struct bdev_specs *specs); int dir_destroy(struct bdev *orig); int dir_detect(const char *path); int dir_mount(struct bdev *bdev); int dir_umount(struct bdev *bdev); #endif /* __LXC_DIR_H */ lxc-2.0.8/src/lxc/bdev/lxcbtrfs.c0000644061062106075000000004103413105116772013535 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include "bdev.h" #include "log.h" #include "lxcbtrfs.h" #include "lxcrsync.h" #include "utils.h" lxc_log_define(lxcbtrfs, lxc); /* defined in lxccontainer.c: needs to become common helper */ extern char *dir_new_path(char *src, const char *oldname, const char *name, const char *oldpath, const char *lxcpath); /* * Return the full path of objid under dirid. Let's say dirid is * /lxc/c1/rootfs, and objid is /lxc/c1/rootfs/a/b/c. Then we will * return a/b/c. If instead objid is for /lxc/c1/rootfs/a, we will * simply return a. */ char *get_btrfs_subvol_path(int fd, u64 dir_id, u64 objid, char *name, int name_len) { struct btrfs_ioctl_ino_lookup_args args; int ret, e; size_t len; char *retpath; memset(&args, 0, sizeof(args)); args.treeid = dir_id; args.objectid = objid; ret = ioctl(fd, BTRFS_IOC_INO_LOOKUP, &args); e = errno; if (ret) { ERROR("%s: ERROR: Failed to lookup path for %llu %llu %s - %s\n", __func__, (unsigned long long) dir_id, (unsigned long long) objid, name, strerror(e)); return NULL; } else INFO("%s: got path for %llu %llu - %s\n", __func__, (unsigned long long) objid, (unsigned long long) dir_id, name); if (args.name[0]) { /* * we're in a subdirectory of ref_tree, the kernel ioctl * puts a / in there for us */ len = strlen(args.name) + name_len + 2; retpath = malloc(len); if (!retpath) return NULL; strcpy(retpath, args.name); strcat(retpath, "/"); strncat(retpath, name, name_len); } else { /* we're at the root of ref_tree */ len = name_len + 1; retpath = malloc(len); if (!retpath) return NULL; *retpath = '\0'; strncat(retpath, name, name_len); } return retpath; } // // btrfs ops // int btrfs_list_get_path_rootid(int fd, u64 *treeid) { int ret; struct btrfs_ioctl_ino_lookup_args args; memset(&args, 0, sizeof(args)); args.objectid = BTRFS_FIRST_FREE_OBJECTID; ret = ioctl(fd, BTRFS_IOC_INO_LOOKUP, &args); if (ret < 0) { WARN("Warning: can't perform the search -%s\n", strerror(errno)); return ret; } *treeid = args.treeid; return 0; } bool is_btrfs_fs(const char *path) { int fd, ret; struct btrfs_ioctl_space_args sargs; // make sure this is a btrfs filesystem fd = open(path, O_RDONLY); if (fd < 0) return false; sargs.space_slots = 0; sargs.total_spaces = 0; ret = ioctl(fd, BTRFS_IOC_SPACE_INFO, &sargs); close(fd); if (ret < 0) return false; return true; } /* * Taken from btrfs toolsuite. Test if path is a subvolume. * return 0; path exists but it is not a subvolume * return 1; path exists and it is a subvolume * return < 0; error */ int is_btrfs_subvol(const char *path) { struct stat st; struct statfs stfs; int ret; ret = stat(path, &st); if (ret < 0) return -errno; if (st.st_ino != BTRFS_FIRST_FREE_OBJECTID || !S_ISDIR(st.st_mode)) return 0; ret = statfs(path, &stfs); if (ret < 0) return -errno; return stfs.f_type == BTRFS_SUPER_MAGIC; } int btrfs_detect(const char *path) { struct stat st; int ret; if (!is_btrfs_fs(path)) return 0; // and make sure it's a subvolume. ret = stat(path, &st); if (ret < 0) return 0; if (st.st_ino == 256 && S_ISDIR(st.st_mode)) return 1; return 0; } int btrfs_mount(struct bdev *bdev) { unsigned long mntflags; char *mntdata; int ret; if (strcmp(bdev->type, "btrfs")) return -22; if (!bdev->src || !bdev->dest) return -22; if (parse_mntopts(bdev->mntopts, &mntflags, &mntdata) < 0) { free(mntdata); return -22; } ret = mount(bdev->src, bdev->dest, "bind", MS_BIND | MS_REC | mntflags, mntdata); free(mntdata); return ret; } int btrfs_umount(struct bdev *bdev) { if (strcmp(bdev->type, "btrfs")) return -22; if (!bdev->src || !bdev->dest) return -22; return umount(bdev->dest); } static int btrfs_subvolume_create(const char *path) { int ret, fd = -1; struct btrfs_ioctl_vol_args args; char *p, *newfull = strdup(path); if (!newfull) { ERROR("Error: out of memory"); return -1; } p = strrchr(newfull, '/'); if (!p) { ERROR("bad path: %s", path); free(newfull); return -1; } *p = '\0'; fd = open(newfull, O_RDONLY); if (fd < 0) { ERROR("Error opening %s", newfull); free(newfull); return -1; } memset(&args, 0, sizeof(args)); strncpy(args.name, p+1, BTRFS_SUBVOL_NAME_MAX); args.name[BTRFS_SUBVOL_NAME_MAX-1] = 0; ret = ioctl(fd, BTRFS_IOC_SUBVOL_CREATE, &args); INFO("btrfs: snapshot create ioctl returned %d", ret); free(newfull); close(fd); return ret; } int btrfs_same_fs(const char *orig, const char *new) { int fd_orig = -1, fd_new = -1, ret = -1; struct btrfs_ioctl_fs_info_args orig_args, new_args; fd_orig = open(orig, O_RDONLY); if (fd_orig < 0) { SYSERROR("Error opening original rootfs %s", orig); goto out; } ret = ioctl(fd_orig, BTRFS_IOC_FS_INFO, &orig_args); if (ret < 0) { SYSERROR("BTRFS_IOC_FS_INFO %s", orig); goto out; } fd_new = open(new, O_RDONLY); if (fd_new < 0) { SYSERROR("Error opening new container dir %s", new); ret = -1; goto out; } ret = ioctl(fd_new, BTRFS_IOC_FS_INFO, &new_args); if (ret < 0) { SYSERROR("BTRFS_IOC_FS_INFO %s", new); goto out; } if (strncmp(orig_args.fsid, new_args.fsid, BTRFS_FSID_SIZE) != 0) { ret = -1; goto out; } ret = 0; out: if (fd_new != -1) close(fd_new); if (fd_orig != -1) close(fd_orig); return ret; } int btrfs_snapshot(const char *orig, const char *new) { int fd = -1, fddst = -1, ret = -1; struct btrfs_ioctl_vol_args_v2 args; char *newdir, *newname, *newfull = NULL; newfull = strdup(new); if (!newfull) { ERROR("Error: out of memory"); goto out; } // make sure the directory doesn't already exist if (rmdir(newfull) < 0 && errno != ENOENT) { SYSERROR("Error removing empty new rootfs"); goto out; } newname = basename(newfull); newdir = dirname(newfull); fd = open(orig, O_RDONLY); if (fd < 0) { SYSERROR("Error opening original rootfs %s", orig); goto out; } fddst = open(newdir, O_RDONLY); if (fddst < 0) { SYSERROR("Error opening new container dir %s", newdir); goto out; } memset(&args, 0, sizeof(args)); args.fd = fd; strncpy(args.name, newname, BTRFS_SUBVOL_NAME_MAX); args.name[BTRFS_SUBVOL_NAME_MAX-1] = 0; ret = ioctl(fddst, BTRFS_IOC_SNAP_CREATE_V2, &args); INFO("btrfs: snapshot create ioctl returned %d", ret); out: if (fddst != -1) close(fddst); if (fd != -1) close(fd); free(newfull); return ret; } static int btrfs_snapshot_wrapper(void *data) { struct rsync_data_char *arg = data; if (setgid(0) < 0) { ERROR("Failed to setgid to 0"); return -1; } if (setgroups(0, NULL) < 0) WARN("Failed to clear groups"); if (setuid(0) < 0) { ERROR("Failed to setuid to 0"); return -1; } return btrfs_snapshot(arg->src, arg->dest); } int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, int snap, uint64_t newsize, struct lxc_conf *conf) { if (!orig->dest || !orig->src) return -1; if (strcmp(orig->type, "btrfs")) { int len, ret; if (snap) { ERROR("btrfs snapshot from %s backing store is not supported", orig->type); return -1; } len = strlen(lxcpath) + strlen(cname) + strlen("rootfs") + 3; new->src = malloc(len); if (!new->src) return -1; ret = snprintf(new->src, len, "%s/%s/rootfs", lxcpath, cname); if (ret < 0 || ret >= len) return -1; } else { // in case rootfs is in custom path, reuse it if ((new->src = dir_new_path(orig->src, oldname, cname, oldpath, lxcpath)) == NULL) return -1; } if ((new->dest = strdup(new->src)) == NULL) return -1; if (orig->mntopts && (new->mntopts = strdup(orig->mntopts)) == NULL) return -1; if (snap) { struct rsync_data_char sdata; if (!am_unpriv()) return btrfs_snapshot(orig->dest, new->dest); sdata.dest = new->dest; sdata.src = orig->dest; return userns_exec_1(conf, btrfs_snapshot_wrapper, &sdata); } if (rmdir(new->dest) < 0 && errno != ENOENT) { SYSERROR("removing %s", new->dest); return -1; } return btrfs_subvolume_create(new->dest); } static int btrfs_do_destroy_subvol(const char *path) { int ret, fd = -1; struct btrfs_ioctl_vol_args args; char *p, *newfull = strdup(path); if (!newfull) { ERROR("Error: out of memory"); return -1; } p = strrchr(newfull, '/'); if (!p) { ERROR("bad path: %s", path); free(newfull); return -1; } *p = '\0'; fd = open(newfull, O_RDONLY); if (fd < 0) { SYSERROR("Error opening %s", newfull); free(newfull); return -1; } memset(&args, 0, sizeof(args)); strncpy(args.name, p+1, BTRFS_SUBVOL_NAME_MAX); args.name[BTRFS_SUBVOL_NAME_MAX-1] = 0; ret = ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &args); INFO("btrfs: snapshot destroy ioctl returned %d for %s", ret, path); if (ret < 0 && errno == EPERM) ERROR("Is the rootfs mounted with -o user_subvol_rm_allowed?"); free(newfull); close(fd); return ret; } static int get_btrfs_tree_idx(struct my_btrfs_tree *tree, u64 id) { int i; if (!tree) return -1; for (i = 0; i < tree->num; i++) { if (tree->nodes[i].objid == id) return i; } return -1; } static struct my_btrfs_tree *create_my_btrfs_tree(u64 id, const char *path, int name_len) { struct my_btrfs_tree *tree; tree = malloc(sizeof(struct my_btrfs_tree)); if (!tree) return NULL; tree->nodes = malloc(sizeof(struct mytree_node)); if (!tree->nodes) { free(tree); return NULL; } tree->num = 1; tree->nodes[0].dirname = NULL; tree->nodes[0].name = strdup(path); if (!tree->nodes[0].name) { free(tree->nodes); free(tree); return NULL; } tree->nodes[0].parentid = 0; tree->nodes[0].objid = id; return tree; } static bool update_tree_node(struct mytree_node *n, u64 id, u64 parent, char *name, int name_len, char *dirname) { if (id) n->objid = id; if (parent) n->parentid = parent; if (name) { n->name = malloc(name_len + 1); if (!n->name) return false; strncpy(n->name, name, name_len); n->name[name_len] = '\0'; } if (dirname) { n->dirname = malloc(strlen(dirname) + 1); if (!n->dirname) { free(n->name); return false; } strcpy(n->dirname, dirname); } return true; } static bool add_btrfs_tree_node(struct my_btrfs_tree *tree, u64 id, u64 parent, char *name, int name_len, char *dirname) { struct mytree_node *tmp; int i = get_btrfs_tree_idx(tree, id); if (i != -1) return update_tree_node(&tree->nodes[i], id, parent, name, name_len, dirname); tmp = realloc(tree->nodes, (tree->num+1) * sizeof(struct mytree_node)); if (!tmp) return false; tree->nodes = tmp; memset(&tree->nodes[tree->num], 0, sizeof(struct mytree_node)); if (!update_tree_node(&tree->nodes[tree->num], id, parent, name, name_len, dirname)) return false; tree->num++; return true; } static void free_btrfs_tree(struct my_btrfs_tree *tree) { int i; if (!tree) return; for (i = 0; i < tree->num; i++) { free(tree->nodes[i].name); free(tree->nodes[i].dirname); } free(tree->nodes); free(tree); } /* * Given a @tree of subvolumes under @path, ask btrfs to remove each * subvolume */ static bool do_remove_btrfs_children(struct my_btrfs_tree *tree, u64 root_id, const char *path) { int i; char *newpath; size_t len; for (i = 0; i < tree->num; i++) { if (tree->nodes[i].parentid == root_id) { if (!tree->nodes[i].dirname) { WARN("Odd condition: child objid with no name under %s\n", path); continue; } len = strlen(path) + strlen(tree->nodes[i].dirname) + 2; newpath = malloc(len); if (!newpath) { ERROR("Out of memory"); return false; } snprintf(newpath, len, "%s/%s", path, tree->nodes[i].dirname); if (!do_remove_btrfs_children(tree, tree->nodes[i].objid, newpath)) { ERROR("Failed to prune %s\n", tree->nodes[i].name); free(newpath); return false; } if (btrfs_do_destroy_subvol(newpath) != 0) { ERROR("Failed to remove %s\n", newpath); free(newpath); return false; } free(newpath); } } return true; } static int btrfs_recursive_destroy(const char *path) { u64 root_id; int fd; struct btrfs_ioctl_search_args args; struct btrfs_ioctl_search_key *sk = &args.key; struct btrfs_ioctl_search_header sh; struct btrfs_root_ref *ref; struct my_btrfs_tree *tree; int ret, e, i; unsigned long off = 0; int name_len; char *name; char *tmppath; u64 dir_id; fd = open(path, O_RDONLY); if (fd < 0) { ERROR("Failed to open %s\n", path); return -1; } if (btrfs_list_get_path_rootid(fd, &root_id)) { e = errno; close(fd); if (e == EPERM || e == EACCES) { WARN("Will simply try removing"); goto ignore_search; } return -1; } tree = create_my_btrfs_tree(root_id, path, strlen(path)); if (!tree) { ERROR("Out of memory\n"); close(fd); return -1; } /* Walk all subvols looking for any under this id */ memset(&args, 0, sizeof(args)); /* search in the tree of tree roots */ sk->tree_id = 1; sk->max_type = BTRFS_ROOT_REF_KEY; sk->min_type = BTRFS_ROOT_ITEM_KEY; sk->min_objectid = 0; sk->max_objectid = (u64)-1; sk->max_offset = (u64)-1; sk->min_offset = 0; sk->max_transid = (u64)-1; sk->nr_items = 4096; while(1) { ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args); e = errno; if (ret < 0) { close(fd); free_btrfs_tree(tree); if (e == EPERM || e == EACCES) { WARN("Warn: can't perform the search under %s. Will simply try removing", path); goto ignore_search; } ERROR("Error: can't perform the search under %s\n", path); return -1; } if (sk->nr_items == 0) break; off = 0; for (i = 0; i < sk->nr_items; i++) { memcpy(&sh, args.buf + off, sizeof(sh)); off += sizeof(sh); /* * A backref key with the name and dirid of the parent * comes followed by the reoot ref key which has the * name of the child subvol in question. */ if (sh.objectid != root_id && sh.type == BTRFS_ROOT_BACKREF_KEY) { ref = (struct btrfs_root_ref *)(args.buf + off); name_len = btrfs_stack_root_ref_name_len(ref); name = (char *)(ref + 1); dir_id = btrfs_stack_root_ref_dirid(ref); tmppath = get_btrfs_subvol_path(fd, sh.offset, dir_id, name, name_len); if (!add_btrfs_tree_node(tree, sh.objectid, sh.offset, name, name_len, tmppath)) { ERROR("Out of memory"); free_btrfs_tree(tree); free(tmppath); close(fd); return -1; } free(tmppath); } off += sh.len; /* * record the mins in sk so we can make sure the * next search doesn't repeat this root */ sk->min_objectid = sh.objectid; sk->min_type = sh.type; sk->min_offset = sh.offset; } sk->nr_items = 4096; sk->min_offset++; if (!sk->min_offset) sk->min_type++; else continue; if (sk->min_type > BTRFS_ROOT_BACKREF_KEY) { sk->min_type = BTRFS_ROOT_ITEM_KEY; sk->min_objectid++; } else continue; if (sk->min_objectid >= sk->max_objectid) break; } close(fd); /* now actually remove them */ if (!do_remove_btrfs_children(tree, root_id, path)) { free_btrfs_tree(tree); ERROR("failed pruning\n"); return -1; } free_btrfs_tree(tree); /* All child subvols have been removed, now remove this one */ ignore_search: return btrfs_do_destroy_subvol(path); } bool btrfs_try_remove_subvol(const char *path) { if (!btrfs_detect(path)) return false; return btrfs_recursive_destroy(path) == 0; } int btrfs_destroy(struct bdev *orig) { return btrfs_recursive_destroy(orig->src); } int btrfs_create(struct bdev *bdev, const char *dest, const char *n, struct bdev_specs *specs) { bdev->src = strdup(dest); bdev->dest = strdup(dest); if (!bdev->src || !bdev->dest) return -1; return btrfs_subvolume_create(bdev->dest); } lxc-2.0.8/src/lxc/bdev/lxcnbd.h0000644061062106075000000000334013105116772013163 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_NBD_H #define __LXC_NBD_H #define _GNU_SOURCE #include #include /* defined in bdev.h */ struct bdev; /* defined in lxccontainer.h */ struct bdev_specs; /* defined conf.h */ struct lxc_conf; /* * Functions associated with an nbd bdev struct. */ int nbd_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, int snap, uint64_t newsize, struct lxc_conf *conf); int nbd_create(struct bdev *bdev, const char *dest, const char *n, struct bdev_specs *specs); int nbd_destroy(struct bdev *orig); int nbd_detect(const char *path); int nbd_mount(struct bdev *bdev); int nbd_umount(struct bdev *bdev); /* helpers */ bool attach_nbd(char *src, struct lxc_conf *conf); void detach_nbd_idx(int idx); bool requires_nbd(const char *path); #endif /* __LXC_NBD_H */ lxc-2.0.8/src/lxc/bdev/lxcrbd.h0000644061062106075000000000310613105116772013167 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_RDB_H #define __LXC_RDB_H #define _GNU_SOURCE #include /* defined in bdev.h */ struct bdev; /* defined in lxccontainer.h */ struct bdev_specs; /* defined conf.h */ struct lxc_conf; /* * Functions associated with an rdb bdev struct. */ int rbd_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, int snap, uint64_t newsize, struct lxc_conf *conf); int rbd_create(struct bdev *bdev, const char *dest, const char *n, struct bdev_specs *specs); int rbd_destroy(struct bdev *orig); int rbd_detect(const char *path); int rbd_mount(struct bdev *bdev); int rbd_umount(struct bdev *bdev); #endif /* __LXC_RDB_H */ lxc-2.0.8/src/lxc/bdev/bdev.c0000644061062106075000000005427313105116772012637 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* * this is all just a first shot for experiment. If we go this route, much * should change. bdev should be a directory with per-bdev file. Things which * I'm doing by calling out to userspace should sometimes be done through * libraries like liblvm2 */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "bdev.h" #include "conf.h" #include "config.h" #include "error.h" #include "log.h" #include "lxc.h" #include "lxcaufs.h" #include "lxcbtrfs.h" #include "lxcdir.h" #include "lxclock.h" #include "lxclvm.h" #include "lxcloop.h" #include "lxcnbd.h" #include "lxcoverlay.h" #include "lxcrbd.h" #include "lxcrsync.h" #include "lxczfs.h" #include "namespace.h" #include "parse.h" #include "utils.h" #ifndef BLKGETSIZE64 #define BLKGETSIZE64 _IOR(0x12, 114, size_t) #endif lxc_log_define(bdev, lxc); /* aufs */ static const struct bdev_ops aufs_ops = { .detect = &aufs_detect, .mount = &aufs_mount, .umount = &aufs_umount, .clone_paths = &aufs_clonepaths, .destroy = &aufs_destroy, .create = &aufs_create, .can_snapshot = true, .can_backup = true, }; /* btrfs */ static const struct bdev_ops btrfs_ops = { .detect = &btrfs_detect, .mount = &btrfs_mount, .umount = &btrfs_umount, .clone_paths = &btrfs_clonepaths, .destroy = &btrfs_destroy, .create = &btrfs_create, .can_snapshot = true, .can_backup = true, }; /* dir */ static const struct bdev_ops dir_ops = { .detect = &dir_detect, .mount = &dir_mount, .umount = &dir_umount, .clone_paths = &dir_clonepaths, .destroy = &dir_destroy, .create = &dir_create, .can_snapshot = false, .can_backup = true, }; /* loop */ static const struct bdev_ops loop_ops = { .detect = &loop_detect, .mount = &loop_mount, .umount = &loop_umount, .clone_paths = &loop_clonepaths, .destroy = &loop_destroy, .create = &loop_create, .can_snapshot = false, .can_backup = true, }; /* lvm */ static const struct bdev_ops lvm_ops = { .detect = &lvm_detect, .mount = &lvm_mount, .umount = &lvm_umount, .clone_paths = &lvm_clonepaths, .destroy = &lvm_destroy, .create = &lvm_create, .can_snapshot = true, .can_backup = false, }; /* nbd */ const struct bdev_ops nbd_ops = { .detect = &nbd_detect, .mount = &nbd_mount, .umount = &nbd_umount, .clone_paths = &nbd_clonepaths, .destroy = &nbd_destroy, .create = &nbd_create, .can_snapshot = true, .can_backup = false, }; /* overlay */ static const struct bdev_ops ovl_ops = { .detect = &ovl_detect, .mount = &ovl_mount, .umount = &ovl_umount, .clone_paths = &ovl_clonepaths, .destroy = &ovl_destroy, .create = &ovl_create, .can_snapshot = true, .can_backup = true, }; /* rbd */ static const struct bdev_ops rbd_ops = { .detect = &rbd_detect, .mount = &rbd_mount, .umount = &rbd_umount, .clone_paths = &rbd_clonepaths, .destroy = &rbd_destroy, .create = &rbd_create, .can_snapshot = false, .can_backup = false, }; /* zfs */ static const struct bdev_ops zfs_ops = { .detect = &zfs_detect, .mount = &zfs_mount, .umount = &zfs_umount, .clone_paths = &zfs_clonepaths, .destroy = &zfs_destroy, .create = &zfs_create, .can_snapshot = true, .can_backup = true, }; struct bdev_type { const char *name; const struct bdev_ops *ops; }; static const struct bdev_type bdevs[] = { {.name = "zfs", .ops = &zfs_ops,}, {.name = "lvm", .ops = &lvm_ops,}, {.name = "rbd", .ops = &rbd_ops,}, {.name = "btrfs", .ops = &btrfs_ops,}, {.name = "dir", .ops = &dir_ops,}, {.name = "aufs", .ops = &aufs_ops,}, {.name = "overlayfs", .ops = &ovl_ops,}, {.name = "loop", .ops = &loop_ops,}, {.name = "nbd", .ops = &nbd_ops,}, }; static const size_t numbdevs = sizeof(bdevs) / sizeof(struct bdev_type); /* helpers */ static const struct bdev_type *bdev_query(struct lxc_conf *conf, const char *src); static struct bdev *bdev_get(const char *type); static struct bdev *do_bdev_create(const char *dest, const char *type, const char *cname, struct bdev_specs *specs); static int find_fstype_cb(char *buffer, void *data); static char *linkderef(char *path, char *dest); static bool unpriv_snap_allowed(struct bdev *b, const char *t, bool snap, bool maybesnap); /* the bulk of this needs to become a common helper */ char *dir_new_path(char *src, const char *oldname, const char *name, const char *oldpath, const char *lxcpath) { char *ret, *p, *p2; int l1, l2, nlen; nlen = strlen(src) + 1; l1 = strlen(oldpath); p = src; /* if src starts with oldpath, look for oldname only after * that path */ if (strncmp(src, oldpath, l1) == 0) { p += l1; nlen += (strlen(lxcpath) - l1); } l2 = strlen(oldname); while ((p = strstr(p, oldname)) != NULL) { p += l2; nlen += strlen(name) - l2; } ret = malloc(nlen); if (!ret) return NULL; p = ret; if (strncmp(src, oldpath, l1) == 0) { p += sprintf(p, "%s", lxcpath); src += l1; } while ((p2 = strstr(src, oldname)) != NULL) { strncpy(p, src, p2 - src); // copy text up to oldname p += p2 - src; // move target pointer (p) p += sprintf(p, "%s", name); // print new name in place of oldname src = p2 + l2; // move src to end of oldname } sprintf(p, "%s", src); // copy the rest of src return ret; } /* * attach_block_device returns true if all went well, * meaning either a block device was attached or was not * needed. It returns false if something went wrong and * container startup should be stopped. */ bool attach_block_device(struct lxc_conf *conf) { char *path; if (!conf->rootfs.path) return true; path = conf->rootfs.path; if (!requires_nbd(path)) return true; path = strchr(path, ':'); if (!path) return false; path++; if (!attach_nbd(path, conf)) return false; return true; } bool bdev_can_backup(struct lxc_conf *conf) { struct bdev *bdev = bdev_init(conf, NULL, NULL, NULL); bool ret; if (!bdev) return false; ret = bdev->ops->can_backup; bdev_put(bdev); return ret; } /* * If we're not snaphotting, then bdev_copy becomes a simple case of mount * the original, mount the new, and rsync the contents. */ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname, const char *lxcpath, const char *bdevtype, int flags, const char *bdevdata, uint64_t newsize, int *needs_rdep) { struct bdev *orig, *new; pid_t pid; int ret; bool snap = flags & LXC_CLONE_SNAPSHOT; bool maybe_snap = flags & LXC_CLONE_MAYBE_SNAPSHOT; bool keepbdevtype = flags & LXC_CLONE_KEEPBDEVTYPE; const char *src = c0->lxc_conf->rootfs.path; const char *oldname = c0->name; const char *oldpath = c0->config_path; struct rsync_data data; /* if the container name doesn't show up in the rootfs path, then * we don't know how to come up with a new name */ if (strstr(src, oldname) == NULL) { ERROR("original rootfs path %s doesn't include container name %s", src, oldname); return NULL; } orig = bdev_init(c0->lxc_conf, src, NULL, NULL); if (!orig) { ERROR("failed to detect blockdev type for %s", src); return NULL; } if (!orig->dest) { int ret; size_t len; struct stat sb; len = strlen(oldpath) + strlen(oldname) + strlen("/rootfs") + 2; orig->dest = malloc(len); if (!orig->dest) { ERROR("out of memory"); bdev_put(orig); return NULL; } ret = snprintf(orig->dest, len, "%s/%s/rootfs", oldpath, oldname); if (ret < 0 || (size_t)ret >= len) { ERROR("rootfs path too long"); bdev_put(orig); return NULL; } ret = stat(orig->dest, &sb); if (ret < 0 && errno == ENOENT) if (mkdir_p(orig->dest, 0755) < 0) WARN("Error creating '%s', continuing.", orig->dest); } /* * special case for snapshot - if caller requested maybe_snapshot and * keepbdevtype and backing store is directory, then proceed with a copy * clone rather than returning error */ if (maybe_snap && keepbdevtype && !bdevtype && !orig->ops->can_snapshot) snap = false; /* * If newtype is NULL and snapshot is set, then use overlayfs */ if (!bdevtype && !keepbdevtype && snap && strcmp(orig->type , "dir") == 0) bdevtype = "overlayfs"; if (am_unpriv() && !unpriv_snap_allowed(orig, bdevtype, snap, maybe_snap)) { ERROR("Unsupported snapshot type for unprivileged users"); bdev_put(orig); return NULL; } *needs_rdep = 0; if (bdevtype && strcmp(orig->type, "dir") == 0 && (strcmp(bdevtype, "aufs") == 0 || strcmp(bdevtype, "overlayfs") == 0)) { *needs_rdep = 1; } else if (snap && strcmp(orig->type, "lvm") == 0 && !lvm_is_thin_volume(orig->src)) { *needs_rdep = 1; } new = bdev_get(bdevtype ? bdevtype : orig->type); if (!new) { ERROR("no such block device type: %s", bdevtype ? bdevtype : orig->type); bdev_put(orig); return NULL; } if (new->ops->clone_paths(orig, new, oldname, cname, oldpath, lxcpath, snap, newsize, c0->lxc_conf) < 0) { ERROR("failed getting pathnames for cloned storage: %s", src); goto err; } if (am_unpriv() && chown_mapped_root(new->src, c0->lxc_conf) < 0) WARN("Failed to update ownership of %s", new->dest); if (snap) return new; /* * https://github.com/lxc/lxc/issues/131 * Use btrfs snapshot feature instead of rsync to restore if both orig and new are btrfs */ if (bdevtype && strcmp(orig->type, "btrfs") == 0 && strcmp(new->type, "btrfs") == 0 && btrfs_same_fs(orig->dest, new->dest) == 0) { if (btrfs_destroy(new) < 0) { ERROR("Error destroying %s subvolume", new->dest); goto err; } if (mkdir_p(new->dest, 0755) < 0) { ERROR("Error creating %s directory", new->dest); goto err; } if (btrfs_snapshot(orig->dest, new->dest) < 0) { ERROR("Error restoring %s to %s", orig->dest, new->dest); goto err; } bdev_put(orig); return new; } pid = fork(); if (pid < 0) { SYSERROR("fork"); goto err; } if (pid > 0) { int ret = wait_for_pid(pid); bdev_put(orig); if (ret < 0) { bdev_put(new); return NULL; } return new; } data.orig = orig; data.new = new; if (am_unpriv()) ret = userns_exec_1(c0->lxc_conf, rsync_rootfs_wrapper, &data); else ret = rsync_rootfs(&data); exit(ret == 0 ? 0 : 1); err: bdev_put(orig); bdev_put(new); return NULL; } /* * bdev_create: * Create a backing store for a container. * If successful, return a struct bdev *, with the bdev mounted and ready * for use. Before completing, the caller will need to call the * umount operation and bdev_put(). * @dest: the mountpoint (i.e. /var/lib/lxc/$name/rootfs) * @type: the bdevtype (dir, btrfs, zfs, rbd, etc) * @cname: the container name * @specs: details about the backing store to create, like fstype */ struct bdev *bdev_create(const char *dest, const char *type, const char *cname, struct bdev_specs *specs) { struct bdev *bdev; char *best_options[] = {"btrfs", "zfs", "lvm", "dir", "rbd", NULL}; if (!type) return do_bdev_create(dest, "dir", cname, specs); if (strcmp(type, "best") == 0) { int i; // try for the best backing store type, according to our // opinionated preferences for (i = 0; best_options[i]; i++) { if ((bdev = do_bdev_create(dest, best_options[i], cname, specs))) return bdev; } return NULL; // 'dir' should never fail, so this shouldn't happen } // -B lvm,dir if (strchr(type, ',') != NULL) { char *dup = alloca(strlen(type) + 1), *saveptr = NULL, *token; strcpy(dup, type); for (token = strtok_r(dup, ",", &saveptr); token; token = strtok_r(NULL, ",", &saveptr)) { if ((bdev = do_bdev_create(dest, token, cname, specs))) return bdev; } } return do_bdev_create(dest, type, cname, specs); } bool bdev_destroy(struct lxc_conf *conf) { struct bdev *r; bool ret = false; r = bdev_init(conf, conf->rootfs.path, conf->rootfs.mount, NULL); if (!r) return ret; if (r->ops->destroy(r) == 0) ret = true; bdev_put(r); return ret; } int bdev_destroy_wrapper(void *data) { struct lxc_conf *conf = data; if (setgid(0) < 0) { ERROR("Failed to setgid to 0"); return -1; } if (setgroups(0, NULL) < 0) WARN("Failed to clear groups"); if (setuid(0) < 0) { ERROR("Failed to setuid to 0"); return -1; } if (!bdev_destroy(conf)) return -1; else return 0; } struct bdev *bdev_init(struct lxc_conf *conf, const char *src, const char *dst, const char *mntopts) { struct bdev *bdev; const struct bdev_type *q; if (!src) src = conf->rootfs.path; if (!src) return NULL; q = bdev_query(conf, src); if (!q) return NULL; bdev = malloc(sizeof(struct bdev)); if (!bdev) return NULL; memset(bdev, 0, sizeof(struct bdev)); bdev->ops = q->ops; bdev->type = q->name; if (mntopts) bdev->mntopts = strdup(mntopts); if (src) bdev->src = strdup(src); if (dst) bdev->dest = strdup(dst); if (strcmp(bdev->type, "nbd") == 0) bdev->nbd_idx = conf->nbd_idx; return bdev; } bool bdev_is_dir(struct lxc_conf *conf, const char *path) { struct bdev *orig = bdev_init(conf, path, NULL, NULL); bool ret = false; if (!orig) return ret; if (strcmp(orig->type, "dir") == 0) ret = true; bdev_put(orig); return ret; } void bdev_put(struct bdev *bdev) { free(bdev->mntopts); free(bdev->src); free(bdev->dest); free(bdev); } /* * return block size of dev->src in units of bytes */ int blk_getsize(struct bdev *bdev, uint64_t *size) { int fd, ret; char *path = bdev->src; if (strcmp(bdev->type, "loop") == 0) path = bdev->src + 5; fd = open(path, O_RDONLY); if (fd < 0) return -1; ret = ioctl(fd, BLKGETSIZE64, size); // size of device in bytes close(fd); return ret; } void detach_block_device(struct lxc_conf *conf) { if (conf->nbd_idx != -1) detach_nbd_idx(conf->nbd_idx); } /* * Given a bdev (presumably blockdev-based), detect the fstype * by trying mounting (in a private mntns) it. * @bdev: bdev to investigate * @type: preallocated char* in which to write the fstype * @len: length of passed in char* * Returns length of fstype, of -1 on error */ int detect_fs(struct bdev *bdev, char *type, int len) { int p[2], ret; size_t linelen; pid_t pid; FILE *f; char *sp1, *sp2, *sp3, *line = NULL; char *srcdev; if (!bdev || !bdev->src || !bdev->dest) return -1; srcdev = bdev->src; if (strcmp(bdev->type, "loop") == 0) srcdev = bdev->src + 5; ret = pipe(p); if (ret < 0) return -1; if ((pid = fork()) < 0) return -1; if (pid > 0) { int status; close(p[1]); memset(type, 0, len); ret = read(p[0], type, len - 1); close(p[0]); if (ret < 0) { SYSERROR("error reading from pipe"); wait(&status); return -1; } else if (ret == 0) { ERROR("child exited early - fstype not found"); wait(&status); return -1; } wait(&status); type[len - 1] = '\0'; INFO("detected fstype %s for %s", type, srcdev); return ret; } if (unshare(CLONE_NEWNS) < 0) exit(1); if (detect_shared_rootfs()) { if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) { SYSERROR("Failed to make / rslave"); ERROR("Continuing..."); } } ret = mount_unknown_fs(srcdev, bdev->dest, bdev->mntopts); if (ret < 0) { ERROR("failed mounting %s onto %s to detect fstype", srcdev, bdev->dest); exit(1); } // if symlink, get the real dev name char devpath[MAXPATHLEN]; char *l = linkderef(srcdev, devpath); if (!l) exit(1); f = fopen("/proc/self/mounts", "r"); if (!f) exit(1); while (getline(&line, &linelen, f) != -1) { sp1 = strchr(line, ' '); if (!sp1) exit(1); *sp1 = '\0'; if (strcmp(line, l)) continue; sp2 = strchr(sp1 + 1, ' '); if (!sp2) exit(1); *sp2 = '\0'; sp3 = strchr(sp2 + 1, ' '); if (!sp3) exit(1); *sp3 = '\0'; sp2++; if (write(p[1], sp2, strlen(sp2)) != strlen(sp2)) exit(1); exit(0); } exit(1); } int do_mkfs(const char *path, const char *fstype) { pid_t pid; if ((pid = fork()) < 0) { ERROR("error forking"); return -1; } if (pid > 0) return wait_for_pid(pid); // If the file is not a block device, we don't want mkfs to ask // us about whether to proceed. if (null_stdfds() < 0) exit(1); execlp("mkfs", "mkfs", "-t", fstype, path, (char *)NULL); exit(1); } /* * This will return 1 for physical disks, qemu-nbd, loop, etc right now only lvm * is a block device. */ int is_blktype(struct bdev *b) { if (strcmp(b->type, "lvm") == 0) return 1; return 0; } int mount_unknown_fs(const char *rootfs, const char *target, const char *options) { struct cbarg { const char *rootfs; const char *target; const char *options; } cbarg = { .rootfs = rootfs, .target = target, .options = options, }; /* * find the filesystem type with brute force: * first we check with /etc/filesystems, in case the modules * are auto-loaded and fall back to the supported kernel fs */ char *fsfile[] = { "/etc/filesystems", "/proc/filesystems", }; size_t i; for (i = 0; i < sizeof(fsfile) / sizeof(fsfile[0]); i++) { int ret; if (access(fsfile[i], F_OK)) continue; ret = lxc_file_for_each_line(fsfile[i], find_fstype_cb, &cbarg); if (ret < 0) { ERROR("failed to parse '%s'", fsfile[i]); return -1; } if (ret) return 0; } ERROR("failed to determine fs type for '%s'", rootfs); return -1; } bool rootfs_is_blockdev(struct lxc_conf *conf) { const struct bdev_type *q; struct stat st; int ret; if (!conf->rootfs.path || strcmp(conf->rootfs.path, "/") == 0 || strlen(conf->rootfs.path) == 0) return false; ret = stat(conf->rootfs.path, &st); if (ret == 0 && S_ISBLK(st.st_mode)) return true; q = bdev_query(conf, conf->rootfs.path); if (!q) return false; if (strcmp(q->name, "lvm") == 0 || strcmp(q->name, "loop") == 0 || strcmp(q->name, "nbd") == 0) return true; return false; } static struct bdev *do_bdev_create(const char *dest, const char *type, const char *cname, struct bdev_specs *specs) { struct bdev *bdev = bdev_get(type); if (!bdev) { return NULL; } if (bdev->ops->create(bdev, dest, cname, specs) < 0) { bdev_put(bdev); return NULL; } return bdev; } static struct bdev *bdev_get(const char *type) { size_t i; struct bdev *bdev; for (i = 0; i < numbdevs; i++) { if (strcmp(bdevs[i].name, type) == 0) break; } if (i == numbdevs) return NULL; bdev = malloc(sizeof(struct bdev)); if (!bdev) return NULL; memset(bdev, 0, sizeof(struct bdev)); bdev->ops = bdevs[i].ops; bdev->type = bdevs[i].name; return bdev; } static const struct bdev_type *get_bdev_by_name(const char *name) { size_t i; for (i = 0; i < numbdevs; i++) { if (strcmp(bdevs[i].name, name) == 0) return &bdevs[i]; } ERROR("Backing store %s unknown but not caught earlier\n", name); return NULL; } static const struct bdev_type *bdev_query(struct lxc_conf *conf, const char *src) { size_t i; if (conf->rootfs.bdev_type) return get_bdev_by_name(conf->rootfs.bdev_type); for (i = 0; i < numbdevs; i++) { int r; r = bdevs[i].ops->detect(src); if (r) break; } if (i == numbdevs) return NULL; return &bdevs[i]; } /* * These are copied from conf.c. However as conf.c will be moved to using * the callback system, they can be pulled from there eventually, so we * don't need to pollute utils.c with these low level functions */ static int find_fstype_cb(char* buffer, void *data) { struct cbarg { const char *rootfs; const char *target; const char *options; } *cbarg = data; unsigned long mntflags; char *mntdata; char *fstype; /* we don't try 'nodev' entries */ if (strstr(buffer, "nodev")) return 0; fstype = buffer; fstype += lxc_char_left_gc(fstype, strlen(fstype)); fstype[lxc_char_right_gc(fstype, strlen(fstype))] = '\0'; DEBUG("trying to mount '%s'->'%s' with fstype '%s'", cbarg->rootfs, cbarg->target, fstype); if (parse_mntopts(cbarg->options, &mntflags, &mntdata) < 0) { free(mntdata); return 0; } if (mount(cbarg->rootfs, cbarg->target, fstype, mntflags, mntdata)) { DEBUG("mount failed with error: %s", strerror(errno)); free(mntdata); return 0; } free(mntdata); INFO("mounted '%s' on '%s', with fstype '%s'", cbarg->rootfs, cbarg->target, fstype); return 1; } static char *linkderef(char *path, char *dest) { struct stat sbuf; ssize_t ret; ret = stat(path, &sbuf); if (ret < 0) return NULL; if (!S_ISLNK(sbuf.st_mode)) return path; ret = readlink(path, dest, MAXPATHLEN); if (ret < 0) { SYSERROR("error reading link %s", path); return NULL; } else if (ret >= MAXPATHLEN) { ERROR("link in %s too long", path); return NULL; } dest[ret] = '\0'; return dest; } /* * is an unprivileged user allowed to make this kind of snapshot */ static bool unpriv_snap_allowed(struct bdev *b, const char *t, bool snap, bool maybesnap) { if (!t) { // new type will be same as original // (unless snap && b->type == dir, in which case it will be // overlayfs -- which is also allowed) if (strcmp(b->type, "dir") == 0 || strcmp(b->type, "aufs") == 0 || strcmp(b->type, "overlayfs") == 0 || strcmp(b->type, "btrfs") == 0 || strcmp(b->type, "loop") == 0) return true; return false; } // unprivileged users can copy and snapshot dir, overlayfs, // and loop. In particular, not zfs, btrfs, or lvm. if (strcmp(t, "dir") == 0 || strcmp(t, "aufs") == 0 || strcmp(t, "overlayfs") == 0 || strcmp(t, "btrfs") == 0 || strcmp(t, "loop") == 0) return true; return false; } bool is_valid_bdev_type(const char *type) { if (strcmp(type, "dir") == 0 || strcmp(type, "btrfs") == 0 || strcmp(type, "aufs") == 0 || strcmp(type, "loop") == 0 || strcmp(type, "lvm") == 0 || strcmp(type, "nbd") == 0 || strcmp(type, "overlayfs") == 0 || strcmp(type, "rbd") == 0 || strcmp(type, "zfs") == 0) return true; return false; } lxc-2.0.8/src/lxc/bdev/lxcoverlay.h0000644061062106075000000000552113105116772014104 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_OVERLAY_H #define __LXC_OVERLAY_H #include #include #include #include #if IS_BIONIC #include <../include/lxcmntent.h> #else #include #endif /* defined in bdev.h */ struct bdev; /* defined in lxccontainer.h */ struct bdev_specs; /* defined conf.h */ struct lxc_conf; /* defined in conf.h */ struct lxc_rootfs; /* * Functions associated with an overlay bdev struct. */ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, int snap, uint64_t newsize, struct lxc_conf *conf); int ovl_create(struct bdev *bdev, const char *dest, const char *n, struct bdev_specs *specs); int ovl_destroy(struct bdev *orig); int ovl_detect(const char *path); int ovl_mount(struct bdev *bdev); int ovl_umount(struct bdev *bdev); /* * To be called from lxcapi_clone() in lxccontainer.c: When we clone a container * with overlay lxc.mount.entry entries we need to update absolute paths for * upper- and workdir. This update is done in two locations: * lxc_conf->unexpanded_config and lxc_conf->mount_list. Both updates are done * independent of each other since lxc_conf->mountlist may container more mount * entries (e.g. from other included files) than lxc_conf->unexpanded_config . */ int ovl_update_abs_paths(struct lxc_conf *lxc_conf, const char *lxc_path, const char *lxc_name, const char *newpath, const char *newname); /* * To be called from functions in lxccontainer.c: Get lower directory for * overlay rootfs. */ char *ovl_getlower(char *p); /* * Get rootfs path for overlay backed containers. Allocated memory must be freed * by caller. */ char *ovl_get_rootfs(const char *rootfs_path, size_t *rootfslen); /* * Create upper- and workdirs for overlay mounts. */ int ovl_mkdir(const struct mntent *mntent, const struct lxc_rootfs *rootfs, const char *lxc_name, const char *lxc_path); #endif /* __LXC_OVERLAY_H */ lxc-2.0.8/src/lxc/bdev/lxcdir.c0000644061062106075000000000603713105116772013177 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #include #include #include "bdev.h" #include "log.h" #include "utils.h" lxc_log_define(lxcdir, lxc); /* * for a simple directory bind mount, we substitute the old container * name and paths for the new */ int dir_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, int snap, uint64_t newsize, struct lxc_conf *conf) { int len, ret; if (snap) { ERROR("directories cannot be snapshotted. Try aufs or overlayfs."); return -1; } if (!orig->dest || !orig->src) return -1; len = strlen(lxcpath) + strlen(cname) + strlen("rootfs") + 3; new->src = malloc(len); if (!new->src) return -1; ret = snprintf(new->src, len, "%s/%s/rootfs", lxcpath, cname); if (ret < 0 || ret >= len) return -1; if ((new->dest = strdup(new->src)) == NULL) return -1; return 0; } int dir_create(struct bdev *bdev, const char *dest, const char *n, struct bdev_specs *specs) { if (specs && specs->dir) bdev->src = strdup(specs->dir); else bdev->src = strdup(dest); bdev->dest = strdup(dest); if (!bdev->src || !bdev->dest) { ERROR("Out of memory"); return -1; } if (mkdir_p(bdev->src, 0755) < 0) { ERROR("Error creating %s", bdev->src); return -1; } if (mkdir_p(bdev->dest, 0755) < 0) { ERROR("Error creating %s", bdev->dest); return -1; } return 0; } int dir_destroy(struct bdev *orig) { if (lxc_rmdir_onedev(orig->src, NULL) < 0) return -1; return 0; } int dir_detect(const char *path) { if (strncmp(path, "dir:", 4) == 0) return 1; // take their word for it if (is_dir(path)) return 1; return 0; } int dir_mount(struct bdev *bdev) { unsigned long mntflags; char *mntdata; int ret; if (strcmp(bdev->type, "dir")) return -22; if (!bdev->src || !bdev->dest) return -22; if (parse_mntopts(bdev->mntopts, &mntflags, &mntdata) < 0) { free(mntdata); return -22; } ret = mount(bdev->src, bdev->dest, "bind", MS_BIND | MS_REC | mntflags, mntdata); free(mntdata); return ret; } int dir_umount(struct bdev *bdev) { if (strcmp(bdev->type, "dir")) return -22; if (!bdev->src || !bdev->dest) return -22; return umount(bdev->dest); } lxc-2.0.8/src/lxc/bdev/lxcbtrfs.h0000644061062106075000000002664413105116772013554 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_BTRFS_H #define __LXC_BTRFS_H #define _GNU_SOURCE #include /* __le64, __l32 ... */ #include #include #include #ifndef BTRFS_SUPER_MAGIC # define BTRFS_SUPER_MAGIC 0x9123683E #endif typedef uint8_t u8; typedef uint16_t u16; typedef uint32_t u32; typedef uint64_t u64; struct btrfs_ioctl_space_info { unsigned long long flags; unsigned long long total_bytes; unsigned long long used_bytes; }; struct btrfs_ioctl_space_args { unsigned long long space_slots; unsigned long long total_spaces; struct btrfs_ioctl_space_info spaces[]; }; #define BTRFS_IOCTL_MAGIC 0x94 #define BTRFS_IOC_SUBVOL_GETFLAGS _IOR(BTRFS_IOCTL_MAGIC, 25, unsigned long long) #define BTRFS_IOC_SPACE_INFO _IOWR(BTRFS_IOCTL_MAGIC, 20, \ struct btrfs_ioctl_space_args) #define BTRFS_FSID_SIZE 16 struct btrfs_ioctl_fs_info_args { unsigned long long max_id; unsigned long long num_devices; char fsid[BTRFS_FSID_SIZE]; unsigned long long reserved[124]; }; #define BTRFS_IOC_FS_INFO _IOR(BTRFS_IOCTL_MAGIC, 31, \ struct btrfs_ioctl_fs_info_args) #define BTRFS_SUBVOL_NAME_MAX 4039 #define BTRFS_PATH_NAME_MAX 4087 struct btrfs_ioctl_vol_args { signed long long fd; char name[BTRFS_PATH_NAME_MAX + 1]; }; #define BTRFS_IOCTL_MAGIC 0x94 #define BTRFS_IOC_SUBVOL_CREATE_V2 _IOW(BTRFS_IOCTL_MAGIC, 24, \ struct btrfs_ioctl_vol_args_v2) #define BTRFS_IOC_SNAP_CREATE_V2 _IOW(BTRFS_IOCTL_MAGIC, 23, \ struct btrfs_ioctl_vol_args_v2) #define BTRFS_IOC_SUBVOL_CREATE _IOW(BTRFS_IOCTL_MAGIC, 14, \ struct btrfs_ioctl_vol_args) #define BTRFS_IOC_SNAP_DESTROY _IOW(BTRFS_IOCTL_MAGIC, 15, \ struct btrfs_ioctl_vol_args) #define BTRFS_QGROUP_INHERIT_SET_LIMITS (1ULL << 0) struct btrfs_ioctl_vol_args_v2 { signed long long fd; unsigned long long transid; unsigned long long flags; union { struct { unsigned long long size; //struct btrfs_qgroup_inherit *qgroup_inherit; void *qgroup_inherit; }; unsigned long long unused[4]; }; char name[BTRFS_SUBVOL_NAME_MAX + 1]; }; /* * root backrefs tie subvols and snapshots to the directory entries that * reference them */ #define BTRFS_ROOT_BACKREF_KEY 144 /* * root items point to tree roots. There are typically in the root * tree used by the super block to find all the other trees */ #define BTRFS_ROOT_ITEM_KEY 132 /* * root refs make a fast index for listing all of the snapshots and * subvolumes referenced by a given root. They point directly to the * directory item in the root that references the subvol */ #define BTRFS_ROOT_REF_KEY 156 #define BTRFS_ROOT_TREE_DIR_OBJECTID 6ULL #define BTRFS_DIR_ITEM_KEY 84 /* * * this is used for both forward and backward root refs * */ struct btrfs_root_ref { __le64 dirid; __le64 sequence; __le16 name_len; } __attribute__ ((__packed__)); struct btrfs_disk_key { __le64 objectid; u8 type; __le64 offset; } __attribute__ ((__packed__)); struct btrfs_dir_item { struct btrfs_disk_key location; __le64 transid; __le16 data_len; __le16 name_len; u8 type; } __attribute__ ((__packed__)); #define BTRFS_IOCTL_MAGIC 0x94 #define BTRFS_VOL_NAME_MAX 255 #define BTRFS_PATH_NAME_MAX 4087 struct btrfs_ioctl_search_key { /* which root are we searching. 0 is the tree of tree roots */ __u64 tree_id; /* keys returned will be >= min and <= max */ __u64 min_objectid; __u64 max_objectid; /* keys returned will be >= min and <= max */ __u64 min_offset; __u64 max_offset; /* max and min transids to search for */ __u64 min_transid; __u64 max_transid; /* keys returned will be >= min and <= max */ __u32 min_type; __u32 max_type; /* * how many items did userland ask for, and how many are we * returning */ __u32 nr_items; /* align to 64 bits */ __u32 unused; /* some extra for later */ __u64 unused1; __u64 unused2; __u64 unused3; __u64 unused4; }; struct btrfs_ioctl_search_header { __u64 transid; __u64 objectid; __u64 offset; __u32 type; __u32 len; } __attribute__((may_alias)); #define BTRFS_SEARCH_ARGS_BUFSIZE (4096 - sizeof(struct btrfs_ioctl_search_key)) /* * the buf is an array of search headers where * each header is followed by the actual item * the type field is expanded to 32 bits for alignment */ struct btrfs_ioctl_search_args { struct btrfs_ioctl_search_key key; char buf[BTRFS_SEARCH_ARGS_BUFSIZE]; }; #define BTRFS_IOC_TREE_SEARCH _IOWR(BTRFS_IOCTL_MAGIC, 17, \ struct btrfs_ioctl_search_args) #define BTRFS_UUID_SIZE 16 struct btrfs_timespec { __le64 sec; __le32 nsec; } __attribute__ ((__packed__)); struct btrfs_inode_item { /* nfs style generation number */ __le64 generation; /* transid that last touched this inode */ __le64 transid; __le64 size; __le64 nbytes; __le64 block_group; __le32 nlink; __le32 uid; __le32 gid; __le32 mode; __le64 rdev; __le64 flags; /* modification sequence number for NFS */ __le64 sequence; /* * a little future expansion, for more than this we can * just grow the inode item and version it */ __le64 reserved[4]; struct btrfs_timespec atime; struct btrfs_timespec ctime; struct btrfs_timespec mtime; struct btrfs_timespec otime; } __attribute__ ((__packed__)); struct btrfs_root_item_v0 { struct btrfs_inode_item inode; __le64 generation; __le64 root_dirid; __le64 bytenr; __le64 byte_limit; __le64 bytes_used; __le64 last_snapshot; __le64 flags; __le32 refs; struct btrfs_disk_key drop_progress; u8 drop_level; u8 level; } __attribute__ ((__packed__)); struct btrfs_root_item { struct btrfs_inode_item inode; __le64 generation; __le64 root_dirid; __le64 bytenr; __le64 byte_limit; __le64 bytes_used; __le64 last_snapshot; __le64 flags; __le32 refs; struct btrfs_disk_key drop_progress; u8 drop_level; u8 level; /* * The following fields appear after subvol_uuids+subvol_times * were introduced. */ /* * This generation number is used to test if the new fields are valid * and up to date while reading the root item. Every time the root item * is written out, the "generation" field is copied into this field. If * anyone ever mounted the fs with an older kernel, we will have * mismatching generation values here and thus must invalidate the * new fields. See btrfs_update_root and btrfs_find_last_root for * details. * the offset of generation_v2 is also used as the start for the memset * when invalidating the fields. */ __le64 generation_v2; u8 uuid[BTRFS_UUID_SIZE]; u8 parent_uuid[BTRFS_UUID_SIZE]; u8 received_uuid[BTRFS_UUID_SIZE]; __le64 ctransid; /* updated when an inode changes */ __le64 otransid; /* trans when created */ __le64 stransid; /* trans when sent. non-zero for received subvol */ __le64 rtransid; /* trans when received. non-zero for received subvol */ struct btrfs_timespec ctime; struct btrfs_timespec otime; struct btrfs_timespec stime; struct btrfs_timespec rtime; __le64 reserved[8]; /* for future */ } __attribute__ ((__packed__)); #define BTRFS_IOC_INO_LOOKUP _IOWR(BTRFS_IOCTL_MAGIC, 18, \ struct btrfs_ioctl_ino_lookup_args) #define BTRFS_INO_LOOKUP_PATH_MAX 4080 struct btrfs_ioctl_ino_lookup_args { __u64 treeid; __u64 objectid; char name[BTRFS_INO_LOOKUP_PATH_MAX]; }; /* * All files have objectids in this range. */ #define BTRFS_FIRST_FREE_OBJECTID 256ULL #define BTRFS_LAST_FREE_OBJECTID -256ULL #define BTRFS_FIRST_CHUNK_TREE_OBJECTID 256ULL /* * The followings are macro for correctly getting member of * structures in both low and big endian platforms as per * btrfs-progs */ #ifdef __CHECKER__ #define __force __attribute__((force)) #else #define __force #endif #if __BYTE_ORDER == __BIG_ENDIAN #define cpu_to_le64(x) ((__force __le64)(u64)(bswap_64(x))) #define le64_to_cpu(x) ((__force u64)(__le64)(bswap_64(x))) #define cpu_to_le32(x) ((__force __le32)(u32)(bswap_32(x))) #define le32_to_cpu(x) ((__force u32)(__le32)(bswap_32(x))) #define cpu_to_le16(x) ((__force __le16)(u16)(bswap_16(x))) #define le16_to_cpu(x) ((__force u16)(__le16)(bswap_16(x))) #else #define cpu_to_le64(x) ((__force __le64)(u64)(x)) #define le64_to_cpu(x) ((__force u64)(__le64)(x)) #define cpu_to_le32(x) ((__force __le32)(u32)(x)) #define le32_to_cpu(x) ((__force u32)(__le32)(x)) #define cpu_to_le16(x) ((__force __le16)(u16)(x)) #define le16_to_cpu(x) ((__force u16)(__le16)(x)) #endif #define BTRFS_SETGET_STACK_FUNCS(name, type, member, bits) \ static inline u##bits btrfs_##name(type *s) \ { \ return le##bits##_to_cpu(s->member); \ } \ static inline void btrfs_set_##name(type *s, u##bits val) \ { \ s->member = cpu_to_le##bits(val); \ } /* defined as btrfs_stack_root_ref_dirid */ BTRFS_SETGET_STACK_FUNCS(stack_root_ref_dirid, struct btrfs_root_ref, dirid, 64); /* defined as btrfs_stack_root_ref_sequence */ BTRFS_SETGET_STACK_FUNCS(stack_root_ref_sequence, struct btrfs_root_ref, sequence, 64); /* defined as btrfs_stack_root_ref_name_len */ BTRFS_SETGET_STACK_FUNCS(stack_root_ref_name_len, struct btrfs_root_ref, name_len, 16); /* defined in bdev.h */ struct bdev; /* defined in lxccontainer.h */ struct bdev_specs; /* defined conf.h */ struct lxc_conf; struct mytree_node { u64 objid; u64 parentid; char *name; char *dirname; }; struct my_btrfs_tree { struct mytree_node *nodes; int num; }; /* * Functions associated with a btrfs bdev struct. */ int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, int snap, uint64_t newsize, struct lxc_conf *conf); int btrfs_create(struct bdev *bdev, const char *dest, const char *n, struct bdev_specs *specs); int btrfs_destroy(struct bdev *orig); int btrfs_detect(const char *path); int btrfs_mount(struct bdev *bdev); int btrfs_umount(struct bdev *bdev); /* * Helper functions */ char *get_btrfs_subvol_path(int fd, u64 dir_id, u64 objid, char *name, int name_len); int btrfs_list_get_path_rootid(int fd, u64 *treeid); bool is_btrfs_fs(const char *path); int is_btrfs_subvol(const char *path); bool btrfs_try_remove_subvol(const char *path); int btrfs_same_fs(const char *orig, const char *new); int btrfs_snapshot(const char *orig, const char *new); #endif // __LXC_BTRFS_H lxc-2.0.8/src/lxc/bdev/lxcrsync.c0000644061062106075000000000612613105116772013556 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "bdev.h" #include "log.h" #include "lxcrsync.h" #include "utils.h" lxc_log_define(lxcrsync, lxc); /* the bulk of this needs to become a common helper */ int do_rsync(const char *src, const char *dest) { // call out to rsync pid_t pid; char *s; size_t l; pid = fork(); if (pid < 0) return -1; if (pid > 0) return wait_for_pid(pid); l = strlen(src) + 2; s = malloc(l); if (!s) exit(1); strcpy(s, src); s[l-2] = '/'; s[l-1] = '\0'; execlp("rsync", "rsync", "-aHXS", "--delete", s, dest, (char *)NULL); exit(1); } int rsync_delta(struct rsync_data_char *data) { if (setgid(0) < 0) { ERROR("Failed to setgid to 0"); return -1; } if (setgroups(0, NULL) < 0) WARN("Failed to clear groups"); if (setuid(0) < 0) { ERROR("Failed to setuid to 0"); return -1; } if (do_rsync(data->src, data->dest) < 0) { ERROR("rsyncing %s to %s", data->src, data->dest); return -1; } return 0; } int rsync_delta_wrapper(void *data) { struct rsync_data_char *arg = data; return rsync_delta(arg); } int rsync_rootfs(struct rsync_data *data) { struct bdev *orig = data->orig, *new = data->new; if (unshare(CLONE_NEWNS) < 0) { SYSERROR("unshare CLONE_NEWNS"); return -1; } if (detect_shared_rootfs()) { if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) { SYSERROR("Failed to make / rslave"); ERROR("Continuing..."); } } // If not a snapshot, copy the fs. if (orig->ops->mount(orig) < 0) { ERROR("failed mounting %s onto %s", orig->src, orig->dest); return -1; } if (new->ops->mount(new) < 0) { ERROR("failed mounting %s onto %s", new->src, new->dest); return -1; } if (setgid(0) < 0) { ERROR("Failed to setgid to 0"); return -1; } if (setgroups(0, NULL) < 0) WARN("Failed to clear groups"); if (setuid(0) < 0) { ERROR("Failed to setuid to 0"); return -1; } if (do_rsync(orig->dest, new->dest) < 0) { ERROR("rsyncing %s to %s", orig->src, new->src); return -1; } return 0; } int rsync_rootfs_wrapper(void *data) { struct rsync_data *arg = data; return rsync_rootfs(arg); } lxc-2.0.8/src/lxc/bdev/lxclvm.h0000644061062106075000000000344613105116772013225 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_LVM_H #define __LXC_LVM_H #define _GNU_SOURCE #include /* defined in bdev.h */ struct bdev; /* defined in lxccontainer.h */ struct bdev_specs; /* defined conf.h */ struct lxc_conf; /* * Functions associated with an lvm bdev struct. */ int lvm_detect(const char *path); int lvm_mount(struct bdev *bdev); int lvm_umount(struct bdev *bdev); int lvm_compare_lv_attr(const char *path, int pos, const char expected); int lvm_is_thin_volume(const char *path); int lvm_is_thin_pool(const char *path); int lvm_snapshot(const char *orig, const char *path, uint64_t size); int lvm_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, int snap, uint64_t newsize, struct lxc_conf *conf); int lvm_destroy(struct bdev *orig); int lvm_create(struct bdev *bdev, const char *dest, const char *n, struct bdev_specs *specs); #endif /* __LXC_LVM_H */ lxc-2.0.8/src/lxc/bdev/lxcloop.c0000644061062106075000000001275513105116772013376 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include "bdev.h" #include "log.h" #include "lxcloop.h" #include "utils.h" lxc_log_define(lxcloop, lxc); static int do_loop_create(const char *path, uint64_t size, const char *fstype); /* * No idea what the original blockdev will be called, but the copy will be * called $lxcpath/$lxcname/rootdev */ int loop_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, int snap, uint64_t newsize, struct lxc_conf *conf) { char fstype[100]; uint64_t size = newsize; int len, ret; char *srcdev; if (snap) { ERROR("loop devices cannot be snapshotted."); return -1; } if (!orig->dest || !orig->src) return -1; len = strlen(lxcpath) + strlen(cname) + strlen("rootdev") + 3; srcdev = alloca(len); ret = snprintf(srcdev, len, "%s/%s/rootdev", lxcpath, cname); if (ret < 0 || ret >= len) return -1; new->src = malloc(len + 5); if (!new->src) return -1; ret = snprintf(new->src, len + 5, "loop:%s", srcdev); if (ret < 0 || ret >= len + 5) return -1; new->dest = malloc(len); if (!new->dest) return -1; ret = snprintf(new->dest, len, "%s/%s/rootfs", lxcpath, cname); if (ret < 0 || ret >= len) return -1; // it's tempting to say: if orig->src == loopback and !newsize, then // copy the loopback file. However, we'd have to make sure to // correctly keep holes! So punt for now. if (is_blktype(orig)) { if (!newsize && blk_getsize(orig, &size) < 0) { ERROR("Error getting size of %s", orig->src); return -1; } if (detect_fs(orig, fstype, 100) < 0) { INFO("could not find fstype for %s, using %s", orig->src, DEFAULT_FSTYPE); return -1; } } else { sprintf(fstype, "%s", DEFAULT_FSTYPE); if (!newsize) size = DEFAULT_FS_SIZE; } return do_loop_create(srcdev, size, fstype); } int loop_create(struct bdev *bdev, const char *dest, const char *n, struct bdev_specs *specs) { const char *fstype; uint64_t sz; int ret, len; char *srcdev; if (!specs) return -1; // dest is passed in as $lxcpath / $lxcname / rootfs // srcdev will be: $lxcpath / $lxcname / rootdev // src will be 'loop:$srcdev' len = strlen(dest) + 2; srcdev = alloca(len); ret = snprintf(srcdev, len, "%s", dest); if (ret < 0 || ret >= len) return -1; sprintf(srcdev + len - 4, "dev"); bdev->src = malloc(len + 5); if (!bdev->src) return -1; ret = snprintf(bdev->src, len + 5, "loop:%s", srcdev); if (ret < 0 || ret >= len + 5) return -1; sz = specs->fssize; if (!sz) sz = DEFAULT_FS_SIZE; fstype = specs->fstype; if (!fstype) fstype = DEFAULT_FSTYPE; if (!(bdev->dest = strdup(dest))) return -1; if (mkdir_p(bdev->dest, 0755) < 0) { ERROR("Error creating %s", bdev->dest); return -1; } return do_loop_create(srcdev, sz, fstype); } int loop_destroy(struct bdev *orig) { return unlink(orig->src + 5); } int loop_detect(const char *path) { if (strncmp(path, "loop:", 5) == 0) return 1; return 0; } int loop_mount(struct bdev *bdev) { int ret, loopfd; char loname[MAXPATHLEN]; if (strcmp(bdev->type, "loop")) return -22; if (!bdev->src || !bdev->dest) return -22; loopfd = lxc_prepare_loop_dev(bdev->src + 5, loname, LO_FLAGS_AUTOCLEAR); if (loopfd < 0) return -1; DEBUG("prepared loop device \"%s\"", loname); ret = mount_unknown_fs(loname, bdev->dest, bdev->mntopts); if (ret < 0) ERROR("failed to mount rootfs \"%s\" onto \"%s\" via loop device \"%s\"", bdev->src, bdev->dest, loname); else bdev->lofd = loopfd; DEBUG("mounted rootfs \"%s\" onto \"%s\" via loop device \"%s\"", bdev->src, bdev->dest, loname); return ret; } int loop_umount(struct bdev *bdev) { int ret; if (strcmp(bdev->type, "loop")) return -22; if (!bdev->src || !bdev->dest) return -22; ret = umount(bdev->dest); if (bdev->lofd >= 0) { close(bdev->lofd); bdev->lofd = -1; } return ret; } static int do_loop_create(const char *path, uint64_t size, const char *fstype) { int fd, ret; // create the new loopback file. fd = creat(path, S_IRUSR|S_IWUSR); if (fd < 0) return -1; if (lseek(fd, size, SEEK_SET) < 0) { SYSERROR("Error seeking to set new loop file size"); close(fd); return -1; } if (write(fd, "1", 1) != 1) { SYSERROR("Error creating new loop file"); close(fd); return -1; } ret = close(fd); if (ret < 0) { SYSERROR("Error closing new loop file"); return -1; } // create an fs in the loopback file if (do_mkfs(path, fstype) < 0) { ERROR("Error creating filesystem type %s on %s", fstype, path); return -1; } return 0; } lxc-2.0.8/src/lxc/bdev/lxczfs.c0000644061062106075000000001614313105116772013222 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #include #include #include #include #include #include #include "bdev.h" #include "config.h" #include "log.h" #include "lxczfs.h" #include "utils.h" lxc_log_define(lxczfs, lxc); /* * zfs ops: * There are two ways we could do this. We could always specify the 'zfs device' * (i.e. tank/lxc lxc/container) as rootfs. But instead (at least right now) we * have lxc-create specify $lxcpath/$lxcname/rootfs as the mountpoint, so that * it is always mounted. That means 'mount' is really never needed and could be * noop, but for the sake of flexibility let's always bind-mount. */ int zfs_list_entry(const char *path, char *output, size_t inlen) { struct lxc_popen_FILE *f; int found=0; f = lxc_popen("zfs list 2> /dev/null"); if (f == NULL) { SYSERROR("popen failed"); return 0; } while (fgets(output, inlen, f->f)) { if (strstr(output, path)) { found = 1; break; } } (void) lxc_pclose(f); return found; } int zfs_detect(const char *path) { char *output = malloc(LXC_LOG_BUFFER_SIZE); if (!output) { ERROR("out of memory"); return 0; } int found = zfs_list_entry(path, output, LXC_LOG_BUFFER_SIZE); free(output); return found; } int zfs_mount(struct bdev *bdev) { if (strcmp(bdev->type, "zfs")) return -22; if (!bdev->src || !bdev->dest) return -22; char *mntdata; unsigned long mntflags; if (parse_mntopts(bdev->mntopts, &mntflags, &mntdata) < 0) { free(mntdata); return -22; } int ret = mount(bdev->src, bdev->dest, "bind", MS_BIND | MS_REC | mntflags, mntdata); free(mntdata); return ret; } int zfs_umount(struct bdev *bdev) { if (strcmp(bdev->type, "zfs")) return -22; if (!bdev->src || !bdev->dest) return -22; return umount(bdev->dest); } int zfs_clone(const char *opath, const char *npath, const char *oname, const char *nname, const char *lxcpath, int snapshot) { // use the 'zfs list | grep opath' entry to get the zfsroot char output[MAXPATHLEN], option[MAXPATHLEN]; char *p; const char *zfsroot = output; int ret; pid_t pid; if (zfs_list_entry(opath, output, MAXPATHLEN)) { // zfsroot is output up to ' ' if ((p = strchr(output, ' ')) == NULL) return -1; *p = '\0'; if ((p = strrchr(output, '/')) == NULL) return -1; *p = '\0'; } else { zfsroot = lxc_global_config_value("lxc.bdev.zfs.root"); } ret = snprintf(option, MAXPATHLEN, "-omountpoint=%s/%s/rootfs", lxcpath, nname); if (ret < 0 || ret >= MAXPATHLEN) return -1; // zfs create -omountpoint=$lxcpath/$lxcname $zfsroot/$nname if (!snapshot) { if ((pid = fork()) < 0) return -1; if (!pid) { char dev[MAXPATHLEN]; ret = snprintf(dev, MAXPATHLEN, "%s/%s", zfsroot, nname); if (ret < 0 || ret >= MAXPATHLEN) exit(EXIT_FAILURE); execlp("zfs", "zfs", "create", option, dev, (char *)NULL); exit(EXIT_FAILURE); } return wait_for_pid(pid); } else { // if snapshot, do // 'zfs snapshot zfsroot/oname@nname // zfs clone zfsroot/oname@nname zfsroot/nname char path1[MAXPATHLEN], path2[MAXPATHLEN]; ret = snprintf(path1, MAXPATHLEN, "%s/%s@%s", zfsroot, oname, nname); if (ret < 0 || ret >= MAXPATHLEN) return -1; (void) snprintf(path2, MAXPATHLEN, "%s/%s", zfsroot, nname); // if the snapshot exists, delete it if ((pid = fork()) < 0) return -1; if (!pid) { int dev0 = open("/dev/null", O_WRONLY); if (dev0 >= 0) dup2(dev0, STDERR_FILENO); execlp("zfs", "zfs", "destroy", path1, (char *)NULL); exit(EXIT_FAILURE); } // it probably doesn't exist so destroy probably will fail. (void) wait_for_pid(pid); // run first (snapshot) command if ((pid = fork()) < 0) return -1; if (!pid) { execlp("zfs", "zfs", "snapshot", path1, (char *)NULL); exit(EXIT_FAILURE); } if (wait_for_pid(pid) < 0) return -1; // run second (clone) command if ((pid = fork()) < 0) return -1; if (!pid) { execlp("zfs", "zfs", "clone", option, path1, path2, (char *)NULL); exit(EXIT_FAILURE); } return wait_for_pid(pid); } } int zfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, int snap, uint64_t newsize, struct lxc_conf *conf) { int len, ret; if (!orig->src || !orig->dest) return -1; if (snap && strcmp(orig->type, "zfs")) { ERROR("zfs snapshot from %s backing store is not supported", orig->type); return -1; } len = strlen(lxcpath) + strlen(cname) + strlen("rootfs") + 3; new->src = malloc(len); if (!new->src) return -1; ret = snprintf(new->src, len, "%s/%s/rootfs", lxcpath, cname); if (ret < 0 || ret >= len) return -1; if ((new->dest = strdup(new->src)) == NULL) return -1; return zfs_clone(orig->src, new->src, oldname, cname, lxcpath, snap); } /* * TODO: detect whether this was a clone, and if so then also delete the * snapshot it was based on, so that we don't hold the original * container busy. */ int zfs_destroy(struct bdev *orig) { pid_t pid; char output[MAXPATHLEN]; char *p; if ((pid = fork()) < 0) return -1; if (pid) return wait_for_pid(pid); if (!zfs_list_entry(orig->src, output, MAXPATHLEN)) { ERROR("Error: zfs entry for %s not found", orig->src); return -1; } // zfs mount is output up to ' ' if ((p = strchr(output, ' ')) == NULL) return -1; *p = '\0'; execlp("zfs", "zfs", "destroy", "-r", output, (char *)NULL); exit(EXIT_FAILURE); } int zfs_create(struct bdev *bdev, const char *dest, const char *n, struct bdev_specs *specs) { const char *zfsroot; char option[MAXPATHLEN]; int ret; pid_t pid; if (!specs || !specs->zfs.zfsroot) zfsroot = lxc_global_config_value("lxc.bdev.zfs.root"); else zfsroot = specs->zfs.zfsroot; if (!(bdev->dest = strdup(dest))) { ERROR("No mount target specified or out of memory"); return -1; } if (!(bdev->src = strdup(bdev->dest))) { ERROR("out of memory"); return -1; } ret = snprintf(option, MAXPATHLEN, "-omountpoint=%s", bdev->dest); if (ret < 0 || ret >= MAXPATHLEN) return -1; if ((pid = fork()) < 0) return -1; if (pid) return wait_for_pid(pid); char dev[MAXPATHLEN]; ret = snprintf(dev, MAXPATHLEN, "%s/%s", zfsroot, n); if (ret < 0 || ret >= MAXPATHLEN) exit(EXIT_FAILURE); execlp("zfs", "zfs", "create", option, dev, (char *)NULL); exit(EXIT_FAILURE); } lxc-2.0.8/src/lxc/bdev/lxcaufs.h0000644061062106075000000000404013105116772013354 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_AUFS_H #define __LXC_AUFS_H #define _GNU_SOURCE #include #if IS_BIONIC #include <../include/lxcmntent.h> #else #include #endif /* defined in bdev.h */ struct bdev; /* defined in lxccontainer.h */ struct bdev_specs; /* defined conf.h */ struct lxc_conf; /* defined in conf.h */ struct lxc_rootfs; /* * Functions associated with an aufs bdev struct. */ int aufs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, int snap, uint64_t newsize, struct lxc_conf *conf); int aufs_create(struct bdev *bdev, const char *dest, const char *n, struct bdev_specs *specs); int aufs_destroy(struct bdev *orig); int aufs_detect(const char *path); int aufs_mount(struct bdev *bdev); int aufs_umount(struct bdev *bdev); /* * Get rootfs path for aufs backed containers. Allocated memory must be freed * by caller. */ char *aufs_get_rootfs(const char *rootfs_path, size_t *rootfslen); /* * Create directories for aufs mounts. */ int aufs_mkdir(const struct mntent *mntent, const struct lxc_rootfs *rootfs, const char *lxc_name, const char *lxc_path); #endif /* __LXC_AUFS_H */ lxc-2.0.8/src/lxc/bdev/lxcoverlay.c0000644061062106075000000004530313105116772014101 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #include #include #include #include #include "bdev.h" #include "conf.h" #include "confile.h" #include "log.h" #include "lxccontainer.h" #include "lxcoverlay.h" #include "lxcrsync.h" #include "utils.h" lxc_log_define(lxcoverlay, lxc); static char *ovl_name; static char *ovl_version[] = {"overlay", "overlayfs"}; /* defined in lxccontainer.c: needs to become common helper */ extern char *dir_new_path(char *src, const char *oldname, const char *name, const char *oldpath, const char *lxcpath); static char *ovl_detect_name(void); static int ovl_do_rsync(struct bdev *orig, struct bdev *new, struct lxc_conf *conf); static int ovl_rsync(struct rsync_data *data); static int ovl_rsync_wrapper(void *data); static int ovl_remount_on_enodev(const char *lower, const char *target, const char *name, unsigned long mountflags, const void *options); int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, int snap, uint64_t newsize, struct lxc_conf *conf) { if (!snap) { ERROR("overlayfs is only for snapshot clones"); return -22; } if (!orig->src || !orig->dest) return -1; new->dest = dir_new_path(orig->dest, oldname, cname, oldpath, lxcpath); if (!new->dest) return -1; if (mkdir_p(new->dest, 0755) < 0) return -1; if (am_unpriv() && chown_mapped_root(new->dest, conf) < 0) WARN("Failed to update ownership of %s", new->dest); if (strcmp(orig->type, "dir") == 0) { char *delta, *lastslash; char *work; int ret, len, lastslashidx; /* * if we have * /var/lib/lxc/c2/rootfs * then delta will be * /var/lib/lxc/c2/delta0 */ lastslash = strrchr(new->dest, '/'); if (!lastslash) return -22; if (strlen(lastslash) < 7) return -22; lastslash++; lastslashidx = lastslash - new->dest; delta = malloc(lastslashidx + 7); if (!delta) return -1; strncpy(delta, new->dest, lastslashidx + 1); strcpy(delta + lastslashidx, "delta0"); if ((ret = mkdir(delta, 0755)) < 0) { SYSERROR("error: mkdir %s", delta); free(delta); return -1; } if (am_unpriv() && chown_mapped_root(delta, conf) < 0) WARN("Failed to update ownership of %s", delta); /* * Make workdir for overlayfs.v22 or higher: * The workdir will be * /var/lib/lxc/c2/olwork * and is used to prepare files before they are atomically * switched to the overlay destination. Workdirs need to be on * the same filesystem as the upperdir so it's OK for it to be * empty. */ work = malloc(lastslashidx + 7); if (!work) { free(delta); return -1; } strncpy(work, new->dest, lastslashidx + 1); strcpy(work + lastslashidx, "olwork"); if (mkdir(work, 0755) < 0) { SYSERROR("error: mkdir %s", work); free(delta); free(work); return -1; } if (am_unpriv() && chown_mapped_root(work, conf) < 0) WARN("Failed to update ownership of %s", work); free(work); // the src will be 'overlayfs:lowerdir:upperdir' len = strlen(delta) + strlen(orig->src) + 12; new->src = malloc(len); if (!new->src) { free(delta); return -ENOMEM; } ret = snprintf(new->src, len, "overlayfs:%s:%s", orig->src, delta); free(delta); if (ret < 0 || ret >= len) return -ENOMEM; } else if (strcmp(orig->type, "overlayfs") == 0) { /* * What exactly do we want to do here? I think we want to use * the original lowerdir, with a private delta which is * originally rsynced from the original delta */ char *osrc, *odelta, *nsrc, *ndelta, *work; char *lastslash; int len, ret, lastslashidx; if (!(osrc = strdup(orig->src))) return -22; nsrc = strchr(osrc, ':') + 1; if (nsrc != osrc + 10 || (odelta = strchr(nsrc, ':')) == NULL) { free(osrc); return -22; } *odelta = '\0'; odelta++; ndelta = dir_new_path(odelta, oldname, cname, oldpath, lxcpath); if (!ndelta) { free(osrc); return -ENOMEM; } if ((ret = mkdir(ndelta, 0755)) < 0 && errno != EEXIST) { SYSERROR("error: mkdir %s", ndelta); free(osrc); free(ndelta); return -1; } if (am_unpriv() && chown_mapped_root(ndelta, conf) < 0) WARN("Failed to update ownership of %s", ndelta); /* * make workdir for overlayfs.v22 or higher (see comment further * up) */ lastslash = strrchr(ndelta, '/'); if (!lastslash) { free(osrc); free(ndelta); return -1; } lastslash++; lastslashidx = lastslash - ndelta; work = malloc(lastslashidx + 7); if (!work) { free(osrc); free(ndelta); return -1; } strncpy(work, ndelta, lastslashidx + 1); strcpy(work + lastslashidx, "olwork"); if ((mkdir(work, 0755) < 0) && errno != EEXIST) { SYSERROR("error: mkdir %s", work); free(osrc); free(ndelta); free(work); return -1; } if (am_unpriv() && chown_mapped_root(work, conf) < 0) WARN("Failed to update ownership of %s", work); free(work); len = strlen(nsrc) + strlen(ndelta) + 12; new->src = malloc(len); if (!new->src) { free(osrc); free(ndelta); return -ENOMEM; } ret = snprintf(new->src, len, "overlayfs:%s:%s", nsrc, ndelta); free(osrc); free(ndelta); if (ret < 0 || ret >= len) return -ENOMEM; return ovl_do_rsync(orig, new, conf); } else { ERROR("overlayfs clone of %s container is not yet supported", orig->type); /* * Note, supporting this will require ovl_mount supporting * mounting of the underlay. No big deal, just needs to be done. */ return -1; } return 0; } /* * to say 'lxc-create -t ubuntu -n o1 -B overlayfs' means you want * $lxcpath/$lxcname/rootfs to have the created container, while all * changes after starting the container are written to * $lxcpath/$lxcname/delta0 */ int ovl_create(struct bdev *bdev, const char *dest, const char *n, struct bdev_specs *specs) { char *delta; int ret, len = strlen(dest), newlen; if (len < 8 || strcmp(dest + len - 7, "/rootfs") != 0) return -1; if (!(bdev->dest = strdup(dest))) { ERROR("Out of memory"); return -1; } delta = alloca(strlen(dest) + 1); strcpy(delta, dest); strcpy(delta + len - 6, "delta0"); if (mkdir_p(delta, 0755) < 0) { ERROR("Error creating %s", delta); return -1; } // overlayfs:lower:upper newlen = (2 * len) + strlen("overlayfs:") + 2; bdev->src = malloc(newlen); if (!bdev->src) { ERROR("Out of memory"); return -1; } ret = snprintf(bdev->src, newlen, "overlayfs:%s:%s", dest, delta); if (ret < 0 || ret >= newlen) return -1; if (mkdir_p(bdev->dest, 0755) < 0) { ERROR("Error creating %s", bdev->dest); return -1; } return 0; } int ovl_destroy(struct bdev *orig) { char *upper; if (strncmp(orig->src, "overlayfs:", 10) != 0) return -22; upper = strchr(orig->src + 10, ':'); if (!upper) return -22; upper++; return lxc_rmdir_onedev(upper, NULL); } int ovl_detect(const char *path) { if (strncmp(path, "overlayfs:", 10) == 0) return 1; // take their word for it return 0; } char *ovl_getlower(char *p) { char *p1 = strchr(p, ':'); if (p1) *p1 = '\0'; return p; } int ovl_mount(struct bdev *bdev) { char *tmp, *options, *dup, *lower, *upper; char *options_work, *work, *lastslash; int lastslashidx; int len, len2; unsigned long mntflags; char *mntdata; int ret, ret2; if (strcmp(bdev->type, "overlayfs")) return -22; if (!bdev->src || !bdev->dest) return -22; if (!ovl_name) ovl_name = ovl_detect_name(); /* * separately mount it first: * mount -t overlayfs * -oupperdir=${upper},lowerdir=${lower} lower dest */ dup = alloca(strlen(bdev->src) + 1); strcpy(dup, bdev->src); /* support multiple lower layers */ if (!(lower = strstr(dup, ":/"))) return -22; lower++; upper = lower; while ((tmp = strstr(++upper, ":/"))) { upper = tmp; } if (--upper == lower) return -22; *upper = '\0'; upper++; // if delta doesn't yet exist, create it if (mkdir_p(upper, 0755) < 0 && errno != EEXIST) return -22; /* * overlayfs.v22 or higher needs workdir option: * if upper is * /var/lib/lxc/c2/delta0 * then workdir is * /var/lib/lxc/c2/olwork */ lastslash = strrchr(upper, '/'); if (!lastslash) return -22; lastslash++; lastslashidx = lastslash - upper; work = alloca(lastslashidx + 7); strncpy(work, upper, lastslashidx + 7); strcpy(work + lastslashidx, "olwork"); if (parse_mntopts(bdev->mntopts, &mntflags, &mntdata) < 0) { free(mntdata); return -22; } if (mkdir_p(work, 0755) < 0 && errno != EEXIST) { free(mntdata); return -22; } /* * TODO: * We should check whether bdev->src is a blockdev but for now only * support overlays of a basic directory */ if (mntdata) { len = strlen(lower) + strlen(upper) + strlen("upperdir=,lowerdir=,") + strlen(mntdata) + 1; options = alloca(len); ret = snprintf(options, len, "upperdir=%s,lowerdir=%s,%s", upper, lower, mntdata); len2 = strlen(lower) + strlen(upper) + strlen(work) + strlen("upperdir=,lowerdir=,workdir=") + strlen(mntdata) + 1; options_work = alloca(len2); ret2 = snprintf(options, len2, "upperdir=%s,lowerdir=%s,workdir=%s,%s", upper, lower, work, mntdata); } else { len = strlen(lower) + strlen(upper) + strlen("upperdir=,lowerdir=") + 1; options = alloca(len); ret = snprintf(options, len, "upperdir=%s,lowerdir=%s", upper, lower); len2 = strlen(lower) + strlen(upper) + strlen(work) + strlen("upperdir=,lowerdir=,workdir=") + 1; options_work = alloca(len2); ret2 = snprintf(options_work, len2, "upperdir=%s,lowerdir=%s,workdir=%s", upper, lower, work); } if (ret < 0 || ret >= len || ret2 < 0 || ret2 >= len2) { free(mntdata); return -1; } /* Assume we need a workdir as we are on a overlay version >= v22. */ ret = ovl_remount_on_enodev(lower, bdev->dest, ovl_name, MS_MGC_VAL | mntflags, options_work); if (ret < 0) { INFO("Overlayfs: Error mounting %s onto %s with options %s. " "Retrying without workdir: %s.", lower, bdev->dest, options_work, strerror(errno)); /* Assume we cannot use a workdir as we are on a version <= v21. */ ret = ovl_remount_on_enodev(lower, bdev->dest, ovl_name, MS_MGC_VAL | mntflags, options); if (ret < 0) SYSERROR("Overlayfs: Error mounting %s onto %s with " "options %s: %s.", lower, bdev->dest, options, strerror(errno)); else INFO("Overlayfs: Mounted %s onto %s with options %s.", lower, bdev->dest, options); } else { INFO("Overlayfs: Mounted %s onto %s with options %s.", lower, bdev->dest, options_work); } return ret; } int ovl_umount(struct bdev *bdev) { if (strcmp(bdev->type, "overlayfs")) return -22; if (!bdev->src || !bdev->dest) return -22; return umount(bdev->dest); } char *ovl_get_rootfs(const char *rootfs_path, size_t *rootfslen) { char *rootfsdir = NULL; char *s1 = NULL; char *s2 = NULL; char *s3 = NULL; if (!rootfs_path || !rootfslen) return NULL; s1 = strdup(rootfs_path); if (!s1) return NULL; if ((s2 = strstr(s1, ":/"))) { s2 = s2 + 1; if ((s3 = strstr(s2, ":/"))) *s3 = '\0'; rootfsdir = strdup(s2); if (!rootfsdir) { free(s1); return NULL; } } if (!rootfsdir) rootfsdir = s1; else free(s1); *rootfslen = strlen(rootfsdir); return rootfsdir; } int ovl_mkdir(const struct mntent *mntent, const struct lxc_rootfs *rootfs, const char *lxc_name, const char *lxc_path) { char lxcpath[MAXPATHLEN]; char *rootfs_path = NULL; char *rootfsdir = NULL; char *upperdir = NULL; char *workdir = NULL; char **opts = NULL; int fret = -1; int ret = 0; size_t arrlen = 0; size_t dirlen = 0; size_t i; size_t len = 0; size_t rootfslen = 0; /* When rootfs == NULL we have a container without a rootfs. */ if (rootfs && rootfs->path) rootfs_path = rootfs->path; opts = lxc_string_split(mntent->mnt_opts, ','); if (opts) arrlen = lxc_array_len((void **)opts); else goto err; for (i = 0; i < arrlen; i++) { if (strstr(opts[i], "upperdir=") && (strlen(opts[i]) > (len = strlen("upperdir=")))) upperdir = opts[i] + len; else if (strstr(opts[i], "workdir=") && (strlen(opts[i]) > (len = strlen("workdir=")))) workdir = opts[i] + len; } if (rootfs_path) { ret = snprintf(lxcpath, MAXPATHLEN, "%s/%s", lxc_path, lxc_name); if (ret < 0 || ret >= MAXPATHLEN) goto err; rootfsdir = ovl_get_rootfs(rootfs_path, &rootfslen); if (!rootfsdir) goto err; dirlen = strlen(lxcpath); } /* * We neither allow users to create upperdirs and workdirs outside the * containerdir nor inside the rootfs. The latter might be debatable. * When we have a container without a rootfs we skip the checks. */ ret = 0; if (upperdir) { if (!rootfs_path) ret = mkdir_p(upperdir, 0755); else if ((strncmp(upperdir, lxcpath, dirlen) == 0) && (strncmp(upperdir, rootfsdir, rootfslen) != 0)) ret = mkdir_p(upperdir, 0755); if (ret < 0) WARN("Failed to create upperdir"); } ret = 0; if (workdir) { if (!rootfs_path) ret = mkdir_p(workdir, 0755); else if ((strncmp(workdir, lxcpath, dirlen) == 0) && (strncmp(workdir, rootfsdir, rootfslen) != 0)) ret = mkdir_p(workdir, 0755); if (ret < 0) WARN("Failed to create workdir"); } fret = 0; err: free(rootfsdir); lxc_free_array((void **)opts, free); return fret; } /* * To be called from lxcapi_clone() in lxccontainer.c: When we clone a container * with overlay lxc.mount.entry entries we need to update absolute paths for * upper- and workdir. This update is done in two locations: * lxc_conf->unexpanded_config and lxc_conf->mount_list. Both updates are done * independent of each other since lxc_conf->mountlist may container more mount * entries (e.g. from other included files) than lxc_conf->unexpanded_config . */ int ovl_update_abs_paths(struct lxc_conf *lxc_conf, const char *lxc_path, const char *lxc_name, const char *newpath, const char *newname) { char new_upper[MAXPATHLEN]; char new_work[MAXPATHLEN]; char old_upper[MAXPATHLEN]; char old_work[MAXPATHLEN]; char *cleanpath = NULL; size_t i; int fret = -1; int ret = 0; struct lxc_list *iterator; const char *ovl_dirs[] = {"br", "upperdir", "workdir"}; cleanpath = strdup(newpath); if (!cleanpath) goto err; remove_trailing_slashes(cleanpath); /* * We have to update lxc_conf->unexpanded_config separately from * lxc_conf->mount_list. */ for (i = 0; i < sizeof(ovl_dirs) / sizeof(ovl_dirs[0]); i++) { if (!clone_update_unexp_ovl_paths(lxc_conf, lxc_path, newpath, lxc_name, newname, ovl_dirs[i])) goto err; } ret = snprintf(old_work, MAXPATHLEN, "workdir=%s/%s", lxc_path, lxc_name); if (ret < 0 || ret >= MAXPATHLEN) goto err; ret = snprintf(new_work, MAXPATHLEN, "workdir=%s/%s", cleanpath, newname); if (ret < 0 || ret >= MAXPATHLEN) goto err; lxc_list_for_each(iterator, &lxc_conf->mount_list) { char *mnt_entry = NULL; char *new_mnt_entry = NULL; char *tmp = NULL; char *tmp_mnt_entry = NULL; mnt_entry = iterator->elem; if (strstr(mnt_entry, "overlay")) tmp = "upperdir"; else if (strstr(mnt_entry, "aufs")) tmp = "br"; if (!tmp) continue; ret = snprintf(old_upper, MAXPATHLEN, "%s=%s/%s", tmp, lxc_path, lxc_name); if (ret < 0 || ret >= MAXPATHLEN) goto err; ret = snprintf(new_upper, MAXPATHLEN, "%s=%s/%s", tmp, cleanpath, newname); if (ret < 0 || ret >= MAXPATHLEN) goto err; if (strstr(mnt_entry, old_upper)) { tmp_mnt_entry = lxc_string_replace(old_upper, new_upper, mnt_entry); } if (strstr(mnt_entry, old_work)) { if (tmp_mnt_entry) new_mnt_entry = lxc_string_replace(old_work, new_work, tmp_mnt_entry); else new_mnt_entry = lxc_string_replace(old_work, new_work, mnt_entry); } if (new_mnt_entry) { free(iterator->elem); iterator->elem = strdup(new_mnt_entry); } else if (tmp_mnt_entry) { free(iterator->elem); iterator->elem = strdup(tmp_mnt_entry); } free(new_mnt_entry); free(tmp_mnt_entry); } fret = 0; err: free(cleanpath); return fret; } static int ovl_remount_on_enodev(const char *lower, const char *target, const char *name, unsigned long mountflags, const void *options) { int ret; ret = mount(lower, target, ovl_name, MS_MGC_VAL | mountflags, options); if (ret < 0 && errno == ENODEV) /* Try other module name. */ ret = mount(lower, target, ovl_name == ovl_version[0] ? ovl_version[1] : ovl_version[0], MS_MGC_VAL | mountflags, options); return ret; } static int ovl_rsync(struct rsync_data *data) { int ret; if (setgid(0) < 0) { ERROR("Failed to setgid to 0"); return -1; } if (setgroups(0, NULL) < 0) WARN("Failed to clear groups"); if (setuid(0) < 0) { ERROR("Failed to setuid to 0"); return -1; } if (unshare(CLONE_NEWNS) < 0) { SYSERROR("Unable to unshare mounts ns"); return -1; } if (detect_shared_rootfs()) { if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) { SYSERROR("Failed to make / rslave"); ERROR("Continuing..."); } } if (ovl_mount(data->orig) < 0) { ERROR("Failed mounting original container fs"); return -1; } if (ovl_mount(data->new) < 0) { ERROR("Failed mounting new container fs"); return -1; } ret = do_rsync(data->orig->dest, data->new->dest); ovl_umount(data->new); ovl_umount(data->orig); if (ret < 0) { ERROR("rsyncing %s to %s", data->orig->dest, data->new->dest); return -1; } return 0; } static char *ovl_detect_name(void) { char *v = ovl_version[0]; char *line = NULL; size_t len = 0; FILE *f = fopen("/proc/filesystems", "r"); if (!f) return v; while (getline(&line, &len, f) != -1) { if (strcmp(line, "nodev\toverlayfs\n") == 0) { v = ovl_version[1]; break; } } fclose(f); free(line); return v; } static int ovl_do_rsync(struct bdev *orig, struct bdev *new, struct lxc_conf *conf) { int ret = -1; struct rsync_data rdata; rdata.orig = orig; rdata.new = new; if (am_unpriv()) ret = userns_exec_1(conf, ovl_rsync_wrapper, &rdata); else ret = ovl_rsync(&rdata); if (ret) ERROR("copying overlayfs delta"); return ret; } static int ovl_rsync_wrapper(void *data) { struct rsync_data *arg = data; return ovl_rsync(arg); } lxc-2.0.8/src/lxc/bdev/lxcrbd.c0000644061062106075000000001020013105116772013153 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */ #include /* Required for PRIu64 to work. */ #include #include #include #include #include "bdev.h" #include "log.h" #include "utils.h" lxc_log_define(lxcrbd, lxc); int rbd_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, int snap, uint64_t newsize, struct lxc_conf *conf) { ERROR("rbd clonepaths not implemented"); return -1; } int rbd_create(struct bdev *bdev, const char *dest, const char *n, struct bdev_specs *specs) { const char *rbdpool, *rbdname = n, *fstype; uint64_t size; int ret, len; char sz[24]; pid_t pid; if (!specs) return -1; rbdpool = specs->rbd.rbdpool; if (!rbdpool) rbdpool = lxc_global_config_value("lxc.bdev.rbd.rbdpool"); if (specs->rbd.rbdname) rbdname = specs->rbd.rbdname; /* source device /dev/rbd/lxc/ctn */ len = strlen(rbdpool) + strlen(rbdname) + 11; bdev->src = malloc(len); if (!bdev->src) return -1; ret = snprintf(bdev->src, len, "/dev/rbd/%s/%s", rbdpool, rbdname); if (ret < 0 || ret >= len) return -1; // fssize is in bytes. size = specs->fssize; if (!size) size = DEFAULT_FS_SIZE; // in megabytes for rbd tool ret = snprintf(sz, 24, "%"PRIu64, size / 1024 / 1024 ); if (ret < 0 || ret >= 24) exit(1); if ((pid = fork()) < 0) return -1; if (!pid) { execlp("rbd", "rbd", "create" , "--pool", rbdpool, rbdname, "--size", sz, (char *)NULL); exit(1); } if (wait_for_pid(pid) < 0) return -1; if ((pid = fork()) < 0) return -1; if (!pid) { execlp("rbd", "rbd", "map", "--pool", rbdpool, rbdname, (char *)NULL); exit(1); } if (wait_for_pid(pid) < 0) return -1; fstype = specs->fstype; if (!fstype) fstype = DEFAULT_FSTYPE; if (do_mkfs(bdev->src, fstype) < 0) { ERROR("Error creating filesystem type %s on %s", fstype, bdev->src); return -1; } if (!(bdev->dest = strdup(dest))) return -1; if (mkdir_p(bdev->dest, 0755) < 0 && errno != EEXIST) { ERROR("Error creating %s", bdev->dest); return -1; } return 0; } int rbd_destroy(struct bdev *orig) { pid_t pid; char *rbdfullname; if ( file_exists(orig->src) ) { if ((pid = fork()) < 0) return -1; if (!pid) { execlp("rbd", "rbd", "unmap" , orig->src, (char *)NULL); exit(1); } if (wait_for_pid(pid) < 0) return -1; } if ((pid = fork()) < 0) return -1; if (!pid) { rbdfullname = alloca(strlen(orig->src) - 8); strcpy( rbdfullname, &orig->src[9] ); execlp("rbd", "rbd", "rm" , rbdfullname, (char *)NULL); exit(1); } return wait_for_pid(pid); } int rbd_detect(const char *path) { if ( memcmp(path, "/dev/rbd/", 9) == 0) return 1; return 0; } int rbd_mount(struct bdev *bdev) { if (strcmp(bdev->type, "rbd")) return -22; if (!bdev->src || !bdev->dest) return -22; if ( !file_exists(bdev->src) ) { // if blkdev does not exist it should be mapped, because it is not persistent on reboot ERROR("Block device %s is not mapped.", bdev->src); return -1; } return mount_unknown_fs(bdev->src, bdev->dest, bdev->mntopts); } int rbd_umount(struct bdev *bdev) { if (strcmp(bdev->type, "rbd")) return -22; if (!bdev->src || !bdev->dest) return -22; return umount(bdev->dest); } lxc-2.0.8/src/lxc/bdev/bdev.h0000644061062106075000000001131213105116772012627 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_BDEV_H #define __LXC_BDEV_H /* blockdev operations for: * aufs, dir, raw, btrfs, overlayfs, aufs, lvm, loop, zfs, nbd (qcow2, raw, vdi, qed) */ #include #include #include #include "config.h" /* define constants if the kernel/glibc headers don't define them */ #ifndef MS_DIRSYNC #define MS_DIRSYNC 128 #endif #ifndef MS_REC #define MS_REC 16384 #endif #ifndef MNT_DETACH #define MNT_DETACH 2 #endif #ifndef MS_SLAVE #define MS_SLAVE (1 << 19) #endif #ifndef MS_RELATIME #define MS_RELATIME (1 << 21) #endif #ifndef MS_STRICTATIME #define MS_STRICTATIME (1 << 24) #endif #define DEFAULT_FS_SIZE 1073741824 #define DEFAULT_FSTYPE "ext3" struct bdev; struct bdev_ops { /* detect whether path is of this bdev type */ int (*detect)(const char *path); // mount requires src and dest to be set. int (*mount)(struct bdev *bdev); int (*umount)(struct bdev *bdev); int (*destroy)(struct bdev *bdev); int (*create)(struct bdev *bdev, const char *dest, const char *n, struct bdev_specs *specs); /* given original mount, rename the paths for cloned container */ int (*clone_paths)(struct bdev *orig, struct bdev *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, int snap, uint64_t newsize, struct lxc_conf *conf); bool can_snapshot; bool can_backup; }; /* * When lxc-start (conf.c) is mounting a rootfs, then src will be the * 'lxc.rootfs' value, dest will be mount dir (i.e. $libdir/lxc) When clone * or create is doing so, then dest will be $lxcpath/$lxcname/rootfs, since * we may need to rsync from one to the other. * data is so far unused. */ struct bdev { const struct bdev_ops *ops; const char *type; char *src; char *dest; char *mntopts; // turn the following into a union if need be // lofd is the open fd for the mounted loopback file int lofd; // index for the connected nbd device int nbd_idx; }; bool bdev_is_dir(struct lxc_conf *conf, const char *path); bool bdev_can_backup(struct lxc_conf *conf); /* * Instantiate a bdev object. The src is used to determine which blockdev * type this should be. The dst and data are optional, and will be used * in case of mount/umount. * * Optionally, src can be 'dir:/var/lib/lxc/c1' or 'lvm:/dev/lxc/c1'. For * other backing stores, this will allow additional options. In particular, * "overlayfs:/var/lib/lxc/canonical/rootfs:/var/lib/lxc/c1/delta" will mean * use /var/lib/lxc/canonical/rootfs as lower dir, and /var/lib/lxc/c1/delta * as the upper, writeable layer. */ struct bdev *bdev_init(struct lxc_conf *conf, const char *src, const char *dst, const char *data); struct bdev *bdev_copy(struct lxc_container *c0, const char *cname, const char *lxcpath, const char *bdevtype, int flags, const char *bdevdata, uint64_t newsize, int *needs_rdep); struct bdev *bdev_create(const char *dest, const char *type, const char *cname, struct bdev_specs *specs); void bdev_put(struct bdev *bdev); bool bdev_destroy(struct lxc_conf *conf); /* callback function to be used with userns_exec_1() */ int bdev_destroy_wrapper(void *data); /* Some helpers for lvm, rdb, and/or loop: * Maybe they should move to a separate implementation and header-file * (bdev_utils.{c,h}) which can be included in bdev.c? */ int blk_getsize(struct bdev *bdev, uint64_t *size); int detect_fs(struct bdev *bdev, char *type, int len); int do_mkfs(const char *path, const char *fstype); int is_blktype(struct bdev *b); int mount_unknown_fs(const char *rootfs, const char *target, const char *options); bool rootfs_is_blockdev(struct lxc_conf *conf); /* * these are really for qemu-nbd support, as container shutdown * must explicitly request device detach. */ bool attach_block_device(struct lxc_conf *conf); void detach_block_device(struct lxc_conf *conf); bool is_valid_bdev_type(const char *type); #endif // __LXC_BDEV_H lxc-2.0.8/src/lxc/bdev/lxcnbd.c0000644061062106075000000001475513105116772013172 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "bdev.h" #include "log.h" #include "lxcnbd.h" #include "utils.h" lxc_log_define(lxcnbd, lxc); struct nbd_attach_data { const char *nbd; const char *path; }; static bool clone_attach_nbd(const char *nbd, const char *path); static int do_attach_nbd(void *d); static bool nbd_busy(int idx); static void nbd_detach(const char *path); static int nbd_get_partition(const char *src); static bool wait_for_partition(const char *path); bool attach_nbd(char *src, struct lxc_conf *conf) { char *orig = alloca(strlen(src)+1), *p, path[50]; int i = 0; strcpy(orig, src); /* if path is followed by a partition, drop that for now */ p = strchr(orig, ':'); if (p) *p = '\0'; while (1) { sprintf(path, "/dev/nbd%d", i); if (!file_exists(path)) return false; if (nbd_busy(i)) { i++; continue; } if (!clone_attach_nbd(path, orig)) return false; conf->nbd_idx = i; return true; } } void detach_nbd_idx(int idx) { int ret; char path[50]; ret = snprintf(path, 50, "/dev/nbd%d", idx); if (ret < 0 || ret >= 50) return; nbd_detach(path); } int nbd_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, int snap, uint64_t newsize, struct lxc_conf *conf) { return -ENOSYS; } int nbd_create(struct bdev *bdev, const char *dest, const char *n, struct bdev_specs *specs) { return -ENOSYS; } int nbd_destroy(struct bdev *orig) { return -ENOSYS; } int nbd_detect(const char *path) { if (strncmp(path, "nbd:", 4) == 0) return 1; return 0; } int nbd_mount(struct bdev *bdev) { int ret = -1, partition; char path[50]; if (strcmp(bdev->type, "nbd")) return -22; if (!bdev->src || !bdev->dest) return -22; /* nbd_idx should have been copied by bdev_init from the lxc_conf */ if (bdev->nbd_idx < 0) return -22; partition = nbd_get_partition(bdev->src); if (partition) ret = snprintf(path, 50, "/dev/nbd%dp%d", bdev->nbd_idx, partition); else ret = snprintf(path, 50, "/dev/nbd%d", bdev->nbd_idx); if (ret < 0 || ret >= 50) { ERROR("Error setting up nbd device path"); return ret; } /* It might take awhile for the partition files to show up */ if (partition) { if (!wait_for_partition(path)) return -2; } ret = mount_unknown_fs(path, bdev->dest, bdev->mntopts); if (ret < 0) ERROR("Error mounting %s", bdev->src); return ret; } int nbd_umount(struct bdev *bdev) { int ret; if (strcmp(bdev->type, "nbd")) return -22; if (!bdev->src || !bdev->dest) return -22; ret = umount(bdev->dest); return ret; } bool requires_nbd(const char *path) { if (strncmp(path, "nbd:", 4) == 0) return true; return false; } static int do_attach_nbd(void *d) { struct nbd_attach_data *data = d; const char *nbd, *path; pid_t pid; sigset_t mask; int sfd; ssize_t s; struct signalfd_siginfo fdsi; sigemptyset(&mask); sigaddset(&mask, SIGHUP); sigaddset(&mask, SIGCHLD); nbd = data->nbd; path = data->path; if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) { SYSERROR("Error blocking signals for nbd watcher"); exit(1); } sfd = signalfd(-1, &mask, 0); if (sfd == -1) { SYSERROR("Error opening signalfd for nbd task"); exit(1); } if (prctl(PR_SET_PDEATHSIG, SIGHUP, 0, 0, 0) < 0) SYSERROR("Error setting parent death signal for nbd watcher"); pid = fork(); if (pid) { for (;;) { s = read(sfd, &fdsi, sizeof(struct signalfd_siginfo)); if (s != sizeof(struct signalfd_siginfo)) SYSERROR("Error reading from signalfd"); if (fdsi.ssi_signo == SIGHUP) { /* container has exited */ nbd_detach(nbd); exit(0); } else if (fdsi.ssi_signo == SIGCHLD) { int status; /* If qemu-nbd fails, or is killed by a signal, * then exit */ while (waitpid(-1, &status, WNOHANG) > 0) { if ((WIFEXITED(status) && WEXITSTATUS(status) != 0) || WIFSIGNALED(status)) { nbd_detach(nbd); exit(1); } } } } } close(sfd); if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1) WARN("Warning: unblocking signals for nbd watcher"); execlp("qemu-nbd", "qemu-nbd", "-c", nbd, path, (char *)NULL); SYSERROR("Error executing qemu-nbd"); exit(1); } static bool clone_attach_nbd(const char *nbd, const char *path) { pid_t pid; struct nbd_attach_data data; data.nbd = nbd; data.path = path; pid = lxc_clone(do_attach_nbd, &data, CLONE_NEWPID); if (pid < 0) return false; return true; } static bool nbd_busy(int idx) { char path[100]; int ret; ret = snprintf(path, 100, "/sys/block/nbd%d/pid", idx); if (ret < 0 || ret >= 100) return true; return file_exists(path); } static void nbd_detach(const char *path) { int ret; pid_t pid = fork(); if (pid < 0) { SYSERROR("Error forking to detach nbd"); return; } if (pid) { ret = wait_for_pid(pid); if (ret < 0) ERROR("nbd disconnect returned an error"); return; } execlp("qemu-nbd", "qemu-nbd", "-d", path, (char *)NULL); SYSERROR("Error executing qemu-nbd"); exit(1); } /* * Pick the partition # off the end of a nbd:file:p * description. Return 1-9 for the partition id, or 0 * for no partition. */ static int nbd_get_partition(const char *src) { char *p = strchr(src, ':'); if (!p) return 0; p = strchr(p+1, ':'); if (!p) return 0; p++; if (*p < '1' || *p > '9') return 0; return *p - '0'; } static bool wait_for_partition(const char *path) { int count = 0; while (count < 5) { if (file_exists(path)) return true; sleep(1); count++; } ERROR("Device %s did not show up after 5 seconds", path); return false; } lxc-2.0.8/src/lxc/monitor.c0000644061062106075000000002336613105116772012465 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * Dwight Engen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "af_unix.h" #include "error.h" #include "log.h" #include "lxclock.h" #include "monitor.h" #include "state.h" #include "utils.h" lxc_log_define(lxc_monitor, lxc); /* routines used by monitor publishers (containers) */ int lxc_monitor_fifo_name(const char *lxcpath, char *fifo_path, size_t fifo_path_sz, int do_mkdirp) { int ret; char *rundir; rundir = get_rundir(); if (!rundir) return -1; if (do_mkdirp) { ret = snprintf(fifo_path, fifo_path_sz, "%s/lxc/%s", rundir, lxcpath); if (ret < 0 || (size_t)ret >= fifo_path_sz) { ERROR("rundir/lxcpath (%s/%s) too long for monitor fifo.", rundir, lxcpath); free(rundir); return -1; } ret = mkdir_p(fifo_path, 0755); if (ret < 0) { ERROR("Unable to create monitor fifo directory %s.", fifo_path); free(rundir); return ret; } } ret = snprintf(fifo_path, fifo_path_sz, "%s/lxc/%s/monitor-fifo", rundir, lxcpath); if (ret < 0 || (size_t)ret >= fifo_path_sz) { ERROR("rundir/lxcpath (%s/%s) too long for monitor fifo.", rundir, lxcpath); free(rundir); return -1; } free(rundir); return 0; } static void lxc_monitor_fifo_send(struct lxc_msg *msg, const char *lxcpath) { int fd,ret; char fifo_path[PATH_MAX]; BUILD_BUG_ON(sizeof(*msg) > PIPE_BUF); /* write not guaranteed atomic */ ret = lxc_monitor_fifo_name(lxcpath, fifo_path, sizeof(fifo_path), 0); if (ret < 0) return; /* Open the fifo nonblock in case the monitor is dead, we don't want the * open to wait for a reader since it may never come. */ fd = open(fifo_path, O_WRONLY | O_NONBLOCK); if (fd < 0) { /* It is normal for this open() to fail with ENXIO when there is * no monitor running, so we don't log it. */ if (errno == ENXIO) return; WARN("Failed to open fifo to send message: %s.", strerror(errno)); return; } if (fcntl(fd, F_SETFL, O_WRONLY) < 0) { close(fd); return; } ret = write(fd, msg, sizeof(*msg)); if (ret != sizeof(*msg)) { close(fd); SYSERROR("Failed to write to monitor fifo \"%s\".", fifo_path); return; } close(fd); } void lxc_monitor_send_state(const char *name, lxc_state_t state, const char *lxcpath) { struct lxc_msg msg = {.type = lxc_msg_state, .value = state}; strncpy(msg.name, name, sizeof(msg.name)); msg.name[sizeof(msg.name) - 1] = 0; lxc_monitor_fifo_send(&msg, lxcpath); } void lxc_monitor_send_exit_code(const char *name, int exit_code, const char *lxcpath) { struct lxc_msg msg = {.type = lxc_msg_exit_code, .value = exit_code}; strncpy(msg.name, name, sizeof(msg.name)); msg.name[sizeof(msg.name) - 1] = 0; lxc_monitor_fifo_send(&msg, lxcpath); } /* routines used by monitor subscribers (lxc-monitor) */ int lxc_monitor_close(int fd) { return close(fd); } /* Enforces \0-termination for the abstract unix socket. This is not required * but allows us to print it out. * * Older version of liblxc only allowed for 105 bytes to be used for the * abstract unix domain socket name because the code for our abstract unix * socket handling performed invalid checks. Since we \0-terminate we could now * have a maximum of 106 chars. But to not break backwards compatibility we keep * the limit at 105. */ int lxc_monitor_sock_name(const char *lxcpath, struct sockaddr_un *addr) { size_t len; int ret; char *path; uint64_t hash; /* addr.sun_path is only 108 bytes, so we hash the full name and * then append as much of the name as we can fit. */ memset(addr, 0, sizeof(*addr)); addr->sun_family = AF_UNIX; /* strlen("lxc/") + strlen("/monitor-sock") + 1 = 18 */ len = strlen(lxcpath) + 18; path = alloca(len); ret = snprintf(path, len, "lxc/%s/monitor-sock", lxcpath); if (ret < 0 || (size_t)ret >= len) { ERROR("failed to create name for monitor socket"); return -1; } /* Note: snprintf() will \0-terminate addr->sun_path on the 106th byte * and so the abstract socket name has 105 "meaningful" characters. This * is absolutely intentional. For further info read the comment for this * function above! */ len = sizeof(addr->sun_path) - 1; hash = fnv_64a_buf(path, ret, FNV1A_64_INIT); ret = snprintf(addr->sun_path, len, "@lxc/%016" PRIx64 "/%s", hash, lxcpath); if (ret < 0) { ERROR("failed to create hashed name for monitor socket"); return -1; } /* replace @ with \0 */ addr->sun_path[0] = '\0'; INFO("using monitor socket name \"%s\" (length of socket name %zu must be <= %zu)", &addr->sun_path[1], strlen(&addr->sun_path[1]), sizeof(addr->sun_path) - 3); return 0; } int lxc_monitor_open(const char *lxcpath) { struct sockaddr_un addr; int fd; size_t retry; size_t len; int ret = -1; int backoff_ms[] = {10, 50, 100}; if (lxc_monitor_sock_name(lxcpath, &addr) < 0) return -1; fd = socket(PF_UNIX, SOCK_STREAM, 0); if (fd < 0) { ERROR("Failed to create socket: %s.", strerror(errno)); return -errno; } len = strlen(&addr.sun_path[1]); DEBUG("opening monitor socket %s with len %zu", &addr.sun_path[1], len); if (len >= sizeof(addr.sun_path) - 1) { errno = ENAMETOOLONG; ret = -errno; ERROR("name of monitor socket too long (%zu bytes): %s", len, strerror(errno)); goto on_error; } for (retry = 0; retry < sizeof(backoff_ms) / sizeof(backoff_ms[0]); retry++) { fd = lxc_abstract_unix_connect(addr.sun_path); if (fd < 0 || errno != ECONNREFUSED) break; ERROR("Failed to connect to monitor socket. Retrying in %d ms: %s", backoff_ms[retry], strerror(errno)); usleep(backoff_ms[retry] * 1000); } if (fd < 0) { ret = -errno; ERROR("Failed to connect to monitor socket: %s.", strerror(errno)); goto on_error; } ret = 0; return fd; on_error: close(fd); return ret; } int lxc_monitor_read_fdset(struct pollfd *fds, nfds_t nfds, struct lxc_msg *msg, int timeout) { long i; int ret; ret = poll(fds, nfds, timeout * 1000); if (ret == -1) return -1; else if (ret == 0) return -2; // timed out /* Only read from the first ready fd, the others will remain ready for * when this routine is called again. */ for (i = 0; i < nfds; i++) { if (fds[i].revents != 0) { fds[i].revents = 0; ret = recv(fds[i].fd, msg, sizeof(*msg), 0); if (ret <= 0) { SYSERROR("Failed to receive message. Did monitord die?: %s.", strerror(errno)); return -1; } return ret; } } SYSERROR("No ready fd found."); return -1; } int lxc_monitor_read_timeout(int fd, struct lxc_msg *msg, int timeout) { struct pollfd fds; fds.fd = fd; fds.events = POLLIN | POLLPRI; fds.revents = 0; return lxc_monitor_read_fdset(&fds, 1, msg, timeout); } int lxc_monitor_read(int fd, struct lxc_msg *msg) { return lxc_monitor_read_timeout(fd, msg, -1); } #define LXC_MONITORD_PATH LIBEXECDIR "/lxc/lxc-monitord" /* Used to spawn a monitord either on startup of a daemon container, or when * lxc-monitor starts. */ int lxc_monitord_spawn(const char *lxcpath) { int ret; int pipefd[2]; char pipefd_str[LXC_NUMSTRLEN64]; pid_t pid1, pid2; char *const args[] = { LXC_MONITORD_PATH, (char *)lxcpath, pipefd_str, NULL, }; /* double fork to avoid zombies when monitord exits */ pid1 = fork(); if (pid1 < 0) { SYSERROR("Failed to fork()."); return -1; } if (pid1) { DEBUG("Going to wait for pid %d.", pid1); if (waitpid(pid1, NULL, 0) != pid1) return -1; DEBUG("Finished waiting on pid %d.", pid1); return 0; } if (pipe(pipefd) < 0) { SYSERROR("Failed to create pipe."); exit(EXIT_FAILURE); } pid2 = fork(); if (pid2 < 0) { SYSERROR("Failed to fork()."); exit(EXIT_FAILURE); } if (pid2) { DEBUG("Trying to sync with child process."); char c; /* Wait for daemon to create socket. */ close(pipefd[1]); /* Sync with child, we're ignoring the return from read * because regardless if it works or not, either way we've * synced with the child process. the if-empty-statement * construct is to quiet the warn-unused-result warning. */ if (read(pipefd[0], &c, 1)) ; close(pipefd[0]); DEBUG("Successfully synced with child process."); exit(EXIT_SUCCESS); } if (setsid() < 0) { SYSERROR("Failed to setsid()."); exit(EXIT_FAILURE); } lxc_check_inherited(NULL, true, pipefd[1]); if (null_stdfds() < 0) { SYSERROR("Failed to dup2() standard file descriptors to /dev/null."); exit(EXIT_FAILURE); } close(pipefd[0]); ret = snprintf(pipefd_str, LXC_NUMSTRLEN64, "%d", pipefd[1]); if (ret < 0 || ret >= LXC_NUMSTRLEN64) { ERROR("Failed to create pid argument to pass to monitord."); exit(EXIT_FAILURE); } DEBUG("Using pipe file descriptor %d for monitord.", pipefd[1]); execvp(args[0], args); SYSERROR("failed to exec lxc-monitord"); exit(EXIT_FAILURE); } lxc-2.0.8/src/lxc/network.h0000644061062106075000000000773013105116772012471 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_NETWORK_H #define __LXC_NETWORK_H /* * Convert a string mac address to a socket structure */ extern int lxc_convert_mac(char *macaddr, struct sockaddr *sockaddr); /* * Move a device between namespaces */ extern int lxc_netdev_move_by_index(int ifindex, pid_t pid, const char* ifname); extern int lxc_netdev_move_by_name(const char *ifname, pid_t pid, const char* newname); /* * Delete a network device */ extern int lxc_netdev_delete_by_name(const char *name); extern int lxc_netdev_delete_by_index(int ifindex); /* * Change the device name */ extern int lxc_netdev_rename_by_name(const char *oldname, const char *newname); extern int lxc_netdev_rename_by_index(int ifindex, const char *newname); extern int netdev_set_flag(const char *name, int flag); /* * Set the device network up or down */ extern int lxc_netdev_isup(const char *name); extern int lxc_netdev_up(const char *name); extern int lxc_netdev_down(const char *name); /* * Change the mtu size for the specified device */ extern int lxc_netdev_set_mtu(const char *name, int mtu); /* * Create a virtual network devices */ extern int lxc_veth_create(const char *name1, const char *name2); extern int lxc_macvlan_create(const char *master, const char *name, int mode); extern int lxc_vlan_create(const char *master, const char *name, unsigned short vid); /* * Activate forwarding */ extern int lxc_ip_forward_on(const char *name, int family); /* * Disable forwarding */ extern int lxc_ip_forward_off(const char *name, int family); /* * Set ip address */ extern int lxc_ipv6_addr_add(int ifindex, struct in6_addr *addr, struct in6_addr *mcast, struct in6_addr *acast, int prefix); extern int lxc_ipv4_addr_add(int ifindex, struct in_addr *addr, struct in_addr *bcast, int prefix); /* * Get ip address */ extern int lxc_ipv4_addr_get(int ifindex, struct in_addr **res); extern int lxc_ipv6_addr_get(int ifindex, struct in6_addr **res); /* * Set a destination route to an interface */ extern int lxc_ipv4_dest_add(int ifindex, struct in_addr *dest); extern int lxc_ipv6_dest_add(int ifindex, struct in6_addr *dest); /* * Set default route. */ extern int lxc_ipv4_gateway_add(int ifindex, struct in_addr *gw); extern int lxc_ipv6_gateway_add(int ifindex, struct in6_addr *gw); /* * Attach an interface to the bridge */ extern int lxc_bridge_attach(const char *lxcpath, const char *name, const char *bridge, const char *ifname); /* * Create default gateway */ extern int lxc_route_create_default(const char *addr, const char *ifname, int gateway); /* * Delete default gateway */ extern int lxc_route_delete_default(const char *addr, const char *ifname, int gateway); /* * Activate neighbor proxying */ extern int lxc_neigh_proxy_on(const char *name, int family); /* * Disable neighbor proxying */ extern int lxc_neigh_proxy_off(const char *name, int family); /* * Generate a new unique network interface name */ extern char *lxc_mkifname(char *template); extern const char *lxc_net_type_to_str(int type); extern int setup_private_host_hw_addr(char *veth1); extern int netdev_get_mtu(int ifindex); #endif lxc-2.0.8/src/lxc/start.c0000644061062106075000000011613213105116772012125 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if HAVE_LIBCAP #include #endif #if !HAVE_DECL_PR_CAPBSET_DROP #define PR_CAPBSET_DROP 24 #endif #include "af_unix.h" #include "bdev.h" #include "caps.h" #include "cgroup.h" #include "commands.h" #include "conf.h" #include "console.h" #include "error.h" #include "log.h" #include "lxclock.h" #include "lxcseccomp.h" #include "lxcutmp.h" #include "mainloop.h" #include "monitor.h" #include "namespace.h" #include "start.h" #include "sync.h" #include "utils.h" #include "lsm/lsm.h" lxc_log_define(lxc_start, lxc); extern void mod_all_rdeps(struct lxc_container *c, bool inc); static bool do_destroy_container(struct lxc_conf *conf); static int lxc_rmdir_onedev_wrapper(void *data); static void lxc_destroy_container_on_signal(struct lxc_handler *handler, const char *name); static void print_top_failing_dir(const char *path) { size_t len = strlen(path); char *copy = alloca(len + 1), *p, *e, saved; strcpy(copy, path); p = copy; e = copy + len; while (p < e) { while (p < e && *p == '/') p++; while (p < e && *p != '/') p++; saved = *p; *p = '\0'; if (access(copy, X_OK)) { SYSERROR("Could not access %s. Please grant it x " "access, or add an ACL for the container " "root.", copy); return; } *p = saved; } } static void close_ns(int ns_fd[LXC_NS_MAX]) { int i; for (i = 0; i < LXC_NS_MAX; i++) { if (ns_fd[i] > -1) { close(ns_fd[i]); ns_fd[i] = -1; } } } /* preserve_ns: open /proc/@pid/ns/@ns for each namespace specified * in clone_flags. * Return true on success, false on failure. */ static bool preserve_ns(int ns_fd[LXC_NS_MAX], int clone_flags, pid_t pid) { int i, ret; for (i = 0; i < LXC_NS_MAX; i++) ns_fd[i] = -1; ret = lxc_preserve_ns(pid, ""); if (ret < 0) { SYSERROR("Kernel does not support attaching to namespaces."); return false; } else { close(ret); } for (i = 0; i < LXC_NS_MAX; i++) { if ((clone_flags & ns_info[i].clone_flag) == 0) continue; ns_fd[i] = lxc_preserve_ns(pid, ns_info[i].proc_name); if (ns_fd[i] < 0) goto error; } return true; error: if (errno == ENOENT) SYSERROR("Kernel does not support attaching to %s namespaces.", ns_info[i].proc_name); else SYSERROR("Failed to open file descriptor for %s namespace: %s.", ns_info[i].proc_name, strerror(errno)); close_ns(ns_fd); return false; } static int attach_ns(const int ns_fd[LXC_NS_MAX]) { int i; for (i = 0; i < LXC_NS_MAX; i++) { if (ns_fd[i] < 0) continue; if (setns(ns_fd[i], 0) != 0) goto error; } return 0; error: SYSERROR("Failed to attach %s namespace.", ns_info[i].proc_name); return -1; } static int match_fd(int fd) { return (fd == 0 || fd == 1 || fd == 2); } /* Check for any fds we need to close. * - If fd_to_ignore != -1, then if we find that fd open we will ignore it. * - By default we warn about open fds we find. * - If closeall is true, we will close open fds. * - If lxc-start was passed "-C", then conf->close_all_fds will be true, in * which case we also close all open fds. * - A daemonized container will always pass closeall=true. */ int lxc_check_inherited(struct lxc_conf *conf, bool closeall, int fd_to_ignore) { struct dirent *direntp; int fd, fddir; DIR *dir; if (conf && conf->close_all_fds) closeall = true; restart: dir = opendir("/proc/self/fd"); if (!dir) { WARN("Failed to open directory: %m."); return -1; } fddir = dirfd(dir); while ((direntp = readdir(dir))) { if (!direntp) break; if (!strcmp(direntp->d_name, ".")) continue; if (!strcmp(direntp->d_name, "..")) continue; if (lxc_safe_int(direntp->d_name, &fd) < 0) { INFO("Could not parse file descriptor for: %s", direntp->d_name); continue; } if (fd == fddir || fd == lxc_log_fd || fd == fd_to_ignore) continue; if (current_config && fd == current_config->logfd) continue; if (match_fd(fd)) continue; if (closeall) { close(fd); closedir(dir); INFO("Closed inherited fd: %d.", fd); goto restart; } WARN("Inherited fd: %d.", fd); } closedir(dir); /* cannot fail */ return 0; } static int setup_signal_fd(sigset_t *oldmask) { sigset_t mask; int fd; /* Block everything except serious error signals. */ if (sigfillset(&mask) || sigdelset(&mask, SIGILL) || sigdelset(&mask, SIGSEGV) || sigdelset(&mask, SIGBUS) || sigdelset(&mask, SIGWINCH) || sigprocmask(SIG_BLOCK, &mask, oldmask)) { SYSERROR("Failed to set signal mask."); return -1; } fd = signalfd(-1, &mask, 0); if (fd < 0) { SYSERROR("Failed to create signal file descriptor."); return -1; } if (fcntl(fd, F_SETFD, FD_CLOEXEC)) { SYSERROR("Failed to set FD_CLOEXEC on the signal file descriptor: %d.", fd); close(fd); return -1; } DEBUG("Set SIGCHLD handler with file descriptor: %d.", fd); return fd; } static int signal_handler(int fd, uint32_t events, void *data, struct lxc_epoll_descr *descr) { struct signalfd_siginfo siginfo; siginfo_t info; int ret; pid_t *pid = data; bool init_died = false; ret = read(fd, &siginfo, sizeof(siginfo)); if (ret < 0) { ERROR("Failed to read signal info from signal file descriptor: %d.", fd); return -1; } if (ret != sizeof(siginfo)) { ERROR("Unexpected size for siginfo struct."); return -1; } /* Check whether init is running. */ info.si_pid = 0; ret = waitid(P_PID, *pid, &info, WEXITED | WNOWAIT | WNOHANG); if (ret == 0 && info.si_pid == *pid) init_died = true; if (siginfo.ssi_signo != SIGCHLD) { kill(*pid, siginfo.ssi_signo); INFO("Forwarded signal %d to pid %d.", siginfo.ssi_signo, *pid); return init_died ? 1 : 0; } if (siginfo.ssi_code == CLD_STOPPED) { INFO("Container init process was stopped."); return init_died ? 1 : 0; } else if (siginfo.ssi_code == CLD_CONTINUED) { INFO("Container init process was continued."); return init_died ? 1 : 0; } /* More robustness, protect ourself from a SIGCHLD sent * by a process different from the container init. */ if (siginfo.ssi_pid != *pid) { NOTICE("Received SIGCHLD from pid %d instead of container init %d.", siginfo.ssi_pid, *pid); return init_died ? 1 : 0; } DEBUG("Container init process %d exited.", *pid); return 1; } int lxc_set_state(const char *name, struct lxc_handler *handler, lxc_state_t state) { handler->state = state; lxc_monitor_send_state(name, state, handler->lxcpath); return 0; } int lxc_poll(const char *name, struct lxc_handler *handler) { int sigfd = handler->sigfd; int pid = handler->pid; struct lxc_epoll_descr descr; if (lxc_mainloop_open(&descr)) { ERROR("Failed to create LXC mainloop."); goto out_sigfd; } if (lxc_mainloop_add_handler(&descr, sigfd, signal_handler, &pid)) { ERROR("Failed to add signal handler with file descriptor %d to LXC mainloop.", sigfd); goto out_mainloop_open; } if (lxc_console_mainloop_add(&descr, handler->conf)) { ERROR("Failed to add console handler to LXC mainloop."); goto out_mainloop_open; } if (lxc_cmd_mainloop_add(name, &descr, handler)) { ERROR("Failed to add command handler to LXC mainloop."); goto out_mainloop_open; } if (handler->conf->need_utmp_watch) { #if HAVE_LIBCAP if (lxc_utmp_mainloop_add(&descr, handler)) { ERROR("Failed to add utmp handler to LXC mainloop."); goto out_mainloop_open; } #else DEBUG("Not starting utmp handler as CAP_SYS_BOOT cannot be dropped without capabilities support."); #endif } return lxc_mainloop(&descr, -1); out_mainloop_open: lxc_mainloop_close(&descr); out_sigfd: close(sigfd); return -1; } struct lxc_handler *lxc_init(const char *name, struct lxc_conf *conf, const char *lxcpath) { int i; struct lxc_handler *handler; handler = malloc(sizeof(*handler)); if (!handler) return NULL; memset(handler, 0, sizeof(*handler)); handler->ttysock[0] = handler->ttysock[1] = -1; handler->conf = conf; handler->lxcpath = lxcpath; handler->pinfd = -1; for (i = 0; i < LXC_NS_MAX; i++) handler->nsfd[i] = -1; lsm_init(); handler->name = strdup(name); if (!handler->name) { ERROR("Failed to allocate memory."); goto out_free; } if (lxc_cmd_init(name, handler, lxcpath)) goto out_free_name; if (lxc_read_seccomp_config(conf) != 0) { ERROR("Failed loading seccomp policy."); goto out_close_maincmd_fd; } /* Begin by setting the state to STARTING. */ if (lxc_set_state(name, handler, STARTING)) { ERROR("Failed to set state for container \"%s\" to \"%s\".", name, lxc_state2str(STARTING)); goto out_close_maincmd_fd; } /* Start of environment variable setup for hooks. */ if (name && setenv("LXC_NAME", name, 1)) SYSERROR("Failed to set environment variable: LXC_NAME=%s.", name); if (conf->rcfile && setenv("LXC_CONFIG_FILE", conf->rcfile, 1)) SYSERROR("Failed to set environment variable: LXC_CONFIG_FILE=%s.", conf->rcfile); if (conf->rootfs.mount && setenv("LXC_ROOTFS_MOUNT", conf->rootfs.mount, 1)) SYSERROR("Failed to set environment variable: LXC_ROOTFS_MOUNT=%s.", conf->rootfs.mount); if (conf->rootfs.path && setenv("LXC_ROOTFS_PATH", conf->rootfs.path, 1)) SYSERROR("Failed to set environment variable: LXC_ROOTFS_PATH=%s.", conf->rootfs.path); if (conf->console.path && setenv("LXC_CONSOLE", conf->console.path, 1)) SYSERROR("Failed to set environment variable: LXC_CONSOLE=%s.", conf->console.path); if (conf->console.log_path && setenv("LXC_CONSOLE_LOGPATH", conf->console.log_path, 1)) SYSERROR("Failed to set environment variable: LXC_CONSOLE_LOGPATH=%s.", conf->console.log_path); if (setenv("LXC_CGNS_AWARE", "1", 1)) SYSERROR("Failed to set environment variable LXC_CGNS_AWARE=1."); /* End of environment variable setup for hooks. */ if (run_lxc_hooks(name, "pre-start", conf, handler->lxcpath, NULL)) { ERROR("Failed to run lxc.hook.pre-start for container \"%s\".", name); goto out_aborting; } /* The signal fd has to be created before forking otherwise if the child * process exits before we setup the signal fd, the event will be lost * and the command will be stuck. */ handler->sigfd = setup_signal_fd(&handler->oldmask); if (handler->sigfd < 0) { ERROR("Failed to setup SIGCHLD fd handler."); goto out_delete_tty; } /* Do this after setting up signals since it might unblock SIGWINCH. */ if (lxc_console_create(conf)) { ERROR("Failed to create console for container \"%s\".", name); goto out_restore_sigmask; } if (ttys_shift_ids(conf) < 0) { ERROR("Failed to shift tty into container."); goto out_restore_sigmask; } INFO("Container \"%s\" is initialized.", name); return handler; out_restore_sigmask: sigprocmask(SIG_SETMASK, &handler->oldmask, NULL); out_delete_tty: lxc_delete_tty(&conf->tty_info); out_aborting: lxc_set_state(name, handler, ABORTING); out_close_maincmd_fd: close(conf->maincmd_fd); conf->maincmd_fd = -1; out_free_name: free(handler->name); handler->name = NULL; out_free: free(handler); return NULL; } void lxc_fini(const char *name, struct lxc_handler *handler) { int i, rc; pid_t self = getpid(); char *namespaces[LXC_NS_MAX+1]; size_t namespace_count = 0; /* The STOPPING state is there for future cleanup code which can take * awhile. */ lxc_set_state(name, handler, STOPPING); for (i = 0; i < LXC_NS_MAX; i++) { if (handler->nsfd[i] != -1) { rc = asprintf(&namespaces[namespace_count], "%s:/proc/%d/fd/%d", ns_info[i].proc_name, self, handler->nsfd[i]); if (rc == -1) { SYSERROR("Failed to allocate memory."); break; } ++namespace_count; } } namespaces[namespace_count] = NULL; if (handler->conf->reboot && setenv("LXC_TARGET", "reboot", 1)) SYSERROR("Failed to set environment variable: LXC_TARGET=reboot."); if (!handler->conf->reboot && setenv("LXC_TARGET", "stop", 1)) SYSERROR("Failed to set environment variable: LXC_TARGET=stop."); if (run_lxc_hooks(name, "stop", handler->conf, handler->lxcpath, namespaces)) ERROR("Failed to run lxc.hook.stop for container \"%s\".", name); while (namespace_count--) free(namespaces[namespace_count]); for (i = 0; i < LXC_NS_MAX; i++) { if (handler->nsfd[i] != -1) { close(handler->nsfd[i]); handler->nsfd[i] = -1; } } if (handler->netnsfd >= 0) { close(handler->netnsfd); handler->netnsfd = -1; } lxc_set_state(name, handler, STOPPED); if (run_lxc_hooks(name, "post-stop", handler->conf, handler->lxcpath, NULL)) { ERROR("Failed to run lxc.hook.post-stop for container \"%s\".", name); if (handler->conf->reboot) { WARN("Container will be stopped instead of rebooted."); handler->conf->reboot = 0; if (setenv("LXC_TARGET", "stop", 1)) WARN("Failed to set environment variable: LXC_TARGET=stop."); } } /* Reset mask set by setup_signal_fd. */ if (sigprocmask(SIG_SETMASK, &handler->oldmask, NULL)) WARN("Failed to restore signal mask."); lxc_console_delete(&handler->conf->console); lxc_delete_tty(&handler->conf->tty_info); close(handler->conf->maincmd_fd); handler->conf->maincmd_fd = -1; free(handler->name); if (handler->ttysock[0] != -1) { close(handler->ttysock[0]); close(handler->ttysock[1]); } if (handler->conf->ephemeral == 1 && handler->conf->reboot != 1) lxc_destroy_container_on_signal(handler, name); cgroup_destroy(handler); free(handler); } void lxc_abort(const char *name, struct lxc_handler *handler) { int ret, status; lxc_set_state(name, handler, ABORTING); if (handler->pid > 0) kill(handler->pid, SIGKILL); while ((ret = waitpid(-1, &status, 0)) > 0) { ; } } #include #include /* reboot(LINUX_REBOOT_CMD_CAD_ON) will return -EINVAL in a child pid namespace * if container reboot support exists. Otherwise, it will either succeed or * return -EPERM. */ static int container_reboot_supported(void *arg) { int *cmd = arg; int ret; ret = reboot(*cmd); if (ret == -1 && errno == EINVAL) return 1; return 0; } static int must_drop_cap_sys_boot(struct lxc_conf *conf) { FILE *f; int ret, cmd, v, flags; long stack_size = 4096; void *stack = alloca(stack_size); int status; pid_t pid; f = fopen("/proc/sys/kernel/ctrl-alt-del", "r"); if (!f) { DEBUG("failed to open /proc/sys/kernel/ctrl-alt-del"); return 1; } ret = fscanf(f, "%d", &v); fclose(f); if (ret != 1) { DEBUG("Failed to read /proc/sys/kernel/ctrl-alt-del."); return 1; } cmd = v ? LINUX_REBOOT_CMD_CAD_ON : LINUX_REBOOT_CMD_CAD_OFF; flags = CLONE_NEWPID | SIGCHLD; if (!lxc_list_empty(&conf->id_map)) flags |= CLONE_NEWUSER; #ifdef __ia64__ pid = __clone2(container_reboot_supported, stack, stack_size, flags, &cmd); #else stack += stack_size; pid = clone(container_reboot_supported, stack, flags, &cmd); #endif if (pid < 0) { if (flags & CLONE_NEWUSER) ERROR("Failed to clone (%#x): %s (includes CLONE_NEWUSER).", flags, strerror(errno)); else ERROR("Failed to clone (%#x): %s.", flags, strerror(errno)); return -1; } if (wait(&status) < 0) { SYSERROR("Unexpected wait error: %m."); return -1; } if (WEXITSTATUS(status) != 1) return 1; return 0; } /* netpipe is used in the unprivileged case to transfer the ifindexes from * parent to child */ static int netpipe = -1; static inline int count_veths(struct lxc_list *network) { struct lxc_list *iterator; struct lxc_netdev *netdev; int count = 0; lxc_list_for_each(iterator, network) { netdev = iterator->elem; if (netdev->type != LXC_NET_VETH) continue; count++; } return count; } static int read_unpriv_netifindex(struct lxc_list *network) { struct lxc_list *iterator; struct lxc_netdev *netdev; if (netpipe == -1) return 0; lxc_list_for_each(iterator, network) { netdev = iterator->elem; if (netdev->type != LXC_NET_VETH) continue; if (!(netdev->name = malloc(IFNAMSIZ))) { ERROR("Out of memory."); close(netpipe); return -1; } if (read(netpipe, netdev->name, IFNAMSIZ) != IFNAMSIZ) { close(netpipe); return -1; } } close(netpipe); return 0; } static int do_start(void *data) { struct lxc_list *iterator; struct lxc_handler *handler = data; int devnull_fd = -1, ret; char path[PATH_MAX]; if (sigprocmask(SIG_SETMASK, &handler->oldmask, NULL)) { SYSERROR("Failed to set signal mask."); return -1; } /* This prctl must be before the synchro, so if the parent dies before * we set the parent death signal, we will detect its death with the * synchro right after, otherwise we have a window where the parent can * exit before we set the pdeath signal leading to a unsupervized * container. */ if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) { SYSERROR("Failed to set PR_SET_PDEATHSIG to SIGKILL."); return -1; } lxc_sync_fini_parent(handler); /* Don't leak the pinfd to the container. */ if (handler->pinfd >= 0) { close(handler->pinfd); } if (lxc_sync_wait_parent(handler, LXC_SYNC_STARTUP)) return -1; /* Unshare CLONE_NEWNET after CLONE_NEWUSER. See * https://github.com/lxc/lxd/issues/1978. */ if ((handler->clone_flags & (CLONE_NEWNET | CLONE_NEWUSER)) == (CLONE_NEWNET | CLONE_NEWUSER)) { ret = unshare(CLONE_NEWNET); if (ret < 0) { SYSERROR("Failed to unshare CLONE_NEWNET."); goto out_warn_father; } INFO("Unshared CLONE_NEWNET."); } /* Tell the parent task it can begin to configure the container and wait * for it to finish. */ if (lxc_sync_barrier_parent(handler, LXC_SYNC_CONFIGURE)) return -1; if (read_unpriv_netifindex(&handler->conf->network) < 0) goto out_warn_father; /* If we are in a new user namespace, become root there to have * privilege over our namespace. */ if (!lxc_list_empty(&handler->conf->id_map)) { if (lxc_switch_uid_gid(0, 0) < 0) goto out_warn_father; /* Drop groups only after we switched to a valid gid in the new * user namespace. */ if (lxc_setgroups(0, NULL) < 0) goto out_warn_father; } if (access(handler->lxcpath, X_OK)) { print_top_failing_dir(handler->lxcpath); goto out_warn_father; } #if HAVE_LIBCAP if (handler->conf->need_utmp_watch) { if (prctl(PR_CAPBSET_DROP, CAP_SYS_BOOT, 0, 0, 0)) { SYSERROR("Failed to remove the CAP_SYS_BOOT capability."); goto out_warn_father; } DEBUG("Dropped the CAP_SYS_BOOT capability."); } #endif ret = snprintf(path, sizeof(path), "%s/dev/null", handler->conf->rootfs.mount); if (ret < 0 || ret >= sizeof(path)) goto out_warn_father; /* In order to checkpoint restore, we need to have everything in the * same mount namespace. However, some containers may not have a * reasonable /dev (in particular, they may not have /dev/null), so we * can't set init's std fds to /dev/null by opening it from inside the * container. * * If that's the case, fall back to using the host's /dev/null. This * means that migration won't work, but at least we won't spew output * where it isn't wanted. */ if (handler->backgrounded && !handler->conf->autodev && access(path, F_OK) < 0) { devnull_fd = open_devnull(); if (devnull_fd < 0) goto out_warn_father; WARN("Using /dev/null from the host for container init's " "standard file descriptors. Migration will not work."); } /* Setup the container, ip, names, utsname, ... */ if (lxc_setup(handler)) { ERROR("Failed to setup container \"%s\".", handler->name); goto out_warn_father; } /* Ask father to setup cgroups and wait for him to finish. */ if (lxc_sync_barrier_parent(handler, LXC_SYNC_CGROUP)) goto out_error; /* Unshare cgroup namespace after we have setup our cgroups. If we do it * earlier we end up with a wrong view of /proc/self/cgroup. For * example, assume we unshare(CLONE_NEWCGROUP) first, and then create * the cgroup for the container, say /sys/fs/cgroup/cpuset/lxc/c, then * /proc/self/cgroup would show us: * * 8:cpuset:/lxc/c * * whereas it should actually show * * 8:cpuset:/ */ if (cgns_supported()) { if (unshare(CLONE_NEWCGROUP) < 0) { INFO("Failed to unshare CLONE_NEWCGROUP."); goto out_warn_father; } INFO("Unshared CLONE_NEWCGROUP."); } /* Set the label to change to when we exec(2) the container's init. */ if (lsm_process_label_set(NULL, handler->conf, 1, 1) < 0) goto out_warn_father; /* Some init's such as busybox will set sane tty settings on stdin, * stdout, stderr which it thinks is the console. We already set them * the way we wanted on the real terminal, and we want init to do its * setup on its console ie. the pty allocated in lxc_console_create() so * make sure that that pty is stdin,stdout,stderr. */ if (lxc_console_set_stdfds(handler->conf->console.slave) < 0) goto out_warn_father; /* If we mounted a temporary proc, then unmount it now. */ tmp_proc_unmount(handler->conf); if (lxc_seccomp_load(handler->conf) != 0) goto out_warn_father; if (run_lxc_hooks(handler->name, "start", handler->conf, handler->lxcpath, NULL)) { ERROR("Failed to run lxc.hook.start for container \"%s\".", handler->name); goto out_warn_father; } /* The container has been setup. We can now switch to an unprivileged * uid/gid. */ if (handler->conf->is_execute) { bool have_cap_setgid; uid_t new_uid = handler->conf->init_uid; gid_t new_gid = handler->conf->init_gid; /* If we are in a new user namespace we already dropped all * groups when we switched to root in the new user namespace * further above. Only drop groups if we can, so ensure that we * have necessary privilege. */ #if HAVE_LIBCAP have_cap_setgid = lxc_proc_cap_is_set(CAP_SETGID, CAP_EFFECTIVE); #else have_cap_setgid = false; #endif if (lxc_list_empty(&handler->conf->id_map) && have_cap_setgid) { if (lxc_setgroups(0, NULL) < 0) goto out_warn_father; } if (lxc_switch_uid_gid(new_uid, new_gid) < 0) goto out_warn_father; } /* The clearenv() and putenv() calls have been moved here to allow us to * use environment variables passed to the various hooks, such as the * start hook above. Not all of the variables like CONFIG_PATH or ROOTFS * are valid in this context but others are. */ if (clearenv()) { SYSERROR("Failed to clear environment."); /* Don't error out though. */ } lxc_list_for_each(iterator, &handler->conf->environment) { if (putenv((char *)iterator->elem)) { SYSERROR("Failed to set environment variable: %s.", (char *)iterator->elem); goto out_warn_father; } } if (putenv("container=lxc")) { SYSERROR("Failed to set environment variable: container=lxc."); goto out_warn_father; } if (handler->conf->pty_names) { if (putenv(handler->conf->pty_names)) { SYSERROR("Failed to set environment variable for container ptys."); goto out_warn_father; } } close(handler->sigfd); if (devnull_fd < 0) { devnull_fd = open_devnull(); if (devnull_fd < 0) goto out_warn_father; } if (handler->backgrounded && set_stdfds(devnull_fd)) goto out_warn_father; if (devnull_fd >= 0) { close(devnull_fd); devnull_fd = -1; } setsid(); /* After this call, we are in error because this ops should not return * as it execs. */ handler->ops->start(handler, handler->data); out_warn_father: /* We want the parent to know something went wrong, so we return a * special error code. */ lxc_sync_wake_parent(handler, LXC_SYNC_ERROR); out_error: if (devnull_fd >= 0) close(devnull_fd); return -1; } static int save_phys_nics(struct lxc_conf *conf) { struct lxc_list *iterator; int am_root = (getuid() == 0); if (!am_root) return 0; lxc_list_for_each(iterator, &conf->network) { struct lxc_netdev *netdev = iterator->elem; if (netdev->type != LXC_NET_PHYS) continue; conf->saved_nics = realloc(conf->saved_nics, (conf->num_savednics+1)*sizeof(struct saved_nic)); if (!conf->saved_nics) return -1; conf->saved_nics[conf->num_savednics].ifindex = netdev->ifindex; conf->saved_nics[conf->num_savednics].orig_name = strdup(netdev->link); if (!conf->saved_nics[conf->num_savednics].orig_name) return -1; INFO("Stored saved_nic #%d idx %d name %s.", conf->num_savednics, conf->saved_nics[conf->num_savednics].ifindex, conf->saved_nics[conf->num_savednics].orig_name); conf->num_savednics++; } return 0; } static int recv_fd(int sock, int *fd) { if (lxc_abstract_unix_recv_fd(sock, fd, NULL, 0) < 0) { SYSERROR("Error receiving tty file descriptor from child process."); return -1; } if (*fd == -1) return -1; return 0; } static int recv_ttys_from_child(struct lxc_handler *handler) { struct lxc_conf *conf = handler->conf; int i, sock = handler->ttysock[1]; struct lxc_tty_info *tty_info = &conf->tty_info; if (!conf->tty) return 0; tty_info->pty_info = malloc(sizeof(*tty_info->pty_info) * conf->tty); if (!tty_info->pty_info) return -1; for (i = 0; i < conf->tty; i++) { struct lxc_pty_info *pty_info = &tty_info->pty_info[i]; pty_info->busy = 0; if (recv_fd(sock, &pty_info->slave) < 0 || recv_fd(sock, &pty_info->master) < 0) { ERROR("Error receiving tty info from child process."); return -1; } } tty_info->nbtty = conf->tty; 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)) 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."); } /* lxc_spawn() performs crucial setup tasks and clone()s the new process which * exec()s the requested container binary. * Note that lxc_spawn() runs in the parent namespaces. Any operations performed * right here should be double checked if they'd pose a security risk. (For * example, any {u}mount() operations performed here will be reflected on the * host!) */ static int lxc_spawn(struct lxc_handler *handler) { int failed_before_rename = 0; const char *name = handler->name; bool cgroups_connected = false; int saved_ns_fd[LXC_NS_MAX]; int preserve_mask = 0, i, flags; int netpipepair[2], nveths; netpipe = -1; for (i = 0; i < LXC_NS_MAX; i++) if (handler->conf->inherit_ns_fd[i] != -1) preserve_mask |= ns_info[i].clone_flag; if (lxc_sync_init(handler)) return -1; if (socketpair(AF_UNIX, SOCK_DGRAM, 0, handler->ttysock) < 0) { lxc_sync_fini(handler); return -1; } 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 * no longer accessible inside the container. Do this * before creating network interfaces, since goto * out_delete_net does not work before lxc_clone. */ if (lxc_find_gateway_addresses(handler)) { ERROR("Failed to find gateway addresses."); lxc_sync_fini(handler); return -1; } /* That should be done before the clone because we will * fill the netdev index and use them in the child. */ if (lxc_create_network(handler)) { ERROR("Failed to create the network."); lxc_sync_fini(handler); return -1; } } if (save_phys_nics(handler->conf)) { ERROR("Failed to save physical nic info."); goto out_abort; } } if (!cgroup_init(handler)) { ERROR("Failed initializing cgroup support."); goto out_delete_net; } cgroups_connected = true; if (!cgroup_create(handler)) { ERROR("Failed creating cgroups."); goto out_delete_net; } /* If the rootfs is not a blockdev, prevent the container from marking * it readonly. * If the container is unprivileged then skip rootfs pinning. */ if (lxc_list_empty(&handler->conf->id_map)) { handler->pinfd = pin_rootfs(handler->conf->rootfs.path); if (handler->pinfd == -1) INFO("Failed to pin the rootfs for container \"%s\".", handler->name); } if (!preserve_ns(saved_ns_fd, preserve_mask, getpid())) goto out_delete_net; if (attach_ns(handler->conf->inherit_ns_fd) < 0) goto out_delete_net; if (am_unpriv() && (nveths = count_veths(&handler->conf->network))) { if (pipe(netpipepair) < 0) { SYSERROR("Failed to create pipe."); goto out_delete_net; } /* Store netpipe in the global var for do_start's use. */ netpipe = netpipepair[0]; } /* Create a process in a new set of namespaces. */ flags = handler->clone_flags; if (handler->clone_flags & CLONE_NEWUSER) { /* If CLONE_NEWUSER and CLONE_NEWNET was requested, we need to * clone a new user namespace first and only later unshare our * network namespace to ensure that network devices ownership is * set up correctly. */ flags &= ~CLONE_NEWNET; } handler->pid = lxc_clone(do_start, handler, flags); if (handler->pid < 0) { SYSERROR("Failed to clone a new set of namespaces."); goto out_delete_net; } for (i = 0; i < LXC_NS_MAX; i++) if (flags & ns_info[i].clone_flag) INFO("Cloned %s.", ns_info[i].flag_name); if (!preserve_ns(handler->nsfd, handler->clone_flags | preserve_mask, handler->pid)) INFO("Failed to preserve namespace for lxc.hook.stop."); if (attach_ns(saved_ns_fd)) WARN("Failed to restore saved namespaces."); lxc_sync_fini_child(handler); /* Map the container uids. The container became an invalid userid the * moment it was cloned with CLONE_NEWUSER. This call doesn't change * anything immediately, but allows the container to setuid(0) (0 being * mapped to something else on the host.) later to become a valid uid * again. */ if (lxc_map_ids(&handler->conf->id_map, handler->pid)) { ERROR("Failed to set up id mapping."); goto out_delete_net; } if (lxc_sync_wake_child(handler, LXC_SYNC_STARTUP)) { failed_before_rename = 1; goto out_delete_net; } if (lxc_sync_wait_child(handler, LXC_SYNC_CONFIGURE)) { failed_before_rename = 1; goto out_delete_net; } if (!cgroup_create_legacy(handler)) { ERROR("Failed to setup legacy cgroups for container \"%s\".", name); goto out_delete_net; } if (!cgroup_setup_limits(handler, false)) { ERROR("Failed to setup cgroup limits for container \"%s\".", name); goto out_delete_net; } if (!cgroup_enter(handler)) goto out_delete_net; if (!cgroup_chown(handler)) goto out_delete_net; if (failed_before_rename) goto out_delete_net; /* Create the network configuration. */ if (handler->clone_flags & CLONE_NEWNET) { if (lxc_assign_network(handler->lxcpath, handler->name, &handler->conf->network, handler->pid)) { ERROR("Failed to create the configured network."); goto out_delete_net; } } if (netpipe != -1) { struct lxc_list *iterator; struct lxc_netdev *netdev; close(netpipe); lxc_list_for_each(iterator, &handler->conf->network) { netdev = iterator->elem; if (netdev->type != LXC_NET_VETH) continue; if (write(netpipepair[1], netdev->name, IFNAMSIZ) != IFNAMSIZ) { ERROR("Error writing veth name to container."); goto out_delete_net; } } close(netpipepair[1]); } /* Tell the child to continue its initialization. We'll get * LXC_SYNC_CGROUP when it is ready for us to setup cgroups. */ if (lxc_sync_barrier_child(handler, LXC_SYNC_POST_CONFIGURE)) goto out_delete_net; if (!cgroup_setup_limits(handler, true)) { ERROR("Failed to setup the devices cgroup for container \"%s\".", name); goto out_delete_net; } cgroup_disconnect(); cgroups_connected = false; /* Read tty fds allocated by child. */ if (recv_ttys_from_child(handler) < 0) { ERROR("Failed to receive tty info from child process."); goto out_delete_net; } /* Tell the child to complete its initialization and wait for it to exec * or return an error. (The child will never return * LXC_SYNC_POST_CGROUP+1. It will either close the sync pipe, causing * lxc_sync_barrier_child to return success, or return a different * value, causing us to error out). */ if (lxc_sync_barrier_child(handler, LXC_SYNC_POST_CGROUP)) return -1; if (handler->ops->post_start(handler, handler->data)) goto out_abort; if (lxc_set_state(name, handler, RUNNING)) { ERROR("Failed to set state for container \"%s\" to \"%s\".", name, lxc_state2str(RUNNING)); goto out_abort; } lxc_sync_fini(handler); handler->netnsfd = lxc_preserve_ns(handler->pid, "net"); return 0; out_delete_net: if (cgroups_connected) cgroup_disconnect(); if (handler->clone_flags & CLONE_NEWNET) lxc_delete_network(handler); out_abort: lxc_abort(name, handler); lxc_sync_fini(handler); if (handler->pinfd >= 0) { close(handler->pinfd); handler->pinfd = -1; } return -1; } int __lxc_start(const char *name, struct lxc_conf *conf, struct lxc_operations* ops, void *data, const char *lxcpath, bool backgrounded) { struct lxc_handler *handler; int err = -1; int status; bool removed_all_netdevs = true; handler = lxc_init(name, conf, lxcpath); if (!handler) { ERROR("Failed to initialize container \"%s\".", name); return -1; } handler->ops = ops; handler->data = data; handler->backgrounded = backgrounded; handler->netnsfd = -1; if (must_drop_cap_sys_boot(handler->conf)) { #if HAVE_LIBCAP DEBUG("Dropping CAP_SYS_BOOT capability."); #else DEBUG("Not dropping CAP_SYS_BOOT capability as capabilities aren't supported."); #endif } else { DEBUG("Not dropping CAP_SYS_BOOT or watching utmp."); handler->conf->need_utmp_watch = 0; } if (!attach_block_device(handler->conf)) { ERROR("Failed to attach block device."); goto out_fini_nonet; } if (geteuid() == 0 && !lxc_list_empty(&conf->id_map)) { /* If the backing store is a device, mount it here and now. */ if (rootfs_is_blockdev(conf)) { if (unshare(CLONE_NEWNS) < 0) { ERROR("Failed to unshare CLONE_NEWNS."); goto out_fini_nonet; } INFO("Unshared CLONE_NEWNS."); remount_all_slave(); if (do_rootfs_setup(conf, name, lxcpath) < 0) { ERROR("Error setting up rootfs mount as root before spawn."); goto out_fini_nonet; } INFO("Set up container rootfs as host root."); } } err = lxc_spawn(handler); if (err) { ERROR("Failed to spawn container \"%s\".", name); goto out_detach_blockdev; } handler->conf->reboot = 0; err = lxc_poll(name, handler); if (err) { ERROR("LXC mainloop exited with error: %d.", err); if (handler->netnsfd >= 0) { close(handler->netnsfd); handler->netnsfd = -1; } goto out_abort; } while (waitpid(handler->pid, &status, 0) < 0 && errno == EINTR) continue; /* If the child process exited but was not signaled, it didn't call * reboot. This should mean it was an lxc-execute which simply exited. * In any case, treat it as a 'halt'. */ if (WIFSIGNALED(status)) { switch(WTERMSIG(status)) { case SIGINT: /* halt */ DEBUG("Container \"%s\" is halting.", name); break; case SIGHUP: /* reboot */ DEBUG("Container \"%s\" is rebooting.", name); handler->conf->reboot = 1; break; case SIGSYS: /* seccomp */ DEBUG("Container \"%s\" violated its seccomp policy.", name); break; default: DEBUG("Unknown exit status for container \"%s\" init %d.", name, WTERMSIG(status)); break; } } DEBUG("Pushing physical nics back to host namespace"); lxc_restore_phys_nics_to_netns(handler->netnsfd, handler->conf); DEBUG("Tearing down virtual network devices used by container \"%s\".", name); removed_all_netdevs = lxc_delete_network(handler); if (handler->pinfd >= 0) { close(handler->pinfd); handler->pinfd = -1; } lxc_monitor_send_exit_code(name, status, handler->lxcpath); err = lxc_error_set_and_log(handler->pid, status); out_fini: if (!removed_all_netdevs) { DEBUG("Failed tearing down network devices used by container. Trying again!"); removed_all_netdevs = lxc_delete_network(handler); if (!removed_all_netdevs) DEBUG("Failed tearing down network devices used by container. Not trying again!"); } out_detach_blockdev: detach_block_device(handler->conf); out_fini_nonet: lxc_fini(name, handler); return err; out_abort: lxc_abort(name, handler); goto out_fini; } struct start_args { char *const *argv; }; static int start(struct lxc_handler *handler, void* data) { struct start_args *arg = data; NOTICE("Exec'ing \"%s\".", arg->argv[0]); execvp(arg->argv[0], arg->argv); SYSERROR("Failed to exec \"%s\".", arg->argv[0]); return 0; } static int post_start(struct lxc_handler *handler, void* data) { struct start_args *arg = data; NOTICE("Started \"%s\" with pid \"%d\".", arg->argv[0], handler->pid); return 0; } static struct lxc_operations start_ops = { .start = start, .post_start = post_start }; int lxc_start(const char *name, char *const argv[], struct lxc_conf *conf, const char *lxcpath, bool backgrounded) { struct start_args start_arg = { .argv = argv, }; conf->need_utmp_watch = 1; return __lxc_start(name, conf, &start_ops, &start_arg, lxcpath, backgrounded); } static void lxc_destroy_container_on_signal(struct lxc_handler *handler, const char *name) { char destroy[MAXPATHLEN]; bool bret = true; int ret = 0; struct lxc_container *c; if (handler->conf->rootfs.path && handler->conf->rootfs.mount) { bret = do_destroy_container(handler->conf); if (!bret) { ERROR("Error destroying rootfs for container \"%s\".", name); return; } } INFO("Destroyed rootfs for container \"%s\".", name); ret = snprintf(destroy, MAXPATHLEN, "%s/%s", handler->lxcpath, name); if (ret < 0 || ret >= MAXPATHLEN) { ERROR("Error destroying directory for container \"%s\".", name); return; } c = lxc_container_new(name, handler->lxcpath); if (c) { if (container_disk_lock(c)) { INFO("Could not update lxc_snapshots file."); lxc_container_put(c); } else { mod_all_rdeps(c, false); container_disk_unlock(c); lxc_container_put(c); } } if (am_unpriv()) ret = userns_exec_1(handler->conf, lxc_rmdir_onedev_wrapper, destroy); else ret = lxc_rmdir_onedev(destroy, NULL); if (ret < 0) { ERROR("Error destroying directory for container \"%s\".", name); return; } INFO("Destroyed directory for container \"%s\".", name); } static int lxc_rmdir_onedev_wrapper(void *data) { char *arg = (char *) data; return lxc_rmdir_onedev(arg, NULL); } static bool do_destroy_container(struct lxc_conf *conf) { if (am_unpriv()) { if (userns_exec_1(conf, bdev_destroy_wrapper, conf) < 0) return false; return true; } return bdev_destroy(conf); } lxc-2.0.8/src/lxc/freezer.c0000644061062106075000000000446713105116772012441 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include #include #include #include #include #include #include #include #include "error.h" #include "state.h" #include "monitor.h" #include "log.h" #include "lxc.h" lxc_log_define(lxc_freezer, lxc); lxc_state_t freezer_state(const char *name, const char *lxcpath) { char v[100]; if (lxc_cgroup_get("freezer.state", v, 100, name, lxcpath) < 0) return -1; if (v[strlen(v)-1] == '\n') v[strlen(v)-1] = '\0'; return lxc_str2state(v); } static int do_freeze_thaw(int freeze, const char *name, const char *lxcpath) { char v[100]; const char *state = freeze ? "FROZEN" : "THAWED"; if (lxc_cgroup_set("freezer.state", state, name, lxcpath) < 0) { ERROR("Failed to freeze %s:%s", lxcpath, name); return -1; } while (1) { if (lxc_cgroup_get("freezer.state", v, 100, name, lxcpath) < 0) { ERROR("Failed to get new freezer state for %s:%s", lxcpath, name); return -1; } if (v[strlen(v)-1] == '\n') v[strlen(v)-1] = '\0'; if (strncmp(v, state, strlen(state)) == 0) { if (name) lxc_monitor_send_state(name, freeze ? FROZEN : THAWED, lxcpath); return 0; } sleep(1); } } int lxc_freeze(const char *name, const char *lxcpath) { lxc_monitor_send_state(name, FREEZING, lxcpath); return do_freeze_thaw(1, name, lxcpath); } int lxc_unfreeze(const char *name, const char *lxcpath) { return do_freeze_thaw(0, name, lxcpath); } lxc-2.0.8/src/lxc/attach_options.h0000644061062106075000000001230713105116772014013 00000000000000/*! \file * * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_ATTACH_OPTIONS_H #define __LXC_ATTACH_OPTIONS_H #include #ifdef __cplusplus extern "C" { #endif /*! * LXC environment policy. */ typedef enum lxc_attach_env_policy_t { LXC_ATTACH_KEEP_ENV, //!< Retain the environment LXC_ATTACH_CLEAR_ENV //!< Clear the environment } lxc_attach_env_policy_t; enum { /* the following are on by default: */ LXC_ATTACH_MOVE_TO_CGROUP = 0x00000001, //!< Move to cgroup LXC_ATTACH_DROP_CAPABILITIES = 0x00000002, //!< Drop capabilities LXC_ATTACH_SET_PERSONALITY = 0x00000004, //!< Set personality LXC_ATTACH_LSM_EXEC = 0x00000008, //!< Execute under a Linux Security Module /* the following are off by default */ LXC_ATTACH_REMOUNT_PROC_SYS = 0x00010000, //!< Remount /proc filesystem LXC_ATTACH_LSM_NOW = 0x00020000, //!< FIXME: unknown /* we have 16 bits for things that are on by default * and 16 bits that are off by default, that should * be sufficient to keep binary compatibility for * a while */ LXC_ATTACH_DEFAULT = 0x0000FFFF //!< Mask of flags to apply by default }; /*! All Linux Security Module flags */ #define LXC_ATTACH_LSM (LXC_ATTACH_LSM_EXEC | LXC_ATTACH_LSM_NOW) /*! LXC attach function type. * * Function to run in container. * * \param payload \ref lxc_attach_command_t to run. * * \return Function should return \c 0 on success, and any other value to denote failure. */ typedef int (*lxc_attach_exec_t)(void* payload); /*! * LXC attach options for \ref lxc_container \c attach(). */ typedef struct lxc_attach_options_t { /*! Any combination of LXC_ATTACH_* flags */ int attach_flags; /*! The namespaces to attach to (CLONE_NEW... flags) */ int namespaces; /*! Initial personality (\c -1 to autodetect). * \warning This may be ignored if lxc is compiled without personality support) */ long personality; /*! Initial current directory, use \c NULL to use cwd. * If the current directory does not exist in the container, the * root directory will be used instead because of kernel defaults. */ char* initial_cwd; /*! The user-id to run as. * * \note Set to \c -1 for default behaviour (init uid for userns * containers or \c 0 (super-user) if detection fails). */ uid_t uid; /*! The group-id to run as. * * \note Set to \c -1 for default behaviour (init gid for userns * containers or \c 0 (super-user) if detection fails). */ gid_t gid; /*! Environment policy */ lxc_attach_env_policy_t env_policy; /*! Extra environment variables to set in the container environment */ char** extra_env_vars; /*! Names of environment variables in existing environment to retain * in container environment. */ char** extra_keep_env; /**@{*/ /*! File descriptors for stdin, stdout and stderr, * \c dup2() will be used before calling exec_function, * (assuming not \c 0, \c 1 and \c 2 are specified) and the * original fds are closed before passing control * over. Any \c O_CLOEXEC flag will be removed after * that. */ int stdin_fd; /*!< stdin file descriptor */ int stdout_fd; /*!< stdout file descriptor */ int stderr_fd; /*!< stderr file descriptor */ /**@}*/ } lxc_attach_options_t; /*! Default attach options to use */ #define LXC_ATTACH_OPTIONS_DEFAULT \ { \ /* .attach_flags = */ LXC_ATTACH_DEFAULT, \ /* .namespaces = */ -1, \ /* .personality = */ -1, \ /* .initial_cwd = */ NULL, \ /* .uid = */ (uid_t)-1, \ /* .gid = */ (gid_t)-1, \ /* .env_policy = */ LXC_ATTACH_KEEP_ENV, \ /* .extra_env_vars = */ NULL, \ /* .extra_keep_env = */ NULL, \ /* .stdin_fd = */ 0, 1, 2 \ } /*! * Representation of a command to run in a container. */ typedef struct lxc_attach_command_t { char* program; /*!< The program to run (passed to execvp) */ char** argv; /*!< The argv pointer of that program, including the program itself in argv[0] */ } lxc_attach_command_t; /*! * \brief Run a command in the container. * * \param payload \ref lxc_attach_command_t to run. * * \return \c -1 on error, exit code of lxc_attach_command_t program on success. */ extern int lxc_attach_run_command(void* payload); /*! * \brief Run a shell command in the container. * * \param payload Not used. * * \return Exit code of shell. */ extern int lxc_attach_run_shell(void* payload); #ifdef __cplusplus } #endif #endif lxc-2.0.8/src/lxc/rtnl.h0000644061062106075000000000622413105116772011754 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_RTNL_H #define __LXC_RTNL_H /* * Use this as a good size to allocate route netlink messages */ #define RTNLMSG_GOOD_SIZE NLMSG_GOOD_SIZE #define RTNLMSG_DATA(glh) ((void *)(NLMSG_DATA(glh) + RTNL_HDRLEN)) /* * struct genl_handler : the structure which store the netlink handler * and the family number * * @nlh: the netlink socket handler */ struct rtnl_handler { struct nl_handler nlh; }; /* * struct rtnlmsg : the struct containing the route netlink message * format * * @nlmsghdr: a netlink message header * @rtnlmsghdr: a route netlink message header pointer * */ struct rtnlmsg { struct nlmsghdr nlmsghdr; }; /* * rtnetlink_open : open a route netlink socket * * @handler: a struct rtnl_handler pointer * * Returns 0 on success, < 0 otherwise */ int rtnetlink_open(struct rtnl_handler *handler); /* * genetlink_close : close a route netlink socket * * @handler: the handler of the socket to be closed * * Returns 0 on success, < 0 otherwise */ int rtnetlink_close(struct rtnl_handler *handler); /* * rtnetlink_rcv : receive a route netlink socket, it is up * to the caller to manage the allocation of the route netlink message * * @handler: the handler of the route netlink socket * @rtnlmsg: the pointer to a route netlink message pre-allocated * * Returns 0 on success, < 0 otherwise */ int rtnetlink_rcv(struct rtnl_handler *handler, struct rtnlmsg *rtnlmsg); /* * rtnetlink_send : send a route netlink socket, it is up * to the caller to manage the allocation of the route netlink message * * @handler: the handler of the route netlink socket * @rtnlmsg: the pointer to a netlink message pre-allocated * * Returns 0 on success, < 0 otherwise */ int rtnetlink_send(struct rtnl_handler *handler, struct rtnlmsg *rtnlmsg); struct genlmsg *genlmsg_alloc(size_t size); void rtnlmsg_free(struct rtnlmsg *rtnlmsg); /* * rtnetlink_transaction : send and receive a route netlink message in one shot * * @handler: the handler of the route netlink socket * @request: a route netlink message containing the request to be sent * @answer: a pre-allocated route netlink message to receive the response * * Returns 0 on success, < 0 otherwise */ int rtnetlink_transaction(struct rtnl_handler *handler, struct rtnlmsg *request, struct rtnlmsg *answer); #endif lxc-2.0.8/src/lxc/lxc_user_nic.c0000644061062106075000000005335413105116772013453 00000000000000/* * * Copyright © 2013 Serge Hallyn . * Copyright © 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "network.h" #include "utils.h" #define usernic_debug_stream(stream, format, ...) \ do { \ fprintf(stream, "%s: %d: %s: " format, __FILE__, __LINE__, \ __func__, __VA_ARGS__); \ } while (false) #define usernic_error(format, ...) usernic_debug_stream(stderr, format, __VA_ARGS__) static void usage(char *me, bool fail) { fprintf(stderr, "Usage: %s lxcpath name pid type bridge nicname\n", me); fprintf(stderr, " nicname is the name to use inside the container\n"); exit(fail ? 1 : 0); } static char *lxcpath, *lxcname; static int open_and_lock(char *path) { int fd; struct flock lk; fd = open(path, O_RDWR|O_CREAT, S_IWUSR | S_IRUSR); if (fd < 0) { usernic_error("Failed to open %s: %s.\n", path, strerror(errno)); return -1; } lk.l_type = F_WRLCK; lk.l_whence = SEEK_SET; lk.l_start = 0; lk.l_len = 0; if (fcntl(fd, F_SETLKW, &lk) < 0) { usernic_error("Failed to lock %s: %s.\n", path, strerror(errno)); close(fd); return -1; } return fd; } static char *get_username(void) { struct passwd *pwd; pwd = getpwuid(getuid()); if (!pwd) { usernic_error("Failed to call get username: %s.\n", strerror(errno)); return NULL; } return pwd->pw_name; } static void free_groupnames(char **groupnames) { int i; if (!groupnames) return; for (i = 0; groupnames[i]; i++) free(groupnames[i]); free(groupnames); } static char **get_groupnames(void) { int ngroups; gid_t *group_ids; int ret, i; char **groupnames; struct group *gr; ngroups = getgroups(0, NULL); if (ngroups < 0) { usernic_error( "Failed to get number of groups the user belongs to: %s.\n", strerror(errno)); return NULL; } if (ngroups == 0) return NULL; group_ids = malloc(sizeof(gid_t) * ngroups); if (!group_ids) { usernic_error("Failed to allocate memory while getting groups " "the user belongs to: %s.\n", strerror(errno)); return NULL; } ret = getgroups(ngroups, group_ids); if (ret < 0) { free(group_ids); usernic_error("Failed to get process groups: %s.\n", strerror(errno)); return NULL; } groupnames = malloc(sizeof(char *) * (ngroups + 1)); if (!groupnames) { free(group_ids); usernic_error("Failed to allocate memory while getting group " "names: %s.\n", strerror(errno)); return NULL; } memset(groupnames, 0, sizeof(char *) * (ngroups + 1)); for (i = 0; i < ngroups; i++) { gr = getgrgid(group_ids[i]); if (!gr) { usernic_error("Failed to get group name: %s.\n", strerror(errno)); free(group_ids); free_groupnames(groupnames); return NULL; } groupnames[i] = strdup(gr->gr_name); if (!groupnames[i]) { usernic_error("Failed to copy group name \"%s\".", gr->gr_name); free(group_ids); free_groupnames(groupnames); return NULL; } } free(group_ids); return groupnames; } static bool name_is_in_groupnames(char *name, char **groupnames) { while (groupnames) { if (!strcmp(name, *groupnames)) return true; groupnames++; } return false; } struct alloted_s { char *name; int allowed; struct alloted_s *next; }; static struct alloted_s *append_alloted(struct alloted_s **head, char *name, int n) { struct alloted_s *cur, *al; if (!head || !name) { // sanity check. parameters should not be null usernic_error("%s\n", "Unexpected NULL argument."); return NULL; } al = malloc(sizeof(struct alloted_s)); if (!al) { usernic_error("Failed to allocate memory: %s.\n", strerror(errno)); return NULL; } al->name = strdup(name); if (!al->name) { free(al); return NULL; } al->allowed = n; al->next = NULL; if (!*head) { *head = al; return al; } cur = *head; while (cur->next) cur = cur->next; cur->next = al; return al; } static void free_alloted(struct alloted_s **head) { struct alloted_s *cur; if (!head) return; cur = *head; while (cur) { cur = cur->next; free((*head)->name); free(*head); *head = cur; } } /* The configuration file consists of lines of the form: * * user type bridge count * or * @group type bridge count * * Return the count entry for the calling user if there is one. Else * return -1. */ static int get_alloted(char *me, char *intype, char *link, struct alloted_s **alloted) { int n, ret; char name[100], type[100], br[100]; char **groups; FILE *fin; int count = 0; size_t len = 0; char *line = NULL; fin = fopen(LXC_USERNIC_CONF, "r"); if (!fin) { usernic_error("Failed to open \"%s\": %s.\n", LXC_USERNIC_CONF, strerror(errno)); return -1; } groups = get_groupnames(); while ((getline(&line, &len, fin)) != -1) { ret = sscanf(line, "%99[^ \t] %99[^ \t] %99[^ \t] %d", name, type, br, &n); if (ret != 4) continue; if (strlen(name) == 0) continue; if (strcmp(name, me)) { if (name[0] != '@') continue; if (!name_is_in_groupnames(name + 1, groups)) continue; } if (strcmp(type, intype)) continue; if (strcmp(link, br)) continue; /* Found the user or group with the appropriate settings, * therefore finish the search. What to do if there are more * than one applicable lines? not specified in the docs. Since * getline is implemented with realloc, we don't need to free * line until exiting func. * * If append_alloted returns NULL, e.g. due to a malloc error, * we set count to 0 and break the loop, allowing cleanup and * then exiting from main(). */ if (!append_alloted(alloted, name, n)) { count = 0; break; } count += n; } free_groupnames(groups); fclose(fin); free(line); /* Now return the total number of nics that this user can create. */ return count; } static char *get_eol(char *s, char *e) { while ((s < e) && *s && (*s != '\n')) s++; return s; } static char *get_eow(char *s, char *e) { while ((s < e) && *s && !isblank(*s) && (*s != '\n')) s++; return s; } static char *find_line(char *p, char *e, char *u, char *t, char *l) { char *p1, *p2, *ret; while ((p < e) && (p1 = get_eol(p, e)) < e) { ret = p; if (*p == '#') goto next; while ((p < e) && isblank(*p)) p++; p2 = get_eow(p, e); if (!p2 || ((size_t)(p2 - p)) != strlen(u) || strncmp(p, u, strlen(u))) goto next; p = p2 + 1; while ((p < e) && isblank(*p)) p++; p2 = get_eow(p, e); if (!p2 || ((size_t)(p2 - p)) != strlen(t) || strncmp(p, t, strlen(t))) goto next; p = p2 + 1; while ((p < e) && isblank(*p)) p++; p2 = get_eow(p, e); if (!p2 || ((size_t)(p2 - p)) != strlen(l) || strncmp(p, l, strlen(l))) goto next; return ret; next: p = p1 + 1; } return NULL; } static bool nic_exists(char *nic) { char path[MAXPATHLEN]; int ret; struct stat sb; if (!strcmp(nic, "none")) return true; ret = snprintf(path, MAXPATHLEN, "/sys/class/net/%s", nic); if (ret < 0 || ret >= MAXPATHLEN) return false; ret = stat(path, &sb); if (ret < 0) return false; return true; } static int instantiate_veth(char *n1, char **n2) { int err; err = snprintf(*n2, IFNAMSIZ, "%sp", n1); if (err < 0 || err >= IFNAMSIZ) { usernic_error("%s\n", "Could not create nic name."); return -1; } err = lxc_veth_create(n1, *n2); if (err) { usernic_error("Failed to create %s-%s : %s.\n", n1, *n2, strerror(-err)); return -1; } /* Changing the high byte of the mac address to 0xfe, the bridge * interface will always keep the host's mac address and not take the * mac address of a container. */ err = setup_private_host_hw_addr(n1); if (err) usernic_error("Failed to change mac address of host interface " "%s : %s.\n", n1, strerror(-err)); return netdev_set_flag(n1, IFF_UP); } static int get_mtu(char *name) { int idx; idx = if_nametoindex(name); return netdev_get_mtu(idx); } static bool create_nic(char *nic, char *br, int pid, char **cnic) { char *veth1buf, *veth2buf; int mtu, ret; veth1buf = alloca(IFNAMSIZ); veth2buf = alloca(IFNAMSIZ); if (!veth1buf || !veth2buf) { usernic_error("Failed allocate memory: %s.\n", strerror(errno)); return false; } ret = snprintf(veth1buf, IFNAMSIZ, "%s", nic); if (ret < 0 || ret >= IFNAMSIZ) { usernic_error("%s", "Could not create nic name.\n"); return false; } /* create the nics */ if (instantiate_veth(veth1buf, &veth2buf) < 0) { usernic_error("%s", "Error creating veth tunnel.\n"); return false; } if (strcmp(br, "none")) { /* copy the bridge's mtu to both ends */ mtu = get_mtu(br); if (mtu > 0) { ret = lxc_netdev_set_mtu(veth1buf, mtu); if (ret < 0) { usernic_error("Failed to set mtu to %d on %s.\n", mtu, veth1buf); goto out_del; } ret = lxc_netdev_set_mtu(veth2buf, mtu); if (ret < 0) { usernic_error("Failed to set mtu to %d on %s.\n", mtu, veth2buf); goto out_del; } } /* attach veth1 to bridge */ ret = lxc_bridge_attach(lxcpath, lxcname, br, veth1buf); if (ret < 0) { usernic_error("Error attaching %s to %s.\n", veth1buf, br); goto out_del; } } /* pass veth2 to target netns */ ret = lxc_netdev_move_by_name(veth2buf, pid, NULL); if (ret < 0) { usernic_error("Error moving %s to network namespace of %d.\n", veth2buf, pid); goto out_del; } *cnic = strdup(veth2buf); if (!*cnic) { usernic_error("Failed to copy string \"%s\".\n", veth2buf); return false; } return true; out_del: lxc_netdev_delete_by_name(veth1buf); return false; } /* * Get a new nic. * *dest will contain the name (vethXXXXXX) which is attached * on the host to the lxc bridge */ static bool get_new_nicname(char **dest, char *br, int pid, char **cnic) { int ret; char template[IFNAMSIZ]; ret = snprintf(template, sizeof(template), "vethXXXXXX"); if (ret < 0 || (size_t)ret >= sizeof(template)) return false; *dest = lxc_mkifname(template); if (!create_nic(*dest, br, pid, cnic)) return false; return true; } static bool get_nic_from_line(char *p, char **nic) { int ret; char user[100], type[100], br[100]; ret = sscanf(p, "%99[^ \t\n] %99[^ \t\n] %99[^ \t\n] %99[^ \t\n]", user, type, br, *nic); if (ret != 4) return false; return true; } struct entry_line { char *start; int len; bool keep; }; static bool cull_entries(int fd, char *me, char *t, char *br) { int i, n = 0; off_t len; char *buf, *p, *e, *nic; struct stat sb; struct entry_line *entry_lines = NULL; nic = alloca(100); if (!nic) return false; if (fstat(fd, &sb) < 0) { usernic_error("Failed to fstat: %s.\n", strerror(errno)); return false; } len = sb.st_size; if (len == 0) return true; buf = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (buf == MAP_FAILED) { usernic_error("Failed to establish shared memory mapping: %s.\n", strerror(errno)); return false; } p = buf; e = buf + len; while ((p = find_line(p, e, me, t, br))) { struct entry_line *newe; newe = realloc(entry_lines, sizeof(*entry_lines) * (n + 1)); if (!newe) { free(entry_lines); return false; } entry_lines = newe; entry_lines[n].start = p; entry_lines[n].len = get_eol(p, e) - entry_lines[n].start; entry_lines[n].keep = true; n++; if (!get_nic_from_line(p, &nic)) continue; if (nic && !nic_exists(nic)) entry_lines[n - 1].keep = false; p += entry_lines[n - 1].len + 1; if (p >= e) break; } p = buf; for (i = 0; i < n; i++) { if (!entry_lines[i].keep) continue; memcpy(p, entry_lines[i].start, entry_lines[i].len); p += entry_lines[i].len; *p = '\n'; p++; } free(entry_lines); munmap(buf, sb.st_size); if (ftruncate(fd, p - buf)) usernic_error("Failed to set new file size: %s.\n", strerror(errno)); return true; } static int count_entries(char *buf, off_t len, char *me, char *t, char *br) { char *e; int count = 0; e = &buf[len]; while ((buf = find_line(buf, e, me, t, br))) { count++; buf = get_eol(buf, e) + 1; if (buf >= e) break; } return count; } /* * The dbfile has lines of the format: * user type bridge nicname */ static bool get_nic_if_avail(int fd, struct alloted_s *names, int pid, char *intype, char *br, int allowed, char **nicname, char **cnic) { int ret; off_t len, slen; char *newline, *owner; struct stat sb; struct alloted_s *n; int count = 0; char *buf = NULL; for (n = names; n != NULL; n = n->next) cull_entries(fd, n->name, intype, br); if (allowed == 0) return false; owner = names->name; if (fstat(fd, &sb) < 0) { usernic_error("Failed to fstat: %s.\n", strerror(errno)); return false; } len = sb.st_size; if (len > 0) { buf = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (buf == MAP_FAILED) { usernic_error("Failed to establish shared memory mapping: %s.\n", strerror(errno)); return false; } owner = NULL; for (n = names; n != NULL; n = n->next) { count = count_entries(buf, len, n->name, intype, br); if (count >= n->allowed) continue; owner = n->name; break; } } if (owner == NULL) return false; if (!get_new_nicname(nicname, br, pid, cnic)) return false; /* owner ' ' intype ' ' br ' ' *nicname + '\n' + '\0' */ slen = strlen(owner) + strlen(intype) + strlen(br) + strlen(*nicname) + 5; newline = alloca(slen); if (!newline) { usernic_error("Failed allocate memory: %s.\n", strerror(errno)); return false; } ret = snprintf(newline, slen, "%s %s %s %s\n", owner, intype, br, *nicname); if (ret < 0 || ret >= slen) { if (lxc_netdev_delete_by_name(*nicname) != 0) usernic_error("Error unlinking %s.\n", *nicname); return false; } if (len) munmap(buf, len); if (ftruncate(fd, len + slen)) usernic_error("Failed to set new file size: %s.\n", strerror(errno)); buf = mmap(NULL, len + slen, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (buf == MAP_FAILED) { usernic_error("Failed to establish shared memory mapping: %s.\n", strerror(errno)); if (lxc_netdev_delete_by_name(*nicname) != 0) usernic_error("Error unlinking %s.\n", *nicname); return false; } strcpy(buf + len, newline); munmap(buf, len + slen); return true; } static bool create_db_dir(char *fnam) { char *p; p = alloca(strlen(fnam) + 1); strcpy(p, fnam); fnam = p; p = p + 1; again: while (*p && *p != '/') p++; if (!*p) return true; *p = '\0'; if (mkdir(fnam, 0755) && errno != EEXIST) { usernic_error("Failed to create %s: %s.\n", fnam, strerror(errno)); *p = '/'; return false; } *(p++) = '/'; goto again; } #define VETH_DEF_NAME "eth%d" static int rename_in_ns(int pid, char *oldname, char **newnamep) { uid_t ruid, suid, euid; int fret = -1; int fd = -1, ifindex = -1, ofd = -1, ret; bool grab_newname = false; ofd = lxc_preserve_ns(getpid(), "net"); if (ofd < 0) { usernic_error("Failed opening network namespace path for '%d'.", getpid()); return fret; } fd = lxc_preserve_ns(pid, "net"); if (fd < 0) { usernic_error("Failed opening network namespace path for '%d'.", pid); goto do_partial_cleanup; } ret = getresuid(&ruid, &euid, &suid); if (ret < 0) { usernic_error("Failed to retrieve real, effective, and saved " "user IDs: %s\n", strerror(errno)); goto do_partial_cleanup; } ret = setns(fd, CLONE_NEWNET); close(fd); fd = -1; if (ret < 0) { usernic_error("Failed to setns() to the network namespace of " "the container with PID %d: %s.\n", pid, strerror(errno)); goto do_partial_cleanup; } ret = setresuid(ruid, ruid, 0); if (ret < 0) { usernic_error("Failed to drop privilege by setting effective " "user id and real user id to %d, and saved user " "ID to 0: %s.\n", ruid, strerror(errno)); // COMMENT(brauner): It's ok to jump to do_full_cleanup here // since setresuid() will succeed when trying to set real, // effective, and saved to values they currently have. goto do_full_cleanup; } if (!*newnamep) { grab_newname = true; *newnamep = VETH_DEF_NAME; ifindex = if_nametoindex(oldname); if (!ifindex) { usernic_error("Failed to get netdev index: %s.\n", strerror(errno)); goto do_full_cleanup; } } ret = lxc_netdev_rename_by_name(oldname, *newnamep); if (ret < 0) { usernic_error("Error %d renaming netdev %s to %s in container.\n", ret, oldname, *newnamep); goto do_full_cleanup; } if (grab_newname) { char ifname[IFNAMSIZ]; char *namep = ifname; if (!if_indextoname(ifindex, namep)) { usernic_error("Failed to get new netdev name: %s.\n", strerror(errno)); goto do_full_cleanup; } *newnamep = strdup(namep); if (!*newnamep) goto do_full_cleanup; } fret = 0; do_full_cleanup: ret = setresuid(ruid, euid, suid); if (ret < 0) { usernic_error("Failed to restore privilege by setting effective " "user id to %d, real user id to %d, and saved user " "ID to %d: %s.\n", ruid, euid, suid, strerror(errno)); fret = -1; // COMMENT(brauner): setns() should fail if setresuid() doesn't // succeed but there's no harm in falling through; keeps the // code cleaner. } ret = setns(ofd, CLONE_NEWNET); if (ret < 0) { usernic_error("Failed to setns() to original network namespace " "of PID %d: %s.\n", ofd, strerror(errno)); fret = -1; } do_partial_cleanup: if (fd >= 0) close(fd); close(ofd); return fret; } /* * If the caller (real uid, not effective uid) may read the * /proc/[pid]/ns/net, then it is either the caller's netns or one * which it created. */ static bool may_access_netns(int pid) { int ret; char s[200]; uid_t ruid, suid, euid; bool may_access = false; ret = getresuid(&ruid, &euid, &suid); if (ret < 0) { usernic_error("Failed to retrieve real, effective, and saved " "user IDs: %s\n", strerror(errno)); return false; } ret = setresuid(ruid, ruid, euid); if (ret < 0) { usernic_error("Failed to drop privilege by setting effective " "user id and real user id to %d, and saved user " "ID to %d: %s.\n", ruid, euid, strerror(errno)); return false; } ret = snprintf(s, 200, "/proc/%d/ns/net", pid); if (ret < 0 || ret >= 200) return false; ret = access(s, R_OK); may_access = true; if (ret < 0) { may_access = false; usernic_error("Uid %d may not access %s: %s\n", (int)ruid, s, strerror(errno)); } ret = setresuid(ruid, euid, suid); if (ret < 0) { usernic_error("Failed to restore user id to %d, real user id " "to %d, and saved user ID to %d: %s.\n", ruid, euid, suid, strerror(errno)); may_access = false; } return may_access; } int main(int argc, char *argv[]) { int n, fd; char *me; char *nicname; int pid; char *cnic = NULL; /* Created nic name in container is returned here. */ char *vethname = NULL; bool gotone = false; struct alloted_s *alloted = NULL; nicname = alloca(40); if (!nicname) { usernic_error("Failed allocate memory: %s.\n", strerror(errno)); exit(EXIT_FAILURE); } /* set a sane env, because we are setuid-root */ if (clearenv() < 0) { usernic_error("%s", "Failed to clear environment.\n"); exit(EXIT_FAILURE); } if (setenv("PATH", "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 1) < 0) { usernic_error("%s", "Failed to set PATH, exiting.\n"); exit(EXIT_FAILURE); } if ((me = get_username()) == NULL) { usernic_error("%s", "Failed to get username.\n"); exit(EXIT_FAILURE); } if (argc < 6) usage(argv[0], true); if (argc >= 7) vethname = argv[6]; lxcpath = argv[1]; lxcname = argv[2]; errno = 0; pid = strtol(argv[3], NULL, 10); if (errno) { usernic_error("Could not read pid: %s.\n", argv[1]); exit(EXIT_FAILURE); } if (!create_db_dir(LXC_USERNIC_DB)) { usernic_error("%s", "Failed to create directory for db file.\n"); exit(EXIT_FAILURE); } if ((fd = open_and_lock(LXC_USERNIC_DB)) < 0) { usernic_error("Failed to lock %s.\n", LXC_USERNIC_DB); exit(EXIT_FAILURE); } if (!may_access_netns(pid)) { usernic_error("User %s may not modify netns for pid %d.\n", me, pid); exit(EXIT_FAILURE); } n = get_alloted(me, argv[4], argv[5], &alloted); if (n > 0) gotone = get_nic_if_avail(fd, alloted, pid, argv[4], argv[5], n, &nicname, &cnic); close(fd); free_alloted(&alloted); if (!gotone) { usernic_error("%s", "Quota reached.\n"); exit(EXIT_FAILURE); } /* Now rename the link. */ if (rename_in_ns(pid, cnic, &vethname) < 0) { usernic_error("%s", "Failed to rename the link.\n"); if (lxc_netdev_delete_by_name(cnic) < 0) usernic_error("Failed to delete link \"%s\" the link. Manual cleanup needed.\n", cnic); exit(EXIT_FAILURE); } /* Write the name of the interface pair to the stdout - like * eth0:veth9MT2L4. */ fprintf(stdout, "%s:%s\n", vethname, nicname); exit(EXIT_SUCCESS); } lxc-2.0.8/src/lxc/log.c0000644061062106075000000003564513105116772011562 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Cedric Le Goater * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "log.h" #include "caps.h" #include "utils.h" /* We're logging in seconds and nanoseconds. Assuming that the underlying * datatype is currently at maximum a 64bit integer, we have a date string that * is of maximum length (2^64 - 1) * 2 = (21 + 21) = 42. */ #define LXC_LOG_TIME_SIZE ((LXC_NUMSTRLEN64)*2) 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; lxc_log_define(lxc_log, lxc); /*---------------------------------------------------------------------------*/ static int log_append_stderr(const struct lxc_log_appender *appender, struct lxc_log_event *event) { if (event->priority < LXC_LOG_PRIORITY_ERROR) return 0; fprintf(stderr, "%s: ", log_prefix); fprintf(stderr, "%s: %s: %d ", event->locinfo->file, event->locinfo->func, event->locinfo->line); vfprintf(stderr, event->fmt, *event->vap); fprintf(stderr, "\n"); return 0; } /*---------------------------------------------------------------------------*/ int lxc_unix_epoch_to_utc(char *buf, size_t bufsize, const struct timespec *time) { int64_t epoch_to_days, z, era, doe, yoe, year, doy, mp, day, month, d_in_s, hours, h_in_s, minutes, seconds; char nanosec[LXC_NUMSTRLEN64]; int ret; /* See https://howardhinnant.github.io/date_algorithms.html for an * explanation of the algorithm used here. */ /* Convert Epoch in seconds to number of days. */ epoch_to_days = time->tv_sec / 86400; /* Shift the Epoch from 1970-01-01 to 0000-03-01. */ z = epoch_to_days + 719468; /* compute the era from the serial date by simply dividing by the number * of days in an era (146097). */ era = (z >= 0 ? z : z - 146096) / 146097; /* The day-of-era (doe) can then be found by subtracting the era number * times the number of days per era, from the serial date. */ doe = (z - era * 146097); /* From the day-of-era (doe), the year-of-era (yoe, range [0, 399]) can * be computed. */ yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; /* Given year-of-era, and era, one can now compute the year. */ year = yoe + era * 400; /* Also the day-of-year, again with the year beginning on Mar. 1, can be * computed from the day-of-era and year-of-era. */ doy = doe - (365 * yoe + yoe / 4 - yoe / 100); /* Given day-of-year, find the month number. */ mp = (5 * doy + 2) / 153; /* From day-of-year and month-of-year we can now easily compute * day-of-month. */ day = doy - (153 * mp + 2) / 5 + 1; /* Transform the month number from the [0, 11] / [Mar, Feb] system to * the civil system: [1, 12] to find the correct month. */ month = mp + (mp < 10 ? 3 : -9); /* The algorithm assumes that a year begins on 1 March, so add 1 before * that. */ if (month < 3) year++; /* Transform days in the epoch to seconds. */ d_in_s = epoch_to_days * 86400; /* To find the current hour simply substract the Epoch_to_days from the * total Epoch and divide by the number of seconds in an hour. */ hours = (time->tv_sec - d_in_s) / 3600; /* Transform hours to seconds. */ h_in_s = hours * 3600; /* Calculate minutes by substracting the seconds for all days in the * epoch and for all hours in the epoch and divide by the number of * minutes in an hour. */ minutes = (time->tv_sec - d_in_s - h_in_s) / 60; /* Calculate the seconds by substracting the seconds for all days in the * epoch, hours in the epoch and minutes in the epoch. */ seconds = (time->tv_sec - d_in_s - h_in_s - (minutes * 60)); /* Make string from nanoseconds. */ ret = snprintf(nanosec, LXC_NUMSTRLEN64, "%ld", time->tv_nsec); if (ret < 0 || ret >= LXC_NUMSTRLEN64) return -1; /* Create final timestamp for the log and shorten nanoseconds to 3 * digit precision. */ ret = snprintf(buf, bufsize, "%" PRId64 "%02" PRId64 "%02" PRId64 "%02" PRId64 "%02" PRId64 "%02" PRId64 ".%.3s", year, month, day, hours, minutes, seconds, nanosec); if (ret < 0 || (size_t)ret >= bufsize) return -1; return 0; } /* This function needs to make extra sure that it is thread-safe. We had some * problems with that before. This especially involves time-conversion * functions. I don't want to find any localtime() or gmtime() functions or * relatives in here. Not even localtime_r() or gmtime_r() or relatives. They * all fiddle with global variables and locking in various libcs. They cause * deadlocks when liblxc is used multi-threaded and no matter how smart you * think you are, you __will__ cause trouble using them. * (As a short example how this can cause trouble: LXD uses forkstart to fork * off a new process that runs the container. At the same time the go runtime * LXD relies on does its own multi-threading thing which we can't controll. The * fork()ing + threading then seems to mess with the locking states in these * time functions causing deadlocks.) * The current solution is to be good old unix people and use the Epoch as our * reference point and simply use the seconds and nanoseconds that have past * since then. This relies on clock_gettime() which is explicitly marked MT-Safe * with no restrictions! This way, anyone who is really strongly invested in * getting the actual time the log entry was created, can just convert it for * themselves. Our logging is mostly done for debugging purposes so don't try * to make it pretty. Pretty might cost you thread-safety. */ static int log_append_logfile(const struct lxc_log_appender *appender, struct lxc_log_event *event) { char buffer[LXC_LOG_BUFFER_SIZE]; char date_time[LXC_LOG_TIME_SIZE]; int n; int fd_to_use = -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; if (lxc_unix_epoch_to_utc(date_time, LXC_LOG_TIME_SIZE, &event->timestamp) < 0) return 0; n = snprintf(buffer, sizeof(buffer), "%15s %s %-8s %s - %s:%s:%d - ", log_prefix, date_time, lxc_log_priority_to_string(event->priority), event->category, event->locinfo->file, event->locinfo->func, event->locinfo->line); if (n < 0) return n; if ((size_t)n < (sizeof(buffer) - 1)) n += vsnprintf(buffer + n, sizeof(buffer) - n, event->fmt, *event->vap); else n = sizeof(buffer) - 1; buffer[n] = '\n'; return write(fd_to_use, buffer, n + 1); } static struct lxc_log_appender log_appender_stderr = { .name = "stderr", .append = log_append_stderr, .next = NULL, }; static struct lxc_log_appender log_appender_logfile = { .name = "logfile", .append = log_append_logfile, .next = NULL, }; static struct lxc_log_category log_root = { .name = "root", .priority = LXC_LOG_PRIORITY_ERROR, .appender = NULL, .parent = NULL, }; struct lxc_log_category lxc_log_category_lxc = { .name = "lxc", .priority = LXC_LOG_PRIORITY_ERROR, .appender = &log_appender_logfile, .parent = &log_root }; /*---------------------------------------------------------------------------*/ static int build_dir(const char *name) { char *n = strdup(name); // because we'll be modifying it char *p, *e; int ret; if (!n) { ERROR("Out of memory while creating directory '%s'.", name); return -1; } e = &n[strlen(n)]; for (p = n+1; p < e; p++) { if (*p != '/') continue; *p = '\0'; if (access(n, F_OK)) { ret = lxc_unpriv(mkdir(n, 0755)); if (ret && errno != EEXIST) { SYSERROR("failed to create directory '%s'.", n); free(n); return -1; } } *p = '/'; } free(n); return 0; } /*---------------------------------------------------------------------------*/ static int log_open(const char *name) { int fd; int newfd; fd = lxc_unpriv(open(name, O_CREAT | O_WRONLY | O_APPEND | O_CLOEXEC, 0666)); if (fd == -1) { ERROR("failed to open log file \"%s\" : %s", name, strerror(errno)); return -1; } if (fd > 2) return fd; newfd = fcntl(fd, F_DUPFD_CLOEXEC, 3); if (newfd == -1) ERROR("failed to dup log fd %d : %s", fd, strerror(errno)); close(fd); return newfd; } /* * Build the path to the log file * @name : the name of the container * @lxcpath : the lxcpath to use as a basename or NULL to use LOGPATH * Returns malloced path on success, or NULL on failure */ static char *build_log_path(const char *name, const char *lxcpath) { char *p; int len, ret, use_dir; if (!name) return NULL; #if USE_CONFIGPATH_LOGS use_dir = 1; #else use_dir = 0; #endif /* * If USE_CONFIGPATH_LOGS is true or lxcpath is given, the resulting * path will be: * '$logpath' + '/' + '$name' + '/' + '$name' + '.log' + '\0' * * If USE_CONFIGPATH_LOGS is false the resulting path will be: * '$logpath' + '/' + '$name' + '.log' + '\0' */ len = strlen(name) + 6; /* 6 == '/' + '.log' + '\0' */ if (lxcpath) use_dir = 1; else lxcpath = LOGPATH; if (use_dir) len += strlen(lxcpath) + 1 + strlen(name) + 1; /* add "/$container_name/" */ else len += strlen(lxcpath) + 1; p = malloc(len); if (!p) return p; if (use_dir) ret = snprintf(p, len, "%s/%s/%s.log", lxcpath, name, name); else ret = snprintf(p, len, "%s/%s.log", lxcpath, name); if (ret < 0 || ret >= len) { free(p); return NULL; } return p; } extern void lxc_log_close(void) { if (lxc_log_fd == -1) return; close(lxc_log_fd); lxc_log_fd = -1; free(log_fname); log_fname = NULL; } /* * This can be called: * 1. when a program calls lxc_log_init with no logfile parameter (in which * case the default is used). In this case lxc.logfile can override this. * 2. when a program calls lxc_log_init with a logfile parameter. In this * case we don't want lxc.logfile to override this. * 3. When a lxc.logfile entry is found in config file. */ static int __lxc_log_set_file(const char *fname, int create_dirs) { if (lxc_log_fd != -1) { // we are overriding the default. lxc_log_close(); } if (!fname) return -1; if (strlen(fname) == 0) { log_fname = NULL; return 0; } #if USE_CONFIGPATH_LOGS // we don't build_dir for the default if the default is // i.e. /var/lib/lxc/$container/$container.log if (create_dirs) #endif if (build_dir(fname)) { ERROR("failed to create dir for log file \"%s\" : %s", fname, strerror(errno)); return -1; } lxc_log_fd = log_open(fname); if (lxc_log_fd == -1) return -1; log_fname = strdup(fname); return 0; } static int _lxc_log_set_file(const char *name, const char *lxcpath, int create_dirs) { char *logfile; int ret; logfile = build_log_path(name, lxcpath); if (!logfile) { ERROR("could not build log path"); return -1; } ret = __lxc_log_set_file(logfile, create_dirs); free(logfile); 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) { int lxc_priority = LXC_LOG_PRIORITY_ERROR; int ret; if (lxc_log_fd != -1) { WARN("lxc_log_init called with log already initialized"); return 0; } if (priority) lxc_priority = lxc_log_priority_to_int(priority); if (!lxc_loglevel_specified) { lxc_log_category_lxc.priority = lxc_priority; lxc_loglevel_specified = 1; } if (!lxc_quiet_specified) { if (!quiet) lxc_log_category_lxc.appender->next = &log_appender_stderr; } if (prefix) lxc_log_set_prefix(prefix); if (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) return 0; ret = -1; if (!lxcpath) lxcpath = LOGPATH; /* try LOGPATH if lxcpath is the default for the privileged containers */ if (!geteuid() && strcmp(LXCPATH, lxcpath) == 0) ret = _lxc_log_set_file(name, NULL, 0); /* try in lxcpath */ if (ret < 0) ret = _lxc_log_set_file(name, lxcpath, 1); /* try LOGPATH in case its writable by the caller */ if (ret < 0) ret = _lxc_log_set_file(name, NULL, 0); } /* * If !file, that is, if the user did not request this logpath, then * ignore failures and continue logging to console */ if (!file && ret != 0) { INFO("Ignoring failure to open default logfile."); ret = 0; } return ret; } /* * This is called when we read a lxc.loglevel entry in a lxc.conf file. This * 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 *dest, int level) { if (level < 0 || level >= LXC_LOG_PRIORITY_NOTSET) { ERROR("invalid log priority %d", level); return -1; } *dest = level; return 0; } extern int lxc_log_get_level(void) { return lxc_log_category_lxc.priority; } extern bool lxc_log_has_valid_level(void) { int log_level = lxc_log_get_level(); if (log_level < 0 || log_level >= LXC_LOG_PRIORITY_NOTSET) return false; return true; } /* * This is called when we read a lxc.logfile entry in a lxc.conf file. This * 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(int *fd, const char *fname) { 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) { return log_fname; } extern void lxc_log_set_prefix(const char *prefix) { strncpy(log_prefix, prefix, sizeof(log_prefix)); log_prefix[sizeof(log_prefix) - 1] = 0; } extern const char *lxc_log_get_prefix(void) { return log_prefix; } extern void lxc_log_options_no_override() { lxc_quiet_specified = 1; lxc_loglevel_specified = 1; } lxc-2.0.8/src/lxc/parse.c0000644061062106075000000000444413105116772012104 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #include #undef _GNU_SOURCE #include #include #include #include #include "parse.h" #include "config.h" #include "utils.h" #include "log.h" lxc_log_define(lxc_parse, lxc); int lxc_file_for_each_line(const char *file, lxc_file_cb callback, void *data) { FILE *f; int err = 0; char *line = NULL; size_t len = 0; f = fopen(file, "r"); if (!f) { SYSERROR("failed to open %s", file); return -1; } while (getline(&line, &len, f) != -1) { err = callback(line, data); if (err) { // callback rv > 0 means stop here // callback rv < 0 means error if (err < 0) ERROR("Failed to parse config: %s", line); break; } } free(line); fclose(f); return err; } int lxc_char_left_gc(const char *buffer, size_t len) { size_t i; for (i = 0; i < len; i++) { if (buffer[i] == ' ' || buffer[i] == '\t') continue; return i; } return 0; } int lxc_char_right_gc(const char *buffer, size_t len) { int i; for (i = len - 1; i >= 0; i--) { if (buffer[i] == ' ' || buffer[i] == '\t' || buffer[i] == '\n' || buffer[i] == '\0') continue; return i + 1; } return 0; } int lxc_is_line_empty(const char *line) { int i; size_t len = strlen(line); for (i = 0; i < len; i++) if (line[i] != ' ' && line[i] != '\t' && line[i] != '\n' && line[i] != '\r' && line[i] != '\f' && line[i] != '\0') return 0; return 1; } lxc-2.0.8/src/lxc/attach.h0000644061062106075000000000246613105116772012245 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_ATTACH_H #define __LXC_ATTACH_H #include #include struct lxc_conf; struct lxc_proc_context_info { char *lsm_label; struct lxc_container *container; signed long personality; unsigned long long capability_mask; }; extern int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_function, void* exec_payload, lxc_attach_options_t* options, pid_t* attached_process); #endif lxc-2.0.8/src/lxc/criu.c0000644061062106075000000006754713105116772011751 00000000000000/* * lxc: linux Container library * * Copyright © 2014-2015 Canonical Ltd. * * Authors: * Tycho Andersen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "bdev.h" #include "cgroup.h" #include "conf.h" #include "commands.h" #include "criu.h" #include "log.h" #include "lxc.h" #include "lxclock.h" #include "network.h" #include "utils.h" #if IS_BIONIC #include <../include/lxcmntent.h> #else #include #endif #define CRIU_VERSION "2.0" #define CRIU_GITID_VERSION "2.0" #define CRIU_GITID_PATCHLEVEL 0 #define CRIU_IN_FLIGHT_SUPPORT "2.4" #define CRIU_EXTERNAL_NOT_VETH "2.8" lxc_log_define(lxc_criu, lxc); struct criu_opts { /* the thing to hook to stdout and stderr for logging */ int pipefd; /* The type of criu invocation, one of "dump" or "restore" */ char *action; /* the user-provided migrate options relevant to this action */ struct migrate_opts *user; /* The container to dump */ struct lxc_container *c; /* dump: stop the container or not after dumping? */ char tty_id[32]; /* the criu tty id for /dev/console, i.e. "tty[${rdev}:${dev}]" */ /* restore: the file to write the init process' pid into */ struct lxc_handler *handler; int console_fd; /* The path that is bind mounted from /dev/console, if any. We don't * want to use `--ext-mount-map auto`'s result here because the pts * device may have a different path (e.g. if the pty number is * different) on the target host. NULL if lxc.console = "none". */ char *console_name; /* The detected version of criu */ char *criu_version; }; static int load_tty_major_minor(char *directory, char *output, int len) { FILE *f; char path[PATH_MAX]; int ret; ret = snprintf(path, sizeof(path), "%s/tty.info", directory); if (ret < 0 || ret >= sizeof(path)) { ERROR("snprintf'd too many chacters: %d", ret); return -1; } f = fopen(path, "r"); if (!f) { /* This means we're coming from a liblxc which didn't export * the tty info. In this case they had to have lxc.console = * none, so there's no problem restoring. */ if (errno == ENOENT) return 0; SYSERROR("couldn't open %s", path); return -1; } if (!fgets(output, len, f)) { fclose(f); SYSERROR("couldn't read %s", path); return -1; } fclose(f); return 0; } static void exec_criu(struct criu_opts *opts) { char **argv, log[PATH_MAX]; int static_args = 23, argc = 0, i, ret; int netnr = 0; struct lxc_list *it; FILE *mnts; struct mntent mntent; char buf[4096], tty_info[32]; size_t pos; /* If we are currently in a cgroup /foo/bar, and the container is in a * cgroup /lxc/foo, lxcfs will give us an ENOENT if some task in the * container has an open fd that points to one of the cgroup files * (systemd always opens its "root" cgroup). So, let's escape to the * /actual/ root cgroup so that lxcfs thinks criu has enough rights to * see all cgroups. */ if (!cgroup_escape()) { ERROR("failed to escape cgroups"); return; } /* The command line always looks like: * criu $(action) --tcp-established --file-locks --link-remap \ * --manage-cgroups=full --action-script foo.sh -D $(directory) \ * -o $(directory)/$(action).log --ext-mount-map auto * --enable-external-sharing --enable-external-masters * --enable-fs hugetlbfs --enable-fs tracefs --ext-mount-map console:/dev/pts/n * +1 for final NULL */ if (strcmp(opts->action, "dump") == 0 || strcmp(opts->action, "pre-dump") == 0) { /* -t pid --freeze-cgroup /lxc/ct */ static_args += 4; /* --prev-images-dir */ if (opts->user->predump_dir) static_args += 2; /* --page-server --address
--port */ if (opts->user->pageserver_address && opts->user->pageserver_port) static_args += 5; /* --leave-running (only for final dump) */ if (strcmp(opts->action, "dump") == 0 && !opts->user->stop) static_args++; /* --external tty[88,4] */ if (opts->tty_id[0]) static_args += 2; /* --force-irmap */ if (!opts->user->preserves_inodes) static_args++; /* --ghost-limit 1024 */ if (opts->user->ghost_limit) static_args += 2; } else if (strcmp(opts->action, "restore") == 0) { /* --root $(lxc_mount_point) --restore-detached * --restore-sibling * --lsm-profile apparmor:whatever */ static_args += 6; tty_info[0] = 0; if (load_tty_major_minor(opts->user->directory, tty_info, sizeof(tty_info))) return; /* --inherit-fd fd[%d]:tty[%s] */ if (tty_info[0]) static_args += 2; } else { return; } if (cgroup_num_hierarchies() > 0) static_args += 2 * cgroup_num_hierarchies(); if (opts->user->verbose) static_args++; if (opts->user->action_script) static_args += 2; static_args += 2 * lxc_list_len(&opts->c->lxc_conf->mount_list); ret = snprintf(log, PATH_MAX, "%s/%s.log", opts->user->directory, opts->action); if (ret < 0 || ret >= PATH_MAX) { ERROR("logfile name too long"); return; } argv = malloc(static_args * sizeof(*argv)); if (!argv) return; memset(argv, 0, static_args * sizeof(*argv)); #define DECLARE_ARG(arg) \ do { \ if (arg == NULL) { \ ERROR("Got NULL argument for criu"); \ goto err; \ } \ argv[argc++] = strdup(arg); \ if (!argv[argc-1]) \ goto err; \ } while (0) argv[argc++] = on_path("criu", NULL); if (!argv[argc-1]) { ERROR("Couldn't find criu binary"); goto err; } DECLARE_ARG(opts->action); DECLARE_ARG("--tcp-established"); DECLARE_ARG("--file-locks"); DECLARE_ARG("--link-remap"); DECLARE_ARG("--manage-cgroups=full"); DECLARE_ARG("--ext-mount-map"); DECLARE_ARG("auto"); DECLARE_ARG("--enable-external-sharing"); DECLARE_ARG("--enable-external-masters"); DECLARE_ARG("--enable-fs"); DECLARE_ARG("hugetlbfs"); DECLARE_ARG("--enable-fs"); DECLARE_ARG("tracefs"); DECLARE_ARG("-D"); DECLARE_ARG(opts->user->directory); DECLARE_ARG("-o"); DECLARE_ARG(log); for (i = 0; i < cgroup_num_hierarchies(); i++) { char **controllers = NULL, *fullname; char *path; if (!cgroup_get_hierarchies(i, &controllers)) { ERROR("failed to get hierarchy %d", i); goto err; } /* if we are in a dump, we have to ask the monitor process what * the right cgroup is. if this is a restore, we can just use * the handler the restore task created. */ if (!strcmp(opts->action, "dump") || !strcmp(opts->action, "pre-dump")) { path = lxc_cmd_get_cgroup_path(opts->c->name, opts->c->config_path, controllers[0]); if (!path) { ERROR("failed to get cgroup path for %s", controllers[0]); goto err; } } else { const char *p; p = cgroup_get_cgroup(opts->handler, controllers[0]); if (!p) { ERROR("failed to get cgroup path for %s", controllers[0]); goto err; } path = strdup(p); if (!path) { ERROR("strdup failed"); goto err; } } if (!lxc_deslashify(&path)) { ERROR("failed to deslashify %s", path); free(path); goto err; } fullname = lxc_string_join(",", (const char **) controllers, false); if (!fullname) { ERROR("failed to join controllers"); free(path); goto err; } ret = sprintf(buf, "%s:%s", fullname, path); free(path); free(fullname); if (ret < 0 || ret >= sizeof(buf)) { ERROR("sprintf of cgroup root arg failed"); goto err; } DECLARE_ARG("--cgroup-root"); DECLARE_ARG(buf); } if (opts->user->verbose) DECLARE_ARG("-vvvvvv"); if (opts->user->action_script) { DECLARE_ARG("--action-script"); DECLARE_ARG(opts->user->action_script); } mnts = make_anonymous_mount_file(&opts->c->lxc_conf->mount_list); if (!mnts) goto err; while (getmntent_r(mnts, &mntent, buf, sizeof(buf))) { char *fmt, *key, *val, *mntdata; char arg[2 * PATH_MAX + 2]; unsigned long flags; if (parse_mntopts(mntent.mnt_opts, &flags, &mntdata) < 0) goto err; free(mntdata); /* only add --ext-mount-map for actual bind mounts */ if (!(flags & MS_BIND)) continue; if (strcmp(opts->action, "dump") == 0) { fmt = "/%s:%s"; key = mntent.mnt_dir; val = mntent.mnt_dir; } else { fmt = "%s:%s"; key = mntent.mnt_dir; val = mntent.mnt_fsname; } ret = snprintf(arg, sizeof(arg), fmt, key, val); if (ret < 0 || ret >= sizeof(arg)) { fclose(mnts); ERROR("snprintf failed"); goto err; } DECLARE_ARG("--ext-mount-map"); DECLARE_ARG(arg); } fclose(mnts); if (strcmp(opts->action, "dump") == 0 || strcmp(opts->action, "pre-dump") == 0) { char pid[32], *freezer_relative; if (sprintf(pid, "%d", opts->c->init_pid(opts->c)) < 0) goto err; DECLARE_ARG("-t"); DECLARE_ARG(pid); freezer_relative = lxc_cmd_get_cgroup_path(opts->c->name, opts->c->config_path, "freezer"); if (!freezer_relative) { ERROR("failed getting freezer path"); goto err; } ret = snprintf(log, sizeof(log), "/sys/fs/cgroup/freezer/%s", freezer_relative); if (ret < 0 || ret >= sizeof(log)) goto err; if (!opts->user->disable_skip_in_flight && strcmp(opts->criu_version, CRIU_IN_FLIGHT_SUPPORT) >= 0) DECLARE_ARG("--skip-in-flight"); DECLARE_ARG("--freeze-cgroup"); DECLARE_ARG(log); if (opts->tty_id[0]) { DECLARE_ARG("--ext-mount-map"); DECLARE_ARG("/dev/console:console"); DECLARE_ARG("--external"); DECLARE_ARG(opts->tty_id); } if (opts->user->predump_dir) { DECLARE_ARG("--prev-images-dir"); DECLARE_ARG(opts->user->predump_dir); } if (opts->user->pageserver_address && opts->user->pageserver_port) { DECLARE_ARG("--page-server"); DECLARE_ARG("--address"); DECLARE_ARG(opts->user->pageserver_address); DECLARE_ARG("--port"); DECLARE_ARG(opts->user->pageserver_port); } if (!opts->user->preserves_inodes) DECLARE_ARG("--force-irmap"); if (opts->user->ghost_limit) { char ghost_limit[32]; ret = sprintf(ghost_limit, "%"PRIu64, opts->user->ghost_limit); if (ret < 0 || ret >= sizeof(ghost_limit)) { ERROR("failed to print ghost limit %"PRIu64, opts->user->ghost_limit); goto err; } DECLARE_ARG("--ghost-limit"); DECLARE_ARG(ghost_limit); } /* only for final dump */ if (strcmp(opts->action, "dump") == 0 && !opts->user->stop) DECLARE_ARG("--leave-running"); } else if (strcmp(opts->action, "restore") == 0) { void *m; int additional; struct lxc_conf *lxc_conf = opts->c->lxc_conf; DECLARE_ARG("--root"); DECLARE_ARG(opts->c->lxc_conf->rootfs.mount); DECLARE_ARG("--restore-detached"); DECLARE_ARG("--restore-sibling"); if (tty_info[0]) { if (opts->console_fd < 0) { ERROR("lxc.console configured on source host but not target"); goto err; } ret = snprintf(buf, sizeof(buf), "fd[%d]:%s", opts->console_fd, tty_info); if (ret < 0 || ret >= sizeof(buf)) goto err; DECLARE_ARG("--inherit-fd"); DECLARE_ARG(buf); } if (opts->console_name) { if (snprintf(buf, sizeof(buf), "console:%s", opts->console_name) < 0) { SYSERROR("sprintf'd too many bytes"); } DECLARE_ARG("--ext-mount-map"); DECLARE_ARG(buf); } if (lxc_conf->lsm_aa_profile || lxc_conf->lsm_se_context) { if (lxc_conf->lsm_aa_profile) ret = snprintf(buf, sizeof(buf), "apparmor:%s", lxc_conf->lsm_aa_profile); else ret = snprintf(buf, sizeof(buf), "selinux:%s", lxc_conf->lsm_se_context); if (ret < 0 || ret >= sizeof(buf)) goto err; DECLARE_ARG("--lsm-profile"); DECLARE_ARG(buf); } additional = lxc_list_len(&opts->c->lxc_conf->network) * 2; m = realloc(argv, (argc + additional + 1) * sizeof(*argv)); if (!m) goto err; argv = m; lxc_list_for_each(it, &opts->c->lxc_conf->network) { char eth[128], *veth; char *fmt; struct lxc_netdev *n = it->elem; bool external_not_veth; if (strcmp(opts->criu_version, CRIU_EXTERNAL_NOT_VETH) >= 0) { /* Since criu version 2.8 the usage of --veth-pair * has been deprecated: * git tag --contains f2037e6d3445fc400 * v2.8 */ external_not_veth = true; } else { external_not_veth = false; } if (n->name) { if (strlen(n->name) >= sizeof(eth)) goto err; strncpy(eth, n->name, sizeof(eth)); } else { ret = snprintf(eth, sizeof(eth), "eth%d", netnr); if (ret < 0 || ret >= sizeof(eth)) goto err; } switch (n->type) { case LXC_NET_VETH: veth = n->priv.veth_attr.pair; if (n->link) { if (external_not_veth) fmt = "veth[%s]:%s@%s"; else fmt = "%s=%s@%s"; ret = snprintf(buf, sizeof(buf), fmt, eth, veth, n->link); } else { if (external_not_veth) fmt = "veth[%s]:%s"; else fmt = "%s=%s"; ret = snprintf(buf, sizeof(buf), fmt, eth, veth); } if (ret < 0 || ret >= sizeof(buf)) goto err; break; case LXC_NET_MACVLAN: if (!n->link) { ERROR("no host interface for macvlan %s", n->name); goto err; } ret = snprintf(buf, sizeof(buf), "macvlan[%s]:%s", eth, n->link); if (ret < 0 || ret >= sizeof(buf)) goto err; break; case LXC_NET_NONE: case LXC_NET_EMPTY: break; default: /* we have screened for this earlier... */ ERROR("unexpected network type %d", n->type); goto err; } if (external_not_veth) DECLARE_ARG("--external"); else DECLARE_ARG("--veth-pair"); DECLARE_ARG(buf); netnr++; } } argv[argc] = NULL; buf[0] = 0; pos = 0; for (i = 0; argv[i]; i++) { ret = snprintf(buf + pos, sizeof(buf) - pos, "%s ", argv[i]); if (ret < 0 || ret >= sizeof(buf) - pos) goto err; else pos += ret; } INFO("execing: %s", buf); /* before criu inits its log, it sometimes prints things to stdout/err; * let's be sure we capture that. */ if (dup2(opts->pipefd, STDOUT_FILENO) < 0) { SYSERROR("dup2 stdout failed"); goto err; } if (dup2(opts->pipefd, STDERR_FILENO) < 0) { SYSERROR("dup2 stderr failed"); goto err; } close(opts->pipefd); #undef DECLARE_ARG execv(argv[0], argv); err: for (i = 0; argv[i]; i++) free(argv[i]); free(argv); } /* * Check to see if the criu version is recent enough for all the features we * use. This version allows either CRIU_VERSION or (CRIU_GITID_VERSION and * CRIU_GITID_PATCHLEVEL) to work, enabling users building from git to c/r * things potentially before a version is released with a particular feature. * * The intent is that when criu development slows down, we can drop this, but * for now we shouldn't attempt to c/r with versions that we know won't work. * * Note: If version != NULL criu_version() stores the detected criu version in * version. Allocates memory for version which must be freed by caller. */ static bool criu_version_ok(char **version) { int pipes[2]; pid_t pid; if (pipe(pipes) < 0) { SYSERROR("pipe() failed"); return false; } pid = fork(); if (pid < 0) { SYSERROR("fork() failed"); return false; } if (pid == 0) { char *args[] = { "criu", "--version", NULL }; char *path; close(pipes[0]); close(STDERR_FILENO); if (dup2(pipes[1], STDOUT_FILENO) < 0) exit(1); path = on_path("criu", NULL); if (!path) exit(1); execv(path, args); exit(1); } else { FILE *f; char *tmp; int patch; close(pipes[1]); if (wait_for_pid(pid) < 0) { close(pipes[0]); SYSERROR("execing criu failed, is it installed?"); return false; } f = fdopen(pipes[0], "r"); if (!f) { close(pipes[0]); return false; } tmp = malloc(1024); if (!tmp) { fclose(f); return false; } if (fscanf(f, "Version: %1023[^\n]s", tmp) != 1) goto version_error; if (fgetc(f) != '\n') goto version_error; if (strcmp(tmp, CRIU_VERSION) >= 0) goto version_match; if (fscanf(f, "GitID: v%1023[^-]s", tmp) != 1) goto version_error; if (fgetc(f) != '-') goto version_error; if (fscanf(f, "%d", &patch) != 1) goto version_error; if (strcmp(tmp, CRIU_GITID_VERSION) < 0) goto version_error; if (patch < CRIU_GITID_PATCHLEVEL) goto version_error; version_match: fclose(f); if (!version) free(tmp); else *version = tmp; return true; version_error: fclose(f); free(tmp); ERROR("must have criu " CRIU_VERSION " or greater to checkpoint/restore"); return false; } } /* Check and make sure the container has a configuration that we know CRIU can * dump. */ static bool criu_ok(struct lxc_container *c, char **criu_version) { struct lxc_list *it; if (!criu_version_ok(criu_version)) return false; if (geteuid()) { ERROR("Must be root to checkpoint"); return false; } /* We only know how to restore containers with veth networks. */ lxc_list_for_each(it, &c->lxc_conf->network) { struct lxc_netdev *n = it->elem; switch(n->type) { case LXC_NET_VETH: case LXC_NET_NONE: case LXC_NET_EMPTY: case LXC_NET_MACVLAN: break; default: ERROR("Found un-dumpable network: %s (%s)", lxc_net_type_to_str(n->type), n->name); return false; } } return true; } static bool restore_net_info(struct lxc_container *c) { struct lxc_list *it; bool has_error = true; if (container_mem_lock(c)) return false; lxc_list_for_each(it, &c->lxc_conf->network) { struct lxc_netdev *netdev = it->elem; char template[IFNAMSIZ]; if (netdev->type != LXC_NET_VETH) continue; snprintf(template, sizeof(template), "vethXXXXXX"); if (!netdev->priv.veth_attr.pair) netdev->priv.veth_attr.pair = lxc_mkifname(template); if (!netdev->priv.veth_attr.pair) goto out_unlock; } has_error = false; out_unlock: container_mem_unlock(c); return !has_error; } // 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 status_pipe, struct migrate_opts *opts, char *criu_version) { pid_t pid; struct lxc_handler *handler; int status, fd; int pipes[2] = {-1, -1}; /* Try to detach from the current controlling tty if it exists. * Othwerise, lxc_init (via lxc_console) will attach the container's * console output to the current tty, which is probably not what any * library user wants, and if they do, they can just manually configure * it :) */ fd = open("/dev/tty", O_RDWR); if (fd >= 0) { if (ioctl(fd, TIOCNOTTY, NULL) < 0) SYSERROR("couldn't detach from tty"); close(fd); } handler = lxc_init(c->name, c->lxc_conf, c->config_path); if (!handler) goto out; if (!cgroup_init(handler)) { ERROR("failed initing cgroups"); goto out_fini_handler; } if (!cgroup_create(handler)) { ERROR("failed creating groups"); goto out_fini_handler; } if (!restore_net_info(c)) { ERROR("failed restoring network info"); goto out_fini_handler; } resolve_clone_flags(handler); if (pipe(pipes) < 0) { SYSERROR("pipe() failed"); goto out_fini_handler; } pid = fork(); if (pid < 0) goto out_fini_handler; if (pid == 0) { struct criu_opts os; struct lxc_rootfs *rootfs; int flags; close(status_pipe); status_pipe = -1; close(pipes[0]); pipes[0] = -1; if (unshare(CLONE_NEWNS)) goto out_fini_handler; /* CRIU needs the lxc root bind mounted so that it is the root of some * mount. */ rootfs = &c->lxc_conf->rootfs; if (rootfs_is_blockdev(c->lxc_conf)) { if (do_rootfs_setup(c->lxc_conf, c->name, c->config_path) < 0) goto out_fini_handler; } else { if (mkdir(rootfs->mount, 0755) < 0 && errno != EEXIST) goto out_fini_handler; if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) { SYSERROR("remount / to private failed"); goto out_fini_handler; } if (mount(rootfs->path, rootfs->mount, NULL, MS_BIND, NULL) < 0) { rmdir(rootfs->mount); goto out_fini_handler; } } os.pipefd = pipes[1]; os.action = "restore"; os.user = opts; os.c = c; os.console_fd = c->lxc_conf->console.slave; os.criu_version = criu_version; os.handler = handler; if (os.console_fd >= 0) { /* Twiddle the FD_CLOEXEC bit. We want to pass this FD to criu * via --inherit-fd, so we don't want it to close. */ flags = fcntl(os.console_fd, F_GETFD); if (flags < 0) { SYSERROR("F_GETFD failed: %d", os.console_fd); goto out_fini_handler; } flags &= ~FD_CLOEXEC; if (fcntl(os.console_fd, F_SETFD, flags) < 0) { SYSERROR("F_SETFD failed"); goto out_fini_handler; } } os.console_name = c->lxc_conf->console.name; /* exec_criu() returning is an error */ exec_criu(&os); umount(rootfs->mount); rmdir(rootfs->mount); goto out_fini_handler; } else { int ret; char title[2048]; close(pipes[1]); pipes[1] = -1; pid_t w = waitpid(pid, &status, 0); if (w == -1) { SYSERROR("waitpid"); goto out_fini_handler; } if (WIFEXITED(status)) { char buf[4096]; if (WEXITSTATUS(status)) { int n; n = read(pipes[0], buf, sizeof(buf)); if (n < 0) { SYSERROR("failed reading from criu stderr"); goto out_fini_handler; } if (n == sizeof(buf)) n--; buf[n] = 0; ERROR("criu process exited %d, output:\n%s", WEXITSTATUS(status), buf); goto out_fini_handler; } else { ret = snprintf(buf, sizeof(buf), "/proc/self/task/%lu/children", (unsigned long)syscall(__NR_gettid)); if (ret < 0 || ret >= sizeof(buf)) { ERROR("snprintf'd too many characters: %d", ret); goto out_fini_handler; } FILE *f = fopen(buf, "r"); if (!f) { SYSERROR("couldn't read restore's children file %s", buf); goto out_fini_handler; } ret = fscanf(f, "%d", (int*) &handler->pid); fclose(f); if (ret != 1) { ERROR("reading restore pid failed"); goto out_fini_handler; } if (lxc_set_state(c->name, handler, RUNNING)) { ERROR("error setting running state after restore"); goto out_fini_handler; } } } else { ERROR("CRIU was killed with signal %d", WTERMSIG(status)); goto out_fini_handler; } close(pipes[0]); ret = write(status_pipe, &status, sizeof(status)); close(status_pipe); status_pipe = -1; if (sizeof(status) != ret) { SYSERROR("failed to write all of status"); goto out_fini_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); lxc_fini(c->name, handler); exit(ret); } out_fini_handler: if (pipes[0] >= 0) close(pipes[0]); if (pipes[1] >= 0) close(pipes[1]); lxc_fini(c->name, handler); out: if (status_pipe >= 0) { /* ensure getting here was a failure, e.g. if we failed to * parse the child pid or something, even after a successful * restore */ if (!status) status = 1; if (write(status_pipe, &status, sizeof(status)) != sizeof(status)) { SYSERROR("writing status failed"); } close(status_pipe); } exit(1); } static int save_tty_major_minor(char *directory, struct lxc_container *c, char *tty_id, int len) { FILE *f; char path[PATH_MAX]; int ret; struct stat sb; if (c->lxc_conf->console.path && !strcmp(c->lxc_conf->console.path, "none")) { tty_id[0] = 0; return 0; } ret = snprintf(path, sizeof(path), "/proc/%d/root/dev/console", c->init_pid(c)); if (ret < 0 || ret >= sizeof(path)) { ERROR("snprintf'd too many chacters: %d", ret); return -1; } ret = stat(path, &sb); if (ret < 0) { SYSERROR("stat of %s failed", path); return -1; } ret = snprintf(path, sizeof(path), "%s/tty.info", directory); if (ret < 0 || ret >= sizeof(path)) { ERROR("snprintf'd too many characters: %d", ret); return -1; } ret = snprintf(tty_id, len, "tty[%llx:%llx]", (long long unsigned) sb.st_rdev, (long long unsigned) sb.st_dev); if (ret < 0 || ret >= sizeof(path)) { ERROR("snprintf'd too many characters: %d", ret); return -1; } f = fopen(path, "w"); if (!f) { SYSERROR("failed to open %s", path); return -1; } ret = fprintf(f, "%s", tty_id); fclose(f); if (ret < 0) SYSERROR("failed to write to %s", path); return ret; } /* do one of either predump or a regular dump */ static bool do_dump(struct lxc_container *c, char *mode, struct migrate_opts *opts) { pid_t pid; char *criu_version = NULL; int criuout[2]; if (!criu_ok(c, &criu_version)) return false; if (pipe(criuout) < 0) { SYSERROR("pipe() failed"); return false; } if (mkdir_p(opts->directory, 0700) < 0) goto fail; pid = fork(); if (pid < 0) { SYSERROR("fork failed"); goto fail; } if (pid == 0) { struct criu_opts os; struct lxc_handler h; close(criuout[0]); h.name = c->name; if (!cgroup_init(&h)) { ERROR("failed to cgroup_init()"); exit(1); } os.pipefd = criuout[1]; os.action = mode; os.user = opts; os.c = c; os.console_name = c->lxc_conf->console.path; os.criu_version = criu_version; if (save_tty_major_minor(opts->directory, c, os.tty_id, sizeof(os.tty_id)) < 0) exit(1); /* exec_criu() returning is an error */ exec_criu(&os); exit(1); } else { int status; ssize_t n; char buf[4096]; bool ret; close(criuout[1]); pid_t w = waitpid(pid, &status, 0); if (w == -1) { SYSERROR("waitpid"); close(criuout[0]); return false; } n = read(criuout[0], buf, sizeof(buf)); close(criuout[0]); if (n < 0) { SYSERROR("read"); n = 0; } buf[n] = 0; if (WIFEXITED(status)) { if (WEXITSTATUS(status)) { ERROR("dump failed with %d", WEXITSTATUS(status)); ret = false; } else { ret = true; } } else if (WIFSIGNALED(status)) { ERROR("dump signaled with %d", WTERMSIG(status)); ret = false; } else { ERROR("unknown dump exit %d", status); ret = false; } if (!ret) ERROR("criu output: %s", buf); return ret; } fail: close(criuout[0]); close(criuout[1]); rmdir(opts->directory); return false; } bool __criu_pre_dump(struct lxc_container *c, struct migrate_opts *opts) { return do_dump(c, "pre-dump", opts); } bool __criu_dump(struct lxc_container *c, struct migrate_opts *opts) { char path[PATH_MAX]; int ret; ret = snprintf(path, sizeof(path), "%s/inventory.img", opts->directory); if (ret < 0 || ret >= sizeof(path)) return false; if (access(path, F_OK) == 0) { ERROR("please use a fresh directory for the dump directory"); return false; } return do_dump(c, "dump", opts); } bool __criu_restore(struct lxc_container *c, struct migrate_opts *opts) { pid_t pid; int status, nread; int pipefd[2]; char *criu_version = NULL; if (!criu_ok(c, &criu_version)) return false; if (geteuid()) { ERROR("Must be root to restore"); 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], opts, criu_version); } 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; } lxc-2.0.8/src/lxc/arguments.c0000644061062106075000000001446613105116772013004 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * Michel Normand * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include /* for isprint() */ #include #include #include #include #include "arguments.h" #include "utils.h" #include "version.h" /*---------------------------------------------------------------------------*/ static int build_shortopts(const struct option *a_options, char *a_shortopts, size_t a_size) { const struct option *opt; size_t i = 0; if (!a_options || !a_shortopts || !a_size) return -1; for (opt = a_options; opt->name; opt++) { if (!isascii(opt->val)) continue; if (i < a_size) a_shortopts[i++] = opt->val; else goto is2big; if (opt->has_arg == no_argument) continue; if (i < a_size) a_shortopts[i++] = ':'; else goto is2big; if (opt->has_arg == required_argument) continue; if (i < a_size) a_shortopts[i++] = ':'; else goto is2big; } if (i < a_size) a_shortopts[i] = '\0'; else goto is2big; return 0; is2big: errno = E2BIG; return -1; } /*---------------------------------------------------------------------------*/ static void print_usage(const struct option longopts[], const struct lxc_arguments *a_args) { int i; const struct option *opt; fprintf(stderr, "Usage: %s ", a_args->progname); for (opt = longopts, i = 1; opt->name; opt++, i++) { int j; char *uppername = strdup(opt->name); if (!uppername) exit(-ENOMEM); for (j = 0; uppername[j]; j++) uppername[j] = toupper(uppername[j]); fprintf(stderr, "["); if (isprint(opt->val)) fprintf(stderr, "-%c|", opt->val); fprintf(stderr, "--%s", opt->name); if (opt->has_arg == required_argument) fprintf(stderr, "=%s", uppername); if (opt->has_arg == optional_argument) fprintf(stderr, "[=%s]", uppername); fprintf(stderr, "] "); if (!(i % 4)) fprintf(stderr, "\n\t"); free(uppername); } fprintf(stderr, "\n"); exit(0); } static void print_version() { printf("%s\n", LXC_VERSION); exit(0); } static void print_help(const struct lxc_arguments *args, int code) { fprintf(stderr, "\ Usage: %s %s\ \n\ Common options :\n\ -o, --logfile=FILE Output log to FILE instead of stderr\n\ -l, --logpriority=LEVEL Set log priority to LEVEL\n\ -q, --quiet Don't produce any output\n\ -P, --lxcpath=PATH Use specified container path\n\ -?, --help Give this help list\n\ --usage Give a short usage message\n\ --version Print the version number\n\ \n\ Mandatory or optional arguments to long options are also mandatory or optional\n\ for any corresponding short options.\n\ \n\ See the %s man page for further information.\n\n", args->progname, args->help, args->progname); if (args->helpfn) args->helpfn(args); exit(code); } static int lxc_arguments_lxcpath_add(struct lxc_arguments *args, const char *lxcpath) { if (args->lxcpath_additional != -1 && args->lxcpath_cnt > args->lxcpath_additional) { fprintf(stderr, "This command only accepts %d -P,--lxcpath arguments\n", args->lxcpath_additional + 1); exit(EXIT_FAILURE); } args->lxcpath = realloc(args->lxcpath, (args->lxcpath_cnt + 1) * sizeof(args->lxcpath[0])); if (args->lxcpath == NULL) { lxc_error(args, "no memory"); return -ENOMEM; } args->lxcpath[args->lxcpath_cnt++] = lxcpath; return 0; } extern int lxc_arguments_parse(struct lxc_arguments *args, int argc, char * const argv[]) { char shortopts[256]; int ret = 0; ret = build_shortopts(args->options, shortopts, sizeof(shortopts)); if (ret < 0) { lxc_error(args, "build_shortopts() failed : %s", strerror(errno)); return ret; } while (1) { int c, index = 0; c = getopt_long(argc, argv, shortopts, args->options, &index); if (c == -1) break; switch (c) { case 'n': args->name = optarg; break; case 'o': args->log_file = optarg; break; case 'l': args->log_priority = optarg; break; case 'q': args->quiet = 1; break; case OPT_RCFILE: args->rcfile = optarg; break; case 'P': remove_trailing_slashes(optarg); ret = lxc_arguments_lxcpath_add(args, optarg); if (ret < 0) return ret; break; case OPT_USAGE: print_usage(args->options, args); case OPT_VERSION: print_version(); case '?': print_help(args, 1); case 'h': print_help(args, 0); default: if (args->parser) { ret = args->parser(args, c, optarg); if (ret) goto error; } } } /* * Reclaim the remaining command arguments */ args->argv = &argv[optind]; args->argc = argc - optind; /* If no lxcpaths were given, use default */ if (!args->lxcpath_cnt) { ret = lxc_arguments_lxcpath_add(args, lxc_global_config_value("lxc.lxcpath")); if (ret < 0) return ret; } /* Check the command options */ if (!args->name && strcmp(args->progname, "lxc-autostart") != 0) { lxc_error(args, "missing container name, use --name option"); return -1; } if (args->checker) ret = args->checker(args); error: if (ret) lxc_error(args, "could not parse command line"); return ret; } int lxc_arguments_str_to_int(struct lxc_arguments *args, const char *str) { long val; char *endptr; errno = 0; val = strtol(str, &endptr, 10); if (errno) { lxc_error(args, "invalid statefd '%s' : %m", str); return -1; } if (*endptr) { lxc_error(args, "invalid digit for statefd '%s'", str); return -1; } return (int)val; } lxc-2.0.8/src/lxc/seccomp.c0000644061062106075000000005202113105116772012415 00000000000000/* * lxc: linux Container library * * (C) Copyright Canonical, Inc. 2012 * * Authors: * Serge Hallyn * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #include #include #include #include #include #include #include "config.h" #include "log.h" #include "lxcseccomp.h" lxc_log_define(lxc_seccomp, lxc); static int parse_config_v1(FILE *f, struct lxc_conf *conf) { char line[1024]; int ret; while (fgets(line, 1024, f)) { int nr; ret = sscanf(line, "%d", &nr); if (ret != 1) return -1; ret = seccomp_rule_add( #if HAVE_SCMP_FILTER_CTX conf->seccomp_ctx, #endif SCMP_ACT_ALLOW, nr, 0); if (ret < 0) { ERROR("Failed loading allow rule for %d.", nr); return ret; } } return 0; } #if HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH static void remove_trailing_newlines(char *l) { char *p = l; while (*p) p++; while (--p >= l && *p == '\n') *p = '\0'; } static uint32_t get_v2_default_action(char *line) { uint32_t ret_action = -1; while (*line == ' ') line++; // after 'whitelist' or 'blacklist' comes default behavior if (strncmp(line, "kill", 4) == 0) ret_action = SCMP_ACT_KILL; else if (strncmp(line, "errno", 5) == 0) { int e; if (sscanf(line + 5, "%d", &e) != 1) { ERROR("Bad errno value in %s.", line); return -2; } ret_action = SCMP_ACT_ERRNO(e); } else if (strncmp(line, "allow", 5) == 0) ret_action = SCMP_ACT_ALLOW; else if (strncmp(line, "trap", 4) == 0) ret_action = SCMP_ACT_TRAP; return ret_action; } static uint32_t get_and_clear_v2_action(char *line, uint32_t def_action) { char *p = strchr(line, ' '); uint32_t ret; if (!p) return def_action; *p = '\0'; p++; while (*p == ' ') p++; if (!*p || *p == '#') return def_action; ret = get_v2_default_action(p); switch(ret) { case -2: return -1; case -1: return def_action; default: return ret; } } #endif #if HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH enum lxc_hostarch_t { lxc_seccomp_arch_all = 0, lxc_seccomp_arch_native, lxc_seccomp_arch_i386, lxc_seccomp_arch_x32, lxc_seccomp_arch_amd64, lxc_seccomp_arch_arm, lxc_seccomp_arch_arm64, lxc_seccomp_arch_ppc64, lxc_seccomp_arch_ppc64le, lxc_seccomp_arch_ppc, lxc_seccomp_arch_mips, lxc_seccomp_arch_mips64, lxc_seccomp_arch_mips64n32, lxc_seccomp_arch_mipsel, lxc_seccomp_arch_mipsel64, lxc_seccomp_arch_mipsel64n32, lxc_seccomp_arch_s390x, lxc_seccomp_arch_unknown = 999, }; #ifdef __MIPSEL__ # define MIPS_ARCH_O32 lxc_seccomp_arch_mipsel # define MIPS_ARCH_N64 lxc_seccomp_arch_mipsel64 #else # define MIPS_ARCH_O32 lxc_seccomp_arch_mips # define MIPS_ARCH_N64 lxc_seccomp_arch_mips64 #endif int get_hostarch(void) { struct utsname uts; if (uname(&uts) < 0) { SYSERROR("Failed to read host arch."); return -1; } if (strcmp(uts.machine, "i686") == 0) return lxc_seccomp_arch_i386; // no x32 kernels else if (strcmp(uts.machine, "x86_64") == 0) return lxc_seccomp_arch_amd64; else if (strncmp(uts.machine, "armv7", 5) == 0) return lxc_seccomp_arch_arm; else if (strncmp(uts.machine, "aarch64", 7) == 0) return lxc_seccomp_arch_arm64; else if (strncmp(uts.machine, "ppc64le", 7) == 0) return lxc_seccomp_arch_ppc64le; else if (strncmp(uts.machine, "ppc64", 5) == 0) return lxc_seccomp_arch_ppc64; else if (strncmp(uts.machine, "ppc", 3) == 0) return lxc_seccomp_arch_ppc; else if (strncmp(uts.machine, "mips64", 6) == 0) return MIPS_ARCH_N64; else if (strncmp(uts.machine, "mips", 4) == 0) return MIPS_ARCH_O32; else if (strncmp(uts.machine, "s390x", 5) == 0) return lxc_seccomp_arch_s390x; return lxc_seccomp_arch_unknown; } scmp_filter_ctx get_new_ctx(enum lxc_hostarch_t n_arch, uint32_t default_policy_action) { scmp_filter_ctx ctx; int ret; uint32_t arch; switch(n_arch) { case lxc_seccomp_arch_i386: arch = SCMP_ARCH_X86; break; case lxc_seccomp_arch_x32: arch = SCMP_ARCH_X32; break; case lxc_seccomp_arch_amd64: arch = SCMP_ARCH_X86_64; break; case lxc_seccomp_arch_arm: arch = SCMP_ARCH_ARM; break; #ifdef SCMP_ARCH_AARCH64 case lxc_seccomp_arch_arm64: arch = SCMP_ARCH_AARCH64; break; #endif #ifdef SCMP_ARCH_PPC64LE case lxc_seccomp_arch_ppc64le: arch = SCMP_ARCH_PPC64LE; break; #endif #ifdef SCMP_ARCH_PPC64 case lxc_seccomp_arch_ppc64: arch = SCMP_ARCH_PPC64; break; #endif #ifdef SCMP_ARCH_PPC case lxc_seccomp_arch_ppc: arch = SCMP_ARCH_PPC; break; #endif #ifdef SCMP_ARCH_MIPS case lxc_seccomp_arch_mips: arch = SCMP_ARCH_MIPS; break; case lxc_seccomp_arch_mips64: arch = SCMP_ARCH_MIPS64; break; case lxc_seccomp_arch_mips64n32: arch = SCMP_ARCH_MIPS64N32; break; case lxc_seccomp_arch_mipsel: arch = SCMP_ARCH_MIPSEL; break; case lxc_seccomp_arch_mipsel64: arch = SCMP_ARCH_MIPSEL64; break; case lxc_seccomp_arch_mipsel64n32: arch = SCMP_ARCH_MIPSEL64N32; break; #endif #ifdef SCMP_ARCH_S390X case lxc_seccomp_arch_s390x: arch = SCMP_ARCH_S390X; break; #endif default: return NULL; } if ((ctx = seccomp_init(default_policy_action)) == NULL) { ERROR("Error initializing seccomp context."); return NULL; } if (seccomp_attr_set(ctx, SCMP_FLTATR_CTL_NNP, 0)) { ERROR("Failed to turn off n-new-privs."); seccomp_release(ctx); return NULL; } #ifdef SCMP_FLTATR_ATL_TSKIP if (seccomp_attr_set(ctx, SCMP_FLTATR_ATL_TSKIP, 1)) { WARN("Failed to turn on seccomp nop-skip, continuing"); } #endif ret = seccomp_arch_add(ctx, arch); if (ret != 0) { ERROR("Seccomp error %d (%s) adding arch: %d", ret, strerror(-ret), (int)n_arch); seccomp_release(ctx); return NULL; } if (seccomp_arch_remove(ctx, SCMP_ARCH_NATIVE) != 0) { ERROR("Seccomp error removing native arch"); seccomp_release(ctx); return NULL; } return ctx; } bool do_resolve_add_rule(uint32_t arch, char *line, scmp_filter_ctx ctx, uint32_t action) { int nr, ret; ret = seccomp_arch_exist(ctx, arch); if (arch && ret != 0) { ERROR("BUG: Seccomp: rule and context arch do not match (arch " "%d): %s.", arch, strerror(-ret)); return false; } if (strncmp(line, "reject_force_umount", 19) == 0) { INFO("Setting Seccomp rule to reject force umounts."); ret = seccomp_rule_add_exact(ctx, SCMP_ACT_ERRNO(EACCES), SCMP_SYS(umount2), 1, SCMP_A1(SCMP_CMP_MASKED_EQ , MNT_FORCE , MNT_FORCE )); if (ret < 0) { ERROR("Failed (%d) loading rule to reject force " "umount: %s.", ret, strerror(-ret)); return false; } return true; } nr = seccomp_syscall_resolve_name(line); if (nr == __NR_SCMP_ERROR) { WARN("Seccomp: failed to resolve syscall: %s.", line); WARN("This syscall will NOT be blacklisted."); return true; } if (nr < 0) { WARN("Seccomp: got negative for syscall: %d: %s.", nr, line); WARN("This syscall will NOT be blacklisted."); return true; } ret = seccomp_rule_add_exact(ctx, action, nr, 0); if (ret < 0) { ERROR("Failed (%d) loading rule for %s (nr %d action %d): %s.", ret, line, nr, action, strerror(-ret)); return false; } return true; } /* * v2 consists of * [x86] * open * read * write * close * # a comment * [x86_64] * open * read * write * close */ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf) { char *p; int ret; scmp_filter_ctx compat_ctx[2] = {NULL, NULL}; bool blacklist = false; uint32_t default_policy_action = -1, default_rule_action = -1, action; enum lxc_hostarch_t native_arch = get_hostarch(), cur_rule_arch = native_arch; uint32_t compat_arch[2] = {SCMP_ARCH_NATIVE, SCMP_ARCH_NATIVE}; if (strncmp(line, "blacklist", 9) == 0) blacklist = true; else if (strncmp(line, "whitelist", 9) != 0) { ERROR("Bad seccomp policy style: %s.", line); return -1; } if ((p = strchr(line, ' '))) { default_policy_action = get_v2_default_action(p + 1); if (default_policy_action == -2) return -1; } /* for blacklist, allow any syscall which has no rule */ if (blacklist) { if (default_policy_action == -1) default_policy_action = SCMP_ACT_ALLOW; if (default_rule_action == -1) default_rule_action = SCMP_ACT_KILL; } else { if (default_policy_action == -1) default_policy_action = SCMP_ACT_KILL; if (default_rule_action == -1) default_rule_action = SCMP_ACT_ALLOW; } if (native_arch == lxc_seccomp_arch_amd64) { cur_rule_arch = lxc_seccomp_arch_all; compat_arch[0] = SCMP_ARCH_X86; compat_ctx[0] = get_new_ctx(lxc_seccomp_arch_i386, default_policy_action); compat_arch[1] = SCMP_ARCH_X32; compat_ctx[1] = get_new_ctx(lxc_seccomp_arch_x32, default_policy_action); if (!compat_ctx[0] || !compat_ctx[1]) goto bad; #ifdef SCMP_ARCH_PPC } else if (native_arch == lxc_seccomp_arch_ppc64) { cur_rule_arch = lxc_seccomp_arch_all; compat_arch[0] = SCMP_ARCH_PPC; compat_ctx[0] = get_new_ctx(lxc_seccomp_arch_ppc, default_policy_action); if (!compat_ctx[0]) goto bad; #endif #ifdef SCMP_ARCH_ARM } else if (native_arch == lxc_seccomp_arch_arm64) { cur_rule_arch = lxc_seccomp_arch_all; compat_arch[0] = SCMP_ARCH_ARM; compat_ctx[0] = get_new_ctx(lxc_seccomp_arch_arm, default_policy_action); if (!compat_ctx[0]) goto bad; #endif #ifdef SCMP_ARCH_MIPS } else if (native_arch == lxc_seccomp_arch_mips64) { cur_rule_arch = lxc_seccomp_arch_all; compat_arch[0] = SCMP_ARCH_MIPS; compat_arch[1] = SCMP_ARCH_MIPS64N32; compat_ctx[0] = get_new_ctx(lxc_seccomp_arch_mips, default_policy_action); compat_ctx[1] = get_new_ctx(lxc_seccomp_arch_mips64n32, default_policy_action); if (!compat_ctx[0] || !compat_ctx[1]) goto bad; } else if (native_arch == lxc_seccomp_arch_mipsel64) { cur_rule_arch = lxc_seccomp_arch_all; compat_arch[0] = SCMP_ARCH_MIPSEL; compat_arch[1] = SCMP_ARCH_MIPSEL64N32; compat_ctx[0] = get_new_ctx(lxc_seccomp_arch_mipsel, default_policy_action); compat_ctx[1] = get_new_ctx(lxc_seccomp_arch_mipsel64n32, default_policy_action); if (!compat_ctx[0] || !compat_ctx[1]) goto bad; #endif } if (default_policy_action != SCMP_ACT_KILL) { ret = seccomp_reset(conf->seccomp_ctx, default_policy_action); if (ret != 0) { ERROR("Error re-initializing Seccomp."); return -1; } if (seccomp_attr_set(conf->seccomp_ctx, SCMP_FLTATR_CTL_NNP, 0)) { ERROR("Failed to turn off n-new-privs."); return -1; } #ifdef SCMP_FLTATR_ATL_TSKIP if (seccomp_attr_set(conf->seccomp_ctx, SCMP_FLTATR_ATL_TSKIP, 1)) { WARN("Failed to turn on seccomp nop-skip, continuing"); } #endif } while (fgets(line, 1024, f)) { if (line[0] == '#') continue; if (strlen(line) == 0) continue; remove_trailing_newlines(line); INFO("processing: .%s.", line); if (line[0] == '[') { // read the architecture for next set of rules if (strcmp(line, "[x86]") == 0 || strcmp(line, "[X86]") == 0) { if (native_arch != lxc_seccomp_arch_i386 && native_arch != lxc_seccomp_arch_amd64) { cur_rule_arch = lxc_seccomp_arch_unknown; continue; } cur_rule_arch = lxc_seccomp_arch_i386; } else if (strcmp(line, "[x32]") == 0 || strcmp(line, "[X32]") == 0) { if (native_arch != lxc_seccomp_arch_amd64) { cur_rule_arch = lxc_seccomp_arch_unknown; continue; } cur_rule_arch = lxc_seccomp_arch_x32; } else if (strcmp(line, "[X86_64]") == 0 || strcmp(line, "[x86_64]") == 0) { if (native_arch != lxc_seccomp_arch_amd64) { cur_rule_arch = lxc_seccomp_arch_unknown; continue; } cur_rule_arch = lxc_seccomp_arch_amd64; } else if (strcmp(line, "[all]") == 0 || strcmp(line, "[ALL]") == 0) { cur_rule_arch = lxc_seccomp_arch_all; } #ifdef SCMP_ARCH_ARM else if (strcmp(line, "[arm]") == 0 || strcmp(line, "[ARM]") == 0) { if (native_arch != lxc_seccomp_arch_arm && native_arch != lxc_seccomp_arch_arm64) { cur_rule_arch = lxc_seccomp_arch_unknown; continue; } cur_rule_arch = lxc_seccomp_arch_arm; } #endif #ifdef SCMP_ARCH_AARCH64 else if (strcmp(line, "[arm64]") == 0 || strcmp(line, "[ARM64]") == 0) { if (native_arch != lxc_seccomp_arch_arm64) { cur_rule_arch = lxc_seccomp_arch_unknown; continue; } cur_rule_arch = lxc_seccomp_arch_arm64; } #endif #ifdef SCMP_ARCH_PPC64LE else if (strcmp(line, "[ppc64le]") == 0 || strcmp(line, "[PPC64LE]") == 0) { if (native_arch != lxc_seccomp_arch_ppc64le) { cur_rule_arch = lxc_seccomp_arch_unknown; continue; } cur_rule_arch = lxc_seccomp_arch_ppc64le; } #endif #ifdef SCMP_ARCH_PPC64 else if (strcmp(line, "[ppc64]") == 0 || strcmp(line, "[PPC64]") == 0) { if (native_arch != lxc_seccomp_arch_ppc64) { cur_rule_arch = lxc_seccomp_arch_unknown; continue; } cur_rule_arch = lxc_seccomp_arch_ppc64; } #endif #ifdef SCMP_ARCH_PPC else if (strcmp(line, "[ppc]") == 0 || strcmp(line, "[PPC]") == 0) { if (native_arch != lxc_seccomp_arch_ppc && native_arch != lxc_seccomp_arch_ppc64) { cur_rule_arch = lxc_seccomp_arch_unknown; continue; } cur_rule_arch = lxc_seccomp_arch_ppc; } #endif #ifdef SCMP_ARCH_MIPS else if (strcmp(line, "[mips64]") == 0 || strcmp(line, "[MIPS64]") == 0) { if (native_arch != lxc_seccomp_arch_mips64) { cur_rule_arch = lxc_seccomp_arch_unknown; continue; } cur_rule_arch = lxc_seccomp_arch_mips64; } else if (strcmp(line, "[mips64n32]") == 0 || strcmp(line, "[MIPS64N32]") == 0) { if (native_arch != lxc_seccomp_arch_mips64) { cur_rule_arch = lxc_seccomp_arch_unknown; continue; } cur_rule_arch = lxc_seccomp_arch_mips64n32; } else if (strcmp(line, "[mips]") == 0 || strcmp(line, "[MIPS]") == 0) { if (native_arch != lxc_seccomp_arch_mips && native_arch != lxc_seccomp_arch_mips64) { cur_rule_arch = lxc_seccomp_arch_unknown; continue; } cur_rule_arch = lxc_seccomp_arch_mips; } else if (strcmp(line, "[mipsel64]") == 0 || strcmp(line, "[MIPSEL64]") == 0) { if (native_arch != lxc_seccomp_arch_mipsel64) { cur_rule_arch = lxc_seccomp_arch_unknown; continue; } cur_rule_arch = lxc_seccomp_arch_mipsel64; } else if (strcmp(line, "[mipsel64n32]") == 0 || strcmp(line, "[MIPSEL64N32]") == 0) { if (native_arch != lxc_seccomp_arch_mipsel64) { cur_rule_arch = lxc_seccomp_arch_unknown; continue; } cur_rule_arch = lxc_seccomp_arch_mipsel64n32; } else if (strcmp(line, "[mipsel]") == 0 || strcmp(line, "[MIPSEL]") == 0) { if (native_arch != lxc_seccomp_arch_mipsel && native_arch != lxc_seccomp_arch_mipsel64) { cur_rule_arch = lxc_seccomp_arch_unknown; continue; } cur_rule_arch = lxc_seccomp_arch_mipsel; } #endif #ifdef SCMP_ARCH_S390X else if (strcmp(line, "[s390x]") == 0 || strcmp(line, "[S390X]") == 0) { if (native_arch != lxc_seccomp_arch_s390x) { cur_rule_arch = lxc_seccomp_arch_unknown; continue; } cur_rule_arch = lxc_seccomp_arch_s390x; } #endif else goto bad_arch; continue; } /* irrelevant arch - i.e. arm on i386 */ if (cur_rule_arch == lxc_seccomp_arch_unknown) continue; /* read optional action which follows the syscall */ action = get_and_clear_v2_action(line, default_rule_action); if (action == -1) { ERROR("Failed to interpret action."); goto bad_rule; } if (cur_rule_arch == native_arch || cur_rule_arch == lxc_seccomp_arch_native || compat_arch[0] == SCMP_ARCH_NATIVE) { INFO("Adding native rule for %s action %d.", line, action); if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, conf->seccomp_ctx, action)) goto bad_rule; } else if (cur_rule_arch != lxc_seccomp_arch_all) { int arch_index = cur_rule_arch == lxc_seccomp_arch_mips64n32 || cur_rule_arch == lxc_seccomp_arch_mipsel64n32 ? 1 : 0; INFO("Adding compat-only rule for %s action %d.", line, action); if (!do_resolve_add_rule(compat_arch[arch_index], line, compat_ctx[arch_index], action)) goto bad_rule; } else { INFO("Adding native rule for %s action %d.", line, action); if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, conf->seccomp_ctx, action)) goto bad_rule; INFO("Adding compat rule for %s action %d.", line, action); if (!do_resolve_add_rule(compat_arch[0], line, compat_ctx[0], action)) goto bad_rule; if (compat_arch[1] != SCMP_ARCH_NATIVE && !do_resolve_add_rule(compat_arch[1], line, compat_ctx[1], action)) goto bad_rule; } } if (compat_ctx[0]) { INFO("Merging in the compat Seccomp ctx into the main one."); if (seccomp_merge(conf->seccomp_ctx, compat_ctx[0]) != 0 || (compat_ctx[1] != NULL && seccomp_merge(conf->seccomp_ctx, compat_ctx[1]) != 0)) { ERROR("Error merging compat Seccomp contexts."); goto bad; } } return 0; bad_arch: ERROR("Unsupported arch: %s.", line); bad_rule: bad: if (compat_ctx[0]) seccomp_release(compat_ctx[0]); if (compat_ctx[1]) seccomp_release(compat_ctx[1]); return -1; } #else /* HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH */ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf) { return -1; } #endif /* HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH */ /* * The first line of the config file has a policy language version * the second line has some directives * then comes policy subject to the directives * right now version must be '1' * the directives must include 'whitelist' (only type of policy currently * supported) and can include 'debug' (though debug is not yet supported). */ static int parse_config(FILE *f, struct lxc_conf *conf) { char line[1024]; int ret, version; ret = fscanf(f, "%d\n", &version); if (ret != 1 || (version != 1 && version != 2)) { ERROR("Invalid version."); return -1; } if (!fgets(line, 1024, f)) { ERROR("Invalid config file."); return -1; } if (version == 1 && !strstr(line, "whitelist")) { ERROR("Only whitelist policy is supported."); return -1; } if (strstr(line, "debug")) { ERROR("Debug not yet implemented."); return -1; } if (version == 1) return parse_config_v1(f, conf); return parse_config_v2(f, line, conf); } /* * use_seccomp: return true if we should try and apply a seccomp policy * if defined for the container. * This will return false if * 1. seccomp is not enabled in the kernel * 2. a seccomp policy is already enabled for this task */ static bool use_seccomp(void) { FILE *f = fopen("/proc/self/status", "r"); char line[1024]; bool already_enabled = false; bool found = false; int ret, v; if (!f) return true; while (fgets(line, 1024, f)) { if (strncmp(line, "Seccomp:", 8) == 0) { found = true; ret = sscanf(line + 8, "%d", &v); if (ret == 1 && v != 0) already_enabled = true; break; } } fclose(f); if (!found) { /* no Seccomp line, no seccomp in kernel */ INFO("Seccomp is not enabled in the kernel."); return false; } if (already_enabled) { /* already seccomp-confined */ INFO("Already seccomp-confined, not loading new policy."); return false; } return true; } int lxc_read_seccomp_config(struct lxc_conf *conf) { FILE *f; int ret; int check_seccomp_attr_set; if (!conf->seccomp) return 0; if (!use_seccomp()) return 0; #if HAVE_SCMP_FILTER_CTX /* XXX for debug, pass in SCMP_ACT_TRAP */ conf->seccomp_ctx = seccomp_init(SCMP_ACT_KILL); ret = !conf->seccomp_ctx; #else ret = seccomp_init(SCMP_ACT_KILL) < 0; #endif if (ret) { ERROR("Failed initializing seccomp."); return -1; } /* turn off no-new-privs. We don't want it in lxc, and it breaks * with apparmor */ #if HAVE_SCMP_FILTER_CTX check_seccomp_attr_set = seccomp_attr_set(conf->seccomp_ctx, SCMP_FLTATR_CTL_NNP, 0); #else check_seccomp_attr_set = seccomp_attr_set(SCMP_FLTATR_CTL_NNP, 0); #endif if (check_seccomp_attr_set) { ERROR("Failed to turn off n-new-privs."); return -1; } #ifdef SCMP_FLTATR_ATL_TSKIP if (seccomp_attr_set(conf->seccomp_ctx, SCMP_FLTATR_ATL_TSKIP, 1)) { WARN("Failed to turn on seccomp nop-skip, continuing"); } #endif f = fopen(conf->seccomp, "r"); if (!f) { SYSERROR("Failed to open seccomp policy file %s.", conf->seccomp); return -1; } ret = parse_config(f, conf); fclose(f); return ret; } int lxc_seccomp_load(struct lxc_conf *conf) { int ret; if (!conf->seccomp) return 0; if (!use_seccomp()) return 0; ret = seccomp_load( #if HAVE_SCMP_FILTER_CTX conf->seccomp_ctx #endif ); if (ret < 0) { ERROR("Error loading the seccomp policy."); return -1; } return 0; } void lxc_seccomp_free(struct lxc_conf *conf) { free(conf->seccomp); conf->seccomp = NULL; #if HAVE_SCMP_FILTER_CTX if (conf->seccomp_ctx) { seccomp_release(conf->seccomp_ctx); conf->seccomp_ctx = NULL; } #endif } lxc-2.0.8/src/lxc/confile.h0000644061062106075000000000521413105116772012412 00000000000000/* * lxc: linux Container library * * (C) Copyright IBM Corp. 2007, 2008 * * Authors: * Daniel Lezcano * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LXC_CONFILE_H #define __LXC_CONFILE_H #include #include #include struct lxc_conf; struct lxc_list; typedef int (*config_cb)(const char *, const char *, struct lxc_conf *); struct lxc_config_t { char *name; config_cb cb; }; extern struct lxc_config_t *lxc_getconfig(const char *key); extern int lxc_list_nicconfigs(struct lxc_conf *c, const char *key, char *retv, int inlen); extern int lxc_listconfigs(char *retv, int inlen); extern int lxc_config_read(const char *file, struct lxc_conf *conf, bool from_include); extern int append_unexp_config_line(const char *line, struct lxc_conf *conf); extern int lxc_config_define_add(struct lxc_list *defines, char* arg); extern int lxc_config_define_load(struct lxc_list *defines, struct lxc_conf *conf); /* needed for lxc-attach */ extern signed long lxc_config_parse_arch(const char *arch); extern int lxc_fill_elevated_privileges(char *flaglist, int *flags); extern int lxc_get_config_item(struct lxc_conf *c, const char *key, char *retv, int inlen); extern int lxc_clear_config_item(struct lxc_conf *c, const char *key); extern void write_config(FILE *fout, struct lxc_conf *c); extern bool do_append_unexp_config_line(struct lxc_conf *conf, const char *key, const char *v); /* These are used when cloning a container */ extern void clear_unexp_config_line(struct lxc_conf *conf, const char *key, bool rm_subkeys); extern bool clone_update_unexp_hooks(struct lxc_conf *conf, const char *oldpath, const char *newpath, const char *oldname, const char *newmame); bool clone_update_unexp_ovl_paths(struct lxc_conf *conf, const char *oldpath, const char *newpath, const char *oldname, const char *newname, const char *ovldir); extern bool network_new_hwaddrs(struct lxc_conf *conf); #endif lxc-2.0.8/src/lxc/Makefile.am0000644061062106075000000001542013105116772012656 00000000000000pkginclude_HEADERS = \ attach_options.h \ lxccontainer.h \ version.h noinst_HEADERS = \ arguments.h \ attach.h \ bdev/bdev.h \ bdev/lxcaufs.h \ bdev/lxcbtrfs.h \ bdev/lxcdir.h \ bdev/lxcloop.h \ bdev/lxclvm.h \ bdev/lxcnbd.h \ bdev/lxcoverlay.h \ bdev/lxcrbd.h \ bdev/lxcrsync.h \ bdev/lxczfs.h \ cgroups/cgroup.h \ caps.h \ conf.h \ console.h \ error.h \ initutils.h \ list.h \ log.h \ lxc.h \ lxclock.h \ monitor.h \ namespace.h \ start.h \ state.h \ utils.h \ criu.h \ ../tests/lxctest.h if IS_BIONIC noinst_HEADERS += \ ../include/ifaddrs.h \ ../include/openpty.h \ ../include/lxcmntent.h endif if !HAVE_GETLINE if HAVE_FGETLN noinst_HEADERS += ../include/getline.h endif endif if !HAVE_GETSUBOPT noinst_HEADERS += ../include/getsubopt.h endif sodir=$(libdir) LSM_SOURCES = \ lsm/nop.c \ lsm/lsm.h lsm/lsm.c if ENABLE_APPARMOR LSM_SOURCES += lsm/apparmor.c endif if ENABLE_SELINUX LSM_SOURCES += lsm/selinux.c endif lib_LTLIBRARIES = liblxc.la liblxc_la_SOURCES = \ arguments.c arguments.h \ bdev/bdev.c bdev/bdev.h \ bdev/lxcaufs.c bdev/lxcaufs.h \ bdev/lxcbtrfs.c bdev/lxcbtrfs.h \ bdev/lxcdir.c bdev/lxcdir.h \ bdev/lxcloop.c bdev/lxcloop.h \ bdev/lxclvm.c bdev/lxclvm.h \ bdev/lxcnbd.c bdev/lxcnbd.h \ bdev/lxcoverlay.c bdev/lxcoverlay.h \ bdev/lxcrbd.c bdev/lxcrbd.h \ bdev/lxcrsync.c bdev/lxcrsync.h \ bdev/lxczfs.c bdev/lxczfs.h \ cgroups/cgfs.c \ cgroups/cgfsng.c \ cgroups/cgroup.c cgroups/cgroup.h \ commands.c commands.h \ start.c start.h \ execute.c \ monitor.c monitor.h \ console.c \ freezer.c \ error.h error.c \ parse.c parse.h \ lxc.h \ initutils.c initutils.h \ utils.c utils.h \ sync.c sync.h \ namespace.h namespace.c \ conf.c conf.h \ confile.c confile.h \ list.h \ state.c state.h \ log.c log.h \ attach.c attach.h \ criu.c criu.h \ \ network.c network.h \ nl.c nl.h \ rtnl.c rtnl.h \ genl.c genl.h \ \ caps.c caps.h \ lxcseccomp.h \ mainloop.c mainloop.h \ af_unix.c af_unix.h \ \ lxcutmp.c lxcutmp.h \ lxclock.h lxclock.c \ lxccontainer.c lxccontainer.h \ version.h \ \ $(LSM_SOURCES) if ENABLE_CGMANAGER liblxc_la_SOURCES += cgroups/cgmanager.c endif if IS_BIONIC liblxc_la_SOURCES += \ ../include/ifaddrs.c ../include/ifaddrs.h \ ../include/openpty.c ../include/openpty.h \ ../include/lxcmntent.c ../include/lxcmntent.h endif if !HAVE_GETLINE if HAVE_FGETLN liblxc_la_SOURCES += ../include/getline.c ../include/getline.h endif endif AM_CFLAGS=-DLXCROOTFSMOUNT=\"$(LXCROOTFSMOUNT)\" \ -DLXCPATH=\"$(LXCPATH)\" \ -DLXC_GLOBAL_CONF=\"$(LXC_GLOBAL_CONF)\" \ -DLXCINITDIR=\"$(LXCINITDIR)\" \ -DLIBEXECDIR=\"$(LIBEXECDIR)\" \ -DLXCTEMPLATEDIR=\"$(LXCTEMPLATEDIR)\" \ -DLXCTEMPLATECONFIG=\"$(LXCTEMPLATECONFIG)\" \ -DLOGPATH=\"$(LOGPATH)\" \ -DLXC_DEFAULT_CONFIG=\"$(LXC_DEFAULT_CONFIG)\" \ -DLXC_USERNIC_DB=\"$(LXC_USERNIC_DB)\" \ -DLXC_USERNIC_CONF=\"$(LXC_USERNIC_CONF)\" \ -DDEFAULT_CGROUP_PATTERN=\"$(DEFAULT_CGROUP_PATTERN)\" \ -DRUNTIME_PATH=\"$(RUNTIME_PATH)\" \ -DSBINDIR=\"$(SBINDIR)\" \ -I $(top_srcdir)/src \ -I $(top_srcdir)/src/lxc \ -I $(top_srcdir)/src/lxc/bdev \ -I $(top_srcdir)/src/lxc/cgroups if ENABLE_APPARMOR AM_CFLAGS += -DHAVE_APPARMOR endif if ENABLE_CGMANAGER AM_CFLAGS += -DHAVE_CGMANAGER endif if ENABLE_SELINUX AM_CFLAGS += -DHAVE_SELINUX endif if USE_CONFIGPATH_LOGS AM_CFLAGS += -DUSE_CONFIGPATH_LOGS endif if ENABLE_SECCOMP AM_CFLAGS += -DHAVE_SECCOMP $(SECCOMP_CFLAGS) liblxc_la_SOURCES += seccomp.c endif liblxc_la_CFLAGS = -fPIC -DPIC $(AM_CFLAGS) -pthread liblxc_la_LDFLAGS = \ -pthread \ -shared \ -Wl,-soname,liblxc.so.$(firstword $(subst ., ,@LXC_ABI@)) \ -version-info @LXC_ABI_MAJOR@ liblxc_la_LIBADD = $(CAP_LIBS) $(APPARMOR_LIBS) $(SELINUX_LIBS) $(SECCOMP_LIBS) if ENABLE_CGMANAGER liblxc_la_LIBADD += $(CGMANAGER_LIBS) $(DBUS_LIBS) $(NIH_LIBS) $(NIH_DBUS_LIBS) liblxc_la_CFLAGS += $(CGMANAGER_CFLAGS) $(DBUS_CFLAGS) $(NIH_CFLAGS) $(NIH_DBUS_CFLAGS) endif bin_SCRIPTS = tools/lxc-checkconfig EXTRA_DIST = \ tools/lxc-top.lua if ENABLE_DEPRECATED if ENABLE_PYTHON bin_SCRIPTS += tools/lxc-start-ephemeral endif endif bin_PROGRAMS = \ lxc-attach \ lxc-autostart \ lxc-cgroup \ lxc-checkpoint \ lxc-copy \ lxc-config \ lxc-console \ lxc-create \ lxc-destroy \ lxc-device \ lxc-execute \ lxc-freeze \ lxc-info \ lxc-ls \ lxc-monitor \ lxc-snapshot \ lxc-start \ lxc-stop \ lxc-top \ lxc-unfreeze \ lxc-unshare \ lxc-usernsexec \ lxc-wait if ENABLE_DEPRECATED bin_PROGRAMS += lxc-clone endif sbin_PROGRAMS = init.lxc pkglibexec_PROGRAMS = \ lxc-monitord \ lxc-user-nic AM_LDFLAGS = -Wl,-E if ENABLE_RPATH AM_LDFLAGS += -Wl,-rpath -Wl,$(libdir) endif LDADD=liblxc.la @CAP_LIBS@ @APPARMOR_LIBS@ @SELINUX_LIBS@ @SECCOMP_LIBS@ lxc_attach_SOURCES = tools/lxc_attach.c lxc_autostart_SOURCES = tools/lxc_autostart.c lxc_cgroup_SOURCES = tools/lxc_cgroup.c lxc_config_SOURCES = tools/lxc_config.c lxc_console_SOURCES = tools/lxc_console.c lxc_destroy_SOURCES = tools/lxc_destroy.c lxc_device_SOURCES = tools/lxc_device.c lxc_execute_SOURCES = tools/lxc_execute.c lxc_freeze_SOURCES = tools/lxc_freeze.c lxc_info_SOURCES = tools/lxc_info.c init_lxc_SOURCES = tools/lxc_init.c lxc_monitor_SOURCES = tools/lxc_monitor.c lxc_ls_SOURCES = tools/lxc_ls.c lxc_copy_SOURCES = tools/lxc_copy.c lxc_start_SOURCES = tools/lxc_start.c lxc_stop_SOURCES = tools/lxc_stop.c lxc_top_SOURCES = tools/lxc_top.c lxc_unfreeze_SOURCES = tools/lxc_unfreeze.c lxc_unshare_SOURCES = tools/lxc_unshare.c lxc_wait_SOURCES = tools/lxc_wait.c lxc_create_SOURCES = tools/lxc_create.c lxc_snapshot_SOURCES = tools/lxc_snapshot.c lxc_usernsexec_SOURCES = tools/lxc_usernsexec.c lxc_checkpoint_SOURCES = tools/lxc_checkpoint.c lxc_user_nic_SOURCES = lxc_user_nic.c network.c network.h lxc_monitord_SOURCES = lxc_monitord.c if ENABLE_DEPRECATED lxc_clone_SOURCES = tools/lxc_clone.c endif if !HAVE_GETSUBOPT lxc_copy_SOURCES += ../include/getsubopt.c ../include/getsubopt.h endif if HAVE_STATIC_LIBCAP sbin_PROGRAMS += init.lxc.static init_lxc_static_SOURCES = tools/lxc_init.c error.c log.c initutils.c caps.c if !HAVE_GETLINE if HAVE_FGETLN init_lxc_static_SOURCES += ../include/getline.c endif endif init_lxc_static_LDFLAGS = -all-static init_lxc_static_LDADD = @CAP_LIBS@ init_lxc_static_CFLAGS = $(AM_CFLAGS) -DNO_LXC_CONF endif install-exec-local: install-libLTLIBRARIES mkdir -p $(DESTDIR)$(datadir)/lxc install -c -m 644 lxc.functions $(DESTDIR)$(datadir)/lxc mv $(shell readlink -f $(DESTDIR)$(libdir)/liblxc.so) $(DESTDIR)$(libdir)/liblxc.so.@LXC_ABI@ rm -f $(DESTDIR)$(libdir)/liblxc.so $(DESTDIR)$(libdir)/liblxc.so.1 cd $(DESTDIR)$(libdir); \ ln -sf liblxc.so.@LXC_ABI@ liblxc.so.$(firstword $(subst ., ,@LXC_ABI@)); \ ln -sf liblxc.so.$(firstword $(subst ., ,@LXC_ABI@)) liblxc.so install-exec-hook: chmod u+s $(DESTDIR)$(libexecdir)/lxc/lxc-user-nic uninstall-local: $(RM) $(DESTDIR)$(libdir)/liblxc.so* lxc-2.0.8/src/lxc/lxc_monitord.c0000644061062106075000000002507513105116772013476 00000000000000/* * lxc: linux Container library * * Copyright © 2012 Oracle. * * Authors: * Dwight Engen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "af_unix.h" #include "log.h" #include "mainloop.h" #include "monitor.h" #include "utils.h" #define CLIENTFDS_CHUNK 64 lxc_log_define(lxc_monitord, lxc); sigjmp_buf mark; static void lxc_monitord_cleanup(void); /* * Defines the structure to store the monitor information * @lxcpath : the path being monitored * @fifofd : the file descriptor for publishers (containers) to write state * @listenfd : the file descriptor for subscribers (lxc-monitors) to connect * @clientfds : accepted client file descriptors * @clientfds_size : number of file descriptors clientfds can hold * @clientfds_cnt : the count of valid fds in clientfds * @descr : the lxc_mainloop state */ struct lxc_monitor { const char *lxcpath; int fifofd; int listenfd; int *clientfds; int clientfds_size; int clientfds_cnt; struct lxc_epoll_descr descr; }; static struct lxc_monitor mon; static int quit; static int lxc_monitord_fifo_create(struct lxc_monitor *mon) { struct flock lk; char fifo_path[PATH_MAX]; int ret; ret = lxc_monitor_fifo_name(mon->lxcpath, fifo_path, sizeof(fifo_path), 1); if (ret < 0) return ret; ret = mknod(fifo_path, S_IFIFO|S_IRUSR|S_IWUSR, 0); if (ret < 0 && errno != EEXIST) { INFO("Failed to mknod monitor fifo %s: %s.", fifo_path, strerror(errno)); return -1; } mon->fifofd = open(fifo_path, O_RDWR); if (mon->fifofd < 0) { unlink(fifo_path); ERROR("Failed to open monitor fifo."); return -1; } lk.l_type = F_WRLCK; lk.l_whence = SEEK_SET; lk.l_start = 0; lk.l_len = 0; if (fcntl(mon->fifofd, F_SETLK, &lk) != 0) { /* another lxc-monitord is already running, don't start up */ DEBUG("lxc-monitord already running on lxcpath %s.", mon->lxcpath); close(mon->fifofd); return -1; } return 0; } static int lxc_monitord_fifo_delete(struct lxc_monitor *mon) { char fifo_path[PATH_MAX]; int ret; ret = lxc_monitor_fifo_name(mon->lxcpath, fifo_path, sizeof(fifo_path), 0); if (ret < 0) return ret; unlink(fifo_path); return 0; } static void lxc_monitord_sockfd_remove(struct lxc_monitor *mon, int fd) { int i; if (lxc_mainloop_del_handler(&mon->descr, fd)) CRIT("File descriptor %d not found in mainloop.", fd); close(fd); for (i = 0; i < mon->clientfds_cnt; i++) { if (mon->clientfds[i] == fd) break; } if (i >= mon->clientfds_cnt) { CRIT("File descriptor %d not found in clients array.", fd); lxc_monitord_cleanup(); exit(EXIT_FAILURE); } memmove(&mon->clientfds[i], &mon->clientfds[i+1], (mon->clientfds_cnt - i - 1) * sizeof(mon->clientfds[0])); mon->clientfds_cnt--; } static int lxc_monitord_sock_handler(int fd, uint32_t events, void *data, struct lxc_epoll_descr *descr) { struct lxc_monitor *mon = data; if (events & EPOLLIN) { int rc; char buf[4]; rc = read(fd, buf, sizeof(buf)); if (rc > 0 && !strncmp(buf, "quit", 4)) quit = 1; } if (events & EPOLLHUP) lxc_monitord_sockfd_remove(mon, fd); return quit; } static int lxc_monitord_sock_accept(int fd, uint32_t events, void *data, struct lxc_epoll_descr *descr) { int ret,clientfd; struct lxc_monitor *mon = data; struct ucred cred; socklen_t credsz = sizeof(cred); ret = -1; clientfd = accept(fd, NULL, 0); if (clientfd < 0) { SYSERROR("Failed to accept connection for client file descriptor %d.", fd); goto out; } if (fcntl(clientfd, F_SETFD, FD_CLOEXEC)) { SYSERROR("Failed to set FD_CLOEXEC on client socket connection %d.", clientfd); goto err1; } if (getsockopt(clientfd, SOL_SOCKET, SO_PEERCRED, &cred, &credsz)) { ERROR("Failed to get credentials on client socket connection %d.", clientfd); goto err1; } if (cred.uid && cred.uid != geteuid()) { WARN("Monitor denied for uid %d on client socket connection %d.", cred.uid, clientfd); ret = -EACCES; goto err1; } if (mon->clientfds_cnt + 1 > mon->clientfds_size) { int *clientfds; clientfds = realloc(mon->clientfds, (mon->clientfds_size + CLIENTFDS_CHUNK) * sizeof(mon->clientfds[0])); if (clientfds == NULL) { ERROR("Failed to realloc memory for %d client file " "descriptors.", mon->clientfds_size + CLIENTFDS_CHUNK); goto err1; } mon->clientfds = clientfds; mon->clientfds_size += CLIENTFDS_CHUNK; } ret = lxc_mainloop_add_handler(&mon->descr, clientfd, lxc_monitord_sock_handler, mon); if (ret) { ERROR("Failed to add socket handler."); goto err1; } mon->clientfds[mon->clientfds_cnt++] = clientfd; INFO("Accepted client file descriptor %d. Number of accepted file descriptors is now %d.", clientfd, mon->clientfds_cnt); goto out; err1: close(clientfd); out: return ret; } static int lxc_monitord_sock_create(struct lxc_monitor *mon) { struct sockaddr_un addr; int fd; if (lxc_monitor_sock_name(mon->lxcpath, &addr) < 0) return -1; fd = lxc_abstract_unix_open(addr.sun_path, SOCK_STREAM, O_TRUNC); if (fd < 0) { ERROR("Failed to open unix socket: %s.", strerror(errno)); return -1; } mon->listenfd = fd; return 0; } static int lxc_monitord_sock_delete(struct lxc_monitor *mon) { struct sockaddr_un addr; if (lxc_monitor_sock_name(mon->lxcpath, &addr) < 0) return -1; if (addr.sun_path[0]) unlink(addr.sun_path); return 0; } static int lxc_monitord_create(struct lxc_monitor *mon) { int ret; ret = lxc_monitord_fifo_create(mon); if (ret < 0) return ret; ret = lxc_monitord_sock_create(mon); return ret; } static void lxc_monitord_delete(struct lxc_monitor *mon) { int i; lxc_mainloop_del_handler(&mon->descr, mon->listenfd); close(mon->listenfd); lxc_monitord_sock_delete(mon); lxc_mainloop_del_handler(&mon->descr, mon->fifofd); lxc_monitord_fifo_delete(mon); close(mon->fifofd); for (i = 0; i < mon->clientfds_cnt; i++) { lxc_mainloop_del_handler(&mon->descr, mon->clientfds[i]); close(mon->clientfds[i]); } mon->clientfds_cnt = 0; } static int lxc_monitord_fifo_handler(int fd, uint32_t events, void *data, struct lxc_epoll_descr *descr) { int ret,i; struct lxc_msg msglxc; struct lxc_monitor *mon = data; ret = read(fd, &msglxc, sizeof(msglxc)); if (ret != sizeof(msglxc)) { SYSERROR("Reading from fifo failed: %s.", strerror(errno)); return 1; } for (i = 0; i < mon->clientfds_cnt; i++) { ret = write(mon->clientfds[i], &msglxc, sizeof(msglxc)); if (ret < 0) ERROR("Failed to send message to client file descriptor %d: %s.", mon->clientfds[i], strerror(errno)); } return 0; } static int lxc_monitord_mainloop_add(struct lxc_monitor *mon) { int ret; ret = lxc_mainloop_add_handler(&mon->descr, mon->fifofd, lxc_monitord_fifo_handler, mon); if (ret < 0) { ERROR("Failed to add to mainloop monitor handler for fifo."); return -1; } ret = lxc_mainloop_add_handler(&mon->descr, mon->listenfd, lxc_monitord_sock_accept, mon); if (ret < 0) { ERROR("Failed to add to mainloop monitor handler for listen socket."); return -1; } return 0; } static void lxc_monitord_cleanup(void) { lxc_monitord_delete(&mon); } static void lxc_monitord_sig_handler(int sig) { siglongjmp(mark, 1); } int main(int argc, char *argv[]) { int ret, pipefd; char logpath[PATH_MAX]; sigset_t mask; char *lxcpath = argv[1]; bool mainloop_opened = false; bool monitord_created = false; if (argc != 3) { fprintf(stderr, "Usage: lxc-monitord lxcpath sync-pipe-fd\n\n" "NOTE: lxc-monitord is intended for use by lxc internally\n" " and does not need to be run by hand\n\n"); exit(EXIT_FAILURE); } ret = snprintf(logpath, sizeof(logpath), "%s/lxc-monitord.log", (strcmp(LXCPATH, lxcpath) ? lxcpath : LOGPATH )); if (ret < 0 || ret >= sizeof(logpath)) exit(EXIT_FAILURE); ret = lxc_log_init(NULL, logpath, "DEBUG", "lxc-monitord", 0, lxcpath); if (ret) INFO("Failed to open log file %s, log will be lost.", lxcpath); lxc_log_options_no_override(); if (lxc_safe_int(argv[2], &pipefd) < 0) exit(EXIT_FAILURE); if (sigfillset(&mask) || sigdelset(&mask, SIGILL) || sigdelset(&mask, SIGSEGV) || sigdelset(&mask, SIGBUS) || sigdelset(&mask, SIGTERM) || sigprocmask(SIG_BLOCK, &mask, NULL)) { SYSERROR("Failed to set signal mask."); exit(EXIT_FAILURE); } signal(SIGILL, lxc_monitord_sig_handler); signal(SIGSEGV, lxc_monitord_sig_handler); signal(SIGBUS, lxc_monitord_sig_handler); signal(SIGTERM, lxc_monitord_sig_handler); if (sigsetjmp(mark, 1) != 0) goto on_signal; ret = EXIT_FAILURE; memset(&mon, 0, sizeof(mon)); mon.lxcpath = lxcpath; if (lxc_mainloop_open(&mon.descr)) { ERROR("Failed to create mainloop."); goto on_error; } mainloop_opened = true; if (lxc_monitord_create(&mon)) goto on_error; monitord_created = true; /* sync with parent, we're ignoring the return from write * because regardless if it works or not, the following * close will sync us with the parent process. the * if-empty-statement construct is to quiet the * warn-unused-result warning. */ if (write(pipefd, "S", 1)) ; close(pipefd); if (lxc_monitord_mainloop_add(&mon)) { ERROR("Failed to add mainloop handlers."); goto on_error; } NOTICE("lxc-monitord with pid %d is now monitoring lxcpath %s.", getpid(), mon.lxcpath); for (;;) { ret = lxc_mainloop(&mon.descr, 1000 * 30); if (mon.clientfds_cnt <= 0) { NOTICE("No remaining clients. lxc-monitord is exiting."); break; } } on_signal: ret = EXIT_SUCCESS; on_error: if (monitord_created) lxc_monitord_cleanup(); if (mainloop_opened) lxc_mainloop_close(&mon.descr); exit(ret); } lxc-2.0.8/src/lxc/lsm/0000755061062106075000000000000013105117015011462 500000000000000lxc-2.0.8/src/lxc/lsm/selinux.c0000644061062106075000000000572613105116772013260 00000000000000/* * lxc: linux Container library * * Copyright © 2013 Oracle. * * Authors: * Dwight Engen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include "log.h" #include "lsm/lsm.h" #include "conf.h" #define DEFAULT_LABEL "unconfined_t" lxc_log_define(lxc_lsm_selinux, lxc); /* * selinux_process_label_get: Get SELinux context of a process * * @pid : the pid to get, or 0 for self * * Returns the context of the given pid. The caller must free() * the returned string. * * Note that this relies on /proc being available. */ static char *selinux_process_label_get(pid_t pid) { security_context_t ctx; char *label; if (getpidcon_raw(pid, &ctx) < 0) { SYSERROR("failed to get SELinux context for pid %d", pid); return NULL; } label = strdup((char *)ctx); freecon(ctx); return label; } /* * selinux_process_label_set: Set SELinux context of a process * * @label : label string * @conf : the container configuration to use @label is NULL * @default : use the default context if label is NULL * @on_exec : the new context will take effect on exec(2) not immediately * * Returns 0 on success, < 0 on failure * * Notes: This relies on /proc being available. */ static int selinux_process_label_set(const char *inlabel, struct lxc_conf *conf, int use_default, int on_exec) { const char *label = inlabel ? inlabel : conf->lsm_se_context; if (!label) { if (use_default) label = DEFAULT_LABEL; else return -1; } if (!strcmp(label, "unconfined_t")) return 0; if (on_exec) { if (setexeccon_raw((char *)label) < 0) { SYSERROR("failed to set new SELinux exec context %s", label); return -1; } } else { if (setcon_raw((char *)label) < 0) { SYSERROR("failed to set new SELinux context %s", label); return -1; } } INFO("changed SELinux%s context to %s", on_exec ? " exec" : "", label); return 0; } static struct lsm_drv selinux_drv = { .name = "SELinux", .enabled = is_selinux_enabled, .process_label_get = selinux_process_label_get, .process_label_set = selinux_process_label_set, }; struct lsm_drv *lsm_selinux_drv_init(void) { if (!is_selinux_enabled()) return NULL; return &selinux_drv; } lxc-2.0.8/src/lxc/lsm/lsm.h0000644061062106075000000000346013105116772012362 00000000000000/* * lxc: linux Container library * * Copyright © 2013 Oracle. * * Authors: * Dwight Engen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __lxc_lsm_h #define __lxc_lsm_h struct lxc_conf; #include struct lsm_drv { const char *name; int (*enabled)(void); char *(*process_label_get)(pid_t pid); int (*process_label_set)(const char *label, struct lxc_conf *conf, int use_default, int on_exec); }; #if HAVE_APPARMOR || HAVE_SELINUX void lsm_init(void); int lsm_enabled(void); const char *lsm_name(void); char *lsm_process_label_get(pid_t pid); int lsm_process_label_set(const char *label, struct lxc_conf *conf, int use_default, int on_exec); #else static inline void lsm_init(void) { } static inline int lsm_enabled(void) { return 0; } static inline const char *lsm_name(void) { return "none"; } static inline char *lsm_process_label_get(pid_t pid) { return NULL; } static inline int lsm_process_label_set(const char *label, struct lxc_conf *conf, int use_default, int on_exec) { return 0; } #endif #endif lxc-2.0.8/src/lxc/lsm/apparmor.c0000644061062106075000000001345613105116772013411 00000000000000/* apparmor * * Copyright © 2012 Serge Hallyn . * Copyright © 2012 Canonical Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include "log.h" #include "lsm/lsm.h" #include "conf.h" #include "utils.h" lxc_log_define(lxc_apparmor, lxc); /* set by lsm_apparmor_drv_init if true */ static int aa_enabled = 0; static int mount_features_enabled = 0; #define AA_DEF_PROFILE "lxc-container-default" #define AA_DEF_PROFILE_CGNS "lxc-container-default-cgns" #define AA_MOUNT_RESTR "/sys/kernel/security/apparmor/features/mount/mask" #define AA_ENABLED_FILE "/sys/module/apparmor/parameters/enabled" #define AA_UNCHANGED "unchanged" static bool check_mount_feature_enabled(void) { return mount_features_enabled == 1; } static void load_mount_features_enabled(void) { struct stat statbuf; int ret; ret = stat(AA_MOUNT_RESTR, &statbuf); if (ret == 0) mount_features_enabled = 1; } /* aa_getcon is not working right now. Use our hand-rolled version below */ static int apparmor_enabled(void) { FILE *fin; char e; int ret; fin = fopen(AA_ENABLED_FILE, "r"); if (!fin) return 0; ret = fscanf(fin, "%c", &e); fclose(fin); if (ret == 1 && e == 'Y') { load_mount_features_enabled(); return 1; } return 0; } static char *apparmor_process_label_get(pid_t pid) { char path[100], *space; int ret; char *buf = NULL, *newbuf; int sz = 0; FILE *f; ret = snprintf(path, 100, "/proc/%d/attr/current", pid); if (ret < 0 || ret >= 100) { ERROR("path name too long"); return NULL; } again: f = fopen(path, "r"); if (!f) { SYSERROR("opening %s", path); free(buf); return NULL; } sz += 1024; newbuf = realloc(buf, sz); if (!newbuf) { free(buf); ERROR("out of memory"); fclose(f); return NULL; } buf = newbuf; memset(buf, 0, sz); ret = fread(buf, 1, sz - 1, f); fclose(f); if (ret < 0) { ERROR("reading %s", path); free(buf); return NULL; } if (ret >= sz) goto again; space = strchr(buf, '\n'); if (space) *space = '\0'; space = strchr(buf, ' '); if (space) *space = '\0'; return buf; } /* * Probably makes sense to reorganize these to only read * the label once */ static bool apparmor_am_unconfined(void) { char *p = apparmor_process_label_get(getpid()); bool ret = false; if (!p || strcmp(p, "unconfined") == 0) ret = true; free(p); return ret; } /* aa stacking is not yet supported */ static bool aa_stacking_supported(void) { return false; } static bool aa_needs_transition(char *curlabel) { if (!curlabel) return false; if (strcmp(curlabel, "unconfined") == 0) return false; if (strcmp(curlabel, "/usr/bin/lxc-start") == 0) return false; return true; } /* * apparmor_process_label_set: Set AppArmor process profile * * @label : the profile to set * @conf : the container configuration to use @label is NULL * @default : use the default profile if label is NULL * @on_exec : this is ignored. Apparmor profile will be changed immediately * * Returns 0 on success, < 0 on failure * * Notes: This relies on /proc being available. */ static int apparmor_process_label_set(const char *inlabel, struct lxc_conf *conf, int use_default, int on_exec) { const char *label = inlabel ? inlabel : conf->lsm_aa_profile; char *curlabel; if (!aa_enabled) return 0; /* user may request that we just ignore apparmor */ if (label && strcmp(label, AA_UNCHANGED) == 0) { INFO("apparmor profile unchanged per user request"); return 0; } curlabel = apparmor_process_label_get(getpid()); if (!aa_stacking_supported() && aa_needs_transition(curlabel)) { // we're already confined, and stacking isn't supported if (!label || strcmp(curlabel, label) == 0) { // no change requested free(curlabel); return 0; } ERROR("already apparmor confined, but new label requested."); free(curlabel); return -1; } free(curlabel); if (!label) { if (use_default) { if (cgns_supported()) label = AA_DEF_PROFILE_CGNS; else label = AA_DEF_PROFILE; } else label = "unconfined"; } if (!check_mount_feature_enabled() && strcmp(label, "unconfined") != 0) { WARN("Incomplete AppArmor support in your kernel"); if (!conf->lsm_aa_allow_incomplete) { ERROR("If you really want to start this container, set"); ERROR("lxc.aa_allow_incomplete = 1"); ERROR("in your container configuration file"); return -1; } } if (strcmp(label, "unconfined") == 0 && apparmor_am_unconfined()) { INFO("apparmor profile unchanged"); return 0; } if (aa_change_profile(label) < 0) { SYSERROR("failed to change apparmor profile to %s", label); return -1; } INFO("changed apparmor profile to %s", label); return 0; } static struct lsm_drv apparmor_drv = { .name = "AppArmor", .enabled = apparmor_enabled, .process_label_get = apparmor_process_label_get, .process_label_set = apparmor_process_label_set, }; struct lsm_drv *lsm_apparmor_drv_init(void) { if (!apparmor_enabled()) return NULL; aa_enabled = 1; return &apparmor_drv; } lxc-2.0.8/src/lxc/lsm/lsm.c0000644061062106075000000000427713105116772012364 00000000000000/* * lxc: linux Container library * * Authors: * Copyright © 2012 Serge Hallyn * Copyright © 2012 Canonical Ltd. * Dwight Engen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #if HAVE_APPARMOR || HAVE_SELINUX #include #include #include #include #include #include "conf.h" #include "log.h" #include "lsm/lsm.h" lxc_log_define(lxc_lsm, lxc); static struct lsm_drv *drv = NULL; extern struct lsm_drv *lsm_apparmor_drv_init(void); extern struct lsm_drv *lsm_selinux_drv_init(void); extern struct lsm_drv *lsm_nop_drv_init(void); __attribute__((constructor)) void lsm_init(void) { if (drv) { INFO("LSM security driver %s", drv->name); return; } #if HAVE_APPARMOR drv = lsm_apparmor_drv_init(); #endif #if HAVE_SELINUX if (!drv) drv = lsm_selinux_drv_init(); #endif if (!drv) drv = lsm_nop_drv_init(); INFO("Initialized LSM security driver %s", drv->name); } int lsm_enabled(void) { if (drv) return drv->enabled(); return 0; } const char *lsm_name(void) { if (drv) return drv->name; return "none"; } char *lsm_process_label_get(pid_t pid) { if (!drv) { ERROR("LSM driver not inited"); return NULL; } return drv->process_label_get(pid); } int lsm_process_label_set(const char *label, struct lxc_conf *conf, int use_default, int on_exec) { if (!drv) { ERROR("LSM driver not inited"); return -1; } return drv->process_label_set(label, conf, use_default, on_exec); } #endif lxc-2.0.8/src/lxc/lsm/nop.c0000644061062106075000000000255213105116772012357 00000000000000/* * lxc: linux Container library * * Copyright © 2013 Oracle. * * Authors: * Dwight Engen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "lsm/lsm.h" static char *nop_process_label_get(pid_t pid) { return NULL; } static int nop_process_label_set(const char *label, struct lxc_conf *conf, int use_default, int on_exec) { return 0; } static int nop_enabled(void) { return 0; } static struct lsm_drv nop_drv = { .name = "nop", .enabled = nop_enabled, .process_label_get = nop_process_label_get, .process_label_set = nop_process_label_set, }; struct lsm_drv *lsm_nop_drv_init(void) { return &nop_drv; } lxc-2.0.8/src/lxc/lxccontainer.c0000644061062106075000000031631513105116772013466 00000000000000/* liblxcapi * * Copyright © 2012 Serge Hallyn . * Copyright © 2012 Canonical Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "attach.h" #include "bdev.h" #include "lxcoverlay.h" #include "lxcbtrfs.h" #include "cgroup.h" #include "conf.h" #include "config.h" #include "commands.h" #include "confile.h" #include "console.h" #include "criu.h" #include "log.h" #include "lxc.h" #include "lxccontainer.h" #include "lxclock.h" #include "monitor.h" #include "namespace.h" #include "network.h" #include "sync.h" #include "state.h" #include "utils.h" #include "version.h" /* major()/minor() */ #ifdef MAJOR_IN_MKDEV # include #endif #if HAVE_IFADDRS_H #include #else #include <../include/ifaddrs.h> #endif #if IS_BIONIC #include <../include/lxcmntent.h> #else #include #endif #define MAX_BUFFER 4096 #define NOT_SUPPORTED_ERROR "the requested function %s is not currently supported with unprivileged containers" /* Define faccessat() if missing from the C library */ #ifndef HAVE_FACCESSAT static int faccessat(int __fd, const char *__file, int __type, int __flag) { #ifdef __NR_faccessat return syscall(__NR_faccessat, __fd, __file, __type, __flag); #else errno = ENOSYS; return -1; #endif } #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 */ int ret, len = strlen(lxcpath) + strlen(cname) + 9; char *fname = alloca(len); ret = snprintf(fname, len, "%s/%s/config", lxcpath, cname); if (ret < 0 || ret >= len) return false; return file_exists(fname); } /* * A few functions to help detect when a container creation failed. * If a container creation was killed partway through, then trying * to actually start that container could harm the host. We detect * this by creating a 'partial' file under the container directory, * and keeping an advisory lock. When container creation completes, * we remove that file. When we load or try to start a container, if * we find that file, without a flock, we remove the container. */ static int ongoing_create(struct lxc_container *c) { int len = strlen(c->config_path) + strlen(c->name) + 10; char *path = alloca(len); int fd, ret; struct flock lk; ret = snprintf(path, len, "%s/%s/partial", c->config_path, c->name); if (ret < 0 || ret >= len) { ERROR("Error writing partial pathname"); return -1; } if (!file_exists(path)) return 0; fd = open(path, O_RDWR); if (fd < 0) { // give benefit of the doubt SYSERROR("Error opening partial file"); return 0; } lk.l_type = F_WRLCK; lk.l_whence = SEEK_SET; lk.l_start = 0; lk.l_len = 0; lk.l_pid = -1; if (fcntl(fd, F_GETLK, &lk) == 0 && lk.l_pid != -1) { // create is still ongoing close(fd); return 1; } // create completed but partial is still there. close(fd); return 2; } static int create_partial(struct lxc_container *c) { // $lxcpath + '/' + $name + '/partial' + \0 int len = strlen(c->config_path) + strlen(c->name) + 10; char *path = alloca(len); int fd, ret; struct flock lk; ret = snprintf(path, len, "%s/%s/partial", c->config_path, c->name); if (ret < 0 || ret >= len) { ERROR("Error writing partial pathname"); return -1; } if ((fd=open(path, O_RDWR | O_CREAT | O_EXCL, 0755)) < 0) { SYSERROR("Error creating partial file"); return -1; } lk.l_type = F_WRLCK; lk.l_whence = SEEK_SET; lk.l_start = 0; lk.l_len = 0; if (fcntl(fd, F_SETLKW, &lk) < 0) { SYSERROR("Error locking partial file %s", path); close(fd); return -1; } return fd; } static void remove_partial(struct lxc_container *c, int fd) { // $lxcpath + '/' + $name + '/partial' + \0 int len = strlen(c->config_path) + strlen(c->name) + 10; char *path = alloca(len); int ret; close(fd); ret = snprintf(path, len, "%s/%s/partial", c->config_path, c->name); if (ret < 0 || ret >= len) { ERROR("Error writing partial pathname"); return; } if (unlink(path) < 0) SYSERROR("Error unlink partial file %s", path); } /* LOCKING * 1. container_mem_lock(c) protects the struct lxc_container from multiple threads. * 2. container_disk_lock(c) protects the on-disk container data - in particular the * container configuration file. * The container_disk_lock also takes the container_mem_lock. * 3. thread_mutex protects process data (ex: fd table) from multiple threads. * NOTHING mutexes two independent programs with their own struct * lxc_container for the same c->name, between API calls. For instance, * c->config_read(); c->start(); Between those calls, data on disk * could change (which shouldn't bother the caller unless for instance * the rootfs get moved). c->config_read(); update; c->config_write(); * Two such updaters could race. The callers should therefore check their * results. Trying to prevent that would necessarily expose us to deadlocks * due to hung callers. So I prefer to keep the locks only within our own * functions, not across functions. * * If you're going to clone while holding a lxccontainer, increment * c->numthreads (under privlock) before forking. When deleting, * decrement numthreads under privlock, then if it hits 0 you can delete. * Do not ever use a lxccontainer whose numthreads you did not bump. */ static void lxc_container_free(struct lxc_container *c) { if (!c) return; free(c->configfile); c->configfile = NULL; free(c->error_string); c->error_string = NULL; if (c->slock) { lxc_putlock(c->slock); c->slock = NULL; } if (c->privlock) { lxc_putlock(c->privlock); c->privlock = NULL; } free(c->name); c->name = NULL; if (c->lxc_conf) { lxc_conf_free(c->lxc_conf); c->lxc_conf = NULL; } free(c->config_path); c->config_path = NULL; free(c); } /* * Consider the following case: freer | racing get()er ================================================================== lxc_container_put() | lxc_container_get() \ lxclock(c->privlock) | c->numthreads < 1? (no) \ c->numthreads = 0 | \ lxclock(c->privlock) -> waits \ lxcunlock() | \ \ lxc_container_free() | \ lxclock() returns | \ c->numthreads < 1 -> return 0 \ \ (free stuff) | \ \ sem_destroy(privlock) | * When the get()er checks numthreads the first time, one of the following * is true: * 1. freer has set numthreads = 0. get() returns 0 * 2. freer is between lxclock and setting numthreads to 0. get()er will * sem_wait on privlock, get lxclock after freer() drops it, then see * numthreads is 0 and exit without touching lxclock again.. * 3. freer has not yet locked privlock. If get()er runs first, then put()er * will see --numthreads = 1 and not call lxc_container_free(). */ int lxc_container_get(struct lxc_container *c) { if (!c) return 0; // if someone else has already started freeing the container, don't // try to take the lock, which may be invalid if (c->numthreads < 1) return 0; if (container_mem_lock(c)) return 0; if (c->numthreads < 1) { // bail without trying to unlock, bc the privlock is now probably // in freed memory return 0; } c->numthreads++; container_mem_unlock(c); return 1; } int lxc_container_put(struct lxc_container *c) { if (!c) return -1; if (container_mem_lock(c)) return -1; if (--c->numthreads < 1) { container_mem_unlock(c); lxc_container_free(c); return 1; } container_mem_unlock(c); return 0; } static bool do_lxcapi_is_defined(struct lxc_container *c) { struct stat statbuf; bool ret = false; int statret; if (!c) return false; if (container_mem_lock(c)) return false; if (!c->configfile) goto out; statret = stat(c->configfile, &statbuf); if (statret != 0) goto out; ret = true; out: container_mem_unlock(c); return ret; } #define WRAP_API(rettype, fnname) \ static rettype fnname(struct lxc_container *c) \ { \ rettype ret; \ bool reset_config = false; \ \ if (!current_config && c && c->lxc_conf) { \ current_config = c->lxc_conf; \ reset_config = true; \ } \ \ ret = do_##fnname(c); \ if (reset_config) \ current_config = NULL; \ \ return ret; \ } #define WRAP_API_1(rettype, fnname, t1) \ static rettype fnname(struct lxc_container *c, t1 a1) \ { \ rettype ret; \ bool reset_config = false; \ \ if (!current_config && c && c->lxc_conf) { \ current_config = c->lxc_conf; \ reset_config = true; \ } \ \ ret = do_##fnname(c, a1); \ if (reset_config) \ current_config = NULL; \ \ return ret; \ } #define WRAP_API_2(rettype, fnname, t1, t2) \ static rettype fnname(struct lxc_container *c, t1 a1, t2 a2) \ { \ rettype ret; \ bool reset_config = false; \ \ if (!current_config && c && c->lxc_conf) { \ current_config = c->lxc_conf; \ reset_config = true; \ } \ \ ret = do_##fnname(c, a1, a2); \ if (reset_config) \ current_config = NULL; \ \ 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; \ bool reset_config = false; \ \ if (!current_config && c && c->lxc_conf) { \ current_config = c->lxc_conf; \ reset_config = true; \ } \ \ ret = do_##fnname(c, a1, a2, a3); \ if (reset_config) \ current_config = NULL; \ \ return ret; \ } WRAP_API(bool, lxcapi_is_defined) static const char *do_lxcapi_state(struct lxc_container *c) { lxc_state_t s; if (!c) return NULL; s = lxc_getstate(c->name, c->config_path); return lxc_state2str(s); } WRAP_API(const char *, lxcapi_state) static bool is_stopped(struct lxc_container *c) { lxc_state_t s; s = lxc_getstate(c->name, c->config_path); return (s == STOPPED); } static bool do_lxcapi_is_running(struct lxc_container *c) { const char *s; if (!c) return false; s = do_lxcapi_state(c); if (!s || strcmp(s, "STOPPED") == 0) return false; return true; } WRAP_API(bool, lxcapi_is_running) static bool do_lxcapi_freeze(struct lxc_container *c) { int ret; if (!c) return false; ret = lxc_freeze(c->name, c->config_path); if (ret) return false; return true; } WRAP_API(bool, lxcapi_freeze) static bool do_lxcapi_unfreeze(struct lxc_container *c) { int ret; if (!c) return false; ret = lxc_unfreeze(c->name, c->config_path); if (ret) return false; return true; } WRAP_API(bool, lxcapi_unfreeze) static int do_lxcapi_console_getfd(struct lxc_container *c, int *ttynum, int *masterfd) { int ttyfd; if (!c) return -1; ttyfd = lxc_console_getfd(c, ttynum, masterfd); 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) { int ret; if (!c) return -1; current_config = c->lxc_conf; ret = lxc_console(c, ttynum, stdinfd, stdoutfd, stderrfd, escape); current_config = NULL; return ret; } static pid_t do_lxcapi_init_pid(struct lxc_container *c) { if (!c) return -1; 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) c->lxc_conf = lxc_conf_init(); if (!c->lxc_conf) return false; if (lxc_config_read(fname, c->lxc_conf, false) != 0) return false; return true; } static bool do_lxcapi_load_config(struct lxc_container *c, const char *alt_file) { bool ret = false, need_disklock = false; int lret; const char *fname; if (!c) return false; fname = c->configfile; if (alt_file) fname = alt_file; if (!fname) return false; /* * If we're reading something other than the container's config, * we only need to lock the in-memory container. If loading the * container's config file, take the disk lock. */ if (strcmp(fname, c->configfile) == 0) need_disklock = true; if (need_disklock) lret = container_disk_lock(c); else lret = container_mem_lock(c); if (lret) return false; ret = load_config_locked(c, fname); if (need_disklock) container_disk_unlock(c); else container_mem_unlock(c); return ret; } 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; if (container_mem_lock(c)) { ERROR("Error getting mem lock"); return false; } c->daemonize = state; container_mem_unlock(c); return true; } 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; if (container_mem_lock(c)) { ERROR("Error getting mem lock"); return false; } c->lxc_conf->close_all_fds = state; container_mem_unlock(c); return true; } 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; if (!c) return false; ret = lxc_wait(c->name, state, timeout, c->config_path); return ret == 0; } WRAP_API_2(bool, lxcapi_wait, const char *, int) 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; /* * our child is going to fork again, then exit. reap the * child */ ret = waitpid(pid, &status, 0); if (ret == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) DEBUG("failed waiting for first dual-fork child"); return do_lxcapi_wait(c, "RUNNING", timeout); } WRAP_API_1(bool, wait_on_daemonized_start, int) static bool am_single_threaded(void) { struct dirent *direntp; DIR *dir; int count=0; dir = opendir("/proc/self/task"); if (!dir) { INFO("failed to open /proc/self/task"); return false; } while ((direntp = readdir(dir))) { if (!direntp) break; if (!strcmp(direntp->d_name, ".")) continue; if (!strcmp(direntp->d_name, "..")) continue; if (++count > 1) break; } closedir(dir); return count == 1; } static void push_arg(char ***argp, char *arg, int *nargs) { char **argv; char *copy; do { copy = strdup(arg); } while (!copy); do { argv = realloc(*argp, (*nargs + 2) * sizeof(char *)); } while (!argv); *argp = argv; argv[*nargs] = copy; (*nargs)++; argv[*nargs] = NULL; } static char **split_init_cmd(const char *incmd) { size_t len; int nargs = 0; char *copy, *p, *saveptr = NULL; char **argv; if (!incmd) return NULL; len = strlen(incmd) + 1; copy = alloca(len); strncpy(copy, incmd, len); copy[len-1] = '\0'; do { argv = malloc(sizeof(char *)); } while (!argv); argv[0] = NULL; for (p = strtok_r(copy, " ", &saveptr); p != NULL; p = strtok_r(NULL, " ", &saveptr)) push_arg(&argv, p, &nargs); if (nargs == 0) { free(argv); return NULL; } return argv; } static void free_init_cmd(char **argv) { int i = 0; if (!argv) return; while (argv[i]) free(argv[i++]); free(argv); } static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const argv[]) { int ret; struct lxc_conf *conf; bool daemonize = false; FILE *pid_fp = NULL; char *default_args[] = { "/sbin/init", NULL, }; char **init_cmd = NULL; /* container exists */ if (!c) return false; /* If anything fails before we set error_num, we want an error in there */ c->error_num = 1; /* container has been setup */ if (!c->lxc_conf) return false; if ((ret = ongoing_create(c)) < 0) { ERROR("Error checking for incomplete creation"); return false; } if (ret == 2) { ERROR("Error: %s creation was not completed", c->name); do_lxcapi_destroy(c); return false; } else if (ret == 1) { ERROR("Error: creation of %s is ongoing", c->name); return false; } /* is this app meant to be run through lxcinit, as in lxc-execute? */ if (useinit && !argv) return false; if (container_mem_lock(c)) return false; conf = c->lxc_conf; daemonize = c->daemonize; container_mem_unlock(c); if (useinit) { ret = lxc_execute(c->name, argv, 1, conf, c->config_path, daemonize); return ret == 0 ? true : false; } /* if no argv was passed in, use lxc.init_cmd if provided in * configuration */ if (!argv) argv = init_cmd = split_init_cmd(conf->init_cmd); /* ... and otherwise use default_args */ if (!argv) argv = default_args; /* * say, I'm not sure - what locks do we want here? Any? * Is liblxc's locking enough here to protect the on disk * container? We don't want to exclude things like lxc_info * while container is running... */ if (daemonize) { char title[2048]; lxc_monitord_spawn(c->config_path); pid_t pid = fork(); if (pid < 0) return false; if (pid != 0) { /* Set to NULL because we don't want father unlink * the PID file, child will do the free and unlink. */ c->pidfile = NULL; return wait_on_daemonized_start(c, pid); } /* We don't really care if this doesn't print all the * characters; all that it means is that the proctitle will be * ugly. Similarly, we also don't care if setproctitle() * fails. */ snprintf(title, sizeof(title), "[lxc monitor] %s %s", c->config_path, c->name); INFO("Attempting to set proc title to %s", title); setproctitle(title); /* second fork to be reparented by init */ pid = fork(); if (pid < 0) { SYSERROR("Error doing dual-fork"); exit(1); } if (pid != 0) exit(0); /* like daemon(), chdir to / and redirect 0,1,2 to /dev/null */ if (chdir("/")) { SYSERROR("Error chdir()ing to /."); exit(1); } lxc_check_inherited(conf, true, -1); if (null_stdfds() < 0) { ERROR("failed to close fds"); exit(1); } setsid(); } else { if (!am_single_threaded()) { ERROR("Cannot start non-daemonized container when threaded"); return false; } } /* We need to write PID file after daeminize, so we always * write the right PID. */ if (c->pidfile) { pid_fp = fopen(c->pidfile, "w"); if (pid_fp == NULL) { SYSERROR("Failed to create pidfile '%s' for '%s'", c->pidfile, c->name); if (daemonize) exit(1); return false; } if (fprintf(pid_fp, "%d\n", getpid()) < 0) { SYSERROR("Failed to write '%s'", c->pidfile); fclose(pid_fp); pid_fp = NULL; if (daemonize) exit(1); return false; } fclose(pid_fp); pid_fp = NULL; } conf->reboot = 0; /* Unshare the mount namespace if requested */ if (conf->monitor_unshare) { if (unshare(CLONE_NEWNS)) { SYSERROR("failed to unshare mount namespace"); return false; } if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) { SYSERROR("Failed to make / rslave at startup"); return false; } } reboot: if (lxc_check_inherited(conf, daemonize, -1)) { ERROR("Inherited fds found"); ret = 1; goto out; } ret = lxc_start(c->name, argv, conf, c->config_path, daemonize); c->error_num = ret; if (conf->reboot == 1) { INFO("container requested reboot"); conf->reboot = 2; goto reboot; } out: if (c->pidfile) { unlink(c->pidfile); free(c->pidfile); c->pidfile = NULL; } free_init_cmd(init_cmd); if (daemonize) exit (ret == 0 ? true : false); else return (ret == 0 ? true : false); } static bool lxcapi_start(struct lxc_container *c, int useinit, char * const argv[]) { bool ret; current_config = c ? c->lxc_conf : NULL; ret = do_lxcapi_start(c, useinit, argv); current_config = NULL; return ret; } /* * note there MUST be an ending NULL */ static bool lxcapi_startl(struct lxc_container *c, int useinit, ...) { va_list ap; char **inargs = NULL; bool bret = false; /* container exists */ if (!c) return false; current_config = c->lxc_conf; va_start(ap, useinit); inargs = lxc_va_arg_list_to_argv(ap, 0, 1); va_end(ap); if (!inargs) { ERROR("Memory allocation error."); goto out; } /* pass NULL if no arguments were supplied */ bret = do_lxcapi_start(c, useinit, *inargs ? inargs : NULL); out: if (inargs) { char **arg; for (arg = inargs; *arg; arg++) free(*arg); free(inargs); } current_config = NULL; return bret; } static bool do_lxcapi_stop(struct lxc_container *c) { int ret; if (!c) return false; ret = lxc_cmd_stop(c->name, c->config_path); 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; char *p = alloca(strlen(path)+1); mode_t mask = umask(0002); ret = mkdir(path, 0770); lasterr = errno; umask(mask); errno = lasterr; if (ret) { if (errno == EEXIST) ret = 0; else { SYSERROR("failed to create container path %s", path); return -1; } } strcpy(p, path); if (!lxc_list_empty(&conf->id_map) && chown_mapped_root(p, conf) != 0) { ERROR("Failed to chown container dir"); ret = -1; } return ret; } /* * create the standard expected container dir */ static bool create_container_dir(struct lxc_container *c) { char *s; int len, ret; len = strlen(c->config_path) + strlen(c->name) + 2; s = malloc(len); if (!s) return false; ret = snprintf(s, len, "%s/%s", c->config_path, c->name); if (ret < 0 || ret >= len) { free(s); return false; } ret = do_create_container_dir(s, c->lxc_conf); free(s); return ret == 0; } /* * do_bdev_create: thin wrapper around bdev_create(). Like bdev_create(), * it returns a mounted bdev on success, NULL on error. */ static struct bdev *do_bdev_create(struct lxc_container *c, const char *type, struct bdev_specs *specs) { char *dest; size_t len; struct bdev *bdev; int ret; /* rootfs.path or lxcpath/lxcname/rootfs */ if (c->lxc_conf->rootfs.path && access(c->lxc_conf->rootfs.path, F_OK) == 0) { const char *rpath = c->lxc_conf->rootfs.path; len = strlen(rpath) + 1; dest = alloca(len); ret = snprintf(dest, len, "%s", rpath); } else { 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); } if (ret < 0 || ret >= len) return NULL; bdev = bdev_create(dest, type, c->name, specs); if (!bdev) { ERROR("Failed to create backing store type %s", type); return NULL; } do_lxcapi_set_config_item(c, "lxc.rootfs", bdev->src); do_lxcapi_set_config_item(c, "lxc.rootfs.backend", bdev->type); /* if we are not root, chown the rootfs dir to root in the * target uidmap */ if (geteuid() != 0 || (c->lxc_conf && !lxc_list_empty(&c->lxc_conf->id_map))) { if (chown_mapped_root(bdev->dest, c->lxc_conf) < 0) { ERROR("Error chowning %s to container root", bdev->dest); suggest_default_idmap(); bdev_put(bdev); return NULL; } } return bdev; } static char *lxcbasename(char *path) { char *p = path + strlen(path) - 1; while (*p != '/' && p > path) p--; return p; } static bool create_run_template(struct lxc_container *c, char *tpath, bool need_null_stdfds, char *const argv[]) { pid_t pid; if (!tpath) return true; pid = fork(); if (pid < 0) { SYSERROR("failed to fork task for container creation template"); return false; } if (pid == 0) { // child char *patharg, *namearg, *rootfsarg; struct bdev *bdev = NULL; int i; int ret, len, nargs = 0; char **newargv; struct lxc_conf *conf = c->lxc_conf; if (need_null_stdfds && null_stdfds() < 0) { exit(1); } bdev = bdev_init(c->lxc_conf, c->lxc_conf->rootfs.path, c->lxc_conf->rootfs.mount, NULL); if (!bdev) { ERROR("Error opening rootfs"); exit(1); } if (geteuid() == 0) { if (unshare(CLONE_NEWNS) < 0) { ERROR("error unsharing mounts"); exit(1); } if (detect_shared_rootfs()) { if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) { SYSERROR("Failed to make / rslave to run template"); ERROR("Continuing..."); } } } if (strcmp(bdev->type, "dir") && strcmp(bdev->type, "btrfs")) { if (geteuid() != 0) { ERROR("non-root users can only create btrfs and directory-backed containers"); exit(1); } if (bdev->ops->mount(bdev) < 0) { ERROR("Error mounting rootfs"); exit(1); } } else { // TODO come up with a better way here! free(bdev->dest); bdev->dest = strdup(bdev->src); } /* * create our new array, pre-pend the template name and * base args */ if (argv) for (nargs = 0; argv[nargs]; nargs++) ; nargs += 4; // template, path, rootfs and name args newargv = malloc(nargs * sizeof(*newargv)); if (!newargv) exit(1); newargv[0] = lxcbasename(tpath); len = strlen(c->config_path) + strlen(c->name) + strlen("--path=") + 2; patharg = malloc(len); if (!patharg) exit(1); ret = snprintf(patharg, len, "--path=%s/%s", c->config_path, c->name); if (ret < 0 || ret >= len) exit(1); newargv[1] = patharg; len = strlen("--name=") + strlen(c->name) + 1; namearg = malloc(len); if (!namearg) exit(1); ret = snprintf(namearg, len, "--name=%s", c->name); if (ret < 0 || ret >= len) exit(1); newargv[2] = namearg; len = strlen("--rootfs=") + 1 + strlen(bdev->dest); rootfsarg = malloc(len); if (!rootfsarg) exit(1); ret = snprintf(rootfsarg, len, "--rootfs=%s", bdev->dest); if (ret < 0 || ret >= len) exit(1); newargv[3] = rootfsarg; /* add passed-in args */ if (argv) for (i = 4; i < nargs; i++) newargv[i] = argv[i-4]; /* add trailing NULL */ nargs++; newargv = realloc(newargv, nargs * sizeof(*newargv)); if (!newargv) exit(1); newargv[nargs - 1] = NULL; /* * If we're running the template in a mapped userns, then * we prepend the template command with: * lxc-usernsexec <-m map1> ... <-m mapn> -- * and we append "--mapped-uid x", where x is the mapped uid * for our geteuid() */ if (!lxc_list_empty(&conf->id_map)) { int n2args = 1; char txtuid[20]; char txtgid[20]; char **n2 = malloc(n2args * sizeof(*n2)); struct lxc_list *it; struct id_map *map; if (!n2) { SYSERROR("out of memory"); exit(1); } newargv[0] = tpath; tpath = "lxc-usernsexec"; n2[0] = "lxc-usernsexec"; lxc_list_for_each(it, &conf->id_map) { map = it->elem; n2args += 2; n2 = realloc(n2, n2args * sizeof(char *)); if (!n2) exit(1); n2[n2args-2] = "-m"; n2[n2args-1] = malloc(200); if (!n2[n2args-1]) exit(1); ret = snprintf(n2[n2args-1], 200, "%c:%lu:%lu:%lu", map->idtype == ID_TYPE_UID ? 'u' : 'g', map->nsid, map->hostid, map->range); if (ret < 0 || ret >= 200) exit(1); } int hostid_mapped = mapped_hostid(geteuid(), conf, ID_TYPE_UID); int extraargs = hostid_mapped >= 0 ? 1 : 3; n2 = realloc(n2, (nargs + n2args + extraargs) * sizeof(char *)); if (!n2) exit(1); if (hostid_mapped < 0) { hostid_mapped = find_unmapped_nsuid(conf, ID_TYPE_UID); n2[n2args++] = "-m"; if (hostid_mapped < 0) { ERROR("Could not find free uid to map"); exit(1); } n2[n2args++] = malloc(200); if (!n2[n2args-1]) { SYSERROR("out of memory"); exit(1); } ret = snprintf(n2[n2args-1], 200, "u:%d:%d:1", hostid_mapped, geteuid()); if (ret < 0 || ret >= 200) { ERROR("string too long"); exit(1); } } int hostgid_mapped = mapped_hostid(getegid(), conf, ID_TYPE_GID); extraargs = hostgid_mapped >= 0 ? 1 : 3; n2 = realloc(n2, (nargs + n2args + extraargs) * sizeof(char *)); if (!n2) exit(1); if (hostgid_mapped < 0) { hostgid_mapped = find_unmapped_nsuid(conf, ID_TYPE_GID); n2[n2args++] = "-m"; if (hostgid_mapped < 0) { ERROR("Could not find free uid to map"); exit(1); } n2[n2args++] = malloc(200); if (!n2[n2args-1]) { SYSERROR("out of memory"); exit(1); } ret = snprintf(n2[n2args-1], 200, "g:%d:%d:1", hostgid_mapped, getegid()); if (ret < 0 || ret >= 200) { ERROR("string too long"); exit(1); } } n2[n2args++] = "--"; for (i = 0; i < nargs; i++) n2[i + n2args] = newargv[i]; n2args += nargs; // Finally add "--mapped-uid $uid" to tell template what to chown // cached images to n2args += 4; n2 = realloc(n2, n2args * sizeof(char *)); if (!n2) { SYSERROR("out of memory"); exit(1); } // note n2[n2args-1] is NULL n2[n2args-5] = "--mapped-uid"; snprintf(txtuid, 20, "%d", hostid_mapped); n2[n2args-4] = txtuid; n2[n2args-3] = "--mapped-gid"; snprintf(txtgid, 20, "%d", hostgid_mapped); n2[n2args-2] = txtgid; n2[n2args-1] = NULL; free(newargv); newargv = n2; } /* execute */ execvp(tpath, newargv); SYSERROR("failed to execute template %s", tpath); exit(1); } if (wait_for_pid(pid) != 0) { ERROR("container creation template for %s failed", c->name); return false; } return true; } static bool prepend_lxc_header(char *path, const char *t, char *const argv[]) { long flen; char *contents; FILE *f; int ret = -1; #if HAVE_LIBGNUTLS int i; unsigned char md_value[SHA_DIGEST_LENGTH]; char *tpath; #endif f = fopen(path, "r"); if (f == NULL) return false; if (fseek(f, 0, SEEK_END) < 0) goto out_error; if ((flen = ftell(f)) < 0) goto out_error; if (fseek(f, 0, SEEK_SET) < 0) goto out_error; if ((contents = malloc(flen + 1)) == NULL) goto out_error; if (fread(contents, 1, flen, f) != flen) goto out_free_contents; contents[flen] = '\0'; ret = fclose(f); f = NULL; if (ret < 0) goto out_free_contents; #if HAVE_LIBGNUTLS tpath = get_template_path(t); if (!tpath) { ERROR("bad template: %s", t); goto out_free_contents; } ret = sha1sum_file(tpath, md_value); if (ret < 0) { ERROR("Error getting sha1sum of %s", tpath); free(tpath); goto out_free_contents; } free(tpath); #endif f = fopen(path, "w"); if (f == NULL) { SYSERROR("reopening config for writing"); free(contents); return false; } fprintf(f, "# Template used to create this container: %s\n", t); if (argv) { fprintf(f, "# Parameters passed to the template:"); while (*argv) { fprintf(f, " %s", *argv); argv++; } fprintf(f, "\n"); } #if HAVE_LIBGNUTLS fprintf(f, "# Template script checksum (SHA-1): "); for (i=0; ilxc_conf) { lxc_conf_free(c->lxc_conf); c->lxc_conf = NULL; } } } #define do_lxcapi_clear_config(c) lxcapi_clear_config(c) /* * lxcapi_create: * create a container with the given parameters. * @c: container to be created. It has the lxcpath, name, and a starting * configuration already set * @t: the template to execute to instantiate the root filesystem and * adjust the configuration. * @bdevtype: backing store type to use. If NULL, dir will be used. * @specs: additional parameters for the backing store, i.e. LVM vg to * use. * * @argv: the arguments to pass to the template, terminated by NULL. If no * arguments, you can just pass NULL. */ static bool do_lxcapi_create(struct lxc_container *c, const char *t, const char *bdevtype, struct bdev_specs *specs, int flags, char *const argv[]) { bool ret = false; pid_t pid; char *tpath = NULL; int partial_fd; if (!c) return false; if (t) { tpath = get_template_path(t); if (!tpath) { ERROR("bad template: %s", t); goto out; } } /* * If a template is passed in, and the rootfs already is defined in * the container config and exists, then * caller is trying to create * an existing container. Return an error, but do NOT delete the * container. */ 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 (!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; } } if (!create_container_dir(c)) goto free_tpath; /* * if both template and rootfs.path are set, template is setup as rootfs.path. * container is already created if we have a config and rootfs.path is accessible */ if (!c->lxc_conf->rootfs.path && !tpath) { /* no template passed in and rootfs does not exist */ if (!c->save_config(c, NULL)) { ERROR("failed to save starting configuration for %s\n", c->name); goto out; } ret = true; goto out; } 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 (do_lxcapi_is_defined(c) && c->lxc_conf->rootfs.path && !tpath) { /* Rootfs already existed, user just wanted to save the * loaded configuration */ if (!c->save_config(c, NULL)) ERROR("failed to save starting configuration for %s\n", c->name); ret = true; goto out; } /* Mark that this container is being created */ if ((partial_fd = create_partial(c)) < 0) goto out; /* no need to get disk lock bc we have the partial locked */ /* * Create the backing store * Note we can't do this in the same task as we use to execute the * template because of the way zfs works. * After you 'zfs create', zfs mounts the fs only in the initial * namespace. */ pid = fork(); if (pid < 0) { SYSERROR("failed to fork task for container creation template"); goto out_unlock; } if (pid == 0) { // child struct bdev *bdev = NULL; if (!(bdev = do_bdev_create(c, bdevtype, specs))) { ERROR("Error creating backing store type %s for %s", bdevtype ? bdevtype : "(none)", c->name); exit(1); } /* save config file again to store the new rootfs location */ 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); bdev->ops->destroy(bdev); exit(1); } exit(0); } if (wait_for_pid(pid) != 0) goto out_unlock; /* reload config to get the rootfs */ lxc_conf_free(c->lxc_conf); c->lxc_conf = NULL; if (!load_config_locked(c, c->configfile)) goto out_unlock; if (!create_run_template(c, tpath, !!(flags & LXC_CREATE_QUIET), argv)) goto out_unlock; // now clear out the lxc_conf we have, reload from the created // container do_lxcapi_clear_config(c); if (t) { if (!prepend_lxc_header(c->configfile, tpath, argv)) { ERROR("Error prepending header to configuration file"); goto out_unlock; } } ret = load_config_locked(c, c->configfile); out_unlock: if (partial_fd >= 0) remove_partial(c, partial_fd); out: if (!ret) container_destroy(c); free_tpath: free(tpath); return ret; } 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; current_config = c ? c->lxc_conf : NULL; ret = do_lxcapi_create(c, t, bdevtype, specs, flags, argv); current_config = NULL; return ret; } static bool do_lxcapi_reboot(struct lxc_container *c) { pid_t pid; int rebootsignal = SIGINT; if (!c) return false; if (!do_lxcapi_is_running(c)) return false; pid = do_lxcapi_init_pid(c); if (pid <= 0) return false; if (c->lxc_conf && c->lxc_conf->rebootsignal) rebootsignal = c->lxc_conf->rebootsignal; if (kill(pid, rebootsignal) < 0) { WARN("Could not send signal %d to pid %d.", rebootsignal, pid); return false; } return true; } WRAP_API(bool, lxcapi_reboot) static bool do_lxcapi_shutdown(struct lxc_container *c, int timeout) { bool retv; pid_t pid; int haltsignal = SIGPWR; if (!c) return false; if (!do_lxcapi_is_running(c)) return true; pid = do_lxcapi_init_pid(c); if (pid <= 0) return true; /* Detect whether we should send SIGRTMIN + 3 (e.g. systemd). */ if (task_blocking_signal(pid, (SIGRTMIN + 3))) haltsignal = (SIGRTMIN + 3); if (c->lxc_conf && c->lxc_conf->haltsignal) haltsignal = c->lxc_conf->haltsignal; INFO("Using signal number '%d' as halt signal.", haltsignal); if (kill(pid, haltsignal) < 0) WARN("Could not send signal %d to pid %d.", haltsignal, pid); 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, ...) { bool bret = false; char **args = NULL; va_list ap; if (!c) return false; current_config = c->lxc_conf; /* * since we're going to wait for create to finish, I don't think we * need to get a copy of the arguments. */ va_start(ap, flags); args = lxc_va_arg_list_to_argv(ap, 0, 0); va_end(ap); if (!args) { ERROR("Memory allocation error."); goto out; } bret = do_lxcapi_create(c, t, bdevtype, specs, flags, args); out: free(args); current_config = NULL; return bret; } static void do_clear_unexp_config_line(struct lxc_conf *conf, const char *key) { if (strcmp(key, "lxc.cgroup") == 0) clear_unexp_config_line(conf, key, true); else if (strcmp(key, "lxc.network") == 0) clear_unexp_config_line(conf, key, true); else if (strcmp(key, "lxc.hook") == 0) clear_unexp_config_line(conf, key, true); else clear_unexp_config_line(conf, key, false); if (!do_append_unexp_config_line(conf, key, "")) WARN("Error clearing configuration for %s", key); } static bool do_lxcapi_clear_config_item(struct lxc_container *c, const char *key) { int ret; if (!c || !c->lxc_conf) return false; if (container_mem_lock(c)) return false; ret = lxc_clear_config_item(c->lxc_conf, key); if (!ret) do_clear_unexp_config_line(c->lxc_conf, key); container_mem_unlock(c); 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 = 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")) return false; } return switch_to_ns(pid, "net"); } // used by qsort and bsearch functions for comparing names static inline int string_cmp(char **first, char **second) { return strcmp(*first, *second); } // used by qsort and bsearch functions for comparing container names static inline int container_cmp(struct lxc_container **first, struct lxc_container **second) { return strcmp((*first)->name, (*second)->name); } static bool add_to_array(char ***names, char *cname, int pos) { char **newnames = realloc(*names, (pos+1) * sizeof(char *)); if (!newnames) { ERROR("Out of memory"); return false; } *names = newnames; newnames[pos] = strdup(cname); if (!newnames[pos]) return false; // sort the arrray as we will use binary search on it qsort(newnames, pos + 1, sizeof(char *), (int (*)(const void *,const void *))string_cmp); return true; } static bool add_to_clist(struct lxc_container ***list, struct lxc_container *c, int pos, bool sort) { struct lxc_container **newlist = realloc(*list, (pos+1) * sizeof(struct lxc_container *)); if (!newlist) { ERROR("Out of memory"); return false; } *list = newlist; newlist[pos] = c; // sort the arrray as we will use binary search on it if (sort) qsort(newlist, pos + 1, sizeof(struct lxc_container *), (int (*)(const void *,const void *))container_cmp); return true; } static char** get_from_array(char ***names, char *cname, int size) { return (char **)bsearch(&cname, *names, size, sizeof(char *), (int (*)(const void *, const void *))string_cmp); } static bool array_contains(char ***names, char *cname, int size) { if(get_from_array(names, cname, size) != NULL) return true; return false; } static bool remove_from_array(char ***names, char *cname, int size) { char **result = get_from_array(names, cname, size); if (result != NULL) { free(result); return true; } return false; } static char ** do_lxcapi_get_interfaces(struct lxc_container *c) { pid_t pid; int i, count = 0, pipefd[2]; char **interfaces = NULL; char interface[IFNAMSIZ]; if(pipe(pipefd) < 0) { SYSERROR("pipe failed"); return NULL; } pid = fork(); if (pid < 0) { SYSERROR("failed to fork task to get interfaces information"); close(pipefd[0]); close(pipefd[1]); return NULL; } if (pid == 0) { // child int ret = 1, nbytes; struct ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL; /* close the read-end of the pipe */ close(pipefd[0]); if (!enter_net_ns(c)) { SYSERROR("failed to enter namespace"); goto out; } /* Grab the list of interfaces */ if (getifaddrs(&interfaceArray)) { SYSERROR("failed to get interfaces list"); goto out; } /* Iterate through the interfaces */ for (tempIfAddr = interfaceArray; tempIfAddr != NULL; tempIfAddr = tempIfAddr->ifa_next) { nbytes = write(pipefd[1], tempIfAddr->ifa_name, IFNAMSIZ); if (nbytes < 0) { ERROR("write failed"); goto out; } count++; } ret = 0; out: if (interfaceArray) freeifaddrs(interfaceArray); /* close the write-end of the pipe, thus sending EOF to the reader */ close(pipefd[1]); exit(ret); } /* close the write-end of the pipe */ close(pipefd[1]); while (read(pipefd[0], &interface, IFNAMSIZ) == IFNAMSIZ) { if (array_contains(&interfaces, interface, count)) continue; if(!add_to_array(&interfaces, interface, count)) ERROR("PARENT: add_to_array failed"); count++; } if (wait_for_pid(pid) != 0) { for(i=0;iifa_next) { if (tempIfAddr->ifa_addr == NULL) continue; if(tempIfAddr->ifa_addr->sa_family == AF_INET) { if (family && strcmp(family, "inet")) continue; tempAddrPtr = &((struct sockaddr_in *)tempIfAddr->ifa_addr)->sin_addr; } else { if (family && strcmp(family, "inet6")) continue; if (((struct sockaddr_in6 *)tempIfAddr->ifa_addr)->sin6_scope_id != scope) continue; tempAddrPtr = &((struct sockaddr_in6 *)tempIfAddr->ifa_addr)->sin6_addr; } if (interface && strcmp(interface, tempIfAddr->ifa_name)) continue; else if (!interface && strcmp("lo", tempIfAddr->ifa_name) == 0) continue; address = (char *)inet_ntop(tempIfAddr->ifa_addr->sa_family, tempAddrPtr, addressOutputBuffer, sizeof(addressOutputBuffer)); if (!address) continue; nbytes = write(pipefd[1], address, INET6_ADDRSTRLEN); if (nbytes < 0) { ERROR("write failed"); goto out; } count++; } ret = 0; out: if(interfaceArray) freeifaddrs(interfaceArray); /* close the write-end of the pipe, thus sending EOF to the reader */ close(pipefd[1]); exit(ret); } /* close the write-end of the pipe */ close(pipefd[1]); while (read(pipefd[0], &address, INET6_ADDRSTRLEN) == INET6_ADDRSTRLEN) { if(!add_to_array(&addresses, address, count)) ERROR("PARENT: add_to_array failed"); count++; } if (wait_for_pid(pid) != 0) { for(i=0;ilxc_conf) return -1; if (container_mem_lock(c)) return -1; ret = lxc_get_config_item(c->lxc_conf, key, retv, inlen); container_mem_unlock(c); return ret; } 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; if (!c || !c->lxc_conf) return NULL; if (container_mem_lock(c)) return NULL; ret = lxc_cmd_get_config_item(c->name, key, do_lxcapi_get_config_path(c)); container_mem_unlock(c); return ret; } 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); /* * Support 'lxc.network.', i.e. 'lxc.network.0' * This is an intelligent result to show which keys are valid given * the type of nic it is */ if (!c || !c->lxc_conf) return -1; if (container_mem_lock(c)) return -1; int ret = -1; if (strncmp(key, "lxc.network.", 12) == 0) ret = lxc_list_nicconfigs(c->lxc_conf, key, retv, inlen); container_mem_unlock(c); return ret; } 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; int lret; if (!alt_file) alt_file = c->configfile; if (!alt_file) return false; // should we write to stdout if no file is specified? // If we haven't yet loaded a config, load the stock config if (!c->lxc_conf) { 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; } } if (!create_container_dir(c)) return false; /* * If we're writing to the container's config file, take the * disk lock. Otherwise just take the memlock to protect the * struct lxc_container while we're traversing it. */ if (strcmp(c->configfile, alt_file) == 0) need_disklock = true; if (need_disklock) lret = container_disk_lock(c); else lret = container_mem_lock(c); if (lret) return false; fout = fopen(alt_file, "w"); if (!fout) goto out; write_config(fout, c->lxc_conf); fclose(fout); ret = true; out: if (need_disklock) container_disk_unlock(c); else container_mem_unlock(c); return ret; } WRAP_API_1(bool, lxcapi_save_config, const char *) static bool mod_rdep(struct lxc_container *c0, struct lxc_container *c, bool inc) { FILE *f1; struct stat fbuf; void *buf = NULL; char *del = NULL; char path[MAXPATHLEN]; char newpath[MAXPATHLEN]; int fd, ret, n = 0, v = 0; bool bret = false; size_t len = 0, bytes = 0; if (container_disk_lock(c0)) return false; ret = snprintf(path, MAXPATHLEN, "%s/%s/lxc_snapshots", c0->config_path, c0->name); if (ret < 0 || ret > MAXPATHLEN) goto out; ret = snprintf(newpath, MAXPATHLEN, "%s\n%s\n", c->config_path, c->name); if (ret < 0 || ret > MAXPATHLEN) goto out; /* If we find an lxc-snapshot file using the old format only listing the * number of snapshots we will keep using it. */ f1 = fopen(path, "r"); if (f1) { n = fscanf(f1, "%d", &v); fclose(f1); if (n == 1 && v == 0) { remove(path); n = 0; } } if (n == 1) { v += inc ? 1 : -1; f1 = fopen(path, "w"); if (!f1) goto out; if (fprintf(f1, "%d\n", v) < 0) { ERROR("Error writing new snapshots value"); fclose(f1); goto out; } ret = fclose(f1); if (ret != 0) { SYSERROR("Error writing to or closing snapshots file"); goto out; } } else { /* Here we know that we have or can use an lxc-snapshot file * using the new format. */ if (inc) { f1 = fopen(path, "a"); if (!f1) goto out; if (fprintf(f1, "%s", newpath) < 0) { ERROR("Error writing new snapshots entry"); ret = fclose(f1); if (ret != 0) SYSERROR("Error writing to or closing snapshots file"); goto out; } ret = fclose(f1); if (ret != 0) { SYSERROR("Error writing to or closing snapshots file"); goto out; } } else if (!inc) { if ((fd = open(path, O_RDWR | O_CLOEXEC)) < 0) goto out; if (fstat(fd, &fbuf) < 0) { close(fd); goto out; } if (fbuf.st_size != 0) { buf = lxc_strmmap(NULL, fbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (buf == MAP_FAILED) { SYSERROR("Failed to create mapping %s", path); close(fd); goto out; } len = strlen(newpath); while ((del = strstr((char *)buf, newpath))) { memmove(del, del + len, strlen(del) - len + 1); bytes += len; } lxc_strmunmap(buf, fbuf.st_size); if (ftruncate(fd, fbuf.st_size - bytes) < 0) { SYSERROR("Failed to truncate file %s", path); close(fd); goto out; } } close(fd); } /* If the lxc-snapshot file is empty, remove it. */ if (stat(path, &fbuf) < 0) goto out; if (!fbuf.st_size) { remove(path); } } bret = true; out: container_disk_unlock(c0); return bret; } static void strip_newline(char *p) { size_t len = strlen(p); if (len < 1) return; if (p[len-1] == '\n') p[len-1] = '\0'; } void mod_all_rdeps(struct lxc_container *c, bool inc) { struct lxc_container *p; char *lxcpath = NULL, *lxcname = NULL, path[MAXPATHLEN]; size_t pathlen = 0, namelen = 0; FILE *f; int ret; ret = snprintf(path, MAXPATHLEN, "%s/%s/lxc_rdepends", c->config_path, c->name); if (ret < 0 || ret >= MAXPATHLEN) { ERROR("Path name too long"); return; } f = fopen(path, "r"); if (f == NULL) return; while (getline(&lxcpath, &pathlen, f) != -1) { if (getline(&lxcname, &namelen, f) == -1) { ERROR("badly formatted file %s", path); goto out; } strip_newline(lxcpath); strip_newline(lxcname); if ((p = lxc_container_new(lxcname, lxcpath)) == NULL) { ERROR("Unable to find dependent container %s:%s", lxcpath, lxcname); continue; } if (!mod_rdep(p, c, inc)) ERROR("Failed to update snapshots file for %s:%s", lxcpath, lxcname); lxc_container_put(p); } out: free(lxcpath); free(lxcname); fclose(f); } static bool has_fs_snapshots(struct lxc_container *c) { FILE *f; char path[MAXPATHLEN]; int ret, v; struct stat fbuf; bool bret = false; ret = snprintf(path, MAXPATHLEN, "%s/%s/lxc_snapshots", c->config_path, c->name); if (ret < 0 || ret > MAXPATHLEN) goto out; /* If the file doesn't exist there are no snapshots. */ if (stat(path, &fbuf) < 0) goto out; v = fbuf.st_size; if (v != 0) { f = fopen(path, "r"); if (!f) goto out; ret = fscanf(f, "%d", &v); fclose(f); // TODO: Figure out what to do with the return value of fscanf. if (ret != 1) INFO("Container uses new lxc-snapshots format %s", path); } bret = v != 0; out: return bret; } static bool has_snapshots(struct lxc_container *c) { char path[MAXPATHLEN]; struct dirent *direntp; int count=0; DIR *dir; if (!get_snappath_dir(c, path)) return false; dir = opendir(path); if (!dir) return false; while ((direntp = readdir(dir))) { if (!direntp) break; if (!strcmp(direntp->d_name, ".")) continue; if (!strcmp(direntp->d_name, "..")) continue; count++; break; } closedir(dir); return count > 0; } static bool do_destroy_container(struct lxc_conf *conf) { if (am_unpriv()) { if (userns_exec_1(conf, bdev_destroy_wrapper, conf) < 0) return false; return true; } return bdev_destroy(conf); } static int lxc_rmdir_onedev_wrapper(void *data) { char *arg = (char *) data; return lxc_rmdir_onedev(arg, "snaps"); } static bool container_destroy(struct lxc_container *c) { bool bret = false; int ret = 0; struct lxc_conf *conf; if (!c || !do_lxcapi_is_defined(c)) return false; conf = c->lxc_conf; if (container_disk_lock(c)) return false; if (!is_stopped(c)) { // we should queue some sort of error - in c->error_string? ERROR("container %s is not stopped", c->name); goto out; } if (conf && !lxc_list_empty(&conf->hooks[LXCHOOK_DESTROY])) { /* Start of environment variable setup for hooks */ if (c->name && setenv("LXC_NAME", c->name, 1)) { SYSERROR("failed to set environment variable for container name"); } if (conf->rcfile && setenv("LXC_CONFIG_FILE", conf->rcfile, 1)) { SYSERROR("failed to set environment variable for config path"); } if (conf->rootfs.mount && setenv("LXC_ROOTFS_MOUNT", conf->rootfs.mount, 1)) { SYSERROR("failed to set environment variable for rootfs mount"); } if (conf->rootfs.path && setenv("LXC_ROOTFS_PATH", conf->rootfs.path, 1)) { SYSERROR("failed to set environment variable for rootfs mount"); } if (conf->console.path && setenv("LXC_CONSOLE", conf->console.path, 1)) { SYSERROR("failed to set environment variable for console path"); } if (conf->console.log_path && setenv("LXC_CONSOLE_LOGPATH", conf->console.log_path, 1)) { SYSERROR("failed to set environment variable for console log"); } /* End of environment variable setup for hooks */ if (run_lxc_hooks(c->name, "destroy", conf, c->get_config_path(c), NULL)) { ERROR("Error executing clone hook for %s", c->name); goto out; } } if (current_config && conf == current_config) { current_config = NULL; if (conf->logfd != -1) { close(conf->logfd); conf->logfd = -1; } } if (conf && conf->rootfs.path && conf->rootfs.mount) { if (!do_destroy_container(conf)) { ERROR("Error destroying rootfs for %s", c->name); goto out; } INFO("Destroyed rootfs for %s", c->name); } mod_all_rdeps(c, false); 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()) ret = userns_exec_1(conf, lxc_rmdir_onedev_wrapper, path); else ret = lxc_rmdir_onedev(path, "snaps"); if (ret < 0) { ERROR("Error destroying container directory for %s", c->name); goto out; } INFO("Destroyed directory for %s", c->name); bret = true; out: container_disk_unlock(c); return bret; } static bool do_lxcapi_destroy(struct lxc_container *c) { if (!c || !lxcapi_is_defined(c)) return false; if (has_snapshots(c)) { ERROR("Container %s has snapshots; not removing", c->name); return false; } if (has_fs_snapshots(c)) { ERROR("container %s has snapshots on its rootfs", c->name); return false; } return container_destroy(c); } WRAP_API(bool, lxcapi_destroy) static bool do_lxcapi_destroy_with_snapshots(struct lxc_container *c) { if (!c || !lxcapi_is_defined(c)) return false; if (!lxcapi_snapshot_destroy_all(c)) { ERROR("Error deleting all snapshots"); return false; } 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; if (!c->lxc_conf) c->lxc_conf = lxc_conf_init(); if (!c->lxc_conf) return false; config = lxc_getconfig(key); if (!config) return false; if (config->cb(key, v, c->lxc_conf) != 0) return false; return do_append_unexp_config_line(c->lxc_conf, key, v); } static bool do_lxcapi_set_config_item(struct lxc_container *c, const char *key, const char *v) { bool b = false; if (!c) return false; if (container_mem_lock(c)) return false; b = set_config_item_locked(c, key, v); container_mem_unlock(c); 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) return NULL; return strdup(c->configfile); } static const char *lxcapi_get_config_path(struct lxc_container *c) { if (!c || !c->config_path) return NULL; return (const char *)(c->config_path); } /* * not for export * Just recalculate the c->configfile based on the * c->config_path, which must be set. * The lxc_container must be locked or not yet public. */ static bool set_config_filename(struct lxc_container *c) { char *newpath; int len, ret; if (!c->config_path) return false; /* $lxc_path + "/" + c->name + "/" + "config" + '\0' */ len = strlen(c->config_path) + strlen(c->name) + strlen("config") + 3; newpath = malloc(len); if (!newpath) return false; ret = snprintf(newpath, len, "%s/%s/config", c->config_path, c->name); if (ret < 0 || ret >= len) { fprintf(stderr, "Error printing out config file name\n"); free(newpath); return false; } free(c->configfile); c->configfile = newpath; return true; } static bool do_lxcapi_set_config_path(struct lxc_container *c, const char *path) { char *p; bool b = false; char *oldpath = NULL; if (!c) return b; if (container_mem_lock(c)) return b; p = strdup(path); if (!p) { ERROR("Out of memory setting new lxc path"); goto err; } b = true; if (c->config_path) oldpath = c->config_path; c->config_path = p; /* Since we've changed the config path, we have to change the * config file name too */ if (!set_config_filename(c)) { ERROR("Out of memory setting new config filename"); b = false; free(c->config_path); c->config_path = oldpath; oldpath = NULL; } err: free(oldpath); container_mem_unlock(c); return b; } WRAP_API_1(bool, lxcapi_set_config_path, const char *) static bool do_lxcapi_set_cgroup_item(struct lxc_container *c, const char *subsys, const char *value) { int ret; if (!c) return false; if (is_stopped(c)) return false; if (container_disk_lock(c)) return false; ret = lxc_cgroup_set(subsys, value, c->name, c->config_path); container_disk_unlock(c); return ret == 0; } 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; if (!c) return -1; if (is_stopped(c)) return -1; if (container_disk_lock(c)) return -1; ret = lxc_cgroup_get(subsys, retv, inlen, c->name, c->config_path); container_disk_unlock(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); } const char *lxc_get_version(void) { return LXC_VERSION; } static int copy_file(const char *old, const char *new) { int in, out; ssize_t len, ret; char buf[8096]; struct stat sbuf; if (file_exists(new)) { ERROR("copy destination %s exists", new); return -1; } ret = stat(old, &sbuf); if (ret < 0) { INFO("Error stat'ing %s", old); return -1; } in = open(old, O_RDONLY); if (in < 0) { SYSERROR("Error opening original file %s", old); return -1; } out = open(new, O_CREAT | O_EXCL | O_WRONLY, 0644); if (out < 0) { SYSERROR("Error opening new file %s", new); close(in); return -1; } while (1) { len = read(in, buf, 8096); if (len < 0) { SYSERROR("Error reading old file %s", old); goto err; } if (len == 0) break; ret = write(out, buf, len); if (ret < len) { // should we retry? SYSERROR("Error: write to new file %s was interrupted", new); goto err; } } close(in); close(out); // we set mode, but not owner/group ret = chmod(new, sbuf.st_mode); if (ret) { SYSERROR("Error setting mode on %s", new); return -1; } return 0; err: close(in); close(out); return -1; } static int copyhooks(struct lxc_container *oldc, struct lxc_container *c) { int i, len, ret; struct lxc_list *it; char *cpath; len = strlen(oldc->config_path) + strlen(oldc->name) + 3; cpath = alloca(len); ret = snprintf(cpath, len, "%s/%s/", oldc->config_path, oldc->name); if (ret < 0 || ret >= len) return -1; for (i=0; ilxc_conf->hooks[i]) { char *hookname = it->elem; char *fname = strrchr(hookname, '/'); char tmppath[MAXPATHLEN]; if (!fname) // relative path - we don't support, but maybe we should return 0; if (strncmp(hookname, cpath, len - 1) != 0) { // this hook is public - ignore continue; } // copy the script, and change the entry in confile ret = snprintf(tmppath, MAXPATHLEN, "%s/%s/%s", c->config_path, c->name, fname+1); if (ret < 0 || ret >= MAXPATHLEN) return -1; ret = copy_file(it->elem, tmppath); if (ret < 0) return -1; free(it->elem); it->elem = strdup(tmppath); if (!it->elem) { ERROR("out of memory copying hook path"); return -1; } } } if (!clone_update_unexp_hooks(c->lxc_conf, oldc->config_path, c->config_path, oldc->name, c->name)) { ERROR("Error saving new hooks in clone"); return -1; } do_lxcapi_save_config(c, NULL); return 0; } static int copy_fstab(struct lxc_container *oldc, struct lxc_container *c) { char newpath[MAXPATHLEN]; char *oldpath = oldc->lxc_conf->fstab; int ret; if (!oldpath) return 0; clear_unexp_config_line(c->lxc_conf, "lxc.mount", false); char *p = strrchr(oldpath, '/'); if (!p) return -1; ret = snprintf(newpath, MAXPATHLEN, "%s/%s%s", c->config_path, c->name, p); if (ret < 0 || ret >= MAXPATHLEN) { ERROR("error printing new path for %s", oldpath); return -1; } if (file_exists(newpath)) { ERROR("error: fstab file %s exists", newpath); return -1; } if (copy_file(oldpath, newpath) < 0) { ERROR("error: copying %s to %s", oldpath, newpath); return -1; } free(c->lxc_conf->fstab); c->lxc_conf->fstab = strdup(newpath); if (!c->lxc_conf->fstab) { ERROR("error: allocating pathname"); return -1; } if (!do_append_unexp_config_line(c->lxc_conf, "lxc.mount", newpath)) { ERROR("error saving new lxctab"); return -1; } return 0; } static void copy_rdepends(struct lxc_container *c, struct lxc_container *c0) { char path0[MAXPATHLEN], path1[MAXPATHLEN]; int ret; ret = snprintf(path0, MAXPATHLEN, "%s/%s/lxc_rdepends", c0->config_path, c0->name); if (ret < 0 || ret >= MAXPATHLEN) { WARN("Error copying reverse dependencies"); return; } ret = snprintf(path1, MAXPATHLEN, "%s/%s/lxc_rdepends", c->config_path, c->name); if (ret < 0 || ret >= MAXPATHLEN) { WARN("Error copying reverse dependencies"); return; } if (copy_file(path0, path1) < 0) { INFO("Error copying reverse dependencies"); return; } } static bool add_rdepends(struct lxc_container *c, struct lxc_container *c0) { int ret; char path[MAXPATHLEN]; FILE *f; bool bret; ret = snprintf(path, MAXPATHLEN, "%s/%s/lxc_rdepends", c->config_path, c->name); if (ret < 0 || ret >= MAXPATHLEN) return false; f = fopen(path, "a"); if (!f) return false; bret = true; // if anything goes wrong, just return an error if (fprintf(f, "%s\n%s\n", c0->config_path, c0->name) < 0) bret = false; if (fclose(f) != 0) bret = false; return bret; } /* * If the fs natively supports snapshot clones with no penalty, * then default to those even if not requested. * Currently we only do this for btrfs. */ bool should_default_to_snapshot(struct lxc_container *c0, struct lxc_container *c1) { size_t l0 = strlen(c0->config_path) + strlen(c0->name) + 2; size_t l1 = strlen(c1->config_path) + strlen(c1->name) + 2; char *p0 = alloca(l0 + 1); char *p1 = alloca(l1 + 1); char *rootfs = c0->lxc_conf->rootfs.path; snprintf(p0, l0, "%s/%s", c0->config_path, c0->name); snprintf(p1, l1, "%s/%s", c1->config_path, c1->name); if (!is_btrfs_fs(p0) || !is_btrfs_fs(p1)) return false; if (is_btrfs_subvol(rootfs) <= 0) return false; return btrfs_same_fs(p0, p1) == 0; } static int copy_storage(struct lxc_container *c0, struct lxc_container *c, const char *newtype, int flags, const char *bdevdata, uint64_t newsize) { struct bdev *bdev; int need_rdep; if (should_default_to_snapshot(c0, c)) flags |= LXC_CLONE_SNAPSHOT; bdev = bdev_copy(c0, c->name, c->config_path, newtype, flags, bdevdata, newsize, &need_rdep); if (!bdev) { ERROR("Error copying storage."); return -1; } /* Set new rootfs. */ free(c->lxc_conf->rootfs.path); c->lxc_conf->rootfs.path = strdup(bdev->src); /* Set new bdev type. */ free(c->lxc_conf->rootfs.bdev_type); c->lxc_conf->rootfs.bdev_type = strdup(bdev->type); bdev_put(bdev); if (!c->lxc_conf->rootfs.path) { ERROR("Out of memory while setting storage path."); return -1; } if (!c->lxc_conf->rootfs.bdev_type) { ERROR("Out of memory while setting rootfs backend."); return -1; } /* Append a new lxc.rootfs entry to the unexpanded config. */ clear_unexp_config_line(c->lxc_conf, "lxc.rootfs", false); if (!do_append_unexp_config_line(c->lxc_conf, "lxc.rootfs", c->lxc_conf->rootfs.path)) { ERROR("Error saving new rootfs to cloned config."); return -1; } /* Append a new lxc.rootfs.backend entry to the unexpanded config. */ clear_unexp_config_line(c->lxc_conf, "lxc.rootfs.backend", false); if (!do_append_unexp_config_line(c->lxc_conf, "lxc.rootfs.backend", c->lxc_conf->rootfs.bdev_type)) { ERROR("Error saving new rootfs backend to cloned config."); return -1; } if (flags & LXC_CLONE_SNAPSHOT) copy_rdepends(c, c0); if (need_rdep) { if (!add_rdepends(c, c0)) WARN("Error adding reverse dependency from %s to %s", c->name, c0->name); } mod_all_rdeps(c, true); return 0; } struct clone_update_data { struct lxc_container *c0; struct lxc_container *c1; int flags; char **hookargs; }; static int clone_update_rootfs(struct clone_update_data *data) { struct lxc_container *c0 = data->c0; struct lxc_container *c = data->c1; int flags = data->flags; char **hookargs = data->hookargs; int ret = -1; char path[MAXPATHLEN]; struct bdev *bdev; FILE *fout; struct lxc_conf *conf = c->lxc_conf; /* update hostname in rootfs */ /* we're going to mount, so run in a clean namespace to simplify cleanup */ if (setgid(0) < 0) { ERROR("Failed to setgid to 0"); return -1; } if (setuid(0) < 0) { ERROR("Failed to setuid to 0"); return -1; } if (setgroups(0, NULL) < 0) WARN("Failed to clear groups"); if (unshare(CLONE_NEWNS) < 0) return -1; bdev = bdev_init(c->lxc_conf, c->lxc_conf->rootfs.path, c->lxc_conf->rootfs.mount, NULL); if (!bdev) return -1; if (strcmp(bdev->type, "dir") != 0) { if (unshare(CLONE_NEWNS) < 0) { ERROR("error unsharing mounts"); bdev_put(bdev); return -1; } if (detect_shared_rootfs()) { if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) { SYSERROR("Failed to make / rslave"); ERROR("Continuing..."); } } if (bdev->ops->mount(bdev) < 0) { bdev_put(bdev); return -1; } } else { // TODO come up with a better way free(bdev->dest); bdev->dest = strdup(bdev->src); } if (!lxc_list_empty(&conf->hooks[LXCHOOK_CLONE])) { /* Start of environment variable setup for hooks */ if (c0->name && setenv("LXC_SRC_NAME", c0->name, 1)) { SYSERROR("failed to set environment variable for source container name"); } if (c->name && setenv("LXC_NAME", c->name, 1)) { SYSERROR("failed to set environment variable for container name"); } if (conf->rcfile && setenv("LXC_CONFIG_FILE", conf->rcfile, 1)) { SYSERROR("failed to set environment variable for config path"); } if (bdev->dest && setenv("LXC_ROOTFS_MOUNT", bdev->dest, 1)) { SYSERROR("failed to set environment variable for rootfs mount"); } if (conf->rootfs.path && setenv("LXC_ROOTFS_PATH", conf->rootfs.path, 1)) { SYSERROR("failed to set environment variable for rootfs mount"); } if (run_lxc_hooks(c->name, "clone", conf, c->get_config_path(c), hookargs)) { ERROR("Error executing clone hook for %s", c->name); bdev_put(bdev); return -1; } } if (!(flags & LXC_CLONE_KEEPNAME)) { ret = snprintf(path, MAXPATHLEN, "%s/etc/hostname", bdev->dest); bdev_put(bdev); if (ret < 0 || ret >= MAXPATHLEN) return -1; if (!file_exists(path)) return 0; if (!(fout = fopen(path, "w"))) { SYSERROR("unable to open %s: ignoring", path); return 0; } if (fprintf(fout, "%s", c->name) < 0) { fclose(fout); return -1; } if (fclose(fout) < 0) return -1; } else bdev_put(bdev); return 0; } static int clone_update_rootfs_wrapper(void *data) { struct clone_update_data *arg = (struct clone_update_data *) data; return clone_update_rootfs(arg); } /* * We want to support: sudo lxc-clone -o o1 -n n1 -s -L|-fssize fssize -v|--vgname vgname \ -p|--lvprefix lvprefix -t|--fstype fstype -B backingstore -s [ implies overlayfs] -s -B overlayfs -s -B aufs only rootfs gets converted (copied/snapshotted) on clone. */ static int create_file_dirname(char *path, struct lxc_conf *conf) { char *p = strrchr(path, '/'); int ret = -1; if (!p) return -1; *p = '\0'; ret = do_create_container_dir(path, conf); *p = '/'; return ret; } 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) { struct lxc_container *c2 = NULL; char newpath[MAXPATHLEN]; int ret, storage_copied = 0; char *origroot = NULL, *saved_unexp_conf = NULL; struct clone_update_data data; size_t saved_unexp_len; FILE *fout; pid_t pid; if (!c || !do_lxcapi_is_defined(c)) return NULL; if (container_mem_lock(c)) return NULL; if (!is_stopped(c)) { ERROR("error: Original container (%s) is running", c->name); goto out; } // Make sure the container doesn't yet exist. if (!newname) newname = c->name; if (!lxcpath) 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"); goto out; } if (file_exists(newpath)) { ERROR("error: clone: %s exists", newpath); goto out; } ret = create_file_dirname(newpath, c->lxc_conf); if (ret < 0 && errno != EEXIST) { ERROR("Error creating container dir for %s", newpath); goto out; } // copy the configuration, tweak it as needed, if (c->lxc_conf->rootfs.path) { origroot = c->lxc_conf->rootfs.path; c->lxc_conf->rootfs.path = NULL; } fout = fopen(newpath, "w"); if (!fout) { SYSERROR("open %s", newpath); goto out; } saved_unexp_conf = c->lxc_conf->unexpanded_config; saved_unexp_len = c->lxc_conf->unexpanded_len; c->lxc_conf->unexpanded_config = strdup(saved_unexp_conf); if (!c->lxc_conf->unexpanded_config) { ERROR("Out of memory"); fclose(fout); goto out; } clear_unexp_config_line(c->lxc_conf, "lxc.rootfs", false); write_config(fout, c->lxc_conf); fclose(fout); c->lxc_conf->rootfs.path = origroot; free(c->lxc_conf->unexpanded_config); c->lxc_conf->unexpanded_config = saved_unexp_conf; saved_unexp_conf = NULL; c->lxc_conf->unexpanded_len = saved_unexp_len; sprintf(newpath, "%s/%s/rootfs", lxcpath, newname); if (mkdir(newpath, 0755) < 0) { SYSERROR("error creating %s", newpath); goto out; } if (am_unpriv()) { if (chown_mapped_root(newpath, c->lxc_conf) < 0) { ERROR("Error chowning %s to container root", newpath); goto out; } } c2 = lxc_container_new(newname, lxcpath); if (!c2) { ERROR("clone: failed to create new container (%s %s)", newname, lxcpath); goto out; } // copy/snapshot rootfs's ret = copy_storage(c, c2, bdevtype, flags, bdevdata, newsize); if (ret < 0) goto out; // update utsname if (!(flags & LXC_CLONE_KEEPNAME)) { clear_unexp_config_line(c2->lxc_conf, "lxc.utsname", false); if (!set_config_item_locked(c2, "lxc.utsname", newname)) { ERROR("Error setting new hostname"); goto out; } } // copy hooks ret = copyhooks(c, c2); if (ret < 0) { ERROR("error copying hooks"); goto out; } if (copy_fstab(c, c2) < 0) { ERROR("error copying fstab"); goto out; } // update macaddrs if (!(flags & LXC_CLONE_KEEPMACADDR)) { if (!network_new_hwaddrs(c2->lxc_conf)) { ERROR("Error updating mac addresses"); goto out; } } // update absolute paths for overlay mount directories if (ovl_update_abs_paths(c2->lxc_conf, c->config_path, c->name, lxcpath, newname) < 0) goto out; // We've now successfully created c2's storage, so clear it out if we // fail after this storage_copied = 1; if (!c2->save_config(c2, NULL)) goto out; if ((pid = fork()) < 0) { SYSERROR("fork"); goto out; } if (pid > 0) { ret = wait_for_pid(pid); if (ret) goto out; container_mem_unlock(c); return c2; } data.c0 = c; data.c1 = c2; data.flags = flags; data.hookargs = hookargs; if (am_unpriv()) ret = userns_exec_1(c->lxc_conf, clone_update_rootfs_wrapper, &data); else ret = clone_update_rootfs(&data); if (ret < 0) exit(1); container_mem_unlock(c); exit(0); out: container_mem_unlock(c); if (c2) { if (!storage_copied) c2->lxc_conf->rootfs.path = NULL; c2->destroy(c2); lxc_container_put(c2); } return NULL; } 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; current_config = c ? c->lxc_conf : NULL; ret = do_lxcapi_clone(c, newname, lxcpath, flags, bdevtype, bdevdata, newsize, hookargs); current_config = NULL; return ret; } static bool do_lxcapi_rename(struct lxc_container *c, const char *newname) { struct bdev *bdev; struct lxc_container *newc; if (!c || !c->name || !c->config_path || !c->lxc_conf) return false; if (has_fs_snapshots(c) || has_snapshots(c)) { ERROR("Renaming a container with snapshots is not supported"); return false; } bdev = bdev_init(c->lxc_conf, c->lxc_conf->rootfs.path, c->lxc_conf->rootfs.mount, NULL); if (!bdev) { ERROR("Failed to find original backing store type"); return false; } newc = lxcapi_clone(c, newname, c->config_path, LXC_CLONE_KEEPMACADDR, NULL, bdev->type, 0, NULL); bdev_put(bdev); if (!newc) { lxc_container_put(newc); return false; } if (newc && lxcapi_is_defined(newc)) lxc_container_put(newc); if (!container_destroy(c)) { ERROR("Could not destroy existing container %s", c->name); return false; } 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) { int ret; if (!c) return -1; current_config = c->lxc_conf; ret = lxc_attach(c->name, c->config_path, exec_function, exec_payload, options, attached_process); current_config = NULL; return ret; } 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; int r; if (!c) return -1; command.program = (char*)program; command.argv = (char**)argv; r = lxc_attach(c->name, c->config_path, lxc_attach_run_command, &command, options, &pid); if (r < 0) { ERROR("ups"); return r; } 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; current_config = c ? c->lxc_conf : NULL; ret = do_lxcapi_attach_run_wait(c, options, program, argv); current_config = NULL; return ret; } static int get_next_index(const char *lxcpath, char *cname) { char *fname; struct stat sb; int i = 0, ret; fname = alloca(strlen(lxcpath) + 20); while (1) { sprintf(fname, "%s/snap%d", lxcpath, i); ret = stat(fname, &sb); if (ret != 0) return i; i++; } } static bool get_snappath_dir(struct lxc_container *c, char *snappath) { int ret; /* * If the old style snapshot path exists, use it * /var/lib/lxc -> /var/lib/lxcsnaps */ ret = snprintf(snappath, MAXPATHLEN, "%ssnaps", c->config_path); if (ret < 0 || ret >= MAXPATHLEN) return false; if (dir_exists(snappath)) { ret = snprintf(snappath, MAXPATHLEN, "%ssnaps/%s", c->config_path, c->name); if (ret < 0 || ret >= MAXPATHLEN) return false; return true; } /* * Use the new style path * /var/lib/lxc -> /var/lib/lxc + c->name + /snaps + \0 */ ret = snprintf(snappath, MAXPATHLEN, "%s/%s/snaps", c->config_path, c->name); if (ret < 0 || ret >= MAXPATHLEN) return false; return true; } static int do_lxcapi_snapshot(struct lxc_container *c, const char *commentfile) { int i, flags, ret; struct lxc_container *c2; char snappath[MAXPATHLEN], newname[20]; if (!c || !lxcapi_is_defined(c)) return -1; if (!bdev_can_backup(c->lxc_conf)) { ERROR("%s's backing store cannot be backed up.", c->name); ERROR("Your container must use another backing store type."); return -1; } if (!get_snappath_dir(c, snappath)) return -1; i = get_next_index(snappath, c->name); if (mkdir_p(snappath, 0755) < 0) { ERROR("Failed to create snapshot directory %s", snappath); return -1; } ret = snprintf(newname, 20, "snap%d", i); if (ret < 0 || ret >= 20) return -1; /* * We pass LXC_CLONE_SNAPSHOT to make sure that a rdepends file entry is * created in the original container */ flags = LXC_CLONE_SNAPSHOT | LXC_CLONE_KEEPMACADDR | LXC_CLONE_KEEPNAME | LXC_CLONE_KEEPBDEVTYPE | LXC_CLONE_MAYBE_SNAPSHOT; if (bdev_is_dir(c->lxc_conf, c->lxc_conf->rootfs.path)) { ERROR("Snapshot of directory-backed container requested."); ERROR("Making a copy-clone. If you do want snapshots, then"); ERROR("please create an aufs or overlayfs clone first, snapshot that"); ERROR("and keep the original container pristine."); flags &= ~LXC_CLONE_SNAPSHOT | LXC_CLONE_MAYBE_SNAPSHOT; } 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; } lxc_container_put(c2); // Now write down the creation time time_t timer; char buffer[25]; struct tm* tm_info; FILE *f; time(&timer); tm_info = localtime(&timer); strftime(buffer, 25, "%Y:%m:%d %H:%M:%S", tm_info); char *dfnam = alloca(strlen(snappath) + strlen(newname) + 5); sprintf(dfnam, "%s/%s/ts", snappath, newname); f = fopen(dfnam, "w"); if (!f) { ERROR("Failed to open %s", dfnam); return -1; } if (fprintf(f, "%s", buffer) < 0) { SYSERROR("Writing timestamp"); fclose(f); return -1; } ret = fclose(f); if (ret != 0) { SYSERROR("Writing timestamp"); return -1; } if (commentfile) { // $p / $name / comment \0 int len = strlen(snappath) + strlen(newname) + 10; char *path = alloca(len); sprintf(path, "%s/%s/comment", snappath, newname); return copy_file(commentfile, path) < 0 ? -1 : i; } return i; } WRAP_API_1(int, lxcapi_snapshot, const char *) static void lxcsnap_free(struct lxc_snapshot *s) { free(s->name); free(s->comment_pathname); free(s->timestamp); free(s->lxcpath); } static char *get_snapcomment_path(char* snappath, char *name) { // $snappath/$name/comment int ret, len = strlen(snappath) + strlen(name) + 10; char *s = malloc(len); if (s) { ret = snprintf(s, len, "%s/%s/comment", snappath, name); if (ret < 0 || ret >= len) { free(s); s = NULL; } } return s; } static char *get_timestamp(char* snappath, char *name) { char path[MAXPATHLEN], *s = NULL; int ret, len; FILE *fin; ret = snprintf(path, MAXPATHLEN, "%s/%s/ts", snappath, name); if (ret < 0 || ret >= MAXPATHLEN) return NULL; fin = fopen(path, "r"); if (!fin) return NULL; (void) fseek(fin, 0, SEEK_END); len = ftell(fin); (void) fseek(fin, 0, SEEK_SET); if (len > 0) { s = malloc(len+1); if (s) { s[len] = '\0'; if (fread(s, 1, len, fin) != len) { SYSERROR("reading timestamp"); free(s); s = NULL; } } } fclose(fin); return s; } static int do_lxcapi_snapshot_list(struct lxc_container *c, struct lxc_snapshot **ret_snaps) { char snappath[MAXPATHLEN], path2[MAXPATHLEN]; int count = 0, ret; struct dirent *direntp; struct lxc_snapshot *snaps =NULL, *nsnaps; DIR *dir; if (!c || !lxcapi_is_defined(c)) return -1; if (!get_snappath_dir(c, snappath)) { ERROR("path name too long"); return -1; } dir = opendir(snappath); if (!dir) { INFO("failed to open %s - assuming no snapshots", snappath); return 0; } while ((direntp = readdir(dir))) { if (!direntp) break; if (!strcmp(direntp->d_name, ".")) continue; if (!strcmp(direntp->d_name, "..")) continue; ret = snprintf(path2, MAXPATHLEN, "%s/%s/config", snappath, direntp->d_name); if (ret < 0 || ret >= MAXPATHLEN) { ERROR("pathname too long"); goto out_free; } if (!file_exists(path2)) continue; nsnaps = realloc(snaps, (count + 1)*sizeof(*snaps)); if (!nsnaps) { SYSERROR("Out of memory"); goto out_free; } snaps = nsnaps; snaps[count].free = lxcsnap_free; snaps[count].name = strdup(direntp->d_name); if (!snaps[count].name) goto out_free; snaps[count].lxcpath = strdup(snappath); if (!snaps[count].lxcpath) { free(snaps[count].name); goto out_free; } snaps[count].comment_pathname = get_snapcomment_path(snappath, direntp->d_name); snaps[count].timestamp = get_timestamp(snappath, direntp->d_name); count++; } if (closedir(dir)) WARN("failed to close directory"); *ret_snaps = snaps; return count; out_free: if (snaps) { int i; for (i=0; iname || !c->config_path) return false; if (has_fs_snapshots(c)) { ERROR("container rootfs has dependent snapshots"); return false; } bdev = bdev_init(c->lxc_conf, c->lxc_conf->rootfs.path, c->lxc_conf->rootfs.mount, NULL); if (!bdev) { ERROR("Failed to find original backing store type"); return false; } if (!newname) newname = c->name; if (!get_snappath_dir(c, clonelxcpath)) { bdev_put(bdev); return false; } // how should we lock this? snap = lxc_container_new(snapname, clonelxcpath); if (!snap || !lxcapi_is_defined(snap)) { ERROR("Could not open snapshot %s", snapname); if (snap) lxc_container_put(snap); bdev_put(bdev); return false; } if (strcmp(c->name, newname) == 0) { if (!container_destroy(c)) { ERROR("Could not destroy existing container %s", newname); lxc_container_put(snap); bdev_put(bdev); return false; } } if (strcmp(bdev->type, "dir") != 0 && strcmp(bdev->type, "loop") != 0) flags = LXC_CLONE_SNAPSHOT | LXC_CLONE_MAYBE_SNAPSHOT; rest = lxcapi_clone(snap, newname, c->config_path, flags, bdev->type, NULL, 0, NULL); bdev_put(bdev); if (rest && lxcapi_is_defined(rest)) b = true; if (rest) lxc_container_put(rest); lxc_container_put(snap); 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; bool bret = false; snap = lxc_container_new(snapname, clonelxcpath); if (!snap) { ERROR("Could not find snapshot %s", snapname); goto err; } if (!do_lxcapi_destroy(snap)) { ERROR("Could not destroy snapshot %s", snapname); goto err; } bret = true; err: if (snap) lxc_container_put(snap); return bret; } static bool remove_all_snapshots(const char *path) { DIR *dir; struct dirent *direntp; bool bret = true; dir = opendir(path); if (!dir) { SYSERROR("opendir on snapshot path %s", path); return false; } while ((direntp = readdir(dir))) { if (!direntp) break; if (!strcmp(direntp->d_name, ".")) continue; if (!strcmp(direntp->d_name, "..")) continue; if (!do_snapshot_destroy(direntp->d_name, path)) { bret = false; continue; } } closedir(dir); if (rmdir(path)) SYSERROR("Error removing directory %s", path); return bret; } static bool do_lxcapi_snapshot_destroy(struct lxc_container *c, const char *snapname) { char clonelxcpath[MAXPATHLEN]; if (!c || !c->name || !c->config_path || !snapname) return false; if (!get_snappath_dir(c, clonelxcpath)) return false; return do_snapshot_destroy(snapname, clonelxcpath); } WRAP_API_1(bool, lxcapi_snapshot_destroy, const char *) static bool do_lxcapi_snapshot_destroy_all(struct lxc_container *c) { char clonelxcpath[MAXPATHLEN]; if (!c || !c->name || !c->config_path) return false; if (!get_snappath_dir(c, clonelxcpath)) return false; return remove_all_snapshots(clonelxcpath); } 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) { char chrootpath[MAXPATHLEN]; char *directory_path = NULL; pid_t pid; int ret; if ((pid = fork()) < 0) { SYSERROR("failed to fork a child helper"); return false; } if (pid) { if (wait_for_pid(pid) != 0) { ERROR("Failed to create note in guest"); return false; } return true; } /* prepare the path */ ret = snprintf(chrootpath, MAXPATHLEN, "/proc/%d/root", init_pid); if (ret < 0 || ret >= MAXPATHLEN) return false; if (chroot(chrootpath) < 0) exit(1); if (chdir("/") < 0) exit(1); /* remove path if it exists */ if(faccessat(AT_FDCWD, path, F_OK, AT_SYMLINK_NOFOLLOW) == 0) { if (unlink(path) < 0) { ERROR("unlink failed"); exit(1); } } if (!add) exit(0); /* create any missing directories */ directory_path = dirname(strdup(path)); if (mkdir_p(directory_path, 0755) < 0 && errno != EEXIST) { ERROR("failed to create directory"); exit(1); } /* create the device node */ if (mknod(path, st->st_mode, st->st_rdev) < 0) { ERROR("mknod failed"); exit(1); } exit(0); } static bool add_remove_device_node(struct lxc_container *c, const char *src_path, const char *dest_path, bool add) { int ret; struct stat st; char value[MAX_BUFFER]; const char *p; /* make sure container is running */ if (!do_lxcapi_is_running(c)) { ERROR("container is not running"); return false; } /* use src_path if dest_path is NULL otherwise use dest_path */ p = dest_path ? dest_path : src_path; /* make sure we can access p */ if(access(p, F_OK) < 0 || stat(p, &st) < 0) return false; /* continue if path is character device or block device */ if (S_ISCHR(st.st_mode)) ret = snprintf(value, MAX_BUFFER, "c %d:%d rwm", major(st.st_rdev), minor(st.st_rdev)); else if (S_ISBLK(st.st_mode)) ret = snprintf(value, MAX_BUFFER, "b %d:%d rwm", major(st.st_rdev), minor(st.st_rdev)); else return false; /* check snprintf return code */ if (ret < 0 || ret >= MAX_BUFFER) return false; 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 (!do_lxcapi_set_cgroup_item(c, "devices.allow", value)) { ERROR("set_cgroup_item failed while adding the device node"); return false; } } else { if (!do_lxcapi_set_cgroup_item(c, "devices.deny", value)) { ERROR("set_cgroup_item failed while removing the device node"); return false; } } return true; } 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__); return false; } return add_remove_device_node(c, src_path, dest_path, true); } 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__); return false; } return add_remove_device_node(c, src_path, dest_path, false); } 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; if (am_unpriv()) { ERROR(NOT_SUPPORTED_ERROR, __FUNCTION__); return false; } if (!ifname) { ERROR("No source interface name given"); return false; } ret = lxc_netdev_isup(ifname); if (ret > 0) { /* netdev of ifname is up. */ ret = lxc_netdev_down(ifname); if (ret) goto err; } ret = lxc_netdev_move_by_name(ifname, do_lxcapi_init_pid(c), dst_ifname); if (ret) goto err; return true; err: return false; } 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; if (am_unpriv()) { ERROR(NOT_SUPPORTED_ERROR, __FUNCTION__); return false; } if (!ifname) { ERROR("No source interface name given"); return false; } pid_outside = getpid(); pid = fork(); if (pid < 0) { ERROR("failed to fork task to get interfaces information"); return false; } if (pid == 0) { // child int ret = 0; if (!enter_net_ns(c)) { ERROR("failed to enter namespace"); exit(-1); } ret = lxc_netdev_isup(ifname); if (ret < 0) exit(ret); /* netdev of ifname is up. */ if (ret) { ret = lxc_netdev_down(ifname); if (ret) exit(ret); } ret = lxc_netdev_move_by_name(ifname, pid_outside, dst_ifname); /* -EINVAL means there is no netdev named as ifanme. */ if (ret == -EINVAL) { ERROR("No network device named as %s.", ifname); } exit(ret); } if (wait_for_pid(pid) != 0) return false; return true; } WRAP_API_2(bool, lxcapi_detach_interface, const char *, const char *) static int do_lxcapi_migrate(struct lxc_container *c, unsigned int cmd, struct migrate_opts *opts, unsigned int size) { int ret; struct migrate_opts *valid_opts = opts; /* If the caller has a bigger (newer) struct migrate_opts, let's make * sure that the stuff on the end is zero, i.e. that they didn't ask us * to do anything special. */ if (size > sizeof(*opts)) { unsigned char *addr; unsigned char *end; addr = (void *)opts + sizeof(*opts); end = (void *)opts + size; for (; addr < end; addr++) { if (*addr) { return -E2BIG; } } } /* If the caller has a smaller struct, let's zero out the end for them * so we don't accidentally use bits of it that they didn't know about * to initialize. */ if (size < sizeof(*opts)) { valid_opts = malloc(sizeof(*opts)); if (!valid_opts) return -ENOMEM; memset(valid_opts, 0, sizeof(*opts)); memcpy(valid_opts, opts, size); } switch (cmd) { case MIGRATE_PRE_DUMP: if (!do_lxcapi_is_running(c)) { ERROR("container is not running"); return false; } ret = !__criu_pre_dump(c, valid_opts); break; case MIGRATE_DUMP: if (!do_lxcapi_is_running(c)) { ERROR("container is not running"); return false; } ret = !__criu_dump(c, valid_opts); break; case MIGRATE_RESTORE: if (do_lxcapi_is_running(c)) { ERROR("container is already running"); return false; } ret = !__criu_restore(c, valid_opts); break; default: ERROR("invalid migrate command %u", cmd); ret = -EINVAL; } if (size < sizeof(*opts)) free(valid_opts); return ret; } WRAP_API_3(int, lxcapi_migrate, unsigned int, struct migrate_opts *, unsigned int) static bool do_lxcapi_checkpoint(struct lxc_container *c, char *directory, bool stop, bool verbose) { struct migrate_opts opts; memset(&opts, 0, sizeof(opts)); opts.directory = directory; opts.stop = stop; opts.verbose = verbose; return !do_lxcapi_migrate(c, MIGRATE_DUMP, &opts, sizeof(opts)); } WRAP_API_3(bool, lxcapi_checkpoint, char *, bool, bool) static bool do_lxcapi_restore(struct lxc_container *c, char *directory, bool verbose) { struct migrate_opts opts; memset(&opts, 0, sizeof(opts)); opts.directory = directory; opts.verbose = verbose; return !do_lxcapi_migrate(c, MIGRATE_RESTORE, &opts, sizeof(opts)); } 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; const char **argv; int ret; if (!c) return -1; 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."); ret = -1; goto out; } argv[0] = arg; ret = do_lxcapi_attach_run_wait(c, options, program, (const char * const *)argv); free((void*)argv); out: current_config = NULL; return ret; } struct lxc_container *lxc_container_new(const char *name, const char *configpath) { struct lxc_container *c; if (!name) return NULL; c = malloc(sizeof(*c)); if (!c) { fprintf(stderr, "failed to malloc lxc_container\n"); return NULL; } memset(c, 0, sizeof(*c)); if (configpath) c->config_path = strdup(configpath); else c->config_path = strdup(lxc_global_config_value("lxc.lxcpath")); if (!c->config_path) { fprintf(stderr, "Out of memory\n"); goto err; } remove_trailing_slashes(c->config_path); c->name = malloc(strlen(name)+1); if (!c->name) { fprintf(stderr, "Error allocating lxc_container name\n"); goto err; } strcpy(c->name, name); c->numthreads = 1; if (!(c->slock = lxc_newlock(c->config_path, name))) { fprintf(stderr, "failed to create lock\n"); goto err; } if (!(c->privlock = lxc_newlock(NULL, NULL))) { fprintf(stderr, "failed to alloc privlock\n"); goto err; } if (!set_config_filename(c)) { fprintf(stderr, "Error allocating config file pathname\n"); goto err; } if (file_exists(c->configfile) && !lxcapi_load_config(c, NULL)) goto err; if (ongoing_create(c) == 2) { ERROR("Error: %s creation was not completed", c->name); container_destroy(c); lxcapi_clear_config(c); } c->daemonize = true; c->pidfile = NULL; // assign the member functions c->is_defined = lxcapi_is_defined; c->state = lxcapi_state; c->is_running = lxcapi_is_running; c->freeze = lxcapi_freeze; c->unfreeze = lxcapi_unfreeze; c->console = lxcapi_console; c->console_getfd = lxcapi_console_getfd; c->init_pid = lxcapi_init_pid; c->load_config = lxcapi_load_config; c->want_daemonize = lxcapi_want_daemonize; c->want_close_all_fds = lxcapi_want_close_all_fds; c->start = lxcapi_start; c->startl = lxcapi_startl; c->stop = lxcapi_stop; c->config_file_name = lxcapi_config_file_name; c->wait = lxcapi_wait; c->set_config_item = lxcapi_set_config_item; c->destroy = lxcapi_destroy; c->destroy_with_snapshots = lxcapi_destroy_with_snapshots; c->rename = lxcapi_rename; c->save_config = lxcapi_save_config; c->get_keys = lxcapi_get_keys; c->create = lxcapi_create; c->createl = lxcapi_createl; c->shutdown = lxcapi_shutdown; c->reboot = lxcapi_reboot; c->clear_config = lxcapi_clear_config; c->clear_config_item = lxcapi_clear_config_item; c->get_config_item = lxcapi_get_config_item; c->get_running_config_item = lxcapi_get_running_config_item; c->get_cgroup_item = lxcapi_get_cgroup_item; c->set_cgroup_item = lxcapi_set_cgroup_item; c->get_config_path = lxcapi_get_config_path; c->set_config_path = lxcapi_set_config_path; c->clone = lxcapi_clone; c->get_interfaces = lxcapi_get_interfaces; c->get_ips = lxcapi_get_ips; c->attach = lxcapi_attach; c->attach_run_wait = lxcapi_attach_run_wait; c->attach_run_waitl = lxcapi_attach_run_waitl; c->snapshot = lxcapi_snapshot; c->snapshot_list = lxcapi_snapshot_list; c->snapshot_restore = lxcapi_snapshot_restore; c->snapshot_destroy = lxcapi_snapshot_destroy; c->snapshot_destroy_all = lxcapi_snapshot_destroy_all; c->may_control = lxcapi_may_control; c->add_device_node = lxcapi_add_device_node; c->remove_device_node = lxcapi_remove_device_node; c->attach_interface = lxcapi_attach_interface; c->detach_interface = lxcapi_detach_interface; c->checkpoint = lxcapi_checkpoint; c->restore = lxcapi_restore; c->migrate = lxcapi_migrate; return c; err: lxc_container_free(c); return NULL; } int lxc_get_wait_states(const char **states) { int i; if (states) for (i=0; i