aboutsummaryrefslogtreecommitdiffstats
path: root/liblfjail/jail_zfs.cc
blob: b8d58cccdaa427a88dda600b8f7606d692e06008 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/*
 * This source code is released into the public domain.
 */

/*
 * ZFS handling.
 */

#include "config_string.hh"
#include "exec.hh"
#include "generic_error.hh"
#include "jail_zfs.hh"

using namespace lfjail;
using namespace std::literals;

namespace lfjail::zfs {

config::string_option filesystem(
	"zfs.filesystem"sv,
	"The ZFS filesystem under which jails are created"sv);

config::string_option mountpoint(
	"zfs.mountpoint"sv,
	"The location where the ZFS hierarchy will be mounted"sv);

} // namespace lfjail::zfs

namespace {

/*
 * Test if the given ZFS dataset exists.
 */
auto dataset_exists(std::string const &/*ds*/) -> bool {
	throw("not implemented");
#if 0
	auto sout = std::string();
	auto serr = std::string();

	auto const ret = lfjail::cexecl(
		std::back_inserter(sout),
		std::back_inserter(serr),
		"/sbin/zfs",
		"zfs", "get", "-H", "-ovalue", "name", ds);

	return (ret == 0);
#endif
}

/*
 * Create a new ZFS dataset.
 */
template<typename... Args>
void dataset_create(std::string const &/*ds*/, Args&& .../*args*/) {
	throw("not implemented");
#if 0
	std::vector<std::string> argv;
	argv.emplace_back("zfs");
	argv.emplace_back("create");
	(argv.emplace_back(std::format("-o{}", std::forward<Args>(args))), ...);
	argv.emplace_back(ds);

	auto sout = std::string();
	auto serr = std::string();

	auto const ret = lfjail::cexec(std::back_inserter(sout),
				       std::back_inserter(serr),
				       "/sbin/zfs", argv);

	if (!serr.empty())
		throw generic_error("zfs create failed: {}", serr);
	if (ret != 0)
		throw generic_error("zfs create failed: {}", ret);
#endif
}

/*
 * Destroy a ZFS datset.
 */
void dataset_destroy(std::string const &/*ds*/) {
	throw("not implemented");
#if 0
	auto sout = std::string();
	auto serr = std::string();

	int ret = lfjail::cexecl(std::back_inserter(sout),
				 std::back_inserter(serr),
				 "/sbin/zfs",
				 "zfs", "destroy", "-r", ds);

	if (!serr.empty())
		throw generic_error("zfs destroy failed: {}", serr);
	if (ret != 0)
		throw generic_error("zfs destroy failed: {}", ret);
#endif
}

/*
 * Return a ZFS properly for a fileystem.
 */
auto get_property(std::string const &/*fs*/, std::string const &/*prop*/)
	-> std::string
{
	throw("not implemented");
#if 0
	auto sout = std::string();
	auto serr = std::string();

	int ret = lfjail::cexecl(
		std::back_inserter(sout),
		std::back_inserter(serr),
		"/sbin/zfs",
		"zfs", "get", "-H", "-ovalue", prop, fs);

	if (!serr.empty())
		throw generic_error("zfs get failed: {}", serr);
	if (ret != 0)
		throw generic_error("zfs get failed: {}", ret);
	if (sout[sout.size() - 1] == '\n')
		sout.resize(sout.size() - 1);
	return sout;
#endif
}

/*
 * Make sure our top-level ZFS dataset exists.
 */
void ensure_jroot(context const &) {
	auto jroot = lfjail::zfs::filesystem.string();
	auto mntpt = lfjail::zfs::mountpoint.string();

	if (dataset_exists(jroot))
		return;

	auto mntptopt = std::format("mountpoint={}", mntpt);
	dataset_create(jroot, mntptopt);
}

} // anonymous namespace

namespace lfjail::zfs {

void create_for_jail(context const &ctx, jail const &jailconf) {
	if (filesystem.string().empty())
		throw generic_error("zfs.filesystem is not set");

	if (mountpoint.string().empty())
		throw generic_error("zfs.mountpoint is not set");

	ensure_jroot(ctx);

	auto const ds = filesystem.string() + "/" + jailconf.name;
	dataset_create(ds);
}

void destroy_for_jail(context const &, jail const &jailconf) {
	auto const dataset = filesystem.string() + "/" + jailconf.name;
	dataset_destroy(dataset);
}

auto jail_root(context const &ctx) -> std::string {
	std::ignore = ctx;

	auto fs = filesystem.string();
	if (fs.empty())
		throw generic_error("zfs.filesystem not set");

	return get_property(fs, "mountpoing");
}

} // namespace lfjail::zfs