diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index ecf157c0b..972bab893 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -286,14 +286,18 @@ void LocalStore::findRootsNoTemp(Roots & roots, bool censor) settings.requireExperimentalFeature(Xp::ExternalGCDaemon); try { + StringMap unescapes = { + { "\\n", "\n"}, + { "\\t", "\t"}, + }; while (true) { auto line = readLine(fd.get()); if (line.empty()) break; // TODO: Handle the broken symlinks auto parsedLine = tokenizeString>(line, "\t"); if (parsedLine.size() != 2) throw Error("Invalid result from the gc helper"); - auto rawDestPath = parsedLine[0]; - auto retainer = parsedLine[1]; + auto rawDestPath = rewriteStrings(parsedLine[0], unescapes); + auto retainer = rewriteStrings(parsedLine[1], unescapes); if (!isInStore(rawDestPath)) continue; try { auto destPath = toStorePath(rawDestPath).first; diff --git a/src/nix-find-roots/main.cc b/src/nix-find-roots/main.cc index 0d8186a04..05697356d 100644 --- a/src/nix-find-roots/main.cc +++ b/src/nix-find-roots/main.cc @@ -68,6 +68,26 @@ TracerConfig parseCmdLine(int argc, char** argv) }; } +/** + * Return `original` with every newline or tab character escaped + */ +std::string escape(std::string original) +{ + map replacements = { + {"\n", "\\n"}, + {"\n", "\\t"}, + }; + for (auto [oldStr, newStr] : replacements) { + size_t currentPos = 0; + while ((currentPos = original.find(oldStr)) != std::string::npos) { + original.replace(currentPos, oldStr.length(), newStr); + currentPos += newStr.length(); + } + } + + return original; +} + #define SD_LISTEN_FDS_START 3 // Like in systemd int main(int argc, char * * argv) @@ -126,16 +146,16 @@ int main(int argc, char * * argv) traceResult.storeRoots.insert(runtimeRoots.begin(), runtimeRoots.end()); for (auto & [rootInStore, externalRoots] : traceResult.storeRoots) { for (auto & externalRoot : externalRoots) { - send(remoteSocket, rootInStore.string().c_str(), rootInStore.string().size(), 0); + send(remoteSocket, escape(rootInStore.string()).c_str(), rootInStore.string().size(), 0); send(remoteSocket, "\t", strlen("\t"), 0); - send(remoteSocket, externalRoot.string().c_str(), externalRoot.string().size(), 0); + send(remoteSocket, escape(externalRoot.string()).c_str(), externalRoot.string().size(), 0); send(remoteSocket, "\n", strlen("\n"), 0); } } send(remoteSocket, "\n", strlen("\n"), 0); for (auto & deadLink : traceResult.deadLinks) { - send(remoteSocket, deadLink.string().c_str(), deadLink.string().size(), 0); + send(remoteSocket, escape(deadLink.string()).c_str(), deadLink.string().size(), 0); send(remoteSocket, "\n", strlen("\n"), 0); }