github.com/hanwen/go-fuse@v1.0.0/example/loopback/main.go (about)

     1  // Copyright 2016 the Go-FUSE Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Mounts another directory as loopback for testing and benchmarking
     6  // purposes.
     7  
     8  package main
     9  
    10  import (
    11  	"flag"
    12  	"fmt"
    13  	"log"
    14  	"os"
    15  	"os/signal"
    16  	"path"
    17  	"path/filepath"
    18  	"runtime/pprof"
    19  	"syscall"
    20  	"time"
    21  
    22  	"github.com/hanwen/go-fuse/fuse"
    23  	"github.com/hanwen/go-fuse/fuse/nodefs"
    24  	"github.com/hanwen/go-fuse/fuse/pathfs"
    25  )
    26  
    27  func writeMemProfile(fn string, sigs <-chan os.Signal) {
    28  	i := 0
    29  	for range sigs {
    30  		fn := fmt.Sprintf("%s-%d.memprof", fn, i)
    31  		i++
    32  
    33  		log.Printf("Writing mem profile to %s\n", fn)
    34  		f, err := os.Create(fn)
    35  		if err != nil {
    36  			log.Printf("Create: %v", err)
    37  			continue
    38  		}
    39  		pprof.WriteHeapProfile(f)
    40  		if err := f.Close(); err != nil {
    41  			log.Printf("close %v", err)
    42  		}
    43  	}
    44  }
    45  
    46  func main() {
    47  	log.SetFlags(log.Lmicroseconds)
    48  	// Scans the arg list and sets up flags
    49  	debug := flag.Bool("debug", false, "print debugging messages.")
    50  	other := flag.Bool("allow-other", false, "mount with -o allowother.")
    51  	enableLinks := flag.Bool("l", false, "Enable hard link support")
    52  	cpuprofile := flag.String("cpuprofile", "", "write cpu profile to this file")
    53  	memprofile := flag.String("memprofile", "", "write memory profile to this file")
    54  	flag.Parse()
    55  	if flag.NArg() < 2 {
    56  		fmt.Printf("usage: %s MOUNTPOINT ORIGINAL\n", path.Base(os.Args[0]))
    57  		fmt.Printf("\noptions:\n")
    58  		flag.PrintDefaults()
    59  		os.Exit(2)
    60  	}
    61  	if *cpuprofile != "" {
    62  		fmt.Printf("Writing cpu profile to %s\n", *cpuprofile)
    63  		f, err := os.Create(*cpuprofile)
    64  		if err != nil {
    65  			fmt.Println(err)
    66  			os.Exit(3)
    67  		}
    68  		pprof.StartCPUProfile(f)
    69  		defer pprof.StopCPUProfile()
    70  	}
    71  	if *memprofile != "" {
    72  		log.Printf("send SIGUSR1 to %d to dump memory profile", os.Getpid())
    73  		profSig := make(chan os.Signal, 1)
    74  		signal.Notify(profSig, syscall.SIGUSR1)
    75  		go writeMemProfile(*memprofile, profSig)
    76  	}
    77  	if *cpuprofile != "" || *memprofile != "" {
    78  		fmt.Printf("Note: You must unmount gracefully, otherwise the profile file(s) will stay empty!\n")
    79  	}
    80  
    81  	var finalFs pathfs.FileSystem
    82  	orig := flag.Arg(1)
    83  	loopbackfs := pathfs.NewLoopbackFileSystem(orig)
    84  	finalFs = loopbackfs
    85  
    86  	opts := &nodefs.Options{
    87  		// These options are to be compatible with libfuse defaults,
    88  		// making benchmarking easier.
    89  		NegativeTimeout: time.Second,
    90  		AttrTimeout:     time.Second,
    91  		EntryTimeout:    time.Second,
    92  	}
    93  	// Enable ClientInodes so hard links work
    94  	pathFsOpts := &pathfs.PathNodeFsOptions{ClientInodes: *enableLinks}
    95  	pathFs := pathfs.NewPathNodeFs(finalFs, pathFsOpts)
    96  	conn := nodefs.NewFileSystemConnector(pathFs.Root(), opts)
    97  	mountPoint := flag.Arg(0)
    98  	origAbs, _ := filepath.Abs(orig)
    99  	mOpts := &fuse.MountOptions{
   100  		AllowOther: *other,
   101  		Name:       "loopbackfs",
   102  		FsName:     origAbs,
   103  		Debug:      *debug,
   104  	}
   105  	state, err := fuse.NewServer(conn.RawFS(), mountPoint, mOpts)
   106  	if err != nil {
   107  		fmt.Printf("Mount fail: %v\n", err)
   108  		os.Exit(1)
   109  	}
   110  
   111  	fmt.Println("Mounted!")
   112  	state.Serve()
   113  }