rustc_back: Rewrite realpath to not use old_io

Just bind the relevant platform-specific functions we should probably be calling
anyway.
This commit is contained in:
Alex Crichton 2015-04-09 18:04:11 -07:00
parent bf4e77d4b5
commit 359ab0b56b
3 changed files with 63 additions and 66 deletions

View File

@ -8,70 +8,67 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use libc;
use std::io;
use std::env;
#[allow(deprecated)] use std::old_path::{self, GenericPath};
#[allow(deprecated)] use std::old_io;
use std::path::{Path, PathBuf};
/// Returns an absolute path in the filesystem that `path` points to. The
/// returned path does not contain any symlinks in its hierarchy.
#[allow(deprecated)] // readlink is deprecated
#[cfg(windows)]
pub fn realpath(original: &Path) -> io::Result<PathBuf> {
let old = old_path::Path::new(original.to_str().unwrap());
match old_realpath(&old) {
Ok(p) => Ok(PathBuf::from(p.as_str().unwrap())),
Err(e) => Err(io::Error::new(io::ErrorKind::Other, e))
use std::fs::File;
use std::ffi::OsString;
use std::os::windows::prelude::*;
extern "system" {
fn GetFinalPathNameByHandleW(hFile: libc::HANDLE,
lpszFilePath: libc::LPCWSTR,
cchFilePath: libc::DWORD,
dwFlags: libc::DWORD) -> libc::DWORD;
}
let mut v = Vec::with_capacity(16 * 1024);
let f = try!(File::open(original));
unsafe {
let ret = GetFinalPathNameByHandleW(f.as_raw_handle(),
v.as_mut_ptr(),
v.capacity() as libc::DWORD,
libc::VOLUME_NAME_DOS);
if ret == 0 {
return Err(io::Error::last_os_error())
}
assert!(ret as usize < v.capacit());
v.set_len(ret);
}
Ok(PathBuf::from(OsString::from_wide(&v)))
}
#[allow(deprecated)]
fn old_realpath(original: &old_path::Path) -> old_io::IoResult<old_path::Path> {
use std::old_io::fs;
const MAX_LINKS_FOLLOWED: usize = 256;
let original = old_path::Path::new(env::current_dir().unwrap()
.to_str().unwrap()).join(original);
#[cfg(unix)]
pub fn realpath(original: &Path) -> io::Result<PathBuf> {
use std::os::unix::prelude::*;
use std::ffi::{OsString, CString};
// Right now lstat on windows doesn't work quite well
if cfg!(windows) {
return Ok(original)
extern {
fn realpath(pathname: *const libc::c_char, resolved: *mut libc::c_char)
-> *mut libc::c_char;
}
let result = original.root_path();
let mut result = result.expect("make_absolute has no root_path");
let mut followed = 0;
for part in original.components() {
result.push(part);
loop {
if followed == MAX_LINKS_FOLLOWED {
return Err(old_io::standard_error(old_io::InvalidInput))
}
match fs::lstat(&result) {
Err(..) => break,
Ok(ref stat) if stat.kind != old_io::FileType::Symlink => break,
Ok(..) => {
followed += 1;
let path = try!(fs::readlink(&result));
result.pop();
result.push(path);
}
}
let path = try!(CString::new(original.as_os_str().as_bytes()));
let mut buf = vec![0u8; 16 * 1024];
unsafe {
let r = realpath(path.as_ptr(), buf.as_mut_ptr() as *mut _);
if r.is_null() {
return Err(io::Error::last_os_error())
}
}
return Ok(result);
let p = buf.iter().position(|i| *i == 0).unwrap();
buf.truncate(p);
Ok(PathBuf::from(OsString::from_vec(buf)))
}
#[cfg(all(not(windows), test))]
mod test {
use std::old_io;
use std::old_io::fs::{File, symlink, mkdir, mkdir_recursive};
use super::old_realpath as realpath;
use std::old_io::TempDir;
use std::old_path::{Path, GenericPath};
use tempdir::TempDir;
use std::fs::{self, File};
use std::path::{Path, PathBuf};
#[test]
fn realpath_works() {
@ -83,15 +80,15 @@ mod test {
let linkdir = tmpdir.join("test3");
File::create(&file).unwrap();
mkdir(&dir, old_io::USER_RWX).unwrap();
symlink(&file, &link).unwrap();
symlink(&dir, &linkdir).unwrap();
fs::create_dir(&dir).unwrap();
fs::soft_link(&file, &link).unwrap();
fs::soft_link(&dir, &linkdir).unwrap();
assert!(realpath(&tmpdir).unwrap() == tmpdir);
assert!(realpath(&file).unwrap() == file);
assert!(realpath(&link).unwrap() == file);
assert!(realpath(&linkdir).unwrap() == dir);
assert!(realpath(&linkdir.join("link")).unwrap() == file);
assert_eq!(realpath(&tmpdir).unwrap(), tmpdir);
assert_eq!(realpath(&file).unwrap(), file);
assert_eq!(realpath(&link).unwrap(), file);
assert_eq!(realpath(&linkdir).unwrap(), dir);
assert_eq!(realpath(&linkdir.join("link")).unwrap(), file);
}
#[test]
@ -106,13 +103,13 @@ mod test {
let e = d.join("e");
let f = a.join("f");
mkdir_recursive(&b, old_io::USER_RWX).unwrap();
mkdir_recursive(&d, old_io::USER_RWX).unwrap();
fs::create_dir_all(&b).unwrap();
fs::create_dir_all(&d).unwrap();
File::create(&f).unwrap();
symlink(&Path::new("../d/e"), &c).unwrap();
symlink(&Path::new("../f"), &e).unwrap();
fs::soft_link("../d/e", &c).unwrap();
fs::soft_link("../f", &e).unwrap();
assert!(realpath(&c).unwrap() == f);
assert!(realpath(&e).unwrap() == f);
assert_eq!(realpath(&c).unwrap(), f);
assert_eq!(realpath(&e).unwrap(), f);
}
}

View File

@ -35,17 +35,16 @@
#![feature(box_syntax)]
#![feature(collections)]
#![feature(core)]
#![feature(old_fs)]
#![feature(old_io)]
#![feature(old_path)]
#![feature(rustc_private)]
#![feature(staged_api)]
#![feature(rand)]
#![feature(path_ext)]
#![feature(step_by)]
#![feature(libc)]
#![cfg_attr(test, feature(test, rand))]
extern crate syntax;
extern crate libc;
extern crate serialize;
#[macro_use] extern crate log;

View File

@ -97,8 +97,9 @@ fn get_rpath_relative_to_output(config: &mut RPathConfig, lib: &Path) -> String
let cwd = env::current_dir().unwrap();
let mut lib = (config.realpath)(&cwd.join(lib)).unwrap();
lib.pop();
let mut output = (config.realpath)(&cwd.join(&config.out_filename)).unwrap();
let mut output = cwd.join(&config.out_filename);
output.pop();
let output = (config.realpath)(&output).unwrap();
let relative = path_relative_from(&lib, &output)
.expect(&format!("couldn't create relative path from {:?} to {:?}", output, lib));
// FIXME (#9639): This needs to handle non-utf8 paths