1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2026-present, Dmitry Prudnikov
//! Platform open flags shared between [`StdFs`] and `IoUringFs`:
//! `O_DIRECT` for [`FsOpenOptions::direct_io`], `O_NOFOLLOW` (or the
//! Windows reparse-point open) for [`FsOpenOptions::no_follow`], and
//! `O_NONBLOCK` for the open alone for [`FsOpenOptions::no_wait`].
//!
//! Lives here (rather than inline in each backend's `open()`) so the
//! arch-gating list and the bit values are defined in exactly one place.
//! Two backends with their own copy would silently diverge if one was
//! updated to support a new arch and the other wasn't. Both flags go
//! through one `custom_flags` call, which replaces whatever an earlier
//! call set.
//!
//! Doc-contract for the `direct_io` flag is on the
//! [`FsOpenOptions::direct_io`](field@super::FsOpenOptions::direct_io)
//! field (disambiguated against the same-named builder method): the
//! flag is best-effort, may be silently dropped, and correctness
//! must not depend on it.
//!
//! # `std` dependency
//!
//! This module touches `std::fs::OpenOptions` directly, so it is
//! std-only and the parent `mod open_flags;` declaration in
//! `fs/mod.rs` is gated behind `#[cfg(feature = "std")]`. That gate
//! is the first concrete honest step toward the no-std backend
//! split, but it does NOT by itself unblock a `no_std + alloc`
//! build: the wider `Fs` / `FsFile` trait surface (`std::io::{Read,
//! Write, Seek}`, `std::path::Path`) is std-bound at the trait
//! definition level, so even `MemFs` (alloc-only in its body) can't
//! compile under `--no-default-features --features alloc`. Porting
//! the traits off `std::io` / `std::path` is tracked separately
//! (issue `#311`), as a prerequisite for the rest of `fs::*` to
//! become honestly feature-gateable. When that lands, this module's
//! gate becomes load-bearing; until then it's a forward-looking
//! marker that keeps new std-side helpers honest with the policy.
//!
//! [`StdFs`]: super::StdFs
//! [`FsOpenOptions::direct_io`]: field@super::FsOpenOptions::direct_io
//! [`FsOpenOptions::no_follow`]: field@super::FsOpenOptions::no_follow
//! [`FsOpenOptions::no_wait`]: field@super::FsOpenOptions::no_wait
use FsOpenOptions;
/// The `O_DIRECT` bit when `direct_io` is requested. The bit differs per
/// architecture (aarch64 and arm `0o200000`, where the asm-generic `0o40000`
/// is `O_DIRECTORY`), so it comes from the C library of the target.
/// No `O_DIRECT` outside Linux/Android, nor where the C library does not
/// define it (uClibc). macOS would need `F_NOCACHE` via `fcntl` post-open,
/// Windows `FILE_FLAG_NO_BUFFERING` at `CreateFile` time: both out of scope
/// per the
/// [`FsOpenOptions::direct_io`](field@crate::fs::FsOpenOptions::direct_io)
/// best-effort contract.
/// Applies the platform flags `opts` asks for to a `std::fs::OpenOptions`
/// builder.
/// Clears what the open alone needed from `file`, opened under `opts`: the
/// `O_NONBLOCK` of a `no_wait` open, so its I/O blocks as any file's does
/// (`io_uring`, for one, fails a write that would block on such a file).
///
/// # Errors
///
/// The `fcntl` that reads or sets the file's status flags failing.
/// Applies the platform flags `opts` asks for to a `std::fs::OpenOptions`
/// builder. Direct I/O is not wired here (see
/// [`FsOpenOptions::direct_io`](field@crate::fs::FsOpenOptions::direct_io)).
/// No platform flags on a target that is neither Unix nor Windows.