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
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
//! This file has been automatically generated by `objc2`'s `header-translator`.
//! DO NOT EDIT
use core::ffi::*;
use core::ptr::NonNull;
use objc2::__framework_prelude::*;
use objc2_foundation::*;
use crate::*;
/// A unique identifier for an operation.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/fskit/fsoperationid?language=objc)
// NS_TYPED_EXTENSIBLE_ENUM
pub type FSOperationID = NSUInteger;
extern "C" {
/// [Apple's documentation](https://developer.apple.com/documentation/fskit/fsoperationidunspecified?language=objc)
pub static FSOperationIDUnspecified: FSOperationID;
}
/// Flags that describe the behavior of a blockmap operation.
///
/// This type is an option set in Swift.
/// In Objective-C, you use the cases of this enumeration to create a bit field.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/fskit/fsblockmapflags?language=objc)
// NS_OPTIONS
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct FSBlockmapFlags(pub NSUInteger);
bitflags::bitflags! {
impl FSBlockmapFlags: NSUInteger {
/// A flag that describes a read operation.
#[doc(alias = "FSBlockmapFlagsRead")]
const Read = 0x000100;
/// A flag that describes a write operation.
#[doc(alias = "FSBlockmapFlagsWrite")]
const Write = 0x000200;
}
}
unsafe impl Encode for FSBlockmapFlags {
const ENCODING: Encoding = NSUInteger::ENCODING;
}
unsafe impl RefEncode for FSBlockmapFlags {
const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
}
/// Flags that describe the behavior of an I/O completion operation.
///
/// This type is an option set in Swift.
/// In Objective-C, the cases of this enumeration combine to create a bit field.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/fskit/fscompleteioflags?language=objc)
// NS_OPTIONS
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct FSCompleteIOFlags(pub NSUInteger);
bitflags::bitflags! {
impl FSCompleteIOFlags: NSUInteger {
/// A flag that describes a read operation.
#[doc(alias = "FSCompleteIOFlagsRead")]
const Read = FSBlockmapFlags::Read.0;
/// A flag that describes a write operation.
#[doc(alias = "FSCompleteIOFlagsWrite")]
const Write = FSBlockmapFlags::Write.0;
/// A flag that requests that the file system module flush metadata I/O asynchronously.
#[doc(alias = "FSCompleteIOFlagsAsync")]
const Async = 0x000400;
}
}
unsafe impl Encode for FSCompleteIOFlags {
const ENCODING: Encoding = NSUInteger::ENCODING;
}
unsafe impl RefEncode for FSCompleteIOFlags {
const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
}
/// An enumeration of types of extents.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/fskit/fsextenttype?language=objc)
// NS_ENUM
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct FSExtentType(pub NSInteger);
impl FSExtentType {
/// An extent type to indicate valid data.
///
/// Use this type for all extents on a file system that doesn't support sparse files.
///
/// > Tip: The kernel keeps track of the end of file, so it knows a range of `[EOF, allocated space]` is uninitialized. Because of this behavior, it's valid to pass the data extent type for such a range.
#[doc(alias = "FSExtentTypeData")]
pub const Data: Self = Self(0);
/// An extent type to indicate uninitialized data.
///
/// Only use this extent type in file systems that support sparse files, and only then to represent ranges in the file that aren't allocated yet.
#[doc(alias = "FSExtentTypeZeroFill")]
pub const ZeroFill: Self = Self(1);
}
unsafe impl Encode for FSExtentType {
const ENCODING: Encoding = NSInteger::ENCODING;
}
unsafe impl RefEncode for FSExtentType {
const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
}
extern_class!(
/// A type that directs the kernel to map space on disk to a specific file managed by this file system.
///
/// _Extents_ provide the kernel the logical-to-physical mapping of a given file.
/// An extent describes a physical offset on disk, and a length and a logical offset within the file.
/// Rather than working with extents directly, you use this type's methods to provide or "pack" extent information, which FSKit then passes to the kernel.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/fskit/fsextentpacker?language=objc)
#[unsafe(super(NSObject))]
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct FSExtentPacker;
);
extern_conformance!(
unsafe impl NSObjectProtocol for FSExtentPacker {}
);
impl FSExtentPacker {
extern_methods!(
#[unsafe(method(init))]
#[unsafe(method_family = init)]
pub unsafe fn init(this: Allocated<Self>) -> Retained<Self>;
#[cfg(all(feature = "FSResource", feature = "libc"))]
/// Packs a single extent to send to the kernel.
///
/// - Parameters:
/// - resource: The resource on which to perform I/O.
/// - type: The type of extent, indicating whether it contains valid data.
/// - logicalOffset: The extent offset within the file, in bytes.
/// - physicalOffset: The extent offset on disk, in bytes.
/// - length: The extent length, in bytes.
/// - Returns: A Boolean value that indicates whether the packer can pack more extents.
#[unsafe(method(packExtentWithResource:type:logicalOffset:physicalOffset:length:))]
#[unsafe(method_family = none)]
pub unsafe fn packExtentWithResource_type_logicalOffset_physicalOffset_length(
&self,
resource: &FSBlockDeviceResource,
r#type: FSExtentType,
logical_offset: libc::off_t,
physical_offset: libc::off_t,
length: usize,
) -> bool;
);
}
/// Methods declared on superclass `NSObject`.
impl FSExtentPacker {
extern_methods!(
#[unsafe(method(new))]
#[unsafe(method_family = new)]
pub unsafe fn new() -> Retained<Self>;
);
}
extern_protocol!(
/// Methods and properties implemented by volumes that use kernel-offloaded I/O to achieve higher file transfer performance.
///
/// A volume that conforms to this protocol supplies file extent mappings to FSKit, which allows file transfers to take place in the kernel.
/// This approach provides higher-performance file transfer than transferring data between the module and kernel, while still allowing the file system to run in user space.
///
/// This protocol uses _extents_ to provide the kernel the logical-to-physical mapping of a given file.
/// An extent describes a physical offset on disk, and a length and a logical offset within the file.
/// You don't manage extents directly.
/// Instead, FSKit provides you with an ``FSExtentPacker`` to define and pack the extents in your implementations of this protocol's methods.
///
/// Most volumes conform to either this protocol or ``FSVolumeReadWriteOperations``.
/// You can conform to both if you need to provide kernel-offloaded I/O only for certain files.
/// In that case, files with the ``FSItem/Attribute/inhibitKernelOffloadedIO`` attribute set use ``FSVolumeReadWriteOperations``, and those without it use this protocol.
/// A volume that doesn't conform to either protocol can't support any I/O operation.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/fskit/fsvolumekerneloffloadediooperations?language=objc)
pub unsafe trait FSVolumeKernelOffloadedIOOperations: NSObjectProtocol {
#[cfg(all(feature = "FSItem", feature = "block2", feature = "libc"))]
/// Maps a file's disk space into extents, allowing the kernel to perform I/O with that space.
///
/// FSKit calls this method when the kernel needs to get a mapping of logical-to-physical offsets of the file's data.
/// This call may occur as part of an I/O operation on the file, or just to get the mapping as part of a `fcntl(F_LOG2PHYS)` system call.
/// In the case of an I/O operation on the file, `operationID` has a nonzero value; a future call to ``completeIO(for:offset:length:status:flags:operationID:replyHandler:)`` uses the same `operationID` to indicate which operation it completes.
/// In the case of a `fcntl(F_LOG2PHYS)` system call, the `operationID` parameter is `0` (Objective-C) or ``FSOperationID/unspecified`` (Swift).
/// In both cases the kernel retains the mapping, and it may perform I/O to this range (or a part of it) at any time.
///
/// If satisfying a blockmap request requires more extents than `packer` can handle, FSKit makes additional calls to this method with the same operation ID to collect the remainder.
///
/// - Parameters:
/// - file: The file for which to map disk space.
/// - offset: The starting logical offset of the range to be mapped (in bytes).
/// - length: The length of the range to be mapped (in bytes).
/// - flags: Flags that affect the behavior of the blockmap operation.
/// - operationID: A unique identifier of the blockmap call. Any value other than `0` (Objective-C) or ``FSOperationID/unspecified`` (Swift) indicates the beginning of an I/O operation. A value of `0` or ``FSOperationID/unspecified`` indicates the kernel maps the file without performing I/O. In this case, FSKit doesn't perform a corresponding call to ``completeIO(for:offset:length:status:flags:operationID:replyHandler:)``.
/// - packer: An extent packer you use to pack the requested range of the file's allocated disk space. FSKit sends all of the packed extents to the kernel when it invokes `reply`.
/// - reply: A block or closure to indicate success or failure. If mapping fails, pass an error as the one parameter to the reply handler. If mapping succeeds, pass `nil`. For an `async` Swift implementation, there's no reply handler; simply throw an error or return normally.
#[unsafe(method(blockmapFile:offset:length:flags:operationID:packer:replyHandler:))]
#[unsafe(method_family = none)]
unsafe fn blockmapFile_offset_length_flags_operationID_packer_replyHandler(
&self,
file: &FSItem,
offset: libc::off_t,
length: usize,
flags: FSBlockmapFlags,
operation_id: FSOperationID,
packer: &FSExtentPacker,
reply: &block2::DynBlock<dyn Fn(*mut NSError)>,
);
#[cfg(all(feature = "FSItem", feature = "block2", feature = "libc"))]
/// Completes an I/O operation for a given file.
///
/// Implement this method by updating a file's metadata, such as its size and modification time.
///
/// FSKit may call this method without an earlier call to ``blockmapFile(_:offset:length:flags:operationID:packer:replyHandler:)``.
/// In this case, the `operationID` is `0` (Objective-C) or ``FSOperationID/unspecified`` (Swift).
///
/// - Parameters:
/// - file: The file for which the I/O operation completed.
/// - offset: The starting logical offset at which I/O started.
/// - length: The length of the I/O range (in bytes).
/// - status: Any error that occurred during the operation. If no error occurred, this parameter is `nil`.
/// - flags: Flags that affect the behavior of the complete I/O operation.
/// - operationID: A unique identifier of the blockmap call. Any value other than `0` (Objective-C) or ``FSOperationID/unspecified`` (Swift) corresponds to a previous call to ``blockmapFile(_:offset:length:flags:operationID:packer:replyHandler:)`` with the same `operationID`.
/// - reply: A block or closure to indicate success or failure. If completing I/O fails, pass an error as the one parameter to the reply handler. If completing I/O succeeds, pass `nil`. For an `async` Swift implementation, there's no reply handler; simply throw an error or return normally.
#[unsafe(method(completeIOForFile:offset:length:status:flags:operationID:replyHandler:))]
#[unsafe(method_family = none)]
unsafe fn completeIOForFile_offset_length_status_flags_operationID_replyHandler(
&self,
file: &FSItem,
offset: libc::off_t,
length: usize,
status: &NSError,
flags: FSCompleteIOFlags,
operation_id: FSOperationID,
reply: &block2::DynBlock<dyn Fn(*mut NSError)>,
);
#[cfg(all(feature = "FSFileName", feature = "FSItem", feature = "block2"))]
/// Creates a new file item and map its disk space.
///
/// This method allows the module to opportunistically supply extents, avoiding future calls to ``blockmapFile(_:offset:length:flags:operationID:packer:replyHandler:)``.
/// Only perform this technique opportunistically.
/// In particular, don't perform additional I/O to fetch extent data.
///
/// Packing extents in this method requires that `attributes` defines a size greater than 0.
///
/// An implementation that doesn't supply the extents can ignore the packer and call the corresponding method in the ``FSVolume/Operations`` protocol, ``FSVolume/Operations/createItem(named:type:inDirectory:attributes:replyHandler:)``.
///
/// - Parameters:
/// - name: The new file's name.
/// - directory: The directory in which to create the file.
/// - attributes: Attributes to apply to the new file.
/// - packer: An extent packer you use to pack the file's allocated disk space.
/// - reply: A block or closure to indicate success or failure. If creation succeeds, pass the newly created ``FSItem`` and its ``FSFileName``, along with a `nil` error. If creation fails, pass the relevant error as the third parameter; FSKit ignores any ``FSItem`` or ``FSFileName`` in this case. For an `async` Swift implementation, there's no reply handler; instead, return a tuple of the ``FSItem`` and its ``FSFileName`` or throw an error.
#[unsafe(method(createFileNamed:inDirectory:attributes:packer:replyHandler:))]
#[unsafe(method_family = none)]
unsafe fn createFileNamed_inDirectory_attributes_packer_replyHandler(
&self,
name: &FSFileName,
directory: &FSItem,
attributes: &FSItemSetAttributesRequest,
packer: &FSExtentPacker,
reply: &block2::DynBlock<dyn Fn(*mut FSItem, *mut FSFileName, *mut NSError)>,
);
#[cfg(all(feature = "FSFileName", feature = "FSItem", feature = "block2"))]
/// Looks up an item within a directory and maps its disk space.
///
/// This method allows the module to opportunistically supply extents, avoiding future calls to ``blockmapFile(_:offset:length:flags:operationID:packer:replyHandler:)``.
/// Only perform this technique opportunistically.
/// In particular, don't perform additional I/O to fetch extent data.
///
/// - Parameters:
/// - name: The name of the file to look up.
/// - directory: The directory in which to look up the file.
/// - packer: An extent packer you use to pack the file's allocated disk space.
/// - reply: A block or closure to indicate success or failure. If lookup succeeds, pass the found ``FSItem`` and its ``FSFileName``, along with a `nil` error. If lookup fails, pass the relevant error as the third parameter; FSKit ignores any ``FSItem`` or ``FSFileName`` in this case. For an `async` Swift implementation, there's no reply handler; instead, return a tuple of the ``FSItem`` and its ``FSFileName`` or throw an error.
#[unsafe(method(lookupItemNamed:inDirectory:packer:replyHandler:))]
#[unsafe(method_family = none)]
unsafe fn lookupItemNamed_inDirectory_packer_replyHandler(
&self,
name: &FSFileName,
directory: &FSItem,
packer: &FSExtentPacker,
reply: &block2::DynBlock<dyn Fn(*mut FSItem, *mut FSFileName, *mut NSError)>,
);
#[cfg(all(
feature = "FSItem",
feature = "FSVolume",
feature = "block2",
feature = "libc"
))]
/// Preallocates and maps disk space for the given file.
///
/// This method allows the module to opportunistically supply extents, avoiding future calls to ``blockmapFile(_:offset:length:flags:operationID:packer:replyHandler:)``.
///
/// > Important: Only implement this method if your file system conforms to ``FSVolume/PreallocateOperations``.
///
/// - Parameters:
/// - file: The item for which to preallocate space.
/// - offset: The offset from which to allocate.
/// - length: The length of the space in bytes.
/// - flags: Flags that affect the preallocation behavior.
/// - packer: An extent packer you use to pack the file's preallocated disk space.
/// - reply: A block or closure to indicate success or failure. If preallocation succeeds, pass the amount of bytes allocated and a nil error. If preallocation fails, pass the relevant error as the second parameter; FSKit ignores any byte count in this case. For an `async` Swift implementation, there’s no reply handler; simply return the allocated byte count or throw an error.
#[optional]
#[unsafe(method(preallocateSpaceForFile:atOffset:length:flags:packer:replyHandler:))]
#[unsafe(method_family = none)]
unsafe fn preallocateSpaceForFile_atOffset_length_flags_packer_replyHandler(
&self,
file: &FSItem,
offset: libc::off_t,
length: usize,
flags: FSPreallocateFlags,
packer: &FSExtentPacker,
reply: &block2::DynBlock<dyn Fn(usize, *mut NSError)>,
);
}
);