Skip to content

Commit

Permalink
rust: file: Add FileFlags type for File flags
Browse files Browse the repository at this point in the history
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 torvalds#606.

Signed-off-by: Daniel Xu <dxu@dxuuu.xyz>
  • Loading branch information
danobi committed Jan 9, 2022
1 parent 73bd4bb commit 1975b81
Showing 1 changed file with 101 additions and 3 deletions.
104 changes: 101 additions & 3 deletions rust/kernel/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) }
}
}

Expand Down

0 comments on commit 1975b81

Please sign in to comment.