1*b0d29bc4SBrooks Davis // Copyright 2010 The Kyua Authors.
2*b0d29bc4SBrooks Davis // All rights reserved.
3*b0d29bc4SBrooks Davis //
4*b0d29bc4SBrooks Davis // Redistribution and use in source and binary forms, with or without
5*b0d29bc4SBrooks Davis // modification, are permitted provided that the following conditions are
6*b0d29bc4SBrooks Davis // met:
7*b0d29bc4SBrooks Davis //
8*b0d29bc4SBrooks Davis // * Redistributions of source code must retain the above copyright
9*b0d29bc4SBrooks Davis // notice, this list of conditions and the following disclaimer.
10*b0d29bc4SBrooks Davis // * Redistributions in binary form must reproduce the above copyright
11*b0d29bc4SBrooks Davis // notice, this list of conditions and the following disclaimer in the
12*b0d29bc4SBrooks Davis // documentation and/or other materials provided with the distribution.
13*b0d29bc4SBrooks Davis // * Neither the name of Google Inc. nor the names of its contributors
14*b0d29bc4SBrooks Davis // may be used to endorse or promote products derived from this software
15*b0d29bc4SBrooks Davis // without specific prior written permission.
16*b0d29bc4SBrooks Davis //
17*b0d29bc4SBrooks Davis // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*b0d29bc4SBrooks Davis // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*b0d29bc4SBrooks Davis // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*b0d29bc4SBrooks Davis // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*b0d29bc4SBrooks Davis // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*b0d29bc4SBrooks Davis // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*b0d29bc4SBrooks Davis // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*b0d29bc4SBrooks Davis // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*b0d29bc4SBrooks Davis // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*b0d29bc4SBrooks Davis // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*b0d29bc4SBrooks Davis // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*b0d29bc4SBrooks Davis
29*b0d29bc4SBrooks Davis #include "utils/fs/operations.hpp"
30*b0d29bc4SBrooks Davis
31*b0d29bc4SBrooks Davis extern "C" {
32*b0d29bc4SBrooks Davis #include <sys/types.h>
33*b0d29bc4SBrooks Davis #include <sys/stat.h>
34*b0d29bc4SBrooks Davis #include <sys/wait.h>
35*b0d29bc4SBrooks Davis
36*b0d29bc4SBrooks Davis #include <dirent.h>
37*b0d29bc4SBrooks Davis #include <signal.h>
38*b0d29bc4SBrooks Davis #include <unistd.h>
39*b0d29bc4SBrooks Davis }
40*b0d29bc4SBrooks Davis
41*b0d29bc4SBrooks Davis #include <cerrno>
42*b0d29bc4SBrooks Davis #include <cstdlib>
43*b0d29bc4SBrooks Davis #include <cstring>
44*b0d29bc4SBrooks Davis #include <iostream>
45*b0d29bc4SBrooks Davis #include <stdexcept>
46*b0d29bc4SBrooks Davis #include <string>
47*b0d29bc4SBrooks Davis #include <vector>
48*b0d29bc4SBrooks Davis
49*b0d29bc4SBrooks Davis #include <atf-c++.hpp>
50*b0d29bc4SBrooks Davis
51*b0d29bc4SBrooks Davis #include "utils/env.hpp"
52*b0d29bc4SBrooks Davis #include "utils/format/containers.ipp"
53*b0d29bc4SBrooks Davis #include "utils/format/macros.hpp"
54*b0d29bc4SBrooks Davis #include "utils/fs/directory.hpp"
55*b0d29bc4SBrooks Davis #include "utils/fs/exceptions.hpp"
56*b0d29bc4SBrooks Davis #include "utils/fs/path.hpp"
57*b0d29bc4SBrooks Davis #include "utils/optional.ipp"
58*b0d29bc4SBrooks Davis #include "utils/passwd.hpp"
59*b0d29bc4SBrooks Davis #include "utils/stream.hpp"
60*b0d29bc4SBrooks Davis #include "utils/units.hpp"
61*b0d29bc4SBrooks Davis
62*b0d29bc4SBrooks Davis namespace fs = utils::fs;
63*b0d29bc4SBrooks Davis namespace passwd = utils::passwd;
64*b0d29bc4SBrooks Davis namespace units = utils::units;
65*b0d29bc4SBrooks Davis
66*b0d29bc4SBrooks Davis using utils::optional;
67*b0d29bc4SBrooks Davis
68*b0d29bc4SBrooks Davis
69*b0d29bc4SBrooks Davis namespace {
70*b0d29bc4SBrooks Davis
71*b0d29bc4SBrooks Davis
72*b0d29bc4SBrooks Davis /// Checks if a directory entry exists and matches a specific type.
73*b0d29bc4SBrooks Davis ///
74*b0d29bc4SBrooks Davis /// \param dir The directory in which to look for the entry.
75*b0d29bc4SBrooks Davis /// \param name The name of the entry to look up.
76*b0d29bc4SBrooks Davis /// \param expected_type The expected type of the file as given by dir(5).
77*b0d29bc4SBrooks Davis ///
78*b0d29bc4SBrooks Davis /// \return True if the entry exists and matches the given type; false
79*b0d29bc4SBrooks Davis /// otherwise.
80*b0d29bc4SBrooks Davis static bool
lookup(const char * dir,const char * name,const unsigned int expected_type)81*b0d29bc4SBrooks Davis lookup(const char* dir, const char* name, const unsigned int expected_type)
82*b0d29bc4SBrooks Davis {
83*b0d29bc4SBrooks Davis DIR* dirp = ::opendir(dir);
84*b0d29bc4SBrooks Davis ATF_REQUIRE(dirp != NULL);
85*b0d29bc4SBrooks Davis
86*b0d29bc4SBrooks Davis bool found = false;
87*b0d29bc4SBrooks Davis struct dirent* dp;
88*b0d29bc4SBrooks Davis while (!found && (dp = readdir(dirp)) != NULL) {
89*b0d29bc4SBrooks Davis if (std::strcmp(dp->d_name, name) == 0) {
90*b0d29bc4SBrooks Davis struct ::stat s;
91*b0d29bc4SBrooks Davis const fs::path lookup_path = fs::path(dir) / name;
92*b0d29bc4SBrooks Davis ATF_REQUIRE(::stat(lookup_path.c_str(), &s) != -1);
93*b0d29bc4SBrooks Davis if ((s.st_mode & S_IFMT) == expected_type) {
94*b0d29bc4SBrooks Davis found = true;
95*b0d29bc4SBrooks Davis }
96*b0d29bc4SBrooks Davis }
97*b0d29bc4SBrooks Davis }
98*b0d29bc4SBrooks Davis ::closedir(dirp);
99*b0d29bc4SBrooks Davis return found;
100*b0d29bc4SBrooks Davis }
101*b0d29bc4SBrooks Davis
102*b0d29bc4SBrooks Davis
103*b0d29bc4SBrooks Davis } // anonymous namespace
104*b0d29bc4SBrooks Davis
105*b0d29bc4SBrooks Davis
106*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(copy__ok);
ATF_TEST_CASE_BODY(copy__ok)107*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(copy__ok)
108*b0d29bc4SBrooks Davis {
109*b0d29bc4SBrooks Davis const fs::path source("f1.txt");
110*b0d29bc4SBrooks Davis const fs::path target("f2.txt");
111*b0d29bc4SBrooks Davis
112*b0d29bc4SBrooks Davis atf::utils::create_file(source.str(), "This is the input");
113*b0d29bc4SBrooks Davis fs::copy(source, target);
114*b0d29bc4SBrooks Davis ATF_REQUIRE(atf::utils::compare_file(target.str(), "This is the input"));
115*b0d29bc4SBrooks Davis }
116*b0d29bc4SBrooks Davis
117*b0d29bc4SBrooks Davis
118*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(copy__fail_open);
ATF_TEST_CASE_BODY(copy__fail_open)119*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(copy__fail_open)
120*b0d29bc4SBrooks Davis {
121*b0d29bc4SBrooks Davis const fs::path source("f1.txt");
122*b0d29bc4SBrooks Davis const fs::path target("f2.txt");
123*b0d29bc4SBrooks Davis
124*b0d29bc4SBrooks Davis ATF_REQUIRE_THROW_RE(fs::error, "Cannot open copy source f1.txt",
125*b0d29bc4SBrooks Davis fs::copy(source, target));
126*b0d29bc4SBrooks Davis }
127*b0d29bc4SBrooks Davis
128*b0d29bc4SBrooks Davis
129*b0d29bc4SBrooks Davis ATF_TEST_CASE(copy__fail_create);
ATF_TEST_CASE_HEAD(copy__fail_create)130*b0d29bc4SBrooks Davis ATF_TEST_CASE_HEAD(copy__fail_create)
131*b0d29bc4SBrooks Davis {
132*b0d29bc4SBrooks Davis set_md_var("require.user", "unprivileged");
133*b0d29bc4SBrooks Davis }
ATF_TEST_CASE_BODY(copy__fail_create)134*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(copy__fail_create)
135*b0d29bc4SBrooks Davis {
136*b0d29bc4SBrooks Davis const fs::path source("f1.txt");
137*b0d29bc4SBrooks Davis const fs::path target("f2.txt");
138*b0d29bc4SBrooks Davis
139*b0d29bc4SBrooks Davis atf::utils::create_file(target.str(), "Do not override");
140*b0d29bc4SBrooks Davis ATF_REQUIRE(::chmod(target.c_str(), 0444) != -1);
141*b0d29bc4SBrooks Davis
142*b0d29bc4SBrooks Davis atf::utils::create_file(source.str(), "This is the input");
143*b0d29bc4SBrooks Davis ATF_REQUIRE_THROW_RE(fs::error, "Cannot create copy target f2.txt",
144*b0d29bc4SBrooks Davis fs::copy(source, target));
145*b0d29bc4SBrooks Davis }
146*b0d29bc4SBrooks Davis
147*b0d29bc4SBrooks Davis
148*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(current_path__ok);
ATF_TEST_CASE_BODY(current_path__ok)149*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(current_path__ok)
150*b0d29bc4SBrooks Davis {
151*b0d29bc4SBrooks Davis const fs::path previous = fs::current_path();
152*b0d29bc4SBrooks Davis fs::mkdir(fs::path("root"), 0755);
153*b0d29bc4SBrooks Davis ATF_REQUIRE(::chdir("root") != -1);
154*b0d29bc4SBrooks Davis const fs::path cwd = fs::current_path();
155*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(cwd.str().length() - 5, cwd.str().find("/root"));
156*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(previous / "root", cwd);
157*b0d29bc4SBrooks Davis }
158*b0d29bc4SBrooks Davis
159*b0d29bc4SBrooks Davis
160*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(current_path__enoent);
ATF_TEST_CASE_BODY(current_path__enoent)161*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(current_path__enoent)
162*b0d29bc4SBrooks Davis {
163*b0d29bc4SBrooks Davis const fs::path previous = fs::current_path();
164*b0d29bc4SBrooks Davis fs::mkdir(fs::path("root"), 0755);
165*b0d29bc4SBrooks Davis ATF_REQUIRE(::chdir("root") != -1);
166*b0d29bc4SBrooks Davis ATF_REQUIRE(::rmdir("../root") != -1);
167*b0d29bc4SBrooks Davis try {
168*b0d29bc4SBrooks Davis (void)fs::current_path();
169*b0d29bc4SBrooks Davis fail("system_errpr not raised");
170*b0d29bc4SBrooks Davis } catch (const fs::system_error& e) {
171*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(ENOENT, e.original_errno());
172*b0d29bc4SBrooks Davis }
173*b0d29bc4SBrooks Davis }
174*b0d29bc4SBrooks Davis
175*b0d29bc4SBrooks Davis
176*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(exists);
ATF_TEST_CASE_BODY(exists)177*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(exists)
178*b0d29bc4SBrooks Davis {
179*b0d29bc4SBrooks Davis const fs::path dir("dir");
180*b0d29bc4SBrooks Davis ATF_REQUIRE(!fs::exists(dir));
181*b0d29bc4SBrooks Davis fs::mkdir(dir, 0755);
182*b0d29bc4SBrooks Davis ATF_REQUIRE(fs::exists(dir));
183*b0d29bc4SBrooks Davis }
184*b0d29bc4SBrooks Davis
185*b0d29bc4SBrooks Davis
186*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(find_in_path__no_path);
ATF_TEST_CASE_BODY(find_in_path__no_path)187*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(find_in_path__no_path)
188*b0d29bc4SBrooks Davis {
189*b0d29bc4SBrooks Davis utils::unsetenv("PATH");
190*b0d29bc4SBrooks Davis ATF_REQUIRE(!fs::find_in_path("ls"));
191*b0d29bc4SBrooks Davis atf::utils::create_file("ls", "");
192*b0d29bc4SBrooks Davis ATF_REQUIRE(!fs::find_in_path("ls"));
193*b0d29bc4SBrooks Davis }
194*b0d29bc4SBrooks Davis
195*b0d29bc4SBrooks Davis
196*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(find_in_path__empty_path);
ATF_TEST_CASE_BODY(find_in_path__empty_path)197*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(find_in_path__empty_path)
198*b0d29bc4SBrooks Davis {
199*b0d29bc4SBrooks Davis utils::setenv("PATH", "");
200*b0d29bc4SBrooks Davis ATF_REQUIRE(!fs::find_in_path("ls"));
201*b0d29bc4SBrooks Davis atf::utils::create_file("ls", "");
202*b0d29bc4SBrooks Davis ATF_REQUIRE(!fs::find_in_path("ls"));
203*b0d29bc4SBrooks Davis }
204*b0d29bc4SBrooks Davis
205*b0d29bc4SBrooks Davis
206*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(find_in_path__one_component);
ATF_TEST_CASE_BODY(find_in_path__one_component)207*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(find_in_path__one_component)
208*b0d29bc4SBrooks Davis {
209*b0d29bc4SBrooks Davis const fs::path dir = fs::current_path() / "bin";
210*b0d29bc4SBrooks Davis fs::mkdir(dir, 0755);
211*b0d29bc4SBrooks Davis utils::setenv("PATH", dir.str());
212*b0d29bc4SBrooks Davis
213*b0d29bc4SBrooks Davis ATF_REQUIRE(!fs::find_in_path("ls"));
214*b0d29bc4SBrooks Davis atf::utils::create_file((dir / "ls").str(), "");
215*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(dir / "ls", fs::find_in_path("ls").get());
216*b0d29bc4SBrooks Davis }
217*b0d29bc4SBrooks Davis
218*b0d29bc4SBrooks Davis
219*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(find_in_path__many_components);
ATF_TEST_CASE_BODY(find_in_path__many_components)220*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(find_in_path__many_components)
221*b0d29bc4SBrooks Davis {
222*b0d29bc4SBrooks Davis const fs::path dir1 = fs::current_path() / "dir1";
223*b0d29bc4SBrooks Davis const fs::path dir2 = fs::current_path() / "dir2";
224*b0d29bc4SBrooks Davis fs::mkdir(dir1, 0755);
225*b0d29bc4SBrooks Davis fs::mkdir(dir2, 0755);
226*b0d29bc4SBrooks Davis utils::setenv("PATH", dir1.str() + ":" + dir2.str());
227*b0d29bc4SBrooks Davis
228*b0d29bc4SBrooks Davis ATF_REQUIRE(!fs::find_in_path("ls"));
229*b0d29bc4SBrooks Davis atf::utils::create_file((dir2 / "ls").str(), "");
230*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(dir2 / "ls", fs::find_in_path("ls").get());
231*b0d29bc4SBrooks Davis atf::utils::create_file((dir1 / "ls").str(), "");
232*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(dir1 / "ls", fs::find_in_path("ls").get());
233*b0d29bc4SBrooks Davis }
234*b0d29bc4SBrooks Davis
235*b0d29bc4SBrooks Davis
236*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(find_in_path__current_directory);
ATF_TEST_CASE_BODY(find_in_path__current_directory)237*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(find_in_path__current_directory)
238*b0d29bc4SBrooks Davis {
239*b0d29bc4SBrooks Davis utils::setenv("PATH", "bin:");
240*b0d29bc4SBrooks Davis
241*b0d29bc4SBrooks Davis ATF_REQUIRE(!fs::find_in_path("foo-bar"));
242*b0d29bc4SBrooks Davis atf::utils::create_file("foo-bar", "");
243*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(fs::path("foo-bar").to_absolute(),
244*b0d29bc4SBrooks Davis fs::find_in_path("foo-bar").get());
245*b0d29bc4SBrooks Davis }
246*b0d29bc4SBrooks Davis
247*b0d29bc4SBrooks Davis
248*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(find_in_path__always_absolute);
ATF_TEST_CASE_BODY(find_in_path__always_absolute)249*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(find_in_path__always_absolute)
250*b0d29bc4SBrooks Davis {
251*b0d29bc4SBrooks Davis fs::mkdir(fs::path("my-bin"), 0755);
252*b0d29bc4SBrooks Davis utils::setenv("PATH", "my-bin");
253*b0d29bc4SBrooks Davis
254*b0d29bc4SBrooks Davis ATF_REQUIRE(!fs::find_in_path("abcd"));
255*b0d29bc4SBrooks Davis atf::utils::create_file("my-bin/abcd", "");
256*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(fs::path("my-bin/abcd").to_absolute(),
257*b0d29bc4SBrooks Davis fs::find_in_path("abcd").get());
258*b0d29bc4SBrooks Davis }
259*b0d29bc4SBrooks Davis
260*b0d29bc4SBrooks Davis
261*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(free_disk_space__ok__smoke);
ATF_TEST_CASE_BODY(free_disk_space__ok__smoke)262*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(free_disk_space__ok__smoke)
263*b0d29bc4SBrooks Davis {
264*b0d29bc4SBrooks Davis const units::bytes space = fs::free_disk_space(fs::path("."));
265*b0d29bc4SBrooks Davis ATF_REQUIRE(space > units::MB); // Simple test that should always pass.
266*b0d29bc4SBrooks Davis }
267*b0d29bc4SBrooks Davis
268*b0d29bc4SBrooks Davis
269*b0d29bc4SBrooks Davis /// Unmounts a directory without raising errors.
270*b0d29bc4SBrooks Davis ///
271*b0d29bc4SBrooks Davis /// \param cookie Name of a file that exists while the mount point is still
272*b0d29bc4SBrooks Davis /// mounted. Used to prevent a double-unmount, which would print a
273*b0d29bc4SBrooks Davis /// misleading error message.
274*b0d29bc4SBrooks Davis /// \param mount_point Path to the mount point to unmount.
275*b0d29bc4SBrooks Davis static void
cleanup_mount_point(const fs::path & cookie,const fs::path & mount_point)276*b0d29bc4SBrooks Davis cleanup_mount_point(const fs::path& cookie, const fs::path& mount_point)
277*b0d29bc4SBrooks Davis {
278*b0d29bc4SBrooks Davis try {
279*b0d29bc4SBrooks Davis if (fs::exists(cookie)) {
280*b0d29bc4SBrooks Davis fs::unmount(mount_point);
281*b0d29bc4SBrooks Davis }
282*b0d29bc4SBrooks Davis } catch (const std::runtime_error& e) {
283*b0d29bc4SBrooks Davis std::cerr << "Failed trying to unmount " + mount_point.str() +
284*b0d29bc4SBrooks Davis " during cleanup: " << e.what() << '\n';
285*b0d29bc4SBrooks Davis }
286*b0d29bc4SBrooks Davis }
287*b0d29bc4SBrooks Davis
288*b0d29bc4SBrooks Davis
289*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITH_CLEANUP(free_disk_space__ok__real);
ATF_TEST_CASE_HEAD(free_disk_space__ok__real)290*b0d29bc4SBrooks Davis ATF_TEST_CASE_HEAD(free_disk_space__ok__real)
291*b0d29bc4SBrooks Davis {
292*b0d29bc4SBrooks Davis set_md_var("require.user", "root");
293*b0d29bc4SBrooks Davis }
ATF_TEST_CASE_BODY(free_disk_space__ok__real)294*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(free_disk_space__ok__real)
295*b0d29bc4SBrooks Davis {
296*b0d29bc4SBrooks Davis try {
297*b0d29bc4SBrooks Davis const fs::path mount_point("mount_point");
298*b0d29bc4SBrooks Davis fs::mkdir(mount_point, 0755);
299*b0d29bc4SBrooks Davis fs::mount_tmpfs(mount_point, units::bytes(32 * units::MB));
300*b0d29bc4SBrooks Davis atf::utils::create_file("mounted", "");
301*b0d29bc4SBrooks Davis const units::bytes space = fs::free_disk_space(fs::path(mount_point));
302*b0d29bc4SBrooks Davis fs::unmount(mount_point);
303*b0d29bc4SBrooks Davis fs::unlink(fs::path("mounted"));
304*b0d29bc4SBrooks Davis ATF_REQUIRE(space < 35 * units::MB);
305*b0d29bc4SBrooks Davis ATF_REQUIRE(space > 28 * units::MB);
306*b0d29bc4SBrooks Davis } catch (const fs::unsupported_operation_error& e) {
307*b0d29bc4SBrooks Davis ATF_SKIP(e.what());
308*b0d29bc4SBrooks Davis }
309*b0d29bc4SBrooks Davis }
ATF_TEST_CASE_CLEANUP(free_disk_space__ok__real)310*b0d29bc4SBrooks Davis ATF_TEST_CASE_CLEANUP(free_disk_space__ok__real)
311*b0d29bc4SBrooks Davis {
312*b0d29bc4SBrooks Davis cleanup_mount_point(fs::path("mounted"), fs::path("mount_point"));
313*b0d29bc4SBrooks Davis }
314*b0d29bc4SBrooks Davis
315*b0d29bc4SBrooks Davis
316*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(free_disk_space__fail);
ATF_TEST_CASE_BODY(free_disk_space__fail)317*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(free_disk_space__fail)
318*b0d29bc4SBrooks Davis {
319*b0d29bc4SBrooks Davis ATF_REQUIRE_THROW_RE(fs::error, "Failed to stat file system for missing",
320*b0d29bc4SBrooks Davis fs::free_disk_space(fs::path("missing")));
321*b0d29bc4SBrooks Davis }
322*b0d29bc4SBrooks Davis
323*b0d29bc4SBrooks Davis
324*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(is_directory__ok);
ATF_TEST_CASE_BODY(is_directory__ok)325*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(is_directory__ok)
326*b0d29bc4SBrooks Davis {
327*b0d29bc4SBrooks Davis const fs::path file("file");
328*b0d29bc4SBrooks Davis atf::utils::create_file(file.str(), "");
329*b0d29bc4SBrooks Davis ATF_REQUIRE(!fs::is_directory(file));
330*b0d29bc4SBrooks Davis
331*b0d29bc4SBrooks Davis const fs::path dir("dir");
332*b0d29bc4SBrooks Davis fs::mkdir(dir, 0755);
333*b0d29bc4SBrooks Davis ATF_REQUIRE(fs::is_directory(dir));
334*b0d29bc4SBrooks Davis }
335*b0d29bc4SBrooks Davis
336*b0d29bc4SBrooks Davis
337*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITH_CLEANUP(is_directory__fail);
ATF_TEST_CASE_HEAD(is_directory__fail)338*b0d29bc4SBrooks Davis ATF_TEST_CASE_HEAD(is_directory__fail)
339*b0d29bc4SBrooks Davis {
340*b0d29bc4SBrooks Davis set_md_var("require.user", "unprivileged");
341*b0d29bc4SBrooks Davis }
ATF_TEST_CASE_BODY(is_directory__fail)342*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(is_directory__fail)
343*b0d29bc4SBrooks Davis {
344*b0d29bc4SBrooks Davis fs::mkdir(fs::path("dir"), 0000);
345*b0d29bc4SBrooks Davis ATF_REQUIRE_THROW(fs::error, fs::is_directory(fs::path("dir/foo")));
346*b0d29bc4SBrooks Davis }
ATF_TEST_CASE_CLEANUP(is_directory__fail)347*b0d29bc4SBrooks Davis ATF_TEST_CASE_CLEANUP(is_directory__fail)
348*b0d29bc4SBrooks Davis {
349*b0d29bc4SBrooks Davis if (::chmod("dir", 0755) == -1) {
350*b0d29bc4SBrooks Davis // If we cannot restore the original permissions, we cannot do much
351*b0d29bc4SBrooks Davis // more. However, leaving an unwritable directory behind will cause the
352*b0d29bc4SBrooks Davis // runtime engine to report us as broken.
353*b0d29bc4SBrooks Davis }
354*b0d29bc4SBrooks Davis }
355*b0d29bc4SBrooks Davis
356*b0d29bc4SBrooks Davis
357*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(mkdir__ok);
ATF_TEST_CASE_BODY(mkdir__ok)358*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(mkdir__ok)
359*b0d29bc4SBrooks Davis {
360*b0d29bc4SBrooks Davis fs::mkdir(fs::path("dir"), 0755);
361*b0d29bc4SBrooks Davis ATF_REQUIRE(lookup(".", "dir", S_IFDIR));
362*b0d29bc4SBrooks Davis }
363*b0d29bc4SBrooks Davis
364*b0d29bc4SBrooks Davis
365*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(mkdir__enoent);
ATF_TEST_CASE_BODY(mkdir__enoent)366*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(mkdir__enoent)
367*b0d29bc4SBrooks Davis {
368*b0d29bc4SBrooks Davis try {
369*b0d29bc4SBrooks Davis fs::mkdir(fs::path("dir1/dir2"), 0755);
370*b0d29bc4SBrooks Davis fail("system_error not raised");
371*b0d29bc4SBrooks Davis } catch (const fs::system_error& e) {
372*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(ENOENT, e.original_errno());
373*b0d29bc4SBrooks Davis }
374*b0d29bc4SBrooks Davis ATF_REQUIRE(!lookup(".", "dir1", S_IFDIR));
375*b0d29bc4SBrooks Davis ATF_REQUIRE(!lookup(".", "dir2", S_IFDIR));
376*b0d29bc4SBrooks Davis }
377*b0d29bc4SBrooks Davis
378*b0d29bc4SBrooks Davis
379*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(mkdir_p__one_component);
ATF_TEST_CASE_BODY(mkdir_p__one_component)380*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(mkdir_p__one_component)
381*b0d29bc4SBrooks Davis {
382*b0d29bc4SBrooks Davis ATF_REQUIRE(!lookup(".", "new-dir", S_IFDIR));
383*b0d29bc4SBrooks Davis fs::mkdir_p(fs::path("new-dir"), 0755);
384*b0d29bc4SBrooks Davis ATF_REQUIRE(lookup(".", "new-dir", S_IFDIR));
385*b0d29bc4SBrooks Davis }
386*b0d29bc4SBrooks Davis
387*b0d29bc4SBrooks Davis
388*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(mkdir_p__many_components);
ATF_TEST_CASE_BODY(mkdir_p__many_components)389*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(mkdir_p__many_components)
390*b0d29bc4SBrooks Davis {
391*b0d29bc4SBrooks Davis ATF_REQUIRE(!lookup(".", "a", S_IFDIR));
392*b0d29bc4SBrooks Davis fs::mkdir_p(fs::path("a/b/c"), 0755);
393*b0d29bc4SBrooks Davis ATF_REQUIRE(lookup(".", "a", S_IFDIR));
394*b0d29bc4SBrooks Davis ATF_REQUIRE(lookup("a", "b", S_IFDIR));
395*b0d29bc4SBrooks Davis ATF_REQUIRE(lookup("a/b", "c", S_IFDIR));
396*b0d29bc4SBrooks Davis }
397*b0d29bc4SBrooks Davis
398*b0d29bc4SBrooks Davis
399*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(mkdir_p__already_exists);
ATF_TEST_CASE_BODY(mkdir_p__already_exists)400*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(mkdir_p__already_exists)
401*b0d29bc4SBrooks Davis {
402*b0d29bc4SBrooks Davis fs::mkdir(fs::path("a"), 0755);
403*b0d29bc4SBrooks Davis fs::mkdir(fs::path("a/b"), 0755);
404*b0d29bc4SBrooks Davis fs::mkdir_p(fs::path("a/b"), 0755);
405*b0d29bc4SBrooks Davis }
406*b0d29bc4SBrooks Davis
407*b0d29bc4SBrooks Davis
408*b0d29bc4SBrooks Davis ATF_TEST_CASE(mkdir_p__eacces)
ATF_TEST_CASE_HEAD(mkdir_p__eacces)409*b0d29bc4SBrooks Davis ATF_TEST_CASE_HEAD(mkdir_p__eacces)
410*b0d29bc4SBrooks Davis {
411*b0d29bc4SBrooks Davis set_md_var("require.user", "unprivileged");
412*b0d29bc4SBrooks Davis }
ATF_TEST_CASE_BODY(mkdir_p__eacces)413*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(mkdir_p__eacces)
414*b0d29bc4SBrooks Davis {
415*b0d29bc4SBrooks Davis fs::mkdir(fs::path("a"), 0755);
416*b0d29bc4SBrooks Davis fs::mkdir(fs::path("a/b"), 0755);
417*b0d29bc4SBrooks Davis ATF_REQUIRE(::chmod("a/b", 0555) != -1);
418*b0d29bc4SBrooks Davis try {
419*b0d29bc4SBrooks Davis fs::mkdir_p(fs::path("a/b/c/d"), 0755);
420*b0d29bc4SBrooks Davis fail("system_error not raised");
421*b0d29bc4SBrooks Davis } catch (const fs::system_error& e) {
422*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(EACCES, e.original_errno());
423*b0d29bc4SBrooks Davis }
424*b0d29bc4SBrooks Davis ATF_REQUIRE(lookup(".", "a", S_IFDIR));
425*b0d29bc4SBrooks Davis ATF_REQUIRE(lookup("a", "b", S_IFDIR));
426*b0d29bc4SBrooks Davis ATF_REQUIRE(!lookup(".", "c", S_IFDIR));
427*b0d29bc4SBrooks Davis ATF_REQUIRE(!lookup("a", "c", S_IFDIR));
428*b0d29bc4SBrooks Davis ATF_REQUIRE(!lookup("a/b", "c", S_IFDIR));
429*b0d29bc4SBrooks Davis }
430*b0d29bc4SBrooks Davis
431*b0d29bc4SBrooks Davis
432*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(mkdtemp_public)
ATF_TEST_CASE_BODY(mkdtemp_public)433*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(mkdtemp_public)
434*b0d29bc4SBrooks Davis {
435*b0d29bc4SBrooks Davis const fs::path tmpdir = fs::current_path() / "tmp";
436*b0d29bc4SBrooks Davis utils::setenv("TMPDIR", tmpdir.str());
437*b0d29bc4SBrooks Davis fs::mkdir(tmpdir, 0755);
438*b0d29bc4SBrooks Davis
439*b0d29bc4SBrooks Davis const std::string dir_template("tempdir.XXXXXX");
440*b0d29bc4SBrooks Davis const fs::path tempdir = fs::mkdtemp_public(dir_template);
441*b0d29bc4SBrooks Davis ATF_REQUIRE(!lookup("tmp", dir_template.c_str(), S_IFDIR));
442*b0d29bc4SBrooks Davis ATF_REQUIRE(lookup("tmp", tempdir.leaf_name().c_str(), S_IFDIR));
443*b0d29bc4SBrooks Davis }
444*b0d29bc4SBrooks Davis
445*b0d29bc4SBrooks Davis
446*b0d29bc4SBrooks Davis ATF_TEST_CASE(mkdtemp_public__getcwd_as_non_root)
ATF_TEST_CASE_HEAD(mkdtemp_public__getcwd_as_non_root)447*b0d29bc4SBrooks Davis ATF_TEST_CASE_HEAD(mkdtemp_public__getcwd_as_non_root)
448*b0d29bc4SBrooks Davis {
449*b0d29bc4SBrooks Davis set_md_var("require.config", "unprivileged-user");
450*b0d29bc4SBrooks Davis set_md_var("require.user", "root");
451*b0d29bc4SBrooks Davis }
ATF_TEST_CASE_BODY(mkdtemp_public__getcwd_as_non_root)452*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(mkdtemp_public__getcwd_as_non_root)
453*b0d29bc4SBrooks Davis {
454*b0d29bc4SBrooks Davis const std::string dir_template("dir.XXXXXX");
455*b0d29bc4SBrooks Davis const fs::path dir = fs::mkdtemp_public(dir_template);
456*b0d29bc4SBrooks Davis const fs::path subdir = dir / "subdir";
457*b0d29bc4SBrooks Davis fs::mkdir(subdir, 0755);
458*b0d29bc4SBrooks Davis
459*b0d29bc4SBrooks Davis const uid_t old_euid = ::geteuid();
460*b0d29bc4SBrooks Davis const gid_t old_egid = ::getegid();
461*b0d29bc4SBrooks Davis
462*b0d29bc4SBrooks Davis const passwd::user unprivileged_user = passwd::find_user_by_name(
463*b0d29bc4SBrooks Davis get_config_var("unprivileged-user"));
464*b0d29bc4SBrooks Davis ATF_REQUIRE(::setegid(unprivileged_user.gid) != -1);
465*b0d29bc4SBrooks Davis ATF_REQUIRE(::seteuid(unprivileged_user.uid) != -1);
466*b0d29bc4SBrooks Davis
467*b0d29bc4SBrooks Davis // The next code block runs as non-root. We cannot use any ATF macros nor
468*b0d29bc4SBrooks Davis // functions in it because a failure would cause the test to attempt to
469*b0d29bc4SBrooks Davis // write to the ATF result file which may not be writable as non-root.
470*b0d29bc4SBrooks Davis bool failed = false;
471*b0d29bc4SBrooks Davis {
472*b0d29bc4SBrooks Davis try {
473*b0d29bc4SBrooks Davis if (::chdir(subdir.c_str()) == -1) {
474*b0d29bc4SBrooks Davis std::cerr << "Cannot enter directory\n";
475*b0d29bc4SBrooks Davis failed |= true;
476*b0d29bc4SBrooks Davis } else {
477*b0d29bc4SBrooks Davis fs::current_path();
478*b0d29bc4SBrooks Davis }
479*b0d29bc4SBrooks Davis } catch (const fs::error& e) {
480*b0d29bc4SBrooks Davis failed |= true;
481*b0d29bc4SBrooks Davis std::cerr << "Failed to query current path in: " << subdir << '\n';
482*b0d29bc4SBrooks Davis }
483*b0d29bc4SBrooks Davis
484*b0d29bc4SBrooks Davis if (::seteuid(old_euid) == -1) {
485*b0d29bc4SBrooks Davis std::cerr << "Failed to restore euid; cannot continue\n";
486*b0d29bc4SBrooks Davis std::abort();
487*b0d29bc4SBrooks Davis }
488*b0d29bc4SBrooks Davis if (::setegid(old_egid) == -1) {
489*b0d29bc4SBrooks Davis std::cerr << "Failed to restore egid; cannot continue\n";
490*b0d29bc4SBrooks Davis std::abort();
491*b0d29bc4SBrooks Davis }
492*b0d29bc4SBrooks Davis }
493*b0d29bc4SBrooks Davis
494*b0d29bc4SBrooks Davis if (failed)
495*b0d29bc4SBrooks Davis fail("Test failed; see stdout for details");
496*b0d29bc4SBrooks Davis }
497*b0d29bc4SBrooks Davis
498*b0d29bc4SBrooks Davis
499*b0d29bc4SBrooks Davis ATF_TEST_CASE(mkdtemp_public__search_permissions_as_non_root)
ATF_TEST_CASE_HEAD(mkdtemp_public__search_permissions_as_non_root)500*b0d29bc4SBrooks Davis ATF_TEST_CASE_HEAD(mkdtemp_public__search_permissions_as_non_root)
501*b0d29bc4SBrooks Davis {
502*b0d29bc4SBrooks Davis set_md_var("require.config", "unprivileged-user");
503*b0d29bc4SBrooks Davis set_md_var("require.user", "root");
504*b0d29bc4SBrooks Davis }
ATF_TEST_CASE_BODY(mkdtemp_public__search_permissions_as_non_root)505*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(mkdtemp_public__search_permissions_as_non_root)
506*b0d29bc4SBrooks Davis {
507*b0d29bc4SBrooks Davis const std::string dir_template("dir.XXXXXX");
508*b0d29bc4SBrooks Davis const fs::path dir = fs::mkdtemp_public(dir_template);
509*b0d29bc4SBrooks Davis const fs::path cookie = dir / "not-secret";
510*b0d29bc4SBrooks Davis atf::utils::create_file(cookie.str(), "this is readable");
511*b0d29bc4SBrooks Davis
512*b0d29bc4SBrooks Davis // We are running as root so there is no reason to assume that our current
513*b0d29bc4SBrooks Davis // work directory is accessible by non-root. Weaken the permissions so that
514*b0d29bc4SBrooks Davis // our code below works.
515*b0d29bc4SBrooks Davis ATF_REQUIRE(::chmod(".", 0755) != -1);
516*b0d29bc4SBrooks Davis
517*b0d29bc4SBrooks Davis const uid_t old_euid = ::geteuid();
518*b0d29bc4SBrooks Davis const gid_t old_egid = ::getegid();
519*b0d29bc4SBrooks Davis
520*b0d29bc4SBrooks Davis const passwd::user unprivileged_user = passwd::find_user_by_name(
521*b0d29bc4SBrooks Davis get_config_var("unprivileged-user"));
522*b0d29bc4SBrooks Davis ATF_REQUIRE(::setegid(unprivileged_user.gid) != -1);
523*b0d29bc4SBrooks Davis ATF_REQUIRE(::seteuid(unprivileged_user.uid) != -1);
524*b0d29bc4SBrooks Davis
525*b0d29bc4SBrooks Davis // The next code block runs as non-root. We cannot use any ATF macros nor
526*b0d29bc4SBrooks Davis // functions in it because a failure would cause the test to attempt to
527*b0d29bc4SBrooks Davis // write to the ATF result file which may not be writable as non-root.
528*b0d29bc4SBrooks Davis bool failed = false;
529*b0d29bc4SBrooks Davis {
530*b0d29bc4SBrooks Davis try {
531*b0d29bc4SBrooks Davis const std::string contents = utils::read_file(cookie);
532*b0d29bc4SBrooks Davis std::cerr << "Read contents: " << contents << '\n';
533*b0d29bc4SBrooks Davis failed |= (contents != "this is readable");
534*b0d29bc4SBrooks Davis } catch (const std::runtime_error& e) {
535*b0d29bc4SBrooks Davis failed |= true;
536*b0d29bc4SBrooks Davis std::cerr << "Failed to read " << cookie << '\n';
537*b0d29bc4SBrooks Davis }
538*b0d29bc4SBrooks Davis
539*b0d29bc4SBrooks Davis if (::seteuid(old_euid) == -1) {
540*b0d29bc4SBrooks Davis std::cerr << "Failed to restore euid; cannot continue\n";
541*b0d29bc4SBrooks Davis std::abort();
542*b0d29bc4SBrooks Davis }
543*b0d29bc4SBrooks Davis if (::setegid(old_egid) == -1) {
544*b0d29bc4SBrooks Davis std::cerr << "Failed to restore egid; cannot continue\n";
545*b0d29bc4SBrooks Davis std::abort();
546*b0d29bc4SBrooks Davis }
547*b0d29bc4SBrooks Davis }
548*b0d29bc4SBrooks Davis
549*b0d29bc4SBrooks Davis if (failed)
550*b0d29bc4SBrooks Davis fail("Test failed; see stdout for details");
551*b0d29bc4SBrooks Davis }
552*b0d29bc4SBrooks Davis
553*b0d29bc4SBrooks Davis
554*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(mkstemp)
ATF_TEST_CASE_BODY(mkstemp)555*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(mkstemp)
556*b0d29bc4SBrooks Davis {
557*b0d29bc4SBrooks Davis const fs::path tmpdir = fs::current_path() / "tmp";
558*b0d29bc4SBrooks Davis utils::setenv("TMPDIR", tmpdir.str());
559*b0d29bc4SBrooks Davis fs::mkdir(tmpdir, 0755);
560*b0d29bc4SBrooks Davis
561*b0d29bc4SBrooks Davis const std::string file_template("tempfile.XXXXXX");
562*b0d29bc4SBrooks Davis const fs::path tempfile = fs::mkstemp(file_template);
563*b0d29bc4SBrooks Davis ATF_REQUIRE(!lookup("tmp", file_template.c_str(), S_IFREG));
564*b0d29bc4SBrooks Davis ATF_REQUIRE(lookup("tmp", tempfile.leaf_name().c_str(), S_IFREG));
565*b0d29bc4SBrooks Davis }
566*b0d29bc4SBrooks Davis
567*b0d29bc4SBrooks Davis
568*b0d29bc4SBrooks Davis static void
test_mount_tmpfs_ok(const units::bytes & size)569*b0d29bc4SBrooks Davis test_mount_tmpfs_ok(const units::bytes& size)
570*b0d29bc4SBrooks Davis {
571*b0d29bc4SBrooks Davis const fs::path mount_point("mount_point");
572*b0d29bc4SBrooks Davis fs::mkdir(mount_point, 0755);
573*b0d29bc4SBrooks Davis
574*b0d29bc4SBrooks Davis try {
575*b0d29bc4SBrooks Davis atf::utils::create_file("outside", "");
576*b0d29bc4SBrooks Davis fs::mount_tmpfs(mount_point, size);
577*b0d29bc4SBrooks Davis atf::utils::create_file("mounted", "");
578*b0d29bc4SBrooks Davis atf::utils::create_file((mount_point / "inside").str(), "");
579*b0d29bc4SBrooks Davis
580*b0d29bc4SBrooks Davis struct ::stat outside, inside;
581*b0d29bc4SBrooks Davis ATF_REQUIRE(::stat("outside", &outside) != -1);
582*b0d29bc4SBrooks Davis ATF_REQUIRE(::stat((mount_point / "inside").c_str(), &inside) != -1);
583*b0d29bc4SBrooks Davis ATF_REQUIRE(outside.st_dev != inside.st_dev);
584*b0d29bc4SBrooks Davis fs::unmount(mount_point);
585*b0d29bc4SBrooks Davis } catch (const fs::unsupported_operation_error& e) {
586*b0d29bc4SBrooks Davis ATF_SKIP(e.what());
587*b0d29bc4SBrooks Davis }
588*b0d29bc4SBrooks Davis }
589*b0d29bc4SBrooks Davis
590*b0d29bc4SBrooks Davis
591*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITH_CLEANUP(mount_tmpfs__ok__default_size)
ATF_TEST_CASE_HEAD(mount_tmpfs__ok__default_size)592*b0d29bc4SBrooks Davis ATF_TEST_CASE_HEAD(mount_tmpfs__ok__default_size)
593*b0d29bc4SBrooks Davis {
594*b0d29bc4SBrooks Davis set_md_var("require.user", "root");
595*b0d29bc4SBrooks Davis }
ATF_TEST_CASE_BODY(mount_tmpfs__ok__default_size)596*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(mount_tmpfs__ok__default_size)
597*b0d29bc4SBrooks Davis {
598*b0d29bc4SBrooks Davis test_mount_tmpfs_ok(units::bytes());
599*b0d29bc4SBrooks Davis }
ATF_TEST_CASE_CLEANUP(mount_tmpfs__ok__default_size)600*b0d29bc4SBrooks Davis ATF_TEST_CASE_CLEANUP(mount_tmpfs__ok__default_size)
601*b0d29bc4SBrooks Davis {
602*b0d29bc4SBrooks Davis cleanup_mount_point(fs::path("mounted"), fs::path("mount_point"));
603*b0d29bc4SBrooks Davis }
604*b0d29bc4SBrooks Davis
605*b0d29bc4SBrooks Davis
606*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITH_CLEANUP(mount_tmpfs__ok__explicit_size)
ATF_TEST_CASE_HEAD(mount_tmpfs__ok__explicit_size)607*b0d29bc4SBrooks Davis ATF_TEST_CASE_HEAD(mount_tmpfs__ok__explicit_size)
608*b0d29bc4SBrooks Davis {
609*b0d29bc4SBrooks Davis set_md_var("require.user", "root");
610*b0d29bc4SBrooks Davis }
ATF_TEST_CASE_BODY(mount_tmpfs__ok__explicit_size)611*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(mount_tmpfs__ok__explicit_size)
612*b0d29bc4SBrooks Davis {
613*b0d29bc4SBrooks Davis test_mount_tmpfs_ok(units::bytes(10 * units::MB));
614*b0d29bc4SBrooks Davis }
ATF_TEST_CASE_CLEANUP(mount_tmpfs__ok__explicit_size)615*b0d29bc4SBrooks Davis ATF_TEST_CASE_CLEANUP(mount_tmpfs__ok__explicit_size)
616*b0d29bc4SBrooks Davis {
617*b0d29bc4SBrooks Davis cleanup_mount_point(fs::path("mounted"), fs::path("mount_point"));
618*b0d29bc4SBrooks Davis }
619*b0d29bc4SBrooks Davis
620*b0d29bc4SBrooks Davis
621*b0d29bc4SBrooks Davis ATF_TEST_CASE(mount_tmpfs__fail)
ATF_TEST_CASE_HEAD(mount_tmpfs__fail)622*b0d29bc4SBrooks Davis ATF_TEST_CASE_HEAD(mount_tmpfs__fail)
623*b0d29bc4SBrooks Davis {
624*b0d29bc4SBrooks Davis set_md_var("require.user", "root");
625*b0d29bc4SBrooks Davis }
ATF_TEST_CASE_BODY(mount_tmpfs__fail)626*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(mount_tmpfs__fail)
627*b0d29bc4SBrooks Davis {
628*b0d29bc4SBrooks Davis try {
629*b0d29bc4SBrooks Davis fs::mount_tmpfs(fs::path("non-existent"));
630*b0d29bc4SBrooks Davis } catch (const fs::unsupported_operation_error& e) {
631*b0d29bc4SBrooks Davis ATF_SKIP(e.what());
632*b0d29bc4SBrooks Davis } catch (const fs::error& e) {
633*b0d29bc4SBrooks Davis // Expected.
634*b0d29bc4SBrooks Davis }
635*b0d29bc4SBrooks Davis }
636*b0d29bc4SBrooks Davis
637*b0d29bc4SBrooks Davis
638*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(rm_r__empty);
ATF_TEST_CASE_BODY(rm_r__empty)639*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(rm_r__empty)
640*b0d29bc4SBrooks Davis {
641*b0d29bc4SBrooks Davis fs::mkdir(fs::path("root"), 0755);
642*b0d29bc4SBrooks Davis ATF_REQUIRE(lookup(".", "root", S_IFDIR));
643*b0d29bc4SBrooks Davis fs::rm_r(fs::path("root"));
644*b0d29bc4SBrooks Davis ATF_REQUIRE(!lookup(".", "root", S_IFDIR));
645*b0d29bc4SBrooks Davis }
646*b0d29bc4SBrooks Davis
647*b0d29bc4SBrooks Davis
648*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(rm_r__files_and_directories);
ATF_TEST_CASE_BODY(rm_r__files_and_directories)649*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(rm_r__files_and_directories)
650*b0d29bc4SBrooks Davis {
651*b0d29bc4SBrooks Davis fs::mkdir(fs::path("root"), 0755);
652*b0d29bc4SBrooks Davis atf::utils::create_file("root/.hidden_file", "");
653*b0d29bc4SBrooks Davis fs::mkdir(fs::path("root/.hidden_dir"), 0755);
654*b0d29bc4SBrooks Davis atf::utils::create_file("root/.hidden_dir/a", "");
655*b0d29bc4SBrooks Davis atf::utils::create_file("root/file", "");
656*b0d29bc4SBrooks Davis atf::utils::create_file("root/with spaces", "");
657*b0d29bc4SBrooks Davis fs::mkdir(fs::path("root/dir1"), 0755);
658*b0d29bc4SBrooks Davis fs::mkdir(fs::path("root/dir1/dir2"), 0755);
659*b0d29bc4SBrooks Davis atf::utils::create_file("root/dir1/dir2/file", "");
660*b0d29bc4SBrooks Davis fs::mkdir(fs::path("root/dir1/dir3"), 0755);
661*b0d29bc4SBrooks Davis ATF_REQUIRE(lookup(".", "root", S_IFDIR));
662*b0d29bc4SBrooks Davis fs::rm_r(fs::path("root"));
663*b0d29bc4SBrooks Davis ATF_REQUIRE(!lookup(".", "root", S_IFDIR));
664*b0d29bc4SBrooks Davis }
665*b0d29bc4SBrooks Davis
666*b0d29bc4SBrooks Davis
667*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(rmdir__ok)
ATF_TEST_CASE_BODY(rmdir__ok)668*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(rmdir__ok)
669*b0d29bc4SBrooks Davis {
670*b0d29bc4SBrooks Davis ATF_REQUIRE(::mkdir("foo", 0755) != -1);
671*b0d29bc4SBrooks Davis ATF_REQUIRE(::access("foo", X_OK) == 0);
672*b0d29bc4SBrooks Davis fs::rmdir(fs::path("foo"));
673*b0d29bc4SBrooks Davis ATF_REQUIRE(::access("foo", X_OK) == -1);
674*b0d29bc4SBrooks Davis }
675*b0d29bc4SBrooks Davis
676*b0d29bc4SBrooks Davis
677*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(rmdir__fail)
ATF_TEST_CASE_BODY(rmdir__fail)678*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(rmdir__fail)
679*b0d29bc4SBrooks Davis {
680*b0d29bc4SBrooks Davis ATF_REQUIRE_THROW_RE(fs::system_error, "Removal of foo failed",
681*b0d29bc4SBrooks Davis fs::rmdir(fs::path("foo")));
682*b0d29bc4SBrooks Davis }
683*b0d29bc4SBrooks Davis
684*b0d29bc4SBrooks Davis
685*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(scan_directory__ok)
ATF_TEST_CASE_BODY(scan_directory__ok)686*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(scan_directory__ok)
687*b0d29bc4SBrooks Davis {
688*b0d29bc4SBrooks Davis fs::mkdir(fs::path("dir"), 0755);
689*b0d29bc4SBrooks Davis atf::utils::create_file("dir/foo", "");
690*b0d29bc4SBrooks Davis atf::utils::create_file("dir/.hidden", "");
691*b0d29bc4SBrooks Davis
692*b0d29bc4SBrooks Davis const std::set< fs::directory_entry > contents = fs::scan_directory(
693*b0d29bc4SBrooks Davis fs::path("dir"));
694*b0d29bc4SBrooks Davis
695*b0d29bc4SBrooks Davis std::set< fs::directory_entry > exp_contents;
696*b0d29bc4SBrooks Davis exp_contents.insert(fs::directory_entry("."));
697*b0d29bc4SBrooks Davis exp_contents.insert(fs::directory_entry(".."));
698*b0d29bc4SBrooks Davis exp_contents.insert(fs::directory_entry(".hidden"));
699*b0d29bc4SBrooks Davis exp_contents.insert(fs::directory_entry("foo"));
700*b0d29bc4SBrooks Davis
701*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(exp_contents, contents);
702*b0d29bc4SBrooks Davis }
703*b0d29bc4SBrooks Davis
704*b0d29bc4SBrooks Davis
705*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(scan_directory__fail)
ATF_TEST_CASE_BODY(scan_directory__fail)706*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(scan_directory__fail)
707*b0d29bc4SBrooks Davis {
708*b0d29bc4SBrooks Davis ATF_REQUIRE_THROW_RE(fs::system_error, "opendir(.*missing.*) failed",
709*b0d29bc4SBrooks Davis fs::scan_directory(fs::path("missing")));
710*b0d29bc4SBrooks Davis }
711*b0d29bc4SBrooks Davis
712*b0d29bc4SBrooks Davis
713*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(unlink__ok)
ATF_TEST_CASE_BODY(unlink__ok)714*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(unlink__ok)
715*b0d29bc4SBrooks Davis {
716*b0d29bc4SBrooks Davis atf::utils::create_file("foo", "");
717*b0d29bc4SBrooks Davis ATF_REQUIRE(::access("foo", R_OK) == 0);
718*b0d29bc4SBrooks Davis fs::unlink(fs::path("foo"));
719*b0d29bc4SBrooks Davis ATF_REQUIRE(::access("foo", R_OK) == -1);
720*b0d29bc4SBrooks Davis }
721*b0d29bc4SBrooks Davis
722*b0d29bc4SBrooks Davis
723*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(unlink__fail)
ATF_TEST_CASE_BODY(unlink__fail)724*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(unlink__fail)
725*b0d29bc4SBrooks Davis {
726*b0d29bc4SBrooks Davis ATF_REQUIRE_THROW_RE(fs::system_error, "Removal of foo failed",
727*b0d29bc4SBrooks Davis fs::unlink(fs::path("foo")));
728*b0d29bc4SBrooks Davis }
729*b0d29bc4SBrooks Davis
730*b0d29bc4SBrooks Davis
731*b0d29bc4SBrooks Davis ATF_TEST_CASE(unmount__ok)
ATF_TEST_CASE_HEAD(unmount__ok)732*b0d29bc4SBrooks Davis ATF_TEST_CASE_HEAD(unmount__ok)
733*b0d29bc4SBrooks Davis {
734*b0d29bc4SBrooks Davis set_md_var("require.user", "root");
735*b0d29bc4SBrooks Davis }
ATF_TEST_CASE_BODY(unmount__ok)736*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(unmount__ok)
737*b0d29bc4SBrooks Davis {
738*b0d29bc4SBrooks Davis const fs::path mount_point("mount_point");
739*b0d29bc4SBrooks Davis fs::mkdir(mount_point, 0755);
740*b0d29bc4SBrooks Davis
741*b0d29bc4SBrooks Davis atf::utils::create_file((mount_point / "test1").str(), "");
742*b0d29bc4SBrooks Davis try {
743*b0d29bc4SBrooks Davis fs::mount_tmpfs(mount_point);
744*b0d29bc4SBrooks Davis } catch (const fs::unsupported_operation_error& e) {
745*b0d29bc4SBrooks Davis ATF_SKIP(e.what());
746*b0d29bc4SBrooks Davis }
747*b0d29bc4SBrooks Davis
748*b0d29bc4SBrooks Davis atf::utils::create_file((mount_point / "test2").str(), "");
749*b0d29bc4SBrooks Davis
750*b0d29bc4SBrooks Davis ATF_REQUIRE(!fs::exists(mount_point / "test1"));
751*b0d29bc4SBrooks Davis ATF_REQUIRE( fs::exists(mount_point / "test2"));
752*b0d29bc4SBrooks Davis fs::unmount(mount_point);
753*b0d29bc4SBrooks Davis ATF_REQUIRE( fs::exists(mount_point / "test1"));
754*b0d29bc4SBrooks Davis ATF_REQUIRE(!fs::exists(mount_point / "test2"));
755*b0d29bc4SBrooks Davis }
756*b0d29bc4SBrooks Davis
757*b0d29bc4SBrooks Davis
758*b0d29bc4SBrooks Davis ATF_TEST_CASE(unmount__fail)
ATF_TEST_CASE_HEAD(unmount__fail)759*b0d29bc4SBrooks Davis ATF_TEST_CASE_HEAD(unmount__fail)
760*b0d29bc4SBrooks Davis {
761*b0d29bc4SBrooks Davis set_md_var("require.user", "root");
762*b0d29bc4SBrooks Davis }
ATF_TEST_CASE_BODY(unmount__fail)763*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(unmount__fail)
764*b0d29bc4SBrooks Davis {
765*b0d29bc4SBrooks Davis ATF_REQUIRE_THROW(fs::error, fs::unmount(fs::path("non-existent")));
766*b0d29bc4SBrooks Davis }
767*b0d29bc4SBrooks Davis
768*b0d29bc4SBrooks Davis
ATF_INIT_TEST_CASES(tcs)769*b0d29bc4SBrooks Davis ATF_INIT_TEST_CASES(tcs)
770*b0d29bc4SBrooks Davis {
771*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, copy__ok);
772*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, copy__fail_open);
773*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, copy__fail_create);
774*b0d29bc4SBrooks Davis
775*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, current_path__ok);
776*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, current_path__enoent);
777*b0d29bc4SBrooks Davis
778*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, exists);
779*b0d29bc4SBrooks Davis
780*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, find_in_path__no_path);
781*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, find_in_path__empty_path);
782*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, find_in_path__one_component);
783*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, find_in_path__many_components);
784*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, find_in_path__current_directory);
785*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, find_in_path__always_absolute);
786*b0d29bc4SBrooks Davis
787*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, free_disk_space__ok__smoke);
788*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, free_disk_space__ok__real);
789*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, free_disk_space__fail);
790*b0d29bc4SBrooks Davis
791*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, is_directory__ok);
792*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, is_directory__fail);
793*b0d29bc4SBrooks Davis
794*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, mkdir__ok);
795*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, mkdir__enoent);
796*b0d29bc4SBrooks Davis
797*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, mkdir_p__one_component);
798*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, mkdir_p__many_components);
799*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, mkdir_p__already_exists);
800*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, mkdir_p__eacces);
801*b0d29bc4SBrooks Davis
802*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, mkdtemp_public);
803*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, mkdtemp_public__getcwd_as_non_root);
804*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, mkdtemp_public__search_permissions_as_non_root);
805*b0d29bc4SBrooks Davis
806*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, mkstemp);
807*b0d29bc4SBrooks Davis
808*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, mount_tmpfs__ok__default_size);
809*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, mount_tmpfs__ok__explicit_size);
810*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, mount_tmpfs__fail);
811*b0d29bc4SBrooks Davis
812*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, rm_r__empty);
813*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, rm_r__files_and_directories);
814*b0d29bc4SBrooks Davis
815*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, rmdir__ok);
816*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, rmdir__fail);
817*b0d29bc4SBrooks Davis
818*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, scan_directory__ok);
819*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, scan_directory__fail);
820*b0d29bc4SBrooks Davis
821*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, unlink__ok);
822*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, unlink__fail);
823*b0d29bc4SBrooks Davis
824*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, unmount__ok);
825*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, unmount__fail);
826*b0d29bc4SBrooks Davis }
827