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( 53 std::remove_if( 54 strippedId.begin(), strippedId.end(), 55 [](char c) { 56 return c == '/' || 57 utils::constants::allowedCharactersInPath.find(c) == 58 std::string_view::npos; 59 }), 60 strippedId.end()); 61 62 size_t idx = 0; 63 std::string tmpId = 64 prefixes + strippedId.substr(0, constants::maxIdNameLength); 65 66 while (std::find(conflictIds.begin(), conflictIds.end(), tmpId) != 67 conflictIds.end()) 68 { 69 size_t digitsInIdx = countDigits(idx); 70 71 if (digitsInIdx > constants::maxIdNameLength) 72 { 73 throw sdbusplus::exception::SdBusError( 74 static_cast<int>(std::errc::file_exists), 75 "Unique indices are depleted"); 76 } 77 78 tmpId = prefixes + 79 strippedId.substr(0, constants::maxIdNameLength - digitsInIdx) + 80 std::to_string(idx); 81 ++idx; 82 } 83 84 return tmpId; 85 } 86 87 } // namespace details 88 89 std::pair<std::string, std::string> 90 makeIdName(std::string_view id, std::string_view name, 91 std::string_view defaultName, 92 const std::vector<std::string>& conflictIds) 93 { 94 if (name.length() > constants::maxIdNameLength) 95 { 96 throw sdbusplus::exception::SdBusError( 97 static_cast<int>(std::errc::invalid_argument), "Name too long"); 98 } 99 100 if (name.empty() && !id.ends_with('/')) 101 { 102 name = id; 103 104 if (auto pos = name.find_last_of("/"); pos != std::string::npos) 105 { 106 name = name.substr(pos + 1); 107 } 108 109 name = name.substr(0, constants::maxIdNameLength); 110 } 111 112 if (name.empty()) 113 { 114 name = defaultName; 115 } 116 117 return std::make_pair( 118 details::generateId(id, name, defaultName, conflictIds), 119 std::string{name}); 120 } 121 122 } // namespace utils 123