Skip to content

Commit f0feb20

Browse files
committed
std: Expand the area of std::fs
This commit is an implementation of [RFC 1044][rfc] which adds additional surface area to the `std::fs` module. All new APIs are `#[unstable]` behind assorted feature names for each one. [rfc]: rust-lang/rfcs#1044 The new APIs added are: * `fs::canonicalize` - bindings to `realpath` on unix and `GetFinalPathNameByHandle` on windows. * `fs::symlink_metadata` - similar to `lstat` on unix * `fs::FileType` and accessor methods as `is_{file,dir,symlink}` * `fs::Metadata::file_type` - accessor for the raw file type * `fs::DirEntry::metadata` - acquisition of metadata which is free on Windows but requires a syscall on unix. * `fs::DirEntry::file_type` - access the file type which may not require a syscall on most platforms. * `fs::DirEntry::file_name` - access just the file name without leading components. * `fs::PathExt::symlink_metadata` - convenience method for the top-level function. * `fs::PathExt::canonicalize` - convenience method for the top-level function. * `fs::PathExt::read_link` - convenience method for the top-level function. * `fs::PathExt::read_dir` - convenience method for the top-level function. * `std::os::raw` - type definitions for raw OS/C types available on all platforms. * `std::os::$platform` - new modules have been added for all currently supported platforms (e.g. those more specific than just `unix`). * `std::os::$platform::raw` - platform-specific type definitions. These modules are populated with the bare essentials necessary for lowing I/O types into their raw representations, and currently largely consist of the `stat` definition for unix platforms. This commit also deprecates `Metadata::{modified, accessed}` in favor of inspecting the raw representations via the lowering methods of `Metadata`.
1 parent 5c96369 commit f0feb20

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+2389
-909
lines changed

src/librustc/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#![feature(path_ext)]
4141
#![feature(str_char)]
4242
#![feature(into_cow)]
43+
#![feature(fs_canonicalize)]
4344
#![feature(slice_patterns)]
4445
#![cfg_attr(test, feature(test))]
4546

@@ -137,7 +138,6 @@ pub mod plugin;
137138
pub mod lint;
138139

