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

Commit ae3d73c

Browse files
committed
Introduce a less verbose, type safe, idiom for C strings.
Fixes #16
1 parent 6e3fa4a commit ae3d73c

File tree

8 files changed

+50
-25
lines changed

8 files changed

+50
-25
lines changed

src/chrdev.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,10 @@ use alloc::vec::Vec;
99
use crate::bindings;
1010
use crate::c_types;
1111
use crate::error::{Error, KernelResult};
12+
use crate::types::CStr;
1213
use crate::user_ptr::{UserSlicePtr, UserSlicePtrWriter};
1314

14-
pub fn builder(name: &'static str, minors: Range<u16>) -> KernelResult<Builder> {
15-
if !name.ends_with('\x00') {
16-
return Err(Error::EINVAL);
17-
}
18-
15+
pub fn builder(name: &'static CStr, minors: Range<u16>) -> KernelResult<Builder> {
1916
Ok(Builder {
2017
name,
2118
minors,
@@ -24,7 +21,7 @@ pub fn builder(name: &'static str, minors: Range<u16>) -> KernelResult<Builder>
2421
}
2522

2623
pub struct Builder {
27-
name: &'static str,
24+
name: &'static CStr,
2825
minors: Range<u16>,
2926
file_ops: Vec<&'static FileOperationsVtable>,
3027
}

src/filesystem.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use bitflags;
77
use crate::bindings;
88
use crate::c_types;
99
use crate::error;
10+
use crate::types::CStr;
1011

1112
pub struct FileSystemRegistration<T: FileSystem> {
1213
_phantom: marker::PhantomData<T>,
@@ -20,7 +21,7 @@ impl<T: FileSystem> Drop for FileSystemRegistration<T> {
2021
}
2122

2223
pub trait FileSystem {
23-
const NAME: &'static str;
24+
const NAME: &'static CStr;
2425
const FLAGS: FileSystemFlags;
2526
}
2627

@@ -56,9 +57,6 @@ extern "C" fn mount_callback<T: FileSystem>(
5657
}
5758

5859
pub fn register<T: FileSystem>() -> error::KernelResult<FileSystemRegistration<T>> {
59-
if !T::NAME.ends_with('\x00') {
60-
return Err(error::Error::EINVAL);
61-
}
6260
let mut fs_registration = FileSystemRegistration {
6361
ptr: Box::new(bindings::file_system_type {
6462
name: T::NAME.as_ptr() as *const i8,

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ mod types;
1717
pub mod user_ptr;
1818

1919
pub use crate::error::{Error, KernelResult};
20-
pub use crate::types::Mode;
20+
pub use crate::types::{CStr, Mode};
2121

2222
pub type _InitResult = c_types::c_int;
2323

src/sysctl.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,12 +118,12 @@ unsafe extern "C" fn proc_handler<T: SysctlStorage>(
118118

119119
impl<T: SysctlStorage> Sysctl<T> {
120120
pub fn register(
121-
path: &'static str,
122-
name: &'static str,
121+
path: &'static types::CStr,
122+
name: &'static types::CStr,
123123
storage: T,
124124
mode: types::Mode,
125125
) -> error::KernelResult<Sysctl<T>> {
126-
if !path.ends_with('\x00') || !name.ends_with('\x00') || name.contains('/') {
126+
if name.contains('/') {
127127
return Err(error::Error::EINVAL);
128128
}
129129

src/types.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use core::ops::Deref;
2+
13
use crate::bindings;
24

35
pub struct Mode(bindings::umode_t);
@@ -11,3 +13,30 @@ impl Mode {
1113
self.0
1214
}
1315
}
16+
17+
#[repr(transparent)]
18+
pub struct CStr(str);
19+
20+
impl CStr {
21+
pub fn new(data: &str) -> &CStr {
22+
if data.bytes().position(|b| b == b'\x00') != Some(data.len() - 1) {
23+
panic!("CStr must contain a single NUL byte at the end");
24+
}
25+
unsafe { &*(data as *const str as *const CStr) }
26+
}
27+
}
28+
29+
impl Deref for CStr {
30+
type Target = str;
31+
32+
fn deref(&self) -> &str {
33+
&self.0
34+
}
35+
}
36+
37+
#[macro_export]
38+
macro_rules! cstr {
39+
($str:expr) => {{
40+
$crate::CStr::new(concat!($str, "\x00"))
41+
}};
42+
}

tests/chrdev-region-allocation/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#![no_std]
22
#![feature(const_str_as_bytes)]
33

4-
use linux_kernel_module;
4+
use linux_kernel_module::{self, cstr};
55

66
struct ChrdevRegionAllocationTestModule {
77
_chrdev_reg: linux_kernel_module::chrdev::Registration,
@@ -10,7 +10,7 @@ struct ChrdevRegionAllocationTestModule {
1010
impl linux_kernel_module::KernelModule for ChrdevRegionAllocationTestModule {
1111
fn init() -> linux_kernel_module::KernelResult<Self> {
1212
let chrdev_reg =
13-
linux_kernel_module::chrdev::builder("chrdev-region-allocation-tests\x00", 0..1)?
13+
linux_kernel_module::chrdev::builder(cstr!("chrdev-region-allocation-tests"), 0..1)?
1414
.build()?;
1515

1616
Ok(ChrdevRegionAllocationTestModule {

tests/chrdev/src/lib.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#![no_std]
22
#![feature(const_str_as_bytes)]
33

4-
use linux_kernel_module;
4+
use linux_kernel_module::{self, cstr};
55

66
struct CycleFile;
77

@@ -30,9 +30,10 @@ struct ChrdevTestModule {
3030

3131
impl linux_kernel_module::KernelModule for ChrdevTestModule {
3232
fn init() -> linux_kernel_module::KernelResult<Self> {
33-
let chrdev_registration = linux_kernel_module::chrdev::builder("chrdev-tests\x00", 0..1)?
34-
.register_device::<CycleFile>()
35-
.build()?;
33+
let chrdev_registration =
34+
linux_kernel_module::chrdev::builder(cstr!("chrdev-tests"), 0..1)?
35+
.register_device::<CycleFile>()
36+
.build()?;
3637
Ok(ChrdevTestModule {
3738
_chrdev_registration: chrdev_registration,
3839
})

tests/sysctl/src/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
use core::sync::atomic::AtomicBool;
55

6-
use linux_kernel_module;
6+
use linux_kernel_module::{self, cstr};
77

88
use linux_kernel_module::sysctl::Sysctl;
99
use linux_kernel_module::Mode;
@@ -17,14 +17,14 @@ impl linux_kernel_module::KernelModule for SysctlTestModule {
1717
fn init() -> linux_kernel_module::KernelResult<Self> {
1818
Ok(SysctlTestModule {
1919
_sysctl_a: Sysctl::register(
20-
"rust/sysctl-tests\x00",
21-
"a\x00",
20+
cstr!("rust/sysctl-tests"),
21+
cstr!("a"),
2222
AtomicBool::new(false),
2323
Mode::from_int(0o666),
2424
)?,
2525
_sysctl_b: Sysctl::register(
26-
"rust/sysctl-tests\x00",
27-
"b\x00",
26+
cstr!("rust/sysctl-tests"),
27+
cstr!("b"),
2828
AtomicBool::new(false),
2929
Mode::from_int(0o666),
3030
)?,

0 commit comments

Comments
 (0)