diff options
-rw-r--r-- | doc/manual/release-notes.xml | 6 | ||||
-rw-r--r-- | src/libstore/build.cc | 76 | ||||
-rw-r--r-- | src/libstore/store.cc | 4 |
3 files changed, 65 insertions, 21 deletions
diff --git a/doc/manual/release-notes.xml b/doc/manual/release-notes.xml index 098e2a4497d8..00c8042098fb 100644 --- a/doc/manual/release-notes.xml +++ b/doc/manual/release-notes.xml @@ -30,8 +30,12 @@ <listitem><para>TODO: now using Berkeley DB 4.5.</para></listitem> - <listitem><para>Option <option>--reregister</option> in + <listitem><para>TODO: option <option>--reregister</option> in <command>nix-store --register-validity</command>.</para></listitem> + + + <listitem><para>TODO: magic <varname>exportReferencesGraph</varname> + attribute.</para></listitem> </itemizedlist> diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 43ac5cf53f84..82f713c8c8c7 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -901,6 +901,34 @@ string showPaths(const PathSet & paths) } +/* Return a string accepted by `nix-store --register-validity' that + registers the specified paths as valid. Note: it's the + responsibility of the caller to provide a closure. */ +static string makeValidityRegistration(const PathSet & paths, + bool showDerivers) +{ + string s = ""; + + for (PathSet::iterator i = paths.begin(); i != paths.end(); ++i) { + s += *i + "\n"; + + Path deriver = showDerivers ? queryDeriver(noTxn, *i) : ""; + s += deriver + "\n"; + + PathSet references; + queryReferences(noTxn, *i, references); + + s += (format("%1%\n") % references.size()).str(); + + for (PathSet::iterator j = references.begin(); + j != references.end(); ++j) + s += *j + "\n"; + } + + return s; +} + + DerivationGoal::HookReply DerivationGoal::tryBuildHook() { Path buildHook = getEnv("NIX_BUILD_HOOK"); @@ -1024,26 +1052,8 @@ DerivationGoal::HookReply DerivationGoal::tryBuildHook() /* The `references' file has exactly the format accepted by `nix-store --register-validity'. */ - s = ""; - for (PathSet::iterator i = allInputs.begin(); - i != allInputs.end(); ++i) - { - s += *i + "\n"; - - Path deriver = queryDeriver(noTxn, *i); - s += deriver + "\n"; - - PathSet references; - queryReferences(noTxn, *i, references); - - s += (format("%1%\n") % references.size()).str(); - - for (PathSet::iterator j = references.begin(); - j != references.end(); ++j) - s += *j + "\n"; - } - - writeStringToFile(referencesFN, s); + writeStringToFile(referencesFN, + makeValidityRegistration(allInputs, true)); /* Tell the hook to proceed. */ writeLine(toHook.writeSide, "okay"); @@ -1235,6 +1245,32 @@ void DerivationGoal::startBuilder() env[*i] = getEnv(*i); } + /* The `exportReferencesGraph' feature allows the references graph + to be passed to a builder. This attribute should be a list of + pairs [name1 path1 name2 path2 ...]. The references graph of + each `pathN' will be stored in a text file `nameN' in the + temporary build directory. The text files have the format used + by `nix-store --register-validity'. However, the deriver + fields are left empty. */ + string s = drv.env["exportReferencesGraph"]; + Strings ss = tokenizeString(s); + if (ss.size() % 2 != 0) + throw Error(format("odd number of tokens in `exportReferencesGraph': `%1%'") % s); + for (Strings::iterator i = ss.begin(); i != ss.end(); ) { + string fileName = *i++; + Path storePath = *i++; + if (!isValidPath(storePath)) + throw Error(format("`exportReferencesGraph' refers to an invalid path `%1%'") + % storePath); + checkStoreName(fileName); /* !!! abuse of this function */ + PathSet refs; + computeFSClosure(storePath, refs); + /* !!! in secure Nix, the writing should be done on the + build uid for security (maybe). */ + writeStringToFile(tmpDir + "/" + fileName, + makeValidityRegistration(refs, false)); + } + /* If we are running as root, and the `build-allow-root' setting is `false', then we have to build as one of the users listed in diff --git a/src/libstore/store.cc b/src/libstore/store.cc index f8441af9cb42..e073d64adaff 100644 --- a/src/libstore/store.cc +++ b/src/libstore/store.cc @@ -259,6 +259,10 @@ Path toStorePath(const Path & path) void checkStoreName(const string & name) { string validChars = "+-._?="; + /* Disallow names starting with a dot for possible security + reasons (e.g., "." and ".."). */ + if (string(name, 0, 1) == ".") + throw Error(format("illegal name: `%1%'") % name); for (string::const_iterator i = name.begin(); i != name.end(); ++i) if (!((*i >= 'A' && *i <= 'Z') || (*i >= 'a' && *i <= 'z') || |