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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
//! Link classification, permission bits, change markers, volume facts, and
//! native path spellings for callers that materialize cached artifacts.
//!
//! These are path-based compatibility operations: they follow links unless
//! stated otherwise, retain no handles, and are not secure-open or ACL
//! isolation primitives. The caller controls the paths involved.
use io;
use ;
use cratenative_fs_materialize as native;
// ---------------------------------------------------------------------------
// Links
// ---------------------------------------------------------------------------
/// A no-follow classification of one directory entry, without native
/// attribute bits.
/// Classify the entry at `path` without following its final component.
///
/// On Windows a reparse point whose tag cannot be read classifies as
/// [`LinkKind::Reparse`], never as a symlink.
///
/// # Errors
///
/// Returns the no-follow metadata error, including `NotFound` for a missing
/// entry. A dangling symbolic link is still classified.
/// Number of hard links to the object `path` currently names.
///
/// Follows symbolic links, so a dangling link reports `NotFound`. On Windows
/// the handle is opened metadata-only with every share mode, so observing a
/// count never evicts an existing writer.
///
/// # Errors
///
/// Returns the metadata or native query error.
/// Result of [`await_no_writers`].
/// Wait up to `timeout` until no process (this one or any other) holds the
/// file at `path` open for writing.
///
/// Publishing an executable is only safe to `exec` once every write
/// descriptor on its inode is closed. A child forked while the publisher's
/// write descriptor was open inherits that descriptor until its own `exec`,
/// so closing the publisher's copy is not enough: Linux refuses to execute
/// the file (`ETXTBSY`) for the child's fork-to-exec window. Call this after
/// closing the file and before handing it to anything that will execute it.
/// The file is opened read-only and no handle is retained.
///
/// # Errors
///
/// Returns the error from opening `path`.
/// Whether a file's storage blocks are shared with another file.
///
/// Reflinks (Linux `FICLONE`, macOS `clonefile`, Windows ReFS block
/// cloning) and snapshots let two files share blocks while each has one
/// hard link, so a link count alone cannot prove that deleting a file frees
/// its space.
/// Report whether the regular file at `path` shares storage blocks with
/// another file. Follows symbolic links and retains no handle.
///
/// Linux asks the file system for the file's extent map (`FIEMAP`) and
/// looks for the shared-extent flag; a volume without an extent map is
/// answered from its type. macOS and Windows answer from the volume's file
/// system: one that cannot clone blocks is `Exclusive`, and APFS or ReFS is
/// `Unknown`.
///
/// # Errors
///
/// Returns the metadata or native query error, including `NotFound`.
/// Create a symbolic link at `link` to the file `target`, which may not
/// exist yet.
///
/// Windows creates the file flavor of symbolic link, which may require the
/// Developer Mode or `SeCreateSymbolicLinkPrivilege` the host grants.
///
/// # Errors
///
/// Returns the native error, including `AlreadyExists` when `link` exists.
// ---------------------------------------------------------------------------
// Permissions
// ---------------------------------------------------------------------------
/// Capture the host permission representation from already-fetched
/// metadata: the full Unix mode bits, or the Windows readonly attribute as
/// `0`/`1`. Values are host-specific, not portable archive modes; restore one
/// only with [`apply_metadata_mode`] on the same host.
/// Restore a value returned by [`metadata_mode`]. Unix applies the exact
/// mode; Windows treats any nonzero value as readonly and preserves every
/// other attribute.
///
/// # Errors
///
/// Returns the metadata or permission-change error.
/// Toggle write permission while retaining unrelated mode bits and
/// attributes.
///
/// Unix `readonly = true` clears every write bit; `false` adds only the
/// owner-write bit. Windows toggles its readonly attribute and skips the
/// write when it already has the requested value. Follows symbolic links.
///
/// # Errors
///
/// Returns the metadata error for a missing path (including a dangling
/// link), or the permission-change error.
/// Add every Unix execute bit, retaining the other mode bits. Windows has no
/// per-file execute bit and performs no filesystem operation.
///
/// # Errors
///
/// On Unix, returns the metadata or permission-change error.
// ---------------------------------------------------------------------------
// Change markers
// ---------------------------------------------------------------------------
/// An opaque change-journal observation of one file: its Windows USN.
///
/// Compare only observations of the same file within one journal epoch. It
/// is not a content hash, a file identity, or proof against a journal
/// reset, a concurrent write, or path replacement.
;
/// Observe `path`'s change-journal position.
///
/// Windows reads the file's USN record (record versions 2 and 3). Missing
/// journals, query failures, and unsupported record versions return `None`,
/// never a timestamp substitute. Linux and macOS keep no such journal and
/// return `None` without probing the path. `None` means "cannot prove the
/// file is unchanged".
// ---------------------------------------------------------------------------
// Volume facts
// ---------------------------------------------------------------------------
/// The raw identity of the volume hosting `path`: `st_dev` on Unix, the
/// volume serial number on Windows. For callers whose persisted keys need
/// the raw value; compare values from the same host only. Follows symbolic
/// links. `None` when the path cannot be inspected.
/// Width in bits of the host's native file identifier: 128 on Windows
/// (NTFS/ReFS `FILE_ID_INFO`), 64 (the inode) on Linux and macOS.
pub const
/// Bytes of storage the file described by `metadata` actually occupies.
///
/// Unix reports allocated 512-byte blocks, so a sparse file can report less
/// than its length. Windows reports the compressed size
/// (`GetCompressedFileSizeW` on `path`), falling back to the logical length
/// when the volume cannot answer. Never fails.
// ---------------------------------------------------------------------------
// Paths and durability
// ---------------------------------------------------------------------------
/// Convert tool-emitted path bytes to a host path.
///
/// Unix preserves arbitrary bytes. Windows accepts UTF-8 only, because a
/// byte stream cannot represent native UTF-16 losslessly, and returns `None`
/// otherwise rather than converting lossily. This does not validate the path
/// for filesystem use (an embedded NUL is retained).
/// Prepare a file path for direct native calls.
///
/// Windows canonicalizes the existing parent and appends the unchanged file
/// name, yielding an extended-length absolute path that escapes `MAX_PATH`
/// without requiring the final file to exist. Linux and macOS return the
/// path unchanged. Follows parent links; this is not a secure-open or a
/// lexical-only operation.
///
/// # Errors
///
/// On Windows, `InvalidInput` when `path` has no file name, or the parent's
/// canonicalization error.
/// Flush `directory`'s entries to stable storage where the host exposes a
/// directory flush.
///
/// Linux and macOS open and fsync the directory. Windows has no directory
/// handle to flush and succeeds without resolving `directory`; unlike
/// [`sync_directory`](super::sync_directory), a missing directory is not an
/// error there. Callers whose durability protocol can use directory fsync
/// where it exists, but must stay portable to hosts without it, use this.
///
/// # Errors
///
/// On Linux and macOS, the open or fsync error.