Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/fuse/src/sys.rs
5394 views
1
// Copyright 2019 The ChromiumOS Authors
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
use std::mem;
6
7
use bitflags::bitflags;
8
use enumn::N;
9
use zerocopy::FromBytes;
10
use zerocopy::Immutable;
11
use zerocopy::IntoBytes;
12
use zerocopy::KnownLayout;
13
use zerocopy::TryFromBytes;
14
15
/// Version number of this interface.
16
pub const KERNEL_VERSION: u32 = 7;
17
18
/// Oldest supported minor version of the fuse interface.
19
pub const OLDEST_SUPPORTED_KERNEL_MINOR_VERSION: u32 = 27;
20
21
/// Minor version number of this interface.
22
pub const KERNEL_MINOR_VERSION: u32 = 31;
23
24
/// The ID of the inode corresponding to the root directory of the file system.
25
pub const ROOT_ID: u64 = 1;
26
27
// Bitmasks for `fuse_setattr_in.valid`.
28
const FATTR_MODE: u32 = 1;
29
const FATTR_UID: u32 = 2;
30
const FATTR_GID: u32 = 4;
31
const FATTR_SIZE: u32 = 8;
32
const FATTR_ATIME: u32 = 16;
33
const FATTR_MTIME: u32 = 32;
34
pub const FATTR_FH: u32 = 64;
35
const FATTR_ATIME_NOW: u32 = 128;
36
const FATTR_MTIME_NOW: u32 = 256;
37
pub const FATTR_LOCKOWNER: u32 = 512;
38
const FATTR_CTIME: u32 = 1024;
39
40
bitflags! {
41
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
42
#[repr(transparent)]
43
pub struct SetattrValid: u32 {
44
const MODE = FATTR_MODE;
45
const UID = FATTR_UID;
46
const GID = FATTR_GID;
47
const SIZE = FATTR_SIZE;
48
const ATIME = FATTR_ATIME;
49
const MTIME = FATTR_MTIME;
50
const ATIME_NOW = FATTR_ATIME_NOW;
51
const MTIME_NOW = FATTR_MTIME_NOW;
52
const CTIME = FATTR_CTIME;
53
}
54
}
55
56
// Flags returned by the OPEN request.
57
58
/// Bypass page cache for this open file.
59
const FOPEN_DIRECT_IO: u32 = 1 << 0;
60
61
/// Don't invalidate the data cache on open.
62
const FOPEN_KEEP_CACHE: u32 = 1 << 1;
63
64
/// The file is not seekable.
65
const FOPEN_NONSEEKABLE: u32 = 1 << 2;
66
67
/// Allow caching the directory entries.
68
const FOPEN_CACHE_DIR: u32 = 1 << 3;
69
70
/// This file is stream-like (i.e., no file position).
71
const FOPEN_STREAM: u32 = 1 << 4;
72
73
/// New file was created in atomic open
74
const FOPEN_FILE_CREATED: u32 = 1 << 7;
75
76
bitflags! {
77
/// Options controlling the behavior of files opened by the server in response
78
/// to an open or create request.
79
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
80
#[repr(transparent)]
81
pub struct OpenOptions: u32 {
82
const DIRECT_IO = FOPEN_DIRECT_IO;
83
const KEEP_CACHE = FOPEN_KEEP_CACHE;
84
const NONSEEKABLE = FOPEN_NONSEEKABLE;
85
const CACHE_DIR = FOPEN_CACHE_DIR;
86
const STREAM = FOPEN_STREAM;
87
const FILE_CREATED = FOPEN_FILE_CREATED;
88
}
89
}
90
91
// INIT request/reply flags.
92
93
/// Asynchronous read requests.
94
const ASYNC_READ: u64 = 1;
95
96
/// Remote locking for POSIX file locks.
97
const POSIX_LOCKS: u64 = 2;
98
99
/// Kernel sends file handle for fstat, etc... (not yet supported).
100
const FILE_OPS: u64 = 4;
101
102
/// Handles the O_TRUNC open flag in the filesystem.
103
const ATOMIC_O_TRUNC: u64 = 8;
104
105
/// FileSystem handles lookups of "." and "..".
106
const EXPORT_SUPPORT: u64 = 16;
107
108
/// FileSystem can handle write size larger than 4kB.
109
const BIG_WRITES: u64 = 32;
110
111
/// Don't apply umask to file mode on create operations.
112
const DONT_MASK: u64 = 64;
113
114
/// Kernel supports splice write on the device.
115
const SPLICE_WRITE: u64 = 128;
116
117
/// Kernel supports splice move on the device.
118
const SPLICE_MOVE: u64 = 256;
119
120
/// Kernel supports splice read on the device.
121
const SPLICE_READ: u64 = 512;
122
123
/// Remote locking for BSD style file locks.
124
const FLOCK_LOCKS: u64 = 1024;
125
126
/// Kernel supports ioctl on directories.
127
const HAS_IOCTL_DIR: u64 = 2048;
128
129
/// Automatically invalidate cached pages.
130
const AUTO_INVAL_DATA: u64 = 4096;
131
132
/// Do READDIRPLUS (READDIR+LOOKUP in one).
133
const DO_READDIRPLUS: u64 = 8192;
134
135
/// Adaptive readdirplus.
136
const READDIRPLUS_AUTO: u64 = 16384;
137
138
/// Asynchronous direct I/O submission.
139
const ASYNC_DIO: u64 = 32768;
140
141
/// Use writeback cache for buffered writes.
142
const WRITEBACK_CACHE: u64 = 65536;
143
144
/// Kernel supports zero-message opens.
145
const NO_OPEN_SUPPORT: u64 = 131072;
146
147
/// Allow parallel lookups and readdir.
148
const PARALLEL_DIROPS: u64 = 262144;
149
150
/// Fs handles killing suid/sgid/cap on write/chown/trunc.
151
const HANDLE_KILLPRIV: u64 = 524288;
152
153
/// FileSystem supports posix acls.
154
const POSIX_ACL: u64 = 1048576;
155
156
/// Reading the device after an abort returns `ECONNABORTED`.
157
const ABORT_ERROR: u64 = 2097152;
158
159
/// The reply to the `init` message contains the max number of request pages.
160
const MAX_PAGES: u64 = 4194304;
161
162
/// Cache `readlink` responses.
163
const CACHE_SYMLINKS: u64 = 8388608;
164
165
/// Kernel supports zero-message opens for directories.
166
const NO_OPENDIR_SUPPORT: u64 = 16777216;
167
168
/// Kernel supports explicit cache invalidation.
169
const EXPLICIT_INVAL_DATA: u64 = 33554432;
170
171
/// The `map_alignment` field of the `InitOut` struct is valid.
172
const MAP_ALIGNMENT: u64 = 67108864;
173
174
/// Extended fuse_init_in request to hold additional flags
175
const INIT_EXT: u64 = 1073741824;
176
177
/// The client should send the security context along with open, mkdir, create, and symlink
178
/// requests.
179
const SECURITY_CONTEXT: u64 = 4294967296;
180
181
bitflags! {
182
/// A bitfield passed in as a parameter to and returned from the `init` method of the
183
/// `FileSystem` trait.
184
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
185
#[repr(transparent)]
186
pub struct FsOptions: u64 {
187
/// Indicates that the filesystem supports asynchronous read requests.
188
///
189
/// If this capability is not requested/available, the kernel will ensure that there is at
190
/// most one pending read request per file-handle at any time, and will attempt to order
191
/// read requests by increasing offset.
192
///
193
/// This feature is enabled by default when supported by the kernel.
194
const ASYNC_READ = ASYNC_READ;
195
196
/// Indicates that the filesystem supports "remote" locking.
197
///
198
/// This feature is not enabled by default and should only be set if the filesystem
199
/// implements the `getlk` and `setlk` methods of the `FileSystem` trait.
200
const POSIX_LOCKS = POSIX_LOCKS;
201
202
/// Kernel sends file handle for fstat, etc... (not yet supported).
203
const FILE_OPS = FILE_OPS;
204
205
/// Indicates that the filesystem supports the `O_TRUNC` open flag. If disabled, and an
206
/// application specifies `O_TRUNC`, fuse first calls `setattr` to truncate the file and
207
/// then calls `open` with `O_TRUNC` filtered out.
208
///
209
/// This feature is enabled by default when supported by the kernel.
210
const ATOMIC_O_TRUNC = ATOMIC_O_TRUNC;
211
212
/// Indicates that the filesystem supports lookups of "." and "..".
213
///
214
/// This feature is disabled by default.
215
const EXPORT_SUPPORT = EXPORT_SUPPORT;
216
217
/// FileSystem can handle write size larger than 4kB.
218
const BIG_WRITES = BIG_WRITES;
219
220
/// Indicates that the kernel should not apply the umask to the file mode on create
221
/// operations.
222
///
223
/// This feature is disabled by default.
224
const DONT_MASK = DONT_MASK;
225
226
/// Indicates that the server should try to use `splice(2)` when writing to the fuse device.
227
/// This may improve performance.
228
///
229
/// This feature is not currently supported.
230
const SPLICE_WRITE = SPLICE_WRITE;
231
232
/// Indicates that the server should try to move pages instead of copying when writing to /
233
/// reading from the fuse device. This may improve performance.
234
///
235
/// This feature is not currently supported.
236
const SPLICE_MOVE = SPLICE_MOVE;
237
238
/// Indicates that the server should try to use `splice(2)` when reading from the fuse
239
/// device. This may improve performance.
240
///
241
/// This feature is not currently supported.
242
const SPLICE_READ = SPLICE_READ;
243
244
/// If set, then calls to `flock` will be emulated using POSIX locks and must
245
/// then be handled by the filesystem's `setlock()` handler.
246
///
247
/// If not set, `flock` calls will be handled by the FUSE kernel module internally (so any
248
/// access that does not go through the kernel cannot be taken into account).
249
///
250
/// This feature is disabled by default.
251
const FLOCK_LOCKS = FLOCK_LOCKS;
252
253
/// Indicates that the filesystem supports ioctl's on directories.
254
///
255
/// This feature is enabled by default when supported by the kernel.
256
const HAS_IOCTL_DIR = HAS_IOCTL_DIR;
257
258
/// Traditionally, while a file is open the FUSE kernel module only asks the filesystem for
259
/// an update of the file's attributes when a client attempts to read beyond EOF. This is
260
/// unsuitable for e.g. network filesystems, where the file contents may change without the
261
/// kernel knowing about it.
262
///
263
/// If this flag is set, FUSE will check the validity of the attributes on every read. If
264
/// the attributes are no longer valid (i.e., if the *attribute* timeout has expired) then
265
/// FUSE will first send another `getattr` request. If the new mtime differs from the
266
/// previous value, any cached file *contents* will be invalidated as well.
267
///
268
/// This flag should always be set when available. If all file changes go through the
269
/// kernel, *attribute* validity should be set to a very large number to avoid unnecessary
270
/// `getattr()` calls.
271
///
272
/// This feature is enabled by default when supported by the kernel.
273
const AUTO_INVAL_DATA = AUTO_INVAL_DATA;
274
275
/// Indicates that the filesystem supports readdirplus.
276
///
277
/// The feature is not enabled by default and should only be set if the filesystem
278
/// implements the `readdirplus` method of the `FileSystem` trait.
279
const DO_READDIRPLUS = DO_READDIRPLUS;
280
281
/// Indicates that the filesystem supports adaptive readdirplus.
282
///
283
/// If `DO_READDIRPLUS` is not set, this flag has no effect.
284
///
285
/// If `DO_READDIRPLUS` is set and this flag is not set, the kernel will always issue
286
/// `readdirplus()` requests to retrieve directory contents.
287
///
288
/// If `DO_READDIRPLUS` is set and this flag is set, the kernel will issue both `readdir()`
289
/// and `readdirplus()` requests, depending on how much information is expected to be
290
/// required.
291
///
292
/// This feature is not enabled by default and should only be set if the file system
293
/// implements both the `readdir` and `readdirplus` methods of the `FileSystem` trait.
294
const READDIRPLUS_AUTO = READDIRPLUS_AUTO;
295
296
/// Indicates that the filesystem supports asynchronous direct I/O submission.
297
///
298
/// If this capability is not requested/available, the kernel will ensure that there is at
299
/// most one pending read and one pending write request per direct I/O file-handle at any
300
/// time.
301
///
302
/// This feature is enabled by default when supported by the kernel.
303
const ASYNC_DIO = ASYNC_DIO;
304
305
/// Indicates that writeback caching should be enabled. This means that individual write
306
/// request may be buffered and merged in the kernel before they are sent to the file
307
/// system.
308
///
309
/// This feature is disabled by default.
310
const WRITEBACK_CACHE = WRITEBACK_CACHE;
311
312
/// Indicates support for zero-message opens. If this flag is set in the `capable` parameter
313
/// of the `init` trait method, then the file system may return `ENOSYS` from the open() handler
314
/// to indicate success. Further attempts to open files will be handled in the kernel. (If
315
/// this flag is not set, returning ENOSYS will be treated as an error and signaled to the
316
/// caller).
317
///
318
/// Setting (or not setting) the field in the `FsOptions` returned from the `init` method
319
/// has no effect.
320
const ZERO_MESSAGE_OPEN = NO_OPEN_SUPPORT;
321
322
/// Indicates support for parallel directory operations. If this flag is unset, the FUSE
323
/// kernel module will ensure that lookup() and readdir() requests are never issued
324
/// concurrently for the same directory.
325
///
326
/// This feature is enabled by default when supported by the kernel.
327
const PARALLEL_DIROPS = PARALLEL_DIROPS;
328
329
/// Indicates that the file system is responsible for unsetting setuid and setgid bits when a
330
/// file is written, truncated, or its owner is changed.
331
///
332
/// This feature is enabled by default when supported by the kernel.
333
const HANDLE_KILLPRIV = HANDLE_KILLPRIV;
334
335
/// Indicates support for POSIX ACLs.
336
///
337
/// If this feature is enabled, the kernel will cache and have responsibility for enforcing
338
/// ACLs. ACL will be stored as xattrs and passed to userspace, which is responsible for
339
/// updating the ACLs in the filesystem, keeping the file mode in sync with the ACL, and
340
/// ensuring inheritance of default ACLs when new filesystem nodes are created. Note that
341
/// this requires that the file system is able to parse and interpret the xattr
342
/// representation of ACLs.
343
///
344
/// Enabling this feature implicitly turns on the `default_permissions` mount option (even
345
/// if it was not passed to mount(2)).
346
///
347
/// This feature is disabled by default.
348
const POSIX_ACL = POSIX_ACL;
349
350
/// Indicates that the kernel may cache responses to `readlink` calls.
351
const CACHE_SYMLINKS = CACHE_SYMLINKS;
352
353
/// Indicates support for zero-message opens for directories. If this flag is set in the
354
/// `capable` parameter of the `init` trait method, then the file system may return `ENOSYS`
355
/// from the opendir() handler to indicate success. Further attempts to open directories
356
/// will be handled in the kernel. (If this flag is not set, returning ENOSYS will be
357
/// treated as an error and signaled to the caller).
358
///
359
/// Setting (or not setting) the field in the `FsOptions` returned from the `init` method
360
/// has no effect.
361
const ZERO_MESSAGE_OPENDIR = NO_OPENDIR_SUPPORT;
362
363
/// Indicates support for invalidating cached pages only on explicit request.
364
///
365
/// If this flag is set in the `capable` parameter of the `init` trait method, then the FUSE
366
/// kernel module supports invalidating cached pages only on explicit request by the
367
/// filesystem.
368
///
369
/// By setting this flag in the return value of the `init` trait method, the filesystem is
370
/// responsible for invalidating cached pages through explicit requests to the kernel.
371
///
372
/// Note that setting this flag does not prevent the cached pages from being flushed by OS
373
/// itself and/or through user actions.
374
///
375
/// Note that if both EXPLICIT_INVAL_DATA and AUTO_INVAL_DATA are set in the `capable`
376
/// parameter of the `init` trait method then AUTO_INVAL_DATA takes precedence.
377
///
378
/// This feature is disabled by default.
379
const EXPLICIT_INVAL_DATA = EXPLICIT_INVAL_DATA;
380
381
/// Indicates that the `map_alignment` field of the `InitOut` struct is valid.
382
///
383
/// The `MAP_ALIGNMENT` field is used by the FUSE kernel driver to ensure that its DAX
384
/// mapping requests are pagesize-aligned. This field automatically set by the server and
385
/// this feature is enabled by default.
386
const MAP_ALIGNMENT = MAP_ALIGNMENT;
387
388
/// Indicates that the `max_pages` field of the `InitOut` struct is valid.
389
///
390
/// This field is used by the kernel driver to determine the maximum number of pages that
391
/// may be used for any read or write requests.
392
const MAX_PAGES = MAX_PAGES;
393
394
/// Indicates that `InitIn`/`InitOut` struct is extended to hold additional flags.
395
const INIT_EXT = INIT_EXT;
396
397
/// Indicates support for sending the security context with creation requests.
398
const SECURITY_CONTEXT = SECURITY_CONTEXT;
399
}
400
}
401
402
// Release flags.
403
pub const RELEASE_FLUSH: u32 = 1;
404
pub const RELEASE_FLOCK_UNLOCK: u32 = 2;
405
406
// Getattr flags.
407
pub const GETATTR_FH: u32 = 1;
408
409
// Lock flags.
410
pub const LK_FLOCK: u32 = 1;
411
412
// Write flags.
413
414
/// Delayed write from page cache, file handle is guessed.
415
pub const WRITE_CACHE: u32 = 1;
416
417
/// `lock_owner` field is valid.
418
pub const WRITE_LOCKOWNER: u32 = 2;
419
420
/// Kill the suid and sgid bits.
421
pub const WRITE_KILL_PRIV: u32 = 3;
422
423
// Read flags.
424
pub const READ_LOCKOWNER: u32 = 2;
425
426
// Ioctl flags.
427
428
/// 32bit compat ioctl on 64bit machine
429
const IOCTL_COMPAT: u32 = 1;
430
431
/// Not restricted to well-formed ioctls, retry allowed
432
const IOCTL_UNRESTRICTED: u32 = 2;
433
434
/// Retry with new iovecs
435
const IOCTL_RETRY: u32 = 4;
436
437
/// 32bit ioctl
438
const IOCTL_32BIT: u32 = 8;
439
440
/// Is a directory
441
const IOCTL_DIR: u32 = 16;
442
443
/// 32-bit compat ioctl on 64-bit machine with 64-bit time_t.
444
const IOCTL_COMPAT_X32: u32 = 32;
445
446
/// Maximum of in_iovecs + out_iovecs
447
pub const IOCTL_MAX_IOV: usize = 256;
448
449
bitflags! {
450
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
451
#[repr(transparent)]
452
pub struct IoctlFlags: u32 {
453
/// 32bit compat ioctl on 64bit machine
454
const COMPAT = IOCTL_COMPAT;
455
456
/// Not restricted to well-formed ioctls, retry allowed
457
const UNRESTRICTED = IOCTL_UNRESTRICTED;
458
459
/// Retry with new iovecs
460
const RETRY = IOCTL_RETRY;
461
462
/// 32bit ioctl
463
const IOCTL_32BIT = IOCTL_32BIT;
464
465
/// Is a directory
466
const DIR = IOCTL_DIR;
467
468
/// 32-bit compat ioctl on 64-bit machine with 64-bit time_t.
469
const COMPAT_X32 = IOCTL_COMPAT_X32;
470
}
471
}
472
473
/// Request poll notify.
474
pub const POLL_SCHEDULE_NOTIFY: u32 = 1;
475
476
/// The read buffer is required to be at least 8k, but may be much larger.
477
pub const FUSE_MIN_READ_BUFFER: u32 = 8192;
478
479
pub const FUSE_COMPAT_ENTRY_OUT_SIZE: u32 = 120;
480
pub const FUSE_COMPAT_ATTR_OUT_SIZE: u32 = 96;
481
pub const FUSE_COMPAT_MKNOD_IN_SIZE: u32 = 8;
482
pub const FUSE_COMPAT_WRITE_IN_SIZE: u32 = 24;
483
pub const FUSE_COMPAT_STATFS_SIZE: u32 = 48;
484
pub const FUSE_COMPAT_INIT_OUT_SIZE: u32 = 8;
485
pub const FUSE_COMPAT_22_INIT_OUT_SIZE: u32 = 24;
486
487
const SETUPMAPPING_FLAG_WRITE: u64 = 1;
488
const SETUPMAPPING_FLAG_READ: u64 = 2;
489
490
bitflags! {
491
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
492
#[repr(transparent)]
493
pub struct SetUpMappingFlags: u64 {
494
/// Create writable mapping.
495
const WRITE = SETUPMAPPING_FLAG_WRITE;
496
/// Create readable mapping.
497
const READ = SETUPMAPPING_FLAG_READ;
498
}
499
}
500
501
// Request Extension Constants
502
/// Maximum security contexts in a request
503
pub const MAX_NR_SECCTX: u32 = 31;
504
505
#[repr(C)]
506
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
507
pub struct Attr {
508
pub ino: u64,
509
pub size: u64,
510
pub blocks: u64,
511
pub atime: u64,
512
pub mtime: u64,
513
pub ctime: u64,
514
pub atimensec: u32,
515
pub mtimensec: u32,
516
pub ctimensec: u32,
517
pub mode: u32,
518
pub nlink: u32,
519
pub uid: u32,
520
pub gid: u32,
521
pub rdev: u32,
522
pub blksize: u32,
523
pub padding: u32,
524
}
525
526
impl From<libc::stat64> for Attr {
527
fn from(st: libc::stat64) -> Attr {
528
Attr {
529
ino: st.st_ino,
530
size: st.st_size as u64,
531
blocks: st.st_blocks as u64,
532
atime: st.st_atime as u64,
533
mtime: st.st_mtime as u64,
534
ctime: st.st_ctime as u64,
535
atimensec: st.st_atime_nsec as u32,
536
mtimensec: st.st_mtime_nsec as u32,
537
ctimensec: st.st_ctime_nsec as u32,
538
mode: st.st_mode,
539
#[allow(clippy::unnecessary_cast)]
540
nlink: st.st_nlink as u32,
541
uid: st.st_uid,
542
gid: st.st_gid,
543
rdev: st.st_rdev as u32,
544
blksize: st.st_blksize as u32,
545
..Default::default()
546
}
547
}
548
}
549
550
#[repr(C)]
551
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
552
pub struct Kstatfs {
553
pub blocks: u64,
554
pub bfree: u64,
555
pub bavail: u64,
556
pub files: u64,
557
pub ffree: u64,
558
pub bsize: u32,
559
pub namelen: u32,
560
pub frsize: u32,
561
pub padding: u32,
562
pub spare: [u32; 6],
563
}
564
565
impl From<libc::statvfs64> for Kstatfs {
566
#[allow(clippy::unnecessary_cast)]
567
fn from(st: libc::statvfs64) -> Self {
568
Kstatfs {
569
blocks: st.f_blocks,
570
bfree: st.f_bfree,
571
bavail: st.f_bavail,
572
files: st.f_files,
573
ffree: st.f_ffree,
574
bsize: st.f_bsize as u32,
575
namelen: st.f_namemax as u32,
576
frsize: st.f_frsize as u32,
577
..Default::default()
578
}
579
}
580
}
581
582
#[repr(C)]
583
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
584
pub struct FileLock {
585
pub start: u64,
586
pub end: u64,
587
pub type_: u32,
588
pub pid: u32, /* tgid */
589
}
590
591
#[repr(u32)]
592
#[derive(Debug, Copy, Clone, N, IntoBytes, Immutable, KnownLayout, TryFromBytes)]
593
pub enum Opcode {
594
Lookup = 1,
595
Forget = 2, /* No Reply */
596
Getattr = 3,
597
Setattr = 4,
598
Readlink = 5,
599
Symlink = 6,
600
Mknod = 8,
601
Mkdir = 9,
602
Unlink = 10,
603
Rmdir = 11,
604
Rename = 12,
605
Link = 13,
606
Open = 14,
607
Read = 15,
608
Write = 16,
609
Statfs = 17,
610
Release = 18,
611
Fsync = 20,
612
Setxattr = 21,
613
Getxattr = 22,
614
Listxattr = 23,
615
Removexattr = 24,
616
Flush = 25,
617
Init = 26,
618
Opendir = 27,
619
Readdir = 28,
620
Releasedir = 29,
621
Fsyncdir = 30,
622
Getlk = 31,
623
Setlk = 32,
624
Setlkw = 33,
625
Access = 34,
626
Create = 35,
627
Interrupt = 36,
628
Bmap = 37,
629
Destroy = 38,
630
Ioctl = 39,
631
Poll = 40,
632
NotifyReply = 41,
633
BatchForget = 42,
634
Fallocate = 43,
635
Readdirplus = 44,
636
Rename2 = 45,
637
Lseek = 46,
638
CopyFileRange = 47,
639
SetUpMapping = 48,
640
RemoveMapping = 49,
641
// TODO(b/310102543): Update the opcode keep same with kernel patch after the atomic open
642
// kernel is merged to upstream.
643
OpenAtomic = u32::MAX - 1,
644
ChromeOsTmpfile = u32::MAX,
645
}
646
647
#[repr(u32)]
648
#[derive(Debug, Copy, Clone, N)]
649
pub enum NotifyOpcode {
650
Poll = 1,
651
InvalInode = 2,
652
InvalEntry = 3,
653
Store = 4,
654
Retrieve = 5,
655
Delete = 6,
656
CodeMax = 7,
657
}
658
659
#[repr(C)]
660
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
661
pub struct EntryOut {
662
pub nodeid: u64, /* Inode ID */
663
pub generation: u64, /* Inode generation: nodeid:gen must be unique for the fs's lifetime */
664
pub entry_valid: u64, /* Cache timeout for the name */
665
pub attr_valid: u64, /* Cache timeout for the attributes */
666
pub entry_valid_nsec: u32,
667
pub attr_valid_nsec: u32,
668
pub attr: Attr,
669
}
670
671
#[repr(C)]
672
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
673
pub struct ForgetIn {
674
pub nlookup: u64,
675
}
676
677
#[repr(C)]
678
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
679
pub struct ForgetOne {
680
pub nodeid: u64,
681
pub nlookup: u64,
682
}
683
684
#[repr(C)]
685
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
686
pub struct BatchForgetIn {
687
pub count: u32,
688
pub dummy: u32,
689
}
690
691
#[repr(C)]
692
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
693
pub struct GetattrIn {
694
pub flags: u32,
695
pub dummy: u32,
696
pub fh: u64,
697
}
698
699
#[repr(C)]
700
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
701
pub struct AttrOut {
702
pub attr_valid: u64, /* Cache timeout for the attributes */
703
pub attr_valid_nsec: u32,
704
pub dummy: u32,
705
pub attr: Attr,
706
}
707
708
#[repr(C)]
709
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
710
pub struct MknodIn {
711
pub mode: u32,
712
pub rdev: u32,
713
pub umask: u32,
714
pub padding: u32,
715
}
716
717
#[repr(C)]
718
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
719
pub struct MkdirIn {
720
pub mode: u32,
721
pub umask: u32,
722
}
723
724
#[repr(C)]
725
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
726
pub struct ChromeOsTmpfileIn {
727
pub mode: u32,
728
pub umask: u32,
729
}
730
731
#[repr(C)]
732
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
733
pub struct RenameIn {
734
pub newdir: u64,
735
}
736
737
#[repr(C)]
738
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
739
pub struct Rename2In {
740
pub newdir: u64,
741
pub flags: u32,
742
pub padding: u32,
743
}
744
745
#[repr(C)]
746
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
747
pub struct LinkIn {
748
pub oldnodeid: u64,
749
}
750
751
#[repr(C)]
752
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
753
pub struct SetattrIn {
754
pub valid: u32,
755
pub padding: u32,
756
pub fh: u64,
757
pub size: u64,
758
pub lock_owner: u64,
759
pub atime: u64,
760
pub mtime: u64,
761
pub ctime: u64,
762
pub atimensec: u32,
763
pub mtimensec: u32,
764
pub ctimensec: u32,
765
pub mode: u32,
766
pub unused4: u32,
767
pub uid: u32,
768
pub gid: u32,
769
pub unused5: u32,
770
}
771
772
impl From<SetattrIn> for libc::stat64 {
773
fn from(s: SetattrIn) -> libc::stat64 {
774
// SAFETY: zero-initializing a struct with only POD fields.
775
let mut out: libc::stat64 = unsafe { mem::zeroed() };
776
out.st_mode = s.mode;
777
out.st_uid = s.uid;
778
out.st_gid = s.gid;
779
out.st_size = s.size as i64;
780
out.st_atime = s.atime as libc::time_t;
781
out.st_mtime = s.mtime as libc::time_t;
782
out.st_ctime = s.ctime as libc::time_t;
783
out.st_atime_nsec = s.atimensec as libc::c_long;
784
out.st_mtime_nsec = s.mtimensec as libc::c_long;
785
out.st_ctime_nsec = s.ctimensec as libc::c_long;
786
787
out
788
}
789
}
790
791
#[repr(C)]
792
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
793
pub struct OpenIn {
794
pub flags: u32,
795
pub unused: u32,
796
}
797
798
#[repr(C)]
799
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
800
pub struct CreateIn {
801
pub flags: u32,
802
pub mode: u32,
803
pub umask: u32,
804
pub padding: u32,
805
}
806
807
#[repr(C)]
808
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
809
pub struct OpenOut {
810
pub fh: u64,
811
pub open_flags: u32,
812
pub padding: u32,
813
}
814
815
#[repr(C)]
816
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
817
pub struct ReleaseIn {
818
pub fh: u64,
819
pub flags: u32,
820
pub release_flags: u32,
821
pub lock_owner: u64,
822
}
823
824
#[repr(C)]
825
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
826
pub struct FlushIn {
827
pub fh: u64,
828
pub unused: u32,
829
pub padding: u32,
830
pub lock_owner: u64,
831
}
832
833
#[repr(C)]
834
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
835
pub struct ReadIn {
836
pub fh: u64,
837
pub offset: u64,
838
pub size: u32,
839
pub read_flags: u32,
840
pub lock_owner: u64,
841
pub flags: u32,
842
pub padding: u32,
843
}
844
845
#[repr(C)]
846
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
847
pub struct WriteIn {
848
pub fh: u64,
849
pub offset: u64,
850
pub size: u32,
851
pub write_flags: u32,
852
pub lock_owner: u64,
853
pub flags: u32,
854
pub padding: u32,
855
}
856
857
#[repr(C)]
858
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
859
pub struct WriteOut {
860
pub size: u32,
861
pub padding: u32,
862
}
863
864
#[repr(C)]
865
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
866
pub struct StatfsOut {
867
pub st: Kstatfs,
868
}
869
870
#[repr(C)]
871
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
872
pub struct FsyncIn {
873
pub fh: u64,
874
pub fsync_flags: u32,
875
pub padding: u32,
876
}
877
878
#[repr(C)]
879
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
880
pub struct SetxattrIn {
881
pub size: u32,
882
pub flags: u32,
883
}
884
885
#[repr(C)]
886
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
887
pub struct GetxattrIn {
888
pub size: u32,
889
pub padding: u32,
890
}
891
892
#[repr(C)]
893
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
894
pub struct GetxattrOut {
895
pub size: u32,
896
pub padding: u32,
897
}
898
899
#[repr(C)]
900
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
901
pub struct LkIn {
902
pub fh: u64,
903
pub owner: u64,
904
pub lk: FileLock,
905
pub lk_flags: u32,
906
pub padding: u32,
907
}
908
909
#[repr(C)]
910
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
911
pub struct LkOut {
912
pub lk: FileLock,
913
}
914
915
#[repr(C)]
916
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
917
pub struct AccessIn {
918
pub mask: u32,
919
pub padding: u32,
920
}
921
922
#[repr(C)]
923
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
924
pub struct InitIn {
925
pub major: u32,
926
pub minor: u32,
927
pub max_readahead: u32,
928
pub flags: u32,
929
}
930
931
#[repr(C)]
932
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
933
pub struct InitInExt {
934
pub flags2: u32,
935
pub unused: [u32; 11],
936
}
937
938
#[repr(C)]
939
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
940
pub struct InitOut {
941
pub major: u32,
942
pub minor: u32,
943
pub max_readahead: u32,
944
pub flags: u32,
945
pub max_background: u16,
946
pub congestion_threshold: u16,
947
pub max_write: u32,
948
pub time_gran: u32,
949
pub max_pages: u16,
950
pub map_alignment: u16,
951
pub flags2: u32,
952
pub unused: [u32; 7],
953
}
954
955
#[repr(C)]
956
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
957
pub struct InterruptIn {
958
pub unique: u64,
959
}
960
961
#[repr(C)]
962
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
963
pub struct BmapIn {
964
pub block: u64,
965
pub blocksize: u32,
966
pub padding: u32,
967
}
968
969
#[repr(C)]
970
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
971
pub struct BmapOut {
972
pub block: u64,
973
}
974
975
#[repr(C)]
976
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
977
pub struct IoctlIn {
978
pub fh: u64,
979
pub flags: u32,
980
pub cmd: u32,
981
pub arg: u64,
982
pub in_size: u32,
983
pub out_size: u32,
984
}
985
986
/// Describes a region of memory in the address space of the process that made the ioctl syscall.
987
/// Similar to `libc::iovec` but uses `u64`s for the address and the length.
988
#[repr(C)]
989
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
990
pub struct IoctlIovec {
991
/// The start address of the memory region. This must be in the address space of the process
992
/// that made the ioctl syscall.
993
pub base: u64,
994
995
/// The length of the memory region.
996
pub len: u64,
997
}
998
999
#[repr(C)]
1000
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
1001
pub struct IoctlOut {
1002
pub result: i32,
1003
pub flags: u32,
1004
pub in_iovs: u32,
1005
pub out_iovs: u32,
1006
}
1007
1008
#[repr(C)]
1009
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
1010
pub struct PollIn {
1011
pub fh: u64,
1012
pub kh: u64,
1013
pub flags: u32,
1014
pub events: u32,
1015
}
1016
1017
#[repr(C)]
1018
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
1019
pub struct PollOut {
1020
pub revents: u32,
1021
pub padding: u32,
1022
}
1023
1024
#[repr(C)]
1025
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
1026
pub struct NotifyPollWakeupOut {
1027
pub kh: u64,
1028
}
1029
1030
#[repr(C)]
1031
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
1032
pub struct FallocateIn {
1033
pub fh: u64,
1034
pub offset: u64,
1035
pub length: u64,
1036
pub mode: u32,
1037
pub padding: u32,
1038
}
1039
1040
#[repr(C)]
1041
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
1042
pub struct InHeader {
1043
pub len: u32,
1044
pub opcode: u32,
1045
pub unique: u64,
1046
pub nodeid: u64,
1047
pub uid: u32,
1048
pub gid: u32,
1049
pub pid: u32,
1050
pub padding: u32,
1051
}
1052
1053
#[repr(C)]
1054
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
1055
pub struct OutHeader {
1056
pub len: u32,
1057
pub error: i32,
1058
pub unique: u64,
1059
}
1060
1061
#[repr(C)]
1062
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
1063
pub struct Dirent {
1064
pub ino: u64,
1065
pub off: u64,
1066
pub namelen: u32,
1067
pub type_: u32,
1068
// char name[];
1069
}
1070
1071
#[repr(C)]
1072
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
1073
pub struct Direntplus {
1074
pub entry_out: EntryOut,
1075
pub dirent: Dirent,
1076
}
1077
1078
#[repr(C)]
1079
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
1080
pub struct NotifyInvalInodeOut {
1081
pub ino: u64,
1082
pub off: i64,
1083
pub len: i64,
1084
}
1085
1086
#[repr(C)]
1087
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
1088
pub struct NotifyInvalEntryOut {
1089
pub parent: u64,
1090
pub namelen: u32,
1091
pub padding: u32,
1092
}
1093
1094
#[repr(C)]
1095
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
1096
pub struct NotifyDeleteOut {
1097
pub parent: u64,
1098
pub child: u64,
1099
pub namelen: u32,
1100
pub padding: u32,
1101
}
1102
1103
#[repr(C)]
1104
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
1105
pub struct NotifyStoreOut {
1106
pub nodeid: u64,
1107
pub offset: u64,
1108
pub size: u32,
1109
pub padding: u32,
1110
}
1111
1112
#[repr(C)]
1113
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
1114
pub struct Notify_Retrieve_Out {
1115
pub notify_unique: u64,
1116
pub nodeid: u64,
1117
pub offset: u64,
1118
pub size: u32,
1119
pub padding: u32,
1120
}
1121
1122
/* Matches the size of fuse_write_in */
1123
#[repr(C)]
1124
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
1125
pub struct NotifyRetrieveIn {
1126
pub dummy1: u64,
1127
pub offset: u64,
1128
pub size: u32,
1129
pub dummy2: u32,
1130
pub dummy3: u64,
1131
pub dummy4: u64,
1132
}
1133
1134
#[repr(C)]
1135
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
1136
pub struct LseekIn {
1137
pub fh: u64,
1138
pub offset: u64,
1139
pub whence: u32,
1140
pub padding: u32,
1141
}
1142
1143
#[repr(C)]
1144
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
1145
pub struct LseekOut {
1146
pub offset: u64,
1147
}
1148
1149
#[repr(C)]
1150
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
1151
pub struct CopyFileRangeIn {
1152
pub fh_src: u64,
1153
pub off_src: u64,
1154
pub nodeid_dst: u64,
1155
pub fh_dst: u64,
1156
pub off_dst: u64,
1157
pub len: u64,
1158
pub flags: u64,
1159
}
1160
1161
#[repr(C)]
1162
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
1163
pub struct SetUpMappingIn {
1164
/* An already open handle */
1165
pub fh: u64,
1166
/* Offset into the file to start the mapping */
1167
pub foffset: u64,
1168
/* Length of mapping required */
1169
pub len: u64,
1170
/* Flags, FUSE_SETUPMAPPING_FLAG_* */
1171
pub flags: u64,
1172
/* Offset in Memory Window */
1173
pub moffset: u64,
1174
}
1175
1176
#[repr(C)]
1177
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
1178
pub struct RemoveMappingIn {
1179
/* number of fuse_removemapping_one follows */
1180
pub count: u32,
1181
}
1182
1183
#[repr(C)]
1184
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
1185
pub struct RemoveMappingOne {
1186
/* Offset into the dax window start the unmapping */
1187
pub moffset: u64,
1188
/* Length of mapping required */
1189
pub len: u64,
1190
}
1191
1192
/// For each security context, send fuse_secctx with size of security context
1193
/// fuse_secctx will be followed by security context name and this in turn
1194
/// will be followed by actual context label.
1195
/// fuse_secctx, name, context
1196
#[repr(C)]
1197
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
1198
pub struct Secctx {
1199
pub size: u32,
1200
pub padding: u32,
1201
}
1202
1203
/// Contains the information about how many fuse_secctx structures are being
1204
/// sent and what's the total size of all security contexts (including
1205
/// size of fuse_secctx_header).
1206
#[repr(C)]
1207
#[derive(Debug, Default, Copy, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
1208
pub struct SecctxHeader {
1209
pub size: u32,
1210
pub nr_secctx: u32,
1211
}
1212
1213