func main() { version := flag.Bool("version", false, "print version number") debug := flag.Bool("debug", false, "debug on") hardlinks := flag.Bool("hardlinks", false, "support hardlinks") delcache_ttl := flag.Float64("deletion_cache_ttl", 5.0, "Deletion cache TTL in seconds.") branchcache_ttl := flag.Float64("branchcache_ttl", 5.0, "Branch cache TTL in seconds.") deldirname := flag.String( "deletion_dirname", "GOUNIONFS_DELETIONS", "Directory name to use for deletions.") flag.Parse() if *version { fmt.Println(fuse.Version()) os.Exit(0) } if len(flag.Args()) < 2 { fmt.Println("Usage:\n main MOUNTPOINT BASEDIR") os.Exit(2) } ufsOptions := unionfs.UnionFsOptions{ DeletionCacheTTL: time.Duration(*delcache_ttl * float64(time.Second)), BranchCacheTTL: time.Duration(*branchcache_ttl * float64(time.Second)), DeletionDirName: *deldirname, } options := unionfs.AutoUnionFsOptions{ UnionFsOptions: ufsOptions, FileSystemOptions: fuse.FileSystemOptions{ EntryTimeout: time.Second, AttrTimeout: time.Second, NegativeTimeout: time.Second, Owner: fuse.CurrentOwner(), }, UpdateOnMount: true, PathNodeFsOptions: fuse.PathNodeFsOptions{ ClientInodes: *hardlinks, }, } fmt.Printf("AutoUnionFs - Go-FUSE Version %v.\n", fuse.Version()) gofs := unionfs.NewAutoUnionFs(flag.Arg(1), options) pathfs := fuse.NewPathNodeFs(gofs, nil) state, conn, err := fuse.MountNodeFileSystem(flag.Arg(0), pathfs, nil) if err != nil { fmt.Printf("Mount fail: %v\n", err) os.Exit(1) } pathfs.Debug = *debug conn.Debug = *debug state.Debug = *debug gofs.SetMountState(state) state.Loop() }
func (fs *autoUnionFs) GetAttr(path string, context *fuse.Context) (*fuse.Attr, fuse.Status) { if path == "" || path == _CONFIG || path == _STATUS { a := &fuse.Attr{ Mode: fuse.S_IFDIR | 0755, } return a, fuse.OK } if path == filepath.Join(_STATUS, _DEBUG_SETTING) && fs.hasDebug() { return &fuse.Attr{ Mode: fuse.S_IFLNK | 0644, }, fuse.OK } if path == filepath.Join(_STATUS, _VERSION) { a := &fuse.Attr{ Mode: fuse.S_IFREG | 0644, Size: uint64(len(fuse.Version())), } return a, fuse.OK } if path == filepath.Join(_STATUS, _DEBUG) { a := &fuse.Attr{ Mode: fuse.S_IFREG | 0644, Size: uint64(len(fs.DebugData())), } return a, fuse.OK } if path == filepath.Join(_STATUS, _ROOT) { a := &fuse.Attr{ Mode: syscall.S_IFLNK | 0644, } return a, fuse.OK } if path == filepath.Join(_CONFIG, _SCAN_CONFIG) { a := &fuse.Attr{ Mode: fuse.S_IFREG | 0644, } return a, fuse.OK } comps := strings.Split(path, string(filepath.Separator)) if len(comps) > 1 && comps[0] == _CONFIG { fs := fs.getUnionFs(comps[1]) if fs == nil { return nil, fuse.ENOENT } a := &fuse.Attr{ Mode: syscall.S_IFLNK | 0644, } return a, fuse.OK } return nil, fuse.ENOENT }
func (fs *AutoUnionFs) DebugData() string { if fs.mountState == nil { return "AutoUnionFs.mountState not set" } setting := fs.mountState.KernelSettings() msg := fmt.Sprintf( "Version: %v\n"+ "Bufferpool: %v\n"+ "Kernel: %v\n", fuse.Version(), fs.mountState.BufferPoolStats(), &setting) lat := fs.mountState.Latencies() if len(lat) > 0 { msg += fmt.Sprintf("Latencies: %v\n", lat) } counts := fs.mountState.OperationCounts() if len(counts) > 0 { msg += fmt.Sprintf("Op counts: %v\n", counts) } if fs.connector != nil { msg += fmt.Sprintf("Live inodes: %d\n", fs.connector.InodeHandleCount()) } return msg }
func (me *AutoUnionFs) DebugData() string { if me.mountState == nil { return "AutoUnionFs.mountState not set" } setting := me.mountState.KernelSettings() msg := fmt.Sprintf( "Version: %v\n"+ "Bufferpool: %v\n"+ "Kernel: %v\n", fuse.Version(), me.mountState.BufferPoolStats(), &setting) lat := me.mountState.Latencies() if len(lat) > 0 { msg += fmt.Sprintf("Latencies: %v\n", lat) } counts := me.mountState.OperationCounts() if len(counts) > 0 { msg += fmt.Sprintf("Op counts: %v\n", counts) } return msg }
func Version() string { tVersion := "unknown" if version != nil { tVersion = *version } return fmt.Sprintf("Termite %s (go-fuse %s)", tVersion, fuse.Version()) }
func main() { fsdebug := flag.Bool("fs-debug", false, "switch on FS debugging") mtpDebug := flag.Bool("mtp-debug", false, "switch on MTP debugging") vfat := flag.Bool("vfat", true, "assume removable RAM media uses VFAT, and rewrite names.") other := flag.Bool("allow-other", false, "allow other users to access mounted fuse. Default: false.") deviceFilter := flag.String("dev", "", "regular expression to filter devices.") storageFilter := flag.String("storage", "", "regular expression to filter storage areas.") flag.Parse() if len(flag.Args()) != 1 { log.Fatalf("Usage: %s [options] MOUNT-POINT\n", os.Args[0]) } mountpoint := flag.Arg(0) dev, err := mtp.SelectDevice(*deviceFilter) if err != nil { log.Fatalf("detect failed: %v", err) } defer dev.Close() if err = dev.OpenSession(); err != nil { log.Fatalf("OpenSession failed: %v", err) } sids, err := fs.SelectStorages(dev, *storageFilter) if err != nil { log.Fatalf("selectStorages failed: %v", err) } dev.DebugPrint = *mtpDebug opts := fs.DeviceFsOptions{ RemovableVFat: *vfat, } fs, err := fs.NewDeviceFs(dev, sids, opts) if err != nil { log.Fatalf("NewDeviceFs failed: %v", err) } conn := fuse.NewFileSystemConnector(fs, fuse.NewFileSystemOptions()) rawFs := fuse.NewLockingRawFileSystem(conn) mount := fuse.NewMountState(rawFs) mOpts := &fuse.MountOptions{ AllowOther: *other, } if err := mount.Mount(mountpoint, mOpts); err != nil { log.Fatalf("mount failed: %v", err) } conn.Debug = *fsdebug mount.Debug = *fsdebug log.Printf("starting FUSE %v", fuse.Version()) mount.Loop() }
func (me *AutoUnionFs) GetAttr(path string) (*os.FileInfo, fuse.Status) { if path == "" || path == _CONFIG || path == _STATUS { a := &os.FileInfo{ Mode: fuse.S_IFDIR | 0755, } return a, fuse.OK } if path == filepath.Join(_STATUS, _VERSION) { a := &os.FileInfo{ Mode: fuse.S_IFREG | 0644, Size: int64(len(fuse.Version())), } return a, fuse.OK } if path == filepath.Join(_STATUS, _ROOT) { a := &os.FileInfo{ Mode: syscall.S_IFLNK | 0644, } return a, fuse.OK } if path == filepath.Join(_CONFIG, _SCAN_CONFIG) { a := &os.FileInfo{ Mode: fuse.S_IFREG | 0644, } return a, fuse.OK } comps := strings.Split(path, fuse.SeparatorString, -1) if len(comps) > 1 && comps[0] == _CONFIG { fs := me.getUnionFs(comps[1]) if fs == nil { return nil, fuse.ENOENT } a := &os.FileInfo{ Mode: syscall.S_IFLNK | 0644, } return a, fuse.OK } if me.getUnionFs(path) != nil { return &os.FileInfo{ Mode: fuse.S_IFDIR | 0755, }, fuse.OK } return nil, fuse.ENOENT }
func (me *AutoUnionFs) Open(path string, flags uint32, context *fuse.Context) (fuse.File, fuse.Status) { if path == filepath.Join(_STATUS, _VERSION) { if flags&fuse.O_ANYWRITE != 0 { return nil, fuse.EPERM } return fuse.NewDataFile([]byte(fuse.Version())), fuse.OK } if path == filepath.Join(_CONFIG, _SCAN_CONFIG) { if flags&fuse.O_ANYWRITE != 0 { me.updateKnownFses() } return fuse.NewDevNullFile(), fuse.OK } return nil, fuse.ENOENT }
func main() { version := flag.Bool("version", false, "print version number") debug := flag.Bool("debug", false, "debug on") threaded := flag.Bool("threaded", true, "threading on") delcache_ttl := flag.Float64("deletion_cache_ttl", 5.0, "Deletion cache TTL in seconds.") branchcache_ttl := flag.Float64("branchcache_ttl", 5.0, "Branch cache TTL in seconds.") deldirname := flag.String( "deletion_dirname", "GOUNIONFS_DELETIONS", "Directory name to use for deletions.") flag.Parse() if *version { fmt.Println(fuse.Version()) os.Exit(0) } if len(flag.Args()) < 2 { fmt.Println("Usage:\n main MOUNTPOINT BASEDIR") os.Exit(2) } ufsOptions := unionfs.UnionFsOptions{ DeletionCacheTTLSecs: *delcache_ttl, BranchCacheTTLSecs: *branchcache_ttl, DeletionDirName: *deldirname, } options := unionfs.AutoUnionFsOptions{ UnionFsOptions: ufsOptions, FileSystemOptions: fuse.FileSystemOptions{ EntryTimeout: 1.0, AttrTimeout: 1.0, NegativeTimeout: 1.0, Owner: fuse.CurrentOwner(), }, UpdateOnMount: true, } gofs := unionfs.NewAutoUnionFs(flag.Arg(1), options) pathfs := fuse.NewPathNodeFs(gofs) state, conn, err := fuse.MountNodeFileSystem(flag.Arg(0), pathfs, nil) if err != nil { fmt.Printf("Mount fail: %v\n", err) os.Exit(1) } pathfs.Debug = *debug conn.Debug = *debug state.Debug = *debug state.Loop(*threaded) }
func (fs *AutoUnionFs) DebugData() string { if fs.mountState == nil { return "AutoUnionFs.mountState not set" } setting := fs.mountState.KernelSettings() msg := fmt.Sprintf( "Version: %v\n"+ "Bufferpool: %v\n"+ "Kernel: %v\n", fuse.Version(), fs.mountState.BufferPoolStats(), &setting) if fs.connector != nil { msg += fmt.Sprintf("Live inodes: %d\n", fs.connector.InodeHandleCount()) } return msg }
func (fs *autoUnionFs) DebugData() string { conn := fs.nodeFs.Connector() if conn.Server() == nil { return "autoUnionFs.mountState not set" } setting := conn.Server().KernelSettings() msg := fmt.Sprintf( "Version: %v\n"+ "Bufferpool: %v\n"+ "Kernel: %v\n", fuse.Version(), conn.Server().DebugData(), &setting) if conn != nil { msg += fmt.Sprintf("Live inodes: %d\n", conn.InodeHandleCount()) } return msg }
func main() { fsdebug := flag.Bool("fs-debug", false, "switch on FS debugging") mtpDebug := flag.Int("mtp-debug", 0, "switch on MTP debugging. 1=PTP, 2=PLST, 4=USB, 8=DATA") backing := flag.String("backing-dir", "", "backing store for locally cached files. Default: use a temporary directory.") vfat := flag.Bool("vfat", true, "assume removable RAM media uses VFAT, and rewrite names.") other := flag.Bool("allow-other", false, "allow other users to access mounted fuse. Default: false.") deviceFilter := flag.String("dev", "", "regular expression to filter devices.") storageFilter := flag.String("storage", "", "regular expression to filter storage areas.") flag.Parse() if len(flag.Args()) != 1 { log.Fatalf("Usage: %s [options] MOUNT-POINT\n", os.Args[0]) } mountpoint := flag.Arg(0) Init() SetDebug(*mtpDebug) devs, err := Detect() if err != nil { log.Fatalf("detect failed: %v", err) } if *deviceFilter != "" { re, err := regexp.Compile(*deviceFilter) if err != nil { log.Fatalf("invalid regexp %q: %v", *deviceFilter, err) } filtered := []*RawDevice{} for _, d := range devs { if re.FindStringIndex(d.String()) != nil { filtered = append(filtered, d) } else { log.Printf("filtering out device %v: ", d) } } devs = filtered } else { for _, d := range devs { log.Printf("found device %v: ", d) } } if len(devs) == 0 { log.Fatal("no device found. Try replugging it.") } if len(devs) > 1 { log.Fatal("must have exactly one device. Try using -dev") } rdev := devs[0] dev, err := rdev.Open() if err != nil { log.Fatalf("rdev.open failed: %v", err) } defer dev.Release() dev.GetStorage(0) storages := []*DeviceStorage{} for _, s := range dev.ListStorage() { if !s.IsHierarchical() { log.Printf("skipping non hierarchical storage %q", s.Description()) continue } storages = append(storages, s) } if *storageFilter != "" { re, err := regexp.Compile(*storageFilter) if err != nil { log.Fatalf("invalid regexp %q: %v", *storageFilter, err) } filtered := []*DeviceStorage{} for _, s := range storages { if re.FindStringIndex(s.Description()) == nil { log.Printf("filtering out storage %q", s.Description()) continue } filtered = append(filtered, s) } if len(filtered) == 0 { log.Fatalf("No storages found. Try changing the -storage flag.") } storages = filtered } else { for _, s := range storages { log.Printf("storage ID %d: %s", s.Id(), s.Description()) } } if len(storages) == 0 { log.Fatalf("No storages found. Try unlocking the device.") } if *backing == "" { *backing, err = ioutil.TempDir("", "go-mtpfs") if err != nil { log.Fatalf("TempDir failed: %v", err) } } else { *backing = *backing + "/go-mtpfs" err = os.Mkdir(*backing, 0700) if err != nil { log.Fatalf("Mkdir failed: %v", err) } } log.Println("backing data", *backing) defer os.RemoveAll(*backing) opts := DeviceFsOptions{ Dir: *backing, RemovableVFat: *vfat, } fs := NewDeviceFs(dev, storages, opts) conn := fuse.NewFileSystemConnector(fs, fuse.NewFileSystemOptions()) rawFs := fuse.NewLockingRawFileSystem(conn) mount := fuse.NewMountState(rawFs) mOpts := &fuse.MountOptions{ AllowOther: *other, } if err := mount.Mount(mountpoint, mOpts); err != nil { log.Fatalf("mount failed: %v", err) } conn.Debug = *fsdebug mount.Debug = *fsdebug log.Printf("starting FUSE %v", fuse.Version()) mount.Loop() }
func main() { debug := flag.String("debug", "", "comma-separated list of debugging options: usb, data, mtp, fuse") usbTimeout := flag.Int("usb-timeout", 5000, "timeout in milliseconds") vfat := flag.Bool("vfat", true, "assume removable RAM media uses VFAT, and rewrite names.") other := flag.Bool("allow-other", false, "allow other users to access mounted fuse. Default: false.") deviceFilter := flag.String("dev", "", "regular expression to filter devices.") storageFilter := flag.String("storage", "", "regular expression to filter storage areas.") android := flag.Bool("android", true, "use android extensions if available") flag.Parse() if len(flag.Args()) != 1 { log.Fatalf("Usage: %s [options] MOUNT-POINT\n", os.Args[0]) } mountpoint := flag.Arg(0) dev, err := mtp.SelectDevice(*deviceFilter) if err != nil { log.Fatalf("detect failed: %v", err) } defer dev.Close() debugs := map[string]bool{} for _, s := range strings.Split(*debug, ",") { debugs[s] = true } dev.MTPDebug = debugs["mtp"] dev.DataDebug = debugs["data"] dev.USBDebug = debugs["usb"] dev.Timeout = *usbTimeout if err = dev.Configure(); err != nil { log.Fatalf("Configure failed: %v", err) } sids, err := fs.SelectStorages(dev, *storageFilter) if err != nil { log.Fatalf("selectStorages failed: %v", err) } opts := fs.DeviceFsOptions{ RemovableVFat: *vfat, Android: *android, } fs, err := fs.NewDeviceFs(dev, sids, opts) if err != nil { log.Fatalf("NewDeviceFs failed: %v", err) } conn := fuse.NewFileSystemConnector(fs, fuse.NewFileSystemOptions()) rawFs := fuse.NewLockingRawFileSystem(conn) mount := fuse.NewMountState(rawFs) mOpts := &fuse.MountOptions{ AllowOther: *other, } if err := mount.Mount(mountpoint, mOpts); err != nil { log.Fatalf("mount failed: %v", err) } conn.Debug = debugs["fuse"] || debugs["fs"] mount.Debug = debugs["fuse"] || debugs["fs"] log.Printf("starting FUSE %v", fuse.Version()) mount.Loop() fs.OnUnmount() }
func main() { version := flag.Bool("version", false, "print version number") debug := flag.Bool("debug", false, "debug on") hardlinks := flag.Bool("hardlinks", false, "support hardlinks") delcache_ttl := flag.Float64("deletion_cache_ttl", 5.0, "Deletion cache TTL in seconds.") branchcache_ttl := flag.Float64("branchcache_ttl", 5.0, "Branch cache TTL in seconds.") deldirname := flag.String( "deletion_dirname", "GOUNIONFS_DELETIONS", "Directory name to use for deletions.") hide_readonly_link := flag.Bool("hide_readonly_link", true, "Hides READONLY link from the top mountpoints. "+ "Enabled by default.") portableInodes := flag.Bool("portable-inodes", false, "Use sequential 32-bit inode numbers.") flag.Parse() if *version { fmt.Println(fuse.Version()) os.Exit(0) } if len(flag.Args()) < 2 { fmt.Println("Usage:\n main MOUNTPOINT BASEDIR") os.Exit(2) } ufsOptions := unionfs.UnionFsOptions{ DeletionCacheTTL: time.Duration(*delcache_ttl * float64(time.Second)), BranchCacheTTL: time.Duration(*branchcache_ttl * float64(time.Second)), DeletionDirName: *deldirname, } options := unionfs.AutoUnionFsOptions{ UnionFsOptions: ufsOptions, Options: nodefs.Options{ EntryTimeout: time.Second, AttrTimeout: time.Second, NegativeTimeout: time.Second, Owner: fuse.CurrentOwner(), }, UpdateOnMount: true, PathNodeFsOptions: pathfs.PathNodeFsOptions{ ClientInodes: *hardlinks, }, HideReadonly: *hide_readonly_link, } fsOpts := nodefs.Options{ PortableInodes: *portableInodes, } fmt.Printf("AutoUnionFs - Go-FUSE Version %v.\n", fuse.Version()) gofs := unionfs.NewAutoUnionFs(flag.Arg(1), options) pathfs := pathfs.NewPathNodeFs(gofs, nil) state, conn, err := nodefs.MountFileSystem(flag.Arg(0), pathfs, &fsOpts) if err != nil { fmt.Printf("Mount fail: %v\n", err) os.Exit(1) } pathfs.SetDebug(*debug) conn.SetDebug(*debug) state.SetDebug(*debug) state.Serve() time.Sleep(1 * time.Second) }