starnix_uapi/
open_flags.rs

1// Copyright 2023 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::uapi;
6use bitflags::bitflags;
7
8// The inner mod is required because bitflags cannot pass the attribute through to the single
9// variant, and attributes cannot be applied to macro invocations.
10mod inner_flags {
11    // Part of the code for the O_RDONLY case that's produced by the macro triggers the lint, but as
12    // a whole, the produced code is still correct.
13    #![allow(clippy::bad_bit_mask)] // TODO(b/303500202) Remove once addressed in bitflags.
14    use super::{bitflags, uapi};
15
16    bitflags! {
17        #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
18        pub struct OpenFlags: u32 {
19        const ACCESS_MASK = 0x3;
20
21        // The access modes are not really bits. Instead, they're an enum
22        // embedded in the bitfield. Use ACCESS_MASK to extract the enum
23        // or use the OpenFlags::can_read and OpenFlags::can_write functions.
24        const RDONLY = uapi::O_RDONLY;
25        const WRONLY = uapi::O_WRONLY;
26        const RDWR = uapi::O_RDWR;
27
28        const CREAT = uapi::O_CREAT;
29        const EXCL = uapi::O_EXCL;
30        const NOCTTY = uapi::O_NOCTTY;
31        const TRUNC = uapi::O_TRUNC;
32        const APPEND = uapi::O_APPEND;
33        const NONBLOCK = uapi::O_NONBLOCK;
34        const DSYNC = uapi::O_DSYNC;
35        const ASYNC = uapi::FASYNC;
36        const DIRECT = uapi::O_DIRECT;
37        const LARGEFILE = uapi::O_LARGEFILE;
38        const DIRECTORY = uapi::O_DIRECTORY;
39        const NOFOLLOW = uapi::O_NOFOLLOW;
40        const NOATIME = uapi::O_NOATIME;
41        const CLOEXEC = uapi::O_CLOEXEC;
42        const SYNC = uapi::O_SYNC;
43        const PATH = uapi::O_PATH;
44        const TMPFILE = uapi::O_TMPFILE;
45        const NDELAY = uapi::O_NDELAY;
46        }
47    }
48
49    impl OpenFlags {
50        pub fn can_read(&self) -> bool {
51            let access_mode = self.bits() & Self::ACCESS_MASK.bits();
52            access_mode == uapi::O_RDONLY || access_mode == uapi::O_RDWR
53        }
54
55        pub fn can_write(&self) -> bool {
56            let access_mode = self.bits() & Self::ACCESS_MASK.bits();
57            access_mode == uapi::O_WRONLY || access_mode == uapi::O_RDWR
58        }
59    }
60}
61
62pub use inner_flags::OpenFlags;