summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/mattermost/rsc/fuse/serve.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/mattermost/rsc/fuse/serve.go')
-rw-r--r--vendor/github.com/mattermost/rsc/fuse/serve.go1022
1 files changed, 0 insertions, 1022 deletions
diff --git a/vendor/github.com/mattermost/rsc/fuse/serve.go b/vendor/github.com/mattermost/rsc/fuse/serve.go
deleted file mode 100644
index fa4f27e3f..000000000
--- a/vendor/github.com/mattermost/rsc/fuse/serve.go
+++ /dev/null
@@ -1,1022 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// FUSE service loop, for servers that wish to use it.
-
-package fuse
-
-import (
- "fmt"
- "hash/fnv"
- "io"
- "log"
- "os"
- "path"
- "sync"
- "syscall"
- "time"
-)
-
-// TODO: FINISH DOCS
-
-// An Intr is a channel that signals that a request has been interrupted.
-// Being able to receive from the channel means the request has been
-// interrupted.
-type Intr chan struct{}
-
-func (Intr) String() string { return "fuse.Intr" }
-
-// An FS is the interface required of a file system.
-//
-// Root() (Node, Error)
-//
-// Root is called to obtain the Node for the file system root.
-//
-// Optional Methods
-//
-// An FS implementation may implement
-// additional methods to handle the corresponding FUSE requests:
-//
-// Init(req *InitRequest, resp *InitResponse) Error
-//
-// Init is called to initialize the FUSE connection.
-// It can inspect the request and adjust the response as desired.
-// The default response sets MaxReadahead to 0 and MaxWrite to 4096.
-// Init must return promptly.
-//
-// Statfs(resp *StatfsResponse, intr Intr) Error
-//
-// Statfs is called to obtain file system metadata. It should write that data to resp.
-//
-// Rename(req *RenameRequest, intr Intr) Error
-//
-// XXXX this is not implemented like this. Instead, Rename is a method
-// on the source dierctory node, and takes a newDir Node parameter. Fix it like this?
-// Rename is called to rename the file req.OldName in the directory req.OldDir to
-// become the file req.NewName in the directory req.NewDir.
-//
-type FS interface {
- Root() (Node, Error)
-}
-
-// A Node is the interface required of a file or directory.
-// See the documentation for type FS for general information
-// pertaining to all methods.
-//
-// Getattr(resp *GetattrResponse, intr Intr) fuse.Error
-//
-// Getattr obtains the standard metadata for the receiver.
-// It should store that metadata in resp.
-//
-// Open(xxx, intr Intr) (Handle, fuse.Error)
-//
-// Open opens the receiver.
-// XXX note about access. XXX OpenFlags.
-// XXX note that the Node may be a file or directory.
-//
-// Optional Methods
-//
-// An Node implementation may implement additional methods
-// to handle the corresponding FUSE requests.
-//
-// These optional requests can be called for both file and directory nodes:
-//
-// Access
-//
-// Access checks whether the calling context has permission for
-// the given operations on the receiver. If so, Access should return nil. If not, Access should
-// return EPERM. Note that this call affects the result of the access(2) system call
-// but not the open(2) system call. If Access is not implemented, the Node behaves
-// as if it always returns nil (permission granted), relying on checks in Open instead.
-//
-// Getxattr
-//
-// Getxattr obtains an extended attribute for the receiver.
-// XXX
-//
-// Listxattr
-//
-// Listxattr lists the extended attributes recorded for the receiver.
-//
-// Removexattr
-//
-// Removexattr removes an extended attribute from the receiver.
-//
-// Setattr
-//
-// Setattr sets the standard metadata for the receiver.
-//
-// Setxattr
-//
-// Setxattr sets an extended attribute for the receiver.
-//
-// Optional Directory Methods
-//
-// These optional requests will be called only for directory nodes:
-//
-// Create(xxx)
-//
-// Create creates
-//
-// Link(xxx)
-//
-// Link XXX
-//
-// Lookup(name string, intr Intr) (Node, Error)
-//
-// Lookup looks up a specific entry in the receiver,
-// which must be a directory. Lookup should return a Node
-// corresponding to the entry. If the name does not exist in
-// the directory, Lookup should return nil, err.
-//
-// Lookup need not to handle the names "." and "..".
-//
-// Mkdir
-//
-// Mkdir creates XXX
-//
-// Mknod XXX
-//
-// XXX
-//
-// Remove
-//
-// Remove removes the entry with the given name from
-// the receiver, which must be a directory. The entry to be removed
-// may correspond to a file (unlink) or to a directory (rmdir).
-//
-// Symlink
-//
-// Symlink creates a new symbolic link in the receiver, which must be a directory.
-// The entry
-//
-// Optional Symlink Methods
-//
-// This optional request will be called only for symbolic link nodes:
-//
-// Readlink
-//
-// Readlink reads a symbolic link.
-type Node interface {
- Attr() Attr
-}
-
-var startTime = time.Now()
-
-func nodeAttr(inode uint64, n Node) (attr Attr) {
- attr = n.Attr()
- if attr.Nlink == 0 {
- attr.Nlink = 1
- }
- if attr.Atime.IsZero() {
- attr.Atime = startTime
- }
- if attr.Mtime.IsZero() {
- attr.Mtime = startTime
- }
- if attr.Ctime.IsZero() {
- attr.Ctime = startTime
- }
- if attr.Crtime.IsZero() {
- attr.Crtime = startTime
- }
- if attr.Inode == 0 {
- attr.Inode = inode
- }
- return
-}
-
-// A Handle is the interface required of an opened file or directory.
-// See the documentation for type FS for general information
-// pertaining to all methods.
-//
-// Flush
-//
-// Flush is called each time the file or directory is closed. Because there can be
-// multiple file descriptors referring to a single opened file, Flush can be called
-// multiple times.
-//
-// Optional Methods
-//
-// A Handle implementation may implement additional methods to handle
-// the corresponding FUSE requests. The most common to implement are
-// Read, ReadDir, and Write.
-//
-// Fsync
-//
-// Getlk
-//
-// Read
-//
-// Readdir
-//
-// Release
-//
-// Setlk
-//
-// Setlkw
-//
-// Write
-//
-type Handle interface {
-}
-
-// Serve serves the FUSE connection by making calls to the methods
-// of fs and the Nodes and Handles it makes available. It returns only
-// when the connection has been closed or an unexpected error occurs.
-func (c *Conn) Serve(fs FS) error {
- if c.req != nil {
- panic("fuse: Serve called twice")
- }
- c.req = map[RequestID]*serveRequest{}
-
- root, err := fs.Root()
- if err != nil {
- return fmt.Errorf("cannot obtain root node: %v", syscall.Errno(err.(Errno)).Error())
- }
- c.node = append(c.node, nil, &serveNode{name: "/", node: root})
- c.handle = append(c.handle, nil)
-
- for {
- req, err := c.ReadRequest()
- if err != nil {
- if err == io.EOF {
- break
- }
- return err
- }
-
- go c.serve(fs, req)
- }
- return nil
-}
-
-type serveConn struct {
- meta sync.Mutex
- req map[RequestID]*serveRequest
- node []*serveNode
- handle []*serveHandle
- freeNode []NodeID
- freeHandle []HandleID
- nodeGen uint64
- nodeHandles []map[HandleID]bool // open handles for a node; slice index is NodeID
-}
-
-type serveRequest struct {
- Request Request
- Intr Intr
-}
-
-type serveNode struct {
- name string
- node Node
- inode uint64
- isDir bool
-}
-
-func (sn *serveNode) attr() (attr Attr) {
- attr = nodeAttr(sn.inode, sn.node)
- if attr.Inode == 0 {
- sn.inode = hash(sn.name)
- attr.Inode = sn.inode
- }
- sn.isDir = attr.Mode&os.ModeDir != 0
- return
-}
-
-func hash(s string) uint64 {
- f := fnv.New64()
- f.Write([]byte(s))
- return f.Sum64()
-}
-
-type serveHandle struct {
- handle Handle
- readData []byte
- trunc bool
- writeData []byte
- nodeID NodeID
-}
-
-func (c *Conn) saveNode(name string, node Node) (id NodeID, gen uint64, sn *serveNode) {
- sn = &serveNode{name: name, node: node}
- c.meta.Lock()
- if n := len(c.freeNode); n > 0 {
- id = c.freeNode[n-1]
- c.freeNode = c.freeNode[:n-1]
- c.node[id] = sn
- c.nodeGen++
- } else {
- id = NodeID(len(c.node))
- c.node = append(c.node, sn)
- }
- gen = c.nodeGen
- c.meta.Unlock()
- return
-}
-
-func (c *Conn) saveHandle(handle Handle, nodeID NodeID) (id HandleID, shandle *serveHandle) {
- c.meta.Lock()
- shandle = &serveHandle{handle: handle, nodeID: nodeID}
- if n := len(c.freeHandle); n > 0 {
- id = c.freeHandle[n-1]
- c.freeHandle = c.freeHandle[:n-1]
- c.handle[id] = shandle
- } else {
- id = HandleID(len(c.handle))
- c.handle = append(c.handle, shandle)
- }
-
- // Update mapping from node ID -> set of open Handle IDs.
- for len(c.nodeHandles) <= int(nodeID) {
- c.nodeHandles = append(c.nodeHandles, nil)
- }
- if c.nodeHandles[nodeID] == nil {
- c.nodeHandles[nodeID] = make(map[HandleID]bool)
- }
- c.nodeHandles[nodeID][id] = true
-
- c.meta.Unlock()
- return
-}
-
-func (c *Conn) dropNode(id NodeID) {
- c.meta.Lock()
- c.node[id] = nil
- if len(c.nodeHandles) > int(id) {
- c.nodeHandles[id] = nil
- }
- c.freeNode = append(c.freeNode, id)
- c.meta.Unlock()
-}
-
-func (c *Conn) dropHandle(id HandleID) {
- c.meta.Lock()
- h := c.handle[id]
- delete(c.nodeHandles[h.nodeID], id)
- c.handle[id] = nil
- c.freeHandle = append(c.freeHandle, id)
- c.meta.Unlock()
-}
-
-func (c *Conn) serve(fs FS, r Request) {
- intr := make(Intr)
- req := &serveRequest{Request: r, Intr: intr}
-
- Debugf("<- %s", req)
- var node Node
- var handle Handle
- var snode *serveNode
- var shandle *serveHandle
- c.meta.Lock()
- hdr := r.Hdr()
- if id := hdr.Node; id != 0 {
- if id < NodeID(len(c.node)) {
- snode = c.node[uint(id)]
- }
- if snode == nil {
- c.meta.Unlock()
- println("missing node", id, len(c.node), snode)
- Debugf("-> %#x %v", hdr.ID, ESTALE)
- r.RespondError(ESTALE)
- return
- }
- node = snode.node
- }
- if id := r.handle(); id != 0 {
- if id < HandleID(len(c.handle)) {
- shandle = c.handle[uint(id)]
- }
- if shandle == nil {
- println("missing handle", id, len(c.handle), shandle)
- c.meta.Unlock()
- Debugf("-> %#x %v", hdr.ID, ESTALE)
- r.RespondError(ESTALE)
- return
- }
- handle = shandle.handle
- }
- intr = make(chan struct{})
- if c.req[hdr.ID] != nil {
- // This happens with OSXFUSE. Assume it's okay and
- // that we'll never see an interrupt for this one.
- // Otherwise everything wedges. TODO: Report to OSXFUSE?
- intr = nil
- } else {
- c.req[hdr.ID] = req
- }
- c.meta.Unlock()
-
- // Call this before responding.
- // After responding is too late: we might get another request
- // with the same ID and be very confused.
- done := func(resp interface{}) {
- Debugf("-> %#x %v", hdr.ID, resp)
- c.meta.Lock()
- c.req[hdr.ID] = nil
- c.meta.Unlock()
- }
-
- switch r := r.(type) {
- default:
- // Note: To FUSE, ENOSYS means "this server never implements this request."
- // It would be inappropriate to return ENOSYS for other operations in this
- // switch that might only be unavailable in some contexts, not all.
- done(ENOSYS)
- r.RespondError(ENOSYS)
-
- // FS operations.
- case *InitRequest:
- s := &InitResponse{
- MaxWrite: 4096,
- }
- if fs, ok := fs.(interface {
- Init(*InitRequest, *InitResponse, Intr) Error
- }); ok {
- if err := fs.Init(r, s, intr); err != nil {
- done(err)
- r.RespondError(err)
- break
- }
- }
- done(s)
- r.Respond(s)
-
- case *StatfsRequest:
- s := &StatfsResponse{}
- if fs, ok := fs.(interface {
- Statfs(*StatfsRequest, *StatfsResponse, Intr) Error
- }); ok {
- if err := fs.Statfs(r, s, intr); err != nil {
- done(err)
- r.RespondError(err)
- break
- }
- }
- done(s)
- r.Respond(s)
-
- // Node operations.
- case *GetattrRequest:
- s := &GetattrResponse{}
- if n, ok := node.(interface {
- Getattr(*GetattrRequest, *GetattrResponse, Intr) Error
- }); ok {
- if err := n.Getattr(r, s, intr); err != nil {
- done(err)
- r.RespondError(err)
- break
- }
- } else {
- s.AttrValid = 1 * time.Minute
- s.Attr = snode.attr()
- }
- done(s)
- r.Respond(s)
-
- case *SetattrRequest:
- s := &SetattrResponse{}
-
- // Special-case truncation, if no other bits are set
- // and the open Handles all have a WriteAll method.
- if r.Valid&SetattrSize != 0 && r.Size == 0 {
- type writeAll interface {
- WriteAll([]byte, Intr) Error
- }
- switch r.Valid {
- case SetattrLockOwner | SetattrSize, SetattrSize:
- // Seen on Linux. Handle isn't set.
- c.meta.Lock()
- for hid := range c.nodeHandles[hdr.Node] {
- shandle := c.handle[hid]
- if _, ok := shandle.handle.(writeAll); ok {
- shandle.trunc = true
- }
- }
- c.meta.Unlock()
- case SetattrHandle | SetattrSize:
- // Seen on OS X; the Handle is provided.
- if _, ok := handle.(writeAll); ok {
- shandle.trunc = true
- }
- }
- }
-
- log.Printf("setattr %v", r)
- if n, ok := node.(interface {
- Setattr(*SetattrRequest, *SetattrResponse, Intr) Error
- }); ok {
- if err := n.Setattr(r, s, intr); err != nil {
- done(err)
- r.RespondError(err)
- break
- }
- done(s)
- r.Respond(s)
- break
- }
-
- if s.AttrValid == 0 {
- s.AttrValid = 1 * time.Minute
- }
- s.Attr = snode.attr()
- done(s)
- r.Respond(s)
-
- case *SymlinkRequest:
- s := &SymlinkResponse{}
- n, ok := node.(interface {
- Symlink(*SymlinkRequest, Intr) (Node, Error)
- })
- if !ok {
- done(EIO) // XXX or EPERM like Mkdir?
- r.RespondError(EIO)
- break
- }
- n2, err := n.Symlink(r, intr)
- if err != nil {
- done(err)
- r.RespondError(err)
- break
- }
- c.saveLookup(&s.LookupResponse, snode, r.NewName, n2)
- done(s)
- r.Respond(s)
-
- case *ReadlinkRequest:
- n, ok := node.(interface {
- Readlink(*ReadlinkRequest, Intr) (string, Error)
- })
- if !ok {
- done(EIO) /// XXX or EPERM?
- r.RespondError(EIO)
- break
- }
- target, err := n.Readlink(r, intr)
- if err != nil {
- done(err)
- r.RespondError(err)
- break
- }
- done(target)
- r.Respond(target)
-
- case *LinkRequest:
- n, ok := node.(interface {
- Link(r *LinkRequest, old Node, intr Intr) (Node, Error)
- })
- if !ok {
- log.Printf("Node %T doesn't implement fuse Link", node)
- done(EIO) /// XXX or EPERM?
- r.RespondError(EIO)
- break
- }
- c.meta.Lock()
- var oldNode *serveNode
- if int(r.OldNode) < len(c.node) {
- oldNode = c.node[r.OldNode]
- }
- c.meta.Unlock()
- if oldNode == nil {
- log.Printf("In LinkRequest, node %d not found", r.OldNode)
- done(EIO)
- r.RespondError(EIO)
- break
- }
- n2, err := n.Link(r, oldNode.node, intr)
- if err != nil {
- done(err)
- r.RespondError(err)
- break
- }
- s := &LookupResponse{}
- c.saveLookup(s, snode, r.NewName, n2)
- done(s)
- r.Respond(s)
-
- case *RemoveRequest:
- n, ok := node.(interface {
- Remove(*RemoveRequest, Intr) Error
- })
- if !ok {
- done(EIO) /// XXX or EPERM?
- r.RespondError(EIO)
- break
- }
- err := n.Remove(r, intr)
- if err != nil {
- done(err)
- r.RespondError(err)
- break
- }
- done(nil)
- r.Respond()
-
- case *AccessRequest:
- if n, ok := node.(interface {
- Access(*AccessRequest, Intr) Error
- }); ok {
- if err := n.Access(r, intr); err != nil {
- done(err)
- r.RespondError(err)
- break
- }
- }
- done(r)
- r.Respond()
-
- case *LookupRequest:
- var n2 Node
- var err Error
- s := &LookupResponse{}
- if n, ok := node.(interface {
- Lookup(string, Intr) (Node, Error)
- }); ok {
- n2, err = n.Lookup(r.Name, intr)
- } else if n, ok := node.(interface {
- Lookup(*LookupRequest, *LookupResponse, Intr) (Node, Error)
- }); ok {
- n2, err = n.Lookup(r, s, intr)
- } else {
- done(ENOENT)
- r.RespondError(ENOENT)
- break
- }
- if err != nil {
- done(err)
- r.RespondError(err)
- break
- }
- c.saveLookup(s, snode, r.Name, n2)
- done(s)
- r.Respond(s)
-
- case *MkdirRequest:
- s := &MkdirResponse{}
- n, ok := node.(interface {
- Mkdir(*MkdirRequest, Intr) (Node, Error)
- })
- if !ok {
- done(EPERM)
- r.RespondError(EPERM)
- break
- }
- n2, err := n.Mkdir(r, intr)
- if err != nil {
- done(err)
- r.RespondError(err)
- break
- }
- c.saveLookup(&s.LookupResponse, snode, r.Name, n2)
- done(s)
- r.Respond(s)
-
- case *OpenRequest:
- s := &OpenResponse{Flags: OpenDirectIO}
- var h2 Handle
- if n, ok := node.(interface {
- Open(*OpenRequest, *OpenResponse, Intr) (Handle, Error)
- }); ok {
- hh, err := n.Open(r, s, intr)
- if err != nil {
- done(err)
- r.RespondError(err)
- break
- }
- h2 = hh
- } else {
- h2 = node
- }
- s.Handle, _ = c.saveHandle(h2, hdr.Node)
- done(s)
- r.Respond(s)
-
- case *CreateRequest:
- n, ok := node.(interface {
- Create(*CreateRequest, *CreateResponse, Intr) (Node, Handle, Error)
- })
- if !ok {
- // If we send back ENOSYS, FUSE will try mknod+open.
- done(EPERM)
- r.RespondError(EPERM)
- break
- }
- s := &CreateResponse{OpenResponse: OpenResponse{Flags: OpenDirectIO}}
- n2, h2, err := n.Create(r, s, intr)
- if err != nil {
- done(err)
- r.RespondError(err)
- break
- }
- c.saveLookup(&s.LookupResponse, snode, r.Name, n2)
- h, shandle := c.saveHandle(h2, hdr.Node)
- s.Handle = h
- shandle.trunc = true
- done(s)
- r.Respond(s)
-
- case *GetxattrRequest, *SetxattrRequest, *ListxattrRequest, *RemovexattrRequest:
- // TODO: Use n.
- done(ENOSYS)
- r.RespondError(ENOSYS)
-
- case *ForgetRequest:
- n, ok := node.(interface {
- Forget()
- })
- if ok {
- n.Forget()
- }
- c.dropNode(hdr.Node)
- done(r)
- r.Respond()
-
- // Handle operations.
- case *ReadRequest:
- s := &ReadResponse{Data: make([]byte, 0, r.Size)}
- if snode.isDir {
- if h, ok := handle.(interface {
- ReadDir(Intr) ([]Dirent, Error)
- }); ok {
- if shandle.readData == nil {
- attr := snode.attr()
- dirs, err := h.ReadDir(intr)
- if err != nil {
- done(err)
- r.RespondError(err)
- break
- }
- var data []byte
- data = AppendDirent(data, Dirent{Inode: attr.Inode, Name: "."})
- data = AppendDirent(data, Dirent{Inode: attr.Inode, Name: ".."})
- for _, dir := range dirs {
- if dir.Inode == 0 {
- dir.Inode = hash(path.Join(snode.name, dir.Name))
- }
- data = AppendDirent(data, dir)
- }
- shandle.readData = data
- }
- HandleRead(r, s, shandle.readData)
- done(s)
- r.Respond(s)
- break
- }
- } else {
- if h, ok := handle.(interface {
- ReadAll(Intr) ([]byte, Error)
- }); ok {
- if shandle.readData == nil {
- data, err := h.ReadAll(intr)
- if err != nil {
- done(err)
- r.RespondError(err)
- break
- }
- if data == nil {
- data = []byte{}
- }
- shandle.readData = data
- }
- HandleRead(r, s, shandle.readData)
- done(s)
- r.Respond(s)
- break
- }
- }
- h, ok := handle.(interface {
- Read(*ReadRequest, *ReadResponse, Intr) Error
- })
- if !ok {
- fmt.Printf("NO READ FOR %T\n", handle)
- done(EIO)
- r.RespondError(EIO)
- break
- }
- if err := h.Read(r, s, intr); err != nil {
- done(err)
- r.RespondError(err)
- break
- }
- done(s)
- r.Respond(s)
-
- case *WriteRequest:
- s := &WriteResponse{}
- if shandle.trunc && r.Offset == int64(len(shandle.writeData)) {
- shandle.writeData = append(shandle.writeData, r.Data...)
- s.Size = len(r.Data)
- done(s)
- r.Respond(s)
- break
- }
- if h, ok := handle.(interface {
- Write(*WriteRequest, *WriteResponse, Intr) Error
- }); ok {
- if err := h.Write(r, s, intr); err != nil {
- done(err)
- r.RespondError(err)
- break
- }
- done(s)
- r.Respond(s)
- break
- }
- println("NO WRITE")
- done(EIO)
- r.RespondError(EIO)
-
- case *FlushRequest:
- if shandle.trunc {
- h := handle.(interface {
- WriteAll([]byte, Intr) Error
- })
- if err := h.WriteAll(shandle.writeData, intr); err != nil {
- done(err)
- r.RespondError(err)
- break
- }
- shandle.writeData = nil
- shandle.trunc = false
- }
- if h, ok := handle.(interface {
- Flush(*FlushRequest, Intr) Error
- }); ok {
- if err := h.Flush(r, intr); err != nil {
- done(err)
- r.RespondError(err)
- break
- }
- }
- done(nil)
- r.Respond()
-
- case *ReleaseRequest:
- // No matter what, release the handle.
- c.dropHandle(r.handle())
- if h, ok := handle.(interface {
- Release(*ReleaseRequest, Intr) Error
- }); ok {
- if err := h.Release(r, intr); err != nil {
- done(err)
- r.RespondError(err)
- break
- }
- }
- done(nil)
- r.Respond()
-
- case *DestroyRequest:
- fs, ok := fs.(interface {
- Destroy()
- })
- if ok {
- fs.Destroy()
- }
- done(nil)
- r.Respond()
-
- case *RenameRequest:
- c.meta.Lock()
- var newDirNode *serveNode
- if int(r.NewDir) < len(c.node) {
- newDirNode = c.node[r.NewDir]
- }
- c.meta.Unlock()
- if newDirNode == nil {
- println("RENAME NEW DIR NODE NOT FOUND")
- done(EIO)
- r.RespondError(EIO)
- break
- }
- n, ok := node.(interface {
- Rename(r *RenameRequest, newDir Node, intr Intr) Error
- })
- if !ok {
- log.Printf("Node %T missing Rename method", node)
- done(EIO) // XXX or EPERM like Mkdir?
- r.RespondError(EIO)
- break
- }
- err := n.Rename(r, newDirNode.node, intr)
- if err != nil {
- done(err)
- r.RespondError(err)
- break
- }
- done(nil)
- r.Respond()
-
- case *MknodRequest:
- n, ok := node.(interface {
- Mknod(r *MknodRequest, intr Intr) (Node, Error)
- })
- if !ok {
- log.Printf("Node %T missing Mknod method", node)
- done(EIO)
- r.RespondError(EIO)
- break
- }
- n2, err := n.Mknod(r, intr)
- if err != nil {
- done(err)
- r.RespondError(err)
- break
- }
- s := &LookupResponse{}
- c.saveLookup(s, snode, r.Name, n2)
- done(s)
- r.Respond(s)
-
- case *FsyncRequest:
- n, ok := node.(interface {
- Fsync(r *FsyncRequest, intr Intr) Error
- })
- if !ok {
- log.Printf("Node %T missing Fsync method", node)
- done(EIO)
- r.RespondError(EIO)
- break
- }
- err := n.Fsync(r, intr)
- if err != nil {
- done(err)
- r.RespondError(err)
- break
- }
- done(nil)
- r.Respond()
-
- /* case *FsyncdirRequest:
- done(ENOSYS)
- r.RespondError(ENOSYS)
-
- case *GetlkRequest, *SetlkRequest, *SetlkwRequest:
- done(ENOSYS)
- r.RespondError(ENOSYS)
-
- // One of a kind.
- case *InterruptRequest:
- c.meta.Lock()
- ireq := c.req[r.OldID]
- if ireq != nil && ireq.Intr != nil {
- close(ireq.Intr)
- ireq.Intr = nil
- }
- c.meta.Unlock()
- done(nil)
- r.Respond()
-
- case *BmapRequest:
- done(ENOSYS)
- r.RespondError(ENOSYS)
-
- case *SetvolnameRequest, *GetxtimesRequest, *ExchangeRequest:
- done(ENOSYS)
- r.RespondError(ENOSYS)
- */
- }
-}
-
-func (c *Conn) saveLookup(s *LookupResponse, snode *serveNode, elem string, n2 Node) {
- name := path.Join(snode.name, elem)
- var sn *serveNode
- s.Node, s.Generation, sn = c.saveNode(name, n2)
- if s.EntryValid == 0 {
- s.EntryValid = 1 * time.Minute
- }
- if s.AttrValid == 0 {
- s.AttrValid = 1 * time.Minute
- }
- s.Attr = sn.attr()
-}
-
-// HandleRead handles a read request assuming that data is the entire file content.
-// It adjusts the amount returned in resp according to req.Offset and req.Size.
-func HandleRead(req *ReadRequest, resp *ReadResponse, data []byte) {
- if req.Offset >= int64(len(data)) {
- data = nil
- } else {
- data = data[req.Offset:]
- }
- if len(data) > req.Size {
- data = data[:req.Size]
- }
- n := copy(resp.Data[:req.Size], data)
- resp.Data = resp.Data[:n]
-}
-
-// DataHandle returns a read-only Handle that satisfies reads
-// using the given data.
-func DataHandle(data []byte) Handle {
- return &dataHandle{data}
-}
-
-type dataHandle struct {
- data []byte
-}
-
-func (d *dataHandle) Read(intr Intr) ([]byte, Error) {
- return d.data, nil
-}