github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/p9/p9.go (about)

     1  // Copyright 2018 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 p9 is a 9P2000.L implementation.
    16  package p9
    17  
    18  import (
    19  	"fmt"
    20  	"math"
    21  	"os"
    22  	"strings"
    23  	"sync/atomic"
    24  	"syscall"
    25  
    26  	"golang.org/x/sys/unix"
    27  )
    28  
    29  // OpenFlags is the mode passed to Open and Create operations.
    30  //
    31  // These correspond to bits sent over the wire.
    32  type OpenFlags uint32
    33  
    34  const (
    35  	// ReadOnly is a Tlopen and Tlcreate flag indicating read-only mode.
    36  	ReadOnly OpenFlags = 0
    37  
    38  	// WriteOnly is a Tlopen and Tlcreate flag indicating write-only mode.
    39  	WriteOnly OpenFlags = 1
    40  
    41  	// ReadWrite is a Tlopen flag indicates read-write mode.
    42  	ReadWrite OpenFlags = 2
    43  
    44  	// OpenFlagsModeMask is a mask of valid OpenFlags mode bits.
    45  	OpenFlagsModeMask OpenFlags = 3
    46  
    47  	// OpenTruncate is a Tlopen flag indicating that the opened file should be
    48  	// truncated.
    49  	OpenTruncate OpenFlags = 01000
    50  )
    51  
    52  // ConnectFlags is the mode passed to Connect operations.
    53  //
    54  // These correspond to bits sent over the wire.
    55  type ConnectFlags uint32
    56  
    57  const (
    58  	// StreamSocket is a Tlconnect flag indicating SOCK_STREAM mode.
    59  	StreamSocket ConnectFlags = 0
    60  
    61  	// DgramSocket is a Tlconnect flag indicating SOCK_DGRAM mode.
    62  	DgramSocket ConnectFlags = 1
    63  
    64  	// SeqpacketSocket is a Tlconnect flag indicating SOCK_SEQPACKET mode.
    65  	SeqpacketSocket ConnectFlags = 2
    66  
    67  	// AnonymousSocket is a Tlconnect flag indicating that the mode does not
    68  	// matter and that the requester will accept any socket type.
    69  	AnonymousSocket ConnectFlags = 3
    70  )
    71  
    72  // OSFlags converts a p9.OpenFlags to an int compatible with open(2).
    73  func (o OpenFlags) OSFlags() int {
    74  	// "flags contains Linux open(2) flags bits" - 9P2000.L
    75  	return int(o)
    76  }
    77  
    78  // String implements fmt.Stringer.
    79  func (o OpenFlags) String() string {
    80  	var buf strings.Builder
    81  	switch mode := o & OpenFlagsModeMask; mode {
    82  	case ReadOnly:
    83  		buf.WriteString("ReadOnly")
    84  	case WriteOnly:
    85  		buf.WriteString("WriteOnly")
    86  	case ReadWrite:
    87  		buf.WriteString("ReadWrite")
    88  	default:
    89  		fmt.Fprintf(&buf, "%#o", mode)
    90  	}
    91  	otherFlags := o &^ OpenFlagsModeMask
    92  	if otherFlags&OpenTruncate != 0 {
    93  		buf.WriteString("|OpenTruncate")
    94  		otherFlags &^= OpenTruncate
    95  	}
    96  	if otherFlags != 0 {
    97  		fmt.Fprintf(&buf, "|%#o", otherFlags)
    98  	}
    99  	return buf.String()
   100  }
   101  
   102  // Tag is a message tag.
   103  type Tag uint16
   104  
   105  // FID is a file identifier.
   106  type FID uint64
   107  
   108  // FileMode are flags corresponding to file modes.
   109  //
   110  // These correspond to bits sent over the wire.
   111  // These also correspond to mode_t bits.
   112  type FileMode uint32
   113  
   114  const (
   115  	// FileModeMask is a mask of all the file mode bits of FileMode.
   116  	FileModeMask FileMode = 0170000
   117  
   118  	// ModeSocket is an (unused) mode bit for a socket.
   119  	ModeSocket FileMode = 0140000
   120  
   121  	// ModeSymlink is a mode bit for a symlink.
   122  	ModeSymlink FileMode = 0120000
   123  
   124  	// ModeRegular is a mode bit for regular files.
   125  	ModeRegular FileMode = 0100000
   126  
   127  	// ModeBlockDevice is a mode bit for block devices.
   128  	ModeBlockDevice FileMode = 060000
   129  
   130  	// ModeDirectory is a mode bit for directories.
   131  	ModeDirectory FileMode = 040000
   132  
   133  	// ModeCharacterDevice is a mode bit for a character device.
   134  	ModeCharacterDevice FileMode = 020000
   135  
   136  	// ModeNamedPipe is a mode bit for a named pipe.
   137  	ModeNamedPipe FileMode = 010000
   138  
   139  	// Read is a mode bit indicating read permission.
   140  	Read FileMode = 04
   141  
   142  	// Write is a mode bit indicating write permission.
   143  	Write FileMode = 02
   144  
   145  	// Exec is a mode bit indicating exec permission.
   146  	Exec FileMode = 01
   147  
   148  	// AllPermissions is a mask with rwx bits set for user, group and others.
   149  	AllPermissions FileMode = 0777
   150  
   151  	// Sticky is a mode bit indicating sticky directories.
   152  	Sticky FileMode = 01000
   153  
   154  	// SetGID is the set group ID bit.
   155  	SetGID FileMode = 02000
   156  
   157  	// SetUID is the set user ID bit.
   158  	SetUID FileMode = 04000
   159  
   160  	// permissionsMask is the mask to apply to FileModes for permissions. It
   161  	// includes rwx bits for user, group, and others, as well as the sticky
   162  	// bit, setuid bit, and setgid bit.
   163  	permissionsMask FileMode = 07777
   164  )
   165  
   166  // QIDType is the most significant byte of the FileMode word, to be used as the
   167  // Type field of p9.QID.
   168  func (m FileMode) QIDType() QIDType {
   169  	switch {
   170  	case m.IsDir():
   171  		return TypeDir
   172  	case m.IsSocket(), m.IsNamedPipe(), m.IsCharacterDevice():
   173  		// Best approximation.
   174  		return TypeAppendOnly
   175  	case m.IsSymlink():
   176  		return TypeSymlink
   177  	default:
   178  		return TypeRegular
   179  	}
   180  }
   181  
   182  // FileType returns the file mode without the permission bits.
   183  func (m FileMode) FileType() FileMode {
   184  	return m & FileModeMask
   185  }
   186  
   187  // Permissions returns just the permission bits of the mode.
   188  func (m FileMode) Permissions() FileMode {
   189  	return m & permissionsMask
   190  }
   191  
   192  // Writable returns the mode with write bits added.
   193  func (m FileMode) Writable() FileMode {
   194  	return m | 0222
   195  }
   196  
   197  // IsReadable returns true if m represents a file that can be read.
   198  func (m FileMode) IsReadable() bool {
   199  	return m&0444 != 0
   200  }
   201  
   202  // IsWritable returns true if m represents a file that can be written to.
   203  func (m FileMode) IsWritable() bool {
   204  	return m&0222 != 0
   205  }
   206  
   207  // IsExecutable returns true if m represents a file that can be executed.
   208  func (m FileMode) IsExecutable() bool {
   209  	return m&0111 != 0
   210  }
   211  
   212  // IsRegular returns true if m is a regular file.
   213  func (m FileMode) IsRegular() bool {
   214  	return m&FileModeMask == ModeRegular
   215  }
   216  
   217  // IsDir returns true if m represents a directory.
   218  func (m FileMode) IsDir() bool {
   219  	return m&FileModeMask == ModeDirectory
   220  }
   221  
   222  // IsNamedPipe returns true if m represents a named pipe.
   223  func (m FileMode) IsNamedPipe() bool {
   224  	return m&FileModeMask == ModeNamedPipe
   225  }
   226  
   227  // IsCharacterDevice returns true if m represents a character device.
   228  func (m FileMode) IsCharacterDevice() bool {
   229  	return m&FileModeMask == ModeCharacterDevice
   230  }
   231  
   232  // IsBlockDevice returns true if m represents a character device.
   233  func (m FileMode) IsBlockDevice() bool {
   234  	return m&FileModeMask == ModeBlockDevice
   235  }
   236  
   237  // IsSocket returns true if m represents a socket.
   238  func (m FileMode) IsSocket() bool {
   239  	return m&FileModeMask == ModeSocket
   240  }
   241  
   242  // IsSymlink returns true if m represents a symlink.
   243  func (m FileMode) IsSymlink() bool {
   244  	return m&FileModeMask == ModeSymlink
   245  }
   246  
   247  // ModeFromOS returns a FileMode from an os.FileMode.
   248  func ModeFromOS(mode os.FileMode) FileMode {
   249  	m := FileMode(mode.Perm())
   250  	switch {
   251  	case mode.IsDir():
   252  		m |= ModeDirectory
   253  	case mode&os.ModeSymlink != 0:
   254  		m |= ModeSymlink
   255  	case mode&os.ModeSocket != 0:
   256  		m |= ModeSocket
   257  	case mode&os.ModeNamedPipe != 0:
   258  		m |= ModeNamedPipe
   259  	case mode&os.ModeCharDevice != 0:
   260  		m |= ModeCharacterDevice
   261  	case mode&os.ModeDevice != 0:
   262  		m |= ModeBlockDevice
   263  	default:
   264  		m |= ModeRegular
   265  	}
   266  	return m
   267  }
   268  
   269  // OSMode converts a p9.FileMode to an os.FileMode.
   270  func (m FileMode) OSMode() os.FileMode {
   271  	var osMode os.FileMode
   272  	osMode |= os.FileMode(m.Permissions())
   273  	switch {
   274  	case m.IsDir():
   275  		osMode |= os.ModeDir
   276  	case m.IsSymlink():
   277  		osMode |= os.ModeSymlink
   278  	case m.IsSocket():
   279  		osMode |= os.ModeSocket
   280  	case m.IsNamedPipe():
   281  		osMode |= os.ModeNamedPipe
   282  	case m.IsCharacterDevice():
   283  		osMode |= os.ModeCharDevice | os.ModeDevice
   284  	case m.IsBlockDevice():
   285  		osMode |= os.ModeDevice
   286  	}
   287  	return osMode
   288  }
   289  
   290  // UID represents a user ID.
   291  type UID uint32
   292  
   293  // Ok returns true if uid is not NoUID.
   294  func (uid UID) Ok() bool {
   295  	return uid != NoUID
   296  }
   297  
   298  // GID represents a group ID.
   299  type GID uint32
   300  
   301  // Ok returns true if gid is not NoGID.
   302  func (gid GID) Ok() bool {
   303  	return gid != NoGID
   304  }
   305  
   306  const (
   307  	// NoTag is a sentinel used to indicate no valid tag.
   308  	NoTag Tag = math.MaxUint16
   309  
   310  	// NoFID is a sentinel used to indicate no valid FID.
   311  	NoFID FID = math.MaxUint32
   312  
   313  	// NoUID is a sentinel used to indicate no valid UID.
   314  	NoUID UID = math.MaxUint32
   315  
   316  	// NoGID is a sentinel used to indicate no valid GID.
   317  	NoGID GID = math.MaxUint32
   318  )
   319  
   320  // MsgType is a type identifier.
   321  type MsgType uint8
   322  
   323  // MsgType declarations.
   324  const (
   325  	MsgTlerror       MsgType = 6
   326  	MsgRlerror       MsgType = 7
   327  	MsgTstatfs       MsgType = 8
   328  	MsgRstatfs       MsgType = 9
   329  	MsgTlopen        MsgType = 12
   330  	MsgRlopen        MsgType = 13
   331  	MsgTlcreate      MsgType = 14
   332  	MsgRlcreate      MsgType = 15
   333  	MsgTsymlink      MsgType = 16
   334  	MsgRsymlink      MsgType = 17
   335  	MsgTmknod        MsgType = 18
   336  	MsgRmknod        MsgType = 19
   337  	MsgTrename       MsgType = 20
   338  	MsgRrename       MsgType = 21
   339  	MsgTreadlink     MsgType = 22
   340  	MsgRreadlink     MsgType = 23
   341  	MsgTgetattr      MsgType = 24
   342  	MsgRgetattr      MsgType = 25
   343  	MsgTsetattr      MsgType = 26
   344  	MsgRsetattr      MsgType = 27
   345  	MsgTlistxattr    MsgType = 28
   346  	MsgRlistxattr    MsgType = 29
   347  	MsgTxattrwalk    MsgType = 30
   348  	MsgRxattrwalk    MsgType = 31
   349  	MsgTxattrcreate  MsgType = 32
   350  	MsgRxattrcreate  MsgType = 33
   351  	MsgTgetxattr     MsgType = 34
   352  	MsgRgetxattr     MsgType = 35
   353  	MsgTsetxattr     MsgType = 36
   354  	MsgRsetxattr     MsgType = 37
   355  	MsgTremovexattr  MsgType = 38
   356  	MsgRremovexattr  MsgType = 39
   357  	MsgTreaddir      MsgType = 40
   358  	MsgRreaddir      MsgType = 41
   359  	MsgTfsync        MsgType = 50
   360  	MsgRfsync        MsgType = 51
   361  	MsgTlink         MsgType = 70
   362  	MsgRlink         MsgType = 71
   363  	MsgTmkdir        MsgType = 72
   364  	MsgRmkdir        MsgType = 73
   365  	MsgTrenameat     MsgType = 74
   366  	MsgRrenameat     MsgType = 75
   367  	MsgTunlinkat     MsgType = 76
   368  	MsgRunlinkat     MsgType = 77
   369  	MsgTversion      MsgType = 100
   370  	MsgRversion      MsgType = 101
   371  	MsgTauth         MsgType = 102
   372  	MsgRauth         MsgType = 103
   373  	MsgTattach       MsgType = 104
   374  	MsgRattach       MsgType = 105
   375  	MsgTflush        MsgType = 108
   376  	MsgRflush        MsgType = 109
   377  	MsgTwalk         MsgType = 110
   378  	MsgRwalk         MsgType = 111
   379  	MsgTread         MsgType = 116
   380  	MsgRread         MsgType = 117
   381  	MsgTwrite        MsgType = 118
   382  	MsgRwrite        MsgType = 119
   383  	MsgTclunk        MsgType = 120
   384  	MsgRclunk        MsgType = 121
   385  	MsgTremove       MsgType = 122
   386  	MsgRremove       MsgType = 123
   387  	MsgTflushf       MsgType = 124
   388  	MsgRflushf       MsgType = 125
   389  	MsgTwalkgetattr  MsgType = 126
   390  	MsgRwalkgetattr  MsgType = 127
   391  	MsgTucreate      MsgType = 128
   392  	MsgRucreate      MsgType = 129
   393  	MsgTumkdir       MsgType = 130
   394  	MsgRumkdir       MsgType = 131
   395  	MsgTumknod       MsgType = 132
   396  	MsgRumknod       MsgType = 133
   397  	MsgTusymlink     MsgType = 134
   398  	MsgRusymlink     MsgType = 135
   399  	MsgTlconnect     MsgType = 136
   400  	MsgRlconnect     MsgType = 137
   401  	MsgTallocate     MsgType = 138
   402  	MsgRallocate     MsgType = 139
   403  	MsgTsetattrclunk MsgType = 140
   404  	MsgRsetattrclunk MsgType = 141
   405  	MsgTmultigetattr MsgType = 142
   406  	MsgRmultigetattr MsgType = 143
   407  	MsgTchannel      MsgType = 250
   408  	MsgRchannel      MsgType = 251
   409  )
   410  
   411  // QIDType represents the file type for QIDs.
   412  //
   413  // QIDType corresponds to the high 8 bits of a Plan 9 file mode.
   414  type QIDType uint8
   415  
   416  const (
   417  	// TypeDir represents a directory type.
   418  	TypeDir QIDType = 0x80
   419  
   420  	// TypeAppendOnly represents an append only file.
   421  	TypeAppendOnly QIDType = 0x40
   422  
   423  	// TypeExclusive represents an exclusive-use file.
   424  	TypeExclusive QIDType = 0x20
   425  
   426  	// TypeMount represents a mounted channel.
   427  	TypeMount QIDType = 0x10
   428  
   429  	// TypeAuth represents an authentication file.
   430  	TypeAuth QIDType = 0x08
   431  
   432  	// TypeTemporary represents a temporary file.
   433  	TypeTemporary QIDType = 0x04
   434  
   435  	// TypeSymlink represents a symlink.
   436  	TypeSymlink QIDType = 0x02
   437  
   438  	// TypeLink represents a hard link.
   439  	TypeLink QIDType = 0x01
   440  
   441  	// TypeRegular represents a regular file.
   442  	TypeRegular QIDType = 0x00
   443  )
   444  
   445  // QID is a unique file identifier.
   446  //
   447  // This may be embedded in other requests and responses.
   448  type QID struct {
   449  	// Type is the highest order byte of the file mode.
   450  	Type QIDType
   451  
   452  	// Version is an arbitrary server version number.
   453  	Version uint32
   454  
   455  	// Path is a unique server identifier for this path (e.g. inode).
   456  	Path uint64
   457  }
   458  
   459  // String implements fmt.Stringer.
   460  func (q QID) String() string {
   461  	return fmt.Sprintf("QID{Type: %d, Version: %d, Path: %d}", q.Type, q.Version, q.Path)
   462  }
   463  
   464  // decode implements encoder.decode.
   465  func (q *QID) decode(b *buffer) {
   466  	q.Type = b.ReadQIDType()
   467  	q.Version = b.Read32()
   468  	q.Path = b.Read64()
   469  }
   470  
   471  // encode implements encoder.encode.
   472  func (q *QID) encode(b *buffer) {
   473  	b.WriteQIDType(q.Type)
   474  	b.Write32(q.Version)
   475  	b.Write64(q.Path)
   476  }
   477  
   478  // QIDGenerator is a simple generator for QIDs that atomically increments Path
   479  // values.
   480  type QIDGenerator struct {
   481  	// uids is an ever increasing value that can be atomically incremented
   482  	// to provide unique Path values for QIDs.
   483  	uids uint64
   484  }
   485  
   486  // Get returns a new 9P unique ID with a unique Path given a QID type.
   487  //
   488  // While the 9P spec allows Version to be incremented every time the file is
   489  // modified, we currently do not use the Version member for anything.  Hence,
   490  // it is set to 0.
   491  func (q *QIDGenerator) Get(t QIDType) QID {
   492  	return QID{
   493  		Type:    t,
   494  		Version: 0,
   495  		Path:    atomic.AddUint64(&q.uids, 1),
   496  	}
   497  }
   498  
   499  // FSStat is used by statfs.
   500  type FSStat struct {
   501  	// Type is the filesystem type.
   502  	Type uint32
   503  
   504  	// BlockSize is the blocksize.
   505  	BlockSize uint32
   506  
   507  	// Blocks is the number of blocks.
   508  	Blocks uint64
   509  
   510  	// BlocksFree is the number of free blocks.
   511  	BlocksFree uint64
   512  
   513  	// BlocksAvailable is the number of blocks *available*.
   514  	BlocksAvailable uint64
   515  
   516  	// Files is the number of files available.
   517  	Files uint64
   518  
   519  	// FilesFree is the number of free file nodes.
   520  	FilesFree uint64
   521  
   522  	// FSID is the filesystem ID.
   523  	FSID uint64
   524  
   525  	// NameLength is the maximum name length.
   526  	NameLength uint32
   527  }
   528  
   529  // decode implements encoder.decode.
   530  func (f *FSStat) decode(b *buffer) {
   531  	f.Type = b.Read32()
   532  	f.BlockSize = b.Read32()
   533  	f.Blocks = b.Read64()
   534  	f.BlocksFree = b.Read64()
   535  	f.BlocksAvailable = b.Read64()
   536  	f.Files = b.Read64()
   537  	f.FilesFree = b.Read64()
   538  	f.FSID = b.Read64()
   539  	f.NameLength = b.Read32()
   540  }
   541  
   542  // encode implements encoder.encode.
   543  func (f *FSStat) encode(b *buffer) {
   544  	b.Write32(f.Type)
   545  	b.Write32(f.BlockSize)
   546  	b.Write64(f.Blocks)
   547  	b.Write64(f.BlocksFree)
   548  	b.Write64(f.BlocksAvailable)
   549  	b.Write64(f.Files)
   550  	b.Write64(f.FilesFree)
   551  	b.Write64(f.FSID)
   552  	b.Write32(f.NameLength)
   553  }
   554  
   555  // AttrMask is a mask of attributes for getattr.
   556  type AttrMask struct {
   557  	Mode        bool
   558  	NLink       bool
   559  	UID         bool
   560  	GID         bool
   561  	RDev        bool
   562  	ATime       bool
   563  	MTime       bool
   564  	CTime       bool
   565  	INo         bool
   566  	Size        bool
   567  	Blocks      bool
   568  	BTime       bool
   569  	Gen         bool
   570  	DataVersion bool
   571  }
   572  
   573  // Contains returns true if a contains all of the attributes masked as b.
   574  func (a AttrMask) Contains(b AttrMask) bool {
   575  	if b.Mode && !a.Mode {
   576  		return false
   577  	}
   578  	if b.NLink && !a.NLink {
   579  		return false
   580  	}
   581  	if b.UID && !a.UID {
   582  		return false
   583  	}
   584  	if b.GID && !a.GID {
   585  		return false
   586  	}
   587  	if b.RDev && !a.RDev {
   588  		return false
   589  	}
   590  	if b.ATime && !a.ATime {
   591  		return false
   592  	}
   593  	if b.MTime && !a.MTime {
   594  		return false
   595  	}
   596  	if b.CTime && !a.CTime {
   597  		return false
   598  	}
   599  	if b.INo && !a.INo {
   600  		return false
   601  	}
   602  	if b.Size && !a.Size {
   603  		return false
   604  	}
   605  	if b.Blocks && !a.Blocks {
   606  		return false
   607  	}
   608  	if b.BTime && !a.BTime {
   609  		return false
   610  	}
   611  	if b.Gen && !a.Gen {
   612  		return false
   613  	}
   614  	if b.DataVersion && !a.DataVersion {
   615  		return false
   616  	}
   617  	return true
   618  }
   619  
   620  // Empty returns true if no fields are masked.
   621  func (a AttrMask) Empty() bool {
   622  	return !a.Mode && !a.NLink && !a.UID && !a.GID && !a.RDev && !a.ATime && !a.MTime && !a.CTime && !a.INo && !a.Size && !a.Blocks && !a.BTime && !a.Gen && !a.DataVersion
   623  }
   624  
   625  // AttrMaskAll returns an AttrMask with all fields masked.
   626  func AttrMaskAll() AttrMask {
   627  	return AttrMask{
   628  		Mode:        true,
   629  		NLink:       true,
   630  		UID:         true,
   631  		GID:         true,
   632  		RDev:        true,
   633  		ATime:       true,
   634  		MTime:       true,
   635  		CTime:       true,
   636  		INo:         true,
   637  		Size:        true,
   638  		Blocks:      true,
   639  		BTime:       true,
   640  		Gen:         true,
   641  		DataVersion: true,
   642  	}
   643  }
   644  
   645  // String implements fmt.Stringer.
   646  func (a AttrMask) String() string {
   647  	var masks []string
   648  	if a.Mode {
   649  		masks = append(masks, "Mode")
   650  	}
   651  	if a.NLink {
   652  		masks = append(masks, "NLink")
   653  	}
   654  	if a.UID {
   655  		masks = append(masks, "UID")
   656  	}
   657  	if a.GID {
   658  		masks = append(masks, "GID")
   659  	}
   660  	if a.RDev {
   661  		masks = append(masks, "RDev")
   662  	}
   663  	if a.ATime {
   664  		masks = append(masks, "ATime")
   665  	}
   666  	if a.MTime {
   667  		masks = append(masks, "MTime")
   668  	}
   669  	if a.CTime {
   670  		masks = append(masks, "CTime")
   671  	}
   672  	if a.INo {
   673  		masks = append(masks, "INo")
   674  	}
   675  	if a.Size {
   676  		masks = append(masks, "Size")
   677  	}
   678  	if a.Blocks {
   679  		masks = append(masks, "Blocks")
   680  	}
   681  	if a.BTime {
   682  		masks = append(masks, "BTime")
   683  	}
   684  	if a.Gen {
   685  		masks = append(masks, "Gen")
   686  	}
   687  	if a.DataVersion {
   688  		masks = append(masks, "DataVersion")
   689  	}
   690  	return fmt.Sprintf("AttrMask{with: %s}", strings.Join(masks, " "))
   691  }
   692  
   693  // decode implements encoder.decode.
   694  func (a *AttrMask) decode(b *buffer) {
   695  	mask := b.Read64()
   696  	a.Mode = mask&0x00000001 != 0
   697  	a.NLink = mask&0x00000002 != 0
   698  	a.UID = mask&0x00000004 != 0
   699  	a.GID = mask&0x00000008 != 0
   700  	a.RDev = mask&0x00000010 != 0
   701  	a.ATime = mask&0x00000020 != 0
   702  	a.MTime = mask&0x00000040 != 0
   703  	a.CTime = mask&0x00000080 != 0
   704  	a.INo = mask&0x00000100 != 0
   705  	a.Size = mask&0x00000200 != 0
   706  	a.Blocks = mask&0x00000400 != 0
   707  	a.BTime = mask&0x00000800 != 0
   708  	a.Gen = mask&0x00001000 != 0
   709  	a.DataVersion = mask&0x00002000 != 0
   710  }
   711  
   712  // encode implements encoder.encode.
   713  func (a *AttrMask) encode(b *buffer) {
   714  	var mask uint64
   715  	if a.Mode {
   716  		mask |= 0x00000001
   717  	}
   718  	if a.NLink {
   719  		mask |= 0x00000002
   720  	}
   721  	if a.UID {
   722  		mask |= 0x00000004
   723  	}
   724  	if a.GID {
   725  		mask |= 0x00000008
   726  	}
   727  	if a.RDev {
   728  		mask |= 0x00000010
   729  	}
   730  	if a.ATime {
   731  		mask |= 0x00000020
   732  	}
   733  	if a.MTime {
   734  		mask |= 0x00000040
   735  	}
   736  	if a.CTime {
   737  		mask |= 0x00000080
   738  	}
   739  	if a.INo {
   740  		mask |= 0x00000100
   741  	}
   742  	if a.Size {
   743  		mask |= 0x00000200
   744  	}
   745  	if a.Blocks {
   746  		mask |= 0x00000400
   747  	}
   748  	if a.BTime {
   749  		mask |= 0x00000800
   750  	}
   751  	if a.Gen {
   752  		mask |= 0x00001000
   753  	}
   754  	if a.DataVersion {
   755  		mask |= 0x00002000
   756  	}
   757  	b.Write64(mask)
   758  }
   759  
   760  // Attr is a set of attributes for getattr.
   761  type Attr struct {
   762  	Mode             FileMode
   763  	UID              UID
   764  	GID              GID
   765  	NLink            uint64
   766  	RDev             uint64
   767  	Size             uint64
   768  	BlockSize        uint64
   769  	Blocks           uint64
   770  	ATimeSeconds     uint64
   771  	ATimeNanoSeconds uint64
   772  	MTimeSeconds     uint64
   773  	MTimeNanoSeconds uint64
   774  	CTimeSeconds     uint64
   775  	CTimeNanoSeconds uint64
   776  	BTimeSeconds     uint64
   777  	BTimeNanoSeconds uint64
   778  	Gen              uint64
   779  	DataVersion      uint64
   780  }
   781  
   782  // String implements fmt.Stringer.
   783  func (a Attr) String() string {
   784  	return fmt.Sprintf("Attr{Mode: 0o%o, UID: %d, GID: %d, NLink: %d, RDev: %d, Size: %d, BlockSize: %d, Blocks: %d, ATime: {Sec: %d, NanoSec: %d}, MTime: {Sec: %d, NanoSec: %d}, CTime: {Sec: %d, NanoSec: %d}, BTime: {Sec: %d, NanoSec: %d}, Gen: %d, DataVersion: %d}",
   785  		a.Mode, a.UID, a.GID, a.NLink, a.RDev, a.Size, a.BlockSize, a.Blocks, a.ATimeSeconds, a.ATimeNanoSeconds, a.MTimeSeconds, a.MTimeNanoSeconds, a.CTimeSeconds, a.CTimeNanoSeconds, a.BTimeSeconds, a.BTimeNanoSeconds, a.Gen, a.DataVersion)
   786  }
   787  
   788  // encode implements encoder.encode.
   789  func (a *Attr) encode(b *buffer) {
   790  	b.WriteFileMode(a.Mode)
   791  	b.WriteUID(a.UID)
   792  	b.WriteGID(a.GID)
   793  	b.Write64(a.NLink)
   794  	b.Write64(a.RDev)
   795  	b.Write64(a.Size)
   796  	b.Write64(a.BlockSize)
   797  	b.Write64(a.Blocks)
   798  	b.Write64(a.ATimeSeconds)
   799  	b.Write64(a.ATimeNanoSeconds)
   800  	b.Write64(a.MTimeSeconds)
   801  	b.Write64(a.MTimeNanoSeconds)
   802  	b.Write64(a.CTimeSeconds)
   803  	b.Write64(a.CTimeNanoSeconds)
   804  	b.Write64(a.BTimeSeconds)
   805  	b.Write64(a.BTimeNanoSeconds)
   806  	b.Write64(a.Gen)
   807  	b.Write64(a.DataVersion)
   808  }
   809  
   810  // decode implements encoder.decode.
   811  func (a *Attr) decode(b *buffer) {
   812  	a.Mode = b.ReadFileMode()
   813  	a.UID = b.ReadUID()
   814  	a.GID = b.ReadGID()
   815  	a.NLink = b.Read64()
   816  	a.RDev = b.Read64()
   817  	a.Size = b.Read64()
   818  	a.BlockSize = b.Read64()
   819  	a.Blocks = b.Read64()
   820  	a.ATimeSeconds = b.Read64()
   821  	a.ATimeNanoSeconds = b.Read64()
   822  	a.MTimeSeconds = b.Read64()
   823  	a.MTimeNanoSeconds = b.Read64()
   824  	a.CTimeSeconds = b.Read64()
   825  	a.CTimeNanoSeconds = b.Read64()
   826  	a.BTimeSeconds = b.Read64()
   827  	a.BTimeNanoSeconds = b.Read64()
   828  	a.Gen = b.Read64()
   829  	a.DataVersion = b.Read64()
   830  }
   831  
   832  // StatToAttr converts a Linux syscall stat structure to an Attr.
   833  func StatToAttr(s *syscall.Stat_t, req AttrMask) (Attr, AttrMask) {
   834  	attr := Attr{
   835  		UID: NoUID,
   836  		GID: NoGID,
   837  	}
   838  	if req.Mode {
   839  		// p9.FileMode corresponds to Linux mode_t.
   840  		attr.Mode = FileMode(s.Mode)
   841  	}
   842  	if req.NLink {
   843  		attr.NLink = uint64(s.Nlink)
   844  	}
   845  	if req.UID {
   846  		attr.UID = UID(s.Uid)
   847  	}
   848  	if req.GID {
   849  		attr.GID = GID(s.Gid)
   850  	}
   851  	if req.RDev {
   852  		attr.RDev = s.Dev
   853  	}
   854  	if req.ATime {
   855  		attr.ATimeSeconds = uint64(s.Atim.Sec)
   856  		attr.ATimeNanoSeconds = uint64(s.Atim.Nsec)
   857  	}
   858  	if req.MTime {
   859  		attr.MTimeSeconds = uint64(s.Mtim.Sec)
   860  		attr.MTimeNanoSeconds = uint64(s.Mtim.Nsec)
   861  	}
   862  	if req.CTime {
   863  		attr.CTimeSeconds = uint64(s.Ctim.Sec)
   864  		attr.CTimeNanoSeconds = uint64(s.Ctim.Nsec)
   865  	}
   866  	if req.Size {
   867  		attr.Size = uint64(s.Size)
   868  	}
   869  	if req.Blocks {
   870  		attr.BlockSize = uint64(s.Blksize)
   871  		attr.Blocks = uint64(s.Blocks)
   872  	}
   873  
   874  	// Use the req field because we already have it.
   875  	req.BTime = false
   876  	req.Gen = false
   877  	req.DataVersion = false
   878  
   879  	return attr, req
   880  }
   881  
   882  // SetAttrMask specifies a valid mask for setattr.
   883  type SetAttrMask struct {
   884  	Permissions        bool
   885  	UID                bool
   886  	GID                bool
   887  	Size               bool
   888  	ATime              bool
   889  	MTime              bool
   890  	CTime              bool
   891  	ATimeNotSystemTime bool
   892  	MTimeNotSystemTime bool
   893  }
   894  
   895  // IsSubsetOf returns whether s is a subset of m.
   896  func (s SetAttrMask) IsSubsetOf(m SetAttrMask) bool {
   897  	sb := s.bitmask()
   898  	sm := m.bitmask()
   899  	return sm|sb == sm
   900  }
   901  
   902  // String implements fmt.Stringer.
   903  func (s SetAttrMask) String() string {
   904  	var masks []string
   905  	if s.Permissions {
   906  		masks = append(masks, "Permissions")
   907  	}
   908  	if s.UID {
   909  		masks = append(masks, "UID")
   910  	}
   911  	if s.GID {
   912  		masks = append(masks, "GID")
   913  	}
   914  	if s.Size {
   915  		masks = append(masks, "Size")
   916  	}
   917  	if s.ATime {
   918  		masks = append(masks, "ATime")
   919  	}
   920  	if s.MTime {
   921  		masks = append(masks, "MTime")
   922  	}
   923  	if s.CTime {
   924  		masks = append(masks, "CTime")
   925  	}
   926  	if s.ATimeNotSystemTime {
   927  		masks = append(masks, "ATimeNotSystemTime")
   928  	}
   929  	if s.MTimeNotSystemTime {
   930  		masks = append(masks, "MTimeNotSystemTime")
   931  	}
   932  	return fmt.Sprintf("SetAttrMask{with: %s}", strings.Join(masks, " "))
   933  }
   934  
   935  // Empty returns true if no fields are masked.
   936  func (s SetAttrMask) Empty() bool {
   937  	return !s.Permissions && !s.UID && !s.GID && !s.Size && !s.ATime && !s.MTime && !s.CTime && !s.ATimeNotSystemTime && !s.MTimeNotSystemTime
   938  }
   939  
   940  // decode implements encoder.decode.
   941  func (s *SetAttrMask) decode(b *buffer) {
   942  	mask := b.Read32()
   943  	s.Permissions = mask&0x00000001 != 0
   944  	s.UID = mask&0x00000002 != 0
   945  	s.GID = mask&0x00000004 != 0
   946  	s.Size = mask&0x00000008 != 0
   947  	s.ATime = mask&0x00000010 != 0
   948  	s.MTime = mask&0x00000020 != 0
   949  	s.CTime = mask&0x00000040 != 0
   950  	s.ATimeNotSystemTime = mask&0x00000080 != 0
   951  	s.MTimeNotSystemTime = mask&0x00000100 != 0
   952  }
   953  
   954  func (s SetAttrMask) bitmask() uint32 {
   955  	var mask uint32
   956  	if s.Permissions {
   957  		mask |= 0x00000001
   958  	}
   959  	if s.UID {
   960  		mask |= 0x00000002
   961  	}
   962  	if s.GID {
   963  		mask |= 0x00000004
   964  	}
   965  	if s.Size {
   966  		mask |= 0x00000008
   967  	}
   968  	if s.ATime {
   969  		mask |= 0x00000010
   970  	}
   971  	if s.MTime {
   972  		mask |= 0x00000020
   973  	}
   974  	if s.CTime {
   975  		mask |= 0x00000040
   976  	}
   977  	if s.ATimeNotSystemTime {
   978  		mask |= 0x00000080
   979  	}
   980  	if s.MTimeNotSystemTime {
   981  		mask |= 0x00000100
   982  	}
   983  	return mask
   984  }
   985  
   986  // encode implements encoder.encode.
   987  func (s *SetAttrMask) encode(b *buffer) {
   988  	b.Write32(s.bitmask())
   989  }
   990  
   991  // SetAttr specifies a set of attributes for a setattr.
   992  type SetAttr struct {
   993  	Permissions      FileMode
   994  	UID              UID
   995  	GID              GID
   996  	Size             uint64
   997  	ATimeSeconds     uint64
   998  	ATimeNanoSeconds uint64
   999  	MTimeSeconds     uint64
  1000  	MTimeNanoSeconds uint64
  1001  }
  1002  
  1003  // String implements fmt.Stringer.
  1004  func (s SetAttr) String() string {
  1005  	return fmt.Sprintf("SetAttr{Permissions: 0o%o, UID: %d, GID: %d, Size: %d, ATime: {Sec: %d, NanoSec: %d}, MTime: {Sec: %d, NanoSec: %d}}", s.Permissions, s.UID, s.GID, s.Size, s.ATimeSeconds, s.ATimeNanoSeconds, s.MTimeSeconds, s.MTimeNanoSeconds)
  1006  }
  1007  
  1008  // decode implements encoder.decode.
  1009  func (s *SetAttr) decode(b *buffer) {
  1010  	s.Permissions = b.ReadPermissions()
  1011  	s.UID = b.ReadUID()
  1012  	s.GID = b.ReadGID()
  1013  	s.Size = b.Read64()
  1014  	s.ATimeSeconds = b.Read64()
  1015  	s.ATimeNanoSeconds = b.Read64()
  1016  	s.MTimeSeconds = b.Read64()
  1017  	s.MTimeNanoSeconds = b.Read64()
  1018  }
  1019  
  1020  // encode implements encoder.encode.
  1021  func (s *SetAttr) encode(b *buffer) {
  1022  	b.WritePermissions(s.Permissions)
  1023  	b.WriteUID(s.UID)
  1024  	b.WriteGID(s.GID)
  1025  	b.Write64(s.Size)
  1026  	b.Write64(s.ATimeSeconds)
  1027  	b.Write64(s.ATimeNanoSeconds)
  1028  	b.Write64(s.MTimeSeconds)
  1029  	b.Write64(s.MTimeNanoSeconds)
  1030  }
  1031  
  1032  // Apply applies this to the given Attr.
  1033  func (a *Attr) Apply(mask SetAttrMask, attr SetAttr) {
  1034  	if mask.Permissions {
  1035  		a.Mode = a.Mode&^permissionsMask | (attr.Permissions & permissionsMask)
  1036  	}
  1037  	if mask.UID {
  1038  		a.UID = attr.UID
  1039  	}
  1040  	if mask.GID {
  1041  		a.GID = attr.GID
  1042  	}
  1043  	if mask.Size {
  1044  		a.Size = attr.Size
  1045  	}
  1046  	if mask.ATime {
  1047  		a.ATimeSeconds = attr.ATimeSeconds
  1048  		a.ATimeNanoSeconds = attr.ATimeNanoSeconds
  1049  	}
  1050  	if mask.MTime {
  1051  		a.MTimeSeconds = attr.MTimeSeconds
  1052  		a.MTimeNanoSeconds = attr.MTimeNanoSeconds
  1053  	}
  1054  }
  1055  
  1056  // Dirent is used for readdir.
  1057  type Dirent struct {
  1058  	// QID is the entry QID.
  1059  	QID QID
  1060  
  1061  	// Offset is the offset in the directory.
  1062  	//
  1063  	// This will be communicated back the original caller.
  1064  	Offset uint64
  1065  
  1066  	// Type is the 9P type.
  1067  	Type QIDType
  1068  
  1069  	// Name is the name of the entry (i.e. basename).
  1070  	Name string
  1071  }
  1072  
  1073  // String implements fmt.Stringer.
  1074  func (d Dirent) String() string {
  1075  	return fmt.Sprintf("Dirent{QID: %d, Offset: %d, Type: 0x%X, Name: %s}", d.QID, d.Offset, d.Type, d.Name)
  1076  }
  1077  
  1078  // decode implements encoder.decode.
  1079  func (d *Dirent) decode(b *buffer) {
  1080  	d.QID.decode(b)
  1081  	d.Offset = b.Read64()
  1082  	d.Type = b.ReadQIDType()
  1083  	d.Name = b.ReadString()
  1084  }
  1085  
  1086  // encode implements encoder.encode.
  1087  func (d *Dirent) encode(b *buffer) {
  1088  	d.QID.encode(b)
  1089  	b.Write64(d.Offset)
  1090  	b.WriteQIDType(d.Type)
  1091  	b.WriteString(d.Name)
  1092  }
  1093  
  1094  // AllocateMode are possible modes to p9.File.Allocate().
  1095  type AllocateMode struct {
  1096  	KeepSize      bool
  1097  	PunchHole     bool
  1098  	NoHideStale   bool
  1099  	CollapseRange bool
  1100  	ZeroRange     bool
  1101  	InsertRange   bool
  1102  	Unshare       bool
  1103  }
  1104  
  1105  // ToAllocateMode returns an AllocateMode from a fallocate(2) mode.
  1106  func ToAllocateMode(mode uint64) AllocateMode {
  1107  	return AllocateMode{
  1108  		KeepSize:      mode&unix.FALLOC_FL_KEEP_SIZE != 0,
  1109  		PunchHole:     mode&unix.FALLOC_FL_PUNCH_HOLE != 0,
  1110  		NoHideStale:   mode&unix.FALLOC_FL_NO_HIDE_STALE != 0,
  1111  		CollapseRange: mode&unix.FALLOC_FL_COLLAPSE_RANGE != 0,
  1112  		ZeroRange:     mode&unix.FALLOC_FL_ZERO_RANGE != 0,
  1113  		InsertRange:   mode&unix.FALLOC_FL_INSERT_RANGE != 0,
  1114  		Unshare:       mode&unix.FALLOC_FL_UNSHARE_RANGE != 0,
  1115  	}
  1116  }
  1117  
  1118  // ToLinux converts to a value compatible with fallocate(2)'s mode.
  1119  func (a *AllocateMode) ToLinux() uint32 {
  1120  	rv := uint32(0)
  1121  	if a.KeepSize {
  1122  		rv |= unix.FALLOC_FL_KEEP_SIZE
  1123  	}
  1124  	if a.PunchHole {
  1125  		rv |= unix.FALLOC_FL_PUNCH_HOLE
  1126  	}
  1127  	if a.NoHideStale {
  1128  		rv |= unix.FALLOC_FL_NO_HIDE_STALE
  1129  	}
  1130  	if a.CollapseRange {
  1131  		rv |= unix.FALLOC_FL_COLLAPSE_RANGE
  1132  	}
  1133  	if a.ZeroRange {
  1134  		rv |= unix.FALLOC_FL_ZERO_RANGE
  1135  	}
  1136  	if a.InsertRange {
  1137  		rv |= unix.FALLOC_FL_INSERT_RANGE
  1138  	}
  1139  	if a.Unshare {
  1140  		rv |= unix.FALLOC_FL_UNSHARE_RANGE
  1141  	}
  1142  	return rv
  1143  }
  1144  
  1145  // decode implements encoder.decode.
  1146  func (a *AllocateMode) decode(b *buffer) {
  1147  	mask := b.Read32()
  1148  	a.KeepSize = mask&0x01 != 0
  1149  	a.PunchHole = mask&0x02 != 0
  1150  	a.NoHideStale = mask&0x04 != 0
  1151  	a.CollapseRange = mask&0x08 != 0
  1152  	a.ZeroRange = mask&0x10 != 0
  1153  	a.InsertRange = mask&0x20 != 0
  1154  	a.Unshare = mask&0x40 != 0
  1155  }
  1156  
  1157  // encode implements encoder.encode.
  1158  func (a *AllocateMode) encode(b *buffer) {
  1159  	mask := uint32(0)
  1160  	if a.KeepSize {
  1161  		mask |= 0x01
  1162  	}
  1163  	if a.PunchHole {
  1164  		mask |= 0x02
  1165  	}
  1166  	if a.NoHideStale {
  1167  		mask |= 0x04
  1168  	}
  1169  	if a.CollapseRange {
  1170  		mask |= 0x08
  1171  	}
  1172  	if a.ZeroRange {
  1173  		mask |= 0x10
  1174  	}
  1175  	if a.InsertRange {
  1176  		mask |= 0x20
  1177  	}
  1178  	if a.Unshare {
  1179  		mask |= 0x40
  1180  	}
  1181  	b.Write32(mask)
  1182  }
  1183  
  1184  // FullStat is used in the result of a MultiGetAttr call.
  1185  type FullStat struct {
  1186  	QID   QID
  1187  	Valid AttrMask
  1188  	Attr  Attr
  1189  }
  1190  
  1191  // String implements fmt.Stringer.
  1192  func (f *FullStat) String() string {
  1193  	return fmt.Sprintf("FullStat{QID: %v, Valid: %v, Attr: %v}", f.QID, f.Valid, f.Attr)
  1194  }
  1195  
  1196  // decode implements encoder.decode.
  1197  func (f *FullStat) decode(b *buffer) {
  1198  	f.QID.decode(b)
  1199  	f.Valid.decode(b)
  1200  	f.Attr.decode(b)
  1201  }
  1202  
  1203  // encode implements encoder.encode.
  1204  func (f *FullStat) encode(b *buffer) {
  1205  	f.QID.encode(b)
  1206  	f.Valid.encode(b)
  1207  	f.Attr.encode(b)
  1208  }