Skip to content
This repository was archived by the owner on Mar 7, 2021. It is now read-only.

Commit 5416d8f

Browse files
committed
chrdev: Pass offset to read
1 parent 7ec8032 commit 5416d8f

File tree

3 files changed

+51
-9
lines changed

3 files changed

+51
-9
lines changed

src/chrdev.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use core::convert::TryInto;
1+
use core::convert::{TryFrom, TryInto};
22
use core::ops::Range;
33
use core::{mem, ptr};
44

@@ -139,17 +139,22 @@ unsafe extern "C" fn read_callback<T: FileOperations>(
139139
) -> c_types::c_ssize_t {
140140
let mut data = match UserSlicePtr::new(buf as *mut c_types::c_void, len) {
141141
Ok(ptr) => ptr.writer(),
142-
Err(e) => return e.to_kernel_errno() as c_types::c_ssize_t,
142+
Err(e) => return e.to_kernel_errno().try_into().unwrap(),
143143
};
144144
let f = &*((*file).private_data as *const T);
145-
// TODO: Pass offset to read()?
146-
match f.read(&mut data) {
145+
// No FMODE_UNSIGNED_OFFSET support, so offset must be in [0, 2^63).
146+
// See discussion in #113
147+
let positive_offset = match (*offset).try_into() {
148+
Ok(v) => v,
149+
Err(_) => return Error::EINVAL.to_kernel_errno().try_into().unwrap(),
150+
};
151+
match f.read(&mut data, positive_offset) {
147152
Ok(()) => {
148153
let written = len - data.len();
149-
(*offset) += written as bindings::loff_t;
150-
written as c_types::c_ssize_t
154+
(*offset) += bindings::loff_t::try_from(written).unwrap();
155+
written.try_into().unwrap()
151156
}
152-
Err(e) => e.to_kernel_errno() as c_types::c_ssize_t,
157+
Err(e) => e.to_kernel_errno().try_into().unwrap(),
153158
}
154159
}
155160

@@ -236,7 +241,7 @@ pub trait FileOperations: Sync + Sized {
236241
const VTABLE: FileOperationsVtable;
237242

238243
fn open() -> KernelResult<Self>;
239-
fn read(&self, _buf: &mut UserSlicePtrWriter) -> KernelResult<()> {
244+
fn read(&self, _buf: &mut UserSlicePtrWriter, _offset: u64) -> KernelResult<()> {
240245
Err(Error::EINVAL)
241246
}
242247
fn seek(&self, _file: &File, _offset: SeekFrom) -> KernelResult<u64> {

tests/chrdev/src/lib.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,14 @@ impl linux_kernel_module::chrdev::FileOperations for CycleFile {
1616
fn read(
1717
&self,
1818
buf: &mut linux_kernel_module::user_ptr::UserSlicePtrWriter,
19+
offset: u64,
1920
) -> linux_kernel_module::KernelResult<()> {
20-
for c in b"123456789".iter().cycle().take(buf.len()) {
21+
for c in b"123456789"
22+
.iter()
23+
.cycle()
24+
.skip((offset % 9) as _)
25+
.take(buf.len())
26+
{
2127
buf.write(&[*c])?;
2228
}
2329
return Ok(());

tests/chrdev/tests/tests.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::fs;
22
use std::io::{Read, Seek, SeekFrom};
3+
use std::os::unix::prelude::FileExt;
34
use std::path::PathBuf;
45
use std::process::Command;
56

@@ -78,6 +79,36 @@ fn test_read() {
7879
});
7980
}
8081

82+
#[test]
83+
fn test_read_offset() {
84+
with_kernel_module(|| {
85+
let device_number = get_device_major_number();
86+
let p = temporary_file_path();
87+
let _u = mknod(&p, device_number, READ_FILE_MINOR);
88+
89+
let mut f = fs::File::open(&p).unwrap();
90+
let mut data = [0; 5];
91+
f.read_exact(&mut data).unwrap();
92+
assert_eq!(&data, b"12345");
93+
f.read_exact(&mut data).unwrap();
94+
assert_eq!(&data, b"67891");
95+
});
96+
}
97+
98+
#[test]
99+
fn test_read_at() {
100+
with_kernel_module(|| {
101+
let device_number = get_device_major_number();
102+
let p = temporary_file_path();
103+
let _u = mknod(&p, device_number, READ_FILE_MINOR);
104+
105+
let f = fs::File::open(&p).unwrap();
106+
let mut data = [0; 5];
107+
f.read_exact_at(&mut data, 7).unwrap();
108+
assert_eq!(&data, b"89123");
109+
});
110+
}
111+
81112
#[test]
82113
fn test_read_unimplemented() {
83114
with_kernel_module(|| {

0 commit comments

Comments
 (0)