|
4 | 4 |
|
5 | 5 | use crate::{ |
6 | 6 | alloc::{flags::*, AllocError, KVec}, |
| 7 | + error::{to_result, Result}, |
7 | 8 | fmt::{self, Write}, |
8 | 9 | prelude::*, |
9 | 10 | }; |
@@ -920,6 +921,84 @@ impl Write for NullTerminatedFormatter<'_> { |
920 | 921 | } |
921 | 922 | } |
922 | 923 |
|
| 924 | +/// # Safety |
| 925 | +/// |
| 926 | +/// - `string` must point to a null terminated string that is valid for read. |
| 927 | +unsafe fn kstrtobool_raw(string: *const u8) -> Result<bool> { |
| 928 | + let mut result: bool = false; |
| 929 | + |
| 930 | + // SAFETY: |
| 931 | + // - By function safety requirement, `string` is a valid null-terminated string. |
| 932 | + // - `result` is a valid `bool` that we own. |
| 933 | + to_result(unsafe { bindings::kstrtobool(string, &mut result) })?; |
| 934 | + Ok(result) |
| 935 | +} |
| 936 | + |
| 937 | +/// Convert common user inputs into boolean values using the kernel's `kstrtobool` function. |
| 938 | +/// |
| 939 | +/// This routine returns `Ok(bool)` if the first character is one of 'YyTt1NnFf0', or |
| 940 | +/// \[oO\]\[NnFf\] for "on" and "off". Otherwise it will return `Err(EINVAL)`. |
| 941 | +/// |
| 942 | +/// # Examples |
| 943 | +/// |
| 944 | +/// ``` |
| 945 | +/// # use kernel::{c_str, str::kstrtobool}; |
| 946 | +/// |
| 947 | +/// // Lowercase |
| 948 | +/// assert_eq!(kstrtobool(c_str!("true")), Ok(true)); |
| 949 | +/// assert_eq!(kstrtobool(c_str!("tr")), Ok(true)); |
| 950 | +/// assert_eq!(kstrtobool(c_str!("t")), Ok(true)); |
| 951 | +/// assert_eq!(kstrtobool(c_str!("twrong")), Ok(true)); |
| 952 | +/// assert_eq!(kstrtobool(c_str!("false")), Ok(false)); |
| 953 | +/// assert_eq!(kstrtobool(c_str!("f")), Ok(false)); |
| 954 | +/// assert_eq!(kstrtobool(c_str!("yes")), Ok(true)); |
| 955 | +/// assert_eq!(kstrtobool(c_str!("no")), Ok(false)); |
| 956 | +/// assert_eq!(kstrtobool(c_str!("on")), Ok(true)); |
| 957 | +/// assert_eq!(kstrtobool(c_str!("off")), Ok(false)); |
| 958 | +/// |
| 959 | +/// // Camel case |
| 960 | +/// assert_eq!(kstrtobool(c_str!("True")), Ok(true)); |
| 961 | +/// assert_eq!(kstrtobool(c_str!("False")), Ok(false)); |
| 962 | +/// assert_eq!(kstrtobool(c_str!("Yes")), Ok(true)); |
| 963 | +/// assert_eq!(kstrtobool(c_str!("No")), Ok(false)); |
| 964 | +/// assert_eq!(kstrtobool(c_str!("On")), Ok(true)); |
| 965 | +/// assert_eq!(kstrtobool(c_str!("Off")), Ok(false)); |
| 966 | +/// |
| 967 | +/// // All caps |
| 968 | +/// assert_eq!(kstrtobool(c_str!("TRUE")), Ok(true)); |
| 969 | +/// assert_eq!(kstrtobool(c_str!("FALSE")), Ok(false)); |
| 970 | +/// assert_eq!(kstrtobool(c_str!("YES")), Ok(true)); |
| 971 | +/// assert_eq!(kstrtobool(c_str!("NO")), Ok(false)); |
| 972 | +/// assert_eq!(kstrtobool(c_str!("ON")), Ok(true)); |
| 973 | +/// assert_eq!(kstrtobool(c_str!("OFF")), Ok(false)); |
| 974 | +/// |
| 975 | +/// // Numeric |
| 976 | +/// assert_eq!(kstrtobool(c_str!("1")), Ok(true)); |
| 977 | +/// assert_eq!(kstrtobool(c_str!("0")), Ok(false)); |
| 978 | +/// |
| 979 | +/// // Invalid input |
| 980 | +/// assert_eq!(kstrtobool(c_str!("invalid")), Err(EINVAL)); |
| 981 | +/// assert_eq!(kstrtobool(c_str!("2")), Err(EINVAL)); |
| 982 | +/// ``` |
| 983 | +pub fn kstrtobool(string: &CStr) -> Result<bool> { |
| 984 | + // SAFETY: |
| 985 | + // - The pointer returned by `CStr::as_char_ptr` is guaranteed to be |
| 986 | + // null terminated. |
| 987 | + // - `string` is live and thus the string is valid for read. |
| 988 | + unsafe { kstrtobool_raw(string.as_char_ptr()) } |
| 989 | +} |
| 990 | + |
| 991 | +/// Convert `&[u8]` to `bool` by deferring to [`kernel::str::kstrtobool`]. |
| 992 | +/// |
| 993 | +/// Only considers at most the first two bytes of `bytes`. |
| 994 | +pub fn kstrtobool_bytes(bytes: &[u8]) -> Result<bool> { |
| 995 | + // `ktostrbool` only considers the first two bytes of the input. |
| 996 | + let stack_string = [*bytes.first().unwrap_or(&0), *bytes.get(1).unwrap_or(&0), 0]; |
| 997 | + // SAFETY: `stack_string` is null terminated and it is live on the stack so |
| 998 | + // it is valid for read. |
| 999 | + unsafe { kstrtobool_raw(stack_string.as_ptr()) } |
| 1000 | +} |
| 1001 | + |
923 | 1002 | /// An owned string that is guaranteed to have exactly one `NUL` byte, which is at the end. |
924 | 1003 | /// |
925 | 1004 | /// Used for interoperability with kernel APIs that take C strings. |
|
0 commit comments