Skip to content

Commit

Permalink
Merge pull request #35 from zec/misc-file-apis
Browse files Browse the repository at this point in the history
Addition of several bindings for OSAL file APIs
  • Loading branch information
dmopalmer authored Dec 13, 2024
2 parents 1837c3a + 5197216 commit 79c587a
Show file tree
Hide file tree
Showing 3 changed files with 195 additions and 7 deletions.
184 changes: 184 additions & 0 deletions src/osal/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,3 +282,187 @@ pub enum SeekReference {
#[doc(alias = "OS_SEEK_END")]
End = OS_SEEK_END,
}

/// Information about a file or directory.
///
/// Semantically equivalent to `os_fstat_t`.
#[doc(alias = "os_fstat_t")]
pub struct FileStat {
/// The file's mode bits.
///
/// For the individual bits,
/// see [`DIR`](Self::DIR), [`READ`](Self::READ),
/// [`WRITE`](Self::WRITE), and [`EXEC`](Self::EXEC).
pub file_mode_bits: u32,

/// The time the file was last modified.
pub file_time: super::OSTime,

/// The size of the file, in bytes.
pub file_size: usize,
}

impl FileStat {
/// Set if the file is a directory.
///
/// Wraps `OS_FILESTAT_MODE_DIR`.
#[doc(alias = "OS_FILESTAT_MODE_DIR")]
pub const DIR: u32 = OS_FILESTAT_MODE_DIR;

/// Set if the file is readable.
///
/// Wraps `OS_FILESTAT_MODE_READ`.
#[doc(alias = "OS_FILESTAT_MODE_READ")]
pub const READ: u32 = OS_FILESTAT_MODE_READ;

/// Set if the file is writable.
///
/// Wraps `OS_FILESTAT_MODE_WRITE`.
#[doc(alias = "OS_FILESTAT_MODE_WRITE")]
pub const WRITE: u32 = OS_FILESTAT_MODE_WRITE;

/// Set if the file is executable.
///
/// Wraps `OS_FILESTAT_MODE_EXEC`.
#[doc(alias = "OS_FILESTAT_MODE_EXEC")]
pub const EXEC: u32 = OS_FILESTAT_MODE_EXEC;
}

/// Obtains information about the file or directory at `path`.
///
/// Wraps `OS_stat`.
#[doc(alias = "OS_stat")]
#[inline]
pub fn stat<S: AsRef<CStr>>(path: &S) -> Result<FileStat, OsalError> {
let path = path.as_ref().as_ptr();
let mut filestats: os_fstat_t = os_fstat_t {
FileModeBits: 0,
FileTime: OS_time_t { ticks: 0 },
FileSize: 0,
};

// Safety: path isn't modified, and any possible bit-pattern is a valid
// os_fstat_t.
unsafe { OS_stat(path, &mut filestats) }.as_osal_status()?;

Ok(FileStat {
file_mode_bits: filestats.FileModeBits,
file_time: OSTime::from_os_time(filestats.FileTime),
file_size: filestats.FileSize,
})
}

/// Removes the file at `path` from the file system.
///
/// This function's behavior is system-dependent if the file is open;
/// for maximum portability, make sure the file is closed before calling `remove`.
///
/// Wraps `OS_remove`.
#[doc(alias = "OS_remove")]
#[inline]
pub fn remove<S: AsRef<CStr>>(path: &S) -> Result<(), OsalError> {
let path = path.as_ref().as_ptr();

// Safety: the string pointed to by path lasts longer than this function invocation
// and is not modified by the function.
unsafe { OS_remove(path) }.as_osal_status()?;

Ok(())
}

/// Changes the name of the file originally at `src` to `dest`.
///
/// `src` and `dest` must reside on the same file system.
///
/// This function's behavior is system-dependent if the file is open;
/// for maximum portability, make sure the file is closed before calling `rename`.
///
/// Wraps `OS_rename`.
#[doc(alias = "OS_rename")]
#[inline]
pub fn rename<S1, S2>(src: &S1, dest: &S2) -> Result<(), OsalError>
where
S1: AsRef<CStr>,
S2: AsRef<CStr>,
{
let src = src.as_ref().as_ptr();
let dest = dest.as_ref().as_ptr();

// Safety: the strings pointed to by src and dest
// are valid for longer than this function invocation
// and are not modified by the function.
unsafe { OS_rename(src, dest) }.as_osal_status()?;

Ok(())
}

