diff options
-rw-r--r-- | Makefile.config.in | 1 | ||||
-rw-r--r-- | configure.ac | 18 | ||||
-rw-r--r-- | doc/manual/command-ref/conf-file.xml | 7 | ||||
-rw-r--r-- | src/libstore/build.cc | 4 | ||||
-rw-r--r-- | src/libstore/globals.cc | 16 | ||||
-rw-r--r-- | src/libstore/globals.hh | 7 | ||||
-rw-r--r-- | src/libstore/local.mk | 2 | ||||
-rw-r--r-- | src/libstore/store-api.cc | 2 | ||||
-rw-r--r-- | src/libutil/compression.cc | 60 | ||||
-rw-r--r-- | src/libutil/config.cc | 39 | ||||
-rw-r--r-- | src/libutil/config.hh | 8 | ||||
-rw-r--r-- | tests/plugins.sh | 2 | ||||
-rw-r--r-- | tests/plugins/plugintest.cc | 13 |
13 files changed, 120 insertions, 59 deletions
diff --git a/Makefile.config.in b/Makefile.config.in index fab82194656e..a9785dc73955 100644 --- a/Makefile.config.in +++ b/Makefile.config.in @@ -7,6 +7,7 @@ ENABLE_S3 = @ENABLE_S3@ HAVE_SODIUM = @HAVE_SODIUM@ HAVE_READLINE = @HAVE_READLINE@ HAVE_BROTLI = @HAVE_BROTLI@ +HAVE_SECCOMP = @HAVE_SECCOMP@ LIBCURL_LIBS = @LIBCURL_LIBS@ OPENSSL_LIBS = @OPENSSL_LIBS@ PACKAGE_NAME = @PACKAGE_NAME@ diff --git a/configure.ac b/configure.ac index 83b2346d065c..4102f32166f5 100644 --- a/configure.ac +++ b/configure.ac @@ -175,6 +175,8 @@ AC_SUBST(HAVE_SODIUM, [$have_sodium]) # Look for liblzma, a required dependency. PKG_CHECK_MODULES([LIBLZMA], [liblzma], [CXXFLAGS="$LIBLZMA_CFLAGS $CXXFLAGS"]) +AC_CHECK_LIB([lzma], [lzma_stream_encoder_mt], + [AC_DEFINE([HAVE_LZMA_MT], [1], [xz multithreaded compression support])]) # Look for libbrotli{enc,dec}, optional dependencies @@ -186,9 +188,21 @@ AC_SUBST(HAVE_BROTLI, [$have_brotli]) # Look for libseccomp, required for Linux sandboxing. if test "$sys_name" = linux; then - PKG_CHECK_MODULES([LIBSECCOMP], [libseccomp], - [CXXFLAGS="$LIBSECCOMP_CFLAGS $CXXFLAGS"]) + AC_ARG_ENABLE([seccomp-sandboxing], + AC_HELP_STRING([--disable-seccomp-sandboxing], + [Don't build support for seccomp sandboxing (only recommended if your arch doesn't support libseccomp yet!)] + )) + if test "x$enable_seccomp_sandboxing" != "xno"; then + PKG_CHECK_MODULES([LIBSECCOMP], [libseccomp], + [CXXFLAGS="$LIBSECCOMP_CFLAGS $CXXFLAGS"]) + have_seccomp=1 + else + have_seccomp= + fi +else + have_seccomp= fi +AC_SUBST(HAVE_SECCOMP, [$have_seccomp]) # Look for aws-cpp-sdk-s3. diff --git a/doc/manual/command-ref/conf-file.xml b/doc/manual/command-ref/conf-file.xml index 42906ddff5e2..c14a4d206b8d 100644 --- a/doc/manual/command-ref/conf-file.xml +++ b/doc/manual/command-ref/conf-file.xml @@ -757,9 +757,10 @@ builtins.fetchurl { plugins may construct static instances of RegisterPrimOp to add new primops or constants to the expression language, RegisterStoreImplementation to add new store implementations, - and RegisterCommand to add new subcommands to the - <literal>nix</literal> command. See the constructors for those - types for more details. + RegisterCommand to add new subcommands to the + <literal>nix</literal> command, and RegisterSetting to add new + nix config settings. See the constructors for those types for + more details. </para> <para> Since these files are loaded into the same address space as diff --git a/src/libstore/build.cc b/src/libstore/build.cc index cc69ff1c74bf..9b7abaa3d1ee 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -49,7 +49,9 @@ #include <sys/param.h> #include <sys/mount.h> #include <sys/syscall.h> +#if HAVE_SECCOMP #include <seccomp.h> +#endif #define pivot_root(new_root, put_old) (syscall(SYS_pivot_root, new_root, put_old)) #endif @@ -2469,7 +2471,7 @@ void DerivationGoal::chownToBuilder(const Path & path) void setupSeccomp() { -#if __linux__ +#if __linux__ && HAVE_SECCOMP if (!settings.filterSyscalls) return; scmp_filter_ctx ctx; diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index 247040606fb7..f46e8326235f 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -162,6 +162,22 @@ void initPlugins() throw Error("could not dynamically open plugin file '%s%': %s%", file, dlerror()); } } + /* We handle settings registrations here, since plugins can add settings */ + if (RegisterSetting::settingRegistrations) { + for (auto & registration : *RegisterSetting::settingRegistrations) + settings.addSetting(registration); + delete RegisterSetting::settingRegistrations; + } + settings.handleUnknownSettings(); +} + +RegisterSetting::SettingRegistrations * RegisterSetting::settingRegistrations; + +RegisterSetting::RegisterSetting(AbstractSetting * s) +{ + if (!settingRegistrations) + settingRegistrations = new SettingRegistrations; + settingRegistrations->emplace_back(s); } diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index fd3fbec9f017..dd01f832df0c 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -386,5 +386,12 @@ void initPlugins(); extern const string nixVersion; +struct RegisterSetting +{ + typedef std::vector<AbstractSetting *> SettingRegistrations; + static SettingRegistrations * settingRegistrations; + RegisterSetting(AbstractSetting * s); +}; + } diff --git a/src/libstore/local.mk b/src/libstore/local.mk index c7ac534e2383..e11efa5c2b54 100644 --- a/src/libstore/local.mk +++ b/src/libstore/local.mk @@ -25,7 +25,7 @@ ifeq ($(OS), SunOS) libstore_LDFLAGS += -lsocket endif -ifeq ($(OS), Linux) +ifeq ($(HAVE_SECCOMP), 1) libstore_LDFLAGS += -lseccomp endif diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 4d43ef082d53..8830edcc3449 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -839,7 +839,7 @@ ref<Store> openStore(const std::string & uri_, for (auto fun : *RegisterStoreImplementation::implementations) { auto store = fun(uri, params); if (store) { - store->warnUnknownSettings(); + store->handleUnknownSettings(); return ref<Store>(store); } } diff --git a/src/libutil/compression.cc b/src/libutil/compression.cc index ed15761b32a2..470c925ed7a6 100644 --- a/src/libutil/compression.cc +++ b/src/libutil/compression.cc @@ -1,6 +1,7 @@ #include "compression.hh" #include "util.hh" #include "finally.hh" +#include "logging.hh" #include <lzma.h> #include <bzlib.h> @@ -189,28 +190,9 @@ struct XzSink : CompressionSink lzma_stream strm = LZMA_STREAM_INIT; bool finished = false; - XzSink(Sink & nextSink, const bool parallel) : nextSink(nextSink) - { - lzma_ret ret; - if (parallel) { - lzma_mt mt_options = {}; - mt_options.flags = 0; - mt_options.timeout = 300; // Using the same setting as the xz cmd line - mt_options.preset = LZMA_PRESET_DEFAULT; - mt_options.filters = NULL; - mt_options.check = LZMA_CHECK_CRC64; - mt_options.threads = lzma_cputhreads(); - mt_options.block_size = 0; - if (mt_options.threads == 0) - mt_options.threads = 1; - // FIXME: maybe use lzma_stream_encoder_mt_memusage() to control the - // number of threads. - ret = lzma_stream_encoder_mt( - &strm, &mt_options); - } else - ret = lzma_easy_encoder( - &strm, 6, LZMA_CHECK_CRC64); - + template <typename F> + XzSink(Sink & nextSink, F&& initEncoder) : nextSink(nextSink) { + lzma_ret ret = initEncoder(); if (ret != LZMA_OK) throw CompressionError("unable to initialise lzma encoder"); // FIXME: apply the x86 BCJ filter? @@ -218,6 +200,9 @@ struct XzSink : CompressionSink strm.next_out = outbuf; strm.avail_out = sizeof(outbuf); } + XzSink(Sink & nextSink) : XzSink(nextSink, [this]() { + return lzma_easy_encoder(&strm, 6, LZMA_CHECK_CRC64); + }) {} ~XzSink() { @@ -271,6 +256,27 @@ struct XzSink : CompressionSink } }; +#ifdef HAVE_LZMA_MT +struct ParallelXzSink : public XzSink +{ + ParallelXzSink(Sink &nextSink) : XzSink(nextSink, [this]() { + lzma_mt mt_options = {}; + mt_options.flags = 0; + mt_options.timeout = 300; // Using the same setting as the xz cmd line + mt_options.preset = LZMA_PRESET_DEFAULT; + mt_options.filters = NULL; + mt_options.check = LZMA_CHECK_CRC64; + mt_options.threads = lzma_cputhreads(); + mt_options.block_size = 0; + if (mt_options.threads == 0) + mt_options.threads = 1; + // FIXME: maybe use lzma_stream_encoder_mt_memusage() to control the + // number of threads. + return lzma_stream_encoder_mt(&strm, &mt_options); + }) {} +}; +#endif + struct BzipSink : CompressionSink { Sink & nextSink; @@ -469,10 +475,18 @@ struct BrotliSink : CompressionSink ref<CompressionSink> makeCompressionSink(const std::string & method, Sink & nextSink, const bool parallel) { + if (parallel) { +#ifdef HAVE_LZMA_MT + if (method == "xz") + return make_ref<ParallelXzSink>(nextSink); +#endif + printMsg(lvlError, format("Warning: parallel compression requested but not supported for method '%1%', falling back to single-threaded compression") % method); + } + if (method == "none") return make_ref<NoneSink>(nextSink); else if (method == "xz") - return make_ref<XzSink>(nextSink, parallel); + return make_ref<XzSink>(nextSink); else if (method == "bzip2") return make_ref<BzipSink>(nextSink); else if (method == "br") diff --git a/src/libutil/config.cc b/src/libutil/config.cc index 0e502769edf8..ce6858f0d65a 100644 --- a/src/libutil/config.cc +++ b/src/libutil/config.cc @@ -7,10 +7,12 @@ namespace nix { void Config::set(const std::string & name, const std::string & value) { auto i = _settings.find(name); - if (i == _settings.end()) - throw UsageError("unknown setting '%s'", name); - i->second.setting->set(value); - i->second.setting->overriden = true; + if (i == _settings.end()) { + extras.emplace(name, value); + } else { + i->second.setting->set(value); + i->second.setting->overriden = true; + } } void Config::addSetting(AbstractSetting * setting) @@ -21,34 +23,34 @@ void Config::addSetting(AbstractSetting * setting) bool set = false; - auto i = initials.find(setting->name); - if (i != initials.end()) { + auto i = extras.find(setting->name); + if (i != extras.end()) { setting->set(i->second); setting->overriden = true; - initials.erase(i); + extras.erase(i); set = true; } for (auto & alias : setting->aliases) { - auto i = initials.find(alias); - if (i != initials.end()) { + auto i = extras.find(alias); + if (i != extras.end()) { if (set) warn("setting '%s' is set, but it's an alias of '%s' which is also set", alias, setting->name); else { setting->set(i->second); setting->overriden = true; - initials.erase(i); + extras.erase(i); set = true; } } } } -void Config::warnUnknownSettings() +void Config::handleUnknownSettings() { - for (auto & i : initials) - warn("unknown setting '%s'", i.first); + for (auto & s : extras) + warn("unknown setting '%s'", s.first); } StringMap Config::getSettings(bool overridenOnly) @@ -60,7 +62,7 @@ StringMap Config::getSettings(bool overridenOnly) return res; } -void Config::applyConfigFile(const Path & path, bool fatal) +void Config::applyConfigFile(const Path & path) { try { string contents = readFile(path); @@ -97,7 +99,7 @@ void Config::applyConfigFile(const Path & path, bool fatal) throw UsageError("illegal configuration line '%1%' in '%2%'", line, path); auto p = absPath(tokens[1], dirOf(path)); if (pathExists(p)) { - applyConfigFile(p, fatal); + applyConfigFile(p); } else if (!ignoreMissing) { throw Error("file '%1%' included from '%2%' not found", p, path); } @@ -112,12 +114,7 @@ void Config::applyConfigFile(const Path & path, bool fatal) vector<string>::iterator i = tokens.begin(); advance(i, 2); - try { - set(name, concatStringsSep(" ", Strings(i, tokens.end()))); // FIXME: slow - } catch (UsageError & e) { - if (fatal) throw; - warn("in configuration file '%s': %s", path, e.what()); - } + set(name, concatStringsSep(" ", Strings(i, tokens.end()))); // FIXME: slow }; } catch (SysError &) { } } diff --git a/src/libutil/config.hh b/src/libutil/config.hh index 9a32af528ec7..d2e7faf17434 100644 --- a/src/libutil/config.hh +++ b/src/libutil/config.hh @@ -48,25 +48,25 @@ private: Settings _settings; - StringMap initials; + StringMap extras; public: Config(const StringMap & initials) - : initials(initials) + : extras(initials) { } void set(const std::string & name, const std::string & value); void addSetting(AbstractSetting * setting); - void warnUnknownSettings(); + void handleUnknownSettings(); StringMap getSettings(bool overridenOnly = false); const Settings & _getSettings() { return _settings; } - void applyConfigFile(const Path & path, bool fatal = false); + void applyConfigFile(const Path & path); void resetOverriden(); diff --git a/tests/plugins.sh b/tests/plugins.sh index 0fad4f773a28..4b1baeddce32 100644 --- a/tests/plugins.sh +++ b/tests/plugins.sh @@ -2,6 +2,6 @@ source common.sh set -o pipefail -res=$(nix eval '(builtins.anotherNull)' --option plugin-files $PWD/plugins/libplugintest*) +res=$(nix eval '(builtins.anotherNull)' --option setting-set true --option plugin-files $PWD/plugins/libplugintest*) [ "$res"x = "nullx" ] diff --git a/tests/plugins/plugintest.cc b/tests/plugins/plugintest.cc index 6b5e6d7cde21..8da15ebabd7d 100644 --- a/tests/plugins/plugintest.cc +++ b/tests/plugins/plugintest.cc @@ -1,10 +1,19 @@ +#include "globals.hh" #include "primops.hh" using namespace nix; +static BaseSetting<bool> settingSet{false, "setting-set", + "Whether the plugin-defined setting was set"}; + +static RegisterSetting rs(&settingSet); + static void prim_anotherNull (EvalState & state, const Pos & pos, Value ** args, Value & v) { - mkNull(v); + if (settingSet) + mkNull(v); + else + mkBool(v, false); } -static RegisterPrimOp r("anotherNull", 0, prim_anotherNull); +static RegisterPrimOp rp("anotherNull", 0, prim_anotherNull); |