mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 07:14:28 +00:00
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]: https://github.com/rust-lang/rfcs/pull/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`.
This commit is contained in:
parent
b772ce6342
commit
9348700007
@ -40,6 +40,7 @@
|
||||
#![feature(path_ext)]
|
||||
#![feature(str_char)]
|
||||
#![feature(into_cow)]
|
||||
#![feature(fs_canonicalize)]
|
||||
#![feature(slice_patterns)]
|
||||
#![cfg_attr(test, feature(test))]
|
||||
|
||||
@ -139,7 +140,6 @@ pub mod plugin;
|
||||
pub mod lint;
|
||||
|
||||
pub mod util {
|
||||
pub use rustc_back::fs;
|
||||
pub use rustc_back::sha2;
|
||||
|
||||
pub mod common;
|
||||
|
@ -21,8 +21,10 @@ use metadata::decoder;
|
||||
use metadata::loader;
|
||||
use metadata::loader::CratePaths;
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use std::fs;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::abi;
|
||||
use syntax::attr;
|
||||
@ -32,7 +34,6 @@ use syntax::parse;
|
||||
use syntax::parse::token::InternedString;
|
||||
use syntax::parse::token;
|
||||
use syntax::visit;
|
||||
use util::fs;
|
||||
use log;
|
||||
|
||||
pub struct CrateReader<'a> {
|
||||
@ -322,7 +323,7 @@ impl<'a> CrateReader<'a> {
|
||||
let source = self.sess.cstore.get_used_crate_source(cnum).unwrap();
|
||||
if let Some(locs) = self.sess.opts.externs.get(name) {
|
||||
let found = locs.iter().any(|l| {
|
||||
let l = fs::realpath(&Path::new(&l[..])).ok();
|
||||
let l = fs::canonicalize(l).ok();
|
||||
source.dylib.as_ref().map(|p| &p.0) == l.as_ref() ||
|
||||
source.rlib.as_ref().map(|p| &p.0) == l.as_ref()
|
||||
});
|
||||
|
@ -18,7 +18,6 @@ use std::fs;
|
||||
use std::io::prelude::*;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use util::fs as myfs;
|
||||
use session::search_paths::{SearchPaths, PathKind};
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
@ -191,7 +190,7 @@ pub fn get_or_default_sysroot() -> PathBuf {
|
||||
// Follow symlinks. If the resolved path is relative, make it absolute.
|
||||
fn canonicalize(path: Option<PathBuf>) -> Option<PathBuf> {
|
||||
path.and_then(|path| {
|
||||
match myfs::realpath(&path) {
|
||||
match fs::canonicalize(&path) {
|
||||
Ok(canon) => Some(canon),
|
||||
Err(e) => panic!("failed to get realpath: {}", e),
|
||||
}
|
||||
|
@ -225,12 +225,12 @@ use metadata::encoder;
|
||||
use metadata::filesearch::{FileSearch, FileMatches, FileDoesntMatch};
|
||||
use syntax::codemap::Span;
|
||||
use syntax::diagnostic::SpanHandler;
|
||||
use util::fs;
|
||||
use util::common;
|
||||
use rustc_back::target::Target;
|
||||
|
||||
use std::cmp;
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::io::prelude::*;
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
@ -430,9 +430,9 @@ impl<'a> Context<'a> {
|
||||
.or_insert_with(|| (HashMap::new(), HashMap::new()));
|
||||
let (ref mut rlibs, ref mut dylibs) = *slot;
|
||||
if rlib {
|
||||
rlibs.insert(fs::realpath(path).unwrap(), kind);
|
||||
rlibs.insert(fs::canonicalize(path).unwrap(), kind);
|
||||
} else {
|
||||
dylibs.insert(fs::realpath(path).unwrap(), kind);
|
||||
dylibs.insert(fs::canonicalize(path).unwrap(), kind);
|
||||
}
|
||||
|
||||
FileMatches
|
||||
@ -660,10 +660,10 @@ impl<'a> Context<'a> {
|
||||
// there's at most one rlib and at most one dylib.
|
||||
for loc in locs {
|
||||
if loc.file_name().unwrap().to_str().unwrap().ends_with(".rlib") {
|
||||
rlibs.insert(fs::realpath(&loc).unwrap(),
|
||||
rlibs.insert(fs::canonicalize(&loc).unwrap(),
|
||||
PathKind::ExternFlag);
|
||||
} else {
|
||||
dylibs.insert(fs::realpath(&loc).unwrap(),
|
||||
dylibs.insert(fs::canonicalize(&loc).unwrap(),
|
||||
PathKind::ExternFlag);
|
||||
}
|
||||
}
|
||||
|
@ -1,91 +0,0 @@
|
||||
// Copyright 2014 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn realpath(original: &Path) -> io::Result<PathBuf> {
|
||||
Ok(original.to_path_buf())
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub fn realpath(original: &Path) -> io::Result<PathBuf> {
|
||||
use libc;
|
||||
use std::ffi::{OsString, CString};
|
||||
use std::os::unix::prelude::*;
|
||||
|
||||
extern {
|
||||
fn realpath(pathname: *const libc::c_char, resolved: *mut libc::c_char)
|
||||
-> *mut libc::c_char;
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
||||
}
|
||||
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 tests {
|
||||
use tempdir::TempDir;
|
||||
use std::fs::{self, File};
|
||||
use super::realpath;
|
||||
|
||||
#[test]
|
||||
fn realpath_works() {
|
||||
let tmpdir = TempDir::new("rustc-fs").unwrap();
|
||||
let tmpdir = realpath(tmpdir.path()).unwrap();
|
||||
let file = tmpdir.join("test");
|
||||
let dir = tmpdir.join("test2");
|
||||
let link = dir.join("link");
|
||||
let linkdir = tmpdir.join("test3");
|
||||
|
||||
File::create(&file).unwrap();
|
||||
fs::create_dir(&dir).unwrap();
|
||||
fs::soft_link(&file, &link).unwrap();
|
||||
fs::soft_link(&dir, &linkdir).unwrap();
|
||||
|
||||
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]
|
||||
fn realpath_works_tricky() {
|
||||
let tmpdir = TempDir::new("rustc-fs").unwrap();
|
||||
let tmpdir = realpath(tmpdir.path()).unwrap();
|
||||
|
||||
let a = tmpdir.join("a");
|
||||
let b = a.join("b");
|
||||
let c = b.join("c");
|
||||
let d = a.join("d");
|
||||
let e = d.join("e");
|
||||
let f = a.join("f");
|
||||
|
||||
fs::create_dir_all(&b).unwrap();
|
||||
fs::create_dir_all(&d).unwrap();
|
||||
File::create(&f).unwrap();
|
||||
fs::soft_link("../d/e", &c).unwrap();
|
||||
fs::soft_link("../f", &e).unwrap();
|
||||
|
||||
assert_eq!(realpath(&c).unwrap(), f);
|
||||
assert_eq!(realpath(&e).unwrap(), f);
|
||||
}
|
||||
}
|
@ -41,6 +41,7 @@
|
||||
#![feature(path_ext)]
|
||||
#![feature(step_by)]
|
||||
#![feature(libc)]
|
||||
#![feature(fs_canonicalize)]
|
||||
#![cfg_attr(test, feature(test, rand))]
|
||||
|
||||
extern crate syntax;
|
||||
@ -53,7 +54,6 @@ pub mod abi;
|
||||
pub mod archive;
|
||||
pub mod tempdir;
|
||||
pub mod arm;
|
||||
pub mod fs;
|
||||
pub mod mips;
|
||||
pub mod mipsel;
|
||||
pub mod rpath;
|
||||
|
@ -10,8 +10,8 @@
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::env;
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::fs;
|
||||
use syntax::ast;
|
||||
|
||||
pub struct RPathConfig<'a> {
|
||||
@ -20,7 +20,6 @@ pub struct RPathConfig<'a> {
|
||||
pub is_like_osx: bool,
|
||||
pub has_rpath: bool,
|
||||
pub get_install_prefix_lib_path: &'a mut FnMut() -> PathBuf,
|
||||
pub realpath: &'a mut FnMut(&Path) -> io::Result<PathBuf>,
|
||||
}
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
let cwd = env::current_dir().unwrap();
|
||||
let mut lib = (config.realpath)(&cwd.join(lib)).unwrap();
|
||||
let mut lib = fs::canonicalize(&cwd.join(lib)).unwrap_or(cwd.join(lib));
|
||||
lib.pop();
|
||||
let mut output = cwd.join(&config.out_filename);
|
||||
output.pop();
|
||||
let output = (config.realpath)(&output).unwrap();
|
||||
let output = fs::canonicalize(&output).unwrap_or(output);
|
||||
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
|
||||
@ -231,7 +230,6 @@ mod tests {
|
||||
is_like_osx: true,
|
||||
out_filename: PathBuf::from("bin/rustc"),
|
||||
get_install_prefix_lib_path: &mut || panic!(),
|
||||
realpath: &mut |p| Ok(p.to_path_buf()),
|
||||
};
|
||||
let res = get_rpath_relative_to_output(config,
|
||||
Path::new("lib/libstd.so"));
|
||||
@ -243,7 +241,6 @@ mod tests {
|
||||
get_install_prefix_lib_path: &mut || panic!(),
|
||||
has_rpath: true,
|
||||
is_like_osx: false,
|
||||
realpath: &mut |p| Ok(p.to_path_buf()),
|
||||
};
|
||||
let res = get_rpath_relative_to_output(config,
|
||||
Path::new("lib/libstd.so"));
|
||||
|
@ -32,7 +32,7 @@ use std::ffi::OsString;
|
||||
use std::fs::{self, PathExt};
|
||||
use std::io::{self, Read, Write};
|
||||
use std::mem;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::{self, Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use std::str;
|
||||
use flate;
|
||||
@ -916,8 +916,9 @@ fn link_args(cmd: &mut Command,
|
||||
// stripped away as much as it could. This has not been seen to impact
|
||||
// link times negatively.
|
||||
//
|
||||
// -dead_strip can't be part of the pre_link_args because it's also used for partial
|
||||
// linking when using multiple codegen units (-r). So we insert it here.
|
||||
// -dead_strip can't be part of the pre_link_args because it's also used
|
||||
// for partial linking when using multiple codegen units (-r). So we
|
||||
// insert it here.
|
||||
cmd.arg("-Wl,-dead_strip");
|
||||
}
|
||||
|
||||
@ -1043,7 +1044,6 @@ fn link_args(cmd: &mut Command,
|
||||
has_rpath: sess.target.target.options.has_rpath,
|
||||
is_like_osx: sess.target.target.options.is_like_osx,
|
||||
get_install_prefix_lib_path: &mut get_install_prefix_lib_path,
|
||||
realpath: &mut ::util::fs::realpath
|
||||
};
|
||||
cmd.args(&rpath::get_rpath_flags(&mut rpath_config));
|
||||
}
|
||||
@ -1258,7 +1258,7 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session,
|
||||
}
|
||||
});
|
||||
} else {
|
||||
cmd.arg(cratepath);
|
||||
cmd.arg(&fix_windows_verbatim_for_gcc(cratepath));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1271,7 +1271,7 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session,
|
||||
// Just need to tell the linker about where the library lives and
|
||||
// what its name is
|
||||
if let Some(dir) = cratepath.parent() {
|
||||
cmd.arg("-L").arg(dir);
|
||||
cmd.arg("-L").arg(&fix_windows_verbatim_for_gcc(dir));
|
||||
}
|
||||
let filestem = cratepath.file_stem().unwrap().to_str().unwrap();
|
||||
cmd.arg(&format!("-l{}", unlib(&sess.target, filestem)));
|
||||
@ -1325,3 +1325,29 @@ fn add_upstream_native_libraries(cmd: &mut Command, sess: &Session) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unfortunately, on windows, gcc cannot accept paths of the form `\\?\C:\...`
|
||||
// (a verbatim path). This form of path is generally pretty rare, but the
|
||||
// implementation of `fs::canonicalize` currently generates paths of this form,
|
||||
// meaning that we're going to be passing quite a few of these down to gcc.
|
||||
//
|
||||
// For now we just strip the "verbatim prefix" of `\\?\` from the path. This
|
||||
// will probably lose information in some cases, but there's not a whole lot
|
||||
// more we can do with a buggy gcc...
|
||||
fn fix_windows_verbatim_for_gcc(p: &Path) -> PathBuf {
|
||||
if !cfg!(windows) {
|
||||
return p.to_path_buf()
|
||||
}
|
||||
let mut components = p.components();
|
||||
let prefix = match components.next() {
|
||||
Some(path::Component::Prefix(p)) => p,
|
||||
_ => return p.to_path_buf(),
|
||||
};
|
||||
let disk = match prefix.kind() {
|
||||
path::Prefix::VerbatimDisk(disk) => disk,
|
||||
_ => return p.to_path_buf(),
|
||||
};
|
||||
let mut base = OsString::from(format!("{}:", disk as char));
|
||||
base.push(components.as_path());
|
||||
PathBuf::from(base)
|
||||
}
|
||||
|
232
src/libstd/fs.rs
232
src/libstd/fs.rs
@ -20,6 +20,7 @@
|
||||
use core::prelude::*;
|
||||
|
||||
use fmt;
|
||||
use ffi::OsString;
|
||||
use io::{self, Error, ErrorKind, SeekFrom, Seek, Read, Write};
|
||||
use path::{Path, PathBuf};
|
||||
use sys::fs2 as fs_imp;
|
||||
@ -146,6 +147,11 @@ pub struct OpenOptions(fs_imp::OpenOptions);
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Permissions(fs_imp::FilePermissions);
|
||||
|
||||
/// An structure representing a type of file with accessors for each file type.
|
||||
#[unstable(feature = "file_type", reason = "recently added API")]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct FileType(fs_imp::FileType);
|
||||
|
||||
impl File {
|
||||
/// Attempts to open a file in read-only mode.
|
||||
///
|
||||
@ -485,6 +491,12 @@ impl AsInnerMut<fs_imp::OpenOptions> for OpenOptions {
|
||||
}
|
||||
|
||||
impl Metadata {
|
||||
/// Returns the file type for this metadata.
|
||||
#[unstable(feature = "file_type", reason = "recently added API")]
|
||||
pub fn file_type(&self) -> FileType {
|
||||
FileType(self.0.file_type())
|
||||
}
|
||||
|
||||
/// Returns whether this metadata is for a directory.
|
||||
///
|
||||
/// # Examples
|
||||
@ -500,7 +512,7 @@ impl Metadata {
|
||||
/// # }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn is_dir(&self) -> bool { self.0.is_dir() }
|
||||
pub fn is_dir(&self) -> bool { self.file_type().is_dir() }
|
||||
|
||||
/// Returns whether this metadata is for a regular file.
|
||||
///
|
||||
@ -517,7 +529,7 @@ impl Metadata {
|
||||
/// # }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn is_file(&self) -> bool { self.0.is_file() }
|
||||
pub fn is_file(&self) -> bool { self.file_type().is_file() }
|
||||
|
||||
/// Returns the size of the file, in bytes, this metadata is for.
|
||||
///
|
||||
@ -562,7 +574,11 @@ impl Metadata {
|
||||
reason = "the return type of u64 is not quite appropriate for \
|
||||
this method and may change if the standard library \
|
||||
gains a type to represent a moment in time")]
|
||||
pub fn accessed(&self) -> u64 { self.0.accessed() }
|
||||
#[deprecated(since = "1.1.0",
|
||||
reason = "use os::platform::fs::MetadataExt extension traits")]
|
||||
pub fn accessed(&self) -> u64 {
|
||||
self.adjust_time(self.0.accessed())
|
||||
}
|
||||
|
||||
/// Returns the most recent modification time for a file.
|
||||
///
|
||||
@ -571,7 +587,21 @@ impl Metadata {
|
||||
reason = "the return type of u64 is not quite appropriate for \
|
||||
this method and may change if the standard library \
|
||||
gains a type to represent a moment in time")]
|
||||
pub fn modified(&self) -> u64 { self.0.modified() }
|
||||
#[deprecated(since = "1.1.0",
|
||||
reason = "use os::platform::fs::MetadataExt extension traits")]
|
||||
pub fn modified(&self) -> u64 {
|
||||
self.adjust_time(self.0.modified())
|
||||
}
|
||||
|
||||
fn adjust_time(&self, val: u64) -> u64 {
|
||||
// FILETIME (what `val` represents) is in 100ns intervals and there are
|
||||
// 10000 intervals in a millisecond.
|
||||
if cfg!(windows) {val / 10000} else {val}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInner<fs_imp::FileAttr> for Metadata {
|
||||
fn as_inner(&self) -> &fs_imp::FileAttr { &self.0 }
|
||||
}
|
||||
|
||||
impl Permissions {
|
||||
@ -624,6 +654,18 @@ impl Permissions {
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "file_type", reason = "recently added API")]
|
||||
impl FileType {
|
||||
/// Test whether this file type represents a directory.
|
||||
pub fn is_dir(&self) -> bool { self.0.is_dir() }
|
||||
|
||||
/// Test whether this file type represents a regular file.
|
||||
pub fn is_file(&self) -> bool { self.0.is_file() }
|
||||
|
||||
/// Test whether this file type represents a symbolic link.
|
||||
pub fn is_symlink(&self) -> bool { self.0.is_symlink() }
|
||||
}
|
||||
|
||||
impl FromInner<fs_imp::FilePermissions> for Permissions {
|
||||
fn from_inner(f: fs_imp::FilePermissions) -> Permissions {
|
||||
Permissions(f)
|
||||
@ -674,6 +716,47 @@ impl DirEntry {
|
||||
/// The exact text, of course, depends on what files you have in `.`.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn path(&self) -> PathBuf { self.0.path() }
|
||||
|
||||
/// Return the metadata for the file that this entry points at.
|
||||
///
|
||||
/// This function will not traverse symlinks if this entry points at a
|
||||
/// symlink.
|
||||
///
|
||||
/// # Platform behavior
|
||||
///
|
||||
/// On Windows this function is cheap to call (no extra system calls
|
||||
/// needed), but on Unix platforms this function is the equivalent of
|
||||
/// calling `symlink_metadata` on the path.
|
||||
#[unstable(feature = "dir_entry_ext", reason = "recently added API")]
|
||||
pub fn metadata(&self) -> io::Result<Metadata> {
|
||||
self.0.metadata().map(Metadata)
|
||||
}
|
||||
|
||||
/// Return the file type for the file that this entry points at.
|
||||
///
|
||||
/// This function will not traverse symlinks if this entry points at a
|
||||
/// symlink.
|
||||
///
|
||||
/// # Platform behavior
|
||||
///
|
||||
/// On Windows and most Unix platforms this function is free (no extra
|
||||
/// system calls needed), but some Unix platforms may require the equivalent
|
||||
/// call to `symlink_metadata` to learn about the target file type.
|
||||
#[unstable(feature = "dir_entry_ext", reason = "recently added API")]
|
||||
pub fn file_type(&self) -> io::Result<FileType> {
|
||||
self.0.file_type().map(FileType)
|
||||
}
|
||||
|
||||
/// Returns the bare file name of this directory entry without any other
|
||||
/// leading path component.
|
||||
#[unstable(feature = "dir_entry_ext", reason = "recently added API")]
|
||||
pub fn file_name(&self) -> OsString {
|
||||
self.0.file_name()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInner<fs_imp::DirEntry> for DirEntry {
|
||||
fn as_inner(&self) -> &fs_imp::DirEntry { &self.0 }
|
||||
}
|
||||
|
||||
/// Removes a file from the underlying filesystem.
|
||||
@ -731,6 +814,25 @@ pub fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
|
||||
fs_imp::stat(path.as_ref()).map(Metadata)
|
||||
}
|
||||
|
||||
/// Query the metadata about a file without following symlinks.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(symlink_metadata)]
|
||||
/// # fn foo() -> std::io::Result<()> {
|
||||
/// use std::fs;
|
||||
///
|
||||
/// let attr = try!(fs::symlink_metadata("/some/file/path.txt"));
|
||||
/// // inspect attr ...
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "symlink_metadata", reason = "recently added API")]
|
||||
pub fn symlink_metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
|
||||
fs_imp::lstat(path.as_ref()).map(Metadata)
|
||||
}
|
||||
|
||||
/// Rename a file or directory to a new name.
|
||||
///
|
||||
/// # Errors
|
||||
@ -869,6 +971,13 @@ pub fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
|
||||
fs_imp::readlink(path.as_ref())
|
||||
}
|
||||
|
||||
/// Returns the canonical form of a path with all intermediate components
|
||||
/// normalized and symbolic links resolved.
|
||||
#[unstable(feature = "fs_canonicalize", reason = "recently added API")]
|
||||
pub fn canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
|
||||
fs_imp::canonicalize(path.as_ref())
|
||||
}
|
||||
|
||||
/// Creates a new, empty directory at the provided path
|
||||
///
|
||||
/// # Errors
|
||||
@ -966,19 +1075,14 @@ pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
|
||||
let path = path.as_ref();
|
||||
for child in try!(read_dir(path)) {
|
||||
let child = try!(child).path();
|
||||
let stat = try!(lstat(&*child));
|
||||
let stat = try!(symlink_metadata(&*child));
|
||||
if stat.is_dir() {
|
||||
try!(remove_dir_all(&*child));
|
||||
} else {
|
||||
try!(remove_file(&*child));
|
||||
}
|
||||
}
|
||||
return remove_dir(path);
|
||||
|
||||
#[cfg(unix)]
|
||||
fn lstat(path: &Path) -> io::Result<fs_imp::FileAttr> { fs_imp::lstat(path) }
|
||||
#[cfg(windows)]
|
||||
fn lstat(path: &Path) -> io::Result<fs_imp::FileAttr> { fs_imp::stat(path) }
|
||||
remove_dir(path)
|
||||
}
|
||||
|
||||
/// Returns an iterator over the entries within a directory.
|
||||
@ -1073,11 +1177,37 @@ impl Iterator for WalkDir {
|
||||
pub trait PathExt {
|
||||
/// Gets information on the file, directory, etc at this path.
|
||||
///
|
||||
/// Consult the `fs::stat` documentation for more info.
|
||||
/// Consult the `fs::metadata` documentation for more info.
|
||||
///
|
||||
/// This call preserves identical runtime/error semantics with `file::stat`.
|
||||
/// This call preserves identical runtime/error semantics with
|
||||
/// `fs::metadata`.
|
||||
fn metadata(&self) -> io::Result<Metadata>;
|
||||
|
||||
/// Gets information on the file, directory, etc at this path.
|
||||
///
|
||||
/// Consult the `fs::symlink_metadata` documentation for more info.
|
||||
///
|
||||
/// This call preserves identical runtime/error semantics with
|
||||
/// `fs::symlink_metadata`.
|
||||
fn symlink_metadata(&self) -> io::Result<Metadata>;
|
||||
|
||||
/// Returns the canonical form of a path, normalizing all components and
|
||||
/// eliminate all symlinks.
|
||||
///
|
||||
/// This call preserves identical runtime/error semantics with
|
||||
/// `fs::canonicalize`.
|
||||
fn canonicalize(&self) -> io::Result<PathBuf>;
|
||||
|
||||
/// Reads the symlink at this path.
|
||||
///
|
||||
/// For more information see `fs::read_link`.
|
||||
fn read_link(&self) -> io::Result<PathBuf>;
|
||||
|
||||
/// Reads the directory at this path.
|
||||
///
|
||||
/// For more information see `fs::read_dir`.
|
||||
fn read_dir(&self) -> io::Result<ReadDir>;
|
||||
|
||||
/// Boolean value indicator whether the underlying file exists on the local
|
||||
/// filesystem. Returns false in exactly the cases where `fs::stat` fails.
|
||||
fn exists(&self) -> bool;
|
||||
@ -1098,12 +1228,16 @@ pub trait PathExt {
|
||||
|
||||
impl PathExt for Path {
|
||||
fn metadata(&self) -> io::Result<Metadata> { metadata(self) }
|
||||
|
||||
fn symlink_metadata(&self) -> io::Result<Metadata> { symlink_metadata(self) }
|
||||
fn canonicalize(&self) -> io::Result<PathBuf> { canonicalize(self) }
|
||||
fn read_link(&self) -> io::Result<PathBuf> { read_link(self) }
|
||||
fn read_dir(&self) -> io::Result<ReadDir> { read_dir(self) }
|
||||
fn exists(&self) -> bool { metadata(self).is_ok() }
|
||||
|
||||
fn is_file(&self) -> bool {
|
||||
metadata(self).map(|s| s.is_file()).unwrap_or(false)
|
||||
}
|
||||
|
||||
fn is_dir(&self) -> bool {
|
||||
metadata(self).map(|s| s.is_dir()).unwrap_or(false)
|
||||
}
|
||||
@ -1924,4 +2058,74 @@ mod tests {
|
||||
let path = tmpdir.join("file");
|
||||
check!(fs::create_dir_all(&path.join("a/")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(windows))]
|
||||
fn realpath_works() {
|
||||
let tmpdir = tmpdir();
|
||||
let tmpdir = fs::canonicalize(tmpdir.path()).unwrap();
|
||||
let file = tmpdir.join("test");
|
||||
let dir = tmpdir.join("test2");
|
||||
let link = dir.join("link");
|
||||
let linkdir = tmpdir.join("test3");
|
||||
|
||||
File::create(&file).unwrap();
|
||||
fs::create_dir(&dir).unwrap();
|
||||
fs::soft_link(&file, &link).unwrap();
|
||||
fs::soft_link(&dir, &linkdir).unwrap();
|
||||
|
||||
assert!(link.symlink_metadata().unwrap().file_type().is_symlink());
|
||||
|
||||
assert_eq!(fs::canonicalize(&tmpdir).unwrap(), tmpdir);
|
||||
assert_eq!(fs::canonicalize(&file).unwrap(), file);
|
||||
assert_eq!(fs::canonicalize(&link).unwrap(), file);
|
||||
assert_eq!(fs::canonicalize(&linkdir).unwrap(), dir);
|
||||
assert_eq!(fs::canonicalize(&linkdir.join("link")).unwrap(), file);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(windows))]
|
||||
fn realpath_works_tricky() {
|
||||
let tmpdir = tmpdir();
|
||||
let tmpdir = fs::canonicalize(tmpdir.path()).unwrap();
|
||||
|
||||
let a = tmpdir.join("a");
|
||||
let b = a.join("b");
|
||||
let c = b.join("c");
|
||||
let d = a.join("d");
|
||||
let e = d.join("e");
|
||||
let f = a.join("f");
|
||||
|
||||
fs::create_dir_all(&b).unwrap();
|
||||
fs::create_dir_all(&d).unwrap();
|
||||
File::create(&f).unwrap();
|
||||
fs::soft_link("../d/e", &c).unwrap();
|
||||
fs::soft_link("../f", &e).unwrap();
|
||||
|
||||
assert_eq!(fs::canonicalize(&c).unwrap(), f);
|
||||
assert_eq!(fs::canonicalize(&e).unwrap(), f);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dir_entry_methods() {
|
||||
let tmpdir = tmpdir();
|
||||
|
||||
fs::create_dir_all(&tmpdir.join("a")).unwrap();
|
||||
File::create(&tmpdir.join("b")).unwrap();
|
||||
|
||||
for file in tmpdir.path().read_dir().unwrap().map(|f| f.unwrap()) {
|
||||
let fname = file.file_name();
|
||||
match fname.to_str() {
|
||||
Some("a") => {
|
||||
assert!(file.file_type().unwrap().is_dir());
|
||||
assert!(file.metadata().unwrap().is_dir());
|
||||
}
|
||||
Some("b") => {
|
||||
assert!(file.file_type().unwrap().is_file());
|
||||
assert!(file.metadata().unwrap().is_file());
|
||||
}
|
||||
f => panic!("unknown file name: {:?}", f),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
@ -8,9 +8,12 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! OS-specific functionality
|
||||
//! Android-specific definitions
|
||||
|
||||
#![stable(feature = "os", since = "1.0.0")]
|
||||
#![unstable(feature = "raw_ext", reason = "recently added API")]
|
||||
|
||||
#[cfg(unix)] pub use sys::ext as unix;
|
||||
#[cfg(windows)] pub use sys::ext as windows;
|
||||
pub mod raw;
|
||||
|
||||
pub mod fs {
|
||||
pub use sys::fs2::MetadataExt;
|
||||
}
|
46
src/libstd/os/android/raw.rs
Normal file
46
src/libstd/os/android/raw.rs
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Android-specific raw type definitions
|
||||
|
||||
use os::raw::{c_uint, c_uchar, c_ulonglong, c_longlong, c_ulong};
|
||||
use os::unix::raw::{uid_t, gid_t};
|
||||
|
||||
pub type blkcnt_t = u32;
|
||||
pub type blksize_t = u32;
|
||||
pub type dev_t = u32;
|
||||
pub type ino_t = u32;
|
||||
pub type mode_t = u16;
|
||||
pub type nlink_t = u16;
|
||||
pub type off_t = i32;
|
||||
pub type time_t = i32;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct stat {
|
||||
pub st_dev: c_ulonglong,
|
||||
pub __pad0: [c_uchar; 4],
|
||||
pub __st_ino: ino_t,
|
||||
pub st_mode: c_uint,
|
||||
pub st_nlink: c_uint,
|
||||
pub st_uid: uid_t,
|
||||
pub st_gid: gid_t,
|
||||
pub st_rdev: c_ulonglong,
|
||||
pub __pad3: [c_uchar; 4],
|
||||
pub st_size: c_longlong,
|
||||
pub st_blksize: blksize_t,
|
||||
pub st_blocks: c_ulonglong,
|
||||
pub st_atime: time_t,
|
||||
pub st_atime_nsec: c_ulong,
|
||||
pub st_mtime: time_t,
|
||||
pub st_mtime_nsec: c_ulong,
|
||||
pub st_ctime: time_t,
|
||||
pub st_ctime_nsec: c_ulong,
|
||||
pub st_ino: c_ulonglong,
|
||||
}
|
19
src/libstd/os/bitrig/mod.rs
Normal file
19
src/libstd/os/bitrig/mod.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Bitrig-specific definitions
|
||||
|
||||
#![unstable(feature = "raw_ext", reason = "recently added API")]
|
||||
|
||||
pub mod raw;
|
||||
|
||||
pub mod fs {
|
||||
pub use sys::fs2::MetadataExt;
|
||||
}
|
48
src/libstd/os/bitrig/raw.rs
Normal file
48
src/libstd/os/bitrig/raw.rs
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Bitrig-specific raw type definitions
|
||||
|
||||
use os::raw::c_long;
|
||||
use os::unix::raw::{uid_t, gid_t};
|
||||
|
||||
pub type blkcnt_t = i64;
|
||||
pub type blksize_t = u32;
|
||||
pub type dev_t = i32;
|
||||
pub type fflags_t = u32; // type not declared, but struct stat have u_int32_t
|
||||
pub type ino_t = u64;
|
||||
pub type mode_t = u32;
|
||||
pub type nlink_t = u32;
|
||||
pub type off_t = i64;
|
||||
pub type time_t = i64;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct stat {
|
||||
pub st_mode: mode_t,
|
||||
pub st_dev: dev_t,
|
||||
pub st_ino: ino_t,
|
||||
pub st_nlink: nlink_t,
|
||||
pub st_uid: uid_t,
|
||||
pub st_gid: gid_t,
|
||||
pub st_rdev: dev_t,
|
||||
pub st_atime: time_t,
|
||||
pub st_atime_nsec: c_long,
|
||||
pub st_mtime: time_t,
|
||||
pub st_mtime_nsec: c_long,
|
||||
pub st_ctime: time_t,
|
||||
pub st_ctime_nsec: c_long,
|
||||
pub st_size: off_t,
|
||||
pub st_blocks: blkcnt_t,
|
||||
pub st_blksize: blksize_t,
|
||||
pub st_flags: fflags_t,
|
||||
pub st_gen: u32,
|
||||
pub st_birthtime: time_t,
|
||||
pub st_birthtime_nsec: c_long,
|
||||
}
|
19
src/libstd/os/dragonfly/mod.rs
Normal file
19
src/libstd/os/dragonfly/mod.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Dragonfly-specific definitions
|
||||
|
||||
#![unstable(feature = "raw_ext", reason = "recently added API")]
|
||||
|
||||
pub mod raw;
|
||||
|
||||
pub mod fs {
|
||||
pub use sys::fs2::MetadataExt;
|
||||
}
|
50
src/libstd/os/dragonfly/raw.rs
Normal file
50
src/libstd/os/dragonfly/raw.rs
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Dragonfly-specific raw type definitions
|
||||
|
||||
use os::raw::c_long;
|
||||
use os::unix::raw::{pid_t, uid_t, gid_t};
|
||||
|
||||
pub type blkcnt_t = i64;
|
||||
pub type blksize_t = u32;
|
||||
pub type dev_t = u32;
|
||||
pub type fflags_t = u32;
|
||||
pub type ino_t = u64;
|
||||
pub type mode_t = u16;
|
||||
pub type nlink_t = u16;
|
||||
pub type off_t = i64;
|
||||
pub type time_t = i64;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct stat {
|
||||
pub st_ino: ino_t,
|
||||
pub st_nlink: nlink_t,
|
||||
pub st_dev: dev_t,
|
||||
pub st_mode: mode_t,
|
||||
pub st_padding1: u16,
|
||||
pub st_uid: uid_t,
|
||||
pub st_gid: gid_t,
|
||||
pub st_rdev: dev_t,
|
||||
pub st_atime: time_t,
|
||||
pub st_atime_nsec: c_long,
|
||||
pub st_mtime: time_t,
|
||||
pub st_mtime_nsec: c_long,
|
||||
pub st_ctime: time_t,
|
||||
pub st_ctime_nsec: c_long,
|
||||
pub st_size: off_t,
|
||||
pub st_blocks: blkcnt_t,
|
||||
pub st_blksize: blksize_t,
|
||||
pub st_flags: fflags_t,
|
||||
pub st_gen: uint32_t,
|
||||
pub st_lspare: int32_t,
|
||||
pub st_qspare1: int64_t,
|
||||
pub st_qspare2: int64_t,
|
||||
}
|
19
src/libstd/os/freebsd/mod.rs
Normal file
19
src/libstd/os/freebsd/mod.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! FreeBSD-specific definitions
|
||||
|
||||
#![unstable(feature = "raw_ext", reason = "recently added API")]
|
||||
|
||||
pub mod raw;
|
||||
|
||||
pub mod fs {
|
||||
pub use sys::fs2::MetadataExt;
|
||||
}
|
50
src/libstd/os/freebsd/raw.rs
Normal file
50
src/libstd/os/freebsd/raw.rs
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! FreeBSD-specific raw type definitions
|
||||
|
||||
use os::raw::c_long;
|
||||
use os::unix::raw::{uid_t, gid_t, pid_t};
|
||||
|
||||
pub type blkcnt_t = i64;
|
||||
pub type blksize_t = i64;
|
||||
pub type dev_t = u32;
|
||||
pub type fflags_t = u32;
|
||||
pub type ino_t = u32;
|
||||
pub type mode_t = u16;
|
||||
pub type nlink_t = u16;
|
||||
pub type off_t = i64;
|
||||
pub type time_t = i64;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct stat {
|
||||
pub st_dev: dev_t,
|
||||
pub st_ino: ino_t,
|
||||
pub st_mode: mode_t,
|
||||
pub st_nlink: nlink_t,
|
||||
pub st_uid: uid_t,
|
||||
pub st_gid: gid_t,
|
||||
pub st_rdev: dev_t,
|
||||
pub st_atime: time_t,
|
||||
pub st_atime_nsec: c_long,
|
||||
pub st_mtime: time_t,
|
||||
pub st_mtime_nsec: c_long,
|
||||
pub st_ctime: time_t,
|
||||
pub st_ctime_nsec: c_long,
|
||||
pub st_size: off_t,
|
||||
pub st_blocks: blkcnt_t,
|
||||
pub st_blksize: blksize_t,
|
||||
pub st_flags: fflags_t,
|
||||
pub st_gen: u32,
|
||||
pub st_lspare: i32,
|
||||
pub st_birthtime: time_t,
|
||||
pub st_birthtime_nsec: c_long,
|
||||
pub __unused: [u8; 2],
|
||||
}
|
19
src/libstd/os/ios/mod.rs
Normal file
19
src/libstd/os/ios/mod.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! iOS-specific definitions
|
||||
|
||||
#![unstable(feature = "raw_ext", reason = "recently added API")]
|
||||
|
||||
pub mod raw;
|
||||
|
||||
pub mod fs {
|
||||
pub use sys::fs2::MetadataExt;
|
||||
}
|
49
src/libstd/os/ios/raw.rs
Normal file
49
src/libstd/os/ios/raw.rs
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! iOS-specific raw type definitions
|
||||
|
||||
use os::raw::c_long;
|
||||
use os::unix::raw::{uid_t, gid_t, pid_t};
|
||||
|
||||
pub type blkcnt_t = i64;
|
||||
pub type blksize_t = i32;
|
||||
pub type dev_t = i32;
|
||||
pub type ino_t = u64;
|
||||
pub type mode_t = u16;
|
||||
pub type nlink_t = u16;
|
||||
pub type off_t = i64;
|
||||
pub type time_t = c_long;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct stat {
|
||||
pub st_dev: dev_t,
|
||||
pub st_mode: mode_t,
|
||||
pub st_nlink: nlink_t,
|
||||
pub st_ino: ino_t,
|
||||
pub st_uid: uid_t,
|
||||
pub st_gid: gid_t,
|
||||
pub st_rdev: dev_t,
|
||||
pub st_atime: time_t,
|
||||
pub st_atime_nsec: c_long,
|
||||
pub st_mtime: time_t,
|
||||
pub st_mtime_nsec: c_long,
|
||||
pub st_ctime: time_t,
|
||||
pub st_ctime_nsec: c_long,
|
||||
pub st_birthtime: time_t,
|
||||
pub st_birthtime_nsec: c_long,
|
||||
pub st_size: off_t,
|
||||
pub st_blocks: blkcnt_t,
|
||||
pub st_blksize: blksize_t,
|
||||
pub st_flags: u32,
|
||||
pub st_gen: u32,
|
||||
pub st_lspare: i32,
|
||||
pub st_qspare: [i64; 2],
|
||||
}
|
19
src/libstd/os/linux/mod.rs
Normal file
19
src/libstd/os/linux/mod.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Linux-specific definitions
|
||||
|
||||
#![unstable(feature = "raw_ext", reason = "recently added API")]
|
||||
|
||||
pub mod raw;
|
||||
|
||||
pub mod fs {
|
||||
pub use sys::fs2::MetadataExt;
|
||||
}
|
170
src/libstd/os/linux/raw.rs
Normal file
170
src/libstd/os/linux/raw.rs
Normal file
@ -0,0 +1,170 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Linux-specific raw type definitions
|
||||
|
||||
pub type dev_t = u64;
|
||||
pub type mode_t = u32;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use self::arch::{off_t, ino_t, nlink_t, blksize_t, blkcnt_t, stat, time_t};
|
||||
|
||||
#[cfg(any(target_arch = "x86",
|
||||
target_arch = "le32",
|
||||
target_arch = "powerpc",
|
||||
target_arch = "arm"))]
|
||||
mod arch {
|
||||
use super::{dev_t, mode_t};
|
||||
use os::raw::{c_long, c_short};
|
||||
use os::unix::raw::{gid_t, uid_t};
|
||||
|
||||
pub type blkcnt_t = i32;
|
||||
pub type blksize_t = i32;
|
||||
pub type ino_t = u32;
|
||||
pub type nlink_t = u32;
|
||||
pub type off_t = i32;
|
||||
pub type time_t = i32;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct stat {
|
||||
pub st_dev: dev_t,
|
||||
pub __pad1: c_short,
|
||||
pub st_ino: ino_t,
|
||||
pub st_mode: mode_t,
|
||||
pub st_nlink: nlink_t,
|
||||
pub st_uid: uid_t,
|
||||
pub st_gid: gid_t,
|
||||
pub st_rdev: dev_t,
|
||||
pub __pad2: c_short,
|
||||
pub st_size: off_t,
|
||||
pub st_blksize: blksize_t,
|
||||
pub st_blocks: blkcnt_t,
|
||||
pub st_atime: time_t,
|
||||
pub st_atime_nsec: c_long,
|
||||
pub st_mtime: time_t,
|
||||
pub st_mtime_nsec: c_long,
|
||||
pub st_ctime: time_t,
|
||||
pub st_ctime_nsec: c_long,
|
||||
pub __unused4: c_long,
|
||||
pub __unused5: c_long,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_arch = "mips",
|
||||
target_arch = "mipsel"))]
|
||||
mod arch {
|
||||
use super::{dev_t, mode_t};
|
||||
use os::raw::c_long;
|
||||
use os::unix::raw::{gid_t, uid_t};
|
||||
|
||||
pub type blkcnt_t = i32;
|
||||
pub type blksize_t = i32;
|
||||
pub type ino_t = u32;
|
||||
pub type nlink_t = u32;
|
||||
pub type off_t = i32;
|
||||
pub type time_t = i32;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct stat {
|
||||
pub st_dev: c_ulong,
|
||||
pub st_pad1: [c_long; 3],
|
||||
pub st_ino: ino_t,
|
||||
pub st_mode: mode_t,
|
||||
pub st_nlink: nlink_t,
|
||||
pub st_uid: uid_t,
|
||||
pub st_gid: gid_t,
|
||||
pub st_rdev: c_ulong,
|
||||
pub st_pad2: [c_long; 2],
|
||||
pub st_size: off_t,
|
||||
pub st_pad3: c_long,
|
||||
pub st_atime: time_t,
|
||||
pub st_atime_nsec: c_long,
|
||||
pub st_mtime: time_t,
|
||||
pub st_mtime_nsec: c_long,
|
||||
pub st_ctime: time_t,
|
||||
pub st_ctime_nsec: c_long,
|
||||
pub st_blksize: blksize_t,
|
||||
pub st_blocks: blkcnt_t,
|
||||
pub st_pad5: [c_long; 14],
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
mod arch {
|
||||
use super::{dev_t, mode_t};
|
||||
use os::raw::{c_long, c_int};
|
||||
use os::unix::raw::{gid_t, uid_t};
|
||||
|
||||
pub type blkcnt_t = i64;
|
||||
pub type blksize_t = i32;
|
||||
pub type ino_t = u64;
|
||||
pub type nlink_t = u32;
|
||||
pub type off_t = i64;
|
||||
pub type time_t = i64;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct stat {
|
||||
pub st_dev: dev_t,
|
||||
pub st_ino: ino_t,
|
||||
pub st_mode: mode_t,
|
||||
pub st_nlink: nlink_t,
|
||||
pub st_uid: uid_t,
|
||||
pub st_gid: gid_t,
|
||||
pub st_rdev: dev_t,
|
||||
pub __pad1: dev_t,
|
||||
pub st_size: off_t,
|
||||
pub st_blksize: blksize_t,
|
||||
pub __pad2: c_int,
|
||||
pub st_blocks: blkcnt_t,
|
||||
pub st_atime: time_t,
|
||||
pub st_atime_nsec: c_long,
|
||||
pub st_mtime: time_t,
|
||||
pub st_mtime_nsec: c_long,
|
||||
pub st_ctime: time_t,
|
||||
pub st_ctime_nsec: c_long,
|
||||
pub __unused: [c_int; 2],
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
mod arch {
|
||||
use super::{dev_t, mode_t};
|
||||
use os::raw::{c_long, c_int};
|
||||
use os::unix::raw::{gid_t, uid_t};
|
||||
|
||||
pub type blkcnt_t = i64;
|
||||
pub type blksize_t = i64;
|
||||
pub type ino_t = u64;
|
||||
pub type nlink_t = u64;
|
||||
pub type off_t = i64;
|
||||
pub type time_t = i64;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct stat {
|
||||
pub st_dev: dev_t,
|
||||
pub st_ino: ino_t,
|
||||
pub st_nlink: nlink_t,
|
||||
pub st_mode: mode_t,
|
||||
pub st_uid: uid_t,
|
||||
pub st_gid: gid_t,
|
||||
pub __pad0: c_int,
|
||||
pub st_rdev: dev_t,
|
||||
pub st_size: off_t,
|
||||
pub st_blksize: blksize_t,
|
||||
pub st_blocks: blkcnt_t,
|
||||
pub st_atime: time_t,
|
||||
pub st_atime_nsec: c_long,
|
||||
pub st_mtime: time_t,
|
||||
pub st_mtime_nsec: c_long,
|
||||
pub st_ctime: time_t,
|
||||
pub st_ctime_nsec: c_long,
|
||||
pub __unused: [c_long; 3],
|
||||
}
|
||||
}
|
19
src/libstd/os/macos/mod.rs
Normal file
19
src/libstd/os/macos/mod.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! MacOS-specific definitions
|
||||
|
||||
#![unstable(feature = "raw_ext", reason = "recently added API")]
|
||||
|
||||
pub mod raw;
|
||||
|
||||
pub mod fs {
|
||||
pub use sys::fs2::MetadataExt;
|
||||
}
|
49
src/libstd/os/macos/raw.rs
Normal file
49
src/libstd/os/macos/raw.rs
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! MacOS-specific raw type definitions
|
||||
|
||||
use os::raw::c_long;
|
||||
use os::unix::raw::{uid_t, gid_t};
|
||||
|
||||
pub type blkcnt_t = i64;
|
||||
pub type blksize_t = i32;
|
||||
pub type dev_t = i32;
|
||||
pub type ino_t = u64;
|
||||
pub type mode_t = u16;
|
||||
pub type nlink_t = u16;
|
||||
pub type off_t = i64;
|
||||
pub type time_t = c_long;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct stat {
|
||||
pub st_dev: dev_t,
|
||||
pub st_mode: mode_t,
|
||||
pub st_nlink: nlink_t,
|
||||
pub st_ino: ino_t,
|
||||
pub st_uid: uid_t,
|
||||
pub st_gid: gid_t,
|
||||
pub st_rdev: dev_t,
|
||||
pub st_atime: time_t,
|
||||
pub st_atime_nsec: c_long,
|
||||
pub st_mtime: time_t,
|
||||
pub st_mtime_nsec: c_long,
|
||||
pub st_ctime: time_t,
|
||||
pub st_ctime_nsec: c_long,
|
||||
pub st_birthtime: time_t,
|
||||
pub st_birthtime_nsec: c_long,
|
||||
pub st_size: off_t,
|
||||
pub st_blocks: blkcnt_t,
|
||||
pub st_blksize: blksize_t,
|
||||
pub st_flags: u32,
|
||||
pub st_gen: u32,
|
||||
pub st_lspare: i32,
|
||||
pub st_qspare: [i64; 2],
|
||||
}
|
29
src/libstd/os/mod.rs
Normal file
29
src/libstd/os/mod.rs
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2012-2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! OS-specific functionality
|
||||
|
||||
#![stable(feature = "os", since = "1.0.0")]
|
||||
#![allow(missing_docs, bad_style)]
|
||||
|
||||
#[cfg(unix)] pub use sys::ext as unix;
|
||||
#[cfg(windows)] pub use sys::ext as windows;
|
||||
|
||||
#[cfg(target_os = "android")] pub mod android;
|
||||
#[cfg(target_os = "bitrig")] pub mod bitrig;
|
||||
#[cfg(target_os = "dragonfly")] pub mod dragonfly;
|
||||
#[cfg(target_os = "freebsd")] pub mod freebsd;
|
||||
#[cfg(target_os = "ios")] pub mod ios;
|
||||
#[cfg(target_os = "linux")] pub mod linux;
|
||||
#[cfg(target_os = "macos")] pub mod macos;
|
||||
#[cfg(target_os = "nacl")] pub mod nacl;
|
||||
#[cfg(target_os = "openbsd")] pub mod openbsd;
|
||||
|
||||
pub mod raw;
|
19
src/libstd/os/nacl/mod.rs
Normal file
19
src/libstd/os/nacl/mod.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Nacl-specific definitions
|
||||
|
||||
#![unstable(feature = "raw_ext", reason = "recently added API")]
|
||||
|
||||
pub mod raw;
|
||||
|
||||
pub mod fs {
|
||||
pub use sys::fs2::MetadataExt;
|
||||
}
|
169
src/libstd/os/nacl/raw.rs
Normal file
169
src/libstd/os/nacl/raw.rs
Normal file
@ -0,0 +1,169 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Nacl-specific raw type definitions
|
||||
|
||||
pub type dev_t = u64;
|
||||
pub type mode_t = u32;
|
||||
|
||||
pub use self::arch::{off_t, ino_t, nlink_t, blksize_t, blkcnt_t, stat, time_t};
|
||||
|
||||
#[cfg(any(target_arch = "x86",
|
||||
target_arch = "le32",
|
||||
target_arch = "powerpc",
|
||||
target_arch = "arm"))]
|
||||
mod arch {
|
||||
use super::{dev_t, mode_t};
|
||||
use os::raw::{c_long, c_short};
|
||||
use os::unix::raw::{gid_t, uid_t};
|
||||
|
||||
pub type blkcnt_t = i32;
|
||||
pub type blksize_t = i32;
|
||||
pub type ino_t = u32;
|
||||
pub type nlink_t = u32;
|
||||
pub type off_t = i32;
|
||||
pub type time_t = i32;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct stat {
|
||||
pub st_dev: dev_t,
|
||||
pub __pad1: c_short,
|
||||
pub st_ino: ino_t,
|
||||
pub st_mode: mode_t,
|
||||
pub st_nlink: nlink_t,
|
||||
pub st_uid: uid_t,
|
||||
pub st_gid: gid_t,
|
||||
pub st_rdev: dev_t,
|
||||
pub __pad2: c_short,
|
||||
pub st_size: off_t,
|
||||
pub st_blksize: blksize_t,
|
||||
pub st_blocks: blkcnt_t,
|
||||
pub st_atime: time_t,
|
||||
pub st_atime_nsec: c_long,
|
||||
pub st_mtime: time_t,
|
||||
pub st_mtime_nsec: c_long,
|
||||
pub st_ctime: time_t,
|
||||
pub st_ctime_nsec: c_long,
|
||||
pub __unused4: c_long,
|
||||
pub __unused5: c_long,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_arch = "mips",
|
||||
target_arch = "mipsel"))]
|
||||
mod arch {
|
||||
use super::{dev_t, mode_t};
|
||||
use os::raw::c_long;
|
||||
use os::unix::raw::{gid_t, uid_t};
|
||||
|
||||
pub type blkcnt_t = i32;
|
||||
pub type blksize_t = i32;
|
||||
pub type ino_t = u32;
|
||||
pub type nlink_t = u32;
|
||||
pub type off_t = i32;
|
||||
pub type time_t = i32;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct stat {
|
||||
pub st_dev: c_ulong,
|
||||
pub st_pad1: [c_long; 3],
|
||||
pub st_ino: ino_t,
|
||||
pub st_mode: mode_t,
|
||||
pub st_nlink: nlink_t,
|
||||
pub st_uid: uid_t,
|
||||
pub st_gid: gid_t,
|
||||
pub st_rdev: c_ulong,
|
||||
pub st_pad2: [c_long; 2],
|
||||
pub st_size: off_t,
|
||||
pub st_pad3: c_long,
|
||||
pub st_atime: time_t,
|
||||
pub st_atime_nsec: c_long,
|
||||
pub st_mtime: time_t,
|
||||
pub st_mtime_nsec: c_long,
|
||||
pub st_ctime: time_t,
|
||||
pub st_ctime_nsec: c_long,
|
||||
pub st_blksize: blksize_t,
|
||||
pub st_blocks: blkcnt_t,
|
||||
pub st_pad5: [c_long; 14],
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
mod arch {
|
||||
use super::{dev_t, mode_t};
|
||||
use os::raw::{c_long, c_int};
|
||||
use os::unix::raw::{gid_t, uid_t};
|
||||
|
||||
pub type blkcnt_t = i64;
|
||||
pub type blksize_t = i32;
|
||||
pub type ino_t = u64;
|
||||
pub type nlink_t = u32;
|
||||
pub type off_t = i64;
|
||||
pub type time_t = i64;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct stat {
|
||||
pub st_dev: dev_t,
|
||||
pub st_ino: ino_t,
|
||||
pub st_mode: mode_t,
|
||||
pub st_nlink: nlink_t,
|
||||
pub st_uid: uid_t,
|
||||
pub st_gid: gid_t,
|
||||
pub st_rdev: dev_t,
|
||||
pub __pad1: dev_t,
|
||||
pub st_size: off_t,
|
||||
pub st_blksize: blksize_t,
|
||||
pub __pad2: c_int,
|
||||
pub st_blocks: blkcnt_t,
|
||||
pub st_atime: time_t,
|
||||
pub st_atime_nsec: c_long,
|
||||
pub st_mtime: time_t,
|
||||
pub st_mtime_nsec: c_long,
|
||||
pub st_ctime: time_t,
|
||||
pub st_ctime_nsec: c_long,
|
||||
pub __unused: [c_int; 2],
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
mod arch {
|
||||
use super::{dev_t, mode_t};
|
||||
use os::raw::{c_long, c_int};
|
||||
use os::unix::raw::{gid_t, uid_t};
|
||||
|
||||
pub type blkcnt_t = i64;
|
||||
pub type blksize_t = i64;
|
||||
pub type ino_t = u64;
|
||||
pub type nlink_t = u64;
|
||||
pub type off_t = i64;
|
||||
pub type time_t = i64;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct stat {
|
||||
pub st_dev: dev_t,
|
||||
pub st_ino: ino_t,
|
||||
pub st_nlink: nlink_t,
|
||||
pub st_mode: mode_t,
|
||||
pub st_uid: uid_t,
|
||||
pub st_gid: gid_t,
|
||||
pub __pad0: c_int,
|
||||
pub st_rdev: dev_t,
|
||||
pub st_size: off_t,
|
||||
pub st_blksize: blksize_t,
|
||||
pub st_blocks: blkcnt_t,
|
||||
pub st_atime: time_t,
|
||||
pub st_atime_nsec: c_long,
|
||||
pub st_mtime: time_t,
|
||||
pub st_mtime_nsec: c_long,
|
||||
pub st_ctime: time_t,
|
||||
pub st_ctime_nsec: c_long,
|
||||
pub __unused: [c_long; 3],
|
||||
}
|
||||
}
|
19
src/libstd/os/openbsd/mod.rs
Normal file
19
src/libstd/os/openbsd/mod.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! OpenBSD-specific definitions
|
||||
|
||||
#![unstable(feature = "raw_ext", reason = "recently added API")]
|
||||
|
||||
pub mod raw;
|
||||
|
||||
pub mod fs {
|
||||
pub use sys::fs2::MetadataExt;
|
||||
}
|
48
src/libstd/os/openbsd/raw.rs
Normal file
48
src/libstd/os/openbsd/raw.rs
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! OpenBSD-specific raw type definitions
|
||||
|
||||
use os::raw::c_long;
|
||||
use os::unix::raw::{uid_t, gid_t, pid_t};
|
||||
|
||||
pub type blkcnt_t = i64;
|
||||
pub type blksize_t = u32;
|
||||
pub type dev_t = i32;
|
||||
pub type fflags_t = u32; // type not declared, but struct stat have u_int32_t
|
||||
pub type ino_t = u64;
|
||||
pub type mode_t = u32;
|
||||
pub type nlink_t = u32;
|
||||
pub type off_t = i64;
|
||||
pub type time_t = i64;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct stat {
|
||||
pub st_mode: mode_t,
|
||||
pub st_dev: dev_t,
|
||||
pub st_ino: ino_t,
|
||||
pub st_nlink: nlink_t,
|
||||
pub st_uid: uid_t,
|
||||
pub st_gid: gid_t,
|
||||
pub st_rdev: dev_t,
|
||||
pub st_atime: time_t,
|
||||
pub st_atime_nsec: c_long,
|
||||
pub st_mtime: time_t,
|
||||
pub st_mtime_nsec: c_long,
|
||||
pub st_ctime: time_t,
|
||||
pub st_ctime_nsec: c_long,
|
||||
pub st_size: off_t,
|
||||
pub st_blocks: blkcnt_t,
|
||||
pub st_blksize: blksize_t,
|
||||
pub st_flags: fflags_t,
|
||||
pub st_gen: u32,
|
||||
pub st_birthtime: time_t,
|
||||
pub st_birthtime_nsec: c_long,
|
||||
}
|
92
src/libstd/os/raw.rs
Normal file
92
src/libstd/os/raw.rs
Normal file
@ -0,0 +1,92 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Raw OS-specific types for the current platform/architecture
|
||||
|
||||
#![unstable(feature = "raw_os", reason = "recently added API")]
|
||||
|
||||
#[cfg(target_arch = "aarch64")] pub type c_char = u8;
|
||||
#[cfg(not(target_arch = "aarch64"))] pub type c_char = i8;
|
||||
pub type c_schar = i8;
|
||||
pub type c_uchar = u8;
|
||||
pub type c_short = i16;
|
||||
pub type c_ushort = u16;
|
||||
pub type c_int = i32;
|
||||
pub type c_uint = u32;
|
||||
#[cfg(any(target_pointer_width = "32", windows))] pub type c_long = i32;
|
||||
#[cfg(any(target_pointer_width = "32", windows))] pub type c_ulong = u32;
|
||||
#[cfg(all(target_pointer_width = "64", not(windows)))] pub type c_long = i64;
|
||||
#[cfg(all(target_pointer_width = "64", not(windows)))] pub type c_ulong = u64;
|
||||
pub type c_longlong = i64;
|
||||
pub type c_ulonglong = u64;
|
||||
pub type c_float = f32;
|
||||
pub type c_double = f64;
|
||||
|
||||
/// Type used to construct void pointers for use with C.
|
||||
///
|
||||
/// This type is only useful as a pointer target. Do not use it as a
|
||||
/// return type for FFI functions which have the `void` return type in
|
||||
/// C. Use the unit type `()` or omit the return type instead.
|
||||
// NB: For LLVM to recognize the void pointer type and by extension
|
||||
// functions like malloc(), we need to have it represented as i8* in
|
||||
// LLVM bitcode. The enum used here ensures this and prevents misuse
|
||||
// of the "raw" type by only having private variants.. We need two
|
||||
// variants, because the compiler complains about the repr attribute
|
||||
// otherwise.
|
||||
#[repr(u8)]
|
||||
pub enum c_void {
|
||||
#[doc(hidden)] __variant1,
|
||||
#[doc(hidden)] __variant2,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use any::TypeId;
|
||||
use libc;
|
||||
use mem;
|
||||
|
||||
macro_rules! ok {
|
||||
($($t:ident)*) => {$(
|
||||
assert!(TypeId::of::<libc::$t>() == TypeId::of::<raw::$t>(),
|
||||
"{} is wrong", stringify!($t));
|
||||
)*}
|
||||
}
|
||||
|
||||
macro_rules! ok_size {
|
||||
($($t:ident)*) => {$(
|
||||
assert!(mem::size_of::<libc::$t>() == mem::size_of::<raw::$t>(),
|
||||
"{} is wrong", stringify!($t));
|
||||
)*}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn same() {
|
||||
use os::raw;
|
||||
ok!(c_char c_schar c_uchar c_short c_ushort c_int c_uint c_long c_ulong
|
||||
c_longlong c_ulonglong c_float c_double);
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn unix() {
|
||||
{
|
||||
use os::unix::raw;
|
||||
ok!(uid_t gid_t dev_t ino_t mode_t nlink_t off_t blksize_t blkcnt_t);
|
||||
}
|
||||
{
|
||||
use sys::platform::raw;
|
||||
ok_size!(stat);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn windows() {
|
||||
use os::windows::raw;
|
||||
}
|
||||
}
|
@ -161,6 +161,8 @@ extern {
|
||||
pub fn gai_strerror(errcode: libc::c_int) -> *const libc::c_char;
|
||||
pub fn setgroups(ngroups: libc::c_int,
|
||||
ptr: *const libc::c_void) -> libc::c_int;
|
||||
pub fn realpath(pathname: *const libc::c_char, resolved: *mut libc::c_char)
|
||||
-> *mut libc::c_char;
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||
|
@ -1,337 +0,0 @@
|
||||
// Copyright 2014 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Experimental extensions to `std` for Unix platforms.
|
||||
//!
|
||||
//! For now, this module is limited to extracting file descriptors,
|
||||
//! but its functionality will grow over time.
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use std::fs::File;
|
||||
//! use std::os::unix::prelude::*;
|
||||
//!
|
||||
//! fn main() {
|
||||
//! let f = File::create("foo.txt").unwrap();
|
||||
//! let fd = f.as_raw_fd();
|
||||
//!
|
||||
//! // use fd with native unix bindings
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
/// Unix-specific extensions to general I/O primitives
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub mod io {
|
||||
use fs;
|
||||
use libc;
|
||||
use net;
|
||||
use sys_common::{net2, AsInner, FromInner};
|
||||
use sys;
|
||||
|
||||
/// Raw file descriptors.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub type RawFd = libc::c_int;
|
||||
|
||||
/// A trait to extract the raw unix file descriptor from an underlying
|
||||
/// object.
|
||||
///
|
||||
/// This is only available on unix platforms and must be imported in order
|
||||
/// to call the method. Windows platforms have a corresponding `AsRawHandle`
|
||||
/// and `AsRawSocket` set of traits.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait AsRawFd {
|
||||
/// Extracts the raw file descriptor.
|
||||
///
|
||||
/// This method does **not** pass ownership of the raw file descriptor
|
||||
/// to the caller. The descriptor is only guarantee to be valid while
|
||||
/// the original object has not yet been destroyed.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn as_raw_fd(&self) -> RawFd;
|
||||
}
|
||||
|
||||
/// A trait to express the ability to construct an object from a raw file
|
||||
/// descriptor.
|
||||
#[unstable(feature = "from_raw_os",
|
||||
reason = "recent addition to std::os::unix::io")]
|
||||
pub trait FromRawFd {
|
||||
/// Constructs a new instances of `Self` from the given raw file
|
||||
/// descriptor.
|
||||
///
|
||||
/// This function **consumes ownership** of the specified file
|
||||
/// descriptor. The returned object will take responsibility for closing
|
||||
/// it when the object goes out of scope.
|
||||
///
|
||||
/// This function is also unsafe as the primitives currently returned
|
||||
/// have the contract that they are the sole owner of the file
|
||||
/// descriptor they are wrapping. Usage of this function could
|
||||
/// accidentally allow violating this contract which can cause memory
|
||||
/// unsafety in code that relies on it being true.
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> Self;
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl AsRawFd for fs::File {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.as_inner().fd().raw()
|
||||
}
|
||||
}
|
||||
#[unstable(feature = "from_raw_os", reason = "trait is unstable")]
|
||||
impl FromRawFd for fs::File {
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> fs::File {
|
||||
fs::File::from_inner(sys::fs2::File::from_inner(fd))
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl AsRawFd for net::TcpStream {
|
||||
fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl AsRawFd for net::TcpListener {
|
||||
fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl AsRawFd for net::UdpSocket {
|
||||
fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
|
||||
}
|
||||
|
||||
#[unstable(feature = "from_raw_os", reason = "trait is unstable")]
|
||||
impl FromRawFd for net::TcpStream {
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream {
|
||||
let socket = sys::net::Socket::from_inner(fd);
|
||||
net::TcpStream::from_inner(net2::TcpStream::from_inner(socket))
|
||||
}
|
||||
}
|
||||
#[unstable(feature = "from_raw_os", reason = "trait is unstable")]
|
||||
impl FromRawFd for net::TcpListener {
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener {
|
||||
let socket = sys::net::Socket::from_inner(fd);
|
||||
net::TcpListener::from_inner(net2::TcpListener::from_inner(socket))
|
||||
}
|
||||
}
|
||||
#[unstable(feature = "from_raw_os", reason = "trait is unstable")]
|
||||
impl FromRawFd for net::UdpSocket {
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket {
|
||||
let socket = sys::net::Socket::from_inner(fd);
|
||||
net::UdpSocket::from_inner(net2::UdpSocket::from_inner(socket))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// OsString and OsStr
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Unix-specific extension to the primitives in the `std::ffi` module
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub mod ffi {
|
||||
use ffi::{OsStr, OsString};
|
||||
use mem;
|
||||
use prelude::v1::*;
|
||||
use sys::os_str::Buf;
|
||||
use sys_common::{FromInner, IntoInner, AsInner};
|
||||
|
||||
/// Unix-specific extensions to `OsString`.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait OsStringExt {
|
||||
/// Creates an `OsString` from a byte vector.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn from_vec(vec: Vec<u8>) -> Self;
|
||||
|
||||
/// Yields the underlying byte vector of this `OsString`.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn into_vec(self) -> Vec<u8>;
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl OsStringExt for OsString {
|
||||
fn from_vec(vec: Vec<u8>) -> OsString {
|
||||
FromInner::from_inner(Buf { inner: vec })
|
||||
}
|
||||
fn into_vec(self) -> Vec<u8> {
|
||||
self.into_inner().inner
|
||||
}
|
||||
}
|
||||
|
||||
/// Unix-specific extensions to `OsStr`.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait OsStrExt {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn from_bytes(slice: &[u8]) -> &Self;
|
||||
|
||||
/// Gets the underlying byte view of the `OsStr` slice.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn as_bytes(&self) -> &[u8];
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl OsStrExt for OsStr {
|
||||
fn from_bytes(slice: &[u8]) -> &OsStr {
|
||||
unsafe { mem::transmute(slice) }
|
||||
}
|
||||
fn as_bytes(&self) -> &[u8] {
|
||||
&self.as_inner().inner
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Unix-specific extensions to primitives in the `std::fs` module.
|
||||
#[unstable(feature = "fs_ext",
|
||||
reason = "may want a more useful mode abstraction")]
|
||||
pub mod fs {
|
||||
use sys;
|
||||
use sys_common::{FromInner, AsInner, AsInnerMut};
|
||||
use fs::{Permissions, OpenOptions};
|
||||
use path::Path;
|
||||
use convert::AsRef;
|
||||
use io;
|
||||
|
||||
/// Unix-specific extensions to `Permissions`
|
||||
pub trait PermissionsExt {
|
||||
fn mode(&self) -> i32;
|
||||
fn set_mode(&mut self, mode: i32);
|
||||
}
|
||||
|
||||
impl PermissionsExt for Permissions {
|
||||
fn mode(&self) -> i32 { self.as_inner().mode() }
|
||||
|
||||
fn set_mode(&mut self, mode: i32) {
|
||||
*self = FromInner::from_inner(FromInner::from_inner(mode));
|
||||
}
|
||||
}
|
||||
|
||||
/// Unix-specific extensions to `OpenOptions`
|
||||
pub trait OpenOptionsExt {
|
||||
/// Sets the mode bits that a new file will be created with.
|
||||
///
|
||||
/// If a new file is created as part of a `File::open_opts` call then this
|
||||
/// specified `mode` will be used as the permission bits for the new file.
|
||||
fn mode(&mut self, mode: i32) -> &mut Self;
|
||||
}
|
||||
|
||||
impl OpenOptionsExt for OpenOptions {
|
||||
fn mode(&mut self, mode: i32) -> &mut OpenOptions {
|
||||
self.as_inner_mut().mode(mode); self
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new symbolic link on the filesystem.
|
||||
///
|
||||
/// The `dst` path will be a symbolic link pointing to the `src` path.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// On Windows, you must specify whether a symbolic link points to a file
|
||||
/// or directory. Use `os::windows::fs::symlink_file` to create a
|
||||
/// symbolic link to a file, or `os::windows::fs::symlink_dir` to create a
|
||||
/// symbolic link to a directory. Additionally, the process must have
|
||||
/// `SeCreateSymbolicLinkPrivilege` in order to be able to create a
|
||||
/// symbolic link.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(fs_ext)]
|
||||
/// use std::os::unix::fs;
|
||||
///
|
||||
/// # fn foo() -> std::io::Result<()> {
|
||||
/// try!(fs::symlink("a.txt", "b.txt"));
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()>
|
||||
{
|
||||
sys::fs2::symlink(src.as_ref(), dst.as_ref())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Process and Command
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Unix-specific extensions to primitives in the `std::process` module.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub mod process {
|
||||
use prelude::v1::*;
|
||||
use libc::{uid_t, gid_t};
|
||||
use process;
|
||||
use sys;
|
||||
use sys_common::{AsInnerMut, AsInner};
|
||||
|
||||
/// Unix-specific extensions to the `std::process::Command` builder
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait CommandExt {
|
||||
/// Sets the child process's user id. This translates to a
|
||||
/// `setuid` call in the child process. Failure in the `setuid`
|
||||
/// call will cause the spawn to fail.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn uid(&mut self, id: uid_t) -> &mut process::Command;
|
||||
|
||||
/// Similar to `uid`, but sets the group id of the child process. This has
|
||||
/// the same semantics as the `uid` field.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn gid(&mut self, id: gid_t) -> &mut process::Command;
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl CommandExt for process::Command {
|
||||
fn uid(&mut self, id: uid_t) -> &mut process::Command {
|
||||
self.as_inner_mut().uid = Some(id);
|
||||
self
|
||||
}
|
||||
|
||||
fn gid(&mut self, id: gid_t) -> &mut process::Command {
|
||||
self.as_inner_mut().gid = Some(id);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Unix-specific extensions to `std::process::ExitStatus`
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait ExitStatusExt {
|
||||
/// If the process was terminated by a signal, returns that signal.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn signal(&self) -> Option<i32>;
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl ExitStatusExt for process::ExitStatus {
|
||||
fn signal(&self) -> Option<i32> {
|
||||
match *self.as_inner() {
|
||||
sys::process2::ExitStatus::Signal(s) => Some(s),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Prelude
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// A prelude for conveniently writing platform-specific code.
|
||||
///
|
||||
/// Includes all extension traits, and some important type definitions.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub mod prelude {
|
||||
#[doc(no_inline)]
|
||||
pub use super::io::{RawFd, AsRawFd};
|
||||
#[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use super::ffi::{OsStrExt, OsStringExt};
|
||||
#[doc(no_inline)]
|
||||
pub use super::fs::{PermissionsExt, OpenOptionsExt};
|
||||
#[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use super::process::{CommandExt, ExitStatusExt};
|
||||
}
|
62
src/libstd/sys/unix/ext/ffi.rs
Normal file
62
src/libstd/sys/unix/ext/ffi.rs
Normal file
@ -0,0 +1,62 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Unix-specific extension to the primitives in the `std::ffi` module
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use ffi::{OsStr, OsString};
|
||||
use mem;
|
||||
use prelude::v1::*;
|
||||
use sys::os_str::Buf;
|
||||
use sys_common::{FromInner, IntoInner, AsInner};
|
||||
|
||||
/// Unix-specific extensions to `OsString`.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait OsStringExt {
|
||||
/// Creates an `OsString` from a byte vector.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn from_vec(vec: Vec<u8>) -> Self;
|
||||
|
||||
/// Yields the underlying byte vector of this `OsString`.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn into_vec(self) -> Vec<u8>;
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl OsStringExt for OsString {
|
||||
fn from_vec(vec: Vec<u8>) -> OsString {
|
||||
FromInner::from_inner(Buf { inner: vec })
|
||||
}
|
||||
fn into_vec(self) -> Vec<u8> {
|
||||
self.into_inner().inner
|
||||
}
|
||||
}
|
||||
|
||||
/// Unix-specific extensions to `OsStr`.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait OsStrExt {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn from_bytes(slice: &[u8]) -> &Self;
|
||||
|
||||
/// Gets the underlying byte view of the `OsStr` slice.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn as_bytes(&self) -> &[u8];
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl OsStrExt for OsStr {
|
||||
fn from_bytes(slice: &[u8]) -> &OsStr {
|
||||
unsafe { mem::transmute(slice) }
|
||||
}
|
||||
fn as_bytes(&self) -> &[u8] {
|
||||
&self.as_inner().inner
|
||||
}
|
||||
}
|
191
src/libstd/sys/unix/ext/fs.rs
Normal file
191
src/libstd/sys/unix/ext/fs.rs
Normal file
@ -0,0 +1,191 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Unix-specific extensions to primitives in the `std::fs` module.
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use prelude::v1::*;
|
||||
|
||||
use fs::{self, Permissions, OpenOptions};
|
||||
use io;
|
||||
use mem;
|
||||
use os::raw::c_long;
|
||||
use os::unix::raw;
|
||||
use path::Path;
|
||||
use sys::platform;
|
||||
use sys;
|
||||
use sys_common::{FromInner, AsInner, AsInnerMut};
|
||||
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API")]
|
||||
pub const USER_READ: raw::mode_t = 0o400;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API")]
|
||||
pub const USER_WRITE: raw::mode_t = 0o200;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API")]
|
||||
pub const USER_EXECUTE: raw::mode_t = 0o100;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API")]
|
||||
pub const USER_RWX: raw::mode_t = 0o700;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API")]
|
||||
pub const GROUP_READ: raw::mode_t = 0o040;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API")]
|
||||
pub const GROUP_WRITE: raw::mode_t = 0o020;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API")]
|
||||
pub const GROUP_EXECUTE: raw::mode_t = 0o010;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API")]
|
||||
pub const GROUP_RWX: raw::mode_t = 0o070;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API")]
|
||||
pub const OTHER_READ: raw::mode_t = 0o004;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API")]
|
||||
pub const OTHER_WRITE: raw::mode_t = 0o002;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API")]
|
||||
pub const OTHER_EXECUTE: raw::mode_t = 0o001;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API")]
|
||||
pub const OTHER_RWX: raw::mode_t = 0o007;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API")]
|
||||
pub const ALL_READ: raw::mode_t = 0o444;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API")]
|
||||
pub const ALL_WRITE: raw::mode_t = 0o222;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API")]
|
||||
pub const ALL_EXECUTE: raw::mode_t = 0o111;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API")]
|
||||
pub const ALL_RWX: raw::mode_t = 0o777;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API")]
|
||||
pub const SETUID: raw::mode_t = 0o4000;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API")]
|
||||
pub const SETGID: raw::mode_t = 0o2000;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API")]
|
||||
pub const STICKY_BIT: raw::mode_t = 0o1000;
|
||||
|
||||
/// Unix-specific extensions to `Permissions`
|
||||
#[unstable(feature = "fs_ext",
|
||||
reason = "may want a more useful mode abstraction")]
|
||||
pub trait PermissionsExt {
|
||||
fn mode(&self) -> raw::mode_t;
|
||||
fn set_mode(&mut self, mode: raw::mode_t);
|
||||
fn from_mode(mode: raw::mode_t) -> Self;
|
||||
}
|
||||
|
||||
impl PermissionsExt for Permissions {
|
||||
fn mode(&self) -> raw::mode_t { self.as_inner().mode() }
|
||||
|
||||
fn set_mode(&mut self, mode: raw::mode_t) {
|
||||
*self = FromInner::from_inner(FromInner::from_inner(mode));
|
||||
}
|
||||
|
||||
fn from_mode(mode: raw::mode_t) -> Permissions {
|
||||
FromInner::from_inner(FromInner::from_inner(mode))
|
||||
}
|
||||
}
|
||||
|
||||
/// Unix-specific extensions to `OpenOptions`
|
||||
#[unstable(feature = "fs_ext",
|
||||
reason = "may want a more useful mode abstraction")]
|
||||
pub trait OpenOptionsExt {
|
||||
/// Sets the mode bits that a new file will be created with.
|
||||
///
|
||||
/// If a new file is created as part of a `File::open_opts` call then this
|
||||
/// specified `mode` will be used as the permission bits for the new file.
|
||||
fn mode(&mut self, mode: raw::mode_t) -> &mut Self;
|
||||
}
|
||||
|
||||
impl OpenOptionsExt for OpenOptions {
|
||||
fn mode(&mut self, mode: raw::mode_t) -> &mut OpenOptions {
|
||||
self.as_inner_mut().mode(mode); self
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "metadata_ext", reason = "recently added API")]
|
||||
pub struct Metadata(sys::fs2::FileAttr);
|
||||
|
||||
#[unstable(feature = "metadata_ext", reason = "recently added API")]
|
||||
pub trait MetadataExt {
|
||||
fn as_raw(&self) -> &Metadata;
|
||||
}
|
||||
|
||||
impl MetadataExt for fs::Metadata {
|
||||
fn as_raw(&self) -> &Metadata {
|
||||
let inner: &sys::fs2::FileAttr = self.as_inner();
|
||||
unsafe { mem::transmute(inner) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInner<platform::raw::stat> for Metadata {
|
||||
fn as_inner(&self) -> &platform::raw::stat { self.0.as_inner() }
|
||||
}
|
||||
|
||||
// Hm, why are there casts here to the returned type, shouldn't the types always
|
||||
// be the same? Right you are! Turns out, however, on android at least the types
|
||||
// in the raw `stat` structure are not the same as the types being returned. Who
|
||||
// knew!
|
||||
//
|
||||
// As a result to make sure this compiles for all platforms we do the manual
|
||||
// casts and rely on manual lowering to `stat` if the raw type is desired.
|
||||
#[unstable(feature = "metadata_ext", reason = "recently added API")]
|
||||
impl Metadata {
|
||||
pub fn dev(&self) -> raw::dev_t { self.0.raw().st_dev as raw::dev_t }
|
||||
pub fn ino(&self) -> raw::ino_t { self.0.raw().st_ino as raw::ino_t }
|
||||
pub fn mode(&self) -> raw::mode_t { self.0.raw().st_mode as raw::mode_t }
|
||||
pub fn nlink(&self) -> raw::nlink_t { self.0.raw().st_nlink as raw::nlink_t }
|
||||
pub fn uid(&self) -> raw::uid_t { self.0.raw().st_uid as raw::uid_t }
|
||||
pub fn gid(&self) -> raw::gid_t { self.0.raw().st_gid as raw::gid_t }
|
||||
pub fn rdev(&self) -> raw::dev_t { self.0.raw().st_rdev as raw::dev_t }
|
||||
pub fn size(&self) -> raw::off_t { self.0.raw().st_size as raw::off_t }
|
||||
pub fn atime(&self) -> raw::time_t { self.0.raw().st_atime }
|
||||
pub fn atime_nsec(&self) -> c_long { self.0.raw().st_atime }
|
||||
pub fn mtime(&self) -> raw::time_t { self.0.raw().st_mtime }
|
||||
pub fn mtime_nsec(&self) -> c_long { self.0.raw().st_mtime }
|
||||
pub fn ctime(&self) -> raw::time_t { self.0.raw().st_ctime }
|
||||
pub fn ctime_nsec(&self) -> c_long { self.0.raw().st_ctime }
|
||||
|
||||
pub fn blksize(&self) -> raw::blksize_t {
|
||||
self.0.raw().st_blksize as raw::blksize_t
|
||||
}
|
||||
pub fn blocks(&self) -> raw::blkcnt_t {
|
||||
self.0.raw().st_blocks as raw::blkcnt_t
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "dir_entry_ext", reason = "recently added API")]
|
||||
pub trait DirEntryExt {
|
||||
fn ino(&self) -> raw::ino_t;
|
||||
}
|
||||
|
||||
impl DirEntryExt for fs::DirEntry {
|
||||
fn ino(&self) -> raw::ino_t { self.as_inner().ino() }
|
||||
}
|
||||
|
||||
/// Creates a new symbolic link on the filesystem.
|
||||
///
|
||||
/// The `dst` path will be a symbolic link pointing to the `src` path.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// On Windows, you must specify whether a symbolic link points to a file
|
||||
/// or directory. Use `os::windows::fs::symlink_file` to create a
|
||||
/// symbolic link to a file, or `os::windows::fs::symlink_dir` to create a
|
||||
/// symbolic link to a directory. Additionally, the process must have
|
||||
/// `SeCreateSymbolicLinkPrivilege` in order to be able to create a
|
||||
/// symbolic link.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::os::unix::fs;
|
||||
///
|
||||
/// # fn foo() -> std::io::Result<()> {
|
||||
/// try!(fs::symlink("a.txt", "b.txt"));
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()>
|
||||
{
|
||||
sys::fs2::symlink(src.as_ref(), dst.as_ref())
|
||||
}
|
108
src/libstd/sys/unix/ext/io.rs
Normal file
108
src/libstd/sys/unix/ext/io.rs
Normal file
@ -0,0 +1,108 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Unix-specific extensions to general I/O primitives
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use fs;
|
||||
use net;
|
||||
use os::raw;
|
||||
use sys;
|
||||
use sys_common::{net2, AsInner, FromInner};
|
||||
|
||||
/// Raw file descriptors.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub type RawFd = raw::c_int;
|
||||
|
||||
/// A trait to extract the raw unix file descriptor from an underlying
|
||||
/// object.
|
||||
///
|
||||
/// This is only available on unix platforms and must be imported in order
|
||||
/// to call the method. Windows platforms have a corresponding `AsRawHandle`
|
||||
/// and `AsRawSocket` set of traits.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait AsRawFd {
|
||||
/// Extracts the raw file descriptor.
|
||||
///
|
||||
/// This method does **not** pass ownership of the raw file descriptor
|
||||
/// to the caller. The descriptor is only guarantee to be valid while
|
||||
/// the original object has not yet been destroyed.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn as_raw_fd(&self) -> RawFd;
|
||||
}
|
||||
|
||||
/// A trait to express the ability to construct an object from a raw file
|
||||
/// descriptor.
|
||||
#[unstable(feature = "from_raw_os",
|
||||
reason = "recent addition to std::os::unix::io")]
|
||||
pub trait FromRawFd {
|
||||
/// Constructs a new instances of `Self` from the given raw file
|
||||
/// descriptor.
|
||||
///
|
||||
/// This function **consumes ownership** of the specified file
|
||||
/// descriptor. The returned object will take responsibility for closing
|
||||
/// it when the object goes out of scope.
|
||||
///
|
||||
/// This function is also unsafe as the primitives currently returned
|
||||
/// have the contract that they are the sole owner of the file
|
||||
/// descriptor they are wrapping. Usage of this function could
|
||||
/// accidentally allow violating this contract which can cause memory
|
||||
/// unsafety in code that relies on it being true.
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> Self;
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl AsRawFd for fs::File {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.as_inner().fd().raw()
|
||||
}
|
||||
}
|
||||
#[unstable(feature = "from_raw_os", reason = "trait is unstable")]
|
||||
impl FromRawFd for fs::File {
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> fs::File {
|
||||
fs::File::from_inner(sys::fs2::File::from_inner(fd))
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl AsRawFd for net::TcpStream {
|
||||
fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl AsRawFd for net::TcpListener {
|
||||
fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl AsRawFd for net::UdpSocket {
|
||||
fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
|
||||
}
|
||||
|
||||
#[unstable(feature = "from_raw_os", reason = "trait is unstable")]
|
||||
impl FromRawFd for net::TcpStream {
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream {
|
||||
let socket = sys::net::Socket::from_inner(fd);
|
||||
net::TcpStream::from_inner(net2::TcpStream::from_inner(socket))
|
||||
}
|
||||
}
|
||||
#[unstable(feature = "from_raw_os", reason = "trait is unstable")]
|
||||
impl FromRawFd for net::TcpListener {
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener {
|
||||
let socket = sys::net::Socket::from_inner(fd);
|
||||
net::TcpListener::from_inner(net2::TcpListener::from_inner(socket))
|
||||
}
|
||||
}
|
||||
#[unstable(feature = "from_raw_os", reason = "trait is unstable")]
|
||||
impl FromRawFd for net::UdpSocket {
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket {
|
||||
let socket = sys::net::Socket::from_inner(fd);
|
||||
net::UdpSocket::from_inner(net2::UdpSocket::from_inner(socket))
|
||||
}
|
||||
}
|
53
src/libstd/sys/unix/ext/mod.rs
Normal file
53
src/libstd/sys/unix/ext/mod.rs
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright 2014 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Experimental extensions to `std` for Unix platforms.
|
||||
//!
|
||||
//! For now, this module is limited to extracting file descriptors,
|
||||
//! but its functionality will grow over time.
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use std::fs::File;
|
||||
//! use std::os::unix::prelude::*;
|
||||
//!
|
||||
//! fn main() {
|
||||
//! let f = File::create("foo.txt").unwrap();
|
||||
//! let fd = f.as_raw_fd();
|
||||
//!
|
||||
//! // use fd with native unix bindings
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
pub mod io;
|
||||
pub mod ffi;
|
||||
pub mod fs;
|
||||
pub mod process;
|
||||
pub mod raw;
|
||||
|
||||
/// A prelude for conveniently writing platform-specific code.
|
||||
///
|
||||
/// Includes all extension traits, and some important type definitions.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub mod prelude {
|
||||
#[doc(no_inline)]
|
||||
pub use super::io::{RawFd, AsRawFd};
|
||||
#[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use super::ffi::{OsStrExt, OsStringExt};
|
||||
#[doc(no_inline)]
|
||||
pub use super::fs::{PermissionsExt, OpenOptionsExt, MetadataExt};
|
||||
#[doc(no_inline)]
|
||||
pub use super::fs::{DirEntryExt};
|
||||
#[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use super::process::{CommandExt, ExitStatusExt};
|
||||
}
|
65
src/libstd/sys/unix/ext/process.rs
Normal file
65
src/libstd/sys/unix/ext/process.rs
Normal file
@ -0,0 +1,65 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Unix-specific extensions to primitives in the `std::process` module.
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use os::unix::raw::{uid_t, gid_t};
|
||||
use prelude::v1::*;
|
||||
use process;
|
||||
use sys;
|
||||
use sys_common::{AsInnerMut, AsInner};
|
||||
|
||||
/// Unix-specific extensions to the `std::process::Command` builder
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait CommandExt {
|
||||
/// Sets the child process's user id. This translates to a
|
||||
/// `setuid` call in the child process. Failure in the `setuid`
|
||||
/// call will cause the spawn to fail.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn uid(&mut self, id: uid_t) -> &mut process::Command;
|
||||
|
||||
/// Similar to `uid`, but sets the group id of the child process. This has
|
||||
/// the same semantics as the `uid` field.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn gid(&mut self, id: gid_t) -> &mut process::Command;
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl CommandExt for process::Command {
|
||||
fn uid(&mut self, id: uid_t) -> &mut process::Command {
|
||||
self.as_inner_mut().uid = Some(id);
|
||||
self
|
||||
}
|
||||
|
||||
fn gid(&mut self, id: gid_t) -> &mut process::Command {
|
||||
self.as_inner_mut().gid = Some(id);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Unix-specific extensions to `std::process::ExitStatus`
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait ExitStatusExt {
|
||||
/// If the process was terminated by a signal, returns that signal.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn signal(&self) -> Option<i32>;
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl ExitStatusExt for process::ExitStatus {
|
||||
fn signal(&self) -> Option<i32> {
|
||||
match *self.as_inner() {
|
||||
sys::process2::ExitStatus::Signal(s) => Some(s),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
22
src/libstd/sys/unix/ext/raw.rs
Normal file
22
src/libstd/sys/unix/ext/raw.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Unix-specific primitives available on all unix platforms
|
||||
|
||||
#![unstable(feature = "raw_ext", reason = "recently added API")]
|
||||
|
||||
pub type uid_t = u32;
|
||||
pub type gid_t = u32;
|
||||
pub type pid_t = i32;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use sys::platform::raw::{dev_t, ino_t, mode_t, nlink_t, off_t, blksize_t};
|
||||
#[doc(inline)]
|
||||
pub use sys::platform::raw::{blkcnt_t, time_t};
|
@ -21,14 +21,15 @@ use path::{Path, PathBuf};
|
||||
use ptr;
|
||||
use sync::Arc;
|
||||
use sys::fd::FileDesc;
|
||||
use sys::platform::raw;
|
||||
use sys::{c, cvt, cvt_r};
|
||||
use sys_common::FromInner;
|
||||
use sys_common::{AsInner, FromInner};
|
||||
use vec::Vec;
|
||||
|
||||
pub struct File(FileDesc);
|
||||
|
||||
pub struct FileAttr {
|
||||
stat: libc::stat,
|
||||
stat: raw::stat,
|
||||
}
|
||||
|
||||
pub struct ReadDir {
|
||||
@ -57,13 +58,10 @@ pub struct OpenOptions {
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct FilePermissions { mode: mode_t }
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct FileType { mode: mode_t }
|
||||
|
||||
impl FileAttr {
|
||||
pub fn is_dir(&self) -> bool {
|
||||
(self.stat.st_mode as mode_t) & libc::S_IFMT == libc::S_IFDIR
|
||||
}
|
||||
pub fn is_file(&self) -> bool {
|
||||
(self.stat.st_mode as mode_t) & libc::S_IFMT == libc::S_IFREG
|
||||
}
|
||||
pub fn size(&self) -> u64 { self.stat.st_size as u64 }
|
||||
pub fn perm(&self) -> FilePermissions {
|
||||
FilePermissions { mode: (self.stat.st_mode as mode_t) & 0o777 }
|
||||
@ -76,12 +74,35 @@ impl FileAttr {
|
||||
self.mktime(self.stat.st_mtime as u64, self.stat.st_mtime_nsec as u64)
|
||||
}
|
||||
|
||||
pub fn file_type(&self) -> FileType {
|
||||
FileType { mode: self.stat.st_mode as mode_t }
|
||||
}
|
||||
|
||||
pub fn raw(&self) -> &raw::stat { &self.stat }
|
||||
|
||||
// times are in milliseconds (currently)
|
||||
fn mktime(&self, secs: u64, nsecs: u64) -> u64 {
|
||||
secs * 1000 + nsecs / 1000000
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInner<raw::stat> for FileAttr {
|
||||
fn as_inner(&self) -> &raw::stat { &self.stat }
|
||||
}
|
||||
|
||||
#[unstable(feature = "metadata_ext", reason = "recently added API")]
|
||||
pub trait MetadataExt {
|
||||
fn as_raw_stat(&self) -> &raw::stat;
|
||||
}
|
||||
|
||||
impl MetadataExt for ::fs::Metadata {
|
||||
fn as_raw_stat(&self) -> &raw::stat { &self.as_inner().stat }
|
||||
}
|
||||
|
||||
impl MetadataExt for ::os::unix::fs::Metadata {
|
||||
fn as_raw_stat(&self) -> &raw::stat { self.as_inner() }
|
||||
}
|
||||
|
||||
impl FilePermissions {
|
||||
pub fn readonly(&self) -> bool { self.mode & 0o222 == 0 }
|
||||
pub fn set_readonly(&mut self, readonly: bool) {
|
||||
@ -91,11 +112,19 @@ impl FilePermissions {
|
||||
self.mode |= 0o222;
|
||||
}
|
||||
}
|
||||
pub fn mode(&self) -> i32 { self.mode as i32 }
|
||||
pub fn mode(&self) -> raw::mode_t { self.mode }
|
||||
}
|
||||
|
||||
impl FromInner<i32> for FilePermissions {
|
||||
fn from_inner(mode: i32) -> FilePermissions {
|
||||
impl FileType {
|
||||
pub fn is_dir(&self) -> bool { self.is(libc::S_IFDIR) }
|
||||
pub fn is_file(&self) -> bool { self.is(libc::S_IFREG) }
|
||||
pub fn is_symlink(&self) -> bool { self.is(libc::S_IFLNK) }
|
||||
|
||||
fn is(&self, mode: mode_t) -> bool { self.mode & libc::S_IFMT == mode }
|
||||
}
|
||||
|
||||
impl FromInner<raw::mode_t> for FilePermissions {
|
||||
fn from_inner(mode: raw::mode_t) -> FilePermissions {
|
||||
FilePermissions { mode: mode as mode_t }
|
||||
}
|
||||
}
|
||||
@ -147,6 +176,33 @@ impl DirEntry {
|
||||
self.root.join(<OsStr as OsStrExt>::from_bytes(self.name_bytes()))
|
||||
}
|
||||
|
||||
pub fn file_name(&self) -> OsString {
|
||||
OsStr::from_bytes(self.name_bytes()).to_os_string()
|
||||
}
|
||||
|
||||
pub fn metadata(&self) -> io::Result<FileAttr> {
|
||||
lstat(&self.path())
|
||||
}
|
||||
|
||||
pub fn file_type(&self) -> io::Result<FileType> {
|
||||
extern {
|
||||
fn rust_dir_get_mode(ptr: *mut libc::dirent_t) -> c_int;
|
||||
}
|
||||
unsafe {
|
||||
match rust_dir_get_mode(self.dirent()) {
|
||||
-1 => lstat(&self.path()).map(|m| m.file_type()),
|
||||
n => Ok(FileType { mode: n as mode_t }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ino(&self) -> raw::ino_t {
|
||||
extern {
|
||||
fn rust_dir_get_ino(ptr: *mut libc::dirent_t) -> raw::ino_t;
|
||||
}
|
||||
unsafe { rust_dir_get_ino(self.dirent()) }
|
||||
}
|
||||
|
||||
fn name_bytes(&self) -> &[u8] {
|
||||
extern {
|
||||
fn rust_list_dir_val(ptr: *mut libc::dirent_t) -> *const c_char;
|
||||
@ -191,7 +247,7 @@ impl OpenOptions {
|
||||
self.flag(libc::O_CREAT, create);
|
||||
}
|
||||
|
||||
pub fn mode(&mut self, mode: i32) {
|
||||
pub fn mode(&mut self, mode: raw::mode_t) {
|
||||
self.mode = mode as mode_t;
|
||||
}
|
||||
|
||||
@ -228,8 +284,10 @@ impl File {
|
||||
pub fn into_fd(self) -> FileDesc { self.0 }
|
||||
|
||||
pub fn file_attr(&self) -> io::Result<FileAttr> {
|
||||
let mut stat: libc::stat = unsafe { mem::zeroed() };
|
||||
try!(cvt(unsafe { libc::fstat(self.0.raw(), &mut stat) }));
|
||||
let mut stat: raw::stat = unsafe { mem::zeroed() };
|
||||
try!(cvt(unsafe {
|
||||
libc::fstat(self.0.raw(), &mut stat as *mut _ as *mut _)
|
||||
}));
|
||||
Ok(FileAttr { stat: stat })
|
||||
}
|
||||
|
||||
@ -420,15 +478,19 @@ pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
|
||||
|
||||
pub fn stat(p: &Path) -> io::Result<FileAttr> {
|
||||
let p = try!(cstr(p));
|
||||
let mut stat: libc::stat = unsafe { mem::zeroed() };
|
||||
try!(cvt(unsafe { libc::stat(p.as_ptr(), &mut stat) }));
|
||||
let mut stat: raw::stat = unsafe { mem::zeroed() };
|
||||
try!(cvt(unsafe {
|
||||
libc::stat(p.as_ptr(), &mut stat as *mut _ as *mut _)
|
||||
}));
|
||||
Ok(FileAttr { stat: stat })
|
||||
}
|
||||
|
||||
pub fn lstat(p: &Path) -> io::Result<FileAttr> {
|
||||
let p = try!(cstr(p));
|
||||
let mut stat: libc::stat = unsafe { mem::zeroed() };
|
||||
try!(cvt(unsafe { libc::lstat(p.as_ptr(), &mut stat) }));
|
||||
let mut stat: raw::stat = unsafe { mem::zeroed() };
|
||||
try!(cvt(unsafe {
|
||||
libc::lstat(p.as_ptr(), &mut stat as *mut _ as *mut _)
|
||||
}));
|
||||
Ok(FileAttr { stat: stat })
|
||||
}
|
||||
|
||||
@ -438,3 +500,17 @@ pub fn utimes(p: &Path, atime: u64, mtime: u64) -> io::Result<()> {
|
||||
try!(cvt(unsafe { c::utimes(p.as_ptr(), buf.as_ptr()) }));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
|
||||
let path = try!(CString::new(p.as_os_str().as_bytes()));
|
||||
let mut buf = vec![0u8; 16 * 1024];
|
||||
unsafe {
|
||||
let r = c::realpath(path.as_ptr(), buf.as_mut_ptr() as *mut _);
|
||||
if r.is_null() {
|
||||
return Err(io::Error::last_os_error())
|
||||
}
|
||||
}
|
||||
let p = buf.iter().position(|i| *i == 0).unwrap();
|
||||
buf.truncate(p);
|
||||
Ok(PathBuf::from(OsString::from_vec(buf)))
|
||||
}
|
||||
|
@ -18,6 +18,16 @@ use libc;
|
||||
use num::One;
|
||||
use ops::Neg;
|
||||
|
||||
#[cfg(target_os = "android")] pub use os::android as platform;
|
||||
#[cfg(target_os = "bitrig")] pub use os::bitrig as platform;
|
||||
#[cfg(target_os = "dragonfly")] pub use os::dragonfly as platform;
|
||||
#[cfg(target_os = "freebsd")] pub use os::freebsd as platform;
|
||||
#[cfg(target_os = "ios")] pub use os::ios as platform;
|
||||
#[cfg(target_os = "linux")] pub use os::linux as platform;
|
||||
#[cfg(target_os = "macos")] pub use os::macos as platform;
|
||||
#[cfg(target_os = "nacl")] pub use os::nacl as platform;
|
||||
#[cfg(target_os = "openbsd")] pub use os::openbsd as platform;
|
||||
|
||||
pub mod backtrace;
|
||||
pub mod c;
|
||||
pub mod condvar;
|
||||
|
@ -1,301 +0,0 @@
|
||||
// Copyright 2014 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Experimental extensions to `std` for Windows.
|
||||
//!
|
||||
//! For now, this module is limited to extracting handles, file
|
||||
//! descriptors, and sockets, but its functionality will grow over
|
||||
//! time.
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub mod io {
|
||||
use fs;
|
||||
use libc;
|
||||
use net;
|
||||
use sys_common::{net2, AsInner, FromInner};
|
||||
use sys;
|
||||
|
||||
/// Raw HANDLEs.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub type RawHandle = libc::HANDLE;
|
||||
|
||||
/// Raw SOCKETs.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub type RawSocket = libc::SOCKET;
|
||||
|
||||
/// Extract raw handles.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait AsRawHandle {
|
||||
/// Extracts the raw handle, without taking any ownership.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn as_raw_handle(&self) -> RawHandle;
|
||||
}
|
||||
|
||||
/// Construct I/O objects from raw handles.
|
||||
#[unstable(feature = "from_raw_os",
|
||||
reason = "recent addition to the std::os::windows::io module")]
|
||||
pub trait FromRawHandle {
|
||||
/// Constructs a new I/O object from the specified raw handle.
|
||||
///
|
||||
/// This function will **consume ownership** of the handle given,
|
||||
/// passing responsibility for closing the handle to the returned
|
||||
/// object.
|
||||
///
|
||||
/// This function is also unsafe as the primitives currently returned
|
||||
/// have the contract that they are the sole owner of the file
|
||||
/// descriptor they are wrapping. Usage of this function could
|
||||
/// accidentally allow violating this contract which can cause memory
|
||||
/// unsafety in code that relies on it being true.
|
||||
unsafe fn from_raw_handle(handle: RawHandle) -> Self;
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl AsRawHandle for fs::File {
|
||||
fn as_raw_handle(&self) -> RawHandle {
|
||||
self.as_inner().handle().raw()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "from_raw_os", reason = "trait is unstable")]
|
||||
impl FromRawHandle for fs::File {
|
||||
unsafe fn from_raw_handle(handle: RawHandle) -> fs::File {
|
||||
fs::File::from_inner(sys::fs2::File::from_inner(handle))
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract raw sockets.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait AsRawSocket {
|
||||
/// Extracts the underlying raw socket from this object.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn as_raw_socket(&self) -> RawSocket;
|
||||
}
|
||||
|
||||
/// Create I/O objects from raw sockets.
|
||||
#[unstable(feature = "from_raw_os", reason = "recent addition to module")]
|
||||
pub trait FromRawSocket {
|
||||
/// Creates a new I/O object from the given raw socket.
|
||||
///
|
||||
/// This function will **consume ownership** of the socket provided and
|
||||
/// it will be closed when the returned object goes out of scope.
|
||||
///
|
||||
/// This function is also unsafe as the primitives currently returned
|
||||
/// have the contract that they are the sole owner of the file
|
||||
/// descriptor they are wrapping. Usage of this function could
|
||||
/// accidentally allow violating this contract which can cause memory
|
||||
/// unsafety in code that relies on it being true.
|
||||
unsafe fn from_raw_socket(sock: RawSocket) -> Self;
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl AsRawSocket for net::TcpStream {
|
||||
fn as_raw_socket(&self) -> RawSocket {
|
||||
*self.as_inner().socket().as_inner()
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl AsRawSocket for net::TcpListener {
|
||||
fn as_raw_socket(&self) -> RawSocket {
|
||||
*self.as_inner().socket().as_inner()
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl AsRawSocket for net::UdpSocket {
|
||||
fn as_raw_socket(&self) -> RawSocket {
|
||||
*self.as_inner().socket().as_inner()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "from_raw_os", reason = "trait is unstable")]
|
||||
impl FromRawSocket for net::TcpStream {
|
||||
unsafe fn from_raw_socket(sock: RawSocket) -> net::TcpStream {
|
||||
let sock = sys::net::Socket::from_inner(sock);
|
||||
net::TcpStream::from_inner(net2::TcpStream::from_inner(sock))
|
||||
}
|
||||
}
|
||||
#[unstable(feature = "from_raw_os", reason = "trait is unstable")]
|
||||
impl FromRawSocket for net::TcpListener {
|
||||
unsafe fn from_raw_socket(sock: RawSocket) -> net::TcpListener {
|
||||
let sock = sys::net::Socket::from_inner(sock);
|
||||
net::TcpListener::from_inner(net2::TcpListener::from_inner(sock))
|
||||
}
|
||||
}
|
||||
#[unstable(feature = "from_raw_os", reason = "trait is unstable")]
|
||||
impl FromRawSocket for net::UdpSocket {
|
||||
unsafe fn from_raw_socket(sock: RawSocket) -> net::UdpSocket {
|
||||
let sock = sys::net::Socket::from_inner(sock);
|
||||
net::UdpSocket::from_inner(net2::UdpSocket::from_inner(sock))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Windows-specific extensions to the primitives in the `std::ffi` module.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub mod ffi {
|
||||
use ffi::{OsString, OsStr};
|
||||
use sys::os_str::Buf;
|
||||
use sys_common::wtf8::Wtf8Buf;
|
||||
use sys_common::{FromInner, AsInner};
|
||||
|
||||
pub use sys_common::wtf8::EncodeWide;
|
||||
|
||||
/// Windows-specific extensions to `OsString`.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait OsStringExt {
|
||||
/// Creates an `OsString` from a potentially ill-formed UTF-16 slice of
|
||||
/// 16-bit code units.
|
||||
///
|
||||
/// This is lossless: calling `.encode_wide()` on the resulting string
|
||||
/// will always return the original code units.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn from_wide(wide: &[u16]) -> Self;
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl OsStringExt for OsString {
|
||||
fn from_wide(wide: &[u16]) -> OsString {
|
||||
FromInner::from_inner(Buf { inner: Wtf8Buf::from_wide(wide) })
|
||||
}
|
||||
}
|
||||
|
||||
/// Windows-specific extensions to `OsStr`.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait OsStrExt {
|
||||
/// Re-encodes an `OsStr` as a wide character sequence,
|
||||
/// i.e. potentially ill-formed UTF-16.
|
||||
///
|
||||
/// This is lossless. Note that the encoding does not include a final
|
||||
/// null.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn encode_wide(&self) -> EncodeWide;
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl OsStrExt for OsStr {
|
||||
fn encode_wide(&self) -> EncodeWide {
|
||||
self.as_inner().inner.encode_wide()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Windows-specific extensions for the primitives in `std::fs`
|
||||
#[unstable(feature = "fs_ext", reason = "may require more thought/methods")]
|
||||
pub mod fs {
|
||||
use fs::OpenOptions;
|
||||
use sys;
|
||||
use sys_common::AsInnerMut;
|
||||
use path::Path;
|
||||
use convert::AsRef;
|
||||
use io;
|
||||
|
||||
/// Windows-specific extensions to `OpenOptions`
|
||||
pub trait OpenOptionsExt {
|
||||
/// Overrides the `dwDesiredAccess` argument to the call to `CreateFile`
|
||||
/// with the specified value.
|
||||
fn desired_access(&mut self, access: i32) -> &mut Self;
|
||||
|
||||
/// Overrides the `dwCreationDisposition` argument to the call to
|
||||
/// `CreateFile` with the specified value.
|
||||
///
|
||||
/// This will override any values of the standard `create` flags, for
|
||||
/// example.
|
||||
fn creation_disposition(&mut self, val: i32) -> &mut Self;
|
||||
|
||||
/// Overrides the `dwFlagsAndAttributes` argument to the call to
|
||||
/// `CreateFile` with the specified value.
|
||||
///
|
||||
/// This will override any values of the standard flags on the
|
||||
/// `OpenOptions` structure.
|
||||
fn flags_and_attributes(&mut self, val: i32) -> &mut Self;
|
||||
|
||||
/// Overrides the `dwShareMode` argument to the call to `CreateFile` with
|
||||
/// the specified value.
|
||||
///
|
||||
/// This will override any values of the standard flags on the
|
||||
/// `OpenOptions` structure.
|
||||
fn share_mode(&mut self, val: i32) -> &mut Self;
|
||||
}
|
||||
|
||||
impl OpenOptionsExt for OpenOptions {
|
||||
fn desired_access(&mut self, access: i32) -> &mut OpenOptions {
|
||||
self.as_inner_mut().desired_access(access); self
|
||||
}
|
||||
fn creation_disposition(&mut self, access: i32) -> &mut OpenOptions {
|
||||
self.as_inner_mut().creation_disposition(access); self
|
||||
}
|
||||
fn flags_and_attributes(&mut self, access: i32) -> &mut OpenOptions {
|
||||
self.as_inner_mut().flags_and_attributes(access); self
|
||||
}
|
||||
fn share_mode(&mut self, access: i32) -> &mut OpenOptions {
|
||||
self.as_inner_mut().share_mode(access); self
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new file symbolic link on the filesystem.
|
||||
///
|
||||
/// The `dst` path will be a file symbolic link pointing to the `src`
|
||||
/// path.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// #![feature(fs_ext)]
|
||||
/// use std::os::windows::fs;
|
||||
///
|
||||
/// # fn foo() -> std::io::Result<()> {
|
||||
/// try!(fs::symlink_file("a.txt", "b.txt"));
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q)
|
||||
-> io::Result<()>
|
||||
{
|
||||
sys::fs2::symlink_inner(src.as_ref(), dst.as_ref(), false)
|
||||
}
|
||||
|
||||
/// Creates a new directory symlink on the filesystem.
|
||||
///
|
||||
/// The `dst` path will be a directory symbolic link pointing to the `src`
|
||||
/// path.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// #![feature(fs_ext)]
|
||||
/// use std::os::windows::fs;
|
||||
///
|
||||
/// # fn foo() -> std::io::Result<()> {
|
||||
/// try!(fs::symlink_file("a", "b"));
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>> (src: P, dst: Q)
|
||||
-> io::Result<()>
|
||||
{
|
||||
sys::fs2::symlink_inner(src.as_ref(), dst.as_ref(), true)
|
||||
}
|
||||
}
|
||||
|
||||
/// A prelude for conveniently writing platform-specific code.
|
||||
///
|
||||
/// Includes all extension traits, and some important type definitions.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub mod prelude {
|
||||
#[doc(no_inline)]
|
||||
pub use super::io::{RawSocket, RawHandle, AsRawSocket, AsRawHandle};
|
||||
#[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use super::ffi::{OsStrExt, OsStringExt};
|
||||
#[doc(no_inline)]
|
||||
pub use super::fs::OpenOptionsExt;
|
||||
}
|
58
src/libstd/sys/windows/ext/ffi.rs
Normal file
58
src/libstd/sys/windows/ext/ffi.rs
Normal file
@ -0,0 +1,58 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Windows-specific extensions to the primitives in the `std::ffi` module.
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use ffi::{OsString, OsStr};
|
||||
use sys::os_str::Buf;
|
||||
use sys_common::wtf8::Wtf8Buf;
|
||||
use sys_common::{FromInner, AsInner};
|
||||
|
||||
pub use sys_common::wtf8::EncodeWide;
|
||||
|
||||
/// Windows-specific extensions to `OsString`.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait OsStringExt {
|
||||
/// Creates an `OsString` from a potentially ill-formed UTF-16 slice of
|
||||
/// 16-bit code units.
|
||||
///
|
||||
/// This is lossless: calling `.encode_wide()` on the resulting string
|
||||
/// will always return the original code units.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn from_wide(wide: &[u16]) -> Self;
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl OsStringExt for OsString {
|
||||
fn from_wide(wide: &[u16]) -> OsString {
|
||||
FromInner::from_inner(Buf { inner: Wtf8Buf::from_wide(wide) })
|
||||
}
|
||||
}
|
||||
|
||||
/// Windows-specific extensions to `OsStr`.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait OsStrExt {
|
||||
/// Re-encodes an `OsStr` as a wide character sequence,
|
||||
/// i.e. potentially ill-formed UTF-16.
|
||||
///
|
||||
/// This is lossless. Note that the encoding does not include a final
|
||||
/// null.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn encode_wide(&self) -> EncodeWide;
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl OsStrExt for OsStr {
|
||||
fn encode_wide(&self) -> EncodeWide {
|
||||
self.as_inner().inner.encode_wide()
|
||||
}
|
||||
}
|
150
src/libstd/sys/windows/ext/fs.rs
Normal file
150
src/libstd/sys/windows/ext/fs.rs
Normal file
@ -0,0 +1,150 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Windows-specific extensions for the primitives in `std::fs`
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use prelude::v1::*;
|
||||
|
||||
use fs::{OpenOptions, Metadata};
|
||||
use io;
|
||||
use path::Path;
|
||||
use sys;
|
||||
use sys_common::{AsInnerMut, AsInner};
|
||||
|
||||
/// Windows-specific extensions to `OpenOptions`
|
||||
#[unstable(feature = "fs_ext", reason = "may require more thought/methods")]
|
||||
pub trait OpenOptionsExt {
|
||||
/// Overrides the `dwDesiredAccess` argument to the call to `CreateFile`
|
||||
/// with the specified value.
|
||||
fn desired_access(&mut self, access: i32) -> &mut Self;
|
||||
|
||||
/// Overrides the `dwCreationDisposition` argument to the call to
|
||||
/// `CreateFile` with the specified value.
|
||||
///
|
||||
/// This will override any values of the standard `create` flags, for
|
||||
/// example.
|
||||
fn creation_disposition(&mut self, val: i32) -> &mut Self;
|
||||
|
||||
/// Overrides the `dwFlagsAndAttributes` argument to the call to
|
||||
/// `CreateFile` with the specified value.
|
||||
///
|
||||
/// This will override any values of the standard flags on the
|
||||
/// `OpenOptions` structure.
|
||||
fn flags_and_attributes(&mut self, val: i32) -> &mut Self;
|
||||
|
||||
/// Overrides the `dwShareMode` argument to the call to `CreateFile` with
|
||||
/// the specified value.
|
||||
///
|
||||
/// This will override any values of the standard flags on the
|
||||
/// `OpenOptions` structure.
|
||||
fn share_mode(&mut self, val: i32) -> &mut Self;
|
||||
}
|
||||
|
||||
impl OpenOptionsExt for OpenOptions {
|
||||
fn desired_access(&mut self, access: i32) -> &mut OpenOptions {
|
||||
self.as_inner_mut().desired_access(access); self
|
||||
}
|
||||
fn creation_disposition(&mut self, access: i32) -> &mut OpenOptions {
|
||||
self.as_inner_mut().creation_disposition(access); self
|
||||
}
|
||||
fn flags_and_attributes(&mut self, access: i32) -> &mut OpenOptions {
|
||||
self.as_inner_mut().flags_and_attributes(access); self
|
||||
}
|
||||
fn share_mode(&mut self, access: i32) -> &mut OpenOptions {
|
||||
self.as_inner_mut().share_mode(access); self
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension methods for `fs::Metadata` to access the raw fields contained
|
||||
/// within.
|
||||
#[unstable(feature = "metadata_ext", reason = "recently added API")]
|
||||
pub trait MetadataExt {
|
||||
/// Returns the value of the `dwFileAttributes` field of this metadata.
|
||||
///
|
||||
/// This field contains the file system attribute information for a file
|
||||
/// or directory.
|
||||
fn file_attributes(&self) -> u32;
|
||||
|
||||
/// Returns the value of the `ftCreationTime` field of this metadata.
|
||||
///
|
||||
/// The returned 64-bit value represents the number of 100-nanosecond
|
||||
/// intervals since January 1, 1601 (UTC).
|
||||
fn creation_time(&self) -> u64;
|
||||
|
||||
/// Returns the value of the `ftLastAccessTime` field of this metadata.
|
||||
///
|
||||
/// The returned 64-bit value represents the number of 100-nanosecond
|
||||
/// intervals since January 1, 1601 (UTC).
|
||||
fn last_access_time(&self) -> u64;
|
||||
|
||||
/// Returns the value of the `ftLastWriteTime` field of this metadata.
|
||||
///
|
||||
/// The returned 64-bit value represents the number of 100-nanosecond
|
||||
/// intervals since January 1, 1601 (UTC).
|
||||
fn last_write_time(&self) -> u64;
|
||||
|
||||
/// Returns the value of the `nFileSize{High,Low}` fields of this
|
||||
/// metadata.
|
||||
///
|
||||
/// The returned value does not have meaning for directories.
|
||||
fn file_size(&self) -> u64;
|
||||
}
|
||||
|
||||
impl MetadataExt for Metadata {
|
||||
fn file_attributes(&self) -> u32 { self.as_inner().attrs() }
|
||||
fn creation_time(&self) -> u64 { self.as_inner().created() }
|
||||
fn last_access_time(&self) -> u64 { self.as_inner().accessed() }
|
||||
fn last_write_time(&self) -> u64 { self.as_inner().modified() }
|
||||
fn file_size(&self) -> u64 { self.as_inner().size() }
|
||||
}
|
||||
|
||||
/// Creates a new file symbolic link on the filesystem.
|
||||
///
|
||||
/// The `dst` path will be a file symbolic link pointing to the `src`
|
||||
/// path.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// use std::os::windows::fs;
|
||||
///
|
||||
/// # fn foo() -> std::io::Result<()> {
|
||||
/// try!(fs::symlink_file("a.txt", "b.txt"));
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q)
|
||||
-> io::Result<()> {
|
||||
sys::fs2::symlink_inner(src.as_ref(), dst.as_ref(), false)
|
||||
}
|
||||
|
||||
/// Creates a new directory symlink on the filesystem.
|
||||
///
|
||||
/// The `dst` path will be a directory symbolic link pointing to the `src`
|
||||
/// path.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// use std::os::windows::fs;
|
||||
///
|
||||
/// # fn foo() -> std::io::Result<()> {
|
||||
/// try!(fs::symlink_file("a", "b"));
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q)
|
||||
-> io::Result<()> {
|
||||
sys::fs2::symlink_inner(src.as_ref(), dst.as_ref(), true)
|
||||
}
|
131
src/libstd/sys/windows/ext/io.rs
Normal file
131
src/libstd/sys/windows/ext/io.rs
Normal file
@ -0,0 +1,131 @@
|
||||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use fs;
|
||||
use os::windows::raw;
|
||||
use net;
|
||||
use sys_common::{net2, AsInner, FromInner};
|
||||
use sys;
|
||||
|
||||
/// Raw HANDLEs.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub type RawHandle = raw::HANDLE;
|
||||
|
||||
/// Raw SOCKETs.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub type RawSocket = raw::SOCKET;
|
||||
|
||||
/// Extract raw handles.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait AsRawHandle {
|
||||
/// Extracts the raw handle, without taking any ownership.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn as_raw_handle(&self) -> RawHandle;
|
||||
}
|
||||
|
||||
/// Construct I/O objects from raw handles.
|
||||
#[unstable(feature = "from_raw_os",
|
||||
reason = "recent addition to the std::os::windows::io module")]
|
||||
pub trait FromRawHandle {
|
||||
/// Constructs a new I/O object from the specified raw handle.
|
||||
///
|
||||
/// This function will **consume ownership** of the handle given,
|
||||
/// passing responsibility for closing the handle to the returned
|
||||
/// object.
|
||||
///
|
||||
/// This function is also unsafe as the primitives currently returned
|
||||
/// have the contract that they are the sole owner of the file
|
||||
/// descriptor they are wrapping. Usage of this function could
|
||||
/// accidentally allow violating this contract which can cause memory
|
||||
/// unsafety in code that relies on it being true.
|
||||
unsafe fn from_raw_handle(handle: RawHandle) -> Self;
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl AsRawHandle for fs::File {
|
||||
fn as_raw_handle(&self) -> RawHandle {
|
||||
self.as_inner().handle().raw() as RawHandle
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "from_raw_os", reason = "trait is unstable")]
|
||||
impl FromRawHandle for fs::File {
|
||||
unsafe fn from_raw_handle(handle: RawHandle) -> fs::File {
|
||||
let handle = handle as ::libc::HANDLE;
|
||||
fs::File::from_inner(sys::fs2::File::from_inner(handle))
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract raw sockets.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait AsRawSocket {
|
||||
/// Extracts the underlying raw socket from this object.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn as_raw_socket(&self) -> RawSocket;
|
||||
}
|
||||
|
||||
/// Create I/O objects from raw sockets.
|
||||
#[unstable(feature = "from_raw_os", reason = "recent addition to module")]
|
||||
pub trait FromRawSocket {
|
||||
/// Creates a new I/O object from the given raw socket.
|
||||
///
|
||||
/// This function will **consume ownership** of the socket provided and
|
||||
/// it will be closed when the returned object goes out of scope.
|
||||
///
|
||||
/// This function is also unsafe as the primitives currently returned
|
||||
/// have the contract that they are the sole owner of the file
|
||||
/// descriptor they are wrapping. Usage of this function could
|
||||
/// accidentally allow violating this contract which can cause memory
|
||||
/// unsafety in code that relies on it being true.
|
||||
unsafe fn from_raw_socket(sock: RawSocket) -> Self;
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl AsRawSocket for net::TcpStream {
|
||||
fn as_raw_socket(&self) -> RawSocket {
|
||||
*self.as_inner().socket().as_inner()
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl AsRawSocket for net::TcpListener {
|
||||
fn as_raw_socket(&self) -> RawSocket {
|
||||
*self.as_inner().socket().as_inner()
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl AsRawSocket for net::UdpSocket {
|
||||
fn as_raw_socket(&self) -> RawSocket {
|
||||
*self.as_inner().socket().as_inner()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "from_raw_os", reason = "trait is unstable")]
|
||||
impl FromRawSocket for net::TcpStream {
|
||||
unsafe fn from_raw_socket(sock: RawSocket) -> net::TcpStream {
|
||||
let sock = sys::net::Socket::from_inner(sock);
|
||||
net::TcpStream::from_inner(net2::TcpStream::from_inner(sock))
|
||||
}
|
||||
}
|
||||
#[unstable(feature = "from_raw_os", reason = "trait is unstable")]
|
||||
impl FromRawSocket for net::TcpListener {
|
||||
unsafe fn from_raw_socket(sock: RawSocket) -> net::TcpListener {
|
||||
let sock = sys::net::Socket::from_inner(sock);
|
||||
net::TcpListener::from_inner(net2::TcpListener::from_inner(sock))
|
||||
}
|
||||
}
|
||||
#[unstable(feature = "from_raw_os", reason = "trait is unstable")]
|
||||
impl FromRawSocket for net::UdpSocket {
|
||||
unsafe fn from_raw_socket(sock: RawSocket) -> net::UdpSocket {
|
||||
let sock = sys::net::Socket::from_inner(sock);
|
||||
net::UdpSocket::from_inner(net2::UdpSocket::from_inner(sock))
|
||||
}
|
||||
}
|
35
src/libstd/sys/windows/ext/mod.rs
Normal file
35
src/libstd/sys/windows/ext/mod.rs
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright 2014 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Experimental extensions to `std` for Windows.
|
||||
//!
|
||||
//! For now, this module is limited to extracting handles, file
|
||||
//! descriptors, and sockets, but its functionality will grow over
|
||||
//! time.
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
pub mod ffi;
|
||||
pub mod fs;
|
||||
pub mod io;
|
||||
pub mod raw;
|
||||
|
||||
/// A prelude for conveniently writing platform-specific code.
|
||||
///
|
||||
/// Includes all extension traits, and some important type definitions.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub mod prelude {
|
||||
#[doc(no_inline)]
|
||||
pub use super::io::{RawSocket, RawHandle, AsRawSocket, AsRawHandle};
|
||||
#[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use super::ffi::{OsStrExt, OsStringExt};
|
||||
#[doc(no_inline)]
|
||||
pub use super::fs::{OpenOptionsExt, MetadataExt};
|
||||
}
|
21
src/libstd/sys/windows/ext/raw.rs
Normal file
21
src/libstd/sys/windows/ext/raw.rs
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2014 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Windows-specific primitives
|
||||
|
||||
#![unstable(feature = "raw_ext", reason = "recently added API")]
|
||||
|
||||
use os::raw;
|
||||
|
||||
pub type HANDLE = *mut raw::c_void;
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
pub type SOCKET = u32;
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub type SOCKET = u64;
|
@ -27,7 +27,16 @@ use sys_common::FromInner;
|
||||
use vec::Vec;
|
||||
|
||||
pub struct File { handle: Handle }
|
||||
pub struct FileAttr { data: c::WIN32_FILE_ATTRIBUTE_DATA }
|
||||
|
||||
pub struct FileAttr {
|
||||
data: c::WIN32_FILE_ATTRIBUTE_DATA,
|
||||
is_symlink: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum FileType {
|
||||
Dir, File, Symlink, ReparsePoint
|
||||
}
|
||||
|
||||
pub struct ReadDir {
|
||||
handle: FindNextFileHandle,
|
||||
@ -111,8 +120,31 @@ impl DirEntry {
|
||||
}
|
||||
|
||||
pub fn path(&self) -> PathBuf {
|
||||
self.root.join(&self.file_name())
|
||||
}
|
||||
|
||||
pub fn file_name(&self) -> OsString {
|
||||
let filename = super::truncate_utf16_at_nul(&self.data.cFileName);
|
||||
self.root.join(&<OsString as OsStringExt>::from_wide(filename))
|
||||
OsString::from_wide(filename)
|
||||
}
|
||||
|
||||
pub fn file_type(&self) -> io::Result<FileType> {
|
||||
Ok(FileType::new(self.data.dwFileAttributes,
|
||||
self.data.dwReserved0 == c::IO_REPARSE_TAG_SYMLINK))
|
||||
}
|
||||
|
||||
pub fn metadata(&self) -> io::Result<FileAttr> {
|
||||
Ok(FileAttr {
|
||||
data: c::WIN32_FILE_ATTRIBUTE_DATA {
|
||||
dwFileAttributes: self.data.dwFileAttributes,
|
||||
ftCreationTime: self.data.ftCreationTime,
|
||||
ftLastAccessTime: self.data.ftLastAccessTime,
|
||||
ftLastWriteTime: self.data.ftLastWriteTime,
|
||||
nFileSizeHigh: self.data.nFileSizeHigh,
|
||||
nFileSizeLow: self.data.nFileSizeLow,
|
||||
},
|
||||
is_symlink: self.data.dwReserved0 == c::IO_REPARSE_TAG_SYMLINK,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -180,6 +212,13 @@ impl OpenOptions {
|
||||
}
|
||||
|
||||
impl File {
|
||||
fn open_reparse_point(path: &Path) -> io::Result<File> {
|
||||
let mut opts = OpenOptions::new();
|
||||
opts.read(true);
|
||||
opts.flags_and_attributes(c::FILE_FLAG_OPEN_REPARSE_POINT as i32);
|
||||
File::open(path, &opts)
|
||||
}
|
||||
|
||||
pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
|
||||
let path = to_utf16(path);
|
||||
let handle = unsafe {
|
||||
@ -224,7 +263,7 @@ impl File {
|
||||
let mut info: c::BY_HANDLE_FILE_INFORMATION = mem::zeroed();
|
||||
try!(cvt(c::GetFileInformationByHandle(self.handle.raw(),
|
||||
&mut info)));
|
||||
Ok(FileAttr {
|
||||
let mut attr = FileAttr {
|
||||
data: c::WIN32_FILE_ATTRIBUTE_DATA {
|
||||
dwFileAttributes: info.dwFileAttributes,
|
||||
ftCreationTime: info.ftCreationTime,
|
||||
@ -232,8 +271,13 @@ impl File {
|
||||
ftLastWriteTime: info.ftLastWriteTime,
|
||||
nFileSizeHigh: info.nFileSizeHigh,
|
||||
nFileSizeLow: info.nFileSizeLow,
|
||||
}
|
||||
})
|
||||
},
|
||||
is_symlink: false,
|
||||
};
|
||||
if attr.is_reparse_point() {
|
||||
attr.is_symlink = self.is_symlink();
|
||||
}
|
||||
Ok(attr)
|
||||
}
|
||||
}
|
||||
|
||||
@ -263,6 +307,41 @@ impl File {
|
||||
}
|
||||
|
||||
pub fn handle(&self) -> &Handle { &self.handle }
|
||||
|
||||
fn is_symlink(&self) -> bool {
|
||||
self.readlink().is_ok()
|
||||
}
|
||||
|
||||
fn readlink(&self) -> io::Result<PathBuf> {
|
||||
let mut space = [0u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
|
||||
let mut bytes = 0;
|
||||
|
||||
unsafe {
|
||||
try!(cvt({
|
||||
c::DeviceIoControl(self.handle.raw(),
|
||||
c::FSCTL_GET_REPARSE_POINT,
|
||||
0 as *mut _,
|
||||
0,
|
||||
space.as_mut_ptr() as *mut _,
|
||||
space.len() as libc::DWORD,
|
||||
&mut bytes,
|
||||
0 as *mut _)
|
||||
}));
|
||||
let buf: *const c::REPARSE_DATA_BUFFER = space.as_ptr() as *const _;
|
||||
if (*buf).ReparseTag != c::IO_REPARSE_TAG_SYMLINK {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "not a symlink"))
|
||||
}
|
||||
let info: *const c::SYMBOLIC_LINK_REPARSE_BUFFER =
|
||||
&(*buf).rest as *const _ as *const _;
|
||||
let path_buffer = &(*info).PathBuffer as *const _ as *const u16;
|
||||
let subst_off = (*info).SubstituteNameOffset / 2;
|
||||
let subst_ptr = path_buffer.offset(subst_off as isize);
|
||||
let subst_len = (*info).SubstituteNameLength / 2;
|
||||
let subst = slice::from_raw_parts(subst_ptr, subst_len as usize);
|
||||
|
||||
Ok(PathBuf::from(OsString::from_wide(subst)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<libc::HANDLE> for File {
|
||||
@ -285,27 +364,30 @@ pub fn to_utf16(s: &Path) -> Vec<u16> {
|
||||
}
|
||||
|
||||
impl FileAttr {
|
||||
pub fn is_dir(&self) -> bool {
|
||||
self.data.dwFileAttributes & c::FILE_ATTRIBUTE_DIRECTORY != 0
|
||||
}
|
||||
pub fn is_file(&self) -> bool {
|
||||
!self.is_dir()
|
||||
}
|
||||
pub fn size(&self) -> u64 {
|
||||
((self.data.nFileSizeHigh as u64) << 32) | (self.data.nFileSizeLow as u64)
|
||||
}
|
||||
|
||||
pub fn perm(&self) -> FilePermissions {
|
||||
FilePermissions { attrs: self.data.dwFileAttributes }
|
||||
}
|
||||
|
||||
pub fn accessed(&self) -> u64 { self.to_ms(&self.data.ftLastAccessTime) }
|
||||
pub fn modified(&self) -> u64 { self.to_ms(&self.data.ftLastWriteTime) }
|
||||
pub fn attrs(&self) -> u32 { self.data.dwFileAttributes as u32 }
|
||||
|
||||
fn to_ms(&self, ft: &libc::FILETIME) -> u64 {
|
||||
// FILETIME is in 100ns intervals and there are 10000 intervals in a
|
||||
// millisecond.
|
||||
let bits = (ft.dwLowDateTime as u64) | ((ft.dwHighDateTime as u64) << 32);
|
||||
bits / 10000
|
||||
pub fn file_type(&self) -> FileType {
|
||||
FileType::new(self.data.dwFileAttributes, self.is_symlink)
|
||||
}
|
||||
|
||||
pub fn created(&self) -> u64 { self.to_u64(&self.data.ftCreationTime) }
|
||||
pub fn accessed(&self) -> u64 { self.to_u64(&self.data.ftLastAccessTime) }
|
||||
pub fn modified(&self) -> u64 { self.to_u64(&self.data.ftLastWriteTime) }
|
||||
|
||||
fn to_u64(&self, ft: &libc::FILETIME) -> u64 {
|
||||
(ft.dwLowDateTime as u64) | ((ft.dwHighDateTime as u64) << 32)
|
||||
}
|
||||
|
||||
fn is_reparse_point(&self) -> bool {
|
||||
self.data.dwFileAttributes & libc::FILE_ATTRIBUTE_REPARSE_POINT != 0
|
||||
}
|
||||
}
|
||||
|
||||
@ -323,6 +405,26 @@ impl FilePermissions {
|
||||
}
|
||||
}
|
||||
|
||||
impl FileType {
|
||||
fn new(attrs: libc::DWORD, is_symlink: bool) -> FileType {
|
||||
if attrs & libc::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
|
||||
if is_symlink {
|
||||
FileType::Symlink
|
||||
} else {
|
||||
FileType::ReparsePoint
|
||||
}
|
||||
} else if attrs & c::FILE_ATTRIBUTE_DIRECTORY != 0 {
|
||||
FileType::Dir
|
||||
} else {
|
||||
FileType::File
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_dir(&self) -> bool { *self == FileType::Dir }
|
||||
pub fn is_file(&self) -> bool { *self == FileType::File }
|
||||
pub fn is_symlink(&self) -> bool { *self == FileType::Symlink }
|
||||
}
|
||||
|
||||
pub fn mkdir(p: &Path) -> io::Result<()> {
|
||||
let p = to_utf16(p);
|
||||
try!(cvt(unsafe {
|
||||
@ -374,40 +476,8 @@ pub fn rmdir(p: &Path) -> io::Result<()> {
|
||||
}
|
||||
|
||||
pub fn readlink(p: &Path) -> io::Result<PathBuf> {
|
||||
let mut opts = OpenOptions::new();
|
||||
opts.read(true);
|
||||
opts.flags_and_attributes(c::FILE_FLAG_OPEN_REPARSE_POINT as i32);
|
||||
let file = try!(File::open(p, &opts));
|
||||
|
||||
let mut space = [0u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
|
||||
let mut bytes = 0;
|
||||
|
||||
unsafe {
|
||||
try!(cvt({
|
||||
c::DeviceIoControl(file.handle.raw(),
|
||||
c::FSCTL_GET_REPARSE_POINT,
|
||||
0 as *mut _,
|
||||
0,
|
||||
space.as_mut_ptr() as *mut _,
|
||||
space.len() as libc::DWORD,
|
||||
&mut bytes,
|
||||
0 as *mut _)
|
||||
}));
|
||||
let buf: *const c::REPARSE_DATA_BUFFER = space.as_ptr() as *const _;
|
||||
if (*buf).ReparseTag != c::IO_REPARSE_TAG_SYMLINK {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "not a symlink"))
|
||||
}
|
||||
let info: *const c::SYMBOLIC_LINK_REPARSE_BUFFER =
|
||||
&(*buf).rest as *const _ as *const _;
|
||||
let path_buffer = &(*info).PathBuffer as *const _ as *const u16;
|
||||
let subst_off = (*info).SubstituteNameOffset / 2;
|
||||
let subst_ptr = path_buffer.offset(subst_off as isize);
|
||||
let subst_len = (*info).SubstituteNameLength / 2;
|
||||
let subst = slice::from_raw_parts(subst_ptr, subst_len as usize);
|
||||
|
||||
Ok(PathBuf::from(OsString::from_wide(subst)))
|
||||
}
|
||||
|
||||
let file = try!(File::open_reparse_point(p));
|
||||
file.readlink()
|
||||
}
|
||||
|
||||
pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
|
||||
@ -435,12 +505,28 @@ pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
|
||||
}
|
||||
|
||||
pub fn stat(p: &Path) -> io::Result<FileAttr> {
|
||||
let p = to_utf16(p);
|
||||
let attr = try!(lstat(p));
|
||||
if attr.data.dwFileAttributes & libc::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
|
||||
let opts = OpenOptions::new();
|
||||
let file = try!(File::open(p, &opts));
|
||||
file.file_attr()
|
||||
} else {
|
||||
Ok(attr)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lstat(p: &Path) -> io::Result<FileAttr> {
|
||||
let utf16 = to_utf16(p);
|
||||
unsafe {
|
||||
let mut attr: FileAttr = mem::zeroed();
|
||||
try!(cvt(c::GetFileAttributesExW(p.as_ptr(),
|
||||
try!(cvt(c::GetFileAttributesExW(utf16.as_ptr(),
|
||||
c::GetFileExInfoStandard,
|
||||
&mut attr.data as *mut _ as *mut _)));
|
||||
if attr.is_reparse_point() {
|
||||
attr.is_symlink = File::open_reparse_point(p).map(|f| {
|
||||
f.is_symlink()
|
||||
}).unwrap_or(false);
|
||||
}
|
||||
Ok(attr)
|
||||
}
|
||||
}
|
||||
@ -465,3 +551,17 @@ pub fn utimes(p: &Path, atime: u64, mtime: u64) -> io::Result<()> {
|
||||
}));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
|
||||
use sys::c::compat::kernel32::GetFinalPathNameByHandleW;
|
||||
|
||||
let mut opts = OpenOptions::new();
|
||||
opts.read(true);
|
||||
let f = try!(File::open(p, &opts));
|
||||
super::fill_utf16_buf(|buf, sz| unsafe {
|
||||
GetFinalPathNameByHandleW(f.handle.raw(), buf, sz,
|
||||
libc::VOLUME_NAME_DOS)
|
||||
}, |buf| {
|
||||
PathBuf::from(OsString::from_wide(buf))
|
||||
})
|
||||
}
|
||||
|
@ -15,12 +15,13 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#if !defined(__WIN32__)
|
||||
#include <dirent.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#else
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
@ -41,44 +42,31 @@
|
||||
//include valgrind.h after stdint.h so that uintptr_t is defined for msys2 w64
|
||||
#include "valgrind/valgrind.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#if (TARGET_OS_IPHONE)
|
||||
extern char **environ;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__linux__) || defined(__ANDROID__) || \
|
||||
defined(__DragonFly__) || defined(__Bitrig__) || defined(__OpenBSD__)
|
||||
extern char **environ;
|
||||
#endif
|
||||
|
||||
#if defined(__WIN32__)
|
||||
char**
|
||||
rust_env_pairs() {
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
char**
|
||||
rust_env_pairs() {
|
||||
#if defined(__APPLE__) && !(TARGET_OS_IPHONE)
|
||||
char **environ = *_NSGetEnviron();
|
||||
#endif
|
||||
return environ;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
char*
|
||||
#if defined(__WIN32__)
|
||||
rust_list_dir_val(WIN32_FIND_DATA* entry_ptr) {
|
||||
return entry_ptr->cFileName;
|
||||
}
|
||||
#else
|
||||
rust_list_dir_val(struct dirent* entry_ptr) {
|
||||
return entry_ptr->d_name;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
int
|
||||
rust_dir_get_mode(struct dirent* entry_ptr) {
|
||||
#if defined(_DIRENT_HAVE_D_TYPE)
|
||||
switch (entry_ptr->d_type) {
|
||||
case DT_BLK: return S_IFBLK;
|
||||
case DT_CHR: return S_IFCHR;
|
||||
case DT_FIFO: return S_IFIFO;
|
||||
case DT_LNK: return S_IFLNK;
|
||||
case DT_REG: return S_IFREG;
|
||||
case DT_SOCK: return S_IFSOCK;
|
||||
}
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
ino_t
|
||||
rust_dir_get_ino(struct dirent* entry_ptr) {
|
||||
return entry_ptr->d_ino;
|
||||
}
|
||||
|
||||
DIR*
|
||||
rust_opendir(char *dirname) {
|
||||
@ -94,21 +82,6 @@ int
|
||||
rust_dirent_t_size() {
|
||||
return sizeof(struct dirent);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void
|
||||
rust_opendir() {
|
||||
}
|
||||
|
||||
void
|
||||
rust_readdir() {
|
||||
}
|
||||
|
||||
void
|
||||
rust_dirent_t_size() {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
uintptr_t
|
||||
@ -173,26 +146,6 @@ rust_valgrind_stack_deregister(unsigned int id) {
|
||||
VALGRIND_STACK_DEREGISTER(id);
|
||||
}
|
||||
|
||||
#if defined(__WIN32__)
|
||||
|
||||
void
|
||||
rust_unset_sigprocmask() {
|
||||
// empty stub for windows to keep linker happy
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void
|
||||
rust_unset_sigprocmask() {
|
||||
// this can't be safely converted to rust code because the
|
||||
// representation of sigset_t is platform-dependent
|
||||
sigset_t sset;
|
||||
sigemptyset(&sset);
|
||||
sigprocmask(SIG_SETMASK, &sset, NULL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__DragonFly__)
|
||||
#include <errno.h>
|
||||
// In DragonFly __error() is an inline function and as such
|
||||
|
Loading…
Reference in New Issue
Block a user