github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/abi/linux/fuse.go (about) 1 // Copyright 2020 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package linux 16 17 import ( 18 "github.com/SagerNet/gvisor/pkg/marshal" 19 "github.com/SagerNet/gvisor/pkg/marshal/primitive" 20 ) 21 22 // FUSEOpcode is a FUSE operation code. 23 // 24 // +marshal 25 type FUSEOpcode uint32 26 27 // FUSEOpID is a FUSE operation ID. 28 // 29 // +marshal 30 type FUSEOpID uint64 31 32 // FUSE_ROOT_ID is the id of root inode. 33 const FUSE_ROOT_ID = 1 34 35 // Opcodes for FUSE operations. 36 // 37 // Analogous to the opcodes in include/linux/fuse.h. 38 const ( 39 FUSE_LOOKUP FUSEOpcode = 1 40 FUSE_FORGET = 2 /* no reply */ 41 FUSE_GETATTR = 3 42 FUSE_SETATTR = 4 43 FUSE_READLINK = 5 44 FUSE_SYMLINK = 6 45 _ 46 FUSE_MKNOD = 8 47 FUSE_MKDIR = 9 48 FUSE_UNLINK = 10 49 FUSE_RMDIR = 11 50 FUSE_RENAME = 12 51 FUSE_LINK = 13 52 FUSE_OPEN = 14 53 FUSE_READ = 15 54 FUSE_WRITE = 16 55 FUSE_STATFS = 17 56 FUSE_RELEASE = 18 57 _ 58 FUSE_FSYNC = 20 59 FUSE_SETXATTR = 21 60 FUSE_GETXATTR = 22 61 FUSE_LISTXATTR = 23 62 FUSE_REMOVEXATTR = 24 63 FUSE_FLUSH = 25 64 FUSE_INIT = 26 65 FUSE_OPENDIR = 27 66 FUSE_READDIR = 28 67 FUSE_RELEASEDIR = 29 68 FUSE_FSYNCDIR = 30 69 FUSE_GETLK = 31 70 FUSE_SETLK = 32 71 FUSE_SETLKW = 33 72 FUSE_ACCESS = 34 73 FUSE_CREATE = 35 74 FUSE_INTERRUPT = 36 75 FUSE_BMAP = 37 76 FUSE_DESTROY = 38 77 FUSE_IOCTL = 39 78 FUSE_POLL = 40 79 FUSE_NOTIFY_REPLY = 41 80 FUSE_BATCH_FORGET = 42 81 ) 82 83 const ( 84 // FUSE_MIN_READ_BUFFER is the minimum size the read can be for any FUSE filesystem. 85 // This is the minimum size Linux supports. See linux.fuse.h. 86 FUSE_MIN_READ_BUFFER uint32 = 8192 87 ) 88 89 // FUSEHeaderIn is the header read by the daemon with each request. 90 // 91 // +marshal 92 type FUSEHeaderIn struct { 93 // Len specifies the total length of the data, including this header. 94 Len uint32 95 96 // Opcode specifies the kind of operation of the request. 97 Opcode FUSEOpcode 98 99 // Unique specifies the unique identifier for this request. 100 Unique FUSEOpID 101 102 // NodeID is the ID of the filesystem object being operated on. 103 NodeID uint64 104 105 // UID is the UID of the requesting process. 106 UID uint32 107 108 // GID is the GID of the requesting process. 109 GID uint32 110 111 // PID is the PID of the requesting process. 112 PID uint32 113 114 _ uint32 115 } 116 117 // FUSEHeaderOut is the header written by the daemon when it processes 118 // a request and wants to send a reply (almost all operations require a 119 // reply; if they do not, this will be explicitly documented). 120 // 121 // +marshal 122 type FUSEHeaderOut struct { 123 // Len specifies the total length of the data, including this header. 124 Len uint32 125 126 // Error specifies the error that occurred (0 if none). 127 Error int32 128 129 // Unique specifies the unique identifier of the corresponding request. 130 Unique FUSEOpID 131 } 132 133 // FUSE_INIT flags, consistent with the ones in include/uapi/linux/fuse.h. 134 // Our taget version is 7.23 but we have few implemented in advance. 135 const ( 136 FUSE_ASYNC_READ = 1 << 0 137 FUSE_POSIX_LOCKS = 1 << 1 138 FUSE_FILE_OPS = 1 << 2 139 FUSE_ATOMIC_O_TRUNC = 1 << 3 140 FUSE_EXPORT_SUPPORT = 1 << 4 141 FUSE_BIG_WRITES = 1 << 5 142 FUSE_DONT_MASK = 1 << 6 143 FUSE_SPLICE_WRITE = 1 << 7 144 FUSE_SPLICE_MOVE = 1 << 8 145 FUSE_SPLICE_READ = 1 << 9 146 FUSE_FLOCK_LOCKS = 1 << 10 147 FUSE_HAS_IOCTL_DIR = 1 << 11 148 FUSE_AUTO_INVAL_DATA = 1 << 12 149 FUSE_DO_READDIRPLUS = 1 << 13 150 FUSE_READDIRPLUS_AUTO = 1 << 14 151 FUSE_ASYNC_DIO = 1 << 15 152 FUSE_WRITEBACK_CACHE = 1 << 16 153 FUSE_NO_OPEN_SUPPORT = 1 << 17 154 FUSE_MAX_PAGES = 1 << 22 // From FUSE 7.28 155 ) 156 157 // currently supported FUSE protocol version numbers. 158 const ( 159 FUSE_KERNEL_VERSION = 7 160 FUSE_KERNEL_MINOR_VERSION = 31 161 ) 162 163 // Constants relevant to FUSE operations. 164 const ( 165 FUSE_NAME_MAX = 1024 166 FUSE_PAGE_SIZE = 4096 167 FUSE_DIRENT_ALIGN = 8 168 ) 169 170 // FUSEInitIn is the request sent by the kernel to the daemon, 171 // to negotiate the version and flags. 172 // 173 // +marshal 174 type FUSEInitIn struct { 175 // Major version supported by kernel. 176 Major uint32 177 178 // Minor version supported by the kernel. 179 Minor uint32 180 181 // MaxReadahead is the maximum number of bytes to read-ahead 182 // decided by the kernel. 183 MaxReadahead uint32 184 185 // Flags of this init request. 186 Flags uint32 187 } 188 189 // FUSEInitOut is the reply sent by the daemon to the kernel 190 // for FUSEInitIn. We target FUSE 7.23; this struct supports 7.28. 191 // 192 // +marshal 193 type FUSEInitOut struct { 194 // Major version supported by daemon. 195 Major uint32 196 197 // Minor version supported by daemon. 198 Minor uint32 199 200 // MaxReadahead is the maximum number of bytes to read-ahead. 201 // Decided by the daemon, after receiving the value from kernel. 202 MaxReadahead uint32 203 204 // Flags of this init reply. 205 Flags uint32 206 207 // MaxBackground is the maximum number of pending background requests 208 // that the daemon wants. 209 MaxBackground uint16 210 211 // CongestionThreshold is the daemon-decided threshold for 212 // the number of the pending background requests. 213 CongestionThreshold uint16 214 215 // MaxWrite is the daemon's maximum size of a write buffer. 216 // Kernel adjusts it to the minimum (fuse/init.go:fuseMinMaxWrite). 217 // if the value from daemon is too small. 218 MaxWrite uint32 219 220 // TimeGran is the daemon's time granularity for mtime and ctime metadata. 221 // The unit is nanosecond. 222 // Value should be power of 10. 223 // 1 indicates full nanosecond granularity support. 224 TimeGran uint32 225 226 // MaxPages is the daemon's maximum number of pages for one write operation. 227 // Kernel adjusts it to the maximum (fuse/init.go:FUSE_MAX_MAX_PAGES). 228 // if the value from daemon is too large. 229 MaxPages uint16 230 231 _ uint16 232 233 _ [8]uint32 234 } 235 236 // FUSE_GETATTR_FH is currently the only flag of FUSEGetAttrIn.GetAttrFlags. 237 // If it is set, the file handle (FUSEGetAttrIn.Fh) is used to indicate the 238 // object instead of the node id attribute in the request header. 239 const FUSE_GETATTR_FH = (1 << 0) 240 241 // FUSEGetAttrIn is the request sent by the kernel to the daemon, 242 // to get the attribute of a inode. 243 // 244 // +marshal 245 type FUSEGetAttrIn struct { 246 // GetAttrFlags specifies whether getattr request is sent with a nodeid or 247 // with a file handle. 248 GetAttrFlags uint32 249 250 _ uint32 251 252 // Fh is the file handler when GetAttrFlags has FUSE_GETATTR_FH bit. If 253 // used, the operation is analogous to fstat(2). 254 Fh uint64 255 } 256 257 // FUSEAttr is the struct used in the reponse FUSEGetAttrOut. 258 // 259 // +marshal 260 type FUSEAttr struct { 261 // Ino is the inode number of this file. 262 Ino uint64 263 264 // Size is the size of this file. 265 Size uint64 266 267 // Blocks is the number of the 512B blocks allocated by this file. 268 Blocks uint64 269 270 // Atime is the time of last access. 271 Atime uint64 272 273 // Mtime is the time of last modification. 274 Mtime uint64 275 276 // Ctime is the time of last status change. 277 Ctime uint64 278 279 // AtimeNsec is the nano second part of Atime. 280 AtimeNsec uint32 281 282 // MtimeNsec is the nano second part of Mtime. 283 MtimeNsec uint32 284 285 // CtimeNsec is the nano second part of Ctime. 286 CtimeNsec uint32 287 288 // Mode contains the file type and mode. 289 Mode uint32 290 291 // Nlink is the number of the hard links. 292 Nlink uint32 293 294 // UID is user ID of the owner. 295 UID uint32 296 297 // GID is group ID of the owner. 298 GID uint32 299 300 // Rdev is the device ID if this is a special file. 301 Rdev uint32 302 303 // BlkSize is the block size for filesystem I/O. 304 BlkSize uint32 305 306 _ uint32 307 } 308 309 // FUSEGetAttrOut is the reply sent by the daemon to the kernel 310 // for FUSEGetAttrIn. 311 // 312 // +marshal 313 type FUSEGetAttrOut struct { 314 // AttrValid and AttrValidNsec describe the attribute cache duration 315 AttrValid uint64 316 317 // AttrValidNsec is the nanosecond part of the attribute cache duration 318 AttrValidNsec uint32 319 320 _ uint32 321 322 // Attr contains the metadata returned from the FUSE server 323 Attr FUSEAttr 324 } 325 326 // FUSEEntryOut is the reply sent by the daemon to the kernel 327 // for FUSE_MKNOD, FUSE_MKDIR, FUSE_SYMLINK, FUSE_LINK and 328 // FUSE_LOOKUP. 329 // 330 // +marshal 331 type FUSEEntryOut struct { 332 // NodeID is the ID for current inode. 333 NodeID uint64 334 335 // Generation is the generation number of inode. 336 // Used to identify an inode that have different ID at different time. 337 Generation uint64 338 339 // EntryValid indicates timeout for an entry. 340 EntryValid uint64 341 342 // AttrValid indicates timeout for an entry's attributes. 343 AttrValid uint64 344 345 // EntryValidNsec indicates timeout for an entry in nanosecond. 346 EntryValidNSec uint32 347 348 // AttrValidNsec indicates timeout for an entry's attributes in nanosecond. 349 AttrValidNSec uint32 350 351 // Attr contains the attributes of an entry. 352 Attr FUSEAttr 353 } 354 355 // FUSELookupIn is the request sent by the kernel to the daemon 356 // to look up a file name. 357 // 358 // Dynamically-sized objects cannot be marshalled. 359 type FUSELookupIn struct { 360 marshal.StubMarshallable 361 362 // Name is a file name to be looked up. 363 Name string 364 } 365 366 // MarshalBytes serializes r.name to the dst buffer. 367 func (r *FUSELookupIn) MarshalBytes(buf []byte) { 368 copy(buf, r.Name) 369 } 370 371 // SizeBytes is the size of the memory representation of FUSELookupIn. 372 // 1 extra byte for null-terminated string. 373 func (r *FUSELookupIn) SizeBytes() int { 374 return len(r.Name) + 1 375 } 376 377 // MAX_NON_LFS indicates the maximum offset without large file support. 378 const MAX_NON_LFS = ((1 << 31) - 1) 379 380 // flags returned by OPEN request. 381 const ( 382 // FOPEN_DIRECT_IO indicates bypassing page cache for this opened file. 383 FOPEN_DIRECT_IO = 1 << 0 384 // FOPEN_KEEP_CACHE avoids invalidate of data cache on open. 385 FOPEN_KEEP_CACHE = 1 << 1 386 // FOPEN_NONSEEKABLE indicates the file cannot be seeked. 387 FOPEN_NONSEEKABLE = 1 << 2 388 ) 389 390 // FUSEOpenIn is the request sent by the kernel to the daemon, 391 // to negotiate flags and get file handle. 392 // 393 // +marshal 394 type FUSEOpenIn struct { 395 // Flags of this open request. 396 Flags uint32 397 398 _ uint32 399 } 400 401 // FUSEOpenOut is the reply sent by the daemon to the kernel 402 // for FUSEOpenIn. 403 // 404 // +marshal 405 type FUSEOpenOut struct { 406 // Fh is the file handler for opened file. 407 Fh uint64 408 409 // OpenFlag for the opened file. 410 OpenFlag uint32 411 412 _ uint32 413 } 414 415 // FUSE_READ flags, consistent with the ones in include/uapi/linux/fuse.h. 416 const ( 417 FUSE_READ_LOCKOWNER = 1 << 1 418 ) 419 420 // FUSEReadIn is the request sent by the kernel to the daemon 421 // for FUSE_READ. 422 // 423 // +marshal 424 type FUSEReadIn struct { 425 // Fh is the file handle in userspace. 426 Fh uint64 427 428 // Offset is the read offset. 429 Offset uint64 430 431 // Size is the number of bytes to read. 432 Size uint32 433 434 // ReadFlags for this FUSE_READ request. 435 // Currently only contains FUSE_READ_LOCKOWNER. 436 ReadFlags uint32 437 438 // LockOwner is the id of the lock owner if there is one. 439 LockOwner uint64 440 441 // Flags for the underlying file. 442 Flags uint32 443 444 _ uint32 445 } 446 447 // FUSEWriteIn is the first part of the payload of the 448 // request sent by the kernel to the daemon 449 // for FUSE_WRITE (struct for FUSE version >= 7.9). 450 // 451 // The second part of the payload is the 452 // binary bytes of the data to be written. 453 // 454 // +marshal 455 type FUSEWriteIn struct { 456 // Fh is the file handle in userspace. 457 Fh uint64 458 459 // Offset is the write offset. 460 Offset uint64 461 462 // Size is the number of bytes to write. 463 Size uint32 464 465 // ReadFlags for this FUSE_WRITE request. 466 WriteFlags uint32 467 468 // LockOwner is the id of the lock owner if there is one. 469 LockOwner uint64 470 471 // Flags for the underlying file. 472 Flags uint32 473 474 _ uint32 475 } 476 477 // FUSEWriteOut is the payload of the reply sent by the daemon to the kernel 478 // for a FUSE_WRITE request. 479 // 480 // +marshal 481 type FUSEWriteOut struct { 482 // Size is the number of bytes written. 483 Size uint32 484 485 _ uint32 486 } 487 488 // FUSEReleaseIn is the request sent by the kernel to the daemon 489 // when there is no more reference to a file. 490 // 491 // +marshal 492 type FUSEReleaseIn struct { 493 // Fh is the file handler for the file to be released. 494 Fh uint64 495 496 // Flags of the file. 497 Flags uint32 498 499 // ReleaseFlags of this release request. 500 ReleaseFlags uint32 501 502 // LockOwner is the id of the lock owner if there is one. 503 LockOwner uint64 504 } 505 506 // FUSECreateMeta contains all the static fields of FUSECreateIn, 507 // which is used for FUSE_CREATE. 508 // 509 // +marshal 510 type FUSECreateMeta struct { 511 // Flags of the creating file. 512 Flags uint32 513 514 // Mode is the mode of the creating file. 515 Mode uint32 516 517 // Umask is the current file mode creation mask. 518 Umask uint32 519 _ uint32 520 } 521 522 // FUSECreateIn contains all the arguments sent by the kernel to the daemon, to 523 // atomically create and open a new regular file. 524 // 525 // Dynamically-sized objects cannot be marshalled. 526 type FUSECreateIn struct { 527 marshal.StubMarshallable 528 529 // CreateMeta contains mode, rdev and umash field for FUSE_MKNODS. 530 CreateMeta FUSECreateMeta 531 532 // Name is the name of the node to create. 533 Name string 534 } 535 536 // MarshalBytes serializes r.CreateMeta and r.Name to the dst buffer. 537 func (r *FUSECreateIn) MarshalBytes(buf []byte) { 538 r.CreateMeta.MarshalBytes(buf[:r.CreateMeta.SizeBytes()]) 539 copy(buf[r.CreateMeta.SizeBytes():], r.Name) 540 } 541 542 // SizeBytes is the size of the memory representation of FUSECreateIn. 543 // 1 extra byte for null-terminated string. 544 func (r *FUSECreateIn) SizeBytes() int { 545 return r.CreateMeta.SizeBytes() + len(r.Name) + 1 546 } 547 548 // FUSEMknodMeta contains all the static fields of FUSEMknodIn, 549 // which is used for FUSE_MKNOD. 550 // 551 // +marshal 552 type FUSEMknodMeta struct { 553 // Mode of the inode to create. 554 Mode uint32 555 556 // Rdev encodes device major and minor information. 557 Rdev uint32 558 559 // Umask is the current file mode creation mask. 560 Umask uint32 561 562 _ uint32 563 } 564 565 // FUSEMknodIn contains all the arguments sent by the kernel 566 // to the daemon, to create a new file node. 567 // 568 // Dynamically-sized objects cannot be marshalled. 569 type FUSEMknodIn struct { 570 marshal.StubMarshallable 571 572 // MknodMeta contains mode, rdev and umash field for FUSE_MKNODS. 573 MknodMeta FUSEMknodMeta 574 575 // Name is the name of the node to create. 576 Name string 577 } 578 579 // MarshalBytes serializes r.MknodMeta and r.Name to the dst buffer. 580 func (r *FUSEMknodIn) MarshalBytes(buf []byte) { 581 r.MknodMeta.MarshalBytes(buf[:r.MknodMeta.SizeBytes()]) 582 copy(buf[r.MknodMeta.SizeBytes():], r.Name) 583 } 584 585 // SizeBytes is the size of the memory representation of FUSEMknodIn. 586 // 1 extra byte for null-terminated string. 587 func (r *FUSEMknodIn) SizeBytes() int { 588 return r.MknodMeta.SizeBytes() + len(r.Name) + 1 589 } 590 591 // FUSESymLinkIn is the request sent by the kernel to the daemon, 592 // to create a symbolic link. 593 // 594 // Dynamically-sized objects cannot be marshalled. 595 type FUSESymLinkIn struct { 596 marshal.StubMarshallable 597 598 // Name of symlink to create. 599 Name string 600 601 // Target of the symlink. 602 Target string 603 } 604 605 // MarshalBytes serializes r.Name and r.Target to the dst buffer. 606 // Left null-termination at end of r.Name and r.Target. 607 func (r *FUSESymLinkIn) MarshalBytes(buf []byte) { 608 copy(buf, r.Name) 609 copy(buf[len(r.Name)+1:], r.Target) 610 } 611 612 // SizeBytes is the size of the memory representation of FUSESymLinkIn. 613 // 2 extra bytes for null-terminated string. 614 func (r *FUSESymLinkIn) SizeBytes() int { 615 return len(r.Name) + len(r.Target) + 2 616 } 617 618 // FUSEEmptyIn is used by operations without request body. 619 type FUSEEmptyIn struct{ marshal.StubMarshallable } 620 621 // MarshalBytes do nothing for marshal. 622 func (r *FUSEEmptyIn) MarshalBytes(buf []byte) {} 623 624 // SizeBytes is 0 for empty request. 625 func (r *FUSEEmptyIn) SizeBytes() int { 626 return 0 627 } 628 629 // FUSEMkdirMeta contains all the static fields of FUSEMkdirIn, 630 // which is used for FUSE_MKDIR. 631 // 632 // +marshal 633 type FUSEMkdirMeta struct { 634 // Mode of the directory of create. 635 Mode uint32 636 637 // Umask is the user file creation mask. 638 Umask uint32 639 } 640 641 // FUSEMkdirIn contains all the arguments sent by the kernel 642 // to the daemon, to create a new directory. 643 // 644 // Dynamically-sized objects cannot be marshalled. 645 type FUSEMkdirIn struct { 646 marshal.StubMarshallable 647 648 // MkdirMeta contains Mode and Umask of the directory to create. 649 MkdirMeta FUSEMkdirMeta 650 651 // Name of the directory to create. 652 Name string 653 } 654 655 // MarshalBytes serializes r.MkdirMeta and r.Name to the dst buffer. 656 func (r *FUSEMkdirIn) MarshalBytes(buf []byte) { 657 r.MkdirMeta.MarshalBytes(buf[:r.MkdirMeta.SizeBytes()]) 658 copy(buf[r.MkdirMeta.SizeBytes():], r.Name) 659 } 660 661 // SizeBytes is the size of the memory representation of FUSEMkdirIn. 662 // 1 extra byte for null-terminated Name string. 663 func (r *FUSEMkdirIn) SizeBytes() int { 664 return r.MkdirMeta.SizeBytes() + len(r.Name) + 1 665 } 666 667 // FUSERmDirIn is the request sent by the kernel to the daemon 668 // when trying to remove a directory. 669 // 670 // Dynamically-sized objects cannot be marshalled. 671 type FUSERmDirIn struct { 672 marshal.StubMarshallable 673 674 // Name is a directory name to be removed. 675 Name string 676 } 677 678 // MarshalBytes serializes r.name to the dst buffer. 679 func (r *FUSERmDirIn) MarshalBytes(buf []byte) { 680 copy(buf, r.Name) 681 } 682 683 // SizeBytes is the size of the memory representation of FUSERmDirIn. 684 func (r *FUSERmDirIn) SizeBytes() int { 685 return len(r.Name) + 1 686 } 687 688 // FUSEDirents is a list of Dirents received from the FUSE daemon server. 689 // It is used for FUSE_READDIR. 690 // 691 // Dynamically-sized objects cannot be marshalled. 692 type FUSEDirents struct { 693 marshal.StubMarshallable 694 695 Dirents []*FUSEDirent 696 } 697 698 // FUSEDirent is a Dirent received from the FUSE daemon server. 699 // It is used for FUSE_READDIR. 700 // 701 // Dynamically-sized objects cannot be marshalled. 702 type FUSEDirent struct { 703 marshal.StubMarshallable 704 705 // Meta contains all the static fields of FUSEDirent. 706 Meta FUSEDirentMeta 707 708 // Name is the filename of the dirent. 709 Name string 710 } 711 712 // FUSEDirentMeta contains all the static fields of FUSEDirent. 713 // It is used for FUSE_READDIR. 714 // 715 // +marshal 716 type FUSEDirentMeta struct { 717 // Inode of the dirent. 718 Ino uint64 719 720 // Offset of the dirent. 721 Off uint64 722 723 // NameLen is the length of the dirent name. 724 NameLen uint32 725 726 // Type of the dirent. 727 Type uint32 728 } 729 730 // SizeBytes is the size of the memory representation of FUSEDirents. 731 func (r *FUSEDirents) SizeBytes() int { 732 var sizeBytes int 733 for _, dirent := range r.Dirents { 734 sizeBytes += dirent.SizeBytes() 735 } 736 737 return sizeBytes 738 } 739 740 // UnmarshalBytes deserializes FUSEDirents from the src buffer. 741 func (r *FUSEDirents) UnmarshalBytes(src []byte) { 742 for { 743 if len(src) <= (*FUSEDirentMeta)(nil).SizeBytes() { 744 break 745 } 746 747 // Its unclear how many dirents there are in src. Each dirent is dynamically 748 // sized and so we can't make assumptions about how many dirents we can allocate. 749 if r.Dirents == nil { 750 r.Dirents = make([]*FUSEDirent, 0) 751 } 752 753 // We have to allocate a struct for each dirent - there must be a better way 754 // to do this. Linux allocates 1 page to store all the dirents and then 755 // simply reads them from the page. 756 var dirent FUSEDirent 757 dirent.UnmarshalBytes(src) 758 r.Dirents = append(r.Dirents, &dirent) 759 760 src = src[dirent.SizeBytes():] 761 } 762 } 763 764 // SizeBytes is the size of the memory representation of FUSEDirent. 765 func (r *FUSEDirent) SizeBytes() int { 766 dataSize := r.Meta.SizeBytes() + len(r.Name) 767 768 // Each Dirent must be padded such that its size is a multiple 769 // of FUSE_DIRENT_ALIGN. Similar to the fuse dirent alignment 770 // in linux/fuse.h. 771 return (dataSize + (FUSE_DIRENT_ALIGN - 1)) & ^(FUSE_DIRENT_ALIGN - 1) 772 } 773 774 // UnmarshalBytes deserializes FUSEDirent from the src buffer. 775 func (r *FUSEDirent) UnmarshalBytes(src []byte) { 776 r.Meta.UnmarshalBytes(src) 777 src = src[r.Meta.SizeBytes():] 778 779 if r.Meta.NameLen > FUSE_NAME_MAX { 780 // The name is too long and therefore invalid. We don't 781 // need to unmarshal the name since it'll be thrown away. 782 return 783 } 784 785 buf := make([]byte, r.Meta.NameLen) 786 name := primitive.ByteSlice(buf) 787 name.UnmarshalBytes(src[:r.Meta.NameLen]) 788 r.Name = string(name) 789 } 790 791 // FATTR_* consts are the attribute flags defined in include/uapi/linux/fuse.h. 792 // These should be or-ed together for setattr to know what has been changed. 793 const ( 794 FATTR_MODE = (1 << 0) 795 FATTR_UID = (1 << 1) 796 FATTR_GID = (1 << 2) 797 FATTR_SIZE = (1 << 3) 798 FATTR_ATIME = (1 << 4) 799 FATTR_MTIME = (1 << 5) 800 FATTR_FH = (1 << 6) 801 FATTR_ATIME_NOW = (1 << 7) 802 FATTR_MTIME_NOW = (1 << 8) 803 FATTR_LOCKOWNER = (1 << 9) 804 FATTR_CTIME = (1 << 10) 805 ) 806 807 // FUSESetAttrIn is the request sent by the kernel to the daemon, 808 // to set the attribute(s) of a file. 809 // 810 // +marshal 811 type FUSESetAttrIn struct { 812 // Valid indicates which attributes are modified by this request. 813 Valid uint32 814 815 _ uint32 816 817 // Fh is used to identify the file if FATTR_FH is set in Valid. 818 Fh uint64 819 820 // Size is the size that the request wants to change to. 821 Size uint64 822 823 // LockOwner is the owner of the lock that the request wants to change to. 824 LockOwner uint64 825 826 // Atime is the access time that the request wants to change to. 827 Atime uint64 828 829 // Mtime is the modification time that the request wants to change to. 830 Mtime uint64 831 832 // Ctime is the status change time that the request wants to change to. 833 Ctime uint64 834 835 // AtimeNsec is the nano second part of Atime. 836 AtimeNsec uint32 837 838 // MtimeNsec is the nano second part of Mtime. 839 MtimeNsec uint32 840 841 // CtimeNsec is the nano second part of Ctime. 842 CtimeNsec uint32 843 844 // Mode is the file mode that the request wants to change to. 845 Mode uint32 846 847 _ uint32 848 849 // UID is the user ID of the owner that the request wants to change to. 850 UID uint32 851 852 // GID is the group ID of the owner that the request wants to change to. 853 GID uint32 854 855 _ uint32 856 } 857 858 // FUSEUnlinkIn is the request sent by the kernel to the daemon 859 // when trying to unlink a node. 860 // 861 // Dynamically-sized objects cannot be marshalled. 862 type FUSEUnlinkIn struct { 863 marshal.StubMarshallable 864 865 // Name of the node to unlink. 866 Name string 867 } 868 869 // MarshalBytes serializes r.name to the dst buffer, which should 870 // have size len(r.Name) + 1 and last byte set to 0. 871 func (r *FUSEUnlinkIn) MarshalBytes(buf []byte) { 872 copy(buf, r.Name) 873 } 874 875 // SizeBytes is the size of the memory representation of FUSEUnlinkIn. 876 // 1 extra byte for null-terminated Name string. 877 func (r *FUSEUnlinkIn) SizeBytes() int { 878 return len(r.Name) + 1 879 }