-
Notifications
You must be signed in to change notification settings - Fork 0
/
cross-fingers.patch
52 lines (51 loc) · 2.49 KB
/
cross-fingers.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc
index 06d0517a2..a30c75744 100644
--- a/src/libstore/build/local-derivation-goal.cc
+++ b/src/libstore/build/local-derivation-goal.cc
@@ -2222,14 +2222,39 @@ void LocalDerivationGoal::registerOutputs()
/* Apply hash rewriting if necessary. */
if (!outputRewrites.empty()) {
debug("rewriting hashes in '%1%'; cross fingers", actualPath);
-
- /* FIXME: this is in-memory. */
- StringSink sink;
- dumpPath(actualPath, sink);
- deletePath(actualPath);
- sink.s = make_ref<std::string>(rewriteStrings(*sink.s, outputRewrites));
- StringSource source(*sink.s);
- restorePath(actualPath, source);
+
+ AutoDelete tmpDir(createTempDir(), true);
+ Path tmpFile = (Path) tmpDir + "/rewrite";
+ {
+ AutoCloseFD fd = open(tmpFile.c_str(), O_WRONLY | O_CREAT | O_EXCL, 0600);
+ if(!fd) throw SysError("creating temporary file '%s'", tmpFile);
+ FdSink sink(fd.get());
+ dumpPath(actualPath, sink);
+ deletePath(actualPath);
+ }
+
+ {
+ AutoCloseFD fd = open(tmpFile.c_str(), O_RDWR);
+ if(!fd) throw SysError("Opening temporary file '%s'", tmpFile);
+ struct stat stat_buf;
+ if(fstat(fd.get(), &stat_buf) == -1) throw SysError("fstat: '%s'", tmpFile);
+ void *ptr = mmap(NULL, stat_buf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd.get(), 0);
+ if(!ptr) throw SysError("mmap: '%s'", tmpFile);
+ for(auto & i : outputRewrites) {
+ if(i.first == i.second) continue;
+ void *j;
+ while((j = memmem(ptr, stat_buf.st_size, i.first.c_str(), i.first.size())))
+ memcpy(j, i.second.c_str(), i.first.size());
+ }
+ munmap(ptr, stat_buf.st_size);
+ }
+
+ {
+ AutoCloseFD fd = open(tmpFile.c_str(), O_RDONLY);
+ if(!fd) throw SysError("Opening temporary file '%s'", tmpFile);
+ FdSource source(fd.get());
+ restorePath(actualPath, source);
+ }
}
};