/// Copies the file at `src` to `dest`.
///
/// This function's behavior is system-dependent if the file is open;
/// for maximum portability, make sure the file is closed before calling `cp`.
///
/// Wraps `OS_cp`.
#[doc(alias = "OS_cp")]
#[inline]
pub fn cp<S1, S2>(src: &S1, dest: &S2) -> Result<(), OsalError>
where
S1: AsRef<CStr>,
S2: AsRef<CStr>,
{
let src = src.as_ref().as_ptr();
let dest = dest.as_ref().as_ptr();

// Safety: the strings pointed to by src and dest
// are valid for longer than this function invocation
// and are not modified by the function.
unsafe { OS_cp(src, dest) }.as_osal_status()?;

Ok(())
}

/// Moves the file at `src` to `dest`.
///
/// This first attempts to rename the file,
/// which only works if `src` and `dest` are on the same file system.
/// Failing that, the function will copy the file, then remove the original.
///
/// This function's behavior is system-dependent if the file is open;
/// for maximum portability, make sure the file is closed before calling `mv`.
///
/// Wraps `OS_mv`.
#[doc(alias = "OS_mv")]
#[inline]
pub fn mv<S1, S2>(src: &S1, dest: &S2) -> Result<(), OsalError>
where
S1: AsRef<CStr>,
S2: AsRef<CStr>,
{
let src = src.as_ref().as_ptr();
let dest = dest.as_ref().as_ptr();

// Safety: the strings pointed to by src and dest
// are valid for longer than this function invocation
// and are not modified by the function.
unsafe { OS_mv(src, dest) }.as_osal_status()?;

Ok(())
}

/// Determines whether the file `filename` is open within OSAL.
///
/// Wraps `OS_FileOpenCheck`.
#[doc(alias = "OS_FileOpenCheck")]
#[inline]
pub fn file_open_check<S: AsRef<CStr>>(filename: &S) -> Result<bool, OsalError> {
let fname = filename.as_ref().as_ptr();

// Safety: the string pointed to by fname lasts longer than this function invocation
// and is not modified by the function.
match unsafe { OS_FileOpenCheck(fname) } {
OS_ERROR => Ok(false),
status => {
status.as_osal_status()?;
Ok(true)
}
}
}
8 changes: 1 addition & 7 deletions src/osal/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,12 @@
//! File system-level APIs.
use super::{I32Ext, OsalError};
pub use super::MAX_PATH_LEN;
use crate::sys::*;
use crate::utils::CStrBuf;

use core::ffi::{c_char, CStr};

/// The maximum allowed length of an OSAL path name,
/// including directory name, file name, and terminating NUL character.
///
/// Wraps `OS_MAX_PATH_LEN`.
#[doc(alias = "OS_MAX_PATH_LEN")]
pub const MAX_PATH_LEN: usize = OS_MAX_PATH_LEN as usize;

/// Translates an OSAL virtual file-system path
/// to a path name in the underlying system being
/// abstracted over.
Expand Down
10 changes: 10 additions & 0 deletions src/osal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,18 @@ pub mod task;
/// The maximum length of strings for names of many OSAL objects.
///
/// The length includes the null terminator.
///
/// Wraps `OS_MAX_API_NAME`.
#[doc(alias = "OS_MAX_API_NAME")]
pub const MAX_NAME_LEN: usize = sys::OS_MAX_API_NAME as usize;

/// The maximum allowed length of an OSAL path name,
/// including directory name, file name, and terminating NUL character.
///
/// Wraps `OS_MAX_PATH_LEN`.
#[doc(alias = "OS_MAX_PATH_LEN")]
pub const MAX_PATH_LEN: usize = sys::OS_MAX_PATH_LEN as usize;

/// An error code, as returned by many OSAL API functions.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct OsalError {
Expand Down

0 comments on commit 79c587a

Please sign in to comment.