From 7edc16c7be4dab322305487d31e18c2b79ed26c5 Mon Sep 17 00:00:00 2001 From: Vadim Chugunov Date: Thu, 7 Apr 2016 22:49:48 -0700 Subject: [PATCH 1/2] Do not rely on file extensions after path canonicalization. --- src/librustc_metadata/loader.rs | 40 ++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/src/librustc_metadata/loader.rs b/src/librustc_metadata/loader.rs index c7cd8ae2dd7f3..be1e194efc33e 100644 --- a/src/librustc_metadata/loader.rs +++ b/src/librustc_metadata/loader.rs @@ -231,6 +231,7 @@ use rustc_back::target::Target; use std::cmp; use std::collections::HashMap; +use std::fmt; use std::fs; use std::io::prelude::*; use std::io; @@ -283,6 +284,21 @@ pub struct CratePaths { pub const METADATA_FILENAME: &'static str = "rust.metadata.bin"; +#[derive(Copy, Clone, PartialEq)] +enum CrateFlavor { + Rlib, + Dylib +} + +impl fmt::Display for CrateFlavor { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(match *self { + CrateFlavor::Rlib => "rlib", + CrateFlavor::Dylib => "dylib" + }) + } +} + impl CratePaths { fn paths(&self) -> Vec { match (&self.dylib, &self.rlib) { @@ -457,8 +473,8 @@ impl<'a> Context<'a> { let mut libraries = Vec::new(); for (_hash, (rlibs, dylibs)) in candidates { let mut metadata = None; - let rlib = self.extract_one(rlibs, "rlib", &mut metadata); - let dylib = self.extract_one(dylibs, "dylib", &mut metadata); + let rlib = self.extract_one(rlibs, CrateFlavor::Rlib, &mut metadata); + let dylib = self.extract_one(dylibs, CrateFlavor::Dylib, &mut metadata); match metadata { Some(metadata) => { libraries.push(Library { @@ -515,7 +531,7 @@ impl<'a> Context<'a> { // read the metadata from it if `*slot` is `None`. If the metadata couldn't // be read, it is assumed that the file isn't a valid rust library (no // errors are emitted). - fn extract_one(&mut self, m: HashMap, flavor: &str, + fn extract_one(&mut self, m: HashMap, flavor: CrateFlavor, slot: &mut Option) -> Option<(PathBuf, PathKind)> { let mut ret = None::<(PathBuf, PathKind)>; let mut error = 0; @@ -535,7 +551,7 @@ impl<'a> Context<'a> { let mut err: Option = None; for (lib, kind) in m { info!("{} reading metadata from: {}", flavor, lib.display()); - let metadata = match get_metadata_section(self.target, &lib) { + let metadata = match get_metadata_section(self.target, flavor, &lib) { Ok(blob) => { if self.crate_matches(blob.as_slice(), &lib) { blob @@ -702,8 +718,8 @@ impl<'a> Context<'a> { // Extract the rlib/dylib pair. let mut metadata = None; - let rlib = self.extract_one(rlibs, "rlib", &mut metadata); - let dylib = self.extract_one(dylibs, "dylib", &mut metadata); + let rlib = self.extract_one(rlibs, CrateFlavor::Rlib, &mut metadata); + let dylib = self.extract_one(dylibs, CrateFlavor::Dylib, &mut metadata); if rlib.is_none() && dylib.is_none() { return None } match metadata { @@ -746,21 +762,21 @@ impl ArchiveMetadata { } // Just a small wrapper to time how long reading metadata takes. -fn get_metadata_section(target: &Target, filename: &Path) +fn get_metadata_section(target: &Target, flavor: CrateFlavor, filename: &Path) -> Result { let start = Instant::now(); - let ret = get_metadata_section_imp(target, filename); + let ret = get_metadata_section_imp(target, flavor, filename); info!("reading {:?} => {:?}", filename.file_name().unwrap(), start.elapsed()); return ret } -fn get_metadata_section_imp(target: &Target, filename: &Path) +fn get_metadata_section_imp(target: &Target, flavor: CrateFlavor, filename: &Path) -> Result { if !filename.exists() { return Err(format!("no such file: '{}'", filename.display())); } - if filename.file_name().unwrap().to_str().unwrap().ends_with(".rlib") { + if flavor == CrateFlavor::Rlib { // Use ArchiveRO for speed here, it's backed by LLVM and uses mmap // internally to read the file. We also avoid even using a memcpy by // just keeping the archive along while the metadata is in use. @@ -864,7 +880,9 @@ pub fn read_meta_section_name(target: &Target) -> &'static str { // A diagnostic function for dumping crate metadata to an output stream pub fn list_file_metadata(target: &Target, path: &Path, out: &mut io::Write) -> io::Result<()> { - match get_metadata_section(target, path) { + let filename = path.file_name().unwrap().to_str().unwrap(); + let flavor = if filename.ends_with(".rlib") { CrateFlavor::Rlib } else { CrateFlavor::Dylib }; + match get_metadata_section(target, flavor, path) { Ok(bytes) => decoder::list_crate_metadata(bytes.as_slice(), out), Err(msg) => { write!(out, "{}\n", msg) From cc3b6f24b7604880279918b3c1a58ef62fb06b36 Mon Sep 17 00:00:00 2001 From: Vadim Chugunov Date: Fri, 8 Apr 2016 17:14:05 -0700 Subject: [PATCH 2/2] Added a test --- src/test/run-make/symlinked-rlib/Makefile | 14 ++++++++++++++ src/test/run-make/symlinked-rlib/bar.rs | 15 +++++++++++++++ src/test/run-make/symlinked-rlib/foo.rs | 11 +++++++++++ 3 files changed, 40 insertions(+) create mode 100644 src/test/run-make/symlinked-rlib/Makefile create mode 100644 src/test/run-make/symlinked-rlib/bar.rs create mode 100644 src/test/run-make/symlinked-rlib/foo.rs diff --git a/src/test/run-make/symlinked-rlib/Makefile b/src/test/run-make/symlinked-rlib/Makefile new file mode 100644 index 0000000000000..2709f786e0ab2 --- /dev/null +++ b/src/test/run-make/symlinked-rlib/Makefile @@ -0,0 +1,14 @@ +-include ../tools.mk + +# ignore windows: `ln` is actually `cp` on msys. +ifndef IS_WINDOWS + +all: + $(RUSTC) foo.rs --crate-type=rlib -o $(TMPDIR)/foo.xxx + ln -nsf $(TMPDIR)/foo.xxx $(TMPDIR)/libfoo.rlib + $(RUSTC) bar.rs -L $(TMPDIR) + +else +all: + +endif diff --git a/src/test/run-make/symlinked-rlib/bar.rs b/src/test/run-make/symlinked-rlib/bar.rs new file mode 100644 index 0000000000000..e8f06680862fc --- /dev/null +++ b/src/test/run-make/symlinked-rlib/bar.rs @@ -0,0 +1,15 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate foo; + +fn main() { + foo::bar(); +} diff --git a/src/test/run-make/symlinked-rlib/foo.rs b/src/test/run-make/symlinked-rlib/foo.rs new file mode 100644 index 0000000000000..5abbb1dcbcef2 --- /dev/null +++ b/src/test/run-make/symlinked-rlib/foo.rs @@ -0,0 +1,11 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn bar() {}