Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add attributes to std::bitflags, use bitflags for std::io::FilePermission #13897

Merged
merged 3 commits into from
May 6, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions src/libnative/io/file_unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ pub fn open(path: &CString, fm: io::FileMode, fa: io::FileAccess)

pub fn mkdir(p: &CString, mode: io::FilePermission) -> IoResult<()> {
super::mkerr_libc(retry(|| unsafe {
libc::mkdir(p.with_ref(|p| p), mode as libc::mode_t)
libc::mkdir(p.with_ref(|p| p), mode.bits() as libc::mode_t)
}))
}

Expand Down Expand Up @@ -392,7 +392,7 @@ pub fn rename(old: &CString, new: &CString) -> IoResult<()> {

pub fn chmod(p: &CString, mode: io::FilePermission) -> IoResult<()> {
super::mkerr_libc(retry(|| unsafe {
libc::chmod(p.with_ref(|p| p), mode as libc::mode_t)
libc::chmod(p.with_ref(|p| p), mode.bits() as libc::mode_t)
}))
}

Expand Down Expand Up @@ -470,7 +470,9 @@ fn mkstat(stat: &libc::stat, path: &CString) -> io::FileStat {
path: Path::new(path),
size: stat.st_size as u64,
kind: kind,
perm: (stat.st_mode) as io::FilePermission & io::AllPermissions,
perm: unsafe {
io::FilePermission::from_bits(stat.st_mode as u32) & io::AllPermissions
},
created: mktime(stat.st_ctime as u64, stat.st_ctime_nsec as u64),
modified: mktime(stat.st_mtime as u64, stat.st_mtime_nsec as u64),
accessed: mktime(stat.st_atime as u64, stat.st_atime_nsec as u64),
Expand Down
6 changes: 4 additions & 2 deletions src/libnative/io/file_win32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ pub fn rename(old: &CString, new: &CString) -> IoResult<()> {

pub fn chmod(p: &CString, mode: io::FilePermission) -> IoResult<()> {
super::mkerr_libc(as_utf16_p(p.as_str().unwrap(), |p| unsafe {
libc::wchmod(p, mode as libc::c_int)
libc::wchmod(p, mode.bits() as libc::c_int)
}))
}

Expand Down Expand Up @@ -470,7 +470,9 @@ fn mkstat(stat: &libc::stat, path: &CString) -> io::FileStat {
path: Path::new(path),
size: stat.st_size as u64,
kind: kind,
perm: (stat.st_mode) as io::FilePermission & io::AllPermissions,
perm: unsafe {
io::FilePermission::from_bits(stat.st_mode as u32) & io::AllPermissions
},
created: stat.st_ctime as u64,
modified: stat.st_mtime as u64,
accessed: stat.st_atime as u64,
Expand Down
4 changes: 3 additions & 1 deletion src/librustuv/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,9 @@ impl FsRequest {
path: path,
size: stat.st_size as u64,
kind: kind,
perm: (stat.st_mode as io::FilePermission) & io::AllPermissions,
perm: unsafe {
io::FilePermission::from_bits(stat.st_mode as u32) & io::AllPermissions
},
created: to_msec(stat.st_birthtim),
modified: to_msec(stat.st_mtim),
accessed: to_msec(stat.st_atim),
Expand Down
4 changes: 2 additions & 2 deletions src/librustuv/uvio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ impl IoFactory for UvIoFactory {
}
fn fs_mkdir(&mut self, path: &CString,
perm: io::FilePermission) -> Result<(), IoError> {
let r = FsRequest::mkdir(&self.loop_, path, perm as c_int);
let r = FsRequest::mkdir(&self.loop_, path, perm.bits() as c_int);
r.map_err(uv_error_to_io_error)
}
fn fs_rmdir(&mut self, path: &CString) -> Result<(), IoError> {
Expand All @@ -237,7 +237,7 @@ impl IoFactory for UvIoFactory {
}
fn fs_chmod(&mut self, path: &CString,
perm: io::FilePermission) -> Result<(), IoError> {
let r = FsRequest::chmod(&self.loop_, path, perm as c_int);
let r = FsRequest::chmod(&self.loop_, path, perm.bits() as c_int);
r.map_err(uv_error_to_io_error)
}
fn fs_readdir(&mut self, path: &CString, flags: c_int)
Expand Down
71 changes: 46 additions & 25 deletions src/libstd/bitflags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@
//! # Example
//!
//! ~~~rust
//! bitflags!(Flags: u32 {
//! FlagA = 0x00000001,
//! FlagB = 0x00000010,
//! FlagC = 0x00000100,
//! FlagABC = FlagA.bits
//! | FlagB.bits
//! | FlagC.bits
//! })
//! bitflags!(
//! flags Flags: u32 {
//! static FlagA = 0x00000001,
//! static FlagB = 0x00000010,
//! static FlagC = 0x00000100,
//! static FlagABC = FlagA.bits
//! | FlagB.bits
//! | FlagC.bits
//! }
//! )
//!
//! fn main() {
//! let e1 = FlagA | FlagC;
Expand All @@ -40,10 +42,12 @@
//! ~~~rust
//! use std::fmt;
//!
//! bitflags!(Flags: u32 {
//! FlagA = 0x00000001,
//! FlagB = 0x00000010
//! })
//! bitflags!(
//! flags Flags: u32 {
//! static FlagA = 0x00000001,
//! static FlagB = 0x00000010
//! }
//! )
//!
//! impl Flags {
//! pub fn clear(&mut self) {
Expand All @@ -66,10 +70,16 @@
//! }
//! ~~~
//!
//! # Attributes
//!
//! Attributes can be attached to the generated `struct` by placing them
//! before the `flags` keyword.
//!
//! # Derived traits
//!
//! The `Eq`, `TotalEq`, and `Clone` traits are automatically derived for the
//! `struct` using the `deriving` attribute.
//! The `Eq` and `Clone` traits are automatically derived for the `struct` using
//! the `deriving` attribute. Additional traits can be derived by providing an
//! explicit `deriving` attribute on `flags`.
//!
//! # Operators
//!
Expand All @@ -91,17 +101,20 @@
//! - `insert`: inserts the specified flags in-place
//! - `remove`: removes the specified flags in-place

#![macro_escape]

#[macro_export]
macro_rules! bitflags(
($BitFlags:ident: $T:ty {
$($Flag:ident = $value:expr),+
($(#[$attr:meta])* flags $BitFlags:ident: $T:ty {
$($(#[$Flag_attr:meta])* static $Flag:ident = $value:expr),+
}) => (
#[deriving(Eq, TotalEq, Clone)]
$(#[$attr])*
pub struct $BitFlags {
bits: $T,
}

$(pub static $Flag: $BitFlags = $BitFlags { bits: $value };)+
$($(#[$Flag_attr])* pub static $Flag: $BitFlags = $BitFlags { bits: $value };)+

impl $BitFlags {
/// Returns an empty set of flags.
Expand All @@ -114,6 +127,12 @@ macro_rules! bitflags(
self.bits
}

/// Convert from underlying bit representation. Unsafe because the
/// bits are not guaranteed to represent valid flags.
pub unsafe fn from_bits(bits: $T) -> $BitFlags {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't there be a safe version of this that just makes sure it's a valid combination of bits?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cmr Yeah, that's a good point. I'll add this after #14009 lands.

$BitFlags { bits: bits }
}

/// Returns `true` if no flags are currently stored.
pub fn is_empty(&self) -> bool {
*self == $BitFlags::empty()
Expand Down Expand Up @@ -170,14 +189,16 @@ macro_rules! bitflags(
mod tests {
use ops::{BitOr, BitAnd, Sub};

bitflags!(Flags: u32 {
FlagA = 0x00000001,
FlagB = 0x00000010,
FlagC = 0x00000100,
FlagABC = FlagA.bits
| FlagB.bits
| FlagC.bits
})
bitflags!(
flags Flags: u32 {
static FlagA = 0x00000001,
static FlagB = 0x00000010,
static FlagC = 0x00000100,
static FlagABC = FlagA.bits
| FlagB.bits
| FlagC.bits
}
)

#[test]
fn test_bits(){
Expand Down
6 changes: 3 additions & 3 deletions src/libstd/io/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1119,7 +1119,7 @@ mod test {
check!(File::create(&input));
check!(chmod(&input, io::UserRead));
check!(copy(&input, &out));
assert!(check!(out.stat()).perm & io::UserWrite == 0);
assert!(!check!(out.stat()).perm.intersects(io::UserWrite));

check!(chmod(&input, io::UserFile));
check!(chmod(&out, io::UserFile));
Expand Down Expand Up @@ -1193,9 +1193,9 @@ mod test {
let file = tmpdir.join("in.txt");

check!(File::create(&file));
assert!(check!(stat(&file)).perm & io::UserWrite == io::UserWrite);
assert!(check!(stat(&file)).perm.contains(io::UserWrite));
check!(chmod(&file, io::UserRead));
assert!(check!(stat(&file)).perm & io::UserWrite == 0);
assert!(!check!(stat(&file)).perm.contains(io::UserWrite));

match chmod(&tmpdir.join("foo"), io::UserRWX) {
Ok(..) => fail!("wanted a failure"),
Expand Down
71 changes: 38 additions & 33 deletions src/libstd/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ use fmt;
use int;
use iter::Iterator;
use libc;
use ops::{BitOr, BitAnd, Sub};
use os;
use option::{Option, Some, None};
use path::Path;
Expand Down Expand Up @@ -1558,36 +1559,40 @@ pub struct UnstableFileStat {
pub gen: u64,
}

/// A set of permissions for a file or directory is represented by a set of
/// flags which are or'd together.
pub type FilePermission = u32;

// Each permission bit
pub static UserRead: FilePermission = 0x100;
pub static UserWrite: FilePermission = 0x080;
pub static UserExecute: FilePermission = 0x040;
pub static GroupRead: FilePermission = 0x020;
pub static GroupWrite: FilePermission = 0x010;
pub static GroupExecute: FilePermission = 0x008;
pub static OtherRead: FilePermission = 0x004;
pub static OtherWrite: FilePermission = 0x002;
pub static OtherExecute: FilePermission = 0x001;

// Common combinations of these bits
pub static UserRWX: FilePermission = UserRead | UserWrite | UserExecute;
pub static GroupRWX: FilePermission = GroupRead | GroupWrite | GroupExecute;
pub static OtherRWX: FilePermission = OtherRead | OtherWrite | OtherExecute;

/// A set of permissions for user owned files, this is equivalent to 0644 on
/// unix-like systems.
pub static UserFile: FilePermission = UserRead | UserWrite | GroupRead | OtherRead;
/// A set of permissions for user owned directories, this is equivalent to 0755
/// on unix-like systems.
pub static UserDir: FilePermission = UserRWX | GroupRead | GroupExecute |
OtherRead | OtherExecute;
/// A set of permissions for user owned executables, this is equivalent to 0755
/// on unix-like systems.
pub static UserExec: FilePermission = UserDir;

/// A mask for all possible permission bits
pub static AllPermissions: FilePermission = 0x1ff;
bitflags!(
#[doc="A set of permissions for a file or directory is represented
by a set of flags which are or'd together."]
#[deriving(Hash)]
#[deriving(Show)]
flags FilePermission: u32 {
static UserRead = 0o400,
static UserWrite = 0o200,
static UserExecute = 0o100,
static GroupRead = 0o040,
static GroupWrite = 0o020,
static GroupExecute = 0o010,
static OtherRead = 0o004,
static OtherWrite = 0o002,
static OtherExecute = 0o001,

static UserRWX = UserRead.bits | UserWrite.bits | UserExecute.bits,
static GroupRWX = GroupRead.bits | GroupWrite.bits | GroupExecute.bits,
static OtherRWX = OtherRead.bits | OtherWrite.bits | OtherExecute.bits,

#[doc="Permissions for user owned files, equivalent to 0644 on
unix-like systems."]
static UserFile = UserRead.bits | UserWrite.bits | GroupRead.bits | OtherRead.bits,

#[doc="Permissions for user owned directories, equivalent to 0755 on
unix-like systems."]
static UserDir = UserRWX.bits | GroupRead.bits | GroupExecute.bits |
OtherRead.bits | OtherExecute.bits,

#[doc="Permissions for user owned executables, equivalent to 0755
on unix-like systems."]
static UserExec = UserDir.bits,

#[doc="All possible permissions enabled."]
static AllPermissions = UserRWX.bits | GroupRWX.bits | OtherRWX.bits
}
)