github.com/slspeek/camlistore_namedsearch@v0.0.0-20140519202248-ed6f70f7721a/third_party/bazil.org/fuse/fuse.go (about)

     1  // See the file LICENSE for copyright and licensing information.
     2  // Adapted from Plan 9 from User Space's src/cmd/9pfuse/fuse.c,
     3  // which carries this notice:
     4  //
     5  // The files in this directory are subject to the following license.
     6  //
     7  // The author of this software is Russ Cox.
     8  //
     9  //         Copyright (c) 2006 Russ Cox
    10  //
    11  // Permission to use, copy, modify, and distribute this software for any
    12  // purpose without fee is hereby granted, provided that this entire notice
    13  // is included in all copies of any software which is or includes a copy
    14  // or modification of this software and in all copies of the supporting
    15  // documentation for such software.
    16  //
    17  // THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
    18  // WARRANTY.  IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION OR WARRANTY
    19  // OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS SOFTWARE OR ITS
    20  // FITNESS FOR ANY PARTICULAR PURPOSE.
    21  
    22  // Package fuse enables writing FUSE file systems on FreeBSD, Linux, and OS X.
    23  //
    24  // On OS X, it requires OSXFUSE (http://osxfuse.github.com/).
    25  //
    26  // There are two approaches to writing a FUSE file system.  The first is to speak
    27  // the low-level message protocol, reading from a Conn using ReadRequest and
    28  // writing using the various Respond methods.  This approach is closest to
    29  // the actual interaction with the kernel and can be the simplest one in contexts
    30  // such as protocol translators.
    31  //
    32  // Servers of synthesized file systems tend to share common
    33  // bookkeeping abstracted away by the second approach, which is to
    34  // call fs.Serve to serve the FUSE protocol using an implementation of
    35  // the service methods in the interfaces FS* (file system), Node* (file
    36  // or directory), and Handle* (opened file or directory).
    37  // There are a daunting number of such methods that can be written,
    38  // but few are required.
    39  // The specific methods are described in the documentation for those interfaces.
    40  //
    41  // The hellofs subdirectory contains a simple illustration of the fs.Serve approach.
    42  //
    43  // Service Methods
    44  //
    45  // The required and optional methods for the FS, Node, and Handle interfaces
    46  // have the general form
    47  //
    48  //	Op(req *OpRequest, resp *OpResponse, intr Intr) Error
    49  //
    50  // where Op is the name of a FUSE operation.  Op reads request parameters
    51  // from req and writes results to resp.  An operation whose only result is
    52  // the error result omits the resp parameter.  Multiple goroutines may call
    53  // service methods simultaneously; the methods being called are responsible
    54  // for appropriate synchronization.
    55  //
    56  // Interrupted Operations
    57  //
    58  // In some file systems, some operations
    59  // may take an undetermined amount of time.  For example, a Read waiting for
    60  // a network message or a matching Write might wait indefinitely.  If the request
    61  // is cancelled and no longer needed, the package will close intr, a chan struct{}.
    62  // Blocking operations should select on a receive from intr and attempt to
    63  // abort the operation early if the receive succeeds (meaning the channel is closed).
    64  // To indicate that the operation failed because it was aborted, return fuse.EINTR.
    65  //
    66  // If an operation does not block for an indefinite amount of time, the intr parameter
    67  // can be ignored.
    68  //
    69  // Authentication
    70  //
    71  // All requests types embed a Header, meaning that the method can inspect
    72  // req.Pid, req.Uid, and req.Gid as necessary to implement permission checking.
    73  // Alternately, XXX.
    74  //
    75  // Mount Options
    76  //
    77  // XXX
    78  //
    79  package fuse
    80  
    81  // BUG(rsc): The mount code for FreeBSD has not been written yet.
    82  
    83  import (
    84  	"bytes"
    85  	"encoding/json"
    86  	"errors"
    87  	"fmt"
    88  	"io"
    89  	"os"
    90  	"sync"
    91  	"syscall"
    92  	"time"
    93  	"unsafe"
    94  )
    95  
    96  // A Conn represents a connection to a mounted FUSE file system.
    97  type Conn struct {
    98  	fd  int
    99  	buf []byte
   100  	wio sync.Mutex
   101  }
   102  
   103  // Mount mounts a new FUSE connection on the named directory
   104  // and returns a connection for reading and writing FUSE messages.
   105  func Mount(dir string) (*Conn, error) {
   106  	// TODO(rsc): mount options (...string?)
   107  	fd, errstr := mount(dir)
   108  	if errstr != "" {
   109  		return nil, errors.New(errstr)
   110  	}
   111  
   112  	return &Conn{fd: fd}, nil
   113  }
   114  
   115  // A Request represents a single FUSE request received from the kernel.
   116  // Use a type switch to determine the specific kind.
   117  // A request of unrecognized type will have concrete type *Header.
   118  type Request interface {
   119  	// Hdr returns the Header associated with this request.
   120  	Hdr() *Header
   121  
   122  	// RespondError responds to the request with the given error.
   123  	RespondError(Error)
   124  
   125  	String() string
   126  }
   127  
   128  // A RequestID identifies an active FUSE request.
   129  type RequestID uint64
   130  
   131  // A NodeID is a number identifying a directory or file.
   132  // It must be unique among IDs returned in LookupResponses
   133  // that have not yet been forgotten by ForgetRequests.
   134  type NodeID uint64
   135  
   136  // A HandleID is a number identifying an open directory or file.
   137  // It only needs to be unique while the directory or file is open.
   138  type HandleID uint64
   139  
   140  // The RootID identifies the root directory of a FUSE file system.
   141  const RootID NodeID = rootID
   142  
   143  // A Header describes the basic information sent in every request.
   144  type Header struct {
   145  	Conn *Conn     `json:"-"` // connection this request was received on
   146  	ID   RequestID // unique ID for request
   147  	Node NodeID    // file or directory the request is about
   148  	Uid  uint32    // user ID of process making request
   149  	Gid  uint32    // group ID of process making request
   150  	Pid  uint32    // process ID of process making request
   151  }
   152  
   153  func (h *Header) String() string {
   154  	return fmt.Sprintf("ID=%#x Node=%#x Uid=%d Gid=%d Pid=%d", h.ID, h.Node, h.Uid, h.Gid, h.Pid)
   155  }
   156  
   157  func (h *Header) Hdr() *Header {
   158  	return h
   159  }
   160  
   161  // An Error is a FUSE error.
   162  type Error interface {
   163  	errno() int32
   164  }
   165  
   166  const (
   167  	// ENOSYS indicates that the call is not supported.
   168  	ENOSYS = Errno(syscall.ENOSYS)
   169  
   170  	// ESTALE is used by Serve to respond to violations of the FUSE protocol.
   171  	ESTALE = Errno(syscall.ESTALE)
   172  
   173  	ENOENT = Errno(syscall.ENOENT)
   174  	EIO    = Errno(syscall.EIO)
   175  	EPERM  = Errno(syscall.EPERM)
   176  
   177  	// EINTR indicates request was interrupted by an InterruptRequest.
   178  	// See also fs.Intr.
   179  	EINTR = Errno(syscall.EINTR)
   180  
   181  	ENODATA = Errno(syscall.ENODATA)
   182  	ERANGE  = Errno(syscall.ERANGE)
   183  	ENOTSUP = Errno(syscall.ENOTSUP)
   184  )
   185  
   186  var errnoNames = map[Errno]string{
   187  	ENOSYS:  "ENOSYS",
   188  	ESTALE:  "ESTALE",
   189  	ENOENT:  "ENOENT",
   190  	EIO:     "EIO",
   191  	EPERM:   "EPERM",
   192  	EINTR:   "EINTR",
   193  	ENODATA: "ENODATA",
   194  }
   195  
   196  type errno int
   197  
   198  func (e errno) errno() int32 {
   199  	return int32(e)
   200  }
   201  
   202  // Errno implements Error using a syscall.Errno.
   203  type Errno syscall.Errno
   204  
   205  func (e Errno) errno() int32 {
   206  	return int32(e)
   207  }
   208  
   209  func (e Errno) String() string {
   210  	return syscall.Errno(e).Error()
   211  }
   212  
   213  func (e Errno) MarshalText() ([]byte, error) {
   214  	s := errnoNames[e]
   215  	if s == "" {
   216  		s = fmt.Sprint(e.errno())
   217  	}
   218  	return []byte(s), nil
   219  }
   220  
   221  func (h *Header) RespondError(err Error) {
   222  	// FUSE uses negative errors!
   223  	// TODO: File bug report against OSXFUSE: positive error causes kernel panic.
   224  	out := &outHeader{Error: -err.errno(), Unique: uint64(h.ID)}
   225  	h.Conn.respond(out, unsafe.Sizeof(*out))
   226  }
   227  
   228  var maxWrite = syscall.Getpagesize()
   229  var bufSize = 4096 + maxWrite
   230  
   231  // a message represents the bytes of a single FUSE message
   232  type message struct {
   233  	conn *Conn
   234  	buf  []byte    // all bytes
   235  	hdr  *inHeader // header
   236  	off  int       // offset for reading additional fields
   237  }
   238  
   239  func newMessage(c *Conn) *message {
   240  	m := &message{conn: c, buf: make([]byte, bufSize)}
   241  	m.hdr = (*inHeader)(unsafe.Pointer(&m.buf[0]))
   242  	return m
   243  }
   244  
   245  func (m *message) len() uintptr {
   246  	return uintptr(len(m.buf) - m.off)
   247  }
   248  
   249  func (m *message) data() unsafe.Pointer {
   250  	var p unsafe.Pointer
   251  	if m.off < len(m.buf) {
   252  		p = unsafe.Pointer(&m.buf[m.off])
   253  	}
   254  	return p
   255  }
   256  
   257  func (m *message) bytes() []byte {
   258  	return m.buf[m.off:]
   259  }
   260  
   261  func (m *message) Header() Header {
   262  	h := m.hdr
   263  	return Header{Conn: m.conn, ID: RequestID(h.Unique), Node: NodeID(h.Nodeid), Uid: h.Uid, Gid: h.Gid, Pid: h.Pid}
   264  }
   265  
   266  // fileMode returns a Go os.FileMode from a Unix mode.
   267  func fileMode(unixMode uint32) os.FileMode {
   268  	mode := os.FileMode(unixMode & 0777)
   269  	switch unixMode & syscall.S_IFMT {
   270  	case syscall.S_IFREG:
   271  		// nothing
   272  	case syscall.S_IFDIR:
   273  		mode |= os.ModeDir
   274  	case syscall.S_IFCHR:
   275  		mode |= os.ModeCharDevice | os.ModeDevice
   276  	case syscall.S_IFBLK:
   277  		mode |= os.ModeDevice
   278  	case syscall.S_IFIFO:
   279  		mode |= os.ModeNamedPipe
   280  	case syscall.S_IFLNK:
   281  		mode |= os.ModeSymlink
   282  	case syscall.S_IFSOCK:
   283  		mode |= os.ModeSocket
   284  	default:
   285  		// no idea
   286  		mode |= os.ModeDevice
   287  	}
   288  	if unixMode&syscall.S_ISUID != 0 {
   289  		mode |= os.ModeSetuid
   290  	}
   291  	if unixMode&syscall.S_ISGID != 0 {
   292  		mode |= os.ModeSetgid
   293  	}
   294  	return mode
   295  }
   296  
   297  type noOpcode struct {
   298  	Opcode uint32
   299  }
   300  
   301  func (m noOpcode) String() string {
   302  	return fmt.Sprintf("No opcode %v", m.Opcode)
   303  }
   304  
   305  type malformedMessage struct {
   306  }
   307  
   308  func (malformedMessage) String() string {
   309  	return "malformed message"
   310  }
   311  
   312  func (c *Conn) ReadRequest() (Request, error) {
   313  	// TODO: Some kind of buffer reuse.
   314  	m := newMessage(c)
   315  	n, err := syscall.Read(c.fd, m.buf)
   316  	if err != nil && err != syscall.ENODEV {
   317  		return nil, err
   318  	}
   319  	if n <= 0 {
   320  		return nil, io.EOF
   321  	}
   322  	m.buf = m.buf[:n]
   323  
   324  	if n < inHeaderSize {
   325  		return nil, errors.New("fuse: message too short")
   326  	}
   327  
   328  	// FreeBSD FUSE sends a short length in the header
   329  	// for FUSE_INIT even though the actual read length is correct.
   330  	if n == inHeaderSize+initInSize && m.hdr.Opcode == opInit && m.hdr.Len < uint32(n) {
   331  		m.hdr.Len = uint32(n)
   332  	}
   333  
   334  	// OSXFUSE sometimes sends the wrong m.hdr.Len in a FUSE_WRITE message.
   335  	if m.hdr.Len < uint32(n) && m.hdr.Len >= uint32(unsafe.Sizeof(writeIn{})) && m.hdr.Opcode == opWrite {
   336  		m.hdr.Len = uint32(n)
   337  	}
   338  
   339  	if m.hdr.Len != uint32(n) {
   340  		return nil, fmt.Errorf("fuse: read %d opcode %d but expected %d", n, m.hdr.Opcode, m.hdr.Len)
   341  	}
   342  
   343  	m.off = inHeaderSize
   344  
   345  	// Convert to data structures.
   346  	// Do not trust kernel to hand us well-formed data.
   347  	var req Request
   348  	switch m.hdr.Opcode {
   349  	default:
   350  		Debug(noOpcode{Opcode: m.hdr.Opcode})
   351  		goto unrecognized
   352  
   353  	case opLookup:
   354  		buf := m.bytes()
   355  		n := len(buf)
   356  		if n == 0 || buf[n-1] != '\x00' {
   357  			goto corrupt
   358  		}
   359  		req = &LookupRequest{
   360  			Header: m.Header(),
   361  			Name:   string(buf[:n-1]),
   362  		}
   363  
   364  	case opForget:
   365  		in := (*forgetIn)(m.data())
   366  		if m.len() < unsafe.Sizeof(*in) {
   367  			goto corrupt
   368  		}
   369  		req = &ForgetRequest{
   370  			Header: m.Header(),
   371  			N:      in.Nlookup,
   372  		}
   373  
   374  	case opGetattr:
   375  		req = &GetattrRequest{
   376  			Header: m.Header(),
   377  		}
   378  
   379  	case opSetattr:
   380  		in := (*setattrIn)(m.data())
   381  		if m.len() < unsafe.Sizeof(*in) {
   382  			goto corrupt
   383  		}
   384  		req = &SetattrRequest{
   385  			Header:   m.Header(),
   386  			Valid:    SetattrValid(in.Valid),
   387  			Handle:   HandleID(in.Fh),
   388  			Size:     in.Size,
   389  			Atime:    time.Unix(int64(in.Atime), int64(in.AtimeNsec)),
   390  			Mtime:    time.Unix(int64(in.Mtime), int64(in.MtimeNsec)),
   391  			Mode:     fileMode(in.Mode),
   392  			Uid:      in.Uid,
   393  			Gid:      in.Gid,
   394  			Bkuptime: in.BkupTime(),
   395  			Chgtime:  in.Chgtime(),
   396  			Flags:    in.Flags(),
   397  		}
   398  
   399  	case opReadlink:
   400  		if len(m.bytes()) > 0 {
   401  			goto corrupt
   402  		}
   403  		req = &ReadlinkRequest{
   404  			Header: m.Header(),
   405  		}
   406  
   407  	case opSymlink:
   408  		// m.bytes() is "newName\0target\0"
   409  		names := m.bytes()
   410  		if len(names) == 0 || names[len(names)-1] != 0 {
   411  			goto corrupt
   412  		}
   413  		i := bytes.IndexByte(names, '\x00')
   414  		if i < 0 {
   415  			goto corrupt
   416  		}
   417  		newName, target := names[0:i], names[i+1:len(names)-1]
   418  		req = &SymlinkRequest{
   419  			Header:  m.Header(),
   420  			NewName: string(newName),
   421  			Target:  string(target),
   422  		}
   423  
   424  	case opLink:
   425  		in := (*linkIn)(m.data())
   426  		if m.len() < unsafe.Sizeof(*in) {
   427  			goto corrupt
   428  		}
   429  		newName := m.bytes()[unsafe.Sizeof(*in):]
   430  		if len(newName) < 2 || newName[len(newName)-1] != 0 {
   431  			goto corrupt
   432  		}
   433  		newName = newName[:len(newName)-1]
   434  		req = &LinkRequest{
   435  			Header:  m.Header(),
   436  			OldNode: NodeID(in.Oldnodeid),
   437  			NewName: string(newName),
   438  		}
   439  
   440  	case opMknod:
   441  		in := (*mknodIn)(m.data())
   442  		if m.len() < unsafe.Sizeof(*in) {
   443  			goto corrupt
   444  		}
   445  		name := m.bytes()[unsafe.Sizeof(*in):]
   446  		if len(name) < 2 || name[len(name)-1] != '\x00' {
   447  			goto corrupt
   448  		}
   449  		name = name[:len(name)-1]
   450  		req = &MknodRequest{
   451  			Header: m.Header(),
   452  			Mode:   fileMode(in.Mode),
   453  			Rdev:   in.Rdev,
   454  			Name:   string(name),
   455  		}
   456  
   457  	case opMkdir:
   458  		in := (*mkdirIn)(m.data())
   459  		if m.len() < unsafe.Sizeof(*in) {
   460  			goto corrupt
   461  		}
   462  		name := m.bytes()[unsafe.Sizeof(*in):]
   463  		i := bytes.IndexByte(name, '\x00')
   464  		if i < 0 {
   465  			goto corrupt
   466  		}
   467  		req = &MkdirRequest{
   468  			Header: m.Header(),
   469  			Name:   string(name[:i]),
   470  			// observed on Linux: mkdirIn.Mode & syscall.S_IFMT == 0,
   471  			// and this causes fileMode to go into it's "no idea"
   472  			// code branch; enforce type to directory
   473  			Mode: fileMode((in.Mode &^ syscall.S_IFMT) | syscall.S_IFDIR),
   474  		}
   475  
   476  	case opUnlink, opRmdir:
   477  		buf := m.bytes()
   478  		n := len(buf)
   479  		if n == 0 || buf[n-1] != '\x00' {
   480  			goto corrupt
   481  		}
   482  		req = &RemoveRequest{
   483  			Header: m.Header(),
   484  			Name:   string(buf[:n-1]),
   485  			Dir:    m.hdr.Opcode == opRmdir,
   486  		}
   487  
   488  	case opRename:
   489  		in := (*renameIn)(m.data())
   490  		if m.len() < unsafe.Sizeof(*in) {
   491  			goto corrupt
   492  		}
   493  		newDirNodeID := NodeID(in.Newdir)
   494  		oldNew := m.bytes()[unsafe.Sizeof(*in):]
   495  		// oldNew should be "old\x00new\x00"
   496  		if len(oldNew) < 4 {
   497  			goto corrupt
   498  		}
   499  		if oldNew[len(oldNew)-1] != '\x00' {
   500  			goto corrupt
   501  		}
   502  		i := bytes.IndexByte(oldNew, '\x00')
   503  		if i < 0 {
   504  			goto corrupt
   505  		}
   506  		oldName, newName := string(oldNew[:i]), string(oldNew[i+1:len(oldNew)-1])
   507  		req = &RenameRequest{
   508  			Header:  m.Header(),
   509  			NewDir:  newDirNodeID,
   510  			OldName: oldName,
   511  			NewName: newName,
   512  		}
   513  
   514  	case opOpendir, opOpen:
   515  		in := (*openIn)(m.data())
   516  		if m.len() < unsafe.Sizeof(*in) {
   517  			goto corrupt
   518  		}
   519  		req = &OpenRequest{
   520  			Header: m.Header(),
   521  			Dir:    m.hdr.Opcode == opOpendir,
   522  			Flags:  openFlags(in.Flags),
   523  		}
   524  
   525  	case opRead, opReaddir:
   526  		in := (*readIn)(m.data())
   527  		if m.len() < unsafe.Sizeof(*in) {
   528  			goto corrupt
   529  		}
   530  		req = &ReadRequest{
   531  			Header: m.Header(),
   532  			Dir:    m.hdr.Opcode == opReaddir,
   533  			Handle: HandleID(in.Fh),
   534  			Offset: int64(in.Offset),
   535  			Size:   int(in.Size),
   536  		}
   537  
   538  	case opWrite:
   539  		in := (*writeIn)(m.data())
   540  		if m.len() < unsafe.Sizeof(*in) {
   541  			goto corrupt
   542  		}
   543  		r := &WriteRequest{
   544  			Header: m.Header(),
   545  			Handle: HandleID(in.Fh),
   546  			Offset: int64(in.Offset),
   547  			Flags:  WriteFlags(in.WriteFlags),
   548  		}
   549  		buf := m.bytes()[unsafe.Sizeof(*in):]
   550  		if uint32(len(buf)) < in.Size {
   551  			goto corrupt
   552  		}
   553  		r.Data = buf
   554  		req = r
   555  
   556  	case opStatfs:
   557  		req = &StatfsRequest{
   558  			Header: m.Header(),
   559  		}
   560  
   561  	case opRelease, opReleasedir:
   562  		in := (*releaseIn)(m.data())
   563  		if m.len() < unsafe.Sizeof(*in) {
   564  			goto corrupt
   565  		}
   566  		req = &ReleaseRequest{
   567  			Header:       m.Header(),
   568  			Dir:          m.hdr.Opcode == opReleasedir,
   569  			Handle:       HandleID(in.Fh),
   570  			Flags:        openFlags(in.Flags),
   571  			ReleaseFlags: ReleaseFlags(in.ReleaseFlags),
   572  			LockOwner:    in.LockOwner,
   573  		}
   574  
   575  	case opFsync, opFsyncdir:
   576  		in := (*fsyncIn)(m.data())
   577  		if m.len() < unsafe.Sizeof(*in) {
   578  			goto corrupt
   579  		}
   580  		req = &FsyncRequest{
   581  			Dir:    m.hdr.Opcode == opFsyncdir,
   582  			Header: m.Header(),
   583  			Handle: HandleID(in.Fh),
   584  			Flags:  in.FsyncFlags,
   585  		}
   586  
   587  	case opSetxattr:
   588  		in := (*setxattrIn)(m.data())
   589  		if m.len() < unsafe.Sizeof(*in) {
   590  			goto corrupt
   591  		}
   592  		m.off += int(unsafe.Sizeof(*in))
   593  		name := m.bytes()
   594  		i := bytes.IndexByte(name, '\x00')
   595  		if i < 0 {
   596  			goto corrupt
   597  		}
   598  		xattr := name[i+1:]
   599  		if uint32(len(xattr)) < in.Size {
   600  			goto corrupt
   601  		}
   602  		xattr = xattr[:in.Size]
   603  		req = &SetxattrRequest{
   604  			Header:   m.Header(),
   605  			Flags:    in.Flags,
   606  			Position: in.position(),
   607  			Name:     string(name[:i]),
   608  			Xattr:    xattr,
   609  		}
   610  
   611  	case opGetxattr:
   612  		in := (*getxattrIn)(m.data())
   613  		if m.len() < unsafe.Sizeof(*in) {
   614  			goto corrupt
   615  		}
   616  		name := m.bytes()[unsafe.Sizeof(*in):]
   617  		i := bytes.IndexByte(name, '\x00')
   618  		if i < 0 {
   619  			goto corrupt
   620  		}
   621  		req = &GetxattrRequest{
   622  			Header:   m.Header(),
   623  			Name:     string(name[:i]),
   624  			Size:     in.Size,
   625  			Position: in.position(),
   626  		}
   627  
   628  	case opListxattr:
   629  		in := (*getxattrIn)(m.data())
   630  		if m.len() < unsafe.Sizeof(*in) {
   631  			goto corrupt
   632  		}
   633  		req = &ListxattrRequest{
   634  			Header:   m.Header(),
   635  			Size:     in.Size,
   636  			Position: in.position(),
   637  		}
   638  
   639  	case opRemovexattr:
   640  		buf := m.bytes()
   641  		n := len(buf)
   642  		if n == 0 || buf[n-1] != '\x00' {
   643  			goto corrupt
   644  		}
   645  		req = &RemovexattrRequest{
   646  			Header: m.Header(),
   647  			Name:   string(buf[:n-1]),
   648  		}
   649  
   650  	case opFlush:
   651  		in := (*flushIn)(m.data())
   652  		if m.len() < unsafe.Sizeof(*in) {
   653  			goto corrupt
   654  		}
   655  		req = &FlushRequest{
   656  			Header:    m.Header(),
   657  			Handle:    HandleID(in.Fh),
   658  			Flags:     in.FlushFlags,
   659  			LockOwner: in.LockOwner,
   660  		}
   661  
   662  	case opInit:
   663  		in := (*initIn)(m.data())
   664  		if m.len() < unsafe.Sizeof(*in) {
   665  			goto corrupt
   666  		}
   667  		req = &InitRequest{
   668  			Header:       m.Header(),
   669  			Major:        in.Major,
   670  			Minor:        in.Minor,
   671  			MaxReadahead: in.MaxReadahead,
   672  			Flags:        InitFlags(in.Flags),
   673  		}
   674  
   675  	case opGetlk:
   676  		panic("opGetlk")
   677  	case opSetlk:
   678  		panic("opSetlk")
   679  	case opSetlkw:
   680  		panic("opSetlkw")
   681  
   682  	case opAccess:
   683  		in := (*accessIn)(m.data())
   684  		if m.len() < unsafe.Sizeof(*in) {
   685  			goto corrupt
   686  		}
   687  		req = &AccessRequest{
   688  			Header: m.Header(),
   689  			Mask:   in.Mask,
   690  		}
   691  
   692  	case opCreate:
   693  		in := (*createIn)(m.data())
   694  		if m.len() < unsafe.Sizeof(*in) {
   695  			goto corrupt
   696  		}
   697  		name := m.bytes()[unsafe.Sizeof(*in):]
   698  		i := bytes.IndexByte(name, '\x00')
   699  		if i < 0 {
   700  			goto corrupt
   701  		}
   702  		req = &CreateRequest{
   703  			Header: m.Header(),
   704  			Flags:  openFlags(in.Flags),
   705  			Mode:   fileMode(in.Mode),
   706  			Name:   string(name[:i]),
   707  		}
   708  
   709  	case opInterrupt:
   710  		in := (*interruptIn)(m.data())
   711  		if m.len() < unsafe.Sizeof(*in) {
   712  			goto corrupt
   713  		}
   714  		req = &InterruptRequest{
   715  			Header: m.Header(),
   716  			IntrID: RequestID(in.Unique),
   717  		}
   718  
   719  	case opBmap:
   720  		panic("opBmap")
   721  
   722  	case opDestroy:
   723  		req = &DestroyRequest{
   724  			Header: m.Header(),
   725  		}
   726  
   727  	// OS X
   728  	case opSetvolname:
   729  		panic("opSetvolname")
   730  	case opGetxtimes:
   731  		panic("opGetxtimes")
   732  	case opExchange:
   733  		panic("opExchange")
   734  	}
   735  
   736  	return req, nil
   737  
   738  corrupt:
   739  	Debug(malformedMessage{})
   740  	return nil, fmt.Errorf("fuse: malformed message")
   741  
   742  unrecognized:
   743  	// Unrecognized message.
   744  	// Assume higher-level code will send a "no idea what you mean" error.
   745  	h := m.Header()
   746  	return &h, nil
   747  }
   748  
   749  type bugShortKernelWrite struct {
   750  	Written int64
   751  	Error   string
   752  	Stack   string
   753  }
   754  
   755  func (c *Conn) respond(out *outHeader, n uintptr) {
   756  	c.wio.Lock()
   757  	defer c.wio.Unlock()
   758  	out.Len = uint32(n)
   759  	msg := (*[1 << 30]byte)(unsafe.Pointer(out))[:n]
   760  	nn, err := syscall.Write(c.fd, msg)
   761  	if nn != len(msg) || err != nil {
   762  		Debug(bugShortKernelWrite{
   763  			Written: int64(nn),
   764  			Error:   err.Error(),
   765  			Stack:   stack(),
   766  		})
   767  	}
   768  }
   769  
   770  func (c *Conn) respondData(out *outHeader, n uintptr, data []byte) {
   771  	c.wio.Lock()
   772  	defer c.wio.Unlock()
   773  	// TODO: use writev
   774  	out.Len = uint32(n + uintptr(len(data)))
   775  	msg := make([]byte, out.Len)
   776  	copy(msg, (*[1 << 30]byte)(unsafe.Pointer(out))[:n])
   777  	copy(msg[n:], data)
   778  	syscall.Write(c.fd, msg)
   779  }
   780  
   781  // An InitRequest is the first request sent on a FUSE file system.
   782  type InitRequest struct {
   783  	Header       `json:"-"`
   784  	Major        uint32
   785  	Minor        uint32
   786  	MaxReadahead uint32
   787  	Flags        InitFlags
   788  }
   789  
   790  func (r *InitRequest) String() string {
   791  	return fmt.Sprintf("Init [%s] %d.%d ra=%d fl=%v", &r.Header, r.Major, r.Minor, r.MaxReadahead, r.Flags)
   792  }
   793  
   794  // An InitResponse is the response to an InitRequest.
   795  type InitResponse struct {
   796  	MaxReadahead uint32
   797  	Flags        InitFlags
   798  	MaxWrite     uint32
   799  }
   800  
   801  func (r *InitResponse) String() string {
   802  	return fmt.Sprintf("Init %+v", *r)
   803  }
   804  
   805  // Respond replies to the request with the given response.
   806  func (r *InitRequest) Respond(resp *InitResponse) {
   807  	out := &initOut{
   808  		outHeader:    outHeader{Unique: uint64(r.ID)},
   809  		Major:        kernelVersion,
   810  		Minor:        kernelMinorVersion,
   811  		MaxReadahead: resp.MaxReadahead,
   812  		Flags:        uint32(resp.Flags),
   813  		MaxWrite:     resp.MaxWrite,
   814  	}
   815  	r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
   816  }
   817  
   818  // A StatfsRequest requests information about the mounted file system.
   819  type StatfsRequest struct {
   820  	Header `json:"-"`
   821  }
   822  
   823  func (r *StatfsRequest) String() string {
   824  	return fmt.Sprintf("Statfs [%s]\n", &r.Header)
   825  }
   826  
   827  // Respond replies to the request with the given response.
   828  func (r *StatfsRequest) Respond(resp *StatfsResponse) {
   829  	out := &statfsOut{
   830  		outHeader: outHeader{Unique: uint64(r.ID)},
   831  		St: kstatfs{
   832  			Blocks:  resp.Blocks,
   833  			Bfree:   resp.Bfree,
   834  			Bavail:  resp.Bavail,
   835  			Files:   resp.Files,
   836  			Bsize:   resp.Bsize,
   837  			Namelen: resp.Namelen,
   838  			Frsize:  resp.Frsize,
   839  		},
   840  	}
   841  	r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
   842  }
   843  
   844  // A StatfsResponse is the response to a StatfsRequest.
   845  type StatfsResponse struct {
   846  	Blocks  uint64 // Total data blocks in file system.
   847  	Bfree   uint64 // Free blocks in file system.
   848  	Bavail  uint64 // Free blocks in file system if you're not root.
   849  	Files   uint64 // Total files in file system.
   850  	Ffree   uint64 // Free files in file system.
   851  	Bsize   uint32 // Block size
   852  	Namelen uint32 // Maximum file name length?
   853  	Frsize  uint32 // ?
   854  }
   855  
   856  func (r *StatfsResponse) String() string {
   857  	return fmt.Sprintf("Statfs %+v", *r)
   858  }
   859  
   860  // An AccessRequest asks whether the file can be accessed
   861  // for the purpose specified by the mask.
   862  type AccessRequest struct {
   863  	Header `json:"-"`
   864  	Mask   uint32
   865  }
   866  
   867  func (r *AccessRequest) String() string {
   868  	return fmt.Sprintf("Access [%s] mask=%#x", &r.Header, r.Mask)
   869  }
   870  
   871  // Respond replies to the request indicating that access is allowed.
   872  // To deny access, use RespondError.
   873  func (r *AccessRequest) Respond() {
   874  	out := &outHeader{Unique: uint64(r.ID)}
   875  	r.Conn.respond(out, unsafe.Sizeof(*out))
   876  }
   877  
   878  // An Attr is the metadata for a single file or directory.
   879  type Attr struct {
   880  	Inode  uint64      // inode number
   881  	Size   uint64      // size in bytes
   882  	Blocks uint64      // size in blocks
   883  	Atime  time.Time   // time of last access
   884  	Mtime  time.Time   // time of last modification
   885  	Ctime  time.Time   // time of last inode change
   886  	Crtime time.Time   // time of creation (OS X only)
   887  	Mode   os.FileMode // file mode
   888  	Nlink  uint32      // number of links
   889  	Uid    uint32      // owner uid
   890  	Gid    uint32      // group gid
   891  	Rdev   uint32      // device numbers
   892  	Flags  uint32      // chflags(2) flags (OS X only)
   893  }
   894  
   895  func unix(t time.Time) (sec uint64, nsec uint32) {
   896  	nano := t.UnixNano()
   897  	sec = uint64(nano / 1e9)
   898  	nsec = uint32(nano % 1e9)
   899  	return
   900  }
   901  
   902  func (a *Attr) attr() (out attr) {
   903  	out.Ino = a.Inode
   904  	out.Size = a.Size
   905  	out.Blocks = a.Blocks
   906  	out.Atime, out.AtimeNsec = unix(a.Atime)
   907  	out.Mtime, out.MtimeNsec = unix(a.Mtime)
   908  	out.Ctime, out.CtimeNsec = unix(a.Ctime)
   909  	out.SetCrtime(unix(a.Crtime))
   910  	out.Mode = uint32(a.Mode) & 0777
   911  	switch {
   912  	default:
   913  		out.Mode |= syscall.S_IFREG
   914  	case a.Mode&os.ModeDir != 0:
   915  		out.Mode |= syscall.S_IFDIR
   916  	case a.Mode&os.ModeDevice != 0:
   917  		if a.Mode&os.ModeCharDevice != 0 {
   918  			out.Mode |= syscall.S_IFCHR
   919  		} else {
   920  			out.Mode |= syscall.S_IFBLK
   921  		}
   922  	case a.Mode&os.ModeNamedPipe != 0:
   923  		out.Mode |= syscall.S_IFIFO
   924  	case a.Mode&os.ModeSymlink != 0:
   925  		out.Mode |= syscall.S_IFLNK
   926  	case a.Mode&os.ModeSocket != 0:
   927  		out.Mode |= syscall.S_IFSOCK
   928  	}
   929  	if a.Mode&os.ModeSetuid != 0 {
   930  		out.Mode |= syscall.S_ISUID
   931  	}
   932  	if a.Mode&os.ModeSetgid != 0 {
   933  		out.Mode |= syscall.S_ISGID
   934  	}
   935  	out.Nlink = a.Nlink
   936  	if out.Nlink < 1 {
   937  		out.Nlink = 1
   938  	}
   939  	out.Uid = a.Uid
   940  	out.Gid = a.Gid
   941  	out.Rdev = a.Rdev
   942  	out.SetFlags(a.Flags)
   943  
   944  	return
   945  }
   946  
   947  // A GetattrRequest asks for the metadata for the file denoted by r.Node.
   948  type GetattrRequest struct {
   949  	Header `json:"-"`
   950  }
   951  
   952  func (r *GetattrRequest) String() string {
   953  	return fmt.Sprintf("Getattr [%s]", &r.Header)
   954  }
   955  
   956  // Respond replies to the request with the given response.
   957  func (r *GetattrRequest) Respond(resp *GetattrResponse) {
   958  	out := &attrOut{
   959  		outHeader:     outHeader{Unique: uint64(r.ID)},
   960  		AttrValid:     uint64(resp.AttrValid / time.Second),
   961  		AttrValidNsec: uint32(resp.AttrValid % time.Second / time.Nanosecond),
   962  		Attr:          resp.Attr.attr(),
   963  	}
   964  	r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
   965  }
   966  
   967  // A GetattrResponse is the response to a GetattrRequest.
   968  type GetattrResponse struct {
   969  	AttrValid time.Duration // how long Attr can be cached
   970  	Attr      Attr          // file attributes
   971  }
   972  
   973  func (r *GetattrResponse) String() string {
   974  	return fmt.Sprintf("Getattr %+v", *r)
   975  }
   976  
   977  // A GetxattrRequest asks for the extended attributes associated with r.Node.
   978  type GetxattrRequest struct {
   979  	Header `json:"-"`
   980  
   981  	// Maximum size to return.
   982  	Size uint32
   983  
   984  	// Name of the attribute requested.
   985  	Name string
   986  
   987  	// Offset within extended attributes.
   988  	//
   989  	// Only valid for OS X, and then only with the resource fork
   990  	// attribute.
   991  	Position uint32
   992  }
   993  
   994  func (r *GetxattrRequest) String() string {
   995  	return fmt.Sprintf("Getxattr [%s] %q %d @%d", &r.Header, r.Name, r.Size, r.Position)
   996  }
   997  
   998  // Respond replies to the request with the given response.
   999  func (r *GetxattrRequest) Respond(resp *GetxattrResponse) {
  1000  	if r.Size == 0 {
  1001  		out := &getxattrOut{
  1002  			outHeader: outHeader{Unique: uint64(r.ID)},
  1003  			Size:      uint32(len(resp.Xattr)),
  1004  		}
  1005  		r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
  1006  	} else {
  1007  		out := &outHeader{Unique: uint64(r.ID)}
  1008  		r.Conn.respondData(out, unsafe.Sizeof(*out), resp.Xattr)
  1009  	}
  1010  }
  1011  
  1012  func (r *GetxattrRequest) RespondError(err Error) {
  1013  	err = translateGetxattrError(err)
  1014  	r.Header.RespondError(err)
  1015  }
  1016  
  1017  // A GetxattrResponse is the response to a GetxattrRequest.
  1018  type GetxattrResponse struct {
  1019  	Xattr []byte
  1020  }
  1021  
  1022  func (r *GetxattrResponse) String() string {
  1023  	return fmt.Sprintf("Getxattr %x", r.Xattr)
  1024  }
  1025  
  1026  // A ListxattrRequest asks to list the extended attributes associated with r.Node.
  1027  type ListxattrRequest struct {
  1028  	Header   `json:"-"`
  1029  	Size     uint32 // maximum size to return
  1030  	Position uint32 // offset within attribute list
  1031  }
  1032  
  1033  func (r *ListxattrRequest) String() string {
  1034  	return fmt.Sprintf("Listxattr [%s] %d @%d", &r.Header, r.Size, r.Position)
  1035  }
  1036  
  1037  // Respond replies to the request with the given response.
  1038  func (r *ListxattrRequest) Respond(resp *ListxattrResponse) {
  1039  	if r.Size == 0 {
  1040  		out := &getxattrOut{
  1041  			outHeader: outHeader{Unique: uint64(r.ID)},
  1042  			Size:      uint32(len(resp.Xattr)),
  1043  		}
  1044  		r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
  1045  	} else {
  1046  		out := &outHeader{Unique: uint64(r.ID)}
  1047  		r.Conn.respondData(out, unsafe.Sizeof(*out), resp.Xattr)
  1048  	}
  1049  }
  1050  
  1051  // A ListxattrResponse is the response to a ListxattrRequest.
  1052  type ListxattrResponse struct {
  1053  	Xattr []byte
  1054  }
  1055  
  1056  func (r *ListxattrResponse) String() string {
  1057  	return fmt.Sprintf("Listxattr %x", r.Xattr)
  1058  }
  1059  
  1060  // Append adds an extended attribute name to the response.
  1061  func (r *ListxattrResponse) Append(names ...string) {
  1062  	for _, name := range names {
  1063  		r.Xattr = append(r.Xattr, name...)
  1064  		r.Xattr = append(r.Xattr, '\x00')
  1065  	}
  1066  }
  1067  
  1068  // A RemovexattrRequest asks to remove an extended attribute associated with r.Node.
  1069  type RemovexattrRequest struct {
  1070  	Header `json:"-"`
  1071  	Name   string // name of extended attribute
  1072  }
  1073  
  1074  func (r *RemovexattrRequest) String() string {
  1075  	return fmt.Sprintf("Removexattr [%s] %q", &r.Header, r.Name)
  1076  }
  1077  
  1078  // Respond replies to the request, indicating that the attribute was removed.
  1079  func (r *RemovexattrRequest) Respond() {
  1080  	out := &outHeader{Unique: uint64(r.ID)}
  1081  	r.Conn.respond(out, unsafe.Sizeof(*out))
  1082  }
  1083  
  1084  func (r *RemovexattrRequest) RespondError(err Error) {
  1085  	err = translateGetxattrError(err)
  1086  	r.Header.RespondError(err)
  1087  }
  1088  
  1089  // A SetxattrRequest asks to set an extended attribute associated with a file.
  1090  type SetxattrRequest struct {
  1091  	Header `json:"-"`
  1092  
  1093  	// Flags can make the request fail if attribute does/not already
  1094  	// exist. Unfortunately, the constants are platform-specific and
  1095  	// not exposed by Go1.2. Look for XATTR_CREATE, XATTR_REPLACE.
  1096  	//
  1097  	// TODO improve this later
  1098  	//
  1099  	// TODO XATTR_CREATE and exist -> EEXIST
  1100  	//
  1101  	// TODO XATTR_REPLACE and not exist -> ENODATA
  1102  	Flags uint32
  1103  
  1104  	// Offset within extended attributes.
  1105  	//
  1106  	// Only valid for OS X, and then only with the resource fork
  1107  	// attribute.
  1108  	Position uint32
  1109  
  1110  	Name  string
  1111  	Xattr []byte
  1112  }
  1113  
  1114  func (r *SetxattrRequest) String() string {
  1115  	return fmt.Sprintf("Setxattr [%s] %q %x fl=%v @%#x", &r.Header, r.Name, r.Xattr, r.Flags, r.Position)
  1116  }
  1117  
  1118  // Respond replies to the request, indicating that the extended attribute was set.
  1119  func (r *SetxattrRequest) Respond() {
  1120  	out := &outHeader{Unique: uint64(r.ID)}
  1121  	r.Conn.respond(out, unsafe.Sizeof(*out))
  1122  }
  1123  
  1124  func (r *SetxattrRequest) RespondError(err Error) {
  1125  	err = translateGetxattrError(err)
  1126  	r.Header.RespondError(err)
  1127  }
  1128  
  1129  // A LookupRequest asks to look up the given name in the directory named by r.Node.
  1130  type LookupRequest struct {
  1131  	Header `json:"-"`
  1132  	Name   string
  1133  }
  1134  
  1135  func (r *LookupRequest) String() string {
  1136  	return fmt.Sprintf("Lookup [%s] %q", &r.Header, r.Name)
  1137  }
  1138  
  1139  // Respond replies to the request with the given response.
  1140  func (r *LookupRequest) Respond(resp *LookupResponse) {
  1141  	out := &entryOut{
  1142  		outHeader:      outHeader{Unique: uint64(r.ID)},
  1143  		Nodeid:         uint64(resp.Node),
  1144  		Generation:     resp.Generation,
  1145  		EntryValid:     uint64(resp.EntryValid / time.Second),
  1146  		EntryValidNsec: uint32(resp.EntryValid % time.Second / time.Nanosecond),
  1147  		AttrValid:      uint64(resp.AttrValid / time.Second),
  1148  		AttrValidNsec:  uint32(resp.AttrValid % time.Second / time.Nanosecond),
  1149  		Attr:           resp.Attr.attr(),
  1150  	}
  1151  	r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
  1152  }
  1153  
  1154  // A LookupResponse is the response to a LookupRequest.
  1155  type LookupResponse struct {
  1156  	Node       NodeID
  1157  	Generation uint64
  1158  	EntryValid time.Duration
  1159  	AttrValid  time.Duration
  1160  	Attr       Attr
  1161  }
  1162  
  1163  func (r *LookupResponse) String() string {
  1164  	return fmt.Sprintf("Lookup %+v", *r)
  1165  }
  1166  
  1167  // An OpenRequest asks to open a file or directory
  1168  type OpenRequest struct {
  1169  	Header `json:"-"`
  1170  	Dir    bool // is this Opendir?
  1171  	Flags  OpenFlags
  1172  }
  1173  
  1174  func (r *OpenRequest) String() string {
  1175  	return fmt.Sprintf("Open [%s] dir=%v fl=%v", &r.Header, r.Dir, r.Flags)
  1176  }
  1177  
  1178  // Respond replies to the request with the given response.
  1179  func (r *OpenRequest) Respond(resp *OpenResponse) {
  1180  	out := &openOut{
  1181  		outHeader: outHeader{Unique: uint64(r.ID)},
  1182  		Fh:        uint64(resp.Handle),
  1183  		OpenFlags: uint32(resp.Flags),
  1184  	}
  1185  	r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
  1186  }
  1187  
  1188  // A OpenResponse is the response to a OpenRequest.
  1189  type OpenResponse struct {
  1190  	Handle HandleID
  1191  	Flags  OpenResponseFlags
  1192  }
  1193  
  1194  func (r *OpenResponse) String() string {
  1195  	return fmt.Sprintf("Open %+v", *r)
  1196  }
  1197  
  1198  // A CreateRequest asks to create and open a file (not a directory).
  1199  type CreateRequest struct {
  1200  	Header `json:"-"`
  1201  	Name   string
  1202  	Flags  OpenFlags
  1203  	Mode   os.FileMode
  1204  }
  1205  
  1206  func (r *CreateRequest) String() string {
  1207  	return fmt.Sprintf("Create [%s] %q fl=%v mode=%v", &r.Header, r.Name, r.Flags, r.Mode)
  1208  }
  1209  
  1210  // Respond replies to the request with the given response.
  1211  func (r *CreateRequest) Respond(resp *CreateResponse) {
  1212  	out := &createOut{
  1213  		outHeader: outHeader{Unique: uint64(r.ID)},
  1214  
  1215  		Nodeid:         uint64(resp.Node),
  1216  		Generation:     resp.Generation,
  1217  		EntryValid:     uint64(resp.EntryValid / time.Second),
  1218  		EntryValidNsec: uint32(resp.EntryValid % time.Second / time.Nanosecond),
  1219  		AttrValid:      uint64(resp.AttrValid / time.Second),
  1220  		AttrValidNsec:  uint32(resp.AttrValid % time.Second / time.Nanosecond),
  1221  		Attr:           resp.Attr.attr(),
  1222  
  1223  		Fh:        uint64(resp.Handle),
  1224  		OpenFlags: uint32(resp.Flags),
  1225  	}
  1226  	r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
  1227  }
  1228  
  1229  // A CreateResponse is the response to a CreateRequest.
  1230  // It describes the created node and opened handle.
  1231  type CreateResponse struct {
  1232  	LookupResponse
  1233  	OpenResponse
  1234  }
  1235  
  1236  func (r *CreateResponse) String() string {
  1237  	return fmt.Sprintf("Create %+v", *r)
  1238  }
  1239  
  1240  // A MkdirRequest asks to create (but not open) a directory.
  1241  type MkdirRequest struct {
  1242  	Header `json:"-"`
  1243  	Name   string
  1244  	Mode   os.FileMode
  1245  }
  1246  
  1247  func (r *MkdirRequest) String() string {
  1248  	return fmt.Sprintf("Mkdir [%s] %q mode=%v", &r.Header, r.Name, r.Mode)
  1249  }
  1250  
  1251  // Respond replies to the request with the given response.
  1252  func (r *MkdirRequest) Respond(resp *MkdirResponse) {
  1253  	out := &entryOut{
  1254  		outHeader:      outHeader{Unique: uint64(r.ID)},
  1255  		Nodeid:         uint64(resp.Node),
  1256  		Generation:     resp.Generation,
  1257  		EntryValid:     uint64(resp.EntryValid / time.Second),
  1258  		EntryValidNsec: uint32(resp.EntryValid % time.Second / time.Nanosecond),
  1259  		AttrValid:      uint64(resp.AttrValid / time.Second),
  1260  		AttrValidNsec:  uint32(resp.AttrValid % time.Second / time.Nanosecond),
  1261  		Attr:           resp.Attr.attr(),
  1262  	}
  1263  	r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
  1264  }
  1265  
  1266  // A MkdirResponse is the response to a MkdirRequest.
  1267  type MkdirResponse struct {
  1268  	LookupResponse
  1269  }
  1270  
  1271  func (r *MkdirResponse) String() string {
  1272  	return fmt.Sprintf("Mkdir %+v", *r)
  1273  }
  1274  
  1275  // A ReadRequest asks to read from an open file.
  1276  type ReadRequest struct {
  1277  	Header `json:"-"`
  1278  	Dir    bool // is this Readdir?
  1279  	Handle HandleID
  1280  	Offset int64
  1281  	Size   int
  1282  }
  1283  
  1284  func (r *ReadRequest) String() string {
  1285  	return fmt.Sprintf("Read [%s] %#x %d @%#x dir=%v", &r.Header, r.Handle, r.Size, r.Offset, r.Dir)
  1286  }
  1287  
  1288  // Respond replies to the request with the given response.
  1289  func (r *ReadRequest) Respond(resp *ReadResponse) {
  1290  	out := &outHeader{Unique: uint64(r.ID)}
  1291  	r.Conn.respondData(out, unsafe.Sizeof(*out), resp.Data)
  1292  }
  1293  
  1294  // A ReadResponse is the response to a ReadRequest.
  1295  type ReadResponse struct {
  1296  	Data []byte
  1297  }
  1298  
  1299  func (r *ReadResponse) String() string {
  1300  	return fmt.Sprintf("Read %d", len(r.Data))
  1301  }
  1302  
  1303  type jsonReadResponse struct {
  1304  	Len uint64
  1305  }
  1306  
  1307  func (r *ReadResponse) MarshalJSON() ([]byte, error) {
  1308  	j := jsonReadResponse{
  1309  		Len: uint64(len(r.Data)),
  1310  	}
  1311  	return json.Marshal(j)
  1312  }
  1313  
  1314  // A ReleaseRequest asks to release (close) an open file handle.
  1315  type ReleaseRequest struct {
  1316  	Header       `json:"-"`
  1317  	Dir          bool // is this Releasedir?
  1318  	Handle       HandleID
  1319  	Flags        OpenFlags // flags from OpenRequest
  1320  	ReleaseFlags ReleaseFlags
  1321  	LockOwner    uint32
  1322  }
  1323  
  1324  func (r *ReleaseRequest) String() string {
  1325  	return fmt.Sprintf("Release [%s] %#x fl=%v rfl=%v owner=%#x", &r.Header, r.Handle, r.Flags, r.ReleaseFlags, r.LockOwner)
  1326  }
  1327  
  1328  // Respond replies to the request, indicating that the handle has been released.
  1329  func (r *ReleaseRequest) Respond() {
  1330  	out := &outHeader{Unique: uint64(r.ID)}
  1331  	r.Conn.respond(out, unsafe.Sizeof(*out))
  1332  }
  1333  
  1334  // A DestroyRequest is sent by the kernel when unmounting the file system.
  1335  // No more requests will be received after this one, but it should still be
  1336  // responded to.
  1337  type DestroyRequest struct {
  1338  	Header `json:"-"`
  1339  }
  1340  
  1341  func (r *DestroyRequest) String() string {
  1342  	return fmt.Sprintf("Destroy [%s]", &r.Header)
  1343  }
  1344  
  1345  // Respond replies to the request.
  1346  func (r *DestroyRequest) Respond() {
  1347  	out := &outHeader{Unique: uint64(r.ID)}
  1348  	r.Conn.respond(out, unsafe.Sizeof(*out))
  1349  }
  1350  
  1351  // A ForgetRequest is sent by the kernel when forgetting about r.Node
  1352  // as returned by r.N lookup requests.
  1353  type ForgetRequest struct {
  1354  	Header `json:"-"`
  1355  	N      uint64
  1356  }
  1357  
  1358  func (r *ForgetRequest) String() string {
  1359  	return fmt.Sprintf("Forget [%s] %d", &r.Header, r.N)
  1360  }
  1361  
  1362  // Respond replies to the request, indicating that the forgetfulness has been recorded.
  1363  func (r *ForgetRequest) Respond() {
  1364  	// Don't reply to forget messages.
  1365  }
  1366  
  1367  // A Dirent represents a single directory entry.
  1368  type Dirent struct {
  1369  	// Inode this entry names.
  1370  	Inode uint64
  1371  
  1372  	// Type of the entry, for example DT_File.
  1373  	//
  1374  	// Setting this is optional. The zero value (DT_Unknown) means
  1375  	// callers will just need to do a Getattr when the type is
  1376  	// needed. Providing a type can speed up operations
  1377  	// significantly.
  1378  	Type DirentType
  1379  
  1380  	// Name of the entry
  1381  	Name string
  1382  }
  1383  
  1384  // Type of an entry in a directory listing.
  1385  type DirentType uint32
  1386  
  1387  const (
  1388  	// These don't quite match os.FileMode; especially there's an
  1389  	// explicit unknown, instead of zero value meaning file. They
  1390  	// are also not quite syscall.DT_*; nothing says the FUSE
  1391  	// protocol follows those, and even if they were, we don't
  1392  	// want each fs to fiddle with syscall.
  1393  
  1394  	// The shift by 12 is hardcoded in the FUSE userspace
  1395  	// low-level C library, so it's safe here.
  1396  
  1397  	DT_Unknown DirentType = 0
  1398  	DT_Socket  DirentType = syscall.S_IFSOCK >> 12
  1399  	DT_Link    DirentType = syscall.S_IFLNK >> 12
  1400  	DT_File    DirentType = syscall.S_IFREG >> 12
  1401  	DT_Block   DirentType = syscall.S_IFBLK >> 12
  1402  	DT_Dir     DirentType = syscall.S_IFDIR >> 12
  1403  	DT_Char    DirentType = syscall.S_IFCHR >> 12
  1404  	DT_FIFO    DirentType = syscall.S_IFIFO >> 12
  1405  )
  1406  
  1407  func (t DirentType) String() string {
  1408  	switch t {
  1409  	case DT_Unknown:
  1410  		return "unknown"
  1411  	case DT_Socket:
  1412  		return "socket"
  1413  	case DT_Link:
  1414  		return "link"
  1415  	case DT_File:
  1416  		return "file"
  1417  	case DT_Block:
  1418  		return "block"
  1419  	case DT_Dir:
  1420  		return "dir"
  1421  	case DT_Char:
  1422  		return "char"
  1423  	case DT_FIFO:
  1424  		return "fifo"
  1425  	}
  1426  	return "invalid"
  1427  }
  1428  
  1429  // AppendDirent appends the encoded form of a directory entry to data
  1430  // and returns the resulting slice.
  1431  func AppendDirent(data []byte, dir Dirent) []byte {
  1432  	de := dirent{
  1433  		Ino:     dir.Inode,
  1434  		Namelen: uint32(len(dir.Name)),
  1435  		Type:    uint32(dir.Type),
  1436  	}
  1437  	de.Off = uint64(len(data) + direntSize + (len(dir.Name)+7)&^7)
  1438  	data = append(data, (*[direntSize]byte)(unsafe.Pointer(&de))[:]...)
  1439  	data = append(data, dir.Name...)
  1440  	n := direntSize + uintptr(len(dir.Name))
  1441  	if n%8 != 0 {
  1442  		var pad [8]byte
  1443  		data = append(data, pad[:8-n%8]...)
  1444  	}
  1445  	return data
  1446  }
  1447  
  1448  // A WriteRequest asks to write to an open file.
  1449  type WriteRequest struct {
  1450  	Header
  1451  	Handle HandleID
  1452  	Offset int64
  1453  	Data   []byte
  1454  	Flags  WriteFlags
  1455  }
  1456  
  1457  func (r *WriteRequest) String() string {
  1458  	return fmt.Sprintf("Write [%s] %#x %d @%d fl=%v", &r.Header, r.Handle, len(r.Data), r.Offset, r.Flags)
  1459  }
  1460  
  1461  type jsonWriteRequest struct {
  1462  	Handle HandleID
  1463  	Offset int64
  1464  	Len    uint64
  1465  	Flags  WriteFlags
  1466  }
  1467  
  1468  func (r *WriteRequest) MarshalJSON() ([]byte, error) {
  1469  	j := jsonWriteRequest{
  1470  		Handle: r.Handle,
  1471  		Offset: r.Offset,
  1472  		Len:    uint64(len(r.Data)),
  1473  		Flags:  r.Flags,
  1474  	}
  1475  	return json.Marshal(j)
  1476  }
  1477  
  1478  // Respond replies to the request with the given response.
  1479  func (r *WriteRequest) Respond(resp *WriteResponse) {
  1480  	out := &writeOut{
  1481  		outHeader: outHeader{Unique: uint64(r.ID)},
  1482  		Size:      uint32(resp.Size),
  1483  	}
  1484  	r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
  1485  }
  1486  
  1487  // A WriteResponse replies to a write indicating how many bytes were written.
  1488  type WriteResponse struct {
  1489  	Size int
  1490  }
  1491  
  1492  func (r *WriteResponse) String() string {
  1493  	return fmt.Sprintf("Write %+v", *r)
  1494  }
  1495  
  1496  // A SetattrRequest asks to change one or more attributes associated with a file,
  1497  // as indicated by Valid.
  1498  type SetattrRequest struct {
  1499  	Header `json:"-"`
  1500  	Valid  SetattrValid
  1501  	Handle HandleID
  1502  	Size   uint64
  1503  	Atime  time.Time
  1504  	Mtime  time.Time
  1505  	Mode   os.FileMode
  1506  	Uid    uint32
  1507  	Gid    uint32
  1508  
  1509  	// OS X only
  1510  	Bkuptime time.Time
  1511  	Chgtime  time.Time
  1512  	Crtime   time.Time
  1513  	Flags    uint32 // see chflags(2)
  1514  }
  1515  
  1516  func (r *SetattrRequest) String() string {
  1517  	var buf bytes.Buffer
  1518  	fmt.Fprintf(&buf, "Setattr [%s]", &r.Header)
  1519  	if r.Valid.Mode() {
  1520  		fmt.Fprintf(&buf, " mode=%v", r.Mode)
  1521  	}
  1522  	if r.Valid.Uid() {
  1523  		fmt.Fprintf(&buf, " uid=%d", r.Uid)
  1524  	}
  1525  	if r.Valid.Gid() {
  1526  		fmt.Fprintf(&buf, " gid=%d", r.Gid)
  1527  	}
  1528  	if r.Valid.Size() {
  1529  		fmt.Fprintf(&buf, " size=%d", r.Size)
  1530  	}
  1531  	if r.Valid.Atime() {
  1532  		fmt.Fprintf(&buf, " atime=%v", r.Atime)
  1533  	}
  1534  	if r.Valid.AtimeNow() {
  1535  		fmt.Fprintf(&buf, " atime=now")
  1536  	}
  1537  	if r.Valid.Mtime() {
  1538  		fmt.Fprintf(&buf, " mtime=%v", r.Mtime)
  1539  	}
  1540  	if r.Valid.MtimeNow() {
  1541  		fmt.Fprintf(&buf, " mtime=now")
  1542  	}
  1543  	if r.Valid.Handle() {
  1544  		fmt.Fprintf(&buf, " handle=%#x", r.Handle)
  1545  	} else {
  1546  		fmt.Fprintf(&buf, " handle=INVALID-%#x", r.Handle)
  1547  	}
  1548  	if r.Valid.LockOwner() {
  1549  		fmt.Fprintf(&buf, " lockowner")
  1550  	}
  1551  	if r.Valid.Crtime() {
  1552  		fmt.Fprintf(&buf, " crtime=%v", r.Crtime)
  1553  	}
  1554  	if r.Valid.Chgtime() {
  1555  		fmt.Fprintf(&buf, " chgtime=%v", r.Chgtime)
  1556  	}
  1557  	if r.Valid.Bkuptime() {
  1558  		fmt.Fprintf(&buf, " bkuptime=%v", r.Bkuptime)
  1559  	}
  1560  	if r.Valid.Flags() {
  1561  		fmt.Fprintf(&buf, " flags=%#x", r.Flags)
  1562  	}
  1563  	return buf.String()
  1564  }
  1565  
  1566  // Respond replies to the request with the given response,
  1567  // giving the updated attributes.
  1568  func (r *SetattrRequest) Respond(resp *SetattrResponse) {
  1569  	out := &attrOut{
  1570  		outHeader:     outHeader{Unique: uint64(r.ID)},
  1571  		AttrValid:     uint64(resp.AttrValid / time.Second),
  1572  		AttrValidNsec: uint32(resp.AttrValid % time.Second / time.Nanosecond),
  1573  		Attr:          resp.Attr.attr(),
  1574  	}
  1575  	r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
  1576  }
  1577  
  1578  // A SetattrResponse is the response to a SetattrRequest.
  1579  type SetattrResponse struct {
  1580  	AttrValid time.Duration // how long Attr can be cached
  1581  	Attr      Attr          // file attributes
  1582  }
  1583  
  1584  func (r *SetattrResponse) String() string {
  1585  	return fmt.Sprintf("Setattr %+v", *r)
  1586  }
  1587  
  1588  // A FlushRequest asks for the current state of an open file to be flushed
  1589  // to storage, as when a file descriptor is being closed.  A single opened Handle
  1590  // may receive multiple FlushRequests over its lifetime.
  1591  type FlushRequest struct {
  1592  	Header    `json:"-"`
  1593  	Handle    HandleID
  1594  	Flags     uint32
  1595  	LockOwner uint64
  1596  }
  1597  
  1598  func (r *FlushRequest) String() string {
  1599  	return fmt.Sprintf("Flush [%s] %#x fl=%#x lk=%#x", &r.Header, r.Handle, r.Flags, r.LockOwner)
  1600  }
  1601  
  1602  // Respond replies to the request, indicating that the flush succeeded.
  1603  func (r *FlushRequest) Respond() {
  1604  	out := &outHeader{Unique: uint64(r.ID)}
  1605  	r.Conn.respond(out, unsafe.Sizeof(*out))
  1606  }
  1607  
  1608  // A RemoveRequest asks to remove a file or directory.
  1609  type RemoveRequest struct {
  1610  	Header `json:"-"`
  1611  	Name   string // name of extended attribute
  1612  	Dir    bool   // is this rmdir?
  1613  }
  1614  
  1615  func (r *RemoveRequest) String() string {
  1616  	return fmt.Sprintf("Remove [%s] %q dir=%v", &r.Header, r.Name, r.Dir)
  1617  }
  1618  
  1619  // Respond replies to the request, indicating that the file was removed.
  1620  func (r *RemoveRequest) Respond() {
  1621  	out := &outHeader{Unique: uint64(r.ID)}
  1622  	r.Conn.respond(out, unsafe.Sizeof(*out))
  1623  }
  1624  
  1625  // A SymlinkRequest is a request to create a symlink making NewName point to Target.
  1626  type SymlinkRequest struct {
  1627  	Header          `json:"-"`
  1628  	NewName, Target string
  1629  }
  1630  
  1631  func (r *SymlinkRequest) String() string {
  1632  	return fmt.Sprintf("Symlink [%s] from %q to target %q", &r.Header, r.NewName, r.Target)
  1633  }
  1634  
  1635  // Respond replies to the request, indicating that the symlink was created.
  1636  func (r *SymlinkRequest) Respond(resp *SymlinkResponse) {
  1637  	out := &entryOut{
  1638  		outHeader:      outHeader{Unique: uint64(r.ID)},
  1639  		Nodeid:         uint64(resp.Node),
  1640  		Generation:     resp.Generation,
  1641  		EntryValid:     uint64(resp.EntryValid / time.Second),
  1642  		EntryValidNsec: uint32(resp.EntryValid % time.Second / time.Nanosecond),
  1643  		AttrValid:      uint64(resp.AttrValid / time.Second),
  1644  		AttrValidNsec:  uint32(resp.AttrValid % time.Second / time.Nanosecond),
  1645  		Attr:           resp.Attr.attr(),
  1646  	}
  1647  	r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
  1648  }
  1649  
  1650  // A SymlinkResponse is the response to a SymlinkRequest.
  1651  type SymlinkResponse struct {
  1652  	LookupResponse
  1653  }
  1654  
  1655  // A ReadlinkRequest is a request to read a symlink's target.
  1656  type ReadlinkRequest struct {
  1657  	Header `json:"-"`
  1658  }
  1659  
  1660  func (r *ReadlinkRequest) String() string {
  1661  	return fmt.Sprintf("Readlink [%s]", &r.Header)
  1662  }
  1663  
  1664  func (r *ReadlinkRequest) Respond(target string) {
  1665  	out := &outHeader{Unique: uint64(r.ID)}
  1666  	r.Conn.respondData(out, unsafe.Sizeof(*out), []byte(target))
  1667  }
  1668  
  1669  // A LinkRequest is a request to create a hard link.
  1670  type LinkRequest struct {
  1671  	Header  `json:"-"`
  1672  	OldNode NodeID
  1673  	NewName string
  1674  }
  1675  
  1676  func (r *LinkRequest) Respond(resp *LookupResponse) {
  1677  	out := &entryOut{
  1678  		outHeader:      outHeader{Unique: uint64(r.ID)},
  1679  		Nodeid:         uint64(resp.Node),
  1680  		Generation:     resp.Generation,
  1681  		EntryValid:     uint64(resp.EntryValid / time.Second),
  1682  		EntryValidNsec: uint32(resp.EntryValid % time.Second / time.Nanosecond),
  1683  		AttrValid:      uint64(resp.AttrValid / time.Second),
  1684  		AttrValidNsec:  uint32(resp.AttrValid % time.Second / time.Nanosecond),
  1685  		Attr:           resp.Attr.attr(),
  1686  	}
  1687  	r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
  1688  }
  1689  
  1690  // A RenameRequest is a request to rename a file.
  1691  type RenameRequest struct {
  1692  	Header           `json:"-"`
  1693  	NewDir           NodeID
  1694  	OldName, NewName string
  1695  }
  1696  
  1697  func (r *RenameRequest) String() string {
  1698  	return fmt.Sprintf("Rename [%s] from %q to dirnode %d %q", &r.Header, r.OldName, r.NewDir, r.NewName)
  1699  }
  1700  
  1701  func (r *RenameRequest) Respond() {
  1702  	out := &outHeader{Unique: uint64(r.ID)}
  1703  	r.Conn.respond(out, unsafe.Sizeof(*out))
  1704  }
  1705  
  1706  type MknodRequest struct {
  1707  	Header `json:"-"`
  1708  	Name   string
  1709  	Mode   os.FileMode
  1710  	Rdev   uint32
  1711  }
  1712  
  1713  func (r *MknodRequest) String() string {
  1714  	return fmt.Sprintf("Mknod [%s] Name %q mode %v rdev %d", &r.Header, r.Name, r.Mode, r.Rdev)
  1715  }
  1716  
  1717  func (r *MknodRequest) Respond(resp *LookupResponse) {
  1718  	out := &entryOut{
  1719  		outHeader:      outHeader{Unique: uint64(r.ID)},
  1720  		Nodeid:         uint64(resp.Node),
  1721  		Generation:     resp.Generation,
  1722  		EntryValid:     uint64(resp.EntryValid / time.Second),
  1723  		EntryValidNsec: uint32(resp.EntryValid % time.Second / time.Nanosecond),
  1724  		AttrValid:      uint64(resp.AttrValid / time.Second),
  1725  		AttrValidNsec:  uint32(resp.AttrValid % time.Second / time.Nanosecond),
  1726  		Attr:           resp.Attr.attr(),
  1727  	}
  1728  	r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
  1729  }
  1730  
  1731  type FsyncRequest struct {
  1732  	Header `json:"-"`
  1733  	Handle HandleID
  1734  	// TODO bit 1 is datasync, not well documented upstream
  1735  	Flags uint32
  1736  	Dir   bool
  1737  }
  1738  
  1739  func (r *FsyncRequest) String() string {
  1740  	return fmt.Sprintf("Fsync [%s] Handle %v Flags %v", &r.Header, r.Handle, r.Flags)
  1741  }
  1742  
  1743  func (r *FsyncRequest) Respond() {
  1744  	out := &outHeader{Unique: uint64(r.ID)}
  1745  	r.Conn.respond(out, unsafe.Sizeof(*out))
  1746  }
  1747  
  1748  // An InterruptRequest is a request to interrupt another pending request. The
  1749  // response to that request should return an error status of EINTR.
  1750  type InterruptRequest struct {
  1751  	Header `json:"-"`
  1752  	IntrID RequestID // ID of the request to be interrupt.
  1753  }
  1754  
  1755  func (r *InterruptRequest) Respond() {
  1756  	// nothing to do here
  1757  }
  1758  
  1759  func (r *InterruptRequest) String() string {
  1760  	return fmt.Sprintf("Interrupt [%s] ID %v", &r.Header, r.IntrID)
  1761  }
  1762  
  1763  /*{
  1764  
  1765  // A XXXRequest xxx.
  1766  type XXXRequest struct {
  1767  	Header `json:"-"`
  1768  	xxx
  1769  }
  1770  
  1771  func (r *XXXRequest) String() string {
  1772  	return fmt.Sprintf("XXX [%s] xxx", &r.Header)
  1773  }
  1774  
  1775  // Respond replies to the request with the given response.
  1776  func (r *XXXRequest) Respond(resp *XXXResponse) {
  1777  	out := &xxxOut{
  1778  		outHeader: outHeader{Unique: uint64(r.ID)},
  1779  		xxx,
  1780  	}
  1781  	r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
  1782  }
  1783  
  1784  // A XXXResponse is the response to a XXXRequest.
  1785  type XXXResponse struct {
  1786  	xxx
  1787  }
  1788  
  1789  func (r *XXXResponse) String() string {
  1790  	return fmt.Sprintf("XXX %+v", *r)
  1791  }
  1792  
  1793   }
  1794  */