github.com/sagernet/gvisor@v0.0.0-20240428053021-e691de28565f/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  	"time"
    19  
    20  	"github.com/sagernet/gvisor/pkg/marshal/primitive"
    21  )
    22  
    23  // FUSEOpcode is a FUSE operation code.
    24  //
    25  // +marshal
    26  type FUSEOpcode uint32
    27  
    28  // FUSEOpID is a FUSE operation ID.
    29  //
    30  // +marshal
    31  type FUSEOpID uint64
    32  
    33  // FUSE_ROOT_ID is the id of root inode.
    34  const FUSE_ROOT_ID = 1
    35  
    36  // Opcodes for FUSE operations.
    37  //
    38  // Analogous to the opcodes in include/linux/fuse.h.
    39  const (
    40  	FUSE_LOOKUP   FUSEOpcode = 1
    41  	FUSE_FORGET              = 2 /* no reply */
    42  	FUSE_GETATTR             = 3
    43  	FUSE_SETATTR             = 4
    44  	FUSE_READLINK            = 5
    45  	FUSE_SYMLINK             = 6
    46  	_
    47  	FUSE_MKNOD   = 8
    48  	FUSE_MKDIR   = 9
    49  	FUSE_UNLINK  = 10
    50  	FUSE_RMDIR   = 11
    51  	FUSE_RENAME  = 12
    52  	FUSE_LINK    = 13
    53  	FUSE_OPEN    = 14
    54  	FUSE_READ    = 15
    55  	FUSE_WRITE   = 16
    56  	FUSE_STATFS  = 17
    57  	FUSE_RELEASE = 18
    58  	_
    59  	FUSE_FSYNC        = 20
    60  	FUSE_SETXATTR     = 21
    61  	FUSE_GETXATTR     = 22
    62  	FUSE_LISTXATTR    = 23
    63  	FUSE_REMOVEXATTR  = 24
    64  	FUSE_FLUSH        = 25
    65  	FUSE_INIT         = 26
    66  	FUSE_OPENDIR      = 27
    67  	FUSE_READDIR      = 28
    68  	FUSE_RELEASEDIR   = 29
    69  	FUSE_FSYNCDIR     = 30
    70  	FUSE_GETLK        = 31
    71  	FUSE_SETLK        = 32
    72  	FUSE_SETLKW       = 33
    73  	FUSE_ACCESS       = 34
    74  	FUSE_CREATE       = 35
    75  	FUSE_INTERRUPT    = 36
    76  	FUSE_BMAP         = 37
    77  	FUSE_DESTROY      = 38
    78  	FUSE_IOCTL        = 39
    79  	FUSE_POLL         = 40
    80  	FUSE_NOTIFY_REPLY = 41
    81  	FUSE_BATCH_FORGET = 42
    82  	FUSE_FALLOCATE    = 43
    83  )
    84  
    85  const (
    86  	// FUSE_MIN_READ_BUFFER is the minimum size the read can be for any FUSE filesystem.
    87  	// This is the minimum size Linux supports. See linux.fuse.h.
    88  	FUSE_MIN_READ_BUFFER uint32 = 8192
    89  )
    90  
    91  // FUSEHeaderIn is the header read by the daemon with each request.
    92  //
    93  // +marshal
    94  // +stateify savable
    95  type FUSEHeaderIn struct {
    96  	// Len specifies the total length of the data, including this header.
    97  	Len uint32
    98  
    99  	// Opcode specifies the kind of operation of the request.
   100  	Opcode FUSEOpcode
   101  
   102  	// Unique specifies the unique identifier for this request.
   103  	Unique FUSEOpID
   104  
   105  	// NodeID is the ID of the filesystem object being operated on.
   106  	NodeID uint64
   107  
   108  	// UID is the UID of the requesting process.
   109  	UID uint32
   110  
   111  	// GID is the GID of the requesting process.
   112  	GID uint32
   113  
   114  	// PID is the PID of the requesting process.
   115  	PID uint32
   116  
   117  	_ uint32
   118  }
   119  
   120  // SizeOfFUSEHeaderIn is the size of the FUSEHeaderIn struct.
   121  var SizeOfFUSEHeaderIn = uint32((*FUSEHeaderIn)(nil).SizeBytes())
   122  
   123  // FUSEHeaderOut is the header written by the daemon when it processes
   124  // a request and wants to send a reply (almost all operations require a
   125  // reply; if they do not, this will be explicitly documented).
   126  //
   127  // +marshal
   128  // +stateify savable
   129  type FUSEHeaderOut struct {
   130  	// Len specifies the total length of the data, including this header.
   131  	Len uint32
   132  
   133  	// Error specifies the error that occurred (0 if none).
   134  	Error int32
   135  
   136  	// Unique specifies the unique identifier of the corresponding request.
   137  	Unique FUSEOpID
   138  }
   139  
   140  // SizeOfFUSEHeaderOut is the size of the FUSEHeaderOut struct.
   141  var SizeOfFUSEHeaderOut = uint32((*FUSEHeaderOut)(nil).SizeBytes())
   142  
   143  // FUSE_INIT flags, consistent with the ones in include/uapi/linux/fuse.h.
   144  // Our target version is 7.23 but we have few implemented in advance.
   145  const (
   146  	FUSE_ASYNC_READ       = 1 << 0
   147  	FUSE_POSIX_LOCKS      = 1 << 1
   148  	FUSE_FILE_OPS         = 1 << 2
   149  	FUSE_ATOMIC_O_TRUNC   = 1 << 3
   150  	FUSE_EXPORT_SUPPORT   = 1 << 4
   151  	FUSE_BIG_WRITES       = 1 << 5
   152  	FUSE_DONT_MASK        = 1 << 6
   153  	FUSE_SPLICE_WRITE     = 1 << 7
   154  	FUSE_SPLICE_MOVE      = 1 << 8
   155  	FUSE_SPLICE_READ      = 1 << 9
   156  	FUSE_FLOCK_LOCKS      = 1 << 10
   157  	FUSE_HAS_IOCTL_DIR    = 1 << 11
   158  	FUSE_AUTO_INVAL_DATA  = 1 << 12
   159  	FUSE_DO_READDIRPLUS   = 1 << 13
   160  	FUSE_READDIRPLUS_AUTO = 1 << 14
   161  	FUSE_ASYNC_DIO        = 1 << 15
   162  	FUSE_WRITEBACK_CACHE  = 1 << 16
   163  	FUSE_NO_OPEN_SUPPORT  = 1 << 17
   164  	FUSE_MAX_PAGES        = 1 << 22 // From FUSE 7.28
   165  )
   166  
   167  // currently supported FUSE protocol version numbers.
   168  const (
   169  	FUSE_KERNEL_VERSION       = 7
   170  	FUSE_KERNEL_MINOR_VERSION = 31
   171  )
   172  
   173  // Constants relevant to FUSE operations.
   174  const (
   175  	FUSE_NAME_MAX     = 1024
   176  	FUSE_PAGE_SIZE    = 4096
   177  	FUSE_DIRENT_ALIGN = 8
   178  )
   179  
   180  // FUSEInitIn is the request sent by the kernel to the daemon,
   181  // to negotiate the version and flags.
   182  //
   183  // +marshal
   184  type FUSEInitIn struct {
   185  	// Major version supported by kernel.
   186  	Major uint32
   187  
   188  	// Minor version supported by the kernel.
   189  	Minor uint32
   190  
   191  	// MaxReadahead is the maximum number of bytes to read-ahead
   192  	// decided by the kernel.
   193  	MaxReadahead uint32
   194  
   195  	// Flags of this init request.
   196  	Flags uint32
   197  }
   198  
   199  // FUSEInitOut is the reply sent by the daemon to the kernel
   200  // for FUSEInitIn. We target FUSE 7.23; this struct supports 7.28.
   201  //
   202  // +marshal
   203  type FUSEInitOut struct {
   204  	// Major version supported by daemon.
   205  	Major uint32
   206  
   207  	// Minor version supported by daemon.
   208  	Minor uint32
   209  
   210  	// MaxReadahead is the maximum number of bytes to read-ahead.
   211  	// Decided by the daemon, after receiving the value from kernel.
   212  	MaxReadahead uint32
   213  
   214  	// Flags of this init reply.
   215  	Flags uint32
   216  
   217  	// MaxBackground is the maximum number of pending background requests
   218  	// that the daemon wants.
   219  	MaxBackground uint16
   220  
   221  	// CongestionThreshold is the daemon-decided threshold for
   222  	// the number of the pending background requests.
   223  	CongestionThreshold uint16
   224  
   225  	// MaxWrite is the daemon's maximum size of a write buffer.
   226  	// Kernel adjusts it to the minimum (fuse/init.go:fuseMinMaxWrite).
   227  	// if the value from daemon is too small.
   228  	MaxWrite uint32
   229  
   230  	// TimeGran is the daemon's time granularity for mtime and ctime metadata.
   231  	// The unit is nanosecond.
   232  	// Value should be power of 10.
   233  	// 1 indicates full nanosecond granularity support.
   234  	TimeGran uint32
   235  
   236  	// MaxPages is the daemon's maximum number of pages for one write operation.
   237  	// Kernel adjusts it to the maximum (fuse/init.go:FUSE_MAX_MAX_PAGES).
   238  	// if the value from daemon is too large.
   239  	MaxPages uint16
   240  
   241  	_ uint16
   242  
   243  	_ [8]uint32
   244  }
   245  
   246  // FUSEStatfsOut is the reply sent by the daemon to the kernel
   247  // for FUSE_STATFS.
   248  // from https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/fuse.h#L252
   249  //
   250  // +marshal
   251  type FUSEStatfsOut struct {
   252  	// Blocks is the maximum number of data blocks the filesystem may store, in
   253  	// units of BlockSize.
   254  	Blocks uint64
   255  
   256  	// BlocksFree is the number of free data blocks, in units of BlockSize.
   257  	BlocksFree uint64
   258  
   259  	// BlocksAvailable is the number of data blocks free for use by
   260  	// unprivileged users, in units of BlockSize.
   261  	BlocksAvailable uint64
   262  
   263  	// Files is the number of used file nodes on the filesystem.
   264  	Files uint64
   265  
   266  	// FileFress is the number of free file nodes on the filesystem.
   267  	FilesFree uint64
   268  
   269  	// BlockSize is the optimal transfer block size in bytes.
   270  	BlockSize uint32
   271  
   272  	// NameLength is the maximum file name length.
   273  	NameLength uint32
   274  
   275  	// FragmentSize is equivalent to BlockSize.
   276  	FragmentSize uint32
   277  
   278  	_ uint32
   279  
   280  	Spare [6]uint32
   281  }
   282  
   283  // FUSE_GETATTR_FH is currently the only flag of FUSEGetAttrIn.GetAttrFlags.
   284  // If it is set, the file handle (FUSEGetAttrIn.Fh) is used to indicate the
   285  // object instead of the node id attribute in the request header.
   286  const FUSE_GETATTR_FH = (1 << 0)
   287  
   288  // FUSEGetAttrIn is the request sent by the kernel to the daemon,
   289  // to get the attribute of a inode.
   290  //
   291  // +marshal
   292  type FUSEGetAttrIn struct {
   293  	// GetAttrFlags specifies whether getattr request is sent with a nodeid or
   294  	// with a file handle.
   295  	GetAttrFlags uint32
   296  
   297  	_ uint32
   298  
   299  	// Fh is the file handler when GetAttrFlags has FUSE_GETATTR_FH bit. If
   300  	// used, the operation is analogous to fstat(2).
   301  	Fh uint64
   302  }
   303  
   304  // FUSEAttr is the struct used in the response FUSEGetAttrOut.
   305  //
   306  // +marshal
   307  type FUSEAttr struct {
   308  	// Ino is the inode number of this file.
   309  	Ino uint64
   310  
   311  	// Size is the size of this file.
   312  	Size uint64
   313  
   314  	// Blocks is the number of the 512B blocks allocated by this file.
   315  	Blocks uint64
   316  
   317  	// Atime is the time of last access.
   318  	Atime uint64
   319  
   320  	// Mtime is the time of last modification.
   321  	Mtime uint64
   322  
   323  	// Ctime is the time of last status change.
   324  	Ctime uint64
   325  
   326  	// AtimeNsec is the nano second part of Atime.
   327  	AtimeNsec uint32
   328  
   329  	// MtimeNsec is the nano second part of Mtime.
   330  	MtimeNsec uint32
   331  
   332  	// CtimeNsec is the nano second part of Ctime.
   333  	CtimeNsec uint32
   334  
   335  	// Mode contains the file type and mode.
   336  	Mode uint32
   337  
   338  	// Nlink is the number of the hard links.
   339  	Nlink uint32
   340  
   341  	// UID is user ID of the owner.
   342  	UID uint32
   343  
   344  	// GID is group ID of the owner.
   345  	GID uint32
   346  
   347  	// Rdev is the device ID if this is a special file.
   348  	Rdev uint32
   349  
   350  	// BlkSize is the block size for filesystem I/O.
   351  	BlkSize uint32
   352  
   353  	_ uint32
   354  }
   355  
   356  // ATimeNsec returns the last access time as the total time since the unix epoch
   357  // in nanoseconds.
   358  func (a FUSEAttr) ATimeNsec() int64 {
   359  	return int64(a.Atime)*time.Second.Nanoseconds() + int64(a.AtimeNsec)
   360  }
   361  
   362  // MTimeNsec returns the last modification time as the total time since the unix
   363  // epoch in nanoseconds.
   364  func (a FUSEAttr) MTimeNsec() int64 {
   365  	return int64(a.Mtime)*time.Second.Nanoseconds() + int64(a.MtimeNsec)
   366  }
   367  
   368  // CTimeNsec returns the last change time as the total time since the unix epoch
   369  // in nanoseconds.
   370  func (a FUSEAttr) CTimeNsec() int64 {
   371  	return int64(a.Ctime)*time.Second.Nanoseconds() + int64(a.CtimeNsec)
   372  }
   373  
   374  // FUSEAttrOut is the reply sent by the daemon to the kernel
   375  // for FUSEGetAttrIn and FUSESetAttrIn.
   376  //
   377  // +marshal
   378  type FUSEAttrOut struct {
   379  	// AttrValid and AttrValidNsec describe the attribute cache duration
   380  	AttrValid uint64
   381  
   382  	// AttrValidNsec is the nanosecond part of the attribute cache duration
   383  	AttrValidNsec uint32
   384  
   385  	_ uint32
   386  
   387  	// Attr contains the metadata returned from the FUSE server
   388  	Attr FUSEAttr
   389  }
   390  
   391  // FUSEEntryOut is the reply sent by the daemon to the kernel
   392  // for FUSE_MKNOD, FUSE_MKDIR, FUSE_SYMLINK, FUSE_LINK and
   393  // FUSE_LOOKUP.
   394  //
   395  // +marshal
   396  type FUSEEntryOut struct {
   397  	// NodeID is the ID for current inode.
   398  	NodeID uint64
   399  
   400  	// Generation is the generation number of inode.
   401  	// Used to identify an inode that have different ID at different time.
   402  	Generation uint64
   403  
   404  	// EntryValid indicates timeout for an entry.
   405  	EntryValid uint64
   406  
   407  	// AttrValid indicates timeout for an entry's attributes.
   408  	AttrValid uint64
   409  
   410  	// EntryValidNsec indicates timeout for an entry in nanosecond.
   411  	EntryValidNSec uint32
   412  
   413  	// AttrValidNsec indicates timeout for an entry's attributes in nanosecond.
   414  	AttrValidNSec uint32
   415  
   416  	// Attr contains the attributes of an entry.
   417  	Attr FUSEAttr
   418  }
   419  
   420  // CString represents a null terminated string which can be marshalled.
   421  //
   422  // +marshal dynamic
   423  type CString string
   424  
   425  // MarshalBytes implements marshal.Marshallable.MarshalBytes.
   426  func (s *CString) MarshalBytes(buf []byte) []byte {
   427  	copy(buf, *s)
   428  	buf[len(*s)] = 0 // null char
   429  	return buf[s.SizeBytes():]
   430  }
   431  
   432  // UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
   433  func (s *CString) UnmarshalBytes(buf []byte) []byte {
   434  	panic("Unimplemented, CString is never unmarshalled")
   435  }
   436  
   437  // SizeBytes implements marshal.Marshallable.SizeBytes.
   438  func (s *CString) SizeBytes() int {
   439  	// 1 extra byte for null-terminated string.
   440  	return len(*s) + 1
   441  }
   442  
   443  // FUSELookupIn is the request sent by the kernel to the daemon
   444  // to look up a file name.
   445  //
   446  // +marshal dynamic
   447  type FUSELookupIn struct {
   448  	// Name is a file name to be looked up.
   449  	Name CString
   450  }
   451  
   452  // UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
   453  func (r *FUSELookupIn) UnmarshalBytes(buf []byte) []byte {
   454  	panic("Unimplemented, FUSELookupIn is never unmarshalled")
   455  }
   456  
   457  // MarshalBytes implements marshal.Marshallable.MarshalBytes.
   458  func (r *FUSELookupIn) MarshalBytes(buf []byte) []byte {
   459  	return r.Name.MarshalBytes(buf)
   460  }
   461  
   462  // SizeBytes implements marshal.Marshallable.SizeBytes.
   463  func (r *FUSELookupIn) SizeBytes() int {
   464  	return r.Name.SizeBytes()
   465  }
   466  
   467  // MAX_NON_LFS indicates the maximum offset without large file support.
   468  const MAX_NON_LFS = ((1 << 31) - 1)
   469  
   470  // flags returned by OPEN request.
   471  const (
   472  	// FOPEN_DIRECT_IO indicates bypassing page cache for this opened file.
   473  	FOPEN_DIRECT_IO = 1 << 0
   474  	// FOPEN_KEEP_CACHE avoids invalidating the data cache on open.
   475  	FOPEN_KEEP_CACHE = 1 << 1
   476  	// FOPEN_NONSEEKABLE indicates the file cannot be seeked.
   477  	FOPEN_NONSEEKABLE = 1 << 2
   478  )
   479  
   480  // FUSEOpenIn is the request sent by the kernel to the daemon,
   481  // to negotiate flags and get file handle.
   482  //
   483  // +marshal
   484  type FUSEOpenIn struct {
   485  	// Flags of this open request.
   486  	Flags uint32
   487  
   488  	_ uint32
   489  }
   490  
   491  // FUSEOpenOut is the reply sent by the daemon to the kernel
   492  // for FUSEOpenIn.
   493  //
   494  // +marshal
   495  type FUSEOpenOut struct {
   496  	// Fh is the file handler for opened files.
   497  	Fh uint64
   498  
   499  	// OpenFlag for the opened files.
   500  	OpenFlag uint32
   501  
   502  	_ uint32
   503  }
   504  
   505  // FUSECreateOut is the reply sent by the daemon to the kernel
   506  // for FUSECreateMeta.
   507  //
   508  // +marshal
   509  type FUSECreateOut struct {
   510  	FUSEEntryOut
   511  	FUSEOpenOut
   512  }
   513  
   514  // FUSE_READ flags, consistent with the ones in include/uapi/linux/fuse.h.
   515  const (
   516  	FUSE_READ_LOCKOWNER = 1 << 1
   517  )
   518  
   519  // FUSEReadIn is the request sent by the kernel to the daemon
   520  // for FUSE_READ.
   521  //
   522  // +marshal
   523  type FUSEReadIn struct {
   524  	// Fh is the file handle in userspace.
   525  	Fh uint64
   526  
   527  	// Offset is the read offset.
   528  	Offset uint64
   529  
   530  	// Size is the number of bytes to read.
   531  	Size uint32
   532  
   533  	// ReadFlags for this FUSE_READ request.
   534  	// Currently only contains FUSE_READ_LOCKOWNER.
   535  	ReadFlags uint32
   536  
   537  	// LockOwner is the id of the lock owner if there is one.
   538  	LockOwner uint64
   539  
   540  	// Flags for the underlying file.
   541  	Flags uint32
   542  
   543  	_ uint32
   544  }
   545  
   546  // FUSEWriteIn is the first part of the payload of the
   547  // request sent by the kernel to the daemon
   548  // for FUSE_WRITE (struct for FUSE version >= 7.9).
   549  //
   550  // The second part of the payload is the
   551  // binary bytes of the data to be written.
   552  // See FUSEWritePayloadIn that combines header & payload.
   553  //
   554  // +marshal
   555  type FUSEWriteIn struct {
   556  	// Fh is the file handle in userspace.
   557  	Fh uint64
   558  
   559  	// Offset is the write offset.
   560  	Offset uint64
   561  
   562  	// Size is the number of bytes to write.
   563  	Size uint32
   564  
   565  	// ReadFlags for this FUSE_WRITE request.
   566  	WriteFlags uint32
   567  
   568  	// LockOwner is the id of the lock owner if there is one.
   569  	LockOwner uint64
   570  
   571  	// Flags for the underlying file.
   572  	Flags uint32
   573  
   574  	_ uint32
   575  }
   576  
   577  // SizeOfFUSEWriteIn is the size of the FUSEWriteIn struct.
   578  var SizeOfFUSEWriteIn = uint32((*FUSEWriteIn)(nil).SizeBytes())
   579  
   580  // FUSEWritePayloadIn combines header - FUSEWriteIn and payload
   581  // in a single marshallable struct when sending request by the
   582  // kernel to the daemon
   583  //
   584  // +marshal dynamic
   585  type FUSEWritePayloadIn struct {
   586  	Header  FUSEWriteIn
   587  	Payload primitive.ByteSlice
   588  }
   589  
   590  // SizeBytes implements marshal.Marshallable.SizeBytes.
   591  func (r *FUSEWritePayloadIn) SizeBytes() int {
   592  	if r == nil {
   593  		return (*FUSEWriteIn)(nil).SizeBytes()
   594  	}
   595  	return r.Header.SizeBytes() + r.Payload.SizeBytes()
   596  }
   597  
   598  // MarshalBytes implements marshal.Marshallable.MarshalBytes.
   599  func (r *FUSEWritePayloadIn) MarshalBytes(dst []byte) []byte {
   600  	dst = r.Header.MarshalUnsafe(dst)
   601  	dst = r.Payload.MarshalUnsafe(dst)
   602  	return dst
   603  }
   604  
   605  // UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
   606  func (r *FUSEWritePayloadIn) UnmarshalBytes(src []byte) []byte {
   607  	panic("Unimplemented, FUSEWritePayloadIn is never unmarshalled")
   608  }
   609  
   610  // FUSEWriteOut is the payload of the reply sent by the daemon to the kernel
   611  // for a FUSE_WRITE request.
   612  //
   613  // +marshal
   614  type FUSEWriteOut struct {
   615  	// Size is the number of bytes written.
   616  	Size uint32
   617  
   618  	_ uint32
   619  }
   620  
   621  // FUSEReleaseIn is the request sent by the kernel to the daemon
   622  // when there is no more reference to a file.
   623  //
   624  // +marshal
   625  type FUSEReleaseIn struct {
   626  	// Fh is the file handler for the file to be released.
   627  	Fh uint64
   628  
   629  	// Flags of the file.
   630  	Flags uint32
   631  
   632  	// ReleaseFlags of this release request.
   633  	ReleaseFlags uint32
   634  
   635  	// LockOwner is the id of the lock owner if there is one.
   636  	LockOwner uint64
   637  }
   638  
   639  // FUSECreateMeta contains all the static fields of FUSECreateIn,
   640  // which is used for FUSE_CREATE.
   641  //
   642  // +marshal
   643  type FUSECreateMeta struct {
   644  	// Flags of the creating file.
   645  	Flags uint32
   646  
   647  	// Mode is the mode of the creating file.
   648  	Mode uint32
   649  
   650  	// Umask is the current file mode creation mask.
   651  	Umask uint32
   652  	_     uint32
   653  }
   654  
   655  // FUSERenameIn sent by the kernel for FUSE_RENAME
   656  //
   657  // +marshal dynamic
   658  type FUSERenameIn struct {
   659  	Newdir  primitive.Uint64
   660  	Oldname CString
   661  	Newname CString
   662  }
   663  
   664  // MarshalBytes implements marshal.Marshallable.MarshalBytes.
   665  func (r *FUSERenameIn) MarshalBytes(dst []byte) []byte {
   666  	dst = r.Newdir.MarshalBytes(dst)
   667  	dst = r.Oldname.MarshalBytes(dst)
   668  	return r.Newname.MarshalBytes(dst)
   669  }
   670  
   671  // UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
   672  func (r *FUSERenameIn) UnmarshalBytes(buf []byte) []byte {
   673  	panic("Unimplemented, FUSERmDirIn is never unmarshalled")
   674  }
   675  
   676  // SizeBytes implements marshal.Marshallable.SizeBytes.
   677  func (r *FUSERenameIn) SizeBytes() int {
   678  	return r.Newdir.SizeBytes() + r.Oldname.SizeBytes() + r.Newname.SizeBytes()
   679  }
   680  
   681  // FUSECreateIn contains all the arguments sent by the kernel to the daemon, to
   682  // atomically create and open a new regular file.
   683  //
   684  // +marshal dynamic
   685  type FUSECreateIn struct {
   686  	// CreateMeta contains mode, rdev and umash fields for FUSE_MKNODS.
   687  	CreateMeta FUSECreateMeta
   688  
   689  	// Name is the name of the node to create.
   690  	Name CString
   691  }
   692  
   693  // MarshalBytes implements marshal.Marshallable.MarshalBytes.
   694  func (r *FUSECreateIn) MarshalBytes(buf []byte) []byte {
   695  	buf = r.CreateMeta.MarshalBytes(buf)
   696  	return r.Name.MarshalBytes(buf)
   697  }
   698  
   699  // UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
   700  func (r *FUSECreateIn) UnmarshalBytes(buf []byte) []byte {
   701  	panic("Unimplemented, FUSECreateIn is never unmarshalled")
   702  }
   703  
   704  // SizeBytes implements marshal.Marshallable.SizeBytes.
   705  func (r *FUSECreateIn) SizeBytes() int {
   706  	return r.CreateMeta.SizeBytes() + r.Name.SizeBytes()
   707  }
   708  
   709  // FUSEMknodMeta contains all the static fields of FUSEMknodIn,
   710  // which is used for FUSE_MKNOD.
   711  //
   712  // +marshal
   713  type FUSEMknodMeta struct {
   714  	// Mode of the inode to create.
   715  	Mode uint32
   716  
   717  	// Rdev encodes device major and minor information.
   718  	Rdev uint32
   719  
   720  	// Umask is the current file mode creation mask.
   721  	Umask uint32
   722  
   723  	_ uint32
   724  }
   725  
   726  // FUSEMknodIn contains all the arguments sent by the kernel
   727  // to the daemon, to create a new file node.
   728  //
   729  // +marshal dynamic
   730  type FUSEMknodIn struct {
   731  	// MknodMeta contains mode, rdev and umash fields for FUSE_MKNODS.
   732  	MknodMeta FUSEMknodMeta
   733  	// Name is the name of the node to create.
   734  	Name CString
   735  }
   736  
   737  // MarshalBytes implements marshal.Marshallable.MarshalBytes.
   738  func (r *FUSEMknodIn) MarshalBytes(buf []byte) []byte {
   739  	buf = r.MknodMeta.MarshalBytes(buf)
   740  	return r.Name.MarshalBytes(buf)
   741  }
   742  
   743  // UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
   744  func (r *FUSEMknodIn) UnmarshalBytes(buf []byte) []byte {
   745  	panic("Unimplemented, FUSEMknodIn is never unmarshalled")
   746  }
   747  
   748  // SizeBytes implements marshal.Marshallable.SizeBytes.
   749  func (r *FUSEMknodIn) SizeBytes() int {
   750  	return r.MknodMeta.SizeBytes() + r.Name.SizeBytes()
   751  }
   752  
   753  // FUSESymlinkIn is the request sent by the kernel to the daemon,
   754  // to create a symbolic link.
   755  //
   756  // +marshal dynamic
   757  type FUSESymlinkIn struct {
   758  	// Name of symlink to create.
   759  	Name CString
   760  
   761  	// Target of the symlink.
   762  	Target CString
   763  }
   764  
   765  // MarshalBytes implements marshal.Marshallable.MarshalBytes.
   766  func (r *FUSESymlinkIn) MarshalBytes(buf []byte) []byte {
   767  	buf = r.Name.MarshalBytes(buf)
   768  	return r.Target.MarshalBytes(buf)
   769  }
   770  
   771  // UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
   772  func (r *FUSESymlinkIn) UnmarshalBytes(buf []byte) []byte {
   773  	panic("Unimplemented, FUSEMknodIn is never unmarshalled")
   774  }
   775  
   776  // SizeBytes implements marshal.Marshallable.SizeBytes.
   777  func (r *FUSESymlinkIn) SizeBytes() int {
   778  	return r.Name.SizeBytes() + r.Target.SizeBytes()
   779  }
   780  
   781  // FUSELinkIn is the request sent by the kernel to create a hard link.
   782  //
   783  // +marshal dynamic
   784  type FUSELinkIn struct {
   785  	// OldNodeID is the ID of the inode that is being linked to.
   786  	OldNodeID primitive.Uint64
   787  	// Name of the new hard link to create.
   788  	Name CString
   789  }
   790  
   791  // MarshalBytes implements marshal.Marshallable.MarshalBytes.
   792  func (r *FUSELinkIn) MarshalBytes(buf []byte) []byte {
   793  	buf = r.OldNodeID.MarshalBytes(buf)
   794  	return r.Name.MarshalBytes(buf)
   795  }
   796  
   797  // UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
   798  func (r *FUSELinkIn) UnmarshalBytes(buf []byte) []byte {
   799  	panic("Unimplemented, FUSELinkIn is never unmarshalled")
   800  }
   801  
   802  // SizeBytes implements marshal.Marshallable.SizeBytes.
   803  func (r *FUSELinkIn) SizeBytes() int {
   804  	return r.OldNodeID.SizeBytes() + r.Name.SizeBytes()
   805  }
   806  
   807  // FUSEEmptyIn is used by operations without request body.
   808  //
   809  // +marshal dynamic
   810  type FUSEEmptyIn struct{}
   811  
   812  // MarshalBytes implements marshal.Marshallable.MarshalBytes.
   813  func (r *FUSEEmptyIn) MarshalBytes(buf []byte) []byte {
   814  	return buf
   815  }
   816  
   817  // UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
   818  func (r *FUSEEmptyIn) UnmarshalBytes(buf []byte) []byte {
   819  	panic("Unimplemented, FUSEEmptyIn is never unmarshalled")
   820  }
   821  
   822  // SizeBytes implements marshal.Marshallable.SizeBytes.
   823  func (r *FUSEEmptyIn) SizeBytes() int {
   824  	return 0
   825  }
   826  
   827  // FUSEMkdirMeta contains all the static fields of FUSEMkdirIn,
   828  // which is used for FUSE_MKDIR.
   829  //
   830  // +marshal
   831  type FUSEMkdirMeta struct {
   832  	// Mode of the directory of create.
   833  	Mode uint32
   834  	// Umask is the user file creation mask.
   835  	Umask uint32
   836  }
   837  
   838  // FUSEMkdirIn contains all the arguments sent by the kernel
   839  // to the daemon, to create a new directory.
   840  //
   841  // +marshal dynamic
   842  type FUSEMkdirIn struct {
   843  	// MkdirMeta contains Mode and Umask of the directory to create.
   844  	MkdirMeta FUSEMkdirMeta
   845  	// Name of the directory to create.
   846  	Name CString
   847  }
   848  
   849  // MarshalBytes implements marshal.Marshallable.MarshalBytes.
   850  func (r *FUSEMkdirIn) MarshalBytes(buf []byte) []byte {
   851  	buf = r.MkdirMeta.MarshalBytes(buf)
   852  	return r.Name.MarshalBytes(buf)
   853  }
   854  
   855  // UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
   856  func (r *FUSEMkdirIn) UnmarshalBytes(buf []byte) []byte {
   857  	panic("Unimplemented, FUSEMkdirIn is never unmarshalled")
   858  }
   859  
   860  // SizeBytes implements marshal.Marshallable.SizeBytes.
   861  func (r *FUSEMkdirIn) SizeBytes() int {
   862  	return r.MkdirMeta.SizeBytes() + r.Name.SizeBytes()
   863  }
   864  
   865  // FUSERmDirIn is the request sent by the kernel to the daemon
   866  // when trying to remove a directory.
   867  //
   868  // +marshal dynamic
   869  type FUSERmDirIn struct {
   870  	// Name is a directory name to be removed.
   871  	Name CString
   872  }
   873  
   874  // MarshalBytes implements marshal.Marshallable.MarshalBytes.
   875  func (r *FUSERmDirIn) MarshalBytes(buf []byte) []byte {
   876  	return r.Name.MarshalBytes(buf)
   877  }
   878  
   879  // UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
   880  func (r *FUSERmDirIn) UnmarshalBytes(buf []byte) []byte {
   881  	panic("Unimplemented, FUSERmDirIn is never unmarshalled")
   882  }
   883  
   884  // SizeBytes implements marshal.Marshallable.SizeBytes.
   885  func (r *FUSERmDirIn) SizeBytes() int {
   886  	return r.Name.SizeBytes()
   887  }
   888  
   889  // FUSEDirents is a list of Dirents received from the FUSE daemon server.
   890  // It is used for FUSE_READDIR.
   891  //
   892  // +marshal dynamic
   893  type FUSEDirents struct {
   894  	Dirents []*FUSEDirent
   895  }
   896  
   897  // FUSEDirent is a Dirent received from the FUSE daemon server.
   898  // It is used for FUSE_READDIR.
   899  //
   900  // +marshal dynamic
   901  type FUSEDirent struct {
   902  	// Meta contains all the static fields of FUSEDirent.
   903  	Meta FUSEDirentMeta
   904  	// Name is the filename of the dirent.
   905  	Name string
   906  }
   907  
   908  // FUSEDirentMeta contains all the static fields of FUSEDirent.
   909  // It is used for FUSE_READDIR.
   910  //
   911  // +marshal
   912  type FUSEDirentMeta struct {
   913  	// Inode of the dirent.
   914  	Ino uint64
   915  	// Offset of the dirent.
   916  	Off uint64
   917  	// NameLen is the length of the dirent name.
   918  	NameLen uint32
   919  	// Type of the dirent.
   920  	Type uint32
   921  }
   922  
   923  // SizeBytes implements marshal.Marshallable.SizeBytes.
   924  func (r *FUSEDirents) SizeBytes() int {
   925  	var sizeBytes int
   926  	for _, dirent := range r.Dirents {
   927  		sizeBytes += dirent.SizeBytes()
   928  	}
   929  
   930  	return sizeBytes
   931  }
   932  
   933  // MarshalBytes implements marshal.Marshallable.MarshalBytes.
   934  func (r *FUSEDirents) MarshalBytes(buf []byte) []byte {
   935  	panic("Unimplemented, FUSEDirents is never marshalled")
   936  }
   937  
   938  // UnmarshalBytes deserializes FUSEDirents from the src buffer.
   939  func (r *FUSEDirents) UnmarshalBytes(src []byte) []byte {
   940  	for {
   941  		if len(src) <= (*FUSEDirentMeta)(nil).SizeBytes() {
   942  			break
   943  		}
   944  
   945  		// Its unclear how many dirents there are in src. Each dirent is dynamically
   946  		// sized and so we can't make assumptions about how many dirents we can allocate.
   947  		if r.Dirents == nil {
   948  			r.Dirents = make([]*FUSEDirent, 0)
   949  		}
   950  
   951  		// We have to allocate a struct for each dirent - there must be a better way
   952  		// to do this. Linux allocates 1 page to store all the dirents and then
   953  		// simply reads them from the page.
   954  		var dirent FUSEDirent
   955  		src = dirent.UnmarshalBytes(src)
   956  		r.Dirents = append(r.Dirents, &dirent)
   957  	}
   958  	return src
   959  }
   960  
   961  // SizeBytes implements marshal.Marshallable.SizeBytes.
   962  func (r *FUSEDirent) SizeBytes() int {
   963  	dataSize := r.Meta.SizeBytes() + len(r.Name)
   964  
   965  	// Each Dirent must be padded such that its size is a multiple
   966  	// of FUSE_DIRENT_ALIGN. Similar to the fuse dirent alignment
   967  	// in linux/fuse.h.
   968  	return (dataSize + (FUSE_DIRENT_ALIGN - 1)) & ^(FUSE_DIRENT_ALIGN - 1)
   969  }
   970  
   971  // MarshalBytes implements marshal.Marshallable.MarshalBytes.
   972  func (r *FUSEDirent) MarshalBytes(buf []byte) []byte {
   973  	panic("Unimplemented, FUSEDirent is never marshalled")
   974  }
   975  
   976  // shiftNextDirent advances buf to the start of the next dirent, per
   977  // FUSE ABI. buf should begin at the start of a dirent.
   978  func (r *FUSEDirent) shiftNextDirent(buf []byte) []byte {
   979  	nextOff := r.SizeBytes()
   980  	if nextOff > len(buf) { // Handle overflow.
   981  		return buf[len(buf):]
   982  	}
   983  	return buf[nextOff:]
   984  }
   985  
   986  // UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
   987  func (r *FUSEDirent) UnmarshalBytes(src []byte) []byte {
   988  	srcP := r.Meta.UnmarshalBytes(src)
   989  
   990  	if r.Meta.NameLen > FUSE_NAME_MAX || r.Meta.NameLen > uint32(len(srcP)) {
   991  		// The name is too long and therefore invalid. We don't
   992  		// need to unmarshal the name since it'll be thrown away.
   993  		return r.shiftNextDirent(src)
   994  	}
   995  
   996  	buf := make([]byte, r.Meta.NameLen)
   997  	name := primitive.ByteSlice(buf)
   998  	name.UnmarshalBytes(srcP[:r.Meta.NameLen])
   999  	r.Name = string(name)
  1000  	return r.shiftNextDirent(src)
  1001  }
  1002  
  1003  // FATTR_* consts are the attribute flags defined in include/uapi/linux/fuse.h.
  1004  // These should be or-ed together for setattr to know what has been changed.
  1005  const (
  1006  	FATTR_MODE      = (1 << 0)
  1007  	FATTR_UID       = (1 << 1)
  1008  	FATTR_GID       = (1 << 2)
  1009  	FATTR_SIZE      = (1 << 3)
  1010  	FATTR_ATIME     = (1 << 4)
  1011  	FATTR_MTIME     = (1 << 5)
  1012  	FATTR_FH        = (1 << 6)
  1013  	FATTR_ATIME_NOW = (1 << 7)
  1014  	FATTR_MTIME_NOW = (1 << 8)
  1015  	FATTR_LOCKOWNER = (1 << 9)
  1016  	FATTR_CTIME     = (1 << 10)
  1017  )
  1018  
  1019  // FUSESetAttrIn is the request sent by the kernel to the daemon,
  1020  // to set the attribute(s) of a file.
  1021  //
  1022  // +marshal
  1023  type FUSESetAttrIn struct {
  1024  	// Valid indicates which attributes are modified by this request.
  1025  	Valid uint32
  1026  
  1027  	_ uint32
  1028  
  1029  	// Fh is used to identify the file if FATTR_FH is set in Valid.
  1030  	Fh uint64
  1031  
  1032  	// Size is the size that the request wants to change to.
  1033  	Size uint64
  1034  
  1035  	// LockOwner is the owner of the lock that the request wants to change to.
  1036  	LockOwner uint64
  1037  
  1038  	// Atime is the access time that the request wants to change to.
  1039  	Atime uint64
  1040  
  1041  	// Mtime is the modification time that the request wants to change to.
  1042  	Mtime uint64
  1043  
  1044  	// Ctime is the status change time that the request wants to change to.
  1045  	Ctime uint64
  1046  
  1047  	// AtimeNsec is the nano second part of Atime.
  1048  	AtimeNsec uint32
  1049  
  1050  	// MtimeNsec is the nano second part of Mtime.
  1051  	MtimeNsec uint32
  1052  
  1053  	// CtimeNsec is the nano second part of Ctime.
  1054  	CtimeNsec uint32
  1055  
  1056  	// Mode is the file mode that the request wants to change to.
  1057  	Mode uint32
  1058  
  1059  	_ uint32
  1060  
  1061  	// UID is the user ID of the owner that the request wants to change to.
  1062  	UID uint32
  1063  
  1064  	// GID is the group ID of the owner that the request wants to change to.
  1065  	GID uint32
  1066  
  1067  	_ uint32
  1068  }
  1069  
  1070  // FUSEUnlinkIn is the request sent by the kernel to the daemon
  1071  // when trying to unlink a node.
  1072  //
  1073  // +marshal dynamic
  1074  type FUSEUnlinkIn struct {
  1075  	// Name of the node to unlink.
  1076  	Name CString
  1077  }
  1078  
  1079  // MarshalBytes implements marshal.Marshallable.MarshalBytes.
  1080  func (r *FUSEUnlinkIn) MarshalBytes(buf []byte) []byte {
  1081  	return r.Name.MarshalBytes(buf)
  1082  }
  1083  
  1084  // UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
  1085  func (r *FUSEUnlinkIn) UnmarshalBytes(buf []byte) []byte {
  1086  	panic("Unimplemented, FUSEUnlinkIn is never unmarshalled")
  1087  }
  1088  
  1089  // SizeBytes implements marshal.Marshallable.SizeBytes.
  1090  func (r *FUSEUnlinkIn) SizeBytes() int {
  1091  	return r.Name.SizeBytes()
  1092  }
  1093  
  1094  // FUSEFsyncIn is the request sent by the kernel to the daemon
  1095  // when trying to fsync a file.
  1096  //
  1097  // +marshal
  1098  type FUSEFsyncIn struct {
  1099  	Fh uint64
  1100  
  1101  	FsyncFlags uint32
  1102  
  1103  	// padding
  1104  	_ uint32
  1105  }
  1106  
  1107  // FUSEAccessIn is the request sent by the kernel to the daemon when checking
  1108  // permissions on a file.
  1109  //
  1110  // +marshal
  1111  type FUSEAccessIn struct {
  1112  	Mask uint32
  1113  	// padding
  1114  	_ uint32
  1115  }
  1116  
  1117  // FUSEFallocateIn is the request sent by the kernel to the daemon to perform
  1118  // a fallocate operation.
  1119  //
  1120  // +marshal
  1121  type FUSEFallocateIn struct {
  1122  	Fh     uint64
  1123  	Offset uint64
  1124  	Length uint64
  1125  	Mode   uint32
  1126  	// padding
  1127  	_ uint32
  1128  }
  1129  
  1130  // FUSEFlushIn is the request sent by the kernel to the daemon after a file is
  1131  // closed.
  1132  //
  1133  // +marshal
  1134  type FUSEFlushIn struct {
  1135  	Fh        uint64
  1136  	_         uint32 // unused
  1137  	_         uint32 // padding
  1138  	LockOwner uint64
  1139  }