Skip to content

Commit 8d1d7d9

Browse files
committed
Change std::io::FilePermission to a typesafe representation
This patch changes `std::io::FilePermissions` from an exposed `u32` representation to a typesafe representation (that only allows valid flag combinations) using the `std::bitflags`, thus ensuring a greater degree of safety on the Rust side. Despite the change to the type, most code should continue to work as-is, sincde the new type provides bit operations in the style of C flags. To get at the underlying integer representation, use the `bits` method; to (unsafely) convert to `FilePermissions`, use `FilePermissions::from_bits`. Closes #6085. [breaking-change]
1 parent c00d8fd commit 8d1d7d9

File tree

6 files changed

+55
-44
lines changed

6 files changed

+55
-44
lines changed

src/libnative/io/file_unix.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ pub fn open(path: &CString, fm: io::FileMode, fa: io::FileAccess)
335335

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

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

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

@@ -470,7 +470,9 @@ fn mkstat(stat: &libc::stat, path: &CString) -> io::FileStat {
470470
path: Path::new(path),
471471
size: stat.st_size as u64,
472472
kind: kind,
473-
perm: (stat.st_mode) as io::FilePermission & io::AllPermissions,
473+
perm: unsafe {
474+
io::FilePermission::from_bits(stat.st_mode as u32) & io::AllPermissions
475+
},
474476
created: mktime(stat.st_ctime as u64, stat.st_ctime_nsec as u64),
475477
modified: mktime(stat.st_mtime as u64, stat.st_mtime_nsec as u64),
476478
accessed: mktime(stat.st_atime as u64, stat.st_atime_nsec as u64),

src/libnative/io/file_win32.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ pub fn rename(old: &CString, new: &CString) -> IoResult<()> {
391391

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

@@ -470,7 +470,9 @@ fn mkstat(stat: &libc::stat, path: &CString) -> io::FileStat {
470470
path: Path::new(path),
471471
size: stat.st_size as u64,
472472
kind: kind,
473-
perm: (stat.st_mode) as io::FilePermission & io::AllPermissions,
473+
perm: unsafe {
474+
io::FilePermission::from_bits(stat.st_mode as u32) & io::AllPermissions
475+
},
474476
created: stat.st_ctime as u64,
475477
modified: stat.st_mtime as u64,
476478
accessed: stat.st_atime as u64,

src/librustuv/file.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,9 @@ impl FsRequest {
283283
path: path,
284284
size: stat.st_size as u64,
285285
kind: kind,
286-
perm: (stat.st_mode as io::FilePermission) & io::AllPermissions,
286+
perm: unsafe {
287+
io::FilePermission::from_bits(stat.st_mode as u32) & io::AllPermissions
288+
},
287289
created: to_msec(stat.st_birthtim),
288290
modified: to_msec(stat.st_mtim),
289291
accessed: to_msec(stat.st_atim),

src/librustuv/uvio.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ impl IoFactory for UvIoFactory {
224224
}
225225
fn fs_mkdir(&mut self, path: &CString,
226226
perm: io::FilePermission) -> Result<(), IoError> {
227-
let r = FsRequest::mkdir(&self.loop_, path, perm as c_int);
227+
let r = FsRequest::mkdir(&self.loop_, path, perm.bits() as c_int);
228228
r.map_err(uv_error_to_io_error)
229229
}
230230
fn fs_rmdir(&mut self, path: &CString) -> Result<(), IoError> {
@@ -237,7 +237,7 @@ impl IoFactory for UvIoFactory {
237237
}
238238
fn fs_chmod(&mut self, path: &CString,
239239
perm: io::FilePermission) -> Result<(), IoError> {
240-
let r = FsRequest::chmod(&self.loop_, path, perm as c_int);
240+
let r = FsRequest::chmod(&self.loop_, path, perm.bits() as c_int);
241241
r.map_err(uv_error_to_io_error)
242242
}
243243
fn fs_readdir(&mut self, path: &CString, flags: c_int)

src/libstd/io/fs.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,7 +1119,7 @@ mod test {
11191119
check!(File::create(&input));
11201120
check!(chmod(&input, io::UserRead));
11211121
check!(copy(&input, &out));
1122-
assert!(check!(out.stat()).perm & io::UserWrite == 0);
1122+
assert!(!check!(out.stat()).perm.intersects(io::UserWrite));
11231123

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

11951195
check!(File::create(&file));
1196-
assert!(check!(stat(&file)).perm & io::UserWrite == io::UserWrite);
1196+
assert!(check!(stat(&file)).perm.contains(io::UserWrite));
11971197
check!(chmod(&file, io::UserRead));
1198-
assert!(check!(stat(&file)).perm & io::UserWrite == 0);
1198+
assert!(!check!(stat(&file)).perm.contains(io::UserWrite));
11991199

12001200
match chmod(&tmpdir.join("foo"), io::UserRWX) {
12011201
Ok(..) => fail!("wanted a failure"),

src/libstd/io/mod.rs

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ use fmt;
224224
use int;
225225
use iter::Iterator;
226226
use libc;
227+
use ops::{BitOr, BitAnd, Sub};
227228
use os;
228229
use option::{Option, Some, None};
229230
use path::Path;
@@ -1558,36 +1559,40 @@ pub struct UnstableFileStat {
15581559
pub gen: u64,
15591560
}
15601561

1561-
/// A set of permissions for a file or directory is represented by a set of
1562-
/// flags which are or'd together.
1563-
pub type FilePermission = u32;
1564-
1565-
// Each permission bit
1566-
pub static UserRead: FilePermission = 0x100;
1567-
pub static UserWrite: FilePermission = 0x080;
1568-
pub static UserExecute: FilePermission = 0x040;
1569-
pub static GroupRead: FilePermission = 0x020;
1570-
pub static GroupWrite: FilePermission = 0x010;
1571-
pub static GroupExecute: FilePermission = 0x008;
1572-
pub static OtherRead: FilePermission = 0x004;
1573-
pub static OtherWrite: FilePermission = 0x002;
1574-
pub static OtherExecute: FilePermission = 0x001;
1575-
1576-
// Common combinations of these bits
1577-
pub static UserRWX: FilePermission = UserRead | UserWrite | UserExecute;
1578-
pub static GroupRWX: FilePermission = GroupRead | GroupWrite | GroupExecute;
1579-
pub static OtherRWX: FilePermission = OtherRead | OtherWrite | OtherExecute;
1580-
1581-
/// A set of permissions for user owned files, this is equivalent to 0644 on
1582-
/// unix-like systems.
1583-
pub static UserFile: FilePermission = UserRead | UserWrite | GroupRead | OtherRead;
1584-
/// A set of permissions for user owned directories, this is equivalent to 0755
1585-
/// on unix-like systems.
1586-
pub static UserDir: FilePermission = UserRWX | GroupRead | GroupExecute |
1587-
OtherRead | OtherExecute;
1588-
/// A set of permissions for user owned executables, this is equivalent to 0755
1589-
/// on unix-like systems.
1590-
pub static UserExec: FilePermission = UserDir;
1591-
1592-
/// A mask for all possible permission bits
1593-
pub static AllPermissions: FilePermission = 0x1ff;
1562+
bitflags!(
1563+
#[doc="A set of permissions for a file or directory is represented
1564+
by a set of flags which are or'd together."]
1565+
#[deriving(Hash)]
1566+
#[deriving(Show)]
1567+
flags FilePermission: u32 {
1568+
static UserRead = 0o400,
1569+
static UserWrite = 0o200,
1570+
static UserExecute = 0o100,
1571+
static GroupRead = 0o040,
1572+
static GroupWrite = 0o020,
1573+
static GroupExecute = 0o010,
1574+
static OtherRead = 0o004,
1575+
static OtherWrite = 0o002,
1576+
static OtherExecute = 0o001,
1577+
1578+
static UserRWX = UserRead.bits | UserWrite.bits | UserExecute.bits,
1579+
static GroupRWX = GroupRead.bits | GroupWrite.bits | GroupExecute.bits,
1580+
static OtherRWX = OtherRead.bits | OtherWrite.bits | OtherExecute.bits,
1581+
1582+
#[doc="Permissions for user owned files, equivalent to 0644 on
1583+
unix-like systems."]
1584+
static UserFile = UserRead.bits | UserWrite.bits | GroupRead.bits | OtherRead.bits,
1585+
1586+
#[doc="Permissions for user owned directories, equivalent to 0755 on
1587+
unix-like systems."]
1588+
static UserDir = UserRWX.bits | GroupRead.bits | GroupExecute.bits |
1589+
OtherRead.bits | OtherExecute.bits,
1590+
1591+
#[doc="Permissions for user owned executables, equivalent to 0755
1592+
on unix-like systems."]
1593+
static UserExec = UserDir.bits,
1594+
1595+
#[doc="All possible permissions enabled."]
1596+
static AllPermissions = UserRWX.bits | GroupRWX.bits | OtherRWX.bits
1597+
}
1598+
)

0 commit comments

Comments
 (0)