139140
pub mod util {
140-
pub use rustc_back::fs;
141141
pub use rustc_back::sha2;
142142

143143
pub mod common;

src/librustc/metadata/creader.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ use metadata::decoder;
2121
use metadata::loader;
2222
use metadata::loader::CratePaths;
2323

24-
use std::path::{Path, PathBuf};
24+
use std::path::PathBuf;
2525
use std::rc::Rc;
26+
use std::fs;
27+
2628
use syntax::ast;
2729
use syntax::abi;
2830
use syntax::attr;
@@ -32,7 +34,6 @@ use syntax::parse;
3234
use syntax::parse::token::InternedString;
3335
use syntax::parse::token;
3436
use syntax::visit;
35-
use util::fs;
3637
use log;
3738

3839
pub struct CrateReader<'a> {
@@ -322,7 +323,7 @@ impl<'a> CrateReader<'a> {
322323
let source = self.sess.cstore.get_used_crate_source(cnum).unwrap();
323324
if let Some(locs) = self.sess.opts.externs.get(name) {
324325
let found = locs.iter().any(|l| {
325-
let l = fs::realpath(&Path::new(&l[..])).ok();
326+
let l = fs::canonicalize(l).ok();
326327
source.dylib.as_ref().map(|p| &p.0) == l.as_ref() ||
327328
source.rlib.as_ref().map(|p| &p.0) == l.as_ref()
328329
});

src/librustc/metadata/filesearch.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use std::fs;
1818
use std::io::prelude::*;
1919
use std::path::{Path, PathBuf};
2020

21-
use util::fs as myfs;
2221
use session::search_paths::{SearchPaths, PathKind};
2322

2423
#[derive(Copy, Clone)]
@@ -191,7 +190,7 @@ pub fn get_or_default_sysroot() -> PathBuf {
191190
// Follow symlinks. If the resolved path is relative, make it absolute.
192191
fn canonicalize(path: Option<PathBuf>) -> Option<PathBuf> {
193192
path.and_then(|path| {
194-
match myfs::realpath(&path) {
193+
match fs::canonicalize(&path) {
195194
Ok(canon) => Some(canon),
196195
Err(e) => panic!("failed to get realpath: {}", e),
197196
}

src/librustc/metadata/loader.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -225,12 +225,12 @@ use metadata::encoder;
225225
use metadata::filesearch::{FileSearch, FileMatches, FileDoesntMatch};
226226
use syntax::codemap::Span;
227227
use syntax::diagnostic::SpanHandler;
228-
use util::fs;
229228
use util::common;
230229
use rustc_back::target::Target;
231230

232231
use std::cmp;
233232
use std::collections::HashMap;
233+
use std::fs;
234234
use std::io::prelude::*;
235235
use std::io;
236236
use std::path::{Path, PathBuf};
@@ -430,9 +430,9 @@ impl<'a> Context<'a> {
430430
.or_insert_with(|| (HashMap::new(), HashMap::new()));
431431
let (ref mut rlibs, ref mut dylibs) = *slot;
432432
if rlib {
433-
rlibs.insert(fs::realpath(path).unwrap(), kind);
433+
rlibs.insert(fs::canonicalize(path).unwrap(), kind);
434434
} else {
435-
dylibs.insert(fs::realpath(path).unwrap(), kind);
435+
dylibs.insert(fs::canonicalize(path).unwrap(), kind);
436436
}
437437

438438
FileMatches
@@ -660,10 +660,10 @@ impl<'a> Context<'a> {
660660
// there's at most one rlib and at most one dylib.
661661
for loc in locs {
662662
if loc.file_name().unwrap().to_str().unwrap().ends_with(".rlib") {
663-
rlibs.insert(fs::realpath(&loc).unwrap(),
663+
rlibs.insert(fs::canonicalize(&loc).unwrap(),
664664
PathKind::ExternFlag);
665665
} else {
666-
dylibs.insert(fs::realpath(&loc).unwrap(),
666+
dylibs.insert(fs::canonicalize(&loc).unwrap(),
667667
PathKind::ExternFlag);
668668
}
669669
}

src/librustc_back/fs.rs

-91
This file was deleted.

src/librustc_back/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#![feature(path_ext)]
4242
#![feature(step_by)]
4343
#![feature(libc)]
44+
#![feature(fs_canonicalize)]
4445
#![cfg_attr(test, feature(test, rand))]
4546

4647
extern crate syntax;
@@ -53,7 +54,6 @@ pub mod abi;
5354
pub mod archive;
5455
pub mod tempdir;
5556
pub mod arm;
56-
pub mod fs;
5757
pub mod mips;
5858
pub mod mipsel;
5959
pub mod rpath;

src/librustc_back/rpath.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010

1111
use std::collections::HashSet;
1212
use std::env;
13-
use std::io;
1413
use std::path::{Path, PathBuf};
14+
use std::fs;
1515
use syntax::ast;
1616

1717
pub struct RPathConfig<'a> {
@@ -20,7 +20,6 @@ pub struct RPathConfig<'a> {
2020
pub is_like_osx: bool,
2121
pub has_rpath: bool,
2222
pub get_install_prefix_lib_path: &'a mut FnMut() -> PathBuf,
23-
pub realpath: &'a mut FnMut(&Path) -> io::Result<PathBuf>,
2423
}
2524

2625
pub fn get_rpath_flags(config: &mut RPathConfig) -> Vec<String> {
@@ -95,11 +94,11 @@ fn get_rpath_relative_to_output(config: &mut RPathConfig, lib: &Path) -> String
9594
};
9695

9796
let cwd = env::current_dir().unwrap();
98-
let mut lib = (config.realpath)(&cwd.join(lib)).unwrap();
97+
let mut lib = fs::canonicalize(&cwd.join(lib)).unwrap_or(cwd.join(lib));
9998
lib.pop();
10099
let mut output = cwd.join(&config.out_filename);
101100
output.pop();
102-
let output = (config.realpath)(&output).unwrap();
101+
let output = fs::canonicalize(&output).unwrap_or(output);
103102
let relative = path_relative_from(&lib, &output)
104103
.expect(&format!("couldn't create relative path from {:?} to {:?}", output, lib));
105104
// FIXME (#9639): This needs to handle non-utf8 paths
@@ -231,7 +230,6 @@ mod test {
231230
is_like_osx: true,
232231
out_filename: PathBuf::from("bin/rustc"),
233232
get_install_prefix_lib_path: &mut || panic!(),
234-
realpath: &mut |p| Ok(p.to_path_buf()),
235233
};
236234
let res = get_rpath_relative_to_output(config,
237235
Path::new("lib/libstd.so"));
@@ -243,7 +241,6 @@ mod test {
243241
get_install_prefix_lib_path: &mut || panic!(),
244242
has_rpath: true,
245243
is_like_osx: false,
246-
realpath: &mut |p| Ok(p.to_path_buf()),
247244
};
248245
let res = get_rpath_relative_to_output(config,
249246
Path::new("lib/libstd.so"));

src/librustc_trans/back/link.rs

+32-6
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use std::ffi::OsString;
3232
use std::fs::{self, PathExt};
3333
use std::io::{self, Read, Write};
3434
use std::mem;
35-
use std::path::{Path, PathBuf};
35+
use std::path::{self, Path, PathBuf};
3636
use std::process::Command;
3737
use std::str;
3838
use flate;
@@ -916,8 +916,9 @@ fn link_args(cmd: &mut Command,
916916
// stripped away as much as it could. This has not been seen to impact
917917
// link times negatively.
918918
//
919-
// -dead_strip can't be part of the pre_link_args because it's also used for partial
920-
// linking when using multiple codegen units (-r). So we insert it here.
919+
// -dead_strip can't be part of the pre_link_args because it's also used
920+
// for partial linking when using multiple codegen units (-r). So we
921+
// insert it here.
921922
cmd.arg("-Wl,-dead_strip");
922923
}
923924

@@ -1043,7 +1044,6 @@ fn link_args(cmd: &mut Command,
10431044
has_rpath: sess.target.target.options.has_rpath,
10441045
is_like_osx: sess.target.target.options.is_like_osx,
10451046
get_install_prefix_lib_path: &mut get_install_prefix_lib_path,
1046-
realpath: &mut ::util::fs::realpath
10471047
};
10481048
cmd.args(&rpath::get_rpath_flags(&mut rpath_config));
10491049
}
@@ -1258,7 +1258,7 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session,
12581258
}
12591259
});
12601260
} else {
1261-
cmd.arg(cratepath);
1261+
cmd.arg(&fix_windows_verbatim_for_gcc(cratepath));
12621262
}
12631263
}
12641264

@@ -1271,7 +1271,7 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session,
12711271
// Just need to tell the linker about where the library lives and
12721272
// what its name is
12731273
if let Some(dir) = cratepath.parent() {
1274-
cmd.arg("-L").arg(dir);
1274+
cmd.arg("-L").arg(&fix_windows_verbatim_for_gcc(dir));
12751275
}
12761276
let filestem = cratepath.file_stem().unwrap().to_str().unwrap();
12771277
cmd.arg(&format!("-l{}", unlib(&sess.target, filestem)));
@@ -1325,3 +1325,29 @@ fn add_upstream_native_libraries(cmd: &mut Command, sess: &Session) {
13251325
}
13261326
}
13271327
}
1328+
1329+
// Unfortunately, on windows, gcc cannot accept paths of the form `\\?\C:\...`
1330+
// (a verbatim path). This form of path is generally pretty rare, but the
1331+
// implementation of `fs::canonicalize` currently generates paths of this form,
1332+
// meaning that we're going to be passing quite a few of these down to gcc.
1333+
//
1334+
// For now we just strip the "verbatim prefix" of `\\?\` from the path. This
1335+
// will probably lose information in some cases, but there's not a whole lot
1336+
// more we can do with a buggy gcc...
1337+
fn fix_windows_verbatim_for_gcc(p: &Path) -> PathBuf {
1338+
if !cfg!(windows) {
1339+
return p.to_path_buf()
1340+
}
1341+
let mut components = p.components();
1342+
let prefix = match components.next() {
1343+
Some(path::Component::Prefix(p)) => p,
1344+
_ => return p.to_path_buf(),
1345+
};
1346+
let disk = match prefix.kind() {
1347+
path::Prefix::VerbatimDisk(disk) => disk,
1348+
_ => return p.to_path_buf(),
1349+
};
1350+
let mut base = OsString::from(format!("{}:", disk as char));
1351+
base.push(components.as_path());
1352+
PathBuf::from(base)
1353+
}

0 commit comments

Comments
 (0)