From 2addadc2de02f5c6080fca91a393eb3ceb4d99c8 Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Mon, 5 May 2014 14:53:57 -0700 Subject: [PATCH] Change dynamic_library::open_external to take ToCStr `std::unstable::dynamic_library::open_external` currently takes a `Path`, but because `Paths` produce normalized strings, this can change the semantics of lookups in a given environment. This patch generalizes the function to take a `ToCStr`-bounded type, which includes both `Path`s and `str`s. Closes #11650. --- src/libstd/unstable/dynamic_lib.rs | 31 ++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/libstd/unstable/dynamic_lib.rs b/src/libstd/unstable/dynamic_lib.rs index 1e88bffd00ea9..68bfde84e2a2d 100644 --- a/src/libstd/unstable/dynamic_lib.rs +++ b/src/libstd/unstable/dynamic_lib.rs @@ -45,12 +45,22 @@ impl Drop for DynamicLibrary { } impl DynamicLibrary { + // FIXME (#12938): Until DST lands, we cannot decompose &str into + // & and str, so we cannot usefully take ToCStr arguments by + // reference (without forcing an additional & around &str). So we + // are instead temporarily adding an instance for &Path, so that + // we can take ToCStr as owned. When DST lands, the &Path instance + // should be removed, and arguments bound by ToCStr should be + // passed by reference. (Here: in the `open` method.) + /// Lazily open a dynamic library. When passed None it gives a /// handle to the calling process - pub fn open(filename: Option<&path::Path>) -> Result { + pub fn open(filename: Option) + -> Result { unsafe { + let mut filename = filename; let maybe_library = dl::check_for_errors_in(|| { - match filename { + match filename.take() { Some(name) => dl::open_external(name), None => dl::open_internal() } @@ -114,7 +124,8 @@ mod test { fn test_loading_cosine() { // The math library does not need to be loaded since it is already // statically linked in - let libm = match DynamicLibrary::open(None) { + let none: Option = None; // appease the typechecker + let libm = match DynamicLibrary::open(none) { Err(error) => fail!("Could not load self as module: {}", error), Ok(libm) => libm }; @@ -142,7 +153,7 @@ mod test { fn test_errors_do_not_crash() { // Open /dev/null as a library to get an error, and make sure // that only causes an error, and not a crash. - let path = GenericPath::new("/dev/null"); + let path = Path::new("/dev/null"); match DynamicLibrary::open(Some(&path)) { Err(_) => {} Ok(_) => fail!("Successfully opened the empty library.") @@ -157,12 +168,11 @@ mod test { pub mod dl { use c_str::ToCStr; use libc; - use path; use ptr; use str; use result::*; - pub unsafe fn open_external(filename: &path::Path) -> *u8 { + pub unsafe fn open_external(filename: T) -> *u8 { filename.with_c_str(|raw_name| { dlopen(raw_name, Lazy as libc::c_int) as *u8 }) @@ -223,9 +233,14 @@ pub mod dl { use os; use ptr; use result::{Ok, Err, Result}; + use str; + use c_str::ToCStr; - pub unsafe fn open_external(filename: &path::Path) -> *u8 { - os::win32::as_utf16_p(filename.as_str().unwrap(), |raw_name| { + pub unsafe fn open_external(filename: T) -> *u8 { + // Windows expects Unicode data + let filename_cstr = filename.to_c_str(); + let filename_str = str::from_utf8(filename_cstr.as_bytes_no_nul()).unwrap(); + os::win32::as_utf16_p(filename_str, |raw_name| { LoadLibraryW(raw_name as *libc::c_void) as *u8 }) }