132305f14SSzymon Dompke #include "utils/make_id_name.hpp"
232305f14SSzymon Dompke
332305f14SSzymon Dompke #include "utils/dbus_path_utils.hpp"
432305f14SSzymon Dompke
532305f14SSzymon Dompke #include <sdbusplus/exception.hpp>
632305f14SSzymon Dompke
732305f14SSzymon Dompke #include <algorithm>
832305f14SSzymon Dompke #include <system_error>
932305f14SSzymon Dompke
1032305f14SSzymon Dompke namespace utils
1132305f14SSzymon Dompke {
1232305f14SSzymon Dompke namespace details
1332305f14SSzymon Dompke {
1432305f14SSzymon Dompke
countDigits(size_t value)1532305f14SSzymon Dompke size_t countDigits(size_t value)
1632305f14SSzymon Dompke {
1732305f14SSzymon Dompke size_t result = 1;
1832305f14SSzymon Dompke while (value >= 10)
1932305f14SSzymon Dompke {
2032305f14SSzymon Dompke ++result;
2132305f14SSzymon Dompke value /= 10;
2232305f14SSzymon Dompke }
2332305f14SSzymon Dompke return result;
2432305f14SSzymon Dompke }
2532305f14SSzymon Dompke
generateId(std::string_view idIn,std::string_view nameIn,std::string_view defaultName,const std::vector<std::string> & conflictIds)2632305f14SSzymon Dompke std::string generateId(std::string_view idIn, std::string_view nameIn,
2732305f14SSzymon Dompke std::string_view defaultName,
2832305f14SSzymon Dompke const std::vector<std::string>& conflictIds)
2932305f14SSzymon Dompke {
3032305f14SSzymon Dompke verifyIdCharacters(idIn);
3132305f14SSzymon Dompke verifyIdPrefixes(idIn);
3232305f14SSzymon Dompke
3332305f14SSzymon Dompke if (!idIn.empty() && !idIn.ends_with('/'))
3432305f14SSzymon Dompke {
3532305f14SSzymon Dompke if (std::find(conflictIds.begin(), conflictIds.end(), idIn) !=
3632305f14SSzymon Dompke conflictIds.end())
3732305f14SSzymon Dompke {
3832305f14SSzymon Dompke throw sdbusplus::exception::SdBusError(
3932305f14SSzymon Dompke static_cast<int>(std::errc::file_exists), "Duplicated id");
4032305f14SSzymon Dompke }
4132305f14SSzymon Dompke return std::string(idIn);
4232305f14SSzymon Dompke }
4332305f14SSzymon Dompke
4432305f14SSzymon Dompke const std::string prefixes(idIn);
4532305f14SSzymon Dompke
4632305f14SSzymon Dompke std::string strippedId(nameIn);
4732305f14SSzymon Dompke if (strippedId.find_first_of(utils::constants::allowedCharactersInPath) ==
4832305f14SSzymon Dompke std::string::npos)
4932305f14SSzymon Dompke {
5032305f14SSzymon Dompke strippedId = defaultName;
5132305f14SSzymon Dompke }
52*583ba441SPatrick Williams strippedId.erase(
53*583ba441SPatrick Williams std::remove_if(
54*583ba441SPatrick Williams strippedId.begin(), strippedId.end(),
5532305f14SSzymon Dompke [](char c) {
56*583ba441SPatrick Williams return c == '/' ||
57*583ba441SPatrick Williams utils::constants::allowedCharactersInPath.find(c) ==
5832305f14SSzymon Dompke std::string_view::npos;
5932305f14SSzymon Dompke }),
6032305f14SSzymon Dompke strippedId.end());
6132305f14SSzymon Dompke
6232305f14SSzymon Dompke size_t idx = 0;
63*583ba441SPatrick Williams std::string tmpId =
64*583ba441SPatrick Williams prefixes + strippedId.substr(0, constants::maxIdNameLength);
6532305f14SSzymon Dompke
6632305f14SSzymon Dompke while (std::find(conflictIds.begin(), conflictIds.end(), tmpId) !=
6732305f14SSzymon Dompke conflictIds.end())
6832305f14SSzymon Dompke {
6932305f14SSzymon Dompke size_t digitsInIdx = countDigits(idx);
7032305f14SSzymon Dompke
7132305f14SSzymon Dompke if (digitsInIdx > constants::maxIdNameLength)
7232305f14SSzymon Dompke {
7332305f14SSzymon Dompke throw sdbusplus::exception::SdBusError(
7432305f14SSzymon Dompke static_cast<int>(std::errc::file_exists),
7532305f14SSzymon Dompke "Unique indices are depleted");
7632305f14SSzymon Dompke }
7732305f14SSzymon Dompke
7832305f14SSzymon Dompke tmpId = prefixes +
7932305f14SSzymon Dompke strippedId.substr(0, constants::maxIdNameLength - digitsInIdx) +
8032305f14SSzymon Dompke std::to_string(idx);
8132305f14SSzymon Dompke ++idx;
8232305f14SSzymon Dompke }
8332305f14SSzymon Dompke
8432305f14SSzymon Dompke return tmpId;
8532305f14SSzymon Dompke }
8632305f14SSzymon Dompke
8732305f14SSzymon Dompke } // namespace details
8832305f14SSzymon Dompke
makeIdName(std::string_view id,std::string_view name,std::string_view defaultName,const std::vector<std::string> & conflictIds)89*583ba441SPatrick Williams std::pair<std::string, std::string> makeIdName(
90*583ba441SPatrick Williams std::string_view id, std::string_view name, std::string_view defaultName,
9132305f14SSzymon Dompke const std::vector<std::string>& conflictIds)
9232305f14SSzymon Dompke {
9332305f14SSzymon Dompke if (name.length() > constants::maxIdNameLength)
9432305f14SSzymon Dompke {
9562c08e9bSKrzysztof Grobelny throw errors::InvalidArgument("Name", "Too long.");
9632305f14SSzymon Dompke }
9732305f14SSzymon Dompke
9832305f14SSzymon Dompke if (name.empty() && !id.ends_with('/'))
9932305f14SSzymon Dompke {
10032305f14SSzymon Dompke name = id;
10132305f14SSzymon Dompke
10232305f14SSzymon Dompke if (auto pos = name.find_last_of("/"); pos != std::string::npos)
10332305f14SSzymon Dompke {
10432305f14SSzymon Dompke name = name.substr(pos + 1);
10532305f14SSzymon Dompke }
10632305f14SSzymon Dompke
10732305f14SSzymon Dompke name = name.substr(0, constants::maxIdNameLength);
10832305f14SSzymon Dompke }
10932305f14SSzymon Dompke
11032305f14SSzymon Dompke if (name.empty())
11132305f14SSzymon Dompke {
11232305f14SSzymon Dompke name = defaultName;
11332305f14SSzymon Dompke }
11432305f14SSzymon Dompke
11532305f14SSzymon Dompke return std::make_pair(
11632305f14SSzymon Dompke details::generateId(id, name, defaultName, conflictIds),
11732305f14SSzymon Dompke std::string{name});
11832305f14SSzymon Dompke }
11932305f14SSzymon Dompke
12032305f14SSzymon Dompke } // namespace utils
121