Make most of the scheme work, except for deletion.
This commit is contained in:
Generated
-39
@@ -6,40 +6,10 @@ version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2889e6d50f394968c8bf4240dc3f2a7eb4680844d27308f798229ac9d4725f41"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
|
||||
|
||||
[[package]]
|
||||
name = "ramfs"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
@@ -50,12 +20,3 @@ source = "git+https://gitlab.redox-os.org/redox-os/syscall.git#8d0015be8693a81c2
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
@@ -8,4 +8,3 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
redox_syscall = { git = "https://gitlab.redox-os.org/redox-os/syscall.git" }
|
||||
bstr = "0.2"
|
||||
|
||||
+67
-10
@@ -1,18 +1,18 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::convert::TryInto;
|
||||
use std::ffi::OsStr;
|
||||
use std::fs;
|
||||
use std::{iter, fs, time};
|
||||
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
|
||||
use bstr::ByteSlice;
|
||||
|
||||
use syscall::{Error, Result, StatVfs, TimeSpec};
|
||||
use syscall::{Error, Result, StatVfs, TimeSpec, MODE_DIR};
|
||||
use syscall::error::{EACCES, EIO, ENFILE, ENOENT};
|
||||
use syscall::flag::{O_RDONLY, O_STAT};
|
||||
|
||||
use super::scheme::current_perm;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct File {
|
||||
pub mode: u16,
|
||||
pub uid: u32,
|
||||
@@ -30,11 +30,13 @@ pub struct File {
|
||||
pub data: FileData,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DirEntry {
|
||||
pub name: Vec<u8>,
|
||||
pub inode: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum FileData {
|
||||
File(Vec<u8>),
|
||||
Directory(Vec<DirEntry>),
|
||||
@@ -71,11 +73,30 @@ impl Filesystem {
|
||||
|
||||
pub fn new() -> Result<Self> {
|
||||
Ok(Self {
|
||||
files: BTreeMap::new(),
|
||||
files: iter::once((Self::ROOT_INODE, Self::create_root_inode())).collect(),
|
||||
memory_file: fs::File::open("memory:").or(Err(Error::new(EIO)))?,
|
||||
last_inode_number: Self::ROOT_INODE,
|
||||
})
|
||||
}
|
||||
fn create_root_inode() -> File {
|
||||
let cur_time = current_time();
|
||||
File {
|
||||
atime: cur_time,
|
||||
crtime: cur_time,
|
||||
ctime: cur_time,
|
||||
mtime: cur_time,
|
||||
|
||||
mode: MODE_DIR | 0o755,
|
||||
ino: Self::ROOT_INODE,
|
||||
nlink: 1,
|
||||
open_handles: 0,
|
||||
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
|
||||
data: FileData::Directory(Vec::new()),
|
||||
}
|
||||
}
|
||||
pub fn get_block_size(&self) -> Result<u32> {
|
||||
let mut statvfs = StatVfs::default();
|
||||
syscall::fstatvfs(self.memory_file.as_raw_fd() as usize, &mut statvfs)?;
|
||||
@@ -89,13 +110,19 @@ impl Filesystem {
|
||||
self.last_inode_number = next;
|
||||
Ok(next)
|
||||
}
|
||||
fn resolve_generic(&self, parts: Vec<&[u8]>, uid: u32, gid: u32) -> Result<usize> {
|
||||
fn resolve_generic(&self, mut parts: Vec<&[u8]>, uid: u32, gid: u32) -> Result<usize> {
|
||||
let mut current_file = self.files.get(&Self::ROOT_INODE).ok_or(Error::new(ENOENT))?;
|
||||
dbg!();
|
||||
let mut current_inode = Self::ROOT_INODE;
|
||||
|
||||
let mut i = 0;
|
||||
|
||||
while let Some(part) = parts.get(i) {
|
||||
loop {
|
||||
let part = match parts.get(i) {
|
||||
Some(p) => p,
|
||||
None => break,
|
||||
};
|
||||
dbg!(current_inode, part);
|
||||
let dentries = match current_file.data {
|
||||
FileData::Directory(ref dentries) => dentries,
|
||||
FileData::File(_) => return Err(Error::new(ENOENT)),
|
||||
@@ -106,12 +133,15 @@ impl Filesystem {
|
||||
if part == b"." || part == b".." {
|
||||
parts.remove(i);
|
||||
}
|
||||
|
||||
let part = parts.get(i).unwrap();
|
||||
if part == b".." {
|
||||
if i > 0 {
|
||||
i -= 1;
|
||||
parts.remove(i);
|
||||
}
|
||||
}
|
||||
let part = parts.get(i).unwrap();
|
||||
|
||||
let entry = dentries.iter().find(|dentry| &dentry.name == part).ok_or(Error::new(ENOENT))?;
|
||||
current_file = self.files.get(&entry.inode).ok_or(Error::new(EIO))?;
|
||||
@@ -121,10 +151,15 @@ impl Filesystem {
|
||||
}
|
||||
Ok(current_inode)
|
||||
}
|
||||
pub fn resolve_except_last<'a>(&self, mut path_bytes: &'a [u8], uid: u32, gid: u32) -> Result<(usize, &'a [u8])> {
|
||||
pub fn resolve_except_last<'a>(&self, mut path_bytes: &'a [u8], uid: u32, gid: u32) -> Result<(usize, Option<&'a [u8]>)> {
|
||||
if path_bytes.first() == Some(&b'/') { path_bytes = &path_bytes[1..] }
|
||||
let parts = path_components_iter(path_bytes).collect::<Vec<_>>();
|
||||
let last = parts.pop().ok_or(Error::new(ENOENT))?;
|
||||
let mut parts = path_components_iter(path_bytes).collect::<Vec<_>>();
|
||||
|
||||
let last = if parts.len() >= 1 {
|
||||
Some(parts.pop().unwrap())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok((self.resolve_generic(parts, uid, gid)?, last))
|
||||
}
|
||||
@@ -139,3 +174,25 @@ pub fn path_components_iter(bytes: &[u8]) -> impl Iterator<Item = &[u8]> + '_ {
|
||||
let components_iter = bytes.split(|c| c == &b'/');
|
||||
components_iter.filter(|item| !item.is_empty())
|
||||
}
|
||||
pub fn current_time() -> TimeSpec {
|
||||
let sys_time = time::SystemTime::now();
|
||||
|
||||
let duration = match sys_time.duration_since(time::SystemTime::UNIX_EPOCH) {
|
||||
Ok(d) => d,
|
||||
Err(e) => {
|
||||
eprintln!("Apparently the signed 32-bit integer has overflowed; the time is now before the Unix epoch...");
|
||||
|
||||
let negative_duration = e.duration();
|
||||
|
||||
return TimeSpec {
|
||||
tv_sec: negative_duration.as_secs().try_into().unwrap_or(i64::min_value()),
|
||||
tv_nsec: negative_duration.subsec_nanos().try_into().unwrap_or(i32::min_value()),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
TimeSpec {
|
||||
tv_sec: duration.as_secs().try_into().unwrap_or(i64::max_value()),
|
||||
tv_nsec: duration.subsec_nanos().try_into().unwrap_or(i32::max_value()),
|
||||
}
|
||||
}
|
||||
|
||||
+8
-5
@@ -2,7 +2,7 @@
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::env;
|
||||
use std::{env, io};
|
||||
|
||||
use syscall::{CloneFlags, Packet, SchemeMut};
|
||||
|
||||
@@ -13,26 +13,29 @@ use self::scheme::Scheme;
|
||||
|
||||
fn main() {
|
||||
let scheme_name = env::args().nth(1).expect("Usage:\n\tramfs SCHEME_NAME");
|
||||
let mut socket = File::create(format!(":{}", scheme_name)).expect("ramfs: failed to create socket");
|
||||
|
||||
if unsafe { syscall::clone(CloneFlags::empty()) }.expect("ramfs: failed to fork") != 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut socket = File::create(format!(":{}", scheme_name)).expect("ramfs: failed to create socket");
|
||||
let mut scheme = Scheme::new(scheme_name).expect("ramfs: failed to initialize scheme");
|
||||
|
||||
loop {
|
||||
'packet_loop: loop {
|
||||
let mut packet = Packet::default();
|
||||
|
||||
match socket.read(&mut packet) {
|
||||
Ok(0) => break,
|
||||
Ok(0) => break 'packet_loop,
|
||||
Ok(_) => (),
|
||||
Err(error) if error.kind() == io::ErrorKind::Interrupted => continue 'packet_loop,
|
||||
Err(error) => panic!("ramfs: failed to read from socket: {:?}", error),
|
||||
}
|
||||
|
||||
scheme.handle(&mut packet);
|
||||
|
||||
match socket.write(&packet) {
|
||||
Ok(0) => break,
|
||||
Ok(_) => (),
|
||||
Err(error) if error.kind() == io::ErrorKind::Interrupted => continue 'packet_loop,
|
||||
Err(error) => panic!("ramfs: failed to write to socket: {:?}", error),
|
||||
}
|
||||
}
|
||||
|
||||
+46
-49
@@ -1,14 +1,14 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::{cmp, ops, time};
|
||||
use std::{cmp, ops};
|
||||
|
||||
use syscall::{Error, EventFlags, Map, Result, SchemeMut, Stat, StatVfs, TimeSpec};
|
||||
use syscall::flag::{O_CREAT, O_EXCL, O_RDWR, O_RDONLY, O_WRONLY, O_DIRECTORY, O_STAT};
|
||||
use syscall::{MODE_DIR, MODE_PERM, MODE_TYPE, SEEK_CUR, SEEK_END, SEEK_SET};
|
||||
use syscall::error::{EACCES, EBADF, EBADFD, EEXIST, EFBIG, EINVAL, EISDIR, EIO, ENOENT, ENOMEM, ENOSYS, ENOTDIR, ENOTEMPTY, EOPNOTSUPP, EOVERFLOW};
|
||||
use syscall::flag::{O_ACCMODE, O_CREAT, O_EXCL, O_RDWR, O_RDONLY, O_WRONLY, O_DIRECTORY, O_STAT};
|
||||
use syscall::{MODE_FILE, MODE_DIR, MODE_PERM, MODE_TYPE, SEEK_CUR, SEEK_END, SEEK_SET};
|
||||
use syscall::error::{EACCES, EBADF, EBADFD, EEXIST, EINVAL, EISDIR, EIO, ENOMEM, ENOSYS, ENOTDIR, ENOTEMPTY, EOVERFLOW};
|
||||
|
||||
use crate::filesystem::{DirEntry, File, FileData, Filesystem};
|
||||
use crate::filesystem::{self, DirEntry, File, FileData, Filesystem};
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Handle {
|
||||
@@ -44,10 +44,11 @@ impl Scheme {
|
||||
pub fn remove_dentry(&mut self, path: &[u8], uid: u32, gid: u32, directory: bool) -> Result<usize> {
|
||||
let removed_entry = {
|
||||
let (parent_dir_inode, name_to_delete) = self.filesystem.resolve_except_last(path, uid, gid)?;
|
||||
let name_to_delete = name_to_delete.ok_or(Error::new(EINVAL))?; // can't remove root
|
||||
let parent = self.filesystem.files.get_mut(&parent_dir_inode).ok_or(Error::new(EIO))?;
|
||||
|
||||
let mode = current_perm(parent, uid, gid);
|
||||
if mode & 0o2 != 0 {
|
||||
if mode & 0o2 == 0 {
|
||||
return Err(Error::new(EACCES));
|
||||
}
|
||||
|
||||
@@ -89,43 +90,27 @@ impl Scheme {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn current_time() -> TimeSpec {
|
||||
let sys_time = time::SystemTime::now();
|
||||
|
||||
let duration = match sys_time.duration_since(time::SystemTime::UNIX_EPOCH) {
|
||||
Ok(d) => d,
|
||||
Err(e) => {
|
||||
eprintln!("Apparently the signed 32-bit integer has overflowed; the time is now before the Unix epoch...");
|
||||
|
||||
let negative_duration = e.duration();
|
||||
|
||||
return TimeSpec {
|
||||
tv_sec: negative_duration.as_secs().try_into().unwrap_or(i64::min_value()),
|
||||
tv_nsec: negative_duration.subsec_nanos().try_into().unwrap_or(i32::min_value()),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
TimeSpec {
|
||||
tv_sec: duration.as_secs().try_into().unwrap_or(i64::max_value()),
|
||||
tv_nsec: duration.subsec_nanos().try_into().unwrap_or(i32::max_value()),
|
||||
}
|
||||
}
|
||||
|
||||
impl SchemeMut for Scheme {
|
||||
fn open(&mut self, path: &[u8], flags: usize, uid: u32, gid: u32) -> Result<usize> {
|
||||
let handle = if flags & O_CREAT != 0 {
|
||||
if flags & O_EXCL != 0 && self.filesystem.resolve(path, 0, 0).is_ok() {
|
||||
return Err(Error::new(EEXIST))
|
||||
return Err(Error::new(EEXIST));
|
||||
}
|
||||
if flags & O_STAT != 0 { return Err(Error::new(EINVAL)) }
|
||||
|
||||
let (parent_dir_inode, new_name) = self.filesystem.resolve_except_last(path, uid, gid)?;
|
||||
let new_name = new_name.ok_or(Error::new(EINVAL))?; // cannot mkdir /
|
||||
|
||||
let current_time = current_time();
|
||||
let current_time = filesystem::current_time();
|
||||
|
||||
let new_inode_number = self.filesystem.next_inode_number()?;
|
||||
|
||||
let mut mode = (flags & 0xFFFF) as u16;
|
||||
|
||||
let new_inode = if flags & O_DIRECTORY != 0 {
|
||||
if mode & MODE_TYPE == 0 { mode |= MODE_DIR }
|
||||
if mode & MODE_TYPE != MODE_DIR { return Err(Error::new(EINVAL)) }
|
||||
|
||||
File {
|
||||
atime: current_time,
|
||||
crtime: current_time,
|
||||
@@ -134,12 +119,15 @@ impl SchemeMut for Scheme {
|
||||
gid,
|
||||
uid,
|
||||
ino: new_inode_number,
|
||||
mode: 0o755,
|
||||
mode,
|
||||
nlink: 2, // parent entry, "."
|
||||
data: FileData::Directory(Vec::new()),
|
||||
open_handles: 1,
|
||||
}
|
||||
} else {
|
||||
if mode & MODE_TYPE == 0 { mode |= MODE_FILE }
|
||||
if mode & MODE_TYPE == MODE_DIR { return Err(Error::new(EINVAL)) }
|
||||
|
||||
File {
|
||||
atime: current_time,
|
||||
crtime: current_time,
|
||||
@@ -148,7 +136,7 @@ impl SchemeMut for Scheme {
|
||||
gid,
|
||||
uid,
|
||||
ino: new_inode_number,
|
||||
mode: 0o644,
|
||||
mode,
|
||||
nlink: 1,
|
||||
data: FileData::File(Vec::new()),
|
||||
open_handles: 1,
|
||||
@@ -168,14 +156,13 @@ impl SchemeMut for Scheme {
|
||||
Handle {
|
||||
inode: new_inode_number,
|
||||
offset: 0,
|
||||
opened_as_read: flags & O_RDWR == O_RDONLY || flags & O_RDWR == O_RDWR,
|
||||
opened_as_write: flags & O_RDWR == O_WRONLY || flags & O_RDWR == O_RDWR,
|
||||
opened_as_read: flags & O_ACCMODE == O_RDONLY || flags & O_ACCMODE == O_RDWR,
|
||||
opened_as_write: flags & O_ACCMODE == O_WRONLY || flags & O_ACCMODE == O_RDWR,
|
||||
current_perm,
|
||||
}
|
||||
} else {
|
||||
let inode = self.filesystem.resolve(path, uid, gid)?;
|
||||
let file = self.filesystem.files.get_mut(&inode).ok_or(Error::new(ENOENT))?;
|
||||
|
||||
let file = self.filesystem.files.get_mut(&inode).ok_or(Error::new(EIO))?;
|
||||
if flags & O_STAT == 0 && flags & O_DIRECTORY != 0 && file.mode & MODE_TYPE != MODE_DIR {
|
||||
return Err(Error::new(ENOTDIR));
|
||||
}
|
||||
@@ -195,8 +182,8 @@ impl SchemeMut for Scheme {
|
||||
Handle {
|
||||
inode,
|
||||
offset: 0,
|
||||
opened_as_read: flags & O_RDWR == O_RDONLY || flags & O_RDWR == O_RDWR,
|
||||
opened_as_write: flags & O_RDWR == O_WRONLY || flags & O_RDWR == O_RDWR,
|
||||
opened_as_read: flags & O_ACCMODE == O_RDONLY || flags & O_ACCMODE == O_RDWR,
|
||||
opened_as_write: flags & O_ACCMODE == O_WRONLY || flags & O_ACCMODE == O_RDWR,
|
||||
current_perm,
|
||||
}
|
||||
};
|
||||
@@ -212,13 +199,15 @@ impl SchemeMut for Scheme {
|
||||
let inode_num = self.filesystem.resolve(path, uid, gid)?;
|
||||
let inode = self.filesystem.files.get_mut(&inode_num).ok_or(Error::new(EIO))?;
|
||||
|
||||
let cur_mode = inode.mode & MODE_TYPE;
|
||||
|
||||
if inode.uid != uid && uid != 0 {
|
||||
return Err(Error::new(EACCES));
|
||||
}
|
||||
if mode & MODE_TYPE != 0 {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
inode.mode = mode;
|
||||
inode.mode = mode | cur_mode;
|
||||
Ok(0)
|
||||
}
|
||||
fn rmdir(&mut self, path: &[u8], uid: u32, gid: u32) -> Result<usize> {
|
||||
@@ -251,6 +240,7 @@ impl SchemeMut for Scheme {
|
||||
}
|
||||
let bytes_to_read = cmp::min(bytes.len(), buf.len() + handle.offset) - handle.offset;
|
||||
buf[..bytes_to_read].copy_from_slice(&bytes[handle.offset..handle.offset + bytes_to_read]);
|
||||
handle.offset += bytes_to_read;
|
||||
Ok(bytes_to_read)
|
||||
}
|
||||
FileData::Directory(ref entries) => {
|
||||
@@ -269,14 +259,16 @@ impl SchemeMut for Scheme {
|
||||
continue;
|
||||
}
|
||||
|
||||
let bytes_to_read = cmp::min(entry_bytes.len() - bytes_to_skip, bytes_left_to_read);
|
||||
let bytes_to_read = cmp::min(entry_bytes.len() + 1 - bytes_to_skip, bytes_left_to_read);
|
||||
|
||||
let entry_bytes = &entry_bytes[bytes_to_skip..bytes_to_skip + bytes_to_read];
|
||||
let entry_bytes = &entry_bytes[bytes_to_skip..bytes_to_skip + bytes_to_read - 1];
|
||||
bytes_to_skip -= bytes_to_skip;
|
||||
|
||||
buf[handle.offset..handle.offset + bytes_to_read].copy_from_slice(&entry_bytes[..bytes_to_read]);
|
||||
buf[bytes_read..bytes_read + bytes_to_read - 1].copy_from_slice(&entry_bytes[..bytes_to_read - 1]);
|
||||
buf[bytes_read + bytes_to_read - 1] = b'\n';
|
||||
bytes_left_to_read -= bytes_to_read;
|
||||
bytes_read += bytes_to_read;
|
||||
handle.offset += bytes_read;
|
||||
}
|
||||
Ok(bytes_read)
|
||||
}
|
||||
@@ -308,6 +300,7 @@ impl SchemeMut for Scheme {
|
||||
// cast to isize, possibly making the offset negative
|
||||
let pos = pos as isize;
|
||||
|
||||
let old = handle.offset;
|
||||
handle.offset = match whence {
|
||||
SEEK_SET => cmp::max(0, pos) as usize,
|
||||
SEEK_CUR => cmp::max(0, pos + isize::try_from(handle.offset).or(Err(Error::new(EOVERFLOW)))?) as usize,
|
||||
@@ -320,11 +313,13 @@ impl SchemeMut for Scheme {
|
||||
let handle = self.handles.get_mut(&fd).ok_or(Error::new(EBADF))?;
|
||||
let file = self.filesystem.files.get_mut(&handle.inode).ok_or(Error::new(EBADFD))?;
|
||||
|
||||
let cur_type = file.mode & MODE_TYPE;
|
||||
|
||||
if mode & MODE_TYPE != 0 {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
|
||||
file.mode = mode;
|
||||
file.mode = mode | cur_type;
|
||||
|
||||
Ok(0)
|
||||
}
|
||||
@@ -379,6 +374,8 @@ impl SchemeMut for Scheme {
|
||||
let block_size = self.filesystem.block_size();
|
||||
let file = self.filesystem.files.get_mut(&handle.inode).ok_or(Error::new(EBADFD))?;
|
||||
|
||||
let size = file.data.size().try_into().or(Err(Error::new(EOVERFLOW)))?;
|
||||
|
||||
*stat = Stat {
|
||||
st_mode: file.mode,
|
||||
st_uid: file.uid,
|
||||
@@ -387,9 +384,9 @@ impl SchemeMut for Scheme {
|
||||
st_nlink: file.nlink.try_into().or(Err(Error::new(EOVERFLOW)))?,
|
||||
st_dev: 0,
|
||||
|
||||
st_size: file.data.size().try_into().or(Err(Error::new(EOVERFLOW)))?,
|
||||
st_size: size,
|
||||
st_blksize: block_size,
|
||||
st_blocks: div_round_up(stat.st_size, u64::from(stat.st_blksize)),
|
||||
st_blocks: div_round_up(size, u64::from(block_size)),
|
||||
|
||||
st_atime: file.atime.tv_sec.try_into().or(Err(Error::new(EOVERFLOW)))?,
|
||||
st_atime_nsec: file.atime.tv_nsec.try_into().or(Err(Error::new(EOVERFLOW)))?,
|
||||
@@ -483,11 +480,11 @@ pub fn current_perm(file: &crate::filesystem::File, uid: u32, gid: u32) -> u8 {
|
||||
}
|
||||
}
|
||||
fn check_permissions(flags: usize, single_mode: u8) -> Result<()> {
|
||||
if flags & O_RDWR == O_RDONLY && single_mode & 0o4 == 0 {
|
||||
if flags & O_ACCMODE == O_RDONLY && single_mode & 0o4 == 0 {
|
||||
return Err(Error::new(EACCES));
|
||||
} else if flags & O_RDWR == O_WRONLY && single_mode & 0o2 == 0 {
|
||||
} else if flags & O_ACCMODE == O_WRONLY && single_mode & 0o2 == 0 {
|
||||
return Err(Error::new(EACCES));
|
||||
} else if flags & O_RDWR == O_RDWR && single_mode & 0o6 != 0o6 {
|
||||
} else if flags & O_ACCMODE == O_RDWR && single_mode & 0o6 != 0o6 {
|
||||
return Err(Error::new(EACCES));
|
||||
}
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user