diff options
-rw-r--r-- | src/normalise.cc | 15 | ||||
-rw-r--r-- | src/util.cc | 38 | ||||
-rw-r--r-- | src/util.hh | 5 |
3 files changed, 52 insertions, 6 deletions
diff --git a/src/normalise.cc b/src/normalise.cc index 52437059a4e3..059b3c83a9ab 100644 --- a/src/normalise.cc +++ b/src/normalise.cc @@ -131,6 +131,14 @@ FSId normaliseFState(FSId id, FSIdSet pending) value. */ env["PATH"] = "/path-not-set"; + /* Set HOME to a non-existing path to prevent certain programs from using + /etc/passwd (or NIS, or whatever) to locate the home directory (for + example, wget looks for ~/.wgetrc). I.e., these tools use /etc/passwd + if HOME is not set, but they will just assume that the settings file + they are looking for does not exist if HOME is set but points to some + non-existing path. */ + env["HOME"] = "/homeless-shelter"; + /* Build the environment. */ for (StringPairs::iterator i = fs.derive.env.begin(); i != fs.derive.env.end(); i++) @@ -178,7 +186,8 @@ FSId normaliseFState(FSId id, FSIdSet pending) msg(lvlChatty, format("fast build succesful")); /* Check whether the output paths were created, and grep each - output path to determine what other paths it references. */ + output path to determine what other paths it references. Also make all + output paths read-only. */ StringSet usedPaths; for (DeriveOutputs::iterator i = fs.derive.outputs.begin(); i != fs.derive.outputs.end(); i++) @@ -188,10 +197,12 @@ FSId normaliseFState(FSId id, FSIdSet pending) throw Error(format("path `%1%' does not exist") % path); nfFS.slice.roots.insert(path); + makePathReadOnly(path); + /* For this output path, find the references to other paths contained in it. */ Strings refPaths = filterReferences(path, - Strings(allPaths.begin(), allPaths.end())); + Strings(allPaths.begin(), allPaths.end())); /* Construct a slice element for this output path. */ SliceElem elem; diff --git a/src/util.cc b/src/util.cc index 1e1c799ece6d..c7ae711bbac7 100644 --- a/src/util.cc +++ b/src/util.cc @@ -106,13 +106,13 @@ bool pathExists(const string & path) } -void deletePath(string path) +void deletePath(const string & path) { msg(lvlVomit, format("deleting path `%1%'") % path); struct stat st; if (lstat(path.c_str(), &st)) - throw SysError(format("getting attributes of path %1%") % path); + throw SysError(format("getting attributes of path `%1%'") % path); if (S_ISDIR(st.st_mode)) { Strings names; @@ -128,12 +128,44 @@ void deletePath(string path) closedir(dir); /* !!! close on exception */ + /* Make the directory writable. */ + if (!(st.st_mode & S_IWUSR)) { + if (chmod(path.c_str(), st.st_mode | S_IWUSR) == -1) + throw SysError(format("making `%1%' writable")); + } + for (Strings::iterator i = names.begin(); i != names.end(); i++) deletePath(path + "/" + *i); } if (remove(path.c_str()) == -1) - throw SysError(format("cannot unlink %1%") % path); + throw SysError(format("cannot unlink `%1%'") % path); +} + + +void makePathReadOnly(const string & path) +{ + struct stat st; + if (lstat(path.c_str(), &st)) + throw SysError(format("getting attributes of path `%1%'") % path); + + if (st.st_mode & S_IWUSR) { + if (chmod(path.c_str(), st.st_mode & ~S_IWUSR) == -1) + throw SysError(format("making `%1%' read-only")); + } + + if (S_ISDIR(st.st_mode)) { + DIR * dir = opendir(path.c_str()); + + struct dirent * dirent; + while (errno = 0, dirent = readdir(dir)) { + string name = dirent->d_name; + if (name == "." || name == "..") continue; + makePathReadOnly(path + "/" + name); + } + + closedir(dir); /* !!! close on exception */ + } } diff --git a/src/util.hh b/src/util.hh index 2863085c16f9..d0e42f3b1707 100644 --- a/src/util.hh +++ b/src/util.hh @@ -67,7 +67,10 @@ bool pathExists(const string & path); /* Delete a path; i.e., in the case of a directory, it is deleted recursively. Don't use this at home, kids. */ -void deletePath(string path); +void deletePath(const string & path); + +/* Make a path read-only recursively. */ +void makePathReadOnly(const string & path); /* Messages. */ |