about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Makefile.config.in1
-rw-r--r--configure.ac18
-rw-r--r--doc/manual/command-ref/conf-file.xml7
-rw-r--r--src/libstore/build.cc4
-rw-r--r--src/libstore/globals.cc16
-rw-r--r--src/libstore/globals.hh7
-rw-r--r--src/libstore/local.mk2
-rw-r--r--src/libstore/store-api.cc2
-rw-r--r--src/libutil/compression.cc60
-rw-r--r--src/libutil/config.cc39
-rw-r--r--src/libutil/config.hh8
-rw-r--r--tests/plugins.sh2
-rw-r--r--tests/plugins/plugintest.cc13
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);