From 1b6ee8f4c7e74f75e1f49b43cf22be7730b30649 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 13 Jun 2013 17:29:56 +0200 Subject: [PATCH] Allow hard links between the outputs of a derivation --- src/libstore/build.cc | 9 +++++++-- src/libstore/local-store.cc | 15 ++++++++------- src/libstore/local-store.hh | 5 +++++ 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/libstore/build.cc b/src/libstore/build.cc index e49c66fc5..20ed2de39 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -844,6 +844,11 @@ private: bool repair; map redirectedBadOutputs; + /* Set of inodes seen during calls to canonicalisePathMetaData() + for this build's outputs. This needs to be shared between + outputs to allow hard links between outputs. */ + InodesSeen inodesSeen; + /* Magic exit code denoting that setting up the child environment failed. (It's possible that the child actually returns the exit code, but ah well.) */ @@ -1493,7 +1498,7 @@ void DerivationGoal::buildDone() /* Canonicalise first. This ensures that the path we're rewriting doesn't contain a hard link to /etc/shadow or something like that. */ - canonicalisePathMetaData(path, buildUser.enabled() ? buildUser.getUID() : -1); + canonicalisePathMetaData(path, buildUser.enabled() ? buildUser.getUID() : -1, inodesSeen); /* FIXME: this is in-memory. */ StringSink sink; @@ -2307,7 +2312,7 @@ void DerivationGoal::computeClosure() /* Get rid of all weird permissions. This also checks that all files are owned by the build user, if applicable. */ canonicalisePathMetaData(path, - buildUser.enabled() && rewrittenPaths.find(path) == rewrittenPaths.end() ? buildUser.getUID() : -1); + buildUser.enabled() && rewrittenPaths.find(path) == rewrittenPaths.end() ? buildUser.getUID() : -1, inodesSeen); /* For this output path, find the references to other paths contained in it. Compute the SHA-256 NAR hash at the same diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 857d4cee0..13c70fbf5 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -500,10 +500,6 @@ void canonicaliseTimestampAndPermissions(const Path & path) } -typedef std::pair Inode; -typedef set InodesSeen; - - static void canonicalisePathMetaData_(const Path & path, uid_t fromUid, InodesSeen & inodesSeen) { checkInterrupt(); @@ -561,10 +557,8 @@ static void canonicalisePathMetaData_(const Path & path, uid_t fromUid, InodesSe } -void canonicalisePathMetaData(const Path & path, uid_t fromUid) +void canonicalisePathMetaData(const Path & path, uid_t fromUid, InodesSeen & inodesSeen) { - InodesSeen inodesSeen; - canonicalisePathMetaData_(path, fromUid, inodesSeen); /* On platforms that don't have lchown(), the top-level path can't @@ -580,6 +574,13 @@ void canonicalisePathMetaData(const Path & path, uid_t fromUid) } +void canonicalisePathMetaData(const Path & path, uid_t fromUid) +{ + InodesSeen inodesSeen; + canonicalisePathMetaData(path, fromUid, inodesSeen); +} + + void LocalStore::checkDerivationOutputs(const Path & drvPath, const Derivation & drv) { string drvName = storePathToName(drvPath); diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index b1fde99cf..4b132972e 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -305,6 +305,10 @@ private: }; +typedef std::pair Inode; +typedef set InodesSeen; + + /* "Fix", or canonicalise, the meta-data of the files in a store path after it has been built. In particular: - the last modification date on each file is set to 1 (i.e., @@ -313,6 +317,7 @@ private: without execute permission; setuid bits etc. are cleared) - the owner and group are set to the Nix user and group, if we're in a setuid Nix installation. */ +void canonicalisePathMetaData(const Path & path, uid_t fromUid, InodesSeen & inodesSeen); void canonicalisePathMetaData(const Path & path, uid_t fromUid); void canonicaliseTimestampAndPermissions(const Path & path);