diff options
| author | Lexi Winter <ivy@FreeBSD.org> | 2025-06-16 02:43:15 +0100 |
|---|---|---|
| committer | Lexi Winter <ivy@FreeBSD.org> | 2025-06-16 02:43:15 +0100 |
| commit | 8129d0ef4629f44cd89e3b79e8b66129bb9dc866 (patch) | |
| tree | 271a7698c45d301a6f89f79fb1f2d0cac62f39da /liblfjail | |
| parent | 737fb60605e8b9c64d6dd9e4c982a4e7ee2ef5d3 (diff) | |
| download | lfjail-8129d0ef4629f44cd89e3b79e8b66129bb9dc866.tar.gz lfjail-8129d0ef4629f44cd89e3b79e8b66129bb9dc866.tar.bz2 | |
updates
Diffstat (limited to 'liblfjail')
| -rw-r--r-- | liblfjail/command_map.cc | 10 | ||||
| -rw-r--r-- | liblfjail/exec.cc | 14 | ||||
| -rw-r--r-- | liblfjail/exec.hh | 16 | ||||
| -rw-r--r-- | liblfjail/fd.cc | 16 | ||||
| -rw-r--r-- | liblfjail/fd.hh | 4 | ||||
| -rw-r--r-- | liblfjail/jail.cc | 23 | ||||
| -rw-r--r-- | liblfjail/spawn.hh | 4 | ||||
| -rw-r--r-- | liblfjail/split.hh | 64 | ||||
| -rw-r--r-- | liblfjail/zfs.cc | 55 | ||||
| -rw-r--r-- | liblfjail/zfs.hh | 18 |
10 files changed, 79 insertions, 145 deletions
diff --git a/liblfjail/command_map.cc b/liblfjail/command_map.cc index 96883a0..82b2fe0 100644 --- a/liblfjail/command_map.cc +++ b/liblfjail/command_map.cc @@ -23,13 +23,13 @@ struct node { node(std::string command); // Run the handler for this node. - int invoke(context const &ctx, int argc, char **argv) const; + auto invoke(context const &ctx, int argc, char **argv) const -> int; // Create a new node under this one, or return it if it already exists. // If path is empty, return this node. - node &create_node(std::string_view path); + auto create_node(std::string_view path) -> node&; - void print_usage(std::string prefix) const; + auto print_usage(std::string prefix) const -> void; private: std::map<std::string_view, node> commands; @@ -50,7 +50,7 @@ auto node::invoke(context const &ctx, int argc, char **argv) const -> int { auto const &child = it->second; // If the child has a handler, invoke it. - if (child.handler) + if (child.handler != nullptr) return child.handler->invoke(ctx, argc, argv); --argc; @@ -84,7 +84,7 @@ auto node::create_node(std::string_view path) -> node& { } void node::print_usage(std::string prefix) const { - if (handler) + if (handler != nullptr) std::print("{}{}\n", prefix, command); for (auto const &it : commands) diff --git a/liblfjail/exec.cc b/liblfjail/exec.cc index a1c9a4d..d86559e 100644 --- a/liblfjail/exec.cc +++ b/liblfjail/exec.cc @@ -35,27 +35,27 @@ auto fexecv::exec(this fexecv &self) noexcept -> void { /* * execv() */ -auto execv(std::string file, argv &&argv) -> fexecv { - auto const ret = ::open(file.c_str(), O_EXEC); +auto execv(std::string const &path, argv &&argv) -> fexecv { + auto const ret = ::open(path.c_str(), O_EXEC); if (ret == -1) - throw executable_not_found(file); - return fexecv(fd(ret), std::move(argv)); + throw executable_not_found(path); + return {fd(ret), std::move(argv)}; } /* * execvp() */ -auto execvp(std::string file, argv &&argv) -> fexecv { +auto execvp(std::string const &file, argv &&argv) -> fexecv { auto execfd = find_in_path(file); if (!execfd) throw executable_not_found(file); - return fexecv(std::move(*execfd), std::move(argv)); + return {std::move(*execfd), std::move(argv)}; } /* * shell */ -auto shell(std::string command) -> fexecv { +auto shell(std::string const &command) -> fexecv { return execl("/bin/sh", "sh", "-c", command); } diff --git a/liblfjail/exec.hh b/liblfjail/exec.hh index 18a2dd7..caadb66 100644 --- a/liblfjail/exec.hh +++ b/liblfjail/exec.hh @@ -64,38 +64,36 @@ static_assert(executor<fexecv>); * execv: equivalent to fexecv(), except the command is passed as * a pathname instead of a file descriptor. Does not search $PATH. */ -auto execv(std::string path, argv &&argv) -> fexecv; +auto execv(std::string const &path, argv &&argv) -> fexecv; /* * execvp: equivalent to fexecv(), except the command is passed as * a filename instead of a file descriptor. If the filename is not * an absolute path, it will be searched for in $PATH. */ -auto execvp(std::string file, argv &&argv) -> fexecv; +auto execvp(std::string const &file, argv &&argv) -> fexecv; /* * execl: equivalent to execv, except the arguments are passed as a * variadic pack of string-like objects. */ -auto execl(std::string path, auto &&...args) { - return execv(std::move(path), - argv::from_args({std::string_view(args)...})); +auto execl(std::string const &path, auto &&...args) { + return execv(path, argv::from_args({std::string_view(args)...})); } /* * execlp: equivalent to execvp, except the arguments are passed as a * variadic pack of string-like objects. */ -auto execlp(std::string file, auto &&...args) { - return execvp(std::move(file), - argv::from_args({std::string_view(args)...})); +auto execlp(std::string const &file, auto &&...args) { + return execvp(file, argv::from_args({std::string_view(args)...})); } /* * shell: run the process by invoking /bin/sh -c with the single argument, * equivalent to system(3). */ -auto shell(std::string command) -> fexecv; +auto shell(std::string const &command) -> fexecv; } // namespace lfjail diff --git a/liblfjail/fd.cc b/liblfjail/fd.cc index 058a62d..df6119d 100644 --- a/liblfjail/fd.cc +++ b/liblfjail/fd.cc @@ -14,14 +14,14 @@ fd::fd(fd &&other) noexcept : _fd(std::exchange(other._fd, _invalid_fd)) {} -auto fd::operator=(this fd &self, fd &&other) noexcept -> fd & { - if (&self != &other) - self._fd = std::exchange(other._fd, _invalid_fd); - return self; +auto fd::operator=(fd &&other) noexcept -> fd & { + if (this != &other) + _fd = std::exchange(other._fd, _invalid_fd); + return *this; } fd::operator bool(this fd const &self) noexcept { - return self._fd != self._invalid_fd; + return self._fd != _invalid_fd; } fd::~fd() { @@ -40,10 +40,10 @@ auto fd::get(this fd const &self) -> int { return self._fd; } -auto fd::release(this fd &&self) -> int { - if (!self) +auto fd::release() && noexcept -> int { + if (!*this) std::abort(); - return std::exchange(self._fd, _invalid_fd); + return std::exchange(_fd, _invalid_fd); } // Create a copy of this fd by calling dup(). diff --git a/liblfjail/fd.hh b/liblfjail/fd.hh index 7437a24..f20acb8 100644 --- a/liblfjail/fd.hh +++ b/liblfjail/fd.hh @@ -27,7 +27,7 @@ struct fd final { // Move from another fd, leaving the moved-from fd in an invalid state. fd(fd &&other) noexcept; - auto operator=(this fd &self, fd &&other) noexcept -> fd &; + auto operator=(fd &&other) noexcept -> fd &; // Not copyable. fd(fd const &) = delete; @@ -44,7 +44,7 @@ struct fd final { // Release the stored fd and return it. The caller must close // the fd. - auto release(this fd &&self) -> int; + auto release() && noexcept -> int; private: static constexpr int _invalid_fd = -1; diff --git a/liblfjail/jail.cc b/liblfjail/jail.cc index 82bec5c..cf5d600 100644 --- a/liblfjail/jail.cc +++ b/liblfjail/jail.cc @@ -7,6 +7,7 @@ #include "generic_error.hh" #include "fileutils.hh" #include "jail_zfs.hh" +#include "spawn.hh" namespace { @@ -102,26 +103,18 @@ void jail_destroy(context const &ctx, jail const &jailconf) { zfs::destroy_for_jail(ctx, jailconf); } -void jail_install(context const &, jail const &/*jailconf*/) { - auto sout = std::string(); - auto serr = std::string(); - - throw generic_error("not implemented"); -#if 0 - int ret = lfjail::cexecl( - std::back_inserter(sout), - std::back_inserter(serr), - "/usr/sbin/pkg", +void jail_install(context const &, jail const &jailconf) { + auto executor = exec::execl("/usr/sbin/pkg", "pkg", "-r", jailconf.root_path, "install", "-y", "FreeBSD-runtime", "FreeBSD-utilities", "FreeBSD-periodic", "FreeBSD-rc", "FreeBSD-syslogd", "FreeBSD-newsyslog", "FreeBSD-pkg-bootstrap", "pkg"); - if (!serr.empty()) - throw generic_error("pkg install failed: {}", serr); - if (ret != 0) - throw generic_error("pkg install failed: {}", ret); -#endif + auto output = std::string(); + auto ret = spawn(std::move(executor), + capture(STDOUT_FILENO, output)).wait(); + if (!ret) + throw generic_error("pkg install failed"); } } // namespace lfjail diff --git a/liblfjail/spawn.hh b/liblfjail/spawn.hh index 606ccf9..affa035 100644 --- a/liblfjail/spawn.hh +++ b/liblfjail/spawn.hh @@ -164,11 +164,11 @@ private: } -auto capture(int fd, std::string &s) { +inline auto capture(int fd, std::string &s) { return detail::capture(fd, std::back_inserter(s)); } -auto capture(int fd, std::output_iterator<char> auto &&it) { +inline auto capture(int fd, std::output_iterator<char> auto &&it) { return detail::capture(fd, std::forward<decltype(it)>(it)); } diff --git a/liblfjail/split.hh b/liblfjail/split.hh deleted file mode 100644 index 419b479..0000000 --- a/liblfjail/split.hh +++ /dev/null @@ -1,64 +0,0 @@ -/* - * This source code is released into the public domain. - */ - -#ifndef LFJAIL_SPLIT_HH -#define LFJAIL_SPLIT_HH - -#include "generator.hh" - -namespace lfjail { - -/* - * split: split a range of items on a given predicate and return each element - * as a subrange. This is intended to be used with strings, but in theory it - * can accept any range. - * - * The input range is never copied, so the returned ranges reference the - * input range. - */ - -template<std::ranges::range Range, - std::indirect_unary_predicate<std::ranges::iterator_t<Range>> Pred> -auto split(Range &&range, Pred &&pred) - -> std::generator<decltype(std::ranges::subrange(range))> -{ - auto pos = std::ranges::begin(range); - auto end = std::ranges::end(range); - - for (;;) { - // Skip leading separators. - while (pos != end && pred(*pos)) - ++pos; - - if (pos == end) - co_return; - - auto const split_point = std::find_if(pos, end, pred); - - // Yield this value. - co_yield std::ranges::subrange(pos, split_point); - - pos = split_point; - } -} - -/* - * split_string: helper function to make split() a bit more useful for strings. - * Instead of returning subranges, it returns basic_string_views. - */ -auto split_string(std::ranges::contiguous_range auto &&string, auto pred) - -> std::generator< - std::basic_string_view< - std::ranges::range_value_t<decltype(string)>>> -{ - using sv_type = std::basic_string_view< - std::ranges::range_value_t<decltype(string)>>; - - for (auto const &&subrange : split(string, pred)) - co_yield sv_type(subrange); -} - -} // namespace lfjail - -#endif // !LFJAIL_SPLIT_HH diff --git a/liblfjail/zfs.cc b/liblfjail/zfs.cc index 5ecd826..bc0caee 100644 --- a/liblfjail/zfs.cc +++ b/liblfjail/zfs.cc @@ -28,12 +28,12 @@ namespace { constexpr std::string path_zpool = "/sbin/zpool"; constexpr std::string path_zfs = "/sbin/zfs"; -// Run a command (probably a zfs command), split its output into lines, -// and return each line. -// -// The spawn_how argument is the same as lfjail::spawn(). -auto spawn_lines(exec::executor auto &&executor) - -> std::generator<std::string_view> +/* + * Run a command and split each line of output into whitespace-separated + * columns. + */ +auto columns(exec::executor auto &&executor) + -> std::generator<std::vector<std::string_view>> { std::string output; @@ -43,17 +43,9 @@ auto spawn_lines(exec::executor auto &&executor) if (!result) throw zfs_error("failed to run zfs command"); - co_yield std::ranges::elements_of(words(output, '\n')); -} - -// Like spawn_lines, but each line is returned as a vector of words. -auto spawn_words(auto &&spawn_how) - -> std::generator<std::vector<std::string_view>> -{ - auto lines = spawn_lines(std::forward<decltype(spawn_how)>(spawn_how)); - - for (auto &&line : lines) + for (auto &&line : words(output, '\n')) { co_yield std::vector(std::from_range, words(line)); + } } // Run a command which produces two columns of output, assumed to be @@ -61,7 +53,7 @@ auto spawn_words(auto &&spawn_how) // each line. auto set_values(auto &&map, std::string command, auto &&...args) -> void { - auto lines = spawn_words( + auto lines = columns( exec::execl(std::move(command), std::move(args)...)); for (auto &&words : lines) { @@ -86,22 +78,22 @@ auto get_pool(std::string_view name) -> pool { std::pair{"name"sv, [&ret](auto &&v) { ret.name = v; }}, }; - set_values(handlers, path_zpool, "zpool", "get", - "-H", "-oproperty,value", "all", name); + set_values(handlers, path_zpool, + "zpool", "get", "-H", "-oproperty,value", "all", name); return ret; } auto get_pools() -> std::generator<pool> { - auto lines = spawn_words( - exec::execl(path_zpool, "zpool", "get", "-H", "-o", "name")); + auto lines = columns(exec::execl(path_zpool, + "zpool", "get", "-H", "-o", "name")); for (auto &&words : lines) co_yield get_pool(words[0]); } -auto get_filesystem(std::string_view name) -> filesystem { - auto ret = filesystem{}; +auto get_dataset(std::string_view name) -> dataset { + auto ret = dataset{}; auto handlers = std::unordered_map{ std::pair{"name"sv, [&ret](auto &&v) { ret.name = v; }}, @@ -113,12 +105,21 @@ auto get_filesystem(std::string_view name) -> filesystem { return ret; } -auto get_filesystems() -> std::generator<filesystem> { - auto lines = spawn_words( - exec::execl(path_zfs, "zfs", "get", "-H", "-o", "name")); +auto get_dataset_names() -> std::generator<std::string> { + auto lines = columns(exec::execl(path_zfs, + "zfs", "get", "-H", "-o", "name")); for (auto &&words : lines) - co_yield get_filesystem(words[0]); + co_yield std::string(words[0]); +} + +auto get_datasets() -> std::generator<dataset> { + for (auto &&dataset : get_dataset_names()) + co_yield get_dataset(dataset); +} + +auto dataset_exists(std::string name) -> bool { + return std::ranges::contains(get_dataset_names(), name); } } // namespace lfjail::zfs diff --git a/liblfjail/zfs.hh b/liblfjail/zfs.hh index 30bd457..915e042 100644 --- a/liblfjail/zfs.hh +++ b/liblfjail/zfs.hh @@ -34,18 +34,24 @@ auto get_pool(std::string_view name) -> pool; auto get_pools() -> std::generator<pool>; /* - * Filesystems. + * Datasets. */ -struct filesystem { +struct dataset { std::string name; }; -/* Fetch details for a specific filesystem by name. */ -auto get_filesystem(std::string_view name) -> filesystem; +/* Return true if a dataset by this name exists. */ +auto dataset_exists(std::string_view name) -> bool; -/* Fetch details for all filesystems on the system. */ -auto get_filesystems() -> std::generator<filesystem>; +/* Fetch details for a specific dataset by name. */ +auto get_dataset(std::string_view name) -> dataset; + +/* Fetch names for all datasets on the system. */ +auto get_dataset_names() -> std::generator<std::string>; + +/* Fetch details for all datasets on the system. */ +auto get_datasets() -> std::generator<dataset>; } // namespace lfjail::zfs |
