aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/platform
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstore/platform')
-rw-r--r--src/libstore/platform/fallback.cc5
-rw-r--r--src/libstore/platform/fallback.hh31
-rw-r--r--src/libstore/platform/linux.cc123
-rw-r--r--src/libstore/platform/linux.hh35
4 files changed, 194 insertions, 0 deletions
diff --git a/src/libstore/platform/fallback.cc b/src/libstore/platform/fallback.cc
new file mode 100644
index 000000000..5a01d64c8
--- /dev/null
+++ b/src/libstore/platform/fallback.cc
@@ -0,0 +1,5 @@
+#include "platform/fallback.hh"
+
+namespace nix {
+static RegisterStoreImplementation<FallbackLocalStore, LocalStoreConfig> regLocalStore;
+}
diff --git a/src/libstore/platform/fallback.hh b/src/libstore/platform/fallback.hh
new file mode 100644
index 000000000..fd27edbe6
--- /dev/null
+++ b/src/libstore/platform/fallback.hh
@@ -0,0 +1,31 @@
+#pragma once
+///@file
+
+#include "local-store.hh"
+
+namespace nix {
+
+/**
+ * Fallback platform implementation of LocalStore
+ * Exists so we can make LocalStore constructor protected
+ */
+class FallbackLocalStore : public LocalStore
+{
+public:
+ FallbackLocalStore(const Params & params)
+ : StoreConfig(params)
+ , LocalFSStoreConfig(params)
+ , LocalStoreConfig(params)
+ , Store(params)
+ , LocalFSStore(params)
+ , LocalStore(params)
+ {
+ }
+ FallbackLocalStore(const std::string scheme, std::string path, const Params & params)
+ : FallbackLocalStore(params)
+ {
+ throw UnimplementedError("FallbackLocalStore");
+ }
+};
+
+}
diff --git a/src/libstore/platform/linux.cc b/src/libstore/platform/linux.cc
new file mode 100644
index 000000000..9be3e47da
--- /dev/null
+++ b/src/libstore/platform/linux.cc
@@ -0,0 +1,123 @@
+#include "gc-store.hh"
+#include "signals.hh"
+#include "platform/linux.hh"
+
+#include <regex>
+
+namespace nix {
+static RegisterStoreImplementation<LinuxLocalStore, LocalStoreConfig> regLocalStore;
+
+static void readProcLink(const std::string & file, UncheckedRoots & roots)
+{
+ constexpr auto bufsiz = PATH_MAX;
+ char buf[bufsiz];
+ auto res = readlink(file.c_str(), buf, bufsiz);
+ if (res == -1) {
+ if (errno == ENOENT || errno == EACCES || errno == ESRCH) {
+ return;
+ }
+ throw SysError("reading symlink");
+ }
+ if (res == bufsiz) {
+ throw Error("overly long symlink starting with '%1%'", std::string_view(buf, bufsiz));
+ }
+ if (res > 0 && buf[0] == '/') {
+ roots[std::string(static_cast<char *>(buf), res)].emplace(file);
+ }
+}
+
+static std::string quoteRegexChars(const std::string & raw)
+{
+ static auto specialRegex = std::regex(R"([.^$\\*+?()\[\]{}|])");
+ return std::regex_replace(raw, specialRegex, R"(\$&)");
+}
+
+static void readFileRoots(const char * path, UncheckedRoots & roots)
+{
+ try {
+ roots[readFile(path)].emplace(path);
+ } catch (SysError & e) {
+ if (e.errNo != ENOENT && e.errNo != EACCES) {
+ throw;
+ }
+ }
+}
+
+void LinuxLocalStore::findPlatformRoots(UncheckedRoots & unchecked)
+{
+ auto procDir = AutoCloseDir{opendir("/proc")};
+ if (procDir) {
+ struct dirent * ent;
+ auto digitsRegex = std::regex(R"(^\d+$)");
+ auto mapRegex = std::regex(R"(^\s*\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+(/\S+)\s*$)");
+ auto storePathRegex =
+ std::regex(quoteRegexChars(storeDir) + R"(/[0-9a-z]+[0-9a-zA-Z\+\-\._\?=]*)");
+ while (errno = 0, ent = readdir(procDir.get())) {
+ checkInterrupt();
+ if (std::regex_match(ent->d_name, digitsRegex)) {
+ try {
+ readProcLink(fmt("/proc/%s/exe", ent->d_name), unchecked);
+ readProcLink(fmt("/proc/%s/cwd", ent->d_name), unchecked);
+
+ auto fdStr = fmt("/proc/%s/fd", ent->d_name);
+ auto fdDir = AutoCloseDir(opendir(fdStr.c_str()));
+ if (!fdDir) {
+ if (errno == ENOENT || errno == EACCES) {
+ continue;
+ }
+ throw SysError("opening %1%", fdStr);
+ }
+ struct dirent * fd_ent;
+ while (errno = 0, fd_ent = readdir(fdDir.get())) {
+ if (fd_ent->d_name[0] != '.') {
+ readProcLink(fmt("%s/%s", fdStr, fd_ent->d_name), unchecked);
+ }
+ }
+ if (errno) {
+ if (errno == ESRCH) {
+ continue;
+ }
+ throw SysError("iterating /proc/%1%/fd", ent->d_name);
+ }
+ fdDir.reset();
+
+ auto mapFile = fmt("/proc/%s/maps", ent->d_name);
+ auto mapLines =
+ tokenizeString<std::vector<std::string>>(readFile(mapFile), "\n");
+ for (const auto & line : mapLines) {
+ auto match = std::smatch{};
+ if (std::regex_match(line, match, mapRegex)) {
+ unchecked[match[1]].emplace(mapFile);
+ }
+ }
+
+ auto envFile = fmt("/proc/%s/environ", ent->d_name);
+ auto envString = readFile(envFile);
+ auto env_end = std::sregex_iterator{};
+ for (auto i =
+ std::sregex_iterator{
+ envString.begin(), envString.end(), storePathRegex
+ };
+ i != env_end;
+ ++i)
+ {
+ unchecked[i->str()].emplace(envFile);
+ }
+ } catch (SysError & e) {
+ if (errno == ENOENT || errno == EACCES || errno == ESRCH) {
+ continue;
+ }
+ throw;
+ }
+ }
+ }
+ if (errno) {
+ throw SysError("iterating /proc");
+ }
+ }
+
+ readFileRoots("/proc/sys/kernel/modprobe", unchecked);
+ readFileRoots("/proc/sys/kernel/fbsplash", unchecked);
+ readFileRoots("/proc/sys/kernel/poweroff_cmd", unchecked);
+}
+}
diff --git a/src/libstore/platform/linux.hh b/src/libstore/platform/linux.hh
new file mode 100644
index 000000000..8b97e17c5
--- /dev/null
+++ b/src/libstore/platform/linux.hh
@@ -0,0 +1,35 @@
+#pragma once
+///@file
+
+#include "gc-store.hh"
+#include "local-store.hh"
+
+namespace nix {
+
+/**
+ * Linux-specific implementation of LocalStore
+ */
+class LinuxLocalStore : public LocalStore
+{
+public:
+ LinuxLocalStore(const Params & params)
+ : StoreConfig(params)
+ , LocalFSStoreConfig(params)
+ , LocalStoreConfig(params)
+ , Store(params)
+ , LocalFSStore(params)
+ , LocalStore(params)
+ {
+ }
+ LinuxLocalStore(const std::string scheme, std::string path, const Params & params)
+ : LinuxLocalStore(params)
+ {
+ throw UnimplementedError("LinuxLocalStore");
+ }
+
+private:
+
+ void findPlatformRoots(UncheckedRoots & unchecked) override;
+};
+
+}