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:
Alex Crichton 2015-04-15 23:21:13 -07:00
parent b772ce6342
commit 9348700007
47 changed files with 2405 additions and 915 deletions

View File

@ -40,6 +40,7 @@
#![feature(path_ext)] #![feature(path_ext)]
#![feature(str_char)] #![feature(str_char)]
#![feature(into_cow)] #![feature(into_cow)]
#![feature(fs_canonicalize)]
#![feature(slice_patterns)] #![feature(slice_patterns)]
#![cfg_attr(test, feature(test))] #![cfg_attr(test, feature(test))]
@ -139,7 +140,6 @@ pub mod plugin;
pub mod lint; pub mod lint;
pub mod util { pub mod util {
pub use rustc_back::fs;
pub use rustc_back::sha2; pub use rustc_back::sha2;
pub mod common; pub mod common;

View File

@ -21,8 +21,10 @@ use metadata::decoder;
use metadata::loader; use metadata::loader;
use metadata::loader::CratePaths; use metadata::loader::CratePaths;
use std::path::{Path, PathBuf}; use std::path::PathBuf;
use std::rc::Rc; use std::rc::Rc;
use std::fs;
use syntax::ast; use syntax::ast;
use syntax::abi; use syntax::abi;
use syntax::attr; use syntax::attr;
@ -32,7 +34,6 @@ use syntax::parse;
use syntax::parse::token::InternedString; use syntax::parse::token::InternedString;
use syntax::parse::token; use syntax::parse::token;
use syntax::visit; use syntax::visit;
use util::fs;
use log; use log;
pub struct CrateReader<'a> { pub struct CrateReader<'a> {
@ -322,7 +323,7 @@ impl<'a> CrateReader<'a> {
let source = self.sess.cstore.get_used_crate_source(cnum).unwrap(); let source = self.sess.cstore.get_used_crate_source(cnum).unwrap();
if let Some(locs) = self.sess.opts.externs.get(name) { if let Some(locs) = self.sess.opts.externs.get(name) {
let found = locs.iter().any(|l| { 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.dylib.as_ref().map(|p| &p.0) == l.as_ref() ||
source.rlib.as_ref().map(|p| &p.0) == l.as_ref() source.rlib.as_ref().map(|p| &p.0) == l.as_ref()
}); });

View File

@ -18,7 +18,6 @@ use std::fs;
use std::io::prelude::*; use std::io::prelude::*;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use util::fs as myfs;
use session::search_paths::{SearchPaths, PathKind}; use session::search_paths::{SearchPaths, PathKind};
#[derive(Copy, Clone)] #[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. // Follow symlinks. If the resolved path is relative, make it absolute.
fn canonicalize(path: Option<PathBuf>) -> Option<PathBuf> { fn canonicalize(path: Option<PathBuf>) -> Option<PathBuf> {
path.and_then(|path| { path.and_then(|path| {
match myfs::realpath(&path) { match fs::canonicalize(&path) {
Ok(canon) => Some(canon), Ok(canon) => Some(canon),
Err(e) => panic!("failed to get realpath: {}", e), Err(e) => panic!("failed to get realpath: {}", e),
} }

View File

@ -225,12 +225,12 @@ use metadata::encoder;
use metadata::filesearch::{FileSearch, FileMatches, FileDoesntMatch}; use metadata::filesearch::{FileSearch, FileMatches, FileDoesntMatch};
use syntax::codemap::Span; use syntax::codemap::Span;
use syntax::diagnostic::SpanHandler; use syntax::diagnostic::SpanHandler;
use util::fs;
use util::common; use util::common;
use rustc_back::target::Target; use rustc_back::target::Target;
use std::cmp; use std::cmp;
use std::collections::HashMap; use std::collections::HashMap;
use std::fs;
use std::io::prelude::*; use std::io::prelude::*;
use std::io; use std::io;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
@ -430,9 +430,9 @@ impl<'a> Context<'a> {
.or_insert_with(|| (HashMap::new(), HashMap::new())); .or_insert_with(|| (HashMap::new(), HashMap::new()));
let (ref mut rlibs, ref mut dylibs) = *slot; let (ref mut rlibs, ref mut dylibs) = *slot;
if rlib { if rlib {
rlibs.insert(fs::realpath(path).unwrap(), kind); rlibs.insert(fs::canonicalize(path).unwrap(), kind);
} else { } else {
dylibs.insert(fs::realpath(path).unwrap(), kind); dylibs.insert(fs::canonicalize(path).unwrap(), kind);
} }
FileMatches FileMatches
@ -660,10 +660,10 @@ impl<'a> Context<'a> {
// there's at most one rlib and at most one dylib. // there's at most one rlib and at most one dylib.
for loc in locs { for loc in locs {
if loc.file_name().unwrap().to_str().unwrap().ends_with(".rlib") { 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); PathKind::ExternFlag);
} else { } else {
dylibs.insert(fs::realpath(&loc).unwrap(), dylibs.insert(fs::canonicalize(&loc).unwrap(),
PathKind::ExternFlag); PathKind::ExternFlag);
} }
} }

View File

@ -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);
}
}

View File

@ -41,6 +41,7 @@
#![feature(path_ext)] #![feature(path_ext)]
#![feature(step_by)] #![feature(step_by)]
#![feature(libc)] #![feature(libc)]
#![feature(fs_canonicalize)]
#![cfg_attr(test, feature(test, rand))] #![cfg_attr(test, feature(test, rand))]
extern crate syntax; extern crate syntax;
@ -53,7 +54,6 @@ pub mod abi;
pub mod archive; pub mod archive;
pub mod tempdir; pub mod tempdir;
pub mod arm; pub mod arm;
pub mod fs;
pub mod mips; pub mod mips;
pub mod mipsel; pub mod mipsel;
pub mod rpath; pub mod rpath;

View File

@ -10,8 +10,8 @@
use std::collections::HashSet; use std::collections::HashSet;
use std::env; use std::env;
use std::io;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::fs;
use syntax::ast; use syntax::ast;
pub struct RPathConfig<'a> { pub struct RPathConfig<'a> {
@ -20,7 +20,6 @@ pub struct RPathConfig<'a> {
pub is_like_osx: bool, pub is_like_osx: bool,
pub has_rpath: bool, pub has_rpath: bool,
pub get_install_prefix_lib_path: &'a mut FnMut() -> PathBuf, 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> { 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 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(); lib.pop();
let mut output = cwd.join(&config.out_filename); let mut output = cwd.join(&config.out_filename);
output.pop(); output.pop();
let output = (config.realpath)(&output).unwrap(); let output = fs::canonicalize(&output).unwrap_or(output);
let relative = path_relative_from(&lib, &output) let relative = path_relative_from(&lib, &output)
.expect(&format!("couldn't create relative path from {:?} to {:?}", output, lib)); .expect(&format!("couldn't create relative path from {:?} to {:?}", output, lib));
// FIXME (#9639): This needs to handle non-utf8 paths // FIXME (#9639): This needs to handle non-utf8 paths
@ -231,7 +230,6 @@ mod tests {
is_like_osx: true, is_like_osx: true,
out_filename: PathBuf::from("bin/rustc"), out_filename: PathBuf::from("bin/rustc"),
get_install_prefix_lib_path: &mut || panic!(), get_install_prefix_lib_path: &mut || panic!(),
realpath: &mut |p| Ok(p.to_path_buf()),
}; };
let res = get_rpath_relative_to_output(config, let res = get_rpath_relative_to_output(config,
Path::new("lib/libstd.so")); Path::new("lib/libstd.so"));
@ -243,7 +241,6 @@ mod tests {
get_install_prefix_lib_path: &mut || panic!(), get_install_prefix_lib_path: &mut || panic!(),
has_rpath: true, has_rpath: true,
is_like_osx: false, is_like_osx: false,
realpath: &mut |p| Ok(p.to_path_buf()),
}; };
let res = get_rpath_relative_to_output(config, let res = get_rpath_relative_to_output(config,
Path::new("lib/libstd.so")); Path::new("lib/libstd.so"));

View File

@ -32,7 +32,7 @@ use std::ffi::OsString;
use std::fs::{self, PathExt}; use std::fs::{self, PathExt};
use std::io::{self, Read, Write}; use std::io::{self, Read, Write};
use std::mem; use std::mem;
use std::path::{Path, PathBuf}; use std::path::{self, Path, PathBuf};
use std::process::Command; use std::process::Command;
use std::str; use std::str;
use flate; 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 // stripped away as much as it could. This has not been seen to impact
// link times negatively. // link times negatively.
// //
// -dead_strip can't be part of the pre_link_args because it's also used for partial // -dead_strip can't be part of the pre_link_args because it's also used
// linking when using multiple codegen units (-r). So we insert it here. // for partial linking when using multiple codegen units (-r). So we
// insert it here.
cmd.arg("-Wl,-dead_strip"); cmd.arg("-Wl,-dead_strip");
} }
@ -1043,7 +1044,6 @@ fn link_args(cmd: &mut Command,
has_rpath: sess.target.target.options.has_rpath, has_rpath: sess.target.target.options.has_rpath,
is_like_osx: sess.target.target.options.is_like_osx, is_like_osx: sess.target.target.options.is_like_osx,
get_install_prefix_lib_path: &mut get_install_prefix_lib_path, 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)); cmd.args(&rpath::get_rpath_flags(&mut rpath_config));
} }
@ -1258,7 +1258,7 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session,
} }
}); });
} else { } 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 // Just need to tell the linker about where the library lives and
// what its name is // what its name is
if let Some(dir) = cratepath.parent() { 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(); let filestem = cratepath.file_stem().unwrap().to_str().unwrap();
cmd.arg(&format!("-l{}", unlib(&sess.target, filestem))); 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)
}

