func main() { flag.Usage = Usage flag.Parse() if flag.NArg() != 1 { Usage() os.Exit(2) } mountpoint := flag.Arg(0) c, err := fuse.Mount( mountpoint, fuse.FSName("helloworld"), fuse.Subtype("hellofs"), fuse.LocalVolume(), fuse.VolumeName("Hello world!"), ) if err != nil { log.Fatal(err) } defer c.Close() err = fs.Serve(c, FS{}) if err != nil { log.Fatal(err) } // check if the mount process has an error to report <-c.Ready if err := c.MountError; err != nil { log.Fatal(err) } }
// MountedFunc mounts a filesystem at a temporary directory. The // filesystem used is constructed by calling a function, to allow // storing fuse.Conn and fs.Server in the FS. // // It also waits until the filesystem is known to be visible (OS X // workaround). // // After successful return, caller must clean up by calling Close. func MountedFunc(fn func(*Mount) fs.FS, conf *fs.Config, options ...fuse.MountOption) (*Mount, error) { dir, err := ioutil.TempDir("", "fusetest") if err != nil { return nil, err } c, err := fuse.Mount(dir, options...) if err != nil { return nil, err } server := fs.New(c, conf) done := make(chan struct{}) serveErr := make(chan error, 1) mnt := &Mount{ Dir: dir, Conn: c, Server: server, Error: serveErr, done: done, } filesys := fn(mnt) go func() { defer close(done) serveErr <- server.Serve(filesys) }() select { case <-mnt.Conn.Ready: if err := mnt.Conn.MountError; err != nil { return nil, err } return mnt, nil case err = <-mnt.Error: // Serve quit early if err != nil { return nil, err } return nil, errors.New("Serve exited early") } }
// // Main function. // - Exposes remote FS structure locally using FUSE (bazil-fuse) // - Gets files from remote on-demand // - TODO: // - Check-in files to remote // - Version control // func Revelo(Name string, accType string, cacheDir string, mntDir string) error { GlobalData.metaName = Name + ".meta" acc, err := initAccess(accType, mntDir) if err != nil { log.Errorf("Revelo: Invalid Access type: %v", accType) return err } remoteDir, err := acc.Init() if err != nil { log.WithFields(log.Fields{"Acc": acc, "Error": err}).Error("Revelo: Cannot init access") return err } GlobalData.cacheDir = cacheDir GlobalData.mntDir = mntDir log.WithFields(log.Fields{ "Access": acc, "CacheDir": cacheDir, "mntDir": mntDir, "RemoteDir": remoteDir, }).Info("Revelo - Init done...") _, err = os.Stat(cacheDir + "/" + GlobalData.metaName) // If some error happened here, we might fail in open later. // Its better not to GetFile in that case. // Get meta from <name>.meta file metaPresent := ((err == nil) || !os.IsNotExist(err)) if metaPresent == false { var metaName string if remoteDir == "" { metaName = GlobalData.metaName } else { metaName = remoteDir + "/" + GlobalData.metaName } err = acc.GetFile(metaName, cacheDir+"/"+GlobalData.metaName) if err != nil { log.WithFields(log.Fields{ "Remote": metaName, "Local": cacheDir + "/" + GlobalData.metaName, "AccData": acc, }).Error("Revelo: Cannot get meta file") return err } } else { log.Info("Revelo: Meta file present, using it...") } metaFile, err := os.Open(cacheDir + "/" + GlobalData.metaName) if err != nil { log.WithFields(log.Fields{ "Meta File": cacheDir + "/" + GlobalData.metaName, "Error": err, }).Error("Cannot open meta file") return err } defer metaFile.Close() st, _ := metaFile.Stat() //XXX This should not fail metaData := make([]byte, st.Size()+1) n, err := metaFile.Read(metaData) if err != nil || n == 0 { log.WithFields(log.Fields{ "Meta File": cacheDir + "/" + GlobalData.metaName, "Read bytes": n, "Error": err, }).Error("Revelo: Cannot read meta file, error or empty") return syscall.EINVAL } // Unmarshal the meta data metaData = metaData[:n] meta := new(horcrux.Meta) err = json.Unmarshal(metaData, meta) if err != nil { log.WithFields(log.Fields{ "Meta Data": string(metaData), "Error": err, }).Error("Revelo: Cannot unmarshal meta data") return err } // Create dirTree GlobalData.Root, err = dirTree.Create(meta) GlobalData.Config = meta.Config GlobalData.CurrVer = meta.CurrVer GlobalData.NumFiles = meta.NumFiles // Mount local fuseConn, err := fuse.Mount(mntDir, fuse.FSName("Horcrux"), fuse.Subtype("Horcrux-"+acc.Name()), fuse.MaxReadahead(128*(1<<10)), fuse.AllowOther()) //XXX : Revisit AllowOther if err != nil { log.WithFields(log.Fields{"Conn": fuseConn, "Error": err}).Error("Mount Failed") return err } defer fuseConn.Close() GlobalData.fuseConn = fuseConn log.Debugf("Mount OK: %v", GlobalData.CurrVer) horcruxFS := &FS{Acc: &acc, RData: &GlobalData, remoteDir: remoteDir, cacheDir: cacheDir} err = fs.Serve(fuseConn, horcruxFS) if err != nil { log.WithFields(log.Fields{"Conn": fuseConn, "Error": err}).Error("Cannot fs.Serve") return err } <-fuseConn.Ready if err := fuseConn.MountError; err != nil { log.WithFields(log.Fields{"Conn": fuseConn, "Error": err}).Error("Mount Failed") return err } log.Info("Revelo Done...") return nil }