func (t *Lfs) fileAttrs(fpath string, d zx.Dir) { dpath := path.Dir(fpath) ds, _ := t.dirAttrs(dpath) if len(ds) >= 0 { xd := ds[d["name"]] if xd["name"] == d["name"] { ty, m, s := xd["type"], xd["mtime"], xd["size"] for k, v := range xd { if zx.IsUpper(k) { d[k] = v } } if d["type"] == "-" && t.saveattrs && ((d["Sum"] == "" && DoSum) || d["type"] != ty || d["mtime"] != m || d["size"] != s) { fi, err := os.Stat(fpath) if err == nil { xd["type"] = "-" xd.SetTime("mtime", fi.ModTime()) xd["size"] = strconv.FormatInt(fi.Size(), 10) } if DoSum { xd["Sum"] = newFileSum(fpath) d["Sum"] = xd["Sum"] } fn := path.Join(dpath, afname) appAttrFile(fn, xd.Pack()) } setUids(d) return } } setUids(d) }
func saveAttrs(dpath string, d zx.Dir) { nd := zx.Dir{"name": d["name"]} for k, v := range d { if zx.IsUpper(k) { nd[k] = v } } if len(nd) == 1 { return } dprintf("wrattr %s/%s %v\n", dpath, d["name"], nd) fn := path.Join(dpath, afname) fd, err := os.OpenFile(fn, os.O_WRONLY|os.O_APPEND, 0600) if err != nil { fd, err = os.OpenFile(fn, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0600) } if err != nil { return } defer fd.Close() fd.Write(nd.Pack()) }
func (t *Lfs) writeFileAttrs(fpath string, d zx.Dir) error { dpath := path.Dir(fpath) ds, _ := t.dirAttrs(dpath) nm := path.Base(fpath) od := ds[nm] if od == nil { od = zx.Dir{} } od["name"] = nm if d["type"] != "d" && (d["size"] == "" || d["type"] == "" || d["mtime"] == "") { // record type, size, and mtime for files, to know when to recompute Sum fi, err := os.Stat(fpath) if err == nil && !fi.IsDir() { od["type"] = "-" od.SetTime("mtime", fi.ModTime()) od["size"] = strconv.FormatInt(fi.Size(), 10) } } for k, v := range d { if zx.IsUpper(k) { if v == "" { delete(od, k) } else { od[k] = v } } } if len(od) == 0 { return nil } fn := path.Join(dpath, afname) if !DoSum { delete(od, "Sum") } return appAttrFile(fn, od.Pack()) }
func (t *Lfs) get(rid string, off, count int64, dc chan<- []byte, cs *zx.CallStat) (int64, error) { rid, err := zx.AbsPath(rid) if err != nil { return 0, err } if rid == "/Ctl" { return t.getCtl(off, count, dc, cs) } path := zx.Path(t.path, rid) fd, err := os.Open(path) if err==nil && t.ai!=nil && !t.NoPermCheck { _, _, err = t.canWalkTo(rid, 0444) } if err != nil { return 0, err } defer fd.Close() st, err := fd.Stat() if err != nil { return 0, err } if off!=0 && !st.IsDir() { if _, err := fd.Seek(off, 0); err != nil { return 0, err } } if st.IsDir() { ds, err := ioutil.ReadDir(path) nd := 0 tot := 0 ctlsent := false var xds map[string]zx.Dir if t.readattrs { xds, _ = t.dirAttrs(path) } Dloop: for i := 0; i < len(ds); { if off > 0 { off-- if !ctlsent && rid=="/" { ctlsent = true } else { i++ } continue } switch count { case zx.All: break case 0: break Dloop default: count-- } if !ctlsent && rid=="/" { ctlsent = true nd++ d := ctldir n, _ := d.Send(dc) nd++ // but not i++ tot += n continue } fi := ds[i] if fi.Name() == afname { if i == len(ds)-1 { break } ds = append(ds[:i], ds[i+1:]...) fi = ds[i] } cpath := zx.Path(path, fi.Name()) n := 0 sum := "" if fi.IsDir() { n, sum = dirsz(cpath) } d := zx.NewDir(fi, n) d["path"] = zx.Path(rid, fi.Name()) d["spath"] = d["path"] d["tpath"] = t.path if t.readattrs { if xd, ok := xds[fi.Name()]; ok { for k, v := range xd { if zx.IsUpper(k) { d[k] = v } } } else { d["Uid"] = dbg.Usr d["Gid"] = dbg.Usr } } if sum != "" { d["Sum"] = sum } cs.Send(0) n, err := d.Send(dc) if err != nil { return int64(tot), err } nd++ i++ tot += n } return int64(tot), err } if count == zx.All { cs.Sending() nm, n, err := nchan.ReadBytesFrom(fd, dc) cs.Sends(nm, n) return n, err } rr := io.LimitReader(fd, count) cs.Sending() nm, n, err := nchan.ReadBytesFrom(rr, dc) cs.Sends(nm, n) return n, err }