View File

@ -20,6 +20,7 @@
use core::prelude::*; use core::prelude::*;
use fmt; use fmt;
use ffi::OsString;
use io::{self, Error, ErrorKind, SeekFrom, Seek, Read, Write}; use io::{self, Error, ErrorKind, SeekFrom, Seek, Read, Write};
use path::{Path, PathBuf}; use path::{Path, PathBuf};
use sys::fs2 as fs_imp; use sys::fs2 as fs_imp;
@ -146,6 +147,11 @@ pub struct OpenOptions(fs_imp::OpenOptions);
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct Permissions(fs_imp::FilePermissions); 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 { impl File {
/// Attempts to open a file in read-only mode. /// Attempts to open a file in read-only mode.
/// ///
@ -485,6 +491,12 @@ impl AsInnerMut<fs_imp::OpenOptions> for OpenOptions {
} }
impl Metadata { 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. /// Returns whether this metadata is for a directory.
/// ///
/// # Examples /// # Examples
@ -500,7 +512,7 @@ impl Metadata {
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[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. /// Returns whether this metadata is for a regular file.
/// ///
@ -517,7 +529,7 @@ impl Metadata {
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[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. /// 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 \ reason = "the return type of u64 is not quite appropriate for \
this method and may change if the standard library \ this method and may change if the standard library \
gains a type to represent a moment in time")] 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. /// 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 \ reason = "the return type of u64 is not quite appropriate for \
this method and may change if the standard library \ this method and may change if the standard library \
gains a type to represent a moment in time")] 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 { 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 { impl FromInner<fs_imp::FilePermissions> for Permissions {
fn from_inner(f: fs_imp::FilePermissions) -> Permissions { fn from_inner(f: fs_imp::FilePermissions) -> Permissions {
Permissions(f) Permissions(f)
@ -674,6 +716,47 @@ impl DirEntry {
/// The exact text, of course, depends on what files you have in `.`. /// The exact text, of course, depends on what files you have in `.`.
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn path(&self) -> PathBuf { self.0.path() } 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. /// 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) 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. /// Rename a file or directory to a new name.
/// ///
/// # Errors /// # Errors
@ -869,6 +971,13 @@ pub fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
fs_imp::readlink(path.as_ref()) 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 /// Creates a new, empty directory at the provided path
/// ///
/// # Errors /// # Errors
@ -966,19 +1075,14 @@ pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
let path = path.as_ref(); let path = path.as_ref();
for child in try!(read_dir(path)) { for child in try!(read_dir(path)) {
let child = try!(child).path(); let child = try!(child).path();
let stat = try!(lstat(&*child)); let stat = try!(symlink_metadata(&*child));
if stat.is_dir() { if stat.is_dir() {
try!(remove_dir_all(&*child)); try!(remove_dir_all(&*child));
} else { } else {
try!(remove_file(&*child)); try!(remove_file(&*child));
} }
} }
return remove_dir(path); 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) }
} }
/// Returns an iterator over the entries within a directory. /// Returns an iterator over the entries within a directory.
@ -1073,11 +1177,37 @@ impl Iterator for WalkDir {
pub trait PathExt { pub trait PathExt {
/// Gets information on the file, directory, etc at this path. /// 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>; 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 /// Boolean value indicator whether the underlying file exists on the local
/// filesystem. Returns false in exactly the cases where `fs::stat` fails. /// filesystem. Returns false in exactly the cases where `fs::stat` fails.
fn exists(&self) -> bool; fn exists(&self) -> bool;
@ -1098,12 +1228,16 @@ pub trait PathExt {
impl PathExt for Path { impl PathExt for Path {
fn metadata(&self) -> io::Result<Metadata> { metadata(self) } 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 exists(&self) -> bool { metadata(self).is_ok() }
fn is_file(&self) -> bool { fn is_file(&self) -> bool {
metadata(self).map(|s| s.is_file()).unwrap_or(false) metadata(self).map(|s| s.is_file()).unwrap_or(false)
} }
fn is_dir(&self) -> bool { fn is_dir(&self) -> bool {
metadata(self).map(|s| s.is_dir()).unwrap_or(false) metadata(self).map(|s| s.is_dir()).unwrap_or(false)
} }
@ -1924,4 +2058,74 @@ mod tests {
let path = tmpdir.join("file"); let path = tmpdir.join("file");
check!(fs::create_dir_all(&path.join("a/"))); 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),
}
}
}
} }

View File

@ -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 // file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT. // http://rust-lang.org/COPYRIGHT.
// //
@ -8,9 +8,12 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // 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; pub mod raw;
#[cfg(windows)] pub use sys::ext as windows;
pub mod fs {
pub use sys::fs2::MetadataExt;
}

View 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,
}

View 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;
}

View 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,
}

View 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;
}

View 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,
}

View 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;
}

