Positioned IO.

This commit is contained in:
4lDO2
2024-06-12 17:22:05 +02:00
parent a366841777
commit 0058d7c948
10 changed files with 166 additions and 331 deletions
Generated
+2 -2
View File
@@ -1100,7 +1100,7 @@ dependencies = [
[[package]]
name = "redox-scheme"
version = "0.2.0"
source = "git+https://gitlab.redox-os.org/4lDO2/redox-scheme.git?branch=schemev2#aeff1a7ef5d456679437551a910e5b22a213d8a7"
source = "git+https://gitlab.redox-os.org/4lDO2/redox-scheme.git?branch=schemev2plus#ca239589c873374a17715b637be1f9385345721c"
dependencies = [
"libredox 0.1.3",
"redox_syscall 0.5.1",
@@ -1137,7 +1137,7 @@ dependencies = [
[[package]]
name = "redox_syscall"
version = "0.5.1"
source = "git+https://gitlab.redox-os.org/4lDO2/syscall.git?branch=schemev2#ef3273b17114fe02848eaccf102119fc7fdd6056"
source = "git+https://gitlab.redox-os.org/4lDO2/syscall.git?branch=schemev2plus#b4f9a8952cec870ed7f457e3c15652d09aa0c9c7"
dependencies = [
"bitflags 2.5.0",
]
+1 -1
View File
@@ -47,4 +47,4 @@ lto = "fat"
mio = { git = "https://gitlab.redox-os.org/redox-os/mio.git", branch = "redox-unix" }
orbclient = { git = "https://gitlab.redox-os.org/redox-os/orbclient.git", version = "0.3.44" }
redox-daemon = { git = "https://gitlab.redox-os.org/redox-os/redox-daemon.git" }
redox_syscall = { git = "https://gitlab.redox-os.org/4lDO2/syscall.git", branch = "schemev2", features = ["std"] }
redox_syscall = { git = "https://gitlab.redox-os.org/4lDO2/syscall.git", branch = "schemev2plus", features = ["std"] }
+1 -1
View File
@@ -15,5 +15,5 @@ common = { path = "../../common" }
driver-block = { path = "../driver-block" }
pcid = { path = "../../pcid" }
libredox = "0.1.3"
redox-scheme = { git = "https://gitlab.redox-os.org/4lDO2/redox-scheme.git", branch = "schemev2" }
redox-scheme = { git = "https://gitlab.redox-os.org/4lDO2/redox-scheme.git", branch = "schemev2plus" }
redox_event = "0.4"
+44 -88
View File
@@ -1,12 +1,11 @@
use std::collections::BTreeMap;
use std::{cmp, str};
use std::str;
use std::fmt::Write;
use std::io::prelude::*;
use driver_block::{Disk, DiskWrapper};
use syscall::{
Error, EACCES, EBADF, EINVAL, EISDIR, ENOENT, ENOLCK, EOVERFLOW, Result, Io, Stat, MODE_DIR,
MODE_FILE, O_DIRECTORY, O_STAT, SEEK_CUR, SEEK_END, SEEK_SET,
MODE_FILE, O_DIRECTORY, O_STAT,
};
use redox_scheme::SchemeBlockMut;
@@ -14,9 +13,9 @@ use crate::ahci::hba::HbaMem;
#[derive(Clone)]
enum Handle {
List(Vec<u8>, usize), // Dir contents buffer, position
Disk(usize, usize), // Disk index, position
Partition(usize, u32, usize), // Disk index, partition index, position
List(Vec<u8>), // Dir contents buffer
Disk(usize), // Disk index
Partition(usize, u32), // Disk index, partition index
}
pub struct DiskScheme {
@@ -61,10 +60,10 @@ impl DiskScheme {
fn check_locks(&self, disk_i: usize, part_i_opt: Option<u32>) -> Result<()> {
for (_, handle) in self.handles.iter() {
match handle {
Handle::Disk(i, _) => if disk_i == *i {
Handle::Disk(i) => if disk_i == *i {
return Err(Error::new(ENOLCK));
},
Handle::Partition(i, p, _) => if disk_i == *i {
Handle::Partition(i, p) => if disk_i == *i {
match part_i_opt {
Some(part_i) => if part_i == *p {
return Err(Error::new(ENOLCK));
@@ -102,7 +101,7 @@ impl SchemeBlockMut for DiskScheme {
let id = self.next_id;
self.next_id += 1;
self.handles.insert(id, Handle::List(list.into_bytes(), 0));
self.handles.insert(id, Handle::List(list.into_bytes()));
Ok(Some(id))
} else {
Err(Error::new(EISDIR))
@@ -125,7 +124,7 @@ impl SchemeBlockMut for DiskScheme {
let id = self.next_id;
self.next_id += 1;
self.handles.insert(id, Handle::Partition(i, p, 0));
self.handles.insert(id, Handle::Partition(i, p));
Ok(Some(id))
} else {
Err(Error::new(ENOENT))
@@ -138,7 +137,7 @@ impl SchemeBlockMut for DiskScheme {
let id = self.next_id;
self.next_id += 1;
self.handles.insert(id, Handle::Disk(i, 0));
self.handles.insert(id, Handle::Disk(i));
Ok(Some(id))
} else {
Err(Error::new(ENOENT))
@@ -167,19 +166,19 @@ impl SchemeBlockMut for DiskScheme {
fn fstat(&mut self, id: usize, stat: &mut Stat) -> Result<Option<usize>> {
match *self.handles.get(&id).ok_or(Error::new(EBADF))? {
Handle::List(ref data, _) => {
Handle::List(ref data) => {
stat.st_mode = MODE_DIR;
stat.st_size = data.len() as u64;
Ok(Some(0))
},
Handle::Disk(number, _) => {
Handle::Disk(number) => {
let disk = self.disks.get_mut(number).ok_or(Error::new(EBADF))?;
stat.st_mode = MODE_FILE;
stat.st_size = disk.size();
stat.st_blksize = disk.block_length()?;
Ok(Some(0))
}
Handle::Partition(disk_id, part_num, _) => {
Handle::Partition(disk_id, part_num) => {
let disk = self.disks.get_mut(disk_id).ok_or(Error::new(EBADF))?;
let size = {
let pt = disk.pt.as_ref().ok_or(Error::new(EBADF))?;
@@ -215,8 +214,8 @@ impl SchemeBlockMut for DiskScheme {
}
match *handle {
Handle::List(_, _) => (),
Handle::Disk(number, _) => {
Handle::List(_) => (),
Handle::Disk(number) => {
let number_str = format!("{}", number);
let number_bytes = number_str.as_bytes();
j = 0;
@@ -226,7 +225,7 @@ impl SchemeBlockMut for DiskScheme {
j += 1;
}
}
Handle::Partition(disk_num, part_num, _) => {
Handle::Partition(disk_num, part_num) => {
let path = format!("{}p{}", disk_num, part_num);
let path_bytes = path.as_bytes();
j = 0;
@@ -241,71 +240,60 @@ impl SchemeBlockMut for DiskScheme {
Ok(Some(i))
}
fn read(&mut self, id: usize, buf: &mut [u8]) -> Result<Option<usize>> {
fn read(&mut self, id: usize, buf: &mut [u8], offset: u64, _fcntl_flags: u32) -> Result<Option<usize>> {
match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List(ref handle, ref mut size) => {
let count = (&handle[*size..]).read(buf).unwrap();
*size += count;
Ok(Some(count))
Handle::List(ref handle) => {
let src = usize::try_from(offset).ok().and_then(|o| handle.get(o..)).unwrap_or(&[]);
let byte_count = core::cmp::min(src.len(), buf.len());
buf[..byte_count].copy_from_slice(&src[..byte_count]);
Ok(Some(byte_count))
},
Handle::Disk(number, ref mut size) => {
Handle::Disk(number) => {
let disk = self.disks.get_mut(number).ok_or(Error::new(EBADF))?;
let blk_len = disk.block_length()?;
if let Some(count) = disk.read((*size as u64)/(blk_len as u64), buf)? {
*size += count;
Ok(Some(count))
} else {
Ok(None)
}
disk.read(offset / u64::from(blk_len), buf)
}
Handle::Partition(disk_num, part_num, ref mut position) => {
Handle::Partition(disk_num, part_num) => {
let disk = self.disks.get_mut(disk_num).ok_or(Error::new(EBADF))?;
let blksize = disk.block_length()?;
// validate that we're actually reading within the bounds of the partition
let rel_block = *position as u64 / blksize as u64;
let rel_block = offset / u64::from(blksize);
let abs_block = {
let pt = disk.pt.as_ref().ok_or(Error::new(EBADF))?;
let partition = pt.partitions.get(part_num as usize).ok_or(Error::new(EBADF))?;
let abs_block = partition.start_lba + rel_block;
// TODO: This shouldn't return EOVERFLOW?
if rel_block >= partition.size {
return Err(Error::new(EOVERFLOW));
}
abs_block
};
if let Some(count) = disk.read(abs_block, buf)? {
Ok(Some(count))
} else {
Ok(None)
}
disk.read(abs_block, buf)
}
}
}
fn write(&mut self, id: usize, buf: &[u8]) -> Result<Option<usize>> {
fn write(&mut self, id: usize, buf: &[u8], offset: u64, _fcntl_flags: u32) -> Result<Option<usize>> {
match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List(_, _) => {
Handle::List(_) => {
Err(Error::new(EBADF))
},
Handle::Disk(number, ref mut size) => {
Handle::Disk(number) => {
let disk = self.disks.get_mut(number).ok_or(Error::new(EBADF))?;
let blk_len = disk.block_length()?;
if let Some(count) = disk.write((*size as u64)/(blk_len as u64), buf)? {
*size += count;
Ok(Some(count))
} else {
Ok(None)
}
disk.write(offset / u64::from(blk_len), buf)
}
Handle::Partition(disk_num, part_num, ref mut position) => {
Handle::Partition(disk_num, part_num) => {
let disk = self.disks.get_mut(disk_num).ok_or(Error::new(EBADF))?;
let blksize = disk.block_length()?;
// validate that we're actually reading within the bounds of the partition
let rel_block = *position as u64 / blksize as u64;
let rel_block = offset / u64::from(blksize);
let abs_block = {
let pt = disk.pt.as_ref().ok_or(Error::new(EBADF))?;
@@ -318,56 +306,24 @@ impl SchemeBlockMut for DiskScheme {
abs_block
};
if let Some(count) = disk.write(abs_block, buf)? {
Ok(Some(count))
} else {
Ok(None)
}
disk.write(abs_block, buf)
}
}
}
fn seek(&mut self, id: usize, pos: isize, whence: usize) -> Result<Option<isize>> {
let pos = pos as usize;
match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List(ref mut handle, ref mut size) => {
let len = handle.len() as usize;
*size = match whence {
SEEK_SET => cmp::min(len, pos),
SEEK_CUR => cmp::max(0, cmp::min(len as isize, *size 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(Some(*size as isize))
},
Handle::Disk(number, ref mut size) => {
fn fsize(&mut self, id: usize) -> Result<Option<u64>> {
Ok(Some(match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List(ref mut handle) => handle.len() as u64,
Handle::Disk(number) => {
let disk = self.disks.get_mut(number).ok_or(Error::new(EBADF))?;
let len = disk.size() as usize;
*size = match whence {
SEEK_SET => cmp::min(len, pos),
SEEK_CUR => cmp::max(0, cmp::min(len as isize, *size 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(Some(*size as isize))
disk.size()
}
Handle::Partition(disk_num, part_num, ref mut position) => {
Handle::Partition(disk_num, part_num) => {
let disk = self.disks.get_mut(disk_num).ok_or(Error::new(EBADF))?;
let block_count = disk.pt.as_ref().ok_or(Error::new(EBADF))?.partitions.get(part_num as usize).ok_or(Error::new(EBADF))?.size;
let len = u64::from(disk.block_length()?) * block_count;
*position = match whence {
SEEK_SET => cmp::min(len as usize, pos) as usize, // Why isn't pos u64?
SEEK_CUR => cmp::max(0, cmp::min(len as isize, *position 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(Some(*position as isize))
u64::from(disk.block_length()?) * block_count
}
}
}))
}
fn close(&mut self, id: usize) -> Result<Option<usize>> {
+1 -1
View File
@@ -12,7 +12,7 @@ log = "0.4"
redox-daemon = "0.1"
redox-log = "0.1"
redox_syscall = { version = "0.5", features = ["std"] }
redox-scheme = { git = "https://gitlab.redox-os.org/4lDO2/redox-scheme.git", branch = "schemev2" }
redox-scheme = { git = "https://gitlab.redox-os.org/4lDO2/redox-scheme.git", branch = "schemev2plus" }
redox_event = "0.4"
partitionlib = { git = "https://gitlab.redox-os.org/redox-os/partitionlib.git" }
smallvec = "1"
+39 -98
View File
@@ -18,9 +18,9 @@ use partitionlib::{LogicalBlockSize, PartitionTable};
#[derive(Clone)]
enum Handle {
List(Vec<u8>, usize), // entries, offset
Disk(u32, usize), // disk num, offset
Partition(u32, u32, usize), // disk num, part num, offset
List(Vec<u8>), // entries
Disk(u32), // disk num
Partition(u32, u32), // disk num, part num
}
pub struct DiskWrapper {
@@ -163,10 +163,10 @@ impl DiskScheme {
fn check_locks(&self, disk_i: u32, part_i_opt: Option<u32>) -> Result<()> {
for (_, handle) in self.handles.iter() {
match handle {
Handle::Disk(i, _) => if disk_i == *i {
Handle::Disk(i) => if disk_i == *i {
return Err(Error::new(ENOLCK));
},
Handle::Partition(i, p, _) => if disk_i == *i {
Handle::Partition(i, p) => if disk_i == *i {
match part_i_opt {
Some(part_i) => if part_i == *p {
return Err(Error::new(ENOLCK));
@@ -205,7 +205,7 @@ impl SchemeBlockMut for DiskScheme {
let id = self.next_id;
self.next_id += 1;
self.handles.insert(id, Handle::List(list.into_bytes(), 0));
self.handles.insert(id, Handle::List(list.into_bytes()));
Ok(Some(id))
} else {
Err(Error::new(EISDIR))
@@ -235,7 +235,7 @@ impl SchemeBlockMut for DiskScheme {
let id = self.next_id;
self.next_id += 1;
self.handles
.insert(id, Handle::Partition(nsid, part_num, 0));
.insert(id, Handle::Partition(nsid, part_num));
Ok(Some(id))
} else {
Err(Error::new(ENOENT))
@@ -251,7 +251,7 @@ impl SchemeBlockMut for DiskScheme {
let id = self.next_id;
self.next_id += 1;
self.handles.insert(id, Handle::Disk(nsid, 0));
self.handles.insert(id, Handle::Disk(nsid));
Ok(Some(id))
} else {
Err(Error::new(ENOENT))
@@ -280,12 +280,12 @@ impl SchemeBlockMut for DiskScheme {
fn fstat(&mut self, id: usize, stat: &mut Stat) -> Result<Option<usize>> {
match *self.handles.get(&id).ok_or(Error::new(EBADF))? {
Handle::List(ref data, _) => {
Handle::List(ref data) => {
stat.st_mode = MODE_DIR;
stat.st_size = data.len() as u64;
Ok(Some(0))
}
Handle::Disk(number, _) => {
Handle::Disk(number) => {
let disk = self.disks.get_mut(&number).ok_or(Error::new(EBADF))?;
stat.st_mode = MODE_FILE;
stat.st_blocks = disk.as_ref().blocks;
@@ -297,7 +297,7 @@ impl SchemeBlockMut for DiskScheme {
stat.st_size = disk.as_ref().blocks * disk.as_ref().block_size;
Ok(Some(0))
}
Handle::Partition(disk_num, part_num, _) => {
Handle::Partition(disk_num, part_num) => {
let disk = self.disks.get_mut(&disk_num).ok_or(Error::new(EBADF))?;
let part = disk
.pt
@@ -338,8 +338,8 @@ impl SchemeBlockMut for DiskScheme {
}
match *handle {
Handle::List(_, _) => (),
Handle::Disk(number, _) => {
Handle::List(_) => (),
Handle::Disk(number) => {
let number_str = format!("{}", number);
let number_bytes = number_str.as_bytes();
j = 0;
@@ -349,7 +349,7 @@ impl SchemeBlockMut for DiskScheme {
j += 1;
}
}
Handle::Partition(disk_num, part_num, _) => {
Handle::Partition(disk_num, part_num) => {
let number_str = format!("{}p{}", disk_num, part_num);
let number_bytes = number_str.as_bytes();
j = 0;
@@ -364,24 +364,20 @@ impl SchemeBlockMut for DiskScheme {
Ok(Some(i))
}
fn read(&mut self, id: usize, buf: &mut [u8]) -> Result<Option<usize>> {
fn read(&mut self, id: usize, buf: &mut [u8], offset: u64, _fcntl_flags: u32) -> Result<Option<usize>> {
match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List(ref mut handle, ref mut size) => {
let count = (&handle[*size..]).read(buf).unwrap();
*size += count;
Handle::List(ref handle) => {
let src = usize::try_from(offset).ok().and_then(|o| handle.get(o..)).unwrap_or(&[]);
let count = core::cmp::min(src.len(), buf.len());
buf[..count].copy_from_slice(&src[..count]);
Ok(Some(count))
}
Handle::Disk(number, ref mut size) => {
Handle::Disk(number) => {
let disk = self.disks.get_mut(&number).ok_or(Error::new(EBADF))?;
let block_size = disk.as_ref().block_size;
if let Some(count) = self.nvme.namespace_read(disk.as_ref(), disk.as_ref().id, (*size as u64) / block_size, buf)? {
*size += count;
Ok(Some(count))
} else {
Ok(None)
}
self.nvme.namespace_read(disk.as_ref(), disk.as_ref().id, offset / block_size, buf)
}
Handle::Partition(disk_num, part_num, ref mut offset) => {
Handle::Partition(disk_num, part_num) => {
let disk = self.disks.get_mut(&disk_num).ok_or(Error::new(EBADF))?;
let part = disk
.pt
@@ -392,38 +388,27 @@ impl SchemeBlockMut for DiskScheme {
.ok_or(Error::new(EBADF))?;
let block_size = disk.as_ref().block_size;
let rel_block = (*offset as u64) / block_size;
let rel_block = offset / block_size;
if rel_block >= part.size {
return Err(Error::new(EOVERFLOW));
}
let abs_block = part.start_lba + rel_block;
if let Some(count) = self.nvme.namespace_read(disk.as_ref(), disk.as_ref().id, abs_block, buf)? {
*offset += count;
Ok(Some(count))
} else {
Ok(None)
}
self.nvme.namespace_read(disk.as_ref(), disk.as_ref().id, abs_block, buf)
}
}
}
fn write(&mut self, id: usize, buf: &[u8]) -> Result<Option<usize>> {
fn write(&mut self, id: usize, buf: &[u8], offset: u64, _fcntl_flags: u32) -> Result<Option<usize>> {
match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List(_, _) => Err(Error::new(EBADF)),
Handle::Disk(number, ref mut size) => {
Handle::List(_) => Err(Error::new(EBADF)),
Handle::Disk(number) => {
let disk = self.disks.get_mut(&number).ok_or(Error::new(EBADF))?;
let block_size = disk.as_ref().block_size;
if let Some(count) = self.nvme
.namespace_write(disk.as_ref(), disk.as_ref().id, (*size as u64) / block_size, buf)? {
*size += count;
Ok(Some(count))
} else {
Ok(None)
}
self.nvme.namespace_write(disk.as_ref(), disk.as_ref().id, offset / block_size, buf)
}
Handle::Partition(disk_num, part_num, ref mut offset) => {
Handle::Partition(disk_num, part_num) => {
let disk = self.disks.get_mut(&disk_num).ok_or(Error::new(EBADF))?;
let part = disk
.pt
@@ -434,57 +419,26 @@ impl SchemeBlockMut for DiskScheme {
.ok_or(Error::new(EBADF))?;
let block_size = disk.as_ref().block_size;
let rel_block = (*offset as u64) / block_size;
let rel_block = offset / block_size;
if rel_block >= part.size {
return Err(Error::new(EOVERFLOW));
}
let abs_block = part.start_lba + rel_block;
if let Some(count) = self.nvme.namespace_write(disk.as_ref(), disk.as_ref().id, abs_block, buf)? {
*offset += count;
Ok(Some(count))
} else {
Ok(None)
}
self.nvme.namespace_write(disk.as_ref(), disk.as_ref().id, abs_block, buf)
}
}
}
fn seek(&mut self, id: usize, pos: isize, whence: usize) -> Result<Option<isize>> {
match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List(ref mut handle, ref mut size) => {
let len = handle.len() as isize;
*size = match whence {
SEEK_SET => cmp::min(len, pos),
SEEK_CUR => {
cmp::max(0, cmp::min(len, *size as isize + pos))
}
SEEK_END => {
cmp::max(0, cmp::min(len, len + pos))
}
_ => return Err(Error::new(EINVAL)),
} as usize;
Ok(Some(*size as isize))
}
Handle::Disk(number, ref mut size) => {
fn fsize(&mut self, id: usize) -> Result<Option<u64>> {
Ok(Some(match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List(ref handle) => handle.len() as u64,
Handle::Disk(number) => {
let disk = self.disks.get_mut(&number).ok_or(Error::new(EBADF))?;
let len = (disk.as_ref().blocks * disk.as_ref().block_size) as isize;
*size = match whence {
SEEK_SET => cmp::min(len, pos),
SEEK_CUR => {
cmp::max(0, cmp::min(len, *size as isize + pos))
}
SEEK_END => {
cmp::max(0, cmp::min(len, len + pos))
}
_ => return Err(Error::new(EINVAL)),
} as usize;
Ok(Some(*size as isize))
disk.as_ref().blocks * disk.as_ref().block_size
}
Handle::Partition(disk_num, part_num, ref mut size) => {
Handle::Partition(disk_num, part_num) => {
let disk = self.disks.get_mut(&disk_num).ok_or(Error::new(EBADF))?;
let part = disk
.pt
@@ -494,22 +448,9 @@ impl SchemeBlockMut for DiskScheme {
.get(part_num as usize)
.ok_or(Error::new(EBADF))?;
let len = (part.size * disk.as_ref().block_size) as isize;
*size = match whence {
SEEK_SET => cmp::min(len, pos),
SEEK_CUR => {
cmp::max(0, cmp::min(len, *size as isize + pos))
}
SEEK_END => {
cmp::max(0, cmp::min(len, len + pos))
}
_ => return Err(Error::new(EINVAL)),
} as usize;
Ok(Some(*size as isize))
part.size * disk.as_ref().block_size
}
}
}))
}
fn close(&mut self, id: usize) -> Result<Option<usize>> {
+2 -2
View File
@@ -2,7 +2,7 @@
name = "usbscsid"
version = "0.1.0"
authors = ["4lDO2 <4lDO2@protonmail.com>"]
edition = "2018"
edition = "2021"
license = "MIT"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -13,6 +13,6 @@ libredox = "0.1.3"
plain = "0.2"
redox-daemon = "0.1"
redox_syscall = { version = "0.5", features = ["std"] }
redox-scheme = { git = "https://gitlab.redox-os.org/4lDO2/redox-scheme.git", branch = "schemev2" }
redox-scheme = { git = "https://gitlab.redox-os.org/4lDO2/redox-scheme.git", branch = "schemev2plus" }
thiserror = "1"
xhcid = { path = "../../xhcid" }
+42 -62
View File
@@ -15,9 +15,9 @@ use syscall::flag::{SEEK_CUR, SEEK_END, SEEK_SET};
const LIST_CONTENTS: &'static [u8] = b"0\n";
enum Handle {
List(usize),
Disk(usize),
//Partition(usize, u32, usize),
List,
Disk,
//Partition(usize, u32),
}
pub struct ScsiScheme<'a> {
@@ -50,12 +50,12 @@ impl SchemeMut for ScsiScheme<'_> {
.trim_start_matches('/');
let handle = if path_str.is_empty() {
// List
Handle::List(0)
Handle::List
} else if let Some(_p_pos) = path_str.chars().position(|c| c == 'p') {
// TODO: Partitions.
return Err(Error::new(ENOSYS));
} else {
Handle::Disk(0)
Handle::Disk
};
self.next_fd += 1;
self.handles.insert(self.next_fd, handle);
@@ -63,13 +63,13 @@ impl SchemeMut for ScsiScheme<'_> {
}
fn fstat(&mut self, fd: usize, stat: &mut syscall::Stat) -> Result<usize> {
match self.handles.get(&fd).ok_or(Error::new(EBADF))? {
Handle::Disk(_) => {
Handle::Disk => {
stat.st_mode = MODE_CHR;
stat.st_size = self.scsi.get_disk_size();
stat.st_blksize = self.scsi.block_size;
stat.st_blocks = self.scsi.block_count;
}
Handle::List(_) => {
Handle::List => {
stat.st_mode = MODE_DIR;
stat.st_size = LIST_CONTENTS.len() as u64;
}
@@ -78,84 +78,64 @@ impl SchemeMut for ScsiScheme<'_> {
}
fn fpath(&mut self, fd: usize, buf: &mut [u8]) -> Result<usize> {
let path = match self.handles.get_mut(&fd).ok_or(Error::new(EBADF))? {
Handle::Disk(_) => "0",
Handle::List(_) => "",
Handle::Disk => "0",
Handle::List => "",
}
.as_bytes();
let min = std::cmp::min(path.len(), buf.len());
buf[..min].copy_from_slice(&path[..min]);
Ok(min)
}
fn seek(&mut self, fd: usize, pos: isize, whence: usize) -> Result<isize> {
match self.handles.get_mut(&fd).ok_or(Error::new(EBADF))? {
Handle::Disk(ref mut offset) => {
let len = self.scsi.get_disk_size() as isize;
*offset = match whence {
SEEK_SET => cmp::max(0, cmp::min(pos, len)),
SEEK_CUR => cmp::max(0, cmp::min(*offset as isize + pos, len)),
SEEK_END => cmp::max(0, cmp::min(len + pos, len)),
_ => return Err(Error::new(EINVAL)),
} as usize;
Ok(*offset as isize)
}
Handle::List(ref mut offset) => {
let len = LIST_CONTENTS.len() as isize;
*offset = match whence {
SEEK_SET => cmp::max(0, cmp::min(pos, len)),
SEEK_CUR => cmp::max(0, cmp::min(*offset as isize + pos, len)),
SEEK_END => cmp::max(0, cmp::min(len + pos, len)),
_ => return Err(Error::new(EINVAL)),
} as usize;
Ok(*offset as isize)
}
}
fn fsize(&mut self, fd: usize) -> Result<u64> {
Ok(match self.handles.get_mut(&fd).ok_or(Error::new(EBADF))? {
Handle::Disk => self.scsi.get_disk_size(),
Handle::List => LIST_CONTENTS.len() as u64,
})
}
fn read(&mut self, fd: usize, buf: &mut [u8]) -> Result<usize> {
fn read(&mut self, fd: usize, buf: &mut [u8], offset: u64, _fcntl_flags: u32) -> Result<usize> {
match self.handles.get_mut(&fd).ok_or(Error::new(EBADF))? {
Handle::Disk(ref mut offset) => {
if *offset as u64 % u64::from(self.scsi.block_size) != 0
Handle::Disk => {
if offset % u64::from(self.scsi.block_size) != 0
|| buf.len() as u64 % u64::from(self.scsi.block_size) != 0
{
return Err(Error::new(EINVAL));
}
let lba = *offset as u64 / u64::from(self.scsi.block_size);
let bytes_read = self
.scsi
.read(self.protocol, lba, buf)
.map_err(|err| dbg!(err))
.or(Err(Error::new(EIO)))?;
*offset += bytes_read as usize;
Ok(bytes_read as usize)
let lba = offset / u64::from(self.scsi.block_size);
match self.scsi.read(self.protocol, lba, buf) {
Ok(bytes_read) => Ok(bytes_read as usize),
Err(err) => {
eprintln!("usbscsid: READ IO ERROR: {err}");
Err(Error::new(EIO))
}
}
}
Handle::List(ref mut offset) => {
let max_bytes_to_read = cmp::min(LIST_CONTENTS.len(), buf.len());
let bytes_to_read = cmp::max(max_bytes_to_read, *offset) - *offset;
Handle::List => {
let src = usize::try_from(offset).ok().and_then(|o| LIST_CONTENTS.get(o..)).unwrap_or(&[]);
let min = core::cmp::min(src.len(), buf.len());
buf[..min].copy_from_slice(&src[..min]);
buf[..bytes_to_read].copy_from_slice(&LIST_CONTENTS[..bytes_to_read]);
*offset += bytes_to_read;
Ok(bytes_to_read)
Ok(min)
}
}
}
fn write(&mut self, fd: usize, buf: &[u8]) -> Result<usize> {
fn write(&mut self, fd: usize, buf: &[u8], offset: u64, _fcntl_flags: u32) -> Result<usize> {
match self.handles.get_mut(&fd).ok_or(Error::new(EBADF))? {
Handle::Disk(ref mut offset) => {
if *offset as u64 % u64::from(self.scsi.block_size) != 0
Handle::Disk => {
if offset % u64::from(self.scsi.block_size) != 0
|| buf.len() as u64 % u64::from(self.scsi.block_size) != 0
{
return Err(Error::new(EINVAL));
}
let lba = *offset as u64 / u64::from(self.scsi.block_size);
let bytes_written = self
.scsi
.write(self.protocol, lba, buf)
.map_err(|err| dbg!(err))
.or(Err(Error::new(EIO)))?;
*offset += bytes_written as usize;
Ok(bytes_written as usize)
let lba = offset / u64::from(self.scsi.block_size);
match self.scsi.write(self.protocol, lba, buf) {
Ok(bytes_written) => Ok(bytes_written as usize),
Err(err) => {
eprintln!("usbscsid: WRITE IO ERROR: {err}");
Err(Error::new(EIO))
}
}
}
Handle::List(_) => Err(Error::new(EBADF)),
Handle::List => Err(Error::new(EBADF)),
}
}
}
+1 -1
View File
@@ -15,7 +15,7 @@ spin = "*"
redox-daemon = "0.1"
redox-log = "0.1"
redox_syscall = { version = "0.5", features = ["std"] }
redox-scheme = { git = "https://gitlab.redox-os.org/4lDO2/redox-scheme.git", branch = "schemev2" }
redox-scheme = { git = "https://gitlab.redox-os.org/4lDO2/redox-scheme.git", branch = "schemev2plus" }
partitionlib = { git = "https://gitlab.redox-os.org/redox-os/partitionlib.git" }
common = { path = "../../common" }
+33 -75
View File
@@ -84,18 +84,13 @@ pub enum Handle {
Partition {
/// Partition Number
number: u32,
/// Offset in bytes
offset: usize,
},
List {
entries: Vec<u8>,
offset: usize,
},
Disk {
offset: usize,
},
Disk,
}
pub struct DiskScheme<'a> {
@@ -224,7 +219,6 @@ impl<'a> SchemeBlockMut for DiskScheme<'a> {
id,
Handle::List {
entries: list.into_bytes(),
offset: 0,
},
);
@@ -250,7 +244,6 @@ impl<'a> SchemeBlockMut for DiskScheme<'a> {
id,
Handle::Partition {
number: part_num,
offset: 0,
},
);
@@ -261,25 +254,24 @@ impl<'a> SchemeBlockMut for DiskScheme<'a> {
let id = self.next_id;
self.next_id += 1;
self.handles.insert(id, Handle::Disk { offset: 0 });
self.handles.insert(id, Handle::Disk);
Ok(Some(id))
}
}
fn read(&mut self, id: usize, buf: &mut [u8]) -> syscall::Result<Option<usize>> {
match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
fn read(&mut self, id: usize, buf: &mut [u8], offset: u64, _fcntl_flags: u32) -> syscall::Result<Option<usize>> {
Ok(Some(match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List {
ref mut entries,
ref mut offset,
} => {
let count = (&entries[*offset..]).read(buf).unwrap();
*offset += count;
Ok(Some(count))
let src = usize::try_from(offset).ok().and_then(|o| entries.get(o..)).unwrap_or(&[]);
let count = core::cmp::min(src.len(), buf.len());
buf[..count].copy_from_slice(&src[..count]);
count
}
Handle::Partition {
number,
ref mut offset,
} => {
let part_table = self.part_table.as_ref().unwrap();
let part = part_table
@@ -288,68 +280,52 @@ impl<'a> SchemeBlockMut for DiskScheme<'a> {
.ok_or(Error::new(EBADF))?;
// Get the offset in sectors.
let rel_block = (*offset as u64) / BLK_SIZE;
let rel_block = offset / BLK_SIZE;
// if rel_block >= part.size {
// return Err(Error::new(EOVERFLOW));
// }
let abs_block = part.start_lba + rel_block;
let count = futures::executor::block_on(self.queue.read(abs_block, buf));
*offset += count;
Ok(Some(count))
futures::executor::block_on(self.queue.read(abs_block, buf))
}
Handle::Disk { ref mut offset } => {
Handle::Disk => {
let block_size = self.cfg.block_size();
let count = futures::executor::block_on(
self.queue.read((*offset as u64) / block_size as u64, buf),
);
*offset += count;
Ok(Some(count))
futures::executor::block_on(
self.queue.read(offset / u64::from(block_size), buf),
)
}
}
}))
}
fn write(&mut self, id: usize, buf: &[u8]) -> syscall::Result<Option<usize>> {
match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::Disk { ref mut offset } => {
fn write(&mut self, id: usize, buf: &[u8], offset: u64, _fcntl_flags: u32) -> syscall::Result<Option<usize>> {
Ok(Some(match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::Disk => {
let block_size = self.cfg.block_size();
let count = futures::executor::block_on(
self.queue.write((*offset as u64) / block_size as u64, buf),
);
*offset += count;
Ok(Some(count))
futures::executor::block_on(
self.queue.write(offset / u64::from(block_size), buf),
)
}
_ => unimplemented!(),
}
_ => todo!(),
}))
}
fn seek(&mut self, id: usize, pos: isize, whence: usize) -> syscall::Result<Option<isize>> {
match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
fn fsize(&mut self, id: usize) -> syscall::Result<Option<u64>> {
Ok(Some(match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List {
ref entries,
ref mut offset,
} => {
let len = entries.len() as isize;
log::debug!("list: whence={whence:?} pos={pos:?} part_len={len:?}");
let len = entries.len() as u64;
log::debug!("list: part_len={len:?}");
*offset = match whence {
SEEK_SET => cmp::min(len, pos),
SEEK_CUR => cmp::max(0, cmp::min(len, *offset as isize + pos)),
SEEK_END => cmp::max(0, cmp::min(len, len + pos)),
_ => return Err(Error::new(EINVAL)),
} as usize;
Ok(Some(*offset as isize))
len
}
Handle::Partition {
number,
ref mut offset,
} => {
let part_table = self.part_table.as_ref().unwrap();
let part = part_table
@@ -358,33 +334,15 @@ impl<'a> SchemeBlockMut for DiskScheme<'a> {
.ok_or(Error::new(EBADF))?;
// Partition size in bytes.
let len = (part.size * BLK_SIZE) as isize;
let len = part.size * BLK_SIZE;
log::debug!("part: whence={whence:?} pos={pos:?} part_len={len:?}");
log::debug!("part: part_len={len:?}");
*offset = match whence {
SEEK_SET => cmp::min(len, pos),
SEEK_CUR => cmp::max(0, cmp::min(len, *offset as isize + pos)),
SEEK_END => cmp::max(0, cmp::min(len, len + pos)),
_ => return Err(Error::new(EINVAL)),
} as usize;
Ok(Some(*offset as isize))
len
}
Handle::Disk { ref mut offset } => {
let len = (self.cfg.capacity() * self.cfg.block_size() as u64) as isize;
*offset = match whence {
SEEK_SET => cmp::min(len, pos),
SEEK_CUR => cmp::max(0, cmp::min(len, *offset as isize + pos)),
SEEK_END => cmp::max(0, cmp::min(len, len + pos)),
_ => return Err(Error::new(EINVAL)),
} as usize;
Ok(Some(*offset as isize))
}
}
Handle::Disk => self.cfg.capacity() * u64::from(self.cfg.block_size()),
}))
}
fn fpath(&mut self, _id: usize, _buf: &mut [u8]) -> syscall::Result<Option<usize>> {