aboutsummaryrefslogtreecommitdiff
path: root/src/libutil
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2019-12-04 00:31:09 +0100
committerEelco Dolstra <edolstra@gmail.com>2019-12-04 00:31:09 +0100
commitc3c23a52ee1c5844343bc5ed075791ec7fec6413 (patch)
treebaf65223d87d2a5a5030f88208ceebab790624da /src/libutil
parente721f99817bb7154d8098c902e25f84521a90b7f (diff)
parentc1d18050b4cfed9eba68d4d21b397c6cce035e37 (diff)
Merge remote-tracking branch 'origin/master' into flakes
Diffstat (limited to 'src/libutil')
-rw-r--r--src/libutil/args.hh26
-rw-r--r--src/libutil/local.mk2
-rw-r--r--src/libutil/rust-ffi.cc12
-rw-r--r--src/libutil/rust-ffi.hh84
-rw-r--r--src/libutil/serialise.hh3
-rw-r--r--src/libutil/tarfile.cc36
-rw-r--r--src/libutil/tarfile.hh10
-rw-r--r--src/libutil/thread-pool.hh2
-rw-r--r--src/libutil/types.hh4
-rw-r--r--src/libutil/util.cc37
-rw-r--r--src/libutil/util.hh8
11 files changed, 181 insertions, 43 deletions
diff --git a/src/libutil/args.hh b/src/libutil/args.hh
index b960a55a8..967efbe1c 100644
--- a/src/libutil/args.hh
+++ b/src/libutil/args.hh
@@ -70,23 +70,23 @@ public:
Args & args;
Flag::ptr flag;
friend class Args;
- FlagMaker(Args & args) : args(args), flag(std::make_shared<Flag>()) { };
+ FlagMaker(Args & args) : args(args), flag(std::make_shared<Flag>()) { }
public:
~FlagMaker();
- FlagMaker & longName(const std::string & s) { flag->longName = s; return *this; };
- FlagMaker & shortName(char s) { flag->shortName = s; return *this; };
- FlagMaker & description(const std::string & s) { flag->description = s; return *this; };
- FlagMaker & label(const std::string & l) { flag->arity = 1; flag->labels = {l}; return *this; };
- FlagMaker & labels(const Strings & ls) { flag->arity = ls.size(); flag->labels = ls; return *this; };
- FlagMaker & arity(size_t arity) { flag->arity = arity; return *this; };
- FlagMaker & handler(std::function<void(std::vector<std::string>)> handler) { flag->handler = handler; return *this; };
- FlagMaker & handler(std::function<void()> handler) { flag->handler = [handler](std::vector<std::string>) { handler(); }; return *this; };
+ FlagMaker & longName(const std::string & s) { flag->longName = s; return *this; }
+ FlagMaker & shortName(char s) { flag->shortName = s; return *this; }
+ FlagMaker & description(const std::string & s) { flag->description = s; return *this; }
+ FlagMaker & label(const std::string & l) { flag->arity = 1; flag->labels = {l}; return *this; }
+ FlagMaker & labels(const Strings & ls) { flag->arity = ls.size(); flag->labels = ls; return *this; }
+ FlagMaker & arity(size_t arity) { flag->arity = arity; return *this; }
+ FlagMaker & handler(std::function<void(std::vector<std::string>)> handler) { flag->handler = handler; return *this; }
+ FlagMaker & handler(std::function<void()> handler) { flag->handler = [handler](std::vector<std::string>) { handler(); }; return *this; }
FlagMaker & handler(std::function<void(std::string)> handler) {
flag->arity = 1;
flag->handler = [handler](std::vector<std::string> ss) { handler(std::move(ss[0])); };
return *this;
- };
- FlagMaker & category(const std::string & s) { flag->category = s; return *this; };
+ }
+ FlagMaker & category(const std::string & s) { flag->category = s; return *this; }
template<class T>
FlagMaker & dest(T * dest)
@@ -94,7 +94,7 @@ public:
flag->arity = 1;
flag->handler = [=](std::vector<std::string> ss) { *dest = ss[0]; };
return *this;
- };
+ }
template<class T>
FlagMaker & set(T * dest, const T & val)
@@ -102,7 +102,7 @@ public:
flag->arity = 0;
flag->handler = [=](std::vector<std::string> ss) { *dest = val; };
return *this;
- };
+ }
FlagMaker & mkHashTypeFlag(HashType * ht);
};
diff --git a/src/libutil/local.mk b/src/libutil/local.mk
index e41a67d1f..35c1f6c13 100644
--- a/src/libutil/local.mk
+++ b/src/libutil/local.mk
@@ -7,3 +7,5 @@ libutil_DIR := $(d)
libutil_SOURCES := $(wildcard $(d)/*.cc)
libutil_LDFLAGS = $(LIBLZMA_LIBS) -lbz2 -pthread $(OPENSSL_LIBS) $(LIBBROTLI_LIBS) $(BOOST_LDFLAGS) -lboost_context
+
+libutil_LIBS = libnixrust
diff --git a/src/libutil/rust-ffi.cc b/src/libutil/rust-ffi.cc
new file mode 100644
index 000000000..931d29542
--- /dev/null
+++ b/src/libutil/rust-ffi.cc
@@ -0,0 +1,12 @@
+#include "logging.hh"
+#include "rust-ffi.hh"
+
+namespace nix {
+
+extern "C" std::exception_ptr * make_error(rust::StringSlice s)
+{
+ // FIXME: leak
+ return new std::exception_ptr(std::make_exception_ptr(Error(std::string(s.ptr, s.size))));
+}
+
+}
diff --git a/src/libutil/rust-ffi.hh b/src/libutil/rust-ffi.hh
new file mode 100644
index 000000000..663758bfc
--- /dev/null
+++ b/src/libutil/rust-ffi.hh
@@ -0,0 +1,84 @@
+#include "serialise.hh"
+
+namespace rust {
+
+// Depending on the internal representation of Rust slices is slightly
+// evil...
+template<typename T>
+struct Slice
+{
+ T * ptr;
+ size_t size;
+
+ Slice(T * ptr, size_t size) : ptr(ptr), size(size)
+ {
+ assert(ptr);
+ }
+};
+
+struct StringSlice : Slice<char>
+{
+ StringSlice(const std::string & s): Slice((char *) s.data(), s.size()) {}
+};
+
+struct Source
+{
+ size_t (*fun)(void * source_this, rust::Slice<uint8_t> data);
+ nix::Source * _this;
+
+ Source(nix::Source & _this)
+ : 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(data.ptr, data.size);
+ return n;
+ }
+};
+
+/* C++ representation of Rust's Result<T, CppException>. */
+template<typename T>
+struct Result
+{
+ unsigned int tag;
+
+ union {
+ T data;
+ std::exception_ptr * exc;
+ };
+
+ /* Rethrow the wrapped exception or return the wrapped value. */
+ T unwrap()
+ {
+ if (tag == 0)
+ return data;
+ else if (tag == 1)
+ 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/serialise.hh b/src/libutil/serialise.hh
index 0120aeecb..5780c93a6 100644
--- a/src/libutil/serialise.hh
+++ b/src/libutil/serialise.hh
@@ -77,7 +77,6 @@ struct BufferedSource : Source
size_t read(unsigned char * data, size_t len) override;
-
bool hasData();
protected:
@@ -274,7 +273,7 @@ Sink & operator << (Sink & sink, const Strings & s);
Sink & operator << (Sink & sink, const StringSet & s);
-MakeError(SerialisationError, Error)
+MakeError(SerialisationError, Error);
template<typename T>
diff --git a/src/libutil/tarfile.cc b/src/libutil/tarfile.cc
new file mode 100644
index 000000000..2cc7793fd
--- /dev/null
+++ b/src/libutil/tarfile.cc
@@ -0,0 +1,36 @@
+#include "rust-ffi.hh"
+#include "compression.hh"
+
+extern "C" {
+ rust::Result<std::tuple<>> *
+ unpack_tarfile(rust::Source source, rust::StringSlice dest_dir);
+}
+
+namespace nix {
+
+void unpackTarfile(Source & source, const Path & destDir)
+{
+ rust::Source source2(source);
+ rust::CBox(unpack_tarfile(source2, destDir))->unwrap();
+}
+
+void unpackTarfile(const Path & tarFile, const Path & destDir,
+ std::optional<std::string> baseName)
+{
+ if (!baseName) baseName = baseNameOf(tarFile);
+
+ 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, ".xz") ? makeDecompressionSink("xz", sink) :
+ makeDecompressionSink("none", sink);
+ readFile(tarFile, *decompressor);
+ decompressor->finish();
+ });
+
+ unpackTarfile(*source, destDir);
+}
+
+}
diff --git a/src/libutil/tarfile.hh b/src/libutil/tarfile.hh
new file mode 100644
index 000000000..ce0911e2a
--- /dev/null
+++ b/src/libutil/tarfile.hh
@@ -0,0 +1,10 @@
+#include "serialise.hh"
+
+namespace nix {
+
+void unpackTarfile(Source & source, const Path & destDir);
+
+void unpackTarfile(const Path & tarFile, const Path & destDir,
+ std::optional<std::string> baseName = {});
+
+}
diff --git a/src/libutil/thread-pool.hh b/src/libutil/thread-pool.hh
index bb16b639a..b22e0d162 100644
--- a/src/libutil/thread-pool.hh
+++ b/src/libutil/thread-pool.hh
@@ -11,7 +11,7 @@
namespace nix {
-MakeError(ThreadPoolShutDown, Error)
+MakeError(ThreadPoolShutDown, Error);
/* A simple thread pool that executes a queue of work items
(lambdas). */
diff --git a/src/libutil/types.hh b/src/libutil/types.hh
index 92bf469b5..4bc91828b 100644
--- a/src/libutil/types.hh
+++ b/src/libutil/types.hh
@@ -116,9 +116,9 @@ public:
{ \
public: \
using superClass::superClass; \
- };
+ }
-MakeError(Error, BaseError)
+MakeError(Error, BaseError);
class SysError : public Error
{
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 998037337..1e5e4851e 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -59,10 +59,11 @@ std::string SysError::addErrno(const std::string & s)
}
-string getEnv(const string & key, const string & def)
+std::optional<std::string> getEnv(const std::string & key)
{
char * value = getenv(key.c_str());
- return value ? string(value) : def;
+ if (!value) return {};
+ return std::string(value);
}
@@ -438,7 +439,7 @@ void deletePath(const Path & path, unsigned long long & bytesFreed)
static Path tempName(Path tmpRoot, const Path & prefix, bool includePid,
int & counter)
{
- tmpRoot = canonPath(tmpRoot.empty() ? getEnv("TMPDIR", "/tmp") : tmpRoot, true);
+ tmpRoot = canonPath(tmpRoot.empty() ? getEnv("TMPDIR").value_or("/tmp") : tmpRoot, true);
if (includePid)
return (format("%1%/%2%-%3%-%4%") % tmpRoot % prefix % getpid() % counter++).str();
else
@@ -479,7 +480,7 @@ Path createTempDir(const Path & tmpRoot, const Path & prefix,
std::pair<AutoCloseFD, Path> createTempFile(const Path & prefix)
{
- Path tmpl(getEnv("TMPDIR", "/tmp") + "/" + prefix + ".XXXXXX");
+ Path tmpl(getEnv("TMPDIR").value_or("/tmp") + "/" + prefix + ".XXXXXX");
// Strictly speaking, this is UB, but who cares...
AutoCloseFD fd(mkstemp((char *) tmpl.c_str()));
if (!fd)
@@ -491,7 +492,7 @@ std::pair<AutoCloseFD, Path> createTempFile(const Path & prefix)
std::string getUserName()
{
auto pw = getpwuid(geteuid());
- std::string name = pw ? pw->pw_name : getEnv("USER", "");
+ std::string name = pw ? pw->pw_name : getEnv("USER").value_or("");
if (name.empty())
throw Error("cannot figure out user name");
return name;
@@ -499,8 +500,8 @@ std::string getUserName()
static Lazy<Path> getHome2([]() {
- Path homeDir = getEnv("HOME");
- if (homeDir.empty()) {
+ auto homeDir = getEnv("HOME");
+ if (!homeDir) {
std::vector<char> buf(16384);
struct passwd pwbuf;
struct passwd * pw;
@@ -509,7 +510,7 @@ static Lazy<Path> getHome2([]() {
throw Error("cannot determine user's home directory");
homeDir = pw->pw_dir;
}
- return homeDir;
+ return *homeDir;
});
Path getHome() { return getHome2(); }
@@ -517,25 +518,21 @@ Path getHome() { return getHome2(); }
Path getCacheDir()
{
- Path cacheDir = getEnv("XDG_CACHE_HOME");
- if (cacheDir.empty())
- cacheDir = getHome() + "/.cache";
- return cacheDir;
+ auto cacheDir = getEnv("XDG_CACHE_HOME");
+ return cacheDir ? *cacheDir : getHome() + "/.cache";
}
Path getConfigDir()
{
- Path configDir = getEnv("XDG_CONFIG_HOME");
- if (configDir.empty())
- configDir = getHome() + "/.config";
- return configDir;
+ auto configDir = getEnv("XDG_CONFIG_HOME");
+ return configDir ? *configDir : getHome() + "/.config";
}
std::vector<Path> getConfigDirs()
{
Path configHome = getConfigDir();
- string configDirs = getEnv("XDG_CONFIG_DIRS");
+ string configDirs = getEnv("XDG_CONFIG_DIRS").value_or("");
std::vector<Path> result = tokenizeString<std::vector<string>>(configDirs, ":");
result.insert(result.begin(), configHome);
return result;
@@ -544,10 +541,8 @@ std::vector<Path> getConfigDirs()
Path getDataDir()
{
- Path dataDir = getEnv("XDG_DATA_HOME");
- if (dataDir.empty())
- dataDir = getHome() + "/.local/share";
- return dataDir;
+ auto dataDir = getEnv("XDG_DATA_HOME");
+ return dataDir ? *dataDir : getHome() + "/.local/share";
}
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index 2e5f4ca4e..ca0b5737c 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -35,7 +35,7 @@ extern const std::string nativeSystem;
/* Return an environment variable. */
-string getEnv(const string & key, const string & def = "");
+std::optional<std::string> getEnv(const std::string & key);
/* Get the entire environment. */
std::map<std::string, std::string> getEnv();
@@ -158,7 +158,7 @@ void readFull(int fd, unsigned char * buf, size_t count);
void writeFull(int fd, const unsigned char * buf, size_t count, bool allowInterrupts = true);
void writeFull(int fd, const string & s, bool allowInterrupts = true);
-MakeError(EndOfFile, Error)
+MakeError(EndOfFile, Error);
/* Read a file descriptor until EOF occurs. */
@@ -339,10 +339,10 @@ void inline checkInterrupt()
_interrupted();
}
-MakeError(Interrupted, BaseError)
+MakeError(Interrupted, BaseError);
-MakeError(FormatError, Error)
+MakeError(FormatError, Error);
/* String tokenizer. */