예제 #1
0
// Creates a temporary dir "wd" with 3 directories:
// mnt ... overlayed (unionfs) mount
// rw .... modifiable data
// ro .... read-only data
func setupUfs(t *testing.T) (wd string, cleanup func()) {
	// Make sure system setting does not affect test.
	syscall.Umask(0)

	wd = testutil.TempDir()
	err := os.Mkdir(wd+"/mnt", 0700)
	if err != nil {
		t.Fatalf("Mkdir failed: %v", err)
	}

	err = os.Mkdir(wd+"/rw", 0700)
	if err != nil {
		t.Fatalf("Mkdir failed: %v", err)
	}

	os.Mkdir(wd+"/ro", 0700)
	if err != nil {
		t.Fatalf("Mkdir failed: %v", err)
	}

	var fses []pathfs.FileSystem
	fses = append(fses, pathfs.NewLoopbackFileSystem(wd+"/rw"))
	fses = append(fses,
		NewCachingFileSystem(pathfs.NewLoopbackFileSystem(wd+"/ro"), 0))
	ufs, err := NewUnionFs(fses, testOpts)
	if err != nil {
		t.Fatalf("NewUnionFs: %v", err)
	}
	// We configure timeouts are smaller, so we can check for
	// UnionFs's cache consistency.
	opts := &nodefs.Options{
		EntryTimeout:    entryTtl / 2,
		AttrTimeout:     entryTtl / 2,
		NegativeTimeout: entryTtl / 2,
		PortableInodes:  true,
		Debug:           testutil.VerboseTest(),
	}

	pathfs := pathfs.NewPathNodeFs(ufs,
		&pathfs.PathNodeFsOptions{ClientInodes: true,
			Debug: opts.Debug,
		})
	state, _, err := nodefs.MountRoot(wd+"/mnt", pathfs.Root(), opts)
	if err != nil {
		t.Fatalf("MountNodeFileSystem failed: %v", err)
	}
	go state.Serve()
	state.WaitMount()

	return wd, func() {
		err := state.Unmount()
		if err != nil {
			return
		}
		setRecursiveWritable(t, wd, true)
		os.RemoveAll(wd)
	}
}
예제 #2
0
파일: cloudfs.go 프로젝트: shaladdle/goaaw
func New(root, hostport string) (pathfs.FileSystem, error) {
	return &cloudFileSystem{
		root:     root,
		hostport: hostport,
		meta:     pathfs.NewLoopbackFileSystem(path.Join(root, metaName)),
		staging:  pathfs.NewLoopbackFileSystem(path.Join(root, stagingName)),
        remote:   blkstore.NewMemStore()
	}, nil
}
예제 #3
0
func setupCacheTest(t *testing.T) (string, *pathfs.PathNodeFs, func()) {
	dir, err := ioutil.TempDir("", "go-fuse-cachetest")
	if err != nil {
		t.Fatalf("TempDir failed: %v", err)
	}
	os.Mkdir(dir+"/mnt", 0755)
	os.Mkdir(dir+"/orig", 0755)

	fs := &cacheFs{
		pathfs.NewLoopbackFileSystem(dir + "/orig"),
	}
	pfs := pathfs.NewPathNodeFs(fs, nil)
	state, conn, err := nodefs.MountRoot(dir+"/mnt", pfs.Root(), nil)
	if err != nil {
		t.Fatalf("MountNodeFileSystem failed: %v", err)
	}
	state.SetDebug(VerboseTest())
	conn.SetDebug(VerboseTest())
	pfs.SetDebug(VerboseTest())
	go state.Serve()

	return dir, pfs, func() {
		err := state.Unmount()
		if err == nil {
			os.RemoveAll(dir)
		}
	}
}
예제 #4
0
func setupCacheTest(t *testing.T) (string, *pathfs.PathNodeFs, func()) {
	dir := testutil.TempDir()
	os.Mkdir(dir+"/mnt", 0755)
	os.Mkdir(dir+"/orig", 0755)

	fs := &cacheFs{
		pathfs.NewLoopbackFileSystem(dir + "/orig"),
	}
	pfs := pathfs.NewPathNodeFs(fs, &pathfs.PathNodeFsOptions{Debug: testutil.VerboseTest()})

	opts := nodefs.NewOptions()
	opts.Debug = testutil.VerboseTest()
	state, _, err := nodefs.MountRoot(dir+"/mnt", pfs.Root(), opts)
	if err != nil {
		t.Fatalf("MountNodeFileSystem failed: %v", err)
	}
	go state.Serve()
	if err := state.WaitMount(); err != nil {
		t.Fatal("WaitMount", err)
	}
	return dir, pfs, func() {
		err := state.Unmount()
		if err == nil {
			os.RemoveAll(dir)
		}
	}
}
예제 #5
0
파일: fs.go 프로젝트: cautio/gocryptfs
// Encrypted FUSE overlay filesystem
func NewFS(args Args) *FS {
	return &FS{
		CryptFS:    cryptfs.NewCryptFS(args.Masterkey, args.OpenSSL, args.PlaintextNames, args.GCMIV128),
		FileSystem: pathfs.NewLoopbackFileSystem(args.Cipherdir),
		args:       args,
	}
}
예제 #6
0
파일: fs.go 프로젝트: theit8514/gocryptfs
// Encrypted FUSE overlay filesystem
func NewFS(key []byte, backing string, useOpenssl bool) *FS {
	return &FS{
		CryptFS:    cryptfs.NewCryptFS(key, useOpenssl),
		FileSystem: pathfs.NewLoopbackFileSystem(backing),
		backing:    backing,
	}
}
예제 #7
0
func TestOriginalIsSymlink(t *testing.T) {
	tmpDir := testutil.TempDir()
	defer os.RemoveAll(tmpDir)
	orig := tmpDir + "/orig"
	err := os.Mkdir(orig, 0755)
	if err != nil {
		t.Fatalf("Mkdir failed: %v", err)
	}
	link := tmpDir + "/link"
	mnt := tmpDir + "/mnt"
	if err := os.Mkdir(mnt, 0755); err != nil {
		t.Fatalf("Mkdir failed: %v", err)
	}
	if err := os.Symlink("orig", link); err != nil {
		t.Fatalf("Symlink failed: %v", err)
	}

	fs := pathfs.NewLoopbackFileSystem(link)
	nfs := pathfs.NewPathNodeFs(fs, nil)
	state, _, err := nodefs.MountRoot(mnt, nfs.Root(), nil)
	if err != nil {
		t.Fatalf("MountNodeFileSystem failed: %v", err)
	}
	defer state.Unmount()

	go state.Serve()
	if err := state.WaitMount(); err != nil {
		t.Fatal("WaitMount", err)
	}

	if _, err := os.Lstat(mnt); err != nil {
		t.Fatalf("Lstat failed: %v", err)
	}
}
예제 #8
0
// Create and mount filesystem.
func NewTestCase(t *testing.T) *testCase {
	tc := &testCase{}
	tc.tester = t

	// Make sure system setting does not affect test.
	syscall.Umask(0)

	const name string = "hello.txt"
	const subdir string = "subdir"

	var err error
	tc.tmpDir, err = ioutil.TempDir("", "go-fuse")
	if err != nil {
		t.Fatalf("TempDir failed: %v", err)
	}
	tc.orig = tc.tmpDir + "/orig"
	tc.mnt = tc.tmpDir + "/mnt"

	tc.Mkdir(tc.orig, 0700)
	tc.Mkdir(tc.mnt, 0700)

	tc.mountFile = filepath.Join(tc.mnt, name)
	tc.mountSubdir = filepath.Join(tc.mnt, subdir)
	tc.origFile = filepath.Join(tc.orig, name)
	tc.origSubdir = filepath.Join(tc.orig, subdir)

	var pfs pathfs.FileSystem
	pfs = pathfs.NewLoopbackFileSystem(tc.orig)
	pfs = pathfs.NewLockingFileSystem(pfs)

	tc.pathFs = pathfs.NewPathNodeFs(pfs, &pathfs.PathNodeFsOptions{
		ClientInodes: true})
	tc.connector = nodefs.NewFileSystemConnector(tc.pathFs.Root(),
		&nodefs.Options{
			EntryTimeout:    testTtl,
			AttrTimeout:     testTtl,
			NegativeTimeout: 0.0,
			Debug:           VerboseTest(),
		})
	tc.state, err = fuse.NewServer(
		fuse.NewRawFileSystem(tc.connector.RawFS()), tc.mnt, &fuse.MountOptions{
			SingleThreaded: true,
			Debug:          VerboseTest(),
		})
	if err != nil {
		t.Fatal("NewServer:", err)
	}

	go tc.state.Serve()
	if err := tc.state.WaitMount(); err != nil {
		t.Fatal("WaitMount", err)
	}
	return tc
}
예제 #9
0
// Create and mount filesystem.
func NewTestCase(t *testing.T) *testCase {
	me := &testCase{}
	me.tester = t

	// Make sure system setting does not affect test.
	syscall.Umask(0)

	const name string = "hello.txt"
	const subdir string = "subdir"

	var err error
	me.tmpDir, err = ioutil.TempDir("", "go-fuse")
	if err != nil {
		t.Fatalf("TempDir failed: %v", err)
	}
	me.orig = me.tmpDir + "/orig"
	me.mnt = me.tmpDir + "/mnt"

	os.Mkdir(me.orig, 0700)
	os.Mkdir(me.mnt, 0700)

	me.mountFile = filepath.Join(me.mnt, name)
	me.mountSubdir = filepath.Join(me.mnt, subdir)
	me.origFile = filepath.Join(me.orig, name)
	me.origSubdir = filepath.Join(me.orig, subdir)

	var pfs pathfs.FileSystem
	pfs = pathfs.NewLoopbackFileSystem(me.orig)
	pfs = pathfs.NewLockingFileSystem(pfs)

	me.pathFs = pathfs.NewPathNodeFs(pfs, &pathfs.PathNodeFsOptions{
		ClientInodes: true})
	me.connector = nodefs.NewFileSystemConnector(me.pathFs.Root(),
		&nodefs.Options{
			EntryTimeout:    testTtl,
			AttrTimeout:     testTtl,
			NegativeTimeout: 0.0,
		})
	me.connector.SetDebug(VerboseTest())
	me.state, err = fuse.NewServer(
		fuse.NewRawFileSystem(me.connector.RawFS()), me.mnt, &fuse.MountOptions{SingleThreaded: true})
	if err != nil {
		t.Fatal("NewServer:", err)
	}

	me.state.SetDebug(VerboseTest())

	// Unthreaded, but in background.
	go me.state.Serve()

	me.state.WaitMount()
	return me
}
예제 #10
0
파일: fs.go 프로젝트: rfjakob/gocryptfs
// NewFS returns a new encrypted FUSE overlay filesystem.
func NewFS(args Args) *FS {
	cryptoCore := cryptocore.New(args.Masterkey, args.CryptoBackend, contentenc.DefaultIVBits)
	contentEnc := contentenc.New(cryptoCore, contentenc.DefaultBS)
	nameTransform := nametransform.New(cryptoCore, args.LongNames, args.Raw64)

	return &FS{
		FileSystem:    pathfs.NewLoopbackFileSystem(args.Cipherdir),
		args:          args,
		nameTransform: nameTransform,
		contentEnc:    contentEnc,
	}
}
예제 #11
0
파일: paths_test.go 프로젝트: LK4D4/grfuse
func startLoopbackServer(root string) (*loopbackServer, error) {
	l, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		return nil, err
	}
	s := grpc.NewServer()
	nfs := pathfs.NewLoopbackFileSystem(root)
	pb.RegisterPathFSServer(s, server.New(nfs))
	go s.Serve(l)
	return &loopbackServer{
		Server: s,
		Addr:   l.Addr().String(),
	}, nil
}
예제 #12
0
func TestMountRename(t *testing.T) {
	ts := NewTestCase(t)
	defer ts.Cleanup()

	fs := pathfs.NewPathNodeFs(pathfs.NewLoopbackFileSystem(ts.orig), nil)
	code := ts.connector.Mount(ts.rootNode(), "mnt", fs.Root(), nil)
	if !code.Ok() {
		t.Fatal("mount should succeed")
	}
	err := os.Rename(ts.mnt+"/mnt", ts.mnt+"/foobar")
	if fuse.ToStatus(err) != fuse.EBUSY {
		t.Fatal("rename mount point should fail with EBUSY:", err)
	}
	ts.pathFs.Unmount("mnt")
}
예제 #13
0
func TestGetAttrRace(t *testing.T) {
	dir, err := ioutil.TempDir("", "go-fuse-cache_test")
	if err != nil {
		t.Fatalf("failed: %v", err)
	}
	defer os.RemoveAll(dir)
	os.Mkdir(dir+"/mnt", 0755)
	os.Mkdir(dir+"/orig", 0755)

	fs := pathfs.NewLoopbackFileSystem(dir + "/orig")
	pfs := pathfs.NewPathNodeFs(fs, nil)
	state, conn, err := nodefs.MountRoot(dir+"/mnt", pfs.Root(),
		&nodefs.Options{})
	if err != nil {
		t.Fatalf("MountNodeFileSystem failed: %v", err)
	}
	state.SetDebug(VerboseTest())
	conn.SetDebug(VerboseTest())
	pfs.SetDebug(VerboseTest())
	go state.Serve()

	defer state.Unmount()

	var wg sync.WaitGroup

	n := 100
	wg.Add(n)
	var statErr error
	for i := 0; i < n; i++ {
		go func() {
			defer wg.Done()
			fn := dir + "/mnt/file"
			err := ioutil.WriteFile(fn, []byte{42}, 0644)
			if err != nil {
				statErr = err
				return
			}
			_, err = os.Lstat(fn)
			if err != nil {
				statErr = err
			}
		}()
	}
	wg.Wait()
	if statErr != nil {
		t.Error(statErr)
	}
}
예제 #14
0
func TestRecursiveMount(t *testing.T) {
	ts := NewTestCase(t)
	defer ts.Cleanup()

	err := ioutil.WriteFile(ts.orig+"/hello.txt", []byte("blabla"), 0644)
	if err != nil {
		t.Fatalf("WriteFile failed: %v", err)
	}

	fs := pathfs.NewPathNodeFs(pathfs.NewLoopbackFileSystem(ts.orig), nil)
	code := ts.connector.Mount(ts.rootNode(), "mnt", fs.Root(), nil)
	if !code.Ok() {
		t.Fatal("mount should succeed")
	}

	submnt := ts.mnt + "/mnt"
	_, err = os.Lstat(submnt)
	if err != nil {
		t.Fatalf("Lstat failed: %v", err)
	}
	_, err = os.Lstat(filepath.Join(submnt, "hello.txt"))
	if err != nil {
		t.Fatalf("Lstat failed: %v", err)
	}

	f, err := os.Open(filepath.Join(submnt, "hello.txt"))
	if err != nil {
		t.Fatalf("Open failed: %v", err)
	}
	code = ts.pathFs.Unmount("mnt")
	if code != fuse.EBUSY {
		t.Error("expect EBUSY")
	}

	if err := f.Close(); err != nil {
		t.Errorf("close: %v", err)
	}

	// We can't avoid a sleep here: the file handle release is not
	// synchronized.
	t.Log("Waiting for kernel to flush file-close to fuse...")
	time.Sleep(testTtl)

	code = ts.pathFs.Unmount("mnt")
	if code != fuse.OK {
		t.Error("umount failed.", code)
	}
}
예제 #15
0
파일: fs.go 프로젝트: osrg/hookfs
// Instantiate a new HookFS object
func NewHookFs(original string, mountpoint string, hook Hook) (*HookFs, error) {
	log.WithFields(log.Fields{
		"original":   original,
		"mountpoint": mountpoint,
	}).Debug("Hooking a fs")

	loopbackfs := pathfs.NewLoopbackFileSystem(original)
	hookfs := &HookFs{
		Original:   original,
		Mountpoint: mountpoint,
		FsName:     "hookfs",
		fs:         loopbackfs,
		hook:       hook,
	}
	return hookfs, nil
}
예제 #16
0
func TestCachingFs(t *testing.T) {
	wd := testutil.TempDir()
	defer os.RemoveAll(wd)

	fs := pathfs.NewLoopbackFileSystem(wd)
	cfs := NewCachingFileSystem(fs, 0)

	os.Mkdir(wd+"/orig", 0755)
	fi, code := cfs.GetAttr("orig", nil)
	if !code.Ok() {
		t.Fatal("GetAttr failure", code)
	}
	if !fi.IsDir() {
		t.Error("unexpected attr", fi)
	}

	os.Symlink("orig", wd+"/symlink")

	val, code := cfs.Readlink("symlink", nil)
	if val != "orig" {
		t.Error("unexpected readlink", val)
	}
	if !code.Ok() {
		t.Error("code !ok ", code)
	}

	stream, code := cfs.OpenDir("", nil)
	if !code.Ok() {
		t.Fatal("Readdir fail", code)
	}

	results := make(map[string]uint32)
	for _, v := range stream {
		results[v.Name] = v.Mode &^ 07777
	}
	expected := map[string]uint32{
		"symlink": syscall.S_IFLNK,
		"orig":    fuse.S_IFDIR,
	}
	if !modeMapEq(results, expected) {
		t.Error("Unexpected readdir result", results, expected)
	}
}
예제 #17
0
func TestMountReaddir(t *testing.T) {
	ts := NewTestCase(t)
	defer ts.Cleanup()

	fs := pathfs.NewPathNodeFs(pathfs.NewLoopbackFileSystem(ts.orig), nil)
	code := ts.connector.Mount(ts.rootNode(), "mnt", fs.Root(), nil)
	if !code.Ok() {
		t.Fatal("mount should succeed")
	}

	entries, err := ioutil.ReadDir(ts.mnt)
	if err != nil {
		t.Fatalf("ReadDir failed: %v", err)
	}
	if len(entries) != 1 || entries[0].Name() != "mnt" {
		t.Error("wrong readdir result", entries)
	}
	ts.pathFs.Unmount("mnt")
}
예제 #18
0
파일: multifs.go 프로젝트: hanwen/gitfs
func (n *configNode) Symlink(name string, content string, context *fuse.Context) (*nodefs.Inode, fuse.Status) {
	dir := content
	components := strings.Split(content, ":")
	if len(components) > 2 || len(components) == 0 {
		return nil, fuse.Status(syscall.EINVAL)
	}

	var root nodefs.Node
	if len(components) == 2 {
		dir = components[0]
	}

	if fi, err := os.Lstat(dir); err != nil {
		return nil, fuse.ToStatus(err)
	} else if !fi.IsDir() {
		return nil, fuse.Status(syscall.ENOTDIR)
	}

	var opts *nodefs.Options
	if len(components) == 1 {
		root = pathfs.NewPathNodeFs(pathfs.NewLoopbackFileSystem(content), nil).Root()
	} else {
		var err error
		root, err = NewGitFSRoot(content, n.fs.opts)
		if err != nil {
			log.Printf("NewGitFSRoot(%q): %v", content, err)
			return nil, fuse.ENOENT
		}
		opts = &nodefs.Options{
			EntryTimeout:    time.Hour,
			NegativeTimeout: time.Hour,
			AttrTimeout:     time.Hour,
			PortableInodes:  true,
		}
	}

	if code := n.fs.fsConn.Mount(n.corresponding.Inode(), name, root, opts); !code.Ok() {
		return nil, code
	}

	linkNode := newGitConfigNode(content)
	return n.Inode().NewChild(name, false, linkNode), fuse.OK
}
예제 #19
0
파일: main.go 프로젝트: eliq/go-fuse
func main() {
	// Scans the arg list and sets up flags
	debug := flag.Bool("debug", false, "print debugging messages.")
	other := flag.Bool("allow-other", false, "mount with -o allowother.")
	flag.Parse()
	if flag.NArg() < 2 {
		// TODO - where to get program name?
		fmt.Println("usage: main MOUNTPOINT ORIGINAL")
		os.Exit(2)
	}

	var finalFs pathfs.FileSystem
	orig := flag.Arg(1)
	loopbackfs := pathfs.NewLoopbackFileSystem(orig)
	finalFs = loopbackfs

	opts := &nodefs.Options{
		// These options are to be compatible with libfuse defaults,
		// making benchmarking easier.
		NegativeTimeout: time.Second,
		AttrTimeout:     time.Second,
		EntryTimeout:    time.Second,
	}
	pathFs := pathfs.NewPathNodeFs(finalFs, nil)
	conn := nodefs.NewFileSystemConnector(pathFs.Root(), opts)
	mountPoint := flag.Arg(0)
	origAbs, _ := filepath.Abs(orig)
	mOpts := &fuse.MountOptions{
		AllowOther: *other,
		Name:       "loopbackfs",
		FsName:     origAbs,
	}
	state, err := fuse.NewServer(conn.RawFS(), mountPoint, mOpts)
	if err != nil {
		fmt.Printf("Mount fail: %v\n", err)
		os.Exit(1)
	}
	state.SetDebug(*debug)

	fmt.Println("Mounted!")
	state.Serve()
}
예제 #20
0
파일: rfs.go 프로젝트: rfjakob/gocryptfs
// NewFS returns an encrypted FUSE overlay filesystem.
// In this case (reverse mode) the backing directory is plain-text and
// ReverseFS provides an encrypted view.
func NewFS(args fusefrontend.Args) *ReverseFS {
	if args.CryptoBackend != cryptocore.BackendAESSIV {
		log.Panic("reverse mode must use AES-SIV, everything else is insecure")
	}
	initLongnameCache()
	cryptoCore := cryptocore.New(args.Masterkey, args.CryptoBackend, contentenc.DefaultIVBits)
	contentEnc := contentenc.New(cryptoCore, contentenc.DefaultBS)
	nameTransform := nametransform.New(cryptoCore, args.LongNames, args.Raw64)

	return &ReverseFS{
		// pathfs.defaultFileSystem returns ENOSYS for all operations
		FileSystem:    pathfs.NewDefaultFileSystem(),
		loopbackfs:    pathfs.NewLoopbackFileSystem(args.Cipherdir),
		args:          args,
		nameTransform: nameTransform,
		contentEnc:    contentEnc,
		inoGen:        newInoGen(),
		inoMap:        map[fusefrontend.DevInoStruct]uint64{},
	}
}
예제 #21
0
// Must run inside mutex.
func (me *memNode) promote() {
	if me.backing == "" {
		me.backing = me.fs.getFilename()
		destfs := pathfs.NewLoopbackFileSystem("/")
		pathfs.CopyFile(me.fs.readonly, destfs,
			me.original, strings.TrimLeft(me.backing, "/"), nil)
		me.original = ""
		files := me.Inode().Files(0)
		for _, f := range files {
			mf := f.File.(*memNodeFile)
			inner := mf.File
			osFile, err := os.Open(me.backing)
			if err != nil {
				panic("error opening backing file")
			}
			mf.File = nodefs.NewLoopbackFile(osFile)
			inner.Flush()
			inner.Release()
		}
	}
}
예제 #22
0
func setupMemUfs(t *testing.T) (workdir string, ufs *MemUnionFs, cleanup func()) {
	// Make sure system setting does not affect test.
	syscall.Umask(0)

	wd, _ := ioutil.TempDir("", "")
	err := os.Mkdir(wd+"/mnt", 0700)
	CheckSuccess(err)

	err = os.Mkdir(wd+"/backing", 0700)
	CheckSuccess(err)

	os.Mkdir(wd+"/ro", 0700)
	CheckSuccess(err)

	roFs := pathfs.NewLoopbackFileSystem(wd + "/ro")
	memFs, err := NewMemUnionFs(wd+"/backing", roFs)
	if err != nil {
		t.Fatal(err)
	}

	// We configure timeouts are smaller, so we can check for
	// UnionFs's cache consistency.
	opts := &nodefs.Options{
		EntryTimeout:    entryTtl / 2,
		AttrTimeout:     entryTtl / 2,
		NegativeTimeout: entryTtl / 2,
		PortableInodes:  true,
	}

	state, conn, err := nodefs.MountRoot(wd+"/mnt", memFs.Root(), opts)
	CheckSuccess(err)
	conn.SetDebug(VerboseTest())
	state.SetDebug(VerboseTest())
	go state.Serve()

	return wd, memFs, func() {
		state.Unmount()
		os.RemoveAll(wd)
	}
}
예제 #23
0
func TestDeletedUnmount(t *testing.T) {
	ts := NewTestCase(t)
	defer ts.Cleanup()

	submnt := filepath.Join(ts.mnt, "mnt")
	pfs2 := pathfs.NewPathNodeFs(pathfs.NewLoopbackFileSystem(ts.orig), nil)
	code := ts.connector.Mount(ts.rootNode(), "mnt", pfs2, nil)
	if !code.Ok() {
		t.Fatal("Mount error", code)
	}
	f, err := os.Create(filepath.Join(submnt, "hello.txt"))
	if err != nil {
		t.Fatalf("Create failed: %v", err)
	}

	t.Log("Removing")
	err = os.Remove(filepath.Join(submnt, "hello.txt"))
	if err != nil {
		t.Fatalf("Remove failed: %v", err)
	}

	t.Log("Removing")
	_, err = f.Write([]byte("bla"))
	if err != nil {
		t.Fatalf("Write failed: %v", err)
	}

	code = ts.pathFs.Unmount("mnt")
	if code != fuse.EBUSY {
		t.Error("expect EBUSY for unmount with open files", code)
	}

	f.Close()
	time.Sleep((3 * testTtl) / 2)
	code = ts.pathFs.Unmount("mnt")
	if !code.Ok() {
		t.Error("should succeed", code)
	}
}
예제 #24
0
func TestOriginalIsSymlink(t *testing.T) {
	tmpDir, err := ioutil.TempDir("", "go-fuse-loopback_test")
	if err != nil {
		t.Fatalf("TempDir failed: %v", err)
	}
	defer os.RemoveAll(tmpDir)
	orig := tmpDir + "/orig"
	err = os.Mkdir(orig, 0755)
	if err != nil {
		t.Fatalf("Mkdir failed: %v", err)
	}
	link := tmpDir + "/link"
	mnt := tmpDir + "/mnt"
	err = os.Mkdir(mnt, 0755)
	if err != nil {
		t.Fatalf("Mkdir failed: %v", err)
	}
	err = os.Symlink("orig", link)
	if err != nil {
		t.Fatalf("Symlink failed: %v", err)
	}

	fs := pathfs.NewLoopbackFileSystem(link)
	nfs := pathfs.NewPathNodeFs(fs, nil)
	state, _, err := nodefs.MountFileSystem(mnt, nfs, nil)
	if err != nil {
		t.Fatalf("MountNodeFileSystem failed: %v", err)
	}
	defer state.Unmount()

	go state.Serve()

	_, err = os.Lstat(mnt)
	if err != nil {
		t.Fatalf("Lstat failed: %v", err)
	}
}
예제 #25
0
파일: create.go 프로젝트: rfjakob/go-fuse
func NewUnionFsFromRoots(roots []string, opts *UnionFsOptions, roCaching bool) (pathfs.FileSystem, error) {
	fses := make([]pathfs.FileSystem, 0)
	for i, r := range roots {
		var fs pathfs.FileSystem
		fi, err := os.Stat(r)
		if err != nil {
			return nil, err
		}
		if fi.IsDir() {
			fs = pathfs.NewLoopbackFileSystem(r)
		}
		if fs == nil {
			return nil, err

		}
		if i > 0 && roCaching {
			fs = NewCachingFileSystem(fs, 0)
		}

		fses = append(fses, fs)
	}

	return NewUnionFs(fses, *opts)
}
예제 #26
0
func TestXAttrCaching(t *testing.T) {
	wd := testutil.TempDir()
	defer os.RemoveAll(wd)
	os.Mkdir(wd+"/mnt", 0700)
	err := os.Mkdir(wd+"/rw", 0700)
	if err != nil {
		t.Fatalf("Mkdir failed: %v", err)
	}

	rwFS := pathfs.NewLoopbackFileSystem(wd + "/rw")
	roFS := &TestFS{
		FileSystem: pathfs.NewDefaultFileSystem(),
	}

	ufs, err := NewUnionFs([]pathfs.FileSystem{rwFS,
		NewCachingFileSystem(roFS, entryTtl)}, testOpts)
	if err != nil {
		t.Fatalf("NewUnionFs: %v", err)
	}

	opts := &nodefs.Options{
		EntryTimeout:    entryTtl / 2,
		AttrTimeout:     entryTtl / 2,
		NegativeTimeout: entryTtl / 2,
		Debug:           testutil.VerboseTest(),
	}

	pathfs := pathfs.NewPathNodeFs(ufs,
		&pathfs.PathNodeFsOptions{ClientInodes: true,
			Debug: testutil.VerboseTest()})

	server, _, err := nodefs.MountRoot(wd+"/mnt", pathfs.Root(), opts)
	if err != nil {
		t.Fatalf("MountNodeFileSystem failed: %v", err)
	}
	defer server.Unmount()
	go server.Serve()
	server.WaitMount()

	if fi, err := os.Lstat(wd + "/mnt"); err != nil || !fi.IsDir() {
		t.Fatalf("root not readable: %v, %v", err, fi)
	}

	buf := make([]byte, 1024)
	n, err := Getxattr(wd+"/mnt/file", "user.attr", buf)
	if err != nil {
		t.Fatalf("Getxattr: %v", err)
	}
	want := "\x2a"
	got := string(buf[:n])
	if got != want {
		t.Fatalf("Got %q want %q", got, err)
	}

	time.Sleep(entryTtl / 3)

	n, err = Getxattr(wd+"/mnt/file", "user.attr", buf)
	if err != nil {
		t.Fatalf("Getxattr: %v", err)
	}
	got = string(buf[:n])
	if got != want {
		t.Fatalf("Got %q want %q", got, err)
	}

	time.Sleep(entryTtl / 3)

	// Make sure that an interceding Getxattr() to a filesystem that doesn't implement GetXAttr() doesn't affect future calls.
	Getxattr(wd, "whatever", buf)

	n, err = Getxattr(wd+"/mnt/file", "user.attr", buf)
	if err != nil {
		t.Fatalf("Getxattr: %v", err)
	}
	got = string(buf[:n])
	if got != want {
		t.Fatalf("Got %q want %q", got, err)
	}

	if roFS.xattrRead != 1 {
		t.Errorf("got xattrRead=%d, want 1", roFS.xattrRead)
	}
}
예제 #27
0
파일: main.go 프로젝트: rfjakob/go-fuse
func main() {
	log.SetFlags(log.Lmicroseconds)
	// Scans the arg list and sets up flags
	debug := flag.Bool("debug", false, "print debugging messages.")
	other := flag.Bool("allow-other", false, "mount with -o allowother.")
	enableLinks := flag.Bool("l", false, "Enable hard link support")
	cpuprofile := flag.String("cpuprofile", "", "write cpu profile to this file")
	memprofile := flag.String("memprofile", "", "write memory profile to this file")
	flag.Parse()
	if flag.NArg() < 2 {
		fmt.Printf("usage: %s MOUNTPOINT ORIGINAL\n", path.Base(os.Args[0]))
		fmt.Printf("\noptions:\n")
		flag.PrintDefaults()
		os.Exit(2)
	}
	if *cpuprofile != "" {
		fmt.Printf("Writing cpu profile to %s\n", *cpuprofile)
		f, err := os.Create(*cpuprofile)
		if err != nil {
			fmt.Println(err)
			os.Exit(3)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}
	if *memprofile != "" {
		log.Printf("send SIGUSR1 to %d to dump memory profile", os.Getpid())
		profSig := make(chan os.Signal, 1)
		signal.Notify(profSig, syscall.SIGUSR1)
		go writeMemProfile(*memprofile, profSig)
	}
	if *cpuprofile != "" || *memprofile != "" {
		fmt.Printf("Note: You must unmount gracefully, otherwise the profile file(s) will stay empty!\n")
	}

	var finalFs pathfs.FileSystem
	orig := flag.Arg(1)
	loopbackfs := pathfs.NewLoopbackFileSystem(orig)
	finalFs = loopbackfs

	opts := &nodefs.Options{
		// These options are to be compatible with libfuse defaults,
		// making benchmarking easier.
		NegativeTimeout: time.Second,
		AttrTimeout:     time.Second,
		EntryTimeout:    time.Second,
	}
	// Enable ClientInodes so hard links work
	pathFsOpts := &pathfs.PathNodeFsOptions{ClientInodes: *enableLinks}
	pathFs := pathfs.NewPathNodeFs(finalFs, pathFsOpts)
	conn := nodefs.NewFileSystemConnector(pathFs.Root(), opts)
	mountPoint := flag.Arg(0)
	origAbs, _ := filepath.Abs(orig)
	mOpts := &fuse.MountOptions{
		AllowOther: *other,
		Name:       "loopbackfs",
		FsName:     origAbs,
		Debug:      *debug,
	}
	state, err := fuse.NewServer(conn.RawFS(), mountPoint, mOpts)
	if err != nil {
		fmt.Printf("Mount fail: %v\n", err)
		os.Exit(1)
	}

	fmt.Println("Mounted!")
	state.Serve()
}
예제 #28
0
func TestXAttrCaching(t *testing.T) {
	wd, _ := ioutil.TempDir("", "unionfs")
	defer os.RemoveAll(wd)
	os.Mkdir(wd+"/mnt", 0700)
	err := os.Mkdir(wd+"/rw", 0700)
	if err != nil {
		t.Fatalf("Mkdir failed: %v", err)
	}

	rwFS := pathfs.NewLoopbackFileSystem(wd + "/rw")
	roFS := &TestFS{
		FileSystem: pathfs.NewDefaultFileSystem(),
	}

	ufs, err := NewUnionFs([]pathfs.FileSystem{rwFS,
		NewCachingFileSystem(roFS, entryTtl)}, testOpts)
	if err != nil {
		t.Fatalf("NewUnionFs: %v", err)
	}

	opts := &nodefs.Options{
		EntryTimeout:    entryTtl / 2,
		AttrTimeout:     entryTtl / 2,
		NegativeTimeout: entryTtl / 2,
	}

	pathfs := pathfs.NewPathNodeFs(ufs,
		&pathfs.PathNodeFsOptions{ClientInodes: true})

	server, conn, err := nodefs.MountRoot(wd+"/mnt", pathfs.Root(), opts)
	if err != nil {
		t.Fatalf("MountNodeFileSystem failed: %v", err)
	}
	server.SetDebug(VerboseTest())
	conn.SetDebug(VerboseTest())
	pathfs.SetDebug(VerboseTest())
	defer server.Unmount()
	go server.Serve()

	if fi, err := os.Lstat(wd + "/mnt"); err != nil || !fi.IsDir() {
		t.Fatalf("root not readable: %v, %v", err, fi)
	}

	buf := make([]byte, 1024)
	n, err := syscall.Getxattr(wd+"/mnt/file", "user.attr", buf)
	if err != nil {
		t.Fatalf("Getxattr: %v", err)
	}
	want := "\x2a"
	got := string(buf[:n])
	if got != want {
		t.Fatalf("Got %q want %q", got, err)
	}
	time.Sleep(entryTtl / 2)
	n, err = syscall.Getxattr(wd+"/mnt/file", "user.attr", buf)
	if err != nil {
		t.Fatalf("Getxattr: %v", err)
	}
	got = string(buf[:n])
	if got != want {
		t.Fatalf("Got %q want %q", got, err)
	}
	server.Unmount()
	if roFS.xattrRead != 1 {
		t.Errorf("got xattrRead=%d, want 1", roFS.xattrRead)
	}
}
예제 #29
0
func (me *memNode) StatFs() *fuse.StatfsOut {
	backingFs := pathfs.NewLoopbackFileSystem(me.fs.backingStore)
	return backingFs.StatFs("")
}
예제 #30
0
func TestUnionFsDisappearing(t *testing.T) {
	// This init is like setupUfs, but we want access to the
	// writable Fs.
	wd, _ := ioutil.TempDir("", "")
	defer os.RemoveAll(wd)
	err := os.Mkdir(wd+"/mnt", 0700)
	if err != nil {
		t.Fatalf("Mkdir failed: %v", err)
	}

	err = os.Mkdir(wd+"/rw", 0700)
	if err != nil {
		t.Fatalf("Mkdir failed: %v", err)
	}

	os.Mkdir(wd+"/ro", 0700)
	if err != nil {
		t.Fatalf("Mkdir failed: %v", err)
	}

	wrFs := newDisappearingFS(pathfs.NewLoopbackFileSystem(wd+"/rw"),
		pathfs.NewLoopbackFileSystem("/dev/null"))
	var fses []pathfs.FileSystem
	fses = append(fses, pathfs.NewLockingFileSystem(wrFs))
	fses = append(fses, pathfs.NewLoopbackFileSystem(wd+"/ro"))
	ufs, err := NewUnionFs(fses, testOpts)
	if err != nil {
		t.Fatalf("NewUnionFs: %v", err)
	}

	opts := &nodefs.Options{
		EntryTimeout:    entryTtl,
		AttrTimeout:     entryTtl,
		NegativeTimeout: entryTtl,
	}

	nfs := pathfs.NewPathNodeFs(ufs, nil)
	state, _, err := nodefs.MountRoot(wd+"/mnt", nfs.Root(), opts)
	if err != nil {
		t.Fatalf("MountNodeFileSystem failed: %v", err)
	}
	defer state.Unmount()
	state.SetDebug(VerboseTest())
	go state.Serve()

	err = ioutil.WriteFile(wd+"/ro/file", []byte("blabla"), 0644)
	if err != nil {
		t.Fatalf("WriteFile failed: %v", err)
	}
	setRecursiveWritable(t, wd+"/ro", false)

	err = os.Remove(wd + "/mnt/file")
	if err != nil {
		t.Fatalf("Remove failed: %v", err)
	}

	wrFs.visibleChan <- false
	time.Sleep((3 * entryTtl) / 2)

	_, err = ioutil.ReadDir(wd + "/mnt")
	if err == nil {
		t.Fatal("Readdir should have failed")
	}

	err = ioutil.WriteFile(wd+"/mnt/file2", []byte("blabla"), 0644)
	if err == nil {
		t.Fatal("write should have failed")
	}

	// Restore, and wait for caches to catch up.
	wrFs.visibleChan <- true
	time.Sleep((3 * entryTtl) / 2)

	_, err = ioutil.ReadDir(wd + "/mnt")
	if err != nil {
		t.Fatal("Readdir should succeed", err)
	}
	err = ioutil.WriteFile(wd+"/mnt/file2", []byte("blabla"), 0644)
	if err != nil {
		t.Fatal("write should succeed", err)
	}
}