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

Commit

Permalink
Introduce a less verbose, type safe, idiom for C strings.
Browse files Browse the repository at this point in the history
Fixes #16
  • Loading branch information
alex committed Aug 20, 2019
1 parent 6e3fa4a commit e008586
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 25 deletions.
9 changes: 3 additions & 6 deletions src/chrdev.rs
Expand Up @@ -9,13 +9,10 @@ use alloc::vec::Vec;
use crate::bindings;
use crate::c_types;
use crate::error::{Error, KernelResult};
use crate::types::CStr;
use crate::user_ptr::{UserSlicePtr, UserSlicePtrWriter};

pub fn builder(name: &'static str, minors: Range<u16>) -> KernelResult<Builder> {
if !name.ends_with('\x00') {
return Err(Error::EINVAL);
}

pub fn builder(name: &'static CStr, minors: Range<u16>) -> KernelResult<Builder> {
Ok(Builder {
name,
minors,
Expand All @@ -24,7 +21,7 @@ pub fn builder(name: &'static str, minors: Range<u16>) -> KernelResult<Builder>
}

pub struct Builder {
name: &'static str,
name: &'static CStr,
minors: Range<u16>,
file_ops: Vec<&'static FileOperationsVtable>,
}
Expand Down
6 changes: 2 additions & 4 deletions src/filesystem.rs
Expand Up @@ -7,6 +7,7 @@ use bitflags;
use crate::bindings;
use crate::c_types;
use crate::error;
use crate::types::CStr;

pub struct FileSystemRegistration<T: FileSystem> {
_phantom: marker::PhantomData<T>,
Expand All @@ -20,7 +21,7 @@ impl<T: FileSystem> Drop for FileSystemRegistration<T> {
}

pub trait FileSystem {
const NAME: &'static str;
const NAME: &'static CStr;
const FLAGS: FileSystemFlags;
}

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

pub fn register<T: FileSystem>() -> error::KernelResult<FileSystemRegistration<T>> {
if !T::NAME.ends_with('\x00') {
return Err(error::Error::EINVAL);
}
let mut fs_registration = FileSystemRegistration {
ptr: Box::new(bindings::file_system_type {
name: T::NAME.as_ptr() as *const i8,
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Expand Up @@ -17,7 +17,7 @@ mod types;
pub mod user_ptr;

pub use crate::error::{Error, KernelResult};
pub use crate::types::Mode;
pub use crate::types::{CStr, Mode};

pub type _InitResult = c_types::c_int;

Expand Down
6 changes: 3 additions & 3 deletions src/sysctl.rs
Expand Up @@ -118,12 +118,12 @@ unsafe extern "C" fn proc_handler<T: SysctlStorage>(

impl<T: SysctlStorage> Sysctl<T> {
pub fn register(
path: &'static str,
name: &'static str,
path: &'static types::CStr,
name: &'static types::CStr,
storage: T,
mode: types::Mode,
) -> error::KernelResult<Sysctl<T>> {
if !path.ends_with('\x00') || !name.ends_with('\x00') || name.contains('/') {
if name.contains('/') {
return Err(error::Error::EINVAL);
}

Expand Down
29 changes: 29 additions & 0 deletions src/types.rs
@@ -1,3 +1,5 @@
use core::ops::Deref;

use crate::bindings;

pub struct Mode(bindings::umode_t);
Expand All @@ -11,3 +13,30 @@ impl Mode {
self.0
}
}

#[repr(transparent)]
pub struct CStr(str);

impl CStr {
pub fn new(data: &str) -> &CStr {
if data.bytes().position(|b| b == b'\x00') != Some(data.len() - 1) {
panic!("CStr must contain a single NUL byte at the end");
}
unsafe { &*(data as *const str as *const CStr) }
}
}

impl Deref for CStr {
type Target = str;

fn deref(&self) -> &str {
&self.0
}
}

#[macro_export]
macro_rules! cstr {
($str:expr) => {{
$crate::CStr::new(concat!($str, "\x00"))
}};
}
4 changes: 2 additions & 2 deletions tests/chrdev-region-allocation/src/lib.rs
@@ -1,7 +1,7 @@
#![no_std]
#![feature(const_str_as_bytes)]

use linux_kernel_module;
use linux_kernel_module::{self, cstr};

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

Ok(ChrdevRegionAllocationTestModule {
Expand Down
9 changes: 5 additions & 4 deletions tests/chrdev/src/lib.rs
@@ -1,7 +1,7 @@
#![no_std]
#![feature(const_str_as_bytes)]

use linux_kernel_module;
use linux_kernel_module::{self, cstr};

struct CycleFile;

Expand Down Expand Up @@ -30,9 +30,10 @@ struct ChrdevTestModule {

impl linux_kernel_module::KernelModule for ChrdevTestModule {
fn init() -> linux_kernel_module::KernelResult<Self> {
let chrdev_registration = linux_kernel_module::chrdev::builder("chrdev-tests\x00", 0..1)?
.register_device::<CycleFile>()
.build()?;
let chrdev_registration =
linux_kernel_module::chrdev::builder(cstr!("chrdev-tests"), 0..1)?
.register_device::<CycleFile>()
.build()?;
Ok(ChrdevTestModule {
_chrdev_registration: chrdev_registration,
})
Expand Down
10 changes: 5 additions & 5 deletions tests/sysctl/src/lib.rs
Expand Up @@ -3,7 +3,7 @@

use core::sync::atomic::AtomicBool;

use linux_kernel_module;
use linux_kernel_module::{self, cstr};

use linux_kernel_module::sysctl::Sysctl;
use linux_kernel_module::Mode;
Expand All @@ -17,14 +17,14 @@ impl linux_kernel_module::KernelModule for SysctlTestModule {
fn init() -> linux_kernel_module::KernelResult<Self> {
Ok(SysctlTestModule {
_sysctl_a: Sysctl::register(
"rust/sysctl-tests\x00",
"a\x00",
cstr!("rust/sysctl-tests"),
cstr!("a"),
AtomicBool::new(false),
Mode::from_int(0o666),
)?,
_sysctl_b: Sysctl::register(
"rust/sysctl-tests\x00",
"b\x00",
cstr!("rust/sysctl-tests"),
cstr!("b"),
AtomicBool::new(false),
Mode::from_int(0o666),
)?,
Expand Down

0 comments on commit e008586

Please sign in to comment.