2015-02-03 05:39:14 +00:00
|
|
|
// Copyright 2013-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.
|
|
|
|
|
2016-02-03 13:45:34 +00:00
|
|
|
use prelude::v1::*;
|
2015-02-03 05:39:14 +00:00
|
|
|
use os::unix::prelude::*;
|
|
|
|
|
2015-03-30 18:00:05 +00:00
|
|
|
use ffi::{CString, CStr, OsString, OsStr};
|
2015-04-19 09:27:19 +00:00
|
|
|
use fmt;
|
2015-07-10 08:54:00 +00:00
|
|
|
use io::{self, Error, ErrorKind, SeekFrom};
|
2016-02-15 00:24:02 +00:00
|
|
|
use libc::{self, c_int, mode_t};
|
2015-02-03 05:39:14 +00:00
|
|
|
use mem;
|
|
|
|
use path::{Path, PathBuf};
|
|
|
|
use ptr;
|
2015-02-20 17:46:56 +00:00
|
|
|
use sync::Arc;
|
2015-02-03 05:39:14 +00:00
|
|
|
use sys::fd::FileDesc;
|
2016-01-13 01:24:16 +00:00
|
|
|
use sys::time::SystemTime;
|
2015-11-03 00:23:22 +00:00
|
|
|
use sys::{cvt, cvt_r};
|
2015-04-16 06:21:13 +00:00
|
|
|
use sys_common::{AsInner, FromInner};
|
2015-02-03 05:39:14 +00:00
|
|
|
|
2016-03-01 10:48:03 +00:00
|
|
|
#[cfg(any(target_os = "linux", target_os = "emscripten"))]
|
2016-02-15 00:27:18 +00:00
|
|
|
use libc::{stat64, fstat64, lstat64, off64_t, ftruncate64, lseek64, dirent64, readdir64_r, open64};
|
2016-02-21 09:04:14 +00:00
|
|
|
#[cfg(target_os = "android")]
|
|
|
|
use libc::{stat as stat64, fstat as fstat64, lstat as lstat64, off64_t, ftruncate64, lseek64,
|
|
|
|
dirent as dirent64, open as open64};
|
2016-03-01 10:48:03 +00:00
|
|
|
#[cfg(not(any(target_os = "linux",
|
|
|
|
target_os = "emscripten",
|
|
|
|
target_os = "android")))]
|
2016-02-15 00:09:57 +00:00
|
|
|
use libc::{stat as stat64, fstat as fstat64, lstat as lstat64, off_t as off64_t,
|
2016-02-15 00:27:18 +00:00
|
|
|
ftruncate as ftruncate64, lseek as lseek64, dirent as dirent64, open as open64};
|
2016-03-01 10:48:03 +00:00
|
|
|
#[cfg(not(any(target_os = "linux",
|
|
|
|
target_os = "emscripten",
|
|
|
|
target_os = "solaris")))]
|
2016-02-15 00:24:02 +00:00
|
|
|
use libc::{readdir_r as readdir64_r};
|
std: Deprecate all std::os::*::raw types
This commit is an implementation of [RFC 1415][rfc] which deprecates all types
in the `std::os::*::raw` modules.
[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1415-trim-std-os.md
Many of the types in these modules don't actually have a canonical platform
representation, for example the definition of `stat` on 32-bit Linux will change
depending on whether C code is compiled with LFS support or not. Unfortunately
the current types in `std::os::*::raw` are billed as "compatible with C", which
in light of this means it isn't really possible.
To make matters worse, platforms like Android sometimes define these types as
*smaller* than the way they're actually represented in the `stat` structure
itself. This means that when methods like `DirEntry::ino` are called on Android
the result may be truncated as we're tied to returning a `ino_t` type, not the
underlying type.
The commit here incorporates two backwards-compatible components:
* Deprecate all `raw` types that aren't in `std::os::raw`
* Expand the `std::os::*::fs::MetadataExt` trait on all platforms for method
accessors of all fields. The fields now returned widened types which are the
same across platforms (consistency across platforms is not required, however,
it's just convenient).
and two also backwards-incompatible components:
* Change the definition of all `std::os::*::raw` type aliases to
correspond to the newly widened types that are being returned on each
platform.
* Change the definition of `std::os::*::raw::stat` on Linux to match the LFS
definitions rather than the standard ones.
The breaking changes here will specifically break code that assumes that `libc`
and `std` agree on the definition of `std::os::*::raw` types, or that the `std`
types are faithful representations of the types in C. An [audit] has been
performed of crates.io to determine the fallout which was determined two be
minimal, with the two found cases of breakage having been fixed now.
[audit]: https://github.com/rust-lang/rfcs/pull/1415#issuecomment-180645582
---
Ok, so after all that, we're finally able to support LFS on Linux! This commit
then simultaneously starts using `stat64` and friends on Linux to ensure that we
can open >4GB files on 32-bit Linux. Yay!
Closes #28978
Closes #30050
Closes #31549
2016-02-05 01:16:47 +00:00
|
|
|
|
2015-02-03 05:39:14 +00:00
|
|
|
pub struct File(FileDesc);
|
|
|
|
|
2015-10-13 12:06:00 +00:00
|
|
|
#[derive(Clone)]
|
2015-02-03 05:39:14 +00:00
|
|
|
pub struct FileAttr {
|
std: Deprecate all std::os::*::raw types
This commit is an implementation of [RFC 1415][rfc] which deprecates all types
in the `std::os::*::raw` modules.
[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1415-trim-std-os.md
Many of the types in these modules don't actually have a canonical platform
representation, for example the definition of `stat` on 32-bit Linux will change
depending on whether C code is compiled with LFS support or not. Unfortunately
the current types in `std::os::*::raw` are billed as "compatible with C", which
in light of this means it isn't really possible.
To make matters worse, platforms like Android sometimes define these types as
*smaller* than the way they're actually represented in the `stat` structure
itself. This means that when methods like `DirEntry::ino` are called on Android
the result may be truncated as we're tied to returning a `ino_t` type, not the
underlying type.
The commit here incorporates two backwards-compatible components:
* Deprecate all `raw` types that aren't in `std::os::raw`
* Expand the `std::os::*::fs::MetadataExt` trait on all platforms for method
accessors of all fields. The fields now returned widened types which are the
same across platforms (consistency across platforms is not required, however,
it's just convenient).
and two also backwards-incompatible components:
* Change the definition of all `std::os::*::raw` type aliases to
correspond to the newly widened types that are being returned on each
platform.
* Change the definition of `std::os::*::raw::stat` on Linux to match the LFS
definitions rather than the standard ones.
The breaking changes here will specifically break code that assumes that `libc`
and `std` agree on the definition of `std::os::*::raw` types, or that the `std`
types are faithful representations of the types in C. An [audit] has been
performed of crates.io to determine the fallout which was determined two be
minimal, with the two found cases of breakage having been fixed now.
[audit]: https://github.com/rust-lang/rfcs/pull/1415#issuecomment-180645582
---
Ok, so after all that, we're finally able to support LFS on Linux! This commit
then simultaneously starts using `stat64` and friends on Linux to ensure that we
can open >4GB files on 32-bit Linux. Yay!
Closes #28978
Closes #30050
Closes #31549
2016-02-05 01:16:47 +00:00
|
|
|
stat: stat64,
|
2015-02-03 05:39:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub struct ReadDir {
|
2015-02-20 17:46:56 +00:00
|
|
|
dirp: Dir,
|
|
|
|
root: Arc<PathBuf>,
|
2015-02-03 05:39:14 +00:00
|
|
|
}
|
|
|
|
|
2015-02-20 17:46:56 +00:00
|
|
|
struct Dir(*mut libc::DIR);
|
|
|
|
|
|
|
|
unsafe impl Send for Dir {}
|
|
|
|
unsafe impl Sync for Dir {}
|
|
|
|
|
2015-02-03 05:39:14 +00:00
|
|
|
pub struct DirEntry {
|
2016-02-15 00:24:02 +00:00
|
|
|
entry: dirent64,
|
2015-02-20 17:46:56 +00:00
|
|
|
root: Arc<PathBuf>,
|
2016-01-21 16:30:22 +00:00
|
|
|
// We need to store an owned copy of the directory name
|
|
|
|
// on Solaris because a) it uses a zero-length array to
|
|
|
|
// store the name, b) its lifetime between readdir calls
|
|
|
|
// is not guaranteed.
|
2016-01-28 11:02:31 +00:00
|
|
|
#[cfg(target_os = "solaris")]
|
2016-01-27 02:46:28 +00:00
|
|
|
name: Box<[u8]>
|
2015-02-03 05:39:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct OpenOptions {
|
2016-01-13 17:08:08 +00:00
|
|
|
// generic
|
2015-02-03 05:39:14 +00:00
|
|
|
read: bool,
|
|
|
|
write: bool,
|
2016-01-13 17:08:08 +00:00
|
|
|
append: bool,
|
|
|
|
truncate: bool,
|
|
|
|
create: bool,
|
|
|
|
create_new: bool,
|
|
|
|
// system-specific
|
2016-01-13 20:47:46 +00:00
|
|
|
custom_flags: i32,
|
2015-02-03 05:39:14 +00:00
|
|
|
mode: mode_t,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
|
|
|
pub struct FilePermissions { mode: mode_t }
|
|
|
|
|
2015-04-16 06:21:13 +00:00
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
|
|
|
pub struct FileType { mode: mode_t }
|
|
|
|
|
2015-04-28 00:29:35 +00:00
|
|
|
pub struct DirBuilder { mode: mode_t }
|
|
|
|
|
2015-02-03 05:39:14 +00:00
|
|
|
impl FileAttr {
|
|
|
|
pub fn size(&self) -> u64 { self.stat.st_size as u64 }
|
|
|
|
pub fn perm(&self) -> FilePermissions {
|
|
|
|
FilePermissions { mode: (self.stat.st_mode as mode_t) & 0o777 }
|
|
|
|
}
|
|
|
|
|
2015-04-16 06:21:13 +00:00
|
|
|
pub fn file_type(&self) -> FileType {
|
|
|
|
FileType { mode: self.stat.st_mode as mode_t }
|
|
|
|
}
|
2015-02-03 05:39:14 +00:00
|
|
|
}
|
|
|
|
|
2016-01-13 01:24:16 +00:00
|
|
|
#[cfg(any(target_os = "ios", target_os = "macos"))]
|
|
|
|
// FIXME: update SystemTime to store a timespec and don't lose precision
|
|
|
|
impl FileAttr {
|
|
|
|
pub fn modified(&self) -> io::Result<SystemTime> {
|
|
|
|
Ok(SystemTime::from(libc::timeval {
|
|
|
|
tv_sec: self.stat.st_mtime,
|
|
|
|
tv_usec: (self.stat.st_mtime_nsec / 1000) as libc::suseconds_t,
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn accessed(&self) -> io::Result<SystemTime> {
|
|
|
|
Ok(SystemTime::from(libc::timeval {
|
|
|
|
tv_sec: self.stat.st_atime,
|
|
|
|
tv_usec: (self.stat.st_atime_nsec / 1000) as libc::suseconds_t,
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn created(&self) -> io::Result<SystemTime> {
|
|
|
|
Ok(SystemTime::from(libc::timeval {
|
|
|
|
tv_sec: self.stat.st_birthtime,
|
|
|
|
tv_usec: (self.stat.st_birthtime_nsec / 1000) as libc::suseconds_t,
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-21 15:31:56 +00:00
|
|
|
#[cfg(target_os = "netbsd")]
|
|
|
|
impl FileAttr {
|
|
|
|
pub fn modified(&self) -> io::Result<SystemTime> {
|
|
|
|
Ok(SystemTime::from(libc::timespec {
|
|
|
|
tv_sec: self.stat.st_mtime as libc::time_t,
|
|
|
|
tv_nsec: self.stat.st_mtimensec as libc::c_long,
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn accessed(&self) -> io::Result<SystemTime> {
|
|
|
|
Ok(SystemTime::from(libc::timespec {
|
|
|
|
tv_sec: self.stat.st_atime as libc::time_t,
|
|
|
|
tv_nsec: self.stat.st_atimensec as libc::c_long,
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn created(&self) -> io::Result<SystemTime> {
|
|
|
|
Ok(SystemTime::from(libc::timespec {
|
|
|
|
tv_sec: self.stat.st_birthtime as libc::time_t,
|
|
|
|
tv_nsec: self.stat.st_birthtimensec as libc::c_long,
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "netbsd")))]
|
2016-01-13 01:24:16 +00:00
|
|
|
impl FileAttr {
|
|
|
|
pub fn modified(&self) -> io::Result<SystemTime> {
|
|
|
|
Ok(SystemTime::from(libc::timespec {
|
std: Deprecate all std::os::*::raw types
This commit is an implementation of [RFC 1415][rfc] which deprecates all types
in the `std::os::*::raw` modules.
[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1415-trim-std-os.md
Many of the types in these modules don't actually have a canonical platform
representation, for example the definition of `stat` on 32-bit Linux will change
depending on whether C code is compiled with LFS support or not. Unfortunately
the current types in `std::os::*::raw` are billed as "compatible with C", which
in light of this means it isn't really possible.
To make matters worse, platforms like Android sometimes define these types as
*smaller* than the way they're actually represented in the `stat` structure
itself. This means that when methods like `DirEntry::ino` are called on Android
the result may be truncated as we're tied to returning a `ino_t` type, not the
underlying type.
The commit here incorporates two backwards-compatible components:
* Deprecate all `raw` types that aren't in `std::os::raw`
* Expand the `std::os::*::fs::MetadataExt` trait on all platforms for method
accessors of all fields. The fields now returned widened types which are the
same across platforms (consistency across platforms is not required, however,
it's just convenient).
and two also backwards-incompatible components:
* Change the definition of all `std::os::*::raw` type aliases to
correspond to the newly widened types that are being returned on each
platform.
* Change the definition of `std::os::*::raw::stat` on Linux to match the LFS
definitions rather than the standard ones.
The breaking changes here will specifically break code that assumes that `libc`
and `std` agree on the definition of `std::os::*::raw` types, or that the `std`
types are faithful representations of the types in C. An [audit] has been
performed of crates.io to determine the fallout which was determined two be
minimal, with the two found cases of breakage having been fixed now.
[audit]: https://github.com/rust-lang/rfcs/pull/1415#issuecomment-180645582
---
Ok, so after all that, we're finally able to support LFS on Linux! This commit
then simultaneously starts using `stat64` and friends on Linux to ensure that we
can open >4GB files on 32-bit Linux. Yay!
Closes #28978
Closes #30050
Closes #31549
2016-02-05 01:16:47 +00:00
|
|
|
tv_sec: self.stat.st_mtime as libc::time_t,
|
2016-01-13 01:24:16 +00:00
|
|
|
tv_nsec: self.stat.st_mtime_nsec as libc::c_long,
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn accessed(&self) -> io::Result<SystemTime> {
|
|
|
|
Ok(SystemTime::from(libc::timespec {
|
std: Deprecate all std::os::*::raw types
This commit is an implementation of [RFC 1415][rfc] which deprecates all types
in the `std::os::*::raw` modules.
[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1415-trim-std-os.md
Many of the types in these modules don't actually have a canonical platform
representation, for example the definition of `stat` on 32-bit Linux will change
depending on whether C code is compiled with LFS support or not. Unfortunately
the current types in `std::os::*::raw` are billed as "compatible with C", which
in light of this means it isn't really possible.
To make matters worse, platforms like Android sometimes define these types as
*smaller* than the way they're actually represented in the `stat` structure
itself. This means that when methods like `DirEntry::ino` are called on Android
the result may be truncated as we're tied to returning a `ino_t` type, not the
underlying type.
The commit here incorporates two backwards-compatible components:
* Deprecate all `raw` types that aren't in `std::os::raw`
* Expand the `std::os::*::fs::MetadataExt` trait on all platforms for method
accessors of all fields. The fields now returned widened types which are the
same across platforms (consistency across platforms is not required, however,
it's just convenient).
and two also backwards-incompatible components:
* Change the definition of all `std::os::*::raw` type aliases to
correspond to the newly widened types that are being returned on each
platform.
* Change the definition of `std::os::*::raw::stat` on Linux to match the LFS
definitions rather than the standard ones.
The breaking changes here will specifically break code that assumes that `libc`
and `std` agree on the definition of `std::os::*::raw` types, or that the `std`
types are faithful representations of the types in C. An [audit] has been
performed of crates.io to determine the fallout which was determined two be
minimal, with the two found cases of breakage having been fixed now.
[audit]: https://github.com/rust-lang/rfcs/pull/1415#issuecomment-180645582
---
Ok, so after all that, we're finally able to support LFS on Linux! This commit
then simultaneously starts using `stat64` and friends on Linux to ensure that we
can open >4GB files on 32-bit Linux. Yay!
Closes #28978
Closes #30050
Closes #31549
2016-02-05 01:16:47 +00:00
|
|
|
tv_sec: self.stat.st_atime as libc::time_t,
|
2016-01-13 01:24:16 +00:00
|
|
|
tv_nsec: self.stat.st_atime_nsec as libc::c_long,
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(any(target_os = "bitrig",
|
|
|
|
target_os = "freebsd",
|
|
|
|
target_os = "openbsd"))]
|
|
|
|
pub fn created(&self) -> io::Result<SystemTime> {
|
|
|
|
Ok(SystemTime::from(libc::timespec {
|
std: Deprecate all std::os::*::raw types
This commit is an implementation of [RFC 1415][rfc] which deprecates all types
in the `std::os::*::raw` modules.
[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1415-trim-std-os.md
Many of the types in these modules don't actually have a canonical platform
representation, for example the definition of `stat` on 32-bit Linux will change
depending on whether C code is compiled with LFS support or not. Unfortunately
the current types in `std::os::*::raw` are billed as "compatible with C", which
in light of this means it isn't really possible.
To make matters worse, platforms like Android sometimes define these types as
*smaller* than the way they're actually represented in the `stat` structure
itself. This means that when methods like `DirEntry::ino` are called on Android
the result may be truncated as we're tied to returning a `ino_t` type, not the
underlying type.
The commit here incorporates two backwards-compatible components:
* Deprecate all `raw` types that aren't in `std::os::raw`
* Expand the `std::os::*::fs::MetadataExt` trait on all platforms for method
accessors of all fields. The fields now returned widened types which are the
same across platforms (consistency across platforms is not required, however,
it's just convenient).
and two also backwards-incompatible components:
* Change the definition of all `std::os::*::raw` type aliases to
correspond to the newly widened types that are being returned on each
platform.
* Change the definition of `std::os::*::raw::stat` on Linux to match the LFS
definitions rather than the standard ones.
The breaking changes here will specifically break code that assumes that `libc`
and `std` agree on the definition of `std::os::*::raw` types, or that the `std`
types are faithful representations of the types in C. An [audit] has been
performed of crates.io to determine the fallout which was determined two be
minimal, with the two found cases of breakage having been fixed now.
[audit]: https://github.com/rust-lang/rfcs/pull/1415#issuecomment-180645582
---
Ok, so after all that, we're finally able to support LFS on Linux! This commit
then simultaneously starts using `stat64` and friends on Linux to ensure that we
can open >4GB files on 32-bit Linux. Yay!
Closes #28978
Closes #30050
Closes #31549
2016-02-05 01:16:47 +00:00
|
|
|
tv_sec: self.stat.st_birthtime as libc::time_t,
|
2016-01-13 01:24:16 +00:00
|
|
|
tv_nsec: self.stat.st_birthtime_nsec as libc::c_long,
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(any(target_os = "bitrig",
|
|
|
|
target_os = "freebsd",
|
|
|
|
target_os = "openbsd")))]
|
|
|
|
pub fn created(&self) -> io::Result<SystemTime> {
|
|
|
|
Err(io::Error::new(io::ErrorKind::Other,
|
|
|
|
"creation time is not available on this platform \
|
|
|
|
currently"))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
std: Deprecate all std::os::*::raw types
This commit is an implementation of [RFC 1415][rfc] which deprecates all types
in the `std::os::*::raw` modules.
[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1415-trim-std-os.md
Many of the types in these modules don't actually have a canonical platform
representation, for example the definition of `stat` on 32-bit Linux will change
depending on whether C code is compiled with LFS support or not. Unfortunately
the current types in `std::os::*::raw` are billed as "compatible with C", which
in light of this means it isn't really possible.
To make matters worse, platforms like Android sometimes define these types as
*smaller* than the way they're actually represented in the `stat` structure
itself. This means that when methods like `DirEntry::ino` are called on Android
the result may be truncated as we're tied to returning a `ino_t` type, not the
underlying type.
The commit here incorporates two backwards-compatible components:
* Deprecate all `raw` types that aren't in `std::os::raw`
* Expand the `std::os::*::fs::MetadataExt` trait on all platforms for method
accessors of all fields. The fields now returned widened types which are the
same across platforms (consistency across platforms is not required, however,
it's just convenient).
and two also backwards-incompatible components:
* Change the definition of all `std::os::*::raw` type aliases to
correspond to the newly widened types that are being returned on each
platform.
* Change the definition of `std::os::*::raw::stat` on Linux to match the LFS
definitions rather than the standard ones.
The breaking changes here will specifically break code that assumes that `libc`
and `std` agree on the definition of `std::os::*::raw` types, or that the `std`
types are faithful representations of the types in C. An [audit] has been
performed of crates.io to determine the fallout which was determined two be
minimal, with the two found cases of breakage having been fixed now.
[audit]: https://github.com/rust-lang/rfcs/pull/1415#issuecomment-180645582
---
Ok, so after all that, we're finally able to support LFS on Linux! This commit
then simultaneously starts using `stat64` and friends on Linux to ensure that we
can open >4GB files on 32-bit Linux. Yay!
Closes #28978
Closes #30050
Closes #31549
2016-02-05 01:16:47 +00:00
|
|
|
impl AsInner<stat64> for FileAttr {
|
|
|
|
fn as_inner(&self) -> &stat64 { &self.stat }
|
2015-04-16 06:21:13 +00:00
|
|
|
}
|
|
|
|
|
2015-02-03 05:39:14 +00:00
|
|
|
impl FilePermissions {
|
|
|
|
pub fn readonly(&self) -> bool { self.mode & 0o222 == 0 }
|
|
|
|
pub fn set_readonly(&mut self, readonly: bool) {
|
|
|
|
if readonly {
|
|
|
|
self.mode &= !0o222;
|
|
|
|
} else {
|
|
|
|
self.mode |= 0o222;
|
|
|
|
}
|
|
|
|
}
|
std: Deprecate all std::os::*::raw types
This commit is an implementation of [RFC 1415][rfc] which deprecates all types
in the `std::os::*::raw` modules.
[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1415-trim-std-os.md
Many of the types in these modules don't actually have a canonical platform
representation, for example the definition of `stat` on 32-bit Linux will change
depending on whether C code is compiled with LFS support or not. Unfortunately
the current types in `std::os::*::raw` are billed as "compatible with C", which
in light of this means it isn't really possible.
To make matters worse, platforms like Android sometimes define these types as
*smaller* than the way they're actually represented in the `stat` structure
itself. This means that when methods like `DirEntry::ino` are called on Android
the result may be truncated as we're tied to returning a `ino_t` type, not the
underlying type.
The commit here incorporates two backwards-compatible components:
* Deprecate all `raw` types that aren't in `std::os::raw`
* Expand the `std::os::*::fs::MetadataExt` trait on all platforms for method
accessors of all fields. The fields now returned widened types which are the
same across platforms (consistency across platforms is not required, however,
it's just convenient).
and two also backwards-incompatible components:
* Change the definition of all `std::os::*::raw` type aliases to
correspond to the newly widened types that are being returned on each
platform.
* Change the definition of `std::os::*::raw::stat` on Linux to match the LFS
definitions rather than the standard ones.
The breaking changes here will specifically break code that assumes that `libc`
and `std` agree on the definition of `std::os::*::raw` types, or that the `std`
types are faithful representations of the types in C. An [audit] has been
performed of crates.io to determine the fallout which was determined two be
minimal, with the two found cases of breakage having been fixed now.
[audit]: https://github.com/rust-lang/rfcs/pull/1415#issuecomment-180645582
---
Ok, so after all that, we're finally able to support LFS on Linux! This commit
then simultaneously starts using `stat64` and friends on Linux to ensure that we
can open >4GB files on 32-bit Linux. Yay!
Closes #28978
Closes #30050
Closes #31549
2016-02-05 01:16:47 +00:00
|
|
|
pub fn mode(&self) -> u32 { self.mode as u32 }
|
2015-04-16 06:21:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl FileType {
|
|
|
|
pub fn is_dir(&self) -> bool { self.is(libc::S_IFDIR) }
|
|
|
|
pub fn is_file(&self) -> bool { self.is(libc::S_IFREG) }
|
|
|
|
pub fn is_symlink(&self) -> bool { self.is(libc::S_IFLNK) }
|
|
|
|
|
2015-07-05 21:16:25 +00:00
|
|
|
pub fn is(&self, mode: mode_t) -> bool { self.mode & libc::S_IFMT == mode }
|
2015-02-03 05:39:14 +00:00
|
|
|
}
|
|
|
|
|
std: Deprecate all std::os::*::raw types
This commit is an implementation of [RFC 1415][rfc] which deprecates all types
in the `std::os::*::raw` modules.
[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1415-trim-std-os.md
Many of the types in these modules don't actually have a canonical platform
representation, for example the definition of `stat` on 32-bit Linux will change
depending on whether C code is compiled with LFS support or not. Unfortunately
the current types in `std::os::*::raw` are billed as "compatible with C", which
in light of this means it isn't really possible.
To make matters worse, platforms like Android sometimes define these types as
*smaller* than the way they're actually represented in the `stat` structure
itself. This means that when methods like `DirEntry::ino` are called on Android
the result may be truncated as we're tied to returning a `ino_t` type, not the
underlying type.
The commit here incorporates two backwards-compatible components:
* Deprecate all `raw` types that aren't in `std::os::raw`
* Expand the `std::os::*::fs::MetadataExt` trait on all platforms for method
accessors of all fields. The fields now returned widened types which are the
same across platforms (consistency across platforms is not required, however,
it's just convenient).
and two also backwards-incompatible components:
* Change the definition of all `std::os::*::raw` type aliases to
correspond to the newly widened types that are being returned on each
platform.
* Change the definition of `std::os::*::raw::stat` on Linux to match the LFS
definitions rather than the standard ones.
The breaking changes here will specifically break code that assumes that `libc`
and `std` agree on the definition of `std::os::*::raw` types, or that the `std`
types are faithful representations of the types in C. An [audit] has been
performed of crates.io to determine the fallout which was determined two be
minimal, with the two found cases of breakage having been fixed now.
[audit]: https://github.com/rust-lang/rfcs/pull/1415#issuecomment-180645582
---
Ok, so after all that, we're finally able to support LFS on Linux! This commit
then simultaneously starts using `stat64` and friends on Linux to ensure that we
can open >4GB files on 32-bit Linux. Yay!
Closes #28978
Closes #30050
Closes #31549
2016-02-05 01:16:47 +00:00
|
|
|
impl FromInner<u32> for FilePermissions {
|
|
|
|
fn from_inner(mode: u32) -> FilePermissions {
|
2015-02-03 05:39:14 +00:00
|
|
|
FilePermissions { mode: mode as mode_t }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Iterator for ReadDir {
|
|
|
|
type Item = io::Result<DirEntry>;
|
|
|
|
|
2016-01-28 11:02:31 +00:00
|
|
|
#[cfg(target_os = "solaris")]
|
2016-01-21 16:30:22 +00:00
|
|
|
fn next(&mut self) -> Option<io::Result<DirEntry>> {
|
|
|
|
unsafe {
|
|
|
|
loop {
|
2016-01-27 02:46:28 +00:00
|
|
|
// Although readdir_r(3) would be a correct function to use here because
|
|
|
|
// of the thread safety, on Illumos the readdir(3C) function is safe to use
|
|
|
|
// in threaded applications and it is generally preferred over the
|
|
|
|
// readdir_r(3C) function.
|
2016-01-21 16:30:22 +00:00
|
|
|
let entry_ptr = libc::readdir(self.dirp.0);
|
|
|
|
if entry_ptr.is_null() {
|
|
|
|
return None
|
|
|
|
}
|
|
|
|
|
|
|
|
let name = (*entry_ptr).d_name.as_ptr();
|
|
|
|
let namelen = libc::strlen(name) as usize;
|
|
|
|
|
|
|
|
let ret = DirEntry {
|
|
|
|
entry: *entry_ptr,
|
2016-01-27 02:46:28 +00:00
|
|
|
name: ::slice::from_raw_parts(name as *const u8,
|
|
|
|
namelen as usize).to_owned().into_boxed_slice(),
|
2016-01-21 16:30:22 +00:00
|
|
|
root: self.root.clone()
|
|
|
|
};
|
|
|
|
if ret.name_bytes() != b"." && ret.name_bytes() != b".." {
|
|
|
|
return Some(Ok(ret))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-28 11:02:31 +00:00
|
|
|
#[cfg(not(target_os = "solaris"))]
|
2015-02-03 05:39:14 +00:00
|
|
|
fn next(&mut self) -> Option<io::Result<DirEntry>> {
|
2015-12-02 18:31:29 +00:00
|
|
|
unsafe {
|
|
|
|
let mut ret = DirEntry {
|
|
|
|
entry: mem::zeroed(),
|
2015-02-03 05:39:14 +00:00
|
|
|
root: self.root.clone()
|
|
|
|
};
|
2015-12-02 18:31:29 +00:00
|
|
|
let mut entry_ptr = ptr::null_mut();
|
|
|
|
loop {
|
2016-02-15 00:24:02 +00:00
|
|
|
if readdir64_r(self.dirp.0, &mut ret.entry, &mut entry_ptr) != 0 {
|
2015-12-02 18:31:29 +00:00
|
|
|
return Some(Err(Error::last_os_error()))
|
|
|
|
}
|
|
|
|
if entry_ptr.is_null() {
|
|
|
|
return None
|
|
|
|
}
|
|
|
|
if ret.name_bytes() != b"." && ret.name_bytes() != b".." {
|
|
|
|
return Some(Ok(ret))
|
|
|
|
}
|
2015-02-03 05:39:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-20 17:46:56 +00:00
|
|
|
impl Drop for Dir {
|
2015-02-03 05:39:14 +00:00
|
|
|
fn drop(&mut self) {
|
2015-02-20 17:46:56 +00:00
|
|
|
let r = unsafe { libc::closedir(self.0) };
|
2015-02-03 05:39:14 +00:00
|
|
|
debug_assert_eq!(r, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl DirEntry {
|
|
|
|
pub fn path(&self) -> PathBuf {
|
2015-12-02 18:31:29 +00:00
|
|
|
self.root.join(OsStr::from_bytes(self.name_bytes()))
|
2015-02-03 05:39:14 +00:00
|
|
|
}
|
|
|
|
|
2015-04-16 06:21:13 +00:00
|
|
|
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())
|
|
|
|
}
|
|
|
|
|
2016-01-28 11:02:31 +00:00
|
|
|
#[cfg(target_os = "solaris")]
|
2016-01-21 16:30:22 +00:00
|
|
|
pub fn file_type(&self) -> io::Result<FileType> {
|
|
|
|
stat(&self.path()).map(|m| m.file_type())
|
|
|
|
}
|
|
|
|
|
2016-01-28 11:02:31 +00:00
|
|
|
#[cfg(not(target_os = "solaris"))]
|
2015-04-16 06:21:13 +00:00
|
|
|
pub fn file_type(&self) -> io::Result<FileType> {
|
2015-12-02 18:31:29 +00:00
|
|
|
match self.entry.d_type {
|
|
|
|
libc::DT_CHR => Ok(FileType { mode: libc::S_IFCHR }),
|
|
|
|
libc::DT_FIFO => Ok(FileType { mode: libc::S_IFIFO }),
|
|
|
|
libc::DT_LNK => Ok(FileType { mode: libc::S_IFLNK }),
|
|
|
|
libc::DT_REG => Ok(FileType { mode: libc::S_IFREG }),
|
|
|
|
libc::DT_SOCK => Ok(FileType { mode: libc::S_IFSOCK }),
|
|
|
|
libc::DT_DIR => Ok(FileType { mode: libc::S_IFDIR }),
|
|
|
|
libc::DT_BLK => Ok(FileType { mode: libc::S_IFBLK }),
|
|
|
|
_ => lstat(&self.path()).map(|m| m.file_type()),
|
2015-04-16 06:21:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-02 18:31:29 +00:00
|
|
|
#[cfg(any(target_os = "macos",
|
|
|
|
target_os = "ios",
|
2016-01-21 16:30:22 +00:00
|
|
|
target_os = "linux",
|
std: Deprecate all std::os::*::raw types
This commit is an implementation of [RFC 1415][rfc] which deprecates all types
in the `std::os::*::raw` modules.
[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1415-trim-std-os.md
Many of the types in these modules don't actually have a canonical platform
representation, for example the definition of `stat` on 32-bit Linux will change
depending on whether C code is compiled with LFS support or not. Unfortunately
the current types in `std::os::*::raw` are billed as "compatible with C", which
in light of this means it isn't really possible.
To make matters worse, platforms like Android sometimes define these types as
*smaller* than the way they're actually represented in the `stat` structure
itself. This means that when methods like `DirEntry::ino` are called on Android
the result may be truncated as we're tied to returning a `ino_t` type, not the
underlying type.
The commit here incorporates two backwards-compatible components:
* Deprecate all `raw` types that aren't in `std::os::raw`
* Expand the `std::os::*::fs::MetadataExt` trait on all platforms for method
accessors of all fields. The fields now returned widened types which are the
same across platforms (consistency across platforms is not required, however,
it's just convenient).
and two also backwards-incompatible components:
* Change the definition of all `std::os::*::raw` type aliases to
correspond to the newly widened types that are being returned on each
platform.
* Change the definition of `std::os::*::raw::stat` on Linux to match the LFS
definitions rather than the standard ones.
The breaking changes here will specifically break code that assumes that `libc`
and `std` agree on the definition of `std::os::*::raw` types, or that the `std`
types are faithful representations of the types in C. An [audit] has been
performed of crates.io to determine the fallout which was determined two be
minimal, with the two found cases of breakage having been fixed now.
[audit]: https://github.com/rust-lang/rfcs/pull/1415#issuecomment-180645582
---
Ok, so after all that, we're finally able to support LFS on Linux! This commit
then simultaneously starts using `stat64` and friends on Linux to ensure that we
can open >4GB files on 32-bit Linux. Yay!
Closes #28978
Closes #30050
Closes #31549
2016-02-05 01:16:47 +00:00
|
|
|
target_os = "emscripten",
|
|
|
|
target_os = "android",
|
|
|
|
target_os = "solaris"))]
|
|
|
|
pub fn ino(&self) -> u64 {
|
|
|
|
self.entry.d_ino as u64
|
2015-12-02 18:31:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(any(target_os = "freebsd",
|
|
|
|
target_os = "openbsd",
|
|
|
|
target_os = "bitrig",
|
|
|
|
target_os = "netbsd",
|
|
|
|
target_os = "dragonfly"))]
|
std: Deprecate all std::os::*::raw types
This commit is an implementation of [RFC 1415][rfc] which deprecates all types
in the `std::os::*::raw` modules.
[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1415-trim-std-os.md
Many of the types in these modules don't actually have a canonical platform
representation, for example the definition of `stat` on 32-bit Linux will change
depending on whether C code is compiled with LFS support or not. Unfortunately
the current types in `std::os::*::raw` are billed as "compatible with C", which
in light of this means it isn't really possible.
To make matters worse, platforms like Android sometimes define these types as
*smaller* than the way they're actually represented in the `stat` structure
itself. This means that when methods like `DirEntry::ino` are called on Android
the result may be truncated as we're tied to returning a `ino_t` type, not the
underlying type.
The commit here incorporates two backwards-compatible components:
* Deprecate all `raw` types that aren't in `std::os::raw`
* Expand the `std::os::*::fs::MetadataExt` trait on all platforms for method
accessors of all fields. The fields now returned widened types which are the
same across platforms (consistency across platforms is not required, however,
it's just convenient).
and two also backwards-incompatible components:
* Change the definition of all `std::os::*::raw` type aliases to
correspond to the newly widened types that are being returned on each
platform.
* Change the definition of `std::os::*::raw::stat` on Linux to match the LFS
definitions rather than the standard ones.
The breaking changes here will specifically break code that assumes that `libc`
and `std` agree on the definition of `std::os::*::raw` types, or that the `std`
types are faithful representations of the types in C. An [audit] has been
performed of crates.io to determine the fallout which was determined two be
minimal, with the two found cases of breakage having been fixed now.
[audit]: https://github.com/rust-lang/rfcs/pull/1415#issuecomment-180645582
---
Ok, so after all that, we're finally able to support LFS on Linux! This commit
then simultaneously starts using `stat64` and friends on Linux to ensure that we
can open >4GB files on 32-bit Linux. Yay!
Closes #28978
Closes #30050
Closes #31549
2016-02-05 01:16:47 +00:00
|
|
|
pub fn ino(&self) -> u64 {
|
|
|
|
self.entry.d_fileno as u64
|
2015-04-16 06:21:13 +00:00
|
|
|
}
|
|
|
|
|
2015-12-02 18:31:29 +00:00
|
|
|
#[cfg(any(target_os = "macos",
|
|
|
|
target_os = "ios",
|
2015-12-23 17:56:42 +00:00
|
|
|
target_os = "netbsd",
|
2016-01-27 05:37:46 +00:00
|
|
|
target_os = "openbsd",
|
|
|
|
target_os = "freebsd",
|
2015-12-02 18:31:29 +00:00
|
|
|
target_os = "dragonfly",
|
2015-12-23 17:56:42 +00:00
|
|
|
target_os = "bitrig"))]
|
2015-12-02 18:31:29 +00:00
|
|
|
fn name_bytes(&self) -> &[u8] {
|
2015-02-03 05:39:14 +00:00
|
|
|
unsafe {
|
2015-12-02 18:31:29 +00:00
|
|
|
::slice::from_raw_parts(self.entry.d_name.as_ptr() as *const u8,
|
2016-01-27 01:37:18 +00:00
|
|
|
self.entry.d_namlen as usize)
|
2015-02-03 05:39:14 +00:00
|
|
|
}
|
|
|
|
}
|
2015-12-02 18:31:29 +00:00
|
|
|
#[cfg(any(target_os = "android",
|
2015-11-26 19:05:10 +00:00
|
|
|
target_os = "linux",
|
|
|
|
target_os = "emscripten"))]
|
2015-12-02 18:31:29 +00:00
|
|
|
fn name_bytes(&self) -> &[u8] {
|
|
|
|
unsafe {
|
|
|
|
CStr::from_ptr(self.entry.d_name.as_ptr()).to_bytes()
|
|
|
|
}
|
2015-02-20 17:46:56 +00:00
|
|
|
}
|
2016-01-28 11:02:31 +00:00
|
|
|
#[cfg(target_os = "solaris")]
|
2016-01-21 16:30:22 +00:00
|
|
|
fn name_bytes(&self) -> &[u8] {
|
|
|
|
&*self.name
|
|
|
|
}
|
2015-02-03 05:39:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl OpenOptions {
|
|
|
|
pub fn new() -> OpenOptions {
|
|
|
|
OpenOptions {
|
2016-01-13 17:08:08 +00:00
|
|
|
// generic
|
2015-02-03 05:39:14 +00:00
|
|
|
read: false,
|
|
|
|
write: false,
|
2016-01-13 17:08:08 +00:00
|
|
|
append: false,
|
|
|
|
truncate: false,
|
|
|
|
create: false,
|
|
|
|
create_new: false,
|
|
|
|
// system-specific
|
|
|
|
custom_flags: 0,
|
2015-02-11 22:40:09 +00:00
|
|
|
mode: 0o666,
|
2015-02-03 05:39:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-13 17:08:08 +00:00
|
|
|
pub fn read(&mut self, read: bool) { self.read = read; }
|
|
|
|
pub fn write(&mut self, write: bool) { self.write = write; }
|
|
|
|
pub fn append(&mut self, append: bool) { self.append = append; }
|
|
|
|
pub fn truncate(&mut self, truncate: bool) { self.truncate = truncate; }
|
|
|
|
pub fn create(&mut self, create: bool) { self.create = create; }
|
|
|
|
pub fn create_new(&mut self, create_new: bool) { self.create_new = create_new; }
|
|
|
|
|
2016-01-13 20:47:46 +00:00
|
|
|
pub fn custom_flags(&mut self, flags: i32) { self.custom_flags = flags; }
|
std: Deprecate all std::os::*::raw types
This commit is an implementation of [RFC 1415][rfc] which deprecates all types
in the `std::os::*::raw` modules.
[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1415-trim-std-os.md
Many of the types in these modules don't actually have a canonical platform
representation, for example the definition of `stat` on 32-bit Linux will change
depending on whether C code is compiled with LFS support or not. Unfortunately
the current types in `std::os::*::raw` are billed as "compatible with C", which
in light of this means it isn't really possible.
To make matters worse, platforms like Android sometimes define these types as
*smaller* than the way they're actually represented in the `stat` structure
itself. This means that when methods like `DirEntry::ino` are called on Android
the result may be truncated as we're tied to returning a `ino_t` type, not the
underlying type.
The commit here incorporates two backwards-compatible components:
* Deprecate all `raw` types that aren't in `std::os::raw`
* Expand the `std::os::*::fs::MetadataExt` trait on all platforms for method
accessors of all fields. The fields now returned widened types which are the
same across platforms (consistency across platforms is not required, however,
it's just convenient).
and two also backwards-incompatible components:
* Change the definition of all `std::os::*::raw` type aliases to
correspond to the newly widened types that are being returned on each
platform.
* Change the definition of `std::os::*::raw::stat` on Linux to match the LFS
definitions rather than the standard ones.
The breaking changes here will specifically break code that assumes that `libc`
and `std` agree on the definition of `std::os::*::raw` types, or that the `std`
types are faithful representations of the types in C. An [audit] has been
performed of crates.io to determine the fallout which was determined two be
minimal, with the two found cases of breakage having been fixed now.
[audit]: https://github.com/rust-lang/rfcs/pull/1415#issuecomment-180645582
---
Ok, so after all that, we're finally able to support LFS on Linux! This commit
then simultaneously starts using `stat64` and friends on Linux to ensure that we
can open >4GB files on 32-bit Linux. Yay!
Closes #28978
Closes #30050
Closes #31549
2016-02-05 01:16:47 +00:00
|
|
|
pub fn mode(&mut self, mode: u32) { self.mode = mode as mode_t; }
|
2016-01-13 17:08:08 +00:00
|
|
|
|
|
|
|
fn get_access_mode(&self) -> io::Result<c_int> {
|
|
|
|
match (self.read, self.write, self.append) {
|
|
|
|
(true, false, false) => Ok(libc::O_RDONLY),
|
|
|
|
(false, true, false) => Ok(libc::O_WRONLY),
|
|
|
|
(true, true, false) => Ok(libc::O_RDWR),
|
|
|
|
(false, _, true) => Ok(libc::O_WRONLY | libc::O_APPEND),
|
|
|
|
(true, _, true) => Ok(libc::O_RDWR | libc::O_APPEND),
|
|
|
|
(false, false, false) => Err(Error::from_raw_os_error(libc::EINVAL)),
|
|
|
|
}
|
2015-02-03 05:39:14 +00:00
|
|
|
}
|
|
|
|
|
2016-01-13 17:08:08 +00:00
|
|
|
fn get_creation_mode(&self) -> io::Result<c_int> {
|
|
|
|
match (self.write, self.append) {
|
2016-01-15 18:04:53 +00:00
|
|
|
(true, false) => {}
|
|
|
|
(false, false) =>
|
|
|
|
if self.truncate || self.create || self.create_new {
|
|
|
|
return Err(Error::from_raw_os_error(libc::EINVAL));
|
|
|
|
},
|
|
|
|
(_, true) =>
|
|
|
|
if self.truncate && !self.create_new {
|
|
|
|
return Err(Error::from_raw_os_error(libc::EINVAL));
|
|
|
|
},
|
2015-02-03 05:39:14 +00:00
|
|
|
}
|
2016-01-13 17:08:08 +00:00
|
|
|
|
|
|
|
Ok(match (self.create, self.truncate, self.create_new) {
|
|
|
|
(false, false, false) => 0,
|
|
|
|
(true, false, false) => libc::O_CREAT,
|
|
|
|
(false, true, false) => libc::O_TRUNC,
|
|
|
|
(true, true, false) => libc::O_CREAT | libc::O_TRUNC,
|
|
|
|
(_, _, true) => libc::O_CREAT | libc::O_EXCL,
|
|
|
|
})
|
2015-02-03 05:39:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl File {
|
|
|
|
pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
|
2016-03-23 03:01:37 +00:00
|
|
|
let path = cstr(path)?;
|
2015-04-03 22:34:15 +00:00
|
|
|
File::open_c(&path, opts)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn open_c(path: &CStr, opts: &OpenOptions) -> io::Result<File> {
|
2016-01-13 17:08:08 +00:00
|
|
|
let flags = libc::O_CLOEXEC |
|
2016-03-23 03:01:37 +00:00
|
|
|
opts.get_access_mode()? |
|
|
|
|
opts.get_creation_mode()? |
|
2016-01-13 17:08:08 +00:00
|
|
|
(opts.custom_flags as c_int & !libc::O_ACCMODE);
|
2016-03-23 03:01:37 +00:00
|
|
|
let fd = cvt_r(|| unsafe {
|
2016-02-15 00:27:18 +00:00
|
|
|
open64(path.as_ptr(), flags, opts.mode as c_int)
|
2016-03-23 03:01:37 +00:00
|
|
|
})?;
|
2015-04-03 22:30:10 +00:00
|
|
|
let fd = FileDesc::new(fd);
|
2016-02-04 19:59:31 +00:00
|
|
|
|
|
|
|
// Currently the standard library supports Linux 2.6.18 which did not
|
|
|
|
// have the O_CLOEXEC flag (passed above). If we're running on an older
|
|
|
|
// Linux kernel then the flag is just ignored by the OS, so we continue
|
|
|
|
// to explicitly ask for a CLOEXEC fd here.
|
|
|
|
//
|
|
|
|
// The CLOEXEC flag, however, is supported on versions of OSX/BSD/etc
|
|
|
|
// that we support, so we only do this on Linux currently.
|
|
|
|
if cfg!(target_os = "linux") {
|
|
|
|
fd.set_cloexec();
|
|
|
|
}
|
|
|
|
|
2015-04-03 22:30:10 +00:00
|
|
|
Ok(File(fd))
|
2015-02-03 05:39:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn file_attr(&self) -> io::Result<FileAttr> {
|
std: Deprecate all std::os::*::raw types
This commit is an implementation of [RFC 1415][rfc] which deprecates all types
in the `std::os::*::raw` modules.
[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1415-trim-std-os.md
Many of the types in these modules don't actually have a canonical platform
representation, for example the definition of `stat` on 32-bit Linux will change
depending on whether C code is compiled with LFS support or not. Unfortunately
the current types in `std::os::*::raw` are billed as "compatible with C", which
in light of this means it isn't really possible.
To make matters worse, platforms like Android sometimes define these types as
*smaller* than the way they're actually represented in the `stat` structure
itself. This means that when methods like `DirEntry::ino` are called on Android
the result may be truncated as we're tied to returning a `ino_t` type, not the
underlying type.
The commit here incorporates two backwards-compatible components:
* Deprecate all `raw` types that aren't in `std::os::raw`
* Expand the `std::os::*::fs::MetadataExt` trait on all platforms for method
accessors of all fields. The fields now returned widened types which are the
same across platforms (consistency across platforms is not required, however,
it's just convenient).
and two also backwards-incompatible components:
* Change the definition of all `std::os::*::raw` type aliases to
correspond to the newly widened types that are being returned on each
platform.
* Change the definition of `std::os::*::raw::stat` on Linux to match the LFS
definitions rather than the standard ones.
The breaking changes here will specifically break code that assumes that `libc`
and `std` agree on the definition of `std::os::*::raw` types, or that the `std`
types are faithful representations of the types in C. An [audit] has been
performed of crates.io to determine the fallout which was determined two be
minimal, with the two found cases of breakage having been fixed now.
[audit]: https://github.com/rust-lang/rfcs/pull/1415#issuecomment-180645582
---
Ok, so after all that, we're finally able to support LFS on Linux! This commit
then simultaneously starts using `stat64` and friends on Linux to ensure that we
can open >4GB files on 32-bit Linux. Yay!
Closes #28978
Closes #30050
Closes #31549
2016-02-05 01:16:47 +00:00
|
|
|
let mut stat: stat64 = unsafe { mem::zeroed() };
|
2016-03-23 03:01:37 +00:00
|
|
|
cvt(unsafe {
|
std: Deprecate all std::os::*::raw types
This commit is an implementation of [RFC 1415][rfc] which deprecates all types
in the `std::os::*::raw` modules.
[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1415-trim-std-os.md
Many of the types in these modules don't actually have a canonical platform
representation, for example the definition of `stat` on 32-bit Linux will change
depending on whether C code is compiled with LFS support or not. Unfortunately
the current types in `std::os::*::raw` are billed as "compatible with C", which
in light of this means it isn't really possible.
To make matters worse, platforms like Android sometimes define these types as
*smaller* than the way they're actually represented in the `stat` structure
itself. This means that when methods like `DirEntry::ino` are called on Android
the result may be truncated as we're tied to returning a `ino_t` type, not the
underlying type.
The commit here incorporates two backwards-compatible components:
* Deprecate all `raw` types that aren't in `std::os::raw`
* Expand the `std::os::*::fs::MetadataExt` trait on all platforms for method
accessors of all fields. The fields now returned widened types which are the
same across platforms (consistency across platforms is not required, however,
it's just convenient).
and two also backwards-incompatible components:
* Change the definition of all `std::os::*::raw` type aliases to
correspond to the newly widened types that are being returned on each
platform.
* Change the definition of `std::os::*::raw::stat` on Linux to match the LFS
definitions rather than the standard ones.
The breaking changes here will specifically break code that assumes that `libc`
and `std` agree on the definition of `std::os::*::raw` types, or that the `std`
types are faithful representations of the types in C. An [audit] has been
performed of crates.io to determine the fallout which was determined two be
minimal, with the two found cases of breakage having been fixed now.
[audit]: https://github.com/rust-lang/rfcs/pull/1415#issuecomment-180645582
---
Ok, so after all that, we're finally able to support LFS on Linux! This commit
then simultaneously starts using `stat64` and friends on Linux to ensure that we
can open >4GB files on 32-bit Linux. Yay!
Closes #28978
Closes #30050
Closes #31549
2016-02-05 01:16:47 +00:00
|
|
|
fstat64(self.0.raw(), &mut stat)
|
2016-03-23 03:01:37 +00:00
|
|
|
})?;
|
2015-02-03 05:39:14 +00:00
|
|
|
Ok(FileAttr { stat: stat })
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn fsync(&self) -> io::Result<()> {
|
2016-03-23 03:01:37 +00:00
|
|
|
cvt_r(|| unsafe { libc::fsync(self.0.raw()) })?;
|
2015-02-03 05:39:14 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn datasync(&self) -> io::Result<()> {
|
2016-03-23 03:01:37 +00:00
|
|
|
cvt_r(|| unsafe { os_datasync(self.0.raw()) })?;
|
2015-02-03 05:39:14 +00:00
|
|
|
return Ok(());
|
|
|
|
|
|
|
|
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
|
|
|
unsafe fn os_datasync(fd: c_int) -> c_int {
|
|
|
|
libc::fcntl(fd, libc::F_FULLFSYNC)
|
|
|
|
}
|
|
|
|
#[cfg(target_os = "linux")]
|
|
|
|
unsafe fn os_datasync(fd: c_int) -> c_int { libc::fdatasync(fd) }
|
|
|
|
#[cfg(not(any(target_os = "macos",
|
|
|
|
target_os = "ios",
|
|
|
|
target_os = "linux")))]
|
|
|
|
unsafe fn os_datasync(fd: c_int) -> c_int { libc::fsync(fd) }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn truncate(&self, size: u64) -> io::Result<()> {
|
2016-03-23 03:01:37 +00:00
|
|
|
cvt_r(|| unsafe {
|
2016-02-15 00:09:57 +00:00
|
|
|
ftruncate64(self.0.raw(), size as off64_t)
|
2016-03-23 03:01:37 +00:00
|
|
|
})?;
|
2015-02-03 05:39:14 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
|
|
|
self.0.read(buf)
|
|
|
|
}
|
|
|
|
|
2016-02-12 08:17:24 +00:00
|
|
|
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
|
|
|
self.0.read_to_end(buf)
|
|
|
|
}
|
|
|
|
|
2015-02-03 05:39:14 +00:00
|
|
|
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
|
|
|
|
self.0.write(buf)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn flush(&self) -> io::Result<()> { Ok(()) }
|
|
|
|
|
|
|
|
pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
|
|
|
|
let (whence, pos) = match pos {
|
2016-02-15 00:15:39 +00:00
|
|
|
SeekFrom::Start(off) => (libc::SEEK_SET, off as off64_t),
|
|
|
|
SeekFrom::End(off) => (libc::SEEK_END, off as off64_t),
|
|
|
|
SeekFrom::Current(off) => (libc::SEEK_CUR, off as off64_t),
|
2015-02-03 05:39:14 +00:00
|
|
|
};
|
2016-03-23 03:01:37 +00:00
|
|
|
let n = cvt(unsafe { lseek64(self.0.raw(), pos, whence) })?;
|
2015-02-03 05:39:14 +00:00
|
|
|
Ok(n as u64)
|
|
|
|
}
|
|
|
|
|
2016-01-21 05:24:23 +00:00
|
|
|
pub fn duplicate(&self) -> io::Result<File> {
|
|
|
|
self.0.duplicate().map(File)
|
|
|
|
}
|
|
|
|
|
2015-02-03 05:39:14 +00:00
|
|
|
pub fn fd(&self) -> &FileDesc { &self.0 }
|
2015-07-16 06:31:24 +00:00
|
|
|
|
|
|
|
pub fn into_fd(self) -> FileDesc { self.0 }
|
2015-02-03 05:39:14 +00:00
|
|
|
}
|
|
|
|
|
2015-04-28 00:29:35 +00:00
|
|
|
impl DirBuilder {
|
|
|
|
pub fn new() -> DirBuilder {
|
|
|
|
DirBuilder { mode: 0o777 }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn mkdir(&self, p: &Path) -> io::Result<()> {
|
2016-03-23 03:01:37 +00:00
|
|
|
let p = cstr(p)?;
|
|
|
|
cvt(unsafe { libc::mkdir(p.as_ptr(), self.mode) })?;
|
2015-04-28 00:29:35 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
std: Deprecate all std::os::*::raw types
This commit is an implementation of [RFC 1415][rfc] which deprecates all types
in the `std::os::*::raw` modules.
[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1415-trim-std-os.md
Many of the types in these modules don't actually have a canonical platform
representation, for example the definition of `stat` on 32-bit Linux will change
depending on whether C code is compiled with LFS support or not. Unfortunately
the current types in `std::os::*::raw` are billed as "compatible with C", which
in light of this means it isn't really possible.
To make matters worse, platforms like Android sometimes define these types as
*smaller* than the way they're actually represented in the `stat` structure
itself. This means that when methods like `DirEntry::ino` are called on Android
the result may be truncated as we're tied to returning a `ino_t` type, not the
underlying type.
The commit here incorporates two backwards-compatible components:
* Deprecate all `raw` types that aren't in `std::os::raw`
* Expand the `std::os::*::fs::MetadataExt` trait on all platforms for method
accessors of all fields. The fields now returned widened types which are the
same across platforms (consistency across platforms is not required, however,
it's just convenient).
and two also backwards-incompatible components:
* Change the definition of all `std::os::*::raw` type aliases to
correspond to the newly widened types that are being returned on each
platform.
* Change the definition of `std::os::*::raw::stat` on Linux to match the LFS
definitions rather than the standard ones.
The breaking changes here will specifically break code that assumes that `libc`
and `std` agree on the definition of `std::os::*::raw` types, or that the `std`
types are faithful representations of the types in C. An [audit] has been
performed of crates.io to determine the fallout which was determined two be
minimal, with the two found cases of breakage having been fixed now.
[audit]: https://github.com/rust-lang/rfcs/pull/1415#issuecomment-180645582
---
Ok, so after all that, we're finally able to support LFS on Linux! This commit
then simultaneously starts using `stat64` and friends on Linux to ensure that we
can open >4GB files on 32-bit Linux. Yay!
Closes #28978
Closes #30050
Closes #31549
2016-02-05 01:16:47 +00:00
|
|
|
pub fn set_mode(&mut self, mode: u32) {
|
|
|
|
self.mode = mode as mode_t;
|
2015-04-28 00:29:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-18 06:47:40 +00:00
|
|
|
fn cstr(path: &Path) -> io::Result<CString> {
|
2016-03-23 03:01:37 +00:00
|
|
|
Ok(CString::new(path.as_os_str().as_bytes())?)
|
2015-02-03 05:39:14 +00:00
|
|
|
}
|
|
|
|
|
std: Stabilize parts of std::os::platform::io
This commit stabilizes the platform-specific `io` modules, specifically around
the traits having to do with the raw representation of each object on each
platform.
Specifically, the following material was stabilized:
* `AsRaw{Fd,Socket,Handle}`
* `RawFd` (renamed from `Fd`)
* `RawHandle` (renamed from `Handle`)
* `RawSocket` (renamed from `Socket`)
* `AsRaw{Fd,Socket,Handle}` implementations
* `std::os::{unix, windows}::io`
The following material was added as `#[unstable]`:
* `FromRaw{Fd,Socket,Handle}`
* Implementations for various primitives
There are a number of future improvements that are possible to make to this
module, but this should cover a good bit of functionality desired from these
modules for now. Some specific future additions may include:
* `IntoRawXXX` traits to consume the raw representation and cancel the
auto-destructor.
* `Fd`, `Socket`, and `Handle` abstractions that behave like Rust objects and
have nice methods for various syscalls.
At this time though, these are considered backwards-compatible extensions and
will not be stabilized at this time.
This commit is a breaking change due to the addition of `Raw` in from of the
type aliases in each of the platform-specific modules.
[breaking-change]
2015-03-26 23:18:29 +00:00
|
|
|
impl FromInner<c_int> for File {
|
|
|
|
fn from_inner(fd: c_int) -> File {
|
|
|
|
File(FileDesc::new(fd))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-19 09:27:19 +00:00
|
|
|
impl fmt::Debug for File {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
#[cfg(target_os = "linux")]
|
|
|
|
fn get_path(fd: c_int) -> Option<PathBuf> {
|
|
|
|
use string::ToString;
|
|
|
|
let mut p = PathBuf::from("/proc/self/fd");
|
|
|
|
p.push(&fd.to_string());
|
|
|
|
readlink(&p).ok()
|
|
|
|
}
|
|
|
|
|
2015-07-10 14:23:14 +00:00
|
|
|
#[cfg(target_os = "macos")]
|
|
|
|
fn get_path(fd: c_int) -> Option<PathBuf> {
|
Reduce the reliance on `PATH_MAX`
- Rewrite `std::sys::fs::readlink` not to rely on `PATH_MAX`
It currently has the following problems:
1. It uses `_PC_NAME_MAX` to query the maximum length of a file path in
the underlying system. However, the meaning of the constant is the
maximum length of *a path component*, not a full path. The correct
constant should be `_PC_PATH_MAX`.
2. `pathconf` *may* fail if the referred file does not exist. This can
be problematic if the file which the symbolic link points to does not
exist, but the link itself does exist. In this case, the current
implementation resorts to the hard-coded value of `1024`, which is not
ideal.
3. There may exist a platform where there is no limit on file path
lengths in general. That's the reaon why GNU Hurd doesn't define
`PATH_MAX` at all, in addition to having `pathconf` always returning
`-1`. In these platforms, the content of the symbolic link can be
silently truncated if the length exceeds the hard-coded limit mentioned
above.
4. The value obtained by `pathconf` may be outdated at the point of
actually calling `readlink`. This is inherently racy.
This commit introduces a loop that gradually increases the length of the
buffer passed to `readlink`, eliminating the need of `pathconf`.
- Remove the arbitrary memory limit of `std::sys::fs::realpath`
As per POSIX 2013, `realpath` will return a malloc'ed buffer if the
second argument is a null pointer.[1]
[1] http://pubs.opengroup.org/onlinepubs/9699919799/functions/realpath.html
- Comment on functions that are still using `PATH_MAX`
There are some functions that only work in terms of `PATH_MAX`, such as
`F_GETPATH` in OS X. Comments on them for posterity.
2015-08-19 04:11:40 +00:00
|
|
|
// FIXME: The use of PATH_MAX is generally not encouraged, but it
|
|
|
|
// is inevitable in this case because OS X defines `fcntl` with
|
|
|
|
// `F_GETPATH` in terms of `MAXPATHLEN`, and there are no
|
|
|
|
// alternatives. If a better method is invented, it should be used
|
|
|
|
// instead.
|
2015-07-10 14:23:14 +00:00
|
|
|
let mut buf = vec![0;libc::PATH_MAX as usize];
|
|
|
|
let n = unsafe { libc::fcntl(fd, libc::F_GETPATH, buf.as_ptr()) };
|
|
|
|
if n == -1 {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
let l = buf.iter().position(|&c| c == 0).unwrap();
|
|
|
|
buf.truncate(l as usize);
|
Reduce the reliance on `PATH_MAX`
- Rewrite `std::sys::fs::readlink` not to rely on `PATH_MAX`
It currently has the following problems:
1. It uses `_PC_NAME_MAX` to query the maximum length of a file path in
the underlying system. However, the meaning of the constant is the
maximum length of *a path component*, not a full path. The correct
constant should be `_PC_PATH_MAX`.
2. `pathconf` *may* fail if the referred file does not exist. This can
be problematic if the file which the symbolic link points to does not
exist, but the link itself does exist. In this case, the current
implementation resorts to the hard-coded value of `1024`, which is not
ideal.
3. There may exist a platform where there is no limit on file path
lengths in general. That's the reaon why GNU Hurd doesn't define
`PATH_MAX` at all, in addition to having `pathconf` always returning
`-1`. In these platforms, the content of the symbolic link can be
silently truncated if the length exceeds the hard-coded limit mentioned
above.
4. The value obtained by `pathconf` may be outdated at the point of
actually calling `readlink`. This is inherently racy.
This commit introduces a loop that gradually increases the length of the
buffer passed to `readlink`, eliminating the need of `pathconf`.
- Remove the arbitrary memory limit of `std::sys::fs::realpath`
As per POSIX 2013, `realpath` will return a malloc'ed buffer if the
second argument is a null pointer.[1]
[1] http://pubs.opengroup.org/onlinepubs/9699919799/functions/realpath.html
- Comment on functions that are still using `PATH_MAX`
There are some functions that only work in terms of `PATH_MAX`, such as
`F_GETPATH` in OS X. Comments on them for posterity.
2015-08-19 04:11:40 +00:00
|
|
|
buf.shrink_to_fit();
|
2015-07-10 14:23:14 +00:00
|
|
|
Some(PathBuf::from(OsString::from_vec(buf)))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
|
2015-04-19 09:27:19 +00:00
|
|
|
fn get_path(_fd: c_int) -> Option<PathBuf> {
|
|
|
|
// FIXME(#24570): implement this for other Unix platforms
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
2015-07-10 14:23:14 +00:00
|
|
|
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
2015-04-19 09:27:19 +00:00
|
|
|
fn get_mode(fd: c_int) -> Option<(bool, bool)> {
|
|
|
|
let mode = unsafe { libc::fcntl(fd, libc::F_GETFL) };
|
|
|
|
if mode == -1 {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
match mode & libc::O_ACCMODE {
|
|
|
|
libc::O_RDONLY => Some((true, false)),
|
|
|
|
libc::O_RDWR => Some((true, true)),
|
|
|
|
libc::O_WRONLY => Some((false, true)),
|
|
|
|
_ => None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-10 14:23:14 +00:00
|
|
|
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
|
2015-04-19 09:27:19 +00:00
|
|
|
fn get_mode(_fd: c_int) -> Option<(bool, bool)> {
|
|
|
|
// FIXME(#24570): implement this for other Unix platforms
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
|
|
|
let fd = self.0.raw();
|
2015-05-17 20:17:26 +00:00
|
|
|
let mut b = f.debug_struct("File");
|
|
|
|
b.field("fd", &fd);
|
2015-04-19 09:27:19 +00:00
|
|
|
if let Some(path) = get_path(fd) {
|
2015-05-17 20:17:26 +00:00
|
|
|
b.field("path", &path);
|
2015-04-19 09:27:19 +00:00
|
|
|
}
|
|
|
|
if let Some((read, write)) = get_mode(fd) {
|
2015-05-17 20:17:26 +00:00
|
|
|
b.field("read", &read).field("write", &write);
|
2015-04-19 09:27:19 +00:00
|
|
|
}
|
|
|
|
b.finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-03 05:39:14 +00:00
|
|
|
pub fn readdir(p: &Path) -> io::Result<ReadDir> {
|
2015-02-20 17:46:56 +00:00
|
|
|
let root = Arc::new(p.to_path_buf());
|
2016-03-23 03:01:37 +00:00
|
|
|
let p = cstr(p)?;
|
2015-02-03 05:39:14 +00:00
|
|
|
unsafe {
|
|
|
|
let ptr = libc::opendir(p.as_ptr());
|
|
|
|
if ptr.is_null() {
|
|
|
|
Err(Error::last_os_error())
|
|
|
|
} else {
|
2015-02-20 17:46:56 +00:00
|
|
|
Ok(ReadDir { dirp: Dir(ptr), root: root })
|
2015-02-03 05:39:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn unlink(p: &Path) -> io::Result<()> {
|
2016-03-23 03:01:37 +00:00
|
|
|
let p = cstr(p)?;
|
|
|
|
cvt(unsafe { libc::unlink(p.as_ptr()) })?;
|
2015-02-03 05:39:14 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
|
2016-03-23 03:01:37 +00:00
|
|
|
let old = cstr(old)?;
|
|
|
|
let new = cstr(new)?;
|
|
|
|
cvt(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) })?;
|
2015-02-03 05:39:14 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> {
|
2016-03-23 03:01:37 +00:00
|
|
|
let p = cstr(p)?;
|
|
|
|
cvt_r(|| unsafe { libc::chmod(p.as_ptr(), perm.mode) })?;
|
2015-02-03 05:39:14 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn rmdir(p: &Path) -> io::Result<()> {
|
2016-03-23 03:01:37 +00:00
|
|
|
let p = cstr(p)?;
|
|
|
|
cvt(unsafe { libc::rmdir(p.as_ptr()) })?;
|
2015-02-03 05:39:14 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2016-02-02 06:04:55 +00:00
|
|
|
pub fn remove_dir_all(path: &Path) -> io::Result<()> {
|
2016-03-23 03:01:37 +00:00
|
|
|
let filetype = lstat(path)?.file_type();
|
2016-02-07 18:31:14 +00:00
|
|
|
if filetype.is_symlink() {
|
|
|
|
unlink(path)
|
|
|
|
} else {
|
|
|
|
remove_dir_all_recursive(path)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn remove_dir_all_recursive(path: &Path) -> io::Result<()> {
|
2016-03-23 03:01:37 +00:00
|
|
|
for child in readdir(path)? {
|
|
|
|
let child = child?;
|
|
|
|
if child.file_type()?.is_dir() {
|
|
|
|
remove_dir_all_recursive(&child.path())?;
|
2016-02-02 06:04:55 +00:00
|
|
|
} else {
|
2016-03-23 03:01:37 +00:00
|
|
|
unlink(&child.path())?;
|
2016-02-02 06:04:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
rmdir(path)
|
|
|
|
}
|
|
|
|
|
2015-02-03 05:39:14 +00:00
|
|
|
pub fn readlink(p: &Path) -> io::Result<PathBuf> {
|
2016-03-23 03:01:37 +00:00
|
|
|
let c_path = cstr(p)?;
|
2015-02-03 05:39:14 +00:00
|
|
|
let p = c_path.as_ptr();
|
Reduce the reliance on `PATH_MAX`
- Rewrite `std::sys::fs::readlink` not to rely on `PATH_MAX`
It currently has the following problems:
1. It uses `_PC_NAME_MAX` to query the maximum length of a file path in
the underlying system. However, the meaning of the constant is the
maximum length of *a path component*, not a full path. The correct
constant should be `_PC_PATH_MAX`.
2. `pathconf` *may* fail if the referred file does not exist. This can
be problematic if the file which the symbolic link points to does not
exist, but the link itself does exist. In this case, the current
implementation resorts to the hard-coded value of `1024`, which is not
ideal.
3. There may exist a platform where there is no limit on file path
lengths in general. That's the reaon why GNU Hurd doesn't define
`PATH_MAX` at all, in addition to having `pathconf` always returning
`-1`. In these platforms, the content of the symbolic link can be
silently truncated if the length exceeds the hard-coded limit mentioned
above.
4. The value obtained by `pathconf` may be outdated at the point of
actually calling `readlink`. This is inherently racy.
This commit introduces a loop that gradually increases the length of the
buffer passed to `readlink`, eliminating the need of `pathconf`.
- Remove the arbitrary memory limit of `std::sys::fs::realpath`
As per POSIX 2013, `realpath` will return a malloc'ed buffer if the
second argument is a null pointer.[1]
[1] http://pubs.opengroup.org/onlinepubs/9699919799/functions/realpath.html
- Comment on functions that are still using `PATH_MAX`
There are some functions that only work in terms of `PATH_MAX`, such as
`F_GETPATH` in OS X. Comments on them for posterity.
2015-08-19 04:11:40 +00:00
|
|
|
|
|
|
|
let mut buf = Vec::with_capacity(256);
|
|
|
|
|
|
|
|
loop {
|
2016-03-23 03:01:37 +00:00
|
|
|
let buf_read = cvt(unsafe {
|
Reduce the reliance on `PATH_MAX`
- Rewrite `std::sys::fs::readlink` not to rely on `PATH_MAX`
It currently has the following problems:
1. It uses `_PC_NAME_MAX` to query the maximum length of a file path in
the underlying system. However, the meaning of the constant is the
maximum length of *a path component*, not a full path. The correct
constant should be `_PC_PATH_MAX`.
2. `pathconf` *may* fail if the referred file does not exist. This can
be problematic if the file which the symbolic link points to does not
exist, but the link itself does exist. In this case, the current
implementation resorts to the hard-coded value of `1024`, which is not
ideal.
3. There may exist a platform where there is no limit on file path
lengths in general. That's the reaon why GNU Hurd doesn't define
`PATH_MAX` at all, in addition to having `pathconf` always returning
`-1`. In these platforms, the content of the symbolic link can be
silently truncated if the length exceeds the hard-coded limit mentioned
above.
4. The value obtained by `pathconf` may be outdated at the point of
actually calling `readlink`. This is inherently racy.
This commit introduces a loop that gradually increases the length of the
buffer passed to `readlink`, eliminating the need of `pathconf`.
- Remove the arbitrary memory limit of `std::sys::fs::realpath`
As per POSIX 2013, `realpath` will return a malloc'ed buffer if the
second argument is a null pointer.[1]
[1] http://pubs.opengroup.org/onlinepubs/9699919799/functions/realpath.html
- Comment on functions that are still using `PATH_MAX`
There are some functions that only work in terms of `PATH_MAX`, such as
`F_GETPATH` in OS X. Comments on them for posterity.
2015-08-19 04:11:40 +00:00
|
|
|
libc::readlink(p, buf.as_mut_ptr() as *mut _, buf.capacity() as libc::size_t)
|
2016-03-23 03:01:37 +00:00
|
|
|
})? as usize;
|
Reduce the reliance on `PATH_MAX`
- Rewrite `std::sys::fs::readlink` not to rely on `PATH_MAX`
It currently has the following problems:
1. It uses `_PC_NAME_MAX` to query the maximum length of a file path in
the underlying system. However, the meaning of the constant is the
maximum length of *a path component*, not a full path. The correct
constant should be `_PC_PATH_MAX`.
2. `pathconf` *may* fail if the referred file does not exist. This can
be problematic if the file which the symbolic link points to does not
exist, but the link itself does exist. In this case, the current
implementation resorts to the hard-coded value of `1024`, which is not
ideal.
3. There may exist a platform where there is no limit on file path
lengths in general. That's the reaon why GNU Hurd doesn't define
`PATH_MAX` at all, in addition to having `pathconf` always returning
`-1`. In these platforms, the content of the symbolic link can be
silently truncated if the length exceeds the hard-coded limit mentioned
above.
4. The value obtained by `pathconf` may be outdated at the point of
actually calling `readlink`. This is inherently racy.
This commit introduces a loop that gradually increases the length of the
buffer passed to `readlink`, eliminating the need of `pathconf`.
- Remove the arbitrary memory limit of `std::sys::fs::realpath`
As per POSIX 2013, `realpath` will return a malloc'ed buffer if the
second argument is a null pointer.[1]
[1] http://pubs.opengroup.org/onlinepubs/9699919799/functions/realpath.html
- Comment on functions that are still using `PATH_MAX`
There are some functions that only work in terms of `PATH_MAX`, such as
`F_GETPATH` in OS X. Comments on them for posterity.
2015-08-19 04:11:40 +00:00
|
|
|
|
|
|
|
unsafe { buf.set_len(buf_read); }
|
|
|
|
|
|
|
|
if buf_read != buf.capacity() {
|
|
|
|
buf.shrink_to_fit();
|
|
|
|
|
|
|
|
return Ok(PathBuf::from(OsString::from_vec(buf)));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Trigger the internal buffer resizing logic of `Vec` by requiring
|
|
|
|
// more space than the current capacity. The length is guaranteed to be
|
|
|
|
// the same as the capacity due to the if statement above.
|
|
|
|
buf.reserve(1);
|
2015-02-03 05:39:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
|
2016-03-23 03:01:37 +00:00
|
|
|
let src = cstr(src)?;
|
|
|
|
let dst = cstr(dst)?;
|
|
|
|
cvt(unsafe { libc::symlink(src.as_ptr(), dst.as_ptr()) })?;
|
2015-02-03 05:39:14 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
|
2016-03-23 03:01:37 +00:00
|
|
|
let src = cstr(src)?;
|
|
|
|
let dst = cstr(dst)?;
|
|
|
|
cvt(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) })?;
|
2015-02-03 05:39:14 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn stat(p: &Path) -> io::Result<FileAttr> {
|
2016-03-23 03:01:37 +00:00
|
|
|
let p = cstr(p)?;
|
std: Deprecate all std::os::*::raw types
This commit is an implementation of [RFC 1415][rfc] which deprecates all types
in the `std::os::*::raw` modules.
[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1415-trim-std-os.md
Many of the types in these modules don't actually have a canonical platform
representation, for example the definition of `stat` on 32-bit Linux will change
depending on whether C code is compiled with LFS support or not. Unfortunately
the current types in `std::os::*::raw` are billed as "compatible with C", which
in light of this means it isn't really possible.
To make matters worse, platforms like Android sometimes define these types as
*smaller* than the way they're actually represented in the `stat` structure
itself. This means that when methods like `DirEntry::ino` are called on Android
the result may be truncated as we're tied to returning a `ino_t` type, not the
underlying type.
The commit here incorporates two backwards-compatible components:
* Deprecate all `raw` types that aren't in `std::os::raw`
* Expand the `std::os::*::fs::MetadataExt` trait on all platforms for method
accessors of all fields. The fields now returned widened types which are the
same across platforms (consistency across platforms is not required, however,
it's just convenient).
and two also backwards-incompatible components:
* Change the definition of all `std::os::*::raw` type aliases to
correspond to the newly widened types that are being returned on each
platform.
* Change the definition of `std::os::*::raw::stat` on Linux to match the LFS
definitions rather than the standard ones.
The breaking changes here will specifically break code that assumes that `libc`
and `std` agree on the definition of `std::os::*::raw` types, or that the `std`
types are faithful representations of the types in C. An [audit] has been
performed of crates.io to determine the fallout which was determined two be
minimal, with the two found cases of breakage having been fixed now.
[audit]: https://github.com/rust-lang/rfcs/pull/1415#issuecomment-180645582
---
Ok, so after all that, we're finally able to support LFS on Linux! This commit
then simultaneously starts using `stat64` and friends on Linux to ensure that we
can open >4GB files on 32-bit Linux. Yay!
Closes #28978
Closes #30050
Closes #31549
2016-02-05 01:16:47 +00:00
|
|
|
let mut stat: stat64 = unsafe { mem::zeroed() };
|
2016-03-23 03:01:37 +00:00
|
|
|
cvt(unsafe {
|
std: Deprecate all std::os::*::raw types
This commit is an implementation of [RFC 1415][rfc] which deprecates all types
in the `std::os::*::raw` modules.
[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1415-trim-std-os.md
Many of the types in these modules don't actually have a canonical platform
representation, for example the definition of `stat` on 32-bit Linux will change
depending on whether C code is compiled with LFS support or not. Unfortunately
the current types in `std::os::*::raw` are billed as "compatible with C", which
in light of this means it isn't really possible.
To make matters worse, platforms like Android sometimes define these types as
*smaller* than the way they're actually represented in the `stat` structure
itself. This means that when methods like `DirEntry::ino` are called on Android
the result may be truncated as we're tied to returning a `ino_t` type, not the
underlying type.
The commit here incorporates two backwards-compatible components:
* Deprecate all `raw` types that aren't in `std::os::raw`
* Expand the `std::os::*::fs::MetadataExt` trait on all platforms for method
accessors of all fields. The fields now returned widened types which are the
same across platforms (consistency across platforms is not required, however,
it's just convenient).
and two also backwards-incompatible components:
* Change the definition of all `std::os::*::raw` type aliases to
correspond to the newly widened types that are being returned on each
platform.
* Change the definition of `std::os::*::raw::stat` on Linux to match the LFS
definitions rather than the standard ones.
The breaking changes here will specifically break code that assumes that `libc`
and `std` agree on the definition of `std::os::*::raw` types, or that the `std`
types are faithful representations of the types in C. An [audit] has been
performed of crates.io to determine the fallout which was determined two be
minimal, with the two found cases of breakage having been fixed now.
[audit]: https://github.com/rust-lang/rfcs/pull/1415#issuecomment-180645582
---
Ok, so after all that, we're finally able to support LFS on Linux! This commit
then simultaneously starts using `stat64` and friends on Linux to ensure that we
can open >4GB files on 32-bit Linux. Yay!
Closes #28978
Closes #30050
Closes #31549
2016-02-05 01:16:47 +00:00
|
|
|
stat64(p.as_ptr(), &mut stat as *mut _ as *mut _)
|
2016-03-23 03:01:37 +00:00
|
|
|
})?;
|
2015-02-03 05:39:14 +00:00
|
|
|
Ok(FileAttr { stat: stat })
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn lstat(p: &Path) -> io::Result<FileAttr> {
|
2016-03-23 03:01:37 +00:00
|
|
|
let p = cstr(p)?;
|
std: Deprecate all std::os::*::raw types
This commit is an implementation of [RFC 1415][rfc] which deprecates all types
in the `std::os::*::raw` modules.
[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1415-trim-std-os.md
Many of the types in these modules don't actually have a canonical platform
representation, for example the definition of `stat` on 32-bit Linux will change
depending on whether C code is compiled with LFS support or not. Unfortunately
the current types in `std::os::*::raw` are billed as "compatible with C", which
in light of this means it isn't really possible.
To make matters worse, platforms like Android sometimes define these types as
*smaller* than the way they're actually represented in the `stat` structure
itself. This means that when methods like `DirEntry::ino` are called on Android
the result may be truncated as we're tied to returning a `ino_t` type, not the
underlying type.
The commit here incorporates two backwards-compatible components:
* Deprecate all `raw` types that aren't in `std::os::raw`
* Expand the `std::os::*::fs::MetadataExt` trait on all platforms for method
accessors of all fields. The fields now returned widened types which are the
same across platforms (consistency across platforms is not required, however,
it's just convenient).
and two also backwards-incompatible components:
* Change the definition of all `std::os::*::raw` type aliases to
correspond to the newly widened types that are being returned on each
platform.
* Change the definition of `std::os::*::raw::stat` on Linux to match the LFS
definitions rather than the standard ones.
The breaking changes here will specifically break code that assumes that `libc`
and `std` agree on the definition of `std::os::*::raw` types, or that the `std`
types are faithful representations of the types in C. An [audit] has been
performed of crates.io to determine the fallout which was determined two be
minimal, with the two found cases of breakage having been fixed now.
[audit]: https://github.com/rust-lang/rfcs/pull/1415#issuecomment-180645582
---
Ok, so after all that, we're finally able to support LFS on Linux! This commit
then simultaneously starts using `stat64` and friends on Linux to ensure that we
can open >4GB files on 32-bit Linux. Yay!
Closes #28978
Closes #30050
Closes #31549
2016-02-05 01:16:47 +00:00
|
|
|
let mut stat: stat64 = unsafe { mem::zeroed() };
|
2016-03-23 03:01:37 +00:00
|
|
|
cvt(unsafe {
|
std: Deprecate all std::os::*::raw types
This commit is an implementation of [RFC 1415][rfc] which deprecates all types
in the `std::os::*::raw` modules.
[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1415-trim-std-os.md
Many of the types in these modules don't actually have a canonical platform
representation, for example the definition of `stat` on 32-bit Linux will change
depending on whether C code is compiled with LFS support or not. Unfortunately
the current types in `std::os::*::raw` are billed as "compatible with C", which
in light of this means it isn't really possible.
To make matters worse, platforms like Android sometimes define these types as
*smaller* than the way they're actually represented in the `stat` structure
itself. This means that when methods like `DirEntry::ino` are called on Android
the result may be truncated as we're tied to returning a `ino_t` type, not the
underlying type.
The commit here incorporates two backwards-compatible components:
* Deprecate all `raw` types that aren't in `std::os::raw`
* Expand the `std::os::*::fs::MetadataExt` trait on all platforms for method
accessors of all fields. The fields now returned widened types which are the
same across platforms (consistency across platforms is not required, however,
it's just convenient).
and two also backwards-incompatible components:
* Change the definition of all `std::os::*::raw` type aliases to
correspond to the newly widened types that are being returned on each
platform.
* Change the definition of `std::os::*::raw::stat` on Linux to match the LFS
definitions rather than the standard ones.
The breaking changes here will specifically break code that assumes that `libc`
and `std` agree on the definition of `std::os::*::raw` types, or that the `std`
types are faithful representations of the types in C. An [audit] has been
performed of crates.io to determine the fallout which was determined two be
minimal, with the two found cases of breakage having been fixed now.
[audit]: https://github.com/rust-lang/rfcs/pull/1415#issuecomment-180645582
---
Ok, so after all that, we're finally able to support LFS on Linux! This commit
then simultaneously starts using `stat64` and friends on Linux to ensure that we
can open >4GB files on 32-bit Linux. Yay!
Closes #28978
Closes #30050
Closes #31549
2016-02-05 01:16:47 +00:00
|
|
|
lstat64(p.as_ptr(), &mut stat as *mut _ as *mut _)
|
2016-03-23 03:01:37 +00:00
|
|
|
})?;
|
2015-02-03 05:39:14 +00:00
|
|
|
Ok(FileAttr { stat: stat })
|
|
|
|
}
|
|
|
|
|
2015-04-16 06:21:13 +00:00
|
|
|
pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
|
2016-03-23 03:01:37 +00:00
|
|
|
let path = CString::new(p.as_os_str().as_bytes())?;
|
Reduce the reliance on `PATH_MAX`
- Rewrite `std::sys::fs::readlink` not to rely on `PATH_MAX`
It currently has the following problems:
1. It uses `_PC_NAME_MAX` to query the maximum length of a file path in
the underlying system. However, the meaning of the constant is the
maximum length of *a path component*, not a full path. The correct
constant should be `_PC_PATH_MAX`.
2. `pathconf` *may* fail if the referred file does not exist. This can
be problematic if the file which the symbolic link points to does not
exist, but the link itself does exist. In this case, the current
implementation resorts to the hard-coded value of `1024`, which is not
ideal.
3. There may exist a platform where there is no limit on file path
lengths in general. That's the reaon why GNU Hurd doesn't define
`PATH_MAX` at all, in addition to having `pathconf` always returning
`-1`. In these platforms, the content of the symbolic link can be
silently truncated if the length exceeds the hard-coded limit mentioned
above.
4. The value obtained by `pathconf` may be outdated at the point of
actually calling `readlink`. This is inherently racy.
This commit introduces a loop that gradually increases the length of the
buffer passed to `readlink`, eliminating the need of `pathconf`.
- Remove the arbitrary memory limit of `std::sys::fs::realpath`
As per POSIX 2013, `realpath` will return a malloc'ed buffer if the
second argument is a null pointer.[1]
[1] http://pubs.opengroup.org/onlinepubs/9699919799/functions/realpath.html
- Comment on functions that are still using `PATH_MAX`
There are some functions that only work in terms of `PATH_MAX`, such as
`F_GETPATH` in OS X. Comments on them for posterity.
2015-08-19 04:11:40 +00:00
|
|
|
let buf;
|
2015-04-16 06:21:13 +00:00
|
|
|
unsafe {
|
2015-11-03 00:23:22 +00:00
|
|
|
let r = libc::realpath(path.as_ptr(), ptr::null_mut());
|
2015-04-16 06:21:13 +00:00
|
|
|
if r.is_null() {
|
|
|
|
return Err(io::Error::last_os_error())
|
|
|
|
}
|
Reduce the reliance on `PATH_MAX`
- Rewrite `std::sys::fs::readlink` not to rely on `PATH_MAX`
It currently has the following problems:
1. It uses `_PC_NAME_MAX` to query the maximum length of a file path in
the underlying system. However, the meaning of the constant is the
maximum length of *a path component*, not a full path. The correct
constant should be `_PC_PATH_MAX`.
2. `pathconf` *may* fail if the referred file does not exist. This can
be problematic if the file which the symbolic link points to does not
exist, but the link itself does exist. In this case, the current
implementation resorts to the hard-coded value of `1024`, which is not
ideal.
3. There may exist a platform where there is no limit on file path
lengths in general. That's the reaon why GNU Hurd doesn't define
`PATH_MAX` at all, in addition to having `pathconf` always returning
`-1`. In these platforms, the content of the symbolic link can be
silently truncated if the length exceeds the hard-coded limit mentioned
above.
4. The value obtained by `pathconf` may be outdated at the point of
actually calling `readlink`. This is inherently racy.
This commit introduces a loop that gradually increases the length of the
buffer passed to `readlink`, eliminating the need of `pathconf`.
- Remove the arbitrary memory limit of `std::sys::fs::realpath`
As per POSIX 2013, `realpath` will return a malloc'ed buffer if the
second argument is a null pointer.[1]
[1] http://pubs.opengroup.org/onlinepubs/9699919799/functions/realpath.html
- Comment on functions that are still using `PATH_MAX`
There are some functions that only work in terms of `PATH_MAX`, such as
`F_GETPATH` in OS X. Comments on them for posterity.
2015-08-19 04:11:40 +00:00
|
|
|
buf = CStr::from_ptr(r).to_bytes().to_vec();
|
|
|
|
libc::free(r as *mut _);
|
2015-04-16 06:21:13 +00:00
|
|
|
}
|
|
|
|
Ok(PathBuf::from(OsString::from_vec(buf)))
|
|
|
|
}
|
2015-07-10 08:54:00 +00:00
|
|
|
|
|
|
|
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
|
std: Stabilize library APIs for 1.5
This commit stabilizes and deprecates library APIs whose FCP has closed in the
last cycle, specifically:
Stabilized APIs:
* `fs::canonicalize`
* `Path::{metadata, symlink_metadata, canonicalize, read_link, read_dir, exists,
is_file, is_dir}` - all moved to inherent methods from the `PathExt` trait.
* `Formatter::fill`
* `Formatter::width`
* `Formatter::precision`
* `Formatter::sign_plus`
* `Formatter::sign_minus`
* `Formatter::alternate`
* `Formatter::sign_aware_zero_pad`
* `string::ParseError`
* `Utf8Error::valid_up_to`
* `Iterator::{cmp, partial_cmp, eq, ne, lt, le, gt, ge}`
* `<[T]>::split_{first,last}{,_mut}`
* `Condvar::wait_timeout` - note that `wait_timeout_ms` is not yet deprecated
but will be once 1.5 is released.
* `str::{R,}MatchIndices`
* `str::{r,}match_indices`
* `char::from_u32_unchecked`
* `VecDeque::insert`
* `VecDeque::shrink_to_fit`
* `VecDeque::as_slices`
* `VecDeque::as_mut_slices`
* `VecDeque::swap_remove_front` - (renamed from `swap_front_remove`)
* `VecDeque::swap_remove_back` - (renamed from `swap_back_remove`)
* `Vec::resize`
* `str::slice_mut_unchecked`
* `FileTypeExt`
* `FileTypeExt::{is_block_device, is_char_device, is_fifo, is_socket}`
* `BinaryHeap::from` - `from_vec` deprecated in favor of this
* `BinaryHeap::into_vec` - plus a `Into` impl
* `BinaryHeap::into_sorted_vec`
Deprecated APIs
* `slice::ref_slice`
* `slice::mut_ref_slice`
* `iter::{range_inclusive, RangeInclusive}`
* `std::dynamic_lib`
Closes #27706
Closes #27725
cc #27726 (align not stabilized yet)
Closes #27734
Closes #27737
Closes #27742
Closes #27743
Closes #27772
Closes #27774
Closes #27777
Closes #27781
cc #27788 (a few remaining methods though)
Closes #27790
Closes #27793
Closes #27796
Closes #27810
cc #28147 (not all parts stabilized)
2015-10-22 23:28:45 +00:00
|
|
|
use fs::{File, set_permissions};
|
2015-07-10 08:54:00 +00:00
|
|
|
if !from.is_file() {
|
|
|
|
return Err(Error::new(ErrorKind::InvalidInput,
|
2015-08-05 22:25:09 +00:00
|
|
|
"the source path is not an existing regular file"))
|
2015-07-10 08:54:00 +00:00
|
|
|
}
|
|
|
|
|
2016-03-23 03:01:37 +00:00
|
|
|
let mut reader = File::open(from)?;
|
|
|
|
let mut writer = File::create(to)?;
|
|
|
|
let perm = reader.metadata()?.permissions();
|
2015-07-10 08:54:00 +00:00
|
|
|
|
2016-03-23 03:01:37 +00:00
|
|
|
let ret = io::copy(&mut reader, &mut writer)?;
|
|
|
|
set_permissions(to, perm)?;
|
2015-07-10 08:54:00 +00:00
|
|
|
Ok(ret)
|
|
|
|
}
|