From 4b2ee2ce3877a87d8b388cbf4791ce91ad6e6e9f Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Thu, 18 Jul 2024 11:10:30 +0200 Subject: [PATCH] Handle platforms where c_int is not i32 Some functions assume that c_int is always i32. This is not true for all platforms. This patch adapts those functions to handle those cases. Some littlefs functions return an error code (c_int) from functions returning i32. In these cases, error codes are truncated to c_int::MIN. --- CHANGELOG.md | 1 + src/fs.rs | 42 ++++++++++++++++++++++-------------------- src/io.rs | 9 ++++++++- 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32b002b8f..da5affa0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). accessing `Storage`, `Filesystem` and `File` implementations for any storage. - Added `Filesystem::mount_or_else` function ([#57][]) - Marked `Path::is_empty`, `Path::from_bytes_with_nul`, `Path::from_cstr`, `Path::from_cstr_unchecked`, `Path::as_str_ref_with_trailing_nul`, `Path::as_str`, and `PathBuf::new` as `const`. +- Support platforms where `c_int` is not `i32`. ### Fixed diff --git a/src/fs.rs b/src/fs.rs index 7c2064556..4c60dd08e 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -287,8 +287,9 @@ impl Filesystem<'_, Storage> { /// by this method available, at any given time. pub fn available_blocks(&self) -> Result { let return_code = unsafe { ll::lfs_fs_size(&mut self.alloc.borrow_mut().state) }; - io::result_from(return_code, return_code) - .map(|blocks| self.total_blocks() - blocks as usize) + io::u32_result(return_code) + .map(|blocks| usize::try_from(blocks).unwrap_or(usize::MAX)) + .map(|blocks| self.total_blocks().saturating_sub(blocks)) } /// Available number of unused bytes in the filesystem @@ -463,17 +464,18 @@ impl Filesystem<'_, Storage> { ) }; - if return_code >= 0 { - attribute.size = cmp::min(attr_max, return_code as u32) as usize; - return Ok(Some(attribute)); - } - if return_code == ll::lfs_error_LFS_ERR_NOATTR { - return Ok(None); - } - - io::result_from((), return_code)?; - // TODO: get rid of this - unreachable!(); + io::u32_result(return_code) + .map(|n| { + attribute.size = cmp::min(attr_max, n) as usize; + Some(attribute) + }) + .or_else(|err| { + if err == Error::NO_ATTRIBUTE { + Ok(None) + } else { + Err(err) + } + }) } /// Remove attribute. @@ -549,7 +551,7 @@ impl Filesystem<'_, Storage> { /// C callback interface used by LittleFS to sync data with the lower level interface below the /// filesystem. Note that this function currently does nothing. - extern "C" fn lfs_config_sync(_c: *const ll::lfs_config) -> i32 { + extern "C" fn lfs_config_sync(_c: *const ll::lfs_config) -> c_int { // println!("in lfs_config_sync"); // Do nothing; we presume that data is synchronized. 0 @@ -605,7 +607,7 @@ impl Attribute { bitflags! { /// Definition of file open flags which can be mixed and matched as appropriate. These definitions /// are reminiscent of the ones defined by POSIX. - struct FileOpenFlags: u32 { + struct FileOpenFlags: c_int { /// Open file in read only mode. const READ = 0x1; /// Open file in write only mode. @@ -754,7 +756,7 @@ impl<'a, 'b, Storage: driver::Storage> File<'a, 'b, Storage> { addr_of_mut!((*(*self.alloc.borrow_mut())).state), ) }; - io::result_from(return_code as usize, return_code) + io::u32_result(return_code).map(|n| n as usize) } pub fn is_empty(&self) -> Result { @@ -851,7 +853,7 @@ impl OpenOptions { &mut fs.alloc.borrow_mut().state, addr_of_mut!(alloc.state), path.as_ptr(), - self.0.bits() as i32, + self.0.bits(), addr_of!(alloc.config), ); @@ -955,7 +957,7 @@ impl io::Read for File<'_, '_, S> { buf.len() as u32, ) }; - io::result_from(return_code as usize, return_code) + io::u32_result(return_code).map(|n| n as usize) } } @@ -972,7 +974,7 @@ impl io::Seek for File<'_, '_, S> { pos.whence(), ) }; - io::result_from(return_code as usize, return_code) + io::u32_result(return_code).map(|n| n as usize) } } @@ -989,7 +991,7 @@ impl io::Write for File<'_, '_, S> { buf.len() as u32, ) }; - io::result_from(return_code as usize, return_code) + io::u32_result(return_code).map(|n| n as usize) } fn flush(&self) -> Result<()> { diff --git a/src/io.rs b/src/io.rs index 9b01c99db..5c590aa6b 100644 --- a/src/io.rs +++ b/src/io.rs @@ -78,7 +78,7 @@ impl SeekFrom { } } - pub(crate) fn whence(self) -> i32 { + pub(crate) fn whence(self) -> c_int { match self { SeekFrom::Start(_) => 0, SeekFrom::End(_) => 2, @@ -265,3 +265,10 @@ pub fn result_from(return_value: T, error_code: ll::lfs_error) -> Result { Ok(return_value) } } + +pub fn u32_result(return_value: i32) -> Result { + u32::try_from(return_value).map_err(|_| { + let error_code = c_int::try_from(return_value).unwrap_or(c_int::MIN); + Error::new(error_code).unwrap() + }) +}