Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,6 +43,12 @@ areas: | |
|
||
# Detailed design | ||
|
||
First, a vision for how lowering APIs in general will be presented, and then a | ||
number of specific APIs will each be proposed. Many of the proposed APIs are | ||
independent from one another and this RFC may not be implemented all-in-one-go | ||
but instead piecemeal over time, allowing the designs to evolve slightly in the | ||
meantime. | ||
|
||
## Lowering APIs | ||
|
||
### The vision for the `os` module | ||
|
@@ -103,7 +109,7 @@ crates in this regard. | |
Concretely, lowering has two ingredients: | ||
|
||
1. Introducing one or more "raw" types that are generally direct aliases for C | ||
types. | ||
types (more on this in the next section). | ||
|
||
2. Providing an extension trait that makes it possible to extract a raw type | ||
from a `std` type. In some cases, it's possible to go the other way around as | ||
|
@@ -120,6 +126,35 @@ lowerings that are currently missing from `std::fs`. | |
[io-reform-vision]: https://github.com/rust-lang/rfcs/blob/master/text/0517-io-os-reform.md#vision-for-io | ||
[AsRawFd]: http://static.rust-lang.org/doc/master/std/os/unix/io/trait.AsRawFd.html | ||
|
||
#### `std::os::platform::raw` | ||
|
||
Each of the primitives in the standard library will expose the ability to be | ||
lowered into its component abstraction, facilitating the need to define these | ||
abstractions and organize them in the platform-specific modules. This RFC | ||
proposes the following guidelines for doing so: | ||
|
||
* Each platform will have a `raw` module inside of `std::os` which houses all of | ||
its platform specific definitions. | ||
* Only type definitions will be contained in `raw` modules, no function | ||
bindings, methods, or trait implementations. | ||
* Cross-platform types (e.g. those shared on all `unix` platforms) will be | ||
located in the respective cross-platform module. Types which only differ in | ||
the width of an integer type are considered to be cross-platform. | ||
* Platform-specific types will exist only in the `raw` module for that platform. | ||
A platform-specific type may have different field names, components, or just | ||
not exist on other platforms. | ||
|
||
Differences in integer widths are not considered to be enough of a platform | ||
difference to define in each separate platform's module, meaning that it will be | ||
possible to write code that uses `os::unix` but doesn't compile on all Unix | ||
platforms. It is believed that most consumers of these types will continue to | ||
store the same type (e.g. not assume it's an `i32`) throughout the application | ||
or immediately cast it to a known type. | ||
|
||
To reiterate, it is not planned for each `raw` module to provide *exhaustive* | ||
bindings to each platform. Only those abstractions which the standard library is | ||
lowering into will be defined in each `raw` module. | ||
|
||
### Lowering `Metadata` (all platforms) | ||
|
||
Currently the `Metadata` structure exposes very few pieces of information about | ||
|
@@ -146,23 +181,23 @@ mod os::windows::fs { | |
|
||
mod os::unix::fs { | ||
pub trait MetadataExt { | ||
fn as_raw(&self) -> &raw::Metadata; | ||
fn as_raw(&self) -> &Metadata; | ||
} | ||
impl MetadataExt for fs::Metadata { ... } | ||
|
||
pub struct RawMetadata(libc::stat); | ||
impl RawMetadata { | ||
// Accessors for fields available in `libc::stat` for *all* platforms | ||
fn dev(&self) -> libc::dev_t; // st_dev field | ||
fn ino(&self) -> libc::ino_t; // st_ino field | ||
fn raw_mode(&self) -> libc::mode_t; // st_mode field | ||
fn nlink(&self) -> libc::nlink_t; // st_nlink field | ||
fn uid(&self) -> libc::uid_t; // st_uid field | ||
fn gid(&self) -> libc::gid_t; // st_gid field | ||
fn rdev(&self) -> libc::dev_t; // st_rdev field | ||
fn size(&self) -> libc::off_t; // st_size field | ||
fn blksize(&self) -> libc::blksize_t; // st_blksize field | ||
fn blocks(&self) -> libc::blkcnt_t; // st_blocks field | ||
pub struct Metadata(raw::stat); | ||
impl Metadata { | ||
// Accessors for fields available in `raw::stat` for *all* platforms | ||
fn dev(&self) -> raw::dev_t; // st_dev field | ||
fn ino(&self) -> raw::ino_t; // st_ino field | ||
fn mode(&self) -> raw::mode_t; // st_mode field | ||
fn nlink(&self) -> raw::nlink_t; // st_nlink field | ||
fn uid(&self) -> raw::uid_t; // st_uid field | ||
fn gid(&self) -> raw::gid_t; // st_gid field | ||
fn rdev(&self) -> raw::dev_t; // st_rdev field | ||
fn size(&self) -> raw::off_t; // st_size field | ||
fn blksize(&self) -> raw::blksize_t; // st_blksize field | ||
fn blocks(&self) -> raw::blkcnt_t; // st_blocks field | ||
fn atime(&self) -> (i64, i32); // st_atime field, (sec, nsec) | ||
fn mtime(&self) -> (i64, i32); // st_mtime field, (sec, nsec) | ||
fn ctime(&self) -> (i64, i32); // st_ctime field, (sec, nsec) | ||
|
@@ -171,9 +206,16 @@ mod os::unix::fs { | |
|
||
// st_flags, st_gen, st_lspare, st_birthtim, st_qspare | ||
mod os::{linux, macos, freebsd, ...}::fs { | ||
pub struct stat { /* same public fields as libc::stat */ } | ||
pub mod raw { | ||
pub type dev_t = ...; | ||
pub type ino_t = ...; | ||
// ... | ||
pub struct stat { | ||
// ... same public fields as libc::stat | ||
} | ||
} | ||
pub trait MetadataExt { | ||
fn as_raw_stat(&self) -> &stat; | ||
fn as_raw_stat(&self) -> &raw::stat; | ||
} | ||
impl MetadataExt for os::unix::fs::RawMetadata { ... } | ||
impl MetadataExt for fs::Metadata { ... } | ||
|
@@ -225,10 +267,31 @@ and it is unclear whether the current unstable methods of doing so, | |
piece of functionality is whether to provide a higher level abstractiong (e.g. | ||
similar to the `bitflags` crate) for the permission bits on unix. | ||
|
||
This RFC proposes renaming `mode` and `set_mode` on `PermissionsExt` and | ||
`OpenOptionsExt` to `raw_mode` and `set_raw_mode` in order enable an addition of | ||
a higher-level `Mode` abstraction in the future. This is also the rationale for | ||
naming the accessor of `st_mode` on `RawMetadata` as `raw_mode`. | ||
This RFC proposes considering the methods for stabilization as-is and not | ||
pursuing a higher level abstraction of the unix permission bits. To facilitate | ||
in their inspection and manipulation, however, the following constants will be | ||
added: | ||
|
||
```rust | ||
mod os::unix::fs { | ||
pub const USER_READ: raw::mode_t; | ||
pub const USER_WRITE: raw::mode_t; | ||
pub const USER_EXECUTE: raw::mode_t; | ||
pub const USER_RWX: raw::mode_t; | ||
pub const OTHER_READ: raw::mode_t; | ||
pub const OTHER_WRITE: raw::mode_t; | ||
pub const OTHER_EXECUTE: raw::mode_t; | ||
pub const OTHER_RWX: raw::mode_t; | ||
pub const GROUP_READ: raw::mode_t; | ||
pub const GROUP_WRITE: raw::mode_t; | ||
pub const GROUP_EXECUTE: raw::mode_t; | ||
pub const GROUP_RWX: raw::mode_t; | ||
pub const ALL_READ: raw::mode_t; | ||
pub const ALL_WRITE: raw::mode_t; | ||
pub const ALL_EXECUTE: raw::mode_t; | ||
pub const ALL_RWX: raw::mode_t; | ||
} | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
alexcrichton
Author
Owner
|
||
``` | ||
|
||
Finally, the `set_permissions` function of the `std::fs` module is also proposed | ||
to be marked `#[stable]` soon as a method of blanket setting permissions for a | ||
|
@@ -245,17 +308,11 @@ impl Permissions { | |
/// | ||
/// On unix platforms this corresponds to the permission bits `0o666` | ||
pub fn new() -> Permissions; | ||
|
||
/// Creates a new set of permissions which when applied to a file will make | ||
/// it read-only for all users. | ||
/// | ||
/// On unix platforms this corresponds to the permission bits `0o444`. | ||
pub fn new_readonly() -> Permissions; | ||
} | ||
|
||
mod os::unix::fs { | ||
pub trait PermissionsExt { | ||
fn from_raw_mode(mode: i32) -> Self; | ||
fn from_mode(mode: raw::mode_t) -> Self; | ||
} | ||
impl PermissionsExt for Permissions { ... } | ||
} | ||
|
@@ -280,22 +337,14 @@ impl CreateDirOptions { | |
/// permissions settings. | ||
pub fn recursive(&mut self, recursive: bool) -> &mut Self; | ||
|
||
/// Use the specified directory as a "template" for permissions and security | ||
/// settings of the new directories to be created. | ||
/// | ||
/// On unix this will issue a `stat` of the specified directory and new | ||
/// directories will be created with the same permission bits. On Windows | ||
/// this will trigger the use of the `CreateDirectoryEx` function. | ||
pub fn template<P: AsRef<Path>>(&mut self, path: P) -> &mut Self; | ||
|
||
/// Create the specified directory with the options configured in this | ||
/// builder. | ||
pub fn create<P: AsRef<Path>>(&self, path: P) -> io::Result<()>; | ||
} | ||
|
||
mod os::unix::fs { | ||
pub trait CreateDirOptionsExt { | ||
fn raw_mode(&mut self, mode: i32) -> &mut Self; | ||
fn mode(&mut self, mode: raw::mode_t) -> &mut Self; | ||
} | ||
impl CreateDirOptionsExt for CreateDirOptions { ... } | ||
} | ||
|
@@ -307,9 +356,26 @@ mod os::windows::fs { | |
} | ||
impl CreateDirOptionsExt for CreateDirOptions { ... } | ||
} | ||
``` | ||
|
||
This sort of builder is also extendable to other flavors of functions in the | ||
future, such as [C++'s template parameter][cpp-dir-template]: | ||
|
||
[cpp-dir-template]: http://en.cppreference.com/w/cpp/experimental/fs/create_directory | ||
|
||
```rust | ||
/// Use the specified directory as a "template" for permissions and security | ||
/// settings of the new directories to be created. | ||
/// | ||
/// On unix this will issue a `stat` of the specified directory and new | ||
/// directories will be created with the same permission bits. On Windows | ||
/// this will trigger the use of the `CreateDirectoryEx` function. | ||
pub fn template<P: AsRef<Path>>(&mut self, path: P) -> &mut Self; | ||
``` | ||
|
||
At this time, however, it it not proposed to add this method to | ||
`CreateDirOptions`. | ||
|
||
## Adding `fs::equivalent` | ||
|
||
A new function `equivalent` will be added to the `fs` module along the lines of | ||
|
This is missing a couple of constants; the SUID, SGID, and sticky bit flags (
S_ISUID
,S_ISGID
, andS_ISVTX
in POSIX/Single Unix Specificaiton). I appreciate the more readable names for the other constants, so more readable constants for these would be good too, perhaps something likeSETUID
,SETGID
(with or without an underscore, I don't particularly mind), andSTICKY_BIT
since that's how people usually refer to them.