View 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
View 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
View 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],
}

View 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
View 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],
}
}

View 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;
}

View 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
View 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
View 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
View 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],
}
}

View 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;
}

View 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
View 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;
}
}

View File

@ -161,6 +161,8 @@ extern {
pub fn gai_strerror(errcode: libc::c_int) -> *const libc::c_char; pub fn gai_strerror(errcode: libc::c_int) -> *const libc::c_char;
pub fn setgroups(ngroups: libc::c_int, pub fn setgroups(ngroups: libc::c_int,
ptr: *const libc::c_void) -> 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"))] #[cfg(any(target_os = "macos", target_os = "ios"))]

View File

@ -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};
}

View 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
}
}

View 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())
}

View 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))
}
}

View 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};
}

View 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
}
}
}

View 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};

View File

@ -21,14 +21,15 @@ use path::{Path, PathBuf};
use ptr; use ptr;
use sync::Arc; use sync::Arc;
use sys::fd::FileDesc; use sys::fd::FileDesc;
use sys::platform::raw;
use sys::{c, cvt, cvt_r}; use sys::{c, cvt, cvt_r};
use sys_common::FromInner; use sys_common::{AsInner, FromInner};
use vec::Vec; use vec::Vec;
pub struct File(FileDesc); pub struct File(FileDesc);
pub struct FileAttr { pub struct FileAttr {
stat: libc::stat, stat: raw::stat,
} }
pub struct ReadDir { pub struct ReadDir {
@ -57,13 +58,10 @@ pub struct OpenOptions {
#[derive(Clone, PartialEq, Eq, Debug)] #[derive(Clone, PartialEq, Eq, Debug)]
pub struct FilePermissions { mode: mode_t } pub struct FilePermissions { mode: mode_t }
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct FileType { mode: mode_t }
impl FileAttr { 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 size(&self) -> u64 { self.stat.st_size as u64 }
pub fn perm(&self) -> FilePermissions { pub fn perm(&self) -> FilePermissions {
FilePermissions { mode: (self.stat.st_mode as mode_t) & 0o777 } 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) 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) // times are in milliseconds (currently)
fn mktime(&self, secs: u64, nsecs: u64) -> u64 { fn mktime(&self, secs: u64, nsecs: u64) -> u64 {
secs * 1000 + nsecs / 1000000 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 { impl FilePermissions {
pub fn readonly(&self) -> bool { self.mode & 0o222 == 0 } pub fn readonly(&self) -> bool { self.mode & 0o222 == 0 }
pub fn set_readonly(&mut self, readonly: bool) { pub fn set_readonly(&mut self, readonly: bool) {
@ -91,11 +112,19 @@ impl FilePermissions {
self.mode |= 0o222; 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 { impl FileType {
fn from_inner(mode: i32) -> FilePermissions { 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 } FilePermissions { mode: mode as mode_t }
} }
} }
@ -147,6 +176,33 @@ impl DirEntry {
self.root.join(<OsStr as OsStrExt>::from_bytes(self.name_bytes())) 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] { fn name_bytes(&self) -> &[u8] {
extern { extern {
fn rust_list_dir_val(ptr: *mut libc::dirent_t) -> *const c_char; 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); 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; self.mode = mode as mode_t;
} }
@ -228,8 +284,10 @@ impl File {
pub fn into_fd(self) -> FileDesc { self.0 } pub fn into_fd(self) -> FileDesc { self.0 }
pub fn file_attr(&self) -> io::Result<FileAttr> { pub fn file_attr(&self) -> io::Result<FileAttr> {
let mut stat: libc::stat = unsafe { mem::zeroed() }; let mut stat: raw::stat = unsafe { mem::zeroed() };
try!(cvt(unsafe { libc::fstat(self.0.raw(), &mut stat) })); try!(cvt(unsafe {
libc::fstat(self.0.raw(), &mut stat as *mut _ as *mut _)
}));
Ok(FileAttr { stat: stat }) 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> { pub fn stat(p: &Path) -> io::Result<FileAttr> {
let p = try!(cstr(p)); let p = try!(cstr(p));
let mut stat: libc::stat = unsafe { mem::zeroed() }; let mut stat: raw::stat = unsafe { mem::zeroed() };
try!(cvt(unsafe { libc::stat(p.as_ptr(), &mut stat) })); try!(cvt(unsafe {
libc::stat(p.as_ptr(), &mut stat as *mut _ as *mut _)
}));
Ok(FileAttr { stat: stat }) Ok(FileAttr { stat: stat })
} }
pub fn lstat(p: &Path) -> io::Result<FileAttr> { pub fn lstat(p: &Path) -> io::Result<FileAttr> {
let p = try!(cstr(p)); let p = try!(cstr(p));
let mut stat: libc::stat = unsafe { mem::zeroed() }; let mut stat: raw::stat = unsafe { mem::zeroed() };
try!(cvt(unsafe { libc::lstat(p.as_ptr(), &mut stat) })); try!(cvt(unsafe {
libc::lstat(p.as_ptr(), &mut stat as *mut _ as *mut _)
}));
Ok(FileAttr { stat: stat }) 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()) })); try!(cvt(unsafe { c::utimes(p.as_ptr(), buf.as_ptr()) }));
Ok(()) 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)))
}

View File

@ -18,6 +18,16 @@ use libc;
use num::One; use num::One;
use ops::Neg; 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 backtrace;
pub mod c; pub mod c;
pub mod condvar; pub mod condvar;

View File

@ -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;
}

View 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()
}
}

View 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)
}

View 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))
}
}

