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  }