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 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); 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); 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); 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 } 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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 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); 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 } 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 } 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); 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); 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); 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 } 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 } 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); 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); 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); 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); 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); 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) 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 } 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) 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) 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 } 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) 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 } 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) 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 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) 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 } 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 } 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) 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 } 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 } 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) 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 } 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); 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); 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) 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) 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) 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) 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) 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) 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) 732*b0d29bc4SBrooks Davis ATF_TEST_CASE_HEAD(unmount__ok) 733*b0d29bc4SBrooks Davis { 734*b0d29bc4SBrooks Davis set_md_var("require.user", "root"); 735*b0d29bc4SBrooks Davis } 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) 759*b0d29bc4SBrooks Davis ATF_TEST_CASE_HEAD(unmount__fail) 760*b0d29bc4SBrooks Davis { 761*b0d29bc4SBrooks Davis set_md_var("require.user", "root"); 762*b0d29bc4SBrooks Davis } 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 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