// Stat produces a styxproto.Stat from an open file. If the value // provides a Stat method matching that of os.File, that is used. // Otherwise, the styxfile package determines the file's attributes // based on other characteristics. func Stat(buf []byte, file Interface, name string, qid styxproto.Qid) (styxproto.Stat, error) { var ( fi os.FileInfo err error ) type hasStat interface { Stat() (os.FileInfo, error) } if v, ok := file.(hasStat); ok { fi, err = v.Stat() if err != nil { return nil, err } } else { fi = statGuess{file, name, qid.Type()} } uid, gid, muid := sys.FileOwner(fi) stat, _, err := styxproto.NewStat(buf, fi.Name(), uid, gid, muid) if err != nil { return nil, err } stat.SetLength(fi.Size()) stat.SetMode(Mode9P(fi.Mode())) stat.SetAtime(uint32(fi.ModTime().Unix())) stat.SetMtime(uint32(fi.ModTime().Unix())) stat.SetQid(qid) return stat, nil }
// Rstat responds to a succesful Tstat request. The styx package will // translate the os.FileInfo value into the appropriate 9P structure. Rstat // will attempt to resolve the names of the file's owner and group. If // that cannot be done, an empty string is sent. If err is non-nil, and error // is sent to the client instead. func (t Tstat) Rstat(info os.FileInfo, err error) { if err != nil { t.Rerror("%s", err) return } buf := make([]byte, styxproto.MaxStatLen) uid, gid, muid := sys.FileOwner(info) name := info.Name() if name == "/" { name = "." } stat, _, err := styxproto.NewStat(buf, name, uid, gid, muid) if err != nil { // should never happen panic(err) } mode := styxfile.Mode9P(info.Mode()) stat.SetLength(info.Size()) stat.SetMode(mode) stat.SetAtime(uint32(info.ModTime().Unix())) // TODO: get atime stat.SetMtime(uint32(info.ModTime().Unix())) stat.SetQid(t.session.conn.qid(t.Path(), styxfile.QidType(mode))) t.session.unhandled = false if t.session.conn.clearTag(t.tag) { t.session.conn.Rstat(t.tag, stat) } }
func marshalStats(buf []byte, files []os.FileInfo, dir string, pool *qidpool.Pool) (int, error) { var ( stat styxproto.Stat n = 0 err error ) for _, fi := range files { uid, gid, muid := sys.FileOwner(fi) stat, buf, err = styxproto.NewStat(buf, fi.Name(), uid, gid, muid) if err != nil { break } n += len(stat) mode := Mode9P(fi.Mode()) qtype := QidType(mode) stat.SetMtime(uint32(fi.ModTime().Unix())) stat.SetAtime(stat.Mtime()) stat.SetLength(fi.Size()) stat.SetMode(mode) stat.SetQid(pool.Put(path.Join(dir, fi.Name()), qtype)) } return n, err }