Add fchmod, fchown

This commit is contained in:
Jeremy Soller
2017-11-29 21:05:17 -07:00
parent 38b24ad321
commit eac37c7dc5
3 changed files with 103 additions and 12 deletions
+78 -5
View File
@@ -2,8 +2,8 @@ use std::cmp::{min, max};
use std::time::{SystemTime, UNIX_EPOCH};
use syscall::data::TimeSpec;
use syscall::error::{Error, Result, EBADF, EINVAL, EISDIR};
use syscall::flag::{O_ACCMODE, O_RDONLY, O_WRONLY, O_RDWR, F_GETFL, F_SETFL};
use syscall::error::{Error, Result, EBADF, EINVAL, EISDIR, EPERM};
use syscall::flag::{O_ACCMODE, O_RDONLY, O_WRONLY, O_RDWR, F_GETFL, F_SETFL, MODE_PERM};
use syscall::{Stat, SEEK_SET, SEEK_CUR, SEEK_END};
use disk::Disk;
@@ -14,6 +14,8 @@ pub trait Resource<D: Disk> {
fn read(&mut self, buf: &mut [u8], fs: &mut FileSystem<D>) -> Result<usize>;
fn write(&mut self, buf: &[u8], fs: &mut FileSystem<D>) -> Result<usize>;
fn seek(&mut self, offset: usize, whence: usize, fs: &mut FileSystem<D>) -> Result<usize>;
fn fchmod(&mut self, mode: u16, fs: &mut FileSystem<D>) -> Result<usize>;
fn fchown(&mut self, uid: u32, gid: u32, fs: &mut FileSystem<D>) -> Result<usize>;
fn fcntl(&mut self, cmd: usize, arg: usize) -> Result<usize>;
fn path(&self, buf: &mut [u8]) -> Result<usize>;
fn stat(&self, _stat: &mut Stat, fs: &mut FileSystem<D>) -> Result<usize>;
@@ -27,15 +29,17 @@ pub struct DirResource {
block: u64,
data: Option<Vec<u8>>,
seek: usize,
uid: u32,
}
impl DirResource {
pub fn new(path: String, block: u64, data: Option<Vec<u8>>) -> DirResource {
pub fn new(path: String, block: u64, data: Option<Vec<u8>>, uid: u32) -> DirResource {
DirResource {
path: path,
block: block,
data: data,
seek: 0,
uid: uid,
}
}
}
@@ -46,7 +50,8 @@ impl<D: Disk> Resource<D> for DirResource {
path: self.path.clone(),
block: self.block,
data: self.data.clone(),
seek: self.seek
seek: self.seek,
uid: self.uid
}))
}
@@ -77,6 +82,40 @@ impl<D: Disk> Resource<D> for DirResource {
Ok(self.seek)
}
fn fchmod(&mut self, mode: u16, fs: &mut FileSystem<D>) -> Result<usize> {
let mut node = fs.node(self.block)?;
if node.1.uid == self.uid || self.uid == 0 {
node.1.mode = (node.1.mode & ! MODE_PERM) | (mode & MODE_PERM);
fs.write_at(node.0, &node.1)?;
Ok(0)
} else {
Err(Error::new(EPERM))
}
}
fn fchown(&mut self, uid: u32, gid: u32, fs: &mut FileSystem<D>) -> Result<usize> {
let mut node = fs.node(self.block)?;
if node.1.uid == self.uid || self.uid == 0 {
if uid as i32 != -1 {
node.1.uid = uid;
}
if gid as i32 != -1 {
node.1.gid = gid;
}
fs.write_at(node.0, &node.1)?;
Ok(0)
} else {
Err(Error::new(EPERM))
}
}
fn fcntl(&mut self, _cmd: usize, _arg: usize) -> Result<usize> {
Err(Error::new(EBADF))
}
@@ -192,6 +231,40 @@ impl<D: Disk> Resource<D> for FileResource {
Ok(self.seek as usize)
}
fn fchmod(&mut self, mode: u16, fs: &mut FileSystem<D>) -> Result<usize> {
let mut node = fs.node(self.block)?;
if node.1.uid == self.uid || self.uid == 0 {
node.1.mode = (node.1.mode & ! MODE_PERM) | (mode & MODE_PERM);
fs.write_at(node.0, &node.1)?;
Ok(0)
} else {
Err(Error::new(EPERM))
}
}
fn fchown(&mut self, uid: u32, gid: u32, fs: &mut FileSystem<D>) -> Result<usize> {
let mut node = fs.node(self.block)?;
if node.1.uid == self.uid || self.uid == 0 {
if uid as i32 != -1 {
node.1.uid = uid;
}
if gid as i32 != -1 {
node.1.gid = gid;
}
fs.write_at(node.0, &node.1)?;
Ok(0)
} else {
Err(Error::new(EPERM))
}
}
fn fcntl(&mut self, cmd: usize, arg: usize) -> Result<usize> {
match cmd {
F_GETFL => Ok(self.flags),
@@ -265,7 +338,7 @@ impl<D: Disk> Resource<D> for FileResource {
Ok(0)
}
} else {
Err(Error::new(EBADF))
Err(Error::new(EPERM))
}
}
}
+21 -3
View File
@@ -210,12 +210,12 @@ impl<D: Disk> Scheme for FileScheme<D> {
}
}
Box::new(DirResource::new(path.to_string(), node.0, Some(data)))
Box::new(DirResource::new(path.to_string(), node.0, Some(data), uid))
} else if flags & O_WRONLY == O_WRONLY {
// println!("{:X} & {:X}: EISDIR {}", flags, O_DIRECTORY, path);
return Err(Error::new(EISDIR));
} else {
Box::new(DirResource::new(path.to_string(), node.0, None))
Box::new(DirResource::new(path.to_string(), node.0, None, uid))
}
} else if node.1.is_symlink() && !(flags & O_STAT == O_STAT && flags & O_NOFOLLOW == O_NOFOLLOW) && flags & O_SYMLINK != O_SYMLINK {
let mut resolve_nodes = Vec::new();
@@ -287,7 +287,7 @@ impl<D: Disk> Scheme for FileScheme<D> {
fs.write_at(node.0, &node.1)?;
if dir {
Box::new(DirResource::new(path.to_string(), node.0, None))
Box::new(DirResource::new(path.to_string(), node.0, None, uid))
} else {
let seek = if flags & O_APPEND == O_APPEND {
fs.node_len(node.0)?
@@ -466,6 +466,24 @@ impl<D: Disk> Scheme for FileScheme<D> {
}
}
fn fchmod(&self, id: usize, mode: u16) -> Result<usize> {
let mut files = self.files.lock();
if let Some(file) = files.get_mut(&id) {
file.fchmod(mode, &mut self.fs.borrow_mut())
} else {
Err(Error::new(EBADF))
}
}
fn fchown(&self, id: usize, uid: u32, gid: u32) -> Result<usize> {
let mut files = self.files.lock();
if let Some(file) = files.get_mut(&id) {
file.fchown(uid, gid, &mut self.fs.borrow_mut())
} else {
Err(Error::new(EBADF))
}
}
fn fcntl(&self, id: usize, cmd: usize, arg: usize) -> Result<usize> {
let mut files = self.files.lock();
if let Some(file) = files.get_mut(&id) {