func dial(d zx.Dir) (zx.Tree, error) { addr := d["addr"] if addr == "" { return nil, errors.New("no address") } spath := d["spath"] if spath == "" { spath = d["path"] } if spath == "" { return nil, errors.New("no server path") } remslk.RLock() r := rems[addr] remslk.RUnlock() if r != nil { return r, nil } remslk.Lock() defer remslk.Unlock() toks := strings.Split(addr, "!") tree := "main" if len(toks) >= 4 { tree = toks[3] } c, err := ds.Dial(addr) if err != nil { return nil, err } if _, err := auth.AtClient(c, "", "zx"); err!=nil && err!=auth.ErrDisabled { close(c.In, err) close(c.Out, err) return nil, err } m := nchan.NewMux(c, true) r, err = New(m, tree) if err != nil { return nil, err } r.addr = addr hc := m.Hup() go func() { <-hc dbg.Warn("rfs hangup on %s", addr) r.gone() }() rems[addr] = r return r, nil }
/* Import the remote ZX server at the given address. This performs authentication if auth.Enabled and honors TLS configuration. Addresses of the form "*!*!lfs!tree!/a/b" are understood as a request to build a local fs at the given path. An address referring to a existing dir path is also used to build a local fs. */ func Import(addr string) (zx.RWTree, error) { if fi, err := os.Stat(addr); err == nil && fi.IsDir(){ dir, err := filepath.Abs(addr) if err != nil { return nil, err } fs, err := lfs.New(addr, dir, lfs.RW) if err == nil { fs.SaveAttrs(true) } return fs, err } toks := strings.Split(addr, "!") if len(toks) < 2 { return nil, errors.New("bad address") } if len(toks) < 3 { toks = append(toks, "zx") addr = strings.Join(toks, "!") } if toks[2] == "lfs" { p := "/" if len(toks) >= 5 { p = toks[4] } fs, err := lfs.New(addr, p, lfs.RW) if err == nil { fs.SaveAttrs(true) } return fs, err } tree := "main" if len(toks) >= 4 { tree = toks[3] } c, err := ds.Dial(addr) if err != nil { return nil, err } if _, err := auth.AtClient(c, "", "zx"); err!=nil && err!=auth.ErrDisabled { err = fmt.Errorf("auth: %s", err) close(c.In, err) close(c.Out, err) return nil, err } return New(nchan.NewMux(c, true), tree) }