diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libexpr/parser.y | 7 | ||||
-rw-r--r-- | src/libstore/local.mk | 2 | ||||
-rw-r--r-- | src/libstore/ssh.cc | 5 | ||||
-rw-r--r-- | src/libutil/compression.cc | 64 | ||||
-rw-r--r-- | src/libutil/rust-ffi.cc | 17 | ||||
-rw-r--r-- | src/libutil/rust-ffi.hh | 58 | ||||
-rw-r--r-- | src/libutil/tarfile.cc | 8 | ||||
-rwxr-xr-x | src/nix-build/nix-build.cc | 2 | ||||
-rw-r--r-- | src/nix/progress-bar.cc | 4 |
9 files changed, 125 insertions, 42 deletions
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 10a057062..afa1fd439 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -576,12 +576,17 @@ Path resolveExprPath(Path path) { assert(path[0] == '/'); + unsigned int followCount = 0, maxFollow = 1024; + /* If `path' is a symlink, follow it. This is so that relative path references work. */ struct stat st; while (true) { + // Basic cycle/depth limit to avoid infinite loops. + if (++followCount >= maxFollow) + throw Error("too many symbolic links encountered while traversing the path '%s'", path); if (lstat(path.c_str(), &st)) - throw SysError(format("getting status of '%1%'") % path); + throw SysError("getting status of '%s'", path); if (!S_ISLNK(st.st_mode)) break; path = absPath(readLink(path), dirOf(path)); } diff --git a/src/libstore/local.mk b/src/libstore/local.mk index d3254554d..ac68c2342 100644 --- a/src/libstore/local.mk +++ b/src/libstore/local.mk @@ -13,7 +13,9 @@ ifneq ($(OS), FreeBSD) libstore_LDFLAGS += -ldl endif +ifeq ($(OS), Darwin) libstore_FILES = sandbox-defaults.sb sandbox-minimal.sb sandbox-network.sb +endif $(foreach file,$(libstore_FILES),$(eval $(call install-data-in,$(d)/$(file),$(datadir)/nix/sandbox))) diff --git a/src/libstore/ssh.cc b/src/libstore/ssh.cc index ac3ccd63d..2ee7115c5 100644 --- a/src/libstore/ssh.cc +++ b/src/libstore/ssh.cc @@ -62,7 +62,8 @@ std::unique_ptr<SSHMaster::Connection> SSHMaster::startCommand(const std::string args.push_back(command); execvp(args.begin()->c_str(), stringsToCharPtrs(args).data()); - throw SysError("executing '%s' on '%s'", command, host); + // could not exec ssh/bash + throw SysError("unable to execute '%s'", args.front()); }); @@ -108,7 +109,7 @@ Path SSHMaster::startMaster() addCommonSSHOpts(args); execvp(args.begin()->c_str(), stringsToCharPtrs(args).data()); - throw SysError("starting SSH master"); + throw SysError("unable to execute '%s'", args.front()); }); out.writeSide = -1; diff --git a/src/libutil/compression.cc b/src/libutil/compression.cc index 0dd84e320..860b04adb 100644 --- a/src/libutil/compression.cc +++ b/src/libutil/compression.cc @@ -11,6 +11,8 @@ #include <brotli/decode.h> #include <brotli/encode.h> +#include <zlib.h> + #include <iostream> namespace nix { @@ -42,6 +44,66 @@ struct NoneSink : CompressionSink void write(const unsigned char * data, size_t len) override { nextSink(data, len); } }; +struct GzipDecompressionSink : CompressionSink +{ + Sink & nextSink; + z_stream strm; + bool finished = false; + uint8_t outbuf[BUFSIZ]; + + GzipDecompressionSink(Sink & nextSink) : nextSink(nextSink) + { + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = 0; + strm.next_in = Z_NULL; + strm.next_out = outbuf; + strm.avail_out = sizeof(outbuf); + + // Enable gzip and zlib decoding (+32) with 15 windowBits + int ret = inflateInit2(&strm,15+32); + if (ret != Z_OK) + throw CompressionError("unable to initialise gzip encoder"); + } + + ~GzipDecompressionSink() + { + inflateEnd(&strm); + } + + void finish() override + { + CompressionSink::flush(); + write(nullptr, 0); + } + + void write(const unsigned char * data, size_t len) override + { + assert(len <= std::numeric_limits<decltype(strm.avail_in)>::max()); + + strm.next_in = (Bytef *) data; + strm.avail_in = len; + + while (!finished && (!data || strm.avail_in)) { + checkInterrupt(); + + int ret = inflate(&strm,Z_SYNC_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) + throw CompressionError("error while decompressing gzip file: %d (%d, %d)", + zError(ret), len, strm.avail_in); + + finished = ret == Z_STREAM_END; + + if (strm.avail_out < sizeof(outbuf) || strm.avail_in == 0) { + nextSink(outbuf, sizeof(outbuf) - strm.avail_out); + strm.next_out = (Bytef *) outbuf; + strm.avail_out = sizeof(outbuf); + } + } + } +}; + struct XzDecompressionSink : CompressionSink { Sink & nextSink; @@ -215,6 +277,8 @@ ref<CompressionSink> makeDecompressionSink(const std::string & method, Sink & ne return make_ref<XzDecompressionSink>(nextSink); else if (method == "bzip2") return make_ref<BzipDecompressionSink>(nextSink); + else if (method == "gzip") + return make_ref<GzipDecompressionSink>(nextSink); else if (method == "br") return make_ref<BrotliDecompressionSink>(nextSink); else diff --git a/src/libutil/rust-ffi.cc b/src/libutil/rust-ffi.cc index accc5e22b..8b8b7b75d 100644 --- a/src/libutil/rust-ffi.cc +++ b/src/libutil/rust-ffi.cc @@ -3,10 +3,14 @@ extern "C" std::exception_ptr * make_error(rust::StringSlice s) { - // FIXME: leak return new std::exception_ptr(std::make_exception_ptr(nix::Error(std::string(s.ptr, s.size)))); } +extern "C" void destroy_error(std::exception_ptr * ex) +{ + free(ex); +} + namespace rust { std::ostream & operator << (std::ostream & str, const String & s) @@ -15,4 +19,15 @@ std::ostream & operator << (std::ostream & str, const String & s) return str; } +size_t Source::sourceWrapper(void * _this, rust::Slice<uint8_t> data) +{ + try { + // FIXME: how to propagate exceptions? + auto n = ((nix::Source *) _this)->read((unsigned char *) data.ptr, data.size); + return n; + } catch (...) { + abort(); + } +} + } diff --git a/src/libutil/rust-ffi.hh b/src/libutil/rust-ffi.hh index a77f83ac5..3b51661c2 100644 --- a/src/libutil/rust-ffi.hh +++ b/src/libutil/rust-ffi.hh @@ -140,64 +140,58 @@ struct Source : fun(sourceWrapper), _this(&_this) {} - // FIXME: how to propagate exceptions? - static size_t sourceWrapper(void * _this, rust::Slice<uint8_t> data) - { - auto n = ((nix::Source *) _this)->read((unsigned char *) data.ptr, data.size); - return n; - } + static size_t sourceWrapper(void * _this, rust::Slice<uint8_t> data); }; /* C++ representation of Rust's Result<T, CppException>. */ template<typename T> struct Result { - unsigned int tag; + enum { Ok = 0, Err = 1, Uninit = 2 } tag; union { T data; std::exception_ptr * exc; }; + Result() : tag(Uninit) { }; // FIXME: remove + + Result(const Result &) = delete; + + Result(Result && other) + : tag(other.tag) + { + other.tag = Uninit; + if (tag == Ok) + data = std::move(other.data); + else if (tag == Err) + exc = other.exc; + } + ~Result() { - if (tag == 0) + if (tag == Ok) data.~T(); - else if (tag == 1) - // FIXME: don't leak exc + else if (tag == Err) + free(exc); + else if (tag == Uninit) ; + else + abort(); } /* Rethrow the wrapped exception or return the wrapped value. */ T unwrap() { - if (tag == 0) + if (tag == Ok) { + tag = Uninit; return std::move(data); - else if (tag == 1) + } + else if (tag == Err) std::rethrow_exception(*exc); else abort(); } }; -template<typename T> -struct CBox -{ - T * ptr; - - T * operator ->() - { - return ptr; - } - - CBox(T * ptr) : ptr(ptr) { } - CBox(const CBox &) = delete; - CBox(CBox &&) = delete; - - ~CBox() - { - free(ptr); - } -}; - } diff --git a/src/libutil/tarfile.cc b/src/libutil/tarfile.cc index 262bc655f..1be0ba24c 100644 --- a/src/libutil/tarfile.cc +++ b/src/libutil/tarfile.cc @@ -3,7 +3,7 @@ extern "C" { rust::Result<std::tuple<>> * - unpack_tarfile(rust::Source source, rust::StringSlice dest_dir); + unpack_tarfile(rust::Source source, rust::StringSlice dest_dir, rust::Result<std::tuple<>> & out); } namespace nix { @@ -11,7 +11,9 @@ namespace nix { void unpackTarfile(Source & source, const Path & destDir) { rust::Source source2(source); - rust::CBox(unpack_tarfile(source2, destDir))->unwrap(); + rust::Result<std::tuple<>> res; + unpack_tarfile(source2, destDir, res); + res.unwrap(); } void unpackTarfile(const Path & tarFile, const Path & destDir, @@ -22,8 +24,8 @@ void unpackTarfile(const Path & tarFile, const Path & destDir, auto source = sinkToSource([&](Sink & sink) { // FIXME: look at first few bytes to determine compression type. auto decompressor = - // FIXME: add .gz support hasSuffix(*baseName, ".bz2") ? makeDecompressionSink("bzip2", sink) : + hasSuffix(*baseName, ".gz") ? makeDecompressionSink("gzip", sink) : hasSuffix(*baseName, ".xz") ? makeDecompressionSink("xz", sink) : makeDecompressionSink("none", sink); readFile(tarFile, *decompressor); diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index 99546876a..205165a4c 100755 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -106,7 +106,7 @@ static void _main(int argc, char * * argv) // Heuristic to see if we're invoked as a shebang script, namely, // if we have at least one argument, it's the name of an // executable file, and it starts with "#!". - if (runEnv && argc > 1 && !std::regex_search(std::string(baseNameOf(argv[1])), std::regex("nix-shell"))) { + if (runEnv && argc > 1) { script = argv[1]; try { auto lines = tokenizeString<Strings>(readFile(script), "\n"); diff --git a/src/nix/progress-bar.cc b/src/nix/progress-bar.cc index d20c09f26..c445f31cc 100644 --- a/src/nix/progress-bar.cc +++ b/src/nix/progress-bar.cc @@ -155,7 +155,7 @@ public: if (type == actBuild) { auto name = storePathToName(getS(fields, 0)); if (hasSuffix(name, ".drv")) - name = name.substr(name.size() - 4); + name = name.substr(0, name.size() - 4); i->s = fmt("building " ANSI_BOLD "%s" ANSI_NORMAL, name); auto machineName = getS(fields, 1); if (machineName != "") @@ -180,7 +180,7 @@ public: if (type == actPostBuildHook) { auto name = storePathToName(getS(fields, 0)); if (hasSuffix(name, ".drv")) - name = name.substr(name.size() - 4); + name = name.substr(0, name.size() - 4); i->s = fmt("post-build " ANSI_BOLD "%s" ANSI_NORMAL, name); i->name = DrvName(name).name; } |