summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/mattermost/rsc/fuse
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/mattermost/rsc/fuse')
-rw-r--r--vendor/github.com/mattermost/rsc/fuse/debug.go20
-rw-r--r--vendor/github.com/mattermost/rsc/fuse/fuse.go1650
-rw-r--r--vendor/github.com/mattermost/rsc/fuse/fuse_kernel.go539
-rw-r--r--vendor/github.com/mattermost/rsc/fuse/fuse_kernel_darwin.go58
-rw-r--r--vendor/github.com/mattermost/rsc/fuse/fuse_kernel_linux.go50
-rw-r--r--vendor/github.com/mattermost/rsc/fuse/fuse_kernel_std.go1
-rw-r--r--vendor/github.com/mattermost/rsc/fuse/fuse_test.go594
-rw-r--r--vendor/github.com/mattermost/rsc/fuse/hellofs/hello.go62
-rw-r--r--vendor/github.com/mattermost/rsc/fuse/mount_darwin.go122
-rw-r--r--vendor/github.com/mattermost/rsc/fuse/mount_linux.go67
-rw-r--r--vendor/github.com/mattermost/rsc/fuse/serve.go1022
-rw-r--r--vendor/github.com/mattermost/rsc/fuse/tree.go93
12 files changed, 0 insertions, 4278 deletions
diff --git a/vendor/github.com/mattermost/rsc/fuse/debug.go b/vendor/github.com/mattermost/rsc/fuse/debug.go
deleted file mode 100644
index 2dc5d4312..000000000
--- a/vendor/github.com/mattermost/rsc/fuse/debug.go
+++ /dev/null
@@ -1,20 +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 (
- "runtime"
-)
-
-func stack() string {
- buf := make([]byte, 1024)
- return string(buf[:runtime.Stack(buf, false)])
-}
-
-var Debugf = nop
-
-func nop(string, ...interface{}) {}
diff --git a/vendor/github.com/mattermost/rsc/fuse/fuse.go b/vendor/github.com/mattermost/rsc/fuse/fuse.go
deleted file mode 100644
index 2ad10c93e..000000000
--- a/vendor/github.com/mattermost/rsc/fuse/fuse.go
+++ /dev/null
@@ -1,1650 +0,0 @@
-// Copyright 2011 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.
-
-// Adapted from Plan 9 from User Space's src/cmd/9pfuse/fuse.c,
-// which carries this notice:
-//
-// The files in this directory are subject to the following license.
-//
-// The author of this software is Russ Cox.
-//
-// Copyright (c) 2006 Russ Cox
-//
-// Permission to use, copy, modify, and distribute this software for any
-// purpose without fee is hereby granted, provided that this entire notice
-// is included in all copies of any software which is or includes a copy
-// or modification of this software and in all copies of the supporting
-// documentation for such software.
-//
-// THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
-// WARRANTY. IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION OR WARRANTY
-// OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS SOFTWARE OR ITS
-// FITNESS FOR ANY PARTICULAR PURPOSE.
-
-// Package fuse enables writing FUSE file systems on FreeBSD, Linux, and OS X.
-//
-// On OS X, it requires OSXFUSE (http://osxfuse.github.com/).
-//
-// There are two approaches to writing a FUSE file system. The first is to speak
-// the low-level message protocol, reading from a Conn using ReadRequest and
-// writing using the various Respond methods. This approach is closest to
-// the actual interaction with the kernel and can be the simplest one in contexts
-// such as protocol translators.
-//
-// Servers of synthesized file systems tend to share common bookkeeping
-// abstracted away by the second approach, which is to call the Conn's
-// Serve method to serve the FUSE protocol using
-// an implementation of the service methods in the interfaces
-// FS (file system), Node (file or directory), and Handle (opened file or directory).
-// There are a daunting number of such methods that can be written,
-// but few are required.
-// The specific methods are described in the documentation for those interfaces.
-//
-// The hellofs subdirectory contains a simple illustration of the ServeFS approach.
-//
-// Service Methods
-//
-// The required and optional methods for the FS, Node, and Handle interfaces
-// have the general form
-//
-// Op(req *OpRequest, resp *OpResponse, intr Intr) Error
-//
-// where Op is the name of a FUSE operation. Op reads request parameters
-// from req and writes results to resp. An operation whose only result is
-// the error result omits the resp parameter. Multiple goroutines may call
-// service methods simultaneously; the methods being called are responsible
-// for appropriate synchronization.
-//
-// Interrupted Operations
-//
-// In some file systems, some operations
-// may take an undetermined amount of time. For example, a Read waiting for
-// a network message or a matching Write might wait indefinitely. If the request
-// is cancelled and no longer needed, the package will close intr, a chan struct{}.
-// Blocking operations should select on a receive from intr and attempt to
-// abort the operation early if the receive succeeds (meaning the channel is closed).
-// To indicate that the operation failed because it was aborted, return fuse.EINTR.
-//
-// If an operation does not block for an indefinite amount of time, the intr parameter
-// can be ignored.
-//
-// Authentication
-//
-// All requests types embed a Header, meaning that the method can inspect
-// req.Pid, req.Uid, and req.Gid as necessary to implement permission checking.
-// Alternately, XXX.
-//
-// Mount Options
-//
-// XXX
-//
-package fuse
-
-// BUG(rsc): The mount code for FreeBSD has not been written yet.
-
-import (
- "bytes"
- "errors"
- "fmt"
- "io"
- "log"
- "os"
- "runtime"
- "sync"
- "syscall"
- "time"
- "unsafe"
-)
-
-// A Conn represents a connection to a mounted FUSE file system.
-type Conn struct {
- fd int
- buf []byte
- wio sync.Mutex
-
- serveConn
-}
-
-// Mount mounts a new FUSE connection on the named directory
-// and returns a connection for reading and writing FUSE messages.
-func Mount(dir string) (*Conn, error) {
- // TODO(rsc): mount options (...string?)
- fd, errstr := mount(dir)
- if errstr != "" {
- return nil, errors.New(errstr)
- }
-
- return &Conn{fd: fd}, nil
-}
-
-// A Request represents a single FUSE request received from the kernel.
-// Use a type switch to determine the specific kind.
-// A request of unrecognized type will have concrete type *Header.
-type Request interface {
- // Hdr returns the Header associated with this request.
- Hdr() *Header
-
- // RespondError responds to the request with the given error.
- RespondError(Error)
-
- String() string
-
- // handle returns the HandleID for the request, or 0.
- handle() HandleID
-}
-
-// A RequestID identifies an active FUSE request.
-type RequestID uint64
-
-// A NodeID is a number identifying a directory or file.
-// It must be unique among IDs returned in LookupResponses
-// that have not yet been forgotten by ForgetRequests.
-type NodeID uint64
-
-// A HandleID is a number identifying an open directory or file.
-// It only needs to be unique while the directory or file is open.
-type HandleID uint64
-
-// The RootID identifies the root directory of a FUSE file system.
-const RootID NodeID = rootID
-
-// A Header describes the basic information sent in every request.
-type Header struct {
- Conn *Conn // connection this request was received on
- ID RequestID // unique ID for request
- Node NodeID // file or directory the request is about
- Uid uint32 // user ID of process making request
- Gid uint32 // group ID of process making request
- Pid uint32 // process ID of process making request
-}
-
-func (h *Header) String() string {
- return fmt.Sprintf("ID=%#x Node=%#x Uid=%d Gid=%d Pid=%d", h.ID, h.Node, h.Uid, h.Gid, h.Pid)
-}
-
-func (h *Header) Hdr() *Header {
- return h
-}
-
-func (h *Header) handle() HandleID {
- return 0
-}
-
-// An Error is a FUSE error.
-type Error interface {
- errno() int32
-}
-
-const (
- // ENOSYS indicates that the call is not supported.
- ENOSYS = Errno(syscall.ENOSYS)
-
- // ESTALE is used by Serve to respond to violations of the FUSE protocol.
- ESTALE = Errno(syscall.ESTALE)
-
- ENOENT = Errno(syscall.ENOENT)
- EIO = Errno(syscall.EIO)
- EPERM = Errno(syscall.EPERM)
-)
-
-type errno int
-
-func (e errno) errno() int32 {
- return int32(e)
-}
-
-// Errno implements Error using a syscall.Errno.
-type Errno syscall.Errno
-
-func (e Errno) errno() int32 {
- return int32(e)
-}
-
-func (e Errno) String() string {
- return syscall.Errno(e).Error()
-}
-
-func (h *Header) RespondError(err Error) {
- // FUSE uses negative errors!
- // TODO: File bug report against OSXFUSE: positive error causes kernel panic.
- out := &outHeader{Error: -err.errno(), Unique: uint64(h.ID)}
- h.Conn.respond(out, unsafe.Sizeof(*out))
-}
-
-var maxWrite = syscall.Getpagesize()
-var bufSize = 4096 + maxWrite
-
-// a message represents the bytes of a single FUSE message
-type message struct {
- conn *Conn
- buf []byte // all bytes
- hdr *inHeader // header
- off int // offset for reading additional fields
-}
-
-func newMessage(c *Conn) *message {
- m := &message{conn: c, buf: make([]byte, bufSize)}
- m.hdr = (*inHeader)(unsafe.Pointer(&m.buf[0]))
- return m
-}
-
-func (m *message) len() uintptr {
- return uintptr(len(m.buf) - m.off)
-}
-
-func (m *message) data() unsafe.Pointer {
- var p unsafe.Pointer
- if m.off < len(m.buf) {
- p = unsafe.Pointer(&m.buf[m.off])
- }
- return p
-}
-
-func (m *message) bytes() []byte {
- return m.buf[m.off:]
-}
-
-func (m *message) Header() Header {
- h := m.hdr
- return Header{Conn: m.conn, ID: RequestID(h.Unique), Node: NodeID(h.Nodeid), Uid: h.Uid, Gid: h.Gid, Pid: h.Pid}
-}
-
-// fileMode returns a Go os.FileMode from a Unix mode.
-func fileMode(unixMode uint32) os.FileMode {
- mode := os.FileMode(unixMode & 0777)
- switch unixMode & syscall.S_IFMT {
- case syscall.S_IFREG:
- // nothing
- case syscall.S_IFDIR:
- mode |= os.ModeDir
- case syscall.S_IFCHR:
- mode |= os.ModeCharDevice | os.ModeDevice
- case syscall.S_IFBLK:
- mode |= os.ModeDevice
- case syscall.S_IFIFO:
- mode |= os.ModeNamedPipe
- case syscall.S_IFLNK:
- mode |= os.ModeSymlink
- case syscall.S_IFSOCK:
- mode |= os.ModeSocket
- default:
- // no idea
- mode |= os.ModeDevice
- }
- if unixMode&syscall.S_ISUID != 0 {
- mode |= os.ModeSetuid
- }
- if unixMode&syscall.S_ISGID != 0 {
- mode |= os.ModeSetgid
- }
- return mode
-}
-
-func (c *Conn) ReadRequest() (Request, error) {
- // TODO: Some kind of buffer reuse.
- m := newMessage(c)
- n, err := syscall.Read(c.fd, m.buf)
- if err != nil && err != syscall.ENODEV {
- return nil, err
- }
- if n <= 0 {
- return nil, io.EOF
- }
- m.buf = m.buf[:n]
-
- if n < inHeaderSize {
- return nil, errors.New("fuse: message too short")
- }
-
- // FreeBSD FUSE sends a short length in the header
- // for FUSE_INIT even though the actual read length is correct.
- if n == inHeaderSize+initInSize && m.hdr.Opcode == opInit && m.hdr.Len < uint32(n) {
- m.hdr.Len = uint32(n)
- }
-
- // OSXFUSE sometimes sends the wrong m.hdr.Len in a FUSE_WRITE message.
- if m.hdr.Len < uint32(n) && m.hdr.Len >= uint32(unsafe.Sizeof(writeIn{})) && m.hdr.Opcode == opWrite {
- m.hdr.Len = uint32(n)
- }
-
- if m.hdr.Len != uint32(n) {
- return nil, fmt.Errorf("fuse: read %d opcode %d but expected %d", n, m.hdr.Opcode, m.hdr.Len)
- }
-
- m.off = inHeaderSize
-
- // Convert to data structures.
- // Do not trust kernel to hand us well-formed data.
- var req Request
- switch m.hdr.Opcode {
- default:
- println("No opcode", m.hdr.Opcode)
- goto unrecognized
-
- case opLookup:
- buf := m.bytes()
- n := len(buf)
- if n == 0 || buf[n-1] != '\x00' {
- goto corrupt
- }
- req = &LookupRequest{
- Header: m.Header(),
- Name: string(buf[:n-1]),
- }
-
- case opForget:
- in := (*forgetIn)(m.data())
- if m.len() < unsafe.Sizeof(*in) {
- goto corrupt
- }
- req = &ForgetRequest{
- Header: m.Header(),
- N: in.Nlookup,
- }
-
- case opGetattr:
- req = &GetattrRequest{
- Header: m.Header(),
- }
-
- case opSetattr:
- in := (*setattrIn)(m.data())
- if m.len() < unsafe.Sizeof(*in) {
- goto corrupt
- }
- req = &SetattrRequest{
- Header: m.Header(),
- Valid: SetattrValid(in.Valid),
- Handle: HandleID(in.Fh),
- Size: in.Size,
- Atime: time.Unix(int64(in.Atime), int64(in.AtimeNsec)),
- Mtime: time.Unix(int64(in.Mtime), int64(in.MtimeNsec)),
- Mode: fileMode(in.Mode),
- Uid: in.Uid,
- Gid: in.Gid,
- Bkuptime: in.BkupTime(),
- Chgtime: in.Chgtime(),
- Flags: in.Flags(),
- }
-
- case opReadlink:
- if len(m.bytes()) > 0 {
- goto corrupt
- }
- req = &ReadlinkRequest{
- Header: m.Header(),
- }
-
- case opSymlink:
- // m.bytes() is "newName\0target\0"
- names := m.bytes()
- if len(names) == 0 || names[len(names)-1] != 0 {
- goto corrupt
- }
- i := bytes.IndexByte(names, '\x00')
- if i < 0 {
- goto corrupt
- }
- newName, target := names[0:i], names[i+1:len(names)-1]
- req = &SymlinkRequest{
- Header: m.Header(),
- NewName: string(newName),
- Target: string(target),
- }
-
- case opLink:
- in := (*linkIn)(m.data())
- if m.len() < unsafe.Sizeof(*in) {
- goto corrupt
- }
- newName := m.bytes()[unsafe.Sizeof(*in):]
- if len(newName) < 2 || newName[len(newName)-1] != 0 {
- goto corrupt
- }
- newName = newName[:len(newName)-1]
- req = &LinkRequest{
- Header: m.Header(),
- OldNode: NodeID(in.Oldnodeid),
- NewName: string(newName),
- }
-
- case opMknod:
- in := (*mknodIn)(m.data())
- if m.len() < unsafe.Sizeof(*in) {
- goto corrupt
- }
- name := m.bytes()[unsafe.Sizeof(*in):]
- if len(name) < 2 || name[len(name)-1] != '\x00' {
- goto corrupt
- }
- name = name[:len(name)-1]
- req = &MknodRequest{
- Header: m.Header(),
- Mode: fileMode(in.Mode),
- Rdev: in.Rdev,
- Name: string(name),
- }
-
- case opMkdir:
- in := (*mkdirIn)(m.data())
- if m.len() < unsafe.Sizeof(*in) {
- goto corrupt
- }
- name := m.bytes()[unsafe.Sizeof(*in):]
- i := bytes.IndexByte(name, '\x00')
- if i < 0 {
- goto corrupt
- }
- req = &MkdirRequest{
- Header: m.Header(),
- Name: string(name[:i]),
- Mode: fileMode(in.Mode) | os.ModeDir,
- }
-
- case opUnlink, opRmdir:
- buf := m.bytes()
- n := len(buf)
- if n == 0 || buf[n-1] != '\x00' {
- goto corrupt
- }
- req = &RemoveRequest{
- Header: m.Header(),
- Name: string(buf[:n-1]),
- Dir: m.hdr.Opcode == opRmdir,
- }
-
- case opRename:
- in := (*renameIn)(m.data())
- if m.len() < unsafe.Sizeof(*in) {
- goto corrupt
- }
- newDirNodeID := NodeID(in.Newdir)
- oldNew := m.bytes()[unsafe.Sizeof(*in):]
- // oldNew should be "old\x00new\x00"
- if len(oldNew) < 4 {
- goto corrupt
- }
- if oldNew[len(oldNew)-1] != '\x00' {
- goto corrupt
- }
- i := bytes.IndexByte(oldNew, '\x00')
- if i < 0 {
- goto corrupt
- }
- oldName, newName := string(oldNew[:i]), string(oldNew[i+1:len(oldNew)-1])
- // log.Printf("RENAME: newDirNode = %d; old = %q, new = %q", newDirNodeID, oldName, newName)
- req = &RenameRequest{
- Header: m.Header(),
- NewDir: newDirNodeID,
- OldName: oldName,
- NewName: newName,
- }
-
- case opOpendir, opOpen:
- in := (*openIn)(m.data())
- if m.len() < unsafe.Sizeof(*in) {
- goto corrupt
- }
- req = &OpenRequest{
- Header: m.Header(),
- Dir: m.hdr.Opcode == opOpendir,
- Flags: in.Flags,
- Mode: fileMode(in.Mode),
- }
-
- case opRead, opReaddir:
- in := (*readIn)(m.data())
- if m.len() < unsafe.Sizeof(*in) {
- goto corrupt
- }
- req = &ReadRequest{
- Header: m.Header(),
- Dir: m.hdr.Opcode == opReaddir,
- Handle: HandleID(in.Fh),
- Offset: int64(in.Offset),
- Size: int(in.Size),
- }
-
- case opWrite:
- in := (*writeIn)(m.data())
- if m.len() < unsafe.Sizeof(*in) {
- goto corrupt
- }
- r := &WriteRequest{
- Header: m.Header(),
- Handle: HandleID(in.Fh),
- Offset: int64(in.Offset),
- Flags: WriteFlags(in.WriteFlags),
- }
- buf := m.bytes()[unsafe.Sizeof(*in):]
- if uint32(len(buf)) < in.Size {
- goto corrupt
- }
- r.Data = buf
- req = r
-
- case opStatfs:
- req = &StatfsRequest{
- Header: m.Header(),
- }
-
- case opRelease, opReleasedir:
- in := (*releaseIn)(m.data())
- if m.len() < unsafe.Sizeof(*in) {
- goto corrupt
- }
- req = &ReleaseRequest{
- Header: m.Header(),
- Dir: m.hdr.Opcode == opReleasedir,
- Handle: HandleID(in.Fh),
- Flags: in.Flags,
- ReleaseFlags: ReleaseFlags(in.ReleaseFlags),
- LockOwner: in.LockOwner,
- }
-
- case opFsync:
- in := (*fsyncIn)(m.data())
- if m.len() < unsafe.Sizeof(*in) {
- goto corrupt
- }
- req = &FsyncRequest{
- Header: m.Header(),
- Handle: HandleID(in.Fh),
- Flags: in.FsyncFlags,
- }
-
- case opSetxattr:
- var size uint32
- var r *SetxattrRequest
- if runtime.GOOS == "darwin" {
- in := (*setxattrInOSX)(m.data())
- if m.len() < unsafe.Sizeof(*in) {
- goto corrupt
- }
- r = &SetxattrRequest{
- Flags: in.Flags,
- Position: in.Position,
- }
- size = in.Size
- m.off += int(unsafe.Sizeof(*in))
- } else {
- in := (*setxattrIn)(m.data())
- if m.len() < unsafe.Sizeof(*in) {
- goto corrupt
- }
- r = &SetxattrRequest{}
- size = in.Size
- m.off += int(unsafe.Sizeof(*in))
- }
- r.Header = m.Header()
- name := m.bytes()
- i := bytes.IndexByte(name, '\x00')
- if i < 0 {
- goto corrupt
- }
- r.Name = string(name[:i])
- r.Xattr = name[i+1:]
- if uint32(len(r.Xattr)) < size {
- goto corrupt
- }
- r.Xattr = r.Xattr[:size]
- req = r
-
- case opGetxattr:
- if runtime.GOOS == "darwin" {
- in := (*getxattrInOSX)(m.data())
- if m.len() < unsafe.Sizeof(*in) {
- goto corrupt
- }
- req = &GetxattrRequest{
- Header: m.Header(),
- Size: in.Size,
- Position: in.Position,
- }
- } else {
- in := (*getxattrIn)(m.data())
- if m.len() < unsafe.Sizeof(*in) {
- goto corrupt
- }
- req = &GetxattrRequest{
- Header: m.Header(),
- Size: in.Size,
- }
- }
-
- case opListxattr:
- if runtime.GOOS == "darwin" {
- in := (*getxattrInOSX)(m.data())
- if m.len() < unsafe.Sizeof(*in) {
- goto corrupt
- }
- req = &ListxattrRequest{
- Header: m.Header(),
- Size: in.Size,
- Position: in.Position,
- }
- } else {
- in := (*getxattrIn)(m.data())
- if m.len() < unsafe.Sizeof(*in) {
- goto corrupt
- }
- req = &ListxattrRequest{
- Header: m.Header(),
- Size: in.Size,
- }
- }
-
- case opRemovexattr:
- buf := m.bytes()
- n := len(buf)
- if n == 0 || buf[n-1] != '\x00' {
- goto corrupt
- }
- req = &RemovexattrRequest{
- Header: m.Header(),
- Name: string(buf[:n-1]),
- }
-
- case opFlush:
- in := (*flushIn)(m.data())
- if m.len() < unsafe.Sizeof(*in) {
- goto corrupt
- }
- req = &FlushRequest{
- Header: m.Header(),
- Handle: HandleID(in.Fh),
- Flags: in.FlushFlags,
- LockOwner: in.LockOwner,
- }
-
- case opInit:
- in := (*initIn)(m.data())
- if m.len() < unsafe.Sizeof(*in) {
- goto corrupt
- }
- req = &InitRequest{
- Header: m.Header(),
- Major: in.Major,
- Minor: in.Minor,
- MaxReadahead: in.MaxReadahead,
- Flags: InitFlags(in.Flags),
- }
-
- case opFsyncdir:
- panic("opFsyncdir")
- case opGetlk:
- panic("opGetlk")
- case opSetlk:
- panic("opSetlk")
- case opSetlkw:
- panic("opSetlkw")
-
- case opAccess:
- in := (*accessIn)(m.data())
- if m.len() < unsafe.Sizeof(*in) {
- goto corrupt
- }
- req = &AccessRequest{
- Header: m.Header(),
- Mask: in.Mask,
- }
-
- case opCreate:
- in := (*openIn)(m.data())
- if m.len() < unsafe.Sizeof(*in) {
- goto corrupt
- }
- name := m.bytes()[unsafe.Sizeof(*in):]
- i := bytes.IndexByte(name, '\x00')
- if i < 0 {
- goto corrupt
- }
- req = &CreateRequest{
- Header: m.Header(),
- Flags: in.Flags,
- Mode: fileMode(in.Mode),
- Name: string(name[:i]),
- }
-
- case opInterrupt:
- panic("opInterrupt")
- case opBmap:
- panic("opBmap")
-
- case opDestroy:
- req = &DestroyRequest{
- Header: m.Header(),
- }
-
- // OS X
- case opSetvolname:
- panic("opSetvolname")
- case opGetxtimes:
- panic("opGetxtimes")
- case opExchange:
- panic("opExchange")
- }
-
- return req, nil
-
-corrupt:
- println("malformed message")
- return nil, fmt.Errorf("fuse: malformed message")
-
-unrecognized:
- // Unrecognized message.
- // Assume higher-level code will send a "no idea what you mean" error.
- h := m.Header()
- return &h, nil
-}
-
-func (c *Conn) respond(out *outHeader, n uintptr) {
- c.wio.Lock()
- defer c.wio.Unlock()
- out.Len = uint32(n)
- msg := (*[1 << 30]byte)(unsafe.Pointer(out))[:n]
- nn, err := syscall.Write(c.fd, msg)
- if nn != len(msg) || err != nil {
- log.Printf("RESPOND WRITE: %d %v", nn, err)
- log.Printf("with stack: %s", stack())
- }
-}
-
-func (c *Conn) respondData(out *outHeader, n uintptr, data []byte) {
- c.wio.Lock()
- defer c.wio.Unlock()
- // TODO: use writev
- out.Len = uint32(n + uintptr(len(data)))
- msg := make([]byte, out.Len)
- copy(msg, (*[1 << 30]byte)(unsafe.Pointer(out))[:n])
- copy(msg[n:], data)
- syscall.Write(c.fd, msg)
-}
-
-// An InitRequest is the first request sent on a FUSE file system.
-type InitRequest struct {
- Header
- Major uint32
- Minor uint32
- MaxReadahead uint32
- Flags InitFlags
-}
-
-func (r *InitRequest) String() string {
- return fmt.Sprintf("Init [%s] %d.%d ra=%d fl=%v", &r.Header, r.Major, r.Minor, r.MaxReadahead, r.Flags)
-}
-
-// An InitResponse is the response to an InitRequest.
-type InitResponse struct {
- MaxReadahead uint32
- Flags InitFlags
- MaxWrite uint32
-}
-
-func (r *InitResponse) String() string {
- return fmt.Sprintf("Init %+v", *r)
-}
-
-// Respond replies to the request with the given response.
-func (r *InitRequest) Respond(resp *InitResponse) {
- out := &initOut{
- outHeader: outHeader{Unique: uint64(r.ID)},
- Major: kernelVersion,
- Minor: kernelMinorVersion,
- MaxReadahead: resp.MaxReadahead,
- Flags: uint32(resp.Flags),
- MaxWrite: resp.MaxWrite,
- }
- r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
-}
-
-// A StatfsRequest requests information about the mounted file system.
-type StatfsRequest struct {
- Header
-}
-
-func (r *StatfsRequest) String() string {
- return fmt.Sprintf("Statfs [%s]\n", &r.Header)
-}
-
-// Respond replies to the request with the given response.
-func (r *StatfsRequest) Respond(resp *StatfsResponse) {
- out := &statfsOut{
- outHeader: outHeader{Unique: uint64(r.ID)},
- St: kstatfs{
- Blocks: resp.Blocks,
- Bfree: resp.Bfree,
- Bavail: resp.Bavail,
- Files: resp.Files,
- Bsize: resp.Bsize,
- Namelen: resp.Namelen,
- Frsize: resp.Frsize,
- },
- }
- r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
-}
-
-// A StatfsResponse is the response to a StatfsRequest.
-type StatfsResponse struct {
- Blocks uint64 // Total data blocks in file system.
- Bfree uint64 // Free blocks in file system.
- Bavail uint64 // Free blocks in file system if you're not root.
- Files uint64 // Total files in file system.
- Ffree uint64 // Free files in file system.
- Bsize uint32 // Block size
- Namelen uint32 // Maximum file name length?
- Frsize uint32 // ?
-}
-
-func (r *StatfsResponse) String() string {
- return fmt.Sprintf("Statfs %+v", *r)
-}
-
-// An AccessRequest asks whether the file can be accessed
-// for the purpose specified by the mask.
-type AccessRequest struct {
- Header
- Mask uint32
-}
-
-func (r *AccessRequest) String() string {
- return fmt.Sprintf("Access [%s] mask=%#x", &r.Header, r.Mask)
-}
-
-// Respond replies to the request indicating that access is allowed.
-// To deny access, use RespondError.
-func (r *AccessRequest) Respond() {
- out := &outHeader{Unique: uint64(r.ID)}
- r.Conn.respond(out, unsafe.Sizeof(*out))
-}
-
-// An Attr is the metadata for a single file or directory.
-type Attr struct {
- Inode uint64 // inode number
- Size uint64 // size in bytes
- Blocks uint64 // size in blocks
- Atime time.Time // time of last access
- Mtime time.Time // time of last modification
- Ctime time.Time // time of last inode change
- Crtime time.Time // time of creation (OS X only)
- Mode os.FileMode // file mode
- Nlink uint32 // number of links
- Uid uint32 // owner uid
- Gid uint32 // group gid
- Rdev uint32 // device numbers
- Flags uint32 // chflags(2) flags (OS X only)
-}
-
-func unix(t time.Time) (sec uint64, nsec uint32) {
- nano := t.UnixNano()
- sec = uint64(nano / 1e9)
- nsec = uint32(nano % 1e9)
- return
-}
-
-func (a *Attr) attr() (out attr) {
- out.Ino = a.Inode
- out.Size = a.Size
- out.Blocks = a.Blocks
- out.Atime, out.AtimeNsec = unix(a.Atime)
- out.Mtime, out.MtimeNsec = unix(a.Mtime)
- out.Ctime, out.CtimeNsec = unix(a.Ctime)
- out.SetCrtime(unix(a.Crtime))
- out.Mode = uint32(a.Mode) & 0777
- switch {
- default:
- out.Mode |= syscall.S_IFREG
- case a.Mode&os.ModeDir != 0:
- out.Mode |= syscall.S_IFDIR
- case a.Mode&os.ModeDevice != 0:
- if a.Mode&os.ModeCharDevice != 0 {
- out.Mode |= syscall.S_IFCHR
- } else {
- out.Mode |= syscall.S_IFBLK
- }
- case a.Mode&os.ModeNamedPipe != 0:
- out.Mode |= syscall.S_IFIFO
- case a.Mode&os.ModeSymlink != 0:
- out.Mode |= syscall.S_IFLNK
- case a.Mode&os.ModeSocket != 0:
- out.Mode |= syscall.S_IFSOCK
- }
- if a.Mode&os.ModeSetuid != 0 {
- out.Mode |= syscall.S_ISUID
- }
- if a.Mode&os.ModeSetgid != 0 {
- out.Mode |= syscall.S_ISGID
- }
- out.Nlink = a.Nlink
- if out.Nlink < 1 {
- out.Nlink = 1
- }
- out.Uid = a.Uid
- out.Gid = a.Gid
- out.Rdev = a.Rdev
- out.SetFlags(a.Flags)
-
- return
-}
-
-// A GetattrRequest asks for the metadata for the file denoted by r.Node.
-type GetattrRequest struct {
- Header
-}
-
-func (r *GetattrRequest) String() string {
- return fmt.Sprintf("Getattr [%s]", &r.Header)
-}
-
-// Respond replies to the request with the given response.
-func (r *GetattrRequest) Respond(resp *GetattrResponse) {
- out := &attrOut{
- outHeader: outHeader{Unique: uint64(r.ID)},
- AttrValid: uint64(resp.AttrValid / time.Second),
- AttrValidNsec: uint32(resp.AttrValid % time.Second / time.Nanosecond),
- Attr: resp.Attr.attr(),
- }
- r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
-}
-
-// A GetattrResponse is the response to a GetattrRequest.
-type GetattrResponse struct {
- AttrValid time.Duration // how long Attr can be cached
- Attr Attr // file attributes
-}
-
-func (r *GetattrResponse) String() string {
- return fmt.Sprintf("Getattr %+v", *r)
-}
-
-// A GetxattrRequest asks for the extended attributes associated with r.Node.
-type GetxattrRequest struct {
- Header
- Size uint32 // maximum size to return
- Position uint32 // offset within extended attributes
-}
-
-func (r *GetxattrRequest) String() string {
- return fmt.Sprintf("Getxattr [%s] %d @%d", &r.Header, r.Size, r.Position)
-}
-
-// Respond replies to the request with the given response.
-func (r *GetxattrRequest) Respond(resp *GetxattrResponse) {
- out := &getxattrOut{
- outHeader: outHeader{Unique: uint64(r.ID)},
- Size: uint32(len(resp.Xattr)),
- }
- r.Conn.respondData(&out.outHeader, unsafe.Sizeof(*out), resp.Xattr)
-}
-
-// A GetxattrResponse is the response to a GetxattrRequest.
-type GetxattrResponse struct {
- Xattr []byte
-}
-
-func (r *GetxattrResponse) String() string {
- return fmt.Sprintf("Getxattr %x", r.Xattr)
-}
-
-// A ListxattrRequest asks to list the extended attributes associated with r.Node.
-type ListxattrRequest struct {
- Header
- Size uint32 // maximum size to return
- Position uint32 // offset within attribute list
-}
-
-func (r *ListxattrRequest) String() string {
- return fmt.Sprintf("Listxattr [%s] %d @%d", &r.Header, r.Size, r.Position)
-}
-
-// Respond replies to the request with the given response.
-func (r *ListxattrRequest) Respond(resp *ListxattrResponse) {
- out := &getxattrOut{
- outHeader: outHeader{Unique: uint64(r.ID)},
- Size: uint32(len(resp.Xattr)),
- }
- r.Conn.respondData(&out.outHeader, unsafe.Sizeof(*out), resp.Xattr)
-}
-
-// A ListxattrResponse is the response to a ListxattrRequest.
-type ListxattrResponse struct {
- Xattr []byte
-}
-
-func (r *ListxattrResponse) String() string {
- return fmt.Sprintf("Listxattr %x", r.Xattr)
-}
-
-// A RemovexattrRequest asks to remove an extended attribute associated with r.Node.
-type RemovexattrRequest struct {
- Header
- Name string // name of extended attribute
-}
-
-func (r *RemovexattrRequest) String() string {
- return fmt.Sprintf("Removexattr [%s] %q", &r.Header, r.Name)
-}
-
-// Respond replies to the request, indicating that the attribute was removed.
-func (r *RemovexattrRequest) Respond() {
- out := &outHeader{Unique: uint64(r.ID)}
- r.Conn.respond(out, unsafe.Sizeof(*out))
-}
-
-// A SetxattrRequest asks to set an extended attribute associated with a file.
-type SetxattrRequest struct {
- Header
- Flags uint32
- Position uint32 // OS X only
- Name string
- Xattr []byte
-}
-
-func (r *SetxattrRequest) String() string {
- return fmt.Sprintf("Setxattr [%s] %q %x fl=%v @%#x", &r.Header, r.Name, r.Xattr, r.Flags, r.Position)
-}
-
-// Respond replies to the request, indicating that the extended attribute was set.
-func (r *SetxattrRequest) Respond() {
- out := &outHeader{Unique: uint64(r.ID)}
- r.Conn.respond(out, unsafe.Sizeof(*out))
-}
-
-// A LookupRequest asks to look up the given name in the directory named by r.Node.
-type LookupRequest struct {
- Header
- Name string
-}
-
-func (r *LookupRequest) String() string {
- return fmt.Sprintf("Lookup [%s] %q", &r.Header, r.Name)
-}
-
-// Respond replies to the request with the given response.
-func (r *LookupRequest) Respond(resp *LookupResponse) {
- out := &entryOut{
- outHeader: outHeader{Unique: uint64(r.ID)},
- Nodeid: uint64(resp.Node),
- Generation: resp.Generation,
- EntryValid: uint64(resp.EntryValid / time.Second),
- EntryValidNsec: uint32(resp.EntryValid % time.Second / time.Nanosecond),
- AttrValid: uint64(resp.AttrValid / time.Second),
- AttrValidNsec: uint32(resp.AttrValid % time.Second / time.Nanosecond),
- Attr: resp.Attr.attr(),
- }
- r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
-}
-
-// A LookupResponse is the response to a LookupRequest.
-type LookupResponse struct {
- Node NodeID
- Generation uint64
- EntryValid time.Duration
- AttrValid time.Duration
- Attr Attr
-}
-
-func (r *LookupResponse) String() string {
- return fmt.Sprintf("Lookup %+v", *r)
-}
-
-// An OpenRequest asks to open a file or directory
-type OpenRequest struct {
- Header
- Dir bool // is this Opendir?
- Flags uint32
- Mode os.FileMode
-}
-
-func (r *OpenRequest) String() string {
- return fmt.Sprintf("Open [%s] dir=%v fl=%v mode=%v", &r.Header, r.Dir, r.Flags, r.Mode)
-}
-
-// Respond replies to the request with the given response.
-func (r *OpenRequest) Respond(resp *OpenResponse) {
- out := &openOut{
- outHeader: outHeader{Unique: uint64(r.ID)},
- Fh: uint64(resp.Handle),
- OpenFlags: uint32(resp.Flags),
- }
- r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
-}
-
-// A OpenResponse is the response to a OpenRequest.
-type OpenResponse struct {
- Handle HandleID
- Flags OpenFlags
-}
-
-func (r *OpenResponse) String() string {
- return fmt.Sprintf("Open %+v", *r)
-}
-
-// A CreateRequest asks to create and open a file (not a directory).
-type CreateRequest struct {
- Header
- Name string
- Flags uint32
- Mode os.FileMode
-}
-
-func (r *CreateRequest) String() string {
- return fmt.Sprintf("Create [%s] %q fl=%v mode=%v", &r.Header, r.Name, r.Flags, r.Mode)
-}
-
-// Respond replies to the request with the given response.
-func (r *CreateRequest) Respond(resp *CreateResponse) {
- out := &createOut{
- outHeader: outHeader{Unique: uint64(r.ID)},
-
- Nodeid: uint64(resp.Node),
- Generation: resp.Generation,
- EntryValid: uint64(resp.EntryValid / time.Second),
- EntryValidNsec: uint32(resp.EntryValid % time.Second / time.Nanosecond),
- AttrValid: uint64(resp.AttrValid / time.Second),
- AttrValidNsec: uint32(resp.AttrValid % time.Second / time.Nanosecond),
- Attr: resp.Attr.attr(),
-
- Fh: uint64(resp.Handle),
- OpenFlags: uint32(resp.Flags),
- }
- r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
-}
-
-// A CreateResponse is the response to a CreateRequest.
-// It describes the created node and opened handle.
-type CreateResponse struct {
- LookupResponse
- OpenResponse
-}
-
-func (r *CreateResponse) String() string {
- return fmt.Sprintf("Create %+v", *r)
-}
-
-// A MkdirRequest asks to create (but not open) a directory.
-type MkdirRequest struct {
- Header
- Name string
- Mode os.FileMode
-}
-
-func (r *MkdirRequest) String() string {
- return fmt.Sprintf("Mkdir [%s] %q mode=%v", &r.Header, r.Name, r.Mode)
-}
-
-// Respond replies to the request with the given response.
-func (r *MkdirRequest) Respond(resp *MkdirResponse) {
- out := &entryOut{
- outHeader: outHeader{Unique: uint64(r.ID)},
- Nodeid: uint64(resp.Node),
- Generation: resp.Generation,
- EntryValid: uint64(resp.EntryValid / time.Second),
- EntryValidNsec: uint32(resp.EntryValid % time.Second / time.Nanosecond),
- AttrValid: uint64(resp.AttrValid / time.Second),
- AttrValidNsec: uint32(resp.AttrValid % time.Second / time.Nanosecond),
- Attr: resp.Attr.attr(),
- }
- r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
-}
-
-// A MkdirResponse is the response to a MkdirRequest.
-type MkdirResponse struct {
- LookupResponse
-}
-
-func (r *MkdirResponse) String() string {
- return fmt.Sprintf("Mkdir %+v", *r)
-}
-
-// A ReadRequest asks to read from an open file.
-type ReadRequest struct {
- Header
- Dir bool // is this Readdir?
- Handle HandleID
- Offset int64
- Size int
-}
-
-func (r *ReadRequest) handle() HandleID {
- return r.Handle
-}
-
-func (r *ReadRequest) String() string {
- return fmt.Sprintf("Read [%s] %#x %d @%#x dir=%v", &r.Header, r.Handle, r.Size, r.Offset, r.Dir)
-}
-
-// Respond replies to the request with the given response.
-func (r *ReadRequest) Respond(resp *ReadResponse) {
- out := &outHeader{Unique: uint64(r.ID)}
- r.Conn.respondData(out, unsafe.Sizeof(*out), resp.Data)
-}
-
-// A ReadResponse is the response to a ReadRequest.
-type ReadResponse struct {
- Data []byte
-}
-
-func (r *ReadResponse) String() string {
- return fmt.Sprintf("Read %x", r.Data)
-}
-
-// A ReleaseRequest asks to release (close) an open file handle.
-type ReleaseRequest struct {
- Header
- Dir bool // is this Releasedir?
- Handle HandleID
- Flags uint32 // flags from OpenRequest
- ReleaseFlags ReleaseFlags
- LockOwner uint32
-}
-
-func (r *ReleaseRequest) handle() HandleID {
- return r.Handle
-}
-
-func (r *ReleaseRequest) String() string {
- return fmt.Sprintf("Release [%s] %#x fl=%v rfl=%v owner=%#x", &r.Header, r.Handle, r.Flags, r.ReleaseFlags, r.LockOwner)
-}
-
-// Respond replies to the request, indicating that the handle has been released.
-func (r *ReleaseRequest) Respond() {
- out := &outHeader{Unique: uint64(r.ID)}
- r.Conn.respond(out, unsafe.Sizeof(*out))
-}
-
-// A DestroyRequest is sent by the kernel when unmounting the file system.
-// No more requests will be received after this one, but it should still be
-// responded to.
-type DestroyRequest struct {
- Header
-}
-
-func (r *DestroyRequest) String() string {
- return fmt.Sprintf("Destroy [%s]", &r.Header)
-}
-
-// Respond replies to the request.
-func (r *DestroyRequest) Respond() {
- out := &outHeader{Unique: uint64(r.ID)}
- r.Conn.respond(out, unsafe.Sizeof(*out))
-}
-
-// A ForgetRequest is sent by the kernel when forgetting about r.Node
-// as returned by r.N lookup requests.
-type ForgetRequest struct {
- Header
- N uint64
-}
-
-func (r *ForgetRequest) String() string {
- return fmt.Sprintf("Forget [%s] %d", &r.Header, r.N)
-}
-
-// Respond replies to the request, indicating that the forgetfulness has been recorded.
-func (r *ForgetRequest) Respond() {
- // Don't reply to forget messages.
-}
-
-// A Dirent represents a single directory entry.
-type Dirent struct {
- Inode uint64 // inode this entry names
- Type uint32 // ?
- Name string // name of entry
-}
-
-// AppendDirent appends the encoded form of a directory entry to data
-// and returns the resulting slice.
-func AppendDirent(data []byte, dir Dirent) []byte {
- de := dirent{
- Ino: dir.Inode,
- Namelen: uint32(len(dir.Name)),
- Type: dir.Type,
- }
- de.Off = uint64(len(data) + direntSize + (len(dir.Name)+7)&^7)
- data = append(data, (*[direntSize]byte)(unsafe.Pointer(&de))[:]...)
- data = append(data, dir.Name...)
- n := direntSize + uintptr(len(dir.Name))
- if n%8 != 0 {
- var pad [8]byte
- data = append(data, pad[:8-n%8]...)
- }
- return data
-}
-
-// A WriteRequest asks to write to an open file.
-type WriteRequest struct {
- Header
- Handle HandleID
- Offset int64
- Data []byte
- Flags WriteFlags
-}
-
-func (r *WriteRequest) String() string {
- return fmt.Sprintf("Write [%s] %#x %d @%d fl=%v", &r.Header, r.Handle, len(r.Data), r.Offset, r.Flags)
-}
-
-// Respond replies to the request with the given response.
-func (r *WriteRequest) Respond(resp *WriteResponse) {
- out := &writeOut{
- outHeader: outHeader{Unique: uint64(r.ID)},
- Size: uint32(resp.Size),
- }
- r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
-}
-
-func (r *WriteRequest) handle() HandleID {
- return r.Handle
-}
-
-// A WriteResponse replies to a write indicating how many bytes were written.
-type WriteResponse struct {
- Size int
-}
-
-func (r *WriteResponse) String() string {
- return fmt.Sprintf("Write %+v", *r)
-}
-
-// A SetattrRequest asks to change one or more attributes associated with a file,
-// as indicated by Valid.
-type SetattrRequest struct {
- Header
- Valid SetattrValid
- Handle HandleID
- Size uint64
- Atime time.Time
- Mtime time.Time
- Mode os.FileMode
- Uid uint32
- Gid uint32
-
- // OS X only
- Bkuptime time.Time
- Chgtime time.Time
- Crtime time.Time
- Flags uint32 // see chflags(2)
-}
-
-func (r *SetattrRequest) String() string {
- var buf bytes.Buffer
- fmt.Fprintf(&buf, "Setattr [%s]", &r.Header)
- if r.Valid.Mode() {
- fmt.Fprintf(&buf, " mode=%v", r.Mode)
- }
- if r.Valid.Uid() {
- fmt.Fprintf(&buf, " uid=%d", r.Uid)
- }
- if r.Valid.Gid() {
- fmt.Fprintf(&buf, " gid=%d", r.Gid)
- }
- if r.Valid.Size() {
- fmt.Fprintf(&buf, " size=%d", r.Size)
- }
- if r.Valid.Atime() {
- fmt.Fprintf(&buf, " atime=%v", r.Atime)
- }
- if r.Valid.Mtime() {
- fmt.Fprintf(&buf, " mtime=%v", r.Mtime)
- }
- if r.Valid.Handle() {
- fmt.Fprintf(&buf, " handle=%#x", r.Handle)
- } else {
- fmt.Fprintf(&buf, " handle=INVALID-%#x", r.Handle)
- }
- if r.Valid.Crtime() {
- fmt.Fprintf(&buf, " crtime=%v", r.Crtime)
- }
- if r.Valid.Chgtime() {
- fmt.Fprintf(&buf, " chgtime=%v", r.Chgtime)
- }
- if r.Valid.Bkuptime() {
- fmt.Fprintf(&buf, " bkuptime=%v", r.Bkuptime)
- }
- if r.Valid.Flags() {
- fmt.Fprintf(&buf, " flags=%#x", r.Flags)
- }
- return buf.String()
-}
-
-func (r *SetattrRequest) handle() HandleID {
- if r.Valid.Handle() {
- return r.Handle
- }
- return 0
-}
-
-// Respond replies to the request with the given response,
-// giving the updated attributes.
-func (r *SetattrRequest) Respond(resp *SetattrResponse) {
- out := &attrOut{
- outHeader: outHeader{Unique: uint64(r.ID)},
- AttrValid: uint64(resp.AttrValid / time.Second),
- AttrValidNsec: uint32(resp.AttrValid % time.Second / time.Nanosecond),
- Attr: resp.Attr.attr(),
- }
- r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
-}
-
-// A SetattrResponse is the response to a SetattrRequest.
-type SetattrResponse struct {
- AttrValid time.Duration // how long Attr can be cached
- Attr Attr // file attributes
-}
-
-func (r *SetattrResponse) String() string {
- return fmt.Sprintf("Setattr %+v", *r)
-}
-
-// A FlushRequest asks for the current state of an open file to be flushed
-// to storage, as when a file descriptor is being closed. A single opened Handle
-// may receive multiple FlushRequests over its lifetime.
-type FlushRequest struct {
- Header
- Handle HandleID
- Flags uint32
- LockOwner uint64
-}
-
-func (r *FlushRequest) String() string {
- return fmt.Sprintf("Flush [%s] %#x fl=%#x lk=%#x", &r.Header, r.Handle, r.Flags, r.LockOwner)
-}
-
-func (r *FlushRequest) handle() HandleID {
- return r.Handle
-}
-
-// Respond replies to the request, indicating that the flush succeeded.
-func (r *FlushRequest) Respond() {
- out := &outHeader{Unique: uint64(r.ID)}
- r.Conn.respond(out, unsafe.Sizeof(*out))
-}
-
-// A RemoveRequest asks to remove a file or directory.
-type RemoveRequest struct {
- Header
- Name string // name of extended attribute
- Dir bool // is this rmdir?
-}
-
-func (r *RemoveRequest) String() string {
- return fmt.Sprintf("Remove [%s] %q dir=%v", &r.Header, r.Name, r.Dir)
-}
-
-// Respond replies to the request, indicating that the file was removed.
-func (r *RemoveRequest) Respond() {
- out := &outHeader{Unique: uint64(r.ID)}
- r.Conn.respond(out, unsafe.Sizeof(*out))
-}
-
-// A SymlinkRequest is a request to create a symlink making NewName point to Target.
-type SymlinkRequest struct {
- Header
- NewName, Target string
-}
-
-func (r *SymlinkRequest) String() string {
- return fmt.Sprintf("Symlink [%s] from %q to target %q", &r.Header, r.NewName, r.Target)
-}
-
-func (r *SymlinkRequest) handle() HandleID {
- return 0
-}
-
-// Respond replies to the request, indicating that the symlink was created.
-func (r *SymlinkRequest) Respond(resp *SymlinkResponse) {
- out := &entryOut{
- outHeader: outHeader{Unique: uint64(r.ID)},
- Nodeid: uint64(resp.Node),
- Generation: resp.Generation,
- EntryValid: uint64(resp.EntryValid / time.Second),
- EntryValidNsec: uint32(resp.EntryValid % time.Second / time.Nanosecond),
- AttrValid: uint64(resp.AttrValid / time.Second),
- AttrValidNsec: uint32(resp.AttrValid % time.Second / time.Nanosecond),
- Attr: resp.Attr.attr(),
- }
- r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
-}
-
-// A SymlinkResponse is the response to a SymlinkRequest.
-type SymlinkResponse struct {
- LookupResponse
-}
-
-// A ReadlinkRequest is a request to read a symlink's target.
-type ReadlinkRequest struct {
- Header
-}
-
-func (r *ReadlinkRequest) String() string {
- return fmt.Sprintf("Readlink [%s]", &r.Header)
-}
-
-func (r *ReadlinkRequest) handle() HandleID {
- return 0
-}
-
-func (r *ReadlinkRequest) Respond(target string) {
- out := &outHeader{Unique: uint64(r.ID)}
- r.Conn.respondData(out, unsafe.Sizeof(*out), []byte(target))
-}
-
-// A LinkRequest is a request to create a hard link.
-type LinkRequest struct {
- Header
- OldNode NodeID
- NewName string
-}
-
-func (r *LinkRequest) Respond(resp *LookupResponse) {
- out := &entryOut{
- outHeader: outHeader{Unique: uint64(r.ID)},
- Nodeid: uint64(resp.Node),
- Generation: resp.Generation,
- EntryValid: uint64(resp.EntryValid / time.Second),
- EntryValidNsec: uint32(resp.EntryValid % time.Second / time.Nanosecond),
- AttrValid: uint64(resp.AttrValid / time.Second),
- AttrValidNsec: uint32(resp.AttrValid % time.Second / time.Nanosecond),
- Attr: resp.Attr.attr(),
- }
- r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
-}
-
-// A RenameRequest is a request to rename a file.
-type RenameRequest struct {
- Header
- NewDir NodeID
- OldName, NewName string
-}
-
-func (r *RenameRequest) handle() HandleID {
- return 0
-}
-
-func (r *RenameRequest) String() string {
- return fmt.Sprintf("Rename [%s] from %q to dirnode %d %q", &r.Header, r.OldName, r.NewDir, r.NewName)
-}
-
-func (r *RenameRequest) Respond() {
- out := &outHeader{Unique: uint64(r.ID)}
- r.Conn.respond(out, unsafe.Sizeof(*out))
-}
-
-type MknodRequest struct {
- Header
- Name string
- Mode os.FileMode
- Rdev uint32
-}
-
-func (r *MknodRequest) String() string {
- return fmt.Sprintf("Mknod [%s] Name %q mode %v rdev %d", &r.Header, r.Name, r.Mode, r.Rdev)
-}
-
-func (r *MknodRequest) Respond(resp *LookupResponse) {
- out := &entryOut{
- outHeader: outHeader{Unique: uint64(r.ID)},
- Nodeid: uint64(resp.Node),
- Generation: resp.Generation,
- EntryValid: uint64(resp.EntryValid / time.Second),
- EntryValidNsec: uint32(resp.EntryValid % time.Second / time.Nanosecond),
- AttrValid: uint64(resp.AttrValid / time.Second),
- AttrValidNsec: uint32(resp.AttrValid % time.Second / time.Nanosecond),
- Attr: resp.Attr.attr(),
- }
- r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
-}
-
-type FsyncRequest struct {
- Header
- Handle HandleID
- Flags uint32
-}
-
-func (r *FsyncRequest) String() string {
- return fmt.Sprintf("Fsync [%s] Handle %v Flags %v", &r.Header, r.Handle, r.Flags)
-}
-
-func (r *FsyncRequest) Respond() {
- out := &outHeader{Unique: uint64(r.ID)}
- r.Conn.respond(out, unsafe.Sizeof(*out))
-}
-
-/*{
-
-// A XXXRequest xxx.
-type XXXRequest struct {
- Header
- xxx
-}
-
-func (r *XXXRequest) String() string {
- return fmt.Sprintf("XXX [%s] xxx", &r.Header)
-}
-
-func (r *XXXRequest) handle() HandleID {
- return r.Handle
-}
-
-// Respond replies to the request with the given response.
-func (r *XXXRequest) Respond(resp *XXXResponse) {
- out := &xxxOut{
- outHeader: outHeader{Unique: uint64(r.ID)},
- xxx,
- }
- r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
-}
-
-// A XXXResponse is the response to a XXXRequest.
-type XXXResponse struct {
- xxx
-}
-
-func (r *XXXResponse) String() string {
- return fmt.Sprintf("XXX %+v", *r)
-}
-
- }
-*/
diff --git a/vendor/github.com/mattermost/rsc/fuse/fuse_kernel.go b/vendor/github.com/mattermost/rsc/fuse/fuse_kernel.go
deleted file mode 100644
index a57360e63..000000000
--- a/vendor/github.com/mattermost/rsc/fuse/fuse_kernel.go
+++ /dev/null
@@ -1,539 +0,0 @@
-// Copyright 2011 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.
-
-// Derived from FUSE's fuse_kernel.h
-/*
- This file defines the kernel interface of FUSE
- Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
-
-
- This -- and only this -- header file may also be distributed under
- the terms of the BSD Licence as follows:
-
- Copyright (C) 2001-2007 Miklos Szeredi. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- SUCH DAMAGE.
-*/
-
-package fuse
-
-import (
- "fmt"
- "unsafe"
-)
-
-// Version is the FUSE version implemented by the package.
-const Version = "7.8"
-
-const (
- kernelVersion = 7
- kernelMinorVersion = 8
- rootID = 1
-)
-
-type kstatfs struct {
- Blocks uint64
- Bfree uint64
- Bavail uint64
- Files uint64
- Ffree uint64
- Bsize uint32
- Namelen uint32
- Frsize uint32
- Padding uint32
- Spare [6]uint32
-}
-
-type fileLock struct {
- Start uint64
- End uint64
- Type uint32
- Pid uint32
-}
-
-// The SetattrValid are bit flags describing which fields in the SetattrRequest
-// are included in the change.
-type SetattrValid uint32
-
-const (
- SetattrMode SetattrValid = 1 << 0
- SetattrUid SetattrValid = 1 << 1
- SetattrGid SetattrValid = 1 << 2
- SetattrSize SetattrValid = 1 << 3
- SetattrAtime SetattrValid = 1 << 4
- SetattrMtime SetattrValid = 1 << 5
- SetattrHandle SetattrValid = 1 << 6 // TODO: What does this mean?
-
- // Linux only(?)
- SetattrAtimeNow SetattrValid = 1 << 7
- SetattrMtimeNow SetattrValid = 1 << 8
- SetattrLockOwner SetattrValid = 1 << 9 // http://www.mail-archive.com/git-commits-head@vger.kernel.org/msg27852.html
-
- // OS X only
- SetattrCrtime SetattrValid = 1 << 28
- SetattrChgtime SetattrValid = 1 << 29
- SetattrBkuptime SetattrValid = 1 << 30
- SetattrFlags SetattrValid = 1 << 31
-)
-
-func (fl SetattrValid) Mode() bool { return fl&SetattrMode != 0 }
-func (fl SetattrValid) Uid() bool { return fl&SetattrUid != 0 }
-func (fl SetattrValid) Gid() bool { return fl&SetattrGid != 0 }
-func (fl SetattrValid) Size() bool { return fl&SetattrSize != 0 }
-func (fl SetattrValid) Atime() bool { return fl&SetattrAtime != 0 }
-func (fl SetattrValid) Mtime() bool { return fl&SetattrMtime != 0 }
-func (fl SetattrValid) Handle() bool { return fl&SetattrHandle != 0 }
-func (fl SetattrValid) Crtime() bool { return fl&SetattrCrtime != 0 }
-func (fl SetattrValid) Chgtime() bool { return fl&SetattrChgtime != 0 }
-func (fl SetattrValid) Bkuptime() bool { return fl&SetattrBkuptime != 0 }
-func (fl SetattrValid) Flags() bool { return fl&SetattrFlags != 0 }
-
-func (fl SetattrValid) String() string {
- return flagString(uint32(fl), setattrValidNames)
-}
-
-var setattrValidNames = []flagName{
- {uint32(SetattrMode), "SetattrMode"},
- {uint32(SetattrUid), "SetattrUid"},
- {uint32(SetattrGid), "SetattrGid"},
- {uint32(SetattrSize), "SetattrSize"},
- {uint32(SetattrAtime), "SetattrAtime"},
- {uint32(SetattrMtime), "SetattrMtime"},
- {uint32(SetattrHandle), "SetattrHandle"},
- {uint32(SetattrCrtime), "SetattrCrtime"},
- {uint32(SetattrChgtime), "SetattrChgtime"},
- {uint32(SetattrBkuptime), "SetattrBkuptime"},
- {uint32(SetattrFlags), "SetattrFlags"},
-}
-
-// The OpenFlags are returned in the OpenResponse.
-type OpenFlags uint32
-
-const (
- OpenDirectIO OpenFlags = 1 << 0 // bypass page cache for this open file
- OpenKeepCache OpenFlags = 1 << 1 // don't invalidate the data cache on open
- OpenNonSeekable OpenFlags = 1 << 2 // (Linux?)
-
- OpenPurgeAttr OpenFlags = 1 << 30 // OS X
- OpenPurgeUBC OpenFlags = 1 << 31 // OS X
-)
-
-func (fl OpenFlags) String() string {
- return flagString(uint32(fl), openFlagNames)
-}
-
-var openFlagNames = []flagName{
- {uint32(OpenDirectIO), "OpenDirectIO"},
- {uint32(OpenKeepCache), "OpenKeepCache"},
- {uint32(OpenPurgeAttr), "OpenPurgeAttr"},
- {uint32(OpenPurgeUBC), "OpenPurgeUBC"},
-}
-
-// The InitFlags are used in the Init exchange.
-type InitFlags uint32
-
-const (
- InitAsyncRead InitFlags = 1 << 0
- InitPosixLocks InitFlags = 1 << 1
-
- InitCaseSensitive InitFlags = 1 << 29 // OS X only
- InitVolRename InitFlags = 1 << 30 // OS X only
- InitXtimes InitFlags = 1 << 31 // OS X only
-)
-
-type flagName struct {
- bit uint32
- name string
-}
-
-var initFlagNames = []flagName{
- {uint32(InitAsyncRead), "InitAsyncRead"},
- {uint32(InitPosixLocks), "InitPosixLocks"},
- {uint32(InitCaseSensitive), "InitCaseSensitive"},
- {uint32(InitVolRename), "InitVolRename"},
- {uint32(InitXtimes), "InitXtimes"},
-}
-
-func (fl InitFlags) String() string {
- return flagString(uint32(fl), initFlagNames)
-}
-
-func flagString(f uint32, names []flagName) string {
- var s string
-
- if f == 0 {
- return "0"
- }
-
- for _, n := range names {
- if f&n.bit != 0 {
- s += "+" + n.name
- f &^= n.bit
- }
- }
- if f != 0 {
- s += fmt.Sprintf("%+#x", f)
- }
- return s[1:]
-}
-
-// The ReleaseFlags are used in the Release exchange.
-type ReleaseFlags uint32
-
-const (
- ReleaseFlush ReleaseFlags = 1 << 0
-)
-
-func (fl ReleaseFlags) String() string {
- return flagString(uint32(fl), releaseFlagNames)
-}
-
-var releaseFlagNames = []flagName{
- {uint32(ReleaseFlush), "ReleaseFlush"},
-}
-
-// Opcodes
-const (
- opLookup = 1
- opForget = 2 // no reply
- opGetattr = 3
- opSetattr = 4
- opReadlink = 5
- opSymlink = 6
- opMknod = 8
- opMkdir = 9
- opUnlink = 10
- opRmdir = 11
- opRename = 12
- opLink = 13
- opOpen = 14
- opRead = 15
- opWrite = 16
- opStatfs = 17
- opRelease = 18
- opFsync = 20
- opSetxattr = 21
- opGetxattr = 22
- opListxattr = 23
- opRemovexattr = 24
- opFlush = 25
- opInit = 26
- opOpendir = 27
- opReaddir = 28
- opReleasedir = 29
- opFsyncdir = 30
- opGetlk = 31
- opSetlk = 32
- opSetlkw = 33
- opAccess = 34
- opCreate = 35
- opInterrupt = 36
- opBmap = 37
- opDestroy = 38
- opIoctl = 39 // Linux?
- opPoll = 40 // Linux?
-
- // OS X
- opSetvolname = 61
- opGetxtimes = 62
- opExchange = 63
-)
-
-// The read buffer is required to be at least 8k but may be much larger
-const minReadBuffer = 8192
-
-type entryOut struct {
- outHeader
- Nodeid uint64 // Inode ID
- Generation uint64 // Inode generation
- EntryValid uint64 // Cache timeout for the name
- AttrValid uint64 // Cache timeout for the attributes
- EntryValidNsec uint32
- AttrValidNsec uint32
- Attr attr
-}
-
-type forgetIn struct {
- Nlookup uint64
-}
-
-type attrOut struct {
- outHeader
- AttrValid uint64 // Cache timeout for the attributes
- AttrValidNsec uint32
- Dummy uint32
- Attr attr
-}
-
-// OS X
-type getxtimesOut struct {
- outHeader
- Bkuptime uint64
- Crtime uint64
- BkuptimeNsec uint32
- CrtimeNsec uint32
-}
-
-type mknodIn struct {
- Mode uint32
- Rdev uint32
- // "filename\x00" follows.
-}
-
-type mkdirIn struct {
- Mode uint32
- Padding uint32
- // filename follows
-}
-
-type renameIn struct {
- Newdir uint64
- // "oldname\x00newname\x00" follows
-}
-
-// OS X
-type exchangeIn struct {
- Olddir uint64
- Newdir uint64
- Options uint64
-}
-
-type linkIn struct {
- Oldnodeid uint64
-}
-
-type setattrInCommon struct {
- Valid uint32
- Padding uint32
- Fh uint64
- Size uint64
- LockOwner uint64 // unused on OS X?
- Atime uint64
- Mtime uint64
- Unused2 uint64
- AtimeNsec uint32
- MtimeNsec uint32
- Unused3 uint32
- Mode uint32
- Unused4 uint32
- Uid uint32
- Gid uint32
- Unused5 uint32
-}
-
-type openIn struct {
- Flags uint32
- Mode uint32
-}
-
-type openOut struct {
- outHeader
- Fh uint64
- OpenFlags uint32
- Padding uint32
-}
-
-type createOut struct {
- outHeader
-
- Nodeid uint64 // Inode ID
- Generation uint64 // Inode generation
- EntryValid uint64 // Cache timeout for the name
- AttrValid uint64 // Cache timeout for the attributes
- EntryValidNsec uint32
- AttrValidNsec uint32
- Attr attr
-
- Fh uint64
- OpenFlags uint32
- Padding uint32
-}
-
-type releaseIn struct {
- Fh uint64
- Flags uint32
- ReleaseFlags uint32
- LockOwner uint32
-}
-
-type flushIn struct {
- Fh uint64
- FlushFlags uint32
- Padding uint32
- LockOwner uint64
-}
-
-type readIn struct {
- Fh uint64
- Offset uint64
- Size uint32
- Padding uint32
-}
-
-type writeIn struct {
- Fh uint64
- Offset uint64
- Size uint32
- WriteFlags uint32
-}
-
-type writeOut struct {
- outHeader
- Size uint32
- Padding uint32
-}
-
-// The WriteFlags are returned in the WriteResponse.
-type WriteFlags uint32
-
-func (fl WriteFlags) String() string {
- return flagString(uint32(fl), writeFlagNames)
-}
-
-var writeFlagNames = []flagName{}
-
-const compatStatfsSize = 48
-
-type statfsOut struct {
- outHeader
- St kstatfs
-}
-
-type fsyncIn struct {
- Fh uint64
- FsyncFlags uint32
- Padding uint32
-}
-
-type setxattrIn struct {
- Size uint32
- Flags uint32
-}
-
-type setxattrInOSX struct {
- Size uint32
- Flags uint32
-
- // OS X only
- Position uint32
- Padding uint32
-}
-
-type getxattrIn struct {
- Size uint32
- Padding uint32
-}
-
-type getxattrInOSX struct {
- Size uint32
- Padding uint32
-
- // OS X only
- Position uint32
- Padding2 uint32
-}
-
-type getxattrOut struct {
- outHeader
- Size uint32
- Padding uint32
-}
-
-type lkIn struct {
- Fh uint64
- Owner uint64
- Lk fileLock
-}
-
-type lkOut struct {
- outHeader
- Lk fileLock
-}
-
-type accessIn struct {
- Mask uint32
- Padding uint32
-}
-
-type initIn struct {
- Major uint32
- Minor uint32
- MaxReadahead uint32
- Flags uint32
-}
-
-const initInSize = int(unsafe.Sizeof(initIn{}))
-
-type initOut struct {
- outHeader
- Major uint32
- Minor uint32
- MaxReadahead uint32
- Flags uint32
- Unused uint32
- MaxWrite uint32
-}
-
-type interruptIn struct {
- Unique uint64
-}
-
-type bmapIn struct {
- Block uint64
- BlockSize uint32
- Padding uint32
-}
-
-type bmapOut struct {
- outHeader
- Block uint64
-}
-
-type inHeader struct {
- Len uint32
- Opcode uint32
- Unique uint64
- Nodeid uint64
- Uid uint32
- Gid uint32
- Pid uint32
- Padding uint32
-}
-
-const inHeaderSize = int(unsafe.Sizeof(inHeader{}))
-
-type outHeader struct {
- Len uint32
- Error int32
- Unique uint64
-}
-
-type dirent struct {
- Ino uint64
- Off uint64
- Namelen uint32
- Type uint32
- Name [0]byte
-}
-
-const direntSize = 8 + 8 + 4 + 4
diff --git a/vendor/github.com/mattermost/rsc/fuse/fuse_kernel_darwin.go b/vendor/github.com/mattermost/rsc/fuse/fuse_kernel_darwin.go
deleted file mode 100644
index f7bc37766..000000000
--- a/vendor/github.com/mattermost/rsc/fuse/fuse_kernel_darwin.go
+++ /dev/null
@@ -1,58 +0,0 @@
-package fuse
-
-import (
- "time"
-)
-
-type attr struct {
- Ino uint64
- Size uint64
- Blocks uint64
- Atime uint64
- Mtime uint64
- Ctime uint64
- Crtime_ uint64 // OS X only
- AtimeNsec uint32
- MtimeNsec uint32
- CtimeNsec uint32
- CrtimeNsec uint32 // OS X only
- Mode uint32
- Nlink uint32
- Uid uint32
- Gid uint32
- Rdev uint32
- Flags_ uint32 // OS X only; see chflags(2)
-}
-
-func (a *attr) SetCrtime(s uint64, ns uint32) {
- a.Crtime_, a.CrtimeNsec = s, ns
-}
-
-func (a *attr) SetFlags(f uint32) {
- a.Flags_ = f
-}
-
-type setattrIn struct {
- setattrInCommon
-
- // OS X only
- Bkuptime_ uint64
- Chgtime_ uint64
- Crtime uint64
- BkuptimeNsec uint32
- ChgtimeNsec uint32
- CrtimeNsec uint32
- Flags_ uint32 // see chflags(2)
-}
-
-func (in *setattrIn) BkupTime() time.Time {
- return time.Unix(int64(in.Bkuptime_), int64(in.BkuptimeNsec))
-}
-
-func (in *setattrIn) Chgtime() time.Time {
- return time.Unix(int64(in.Chgtime_), int64(in.ChgtimeNsec))
-}
-
-func (in *setattrIn) Flags() uint32 {
- return in.Flags_
-}
diff --git a/vendor/github.com/mattermost/rsc/fuse/fuse_kernel_linux.go b/vendor/github.com/mattermost/rsc/fuse/fuse_kernel_linux.go
deleted file mode 100644
index 914bc3063..000000000
--- a/vendor/github.com/mattermost/rsc/fuse/fuse_kernel_linux.go
+++ /dev/null
@@ -1,50 +0,0 @@
-package fuse
-
-import "time"
-
-type attr struct {
- Ino uint64
- Size uint64
- Blocks uint64
- Atime uint64
- Mtime uint64
- Ctime uint64
- AtimeNsec uint32
- MtimeNsec uint32
- CtimeNsec uint32
- Mode uint32
- Nlink uint32
- Uid uint32
- Gid uint32
- Rdev uint32
- // Blksize uint32 // Only in protocol 7.9
- // padding_ uint32 // Only in protocol 7.9
-}
-
-func (a *attr) Crtime() time.Time {
- return time.Time{}
-}
-
-func (a *attr) SetCrtime(s uint64, ns uint32) {
- // Ignored on Linux.
-}
-
-func (a *attr) SetFlags(f uint32) {
- // Ignored on Linux.
-}
-
-type setattrIn struct {
- setattrInCommon
-}
-
-func (in *setattrIn) BkupTime() time.Time {
- return time.Time{}
-}
-
-func (in *setattrIn) Chgtime() time.Time {
- return time.Time{}
-}
-
-func (in *setattrIn) Flags() uint32 {
- return 0
-}
diff --git a/vendor/github.com/mattermost/rsc/fuse/fuse_kernel_std.go b/vendor/github.com/mattermost/rsc/fuse/fuse_kernel_std.go
deleted file mode 100644
index 074cfd322..000000000
--- a/vendor/github.com/mattermost/rsc/fuse/fuse_kernel_std.go
+++ /dev/null
@@ -1 +0,0 @@
-package fuse
diff --git a/vendor/github.com/mattermost/rsc/fuse/fuse_test.go b/vendor/github.com/mattermost/rsc/fuse/fuse_test.go
deleted file mode 100644
index 61533b8c5..000000000
--- a/vendor/github.com/mattermost/rsc/fuse/fuse_test.go
+++ /dev/null
@@ -1,594 +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.
-
-package fuse
-
-import (
- "flag"
- "fmt"
- "io/ioutil"
- "log"
- "os"
- "os/exec"
- "runtime"
- "syscall"
- "testing"
- "time"
-)
-
-var fuseRun = flag.String("fuserun", "", "which fuse test to run. runs all if empty.")
-
-// umount tries its best to unmount dir.
-func umount(dir string) {
- err := exec.Command("umount", dir).Run()
- if err != nil && runtime.GOOS == "linux" {
- exec.Command("/bin/fusermount", "-u", dir).Run()
- }
-}
-
-func TestFuse(t *testing.T) {
- Debugf = log.Printf
- dir, err := ioutil.TempDir("", "fusetest")
- if err != nil {
- t.Fatal(err)
- }
- os.MkdirAll(dir, 0777)
-
- c, err := Mount(dir)
- if err != nil {
- t.Fatal(err)
- }
- defer umount(dir)
-
- go func() {
- err := c.Serve(testFS{})
- if err != nil {
- fmt.Printf("SERVE ERROR: %v\n", err)
- }
- }()
-
- waitForMount(t, dir)
-
- for _, tt := range fuseTests {
- if *fuseRun == "" || *fuseRun == tt.name {
- t.Logf("running %T", tt.node)
- tt.node.test(dir+"/"+tt.name, t)
- }
- }
-}
-
-func waitForMount(t *testing.T, dir string) {
- // Filename to wait for in dir:
- probeEntry := *fuseRun
- if probeEntry == "" {
- probeEntry = fuseTests[0].name
- }
- for tries := 0; tries < 100; tries++ {
- _, err := os.Stat(dir + "/" + probeEntry)
- if err == nil {
- return
- }
- time.Sleep(10 * time.Millisecond)
- }
- t.Fatalf("mount did not work")
-}
-
-var fuseTests = []struct {
- name string
- node interface {
- Node
- test(string, *testing.T)
- }
-}{
- {"readAll", readAll{}},
- {"readAll1", &readAll1{}},
- {"write", &write{}},
- {"writeAll", &writeAll{}},
- {"writeAll2", &writeAll2{}},
- {"release", &release{}},
- {"mkdir1", &mkdir1{}},
- {"create1", &create1{}},
- {"create2", &create2{}},
- {"symlink1", &symlink1{}},
- {"link1", &link1{}},
- {"rename1", &rename1{}},
- {"mknod1", &mknod1{}},
-}
-
-// TO TEST:
-// Statfs
-// Lookup(*LookupRequest, *LookupResponse)
-// Getattr(*GetattrRequest, *GetattrResponse)
-// Attr with explicit inode
-// Setattr(*SetattrRequest, *SetattrResponse)
-// Access(*AccessRequest)
-// Open(*OpenRequest, *OpenResponse)
-// Getxattr, Setxattr, Listxattr, Removexattr
-// Write(*WriteRequest, *WriteResponse)
-// Flush(*FlushRequest, *FlushResponse)
-
-// Test Read calling ReadAll.
-
-type readAll struct{ file }
-
-const hi = "hello, world"
-
-func (readAll) ReadAll(intr Intr) ([]byte, Error) {
- return []byte(hi), nil
-}
-
-func (readAll) test(path string, t *testing.T) {
- data, err := ioutil.ReadFile(path)
- if err != nil {
- t.Errorf("readAll: %v", err)
- return
- }
- if string(data) != hi {
- t.Errorf("readAll = %q, want %q", data, hi)
- }
-}
-
-// Test Read.
-
-type readAll1 struct{ file }
-
-func (readAll1) Read(req *ReadRequest, resp *ReadResponse, intr Intr) Error {
- HandleRead(req, resp, []byte(hi))
- return nil
-}
-
-func (readAll1) test(path string, t *testing.T) {
- readAll{}.test(path, t)
-}
-
-// Test Write calling basic Write, with an fsync thrown in too.
-
-type write struct {
- file
- data []byte
- gotfsync bool
-}
-
-func (w *write) Write(req *WriteRequest, resp *WriteResponse, intr Intr) Error {
- w.data = append(w.data, req.Data...)
- resp.Size = len(req.Data)
- return nil
-}
-
-func (w *write) Fsync(r *FsyncRequest, intr Intr) Error {
- w.gotfsync = true
- return nil
-}
-
-func (w *write) test(path string, t *testing.T) {
- log.Printf("pre-write Create")
- f, err := os.Create(path)
- if err != nil {
- t.Fatalf("Create: %v", err)
- }
- log.Printf("pre-write Write")
- n, err := f.Write([]byte(hi))
- if err != nil {
- t.Fatalf("Write: %v", err)
- }
- if n != len(hi) {
- t.Fatalf("short write; n=%d; hi=%d", n, len(hi))
- }
-
- err = syscall.Fsync(int(f.Fd()))
- if err != nil {
- t.Fatalf("Fsync = %v", err)
- }
- if !w.gotfsync {
- t.Errorf("never received expected fsync call")
- }
-
- log.Printf("pre-write Close")
- err = f.Close()
- if err != nil {
- t.Fatalf("Close: %v", err)
- }
- log.Printf("post-write Close")
- if string(w.data) != hi {
- t.Errorf("writeAll = %q, want %q", w.data, hi)
- }
-}
-
-// Test Write calling WriteAll.
-
-type writeAll struct {
- file
- data []byte
- gotfsync bool
-}
-
-func (w *writeAll) Fsync(r *FsyncRequest, intr Intr) Error {
- w.gotfsync = true
- return nil
-}
-
-func (w *writeAll) WriteAll(data []byte, intr Intr) Error {
- w.data = data
- return nil
-}
-
-func (w *writeAll) test(path string, t *testing.T) {
- err := ioutil.WriteFile(path, []byte(hi), 0666)
- if err != nil {
- t.Fatalf("WriteFile: %v", err)
- return
- }
- if string(w.data) != hi {
- t.Errorf("writeAll = %q, want %q", w.data, hi)
- }
-}
-
-// Test Write calling Setattr+Write+Flush.
-
-type writeAll2 struct {
- file
- data []byte
- setattr bool
- flush bool
-}
-
-func (w *writeAll2) Setattr(req *SetattrRequest, resp *SetattrResponse, intr Intr) Error {
- w.setattr = true
- return nil
-}
-
-func (w *writeAll2) Flush(req *FlushRequest, intr Intr) Error {
- w.flush = true
- return nil
-}
-
-func (w *writeAll2) Write(req *WriteRequest, resp *WriteResponse, intr Intr) Error {
- w.data = append(w.data, req.Data...)
- resp.Size = len(req.Data)
- return nil
-}
-
-func (w *writeAll2) test(path string, t *testing.T) {
- err := ioutil.WriteFile(path, []byte(hi), 0666)
- if err != nil {
- t.Errorf("WriteFile: %v", err)
- return
- }
- if !w.setattr || string(w.data) != hi || !w.flush {
- t.Errorf("writeAll = %v, %q, %v, want %v, %q, %v", w.setattr, string(w.data), w.flush, true, hi, true)
- }
-}
-
-// Test Mkdir.
-
-type mkdir1 struct {
- dir
- name string
-}
-
-func (f *mkdir1) Mkdir(req *MkdirRequest, intr Intr) (Node, Error) {
- f.name = req.Name
- return &mkdir1{}, nil
-}
-
-func (f *mkdir1) test(path string, t *testing.T) {
- f.name = ""
- err := os.Mkdir(path+"/foo", 0777)
- if err != nil {
- t.Error(err)
- return
- }
- if f.name != "foo" {
- t.Error(err)
- return
- }
-}
-
-// Test Create (and fsync)
-
-type create1 struct {
- dir
- name string
- f *writeAll
-}
-
-func (f *create1) Create(req *CreateRequest, resp *CreateResponse, intr Intr) (Node, Handle, Error) {
- f.name = req.Name
- f.f = &writeAll{}
- return f.f, f.f, nil
-}
-
-func (f *create1) test(path string, t *testing.T) {
- f.name = ""
- ff, err := os.Create(path + "/foo")
- if err != nil {
- t.Errorf("create1 WriteFile: %v", err)
- return
- }
-
- err = syscall.Fsync(int(ff.Fd()))
- if err != nil {
- t.Fatalf("Fsync = %v", err)
- }
-
- if !f.f.gotfsync {
- t.Errorf("never received expected fsync call")
- }
-
- ff.Close()
- if f.name != "foo" {
- t.Errorf("create1 name=%q want foo", f.name)
- }
-}
-
-// Test Create + WriteAll + Remove
-
-type create2 struct {
- dir
- name string
- f *writeAll
- fooExists bool
-}
-
-func (f *create2) Create(req *CreateRequest, resp *CreateResponse, intr Intr) (Node, Handle, Error) {
- f.name = req.Name
- f.f = &writeAll{}
- return f.f, f.f, nil
-}
-
-func (f *create2) Lookup(name string, intr Intr) (Node, Error) {
- if f.fooExists && name == "foo" {
- return file{}, nil
- }
- return nil, ENOENT
-}
-
-func (f *create2) Remove(r *RemoveRequest, intr Intr) Error {
- if f.fooExists && r.Name == "foo" && !r.Dir {
- f.fooExists = false
- return nil
- }
- return ENOENT
-}
-
-func (f *create2) test(path string, t *testing.T) {
- f.name = ""
- err := ioutil.WriteFile(path+"/foo", []byte(hi), 0666)
- if err != nil {
- t.Fatalf("create2 WriteFile: %v", err)
- }
- if string(f.f.data) != hi {
- t.Fatalf("create2 writeAll = %q, want %q", f.f.data, hi)
- }
-
- f.fooExists = true
- log.Printf("pre-Remove")
- err = os.Remove(path + "/foo")
- if err != nil {
- t.Fatalf("Remove: %v", err)
- }
- err = os.Remove(path + "/foo")
- if err == nil {
- t.Fatalf("second Remove = nil; want some error")
- }
-}
-
-// Test symlink + readlink
-
-type symlink1 struct {
- dir
- newName, target string
-}
-
-func (f *symlink1) Symlink(req *SymlinkRequest, intr Intr) (Node, Error) {
- f.newName = req.NewName
- f.target = req.Target
- return symlink{target: req.Target}, nil
-}
-
-func (f *symlink1) test(path string, t *testing.T) {
- const target = "/some-target"
-
- err := os.Symlink(target, path+"/symlink.file")
- if err != nil {
- t.Errorf("os.Symlink: %v", err)
- return
- }
-
- if f.newName != "symlink.file" {
- t.Errorf("symlink newName = %q; want %q", f.newName, "symlink.file")
- }
- if f.target != target {
- t.Errorf("symlink target = %q; want %q", f.target, target)
- }
-
- gotName, err := os.Readlink(path + "/symlink.file")
- if err != nil {
- t.Errorf("os.Readlink: %v", err)
- return
- }
- if gotName != target {
- t.Errorf("os.Readlink = %q; want %q", gotName, target)
- }
-}
-
-// Test link
-
-type link1 struct {
- dir
- newName string
-}
-
-func (f *link1) Lookup(name string, intr Intr) (Node, Error) {
- if name == "old" {
- return file{}, nil
- }
- return nil, ENOENT
-}
-
-func (f *link1) Link(r *LinkRequest, old Node, intr Intr) (Node, Error) {
- f.newName = r.NewName
- return file{}, nil
-}
-
-func (f *link1) test(path string, t *testing.T) {
- err := os.Link(path+"/old", path+"/new")
- if err != nil {
- t.Fatalf("Link: %v", err)
- }
- if f.newName != "new" {
- t.Fatalf("saw Link for newName %q; want %q", f.newName, "new")
- }
-}
-
-// Test Rename
-
-type rename1 struct {
- dir
- renames int
-}
-
-func (f *rename1) Lookup(name string, intr Intr) (Node, Error) {
- if name == "old" {
- return file{}, nil
- }
- return nil, ENOENT
-}
-
-func (f *rename1) Rename(r *RenameRequest, newDir Node, intr Intr) Error {
- if r.OldName == "old" && r.NewName == "new" && newDir == f {
- f.renames++
- return nil
- }
- return EIO
-}
-
-func (f *rename1) test(path string, t *testing.T) {
- err := os.Rename(path+"/old", path+"/new")
- if err != nil {
- t.Fatalf("Rename: %v", err)
- }
- if f.renames != 1 {
- t.Fatalf("expected rename didn't happen")
- }
- err = os.Rename(path+"/old2", path+"/new2")
- if err == nil {
- t.Fatal("expected error on second Rename; got nil")
- }
-}
-
-// Test Release.
-
-type release struct {
- file
- did bool
-}
-
-func (r *release) Release(*ReleaseRequest, Intr) Error {
- r.did = true
- return nil
-}
-
-func (r *release) test(path string, t *testing.T) {
- r.did = false
- f, err := os.Open(path)
- if err != nil {
- t.Error(err)
- return
- }
- f.Close()
- time.Sleep(1 * time.Second)
- if !r.did {
- t.Error("Close did not Release")
- }
-}
-
-// Test mknod
-
-type mknod1 struct {
- dir
- gotr *MknodRequest
-}
-
-func (f *mknod1) Mknod(r *MknodRequest, intr Intr) (Node, Error) {
- f.gotr = r
- return fifo{}, nil
-}
-
-func (f *mknod1) test(path string, t *testing.T) {
- if os.Getuid() != 0 {
- t.Logf("skipping unless root")
- return
- }
- defer syscall.Umask(syscall.Umask(0))
- err := syscall.Mknod(path+"/node", syscall.S_IFIFO|0666, 123)
- if err != nil {
- t.Fatalf("Mknod: %v", err)
- }
- if f.gotr == nil {
- t.Fatalf("no recorded MknodRequest")
- }
- if g, e := f.gotr.Name, "node"; g != e {
- t.Errorf("got Name = %q; want %q", g, e)
- }
- if g, e := f.gotr.Rdev, uint32(123); g != e {
- if runtime.GOOS == "linux" {
- // Linux fuse doesn't echo back the rdev if the node
- // isn't a device (we're using a FIFO here, as that
- // bit is portable.)
- } else {
- t.Errorf("got Rdev = %v; want %v", g, e)
- }
- }
- if g, e := f.gotr.Mode, os.FileMode(os.ModeNamedPipe|0666); g != e {
- t.Errorf("got Mode = %v; want %v", g, e)
- }
- t.Logf("Got request: %#v", f.gotr)
-}
-
-type file struct{}
-type dir struct{}
-type fifo struct{}
-type symlink struct {
- target string
-}
-
-func (f file) Attr() Attr { return Attr{Mode: 0666} }
-func (f dir) Attr() Attr { return Attr{Mode: os.ModeDir | 0777} }
-func (f fifo) Attr() Attr { return Attr{Mode: os.ModeNamedPipe | 0666} }
-func (f symlink) Attr() Attr { return Attr{Mode: os.ModeSymlink | 0666} }
-
-func (f symlink) Readlink(*ReadlinkRequest, Intr) (string, Error) {
- return f.target, nil
-}
-
-type testFS struct{}
-
-func (testFS) Root() (Node, Error) {
- return testFS{}, nil
-}
-
-func (testFS) Attr() Attr {
- return Attr{Mode: os.ModeDir | 0555}
-}
-
-func (testFS) Lookup(name string, intr Intr) (Node, Error) {
- for _, tt := range fuseTests {
- if tt.name == name {
- return tt.node, nil
- }
- }
- return nil, ENOENT
-}
-
-func (testFS) ReadDir(intr Intr) ([]Dirent, Error) {
- var dirs []Dirent
- for _, tt := range fuseTests {
- if *fuseRun == "" || *fuseRun == tt.name {
- log.Printf("Readdir; adding %q", tt.name)
- dirs = append(dirs, Dirent{Name: tt.name})
- }
- }
- return dirs, nil
-}
diff --git a/vendor/github.com/mattermost/rsc/fuse/hellofs/hello.go b/vendor/github.com/mattermost/rsc/fuse/hellofs/hello.go
deleted file mode 100644
index d915473f1..000000000
--- a/vendor/github.com/mattermost/rsc/fuse/hellofs/hello.go
+++ /dev/null
@@ -1,62 +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.
-
-// Hellofs implements a simple "hello world" file system.
-package main
-
-import (
- "log"
- "os"
-
- "github.com/mattermost/rsc/fuse"
-)
-
-func main() {
- c, err := fuse.Mount("/mnt/hellofs")
- if err != nil {
- log.Fatal(err)
- }
-
- c.Serve(FS{})
-}
-
-// FS implements the hello world file system.
-type FS struct{}
-
-func (FS) Root() (fuse.Node, fuse.Error) {
- return Dir{}, nil
-}
-
-// Dir implements both Node and Handle for the root directory.
-type Dir struct{}
-
-func (Dir) Attr() fuse.Attr {
- return fuse.Attr{Mode: os.ModeDir | 0555}
-}
-
-func (Dir) Lookup(name string, intr fuse.Intr) (fuse.Node, fuse.Error) {
- if name == "hello" {
- return File{}, nil
- }
- return nil, fuse.ENOENT
-}
-
-var dirDirs = []fuse.Dirent{
- {Inode: 2, Name: "hello", Type: 0},
-}
-
-func (Dir) ReadDir(intr fuse.Intr) ([]fuse.Dirent, fuse.Error) {
- return dirDirs, nil
-}
-
-// File implements both Node and Handle for the hello file.
-type File struct{}
-
-func (File) Attr() fuse.Attr {
- return fuse.Attr{Mode: 0444}
-}
-
-func (File) ReadAll(intr fuse.Intr) ([]byte, fuse.Error) {
- return []byte("hello, world\n"), nil
-}
diff --git a/vendor/github.com/mattermost/rsc/fuse/mount_darwin.go b/vendor/github.com/mattermost/rsc/fuse/mount_darwin.go
deleted file mode 100644
index 5e2caaa76..000000000
--- a/vendor/github.com/mattermost/rsc/fuse/mount_darwin.go
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2011 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.
-
-// TODO: Rewrite using package syscall not cgo
-
-package fuse
-
-/*
-
-// Adapted from Plan 9 from User Space's src/cmd/9pfuse/fuse.c,
-// which carries this notice:
-//
-// The files in this directory are subject to the following license.
-//
-// The author of this software is Russ Cox.
-//
-// Copyright (c) 2006 Russ Cox
-//
-// Permission to use, copy, modify, and distribute this software for any
-// purpose without fee is hereby granted, provided that this entire notice
-// is included in all copies of any software which is or includes a copy
-// or modification of this software and in all copies of the supporting
-// documentation for such software.
-//
-// THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
-// WARRANTY. IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION OR WARRANTY
-// OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS SOFTWARE OR ITS
-// FITNESS FOR ANY PARTICULAR PURPOSE.
-
-#include <stdlib.h>
-#include <sys/param.h>
-#include <sys/mount.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-
-#define nil ((void*)0)
-
-static int
-mountfuse(char *mtpt, char **err)
-{
- int i, pid, fd, r;
- char buf[200];
- struct vfsconf vfs;
- char *f;
-
- if(getvfsbyname("fusefs", &vfs) < 0){
- if(access(f="/Library/Filesystems/osxfusefs.fs"
- "/Support/load_osxfusefs", 0) < 0){
- *err = strdup("cannot find load_fusefs");
- return -1;
- }
- if((r=system(f)) < 0){
- snprintf(buf, sizeof buf, "%s: %s", f, strerror(errno));
- *err = strdup(buf);
- return -1;
- }
- if(r != 0){
- snprintf(buf, sizeof buf, "load_fusefs failed: exit %d", r);
- *err = strdup(buf);
- return -1;
- }
- if(getvfsbyname("osxfusefs", &vfs) < 0){
- snprintf(buf, sizeof buf, "getvfsbyname osxfusefs: %s", strerror(errno));
- *err = strdup(buf);
- return -1;
- }
- }
-
- // Look for available FUSE device.
- for(i=0;; i++){
- snprintf(buf, sizeof buf, "/dev/osxfuse%d", i);
- if(access(buf, 0) < 0){
- *err = strdup("no available fuse devices");
- return -1;
- }
- if((fd = open(buf, O_RDWR)) >= 0)
- break;
- }
-
- pid = fork();
- if(pid < 0)
- return -1;
- if(pid == 0){
- snprintf(buf, sizeof buf, "%d", fd);
- setenv("MOUNT_FUSEFS_CALL_BY_LIB", "", 1);
- // Different versions of MacFUSE put the
- // mount_fusefs binary in different places.
- // Try all.
- // Leopard location
- setenv("MOUNT_FUSEFS_DAEMON_PATH",
- "/Library/Filesystems/osxfusefs.fs/Support/mount_osxfusefs", 1);
- execl("/Library/Filesystems/osxfusefs.fs/Support/mount_osxfusefs",
- "mount_osxfusefs",
- "-o", "iosize=4096", buf, mtpt, nil);
- fprintf(stderr, "exec mount_osxfusefs: %s\n", strerror(errno));
- _exit(1);
- }
- return fd;
-}
-
-*/
-import "C"
-
-import "unsafe"
-
-func mount(dir string) (int, string) {
- errp := (**C.char)(C.malloc(16))
- *errp = nil
- defer C.free(unsafe.Pointer(errp))
- cdir := C.CString(dir)
- defer C.free(unsafe.Pointer(cdir))
- fd := C.mountfuse(cdir, errp)
- var err string
- if *errp != nil {
- err = C.GoString(*errp)
- }
- return int(fd), err
-}
diff --git a/vendor/github.com/mattermost/rsc/fuse/mount_linux.go b/vendor/github.com/mattermost/rsc/fuse/mount_linux.go
deleted file mode 100644
index e5bc58b8a..000000000
--- a/vendor/github.com/mattermost/rsc/fuse/mount_linux.go
+++ /dev/null
@@ -1,67 +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.
-
-package fuse
-
-import (
- "fmt"
- "net"
- "os"
- "os/exec"
- "syscall"
-)
-
-func mount(dir string) (fusefd int, errmsg string) {
- fds, err := syscall.Socketpair(syscall.AF_FILE, syscall.SOCK_STREAM, 0)
- if err != nil {
- return -1, fmt.Sprintf("socketpair error: %v", err)
- }
- defer syscall.Close(fds[0])
- defer syscall.Close(fds[1])
-
- cmd := exec.Command("/bin/fusermount", "--", dir)
- cmd.Env = append(os.Environ(), "_FUSE_COMMFD=3")
-
- writeFile := os.NewFile(uintptr(fds[0]), "fusermount-child-writes")
- defer writeFile.Close()
- cmd.ExtraFiles = []*os.File{writeFile}
-
- out, err := cmd.CombinedOutput()
- if len(out) > 0 || err != nil {
- return -1, fmt.Sprintf("fusermount: %q, %v", out, err)
- }
-
- readFile := os.NewFile(uintptr(fds[1]), "fusermount-parent-reads")
- defer readFile.Close()
- c, err := net.FileConn(readFile)
- if err != nil {
- return -1, fmt.Sprintf("FileConn from fusermount socket: %v", err)
- }
- defer c.Close()
-
- uc, ok := c.(*net.UnixConn)
- if !ok {
- return -1, fmt.Sprintf("unexpected FileConn type; expected UnixConn, got %T", c)
- }
-
- buf := make([]byte, 32) // expect 1 byte
- oob := make([]byte, 32) // expect 24 bytes
- _, oobn, _, _, err := uc.ReadMsgUnix(buf, oob)
- scms, err := syscall.ParseSocketControlMessage(oob[:oobn])
- if err != nil {
- return -1, fmt.Sprintf("ParseSocketControlMessage: %v", err)
- }
- if len(scms) != 1 {
- return -1, fmt.Sprintf("expected 1 SocketControlMessage; got scms = %#v", scms)
- }
- scm := scms[0]
- gotFds, err := syscall.ParseUnixRights(&scm)
- if err != nil {
- return -1, fmt.Sprintf("syscall.ParseUnixRights: %v", err)
- }
- if len(gotFds) != 1 {
- return -1, fmt.Sprintf("wanted 1 fd; got %#v", gotFds)
- }
- return gotFds[0], ""
-}
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
-}
diff --git a/vendor/github.com/mattermost/rsc/fuse/tree.go b/vendor/github.com/mattermost/rsc/fuse/tree.go
deleted file mode 100644
index fec0a748f..000000000
--- a/vendor/github.com/mattermost/rsc/fuse/tree.go
+++ /dev/null
@@ -1,93 +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 directory tree, for servers that wish to use it with the service loop.
-
-package fuse
-
-import (
- "os"
- pathpkg "path"
- "strings"
-)
-
-// A Tree implements a basic directory tree for FUSE.
-type Tree struct {
- tree
-}
-
-func (t *Tree) Root() (Node, Error) {
- return &t.tree, nil
-}
-
-// Add adds the path to the tree, resolving to the given node.
-// If path or a prefix of path has already been added to the tree,
-// Add panics.
-func (t *Tree) Add(path string, node Node) {
- path = pathpkg.Clean("/" + path)[1:]
- elems := strings.Split(path, "/")
- dir := Node(&t.tree)
- for i, elem := range elems {
- dt, ok := dir.(*tree)
- if !ok {
- panic("fuse: Tree.Add for " + strings.Join(elems[:i], "/") + " and " + path)
- }
- n := dt.lookup(elem)
- if n != nil {
- if i+1 == len(elems) {
- panic("fuse: Tree.Add for " + path + " conflicts with " + elem)
- }
- dir = n
- } else {
- if i+1 == len(elems) {
- dt.add(elem, node)
- } else {
- dir = &tree{}
- dt.add(elem, dir)
- }
- }
- }
-}
-
-type treeDir struct {
- name string
- node Node
-}
-
-type tree struct {
- dir []treeDir
-}
-
-func (t *tree) lookup(name string) Node {
- for _, d := range t.dir {
- if d.name == name {
- return d.node
- }
- }
- return nil
-}
-
-func (t *tree) add(name string, n Node) {
- t.dir = append(t.dir, treeDir{name, n})
-}
-
-func (t *tree) Attr() Attr {
- return Attr{Mode: os.ModeDir | 0555}
-}
-
-func (t *tree) Lookup(name string, intr Intr) (Node, Error) {
- n := t.lookup(name)
- if n != nil {
- return n, nil
- }
- return nil, ENOENT
-}
-
-func (t *tree) ReadDir(intr Intr) ([]Dirent, Error) {
- var out []Dirent
- for _, d := range t.dir {
- out = append(out, Dirent{Name: d.name})
- }
- return out, nil
-}