github.com/metacubex/gvisor@v0.0.0-20240320004321-933faba989ec/pkg/p9/handlers.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
    16  
    17  import (
    18  	errors2 "errors"
    19  	"fmt"
    20  	"io"
    21  	"os"
    22  	"path"
    23  	"strings"
    24  
    25  	"golang.org/x/sys/unix"
    26  	"github.com/metacubex/gvisor/pkg/atomicbitops"
    27  	"github.com/metacubex/gvisor/pkg/errors"
    28  	"github.com/metacubex/gvisor/pkg/errors/linuxerr"
    29  	"github.com/metacubex/gvisor/pkg/fd"
    30  	"github.com/metacubex/gvisor/pkg/log"
    31  )
    32  
    33  // ExtractErrno extracts a unix.Errno from a error, best effort.
    34  func ExtractErrno(err error) unix.Errno {
    35  	switch err {
    36  	case os.ErrNotExist:
    37  		return unix.ENOENT
    38  	case os.ErrExist:
    39  		return unix.EEXIST
    40  	case os.ErrPermission:
    41  		return unix.EACCES
    42  	case os.ErrInvalid:
    43  		return unix.EINVAL
    44  	}
    45  
    46  	// Attempt to unwrap.
    47  	switch e := err.(type) {
    48  	case *errors.Error:
    49  		return linuxerr.ToUnix(e)
    50  	case unix.Errno:
    51  		return e
    52  	case *os.PathError:
    53  		return ExtractErrno(e.Err)
    54  	case *os.SyscallError:
    55  		return ExtractErrno(e.Err)
    56  	case *os.LinkError:
    57  		return ExtractErrno(e.Err)
    58  	}
    59  
    60  	// Default case.
    61  	log.Warningf("unknown error: %v", err)
    62  	return unix.EIO
    63  }
    64  
    65  // newErr returns a new error message from an error.
    66  func newErr(err error) *Rlerror {
    67  	return &Rlerror{Error: uint32(ExtractErrno(err))}
    68  }
    69  
    70  // ExtractLinuxerrErrno extracts a *errors.Error from a error, best effort.
    71  // TODO(b/34162363): Merge this with ExtractErrno.
    72  func ExtractLinuxerrErrno(err error) error {
    73  	switch err {
    74  	case os.ErrNotExist:
    75  		return linuxerr.ENOENT
    76  	case os.ErrExist:
    77  		return linuxerr.EEXIST
    78  	case os.ErrPermission:
    79  		return linuxerr.EACCES
    80  	case os.ErrInvalid:
    81  		return linuxerr.EINVAL
    82  	}
    83  
    84  	// Attempt to unwrap.
    85  	switch e := err.(type) {
    86  	case *errors.Error:
    87  		return linuxerr.ToError(e)
    88  	case unix.Errno:
    89  		return linuxerr.ErrorFromUnix(e)
    90  	case *os.PathError:
    91  		return ExtractLinuxerrErrno(e.Err)
    92  	case *os.SyscallError:
    93  		return ExtractLinuxerrErrno(e.Err)
    94  	case *os.LinkError:
    95  		return ExtractLinuxerrErrno(e.Err)
    96  	}
    97  
    98  	// Default case.
    99  	log.Warningf("unknown error: %v", err)
   100  	return linuxerr.EIO
   101  }
   102  
   103  // newErrFromLinuxerr returns an Rlerror from the linuxerr list.
   104  // TODO(b/34162363): Merge this with newErr.
   105  func newErrFromLinuxerr(err error) *Rlerror {
   106  	return &Rlerror{Error: uint32(ExtractErrno(err))}
   107  }
   108  
   109  // handler is implemented for server-handled messages.
   110  //
   111  // See server.go for call information.
   112  type handler interface {
   113  	// Handle handles the given message.
   114  	//
   115  	// This may modify the server state. The handle function must return a
   116  	// message which will be sent back to the client. It may be useful to
   117  	// use newErr to automatically extract an error message.
   118  	handle(cs *connState) message
   119  }
   120  
   121  // handle implements handler.handle.
   122  func (t *Tversion) handle(cs *connState) message {
   123  	if t.MSize == 0 {
   124  		return newErr(unix.EINVAL)
   125  	}
   126  	if t.MSize > maximumLength {
   127  		return newErr(unix.EINVAL)
   128  	}
   129  	cs.messageSize.Store(t.MSize)
   130  	requested, ok := parseVersion(t.Version)
   131  	if !ok {
   132  		return newErr(unix.EINVAL)
   133  	}
   134  	// The server cannot support newer versions that it doesn't know about.  In this
   135  	// case we return EAGAIN to tell the client to try again with a lower version.
   136  	if requested > highestSupportedVersion {
   137  		return newErr(unix.EAGAIN)
   138  	}
   139  	// From Tversion(9P): "The server may respond with the client’s version
   140  	// string, or a version string identifying an earlier defined protocol version".
   141  	cs.version.Store(requested)
   142  	return &Rversion{
   143  		MSize:   t.MSize,
   144  		Version: t.Version,
   145  	}
   146  }
   147  
   148  // handle implements handler.handle.
   149  func (t *Tflush) handle(cs *connState) message {
   150  	cs.WaitTag(t.OldTag)
   151  	return &Rflush{}
   152  }
   153  
   154  // checkSafeName validates the name and returns nil or returns an error.
   155  func checkSafeName(name string) error {
   156  	if name != "" && !strings.Contains(name, "/") && name != "." && name != ".." {
   157  		return nil
   158  	}
   159  	return unix.EINVAL
   160  }
   161  
   162  // handle implements handler.handle.
   163  func (t *Tclunk) handle(cs *connState) message {
   164  	if !cs.DeleteFID(t.FID) {
   165  		return newErr(unix.EBADF)
   166  	}
   167  	return &Rclunk{}
   168  }
   169  
   170  func (t *Tsetattrclunk) handle(cs *connState) message {
   171  	ref, ok := cs.LookupFID(t.FID)
   172  	if !ok {
   173  		return newErr(unix.EBADF)
   174  	}
   175  	defer ref.DecRef()
   176  
   177  	setAttrErr := ref.safelyWrite(func() error {
   178  		// We don't allow setattr on files that have been deleted.
   179  		// This might be technically incorrect, as it's possible that
   180  		// there were multiple links and you can still change the
   181  		// corresponding inode information.
   182  		if !cs.server.options.SetAttrOnDeleted && ref.isDeleted() {
   183  			return unix.EINVAL
   184  		}
   185  
   186  		// Set the attributes.
   187  		return ref.file.SetAttr(t.Valid, t.SetAttr)
   188  	})
   189  
   190  	// Try to delete FID even in case of failure above. Since the state of the
   191  	// file is unknown to the caller, it will not attempt to close the file again.
   192  	if !cs.DeleteFID(t.FID) {
   193  		return newErr(unix.EBADF)
   194  	}
   195  	if setAttrErr != nil {
   196  		return newErr(setAttrErr)
   197  	}
   198  	return &Rsetattrclunk{}
   199  }
   200  
   201  // handle implements handler.handle.
   202  func (t *Tremove) handle(cs *connState) message {
   203  	ref, ok := cs.LookupFID(t.FID)
   204  	if !ok {
   205  		return newErr(unix.EBADF)
   206  	}
   207  	defer ref.DecRef()
   208  
   209  	// Frustratingly, because we can't be guaranteed that a rename is not
   210  	// occurring simultaneously with this removal, we need to acquire the
   211  	// global rename lock for this kind of remove operation to ensure that
   212  	// ref.parent does not change out from underneath us.
   213  	//
   214  	// This is why Tremove is a bad idea, and clients should generally use
   215  	// Tunlinkat. All p9 clients will use Tunlinkat.
   216  	err := ref.safelyGlobal(func() error {
   217  		// Is this a root? Can't remove that.
   218  		if ref.isRoot() {
   219  			return unix.EINVAL
   220  		}
   221  
   222  		// N.B. this remove operation is permitted, even if the file is open.
   223  		// See also rename below for reasoning.
   224  
   225  		// Is this file already deleted?
   226  		if ref.isDeleted() {
   227  			return unix.EINVAL
   228  		}
   229  
   230  		// Retrieve the file's proper name.
   231  		name := ref.parent.pathNode.nameFor(ref)
   232  
   233  		// Attempt the removal.
   234  		if err := ref.parent.file.UnlinkAt(name, 0); err != nil {
   235  			return err
   236  		}
   237  
   238  		// Mark all relevant fids as deleted. We don't need to lock any
   239  		// individual nodes because we already hold the global lock.
   240  		ref.parent.markChildDeleted(name)
   241  		return nil
   242  	})
   243  
   244  	// "The remove request asks the file server both to remove the file
   245  	// represented by fid and to clunk the fid, even if the remove fails."
   246  	//
   247  	// "It is correct to consider remove to be a clunk with the side effect
   248  	// of removing the file if permissions allow."
   249  	// https://swtch.com/plan9port/man/man9/remove.html
   250  	if !cs.DeleteFID(t.FID) {
   251  		return newErr(unix.EBADF)
   252  	}
   253  	if err != nil {
   254  		return newErr(err)
   255  	}
   256  
   257  	return &Rremove{}
   258  }
   259  
   260  // handle implements handler.handle.
   261  //
   262  // We don't support authentication, so this just returns ENOSYS.
   263  func (t *Tauth) handle(cs *connState) message {
   264  	return newErr(unix.ENOSYS)
   265  }
   266  
   267  // handle implements handler.handle.
   268  func (t *Tattach) handle(cs *connState) message {
   269  	// Ensure no authentication FID is provided.
   270  	if t.Auth.AuthenticationFID != NoFID {
   271  		return newErr(unix.EINVAL)
   272  	}
   273  
   274  	// Must provide an absolute path.
   275  	if path.IsAbs(t.Auth.AttachName) {
   276  		// Trim off the leading / if the path is absolute. We always
   277  		// treat attach paths as absolute and call attach with the root
   278  		// argument on the server file for clarity.
   279  		t.Auth.AttachName = t.Auth.AttachName[1:]
   280  	}
   281  
   282  	// Do the attach on the root.
   283  	sf, err := cs.server.attacher.Attach()
   284  	if err != nil {
   285  		return newErr(err)
   286  	}
   287  	qid, valid, attr, err := sf.GetAttr(AttrMaskAll())
   288  	if err != nil {
   289  		sf.Close() // Drop file.
   290  		return newErr(err)
   291  	}
   292  	if !valid.Mode {
   293  		sf.Close() // Drop file.
   294  		return newErr(unix.EINVAL)
   295  	}
   296  
   297  	// Build a transient reference.
   298  	root := &fidRef{
   299  		server:   cs.server,
   300  		parent:   nil,
   301  		file:     sf,
   302  		refs:     atomicbitops.FromInt64(1),
   303  		mode:     attr.Mode.FileType(),
   304  		pathNode: cs.server.pathTree,
   305  	}
   306  	defer root.DecRef()
   307  
   308  	// Attach the root?
   309  	if len(t.Auth.AttachName) == 0 {
   310  		cs.InsertFID(t.FID, root)
   311  		return &Rattach{QID: qid}
   312  	}
   313  
   314  	// We want the same traversal checks to apply on attach, so always
   315  	// attach at the root and use the regular walk paths.
   316  	names := strings.Split(t.Auth.AttachName, "/")
   317  	_, newRef, _, _, err := doWalk(cs, root, names, false)
   318  	if err != nil {
   319  		return newErr(err)
   320  	}
   321  	defer newRef.DecRef()
   322  
   323  	// Insert the FID.
   324  	cs.InsertFID(t.FID, newRef)
   325  	return &Rattach{QID: qid}
   326  }
   327  
   328  // CanOpen returns whether this file open can be opened, read and written to.
   329  //
   330  // This includes everything except symlinks and sockets.
   331  func CanOpen(mode FileMode) bool {
   332  	return mode.IsRegular() || mode.IsDir() || mode.IsNamedPipe() || mode.IsBlockDevice() || mode.IsCharacterDevice()
   333  }
   334  
   335  // handle implements handler.handle.
   336  func (t *Tlopen) handle(cs *connState) message {
   337  	ref, ok := cs.LookupFID(t.FID)
   338  	if !ok {
   339  		return newErr(unix.EBADF)
   340  	}
   341  	defer ref.DecRef()
   342  
   343  	var (
   344  		qid    QID
   345  		ioUnit uint32
   346  		osFile *fd.FD
   347  	)
   348  	if err := ref.safelyRead(func() (err error) {
   349  		// Has it been deleted already?
   350  		if ref.isDeleted() {
   351  			return unix.EINVAL
   352  		}
   353  
   354  		// Has it been opened already?
   355  		if ref.opened || !CanOpen(ref.mode) {
   356  			return unix.EINVAL
   357  		}
   358  
   359  		if ref.mode.IsDir() {
   360  			// Directory must be opened ReadOnly.
   361  			if t.Flags&OpenFlagsModeMask != ReadOnly {
   362  				return unix.EISDIR
   363  			}
   364  			// Directory not truncatable.
   365  			if t.Flags&OpenTruncate != 0 {
   366  				return unix.EISDIR
   367  			}
   368  		}
   369  
   370  		osFile, qid, ioUnit, err = ref.file.Open(t.Flags)
   371  		return err
   372  	}); err != nil {
   373  		return newErr(err)
   374  	}
   375  
   376  	// Mark file as opened and set open mode.
   377  	ref.opened = true
   378  	ref.openFlags = t.Flags
   379  
   380  	rlopen := &Rlopen{QID: qid, IoUnit: ioUnit}
   381  	rlopen.SetFilePayload(osFile)
   382  	return rlopen
   383  }
   384  
   385  func (t *Tlcreate) do(cs *connState, uid UID) (*Rlcreate, error) {
   386  	if err := checkSafeName(t.Name); err != nil {
   387  		return nil, err
   388  	}
   389  
   390  	ref, ok := cs.LookupFID(t.FID)
   391  	if !ok {
   392  		return nil, unix.EBADF
   393  	}
   394  	defer ref.DecRef()
   395  
   396  	var (
   397  		osFile *fd.FD
   398  		nsf    File
   399  		qid    QID
   400  		ioUnit uint32
   401  		newRef *fidRef
   402  	)
   403  	if err := ref.safelyWrite(func() (err error) {
   404  		// Don't allow creation from non-directories or deleted directories.
   405  		if ref.isDeleted() || !ref.mode.IsDir() {
   406  			return unix.EINVAL
   407  		}
   408  
   409  		// Not allowed on open directories.
   410  		if ref.opened {
   411  			return unix.EINVAL
   412  		}
   413  
   414  		// Do the create.
   415  		osFile, nsf, qid, ioUnit, err = ref.file.Create(t.Name, t.OpenFlags, t.Permissions, uid, t.GID)
   416  		if err != nil {
   417  			return err
   418  		}
   419  
   420  		newRef = &fidRef{
   421  			server:    cs.server,
   422  			parent:    ref,
   423  			file:      nsf,
   424  			opened:    true,
   425  			openFlags: t.OpenFlags,
   426  			mode:      ModeRegular,
   427  			pathNode:  ref.pathNode.pathNodeFor(t.Name),
   428  		}
   429  		ref.pathNode.addChild(newRef, t.Name)
   430  		ref.IncRef() // Acquire parent reference.
   431  		return nil
   432  	}); err != nil {
   433  		return nil, err
   434  	}
   435  
   436  	// Replace the FID reference.
   437  	cs.InsertFID(t.FID, newRef)
   438  
   439  	rlcreate := &Rlcreate{Rlopen: Rlopen{QID: qid, IoUnit: ioUnit}}
   440  	rlcreate.SetFilePayload(osFile)
   441  	return rlcreate, nil
   442  }
   443  
   444  // handle implements handler.handle.
   445  func (t *Tlcreate) handle(cs *connState) message {
   446  	rlcreate, err := t.do(cs, NoUID)
   447  	if err != nil {
   448  		return newErr(err)
   449  	}
   450  	return rlcreate
   451  }
   452  
   453  // handle implements handler.handle.
   454  func (t *Tsymlink) handle(cs *connState) message {
   455  	rsymlink, err := t.do(cs, NoUID)
   456  	if err != nil {
   457  		return newErr(err)
   458  	}
   459  	return rsymlink
   460  }
   461  
   462  func (t *Tsymlink) do(cs *connState, uid UID) (*Rsymlink, error) {
   463  	if err := checkSafeName(t.Name); err != nil {
   464  		return nil, err
   465  	}
   466  
   467  	ref, ok := cs.LookupFID(t.Directory)
   468  	if !ok {
   469  		return nil, unix.EBADF
   470  	}
   471  	defer ref.DecRef()
   472  
   473  	var qid QID
   474  	if err := ref.safelyWrite(func() (err error) {
   475  		// Don't allow symlinks from non-directories or deleted directories.
   476  		if ref.isDeleted() || !ref.mode.IsDir() {
   477  			return unix.EINVAL
   478  		}
   479  
   480  		// Not allowed on open directories.
   481  		if ref.opened {
   482  			return unix.EINVAL
   483  		}
   484  
   485  		// Do the symlink.
   486  		qid, err = ref.file.Symlink(t.Target, t.Name, uid, t.GID)
   487  		return err
   488  	}); err != nil {
   489  		return nil, err
   490  	}
   491  
   492  	return &Rsymlink{QID: qid}, nil
   493  }
   494  
   495  // handle implements handler.handle.
   496  func (t *Tlink) handle(cs *connState) message {
   497  	if err := checkSafeName(t.Name); err != nil {
   498  		return newErr(err)
   499  	}
   500  
   501  	ref, ok := cs.LookupFID(t.Directory)
   502  	if !ok {
   503  		return newErr(unix.EBADF)
   504  	}
   505  	defer ref.DecRef()
   506  
   507  	refTarget, ok := cs.LookupFID(t.Target)
   508  	if !ok {
   509  		return newErr(unix.EBADF)
   510  	}
   511  	defer refTarget.DecRef()
   512  
   513  	if err := ref.safelyWrite(func() (err error) {
   514  		// Don't allow create links from non-directories or deleted directories.
   515  		if ref.isDeleted() || !ref.mode.IsDir() {
   516  			return unix.EINVAL
   517  		}
   518  
   519  		// Not allowed on open directories.
   520  		if ref.opened {
   521  			return unix.EINVAL
   522  		}
   523  
   524  		// Do the link.
   525  		return ref.file.Link(refTarget.file, t.Name)
   526  	}); err != nil {
   527  		return newErr(err)
   528  	}
   529  
   530  	return &Rlink{}
   531  }
   532  
   533  // handle implements handler.handle.
   534  func (t *Trenameat) handle(cs *connState) message {
   535  	if err := checkSafeName(t.OldName); err != nil {
   536  		return newErr(err)
   537  	}
   538  	if err := checkSafeName(t.NewName); err != nil {
   539  		return newErr(err)
   540  	}
   541  
   542  	ref, ok := cs.LookupFID(t.OldDirectory)
   543  	if !ok {
   544  		return newErr(unix.EBADF)
   545  	}
   546  	defer ref.DecRef()
   547  
   548  	refTarget, ok := cs.LookupFID(t.NewDirectory)
   549  	if !ok {
   550  		return newErr(unix.EBADF)
   551  	}
   552  	defer refTarget.DecRef()
   553  
   554  	// Perform the rename holding the global lock.
   555  	if err := ref.safelyGlobal(func() (err error) {
   556  		// Don't allow renaming across deleted directories.
   557  		if ref.isDeleted() || !ref.mode.IsDir() || refTarget.isDeleted() || !refTarget.mode.IsDir() {
   558  			return unix.EINVAL
   559  		}
   560  
   561  		// Not allowed on open directories.
   562  		if ref.opened {
   563  			return unix.EINVAL
   564  		}
   565  
   566  		// Is this the same file? If yes, short-circuit and return success.
   567  		if ref.pathNode == refTarget.pathNode && t.OldName == t.NewName {
   568  			return nil
   569  		}
   570  
   571  		// Attempt the actual rename.
   572  		if err := ref.file.RenameAt(t.OldName, refTarget.file, t.NewName); err != nil {
   573  			return err
   574  		}
   575  
   576  		// Update the path tree.
   577  		ref.renameChildTo(t.OldName, refTarget, t.NewName)
   578  		return nil
   579  	}); err != nil {
   580  		return newErr(err)
   581  	}
   582  
   583  	return &Rrenameat{}
   584  }
   585  
   586  // handle implements handler.handle.
   587  func (t *Tunlinkat) handle(cs *connState) message {
   588  	if err := checkSafeName(t.Name); err != nil {
   589  		return newErr(err)
   590  	}
   591  
   592  	ref, ok := cs.LookupFID(t.Directory)
   593  	if !ok {
   594  		return newErr(unix.EBADF)
   595  	}
   596  	defer ref.DecRef()
   597  
   598  	if err := ref.safelyWrite(func() (err error) {
   599  		// Don't allow deletion from non-directories or deleted directories.
   600  		if ref.isDeleted() || !ref.mode.IsDir() {
   601  			return unix.EINVAL
   602  		}
   603  
   604  		// Not allowed on open directories.
   605  		if ref.opened {
   606  			return unix.EINVAL
   607  		}
   608  
   609  		// Before we do the unlink itself, we need to ensure that there
   610  		// are no operations in flight on associated path node. The
   611  		// child's path node lock must be held to ensure that the
   612  		// unlinkat marking the child deleted below is atomic with
   613  		// respect to any other read or write operations.
   614  		//
   615  		// This is one case where we have a lock ordering issue, but
   616  		// since we always acquire deeper in the hierarchy, we know
   617  		// that we are free of lock cycles.
   618  		childPathNode := ref.pathNode.pathNodeFor(t.Name)
   619  		childPathNode.opMu.Lock()
   620  		defer childPathNode.opMu.Unlock()
   621  
   622  		// Do the unlink.
   623  		err = ref.file.UnlinkAt(t.Name, t.Flags)
   624  		if err != nil {
   625  			return err
   626  		}
   627  
   628  		// Mark the path as deleted.
   629  		ref.markChildDeleted(t.Name)
   630  		return nil
   631  	}); err != nil {
   632  		return newErr(err)
   633  	}
   634  
   635  	return &Runlinkat{}
   636  }
   637  
   638  // handle implements handler.handle.
   639  func (t *Trename) handle(cs *connState) message {
   640  	if err := checkSafeName(t.Name); err != nil {
   641  		return newErr(err)
   642  	}
   643  
   644  	ref, ok := cs.LookupFID(t.FID)
   645  	if !ok {
   646  		return newErr(unix.EBADF)
   647  	}
   648  	defer ref.DecRef()
   649  
   650  	refTarget, ok := cs.LookupFID(t.Directory)
   651  	if !ok {
   652  		return newErr(unix.EBADF)
   653  	}
   654  	defer refTarget.DecRef()
   655  
   656  	if err := ref.safelyGlobal(func() (err error) {
   657  		// Don't allow a root rename.
   658  		if ref.isRoot() {
   659  			return unix.EINVAL
   660  		}
   661  
   662  		// Don't allow renaming deleting entries, or target non-directories.
   663  		if ref.isDeleted() || refTarget.isDeleted() || !refTarget.mode.IsDir() {
   664  			return unix.EINVAL
   665  		}
   666  
   667  		// If the parent is deleted, but we not, something is seriously wrong.
   668  		// It's fail to die at this point with an assertion failure.
   669  		if ref.parent.isDeleted() {
   670  			panic(fmt.Sprintf("parent %+v deleted, child %+v is not", ref.parent, ref))
   671  		}
   672  
   673  		// N.B. The rename operation is allowed to proceed on open files. It
   674  		// does impact the state of its parent, but this is merely a sanity
   675  		// check in any case, and the operation is safe. There may be other
   676  		// files corresponding to the same path that are renamed anyways.
   677  
   678  		// Check for the exact same file and short-circuit.
   679  		oldName := ref.parent.pathNode.nameFor(ref)
   680  		if ref.parent.pathNode == refTarget.pathNode && oldName == t.Name {
   681  			return nil
   682  		}
   683  
   684  		// Call the rename method on the parent.
   685  		if err := ref.parent.file.RenameAt(oldName, refTarget.file, t.Name); err != nil {
   686  			return err
   687  		}
   688  
   689  		// Update the path tree.
   690  		ref.parent.renameChildTo(oldName, refTarget, t.Name)
   691  		return nil
   692  	}); err != nil {
   693  		return newErr(err)
   694  	}
   695  
   696  	return &Rrename{}
   697  }
   698  
   699  // handle implements handler.handle.
   700  func (t *Treadlink) handle(cs *connState) message {
   701  	ref, ok := cs.LookupFID(t.FID)
   702  	if !ok {
   703  		return newErr(unix.EBADF)
   704  	}
   705  	defer ref.DecRef()
   706  
   707  	var target string
   708  	if err := ref.safelyRead(func() (err error) {
   709  		// Don't allow readlink on deleted files. There is no need to
   710  		// check if this file is opened because symlinks cannot be
   711  		// opened.
   712  		if ref.isDeleted() || !ref.mode.IsSymlink() {
   713  			return unix.EINVAL
   714  		}
   715  
   716  		// Do the read.
   717  		target, err = ref.file.Readlink()
   718  		return err
   719  	}); err != nil {
   720  		return newErr(err)
   721  	}
   722  
   723  	return &Rreadlink{target}
   724  }
   725  
   726  // handle implements handler.handle.
   727  func (t *Tread) handle(cs *connState) message {
   728  	ref, ok := cs.LookupFID(t.FID)
   729  	if !ok {
   730  		return newErr(unix.EBADF)
   731  	}
   732  	defer ref.DecRef()
   733  
   734  	// Constrain the size of the read buffer.
   735  	if int(t.Count) > int(maximumLength) {
   736  		return newErr(unix.ENOBUFS)
   737  	}
   738  
   739  	var (
   740  		data = make([]byte, t.Count)
   741  		n    int
   742  	)
   743  	if err := ref.safelyRead(func() (err error) {
   744  		// Has it been opened already?
   745  		if !ref.opened {
   746  			return unix.EINVAL
   747  		}
   748  
   749  		// Can it be read? Check permissions.
   750  		if ref.openFlags&OpenFlagsModeMask == WriteOnly {
   751  			return unix.EPERM
   752  		}
   753  
   754  		n, err = ref.file.ReadAt(data, t.Offset)
   755  		return err
   756  	}); err != nil && err != io.EOF {
   757  		return newErr(err)
   758  	}
   759  
   760  	return &Rread{Data: data[:n]}
   761  }
   762  
   763  // handle implements handler.handle.
   764  func (t *Twrite) handle(cs *connState) message {
   765  	ref, ok := cs.LookupFID(t.FID)
   766  	if !ok {
   767  		return newErr(unix.EBADF)
   768  	}
   769  	defer ref.DecRef()
   770  
   771  	var n int
   772  	if err := ref.safelyRead(func() (err error) {
   773  		// Has it been opened already?
   774  		if !ref.opened {
   775  			return unix.EINVAL
   776  		}
   777  
   778  		// Can it be written? Check permissions.
   779  		if ref.openFlags&OpenFlagsModeMask == ReadOnly {
   780  			return unix.EPERM
   781  		}
   782  
   783  		n, err = ref.file.WriteAt(t.Data, t.Offset)
   784  		return err
   785  	}); err != nil {
   786  		return newErr(err)
   787  	}
   788  
   789  	return &Rwrite{Count: uint32(n)}
   790  }
   791  
   792  // handle implements handler.handle.
   793  func (t *Tmknod) handle(cs *connState) message {
   794  	rmknod, err := t.do(cs, NoUID)
   795  	if err != nil {
   796  		return newErr(err)
   797  	}
   798  	return rmknod
   799  }
   800  
   801  func (t *Tmknod) do(cs *connState, uid UID) (*Rmknod, error) {
   802  	if err := checkSafeName(t.Name); err != nil {
   803  		return nil, err
   804  	}
   805  
   806  	ref, ok := cs.LookupFID(t.Directory)
   807  	if !ok {
   808  		return nil, unix.EBADF
   809  	}
   810  	defer ref.DecRef()
   811  
   812  	var qid QID
   813  	if err := ref.safelyWrite(func() (err error) {
   814  		// Don't allow mknod on deleted files.
   815  		if ref.isDeleted() || !ref.mode.IsDir() {
   816  			return unix.EINVAL
   817  		}
   818  
   819  		// Not allowed on open directories.
   820  		if ref.opened {
   821  			return unix.EINVAL
   822  		}
   823  
   824  		// Do the mknod.
   825  		qid, err = ref.file.Mknod(t.Name, t.Mode, t.Major, t.Minor, uid, t.GID)
   826  		return err
   827  	}); err != nil {
   828  		return nil, err
   829  	}
   830  
   831  	return &Rmknod{QID: qid}, nil
   832  }
   833  
   834  // handle implements handler.handle.
   835  func (t *Tmkdir) handle(cs *connState) message {
   836  	rmkdir, err := t.do(cs, NoUID)
   837  	if err != nil {
   838  		return newErr(err)
   839  	}
   840  	return rmkdir
   841  }
   842  
   843  func (t *Tmkdir) do(cs *connState, uid UID) (*Rmkdir, error) {
   844  	if err := checkSafeName(t.Name); err != nil {
   845  		return nil, err
   846  	}
   847  
   848  	ref, ok := cs.LookupFID(t.Directory)
   849  	if !ok {
   850  		return nil, unix.EBADF
   851  	}
   852  	defer ref.DecRef()
   853  
   854  	var qid QID
   855  	if err := ref.safelyWrite(func() (err error) {
   856  		// Don't allow mkdir on deleted files.
   857  		if ref.isDeleted() || !ref.mode.IsDir() {
   858  			return unix.EINVAL
   859  		}
   860  
   861  		// Not allowed on open directories.
   862  		if ref.opened {
   863  			return unix.EINVAL
   864  		}
   865  
   866  		// Do the mkdir.
   867  		qid, err = ref.file.Mkdir(t.Name, t.Permissions, uid, t.GID)
   868  		return err
   869  	}); err != nil {
   870  		return nil, err
   871  	}
   872  
   873  	return &Rmkdir{QID: qid}, nil
   874  }
   875  
   876  // handle implements handler.handle.
   877  func (t *Tgetattr) handle(cs *connState) message {
   878  	ref, ok := cs.LookupFID(t.FID)
   879  	if !ok {
   880  		return newErr(unix.EBADF)
   881  	}
   882  	defer ref.DecRef()
   883  
   884  	// We allow getattr on deleted files. Depending on the backing
   885  	// implementation, it's possible that races exist that might allow
   886  	// fetching attributes of other files. But we need to generally allow
   887  	// refreshing attributes and this is a minor leak, if at all.
   888  
   889  	var (
   890  		qid   QID
   891  		valid AttrMask
   892  		attr  Attr
   893  	)
   894  	if err := ref.safelyRead(func() (err error) {
   895  		qid, valid, attr, err = ref.file.GetAttr(t.AttrMask)
   896  		return err
   897  	}); err != nil {
   898  		return newErr(err)
   899  	}
   900  
   901  	return &Rgetattr{QID: qid, Valid: valid, Attr: attr}
   902  }
   903  
   904  // handle implements handler.handle.
   905  func (t *Tsetattr) handle(cs *connState) message {
   906  	ref, ok := cs.LookupFID(t.FID)
   907  	if !ok {
   908  		return newErr(unix.EBADF)
   909  	}
   910  	defer ref.DecRef()
   911  
   912  	if err := ref.safelyWrite(func() error {
   913  		// We don't allow setattr on files that have been deleted.
   914  		// This might be technically incorrect, as it's possible that
   915  		// there were multiple links and you can still change the
   916  		// corresponding inode information.
   917  		if !cs.server.options.SetAttrOnDeleted && ref.isDeleted() {
   918  			return unix.EINVAL
   919  		}
   920  
   921  		// Set the attributes.
   922  		return ref.file.SetAttr(t.Valid, t.SetAttr)
   923  	}); err != nil {
   924  		return newErr(err)
   925  	}
   926  
   927  	return &Rsetattr{}
   928  }
   929  
   930  // handle implements handler.handle.
   931  func (t *Tallocate) handle(cs *connState) message {
   932  	ref, ok := cs.LookupFID(t.FID)
   933  	if !ok {
   934  		return newErr(unix.EBADF)
   935  	}
   936  	defer ref.DecRef()
   937  
   938  	if err := ref.safelyWrite(func() error {
   939  		// Has it been opened already?
   940  		if !ref.opened {
   941  			return unix.EINVAL
   942  		}
   943  
   944  		// Can it be written? Check permissions.
   945  		if ref.openFlags&OpenFlagsModeMask == ReadOnly {
   946  			return unix.EBADF
   947  		}
   948  
   949  		// We don't allow allocate on files that have been deleted.
   950  		if !cs.server.options.AllocateOnDeleted && ref.isDeleted() {
   951  			return unix.EINVAL
   952  		}
   953  
   954  		return ref.file.Allocate(t.Mode, t.Offset, t.Length)
   955  	}); err != nil {
   956  		return newErr(err)
   957  	}
   958  
   959  	return &Rallocate{}
   960  }
   961  
   962  // handle implements handler.handle.
   963  func (t *Txattrwalk) handle(cs *connState) message {
   964  	ref, ok := cs.LookupFID(t.FID)
   965  	if !ok {
   966  		return newErr(unix.EBADF)
   967  	}
   968  	defer ref.DecRef()
   969  
   970  	// We don't support extended attributes.
   971  	return newErr(unix.ENODATA)
   972  }
   973  
   974  // handle implements handler.handle.
   975  func (t *Txattrcreate) handle(cs *connState) message {
   976  	ref, ok := cs.LookupFID(t.FID)
   977  	if !ok {
   978  		return newErr(unix.EBADF)
   979  	}
   980  	defer ref.DecRef()
   981  
   982  	// We don't support extended attributes.
   983  	return newErr(unix.ENOSYS)
   984  }
   985  
   986  // handle implements handler.handle.
   987  func (t *Tgetxattr) handle(cs *connState) message {
   988  	ref, ok := cs.LookupFID(t.FID)
   989  	if !ok {
   990  		return newErr(unix.EBADF)
   991  	}
   992  	defer ref.DecRef()
   993  
   994  	var val string
   995  	if err := ref.safelyRead(func() (err error) {
   996  		// Don't allow getxattr on files that have been deleted.
   997  		if ref.isDeleted() {
   998  			return unix.EINVAL
   999  		}
  1000  		val, err = ref.file.GetXattr(t.Name, t.Size)
  1001  		return err
  1002  	}); err != nil {
  1003  		return newErr(err)
  1004  	}
  1005  	return &Rgetxattr{Value: val}
  1006  }
  1007  
  1008  // handle implements handler.handle.
  1009  func (t *Tsetxattr) handle(cs *connState) message {
  1010  	ref, ok := cs.LookupFID(t.FID)
  1011  	if !ok {
  1012  		return newErr(unix.EBADF)
  1013  	}
  1014  	defer ref.DecRef()
  1015  
  1016  	if err := ref.safelyWrite(func() error {
  1017  		// Don't allow setxattr on files that have been deleted.
  1018  		if ref.isDeleted() {
  1019  			return unix.EINVAL
  1020  		}
  1021  		return ref.file.SetXattr(t.Name, t.Value, t.Flags)
  1022  	}); err != nil {
  1023  		return newErr(err)
  1024  	}
  1025  	return &Rsetxattr{}
  1026  }
  1027  
  1028  // handle implements handler.handle.
  1029  func (t *Tlistxattr) handle(cs *connState) message {
  1030  	ref, ok := cs.LookupFID(t.FID)
  1031  	if !ok {
  1032  		return newErr(unix.EBADF)
  1033  	}
  1034  	defer ref.DecRef()
  1035  
  1036  	var xattrs map[string]struct{}
  1037  	if err := ref.safelyRead(func() (err error) {
  1038  		// Don't allow listxattr on files that have been deleted.
  1039  		if ref.isDeleted() {
  1040  			return unix.EINVAL
  1041  		}
  1042  		xattrs, err = ref.file.ListXattr(t.Size)
  1043  		return err
  1044  	}); err != nil {
  1045  		return newErr(err)
  1046  	}
  1047  
  1048  	xattrList := make([]string, 0, len(xattrs))
  1049  	for x := range xattrs {
  1050  		xattrList = append(xattrList, x)
  1051  	}
  1052  	return &Rlistxattr{Xattrs: xattrList}
  1053  }
  1054  
  1055  // handle implements handler.handle.
  1056  func (t *Tremovexattr) handle(cs *connState) message {
  1057  	ref, ok := cs.LookupFID(t.FID)
  1058  	if !ok {
  1059  		return newErr(unix.EBADF)
  1060  	}
  1061  	defer ref.DecRef()
  1062  
  1063  	if err := ref.safelyWrite(func() error {
  1064  		// Don't allow removexattr on files that have been deleted.
  1065  		if ref.isDeleted() {
  1066  			return unix.EINVAL
  1067  		}
  1068  		return ref.file.RemoveXattr(t.Name)
  1069  	}); err != nil {
  1070  		return newErr(err)
  1071  	}
  1072  	return &Rremovexattr{}
  1073  }
  1074  
  1075  // handle implements handler.handle.
  1076  func (t *Treaddir) handle(cs *connState) message {
  1077  	ref, ok := cs.LookupFID(t.Directory)
  1078  	if !ok {
  1079  		return newErr(unix.EBADF)
  1080  	}
  1081  	defer ref.DecRef()
  1082  
  1083  	var entries []Dirent
  1084  	if err := ref.safelyRead(func() (err error) {
  1085  		// Don't allow reading deleted directories.
  1086  		if ref.isDeleted() || !ref.mode.IsDir() {
  1087  			return unix.EINVAL
  1088  		}
  1089  
  1090  		// Has it been opened yet?
  1091  		if !ref.opened {
  1092  			return unix.EINVAL
  1093  		}
  1094  
  1095  		// Read the entries.
  1096  		entries, err = ref.file.Readdir(t.DirentOffset, t.Count)
  1097  		if err != nil && err != io.EOF {
  1098  			return err
  1099  		}
  1100  		return nil
  1101  	}); err != nil {
  1102  		return newErr(err)
  1103  	}
  1104  
  1105  	return &Rreaddir{Count: t.Count, Entries: entries}
  1106  }
  1107  
  1108  // handle implements handler.handle.
  1109  func (t *Tfsync) handle(cs *connState) message {
  1110  	ref, ok := cs.LookupFID(t.FID)
  1111  	if !ok {
  1112  		return newErr(unix.EBADF)
  1113  	}
  1114  	defer ref.DecRef()
  1115  
  1116  	if err := ref.safelyRead(func() (err error) {
  1117  		// Has it been opened yet?
  1118  		if !ref.opened {
  1119  			return unix.EINVAL
  1120  		}
  1121  
  1122  		// Perform the sync.
  1123  		return ref.file.FSync()
  1124  	}); err != nil {
  1125  		return newErr(err)
  1126  	}
  1127  
  1128  	return &Rfsync{}
  1129  }
  1130  
  1131  // handle implements handler.handle.
  1132  func (t *Tstatfs) handle(cs *connState) message {
  1133  	ref, ok := cs.LookupFID(t.FID)
  1134  	if !ok {
  1135  		return newErr(unix.EBADF)
  1136  	}
  1137  	defer ref.DecRef()
  1138  
  1139  	st, err := ref.file.StatFS()
  1140  	if err != nil {
  1141  		return newErr(err)
  1142  	}
  1143  
  1144  	return &Rstatfs{st}
  1145  }
  1146  
  1147  // handle implements handler.handle.
  1148  func (t *Tflushf) handle(cs *connState) message {
  1149  	ref, ok := cs.LookupFID(t.FID)
  1150  	if !ok {
  1151  		return newErr(unix.EBADF)
  1152  	}
  1153  	defer ref.DecRef()
  1154  
  1155  	if err := ref.safelyRead(ref.file.Flush); err != nil {
  1156  		return newErr(err)
  1157  	}
  1158  
  1159  	return &Rflushf{}
  1160  }
  1161  
  1162  // walkOne walks zero or one path elements.
  1163  //
  1164  // The slice passed as qids is append and returned.
  1165  func walkOne(qids []QID, from File, names []string, getattr bool) ([]QID, File, AttrMask, Attr, error) {
  1166  	if len(names) > 1 {
  1167  		// We require exactly zero or one elements.
  1168  		return nil, nil, AttrMask{}, Attr{}, unix.EINVAL
  1169  	}
  1170  	var (
  1171  		localQIDs []QID
  1172  		sf        File
  1173  		valid     AttrMask
  1174  		attr      Attr
  1175  		err       error
  1176  	)
  1177  	switch {
  1178  	case getattr:
  1179  		localQIDs, sf, valid, attr, err = from.WalkGetAttr(names)
  1180  		// Can't put fallthrough in the if because Go.
  1181  		if err != unix.ENOSYS {
  1182  			break
  1183  		}
  1184  		fallthrough
  1185  	default:
  1186  		localQIDs, sf, err = from.Walk(names)
  1187  		if err != nil {
  1188  			// No way to walk this element.
  1189  			break
  1190  		}
  1191  		if getattr {
  1192  			_, valid, attr, err = sf.GetAttr(AttrMaskAll())
  1193  			if err != nil {
  1194  				// Don't leak the file.
  1195  				sf.Close()
  1196  			}
  1197  		}
  1198  	}
  1199  	if err != nil {
  1200  		// Error walking, don't return anything.
  1201  		return nil, nil, AttrMask{}, Attr{}, err
  1202  	}
  1203  	if len(localQIDs) != 1 {
  1204  		// Expected a single QID.
  1205  		sf.Close()
  1206  		return nil, nil, AttrMask{}, Attr{}, unix.EINVAL
  1207  	}
  1208  	return append(qids, localQIDs...), sf, valid, attr, nil
  1209  }
  1210  
  1211  // doWalk walks from a given fidRef.
  1212  //
  1213  // This enforces that all intermediate nodes are walkable (directories). The
  1214  // fidRef returned (newRef) has a reference associated with it that is now
  1215  // owned by the caller and must be handled appropriately.
  1216  func doWalk(cs *connState, ref *fidRef, names []string, getattr bool) (qids []QID, newRef *fidRef, valid AttrMask, attr Attr, err error) {
  1217  	// Check the names.
  1218  	for _, name := range names {
  1219  		err = checkSafeName(name)
  1220  		if err != nil {
  1221  			return
  1222  		}
  1223  	}
  1224  
  1225  	// Has it been opened already?
  1226  	err = ref.safelyRead(func() (err error) {
  1227  		if ref.opened {
  1228  			return unix.EBUSY
  1229  		}
  1230  		return nil
  1231  	})
  1232  	if err != nil {
  1233  		return
  1234  	}
  1235  
  1236  	// Is this an empty list? Handle specially. We don't actually need to
  1237  	// validate anything since this is always permitted.
  1238  	if len(names) == 0 {
  1239  		var sf File // Temporary.
  1240  		if err := ref.maybeParent().safelyRead(func() (err error) {
  1241  			// Clone the single element.
  1242  			qids, sf, valid, attr, err = walkOne(nil, ref.file, nil, getattr)
  1243  			if err != nil {
  1244  				return err
  1245  			}
  1246  
  1247  			newRef = &fidRef{
  1248  				server:   cs.server,
  1249  				parent:   ref.parent,
  1250  				file:     sf,
  1251  				mode:     ref.mode,
  1252  				pathNode: ref.pathNode,
  1253  			}
  1254  			if !ref.isRoot() {
  1255  				if !newRef.isDeleted() {
  1256  					// Add only if a non-root node; the same node.
  1257  					ref.parent.pathNode.addChild(newRef, ref.parent.pathNode.nameFor(ref))
  1258  				}
  1259  				ref.parent.IncRef() // Acquire parent reference.
  1260  			}
  1261  			// doWalk returns a reference.
  1262  			newRef.IncRef()
  1263  			return nil
  1264  		}); err != nil {
  1265  			return nil, nil, AttrMask{}, Attr{}, err
  1266  		}
  1267  		// Do not return the new QID.
  1268  		return nil, newRef, valid, attr, nil
  1269  	}
  1270  
  1271  	// Do the walk, one element at a time.
  1272  	walkRef := ref
  1273  	walkRef.IncRef()
  1274  	for i := 0; i < len(names); i++ {
  1275  		// We won't allow beyond past symlinks; stop here if this isn't
  1276  		// a proper directory and we have additional paths to walk.
  1277  		if !walkRef.mode.IsDir() {
  1278  			walkRef.DecRef() // Drop walk reference; no lock required.
  1279  			return nil, nil, AttrMask{}, Attr{}, unix.EINVAL
  1280  		}
  1281  
  1282  		var sf File // Temporary.
  1283  		if err := walkRef.safelyRead(func() (err error) {
  1284  			// It is not safe to walk on a deleted directory. It could have been
  1285  			// replaced with a malicious symlink.
  1286  			if walkRef.isDeleted() {
  1287  				// Fail this operation as the result will not be meaningful if walkRef
  1288  				// is deleted.
  1289  				return unix.ENOENT
  1290  			}
  1291  			// Pass getattr = true to walkOne since we need the file type for
  1292  			// newRef.
  1293  			qids, sf, valid, attr, err = walkOne(qids, walkRef.file, names[i:i+1], true)
  1294  			if err != nil {
  1295  				return err
  1296  			}
  1297  
  1298  			// Note that we don't need to acquire a lock on any of
  1299  			// these individual instances. That's because they are
  1300  			// not actually addressable via a FID. They are
  1301  			// anonymous. They exist in the tree for tracking
  1302  			// purposes.
  1303  			newRef := &fidRef{
  1304  				server:   cs.server,
  1305  				parent:   walkRef,
  1306  				file:     sf,
  1307  				mode:     attr.Mode.FileType(),
  1308  				pathNode: walkRef.pathNode.pathNodeFor(names[i]),
  1309  			}
  1310  			walkRef.pathNode.addChild(newRef, names[i])
  1311  			// We allow our walk reference to become the new parent
  1312  			// reference here and so we don't IncRef. Instead, just
  1313  			// set walkRef to the newRef above and acquire a new
  1314  			// walk reference.
  1315  			walkRef = newRef
  1316  			walkRef.IncRef()
  1317  			return nil
  1318  		}); err != nil {
  1319  			walkRef.DecRef() // Drop the old walkRef.
  1320  			return nil, nil, AttrMask{}, Attr{}, err
  1321  		}
  1322  	}
  1323  
  1324  	// Success.
  1325  	return qids, walkRef, valid, attr, nil
  1326  }
  1327  
  1328  // handle implements handler.handle.
  1329  func (t *Twalk) handle(cs *connState) message {
  1330  	ref, ok := cs.LookupFID(t.FID)
  1331  	if !ok {
  1332  		return newErr(unix.EBADF)
  1333  	}
  1334  	defer ref.DecRef()
  1335  
  1336  	// Do the walk.
  1337  	qids, newRef, _, _, err := doWalk(cs, ref, t.Names, false)
  1338  	if err != nil {
  1339  		return newErr(err)
  1340  	}
  1341  	defer newRef.DecRef()
  1342  
  1343  	// Install the new FID.
  1344  	cs.InsertFID(t.NewFID, newRef)
  1345  	return &Rwalk{QIDs: qids}
  1346  }
  1347  
  1348  // handle implements handler.handle.
  1349  func (t *Twalkgetattr) handle(cs *connState) message {
  1350  	ref, ok := cs.LookupFID(t.FID)
  1351  	if !ok {
  1352  		return newErr(unix.EBADF)
  1353  	}
  1354  	defer ref.DecRef()
  1355  
  1356  	// Do the walk.
  1357  	qids, newRef, valid, attr, err := doWalk(cs, ref, t.Names, true)
  1358  	if err != nil {
  1359  		return newErr(err)
  1360  	}
  1361  	defer newRef.DecRef()
  1362  
  1363  	// Install the new FID.
  1364  	cs.InsertFID(t.NewFID, newRef)
  1365  	return &Rwalkgetattr{QIDs: qids, Valid: valid, Attr: attr}
  1366  }
  1367  
  1368  // handle implements handler.handle.
  1369  func (t *Tucreate) handle(cs *connState) message {
  1370  	rlcreate, err := t.Tlcreate.do(cs, t.UID)
  1371  	if err != nil {
  1372  		return newErr(err)
  1373  	}
  1374  	return &Rucreate{*rlcreate}
  1375  }
  1376  
  1377  // handle implements handler.handle.
  1378  func (t *Tumkdir) handle(cs *connState) message {
  1379  	rmkdir, err := t.Tmkdir.do(cs, t.UID)
  1380  	if err != nil {
  1381  		return newErr(err)
  1382  	}
  1383  	return &Rumkdir{*rmkdir}
  1384  }
  1385  
  1386  // handle implements handler.handle.
  1387  func (t *Tusymlink) handle(cs *connState) message {
  1388  	rsymlink, err := t.Tsymlink.do(cs, t.UID)
  1389  	if err != nil {
  1390  		return newErr(err)
  1391  	}
  1392  	return &Rusymlink{*rsymlink}
  1393  }
  1394  
  1395  // handle implements handler.handle.
  1396  func (t *Tumknod) handle(cs *connState) message {
  1397  	rmknod, err := t.Tmknod.do(cs, t.UID)
  1398  	if err != nil {
  1399  		return newErr(err)
  1400  	}
  1401  	return &Rumknod{*rmknod}
  1402  }
  1403  
  1404  // handle implements handler.handle.
  1405  func (t *Tbind) handle(cs *connState) message {
  1406  	if err := checkSafeName(t.SockName); err != nil {
  1407  		return newErr(err)
  1408  	}
  1409  
  1410  	ref, ok := cs.LookupFID(t.Directory)
  1411  	if !ok {
  1412  		return newErr(unix.EBADF)
  1413  	}
  1414  	defer ref.DecRef()
  1415  
  1416  	var (
  1417  		sockRef *fidRef
  1418  		qid     QID
  1419  		valid   AttrMask
  1420  		attr    Attr
  1421  	)
  1422  	if err := ref.safelyWrite(func() (err error) {
  1423  		// Don't allow creation from non-directories or deleted directories.
  1424  		if ref.isDeleted() || !ref.mode.IsDir() {
  1425  			return unix.EINVAL
  1426  		}
  1427  
  1428  		// Not allowed on open directories.
  1429  		if ref.opened {
  1430  			return unix.EINVAL
  1431  		}
  1432  
  1433  		var sockF File
  1434  		sockF, qid, valid, attr, err = ref.file.Bind(t.SockType, t.SockName, t.UID, t.GID)
  1435  		if err != nil {
  1436  			return err
  1437  		}
  1438  
  1439  		sockRef = &fidRef{
  1440  			server:   cs.server,
  1441  			parent:   ref,
  1442  			file:     sockF,
  1443  			mode:     ModeSocket,
  1444  			pathNode: ref.pathNode.pathNodeFor(t.SockName),
  1445  		}
  1446  		ref.pathNode.addChild(sockRef, t.SockName)
  1447  		ref.IncRef() // Acquire parent reference.
  1448  		return nil
  1449  	}); err != nil {
  1450  		return newErr(err)
  1451  	}
  1452  	cs.InsertFID(t.NewFID, sockRef)
  1453  	return &Rbind{QID: qid, Valid: valid, Attr: attr}
  1454  }
  1455  
  1456  // handle implements handler.handle.
  1457  func (t *Tlconnect) handle(cs *connState) message {
  1458  	ref, ok := cs.LookupFID(t.FID)
  1459  	if !ok {
  1460  		return newErr(unix.EBADF)
  1461  	}
  1462  	defer ref.DecRef()
  1463  
  1464  	var osFile *fd.FD
  1465  	if err := ref.safelyRead(func() (err error) {
  1466  		// Don't allow connecting to deleted files.
  1467  		if ref.isDeleted() || !ref.mode.IsSocket() {
  1468  			return unix.EINVAL
  1469  		}
  1470  
  1471  		// Do the connect.
  1472  		osFile, err = ref.file.Connect(t.SocketType)
  1473  		return err
  1474  	}); err != nil {
  1475  		return newErr(err)
  1476  	}
  1477  
  1478  	rlconnect := &Rlconnect{}
  1479  	rlconnect.SetFilePayload(osFile)
  1480  	return rlconnect
  1481  }
  1482  
  1483  // handle implements handler.handle.
  1484  func (t *Tchannel) handle(cs *connState) message {
  1485  	// Ensure that channels are enabled.
  1486  	if err := cs.initializeChannels(); err != nil {
  1487  		return newErr(err)
  1488  	}
  1489  
  1490  	ch := cs.lookupChannel(t.ID)
  1491  	if ch == nil {
  1492  		return newErr(unix.ENOSYS)
  1493  	}
  1494  
  1495  	// Return the payload. Note that we need to duplicate the file
  1496  	// descriptor for the channel allocator, because sending is a
  1497  	// destructive operation between sendRecvLegacy (and now the newer
  1498  	// channel send operations). Same goes for the client FD.
  1499  	rchannel := &Rchannel{
  1500  		Offset: uint64(ch.desc.Offset),
  1501  		Length: uint64(ch.desc.Length),
  1502  	}
  1503  	switch t.Control {
  1504  	case 0:
  1505  		// Open the main data channel.
  1506  		mfd, err := unix.Dup(int(cs.channelAlloc.FD()))
  1507  		if err != nil {
  1508  			return newErr(err)
  1509  		}
  1510  		rchannel.SetFilePayload(fd.New(mfd))
  1511  	case 1:
  1512  		cfd, err := unix.Dup(ch.client.FD())
  1513  		if err != nil {
  1514  			return newErr(err)
  1515  		}
  1516  		rchannel.SetFilePayload(fd.New(cfd))
  1517  	default:
  1518  		return newErr(unix.EINVAL)
  1519  	}
  1520  	return rchannel
  1521  }
  1522  
  1523  // handle implements handler.handle.
  1524  func (t *Tmultigetattr) handle(cs *connState) message {
  1525  	for i, name := range t.Names {
  1526  		if len(name) == 0 && i == 0 {
  1527  			// Empty name is allowed on the first entry to indicate that the current
  1528  			// FID needs to be included in the result.
  1529  			continue
  1530  		}
  1531  		if err := checkSafeName(name); err != nil {
  1532  			return newErr(err)
  1533  		}
  1534  	}
  1535  	ref, ok := cs.LookupFID(t.FID)
  1536  	if !ok {
  1537  		return newErr(unix.EBADF)
  1538  	}
  1539  	defer ref.DecRef()
  1540  
  1541  	if cs.server.options.MultiGetAttrSupported {
  1542  		var stats []FullStat
  1543  		if err := ref.safelyRead(func() (err error) {
  1544  			stats, err = ref.file.MultiGetAttr(t.Names)
  1545  			return err
  1546  		}); err != nil {
  1547  			return newErr(err)
  1548  		}
  1549  		return &Rmultigetattr{Stats: stats}
  1550  	}
  1551  
  1552  	stats := make([]FullStat, 0, len(t.Names))
  1553  	mask := AttrMaskAll()
  1554  	start := ref.file
  1555  	startNode := ref.pathNode
  1556  	parent := start
  1557  	parentNode := startNode
  1558  	closeParent := func() {
  1559  		if parent != start {
  1560  			_ = parent.Close()
  1561  		}
  1562  	}
  1563  	defer closeParent()
  1564  
  1565  	cs.server.renameMu.RLock()
  1566  	defer cs.server.renameMu.RUnlock()
  1567  
  1568  	for i, name := range t.Names {
  1569  		if len(name) == 0 && i == 0 {
  1570  			startNode.opMu.RLock()
  1571  			qid, valid, attr, err := start.GetAttr(mask)
  1572  			startNode.opMu.RUnlock()
  1573  			if err != nil {
  1574  				return newErr(err)
  1575  			}
  1576  			stats = append(stats, FullStat{
  1577  				QID:   qid,
  1578  				Valid: valid,
  1579  				Attr:  attr,
  1580  			})
  1581  			continue
  1582  		}
  1583  
  1584  		parentNode.opMu.RLock()
  1585  		if parentNode.deleted.Load() != 0 {
  1586  			parentNode.opMu.RUnlock()
  1587  			break
  1588  		}
  1589  		qids, child, valid, attr, err := parent.WalkGetAttr([]string{name})
  1590  		if err != nil {
  1591  			parentNode.opMu.RUnlock()
  1592  			if errors2.Is(err, unix.ENOENT) {
  1593  				break
  1594  			}
  1595  			return newErr(err)
  1596  		}
  1597  		stats = append(stats, FullStat{
  1598  			QID:   qids[0],
  1599  			Valid: valid,
  1600  			Attr:  attr,
  1601  		})
  1602  		// Update with next generation.
  1603  		closeParent()
  1604  		parent = child
  1605  		childNode := parentNode.pathNodeFor(name)
  1606  		parentNode.opMu.RUnlock()
  1607  		parentNode = childNode
  1608  		if attr.Mode.FileType() != ModeDirectory {
  1609  			// Doesn't need to continue if entry is not a dir. Including symlinks
  1610  			// that cannot be followed.
  1611  			break
  1612  		}
  1613  	}
  1614  
  1615  	return &Rmultigetattr{Stats: stats}
  1616  }