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