View 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};
}

View 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;

View File

@ -27,7 +27,16 @@ use sys_common::FromInner;
use vec::Vec; use vec::Vec;
pub struct File { handle: Handle } 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 { pub struct ReadDir {
handle: FindNextFileHandle, handle: FindNextFileHandle,
@ -111,8 +120,31 @@ impl DirEntry {
} }
pub fn path(&self) -> PathBuf { 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); 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 { 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> { pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
let path = to_utf16(path); let path = to_utf16(path);
let handle = unsafe { let handle = unsafe {
@ -224,7 +263,7 @@ impl File {
let mut info: c::BY_HANDLE_FILE_INFORMATION = mem::zeroed(); let mut info: c::BY_HANDLE_FILE_INFORMATION = mem::zeroed();
try!(cvt(c::GetFileInformationByHandle(self.handle.raw(), try!(cvt(c::GetFileInformationByHandle(self.handle.raw(),
&mut info))); &mut info)));
Ok(FileAttr { let mut attr = FileAttr {
data: c::WIN32_FILE_ATTRIBUTE_DATA { data: c::WIN32_FILE_ATTRIBUTE_DATA {
dwFileAttributes: info.dwFileAttributes, dwFileAttributes: info.dwFileAttributes,
ftCreationTime: info.ftCreationTime, ftCreationTime: info.ftCreationTime,
@ -232,8 +271,13 @@ impl File {
ftLastWriteTime: info.ftLastWriteTime, ftLastWriteTime: info.ftLastWriteTime,
nFileSizeHigh: info.nFileSizeHigh, nFileSizeHigh: info.nFileSizeHigh,
nFileSizeLow: info.nFileSizeLow, 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 } 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 { impl FromInner<libc::HANDLE> for File {
@ -285,27 +364,30 @@ pub fn to_utf16(s: &Path) -> Vec<u16> {
} }
impl FileAttr { 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 { pub fn size(&self) -> u64 {
((self.data.nFileSizeHigh as u64) << 32) | (self.data.nFileSizeLow as u64) ((self.data.nFileSizeHigh as u64) << 32) | (self.data.nFileSizeLow as u64)
} }
pub fn perm(&self) -> FilePermissions { pub fn perm(&self) -> FilePermissions {
FilePermissions { attrs: self.data.dwFileAttributes } FilePermissions { attrs: self.data.dwFileAttributes }
} }
pub fn accessed(&self) -> u64 { self.to_ms(&self.data.ftLastAccessTime) } pub fn attrs(&self) -> u32 { self.data.dwFileAttributes as u32 }
pub fn modified(&self) -> u64 { self.to_ms(&self.data.ftLastWriteTime) }
fn to_ms(&self, ft: &libc::FILETIME) -> u64 { pub fn file_type(&self) -> FileType {
// FILETIME is in 100ns intervals and there are 10000 intervals in a FileType::new(self.data.dwFileAttributes, self.is_symlink)
// millisecond. }
let bits = (ft.dwLowDateTime as u64) | ((ft.dwHighDateTime as u64) << 32);
bits / 10000 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<()> { pub fn mkdir(p: &Path) -> io::Result<()> {
let p = to_utf16(p); let p = to_utf16(p);
try!(cvt(unsafe { try!(cvt(unsafe {
@ -374,40 +476,8 @@ pub fn rmdir(p: &Path) -> io::Result<()> {
} }
pub fn readlink(p: &Path) -> io::Result<PathBuf> { pub fn readlink(p: &Path) -> io::Result<PathBuf> {
let mut opts = OpenOptions::new(); let file = try!(File::open_reparse_point(p));
opts.read(true); file.readlink()
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)))
}
} }
pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> { 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> { 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 { unsafe {
let mut attr: FileAttr = mem::zeroed(); let mut attr: FileAttr = mem::zeroed();
try!(cvt(c::GetFileAttributesExW(p.as_ptr(), try!(cvt(c::GetFileAttributesExW(utf16.as_ptr(),
c::GetFileExInfoStandard, c::GetFileExInfoStandard,
&mut attr.data as *mut _ as *mut _))); &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) Ok(attr)
} }
} }
@ -465,3 +551,17 @@ pub fn utimes(p: &Path, atime: u64, mtime: u64) -> io::Result<()> {
})); }));
Ok(()) 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))
})
}

View File

@ -15,12 +15,13 @@
#include <stdlib.h> #include <stdlib.h>
#if !defined(__WIN32__) #if !defined(__WIN32__)
#include <dirent.h>
#include <pthread.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/types.h> #include <sys/types.h>
#include <dirent.h>
#include <signal.h>
#include <unistd.h> #include <unistd.h>
#include <pthread.h>
#else #else
#include <windows.h> #include <windows.h>
#include <wincrypt.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.h after stdint.h so that uintptr_t is defined for msys2 w64
#include "valgrind/valgrind.h" #include "valgrind/valgrind.h"
#ifdef __APPLE__ #ifndef _WIN32
#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
char* 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) { rust_list_dir_val(struct dirent* entry_ptr) {
return entry_ptr->d_name; 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* DIR*
rust_opendir(char *dirname) { rust_opendir(char *dirname) {
@ -94,21 +82,6 @@ int
rust_dirent_t_size() { rust_dirent_t_size() {
return sizeof(struct dirent); return sizeof(struct dirent);
} }
#else
void
rust_opendir() {
}
void
rust_readdir() {
}
void
rust_dirent_t_size() {
}
#endif #endif
uintptr_t uintptr_t
@ -173,26 +146,6 @@ rust_valgrind_stack_deregister(unsigned int id) {
VALGRIND_STACK_DEREGISTER(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__) #if defined(__DragonFly__)
#include <errno.h> #include <errno.h>
// In DragonFly __error() is an inline function and as such // In DragonFly __error() is an inline function and as such