mirror of
https://github.com/ipfs/kubo.git
synced 2025-06-26 23:53:19 +08:00
updated bazil.org/fuse
This commit is contained in:
2
Godeps/Godeps.json
generated
2
Godeps/Godeps.json
generated
@ -7,7 +7,7 @@
|
||||
"Deps": [
|
||||
{
|
||||
"ImportPath": "bazil.org/fuse",
|
||||
"Rev": "a04507d54fc3610d38ee951402d8c4acab56c7b1"
|
||||
"Rev": "d62a1291477b51b24becf4def173bd843138c4b6"
|
||||
},
|
||||
{
|
||||
"ImportPath": "bitbucket.org/kardianos/osext",
|
||||
|
7
Godeps/_workspace/src/bazil.org/fuse/debug.go
generated
vendored
7
Godeps/_workspace/src/bazil.org/fuse/debug.go
generated
vendored
@ -11,4 +11,11 @@ func stack() string {
|
||||
|
||||
func nop(msg interface{}) {}
|
||||
|
||||
// Debug is called to output debug messages, including protocol
|
||||
// traces. The default behavior is to do nothing.
|
||||
//
|
||||
// The messages have human-friendly string representations and are
|
||||
// safe to marshal to JSON.
|
||||
//
|
||||
// Implementations must not retain msg.
|
||||
var Debug func(msg interface{}) = nop
|
||||
|
1
Godeps/_workspace/src/bazil.org/fuse/fs/fstestutil/doc.go
generated
vendored
Normal file
1
Godeps/_workspace/src/bazil.org/fuse/fs/fstestutil/doc.go
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
package fstestutil
|
8
Godeps/_workspace/src/bazil.org/fuse/fs/fstestutil/mounted.go
generated
vendored
8
Godeps/_workspace/src/bazil.org/fuse/fs/fstestutil/mounted.go
generated
vendored
@ -55,12 +55,12 @@ func (mnt *Mount) Close() {
|
||||
// workaround).
|
||||
//
|
||||
// After successful return, caller must clean up by calling Close.
|
||||
func Mounted(srv *fs.Server) (*Mount, error) {
|
||||
func Mounted(srv *fs.Server, options ...fuse.MountOption) (*Mount, error) {
|
||||
dir, err := ioutil.TempDir("", "fusetest")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c, err := fuse.Mount(dir)
|
||||
c, err := fuse.Mount(dir, options...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -100,7 +100,7 @@ func Mounted(srv *fs.Server) (*Mount, error) {
|
||||
//
|
||||
// The debug log is not enabled by default. Use `-fuse.debug` or call
|
||||
// DebugByDefault to enable.
|
||||
func MountedT(t testing.TB, filesys fs.FS) (*Mount, error) {
|
||||
func MountedT(t testing.TB, filesys fs.FS, options ...fuse.MountOption) (*Mount, error) {
|
||||
srv := &fs.Server{
|
||||
FS: filesys,
|
||||
}
|
||||
@ -109,5 +109,5 @@ func MountedT(t testing.TB, filesys fs.FS) (*Mount, error) {
|
||||
t.Logf("FUSE: %s", msg)
|
||||
}
|
||||
}
|
||||
return Mounted(srv)
|
||||
return Mounted(srv, options...)
|
||||
}
|
||||
|
14
Godeps/_workspace/src/bazil.org/fuse/fs/fstestutil/mountinfo.go
generated
vendored
Normal file
14
Godeps/_workspace/src/bazil.org/fuse/fs/fstestutil/mountinfo.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
package fstestutil
|
||||
|
||||
// MountInfo describes a mounted file system.
|
||||
type MountInfo struct {
|
||||
FSName string
|
||||
Type string
|
||||
}
|
||||
|
||||
// GetMountInfo finds information about the mount at mnt. It is
|
||||
// intended for use by tests only, and only fetches information
|
||||
// relevant to the current tests.
|
||||
func GetMountInfo(mnt string) (*MountInfo, error) {
|
||||
return getMountInfo(mnt)
|
||||
}
|
41
Godeps/_workspace/src/bazil.org/fuse/fs/fstestutil/mountinfo_darwin.go
generated
vendored
Normal file
41
Godeps/_workspace/src/bazil.org/fuse/fs/fstestutil/mountinfo_darwin.go
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
package fstestutil
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// cstr converts a nil-terminated C string into a Go string
|
||||
func cstr(ca []int8) string {
|
||||
s := make([]byte, 0, len(ca))
|
||||
for _, c := range ca {
|
||||
if c == 0x00 {
|
||||
break
|
||||
}
|
||||
s = append(s, byte(c))
|
||||
}
|
||||
return string(s)
|
||||
}
|
||||
|
||||
var re = regexp.MustCompile(`\\(.)`)
|
||||
|
||||
// unescape removes backslash-escaping. The escaped characters are not
|
||||
// mapped in any way; that is, unescape(`\n` ) == `n`.
|
||||
func unescape(s string) string {
|
||||
return re.ReplaceAllString(s, `$1`)
|
||||
}
|
||||
|
||||
func getMountInfo(mnt string) (*MountInfo, error) {
|
||||
var st syscall.Statfs_t
|
||||
err := syscall.Statfs(mnt, &st)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
i := &MountInfo{
|
||||
// osx getmntent(3) fails to un-escape the data, so we do it..
|
||||
// this might lead to double-unescaping in the future. fun.
|
||||
// TestMountOptionFSNameEvilBackslashDouble checks for that.
|
||||
FSName: unescape(cstr(st.Mntfromname[:])),
|
||||
}
|
||||
return i, nil
|
||||
}
|
51
Godeps/_workspace/src/bazil.org/fuse/fs/fstestutil/mountinfo_linux.go
generated
vendored
Normal file
51
Godeps/_workspace/src/bazil.org/fuse/fs/fstestutil/mountinfo_linux.go
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
package fstestutil
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Linux /proc/mounts shows current mounts.
|
||||
// Same format as /etc/fstab. Quoting getmntent(3):
|
||||
//
|
||||
// Since fields in the mtab and fstab files are separated by whitespace,
|
||||
// octal escapes are used to represent the four characters space (\040),
|
||||
// tab (\011), newline (\012) and backslash (\134) in those files when
|
||||
// they occur in one of the four strings in a mntent structure.
|
||||
//
|
||||
// http://linux.die.net/man/3/getmntent
|
||||
|
||||
var fstabUnescape = strings.NewReplacer(
|
||||
`\040`, "\040",
|
||||
`\011`, "\011",
|
||||
`\012`, "\012",
|
||||
`\134`, "\134",
|
||||
)
|
||||
|
||||
var errNotFound = errors.New("mount not found")
|
||||
|
||||
func getMountInfo(mnt string) (*MountInfo, error) {
|
||||
data, err := ioutil.ReadFile("/proc/mounts")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, line := range strings.Split(string(data), "\n") {
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) < 3 {
|
||||
continue
|
||||
}
|
||||
// Fields are: fsname dir type opts freq passno
|
||||
fsname := fstabUnescape.Replace(fields[0])
|
||||
dir := fstabUnescape.Replace(fields[1])
|
||||
fstype := fstabUnescape.Replace(fields[2])
|
||||
if mnt == dir {
|
||||
info := &MountInfo{
|
||||
FSName: fsname,
|
||||
Type: fstype,
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
}
|
||||
return nil, errNotFound
|
||||
}
|
29
Godeps/_workspace/src/bazil.org/fuse/fs/fstestutil/testfs.go
generated
vendored
Normal file
29
Godeps/_workspace/src/bazil.org/fuse/fs/fstestutil/testfs.go
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
package fstestutil
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/bazil.org/fuse"
|
||||
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/bazil.org/fuse/fs"
|
||||
)
|
||||
|
||||
// SimpleFS is a trivial FS that just implements the Root method.
|
||||
type SimpleFS struct {
|
||||
Node fs.Node
|
||||
}
|
||||
|
||||
var _ = fs.FS(SimpleFS{})
|
||||
|
||||
func (f SimpleFS) Root() (fs.Node, fuse.Error) {
|
||||
return f.Node, nil
|
||||
}
|
||||
|
||||
// File can be embedded in a struct to make it look like a file.
|
||||
type File struct{}
|
||||
|
||||
func (f File) Attr() fuse.Attr { return fuse.Attr{Mode: 0666} }
|
||||
|
||||
// Dir can be embedded in a struct to make it look like a directory.
|
||||
type Dir struct{}
|
||||
|
||||
func (f Dir) Attr() fuse.Attr { return fuse.Attr{Mode: os.ModeDir | 0777} }
|
5
Godeps/_workspace/src/bazil.org/fuse/fs/serve.go
generated
vendored
5
Godeps/_workspace/src/bazil.org/fuse/fs/serve.go
generated
vendored
@ -10,7 +10,6 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -295,6 +294,8 @@ type Server struct {
|
||||
// Function to send debug log messages to. If nil, use fuse.Debug.
|
||||
// Note that changing this or fuse.Debug may not affect existing
|
||||
// calls to Serve.
|
||||
//
|
||||
// See fuse.Debug for the rules that log functions must follow.
|
||||
Debug func(msg interface{})
|
||||
}
|
||||
|
||||
@ -317,7 +318,7 @@ func (s *Server) Serve(c *fuse.Conn) error {
|
||||
|
||||
root, err := sc.fs.Root()
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot obtain root node: %v", syscall.Errno(err.(fuse.Errno)).Error())
|
||||
return fmt.Errorf("cannot obtain root node: %v", err)
|
||||
}
|
||||
sc.node = append(sc.node, nil, &serveNode{inode: 1, node: root, refs: 1})
|
||||
sc.handle = append(sc.handle, nil)
|
||||
|
150
Godeps/_workspace/src/bazil.org/fuse/fs/serve_test.go
generated
vendored
150
Godeps/_workspace/src/bazil.org/fuse/fs/serve_test.go
generated
vendored
@ -87,27 +87,6 @@ func (f childMapFS) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) {
|
||||
return child, nil
|
||||
}
|
||||
|
||||
// simpleFS is a trivial FS that just implements the Root method.
|
||||
type simpleFS struct {
|
||||
node fs.Node
|
||||
}
|
||||
|
||||
var _ = fs.FS(simpleFS{})
|
||||
|
||||
func (f simpleFS) Root() (fs.Node, fuse.Error) {
|
||||
return f.node, nil
|
||||
}
|
||||
|
||||
// file can be embedded in a struct to make it look like a file.
|
||||
type file struct{}
|
||||
|
||||
func (f file) Attr() fuse.Attr { return fuse.Attr{Mode: 0666} }
|
||||
|
||||
// dir can be embedded in a struct to make it look like a directory.
|
||||
type dir struct{}
|
||||
|
||||
func (f dir) Attr() fuse.Attr { return fuse.Attr{Mode: os.ModeDir | 0777} }
|
||||
|
||||
// symlink can be embedded in a struct to make it look like a symlink.
|
||||
type symlink struct {
|
||||
target string
|
||||
@ -261,7 +240,9 @@ func TestStatRoot(t *testing.T) {
|
||||
|
||||
// Test Read calling ReadAll.
|
||||
|
||||
type readAll struct{ file }
|
||||
type readAll struct {
|
||||
fstestutil.File
|
||||
}
|
||||
|
||||
const hi = "hello, world"
|
||||
|
||||
@ -299,7 +280,9 @@ func TestReadAll(t *testing.T) {
|
||||
|
||||
// Test Read.
|
||||
|
||||
type readWithHandleRead struct{ file }
|
||||
type readWithHandleRead struct {
|
||||
fstestutil.File
|
||||
}
|
||||
|
||||
func (readWithHandleRead) Attr() fuse.Attr {
|
||||
return fuse.Attr{
|
||||
@ -327,7 +310,7 @@ func TestReadAllWithHandleRead(t *testing.T) {
|
||||
// Test Release.
|
||||
|
||||
type release struct {
|
||||
file
|
||||
fstestutil.File
|
||||
record.ReleaseWaiter
|
||||
}
|
||||
|
||||
@ -353,7 +336,7 @@ func TestRelease(t *testing.T) {
|
||||
// Test Write calling basic Write, with an fsync thrown in too.
|
||||
|
||||
type write struct {
|
||||
file
|
||||
fstestutil.File
|
||||
record.Writes
|
||||
record.Fsyncs
|
||||
}
|
||||
@ -401,7 +384,7 @@ func TestWrite(t *testing.T) {
|
||||
// Test Write of a larger buffer.
|
||||
|
||||
type writeLarge struct {
|
||||
file
|
||||
fstestutil.File
|
||||
record.Writes
|
||||
}
|
||||
|
||||
@ -446,7 +429,7 @@ func TestWriteLarge(t *testing.T) {
|
||||
// Test Write calling Setattr+Write+Flush.
|
||||
|
||||
type writeTruncateFlush struct {
|
||||
file
|
||||
fstestutil.File
|
||||
record.Writes
|
||||
record.Setattrs
|
||||
record.Flushes
|
||||
@ -479,7 +462,7 @@ func TestWriteTruncateFlush(t *testing.T) {
|
||||
// Test Mkdir.
|
||||
|
||||
type mkdir1 struct {
|
||||
dir
|
||||
fstestutil.Dir
|
||||
record.Mkdirs
|
||||
}
|
||||
|
||||
@ -491,7 +474,7 @@ func (f *mkdir1) Mkdir(req *fuse.MkdirRequest, intr fs.Intr) (fs.Node, fuse.Erro
|
||||
func TestMkdir(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := &mkdir1{}
|
||||
mnt, err := fstestutil.MountedT(t, simpleFS{f})
|
||||
mnt, err := fstestutil.MountedT(t, fstestutil.SimpleFS{f})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -513,12 +496,12 @@ func TestMkdir(t *testing.T) {
|
||||
// Test Create (and fsync)
|
||||
|
||||
type create1file struct {
|
||||
file
|
||||
fstestutil.File
|
||||
record.Fsyncs
|
||||
}
|
||||
|
||||
type create1 struct {
|
||||
dir
|
||||
fstestutil.Dir
|
||||
f create1file
|
||||
}
|
||||
|
||||
@ -553,7 +536,7 @@ func (f *create1) Create(req *fuse.CreateRequest, resp *fuse.CreateResponse, int
|
||||
func TestCreate(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := &create1{}
|
||||
mnt, err := fstestutil.MountedT(t, simpleFS{f})
|
||||
mnt, err := fstestutil.MountedT(t, fstestutil.SimpleFS{f})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -583,12 +566,12 @@ func TestCreate(t *testing.T) {
|
||||
// Test Create + Write + Remove
|
||||
|
||||
type create3file struct {
|
||||
file
|
||||
fstestutil.File
|
||||
record.Writes
|
||||
}
|
||||
|
||||
type create3 struct {
|
||||
dir
|
||||
fstestutil.Dir
|
||||
f create3file
|
||||
fooCreated record.MarkRecorder
|
||||
fooRemoved record.MarkRecorder
|
||||
@ -622,7 +605,7 @@ func (f *create3) Remove(r *fuse.RemoveRequest, intr fs.Intr) fuse.Error {
|
||||
func TestCreateWriteRemove(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := &create3{}
|
||||
mnt, err := fstestutil.MountedT(t, simpleFS{f})
|
||||
mnt, err := fstestutil.MountedT(t, fstestutil.SimpleFS{f})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -659,7 +642,7 @@ func (f symlink1link) Readlink(*fuse.ReadlinkRequest, fs.Intr) (string, fuse.Err
|
||||
}
|
||||
|
||||
type symlink1 struct {
|
||||
dir
|
||||
fstestutil.Dir
|
||||
record.Symlinks
|
||||
}
|
||||
|
||||
@ -671,7 +654,7 @@ func (f *symlink1) Symlink(req *fuse.SymlinkRequest, intr fs.Intr) (fs.Node, fus
|
||||
func TestSymlink(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := &symlink1{}
|
||||
mnt, err := fstestutil.MountedT(t, simpleFS{f})
|
||||
mnt, err := fstestutil.MountedT(t, fstestutil.SimpleFS{f})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -701,26 +684,26 @@ func TestSymlink(t *testing.T) {
|
||||
// Test link
|
||||
|
||||
type link1 struct {
|
||||
dir
|
||||
fstestutil.Dir
|
||||
record.Links
|
||||
}
|
||||
|
||||
func (f *link1) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) {
|
||||
if name == "old" {
|
||||
return file{}, nil
|
||||
return fstestutil.File{}, nil
|
||||
}
|
||||
return nil, fuse.ENOENT
|
||||
}
|
||||
|
||||
func (f *link1) Link(r *fuse.LinkRequest, old fs.Node, intr fs.Intr) (fs.Node, fuse.Error) {
|
||||
f.Links.Link(r, old, intr)
|
||||
return file{}, nil
|
||||
return fstestutil.File{}, nil
|
||||
}
|
||||
|
||||
func TestLink(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := &link1{}
|
||||
mnt, err := fstestutil.MountedT(t, simpleFS{f})
|
||||
mnt, err := fstestutil.MountedT(t, fstestutil.SimpleFS{f})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -745,13 +728,13 @@ func TestLink(t *testing.T) {
|
||||
// Test Rename
|
||||
|
||||
type rename1 struct {
|
||||
dir
|
||||
fstestutil.Dir
|
||||
renamed record.Counter
|
||||
}
|
||||
|
||||
func (f *rename1) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) {
|
||||
if name == "old" {
|
||||
return file{}, nil
|
||||
return fstestutil.File{}, nil
|
||||
}
|
||||
return nil, fuse.ENOENT
|
||||
}
|
||||
@ -767,7 +750,7 @@ func (f *rename1) Rename(r *fuse.RenameRequest, newDir fs.Node, intr fs.Intr) fu
|
||||
func TestRename(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := &rename1{}
|
||||
mnt, err := fstestutil.MountedT(t, simpleFS{f})
|
||||
mnt, err := fstestutil.MountedT(t, fstestutil.SimpleFS{f})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -789,7 +772,7 @@ func TestRename(t *testing.T) {
|
||||
// Test mknod
|
||||
|
||||
type mknod1 struct {
|
||||
dir
|
||||
fstestutil.Dir
|
||||
record.Mknods
|
||||
}
|
||||
|
||||
@ -805,7 +788,7 @@ func TestMknod(t *testing.T) {
|
||||
}
|
||||
|
||||
f := &mknod1{}
|
||||
mnt, err := fstestutil.MountedT(t, simpleFS{f})
|
||||
mnt, err := fstestutil.MountedT(t, fstestutil.SimpleFS{f})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -836,7 +819,7 @@ func TestMknod(t *testing.T) {
|
||||
// Test Read served with DataHandle.
|
||||
|
||||
type dataHandleTest struct {
|
||||
file
|
||||
fstestutil.File
|
||||
}
|
||||
|
||||
func (dataHandleTest) Attr() fuse.Attr {
|
||||
@ -872,7 +855,7 @@ func TestDataHandle(t *testing.T) {
|
||||
// Test interrupt
|
||||
|
||||
type interrupt struct {
|
||||
file
|
||||
fstestutil.File
|
||||
|
||||
// strobes to signal we have a read hanging
|
||||
hanging chan struct{}
|
||||
@ -955,7 +938,7 @@ func TestInterrupt(t *testing.T) {
|
||||
// Test truncate
|
||||
|
||||
type truncate struct {
|
||||
file
|
||||
fstestutil.File
|
||||
record.Setattrs
|
||||
}
|
||||
|
||||
@ -996,7 +979,7 @@ func TestTruncate0(t *testing.T) {
|
||||
// Test ftruncate
|
||||
|
||||
type ftruncate struct {
|
||||
file
|
||||
fstestutil.File
|
||||
record.Setattrs
|
||||
}
|
||||
|
||||
@ -1046,7 +1029,7 @@ func TestFtruncate0(t *testing.T) {
|
||||
// Test opening existing file truncates
|
||||
|
||||
type truncateWithOpen struct {
|
||||
file
|
||||
fstestutil.File
|
||||
record.Setattrs
|
||||
}
|
||||
|
||||
@ -1083,7 +1066,7 @@ func TestTruncateWithOpen(t *testing.T) {
|
||||
// Test readdir
|
||||
|
||||
type readdir struct {
|
||||
dir
|
||||
fstestutil.Dir
|
||||
}
|
||||
|
||||
func (d *readdir) ReadDir(intr fs.Intr) ([]fuse.Dirent, fuse.Error) {
|
||||
@ -1097,7 +1080,7 @@ func (d *readdir) ReadDir(intr fs.Intr) ([]fuse.Dirent, fuse.Error) {
|
||||
func TestReadDir(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := &readdir{}
|
||||
mnt, err := fstestutil.MountedT(t, simpleFS{f})
|
||||
mnt, err := fstestutil.MountedT(t, fstestutil.SimpleFS{f})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -1133,7 +1116,7 @@ func TestReadDir(t *testing.T) {
|
||||
// Test Chmod.
|
||||
|
||||
type chmod struct {
|
||||
file
|
||||
fstestutil.File
|
||||
record.Setattrs
|
||||
}
|
||||
|
||||
@ -1169,7 +1152,7 @@ func TestChmod(t *testing.T) {
|
||||
// Test open
|
||||
|
||||
type open struct {
|
||||
file
|
||||
fstestutil.File
|
||||
record.Opens
|
||||
}
|
||||
|
||||
@ -1233,14 +1216,14 @@ func TestOpen(t *testing.T) {
|
||||
// Test Fsync on a dir
|
||||
|
||||
type fsyncDir struct {
|
||||
dir
|
||||
fstestutil.Dir
|
||||
record.Fsyncs
|
||||
}
|
||||
|
||||
func TestFsyncDir(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := &fsyncDir{}
|
||||
mnt, err := fstestutil.MountedT(t, simpleFS{f})
|
||||
mnt, err := fstestutil.MountedT(t, fstestutil.SimpleFS{f})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -1278,7 +1261,7 @@ func TestFsyncDir(t *testing.T) {
|
||||
// Test Getxattr
|
||||
|
||||
type getxattr struct {
|
||||
file
|
||||
fstestutil.File
|
||||
record.Getxattrs
|
||||
}
|
||||
|
||||
@ -1316,7 +1299,7 @@ func TestGetxattr(t *testing.T) {
|
||||
// Test Getxattr that has no space to return value
|
||||
|
||||
type getxattrTooSmall struct {
|
||||
file
|
||||
fstestutil.File
|
||||
}
|
||||
|
||||
func (f *getxattrTooSmall) Getxattr(req *fuse.GetxattrRequest, resp *fuse.GetxattrResponse, intr fs.Intr) fuse.Error {
|
||||
@ -1347,7 +1330,7 @@ func TestGetxattrTooSmall(t *testing.T) {
|
||||
// Test Getxattr used to probe result size
|
||||
|
||||
type getxattrSize struct {
|
||||
file
|
||||
fstestutil.File
|
||||
}
|
||||
|
||||
func (f *getxattrSize) Getxattr(req *fuse.GetxattrRequest, resp *fuse.GetxattrResponse, intr fs.Intr) fuse.Error {
|
||||
@ -1377,7 +1360,7 @@ func TestGetxattrSize(t *testing.T) {
|
||||
// Test Listxattr
|
||||
|
||||
type listxattr struct {
|
||||
file
|
||||
fstestutil.File
|
||||
record.Listxattrs
|
||||
}
|
||||
|
||||
@ -1418,7 +1401,7 @@ func TestListxattr(t *testing.T) {
|
||||
// Test Listxattr that has no space to return value
|
||||
|
||||
type listxattrTooSmall struct {
|
||||
file
|
||||
fstestutil.File
|
||||
}
|
||||
|
||||
func (f *listxattrTooSmall) Listxattr(req *fuse.ListxattrRequest, resp *fuse.ListxattrResponse, intr fs.Intr) fuse.Error {
|
||||
@ -1449,7 +1432,7 @@ func TestListxattrTooSmall(t *testing.T) {
|
||||
// Test Listxattr used to probe result size
|
||||
|
||||
type listxattrSize struct {
|
||||
file
|
||||
fstestutil.File
|
||||
}
|
||||
|
||||
func (f *listxattrSize) Listxattr(req *fuse.ListxattrRequest, resp *fuse.ListxattrResponse, intr fs.Intr) fuse.Error {
|
||||
@ -1479,11 +1462,16 @@ func TestListxattrSize(t *testing.T) {
|
||||
// Test Setxattr
|
||||
|
||||
type setxattr struct {
|
||||
file
|
||||
fstestutil.File
|
||||
record.Setxattrs
|
||||
}
|
||||
|
||||
func TestSetxattr(t *testing.T) {
|
||||
func testSetxattr(t *testing.T, size int) {
|
||||
const linux_XATTR_NAME_MAX = 64 * 1024
|
||||
if size > linux_XATTR_NAME_MAX && runtime.GOOS == "linux" {
|
||||
t.Skip("large xattrs are not supported by linux")
|
||||
}
|
||||
|
||||
t.Parallel()
|
||||
f := &setxattr{}
|
||||
mnt, err := fstestutil.MountedT(t, childMapFS{"child": f})
|
||||
@ -1492,7 +1480,9 @@ func TestSetxattr(t *testing.T) {
|
||||
}
|
||||
defer mnt.Close()
|
||||
|
||||
err = syscallx.Setxattr(mnt.Dir+"/child", "greeting", []byte("hello, world"), 0)
|
||||
const g = "hello, world"
|
||||
greeting := strings.Repeat(g, size/len(g)+1)[:size]
|
||||
err = syscallx.Setxattr(mnt.Dir+"/child", "greeting", []byte(greeting), 0)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
return
|
||||
@ -1510,15 +1500,27 @@ func TestSetxattr(t *testing.T) {
|
||||
t.Errorf("Setxattr incorrect flags: %d != %d", g, e)
|
||||
}
|
||||
|
||||
if g, e := string(got.Xattr), "hello, world"; g != e {
|
||||
if g, e := string(got.Xattr), greeting; g != e {
|
||||
t.Errorf("Setxattr incorrect data: %q != %q", g, e)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetxattr(t *testing.T) {
|
||||
testSetxattr(t, 20)
|
||||
}
|
||||
|
||||
func TestSetxattr64kB(t *testing.T) {
|
||||
testSetxattr(t, 64*1024)
|
||||
}
|
||||
|
||||
func TestSetxattr16MB(t *testing.T) {
|
||||
testSetxattr(t, 16*1024*1024)
|
||||
}
|
||||
|
||||
// Test Removexattr
|
||||
|
||||
type removexattr struct {
|
||||
file
|
||||
fstestutil.File
|
||||
record.Removexattrs
|
||||
}
|
||||
|
||||
@ -1546,7 +1548,7 @@ func TestRemovexattr(t *testing.T) {
|
||||
// Test default error.
|
||||
|
||||
type defaultErrno struct {
|
||||
dir
|
||||
fstestutil.Dir
|
||||
}
|
||||
|
||||
func (f defaultErrno) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) {
|
||||
@ -1555,7 +1557,7 @@ func (f defaultErrno) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) {
|
||||
|
||||
func TestDefaultErrno(t *testing.T) {
|
||||
t.Parallel()
|
||||
mnt, err := fstestutil.MountedT(t, simpleFS{defaultErrno{}})
|
||||
mnt, err := fstestutil.MountedT(t, fstestutil.SimpleFS{defaultErrno{}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -1580,7 +1582,7 @@ func TestDefaultErrno(t *testing.T) {
|
||||
// Test custom error.
|
||||
|
||||
type customErrNode struct {
|
||||
dir
|
||||
fstestutil.Dir
|
||||
}
|
||||
|
||||
type myCustomError struct {
|
||||
@ -1601,7 +1603,7 @@ func (f customErrNode) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) {
|
||||
|
||||
func TestCustomErrno(t *testing.T) {
|
||||
t.Parallel()
|
||||
mnt, err := fstestutil.MountedT(t, simpleFS{customErrNode{}})
|
||||
mnt, err := fstestutil.MountedT(t, fstestutil.SimpleFS{customErrNode{}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -1736,7 +1738,9 @@ func TestMmap(t *testing.T) {
|
||||
|
||||
// Test direct Read.
|
||||
|
||||
type directRead struct{ file }
|
||||
type directRead struct {
|
||||
fstestutil.File
|
||||
}
|
||||
|
||||
// explicitly not defining Attr and setting Size
|
||||
|
||||
|
233
Godeps/_workspace/src/bazil.org/fuse/fuse.go
generated
vendored
233
Godeps/_workspace/src/bazil.org/fuse/fuse.go
generated
vendored
@ -74,7 +74,8 @@
|
||||
//
|
||||
// Mount Options
|
||||
//
|
||||
// XXX
|
||||
// Behavior and metadata of the mounted file system can be changed by
|
||||
// passing MountOption values to Mount.
|
||||
//
|
||||
package fuse
|
||||
|
||||
@ -120,13 +121,21 @@ type Conn struct {
|
||||
// visible until after Conn.Ready is closed. See Conn.MountError for
|
||||
// possible errors. Incoming requests on Conn must be served to make
|
||||
// progress.
|
||||
func Mount(dir string) (*Conn, error) {
|
||||
// TODO(rsc): mount options (...string?)
|
||||
func Mount(dir string, options ...MountOption) (*Conn, error) {
|
||||
conf := MountConfig{
|
||||
options: make(map[string]string),
|
||||
}
|
||||
for _, option := range options {
|
||||
if err := option(&conf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
ready := make(chan struct{}, 1)
|
||||
c := &Conn{
|
||||
Ready: ready,
|
||||
}
|
||||
f, err := mount(dir, ready, &c.MountError)
|
||||
f, err := mount(dir, &conf, ready, &c.MountError)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -170,6 +179,9 @@ type Header struct {
|
||||
Uid uint32 // user ID of process making request
|
||||
Gid uint32 // group ID of process making request
|
||||
Pid uint32 // process ID of process making request
|
||||
|
||||
// for returning to reqPool
|
||||
msg *message
|
||||
}
|
||||
|
||||
func (h *Header) String() string {
|
||||
@ -180,6 +192,20 @@ func (h *Header) Hdr() *Header {
|
||||
return h
|
||||
}
|
||||
|
||||
func (h *Header) noResponse() {
|
||||
putMessage(h.msg)
|
||||
}
|
||||
|
||||
func (h *Header) respond(out *outHeader, n uintptr) {
|
||||
h.Conn.respond(out, n)
|
||||
putMessage(h.msg)
|
||||
}
|
||||
|
||||
func (h *Header) respondData(out *outHeader, n uintptr, data []byte) {
|
||||
h.Conn.respondData(out, n, data)
|
||||
putMessage(h.msg)
|
||||
}
|
||||
|
||||
// An Error is a FUSE error.
|
||||
//
|
||||
// Errors messages will be visible in the debug log as part of the
|
||||
@ -279,17 +305,48 @@ func (h *Header) RespondError(err Error) {
|
||||
// FUSE uses negative errors!
|
||||
// TODO: File bug report against OSXFUSE: positive error causes kernel panic.
|
||||
out := &outHeader{Error: -int32(errno), Unique: uint64(h.ID)}
|
||||
h.Conn.respond(out, unsafe.Sizeof(*out))
|
||||
h.respond(out, unsafe.Sizeof(*out))
|
||||
}
|
||||
|
||||
// Maximum file write size we are prepared to receive from the kernel.
|
||||
const maxWrite = 128 * 1024
|
||||
const maxWrite = 16 * 1024 * 1024
|
||||
|
||||
// All requests read from the kernel, without data, are shorter than
|
||||
// this.
|
||||
var maxRequestSize = syscall.Getpagesize()
|
||||
var bufSize = maxRequestSize + maxWrite
|
||||
|
||||
// reqPool is a pool of messages.
|
||||
//
|
||||
// Lifetime of a logical message is from getMessage to putMessage.
|
||||
// getMessage is called by ReadRequest. putMessage is called by
|
||||
// Conn.ReadRequest, Request.Respond, or Request.RespondError.
|
||||
//
|
||||
// Messages in the pool are guaranteed to have conn and off zeroed,
|
||||
// buf allocated and len==bufSize, and hdr set.
|
||||
var reqPool = sync.Pool{
|
||||
New: allocMessage,
|
||||
}
|
||||
|
||||
func allocMessage() interface{} {
|
||||
m := &message{buf: make([]byte, bufSize)}
|
||||
m.hdr = (*inHeader)(unsafe.Pointer(&m.buf[0]))
|
||||
return m
|
||||
}
|
||||
|
||||
func getMessage(c *Conn) *message {
|
||||
m := reqPool.Get().(*message)
|
||||
m.conn = c
|
||||
return m
|
||||
}
|
||||
|
||||
func putMessage(m *message) {
|
||||
m.buf = m.buf[:bufSize]
|
||||
m.conn = nil
|
||||
m.off = 0
|
||||
reqPool.Put(m)
|
||||
}
|
||||
|
||||
// a message represents the bytes of a single FUSE message
|
||||
type message struct {
|
||||
conn *Conn
|
||||
@ -298,12 +355,6 @@ type message struct {
|
||||
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)
|
||||
}
|
||||
@ -322,7 +373,16 @@ func (m *message) bytes() []byte {
|
||||
|
||||
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}
|
||||
return Header{
|
||||
Conn: m.conn,
|
||||
ID: RequestID(h.Unique),
|
||||
Node: NodeID(h.Nodeid),
|
||||
Uid: h.Uid,
|
||||
Gid: h.Gid,
|
||||
Pid: h.Pid,
|
||||
|
||||
msg: m,
|
||||
}
|
||||
}
|
||||
|
||||
// fileMode returns a Go os.FileMode from a Unix mode.
|
||||
@ -385,9 +445,12 @@ func (c *Conn) fd() int {
|
||||
return int(c.dev.Fd())
|
||||
}
|
||||
|
||||
// ReadRequest returns the next FUSE request from the kernel.
|
||||
//
|
||||
// Caller must call either Request.Respond or Request.RespondError in
|
||||
// a reasonable time. Caller must not retain Request after that call.
|
||||
func (c *Conn) ReadRequest() (Request, error) {
|
||||
// TODO: Some kind of buffer reuse.
|
||||
m := newMessage(c)
|
||||
m := getMessage(c)
|
||||
loop:
|
||||
c.rio.RLock()
|
||||
n, err := syscall.Read(c.fd(), m.buf)
|
||||
@ -398,14 +461,17 @@ loop:
|
||||
goto loop
|
||||
}
|
||||
if err != nil && err != syscall.ENODEV {
|
||||
putMessage(m)
|
||||
return nil, err
|
||||
}
|
||||
if n <= 0 {
|
||||
putMessage(m)
|
||||
return nil, io.EOF
|
||||
}
|
||||
m.buf = m.buf[:n]
|
||||
|
||||
if n < inHeaderSize {
|
||||
putMessage(m)
|
||||
return nil, errors.New("fuse: message too short")
|
||||
}
|
||||
|
||||
@ -421,7 +487,10 @@ loop:
|
||||
}
|
||||
|
||||
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)
|
||||
// prepare error message before returning m to pool
|
||||
err := fmt.Errorf("fuse: read %d opcode %d but expected %d", n, m.hdr.Opcode, m.hdr.Len)
|
||||
putMessage(m)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m.off = inHeaderSize
|
||||
@ -821,6 +890,7 @@ loop:
|
||||
|
||||
corrupt:
|
||||
Debug(malformedMessage{})
|
||||
putMessage(m)
|
||||
return nil, fmt.Errorf("fuse: malformed message")
|
||||
|
||||
unrecognized:
|
||||
@ -886,6 +956,8 @@ type InitRequest struct {
|
||||
Flags InitFlags
|
||||
}
|
||||
|
||||
var _ = Request(&InitRequest{})
|
||||
|
||||
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)
|
||||
}
|
||||
@ -920,7 +992,7 @@ func (r *InitRequest) Respond(resp *InitResponse) {
|
||||
if out.MaxWrite > maxWrite {
|
||||
out.MaxWrite = maxWrite
|
||||
}
|
||||
r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
r.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
}
|
||||
|
||||
// A StatfsRequest requests information about the mounted file system.
|
||||
@ -928,8 +1000,10 @@ type StatfsRequest struct {
|
||||
Header `json:"-"`
|
||||
}
|
||||
|
||||
var _ = Request(&StatfsRequest{})
|
||||
|
||||
func (r *StatfsRequest) String() string {
|
||||
return fmt.Sprintf("Statfs [%s]\n", &r.Header)
|
||||
return fmt.Sprintf("Statfs [%s]", &r.Header)
|
||||
}
|
||||
|
||||
// Respond replies to the request with the given response.
|
||||
@ -946,7 +1020,7 @@ func (r *StatfsRequest) Respond(resp *StatfsResponse) {
|
||||
Frsize: resp.Frsize,
|
||||
},
|
||||
}
|
||||
r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
r.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
}
|
||||
|
||||
// A StatfsResponse is the response to a StatfsRequest.
|
||||
@ -972,6 +1046,8 @@ type AccessRequest struct {
|
||||
Mask uint32
|
||||
}
|
||||
|
||||
var _ = Request(&AccessRequest{})
|
||||
|
||||
func (r *AccessRequest) String() string {
|
||||
return fmt.Sprintf("Access [%s] mask=%#x", &r.Header, r.Mask)
|
||||
}
|
||||
@ -980,7 +1056,7 @@ func (r *AccessRequest) String() string {
|
||||
// To deny access, use RespondError.
|
||||
func (r *AccessRequest) Respond() {
|
||||
out := &outHeader{Unique: uint64(r.ID)}
|
||||
r.Conn.respond(out, unsafe.Sizeof(*out))
|
||||
r.respond(out, unsafe.Sizeof(*out))
|
||||
}
|
||||
|
||||
// An Attr is the metadata for a single file or directory.
|
||||
@ -1057,6 +1133,8 @@ type GetattrRequest struct {
|
||||
Header `json:"-"`
|
||||
}
|
||||
|
||||
var _ = Request(&GetattrRequest{})
|
||||
|
||||
func (r *GetattrRequest) String() string {
|
||||
return fmt.Sprintf("Getattr [%s]", &r.Header)
|
||||
}
|
||||
@ -1069,7 +1147,7 @@ func (r *GetattrRequest) Respond(resp *GetattrResponse) {
|
||||
AttrValidNsec: uint32(resp.AttrValid % time.Second / time.Nanosecond),
|
||||
Attr: resp.Attr.attr(),
|
||||
}
|
||||
r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
r.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
}
|
||||
|
||||
// A GetattrResponse is the response to a GetattrRequest.
|
||||
@ -1099,6 +1177,8 @@ type GetxattrRequest struct {
|
||||
Position uint32
|
||||
}
|
||||
|
||||
var _ = Request(&GetxattrRequest{})
|
||||
|
||||
func (r *GetxattrRequest) String() string {
|
||||
return fmt.Sprintf("Getxattr [%s] %q %d @%d", &r.Header, r.Name, r.Size, r.Position)
|
||||
}
|
||||
@ -1110,10 +1190,10 @@ func (r *GetxattrRequest) Respond(resp *GetxattrResponse) {
|
||||
outHeader: outHeader{Unique: uint64(r.ID)},
|
||||
Size: uint32(len(resp.Xattr)),
|
||||
}
|
||||
r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
r.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
} else {
|
||||
out := &outHeader{Unique: uint64(r.ID)}
|
||||
r.Conn.respondData(out, unsafe.Sizeof(*out), resp.Xattr)
|
||||
r.respondData(out, unsafe.Sizeof(*out), resp.Xattr)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1138,6 +1218,8 @@ type ListxattrRequest struct {
|
||||
Position uint32 // offset within attribute list
|
||||
}
|
||||
|
||||
var _ = Request(&ListxattrRequest{})
|
||||
|
||||
func (r *ListxattrRequest) String() string {
|
||||
return fmt.Sprintf("Listxattr [%s] %d @%d", &r.Header, r.Size, r.Position)
|
||||
}
|
||||
@ -1149,10 +1231,10 @@ func (r *ListxattrRequest) Respond(resp *ListxattrResponse) {
|
||||
outHeader: outHeader{Unique: uint64(r.ID)},
|
||||
Size: uint32(len(resp.Xattr)),
|
||||
}
|
||||
r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
r.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
} else {
|
||||
out := &outHeader{Unique: uint64(r.ID)}
|
||||
r.Conn.respondData(out, unsafe.Sizeof(*out), resp.Xattr)
|
||||
r.respondData(out, unsafe.Sizeof(*out), resp.Xattr)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1179,6 +1261,8 @@ type RemovexattrRequest struct {
|
||||
Name string // name of extended attribute
|
||||
}
|
||||
|
||||
var _ = Request(&RemovexattrRequest{})
|
||||
|
||||
func (r *RemovexattrRequest) String() string {
|
||||
return fmt.Sprintf("Removexattr [%s] %q", &r.Header, r.Name)
|
||||
}
|
||||
@ -1186,7 +1270,7 @@ func (r *RemovexattrRequest) String() string {
|
||||
// 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))
|
||||
r.respond(out, unsafe.Sizeof(*out))
|
||||
}
|
||||
|
||||
func (r *RemovexattrRequest) RespondError(err Error) {
|
||||
@ -1219,14 +1303,24 @@ type SetxattrRequest struct {
|
||||
Xattr []byte
|
||||
}
|
||||
|
||||
var _ = Request(&SetxattrRequest{})
|
||||
|
||||
func trunc(b []byte, max int) ([]byte, string) {
|
||||
if len(b) > max {
|
||||
return b[:max], "..."
|
||||
}
|
||||
return b, ""
|
||||
}
|
||||
|
||||
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)
|
||||
xattr, tail := trunc(r.Xattr, 16)
|
||||
return fmt.Sprintf("Setxattr [%s] %q %x%s fl=%v @%#x", &r.Header, r.Name, xattr, tail, 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))
|
||||
r.respond(out, unsafe.Sizeof(*out))
|
||||
}
|
||||
|
||||
func (r *SetxattrRequest) RespondError(err Error) {
|
||||
@ -1240,6 +1334,8 @@ type LookupRequest struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
var _ = Request(&LookupRequest{})
|
||||
|
||||
func (r *LookupRequest) String() string {
|
||||
return fmt.Sprintf("Lookup [%s] %q", &r.Header, r.Name)
|
||||
}
|
||||
@ -1256,7 +1352,7 @@ func (r *LookupRequest) Respond(resp *LookupResponse) {
|
||||
AttrValidNsec: uint32(resp.AttrValid % time.Second / time.Nanosecond),
|
||||
Attr: resp.Attr.attr(),
|
||||
}
|
||||
r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
r.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
}
|
||||
|
||||
// A LookupResponse is the response to a LookupRequest.
|
||||
@ -1279,6 +1375,8 @@ type OpenRequest struct {
|
||||
Flags OpenFlags
|
||||
}
|
||||
|
||||
var _ = Request(&OpenRequest{})
|
||||
|
||||
func (r *OpenRequest) String() string {
|
||||
return fmt.Sprintf("Open [%s] dir=%v fl=%v", &r.Header, r.Dir, r.Flags)
|
||||
}
|
||||
@ -1290,7 +1388,7 @@ func (r *OpenRequest) Respond(resp *OpenResponse) {
|
||||
Fh: uint64(resp.Handle),
|
||||
OpenFlags: uint32(resp.Flags),
|
||||
}
|
||||
r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
r.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
}
|
||||
|
||||
// A OpenResponse is the response to a OpenRequest.
|
||||
@ -1311,6 +1409,8 @@ type CreateRequest struct {
|
||||
Mode os.FileMode
|
||||
}
|
||||
|
||||
var _ = Request(&CreateRequest{})
|
||||
|
||||
func (r *CreateRequest) String() string {
|
||||
return fmt.Sprintf("Create [%s] %q fl=%v mode=%v", &r.Header, r.Name, r.Flags, r.Mode)
|
||||
}
|
||||
@ -1331,7 +1431,7 @@ func (r *CreateRequest) Respond(resp *CreateResponse) {
|
||||
Fh: uint64(resp.Handle),
|
||||
OpenFlags: uint32(resp.Flags),
|
||||
}
|
||||
r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
r.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
}
|
||||
|
||||
// A CreateResponse is the response to a CreateRequest.
|
||||
@ -1352,6 +1452,8 @@ type MkdirRequest struct {
|
||||
Mode os.FileMode
|
||||
}
|
||||
|
||||
var _ = Request(&MkdirRequest{})
|
||||
|
||||
func (r *MkdirRequest) String() string {
|
||||
return fmt.Sprintf("Mkdir [%s] %q mode=%v", &r.Header, r.Name, r.Mode)
|
||||
}
|
||||
@ -1368,7 +1470,7 @@ func (r *MkdirRequest) Respond(resp *MkdirResponse) {
|
||||
AttrValidNsec: uint32(resp.AttrValid % time.Second / time.Nanosecond),
|
||||
Attr: resp.Attr.attr(),
|
||||
}
|
||||
r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
r.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
}
|
||||
|
||||
// A MkdirResponse is the response to a MkdirRequest.
|
||||
@ -1389,6 +1491,8 @@ type ReadRequest struct {
|
||||
Size int
|
||||
}
|
||||
|
||||
var _ = Request(&ReadRequest{})
|
||||
|
||||
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)
|
||||
}
|
||||
@ -1396,7 +1500,7 @@ func (r *ReadRequest) String() string {
|
||||
// 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)
|
||||
r.respondData(out, unsafe.Sizeof(*out), resp.Data)
|
||||
}
|
||||
|
||||
// A ReadResponse is the response to a ReadRequest.
|
||||
@ -1429,6 +1533,8 @@ type ReleaseRequest struct {
|
||||
LockOwner uint32
|
||||
}
|
||||
|
||||
var _ = Request(&ReleaseRequest{})
|
||||
|
||||
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)
|
||||
}
|
||||
@ -1436,7 +1542,7 @@ func (r *ReleaseRequest) String() string {
|
||||
// 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))
|
||||
r.respond(out, unsafe.Sizeof(*out))
|
||||
}
|
||||
|
||||
// A DestroyRequest is sent by the kernel when unmounting the file system.
|
||||
@ -1446,6 +1552,8 @@ type DestroyRequest struct {
|
||||
Header `json:"-"`
|
||||
}
|
||||
|
||||
var _ = Request(&DestroyRequest{})
|
||||
|
||||
func (r *DestroyRequest) String() string {
|
||||
return fmt.Sprintf("Destroy [%s]", &r.Header)
|
||||
}
|
||||
@ -1453,7 +1561,7 @@ func (r *DestroyRequest) String() string {
|
||||
// Respond replies to the request.
|
||||
func (r *DestroyRequest) Respond() {
|
||||
out := &outHeader{Unique: uint64(r.ID)}
|
||||
r.Conn.respond(out, unsafe.Sizeof(*out))
|
||||
r.respond(out, unsafe.Sizeof(*out))
|
||||
}
|
||||
|
||||
// A ForgetRequest is sent by the kernel when forgetting about r.Node
|
||||
@ -1463,6 +1571,8 @@ type ForgetRequest struct {
|
||||
N uint64
|
||||
}
|
||||
|
||||
var _ = Request(&ForgetRequest{})
|
||||
|
||||
func (r *ForgetRequest) String() string {
|
||||
return fmt.Sprintf("Forget [%s] %d", &r.Header, r.N)
|
||||
}
|
||||
@ -1470,6 +1580,7 @@ func (r *ForgetRequest) String() string {
|
||||
// Respond replies to the request, indicating that the forgetfulness has been recorded.
|
||||
func (r *ForgetRequest) Respond() {
|
||||
// Don't reply to forget messages.
|
||||
r.noResponse()
|
||||
}
|
||||
|
||||
// A Dirent represents a single directory entry.
|
||||
@ -1562,6 +1673,8 @@ type WriteRequest struct {
|
||||
Flags WriteFlags
|
||||
}
|
||||
|
||||
var _ = Request(&WriteRequest{})
|
||||
|
||||
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)
|
||||
}
|
||||
@ -1589,7 +1702,7 @@ func (r *WriteRequest) Respond(resp *WriteResponse) {
|
||||
outHeader: outHeader{Unique: uint64(r.ID)},
|
||||
Size: uint32(resp.Size),
|
||||
}
|
||||
r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
r.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
}
|
||||
|
||||
// A WriteResponse replies to a write indicating how many bytes were written.
|
||||
@ -1621,6 +1734,8 @@ type SetattrRequest struct {
|
||||
Flags uint32 // see chflags(2)
|
||||
}
|
||||
|
||||
var _ = Request(&SetattrRequest{})
|
||||
|
||||
func (r *SetattrRequest) String() string {
|
||||
var buf bytes.Buffer
|
||||
fmt.Fprintf(&buf, "Setattr [%s]", &r.Header)
|
||||
@ -1680,7 +1795,7 @@ func (r *SetattrRequest) Respond(resp *SetattrResponse) {
|
||||
AttrValidNsec: uint32(resp.AttrValid % time.Second / time.Nanosecond),
|
||||
Attr: resp.Attr.attr(),
|
||||
}
|
||||
r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
r.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
}
|
||||
|
||||
// A SetattrResponse is the response to a SetattrRequest.
|
||||
@ -1703,6 +1818,8 @@ type FlushRequest struct {
|
||||
LockOwner uint64
|
||||
}
|
||||
|
||||
var _ = Request(&FlushRequest{})
|
||||
|
||||
func (r *FlushRequest) String() string {
|
||||
return fmt.Sprintf("Flush [%s] %#x fl=%#x lk=%#x", &r.Header, r.Handle, r.Flags, r.LockOwner)
|
||||
}
|
||||
@ -1710,16 +1827,19 @@ func (r *FlushRequest) String() string {
|
||||
// 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))
|
||||
r.respond(out, unsafe.Sizeof(*out))
|
||||
}
|
||||
|
||||
// A RemoveRequest asks to remove a file or directory.
|
||||
// A RemoveRequest asks to remove a file or directory from the
|
||||
// directory r.Node.
|
||||
type RemoveRequest struct {
|
||||
Header `json:"-"`
|
||||
Name string // name of extended attribute
|
||||
Name string // name of the entry to remove
|
||||
Dir bool // is this rmdir?
|
||||
}
|
||||
|
||||
var _ = Request(&RemoveRequest{})
|
||||
|
||||
func (r *RemoveRequest) String() string {
|
||||
return fmt.Sprintf("Remove [%s] %q dir=%v", &r.Header, r.Name, r.Dir)
|
||||
}
|
||||
@ -1727,7 +1847,7 @@ func (r *RemoveRequest) String() string {
|
||||
// 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))
|
||||
r.respond(out, unsafe.Sizeof(*out))
|
||||
}
|
||||
|
||||
// A SymlinkRequest is a request to create a symlink making NewName point to Target.
|
||||
@ -1736,6 +1856,8 @@ type SymlinkRequest struct {
|
||||
NewName, Target string
|
||||
}
|
||||
|
||||
var _ = Request(&SymlinkRequest{})
|
||||
|
||||
func (r *SymlinkRequest) String() string {
|
||||
return fmt.Sprintf("Symlink [%s] from %q to target %q", &r.Header, r.NewName, r.Target)
|
||||
}
|
||||
@ -1752,7 +1874,7 @@ func (r *SymlinkRequest) Respond(resp *SymlinkResponse) {
|
||||
AttrValidNsec: uint32(resp.AttrValid % time.Second / time.Nanosecond),
|
||||
Attr: resp.Attr.attr(),
|
||||
}
|
||||
r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
r.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
}
|
||||
|
||||
// A SymlinkResponse is the response to a SymlinkRequest.
|
||||
@ -1765,13 +1887,15 @@ type ReadlinkRequest struct {
|
||||
Header `json:"-"`
|
||||
}
|
||||
|
||||
var _ = Request(&ReadlinkRequest{})
|
||||
|
||||
func (r *ReadlinkRequest) String() string {
|
||||
return fmt.Sprintf("Readlink [%s]", &r.Header)
|
||||
}
|
||||
|
||||
func (r *ReadlinkRequest) Respond(target string) {
|
||||
out := &outHeader{Unique: uint64(r.ID)}
|
||||
r.Conn.respondData(out, unsafe.Sizeof(*out), []byte(target))
|
||||
r.respondData(out, unsafe.Sizeof(*out), []byte(target))
|
||||
}
|
||||
|
||||
// A LinkRequest is a request to create a hard link.
|
||||
@ -1781,6 +1905,8 @@ type LinkRequest struct {
|
||||
NewName string
|
||||
}
|
||||
|
||||
var _ = Request(&LinkRequest{})
|
||||
|
||||
func (r *LinkRequest) String() string {
|
||||
return fmt.Sprintf("Link [%s] node %d to %q", &r.Header, r.OldNode, r.NewName)
|
||||
}
|
||||
@ -1796,7 +1922,7 @@ func (r *LinkRequest) Respond(resp *LookupResponse) {
|
||||
AttrValidNsec: uint32(resp.AttrValid % time.Second / time.Nanosecond),
|
||||
Attr: resp.Attr.attr(),
|
||||
}
|
||||
r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
r.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
}
|
||||
|
||||
// A RenameRequest is a request to rename a file.
|
||||
@ -1806,13 +1932,15 @@ type RenameRequest struct {
|
||||
OldName, NewName string
|
||||
}
|
||||
|
||||
var _ = Request(&RenameRequest{})
|
||||
|
||||
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))
|
||||
r.respond(out, unsafe.Sizeof(*out))
|
||||
}
|
||||
|
||||
type MknodRequest struct {
|
||||
@ -1822,6 +1950,8 @@ type MknodRequest struct {
|
||||
Rdev uint32
|
||||
}
|
||||
|
||||
var _ = Request(&MknodRequest{})
|
||||
|
||||
func (r *MknodRequest) String() string {
|
||||
return fmt.Sprintf("Mknod [%s] Name %q mode %v rdev %d", &r.Header, r.Name, r.Mode, r.Rdev)
|
||||
}
|
||||
@ -1837,7 +1967,7 @@ func (r *MknodRequest) Respond(resp *LookupResponse) {
|
||||
AttrValidNsec: uint32(resp.AttrValid % time.Second / time.Nanosecond),
|
||||
Attr: resp.Attr.attr(),
|
||||
}
|
||||
r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
r.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
}
|
||||
|
||||
type FsyncRequest struct {
|
||||
@ -1848,13 +1978,15 @@ type FsyncRequest struct {
|
||||
Dir bool
|
||||
}
|
||||
|
||||
var _ = Request(&FsyncRequest{})
|
||||
|
||||
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))
|
||||
r.respond(out, unsafe.Sizeof(*out))
|
||||
}
|
||||
|
||||
// An InterruptRequest is a request to interrupt another pending request. The
|
||||
@ -1864,8 +1996,11 @@ type InterruptRequest struct {
|
||||
IntrID RequestID // ID of the request to be interrupt.
|
||||
}
|
||||
|
||||
var _ = Request(&InterruptRequest{})
|
||||
|
||||
func (r *InterruptRequest) Respond() {
|
||||
// nothing to do here
|
||||
r.noResponse()
|
||||
}
|
||||
|
||||
func (r *InterruptRequest) String() string {
|
||||
@ -1880,6 +2015,8 @@ type XXXRequest struct {
|
||||
xxx
|
||||
}
|
||||
|
||||
var _ = Request(&XXXRequest{})
|
||||
|
||||
func (r *XXXRequest) String() string {
|
||||
return fmt.Sprintf("XXX [%s] xxx", &r.Header)
|
||||
}
|
||||
@ -1890,7 +2027,7 @@ func (r *XXXRequest) Respond(resp *XXXResponse) {
|
||||
outHeader: outHeader{Unique: uint64(r.ID)},
|
||||
xxx,
|
||||
}
|
||||
r.Conn.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
r.respond(&out.outHeader, unsafe.Sizeof(*out))
|
||||
}
|
||||
|
||||
// A XXXResponse is the response to a XXXRequest.
|
||||
|
2
Godeps/_workspace/src/bazil.org/fuse/fuse_kernel.go
generated
vendored
2
Godeps/_workspace/src/bazil.org/fuse/fuse_kernel.go
generated
vendored
@ -513,7 +513,7 @@ type writeOut struct {
|
||||
Padding uint32
|
||||
}
|
||||
|
||||
// The WriteFlags are returned in the WriteResponse.
|
||||
// The WriteFlags are passed in WriteRequest.
|
||||
type WriteFlags uint32
|
||||
|
||||
func (fl WriteFlags) String() string {
|
||||
|
8
Godeps/_workspace/src/bazil.org/fuse/hellofs/hello.go
generated
vendored
8
Godeps/_workspace/src/bazil.org/fuse/hellofs/hello.go
generated
vendored
@ -28,7 +28,13 @@ func main() {
|
||||
}
|
||||
mountpoint := flag.Arg(0)
|
||||
|
||||
c, err := fuse.Mount(mountpoint)
|
||||
c, err := fuse.Mount(
|
||||
mountpoint,
|
||||
fuse.FSName("helloworld"),
|
||||
fuse.Subtype("hellofs"),
|
||||
fuse.LocalVolume(),
|
||||
fuse.VolumeName("Hello world!"),
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
BIN
Godeps/_workspace/src/bazil.org/fuse/hellofs/hellofs
generated
vendored
Normal file
BIN
Godeps/_workspace/src/bazil.org/fuse/hellofs/hellofs
generated
vendored
Normal file
Binary file not shown.
19
Godeps/_workspace/src/bazil.org/fuse/mount_darwin.go
generated
vendored
19
Godeps/_workspace/src/bazil.org/fuse/mount_darwin.go
generated
vendored
@ -3,9 +3,11 @@ package fuse
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
@ -50,15 +52,22 @@ func openOSXFUSEDev() (*os.File, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func callMount(dir string, f *os.File, ready chan<- struct{}, errp *error) error {
|
||||
func callMount(dir string, conf *MountConfig, f *os.File, ready chan<- struct{}, errp *error) error {
|
||||
bin := "/Library/Filesystems/osxfusefs.fs/Support/mount_osxfusefs"
|
||||
|
||||
for k, v := range conf.options {
|
||||
if strings.Contains(k, ",") || strings.Contains(v, ",") {
|
||||
// Silly limitation but the mount helper does not
|
||||
// understand any escaping. See TestMountOptionCommaError.
|
||||
return fmt.Errorf("mount options cannot contain commas on OS X: %q=%q", k, v)
|
||||
}
|
||||
}
|
||||
cmd := exec.Command(
|
||||
bin,
|
||||
"-o", conf.getOptions(),
|
||||
// Tell osxfuse-kext how large our buffer is. It must split
|
||||
// writes larger than this into multiple writes.
|
||||
//
|
||||
// TODO add buffer reuse, bump this up significantly
|
||||
//
|
||||
// OSXFUSE seems to ignore InitResponse.MaxWrite, and uses
|
||||
// this instead.
|
||||
"-o", "iosize="+strconv.FormatUint(maxWrite, 10),
|
||||
@ -95,7 +104,7 @@ func callMount(dir string, f *os.File, ready chan<- struct{}, errp *error) error
|
||||
return err
|
||||
}
|
||||
|
||||
func mount(dir string, ready chan<- struct{}, errp *error) (*os.File, error) {
|
||||
func mount(dir string, conf *MountConfig, ready chan<- struct{}, errp *error) (*os.File, error) {
|
||||
f, err := openOSXFUSEDev()
|
||||
if err == errNotLoaded {
|
||||
err = loadOSXFUSE()
|
||||
@ -108,7 +117,7 @@ func mount(dir string, ready chan<- struct{}, errp *error) (*os.File, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = callMount(dir, f, ready, errp)
|
||||
err = callMount(dir, conf, f, ready, errp)
|
||||
if err != nil {
|
||||
f.Close()
|
||||
return nil, err
|
||||
|
9
Godeps/_workspace/src/bazil.org/fuse/mount_linux.go
generated
vendored
9
Godeps/_workspace/src/bazil.org/fuse/mount_linux.go
generated
vendored
@ -8,7 +8,7 @@ import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func mount(dir string, ready chan<- struct{}, errp *error) (fusefd *os.File, err error) {
|
||||
func mount(dir string, conf *MountConfig, ready chan<- struct{}, errp *error) (fusefd *os.File, err error) {
|
||||
// linux mount is never delayed
|
||||
close(ready)
|
||||
|
||||
@ -19,7 +19,12 @@ func mount(dir string, ready chan<- struct{}, errp *error) (fusefd *os.File, err
|
||||
defer syscall.Close(fds[0])
|
||||
defer syscall.Close(fds[1])
|
||||
|
||||
cmd := exec.Command("fusermount", "--", dir)
|
||||
cmd := exec.Command(
|
||||
"fusermount",
|
||||
"-o", conf.getOptions(),
|
||||
"--",
|
||||
dir,
|
||||
)
|
||||
cmd.Env = append(os.Environ(), "_FUSE_COMMFD=3")
|
||||
|
||||
writeFile := os.NewFile(uintptr(fds[0]), "fusermount-child-writes")
|
||||
|
100
Godeps/_workspace/src/bazil.org/fuse/options.go
generated
vendored
Normal file
100
Godeps/_workspace/src/bazil.org/fuse/options.go
generated
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// MountConfig holds the configuration for a mount operation.
|
||||
// Use it by passing MountOption values to Mount.
|
||||
type MountConfig struct {
|
||||
options map[string]string
|
||||
}
|
||||
|
||||
func escapeComma(s string) string {
|
||||
s = strings.Replace(s, `\`, `\\`, -1)
|
||||
s = strings.Replace(s, `,`, `\,`, -1)
|
||||
return s
|
||||
}
|
||||
|
||||
// getOptions makes a string of options suitable for passing to FUSE
|
||||
// mount flag `-o`. Returns an empty string if no options were set.
|
||||
// Any platform specific adjustments should happen before the call.
|
||||
func (m *MountConfig) getOptions() string {
|
||||
var opts []string
|
||||
for k, v := range m.options {
|
||||
k = escapeComma(k)
|
||||
if v != "" {
|
||||
k += "=" + escapeComma(v)
|
||||
}
|
||||
opts = append(opts, k)
|
||||
}
|
||||
return strings.Join(opts, ",")
|
||||
}
|
||||
|
||||
// MountOption is passed to Mount to change the behavior of the mount.
|
||||
type MountOption func(*MountConfig) error
|
||||
|
||||
// FSName sets the file system name (also called source) that is
|
||||
// visible in the list of mounted file systems.
|
||||
func FSName(name string) MountOption {
|
||||
return func(conf *MountConfig) error {
|
||||
conf.options["fsname"] = name
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Subtype sets the subtype of the mount. The main type is always
|
||||
// `fuse`. The type in a list of mounted file systems will look like
|
||||
// `fuse.foo`.
|
||||
//
|
||||
// OS X ignores this option.
|
||||
func Subtype(fstype string) MountOption {
|
||||
return func(conf *MountConfig) error {
|
||||
conf.options["subtype"] = fstype
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// LocalVolume sets the volume to be local (instead of network),
|
||||
// changing the behavior of Finder, Spotlight, and such.
|
||||
//
|
||||
// OS X only. Others ignore this option.
|
||||
func LocalVolume() MountOption {
|
||||
return localVolume
|
||||
}
|
||||
|
||||
// VolumeName sets the volume name shown in Finder.
|
||||
//
|
||||
// OS X only. Others ignore this option.
|
||||
func VolumeName(name string) MountOption {
|
||||
return volumeName(name)
|
||||
}
|
||||
|
||||
var ErrCannotCombineAllowOtherAndAllowRoot = errors.New("cannot combine AllowOther and AllowRoot")
|
||||
|
||||
// AllowOther allows other users to access the file system.
|
||||
//
|
||||
// Only one of AllowOther or AllowRoot can be used.
|
||||
func AllowOther() MountOption {
|
||||
return func(conf *MountConfig) error {
|
||||
if _, ok := conf.options["allow_root"]; ok {
|
||||
return ErrCannotCombineAllowOtherAndAllowRoot
|
||||
}
|
||||
conf.options["allow_other"] = ""
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// AllowRoot allows other users to access the file system.
|
||||
//
|
||||
// Only one of AllowOther or AllowRoot can be used.
|
||||
func AllowRoot() MountOption {
|
||||
return func(conf *MountConfig) error {
|
||||
if _, ok := conf.options["allow_other"]; ok {
|
||||
return ErrCannotCombineAllowOtherAndAllowRoot
|
||||
}
|
||||
conf.options["allow_root"] = ""
|
||||
return nil
|
||||
}
|
||||
}
|
13
Godeps/_workspace/src/bazil.org/fuse/options_darwin.go
generated
vendored
Normal file
13
Godeps/_workspace/src/bazil.org/fuse/options_darwin.go
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
package fuse
|
||||
|
||||
func localVolume(conf *MountConfig) error {
|
||||
conf.options["local"] = ""
|
||||
return nil
|
||||
}
|
||||
|
||||
func volumeName(name string) MountOption {
|
||||
return func(conf *MountConfig) error {
|
||||
conf.options["volname"] = name
|
||||
return nil
|
||||
}
|
||||
}
|
27
Godeps/_workspace/src/bazil.org/fuse/options_darwin_test.go
generated
vendored
Normal file
27
Godeps/_workspace/src/bazil.org/fuse/options_darwin_test.go
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
package fuse_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/bazil.org/fuse"
|
||||
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/bazil.org/fuse/fs/fstestutil"
|
||||
)
|
||||
|
||||
func TestMountOptionCommaError(t *testing.T) {
|
||||
t.Parallel()
|
||||
// this test is not tied to FSName, but needs just some option
|
||||
// with string content
|
||||
var name = "FuseTest,Marker"
|
||||
mnt, err := fstestutil.MountedT(t, fstestutil.SimpleFS{fstestutil.Dir{}},
|
||||
fuse.FSName(name),
|
||||
)
|
||||
switch {
|
||||
case err == nil:
|
||||
mnt.Close()
|
||||
t.Fatal("expected an error about commas")
|
||||
case err.Error() == `mount options cannot contain commas on OS X: "fsname"="FuseTest,Marker"`:
|
||||
// all good
|
||||
default:
|
||||
t.Fatalf("expected an error about commas, got: %v", err)
|
||||
}
|
||||
}
|
13
Godeps/_workspace/src/bazil.org/fuse/options_linux.go
generated
vendored
Normal file
13
Godeps/_workspace/src/bazil.org/fuse/options_linux.go
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
package fuse
|
||||
|
||||
func dummyOption(conf *MountConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func localVolume(conf *MountConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func volumeName(name string) MountOption {
|
||||
return dummyOption
|
||||
}
|
141
Godeps/_workspace/src/bazil.org/fuse/options_test.go
generated
vendored
Normal file
141
Godeps/_workspace/src/bazil.org/fuse/options_test.go
generated
vendored
Normal file
@ -0,0 +1,141 @@
|
||||
package fuse_test
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/bazil.org/fuse"
|
||||
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/bazil.org/fuse/fs/fstestutil"
|
||||
)
|
||||
|
||||
func init() {
|
||||
fstestutil.DebugByDefault()
|
||||
}
|
||||
|
||||
func TestMountOptionFSName(t *testing.T) {
|
||||
t.Parallel()
|
||||
const name = "FuseTestMarker"
|
||||
mnt, err := fstestutil.MountedT(t, fstestutil.SimpleFS{fstestutil.Dir{}},
|
||||
fuse.FSName(name),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer mnt.Close()
|
||||
|
||||
info, err := fstestutil.GetMountInfo(mnt.Dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if g, e := info.FSName, name; g != e {
|
||||
t.Errorf("wrong FSName: %q != %q", g, e)
|
||||
}
|
||||
}
|
||||
|
||||
func testMountOptionFSNameEvil(t *testing.T, evil string) {
|
||||
t.Parallel()
|
||||
var name = "FuseTest" + evil + "Marker"
|
||||
mnt, err := fstestutil.MountedT(t, fstestutil.SimpleFS{fstestutil.Dir{}},
|
||||
fuse.FSName(name),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer mnt.Close()
|
||||
|
||||
info, err := fstestutil.GetMountInfo(mnt.Dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if g, e := info.FSName, name; g != e {
|
||||
t.Errorf("wrong FSName: %q != %q", g, e)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMountOptionFSNameEvilComma(t *testing.T) {
|
||||
if runtime.GOOS == "darwin" {
|
||||
// see TestMountOptionCommaError for a test that enforces we
|
||||
// at least give a nice error, instead of corrupting the mount
|
||||
// options
|
||||
t.Skip("TODO: OS X gets this wrong, commas in mount options cannot be escaped at all")
|
||||
}
|
||||
testMountOptionFSNameEvil(t, ",")
|
||||
}
|
||||
|
||||
func TestMountOptionFSNameEvilSpace(t *testing.T) {
|
||||
testMountOptionFSNameEvil(t, " ")
|
||||
}
|
||||
|
||||
func TestMountOptionFSNameEvilTab(t *testing.T) {
|
||||
testMountOptionFSNameEvil(t, "\t")
|
||||
}
|
||||
|
||||
func TestMountOptionFSNameEvilNewline(t *testing.T) {
|
||||
testMountOptionFSNameEvil(t, "\n")
|
||||
}
|
||||
|
||||
func TestMountOptionFSNameEvilBackslash(t *testing.T) {
|
||||
testMountOptionFSNameEvil(t, `\`)
|
||||
}
|
||||
|
||||
func TestMountOptionFSNameEvilBackslashDouble(t *testing.T) {
|
||||
// catch double-unescaping, if it were to happen
|
||||
testMountOptionFSNameEvil(t, `\\`)
|
||||
}
|
||||
|
||||
func TestMountOptionSubtype(t *testing.T) {
|
||||
if runtime.GOOS == "darwin" {
|
||||
t.Skip("OS X does not support Subtype")
|
||||
}
|
||||
t.Parallel()
|
||||
const name = "FuseTestMarker"
|
||||
mnt, err := fstestutil.MountedT(t, fstestutil.SimpleFS{fstestutil.Dir{}},
|
||||
fuse.Subtype(name),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer mnt.Close()
|
||||
|
||||
info, err := fstestutil.GetMountInfo(mnt.Dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if g, e := info.Type, "fuse."+name; g != e {
|
||||
t.Errorf("wrong Subtype: %q != %q", g, e)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO test LocalVolume
|
||||
|
||||
// TODO test AllowOther; hard because needs system-level authorization
|
||||
|
||||
func TestMountOptionAllowOtherThenAllowRoot(t *testing.T) {
|
||||
t.Parallel()
|
||||
mnt, err := fstestutil.MountedT(t, fstestutil.SimpleFS{fstestutil.Dir{}},
|
||||
fuse.AllowOther(),
|
||||
fuse.AllowRoot(),
|
||||
)
|
||||
if err == nil {
|
||||
mnt.Close()
|
||||
}
|
||||
if g, e := err, fuse.ErrCannotCombineAllowOtherAndAllowRoot; g != e {
|
||||
t.Fatalf("wrong error: %v != %v", g, e)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO test AllowRoot; hard because needs system-level authorization
|
||||
|
||||
func TestMountOptionAllowRootThenAllowOther(t *testing.T) {
|
||||
t.Parallel()
|
||||
mnt, err := fstestutil.MountedT(t, fstestutil.SimpleFS{fstestutil.Dir{}},
|
||||
fuse.AllowRoot(),
|
||||
fuse.AllowOther(),
|
||||
)
|
||||
if err == nil {
|
||||
mnt.Close()
|
||||
}
|
||||
if g, e := err, fuse.ErrCannotCombineAllowOtherAndAllowRoot; g != e {
|
||||
t.Fatalf("wrong error: %v != %v", g, e)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user