github.com/advanderveer/restic@v0.8.1-0.20171209104529-42a8c19aaea6/cmd/restic/cmd_mount.go (about) 1 // +build !openbsd 2 // +build !windows 3 4 package main 5 6 import ( 7 "os" 8 9 "github.com/spf13/cobra" 10 11 "github.com/restic/restic/internal/debug" 12 "github.com/restic/restic/internal/errors" 13 "github.com/restic/restic/internal/restic" 14 15 resticfs "github.com/restic/restic/internal/fs" 16 "github.com/restic/restic/internal/fuse" 17 18 systemFuse "bazil.org/fuse" 19 "bazil.org/fuse/fs" 20 ) 21 22 var cmdMount = &cobra.Command{ 23 Use: "mount [flags] mountpoint", 24 Short: "Mount the repository", 25 Long: ` 26 The "mount" command mounts the repository via fuse to a directory. This is a 27 read-only mount. 28 `, 29 DisableAutoGenTag: true, 30 RunE: func(cmd *cobra.Command, args []string) error { 31 return runMount(mountOptions, globalOptions, args) 32 }, 33 } 34 35 // MountOptions collects all options for the mount command. 36 type MountOptions struct { 37 OwnerRoot bool 38 AllowRoot bool 39 AllowOther bool 40 Host string 41 Tags restic.TagLists 42 Paths []string 43 } 44 45 var mountOptions MountOptions 46 47 func init() { 48 cmdRoot.AddCommand(cmdMount) 49 50 mountFlags := cmdMount.Flags() 51 mountFlags.BoolVar(&mountOptions.OwnerRoot, "owner-root", false, "use 'root' as the owner of files and dirs") 52 mountFlags.BoolVar(&mountOptions.AllowRoot, "allow-root", false, "allow root user to access the data in the mounted directory") 53 mountFlags.BoolVar(&mountOptions.AllowOther, "allow-other", false, "allow other users to access the data in the mounted directory") 54 55 mountFlags.StringVarP(&mountOptions.Host, "host", "H", "", `only consider snapshots for this host`) 56 mountFlags.Var(&mountOptions.Tags, "tag", "only consider snapshots which include this `taglist`") 57 mountFlags.StringArrayVar(&mountOptions.Paths, "path", nil, "only consider snapshots which include this (absolute) `path`") 58 } 59 60 func mount(opts MountOptions, gopts GlobalOptions, mountpoint string) error { 61 debug.Log("start mount") 62 defer debug.Log("finish mount") 63 64 repo, err := OpenRepository(gopts) 65 if err != nil { 66 return err 67 } 68 69 lock, err := lockRepo(repo) 70 defer unlockRepo(lock) 71 if err != nil { 72 return err 73 } 74 75 err = repo.LoadIndex(gopts.ctx) 76 if err != nil { 77 return err 78 } 79 80 if _, err := resticfs.Stat(mountpoint); os.IsNotExist(errors.Cause(err)) { 81 Verbosef("Mountpoint %s doesn't exist, creating it\n", mountpoint) 82 err = resticfs.Mkdir(mountpoint, os.ModeDir|0700) 83 if err != nil { 84 return err 85 } 86 } 87 88 mountOptions := []systemFuse.MountOption{ 89 systemFuse.ReadOnly(), 90 systemFuse.FSName("restic"), 91 } 92 93 if opts.AllowRoot { 94 mountOptions = append(mountOptions, systemFuse.AllowRoot()) 95 } 96 97 if opts.AllowOther { 98 mountOptions = append(mountOptions, systemFuse.AllowOther()) 99 } 100 101 c, err := systemFuse.Mount(mountpoint, mountOptions...) 102 if err != nil { 103 return err 104 } 105 106 systemFuse.Debug = func(msg interface{}) { 107 debug.Log("fuse: %v", msg) 108 } 109 110 cfg := fuse.Config{ 111 OwnerIsRoot: opts.OwnerRoot, 112 Host: opts.Host, 113 Tags: opts.Tags, 114 Paths: opts.Paths, 115 } 116 root, err := fuse.NewRoot(gopts.ctx, repo, cfg) 117 if err != nil { 118 return err 119 } 120 121 Printf("Now serving the repository at %s\n", mountpoint) 122 Printf("Don't forget to umount after quitting!\n") 123 124 debug.Log("serving mount at %v", mountpoint) 125 err = fs.Serve(c, root) 126 if err != nil { 127 return err 128 } 129 130 <-c.Ready 131 return c.MountError 132 } 133 134 func umount(mountpoint string) error { 135 return systemFuse.Unmount(mountpoint) 136 } 137 138 func runMount(opts MountOptions, gopts GlobalOptions, args []string) error { 139 if len(args) == 0 { 140 return errors.Fatal("wrong number of parameters") 141 } 142 143 mountpoint := args[0] 144 145 AddCleanupHandler(func() error { 146 debug.Log("running umount cleanup handler for mount at %v", mountpoint) 147 err := umount(mountpoint) 148 if err != nil { 149 Warnf("unable to umount (maybe already umounted?): %v\n", err) 150 } 151 return nil 152 }) 153 154 return mount(opts, gopts, mountpoint) 155 }