]> git.lizzy.rs Git - rust.git/commitdiff
rustc: Check that the output file is writeable before linking
authorTim Chevalier <chevalier@alum.wellesley.edu>
Thu, 3 Oct 2013 01:17:46 +0000 (18:17 -0700)
committerTim Chevalier <chevalier@alum.wellesley.edu>
Sat, 19 Oct 2013 01:36:23 +0000 (18:36 -0700)
This is because on Linux, the linker will silently overwrite
a read-only file.

src/librustc/back/link.rs
src/librustpkg/rustpkg.rs
src/librustpkg/tests.rs
src/librustpkg/util.rs

index 404efa25ff3320f0cc3d735fb564d0e84c3ec3ff..7028d8c42196ddd9cc3fad1cf595c78057551d8d 100644 (file)
@@ -959,6 +959,16 @@ pub fn link_binary(sess: Session,
     }
 }
 
+fn is_writeable(p: &Path) -> bool {
+    use std::libc::consts::os::posix88::S_IWUSR;
+
+    !os::path_exists(p) ||
+        (match p.get_mode() {
+            None => false,
+            Some(m) => m & S_IWUSR as uint == S_IWUSR as uint
+        })
+}
+
 pub fn link_args(sess: Session,
                  obj_filename: &Path,
                  out_filename: &Path,
@@ -982,6 +992,21 @@ fn unlib(config: @session::config, stem: ~str) -> ~str {
         out_filename.clone()
     };
 
+    // Make sure the output and obj_filename are both writeable.
+    // Mac, FreeBSD, and Windows system linkers check this already --
+    // however, the Linux linker will happily overwrite a read-only file.
+    // We should be consistent.
+    let obj_is_writeable = is_writeable(obj_filename);
+    let out_is_writeable = is_writeable(&output);
+    if !out_is_writeable {
+        sess.fatal(format!("Output file {} is not writeable -- check its permissions.",
+                           output.display()));
+    }
+    else if !obj_is_writeable {
+        sess.fatal(format!("Object file {} is not writeable -- check its permissions.",
+                           obj_filename.display()));
+    }
+
     // The default library location, we need this to find the runtime.
     // The location of crates will be determined as needed.
     // FIXME (#9639): This needs to handle non-utf8 paths
index affd53216659c5c96b4f55e85c43ed7777b8980e..e806e515c80e8809f33484a9e85b0fe55200cec9 100644 (file)
@@ -556,7 +556,7 @@ fn install(&self, mut pkg_src: PkgSrc, what: &WhatToBuild) -> (~[Path], ~[(~str,
         debug2!("In declare inputs for {}", id.to_str());
         for cs in to_do.iter() {
             for c in cs.iter() {
-                let path = pkg_src.start_dir.join(&c.file).normalize();
+                let path = pkg_src.start_dir.join(&c.file);
                 debug2!("Recording input: {}", path.display());
                 // FIXME (#9639): This needs to handle non-utf8 paths
                 inputs.push((~"file", path.as_str().unwrap().to_owned()));
@@ -623,19 +623,19 @@ fn install_no_build(&self,
                 // Declare all the *inputs* to the declared input too, as inputs
                 for executable in subex.iter() {
                     exe_thing.discover_input("binary",
-                                             executable.to_str(),
+                                             executable.as_str().unwrap().to_owned(),
                                              workcache_support::digest_only_date(executable));
                 }
                 for library in sublib.iter() {
                     exe_thing.discover_input("binary",
-                                             library.to_str(),
+                                             library.as_str().unwrap().to_owned(),
                                              workcache_support::digest_only_date(library));
                 }
 
                 for transitive_dependency in sub_build_inputs.iter() {
                     exe_thing.discover_input(
                         "file",
-                        transitive_dependency.to_str(),
+                        transitive_dependency.as_str().unwrap().to_owned(),
                         workcache_support::digest_file_with_date(transitive_dependency));
                 }
 
index d522bfb15e42dcac0b3b332a3072f1d9dd5319b9..8722a638c456d3d3f3f2f1388a3c7ee5bc7de3f9 100644 (file)
@@ -516,7 +516,7 @@ fn touch_source_file(workspace: &Path, pkgid: &PkgId) {
             // should be able to do this w/o a process
             // FIXME (#9639): This needs to handle non-utf8 paths
             // n.b. Bumps time up by 2 seconds to get around granularity issues
-            if run::process_output("touch", [~"-A", ~"02", p.to_str()]).status != 0 {
+            if run::process_output("touch", [~"-A", ~"02", p.as_str().unwrap().to_owned()]).status != 0 {
                 let _ = cond.raise((pkg_src_dir.clone(), ~"Bad path"));
             }
         }
index 12b4ce2a8811e2b8367965abe3d3d1e629bf387e..345518eddc7bb6b6f761b2150c55168a066e2872 100644 (file)
@@ -441,8 +441,8 @@ fn visit_view_item(&mut self, vi: &ast::view_item, env: ()) {
                         // Now we know that this crate has a discovered dependency on
                         // installed_path
                         // FIXME (#9639): This needs to handle non-utf8 paths
-                        add_dep(self.deps, self.parent_crate.to_str(),
-                                (~"binary", installed_path.to_str()));
+                        add_dep(self.deps, self.parent_crate.as_str().unwrap().to_owned(),
+                                (~"binary", installed_path.as_str().unwrap().to_owned()));
                         self.exec.discover_input("binary",
                                                  installed_path.as_str().unwrap(),
                                                  digest_only_date(installed_path));
@@ -492,6 +492,10 @@ fn visit_view_item(&mut self, vi: &ast::view_item, env: ()) {
                             self.exec.discover_input("binary",
                                                      dep.as_str().unwrap(),
                                                      digest_only_date(dep));
+                            add_dep(self.deps,
+                                    self.parent_crate.as_str().unwrap().to_owned(),
+                                    (~"binary", dep.as_str().unwrap().to_owned()));
+
                             // Also, add an additional search path
                             let dep_dir = dep.dir_path();
                             debug2!("Installed {} into {}", dep.display(), dep_dir.display());
@@ -502,41 +506,31 @@ fn visit_view_item(&mut self, vi: &ast::view_item, env: ()) {
                                 lib_name, outputs_disc.len(), inputs_disc.len());
                         // It must have installed *something*...
                         assert!(!outputs_disc.is_empty());
-                        let target_workspace = outputs_disc[0].pop();
-                        for dep in outputs_disc.iter() {
-                            debug2!("Discovering a binary input: {}", dep.to_str());
-                            self.exec.discover_input("binary", dep.to_str(),
-                                                     digest_only_date(dep));
-                            add_dep(self.deps,
-                                    self.parent_crate.to_str(),
-                                    (~"binary", dep.to_str()));
-                        }
+                        let mut target_workspace = outputs_disc[0].clone();
+                        target_workspace.pop();
                         for &(ref what, ref dep) in inputs_disc.iter() {
                             if *what == ~"file" {
                                 add_dep(self.deps,
-                                        self.parent_crate.to_str(),
-                                        (~"file", dep.to_str()));
-
+                                        self.parent_crate.as_str().unwrap().to_owned(),
+                                        (~"file", dep.clone()));
                                 self.exec.discover_input(*what,
                                                          *dep,
                                                          digest_file_with_date(
                                                              &Path::new(dep.as_slice())));
-                            }
-                                else if *what == ~"binary" {
+                            } else if *what == ~"binary" {
                                 add_dep(self.deps,
-                                        self.parent_crate.to_str(),
-                                        (~"binary", dep.to_str()));
+                                        self.parent_crate.as_str().unwrap().to_owned(),
+                                        (~"binary", dep.clone()));
                                 self.exec.discover_input(*what,
                                                          *dep,
                                                          digest_only_date(
                                                              &Path::new(dep.as_slice())));
-                            }
-                                else {
+                            } else {
                                 fail2!("Bad kind: {}", *what);
                             }
                             // Also, add an additional search path
                             debug2!("Installed {} into {}",
-                                    lib_name, target_workspace.to_str());
+                                    lib_name, target_workspace.as_str().unwrap().to_owned());
                             (self.save)(target_workspace.clone());
                         }
                     }