func (t *Fs) put(rid string, d zx.Dir, off int64, dc <-chan []byte, pred string) (zx.Dir, int64, int64, error) { noinherit := false if m := d["Mode"]; m != "" { d["mode"] = m delete(d, "Mode") noinherit = true } var pf *mFile f, left, err := t.walk(rid, &pf) if err != nil && !dbg.IsNotExist(err) || len(left) > 1|| d["mode"] == "" && err != nil { return nil, 0, 0, err } pmode := uint64(0755) if pf != nil { pf.mlk.Lock() pmode = pf.d.Mode() pf.mlk.Unlock() } app := false f.mlk.Lock() if err == nil && f.d["type"] == "d" || d["type"] == "d" { err = fmt.Errorf("%s: %s", f, dbg.ErrIsDir) f.mlk.Unlock() return nil, 0, 0, err } if !t.noPerms() && !f.d.CanWrite(t.ai) { err = fmt.Errorf("%s: %s", f, dbg.ErrPerm) f.mlk.Unlock() return nil, 0, 0, err } u := dbg.Usr if t.ai != nil { u = t.ai.Uid } if d == nil { d = zx.Dir{} } ai := t.ai if t.NoPermCheck { ai = nil } if d["mode"] == "" || err == nil { // truncate or rewrite if err := t.matchDir(rid, f.d, pred); err != nil { f.mlk.Unlock() return nil, 0, 0, err } if !t.WstatAll || t.ai != nil { if err := f.d.CanWstat(ai, d); err != nil { f.mlk.Unlock() return nil, 0, 0, err } } } else { if err := t.matchDir(rid, nil, pred); err != nil { f.mlk.Unlock() return nil, 0, 0, err } } if d["mode"] == "" { if off < 0 { off = 0 app = true } if t.WstatAll && t.ai == nil && d["Wuid"] != "" { f.d["Wuid"] = d["Wuid"] } else { f.d["Wuid"] = u } if d["size"] != "" { f.data.Truncate(d.Int64("size")) f.d["size"] = strconv.FormatInt(int64(f.data.Len()), 10) } } else if err == nil { // truncate existing file if !noinherit && (!t.WstatAll || t.ai != nil) { d.Inherit(pmode) } f.data.Truncate(d.Int64("size")) f.d["size"] = strconv.FormatInt(int64(f.data.Len()), 10) if t.WstatAll && t.ai == nil && d["Wuid"] != "" { f.d["Wuid"] = d["Wuid"] } else { f.d["Wuid"] = u } } else { // create a new file nf := &mFile { name: left[0], d: zx.Dir{ "mode": d["mode"], "name": left[0], "path": rid, "spath": rid, "tpath": f.d["tpath"], "Uid": u, "Gid": f.d["Gid"], "Wuid": u, "type": "-", "size": "0", "proto": "proc", }, data: &bufs.Blocks{Mutex: &sync.Mutex{}}, t: t, } if !t.WstatAll || t.ai != nil { if !noinherit { nf.d.Inherit(pmode) d["mode"] = nf.d["mode"] } if err := f.d.CanWstat(ai, d); err != nil { f.mlk.Unlock() return nil, 0, 0, err } } else if d["Wuid"] != "" { f.d["Wuid"] = d["Wuid"] } nf.data.Truncate(d.Int64("size")) nf.d["size"] = strconv.FormatInt(int64(nf.data.Len()), 10) f.clk.Lock() f.attach(nf) f.clk.Unlock() f.mlk.Unlock() f = nf f.mlk.Lock() } if app { off = int64(f.data.Len()) } delete(d, "size") f.wstat(d.UsrAttrs()) f.mlk.Unlock() n, err := f.data.RecvAtFrom(off, dc) f.mlk.Lock() defer f.mlk.Unlock() if DoSum { sum := f.data.Sum() f.d["Sum"] = sum } size := f.data.Len() f.d["size"] = strconv.Itoa(size) if d["mtime"] == "" { f.d.SetTime("mtime", time.Now()) } return f.d.Dup(), 1, int64(n), err }