redox/drivers/ahcid/src/scheme.rs
Jeremy Soller 224c43f761 Orbital (#16)
* Port previous ethernet scheme

* Add ipd

* Fix initfs rebuilds, use QEMU user networking addresses in ipd

* Add tcp/udp, netutils, dns, and network config

* Add fsync to network driver

* Add dns, router, subnet by default

* Fix e1000 driver. Make ethernet and IP non-blocking to avoid deadlocks

* Add orbital server, WIP

* Add futex

* Add orbutils and orbital

* Update libstd, orbutils, and orbital
Move ANSI key encoding to vesad

* Add orbital assets

* Update orbital

* Update to add login manager

* Add blocking primitives, block for most things except waitpid, update orbital

* Wait in waitpid and IRQ, improvements for other waits

* Fevent in root scheme

* WIP: Switch to using fevent

* Reorganize

* Event based e1000d driver

* Superuser-only access to some network schemes, display, and disk

* Superuser root and irq schemes

* Fix orbital
2016-10-13 17:21:42 -06:00

111 lines
3.5 KiB
Rust

use std::collections::BTreeMap;
use std::{cmp, str};
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use spin::Mutex;
use syscall::{Error, EACCES, EBADF, EINVAL, ENOENT, Result, Scheme, Stat, MODE_FILE, SEEK_CUR, SEEK_END, SEEK_SET};
use ahci::disk::Disk;
pub struct DiskScheme {
disks: Box<[Arc<Mutex<Disk>>]>,
handles: Mutex<BTreeMap<usize, (Arc<Mutex<Disk>>, usize)>>,
next_id: AtomicUsize
}
impl DiskScheme {
pub fn new(disks: Vec<Disk>) -> DiskScheme {
let mut disk_arcs = vec![];
for disk in disks {
disk_arcs.push(Arc::new(Mutex::new(disk)));
}
DiskScheme {
disks: disk_arcs.into_boxed_slice(),
handles: Mutex::new(BTreeMap::new()),
next_id: AtomicUsize::new(0)
}
}
}
impl Scheme for DiskScheme {
fn open(&self, path: &[u8], _flags: usize, uid: u32, _gid: u32) -> Result<usize> {
if uid == 0 {
let path_str = str::from_utf8(path).or(Err(Error::new(ENOENT)))?;
let i = path_str.parse::<usize>().or(Err(Error::new(ENOENT)))?;
if let Some(disk) = self.disks.get(i) {
let id = self.next_id.fetch_add(1, Ordering::SeqCst);
self.handles.lock().insert(id, (disk.clone(), 0));
Ok(id)
} else {
Err(Error::new(ENOENT))
}
} else {
Err(Error::new(EACCES))
}
}
fn dup(&self, id: usize) -> Result<usize> {
let mut handles = self.handles.lock();
let new_handle = {
let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
handle.clone()
};
let new_id = self.next_id.fetch_add(1, Ordering::SeqCst);
handles.insert(new_id, new_handle);
Ok(new_id)
}
fn fstat(&self, id: usize, stat: &mut Stat) -> Result<usize> {
let handles = self.handles.lock();
let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
stat.st_mode = MODE_FILE;
stat.st_size = handle.0.lock().size();
Ok(0)
}
fn read(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
let mut handles = self.handles.lock();
let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;
let mut disk = handle.0.lock();
let count = disk.read((handle.1 as u64)/512, buf)?;
handle.1 += count;
Ok(count)
}
fn write(&self, id: usize, buf: &[u8]) -> Result<usize> {
let mut handles = self.handles.lock();
let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;
let mut disk = handle.0.lock();
let count = disk.write((handle.1 as u64)/512, buf)?;
handle.1 += count;
Ok(count)
}
fn seek(&self, id: usize, pos: usize, whence: usize) -> Result<usize> {
let mut handles = self.handles.lock();
let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;
let len = handle.0.lock().size() as usize;
handle.1 = match whence {
SEEK_SET => cmp::min(len, pos),
SEEK_CUR => cmp::max(0, cmp::min(len as isize, handle.1 as isize + pos as isize)) as usize,
SEEK_END => cmp::max(0, cmp::min(len as isize, len as isize + pos as isize)) as usize,
_ => return Err(Error::new(EINVAL))
};
Ok(handle.1)
}
fn close(&self, id: usize) -> Result<usize> {
let mut handles = self.handles.lock();
handles.remove(&id).ok_or(Error::new(EBADF)).and(Ok(0))
}
}