// NB: Attributes that the user can't set are always ignored. // If the user has no permissioin to set an attribute, that's an error. // Setting an attribute to an empty string removes it. // Uid, Gid, and Wuid can't be removed. // Meta locking done by caller, might lock data on truncations func (f *mFile) wstat(d zx.Dir) error { if len(d) == 0 { return nil } d = d.Dup() sum := "" if f.d["type"] != "d" { if _, ok := d["size"]; ok { sz := d.Int64("size") if sz < 0 { sz = 0 } f.data.Truncate(sz) d["size"] = strconv.FormatInt(sz, 10) if DoSum { sum = f.data.Sum() } } } else { delete(d, "size") } if _, ok := d["mode"]; ok { mode := d.Int("mode")&0777 d["mode"] = "0" + strconv.FormatInt(int64(mode), 8) } if _, ok := d["mtime"]; ok { d.SetTime("mtime", d.Time("mtime")) } if sum != "" { f.d["Sum"] = sum } ud := d.UsrAttrs() if d["Wuid"] != "" { ud["Wuid"] = d["Wuid"] } for k, v := range ud { if v == "" { delete(f.d, k) } else { f.d[k] = v } } return nil }
func (t *Fs) Put(rid string, d zx.Dir, off int64, dc <-chan []byte, pred string) chan zx.Dir { d = d.Dup() t.dprintf("put %s %v %d '%s'\n", rid, d, off, pred) cs := t.IOstats.NewCall(zx.Sput) c := make(chan zx.Dir, 1) go func() { cs.Sending() rid, err := zx.AbsPath(rid) var nm, n int64 var nd zx.Dir if err == nil && rid == "/Ctl" { nc, xerr := t.putCtl(dc) if xerr == nil { nd = zx.Dir{"size": "0"} if DoSum { nd["Sum"] = zx.Zsum() } nd.SetTime("mtime", time.Now()) nm = 1 n = int64(nc) } err = xerr } else if err == nil { nd, nm, n, err = t.put(rid, d, off, dc, pred) cs.Sends(nm, n) } if err == nil { rd := zx.Dir{"size": nd["size"], "mtime": nd["mtime"]} if nd["Sum"] != "" { rd["Sum"] = nd["Sum"] } t.dprintf("put %s: %s (wrote %d)\n", rid, rd, n) c <- rd } else { t.dprintf("put %s: %s\n", rid, err) close(dc, err) } close(c, err) cs.End(err != nil) }() return c }
func (t *Fs) Put(rid string, d zx.Dir, off int64, dc <-chan []byte, pred string) chan zx.Dir { d = d.UsrAttrs() t.dprintf("put %s %v %d '%s'\n", rid, d, off, pred) cs := t.IOstats.NewCall(zx.Sput) c := make(chan zx.Dir, 1) go func() { cs.Sending() rid, err := zx.AbsPath(rid) var nd zx.Dir if err == nil && rid == "/" { err = fmt.Errorf("/: %s", dbg.ErrPerm) } if err == nil && rid == "/Ctl" { xerr := t.putCtl(dc) if xerr == nil { nd = zx.Dir{"size": "0", "Sum": zx.Zsum()} nd.SetTime("mtime", time.Now()) } err = xerr } else if err == nil { err = t.put(rid, d, off, dc, pred) if err == nil { nd, err = t.stat(rid) } } if err == nil { rd := zx.Dir{"size": nd["size"], "mtime": nd["mtime"], "Sum": nd["Sum"]} t.dprintf("put %s: %s\n", rid, rd) c <- rd } else { t.dprintf("put %s: %s\n", rid, err) close(dc, err) } close(c, err) cs.End(err != nil) }() return c }
// set a fake mtime that can be predicted. func TouchZX(fs zx.RWTree, path string) error { d := zx.Dir{} d.SetTime("mtime", time.Unix(xt/1e9, xt%1e9)) xt += 1e9 return <-fs.Wstat(path, d) }