about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2003-08-22T20·12+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2003-08-22T20·12+0000
commita88144215c263e62528108dfae1e781058344ef2 (patch)
treeff44455c3a5a5d4e6b3a556c78cc1511f7630378
parent56b98c3857b89d4f81f0127c53cfce6d8e48a71f (diff)
* Remove write permission from output paths after they have been built.
* Point $HOME to a non-existing path when building to prevent certain tools (such as 
  wget) from falling back on /etc/passwd to locate the home directory (which we 
  don't want them to look at since it's not declared as an input).

-rw-r--r--src/normalise.cc15
-rw-r--r--src/util.cc38
-rw-r--r--src/util.hh5
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. */