From 1975b81812cad5e47b4c385a292c5f07e80736a1 Mon Sep 17 00:00:00 2001 From: Daniel Xu Date: Sun, 9 Jan 2022 13:22:05 -0800 Subject: [PATCH] rust: file: Add `FileFlags` type for `File` flags This commit addes a wrapper struct, `FileFlags`, that defines constants and methods for `struct file`'s `f_flags`. This wrapper is desirable b/c callers no longer have to access soon-to-be-private `bindings` module. It also documents the previously ambiguous u32 return value on `flags()`. This closes #606. Signed-off-by: Daniel Xu --- rust/kernel/file.rs | 104 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 101 insertions(+), 3 deletions(-) diff --git a/rust/kernel/file.rs b/rust/kernel/file.rs index 648628837d8239..18e47892a6aca6 100644 --- a/rust/kernel/file.rs +++ b/rust/kernel/file.rs @@ -8,6 +8,104 @@ use crate::{bindings, cred::CredentialRef, error::Error, Result}; use core::{mem::ManuallyDrop, ops::Deref}; +/// Access mode associated with a file +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum AccessMode { + /// File is read only. + ReadOnly, + /// File is write only. + WriteOnly, + /// File is readable and writeable. + ReadWrite, +} + +/// Flags associated with a [`File`]. +/// +/// Wrapper around `struct file`'s `f_flags`. +#[repr(transparent)] +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub struct FileFlags(u32); + +impl FileFlags { + /// Also known as `O_APPEND`. + pub const APPEND: u32 = bindings::O_APPEND; + + /// Also known as `FASYNC`. + pub const ASYNC: u32 = bindings::FASYNC; + + /// Also known as `O_CLOEXEC`. + pub const CLOSE_ON_EXEC: u32 = bindings::O_CLOEXEC; + + /// Also known as `O_CREAT`. + pub const CREATE: u32 = bindings::O_CREAT; + + /// Also known as `O_DIRECT`. + pub const DIRECT: u32 = bindings::O_DIRECT; + + /// Also known as `O_DIRECTORY`. + pub const DIRECTORY: u32 = bindings::O_DIRECTORY; + + /// Also known as `O_DSYNC`. + pub const DATA_SYNC: u32 = bindings::O_DSYNC; + + /// Also known as `O_EXCL`. + pub const EXCLUSIVE: u32 = bindings::O_EXCL; + + /// Also known as `O_LARGEFILE`. + pub const LARGE_FILE: u32 = bindings::O_LARGEFILE; + + /// Also known as `O_NOATIME`. + pub const NO_ACCESS_TIME: u32 = bindings::O_NOATIME; + + /// Also known as `O_NOCTTY`. + pub const NO_CONTROLLING_TTY: u32 = bindings::O_NOCTTY; + + /// Also known as `O_NOFOLLOW`. + pub const NO_FOLLOW: u32 = bindings::O_NOFOLLOW; + + /// Also known as `O_NONBLOCK` + pub const NON_BLOCK: u32 = bindings::O_NONBLOCK; + + /// Also known as `O_NDELAY`. + /// + /// This is effectively the same flag as [`Self::NON_BLOCK`] on all architectures except + /// SPARC64. + pub const NO_DELAY: u32 = bindings::O_NDELAY; + + /// Also known as `O_PATH`. + pub const PATH: u32 = bindings::O_PATH; + + /// Also known as `O_SYNC`. + pub const SYNC: u32 = bindings::O_SYNC; + + /// Also known as `O_TMPFILE`. + pub const TEMPORARY_FILE: u32 = bindings::O_TMPFILE; + + /// Also known as `O_TRUNC`. + pub const TRUNCATE: u32 = bindings::O_TRUNC; + + fn new(flags: u32) -> Self { + Self(flags) + } + + /// Access bitmasked set of file flags. + /// + /// Use the above constants to interpret the bitmask. + pub fn flags(&self) -> u32 { + self.0 + } + + /// Access mode associated with the file. + pub fn access_mode(&self) -> AccessMode { + match self.0 & bindings::O_ACCMODE { + bindings::O_RDONLY => AccessMode::ReadOnly, + bindings::O_WRONLY => AccessMode::WriteOnly, + bindings::O_RDWR => AccessMode::ReadWrite, + _ => panic!("Unreachable. Kernel VFS layer guarantees one of the above flags set."), + } + } +} + /// Wraps the kernel's `struct file`. /// /// # Invariants @@ -55,10 +153,10 @@ impl File { unsafe { CredentialRef::from_ptr(ptr) } } - /// Returns the flags associated with the file. - pub fn flags(&self) -> u32 { + /// Returns the [`FileFlags`] associated with the file. + pub fn flags(&self) -> FileFlags { // SAFETY: `File::ptr` is guaranteed to be valid by the type invariants. - unsafe { (*self.ptr).f_flags } + unsafe { FileFlags::new((*self.ptr).f_flags) } } }