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