1 #include "utils/make_id_name.hpp" 2 3 #include "utils/dbus_path_utils.hpp" 4 5 #include <sdbusplus/exception.hpp> 6 7 #include <algorithm> 8 #include <system_error> 9 10 namespace utils 11 { 12 namespace details 13 { 14 15 size_t countDigits(size_t value) 16 { 17 size_t result = 1; 18 while (value >= 10) 19 { 20 ++result; 21 value /= 10; 22 } 23 return result; 24 } 25 26 std::string generateId(std::string_view idIn, std::string_view nameIn, 27 std::string_view defaultName, 28 const std::vector<std::string>& conflictIds) 29 { 30 verifyIdCharacters(idIn); 31 verifyIdPrefixes(idIn); 32 33 if (!idIn.empty() && !idIn.ends_with('/')) 34 { 35 if (std::find(conflictIds.begin(), conflictIds.end(), idIn) != 36 conflictIds.end()) 37 { 38 throw sdbusplus::exception::SdBusError( 39 static_cast<int>(std::errc::file_exists), "Duplicated id"); 40 } 41 return std::string(idIn); 42 } 43 44 const std::string prefixes(idIn); 45 46 std::string strippedId(nameIn); 47 if (strippedId.find_first_of(utils::constants::allowedCharactersInPath) == 48 std::string::npos) 49 { 50 strippedId = defaultName; 51 } 52 strippedId.erase(std::remove_if(strippedId.begin(), strippedId.end(), 53 [](char c) { 54 return c == '/' || utils::constants::allowedCharactersInPath.find(c) == 55 std::string_view::npos; 56 }), 57 strippedId.end()); 58 59 size_t idx = 0; 60 std::string tmpId = prefixes + 61 strippedId.substr(0, constants::maxIdNameLength); 62 63 while (std::find(conflictIds.begin(), conflictIds.end(), tmpId) != 64 conflictIds.end()) 65 { 66 size_t digitsInIdx = countDigits(idx); 67 68 if (digitsInIdx > constants::maxIdNameLength) 69 { 70 throw sdbusplus::exception::SdBusError( 71 static_cast<int>(std::errc::file_exists), 72 "Unique indices are depleted"); 73 } 74 75 tmpId = prefixes + 76 strippedId.substr(0, constants::maxIdNameLength - digitsInIdx) + 77 std::to_string(idx); 78 ++idx; 79 } 80 81 return tmpId; 82 } 83 84 } // namespace details 85 86 std::pair<std::string, std::string> 87 makeIdName(std::string_view id, std::string_view name, 88 std::string_view defaultName, 89 const std::vector<std::string>& conflictIds) 90 { 91 if (name.length() > constants::maxIdNameLength) 92 { 93 throw errors::InvalidArgument("Name", "Too long."); 94 } 95 96 if (name.empty() && !id.ends_with('/')) 97 { 98 name = id; 99 100 if (auto pos = name.find_last_of("/"); pos != std::string::npos) 101 { 102 name = name.substr(pos + 1); 103 } 104 105 name = name.substr(0, constants::maxIdNameLength); 106 } 107 108 if (name.empty()) 109 { 110 name = defaultName; 111 } 112 113 return std::make_pair( 114 details::generateId(id, name, defaultName, conflictIds), 115 std::string{name}); 116 } 117 118 } // namespace utils 119