| 100 | } |
| 101 | |
| 102 | std::unordered_set<std::string> LoadRootTokens(uint32_t accountId, uint32_t appId) { |
| 103 | std::unordered_set<std::string> tokens; |
| 104 | bool needsRewrite = false; |
| 105 | bool fromLegacy = false; |
| 106 | |
| 107 | // Read phase: shared lock allows concurrent readers |
| 108 | { |
| 109 | std::shared_lock<std::shared_mutex> lock(g_metadataMutex); |
| 110 | std::string appPath = GetAppPathInternal(accountId, appId); |
| 111 | std::string path = appPath + kRootTokenFilename; |
| 112 | std::string legacyPath = appPath + kLegacyRootTokenFilename; |
| 113 | |
| 114 | std::ifstream f(FileUtil::Utf8ToPath(path)); |
| 115 | if (!f) { |
| 116 | f.open(FileUtil::Utf8ToPath(legacyPath)); |
| 117 | if (f) fromLegacy = true; |
| 118 | } |
| 119 | if (f) { |
| 120 | std::string line; |
| 121 | while (std::getline(f, line)) { |
| 122 | std::string original = line; |
| 123 | while (!line.empty() && (line.back() == '\r' || line.back() == '\n')) |
| 124 | line.pop_back(); |
| 125 | if (line != original) |
| 126 | needsRewrite = true; |
| 127 | if (!line.empty()) { |
| 128 | tokens.insert(line); |
| 129 | } |
| 130 | } |
| 131 | f.close(); |
| 132 | if (!tokens.empty()) { |
| 133 | LOG("LoadRootTokens: loaded %zu tokens from %s for app %u", |
| 134 | tokens.size(), fromLegacy ? "legacy path" : "disk", appId); |
| 135 | } |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | // Migrate from legacy or rewrite if corrupted. |
| 140 | // Skip if canonical file already exists. |
| 141 | if ((fromLegacy || needsRewrite) && !tokens.empty()) { |
| 142 | if (fromLegacy) { |
| 143 | LOG("LoadRootTokens: migrating tokens for app %u", appId); |
| 144 | } else { |
| 145 | LOG("LoadRootTokens: cleaning corrupted tokens for app %u", appId); |
| 146 | } |
| 147 | (void)SaveRootTokens(accountId, appId, tokens); |
| 148 | } |
| 149 | |
| 150 | return tokens; |
| 151 | } |
| 152 | |
| 153 | bool SaveFileTokens(uint32_t accountId, uint32_t appId, |
| 154 | const std::unordered_map<std::string, std::string>& fileTokens, |
nothing calls this directly
no test coverage detected