#include <cstdlib>
#include <fstream>
#include <string>
-#include <filesystem>
#include <iostream>
#include <dirent.h>
return (valid_path);
}
+std::string
+PathChecker::validateDirectory(const std::string input_path_str,
+ bool enforce_path /* = true */) const {
+ std::string input_copy = trim(input_path_str);
+ if (!enforce_path) {
+ return(input_copy);
+ }
+
+ // We only allow absolute path equal to default. Catch an invalid path.
+ if (!input_path_str.empty()) {
+ std::string input_copy = input_path_str;
+ while (!input_copy.empty() && input_copy.back() == '/') {
+ input_copy.pop_back();
+ }
+
+ if (input_copy != path_) {
+ isc_throw(BadValue, "invalid path specified: '"
+ << input_path_str << "', supported path is '"
+ << path_ << "'");
+ }
+ }
+
+ return (path_);
+}
+
bool
PathChecker::pathHasPermissions(mode_t permissions) {
return(hasPermissions(path_, permissions));
void
setUmask();
-/// \brief Paths on a filesystem
+/// @brief Paths on a filesystem
struct Path {
/// @brief Constructor
///
std::string validatePath(const std::string input_path_str,
bool enforce_path = true) const;
+ /// @brief Validates a directory against a supported path.
+ ///
+ /// Used to validate a string that represents a directory that may or
+ /// may not end with a "/" (i.e "/foo/bar", bar is assumed to be the
+ /// a directory, not a file.
+ ///
+ /// If the input is empty or it matches the supported path, it returns
+ /// the supported path. Otherwise it throws an error.
+ ///
+ /// @param input_path_str file path to validate.
+ /// @param enforce_path enables validation against the supported path. If
+ /// it simply returns the supported path.
+ ///
+ /// @return validated path
+ ///
+ /// @throw BadValue if the input directory does not match the supported
+ /// path.
+ std::string validateDirectory(const std::string input_path_str,
+ bool enforce_path = true) const;
+
/// @brief Tests that the supported path has the given permissions.
///
/// @param permissions mode_t mask of required permissions.
#include <fstream>
#include <list>
#include <string>
+#include <cstdlib>
#include <gtest/gtest.h>
EXPECT_FALSE(hasPermissions(path, current_permissions));
}
+// Verifies PathChecker::validateDirectory() when enforce_path is true.
+TEST(PathChecker, validateDirectoryEnforcePath) {
+ std::string def_path(TEST_DATA_BUILDDIR);
+ struct Scenario {
+ int line_;
+ std::string lib_path_;
+ std::string exp_path_;
+ std::string exp_error_;
+ };
+
+ std::list<Scenario> scenarios = {
+ {
+ // Invalid path with slash.
+ __LINE__,
+ "/var/lib/bs/",
+ "",
+ string("invalid path specified: '/var/lib/bs/', supported path is '" + def_path + "'")
+ },
+ {
+ // Invalid path without slash.
+ __LINE__,
+ "/var/lib/bs",
+ "",
+ string("invalid path specified: '/var/lib/bs', supported path is '" + def_path + "'")
+ },
+ {
+ // File name is just another bad path.
+ __LINE__,
+ "mylib.so",
+ "",
+ string("invalid path specified: 'mylib.so', supported path is '" + def_path + "'")
+ },
+ {
+ // Valid full path with slash.
+ __LINE__,
+ def_path + "/",
+ def_path,
+ ""
+ },
+ {
+ // Valid full path without slash.
+ __LINE__,
+ def_path,
+ def_path,
+ ""
+ },
+ {
+ // Invalid relative path.
+ __LINE__,
+ "../kea/",
+ "",
+ string("invalid path specified: '../kea/', supported path is '" +
+ def_path + "'")
+ }
+ };
+
+ // Create a PathChecker with a supported path of def_path.
+ PathChecker checker(def_path);
+ for (auto scenario : scenarios) {
+ std::ostringstream oss;
+ oss << " Scenario at line: " << scenario.line_;
+ SCOPED_TRACE(oss.str());
+ std::string validated_path;
+ if (scenario.exp_error_.empty()) {
+ ASSERT_NO_THROW_LOG(validated_path =
+ checker.validateDirectory(scenario.lib_path_));
+ EXPECT_EQ(validated_path, scenario.exp_path_);
+ } else {
+ ASSERT_THROW_MSG(validated_path =
+ checker.validateDirectory(scenario.lib_path_),
+ BadValue, scenario.exp_error_);
+ }
+ }
+}
+
+// Verifies PathChecker::validateDirectory() when enforce_path is false.
+TEST(PathChecker, validateDirectoryEnforcePathFalse) {
+ std::string def_path(TEST_DATA_BUILDDIR);
+ struct Scenario {
+ int line_;
+ std::string lib_path_;
+ std::string exp_path_;
+ std::string exp_error_;
+ };
+
+ std::list<Scenario> scenarios = {
+ {
+ // Invalid parent path but shouldn't care.
+ __LINE__,
+ "/var/lib/bs/",
+ "/var/lib/bs/",
+ ""
+ },
+ {
+ // File name only is valid.
+ __LINE__,
+ "mylib.so",
+ "mylib.so",
+ ""
+ },
+ {
+ // Valid full path.
+ __LINE__,
+ def_path + "/",
+ def_path + "/",
+ ""
+ },
+ {
+ // White space for file name.
+ __LINE__,
+ " ",
+ "",
+ ""
+ }
+ };
+
+ // Create a PathChecker with a supported path of def_path.
+ PathChecker checker(def_path);
+ for (auto scenario : scenarios) {
+ std::ostringstream oss;
+ oss << " Scenario at line: " << scenario.line_;
+ SCOPED_TRACE(oss.str());
+ std::string validated_path;
+ if (scenario.exp_error_.empty()) {
+ ASSERT_NO_THROW_LOG(validated_path =
+ checker.validateDirectory(scenario.lib_path_, false));
+ EXPECT_EQ(validated_path, scenario.exp_path_);
+ } else {
+ ASSERT_THROW_MSG(validated_path =
+ checker.validateDirectory(scenario.lib_path_, false),
+ BadValue, scenario.exp_error_);
+ }
+ }
+}
+
} // namespace