/* * Copyright (c) Facebook, Inc. and its affiliates. * * This software may be used and distributed according to the terms of the * GNU General Public License version 2. */ #include "eden/fs/config/FieldConverter.h" #include #include "eden/fs/utils/ChronoParse.h" using folly::Expected; using std::string; namespace { constexpr std::array kEnvVars = { folly::StringPiece{"HOME"}, folly::StringPiece{"USER"}, folly::StringPiece{"USER_ID"}, folly::StringPiece{"THRIFT_TLS_CL_CERT_PATH"}, }; /** * Check if string represents a well-formed file path. */ bool isValidAbsolutePath(folly::StringPiece path) { // All we really care about here is making sure that // normalizeBestEffort() isn't going to treat the path as relatively. We // probably should just add an option to normalizeBestEffort() to make it // reject relative paths. try { facebook::eden::detail::AbsolutePathSanityCheck()(path); return true; } catch (std::domain_error&) { return false; } } } // namespace namespace facebook { namespace eden { Expected FieldConverter::fromString( folly::StringPiece value, const std::map& convData) const { auto sString = value.str(); for (auto varName : kEnvVars) { auto it = convData.find(varName.str()); if (it != convData.end()) { auto envVar = folly::to("${", varName, "}"); // There may be multiple ${USER} tokens to replace, so loop // until we've processed all of them while (true) { auto idx = sString.find(envVar); if (idx == string::npos) { break; } sString.replace(idx, envVar.size(), it->second); } } } if (!::isValidAbsolutePath(sString)) { return folly::makeUnexpected(folly::to( "Cannot convert value '", value, "' to an absolute path")); } // normalizeBestEffort typically will not throw, but, we want to handle // cases where it does, eg. getcwd fails. try { return facebook::eden::normalizeBestEffort(sString); } catch (const std::exception& ex) { return folly::makeUnexpected(folly::to( "Failed to convert value '", value, "' to an absolute path, error : ", ex.what())); } } Expected FieldConverter::fromString( folly::StringPiece value, const std::map& /* unused */) const { return folly::makeExpected(value.toString()); } Expected FieldConverter::fromString( folly::StringPiece value, const std::map& /* unused */) const { auto result = stringToDuration(value); if (result.hasValue()) { return result.value(); } return folly::makeUnexpected(chronoParseErrorToString(result.error()).str()); } std::string FieldConverter::toDebugString( std::chrono::nanoseconds value) const { return durationToString(value); } Expected, string> FieldConverter>::fromString( folly::StringPiece value, const std::map& /* unused */) const { // value is a regex return std::make_shared(value.str()); } std::string FieldConverter>::toDebugString( std::shared_ptr value) const { if (value) { return value->pattern(); } return ""; } } // namespace eden } // namespace facebook