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